diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index fe23269..66bd97a 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -50,6 +50,13 @@ 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).
 
+void *
+dma_zalloc_coherent(struct device *dev, size_t size,
+			     dma_addr_t *dma_handle, gfp_t flag)
+
+Wraps dma_alloc_coherent() and also zeroes the returned memory if the
+allocation attempt succeeded.
+
 void
 dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
 			   dma_addr_t dma_handle)
diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt
index 06eb6d9..cc0ebc5 100644
--- a/Documentation/cgroups/memory.txt
+++ b/Documentation/cgroups/memory.txt
@@ -418,7 +418,6 @@ total_unevictable	- sum of all children's "unevictable"
 
 # The following additional stats are dependent on CONFIG_DEBUG_VM.
 
-inactive_ratio		- VM internal parameter. (see mm/page_alloc.c)
 recent_rotated_anon	- VM internal parameter. (see mm/vmscan.c)
 recent_rotated_file	- VM internal parameter. (see mm/vmscan.c)
 recent_scanned_anon	- VM internal parameter. (see mm/vmscan.c)
diff --git a/Documentation/device-mapper/dm-log.txt b/Documentation/device-mapper/dm-log.txt
index 994dd75..c155ac5 100644
--- a/Documentation/device-mapper/dm-log.txt
+++ b/Documentation/device-mapper/dm-log.txt
@@ -48,7 +48,7 @@ kernel and userspace, 'connector' is used as the interface for
 communication.
 
 There are currently two userspace log implementations that leverage this
-framework - "clustered_disk" and "clustered_core".  These implementations
+framework - "clustered-disk" and "clustered-core".  These implementations
 provide a cluster-coherent log for shared-storage.  Device-mapper mirroring
 can be used in a shared-storage environment when the cluster log implementations
 are employed.
diff --git a/Documentation/device-mapper/persistent-data.txt b/Documentation/device-mapper/persistent-data.txt
new file mode 100644
index 0000000..0e5df9b
--- /dev/null
+++ b/Documentation/device-mapper/persistent-data.txt
@@ -0,0 +1,84 @@
+Introduction
+============
+
+The more-sophisticated device-mapper targets require complex metadata
+that is managed in kernel.  In late 2010 we were seeing that various
+different targets were rolling their own data strutures, for example:
+
+- Mikulas Patocka's multisnap implementation
+- Heinz Mauelshagen's thin provisioning target
+- Another btree-based caching target posted to dm-devel
+- Another multi-snapshot target based on a design of Daniel Phillips
+
+Maintaining these data structures takes a lot of work, so if possible
+we'd like to reduce the number.
+
+The persistent-data library is an attempt to provide a re-usable
+framework for people who want to store metadata in device-mapper
+targets.  It's currently used by the thin-provisioning target and an
+upcoming hierarchical storage target.
+
+Overview
+========
+
+The main documentation is in the header files which can all be found
+under drivers/md/persistent-data.
+
+The block manager
+-----------------
+
+dm-block-manager.[hc]
+
+This provides access to the data on disk in fixed sized-blocks.  There
+is a read/write locking interface to prevent concurrent accesses, and
+keep data that is being used in the cache.
+
+Clients of persistent-data are unlikely to use this directly.
+
+The transaction manager
+-----------------------
+
+dm-transaction-manager.[hc]
+
+This restricts access to blocks and enforces copy-on-write semantics.
+The only way you can get hold of a writable block through the
+transaction manager is by shadowing an existing block (ie. doing
+copy-on-write) or allocating a fresh one.  Shadowing is elided within
+the same transaction so performance is reasonable.  The commit method
+ensures that all data is flushed before it writes the superblock.
+On power failure your metadata will be as it was when last committed.
+
+The Space Maps
+--------------
+
+dm-space-map.h
+dm-space-map-metadata.[hc]
+dm-space-map-disk.[hc]
+
+On-disk data structures that keep track of reference counts of blocks.
+Also acts as the allocator of new blocks.  Currently two
+implementations: a simpler one for managing blocks on a different
+device (eg. thinly-provisioned data blocks); and one for managing
+the metadata space.  The latter is complicated by the need to store
+its own data within the space it's managing.
+
+The data structures
+-------------------
+
+dm-btree.[hc]
+dm-btree-remove.c
+dm-btree-spine.c
+dm-btree-internal.h
+
+Currently there is only one data structure, a hierarchical btree.
+There are plans to add more.  For example, something with an
+array-like interface would see a lot of use.
+
+The btree is 'hierarchical' in that you can define it to be composed
+of nested btrees, and take multiple keys.  For example, the
+thin-provisioning target uses a btree with two levels of nesting.
+The first maps a device id to a mapping tree, and that in turn maps a
+virtual block to a physical block.
+
+Values stored in the btrees can have arbitrary size.  Keys are always
+64bits, although nesting allows you to use multiple keys.
diff --git a/Documentation/device-mapper/thin-provisioning.txt b/Documentation/device-mapper/thin-provisioning.txt
new file mode 100644
index 0000000..801d9d1
--- /dev/null
+++ b/Documentation/device-mapper/thin-provisioning.txt
@@ -0,0 +1,285 @@
+Introduction
+============
+
+This document descibes a collection of device-mapper targets that
+between them implement thin-provisioning and snapshots.
+
+The main highlight of this implementation, compared to the previous
+implementation of snapshots, is that it allows many virtual devices to
+be stored on the same data volume.  This simplifies administration and
+allows the sharing of data between volumes, thus reducing disk usage.
+
+Another significant feature is support for an arbitrary depth of
+recursive snapshots (snapshots of snapshots of snapshots ...).  The
+previous implementation of snapshots did this by chaining together
+lookup tables, and so performance was O(depth).  This new
+implementation uses a single data structure to avoid this degradation
+with depth.  Fragmentation may still be an issue, however, in some
+scenarios.
+
+Metadata is stored on a separate device from data, giving the
+administrator some freedom, for example to:
+
+- Improve metadata resilience by storing metadata on a mirrored volume
+  but data on a non-mirrored one.
+
+- Improve performance by storing the metadata on SSD.
+
+Status
+======
+
+These targets are very much still in the EXPERIMENTAL state.  Please
+do not yet rely on them in production.  But do experiment and offer us
+feedback.  Different use cases will have different performance
+characteristics, for example due to fragmentation of the data volume.
+
+If you find this software is not performing as expected please mail
+dm-devel@redhat.com with details and we'll try our best to improve
+things for you.
+
+Userspace tools for checking and repairing the metadata are under
+development.
+
+Cookbook
+========
+
+This section describes some quick recipes for using thin provisioning.
+They use the dmsetup program to control the device-mapper driver
+directly.  End users will be advised to use a higher-level volume
+manager such as LVM2 once support has been added.
+
+Pool device
+-----------
+
+The pool device ties together the metadata volume and the data volume.
+It maps I/O linearly to the data volume and updates the metadata via
+two mechanisms:
+
+- Function calls from the thin targets
+
+- Device-mapper 'messages' from userspace which control the creation of new
+  virtual devices amongst other things.
+
+Setting up a fresh pool device
+------------------------------
+
+Setting up a pool device requires a valid metadata device, and a
+data device.  If you do not have an existing metadata device you can
+make one by zeroing the first 4k to indicate empty metadata.
+
+    dd if=/dev/zero of=$metadata_dev bs=4096 count=1
+
+The amount of metadata you need will vary according to how many blocks
+are shared between thin devices (i.e. through snapshots).  If you have
+less sharing than average you'll need a larger-than-average metadata device.
+
+As a guide, we suggest you calculate the number of bytes to use in the
+metadata device as 48 * $data_dev_size / $data_block_size but round it up
+to 2MB if the answer is smaller.  The largest size supported is 16GB.
+
+If you're creating large numbers of snapshots which are recording large
+amounts of change, you may need find you need to increase this.
+
+Reloading a pool table
+----------------------
+
+You may reload a pool's table, indeed this is how the pool is resized
+if it runs out of space.  (N.B. While specifying a different metadata
+device when reloading is not forbidden at the moment, things will go
+wrong if it does not route I/O to exactly the same on-disk location as
+previously.)
+
+Using an existing pool device
+-----------------------------
+
+    dmsetup create pool \
+	--table "0 20971520 thin-pool $metadata_dev $data_dev \
+		 $data_block_size $low_water_mark"
+
+$data_block_size gives the smallest unit of disk space that can be
+allocated at a time expressed in units of 512-byte sectors.  People
+primarily interested in thin provisioning may want to use a value such
+as 1024 (512KB).  People doing lots of snapshotting may want a smaller value
+such as 128 (64KB).  If you are not zeroing newly-allocated data,
+a larger $data_block_size in the region of 256000 (128MB) is suggested.
+$data_block_size must be the same for the lifetime of the
+metadata device.
+
+$low_water_mark is expressed in blocks of size $data_block_size.  If
+free space on the data device drops below this level then a dm event
+will be triggered which a userspace daemon should catch allowing it to
+extend the pool device.  Only one such event will be sent.
+Resuming a device with a new table itself triggers an event so the
+userspace daemon can use this to detect a situation where a new table
+already exceeds the threshold.
+
+Thin provisioning
+-----------------
+
+i) Creating a new thinly-provisioned volume.
+
+  To create a new thinly- provisioned volume you must send a message to an
+  active pool device, /dev/mapper/pool in this example.
+
+    dmsetup message /dev/mapper/pool 0 "create_thin 0"
+
+  Here '0' is an identifier for the volume, a 24-bit number.  It's up
+  to the caller to allocate and manage these identifiers.  If the
+  identifier is already in use, the message will fail with -EEXIST.
+
+ii) Using a thinly-provisioned volume.
+
+  Thinly-provisioned volumes are activated using the 'thin' target:
+
+    dmsetup create thin --table "0 2097152 thin /dev/mapper/pool 0"
+
+  The last parameter is the identifier for the thinp device.
+
+Internal snapshots
+------------------
+
+i) Creating an internal snapshot.
+
+  Snapshots are created with another message to the pool.
+
+  N.B.  If the origin device that you wish to snapshot is active, you
+  must suspend it before creating the snapshot to avoid corruption.
+  This is NOT enforced at the moment, so please be careful!
+
+    dmsetup suspend /dev/mapper/thin
+    dmsetup message /dev/mapper/pool 0 "create_snap 1 0"
+    dmsetup resume /dev/mapper/thin
+
+  Here '1' is the identifier for the volume, a 24-bit number.  '0' is the
+  identifier for the origin device.
+
+ii) Using an internal snapshot.
+
+  Once created, the user doesn't have to worry about any connection
+  between the origin and the snapshot.  Indeed the snapshot is no
+  different from any other thinly-provisioned device and can be
+  snapshotted itself via the same method.  It's perfectly legal to
+  have only one of them active, and there's no ordering requirement on
+  activating or removing them both.  (This differs from conventional
+  device-mapper snapshots.)
+
+  Activate it exactly the same way as any other thinly-provisioned volume:
+
+    dmsetup create snap --table "0 2097152 thin /dev/mapper/pool 1"
+
+Deactivation
+------------
+
+All devices using a pool must be deactivated before the pool itself
+can be.
+
+    dmsetup remove thin
+    dmsetup remove snap
+    dmsetup remove pool
+
+Reference
+=========
+
+'thin-pool' target
+------------------
+
+i) Constructor
+
+    thin-pool <metadata dev> <data dev> <data block size (sectors)> \
+	      <low water mark (blocks)> [<number of feature args> [<arg>]*]
+
+    Optional feature arguments:
+    - 'skip_block_zeroing': skips the zeroing of newly-provisioned blocks.
+
+    Data block size must be between 64KB (128 sectors) and 1GB
+    (2097152 sectors) inclusive.
+
+
+ii) Status
+
+    <transaction id> <used metadata blocks>/<total metadata blocks>
+    <used data blocks>/<total data blocks> <held metadata root>
+
+
+    transaction id:
+	A 64-bit number used by userspace to help synchronise with metadata
+	from volume managers.
+
+    used data blocks / total data blocks
+	If the number of free blocks drops below the pool's low water mark a
+	dm event will be sent to userspace.  This event is edge-triggered and
+	it will occur only once after each resume so volume manager writers
+	should register for the event and then check the target's status.
+
+    held metadata root:
+	The location, in sectors, of the metadata root that has been
+	'held' for userspace read access.  '-' indicates there is no
+	held root.  This feature is not yet implemented so '-' is
+	always returned.
+
+iii) Messages
+
+    create_thin <dev id>
+
+	Create a new thinly-provisioned device.
+	<dev id> is an arbitrary unique 24-bit identifier chosen by
+	the caller.
+
+    create_snap <dev id> <origin id>
+
+	Create a new snapshot of another thinly-provisioned device.
+	<dev id> is an arbitrary unique 24-bit identifier chosen by
+	the caller.
+	<origin id> is the identifier of the thinly-provisioned device
+	of which the new device will be a snapshot.
+
+    delete <dev id>
+
+	Deletes a thin device.  Irreversible.
+
+    trim <dev id> <new size in sectors>
+
+	Delete mappings from the end of a thin device.  Irreversible.
+	You might want to use this if you're reducing the size of
+	your thinly-provisioned device.  In many cases, due to the
+	sharing of blocks between devices, it is not possible to
+	determine in advance how much space 'trim' will release.  (In
+	future a userspace tool might be able to perform this
+	calculation.)
+
+    set_transaction_id <current id> <new id>
+
+	Userland volume managers, such as LVM, need a way to
+	synchronise their external metadata with the internal metadata of the
+	pool target.  The thin-pool target offers to store an
+	arbitrary 64-bit transaction id and return it on the target's
+	status line.  To avoid races you must provide what you think
+	the current transaction id is when you change it with this
+	compare-and-swap message.
+
+'thin' target
+-------------
+
+i) Constructor
+
+    thin <pool dev> <dev id>
+
+    pool dev:
+	the thin-pool device, e.g. /dev/mapper/my_pool or 253:0
+
+    dev id:
+	the internal device identifier of the device to be
+	activated.
+
+The pool doesn't store any size against the thin devices.  If you
+load a thin target that is smaller than you've been using previously,
+then you'll have no access to blocks mapped beyond the end.  If you
+load a target that is bigger than before, then extra blocks will be
+provisioned as and when needed.
+
+If you wish to reduce the size of your thin device and potentially
+regain some space then send the 'trim' message to the pool.
+
+ii) Status
+
+     <nr mapped sectors> <highest mapped sector>
diff --git a/Documentation/devicetree/bindings/arm/calxeda.txt b/Documentation/devicetree/bindings/arm/calxeda.txt
new file mode 100644
index 0000000..4755caa
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/calxeda.txt
@@ -0,0 +1,8 @@
+Calxeda Highbank Platforms Device Tree Bindings
+-----------------------------------------------
+
+Boards with Calxeda Cortex-A9 based Highbank SOC shall have the following
+properties.
+
+Required root node properties:
+    - compatible = "calxeda,highbank";
diff --git a/Documentation/devicetree/bindings/arm/fsl.txt b/Documentation/devicetree/bindings/arm/fsl.txt
new file mode 100644
index 0000000..c9848ad
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/fsl.txt
@@ -0,0 +1,26 @@
+Freescale i.MX Platforms Device Tree Bindings
+-----------------------------------------------
+
+i.MX51 Babbage Board
+Required root node properties:
+    - compatible = "fsl,imx51-babbage", "fsl,imx51";
+
+i.MX53 Automotive Reference Design Board
+Required root node properties:
+    - compatible = "fsl,imx53-ard", "fsl,imx53";
+
+i.MX53 Evaluation Kit
+Required root node properties:
+    - compatible = "fsl,imx53-evk", "fsl,imx53";
+
+i.MX53 Quick Start Board
+Required root node properties:
+    - compatible = "fsl,imx53-qsb", "fsl,imx53";
+
+i.MX53 Smart Mobile Reference Design Board
+Required root node properties:
+    - compatible = "fsl,imx53-smd", "fsl,imx53";
+
+i.MX6 Quad SABRE Automotive Board
+Required root node properties:
+    - compatible = "fsl,imx6q-sabreauto", "fsl,imx6q";
diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt
new file mode 100644
index 0000000..52916b4
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/gic.txt
@@ -0,0 +1,55 @@
+* ARM Generic Interrupt Controller
+
+ARM SMP cores are often associated with a GIC, providing per processor
+interrupts (PPI), shared processor interrupts (SPI) and software
+generated interrupts (SGI).
+
+Primary GIC is attached directly to the CPU and typically has PPIs and SGIs.
+Secondary GICs are cascaded into the upward interrupt controller and do not
+have PPIs or SGIs.
+
+Main node required properties:
+
+- compatible : should be one of:
+	"arm,cortex-a9-gic"
+	"arm,arm11mp-gic"
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source.  The type shall be a <u32> and the value shall be 3.
+
+  The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
+  interrupts.
+
+  The 2nd cell contains the interrupt number for the interrupt type.
+  SPI interrupts are in the range [0-987].  PPI interrupts are in the
+  range [0-15].
+
+  The 3rd cell is the flags, encoded as follows:
+	bits[3:0] trigger type and level flags.
+		1 = low-to-high edge triggered
+		2 = high-to-low edge triggered
+		4 = active high level-sensitive
+		8 = active low level-sensitive
+	bits[15:8] PPI interrupt cpu mask.  Each bit corresponds to each of
+	the 8 possible cpus attached to the GIC.  A bit set to '1' indicated
+	the interrupt is wired to that CPU.  Only valid for PPI interrupts.
+
+- reg : Specifies base physical address(s) and size of the GIC registers. The
+  first region is the GIC distributor register base and size. The 2nd region is
+  the GIC cpu interface register base and size.
+
+Optional
+- interrupts	: Interrupt source of the parent interrupt controller. Only
+  present on secondary GICs.
+
+Example:
+
+	intc: interrupt-controller@fff11000 {
+		compatible = "arm,cortex-a9-gic";
+		#interrupt-cells = <3>;
+		#address-cells = <1>;
+		interrupt-controller;
+		reg = <0xfff11000 0x1000>,
+		      <0xfff10100 0x100>;
+	};
+
diff --git a/Documentation/devicetree/bindings/arm/omap/dsp.txt b/Documentation/devicetree/bindings/arm/omap/dsp.txt
new file mode 100644
index 0000000..d3830a3
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/omap/dsp.txt
@@ -0,0 +1,14 @@
+* TI - DSP (Digital Signal Processor)
+
+TI DSP included in OMAP SoC
+
+Required properties:
+- compatible : Should be "ti,omap3-c64" for OMAP3 & 4
+- ti,hwmods: "dsp"
+
+Examples:
+
+dsp {
+    compatible = "ti,omap3-c64";
+    ti,hwmods = "dsp";
+};
diff --git a/Documentation/devicetree/bindings/arm/omap/iva.txt b/Documentation/devicetree/bindings/arm/omap/iva.txt
new file mode 100644
index 0000000..6d62951
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/omap/iva.txt
@@ -0,0 +1,19 @@
+* TI - IVA (Imaging and Video Accelerator) subsystem
+
+The IVA contain various audio, video or imaging HW accelerator
+depending of the version.
+
+Required properties:
+- compatible : Should be:
+  - "ti,ivahd" for OMAP4
+  - "ti,iva2.2" for OMAP3
+  - "ti,iva2.1" for OMAP2430
+  - "ti,iva1" for OMAP2420
+- ti,hwmods: "iva"
+
+Examples:
+
+iva {
+    compatible = "ti,ivahd", "ti,iva";
+    ti,hwmods = "iva";
+};
diff --git a/Documentation/devicetree/bindings/arm/omap/l3-noc.txt b/Documentation/devicetree/bindings/arm/omap/l3-noc.txt
new file mode 100644
index 0000000..6888a5e
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/omap/l3-noc.txt
@@ -0,0 +1,19 @@
+* TI - L3 Network On Chip (NoC)
+
+This version is an implementation of the generic NoC IP
+provided by Arteris.
+
+Required properties:
+- compatible : Should be "ti,omap3-l3-smx" for OMAP3 family
+               Should be "ti,omap4-l3-noc" for OMAP4 family
+- ti,hwmods: "l3_main_1", ... One hwmod for each noc domain.
+
+Examples:
+
+ocp {
+	compatible = "ti,omap4-l3-noc", "simple-bus";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
+	ti,hwmods = "l3_main_1", "l3_main_2", "l3_main_3";
+};
diff --git a/Documentation/devicetree/bindings/arm/omap/mpu.txt b/Documentation/devicetree/bindings/arm/omap/mpu.txt
new file mode 100644
index 0000000..1a5a42c
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/omap/mpu.txt
@@ -0,0 +1,27 @@
+* TI - MPU (Main Processor Unit) subsystem
+
+The MPU subsystem contain one or several ARM cores
+depending of the version.
+The MPU contain CPUs, GIC, L2 cache and a local PRCM.
+
+Required properties:
+- compatible : Should be "ti,omap3-mpu" for OMAP3
+               Should be "ti,omap4-mpu" for OMAP4
+- ti,hwmods: "mpu"
+
+Examples:
+
+- For an OMAP4 SMP system:
+
+mpu {
+    compatible = "ti,omap4-mpu";
+    ti,hwmods = "mpu";
+};
+
+
+- For an OMAP3 monocore system:
+
+mpu {
+    compatible = "ti,omap3-mpu";
+    ti,hwmods = "mpu";
+};
diff --git a/Documentation/devicetree/bindings/arm/omap/omap.txt b/Documentation/devicetree/bindings/arm/omap/omap.txt
new file mode 100644
index 0000000..dbdab40
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/omap/omap.txt
@@ -0,0 +1,43 @@
+* Texas Instruments OMAP
+
+OMAP is currently using a static file per SoC family to describe the
+IPs present in the SoC.
+On top of that an omap_device is created to extend the platform_device
+capabilities and to allow binding with one or several hwmods.
+The hwmods will contain all the information to build the device:
+adresse range, irq lines, dma lines, interconnect, PRCM register,
+clock domain, input clocks.
+For the moment just point to the existing hwmod, the next step will be
+to move data from hwmod to device-tree representation.
+
+
+Required properties:
+- compatible: Every devices present in OMAP SoC should be in the
+  form: "ti,XXX"
+- ti,hwmods: list of hwmod names (ascii strings), that comes from the OMAP
+  HW documentation, attached to a device. Must contain at least
+  one hwmod.
+
+Optional properties:
+- ti,no_idle_on_suspend: When present, it prevents the PM to idle the module
+  during suspend.
+
+
+Example:
+
+spinlock@1 {
+    compatible = "ti,omap4-spinlock";
+    ti,hwmods = "spinlock";
+};
+
+
+Boards:
+
+- OMAP3 BeagleBoard : Low cost community board
+  compatible = "ti,omap3-beagle", "ti,omap3"
+
+- OMAP4 SDP : Software Developement Board
+  compatible = "ti,omap4-sdp", "ti,omap4430"
+
+- OMAP4 PandaBoard : Low cost community board
+  compatible = "ti,omap4-panda", "ti,omap4430"
diff --git a/Documentation/devicetree/bindings/arm/picoxcell.txt b/Documentation/devicetree/bindings/arm/picoxcell.txt
new file mode 100644
index 0000000..e75c0ef
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/picoxcell.txt
@@ -0,0 +1,24 @@
+Picochip picoXcell device tree bindings.
+========================================
+
+Required root node properties:
+    - compatible:
+	- "picochip,pc7302-pc3x3" : PC7302 development board with PC3X3 device.
+	- "picochip,pc7302-pc3x2" : PC7302 development board with PC3X2 device.
+	- "picochip,pc3x3" : picoXcell PC3X3 device based board.
+	- "picochip,pc3x2" : picoXcell PC3X2 device based board.
+
+Timers required properties:
+    - compatible = "picochip,pc3x2-timer"
+    - interrupts : The single IRQ line for the timer.
+    - clock-freq : The frequency in HZ of the timer.
+    - reg : The register bank for the timer.
+
+Note: two timers are required - one for the scheduler clock and one for the
+event tick/NOHZ.
+
+VIC required properties:
+    - compatible = "arm,pl192-vic".
+    - interrupt-controller.
+    - reg : The register bank for the device.
+    - #interrupt-cells : Must be 1.
diff --git a/Documentation/devicetree/bindings/crypto/picochip-spacc.txt b/Documentation/devicetree/bindings/crypto/picochip-spacc.txt
new file mode 100644
index 0000000..d8609ec
--- /dev/null
+++ b/Documentation/devicetree/bindings/crypto/picochip-spacc.txt
@@ -0,0 +1,23 @@
+Picochip picoXcell SPAcc (Security Protocol Accelerator) bindings
+
+Picochip picoXcell devices contain crypto offload engines that may be used for
+IPSEC and femtocell layer 2 ciphering.
+
+Required properties:
+  - compatible : "picochip,spacc-ipsec" for the IPSEC offload engine
+    "picochip,spacc-l2" for the femtocell layer 2 ciphering engine.
+  - reg : Offset and length of the register set for this device
+  - interrupt-parent : The interrupt controller that controls the SPAcc
+    interrupt.
+  - interrupts : The interrupt line from the SPAcc.
+  - ref-clock : The input clock that drives the SPAcc.
+
+Example SPAcc node:
+
+spacc@10000 {
+	compatible = "picochip,spacc-ipsec";
+	reg = <0x100000 0x10000>;
+	interrupt-parent = <&vic0>;
+	interrupts = <24>;
+	ref-clock = <&ipsec_clk>, "ref";
+};
diff --git a/Documentation/devicetree/bindings/i2c/fsl-imx-i2c.txt b/Documentation/devicetree/bindings/i2c/fsl-imx-i2c.txt
new file mode 100644
index 0000000..f3cf43b
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/fsl-imx-i2c.txt
@@ -0,0 +1,25 @@
+* Freescale Inter IC (I2C) and High Speed Inter IC (HS-I2C) for i.MX
+
+Required properties:
+- compatible : Should be "fsl,<chip>-i2c"
+- reg : Should contain I2C/HS-I2C registers location and length
+- interrupts : Should contain I2C/HS-I2C interrupt
+
+Optional properties:
+- clock-frequency : Constains desired I2C/HS-I2C bus clock frequency in Hz.
+  The absence of the propoerty indicates the default frequency 100 kHz.
+
+Examples:
+
+i2c@83fc4000 { /* I2C2 on i.MX51 */
+	compatible = "fsl,imx51-i2c", "fsl,imx1-i2c";
+	reg = <0x83fc4000 0x4000>;
+	interrupts = <63>;
+};
+
+i2c@70038000 { /* HS-I2C on i.MX51 */
+	compatible = "fsl,imx51-i2c", "fsl,imx1-i2c";
+	reg = <0x70038000 0x4000>;
+	interrupts = <64>;
+	clock-frequency = <400000>;
+};
diff --git a/Documentation/devicetree/bindings/i2c/samsung-i2c.txt b/Documentation/devicetree/bindings/i2c/samsung-i2c.txt
new file mode 100644
index 0000000..38832c7
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/samsung-i2c.txt
@@ -0,0 +1,39 @@
+* Samsung's I2C controller
+
+The Samsung's I2C controller is used to interface with I2C devices.
+
+Required properties:
+  - compatible: value should be either of the following.
+      (a) "samsung, s3c2410-i2c", for i2c compatible with s3c2410 i2c.
+      (b) "samsung, s3c2440-i2c", for i2c compatible with s3c2440 i2c.
+  - reg: physical base address of the controller and length of memory mapped
+    region.
+  - interrupts: interrupt number to the cpu.
+  - samsung,i2c-sda-delay: Delay (in ns) applied to data line (SDA) edges.
+  - gpios: The order of the gpios should be the following: <SDA, SCL>.
+    The gpio specifier depends on the gpio controller.
+
+Optional properties:
+  - samsung,i2c-slave-addr: Slave address in multi-master enviroment. If not
+    specified, default value is 0.
+  - samsung,i2c-max-bus-freq: Desired frequency in Hz of the bus. If not
+    specified, the default value in Hz is 100000.
+
+Example:
+
+	i2c@13870000 {
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0x13870000 0x100>;
+		interrupts = <345>;
+		samsung,i2c-sda-delay = <100>;
+		samsung,i2c-max-bus-freq = <100000>;
+		gpios = <&gpd1 2 0 /* SDA */
+			 &gpd1 3 0 /* SCL */>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		wm8994@1a {
+			compatible = "wlf,wm8994";
+			reg = <0x1a>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt b/Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt
new file mode 100644
index 0000000..36f82db
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt
@@ -0,0 +1,5 @@
+NVIDIA Tegra 2 pinmux controller
+
+Required properties:
+- compatible : "nvidia,tegra20-pinmux"
+
diff --git a/Documentation/devicetree/bindings/tty/serial/msm_serial.txt b/Documentation/devicetree/bindings/tty/serial/msm_serial.txt
new file mode 100644
index 0000000..aef383e
--- /dev/null
+++ b/Documentation/devicetree/bindings/tty/serial/msm_serial.txt
@@ -0,0 +1,27 @@
+* Qualcomm MSM UART
+
+Required properties:
+- compatible :
+	- "qcom,msm-uart", and one of "qcom,msm-hsuart" or
+	  "qcom,msm-lsuart".
+- reg : offset and length of the register set for the device
+	for the hsuart operating in compatible mode, there should be a
+	second pair describing the gsbi registers.
+- interrupts : should contain the uart interrupt.
+
+There are two different UART blocks used in MSM devices,
+"qcom,msm-hsuart" and "qcom,msm-lsuart".  The msm-serial driver is
+able to handle both of these, and matches against the "qcom,msm-uart"
+as the compatibility.
+
+The registers for the "qcom,msm-hsuart" device need to specify both
+register blocks, even for the common driver.
+
+Example:
+
+	uart@19c400000 {
+		compatible = "qcom,msm-hsuart", "qcom,msm-uart";
+		reg = <0x19c40000 0x1000>,
+		      <0x19c00000 0x1000>;
+		interrupts = <195>;
+	};
diff --git a/Documentation/devicetree/bindings/virtio/mmio.txt b/Documentation/devicetree/bindings/virtio/mmio.txt
new file mode 100644
index 0000000..5069c1b
--- /dev/null
+++ b/Documentation/devicetree/bindings/virtio/mmio.txt
@@ -0,0 +1,17 @@
+* virtio memory mapped device
+
+See http://ozlabs.org/~rusty/virtio-spec/ for more details.
+
+Required properties:
+
+- compatible:	"virtio,mmio" compatibility string
+- reg:		control registers base address and size including configuration space
+- interrupts:	interrupt generated by the device
+
+Example:
+
+	virtio_block@3000 {
+		compatible = "virtio,mmio";
+		reg = <0x3000 0x100>;
+		interrupts = <41>;
+	}
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 7c799fc..3d84912 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -133,41 +133,6 @@ Who:	Pavel Machek <pavel@ucw.cz>
 
 ---------------------------
 
-What:	sys_sysctl
-When:	September 2010
-Option: CONFIG_SYSCTL_SYSCALL
-Why:	The same information is available in a more convenient from
-	/proc/sys, and none of the sysctl variables appear to be
-	important performance wise.
-
-	Binary sysctls are a long standing source of subtle kernel
-	bugs and security issues.
-
-	When I looked several months ago all I could find after
-	searching several distributions were 5 user space programs and
-	glibc (which falls back to /proc/sys) using this syscall.
-
-	The man page for sysctl(2) documents it as unusable for user
-	space programs.
-
-	sysctl(2) is not generally ABI compatible to a 32bit user
-	space application on a 64bit and a 32bit kernel.
-
-	For the last several months the policy has been no new binary
-	sysctls and no one has put forward an argument to use them.
-
-	Binary sysctls issues seem to keep happening appearing so
-	properly deprecating them (with a warning to user space) and a
-	2 year grace warning period will mean eventually we can kill
-	them and end the pain.
-
-	In the mean time individual binary sysctls can be dealt with
-	in a piecewise fashion.
-
-Who:	Eric Biederman <ebiederm@xmission.com>
-
----------------------------
-
 What:	/proc/<pid>/oom_adj
 When:	August 2012
 Why:	/proc/<pid>/oom_adj allows userspace to influence the oom killer's
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 6533807..d819ba1 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -29,6 +29,7 @@ d_hash		no		no		no		maybe
 d_compare:	yes		no		no		maybe
 d_delete:	no		yes		no		no
 d_release:	no		no		yes		no
+d_prune:        no              yes             no              no
 d_iput:		no		no		yes		no
 d_dname:	no		no		no		no
 d_automount:	no		no		yes		no
diff --git a/Documentation/filesystems/ext3.txt b/Documentation/filesystems/ext3.txt
index 22f3a0e..b100adc 100644
--- a/Documentation/filesystems/ext3.txt
+++ b/Documentation/filesystems/ext3.txt
@@ -73,14 +73,6 @@ nobarrier	(*)	This also requires an IO stack which can support
 			also be used to enable or disable barriers, for
 			consistency with other ext3 mount options.
 
-orlov		(*)	This enables the new Orlov block allocator. It is
-			enabled by default.
-
-oldalloc		This disables the Orlov block allocator and enables
-			the old block allocator.  Orlov should have better
-			performance - we'd like to get some feedback if it's
-			the contrary for you.
-
 user_xattr		Enables Extended User Attributes.  Additionally, you
 			need to have extended attribute support enabled in the
 			kernel configuration (CONFIG_EXT3_FS_XATTR).  See the
diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt
index 232a575..4917cf2 100644
--- a/Documentation/filesystems/ext4.txt
+++ b/Documentation/filesystems/ext4.txt
@@ -160,7 +160,9 @@ noload			if the filesystem was not unmounted cleanly,
                      	lead to any number of problems.
 
 data=journal		All data are committed into the journal prior to being
-			written into the main file system.
+			written into the main file system.  Enabling
+			this mode will disable delayed allocation and
+			O_DIRECT support.
 
 data=ordered	(*)	All data are forced directly out to the main file
 			system prior to its metadata being committed to the
@@ -201,30 +203,19 @@ inode_readahead_blks=n	This tuning parameter controls the maximum
 			table readahead algorithm will pre-read into
 			the buffer cache.  The default value is 32 blocks.
 
-orlov		(*)	This enables the new Orlov block allocator. It is
-			enabled by default.
-
-oldalloc		This disables the Orlov block allocator and enables
-			the old block allocator.  Orlov should have better
-			performance - we'd like to get some feedback if it's
-			the contrary for you.
-
-user_xattr		Enables Extended User Attributes.  Additionally, you
-			need to have extended attribute support enabled in the
-			kernel configuration (CONFIG_EXT4_FS_XATTR).  See the
-			attr(5) manual page and http://acl.bestbits.at/ to
-			learn more about extended attributes.
-
-nouser_xattr		Disables Extended User Attributes.
-
-acl			Enables POSIX Access Control Lists support.
-			Additionally, you need to have ACL support enabled in
-			the kernel configuration (CONFIG_EXT4_FS_POSIX_ACL).
-			See the acl(5) manual page and http://acl.bestbits.at/
-			for more information.
+nouser_xattr		Disables Extended User Attributes. If you have extended
+			attribute support enabled in the kernel configuration
+			(CONFIG_EXT4_FS_XATTR), extended attribute support
+			is enabled by default on mount. See the attr(5) manual
+			page and http://acl.bestbits.at/ for more information
+			about extended attributes.
 
 noacl			This option disables POSIX Access Control List
-			support.
+			support. If ACL support is enabled in the kernel
+			configuration (CONFIG_EXT4_FS_POSIX_ACL), ACL is
+			enabled by default on mount. See the acl(5) manual
+			page and http://acl.bestbits.at/ for more information
+			about acl.
 
 bsddf		(*)	Make 'df' act like BSD.
 minixdf			Make 'df' act like Minix.
@@ -419,8 +410,8 @@ written to the journal first, and then to its final location.
 In the event of a crash, the journal can be replayed, bringing both data and
 metadata into a consistent state.  This mode is the slowest except when data
 needs to be read from and written to disk at the same time where it
-outperforms all others modes.  Currently ext4 does not have delayed
-allocation support if this data journalling mode is selected.
+outperforms all others modes.  Enabling this mode will disable delayed
+allocation and O_DIRECT support.
 
 /proc entries
 =============
diff --git a/Documentation/power/regulator/machine.txt b/Documentation/power/regulator/machine.txt
index b42419b..ce63af0 100644
--- a/Documentation/power/regulator/machine.txt
+++ b/Documentation/power/regulator/machine.txt
@@ -16,7 +16,7 @@ initialisation code by creating a struct regulator_consumer_supply for
 each regulator.
 
 struct regulator_consumer_supply {
-	struct device *dev;	/* consumer */
+	const char *dev_name;	/* consumer dev_name() */
 	const char *supply;	/* consumer supply - e.g. "vcc" */
 };
 
@@ -24,13 +24,13 @@ e.g. for the machine above
 
 static struct regulator_consumer_supply regulator1_consumers[] = {
 {
-	.dev	= &platform_consumerB_device.dev,
-	.supply	= "Vcc",
+	.dev_name	= "dev_name(consumer B)",
+	.supply		= "Vcc",
 },};
 
 static struct regulator_consumer_supply regulator2_consumers[] = {
 {
-	.dev	= &platform_consumerA_device.dev,
+	.dev	= "dev_name(consumer A"),
 	.supply	= "Vcc",
 },};
 
@@ -43,6 +43,7 @@ to their supply regulator :-
 
 static struct regulator_init_data regulator1_data = {
 	.constraints = {
+		.name = "Regulator-1",
 		.min_uV = 3300000,
 		.max_uV = 3300000,
 		.valid_modes_mask = REGULATOR_MODE_NORMAL,
@@ -51,13 +52,19 @@ static struct regulator_init_data regulator1_data = {
 	.consumer_supplies = regulator1_consumers,
 };
 
+The name field should be set to something that is usefully descriptive
+for the board for configuration of supplies for other regulators and
+for use in logging and other diagnostic output.  Normally the name
+used for the supply rail in the schematic is a good choice.  If no
+name is provided then the subsystem will choose one.
+
 Regulator-1 supplies power to Regulator-2. This relationship must be registered
 with the core so that Regulator-1 is also enabled when Consumer A enables its
 supply (Regulator-2). The supply regulator is set by the supply_regulator
-field below:-
+field below and co:-
 
 static struct regulator_init_data regulator2_data = {
-	.supply_regulator = "regulator_name",
+	.supply_regulator = "Regulator-1",
 	.constraints = {
 		.min_uV = 1800000,
 		.max_uV = 2000000,
diff --git a/Documentation/rapidio/rapidio.txt b/Documentation/rapidio/rapidio.txt
index be70ee1..c75694b 100644
--- a/Documentation/rapidio/rapidio.txt
+++ b/Documentation/rapidio/rapidio.txt
@@ -144,7 +144,7 @@ and the default device ID in order to access the device on the active port.
 
 After the host has completed enumeration of the entire network it releases
 devices by clearing device ID locks (calls rio_clear_locks()). For each endpoint
-in the system, it sets the Master Enable bit in the Port General Control CSR
+in the system, it sets the Discovered bit in the Port General Control CSR
 to indicate that enumeration is completed and agents are allowed to execute
 passive discovery of the network.
 
diff --git a/Documentation/rapidio/tsi721.txt b/Documentation/rapidio/tsi721.txt
new file mode 100644
index 0000000..335f3c6
--- /dev/null
+++ b/Documentation/rapidio/tsi721.txt
@@ -0,0 +1,49 @@
+RapidIO subsystem mport driver for IDT Tsi721 PCI Express-to-SRIO bridge.
+=========================================================================
+
+I. Overview
+
+This driver implements all currently defined RapidIO mport callback functions.
+It supports maintenance read and write operations, inbound and outbound RapidIO
+doorbells, inbound maintenance port-writes and RapidIO messaging.
+
+To generate SRIO maintenance transactions this driver uses one of Tsi721 DMA
+channels. This mechanism provides access to larger range of hop counts and
+destination IDs without need for changes in outbound window translation.
+
+RapidIO messaging support uses dedicated messaging channels for each mailbox.
+For inbound messages this driver uses destination ID matching to forward messages
+into the corresponding message queue. Messaging callbacks are implemented to be
+fully compatible with RIONET driver (Ethernet over RapidIO messaging services).
+
+II. Known problems
+
+  None.
+
+III. To do
+
+ Add DMA data transfers (non-messaging).
+ Add inbound region (SRIO-to-PCIe) mapping.
+
+IV. Version History
+
+  1.0.0 - Initial driver release.
+
+V.  License
+-----------------------------------------------
+
+  Copyright(c) 2011 Integrated Device Technology, Inc. All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by the Free
+  Software Foundation; either version 2 of the License, or (at your option)
+  any later version.
+
+  This program is distributed in the hope that it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+  more details.
+
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc.,
+  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
diff --git a/Documentation/virtual/uml/UserModeLinux-HOWTO.txt b/Documentation/virtual/uml/UserModeLinux-HOWTO.txt
index 5d0fc8b..77dfecf 100644
--- a/Documentation/virtual/uml/UserModeLinux-HOWTO.txt
+++ b/Documentation/virtual/uml/UserModeLinux-HOWTO.txt
@@ -134,13 +134,13 @@
 
   ______________________________________________________________________
 
-  11..  IInnttrroodduuccttiioonn
+  1.  Introduction
 
   Welcome to User Mode Linux.  It's going to be fun.
 
 
 
-  11..11..  HHooww iiss UUsseerr MMooddee LLiinnuuxx DDiiffffeerreenntt??
+  1.1.  How is User Mode Linux Different?
 
   Normally, the Linux Kernel talks straight to your hardware (video
   card, keyboard, hard drives, etc), and any programs which run ask the
@@ -181,7 +181,7 @@
 
 
 
-  11..22..  WWhhyy WWoouulldd II WWaanntt UUsseerr MMooddee LLiinnuuxx??
+  1.2.  Why Would I Want User Mode Linux?
 
 
   1. If User Mode Linux crashes, your host kernel is still fine.
@@ -206,12 +206,12 @@
 
 
 
-  22..  CCoommppiilliinngg tthhee kkeerrnneell aanndd mmoodduulleess
+  2.  Compiling the kernel and modules
 
 
 
 
-  22..11..  CCoommppiilliinngg tthhee kkeerrnneell
+  2.1.  Compiling the kernel
 
 
   Compiling the user mode kernel is just like compiling any other
@@ -322,7 +322,7 @@
   bug fixes and enhancements that have gone into subsequent releases.
 
 
-  22..22..  CCoommppiilliinngg aanndd iinnssttaalllliinngg kkeerrnneell mmoodduulleess
+  2.2.  Compiling and installing kernel modules
 
   UML modules are built in the same way as the native kernel (with the
   exception of the 'ARCH=um' that you always need for UML):
@@ -386,19 +386,19 @@
 
 
 
-  22..33..  CCoommppiilliinngg aanndd iinnssttaalllliinngg uummll__uuttiilliittiieess
+  2.3.  Compiling and installing uml_utilities
 
   Many features of the UML kernel require a user-space helper program,
   so a uml_utilities package is distributed separately from the kernel
   patch which provides these helpers. Included within this is:
 
-  +o  port-helper - Used by consoles which connect to xterms or ports
+  o  port-helper - Used by consoles which connect to xterms or ports
 
-  +o  tunctl - Configuration tool to create and delete tap devices
+  o  tunctl - Configuration tool to create and delete tap devices
 
-  +o  uml_net - Setuid binary for automatic tap device configuration
+  o  uml_net - Setuid binary for automatic tap device configuration
 
-  +o  uml_switch - User-space virtual switch required for daemon
+  o  uml_switch - User-space virtual switch required for daemon
      transport
 
      The uml_utilities tree is compiled with:
@@ -423,11 +423,11 @@
 
 
 
-  33..  RRuunnnniinngg UUMMLL aanndd llooggggiinngg iinn
+  3.  Running UML and logging in
 
 
 
-  33..11..  RRuunnnniinngg UUMMLL
+  3.1.  Running UML
 
   It runs on 2.2.15 or later, and all 2.4 kernels.
 
@@ -454,7 +454,7 @@
 
 
 
-  33..22..  LLooggggiinngg iinn
+  3.2.  Logging in
 
 
 
@@ -468,7 +468,7 @@
 
   There are a couple of other ways to log in:
 
-  +o  On a virtual console
+  o  On a virtual console
 
 
 
@@ -480,7 +480,7 @@
 
 
 
-  +o  Over the serial line
+  o  Over the serial line
 
 
      In the boot output, find a line that looks like:
@@ -503,7 +503,7 @@
 
 
 
-  +o  Over the net
+  o  Over the net
 
 
      If the network is running, then you can telnet to the virtual
@@ -514,13 +514,13 @@
   down and the process will exit.
 
 
-  33..33..  EExxaammpplleess
+  3.3.  Examples
 
   Here are some examples of UML in action:
 
-  +o  A login session <http://user-mode-linux.sourceforge.net/login.html>
+  o  A login session <http://user-mode-linux.sourceforge.net/login.html>
 
-  +o  A virtual network <http://user-mode-linux.sourceforge.net/net.html>
+  o  A virtual network <http://user-mode-linux.sourceforge.net/net.html>
 
 
 
@@ -528,12 +528,12 @@
 
 
 
-  44..  UUMMLL oonn 22GG//22GG hhoossttss
+  4.  UML on 2G/2G hosts
 
 
 
 
-  44..11..  IInnttrroodduuccttiioonn
+  4.1.  Introduction
 
 
   Most Linux machines are configured so that the kernel occupies the
@@ -546,7 +546,7 @@
 
 
 
-  44..22..  TThhee pprroobblleemm
+  4.2.  The problem
 
 
   The prebuilt UML binaries on this site will not run on 2G/2G hosts
@@ -558,7 +558,7 @@
 
 
 
-  44..33..  TThhee ssoolluuttiioonn
+  4.3.  The solution
 
 
   The fix for this is to rebuild UML from source after enabling
@@ -576,7 +576,7 @@
 
 
 
-  55..  SSeettttiinngg uupp sseerriiaall lliinneess aanndd ccoonnssoolleess
+  5.  Setting up serial lines and consoles
 
 
   It is possible to attach UML serial lines and consoles to many types
@@ -586,12 +586,12 @@
   You can attach them to host ptys, ttys, file descriptors, and ports.
   This allows you to do things like
 
-  +o  have a UML console appear on an unused host console,
+  o  have a UML console appear on an unused host console,
 
-  +o  hook two virtual machines together by having one attach to a pty
+  o  hook two virtual machines together by having one attach to a pty
      and having the other attach to the corresponding tty
 
-  +o  make a virtual machine accessible from the net by attaching a
+  o  make a virtual machine accessible from the net by attaching a
      console to a port on the host.
 
 
@@ -599,7 +599,7 @@
 
 
 
-  55..11..  SSppeecciiffyyiinngg tthhee ddeevviiccee
+  5.1.  Specifying the device
 
   Devices are specified with "con" or "ssl" (console or serial line,
   respectively), optionally with a device number if you are talking
@@ -626,13 +626,13 @@
 
 
 
-  55..22..  SSppeecciiffyyiinngg tthhee cchhaannnneell
+  5.2.  Specifying the channel
 
   There are a number of different types of channels to attach a UML
   device to, each with a different way of specifying exactly what to
   attach to.
 
-  +o  pseudo-terminals - device=pty pts terminals - device=pts
+  o  pseudo-terminals - device=pty pts terminals - device=pts
 
 
      This will cause UML to allocate a free host pseudo-terminal for the
@@ -640,20 +640,20 @@
      log.  You access it by attaching a terminal program to the
      corresponding tty:
 
-  +o  screen /dev/pts/n
+  o  screen /dev/pts/n
 
-  +o  screen /dev/ttyxx
+  o  screen /dev/ttyxx
 
-  +o  minicom -o -p /dev/ttyxx - minicom seems not able to handle pts
+  o  minicom -o -p /dev/ttyxx - minicom seems not able to handle pts
      devices
 
-  +o  kermit - start it up, 'open' the device, then 'connect'
+  o  kermit - start it up, 'open' the device, then 'connect'
 
 
 
 
 
-  +o  terminals - device=tty:tty device file
+  o  terminals - device=tty:tty device file
 
 
      This will make UML attach the device to the specified tty (i.e
@@ -672,7 +672,7 @@
 
 
 
-  +o  xterms - device=xterm
+  o  xterms - device=xterm
 
 
      UML will run an xterm and the device will be attached to it.
@@ -681,7 +681,7 @@
 
 
 
-  +o  Port - device=port:port number
+  o  Port - device=port:port number
 
 
      This will attach the UML devices to the specified host port.
@@ -725,7 +725,7 @@
 
 
 
-  +o  already-existing file descriptors - device=file descriptor
+  o  already-existing file descriptors - device=file descriptor
 
 
      If you set up a file descriptor on the UML command line, you can
@@ -743,7 +743,7 @@
 
 
 
-  +o  Nothing - device=null
+  o  Nothing - device=null
 
 
      This allows the device to be opened, in contrast to 'none', but
@@ -754,7 +754,7 @@
 
 
 
-  +o  None - device=none
+  o  None - device=none
 
 
      This causes the device to disappear.
@@ -770,7 +770,7 @@
 
 
 
-  will cause serial line 3 to accept input on the host's /dev/tty3 and
+  will cause serial line 3 to accept input on the host's /dev/tty2 and
   display output on an xterm.  That's a silly example - the most common
   use of this syntax is to reattach the main console to stdin and stdout
   as shown above.
@@ -785,7 +785,7 @@
 
 
 
-  55..33..  EExxaammpplleess
+  5.3.  Examples
 
   There are a number of interesting things you can do with this
   capability.
@@ -838,7 +838,7 @@
   prompt of the other virtual machine.
 
 
-  66..  SSeettttiinngg uupp tthhee nneettwwoorrkk
+  6.  Setting up the network
 
 
 
@@ -858,19 +858,19 @@
   There are currently five transport types available for a UML virtual
   machine to exchange packets with other hosts:
 
-  +o  ethertap
+  o  ethertap
 
-  +o  TUN/TAP
+  o  TUN/TAP
 
-  +o  Multicast
+  o  Multicast
 
-  +o  a switch daemon
+  o  a switch daemon
 
-  +o  slip
+  o  slip
 
-  +o  slirp
+  o  slirp
 
-  +o  pcap
+  o  pcap
 
      The TUN/TAP, ethertap, slip, and slirp transports allow a UML
      instance to exchange packets with the host.  They may be directed
@@ -893,28 +893,28 @@
   With so many host transports, which one should you use?  Here's when
   you should use each one:
 
-  +o  ethertap - if you want access to the host networking and it is
+  o  ethertap - if you want access to the host networking and it is
      running 2.2
 
-  +o  TUN/TAP - if you want access to the host networking and it is
+  o  TUN/TAP - if you want access to the host networking and it is
      running 2.4.  Also, the TUN/TAP transport is able to use a
      preconfigured device, allowing it to avoid using the setuid uml_net
      helper, which is a security advantage.
 
-  +o  Multicast - if you want a purely virtual network and you don't want
+  o  Multicast - if you want a purely virtual network and you don't want
      to set up anything but the UML
 
-  +o  a switch daemon - if you want a purely virtual network and you
+  o  a switch daemon - if you want a purely virtual network and you
      don't mind running the daemon in order to get somewhat better
      performance
 
-  +o  slip - there is no particular reason to run the slip backend unless
+  o  slip - there is no particular reason to run the slip backend unless
      ethertap and TUN/TAP are just not available for some reason
 
-  +o  slirp - if you don't have root access on the host to setup
+  o  slirp - if you don't have root access on the host to setup
      networking, or if you don't want to allocate an IP to your UML
 
-  +o  pcap - not much use for actual network connectivity, but great for
+  o  pcap - not much use for actual network connectivity, but great for
      monitoring traffic on the host
 
      Ethertap is available on 2.4 and works fine.  TUN/TAP is preferred
@@ -926,7 +926,7 @@
      exploit the helper's root privileges.
 
 
-  66..11..  GGeenneerraall sseettuupp
+  6.1.  General setup
 
   First, you must have the virtual network enabled in your UML.  If are
   running a prebuilt kernel from this site, everything is already
@@ -995,7 +995,7 @@
 
 
 
-  66..22..  UUsseerrssppaaccee ddaaeemmoonnss
+  6.2.  Userspace daemons
 
   You will likely need the setuid helper, or the switch daemon, or both.
   They are both installed with the RPM and deb, so if you've installed
@@ -1011,7 +1011,7 @@
 
 
 
-  66..33..  SSppeecciiffyyiinngg eetthheerrnneett aaddddrreesssseess
+  6.3.  Specifying ethernet addresses
 
   Below, you will see that the TUN/TAP, ethertap, and daemon interfaces
   allow you to specify hardware addresses for the virtual ethernet
@@ -1023,11 +1023,11 @@
   sufficient to guarantee a unique hardware address for the device.  A
   couple of exceptions are:
 
-  +o  Another set of virtual ethernet devices are on the same network and
+  o  Another set of virtual ethernet devices are on the same network and
      they are assigned hardware addresses using a different scheme which
      may conflict with the UML IP address-based scheme
 
-  +o  You aren't going to use the device for IP networking, so you don't
+  o  You aren't going to use the device for IP networking, so you don't
      assign the device an IP address
 
      If you let the driver provide the hardware address, you should make
@@ -1049,7 +1049,7 @@
 
 
 
-  66..44..  UUMMLL iinntteerrffaaccee sseettuupp
+  6.4.  UML interface setup
 
   Once the network devices have been described on the command line, you
   should boot UML and log in.
@@ -1131,7 +1131,7 @@
 
 
 
-  66..55..  MMuullttiiccaasstt
+  6.5.  Multicast
 
   The simplest way to set up a virtual network between multiple UMLs is
   to use the mcast transport.  This was written by Harald Welte and is
@@ -1194,7 +1194,7 @@
 
 
 
-  66..66..  TTUUNN//TTAAPP wwiitthh tthhee uummll__nneett hheellppeerr
+  6.6.  TUN/TAP with the uml_net helper
 
   TUN/TAP is the preferred mechanism on 2.4 to exchange packets with the
   host.  The TUN/TAP backend has been in UML since 2.4.9-3um.
@@ -1247,10 +1247,10 @@
   There are a couple potential problems with running the TUN/TAP
   transport on a 2.4 host kernel
 
-  +o  TUN/TAP seems not to work on 2.4.3 and earlier.  Upgrade the host
+  o  TUN/TAP seems not to work on 2.4.3 and earlier.  Upgrade the host
      kernel or use the ethertap transport.
 
-  +o  With an upgraded kernel, TUN/TAP may fail with
+  o  With an upgraded kernel, TUN/TAP may fail with
 
 
        File descriptor in bad state
@@ -1269,7 +1269,7 @@
 
 
 
-  66..77..  TTUUNN//TTAAPP wwiitthh aa pprreeccoonnffiigguurreedd ttaapp ddeevviiccee
+  6.7.  TUN/TAP with a preconfigured tap device
 
   If you prefer not to have UML use uml_net (which is somewhat
   insecure), with UML 2.4.17-11, you can set up a TUN/TAP device
@@ -1277,7 +1277,7 @@
   there is no need for root assistance.  Setting up the device is done
   as follows:
 
-  +o  Create the device with tunctl (available from the UML utilities
+  o  Create the device with tunctl (available from the UML utilities
      tarball)
 
 
@@ -1291,7 +1291,7 @@
   where uid is the user id or username that UML will be run as.  This
   will tell you what device was created.
 
-  +o  Configure the device IP (change IP addresses and device name to
+  o  Configure the device IP (change IP addresses and device name to
      suit)
 
 
@@ -1303,7 +1303,7 @@
 
 
 
-  +o  Set up routing and arping if desired - this is my recipe, there are
+  o  Set up routing and arping if desired - this is my recipe, there are
      other ways of doing the same thing
 
 
@@ -1338,7 +1338,7 @@
   utility which reads the information from a config file and sets up
   devices at boot time.
 
-  +o  Rather than using up two IPs and ARPing for one of them, you can
+  o  Rather than using up two IPs and ARPing for one of them, you can
      also provide direct access to your LAN by the UML by using a
      bridge.
 
@@ -1417,7 +1417,7 @@
   Note that 'br0' should be setup using ifconfig with the existing IP
   address of eth0, as eth0 no longer has its own IP.
 
-  +o
+  o
 
 
      Also, the /dev/net/tun device must be writable by the user running
@@ -1438,11 +1438,11 @@
   devices and chgrp /dev/net/tun to that group with mode 664 or 660.
 
 
-  +o  Once the device is set up, run UML with 'eth0=tuntap,device name'
+  o  Once the device is set up, run UML with 'eth0=tuntap,device name'
      (i.e. 'eth0=tuntap,tap0') on the command line (or do it with the
      mconsole config command).
 
-  +o  Bring the eth device up in UML and you're in business.
+  o  Bring the eth device up in UML and you're in business.
 
      If you don't want that tap device any more, you can make it non-
      persistent with
@@ -1465,7 +1465,7 @@
 
 
 
-  66..88..  EEtthheerrttaapp
+  6.8.  Ethertap
 
   Ethertap is the general mechanism on 2.2 for userspace processes to
   exchange packets with the kernel.
@@ -1561,9 +1561,9 @@
 
 
 
-  66..99..  TThhee sswwiittcchh ddaaeemmoonn
+  6.9.  The switch daemon
 
-  NNoottee: This is the daemon formerly known as uml_router, but which was
+  Note: This is the daemon formerly known as uml_router, but which was
   renamed so the network weenies of the world would stop growling at me.
 
 
@@ -1649,7 +1649,7 @@
 
 
 
-  66..1100..  SSlliipp
+  6.10.  Slip
 
   Slip is another, less general, mechanism for a process to communicate
   with the host networking.  In contrast to the ethertap interface,
@@ -1681,7 +1681,7 @@
 
 
 
-  66..1111..  SSlliirrpp
+  6.11.  Slirp
 
   slirp uses an external program, usually /usr/bin/slirp, to provide IP
   only networking connectivity through the host. This is similar to IP
@@ -1737,7 +1737,7 @@
 
 
 
-  66..1122..  ppccaapp
+  6.12.  pcap
 
   The pcap transport is attached to a UML ethernet device on the command
   line or with uml_mconsole with the following syntax:
@@ -1777,7 +1777,7 @@
 
 
 
-  66..1133..  SSeettttiinngg uupp tthhee hhoosstt yyoouurrsseellff
+  6.13.  Setting up the host yourself
 
   If you don't specify an address for the host side of the ethertap or
   slip device, UML won't do any setup on the host.  So this is what is
@@ -1785,7 +1785,7 @@
   192.168.0.251 and a UML-side IP of 192.168.0.250 - adjust to suit your
   own network):
 
-  +o  The device needs to be configured with its IP address.  Tap devices
+  o  The device needs to be configured with its IP address.  Tap devices
      are also configured with an mtu of 1484.  Slip devices are
      configured with a point-to-point address pointing at the UML ip
      address.
@@ -1805,7 +1805,7 @@
 
 
 
-  +o  If a tap device is being set up, a route is set to the UML IP.
+  o  If a tap device is being set up, a route is set to the UML IP.
 
 
        UML# route add -host 192.168.0.250 gw 192.168.0.251
@@ -1814,7 +1814,7 @@
 
 
 
-  +o  To allow other hosts on your network to see the virtual machine,
+  o  To allow other hosts on your network to see the virtual machine,
      proxy arp is set up for it.
 
 
@@ -1824,7 +1824,7 @@
 
 
 
-  +o  Finally, the host is set up to route packets.
+  o  Finally, the host is set up to route packets.
 
 
        host#  echo 1 > /proc/sys/net/ipv4/ip_forward
@@ -1838,12 +1838,12 @@
 
 
 
-  77..  SShhaarriinngg FFiilleessyysstteemmss bbeettwweeeenn VViirrttuuaall MMaacchhiinneess
+  7.  Sharing Filesystems between Virtual Machines
 
 
 
 
-  77..11..  AA wwaarrnniinngg
+  7.1.  A warning
 
   Don't attempt to share filesystems simply by booting two UMLs from the
   same file.  That's the same thing as booting two physical machines
@@ -1851,7 +1851,7 @@
 
 
 
-  77..22..  UUssiinngg llaayyeerreedd bblloocckk ddeevviicceess
+  7.2.  Using layered block devices
 
   The way to share a filesystem between two virtual machines is to use
   the copy-on-write (COW) layering capability of the ubd block driver.
@@ -1896,7 +1896,7 @@
 
 
 
-  77..33..  NNoottee!!
+  7.3.  Note!
 
   When checking the size of the COW file in order to see the gobs of
   space that you're saving, make sure you use 'ls -ls' to see the actual
@@ -1926,7 +1926,7 @@
 
 
 
-  77..44..  AAnnootthheerr wwaarrnniinngg
+  7.4.  Another warning
 
   Once a filesystem is being used as a readonly backing file for a COW
   file, do not boot directly from it or modify it in any way.  Doing so
@@ -1952,7 +1952,7 @@
 
 
 
-  77..55..  uummll__mmoooo :: MMeerrggiinngg aa CCOOWW ffiillee wwiitthh iittss bbaacckkiinngg ffiillee
+  7.5.  uml_moo : Merging a COW file with its backing file
 
   Depending on how you use UML and COW devices, it may be advisable to
   merge the changes in the COW file into the backing file every once in
@@ -2001,7 +2001,7 @@
 
 
 
-  88..  CCrreeaattiinngg ffiilleessyysstteemmss
+  8.  Creating filesystems
 
 
   You may want to create and mount new UML filesystems, either because
@@ -2015,7 +2015,7 @@
   should be easy to translate to the filesystem of your choice.
 
 
-  88..11..  CCrreeaattee tthhee ffiilleessyysstteemm ffiillee
+  8.1.  Create the filesystem file
 
   dd is your friend.  All you need to do is tell dd to create an empty
   file of the appropriate size.  I usually make it sparse to save time
@@ -2032,7 +2032,7 @@
 
 
 
-  88..22..  AAssssiiggnn tthhee ffiillee ttoo aa UUMMLL ddeevviiccee
+  8.2.  Assign the file to a UML device
 
   Add an argument like the following to the UML command line:
 
@@ -2045,7 +2045,7 @@
 
 
 
-  88..33..  CCrreeaattiinngg aanndd mmoouunnttiinngg tthhee ffiilleessyysstteemm
+  8.3.  Creating and mounting the filesystem
 
   Make sure that the filesystem is available, either by being built into
   the kernel, or available as a module, then boot up UML and log in.  If
@@ -2096,7 +2096,7 @@
 
 
 
-  99..  HHoosstt ffiillee aacccceessss
+  9.  Host file access
 
 
   If you want to access files on the host machine from inside UML, you
@@ -2112,7 +2112,7 @@
   files contained in it just as you would on the host.
 
 
-  99..11..  UUssiinngg hhoossttffss
+  9.1.  Using hostfs
 
   To begin with, make sure that hostfs is available inside the virtual
   machine with
@@ -2151,7 +2151,7 @@
 
 
 
-  99..22..  hhoossttffss aass tthhee rroooott ffiilleessyysstteemm
+  9.2.  hostfs as the root filesystem
 
   It's possible to boot from a directory hierarchy on the host using
   hostfs rather than using the standard filesystem in a file.
@@ -2194,20 +2194,20 @@
   UML should then boot as it does normally.
 
 
-  99..33..  BBuuiillddiinngg hhoossttffss
+  9.3.  Building hostfs
 
   If you need to build hostfs because it's not in your kernel, you have
   two choices:
 
 
 
-  +o  Compiling hostfs into the kernel:
+  o  Compiling hostfs into the kernel:
 
 
      Reconfigure the kernel and set the 'Host filesystem' option under
 
 
-  +o  Compiling hostfs as a module:
+  o  Compiling hostfs as a module:
 
 
      Reconfigure the kernel and set the 'Host filesystem' option under
@@ -2228,7 +2228,7 @@
 
 
 
-  1100..  TThhee MMaannaaggeemmeenntt CCoonnssoollee
+  10.  The Management Console
 
 
 
@@ -2240,15 +2240,15 @@
 
   There are a number of things you can do with the mconsole interface:
 
-  +o  get the kernel version
+  o  get the kernel version
 
-  +o  add and remove devices
+  o  add and remove devices
 
-  +o  halt or reboot the machine
+  o  halt or reboot the machine
 
-  +o  Send SysRq commands
+  o  Send SysRq commands
 
-  +o  Pause and resume the UML
+  o  Pause and resume the UML
 
 
   You need the mconsole client (uml_mconsole) which is present in CVS
@@ -2300,28 +2300,28 @@
 
   You'll get a prompt, at which you can run one of these commands:
 
-  +o  version
+  o  version
 
-  +o  halt
+  o  halt
 
-  +o  reboot
+  o  reboot
 
-  +o  config
+  o  config
 
-  +o  remove
+  o  remove
 
-  +o  sysrq
+  o  sysrq
 
-  +o  help
+  o  help
 
-  +o  cad
+  o  cad
 
-  +o  stop
+  o  stop
 
-  +o  go
+  o  go
 
 
-  1100..11..  vveerrssiioonn
+  10.1.  version
 
   This takes no arguments.  It prints the UML version.
 
@@ -2342,7 +2342,7 @@
 
 
 
-  1100..22..  hhaalltt aanndd rreebboooott
+  10.2.  halt and reboot
 
   These take no arguments.  They shut the machine down immediately, with
   no syncing of disks and no clean shutdown of userspace.  So, they are
@@ -2357,7 +2357,7 @@
 
 
 
-  1100..33..  ccoonnffiigg
+  10.3.  config
 
   "config" adds a new device to the virtual machine.  Currently the ubd
   and network drivers support this.  It takes one argument, which is the
@@ -2378,7 +2378,7 @@
 
 
 
-  1100..44..  rreemmoovvee
+  10.4.  remove
 
   "remove" deletes a device from the system.  Its argument is just the
   name of the device to be removed. The device must be idle in whatever
@@ -2397,7 +2397,7 @@
 
 
 
-  1100..55..  ssyyssrrqq
+  10.5.  sysrq
 
   This takes one argument, which is a single letter.  It calls the
   generic kernel's SysRq driver, which does whatever is called for by
@@ -2407,14 +2407,14 @@
 
 
 
-  1100..66..  hheellpp
+  10.6.  help
 
   "help" returns a string listing the valid commands and what each one
   does.
 
 
 
-  1100..77..  ccaadd
+  10.7.  cad
 
   This invokes the Ctl-Alt-Del action on init.  What exactly this ends
   up doing is up to /etc/inittab.  Normally, it reboots the machine.
@@ -2432,7 +2432,7 @@
 
 
 
-  1100..88..  ssttoopp
+  10.8.  stop
 
   This puts the UML in a loop reading mconsole requests until a 'go'
   mconsole command is received. This is very useful for making backups
@@ -2448,7 +2448,7 @@
 
 
 
-  1100..99..  ggoo
+  10.9.  go
 
   This resumes a UML after being paused by a 'stop' command. Note that
   when the UML has resumed, TCP connections may have timed out and if
@@ -2462,10 +2462,10 @@
 
 
 
-  1111..  KKeerrnneell ddeebbuuggggiinngg
+  11.  Kernel debugging
 
 
-  NNoottee:: The interface that makes debugging, as described here, possible
+  Note: The interface that makes debugging, as described here, possible
   is present in 2.4.0-test6 kernels and later.
 
 
@@ -2485,7 +2485,7 @@
 
 
 
-  1111..11..  SSttaarrttiinngg tthhee kkeerrnneell uunnddeerr ggddbb
+  11.1.  Starting the kernel under gdb
 
   You can have the kernel running under the control of gdb from the
   beginning by putting 'debug' on the command line.  You will get an
@@ -2498,7 +2498,7 @@
   There is a transcript of a debugging session  here <debug-
   session.html> , with breakpoints being set in the scheduler and in an
   interrupt handler.
-  1111..22..  EExxaammiinniinngg sslleeeeppiinngg pprroocceesssseess
+  11.2.  Examining sleeping processes
 
   Not every bug is evident in the currently running process.  Sometimes,
   processes hang in the kernel when they shouldn't because they've
@@ -2516,7 +2516,7 @@
 
   Now what you do is this:
 
-  +o  detach from the current thread
+  o  detach from the current thread
 
 
        (UML gdb)  det
@@ -2525,7 +2525,7 @@
 
 
 
-  +o  attach to the thread you are interested in
+  o  attach to the thread you are interested in
 
 
        (UML gdb)  att <host pid>
@@ -2534,7 +2534,7 @@
 
 
 
-  +o  look at its stack and anything else of interest
+  o  look at its stack and anything else of interest
 
 
        (UML gdb)  bt
@@ -2545,7 +2545,7 @@
   Note that you can't do anything at this point that requires that a
   process execute, e.g. calling a function
 
-  +o  when you're done looking at that process, reattach to the current
+  o  when you're done looking at that process, reattach to the current
      thread and continue it
 
 
@@ -2569,12 +2569,12 @@
 
 
 
-  1111..33..  RRuunnnniinngg dddddd oonn UUMMLL
+  11.3.  Running ddd on UML
 
   ddd works on UML, but requires a special kludge.  The process goes
   like this:
 
-  +o  Start ddd
+  o  Start ddd
 
 
        host% ddd linux
@@ -2583,14 +2583,14 @@
 
 
 
-  +o  With ps, get the pid of the gdb that ddd started.  You can ask the
+  o  With ps, get the pid of the gdb that ddd started.  You can ask the
      gdb to tell you, but for some reason that confuses things and
      causes a hang.
 
-  +o  run UML with 'debug=parent gdb-pid=<pid>' added to the command line
+  o  run UML with 'debug=parent gdb-pid=<pid>' added to the command line
      - it will just sit there after you hit return
 
-  +o  type 'att 1' to the ddd gdb and you will see something like
+  o  type 'att 1' to the ddd gdb and you will see something like
 
 
        0xa013dc51 in __kill ()
@@ -2602,12 +2602,12 @@
 
 
 
-  +o  At this point, type 'c', UML will boot up, and you can use ddd just
+  o  At this point, type 'c', UML will boot up, and you can use ddd just
      as you do on any other process.
 
 
 
-  1111..44..  DDeebbuuggggiinngg mmoodduulleess
+  11.4.  Debugging modules
 
   gdb has support for debugging code which is dynamically loaded into
   the process.  This support is what is needed to debug kernel modules
@@ -2823,7 +2823,7 @@
 
 
 
-  1111..55..  AAttttaacchhiinngg ggddbb ttoo tthhee kkeerrnneell
+  11.5.  Attaching gdb to the kernel
 
   If you don't have the kernel running under gdb, you can attach gdb to
   it later by sending the tracing thread a SIGUSR1.  The first line of
@@ -2857,7 +2857,7 @@
 
 
 
-  1111..66..  UUssiinngg aalltteerrnnaattee ddeebbuuggggeerrss
+  11.6.  Using alternate debuggers
 
   UML has support for attaching to an already running debugger rather
   than starting gdb itself.  This is present in CVS as of 17 Apr 2001.
@@ -2886,7 +2886,7 @@
   An example of an alternate debugger is strace.  You can strace the
   actual kernel as follows:
 
-  +o  Run the following in a shell
+  o  Run the following in a shell
 
 
        host%
@@ -2894,10 +2894,10 @@
 
 
 
-  +o  Run UML with 'debug' and 'gdb-pid=<pid>' with the pid printed out
+  o  Run UML with 'debug' and 'gdb-pid=<pid>' with the pid printed out
      by the previous command
 
-  +o  Hit return in the shell, and UML will start running, and strace
+  o  Hit return in the shell, and UML will start running, and strace
      output will start accumulating in the output file.
 
      Note that this is different from running
@@ -2917,9 +2917,9 @@
 
 
 
-  1122..  KKeerrnneell ddeebbuuggggiinngg eexxaammpplleess
+  12.  Kernel debugging examples
 
-  1122..11..  TThhee ccaassee ooff tthhee hhuunngg ffsscckk
+  12.1.  The case of the hung fsck
 
   When booting up the kernel, fsck failed, and dropped me into a shell
   to fix things up.  I ran fsck -y, which hung:
@@ -3154,9 +3154,9 @@
 
   The interesting things here are :
 
-  +o  There are two segfaults on this stack (frames 9 and 14)
+  o  There are two segfaults on this stack (frames 9 and 14)
 
-  +o  The first faulting address (frame 11) is 0x50000800
+  o  The first faulting address (frame 11) is 0x50000800
 
   (gdb) p (void *)1342179328
   $16 = (void *) 0x50000800
@@ -3399,7 +3399,7 @@
   on will be somewhat clearer.
 
 
-  1122..22..  EEppiissooddee 22:: TThhee ccaassee ooff tthhee hhuunngg ffsscckk
+  12.2.  Episode 2: The case of the hung fsck
 
   After setting a trap in the SEGV handler for accesses to the signal
   thread's stack, I reran the kernel.
@@ -3788,12 +3788,12 @@
 
 
 
-  1133..  WWhhaatt ttoo ddoo wwhheenn UUMMLL ddooeessnn''tt wwoorrkk
+  13.  What to do when UML doesn't work
 
 
 
 
-  1133..11..  SSttrraannggee ccoommppiillaattiioonn eerrrroorrss wwhheenn yyoouu bbuuiilldd ffrroomm ssoouurrccee
+  13.1.  Strange compilation errors when you build from source
 
   As of test11, it is necessary to have "ARCH=um" in the environment or
   on the make command line for all steps in building UML, including
@@ -3824,8 +3824,8 @@
 
 
 
-  1133..33..  AA vvaarriieettyy ooff ppaanniiccss aanndd hhaannggss wwiitthh //ttmmpp oonn aa rreeiisseerrffss  ffiilleessyyss--
-  tteemm
+  13.3.  A variety of panics and hangs with /tmp on a reiserfs  filesys-
+  tem
 
   I saw this on reiserfs 3.5.21 and it seems to be fixed in 3.5.27.
   Panics preceded by
@@ -3842,8 +3842,8 @@
 
 
 
-  1133..44..  TThhee ccoommppiillee ffaaiillss wwiitthh eerrrroorrss aabboouutt ccoonnfflliiccttiinngg ttyyppeess ffoorr
-  ''ooppeenn'',, ''dduupp'',, aanndd ''wwaaiittppiidd''
+  13.4.  The compile fails with errors about conflicting types for
+  'open', 'dup', and 'waitpid'
 
   This happens when you build in /usr/src/linux.  The UML build makes
   the include/asm link point to include/asm-um.  /usr/include/asm points
@@ -3854,14 +3854,14 @@
 
 
 
-  1133..55..  UUMMLL ddooeessnn''tt wwoorrkk wwhheenn //ttmmpp iiss aann NNFFSS ffiilleessyysstteemm
+  13.5.  UML doesn't work when /tmp is an NFS filesystem
 
   This seems to be a similar situation with the ReiserFS problem above.
   Some versions of NFS seems not to handle mmap correctly, which UML
   depends on.  The workaround is have /tmp be a non-NFS directory.
 
 
-  1133..66..  UUMMLL hhaannggss oonn bboooott wwhheenn ccoommppiilleedd wwiitthh ggpprrooff ssuuppppoorrtt
+  13.6.  UML hangs on boot when compiled with gprof support
 
   If you build UML with gprof support and, early in the boot, it does
   this
@@ -3878,7 +3878,7 @@
 
 
 
-  1133..77..  ssyyssllooggdd ddiieess wwiitthh aa SSIIGGTTEERRMM oonn ssttaarrttuupp
+  13.7.  syslogd dies with a SIGTERM on startup
 
   The exact boot error depends on the distribution that you're booting,
   but Debian produces this:
@@ -3897,17 +3897,17 @@
 
 
 
-  1133..88..  TTUUNN//TTAAPP nneettwwoorrkkiinngg ddooeessnn''tt wwoorrkk oonn aa 22..44 hhoosstt
+  13.8.  TUN/TAP networking doesn't work on a 2.4 host
 
   There are a couple of problems which were
   <http://www.geocrawler.com/lists/3/SourceForge/597/0/> name="pointed
   out">  by Tim Robinson <timro at trkr dot net>
 
-  +o  It doesn't work on hosts running 2.4.7 (or thereabouts) or earlier.
+  o  It doesn't work on hosts running 2.4.7 (or thereabouts) or earlier.
      The fix is to upgrade to something more recent and then read the
      next item.
 
-  +o  If you see
+  o  If you see
 
 
        File descriptor in bad state
@@ -3921,8 +3921,8 @@
 
 
 
-  1133..99..  YYoouu ccaann nneettwwoorrkk ttoo tthhee hhoosstt bbuutt nnoott ttoo ootthheerr mmaacchhiinneess oonn tthhee
-  nneett
+  13.9.  You can network to the host but not to other machines on the
+  net
 
   If you can connect to the host, and the host can connect to UML, but
   you cannot connect to any other machines, then you may need to enable
@@ -3972,7 +3972,7 @@
 
 
 
-  1133..1100..  II hhaavvee nnoo rroooott aanndd II wwaanntt ttoo ssccrreeaamm
+  13.10.  I have no root and I want to scream
 
   Thanks to Birgit Wahlich for telling me about this strange one.  It
   turns out that there's a limit of six environment variables on the
@@ -3987,7 +3987,7 @@
 
 
 
-  1133..1111..  UUMMLL bbuuiilldd ccoonnfflliicctt bbeettwweeeenn ppttrraaccee..hh aanndd uuccoonntteexxtt..hh
+  13.11.  UML build conflict between ptrace.h and ucontext.h
 
   On some older systems, /usr/include/asm/ptrace.h and
   /usr/include/sys/ucontext.h define the same names.  So, when they're
@@ -4007,7 +4007,7 @@
 
 
 
-  1133..1122..  TThhee UUMMLL BBooggooMMiippss iiss eexxaaccttllyy hhaallff tthhee hhoosstt''ss BBooggooMMiippss
+  13.12.  The UML BogoMips is exactly half the host's BogoMips
 
   On i386 kernels, there are two ways of running the loop that is used
   to calculate the BogoMips rating, using the TSC if it's there or using
@@ -4019,7 +4019,7 @@
 
 
 
-  1133..1133..  WWhheenn yyoouu rruunn UUMMLL,, iitt iimmmmeeddiiaatteellyy sseeggffaauullttss
+  13.13.  When you run UML, it immediately segfaults
 
   If the host is configured with the 2G/2G address space split, that's
   why.  See ``UML on 2G/2G hosts''  for the details on getting UML to
@@ -4027,7 +4027,7 @@
 
 
 
-  1133..1144..  xxtteerrmmss aappppeeaarr,, tthheenn iimmmmeeddiiaatteellyy ddiissaappppeeaarr
+  13.14.  xterms appear, then immediately disappear
 
   If you're running an up to date kernel with an old release of
   uml_utilities, the port-helper program will not work properly, so
@@ -4039,7 +4039,7 @@
 
 
 
-  1133..1155..  AAnnyy ootthheerr ppaanniicc,, hhaanngg,, oorr ssttrraannggee bbeehhaavviioorr
+  13.15.  Any other panic, hang, or strange behavior
 
   If you're seeing truly strange behavior, such as hangs or panics that
   happen in random places, or you try running the debugger to see what's
@@ -4059,7 +4059,7 @@
 
   If you want to be super-helpful, read ``Diagnosing Problems'' and
   follow the instructions contained therein.
-  1144..  DDiiaaggnnoossiinngg PPrroobblleemmss
+  14.  Diagnosing Problems
 
 
   If you get UML to crash, hang, or otherwise misbehave, you should
@@ -4078,7 +4078,7 @@
   ``Kernel debugging''  UML first.
 
 
-  1144..11..  CCaassee 11 :: NNoorrmmaall kkeerrnneell ppaanniiccss
+  14.1.  Case 1 : Normal kernel panics
 
   The most common case is for a normal thread to panic.  To debug this,
   you will need to run it under the debugger (add 'debug' to the command
@@ -4128,7 +4128,7 @@
   to get that information from the faulting ip.
 
 
-  1144..22..  CCaassee 22 :: TTrraacciinngg tthhrreeaadd ppaanniiccss
+  14.2.  Case 2 : Tracing thread panics
 
   The less common and more painful case is when the tracing thread
   panics.  In this case, the kernel debugger will be useless because it
@@ -4161,7 +4161,7 @@
   backtrace in and wait for our crack debugging team to fix the problem.
 
 
-  1144..33..  CCaassee 33 :: TTrraacciinngg tthhrreeaadd ppaanniiccss ccaauusseedd bbyy ootthheerr tthhrreeaaddss
+  14.3.  Case 3 : Tracing thread panics caused by other threads
 
   However, there are cases where the misbehavior of another thread
   caused the problem.  The most common panic of this type is:
@@ -4227,7 +4227,7 @@
 
 
 
-  1144..44..  CCaassee 44 :: HHaannggss
+  14.4.  Case 4 : Hangs
 
   Hangs seem to be fairly rare, but they sometimes happen.  When a hang
   happens, we need a backtrace from the offending process.  Run the
@@ -4257,7 +4257,7 @@
 
 
 
-  1155..  TThhaannkkss
+  15.  Thanks
 
 
   A number of people have helped this project in various ways, and this
@@ -4274,20 +4274,20 @@
   bookkeeping lapses and I forget about contributions.
 
 
-  1155..11..  CCooddee aanndd DDooccuummeennttaattiioonn
+  15.1.  Code and Documentation
 
   Rusty Russell <rusty at linuxcare.com.au>  -
 
-  +o  wrote the  HOWTO <http://user-mode-
+  o  wrote the  HOWTO <http://user-mode-
      linux.sourceforge.net/UserModeLinux-HOWTO.html>
 
-  +o  prodded me into making this project official and putting it on
+  o  prodded me into making this project official and putting it on
      SourceForge
 
-  +o  came up with the way cool UML logo <http://user-mode-
+  o  came up with the way cool UML logo <http://user-mode-
      linux.sourceforge.net/uml-small.png>
 
-  +o  redid the config process
+  o  redid the config process
 
 
   Peter Moulder <reiter at netspace.net.au>  - Fixed my config and build
@@ -4296,18 +4296,18 @@
 
   Bill Stearns <wstearns at pobox.com>  -
 
-  +o  HOWTO updates
+  o  HOWTO updates
 
-  +o  lots of bug reports
+  o  lots of bug reports
 
-  +o  lots of testing
+  o  lots of testing
 
-  +o  dedicated a box (uml.ists.dartmouth.edu) to support UML development
+  o  dedicated a box (uml.ists.dartmouth.edu) to support UML development
 
-  +o  wrote the mkrootfs script, which allows bootable filesystems of
+  o  wrote the mkrootfs script, which allows bootable filesystems of
      RPM-based distributions to be cranked out
 
-  +o  cranked out a large number of filesystems with said script
+  o  cranked out a large number of filesystems with said script
 
 
   Jim Leu <jleu at mindspring.com>  - Wrote the virtual ethernet driver
@@ -4375,176 +4375,176 @@
 
   David Coulson <http://davidcoulson.net>  -
 
-  +o  Set up the usermodelinux.org <http://usermodelinux.org>  site,
+  o  Set up the usermodelinux.org <http://usermodelinux.org>  site,
      which is a great way of keeping the UML user community on top of
      UML goings-on.
 
-  +o  Site documentation and updates
+  o  Site documentation and updates
 
-  +o  Nifty little UML management daemon  UMLd
+  o  Nifty little UML management daemon  UMLd
      <http://uml.openconsultancy.com/umld/>
 
-  +o  Lots of testing and bug reports
+  o  Lots of testing and bug reports
 
 
 
 
-  1155..22..  FFlluusshhiinngg oouutt bbuuggss
+  15.2.  Flushing out bugs
 
 
 
-  +o  Yuri Pudgorodsky
+  o  Yuri Pudgorodsky
 
-  +o  Gerald Britton
+  o  Gerald Britton
 
-  +o  Ian Wehrman
+  o  Ian Wehrman
 
-  +o  Gord Lamb
+  o  Gord Lamb
 
-  +o  Eugene Koontz
+  o  Eugene Koontz
 
-  +o  John H. Hartman
+  o  John H. Hartman
 
-  +o  Anders Karlsson
+  o  Anders Karlsson
 
-  +o  Daniel Phillips
+  o  Daniel Phillips
 
-  +o  John Fremlin
+  o  John Fremlin
 
-  +o  Rainer Burgstaller
+  o  Rainer Burgstaller
 
-  +o  James Stevenson
+  o  James Stevenson
 
-  +o  Matt Clay
+  o  Matt Clay
 
-  +o  Cliff Jefferies
+  o  Cliff Jefferies
 
-  +o  Geoff Hoff
+  o  Geoff Hoff
 
-  +o  Lennert Buytenhek
+  o  Lennert Buytenhek
 
-  +o  Al Viro
+  o  Al Viro
 
-  +o  Frank Klingenhoefer
+  o  Frank Klingenhoefer
 
-  +o  Livio Baldini Soares
+  o  Livio Baldini Soares
 
-  +o  Jon Burgess
+  o  Jon Burgess
 
-  +o  Petru Paler
+  o  Petru Paler
 
-  +o  Paul
+  o  Paul
 
-  +o  Chris Reahard
+  o  Chris Reahard
 
-  +o  Sverker Nilsson
+  o  Sverker Nilsson
 
-  +o  Gong Su
+  o  Gong Su
 
-  +o  johan verrept
+  o  johan verrept
 
-  +o  Bjorn Eriksson
+  o  Bjorn Eriksson
 
-  +o  Lorenzo Allegrucci
+  o  Lorenzo Allegrucci
 
-  +o  Muli Ben-Yehuda
+  o  Muli Ben-Yehuda
 
-  +o  David Mansfield
+  o  David Mansfield
 
-  +o  Howard Goff
+  o  Howard Goff
 
-  +o  Mike Anderson
+  o  Mike Anderson
 
-  +o  John Byrne
+  o  John Byrne
 
-  +o  Sapan J. Batia
+  o  Sapan J. Batia
 
-  +o  Iris Huang
+  o  Iris Huang
 
-  +o  Jan Hudec
+  o  Jan Hudec
 
-  +o  Voluspa
+  o  Voluspa
 
 
 
 
-  1155..33..  BBuugglleettss aanndd cclleeaann--uuppss
+  15.3.  Buglets and clean-ups
 
 
 
-  +o  Dave Zarzycki
+  o  Dave Zarzycki
 
-  +o  Adam Lazur
+  o  Adam Lazur
 
-  +o  Boria Feigin
+  o  Boria Feigin
 
-  +o  Brian J. Murrell
+  o  Brian J. Murrell
 
-  +o  JS
+  o  JS
 
-  +o  Roman Zippel
+  o  Roman Zippel
 
-  +o  Wil Cooley
+  o  Wil Cooley
 
-  +o  Ayelet Shemesh
+  o  Ayelet Shemesh
 
-  +o  Will Dyson
+  o  Will Dyson
 
-  +o  Sverker Nilsson
+  o  Sverker Nilsson
 
-  +o  dvorak
+  o  dvorak
 
-  +o  v.naga srinivas
+  o  v.naga srinivas
 
-  +o  Shlomi Fish
+  o  Shlomi Fish
 
-  +o  Roger Binns
+  o  Roger Binns
 
-  +o  johan verrept
+  o  johan verrept
 
-  +o  MrChuoi
+  o  MrChuoi
 
-  +o  Peter Cleve
+  o  Peter Cleve
 
-  +o  Vincent Guffens
+  o  Vincent Guffens
 
-  +o  Nathan Scott
+  o  Nathan Scott
 
-  +o  Patrick Caulfield
+  o  Patrick Caulfield
 
-  +o  jbearce
+  o  jbearce
 
-  +o  Catalin Marinas
+  o  Catalin Marinas
 
-  +o  Shane Spencer
+  o  Shane Spencer
 
-  +o  Zou Min
+  o  Zou Min
 
 
-  +o  Ryan Boder
+  o  Ryan Boder
 
-  +o  Lorenzo Colitti
+  o  Lorenzo Colitti
 
-  +o  Gwendal Grignou
+  o  Gwendal Grignou
 
-  +o  Andre' Breiler
+  o  Andre' Breiler
 
-  +o  Tsutomu Yasuda
+  o  Tsutomu Yasuda
 
 
 
-  1155..44..  CCaassee SSttuuddiieess
+  15.4.  Case Studies
 
 
-  +o  Jon Wright
+  o  Jon Wright
 
-  +o  William McEwan
+  o  William McEwan
 
-  +o  Michael Richardson
+  o  Michael Richardson
 
 
 
-  1155..55..  OOtthheerr ccoonnttrriibbuuttiioonnss
+  15.5.  Other contributions
 
 
   Bill Carr <Bill.Carr at compaq.com>  made the Red Hat mkrootfs script
diff --git a/MAINTAINERS b/MAINTAINERS
index 4befa12..4cb8c51 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -692,6 +692,12 @@ F:	drivers/mtd/nand/bcm_umi_nand.c
 F:	drivers/mtd/nand/bcm_umi_bch.c
 F:	drivers/mtd/nand/nand_bcm_umi.h
 
+ARM/CALXEDA HIGHBANK ARCHITECTURE
+M:	Rob Herring <rob.herring@calxeda.com>
+L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:	Maintained
+F:	arch/arm/mach-highbank/
+
 ARM/CAVIUM NETWORKS CNS3XXX MACHINE SUPPORT
 M:	Anton Vorontsov <avorontsov@mvista.com>
 S:	Maintained
@@ -791,6 +797,13 @@ L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 F:	arch/arm/mach-mx5/
 
+ARM/FREESCALE IMX6
+M:	Shawn Guo <shawn.guo@linaro.org>
+L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:	Maintained
+T:	git git://git.linaro.org/people/shawnguo/linux-2.6.git
+F:	arch/arm/mach-imx/*imx6*
+
 ARM/GLOMATION GESBC9312SX MACHINE SUPPORT
 M:	Lennert Buytenhek <kernel@wantstofly.org>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -2454,8 +2467,6 @@ L:	linux-edac@vger.kernel.org
 W:	bluesmoke.sourceforge.net
 S:	Maintained
 F:	drivers/edac/i7core_edac.c
-F:	drivers/edac/edac_mce.c
-F:	include/linux/edac_mce.h
 
 EDAC-I82975X
 M:	Ranganathan Desikan <ravi@jetztechnologies.com>
@@ -2479,6 +2490,13 @@ W:	bluesmoke.sourceforge.net
 S:	Maintained
 F:	drivers/edac/r82600_edac.c
 
+EDAC-SBRIDGE
+M:	Mauro Carvalho Chehab <mchehab@redhat.com>
+L:	linux-edac@vger.kernel.org
+W:	bluesmoke.sourceforge.net
+S:	Maintained
+F:	drivers/edac/sb_edac.c
+
 EDIROL UA-101/UA-1000 DRIVER
 M:	Clemens Ladisch <clemens@ladisch.de>
 L:	alsa-devel@alsa-project.org (moderated for non-subscribers)
@@ -3192,8 +3210,7 @@ IA64 (Itanium) PLATFORM
 M:	Tony Luck <tony.luck@intel.com>
 M:	Fenghua Yu <fenghua.yu@intel.com>
 L:	linux-ia64@vger.kernel.org
-W:	http://www.ia64-linux.org/
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6.git
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux.git
 S:	Maintained
 F:	arch/ia64/
 
@@ -5359,6 +5376,12 @@ F:	fs/qnx4/
 F:	include/linux/qnx4_fs.h
 F:	include/linux/qnxtypes.h
 
+QUALCOMM HEXAGON ARCHITECTURE
+M:	Richard Kuo <rkuo@codeaurora.org>
+L:	linux-hexagon@vger.kernel.org
+S:	Supported
+F:	arch/hexagon/
+
 RADOS BLOCK DEVICE (RBD)
 F:	include/linux/qnxtypes.h
 M:	Yehuda Sadeh <yehuda@hq.newdream.net>
@@ -6664,7 +6687,6 @@ F:	drivers/net/ethernet/8390/ne-h8300.c
 
 UDF FILESYSTEM
 M:	Jan Kara <jack@suse.cz>
-W:	http://linux-udf.sourceforge.net
 S:	Maintained
 F:	Documentation/filesystems/udf.txt
 F:	fs/udf/
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 5ca86e7..fe6b052 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -334,6 +334,20 @@ config ARCH_BCMRING
 	help
 	  Support for Broadcom's BCMRing platform.
 
+config ARCH_HIGHBANK
+	bool "Calxeda Highbank-based"
+	select ARCH_WANT_OPTIONAL_GPIOLIB
+	select ARM_AMBA
+	select ARM_GIC
+	select ARM_TIMER_SP804
+	select CLKDEV_LOOKUP
+	select CPU_V7
+	select GENERIC_CLOCKEVENTS
+	select HAVE_ARM_SCU
+	select USE_OF
+	help
+	  Support for the Calxeda Highbank SoC based boards.
+
 config ARCH_CLPS711X
 	bool "Cirrus Logic CLPS711x/EP721x-based"
 	select CPU_ARM720T
@@ -394,7 +408,7 @@ config ARCH_EP93XX
 	select ARCH_REQUIRE_GPIOLIB
 	select ARCH_HAS_HOLES_MEMORYMODEL
 	select ARCH_USES_GETTIMEOFFSET
-	select NEED_MEMORY_H
+	select NEED_MACH_MEMORY_H
 	help
 	  This enables support for the Cirrus EP93xx series of CPUs.
 
@@ -417,6 +431,7 @@ config ARCH_MXC
 	select CLKSRC_MMIO
 	select GENERIC_IRQ_CHIP
 	select HAVE_SCHED_CLOCK
+	select MULTI_IRQ_HANDLER
 	help
 	  Support for Freescale MXC/iMX-based family of processors
 
@@ -609,14 +624,6 @@ config ARCH_W90X900
 	  <http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/
 		ConsumerElectronicsIC/ARMMicrocontroller/ARMMicrocontroller>
 
-config ARCH_NUC93X
-	bool "Nuvoton NUC93X CPU"
-	select CPU_ARM926T
-	select CLKDEV_LOOKUP
-	help
-	  Support for Nuvoton (Winbond logic dept.) NUC93X MCU,The NUC93X is a
-	  low-power and high performance MPEG-4/JPEG multimedia controller chip.
-
 config ARCH_TEGRA
 	bool "NVIDIA Tegra"
 	select CLKDEV_LOOKUP
@@ -630,6 +637,24 @@ config ARCH_TEGRA
 	  This enables support for NVIDIA Tegra based systems (Tegra APX,
 	  Tegra 6xx and Tegra 2 series).
 
+config ARCH_PICOXCELL
+	bool "Picochip picoXcell"
+	select ARCH_REQUIRE_GPIOLIB
+	select ARM_PATCH_PHYS_VIRT
+	select ARM_VIC
+	select CPU_V6K
+	select DW_APB_TIMER
+	select GENERIC_CLOCKEVENTS
+	select GENERIC_GPIO
+	select HAVE_SCHED_CLOCK
+	select HAVE_TCM
+	select NO_IOPORT
+	select USE_OF
+	help
+	  This enables support for systems based on the Picochip picoXcell
+	  family of Femtocell devices.  The picoxcell support requires device tree
+	  for all boards.
+
 config ARCH_PNX4008
 	bool "Philips Nexperia PNX4008 Mobile"
 	select CPU_ARM926T
@@ -861,6 +886,7 @@ config ARCH_U300
 	select HAVE_SCHED_CLOCK
 	select HAVE_TCM
 	select ARM_AMBA
+	select ARM_PATCH_PHYS_VIRT
 	select ARM_VIC
 	select GENERIC_CLOCKEVENTS
 	select CLKDEV_LOOKUP
@@ -1011,8 +1037,6 @@ source "arch/arm/mach-netx/Kconfig"
 source "arch/arm/mach-nomadik/Kconfig"
 source "arch/arm/plat-nomadik/Kconfig"
 
-source "arch/arm/mach-nuc93x/Kconfig"
-
 source "arch/arm/plat-omap/Kconfig"
 
 source "arch/arm/mach-omap1/Kconfig"
@@ -1406,7 +1430,7 @@ config SMP
 	depends on REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP || \
 		 MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \
 		 ARCH_EXYNOS4 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || \
-		 ARCH_MSM_SCORPIONMP || ARCH_SHMOBILE
+		 ARCH_MSM_SCORPIONMP || ARCH_SHMOBILE || ARCH_HIGHBANK || SOC_IMX6Q
 	depends on MMU
 	select USE_GENERIC_SMP_HELPERS
 	select HAVE_ARM_SCU if !ARCH_MSM_SCORPIONMP
@@ -2044,6 +2068,7 @@ config CPU_FREQ_PXA
 	bool
 	depends on CPU_FREQ && ARCH_PXA && PXA25x
 	default y
+	select CPU_FREQ_TABLE
 	select CPU_FREQ_DEFAULT_GOV_USERSPACE
 
 config CPU_FREQ_S3C
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index f283938..c5213e7 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -128,6 +128,125 @@ choice
 		  Say Y here if you want the debug print routines to direct
 		  their output to the second serial port on these devices.
 
+	config DEBUG_HIGHBANK_UART
+		bool "Kernel low-level debugging messages via Highbank UART"
+		depends on ARCH_HIGHBANK
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the UART on Highbank based devices.
+
+	config DEBUG_IMX1_UART
+		bool "i.MX1 Debug UART"
+		depends on SOC_IMX1
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on i.MX1.
+
+	config DEBUG_IMX23_UART
+		bool "i.MX23 Debug UART"
+		depends on SOC_IMX23
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on i.MX23.
+
+	config DEBUG_IMX25_UART
+		bool "i.MX25 Debug UART"
+		depends on SOC_IMX25
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on i.MX25.
+
+	config DEBUG_IMX21_IMX27_UART
+		bool "i.MX21 and i.MX27 Debug UART"
+		depends on SOC_IMX21 || SOC_IMX27
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on i.MX21 or i.MX27.
+
+	config DEBUG_IMX28_UART
+		bool "i.MX28 Debug UART"
+		depends on SOC_IMX28
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on i.MX28.
+
+	config DEBUG_IMX31_IMX35_UART
+		bool "i.MX31 and i.MX35 Debug UART"
+		depends on SOC_IMX31 || SOC_IMX35
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on i.MX31 or i.MX35.
+
+	config DEBUG_IMX51_UART
+		bool "i.MX51 Debug UART"
+		depends on SOC_IMX51
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on i.MX51.
+
+	config DEBUG_IMX50_IMX53_UART
+		bool "i.MX50 and i.MX53 Debug UART"
+		depends on SOC_IMX50 || SOC_IMX53
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on i.MX50 or i.MX53.
+
+	config DEBUG_IMX6Q_UART
+		bool "i.MX6Q Debug UART"
+		depends on SOC_IMX6Q
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on i.MX6Q.
+
+	config DEBUG_S3C_UART0
+		depends on PLAT_SAMSUNG
+		bool "Use S3C UART 0 for low-level debug"
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to UART 0. The port must have been initialised
+		  by the boot-loader before use.
+
+		  The uncompressor code port configuration is now handled
+		  by CONFIG_S3C_LOWLEVEL_UART_PORT.
+
+	config DEBUG_S3C_UART1
+		depends on PLAT_SAMSUNG
+		bool "Use S3C UART 1 for low-level debug"
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to UART 1. The port must have been initialised
+		  by the boot-loader before use.
+
+		  The uncompressor code port configuration is now handled
+		  by CONFIG_S3C_LOWLEVEL_UART_PORT.
+
+	config DEBUG_S3C_UART2
+		depends on PLAT_SAMSUNG
+		bool "Use S3C UART 2 for low-level debug"
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to UART 2. The port must have been initialised
+		  by the boot-loader before use.
+
+		  The uncompressor code port configuration is now handled
+		  by CONFIG_S3C_LOWLEVEL_UART_PORT.
+
+	config DEBUG_REALVIEW_STD_PORT
+		bool "RealView Default UART"
+		depends on ARCH_REALVIEW
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the serial port on RealView EB, PB11MP, PBA8
+		  and PBX platforms.
+
+	config DEBUG_REALVIEW_PB1176_PORT
+		bool "RealView PB1176 UART"
+		depends on MACH_REALVIEW_PB1176
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the standard serial port on the RealView
+		  PB1176 platform.
+
 endchoice
 
 config EARLY_PRINTK
@@ -146,18 +265,6 @@ config OC_ETM
 	  buffer driver that will allow you to collect traces of the
 	  kernel code.
 
-config DEBUG_S3C_UART
-	depends on PLAT_SAMSUNG
-	int "S3C UART to use for low-level debug"
-	default "0"
-	help
-	  Choice for UART for kernel low-level using S3C UARTS,
-	  should be between zero and two. The port must have been
-	  initialised by the boot-loader before use.
-
-	  The uncompressor code port configuration is now handled
-	  by CONFIG_S3C_LOWLEVEL_UART_PORT.
-
 config ARM_KPROBES_TEST
 	tristate "Kprobes test module"
 	depends on KPROBES && MODULES
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 5665c2a..b7c2d37 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -144,6 +144,7 @@ machine-$(CONFIG_ARCH_EBSA110)		:= ebsa110
 machine-$(CONFIG_ARCH_EP93XX)		:= ep93xx
 machine-$(CONFIG_ARCH_GEMINI)		:= gemini
 machine-$(CONFIG_ARCH_H720X)		:= h720x
+machine-$(CONFIG_ARCH_HIGHBANK)		:= highbank
 machine-$(CONFIG_ARCH_INTEGRATOR)	:= integrator
 machine-$(CONFIG_ARCH_IOP13XX)		:= iop13xx
 machine-$(CONFIG_ARCH_IOP32X)		:= iop32x
@@ -157,10 +158,8 @@ machine-$(CONFIG_ARCH_LPC32XX)		:= lpc32xx
 machine-$(CONFIG_ARCH_MMP)		:= mmp
 machine-$(CONFIG_ARCH_MSM)		:= msm
 machine-$(CONFIG_ARCH_MV78XX0)		:= mv78xx0
-machine-$(CONFIG_ARCH_MX1)		:= imx
-machine-$(CONFIG_ARCH_MX2)		:= imx
-machine-$(CONFIG_ARCH_MX25)		:= imx
-machine-$(CONFIG_ARCH_MX3)		:= imx
+machine-$(CONFIG_ARCH_IMX_V4_V5)	:= imx
+machine-$(CONFIG_ARCH_IMX_V6_V7)	:= imx
 machine-$(CONFIG_ARCH_MX5)		:= mx5
 machine-$(CONFIG_ARCH_MXS)		:= mxs
 machine-$(CONFIG_ARCH_NETX)		:= netx
@@ -170,6 +169,7 @@ machine-$(CONFIG_ARCH_OMAP2)		:= omap2
 machine-$(CONFIG_ARCH_OMAP3)		:= omap2
 machine-$(CONFIG_ARCH_OMAP4)		:= omap2
 machine-$(CONFIG_ARCH_ORION5X)		:= orion5x
+machine-$(CONFIG_ARCH_PICOXCELL)	:= picoxcell
 machine-$(CONFIG_ARCH_PNX4008)		:= pnx4008
 machine-$(CONFIG_ARCH_PRIMA2)		:= prima2
 machine-$(CONFIG_ARCH_PXA)		:= pxa
@@ -192,7 +192,6 @@ machine-$(CONFIG_ARCH_VERSATILE)	:= versatile
 machine-$(CONFIG_ARCH_VEXPRESS)		:= vexpress
 machine-$(CONFIG_ARCH_VT8500)		:= vt8500
 machine-$(CONFIG_ARCH_W90X900)		:= w90x900
-machine-$(CONFIG_ARCH_NUC93X)		:= nuc93x
 machine-$(CONFIG_FOOTBRIDGE)		:= footbridge
 machine-$(CONFIG_MACH_SPEAR300)		:= spear3xx
 machine-$(CONFIG_MACH_SPEAR310)		:= spear3xx
diff --git a/arch/arm/boot/dts/at91sam9g20.dtsi b/arch/arm/boot/dts/at91sam9g20.dtsi
new file mode 100644
index 0000000..aeef042
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9g20.dtsi
@@ -0,0 +1,119 @@
+/*
+ * at91sam9g20.dtsi - Device Tree Include file for AT91SAM9G20 family SoC
+ *
+ *  Copyright (C) 2011 Atmel,
+ *                2011 Nicolas Ferre <nicolas.ferre@atmel.com>,
+ *                2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	model = "Atmel AT91SAM9G20 family SoC";
+	compatible = "atmel,at91sam9g20";
+	interrupt-parent = <&aic>;
+
+	aliases {
+		serial0 = &dbgu;
+		serial1 = &usart0;
+		serial2 = &usart1;
+		serial3 = &usart2;
+		serial4 = &usart3;
+		serial5 = &usart4;
+		serial6 = &usart5;
+	};
+	cpus {
+		cpu@0 {
+			compatible = "arm,arm926ejs";
+		};
+	};
+
+	memory@20000000 {
+		reg = <0x20000000 0x08000000>;
+	};
+
+	ahb {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		apb {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			aic: interrupt-controller@fffff000 {
+				#interrupt-cells = <1>;
+				compatible = "atmel,at91rm9200-aic";
+				interrupt-controller;
+				interrupt-parent;
+				reg = <0xfffff000 0x200>;
+			};
+
+			dbgu: serial@fffff200 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfffff200 0x200>;
+				interrupts = <1>;
+				status = "disabled";
+			};
+
+			usart0: serial@fffb0000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfffb0000 0x200>;
+				interrupts = <6>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+
+			usart1: serial@fffb4000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfffb4000 0x200>;
+				interrupts = <7>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+
+			usart2: serial@fffb8000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfffb8000 0x200>;
+				interrupts = <8>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+
+			usart3: serial@fffd0000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfffd0000 0x200>;
+				interrupts = <23>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+
+			usart4: serial@fffd4000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfffd4000 0x200>;
+				interrupts = <24>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+
+			usart5: serial@fffd8000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfffd8000 0x200>;
+				interrupts = <25>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
new file mode 100644
index 0000000..db6a452
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
@@ -0,0 +1,106 @@
+/*
+ * at91sam9g45.dtsi - Device Tree Include file for AT91SAM9G45 family SoC
+ *                    applies to AT91SAM9G45, AT91SAM9M10,
+ *                    AT91SAM9G46, AT91SAM9M11 SoC
+ *
+ *  Copyright (C) 2011 Atmel,
+ *                2011 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	model = "Atmel AT91SAM9G45 family SoC";
+	compatible = "atmel,at91sam9g45";
+	interrupt-parent = <&aic>;
+
+	aliases {
+		serial0 = &dbgu;
+		serial1 = &usart0;
+		serial2 = &usart1;
+		serial3 = &usart2;
+		serial4 = &usart3;
+	};
+	cpus {
+		cpu@0 {
+			compatible = "arm,arm926ejs";
+		};
+	};
+
+	memory@70000000 {
+		reg = <0x70000000 0x10000000>;
+	};
+
+	ahb {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		apb {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			aic: interrupt-controller@fffff000 {
+				#interrupt-cells = <1>;
+				compatible = "atmel,at91rm9200-aic";
+				interrupt-controller;
+				interrupt-parent;
+				reg = <0xfffff000 0x200>;
+			};
+
+			dma: dma-controller@ffffec00 {
+				compatible = "atmel,at91sam9g45-dma";
+				reg = <0xffffec00 0x200>;
+				interrupts = <21>;
+			};
+
+			dbgu: serial@ffffee00 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xffffee00 0x200>;
+				interrupts = <1>;
+				status = "disabled";
+			};
+
+			usart0: serial@fff8c000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfff8c000 0x200>;
+				interrupts = <7>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+
+			usart1: serial@fff90000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfff90000 0x200>;
+				interrupts = <8>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+
+			usart2: serial@fff94000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfff94000 0x200>;
+				interrupts = <9>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+
+			usart3: serial@fff98000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xfff98000 0x200>;
+				interrupts = <10>;
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/at91sam9m10g45ek.dts b/arch/arm/boot/dts/at91sam9m10g45ek.dts
new file mode 100644
index 0000000..85b34f5
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9m10g45ek.dts
@@ -0,0 +1,35 @@
+/*
+ * at91sam9m10g45ek.dts - Device Tree file for AT91SAM9M10G45-EK board
+ *
+ *  Copyright (C) 2011 Atmel,
+ *                2011 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+/include/ "at91sam9g45.dtsi"
+
+/ {
+	model = "Atmel AT91SAM9M10G45-EK";
+	compatible = "atmel,at91sam9m10g45ek", "atmel,at91sam9g45", "atmel,at91sam9";
+
+	chosen {
+		bootargs = "mem=64M console=ttyS0,115200 mtdparts=atmel_nand:4M(bootstrap/uboot/kernel)ro,60M(rootfs),-(data) root=/dev/mtdblock1 rw rootfstype=jffs2";
+	};
+
+	memory@70000000 {
+		reg = <0x70000000 0x4000000>;
+	};
+
+	ahb {
+		apb {
+			dbgu: serial@ffffee00 {
+				status = "okay";
+			};
+
+			usart1: serial@fff90000 {
+				status = "okay";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/highbank.dts b/arch/arm/boot/dts/highbank.dts
new file mode 100644
index 0000000..aeb1a75
--- /dev/null
+++ b/arch/arm/boot/dts/highbank.dts
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2011 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/dts-v1/;
+
+/* First 4KB has pen for secondary cores. */
+/memreserve/ 0x00000000 0x0001000;
+
+/ {
+	model = "Calxeda Highbank";
+	compatible = "calxeda,highbank";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+			next-level-cache = <&L2>;
+		};
+
+		cpu@1 {
+			compatible = "arm,cortex-a9";
+			reg = <1>;
+			next-level-cache = <&L2>;
+		};
+
+		cpu@2 {
+			compatible = "arm,cortex-a9";
+			reg = <2>;
+			next-level-cache = <&L2>;
+		};
+
+		cpu@3 {
+			compatible = "arm,cortex-a9";
+			reg = <3>;
+			next-level-cache = <&L2>;
+		};
+	};
+
+	memory {
+		name = "memory";
+		device_type = "memory";
+		reg = <0x00000000 0xff900000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyAMA0";
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&intc>;
+		ranges;
+
+		timer@fff10600 {
+			compatible = "arm,smp-twd";
+			reg = <0xfff10600 0x20>;
+			interrupts = <1 13 0xf04>;
+		};
+
+		watchdog@fff10620 {
+			compatible = "arm,cortex-a9-wdt";
+			reg = <0xfff10620 0x20>;
+			interrupts = <1 14 0xf04>;
+		};
+
+		intc: interrupt-controller@fff11000 {
+			compatible = "arm,cortex-a9-gic";
+			#interrupt-cells = <3>;
+			#size-cells = <0>;
+			#address-cells = <1>;
+			interrupt-controller;
+			interrupt-parent;
+			reg = <0xfff11000 0x1000>,
+			      <0xfff10100 0x100>;
+		};
+
+		L2: l2-cache {
+			compatible = "arm,pl310-cache";
+			reg = <0xfff12000 0x1000>;
+			interrupts = <0 70 4>;
+			cache-unified;
+			cache-level = <2>;
+		};
+
+		pmu {
+			compatible = "arm,cortex-a9-pmu";
+			interrupts = <0 76 4  0 75 4  0 74 4  0 73 4>;
+		};
+
+		sata@ffe08000 {
+			compatible = "calxeda,hb-ahci";
+			reg = <0xffe08000 0x10000>;
+			interrupts = <0 83 4>;
+		};
+
+		sdhci@ffe0e000 {
+			compatible = "calxeda,hb-sdhci";
+			reg = <0xffe0e000 0x1000>;
+			interrupts = <0 90 4>;
+		};
+
+		ipc@fff20000 {
+			compatible = "arm,pl320", "arm,primecell";
+			reg = <0xfff20000 0x1000>;
+			interrupts = <0 7 4>;
+		};
+
+		gpioe: gpio@fff30000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0xfff30000 0x1000>;
+			interrupts = <0 14 4>;
+		};
+
+		gpiof: gpio@fff31000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0xfff31000 0x1000>;
+			interrupts = <0 15 4>;
+		};
+
+		gpiog: gpio@fff32000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0xfff32000 0x1000>;
+			interrupts = <0 16 4>;
+		};
+
+		gpioh: gpio@fff33000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0xfff33000 0x1000>;
+			interrupts = <0 17 4>;
+		};
+
+		timer {
+			compatible = "arm,sp804", "arm,primecell";
+			reg = <0xfff34000 0x1000>;
+			interrupts = <0 18 4>;
+		};
+
+		rtc@fff35000 {
+			compatible = "arm,pl031", "arm,primecell";
+			reg = <0xfff35000 0x1000>;
+			interrupts = <0 19 4>;
+		};
+
+		serial@fff36000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0xfff36000 0x1000>;
+			interrupts = <0 20 4>;
+		};
+
+		smic@fff3a000 {
+			compatible = "ipmi-smic";
+			device_type = "ipmi";
+			reg = <0xfff3a000 0x1000>;
+			interrupts = <0 24 4>;
+			reg-size = <4>;
+			reg-spacing = <4>;
+		};
+
+		sregs@fff3c000 {
+			compatible = "calxeda,hb-sregs";
+			reg = <0xfff3c000 0x1000>;
+		};
+
+		dma@fff3d000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0xfff3d000 0x1000>;
+			interrupts = <0 92 4>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx51-babbage.dts b/arch/arm/boot/dts/imx51-babbage.dts
new file mode 100644
index 0000000..f8766af
--- /dev/null
+++ b/arch/arm/boot/dts/imx51-babbage.dts
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx51.dtsi"
+
+/ {
+	model = "Freescale i.MX51 Babbage Board";
+	compatible = "fsl,imx51-babbage", "fsl,imx51";
+
+	chosen {
+		bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait";
+	};
+
+	memory {
+		reg = <0x90000000 0x20000000>;
+	};
+
+	soc {
+		aips@70000000 { /* aips-1 */
+			spba@70000000 {
+				esdhc@70004000 { /* ESDHC1 */
+					fsl,cd-internal;
+					fsl,wp-internal;
+					status = "okay";
+				};
+
+				esdhc@70008000 { /* ESDHC2 */
+					cd-gpios = <&gpio0 6 0>; /* GPIO1_6 */
+					wp-gpios = <&gpio0 5 0>; /* GPIO1_5 */
+					status = "okay";
+				};
+
+				uart2: uart@7000c000 { /* UART3 */
+					fsl,uart-has-rtscts;
+					status = "okay";
+				};
+
+				ecspi@70010000 { /* ECSPI1 */
+					fsl,spi-num-chipselects = <2>;
+					cs-gpios = <&gpio3 24 0>, /* GPIO4_24 */
+						   <&gpio3 25 0>; /* GPIO4_25 */
+					status = "okay";
+
+					pmic: mc13892@0 {
+						#address-cells = <1>;
+						#size-cells = <0>;
+						compatible = "fsl,mc13892";
+						spi-max-frequency = <6000000>;
+						reg = <0>;
+						mc13xxx-irq-gpios = <&gpio0 8 0>; /* GPIO1_8 */
+						fsl,mc13xxx-uses-regulator;
+					};
+
+					flash: at45db321d@1 {
+						#address-cells = <1>;
+						#size-cells = <1>;
+						compatible = "atmel,at45db321d", "atmel,at45", "atmel,dataflash";
+						spi-max-frequency = <25000000>;
+						reg = <1>;
+
+						partition@0 {
+							label = "U-Boot";
+							reg = <0x0 0x40000>;
+							read-only;
+						};
+
+						partition@40000 {
+							label = "Kernel";
+							reg = <0x40000 0x3c0000>;
+						};
+					};
+				};
+			};
+
+			wdog@73f98000 { /* WDOG1 */
+				status = "okay";
+			};
+
+			iomuxc@73fa8000 {
+				compatible = "fsl,imx51-iomuxc-babbage";
+				reg = <0x73fa8000 0x4000>;
+			};
+
+			uart0: uart@73fbc000 {
+				fsl,uart-has-rtscts;
+				status = "okay";
+			};
+
+			uart1: uart@73fc0000 {
+				status = "okay";
+			};
+		};
+
+		aips@80000000 {	/* aips-2 */
+			sdma@83fb0000 {
+				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx51.bin";
+			};
+
+			i2c@83fc4000 { /* I2C2 */
+				status = "okay";
+
+				codec: sgtl5000@0a {
+					compatible = "fsl,sgtl5000";
+					reg = <0x0a>;
+				};
+			};
+
+			fec@83fec000 {
+				phy-mode = "mii";
+				status = "okay";
+			};
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		power {
+			label = "Power Button";
+			gpios = <&gpio1 21 0>;
+			linux,code = <116>; /* KEY_POWER */
+			gpio-key,wakeup;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/imx51.dtsi
new file mode 100644
index 0000000..327ab8e
--- /dev/null
+++ b/arch/arm/boot/dts/imx51.dtsi
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+	};
+
+	tzic: tz-interrupt-controller@e0000000 {
+		compatible = "fsl,imx51-tzic", "fsl,tzic";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		reg = <0xe0000000 0x4000>;
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ckil {
+			compatible = "fsl,imx-ckil", "fixed-clock";
+			clock-frequency = <32768>;
+		};
+
+		ckih1 {
+			compatible = "fsl,imx-ckih1", "fixed-clock";
+			clock-frequency = <22579200>;
+		};
+
+		ckih2 {
+			compatible = "fsl,imx-ckih2", "fixed-clock";
+			clock-frequency = <0>;
+		};
+
+		osc {
+			compatible = "fsl,imx-osc", "fixed-clock";
+			clock-frequency = <24000000>;
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&tzic>;
+		ranges;
+
+		aips@70000000 { /* AIPS1 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x70000000 0x10000000>;
+			ranges;
+
+			spba@70000000 {
+				compatible = "fsl,spba-bus", "simple-bus";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0x70000000 0x40000>;
+				ranges;
+
+				esdhc@70004000 { /* ESDHC1 */
+					compatible = "fsl,imx51-esdhc";
+					reg = <0x70004000 0x4000>;
+					interrupts = <1>;
+					status = "disabled";
+				};
+
+				esdhc@70008000 { /* ESDHC2 */
+					compatible = "fsl,imx51-esdhc";
+					reg = <0x70008000 0x4000>;
+					interrupts = <2>;
+					status = "disabled";
+				};
+
+				uart2: uart@7000c000 { /* UART3 */
+					compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+					reg = <0x7000c000 0x4000>;
+					interrupts = <33>;
+					status = "disabled";
+				};
+
+				ecspi@70010000 { /* ECSPI1 */
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx51-ecspi";
+					reg = <0x70010000 0x4000>;
+					interrupts = <36>;
+					status = "disabled";
+				};
+
+				esdhc@70020000 { /* ESDHC3 */
+					compatible = "fsl,imx51-esdhc";
+					reg = <0x70020000 0x4000>;
+					interrupts = <3>;
+					status = "disabled";
+				};
+
+				esdhc@70024000 { /* ESDHC4 */
+					compatible = "fsl,imx51-esdhc";
+					reg = <0x70024000 0x4000>;
+					interrupts = <4>;
+					status = "disabled";
+				};
+			};
+
+			gpio0: gpio@73f84000 { /* GPIO1 */
+				compatible = "fsl,imx51-gpio", "fsl,imx31-gpio";
+				reg = <0x73f84000 0x4000>;
+				interrupts = <50 51>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio1: gpio@73f88000 { /* GPIO2 */
+				compatible = "fsl,imx51-gpio", "fsl,imx31-gpio";
+				reg = <0x73f88000 0x4000>;
+				interrupts = <52 53>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio2: gpio@73f8c000 { /* GPIO3 */
+				compatible = "fsl,imx51-gpio", "fsl,imx31-gpio";
+				reg = <0x73f8c000 0x4000>;
+				interrupts = <54 55>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio3: gpio@73f90000 { /* GPIO4 */
+				compatible = "fsl,imx51-gpio", "fsl,imx31-gpio";
+				reg = <0x73f90000 0x4000>;
+				interrupts = <56 57>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			wdog@73f98000 { /* WDOG1 */
+				compatible = "fsl,imx51-wdt", "fsl,imx21-wdt";
+				reg = <0x73f98000 0x4000>;
+				interrupts = <58>;
+				status = "disabled";
+			};
+
+			wdog@73f9c000 { /* WDOG2 */
+				compatible = "fsl,imx51-wdt", "fsl,imx21-wdt";
+				reg = <0x73f9c000 0x4000>;
+				interrupts = <59>;
+				status = "disabled";
+			};
+
+			uart0: uart@73fbc000 {
+				compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+				reg = <0x73fbc000 0x4000>;
+				interrupts = <31>;
+				status = "disabled";
+			};
+
+			uart1: uart@73fc0000 {
+				compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+				reg = <0x73fc0000 0x4000>;
+				interrupts = <32>;
+				status = "disabled";
+			};
+		};
+
+		aips@80000000 {	/* AIPS2 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x80000000 0x10000000>;
+			ranges;
+
+			ecspi@83fac000 { /* ECSPI2 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx51-ecspi";
+				reg = <0x83fac000 0x4000>;
+				interrupts = <37>;
+				status = "disabled";
+			};
+
+			sdma@83fb0000 {
+				compatible = "fsl,imx51-sdma", "fsl,imx35-sdma";
+				reg = <0x83fb0000 0x4000>;
+				interrupts = <6>;
+			};
+
+			cspi@83fc0000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx51-cspi", "fsl,imx35-cspi";
+				reg = <0x83fc0000 0x4000>;
+				interrupts = <38>;
+				status = "disabled";
+			};
+
+			i2c@83fc4000 { /* I2C2 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx51-i2c", "fsl,imx1-i2c";
+				reg = <0x83fc4000 0x4000>;
+				interrupts = <63>;
+				status = "disabled";
+			};
+
+			i2c@83fc8000 { /* I2C1 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx51-i2c", "fsl,imx1-i2c";
+				reg = <0x83fc8000 0x4000>;
+				interrupts = <62>;
+				status = "disabled";
+			};
+
+			fec@83fec000 {
+				compatible = "fsl,imx51-fec", "fsl,imx27-fec";
+				reg = <0x83fec000 0x4000>;
+				interrupts = <87>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx53-ard.dts b/arch/arm/boot/dts/imx53-ard.dts
new file mode 100644
index 0000000..2ab7f80
--- /dev/null
+++ b/arch/arm/boot/dts/imx53-ard.dts
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx53.dtsi"
+
+/ {
+	model = "Freescale i.MX53 Automotive Reference Design Board";
+	compatible = "fsl,imx53-ard", "fsl,imx53";
+
+	chosen {
+		bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait";
+	};
+
+	memory {
+		reg = <0x70000000 0x40000000>;
+	};
+
+	soc {
+		aips@50000000 { /* AIPS1 */
+			spba@50000000 {
+				esdhc@50004000 { /* ESDHC1 */
+					cd-gpios = <&gpio0 1 0>; /* GPIO1_1 */
+					wp-gpios = <&gpio0 9 0>; /* GPIO1_9 */
+					status = "okay";
+				};
+			};
+
+			wdog@53f98000 { /* WDOG1 */
+				status = "okay";
+			};
+
+			iomuxc@53fa8000 {
+				compatible = "fsl,imx53-iomuxc-ard";
+				reg = <0x53fa8000 0x4000>;
+			};
+
+			uart0: uart@53fbc000 { /* UART1 */
+				status = "okay";
+			};
+		};
+
+		aips@60000000 {	/* AIPS2 */
+			sdma@63fb0000 {
+				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx53.bin";
+			};
+		};
+	};
+
+	eim-cs1@f4000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,eim-bus", "simple-bus";
+		reg = <0xf4000000 0x3ff0000>;
+		ranges;
+
+		lan9220@f4000000 {
+			compatible = "smsc,lan9220", "smsc,lan9115";
+			reg = <0xf4000000 0x2000000>;
+			phy-mode = "mii";
+			interrupt-parent = <&gpio1>;
+			interrupts = <31>;
+			reg-io-width = <4>;
+			smsc,irq-push-pull;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		home {
+			label = "Home";
+			gpios = <&gpio4 10 0>; /* GPIO5_10 */
+			linux,code = <102>; /* KEY_HOME */
+			gpio-key,wakeup;
+		};
+
+		back {
+			label = "Back";
+			gpios = <&gpio4 11 0>; /* GPIO5_11 */
+			linux,code = <158>; /* KEY_BACK */
+			gpio-key,wakeup;
+		};
+
+		program {
+			label = "Program";
+			gpios = <&gpio4 12 0>; /* GPIO5_12 */
+			linux,code = <362>; /* KEY_PROGRAM */
+			gpio-key,wakeup;
+		};
+
+		volume-up {
+			label = "Volume Up";
+			gpios = <&gpio4 13 0>; /* GPIO5_13 */
+			linux,code = <115>; /* KEY_VOLUMEUP */
+		};
+
+		volume-down {
+			label = "Volume Down";
+			gpios = <&gpio3 0 0>; /* GPIO4_0 */
+			linux,code = <114>; /* KEY_VOLUMEDOWN */
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx53-evk.dts b/arch/arm/boot/dts/imx53-evk.dts
new file mode 100644
index 0000000..3f3a881
--- /dev/null
+++ b/arch/arm/boot/dts/imx53-evk.dts
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx53.dtsi"
+
+/ {
+	model = "Freescale i.MX53 Evaluation Kit";
+	compatible = "fsl,imx53-evk", "fsl,imx53";
+
+	chosen {
+		bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait";
+	};
+
+	memory {
+		reg = <0x70000000 0x80000000>;
+	};
+
+	soc {
+		aips@50000000 { /* AIPS1 */
+			spba@50000000 {
+				esdhc@50004000 { /* ESDHC1 */
+					cd-gpios = <&gpio2 13 0>; /* GPIO3_13 */
+					wp-gpios = <&gpio2 14 0>; /* GPIO3_14 */
+					status = "okay";
+				};
+
+				ecspi@50010000 { /* ECSPI1 */
+					fsl,spi-num-chipselects = <2>;
+					cs-gpios = <&gpio1 30 0>, /* GPIO2_30 */
+						   <&gpio2 19 0>; /* GPIO3_19 */
+					status = "okay";
+
+					flash: at45db321d@1 {
+						#address-cells = <1>;
+						#size-cells = <1>;
+						compatible = "atmel,at45db321d", "atmel,at45", "atmel,dataflash";
+						spi-max-frequency = <25000000>;
+						reg = <1>;
+
+						partition@0 {
+							label = "U-Boot";
+							reg = <0x0 0x40000>;
+							read-only;
+						};
+
+						partition@40000 {
+							label = "Kernel";
+							reg = <0x40000 0x3c0000>;
+						};
+					};
+				};
+
+				esdhc@50020000 { /* ESDHC3 */
+					cd-gpios = <&gpio2 11 0>; /* GPIO3_11 */
+					wp-gpios = <&gpio2 12 0>; /* GPIO3_12 */
+					status = "okay";
+				};
+			};
+
+			wdog@53f98000 { /* WDOG1 */
+				status = "okay";
+			};
+
+			iomuxc@53fa8000 {
+				compatible = "fsl,imx53-iomuxc-evk";
+				reg = <0x53fa8000 0x4000>;
+			};
+
+			uart0: uart@53fbc000 { /* UART1 */
+				status = "okay";
+			};
+		};
+
+		aips@60000000 {	/* AIPS2 */
+			sdma@63fb0000 {
+				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx53.bin";
+			};
+
+			i2c@63fc4000 { /* I2C2 */
+				status = "okay";
+
+				pmic: mc13892@08 {
+					compatible = "fsl,mc13892", "fsl,mc13xxx";
+					reg = <0x08>;
+				};
+
+				codec: sgtl5000@0a {
+					compatible = "fsl,sgtl5000";
+					reg = <0x0a>;
+				};
+			};
+
+			fec@63fec000 {
+				phy-mode = "rmii";
+				phy-reset-gpios = <&gpio6 6 0>; /* GPIO7_6 */
+				status = "okay";
+			};
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		green {
+			label = "Heartbeat";
+			gpios = <&gpio6 7 0>; /* GPIO7_7 */
+			linux,default-trigger = "heartbeat";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx53-qsb.dts b/arch/arm/boot/dts/imx53-qsb.dts
new file mode 100644
index 0000000..ae6de6d
--- /dev/null
+++ b/arch/arm/boot/dts/imx53-qsb.dts
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx53.dtsi"
+
+/ {
+	model = "Freescale i.MX53 Quick Start Board";
+	compatible = "fsl,imx53-qsb", "fsl,imx53";
+
+	chosen {
+		bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait";
+	};
+
+	memory {
+		reg = <0x70000000 0x40000000>;
+	};
+
+	soc {
+		aips@50000000 { /* AIPS1 */
+			spba@50000000 {
+				esdhc@50004000 { /* ESDHC1 */
+					cd-gpios = <&gpio2 13 0>; /* GPIO3_13 */
+					status = "okay";
+				};
+
+				esdhc@50020000 { /* ESDHC3 */
+					cd-gpios = <&gpio2 11 0>; /* GPIO3_11 */
+					wp-gpios = <&gpio2 12 0>; /* GPIO3_12 */
+					status = "okay";
+				};
+			};
+
+			wdog@53f98000 { /* WDOG1 */
+				status = "okay";
+			};
+
+			iomuxc@53fa8000 {
+				compatible = "fsl,imx53-iomuxc-qsb";
+				reg = <0x53fa8000 0x4000>;
+			};
+
+			uart0: uart@53fbc000 { /* UART1 */
+				status = "okay";
+			};
+		};
+
+		aips@60000000 {	/* AIPS2 */
+			sdma@63fb0000 {
+				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx53.bin";
+			};
+
+			i2c@63fc4000 { /* I2C2 */
+				status = "okay";
+
+				codec: sgtl5000@0a {
+					compatible = "fsl,sgtl5000";
+					reg = <0x0a>;
+				};
+			};
+
+			i2c@63fc8000 { /* I2C1 */
+				status = "okay";
+
+				accelerometer: mma8450@1c {
+					compatible = "fsl,mma8450";
+					reg = <0x1c>;
+				};
+
+				pmic: dialog@48 {
+					compatible = "dialog,da9053", "dialog,da9052";
+					reg = <0x48>;
+				};
+			};
+
+			fec@63fec000 {
+				phy-mode = "rmii";
+				phy-reset-gpios = <&gpio6 6 0>; /* GPIO7_6 */
+				status = "okay";
+			};
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		power {
+			label = "Power Button";
+			gpios = <&gpio0 8 0>; /* GPIO1_8 */
+			linux,code = <116>; /* KEY_POWER */
+			gpio-key,wakeup;
+		};
+
+		volume-up {
+			label = "Volume Up";
+			gpios = <&gpio1 14 0>; /* GPIO2_14 */
+			linux,code = <115>; /* KEY_VOLUMEUP */
+		};
+
+		volume-down {
+			label = "Volume Down";
+			gpios = <&gpio1 15 0>; /* GPIO2_15 */
+			linux,code = <114>; /* KEY_VOLUMEDOWN */
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		user {
+			label = "Heartbeat";
+			gpios = <&gpio6 7 0>; /* GPIO7_7 */
+			linux,default-trigger = "heartbeat";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx53-smd.dts b/arch/arm/boot/dts/imx53-smd.dts
new file mode 100644
index 0000000..b1c062e
--- /dev/null
+++ b/arch/arm/boot/dts/imx53-smd.dts
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx53.dtsi"
+
+/ {
+	model = "Freescale i.MX53 Smart Mobile Reference Design Board";
+	compatible = "fsl,imx53-smd", "fsl,imx53";
+
+	chosen {
+		bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p3 rootwait";
+	};
+
+	memory {
+		reg = <0x70000000 0x40000000>;
+	};
+
+	soc {
+		aips@50000000 { /* AIPS1 */
+			spba@50000000 {
+				esdhc@50004000 { /* ESDHC1 */
+					cd-gpios = <&gpio2 13 0>; /* GPIO3_13 */
+					wp-gpios = <&gpio3 11 0>; /* GPIO4_11 */
+					status = "okay";
+				};
+
+				esdhc@50008000 { /* ESDHC2 */
+					fsl,card-wired;
+					status = "okay";
+				};
+
+				uart2: uart@5000c000 { /* UART3 */
+					fsl,uart-has-rtscts;
+					status = "okay";
+				};
+
+				ecspi@50010000 { /* ECSPI1 */
+					fsl,spi-num-chipselects = <2>;
+					cs-gpios = <&gpio1 30 0>, /* GPIO2_30 */
+						   <&gpio2 19 0>; /* GPIO3_19 */
+					status = "okay";
+
+					zigbee: mc1323@0 {
+						compatible = "fsl,mc1323";
+						spi-max-frequency = <8000000>;
+						reg = <0>;
+					};
+
+					flash: m25p32@1 {
+						#address-cells = <1>;
+						#size-cells = <1>;
+						compatible = "st,m25p32", "st,m25p";
+						spi-max-frequency = <20000000>;
+						reg = <1>;
+
+						partition@0 {
+							label = "U-Boot";
+							reg = <0x0 0x40000>;
+							read-only;
+						};
+
+						partition@40000 {
+							label = "Kernel";
+							reg = <0x40000 0x3c0000>;
+						};
+					};
+				};
+
+				esdhc@50020000 { /* ESDHC3 */
+					fsl,card-wired;
+					status = "okay";
+				};
+			};
+
+			wdog@53f98000 { /* WDOG1 */
+				status = "okay";
+			};
+
+			iomuxc@53fa8000 {
+				compatible = "fsl,imx53-iomuxc-smd";
+				reg = <0x53fa8000 0x4000>;
+			};
+
+			uart0: uart@53fbc000 { /* UART1 */
+				status = "okay";
+			};
+
+			uart1: uart@53fc0000 { /* UART2 */
+				status = "okay";
+			};
+		};
+
+		aips@60000000 {	/* AIPS2 */
+			sdma@63fb0000 {
+				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx53.bin";
+			};
+
+			i2c@63fc4000 { /* I2C2 */
+				status = "okay";
+
+				codec: sgtl5000@0a {
+					compatible = "fsl,sgtl5000";
+					reg = <0x0a>;
+				};
+
+				magnetometer: mag3110@0e {
+					compatible = "fsl,mag3110";
+					reg = <0x0e>;
+				};
+
+				touchkey: mpr121@5a {
+					compatible = "fsl,mpr121";
+					reg = <0x5a>;
+				};
+			};
+
+			i2c@63fc8000 { /* I2C1 */
+				status = "okay";
+
+				accelerometer: mma8450@1c {
+					compatible = "fsl,mma8450";
+					reg = <0x1c>;
+				};
+
+				camera: ov5642@3c {
+					compatible = "ovti,ov5642";
+					reg = <0x3c>;
+				};
+
+				pmic: dialog@48 {
+					compatible = "dialog,da9053", "dialog,da9052";
+					reg = <0x48>;
+				};
+			};
+
+			fec@63fec000 {
+				phy-mode = "rmii";
+				phy-reset-gpios = <&gpio6 6 0>; /* GPIO7_6 */
+				status = "okay";
+			};
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		volume-up {
+			label = "Volume Up";
+			gpios = <&gpio1 14 0>; /* GPIO2_14 */
+			linux,code = <115>; /* KEY_VOLUMEUP */
+		};
+
+		volume-down {
+			label = "Volume Down";
+			gpios = <&gpio1 15 0>; /* GPIO2_15 */
+			linux,code = <114>; /* KEY_VOLUMEDOWN */
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi
new file mode 100644
index 0000000..099cd84
--- /dev/null
+++ b/arch/arm/boot/dts/imx53.dtsi
@@ -0,0 +1,301 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+		serial4 = &uart4;
+	};
+
+	tzic: tz-interrupt-controller@0fffc000 {
+		compatible = "fsl,imx53-tzic", "fsl,tzic";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		reg = <0x0fffc000 0x4000>;
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ckil {
+			compatible = "fsl,imx-ckil", "fixed-clock";
+			clock-frequency = <32768>;
+		};
+
+		ckih1 {
+			compatible = "fsl,imx-ckih1", "fixed-clock";
+			clock-frequency = <22579200>;
+		};
+
+		ckih2 {
+			compatible = "fsl,imx-ckih2", "fixed-clock";
+			clock-frequency = <0>;
+		};
+
+		osc {
+			compatible = "fsl,imx-osc", "fixed-clock";
+			clock-frequency = <24000000>;
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&tzic>;
+		ranges;
+
+		aips@50000000 { /* AIPS1 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x50000000 0x10000000>;
+			ranges;
+
+			spba@50000000 {
+				compatible = "fsl,spba-bus", "simple-bus";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0x50000000 0x40000>;
+				ranges;
+
+				esdhc@50004000 { /* ESDHC1 */
+					compatible = "fsl,imx53-esdhc";
+					reg = <0x50004000 0x4000>;
+					interrupts = <1>;
+					status = "disabled";
+				};
+
+				esdhc@50008000 { /* ESDHC2 */
+					compatible = "fsl,imx53-esdhc";
+					reg = <0x50008000 0x4000>;
+					interrupts = <2>;
+					status = "disabled";
+				};
+
+				uart2: uart@5000c000 { /* UART3 */
+					compatible = "fsl,imx53-uart", "fsl,imx21-uart";
+					reg = <0x5000c000 0x4000>;
+					interrupts = <33>;
+					status = "disabled";
+				};
+
+				ecspi@50010000 { /* ECSPI1 */
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi";
+					reg = <0x50010000 0x4000>;
+					interrupts = <36>;
+					status = "disabled";
+				};
+
+				esdhc@50020000 { /* ESDHC3 */
+					compatible = "fsl,imx53-esdhc";
+					reg = <0x50020000 0x4000>;
+					interrupts = <3>;
+					status = "disabled";
+				};
+
+				esdhc@50024000 { /* ESDHC4 */
+					compatible = "fsl,imx53-esdhc";
+					reg = <0x50024000 0x4000>;
+					interrupts = <4>;
+					status = "disabled";
+				};
+			};
+
+			gpio0: gpio@53f84000 { /* GPIO1 */
+				compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+				reg = <0x53f84000 0x4000>;
+				interrupts = <50 51>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio1: gpio@53f88000 { /* GPIO2 */
+				compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+				reg = <0x53f88000 0x4000>;
+				interrupts = <52 53>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio2: gpio@53f8c000 { /* GPIO3 */
+				compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+				reg = <0x53f8c000 0x4000>;
+				interrupts = <54 55>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio3: gpio@53f90000 { /* GPIO4 */
+				compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+				reg = <0x53f90000 0x4000>;
+				interrupts = <56 57>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			wdog@53f98000 { /* WDOG1 */
+				compatible = "fsl,imx53-wdt", "fsl,imx21-wdt";
+				reg = <0x53f98000 0x4000>;
+				interrupts = <58>;
+				status = "disabled";
+			};
+
+			wdog@53f9c000 { /* WDOG2 */
+				compatible = "fsl,imx53-wdt", "fsl,imx21-wdt";
+				reg = <0x53f9c000 0x4000>;
+				interrupts = <59>;
+				status = "disabled";
+			};
+
+			uart0: uart@53fbc000 { /* UART1 */
+				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
+				reg = <0x53fbc000 0x4000>;
+				interrupts = <31>;
+				status = "disabled";
+			};
+
+			uart1: uart@53fc0000 { /* UART2 */
+				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
+				reg = <0x53fc0000 0x4000>;
+				interrupts = <32>;
+				status = "disabled";
+			};
+
+			gpio4: gpio@53fdc000 { /* GPIO5 */
+				compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+				reg = <0x53fdc000 0x4000>;
+				interrupts = <103 104>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio5: gpio@53fe0000 { /* GPIO6 */
+				compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+				reg = <0x53fe0000 0x4000>;
+				interrupts = <105 106>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio6: gpio@53fe4000 { /* GPIO7 */
+				compatible = "fsl,imx53-gpio", "fsl,imx31-gpio";
+				reg = <0x53fe4000 0x4000>;
+				interrupts = <107 108>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			i2c@53fec000 { /* I2C3 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx53-i2c", "fsl,imx1-i2c";
+				reg = <0x53fec000 0x4000>;
+				interrupts = <64>;
+				status = "disabled";
+			};
+
+			uart3: uart@53ff0000 { /* UART4 */
+				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
+				reg = <0x53ff0000 0x4000>;
+				interrupts = <13>;
+				status = "disabled";
+			};
+		};
+
+		aips@60000000 {	/* AIPS2 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x60000000 0x10000000>;
+			ranges;
+
+			uart4: uart@63f90000 { /* UART5 */
+				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
+				reg = <0x63f90000 0x4000>;
+				interrupts = <86>;
+				status = "disabled";
+			};
+
+			ecspi@63fac000 { /* ECSPI2 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi";
+				reg = <0x63fac000 0x4000>;
+				interrupts = <37>;
+				status = "disabled";
+			};
+
+			sdma@63fb0000 {
+				compatible = "fsl,imx53-sdma", "fsl,imx35-sdma";
+				reg = <0x63fb0000 0x4000>;
+				interrupts = <6>;
+			};
+
+			cspi@63fc0000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx53-cspi", "fsl,imx35-cspi";
+				reg = <0x63fc0000 0x4000>;
+				interrupts = <38>;
+				status = "disabled";
+			};
+
+			i2c@63fc4000 { /* I2C2 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx53-i2c", "fsl,imx1-i2c";
+				reg = <0x63fc4000 0x4000>;
+				interrupts = <63>;
+				status = "disabled";
+			};
+
+			i2c@63fc8000 { /* I2C1 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx53-i2c", "fsl,imx1-i2c";
+				reg = <0x63fc8000 0x4000>;
+				interrupts = <62>;
+				status = "disabled";
+			};
+
+			fec@63fec000 {
+				compatible = "fsl,imx53-fec", "fsl,imx25-fec";
+				reg = <0x63fec000 0x4000>;
+				interrupts = <87>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx6q-sabreauto.dts b/arch/arm/boot/dts/imx6q-sabreauto.dts
new file mode 100644
index 0000000..072974e
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sabreauto.dts
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx6q.dtsi"
+
+/ {
+	model = "Freescale i.MX6 Quad SABRE Automotive Board";
+	compatible = "fsl,imx6q-sabreauto", "fsl,imx6q";
+
+	chosen {
+		bootargs = "console=ttymxc0,115200 root=/dev/mmcblk3p3 rootwait";
+	};
+
+	memory {
+		reg = <0x10000000 0x80000000>;
+	};
+
+	soc {
+		aips-bus@02100000 { /* AIPS2 */
+			enet@02188000 {
+				phy-mode = "rgmii";
+				local-mac-address = [00 04 9F 01 1B 61];
+				status = "okay";
+			};
+
+			usdhc@02198000 { /* uSDHC3 */
+				cd-gpios = <&gpio5 11 0>; /* GPIO6_11 */
+				wp-gpios = <&gpio5 14 0>; /* GPIO6_14 */
+				status = "okay";
+			};
+
+			usdhc@0219c000 { /* uSDHC4 */
+				fsl,card-wired;
+				status = "okay";
+			};
+
+			uart3: uart@021f0000 { /* UART4 */
+				status = "okay";
+			};
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		debug-led {
+			label = "Heartbeat";
+			gpios = <&gpio2 25 0>; /* GPIO3_25 */
+			linux,default-trigger = "heartbeat";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
new file mode 100644
index 0000000..7dda599
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -0,0 +1,575 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+		serial4 = &uart4;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+			next-level-cache = <&L2>;
+		};
+
+		cpu@1 {
+			compatible = "arm,cortex-a9";
+			reg = <1>;
+			next-level-cache = <&L2>;
+		};
+
+		cpu@2 {
+			compatible = "arm,cortex-a9";
+			reg = <2>;
+			next-level-cache = <&L2>;
+		};
+
+		cpu@3 {
+			compatible = "arm,cortex-a9";
+			reg = <3>;
+			next-level-cache = <&L2>;
+		};
+	};
+
+	intc: interrupt-controller@00a01000 {
+		compatible = "arm,cortex-a9-gic";
+		#interrupt-cells = <3>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		interrupt-controller;
+		reg = <0x00a01000 0x1000>,
+		      <0x00a00100 0x100>;
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ckil {
+			compatible = "fsl,imx-ckil", "fixed-clock";
+			clock-frequency = <32768>;
+		};
+
+		ckih1 {
+			compatible = "fsl,imx-ckih1", "fixed-clock";
+			clock-frequency = <0>;
+		};
+
+		osc {
+			compatible = "fsl,imx-osc", "fixed-clock";
+			clock-frequency = <24000000>;
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&intc>;
+		ranges;
+
+		timer@00a00600 {
+			compatible = "arm,smp-twd";
+			reg = <0x00a00600 0x100>;
+			interrupts = <1 13 0xf4>;
+		};
+
+		L2: l2-cache@00a02000 {
+			compatible = "arm,pl310-cache";
+			reg = <0x00a02000 0x1000>;
+			interrupts = <0 92 0x04>;
+			cache-unified;
+			cache-level = <2>;
+		};
+
+		aips-bus@02000000 { /* AIPS1 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x02000000 0x100000>;
+			ranges;
+
+			spba-bus@02000000 {
+				compatible = "fsl,spba-bus", "simple-bus";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0x02000000 0x40000>;
+				ranges;
+
+				spdif@02004000 {
+					reg = <0x02004000 0x4000>;
+					interrupts = <0 52 0x04>;
+				};
+
+				ecspi@02008000 { /* eCSPI1 */
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+					reg = <0x02008000 0x4000>;
+					interrupts = <0 31 0x04>;
+					status = "disabled";
+				};
+
+				ecspi@0200c000 { /* eCSPI2 */
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+					reg = <0x0200c000 0x4000>;
+					interrupts = <0 32 0x04>;
+					status = "disabled";
+				};
+
+				ecspi@02010000 { /* eCSPI3 */
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+					reg = <0x02010000 0x4000>;
+					interrupts = <0 33 0x04>;
+					status = "disabled";
+				};
+
+				ecspi@02014000 { /* eCSPI4 */
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+					reg = <0x02014000 0x4000>;
+					interrupts = <0 34 0x04>;
+					status = "disabled";
+				};
+
+				ecspi@02018000 { /* eCSPI5 */
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+					reg = <0x02018000 0x4000>;
+					interrupts = <0 35 0x04>;
+					status = "disabled";
+				};
+
+				uart0: uart@02020000 { /* UART1 */
+					compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+					reg = <0x02020000 0x4000>;
+					interrupts = <0 26 0x04>;
+					status = "disabled";
+				};
+
+				esai@02024000 {
+					reg = <0x02024000 0x4000>;
+					interrupts = <0 51 0x04>;
+				};
+
+				ssi@02028000 { /* SSI1 */
+					reg = <0x02028000 0x4000>;
+					interrupts = <0 46 0x04>;
+				};
+
+				ssi@0202c000 { /* SSI2 */
+					reg = <0x0202c000 0x4000>;
+					interrupts = <0 47 0x04>;
+				};
+
+				ssi@02030000 { /* SSI3 */
+					reg = <0x02030000 0x4000>;
+					interrupts = <0 48 0x04>;
+				};
+
+				asrc@02034000 {
+					reg = <0x02034000 0x4000>;
+					interrupts = <0 50 0x04>;
+				};
+
+				spba@0203c000 {
+					reg = <0x0203c000 0x4000>;
+				};
+			};
+
+			vpu@02040000 {
+				reg = <0x02040000 0x3c000>;
+				interrupts = <0 3 0x04 0 12 0x04>;
+			};
+
+			aipstz@0207c000 { /* AIPSTZ1 */
+				reg = <0x0207c000 0x4000>;
+			};
+
+			pwm@02080000 { /* PWM1 */
+				reg = <0x02080000 0x4000>;
+				interrupts = <0 83 0x04>;
+			};
+
+			pwm@02084000 { /* PWM2 */
+				reg = <0x02084000 0x4000>;
+				interrupts = <0 84 0x04>;
+			};
+
+			pwm@02088000 { /* PWM3 */
+				reg = <0x02088000 0x4000>;
+				interrupts = <0 85 0x04>;
+			};
+
+			pwm@0208c000 { /* PWM4 */
+				reg = <0x0208c000 0x4000>;
+				interrupts = <0 86 0x04>;
+			};
+
+			flexcan@02090000 { /* CAN1 */
+				reg = <0x02090000 0x4000>;
+				interrupts = <0 110 0x04>;
+			};
+
+			flexcan@02094000 { /* CAN2 */
+				reg = <0x02094000 0x4000>;
+				interrupts = <0 111 0x04>;
+			};
+
+			gpt@02098000 {
+				compatible = "fsl,imx6q-gpt";
+				reg = <0x02098000 0x4000>;
+				interrupts = <0 55 0x04>;
+			};
+
+			gpio0: gpio@0209c000 { /* GPIO1 */
+				compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+				reg = <0x0209c000 0x4000>;
+				interrupts = <0 66 0x04 0 67 0x04>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio1: gpio@020a0000 { /* GPIO2 */
+				compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+				reg = <0x020a0000 0x4000>;
+				interrupts = <0 68 0x04 0 69 0x04>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio2: gpio@020a4000 { /* GPIO3 */
+				compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+				reg = <0x020a4000 0x4000>;
+				interrupts = <0 70 0x04 0 71 0x04>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio3: gpio@020a8000 { /* GPIO4 */
+				compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+				reg = <0x020a8000 0x4000>;
+				interrupts = <0 72 0x04 0 73 0x04>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio4: gpio@020ac000 { /* GPIO5 */
+				compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+				reg = <0x020ac000 0x4000>;
+				interrupts = <0 74 0x04 0 75 0x04>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio5: gpio@020b0000 { /* GPIO6 */
+				compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+				reg = <0x020b0000 0x4000>;
+				interrupts = <0 76 0x04 0 77 0x04>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			gpio6: gpio@020b4000 { /* GPIO7 */
+				compatible = "fsl,imx6q-gpio", "fsl,imx31-gpio";
+				reg = <0x020b4000 0x4000>;
+				interrupts = <0 78 0x04 0 79 0x04>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			kpp@020b8000 {
+				reg = <0x020b8000 0x4000>;
+				interrupts = <0 82 0x04>;
+			};
+
+			wdog@020bc000 { /* WDOG1 */
+				compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
+				reg = <0x020bc000 0x4000>;
+				interrupts = <0 80 0x04>;
+				status = "disabled";
+			};
+
+			wdog@020c0000 { /* WDOG2 */
+				compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
+				reg = <0x020c0000 0x4000>;
+				interrupts = <0 81 0x04>;
+				status = "disabled";
+			};
+
+			ccm@020c4000 {
+				compatible = "fsl,imx6q-ccm";
+				reg = <0x020c4000 0x4000>;
+				interrupts = <0 87 0x04 0 88 0x04>;
+			};
+
+			anatop@020c8000 {
+				compatible = "fsl,imx6q-anatop";
+				reg = <0x020c8000 0x1000>;
+				interrupts = <0 49 0x04 0 54 0x04 0 127 0x04>;
+			};
+
+			usbphy@020c9000 { /* USBPHY1 */
+				reg = <0x020c9000 0x1000>;
+				interrupts = <0 44 0x04>;
+			};
+
+			usbphy@020ca000 { /* USBPHY2 */
+				reg = <0x020ca000 0x1000>;
+				interrupts = <0 45 0x04>;
+			};
+
+			snvs@020cc000 {
+				reg = <0x020cc000 0x4000>;
+				interrupts = <0 19 0x04 0 20 0x04>;
+			};
+
+			epit@020d0000 { /* EPIT1 */
+				reg = <0x020d0000 0x4000>;
+				interrupts = <0 56 0x04>;
+			};
+
+			epit@020d4000 { /* EPIT2 */
+				reg = <0x020d4000 0x4000>;
+				interrupts = <0 57 0x04>;
+			};
+
+			src@020d8000 {
+				compatible = "fsl,imx6q-src";
+				reg = <0x020d8000 0x4000>;
+				interrupts = <0 91 0x04 0 96 0x04>;
+			};
+
+			gpc@020dc000 {
+				compatible = "fsl,imx6q-gpc";
+				reg = <0x020dc000 0x4000>;
+				interrupts = <0 89 0x04 0 90 0x04>;
+			};
+
+			iomuxc@020e0000 {
+				reg = <0x020e0000 0x4000>;
+			};
+
+			dcic@020e4000 { /* DCIC1 */
+				reg = <0x020e4000 0x4000>;
+				interrupts = <0 124 0x04>;
+			};
+
+			dcic@020e8000 { /* DCIC2 */
+				reg = <0x020e8000 0x4000>;
+				interrupts = <0 125 0x04>;
+			};
+
+			sdma@020ec000 {
+				compatible = "fsl,imx6q-sdma", "fsl,imx35-sdma";
+				reg = <0x020ec000 0x4000>;
+				interrupts = <0 2 0x04>;
+			};
+		};
+
+		aips-bus@02100000 { /* AIPS2 */
+			compatible = "fsl,aips-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x02100000 0x100000>;
+			ranges;
+
+			caam@02100000 {
+				reg = <0x02100000 0x40000>;
+				interrupts = <0 105 0x04 0 106 0x04>;
+			};
+
+			aipstz@0217c000 { /* AIPSTZ2 */
+				reg = <0x0217c000 0x4000>;
+			};
+
+			enet@02188000 {
+				compatible = "fsl,imx6q-fec";
+				reg = <0x02188000 0x4000>;
+				interrupts = <0 118 0x04 0 119 0x04>;
+				status = "disabled";
+			};
+
+			mlb@0218c000 {
+				reg = <0x0218c000 0x4000>;
+				interrupts = <0 53 0x04 0 117 0x04 0 126 0x04>;
+			};
+
+			usdhc@02190000 { /* uSDHC1 */
+				compatible = "fsl,imx6q-usdhc";
+				reg = <0x02190000 0x4000>;
+				interrupts = <0 22 0x04>;
+				status = "disabled";
+			};
+
+			usdhc@02194000 { /* uSDHC2 */
+				compatible = "fsl,imx6q-usdhc";
+				reg = <0x02194000 0x4000>;
+				interrupts = <0 23 0x04>;
+				status = "disabled";
+			};
+
+			usdhc@02198000 { /* uSDHC3 */
+				compatible = "fsl,imx6q-usdhc";
+				reg = <0x02198000 0x4000>;
+				interrupts = <0 24 0x04>;
+				status = "disabled";
+			};
+
+			usdhc@0219c000 { /* uSDHC4 */
+				compatible = "fsl,imx6q-usdhc";
+				reg = <0x0219c000 0x4000>;
+				interrupts = <0 25 0x04>;
+				status = "disabled";
+			};
+
+			i2c@021a0000 { /* I2C1 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx6q-i2c", "fsl,imx1-i2c";
+				reg = <0x021a0000 0x4000>;
+				interrupts = <0 36 0x04>;
+				status = "disabled";
+			};
+
+			i2c@021a4000 { /* I2C2 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx6q-i2c", "fsl,imx1-i2c";
+				reg = <0x021a4000 0x4000>;
+				interrupts = <0 37 0x04>;
+				status = "disabled";
+			};
+
+			i2c@021a8000 { /* I2C3 */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx6q-i2c", "fsl,imx1-i2c";
+				reg = <0x021a8000 0x4000>;
+				interrupts = <0 38 0x04>;
+				status = "disabled";
+			};
+
+			romcp@021ac000 {
+				reg = <0x021ac000 0x4000>;
+			};
+
+			mmdc@021b0000 { /* MMDC0 */
+				compatible = "fsl,imx6q-mmdc";
+				reg = <0x021b0000 0x4000>;
+			};
+
+			mmdc@021b4000 { /* MMDC1 */
+				reg = <0x021b4000 0x4000>;
+			};
+
+			weim@021b8000 {
+				reg = <0x021b8000 0x4000>;
+				interrupts = <0 14 0x04>;
+			};
+
+			ocotp@021bc000 {
+				reg = <0x021bc000 0x4000>;
+			};
+
+			ocotp@021c0000 {
+				reg = <0x021c0000 0x4000>;
+				interrupts = <0 21 0x04>;
+			};
+
+			tzasc@021d0000 { /* TZASC1 */
+				reg = <0x021d0000 0x4000>;
+				interrupts = <0 108 0x04>;
+			};
+
+			tzasc@021d4000 { /* TZASC2 */
+				reg = <0x021d4000 0x4000>;
+				interrupts = <0 109 0x04>;
+			};
+
+			audmux@021d8000 {
+				reg = <0x021d8000 0x4000>;
+			};
+
+			mipi@021dc000 { /* MIPI-CSI */
+				reg = <0x021dc000 0x4000>;
+			};
+
+			mipi@021e0000 { /* MIPI-DSI */
+				reg = <0x021e0000 0x4000>;
+			};
+
+			vdoa@021e4000 {
+				reg = <0x021e4000 0x4000>;
+				interrupts = <0 18 0x04>;
+			};
+
+			uart1: uart@021e8000 { /* UART2 */
+				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+				reg = <0x021e8000 0x4000>;
+				interrupts = <0 27 0x04>;
+				status = "disabled";
+			};
+
+			uart2: uart@021ec000 { /* UART3 */
+				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+				reg = <0x021ec000 0x4000>;
+				interrupts = <0 28 0x04>;
+				status = "disabled";
+			};
+
+			uart3: uart@021f0000 { /* UART4 */
+				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+				reg = <0x021f0000 0x4000>;
+				interrupts = <0 29 0x04>;
+				status = "disabled";
+			};
+
+			uart4: uart@021f4000 { /* UART5 */
+				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+				reg = <0x021f4000 0x4000>;
+				interrupts = <0 30 0x04>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/msm8660-surf.dts b/arch/arm/boot/dts/msm8660-surf.dts
new file mode 100644
index 0000000..15ded0d
--- /dev/null
+++ b/arch/arm/boot/dts/msm8660-surf.dts
@@ -0,0 +1,24 @@
+/dts-v1/;
+
+/include/ "skeleton.dtsi"
+
+/ {
+	model = "Qualcomm MSM8660 SURF";
+	compatible = "qcom,msm8660-surf", "qcom,msm8660";
+	interrupt-parent = <&intc>;
+
+	intc: interrupt-controller@02080000 {
+		compatible = "qcom,msm-8660-qgic";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		reg = < 0x02080000 0x1000 >,
+		      < 0x02081000 0x1000 >;
+	};
+
+	serial@19c400000 {
+		compatible = "qcom,msm-hsuart", "qcom,msm-uart";
+		reg = <0x19c40000 0x1000>,
+		      <0x19c00000 0x1000>;
+		interrupts = <195>;
+	};
+};
diff --git a/arch/arm/boot/dts/omap3-beagle.dts b/arch/arm/boot/dts/omap3-beagle.dts
new file mode 100644
index 0000000..9486be6
--- /dev/null
+++ b/arch/arm/boot/dts/omap3-beagle.dts
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+/include/ "omap3.dtsi"
+
+/ {
+	model = "TI OMAP3 BeagleBoard";
+	compatible = "ti,omap3-beagle", "ti,omap3";
+
+	/*
+	 * Since the initial device tree board file does not create any
+	 * devices (MMC, network...), the only way to boot is to provide a
+	 * ramdisk.
+	 */
+	chosen {
+		bootargs = "root=/dev/ram0 rw console=ttyO2,115200n8 initrd=0x81600000,20M ramdisk_size=20480 no_console_suspend debug earlyprintk";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x20000000>; /* 512 MB */
+	};
+};
diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi
new file mode 100644
index 0000000..d202bb5
--- /dev/null
+++ b/arch/arm/boot/dts/omap3.dtsi
@@ -0,0 +1,63 @@
+/*
+ * Device Tree Source for OMAP3 SoC
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	compatible = "ti,omap3430", "ti,omap3";
+
+	cpus {
+		cpu@0 {
+			compatible = "arm,cortex-a8";
+		};
+	};
+
+	/*
+	 * The soc node represents the soc top level view. It is uses for IPs
+	 * that are not memory mapped in the MPU view or for the MPU itself.
+	 */
+	soc {
+		compatible = "ti,omap-infra";
+		mpu {
+			compatible = "ti,omap3-mpu";
+			ti,hwmods = "mpu";
+		};
+
+		iva {
+			compatible = "ti,iva2.2";
+			ti,hwmods = "iva";
+
+			dsp {
+				compatible = "ti,omap3-c64";
+			};
+		};
+	};
+
+	/*
+	 * XXX: Use a flat representation of the OMAP3 interconnect.
+	 * The real OMAP interconnect network is quite complex.
+	 * Since that will not bring real advantage to represent that in DT for
+	 * the moment, just use a fake OCP bus entry to represent the whole bus
+	 * hierarchy.
+	 */
+	ocp {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		ti,hwmods = "l3_main";
+
+		intc: interrupt-controller@1 {
+			compatible = "ti,omap3-intc";
+			interrupt-controller;
+			#interrupt-cells = <1>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/omap4-panda.dts b/arch/arm/boot/dts/omap4-panda.dts
new file mode 100644
index 0000000..c702657
--- /dev/null
+++ b/arch/arm/boot/dts/omap4-panda.dts
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+/include/ "omap4.dtsi"
+
+/ {
+	model = "TI OMAP4 PandaBoard";
+	compatible = "ti,omap4-panda", "ti,omap4430", "ti,omap4";
+
+	/*
+	 * Since the initial device tree board file does not create any
+	 * devices (MMC, network...), the only way to boot is to provide a
+	 * ramdisk.
+	 */
+	chosen {
+		bootargs = "root=/dev/ram0 rw console=ttyO2,115200n8 initrd=0x81600000,20M ramdisk_size=20480 no_console_suspend debug";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x40000000>; /* 1 GB */
+	};
+};
diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts
new file mode 100644
index 0000000..066e28c
--- /dev/null
+++ b/arch/arm/boot/dts/omap4-sdp.dts
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+/include/ "omap4.dtsi"
+
+/ {
+	model = "TI OMAP4 SDP board";
+	compatible = "ti,omap4-sdp", "ti,omap4430", "ti,omap4";
+
+	/*
+	 * Since the initial device tree board file does not create any
+	 * devices (MMC, network...), the only way to boot is to provide a
+	 * ramdisk.
+	 */
+	chosen {
+		bootargs = "root=/dev/ram0 rw console=ttyO2,115200n8 initrd=0x81600000,20M ramdisk_size=20480 no_console_suspend debug";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x40000000>; /* 1 GB */
+	};
+};
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
new file mode 100644
index 0000000..4c61c82
--- /dev/null
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * Carveout for multimedia usecases
+ * It should be the last 48MB of the first 512MB memory part
+ * In theory, it should not even exist. That zone should be reserved
+ * dynamically during the .reserve callback.
+ */
+/memreserve/ 0x9d000000 0x03000000;
+
+/include/ "skeleton.dtsi"
+
+/ {
+	compatible = "ti,omap4430", "ti,omap4";
+	interrupt-parent = <&gic>;
+
+	aliases {
+	};
+
+	cpus {
+		cpu@0 {
+			compatible = "arm,cortex-a9";
+		};
+		cpu@1 {
+			compatible = "arm,cortex-a9";
+		};
+	};
+
+	/*
+	 * The soc node represents the soc top level view. It is uses for IPs
+	 * that are not memory mapped in the MPU view or for the MPU itself.
+	 */
+	soc {
+		compatible = "ti,omap-infra";
+		mpu {
+			compatible = "ti,omap4-mpu";
+			ti,hwmods = "mpu";
+		};
+
+		dsp {
+			compatible = "ti,omap3-c64";
+			ti,hwmods = "dsp";
+		};
+
+		iva {
+			compatible = "ti,ivahd";
+			ti,hwmods = "iva";
+		};
+	};
+
+	/*
+	 * XXX: Use a flat representation of the OMAP4 interconnect.
+	 * The real OMAP interconnect network is quite complex.
+	 *
+	 * MPU -+-- MPU_PRIVATE - GIC, L2
+	 *      |
+	 *      +----------------+----------+
+	 *      |                |          |
+	 *      +            +- EMIF - DDR  |
+	 *      |            |              |
+	 *      |            +     +--------+
+	 *      |            |     |
+	 *      |            +- L4_ABE - AESS, MCBSP, TIMERs...
+	 *      |            |
+	 *      +- L3_MAIN --+- L4_CORE - IPs...
+	 *                   |
+	 *                   +- L4_PER - IPs...
+	 *                   |
+	 *                   +- L4_CFG -+- L4_WKUP - IPs...
+	 *                   |          |
+	 *                   |          +- IPs...
+	 *                   +- IPU ----+
+	 *                   |          |
+	 *                   +- DSP ----+
+	 *                   |          |
+	 *                   +- DSS ----+
+	 *
+	 * Since that will not bring real advantage to represent that in DT for
+	 * the moment, just use a fake OCP bus entry to represent the whole bus
+	 * hierarchy.
+	 */
+	ocp {
+		compatible = "ti,omap4-l3-noc", "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		ti,hwmods = "l3_main_1", "l3_main_2", "l3_main_3";
+
+		gic: interrupt-controller@48241000 {
+			compatible = "arm,cortex-a9-gic";
+			interrupt-controller;
+			#interrupt-cells = <1>;
+			reg = <0x48241000 0x1000>,
+			      <0x48240100 0x0100>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/picoxcell-pc3x2.dtsi b/arch/arm/boot/dts/picoxcell-pc3x2.dtsi
new file mode 100644
index 0000000..f0a8c20
--- /dev/null
+++ b/arch/arm/boot/dts/picoxcell-pc3x2.dtsi
@@ -0,0 +1,249 @@
+/*
+ *  Copyright (C) 2011 Picochip, Jamie Iles
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+/include/ "skeleton.dtsi"
+/ {
+	model = "Picochip picoXcell PC3X2";
+	compatible = "picochip,pc3x2";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			compatible = "arm,1176jz-s";
+			clock-frequency = <400000000>;
+			reg = <0>;
+			d-cache-line-size = <32>;
+			d-cache-size = <32768>;
+			i-cache-line-size = <32>;
+			i-cache-size = <32768>;
+		};
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		pclk: clock@0 {
+			compatible = "fixed-clock";
+			clock-outputs = "bus", "pclk";
+			clock-frequency = <200000000>;
+			ref-clock = <&ref_clk>, "ref";
+		};
+	};
+
+	paxi {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0x80000000 0x400000>;
+
+		emac: gem@30000 {
+			compatible = "cadence,gem";
+			reg = <0x30000 0x10000>;
+			interrupts = <31>;
+		};
+
+		dmac1: dmac@40000 {
+			compatible = "snps,dw-dmac";
+			reg = <0x40000 0x10000>;
+			interrupts = <25>;
+		};
+
+		dmac2: dmac@50000 {
+			compatible = "snps,dw-dmac";
+			reg = <0x50000 0x10000>;
+			interrupts = <26>;
+		};
+
+		vic0: interrupt-controller@60000 {
+			compatible = "arm,pl192-vic";
+			interrupt-controller;
+			reg = <0x60000 0x1000>;
+			#interrupt-cells = <1>;
+		};
+
+		vic1: interrupt-controller@64000 {
+			compatible = "arm,pl192-vic";
+			interrupt-controller;
+			reg = <0x64000 0x1000>;
+			#interrupt-cells = <1>;
+		};
+
+		fuse: picoxcell-fuse@80000 {
+			compatible = "picoxcell,fuse-pc3x2";
+			reg = <0x80000 0x10000>;
+		};
+
+		ssi: picoxcell-spi@90000 {
+			compatible = "picoxcell,spi";
+			reg = <0x90000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <10>;
+		};
+
+		ipsec: spacc@100000 {
+			compatible = "picochip,spacc-ipsec";
+			reg = <0x100000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <24>;
+			ref-clock = <&pclk>, "ref";
+		};
+
+		srtp: spacc@140000 {
+			compatible = "picochip,spacc-srtp";
+			reg = <0x140000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <23>;
+		};
+
+		l2_engine: spacc@180000 {
+			compatible = "picochip,spacc-l2";
+			reg = <0x180000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <22>;
+			ref-clock = <&pclk>, "ref";
+		};
+
+		apb {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 0x200000 0x80000>;
+
+			rtc0: rtc@00000 {
+				compatible = "picochip,pc3x2-rtc";
+				clock-freq = <200000000>;
+				reg = <0x00000 0xf>;
+				interrupt-parent = <&vic1>;
+				interrupts = <8>;
+			};
+
+			timer0: timer@10000 {
+				compatible = "picochip,pc3x2-timer";
+				interrupt-parent = <&vic0>;
+				interrupts = <4>;
+				clock-freq = <200000000>;
+				reg = <0x10000 0x14>;
+			};
+
+			timer1: timer@10014 {
+				compatible = "picochip,pc3x2-timer";
+				interrupt-parent = <&vic0>;
+				interrupts = <5>;
+				clock-freq = <200000000>;
+				reg = <0x10014 0x14>;
+			};
+
+			timer2: timer@10028 {
+				compatible = "picochip,pc3x2-timer";
+				interrupt-parent = <&vic0>;
+				interrupts = <6>;
+				clock-freq = <200000000>;
+				reg = <0x10028 0x14>;
+			};
+
+			timer3: timer@1003c {
+				compatible = "picochip,pc3x2-timer";
+				interrupt-parent = <&vic0>;
+				interrupts = <7>;
+				clock-freq = <200000000>;
+				reg = <0x1003c 0x14>;
+			};
+
+			gpio: gpio@20000 {
+				compatible = "snps,dw-apb-gpio";
+				reg = <0x20000 0x1000>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg-io-width = <4>;
+
+				banka: gpio-controller@0 {
+					compatible = "snps,dw-apb-gpio-bank";
+					gpio-controller;
+					#gpio-cells = <2>;
+					gpio-generic,nr-gpio = <8>;
+
+					regoffset-dat = <0x50>;
+					regoffset-set = <0x00>;
+					regoffset-dirout = <0x04>;
+				};
+
+				bankb: gpio-controller@1 {
+					compatible = "snps,dw-apb-gpio-bank";
+					gpio-controller;
+					#gpio-cells = <2>;
+					gpio-generic,nr-gpio = <8>;
+
+					regoffset-dat = <0x54>;
+					regoffset-set = <0x0c>;
+					regoffset-dirout = <0x10>;
+				};
+			};
+
+			uart0: uart@30000 {
+				compatible = "snps,dw-apb-uart";
+				reg = <0x30000 0x1000>;
+				interrupt-parent = <&vic1>;
+				interrupts = <10>;
+				clock-frequency = <3686400>;
+				reg-shift = <2>;
+				reg-io-width = <4>;
+			};
+
+			uart1: uart@40000 {
+				compatible = "snps,dw-apb-uart";
+				reg = <0x40000 0x1000>;
+				interrupt-parent = <&vic1>;
+				interrupts = <9>;
+				clock-frequency = <3686400>;
+				reg-shift = <2>;
+				reg-io-width = <4>;
+			};
+
+			wdog: watchdog@50000 {
+				compatible = "snps,dw-apb-wdg";
+				reg = <0x50000 0x10000>;
+				interrupt-parent = <&vic0>;
+				interrupts = <11>;
+				bus-clock = <&pclk>, "bus";
+			};
+		};
+	};
+
+	rwid-axi {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges;
+
+		ebi@50000000 {
+			compatible = "simple-bus";
+			#address-cells = <2>;
+			#size-cells = <1>;
+			ranges = <0 0 0x40000000 0x08000000
+				  1 0 0x48000000 0x08000000
+				  2 0 0x50000000 0x08000000
+				  3 0 0x58000000 0x08000000>;
+		};
+
+		axi2pico@c0000000 {
+			compatible = "picochip,axi2pico-pc3x2";
+			reg = <0xc0000000 0x10000>;
+			interrupts = <13 14 15 16 17 18 19 20 21>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/picoxcell-pc3x3.dtsi b/arch/arm/boot/dts/picoxcell-pc3x3.dtsi
new file mode 100644
index 0000000..daa962d
--- /dev/null
+++ b/arch/arm/boot/dts/picoxcell-pc3x3.dtsi
@@ -0,0 +1,365 @@
+/*
+ *  Copyright (C) 2011 Picochip, Jamie Iles
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+/include/ "skeleton.dtsi"
+/ {
+	model = "Picochip picoXcell PC3X3";
+	compatible = "picochip,pc3x3";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			compatible = "arm,1176jz-s";
+			cpu-clock = <&arm_clk>, "cpu";
+			reg = <0>;
+			d-cache-line-size = <32>;
+			d-cache-size = <32768>;
+			i-cache-line-size = <32>;
+			i-cache-size = <32768>;
+		};
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		clkgate: clkgate@800a0048 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x800a0048 4>;
+			compatible = "picochip,pc3x3-clk-gate";
+
+			tzprot_clk: clock@0 {
+				compatible = "picochip,pc3x3-gated-clk";
+				clock-outputs = "bus";
+				picochip,clk-disable-bit = <0>;
+				clock-frequency = <200000000>;
+				ref-clock = <&ref_clk>, "ref";
+			};
+
+			spi_clk: clock@1 {
+				compatible = "picochip,pc3x3-gated-clk";
+				clock-outputs = "bus";
+				picochip,clk-disable-bit = <1>;
+				clock-frequency = <200000000>;
+				ref-clock = <&ref_clk>, "ref";
+			};
+
+			dmac0_clk: clock@2 {
+				compatible = "picochip,pc3x3-gated-clk";
+				clock-outputs = "bus";
+				picochip,clk-disable-bit = <2>;
+				clock-frequency = <200000000>;
+				ref-clock = <&ref_clk>, "ref";
+			};
+
+			dmac1_clk: clock@3 {
+				compatible = "picochip,pc3x3-gated-clk";
+				clock-outputs = "bus";
+				picochip,clk-disable-bit = <3>;
+				clock-frequency = <200000000>;
+				ref-clock = <&ref_clk>, "ref";
+			};
+
+			ebi_clk: clock@4 {
+				compatible = "picochip,pc3x3-gated-clk";
+				clock-outputs = "bus";
+				picochip,clk-disable-bit = <4>;
+				clock-frequency = <200000000>;
+				ref-clock = <&ref_clk>, "ref";
+			};
+
+			ipsec_clk: clock@5 {
+				compatible = "picochip,pc3x3-gated-clk";
+				clock-outputs = "bus";
+				picochip,clk-disable-bit = <5>;
+				clock-frequency = <200000000>;
+				ref-clock = <&ref_clk>, "ref";
+			};
+
+			l2_clk: clock@6 {
+				compatible = "picochip,pc3x3-gated-clk";
+				clock-outputs = "bus";
+				picochip,clk-disable-bit = <6>;
+				clock-frequency = <200000000>;
+				ref-clock = <&ref_clk>, "ref";
+			};
+
+			trng_clk: clock@7 {
+				compatible = "picochip,pc3x3-gated-clk";
+				clock-outputs = "bus";
+				picochip,clk-disable-bit = <7>;
+				clock-frequency = <200000000>;
+				ref-clock = <&ref_clk>, "ref";
+			};
+
+			fuse_clk: clock@8 {
+				compatible = "picochip,pc3x3-gated-clk";
+				clock-outputs = "bus";
+				picochip,clk-disable-bit = <8>;
+				clock-frequency = <200000000>;
+				ref-clock = <&ref_clk>, "ref";
+			};
+
+			otp_clk: clock@9 {
+				compatible = "picochip,pc3x3-gated-clk";
+				clock-outputs = "bus";
+				picochip,clk-disable-bit = <9>;
+				clock-frequency = <200000000>;
+				ref-clock = <&ref_clk>, "ref";
+			};
+		};
+
+		arm_clk: clock@11 {
+			compatible = "picochip,pc3x3-pll";
+			reg = <0x800a0050 0x8>;
+			picochip,min-freq = <140000000>;
+			picochip,max-freq = <700000000>;
+			ref-clock = <&ref_clk>, "ref";
+			clock-outputs = "cpu";
+		};
+
+		pclk: clock@12 {
+			compatible = "fixed-clock";
+			clock-outputs = "bus", "pclk";
+			clock-frequency = <200000000>;
+			ref-clock = <&ref_clk>, "ref";
+		};
+	};
+
+	paxi {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0x80000000 0x400000>;
+
+		emac: gem@30000 {
+			compatible = "cadence,gem";
+			reg = <0x30000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <31>;
+		};
+
+		dmac1: dmac@40000 {
+			compatible = "snps,dw-dmac";
+			reg = <0x40000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <25>;
+		};
+
+		dmac2: dmac@50000 {
+			compatible = "snps,dw-dmac";
+			reg = <0x50000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <26>;
+		};
+
+		vic0: interrupt-controller@60000 {
+			compatible = "arm,pl192-vic";
+			interrupt-controller;
+			reg = <0x60000 0x1000>;
+			#interrupt-cells = <1>;
+		};
+
+		vic1: interrupt-controller@64000 {
+			compatible = "arm,pl192-vic";
+			interrupt-controller;
+			reg = <0x64000 0x1000>;
+			#interrupt-cells = <1>;
+		};
+
+		fuse: picoxcell-fuse@80000 {
+			compatible = "picoxcell,fuse-pc3x3";
+			reg = <0x80000 0x10000>;
+		};
+
+		ssi: picoxcell-spi@90000 {
+			compatible = "picoxcell,spi";
+			reg = <0x90000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <10>;
+		};
+
+		ipsec: spacc@100000 {
+			compatible = "picochip,spacc-ipsec";
+			reg = <0x100000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <24>;
+			ref-clock = <&ipsec_clk>, "ref";
+		};
+
+		srtp: spacc@140000 {
+			compatible = "picochip,spacc-srtp";
+			reg = <0x140000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <23>;
+		};
+
+		l2_engine: spacc@180000 {
+			compatible = "picochip,spacc-l2";
+			reg = <0x180000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <22>;
+			ref-clock = <&l2_clk>, "ref";
+		};
+
+		apb {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 0x200000 0x80000>;
+
+			rtc0: rtc@00000 {
+				compatible = "picochip,pc3x2-rtc";
+				clock-freq = <200000000>;
+				reg = <0x00000 0xf>;
+				interrupt-parent = <&vic0>;
+				interrupts = <8>;
+			};
+
+			timer0: timer@10000 {
+				compatible = "picochip,pc3x2-timer";
+				interrupt-parent = <&vic0>;
+				interrupts = <4>;
+				clock-freq = <200000000>;
+				reg = <0x10000 0x14>;
+			};
+
+			timer1: timer@10014 {
+				compatible = "picochip,pc3x2-timer";
+				interrupt-parent = <&vic0>;
+				interrupts = <5>;
+				clock-freq = <200000000>;
+				reg = <0x10014 0x14>;
+			};
+
+			gpio: gpio@20000 {
+				compatible = "snps,dw-apb-gpio";
+				reg = <0x20000 0x1000>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg-io-width = <4>;
+
+				banka: gpio-controller@0 {
+					compatible = "snps,dw-apb-gpio-bank";
+					gpio-controller;
+					#gpio-cells = <2>;
+					gpio-generic,nr-gpio = <8>;
+
+					regoffset-dat = <0x50>;
+					regoffset-set = <0x00>;
+					regoffset-dirout = <0x04>;
+				};
+
+				bankb: gpio-controller@1 {
+					compatible = "snps,dw-apb-gpio-bank";
+					gpio-controller;
+					#gpio-cells = <2>;
+					gpio-generic,nr-gpio = <16>;
+
+					regoffset-dat = <0x54>;
+					regoffset-set = <0x0c>;
+					regoffset-dirout = <0x10>;
+				};
+
+				bankd: gpio-controller@2 {
+					compatible = "snps,dw-apb-gpio-bank";
+					gpio-controller;
+					#gpio-cells = <2>;
+					gpio-generic,nr-gpio = <30>;
+
+					regoffset-dat = <0x5c>;
+					regoffset-set = <0x24>;
+					regoffset-dirout = <0x28>;
+				};
+			};
+
+			uart0: uart@30000 {
+				compatible = "snps,dw-apb-uart";
+				reg = <0x30000 0x1000>;
+				interrupt-parent = <&vic1>;
+				interrupts = <10>;
+				clock-frequency = <3686400>;
+				reg-shift = <2>;
+				reg-io-width = <4>;
+			};
+
+			uart1: uart@40000 {
+				compatible = "snps,dw-apb-uart";
+				reg = <0x40000 0x1000>;
+				interrupt-parent = <&vic1>;
+				interrupts = <9>;
+				clock-frequency = <3686400>;
+				reg-shift = <2>;
+				reg-io-width = <4>;
+			};
+
+			wdog: watchdog@50000 {
+				compatible = "snps,dw-apb-wdg";
+				reg = <0x50000 0x10000>;
+				interrupt-parent = <&vic0>;
+				interrupts = <11>;
+				bus-clock = <&pclk>, "bus";
+			};
+
+			timer2: timer@60000 {
+				compatible = "picochip,pc3x2-timer";
+				interrupt-parent = <&vic0>;
+				interrupts = <6>;
+				clock-freq = <200000000>;
+				reg = <0x60000 0x14>;
+			};
+
+			timer3: timer@60014 {
+				compatible = "picochip,pc3x2-timer";
+				interrupt-parent = <&vic0>;
+				interrupts = <7>;
+				clock-freq = <200000000>;
+				reg = <0x60014 0x14>;
+			};
+		};
+	};
+
+	rwid-axi {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges;
+
+		ebi@50000000 {
+			compatible = "simple-bus";
+			#address-cells = <2>;
+			#size-cells = <1>;
+			ranges = <0 0 0x40000000 0x08000000
+				  1 0 0x48000000 0x08000000
+				  2 0 0x50000000 0x08000000
+				  3 0 0x58000000 0x08000000>;
+		};
+
+		axi2pico@c0000000 {
+			compatible = "picochip,axi2pico-pc3x3";
+			reg = <0xc0000000 0x10000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <13 14 15 16 17 18 19 20 21>;
+		};
+
+		otp@ffff8000 {
+			compatible = "picochip,otp-pc3x3";
+			reg = <0xffff8000 0x8000>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/picoxcell-pc7302-pc3x2.dts b/arch/arm/boot/dts/picoxcell-pc7302-pc3x2.dts
new file mode 100644
index 0000000..1297414
--- /dev/null
+++ b/arch/arm/boot/dts/picoxcell-pc7302-pc3x2.dts
@@ -0,0 +1,86 @@
+/*
+ *  Copyright (C) 2011 Picochip, Jamie Iles
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/include/ "picoxcell-pc3x2.dtsi"
+/ {
+	model = "Picochip PC7302 (PC3X2)";
+	compatible = "picochip,pc7302-pc3x2", "picochip,pc3x2";
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x08000000>;
+	};
+
+	chosen {
+		linux,stdout-path = &uart0;
+	};
+
+	clocks {
+		ref_clk: clock@1 {
+			compatible = "fixed-clock";
+			clock-outputs = "ref";
+			clock-frequency = <20000000>;
+		};
+	};
+
+	rwid-axi {
+		ebi@50000000 {
+			nand: gpio-nand@2,0 {
+				compatible = "gpio-control-nand";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <2 0x0000 0x1000>;
+				bus-clock = <&pclk>, "bus";
+				gpio-control-nand,io-sync-reg =
+					<0x00000000 0x80220000>;
+
+				gpios = <&banka 1 0	/* rdy */
+					 &banka 2 0 	/* nce */
+					 &banka 3 0 	/* ale */
+					 &banka 4 0 	/* cle */
+					 0		/* nwp */>;
+
+				boot@100000 {
+					label = "Boot";
+					reg = <0x100000 0x80000>;
+				};
+
+				redundant-boot@200000 {
+					label = "Redundant Boot";
+					reg = <0x200000 0x80000>;
+				};
+
+				boot-env@300000 {
+					label = "Boot Evironment";
+					reg = <0x300000 0x20000>;
+				};
+
+				redundant-boot-env@320000 {
+					label = "Redundant Boot Environment";
+					reg = <0x300000 0x20000>;
+				};
+
+				kernel@380000 {
+					label = "Kernel";
+					reg = <0x380000 0x800000>;
+				};
+
+				fs@b80000 {
+					label = "File System";
+					reg = <0xb80000 0xf480000>;
+				};
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/picoxcell-pc7302-pc3x3.dts b/arch/arm/boot/dts/picoxcell-pc7302-pc3x3.dts
new file mode 100644
index 0000000..9e317a4
--- /dev/null
+++ b/arch/arm/boot/dts/picoxcell-pc7302-pc3x3.dts
@@ -0,0 +1,92 @@
+/*
+ *  Copyright (C) 2011 Picochip, Jamie Iles
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/include/ "picoxcell-pc3x3.dtsi"
+/ {
+	model = "Picochip PC7302 (PC3X3)";
+	compatible = "picochip,pc7302-pc3x3", "picochip,pc3x3";
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x08000000>;
+	};
+
+	chosen {
+		linux,stdout-path = &uart0;
+	};
+
+	clocks {
+		ref_clk: clock@10 {
+			compatible = "fixed-clock";
+			clock-outputs = "ref";
+			clock-frequency = <20000000>;
+		};
+
+		clkgate: clkgate@800a0048 {
+			clock@4 {
+				picochip,clk-no-disable;
+			};
+		};
+	};
+
+	rwid-axi {
+		ebi@50000000 {
+			nand: gpio-nand@2,0 {
+				compatible = "gpio-control-nand";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <2 0x0000 0x1000>;
+				bus-clock = <&ebi_clk>, "bus";
+				gpio-control-nand,io-sync-reg =
+					<0x00000000 0x80220000>;
+
+				gpios = <&banka 1 0	/* rdy */
+					 &banka 2 0 	/* nce */
+					 &banka 3 0 	/* ale */
+					 &banka 4 0 	/* cle */
+					 0		/* nwp */>;
+
+				boot@100000 {
+					label = "Boot";
+					reg = <0x100000 0x80000>;
+				};
+
+				redundant-boot@200000 {
+					label = "Redundant Boot";
+					reg = <0x200000 0x80000>;
+				};
+
+				boot-env@300000 {
+					label = "Boot Evironment";
+					reg = <0x300000 0x20000>;
+				};
+
+				redundant-boot-env@320000 {
+					label = "Redundant Boot Environment";
+					reg = <0x300000 0x20000>;
+				};
+
+				kernel@380000 {
+					label = "Kernel";
+					reg = <0x380000 0x800000>;
+				};
+
+				fs@b80000 {
+					label = "File System";
+					reg = <0xb80000 0xf480000>;
+				};
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/prima2-cb.dts b/arch/arm/boot/dts/prima2-cb.dts
index 6fecc88..34ae3a6 100644
--- a/arch/arm/boot/dts/prima2-cb.dts
+++ b/arch/arm/boot/dts/prima2-cb.dts
@@ -39,9 +39,12 @@
 		ranges = <0x40000000 0x40000000 0x80000000>;
 
 		l2-cache-controller@80040000 {
-			compatible = "arm,pl310-cache";
+			compatible = "arm,pl310-cache", "sirf,prima2-pl310-cache";
 			reg = <0x80040000 0x1000>;
 			interrupts = <59>;
+			arm,tag-latency = <1 1 1>;
+			arm,data-latency = <1 1 1>;
+			arm,filter-ranges = <0 0x40000000>;
 		};
 
 		intc: interrupt-controller@80020000 {
@@ -67,6 +70,11 @@
 				compatible = "sirf,prima2-rstc";
 				reg = <0x88010000 0x1000>;
 			};
+
+			rsc-controller@88020000 {
+				compatible = "sirf,prima2-rsc";
+				reg = <0x88020000 0x1000>;
+			};
 		};
 
 		mem-iobg {
@@ -274,7 +282,7 @@
 			gpio: gpio-controller@b0120000 {
 				#gpio-cells = <2>;
 				#interrupt-cells = <2>;
-				compatible = "sirf,prima2-gpio";
+				compatible = "sirf,prima2-gpio-pinmux";
 				reg = <0xb0120000 0x10000>;
 				gpio-controller;
 				interrupt-controller;
@@ -358,7 +366,7 @@
 		};
 
 		rtc-iobg {
-			compatible = "sirf,prima2-rtciobg", "simple-bus";
+			compatible = "sirf,prima2-rtciobg", "sirf-prima2-rtciobg-bus";
 			#address-cells = <1>;
 			#size-cells = <1>;
 			reg = <0x80030000 0x10000>;
diff --git a/arch/arm/boot/dts/tegra-harmony.dts b/arch/arm/boot/dts/tegra-harmony.dts
index e581866..0e225b8 100644
--- a/arch/arm/boot/dts/tegra-harmony.dts
+++ b/arch/arm/boot/dts/tegra-harmony.dts
@@ -66,5 +66,6 @@
 		cd-gpios = <&gpio 58 0>; /* gpio PH2 */
 		wp-gpios = <&gpio 59 0>; /* gpio PH3 */
 		power-gpios = <&gpio 70 0>; /* gpio PI6 */
+		support-8bit;
 	};
 };
diff --git a/arch/arm/boot/dts/tegra-seaboard.dts b/arch/arm/boot/dts/tegra-seaboard.dts
index 64cedca..a72299b 100644
--- a/arch/arm/boot/dts/tegra-seaboard.dts
+++ b/arch/arm/boot/dts/tegra-seaboard.dts
@@ -25,4 +25,8 @@
 		wp-gpios = <&gpio 57 0>; /* gpio PH1 */
 		power-gpios = <&gpio 70 0>; /* gpio PI6 */
 	};
+
+	sdhci@c8000600 {
+		support-8bit;
+	};
 };
diff --git a/arch/arm/boot/dts/tegra-ventana.dts b/arch/arm/boot/dts/tegra-ventana.dts
new file mode 100644
index 0000000..9b29a62
--- /dev/null
+++ b/arch/arm/boot/dts/tegra-ventana.dts
@@ -0,0 +1,32 @@
+/dts-v1/;
+
+/memreserve/ 0x1c000000 0x04000000;
+/include/ "tegra20.dtsi"
+
+/ {
+	model = "NVIDIA Tegra2 Ventana evaluation board";
+	compatible = "nvidia,ventana", "nvidia,tegra20";
+
+	chosen {
+		bootargs = "vmalloc=192M video=tegrafb console=ttyS0,115200n8 root=/dev/ram rdinit=/sbin/init";
+	};
+
+	memory {
+		reg = < 0x00000000 0x40000000 >;
+	};
+
+	serial@70006300 {
+		clock-frequency = < 216000000 >;
+	};
+
+	sdhci@c8000400 {
+		cd-gpios = <&gpio 69 0>; /* gpio PI5 */
+		wp-gpios = <&gpio 57 0>; /* gpio PH1 */
+		power-gpios = <&gpio 155 0>; /* gpio PT3 */
+	};
+
+	sdhci@c8000600 {
+		power-gpios = <&gpio 70 0>; /* gpio PI6 */
+		support-8bit;
+	};
+};
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 5727595..65d7e6a 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -77,6 +77,14 @@
 		gpio-controller;
 	};
 
+	pinmux: pinmux@70000000 {
+		compatible = "nvidia,tegra20-pinmux";
+		reg = < 0x70000014 0x10    /* Tri-state registers */
+			0x70000080 0x20    /* Mux registers */
+			0x700000a0 0x14    /* Pull-up/down registers */
+			0x70000868 0xa8 >; /* Pad control registers */
+	};
+
 	serial@70006000 {
 		compatible = "nvidia,tegra20-uart";
 		reg = <0x70006000 0x40>;
diff --git a/arch/arm/boot/dts/usb_a9g20.dts b/arch/arm/boot/dts/usb_a9g20.dts
new file mode 100644
index 0000000..d66e2c0
--- /dev/null
+++ b/arch/arm/boot/dts/usb_a9g20.dts
@@ -0,0 +1,30 @@
+/*
+ * usb_a9g20.dts - Device Tree file for Caloa USB A9G20 board
+ *
+ *  Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+/include/ "at91sam9g20.dtsi"
+
+/ {
+	model = "Calao USB A9G20";
+	compatible = "calao,usb-a9g20", "atmel,at91sam9g20", "atmel,at91sam9";
+
+	chosen {
+		bootargs = "mem=64M console=ttyS0,115200 mtdparts=atmel_nand:128k(at91bootstrap),256k(barebox)ro,128k(bareboxenv),128k(bareboxenv2),4M(kernel),120M(rootfs),-(data) root=/dev/mtdblock5 rw rootfstype=ubifs";
+	};
+
+	memory@20000000 {
+		reg = <0x20000000 0x4000000>;
+	};
+
+	ahb {
+		apb {
+			dbgu: serial@fffff200 {
+				status = "okay";
+			};
+		};
+	};
+};
diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
index 4b71766..74df9ca 100644
--- a/arch/arm/common/Kconfig
+++ b/arch/arm/common/Kconfig
@@ -1,4 +1,5 @@
 config ARM_GIC
+	select IRQ_DOMAIN
 	bool
 
 config ARM_VIC
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index a8fc6b2..0e6ae47 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -24,11 +24,17 @@
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/module.h>
 #include <linux/list.h>
 #include <linux/smp.h>
 #include <linux/cpu_pm.h>
 #include <linux/cpumask.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/irqdomain.h>
 #include <linux/interrupt.h>
 #include <linux/percpu.h>
 #include <linux/slab.h>
@@ -75,8 +81,7 @@ static inline void __iomem *gic_cpu_base(struct irq_data *d)
 
 static inline unsigned int gic_irq(struct irq_data *d)
 {
-	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
-	return d->irq - gic_data->irq_offset;
+	return d->hwirq;
 }
 
 /*
@@ -84,7 +89,7 @@ static inline unsigned int gic_irq(struct irq_data *d)
  */
 static void gic_mask_irq(struct irq_data *d)
 {
-	u32 mask = 1 << (d->irq % 32);
+	u32 mask = 1 << (gic_irq(d) % 32);
 
 	raw_spin_lock(&irq_controller_lock);
 	writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4);
@@ -95,7 +100,7 @@ static void gic_mask_irq(struct irq_data *d)
 
 static void gic_unmask_irq(struct irq_data *d)
 {
-	u32 mask = 1 << (d->irq % 32);
+	u32 mask = 1 << (gic_irq(d) % 32);
 
 	raw_spin_lock(&irq_controller_lock);
 	if (gic_arch_extn.irq_unmask)
@@ -176,7 +181,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
 			    bool force)
 {
 	void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3);
-	unsigned int shift = (d->irq % 4) * 8;
+	unsigned int shift = (gic_irq(d) % 4) * 8;
 	unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask);
 	u32 val, mask, bit;
 
@@ -227,7 +232,7 @@ static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
 	if (gic_irq == 1023)
 		goto out;
 
-	cascade_irq = gic_irq + chip_data->irq_offset;
+	cascade_irq = irq_domain_to_irq(&chip_data->domain, gic_irq);
 	if (unlikely(gic_irq < 32 || gic_irq > 1020 || cascade_irq >= NR_IRQS))
 		do_bad_IRQ(cascade_irq, desc);
 	else
@@ -259,14 +264,14 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
 	irq_set_chained_handler(irq, gic_handle_cascade_irq);
 }
 
-static void __init gic_dist_init(struct gic_chip_data *gic,
-	unsigned int irq_start)
+static void __init gic_dist_init(struct gic_chip_data *gic)
 {
-	unsigned int gic_irqs, irq_limit, i;
+	unsigned int i, irq;
 	u32 cpumask;
+	unsigned int gic_irqs = gic->gic_irqs;
+	struct irq_domain *domain = &gic->domain;
 	void __iomem *base = gic->dist_base;
 	u32 cpu = 0;
-	u32 nrppis = 0, ppi_base = 0;
 
 #ifdef CONFIG_SMP
 	cpu = cpu_logical_map(smp_processor_id());
@@ -279,34 +284,6 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
 	writel_relaxed(0, base + GIC_DIST_CTRL);
 
 	/*
-	 * Find out how many interrupts are supported.
-	 * The GIC only supports up to 1020 interrupt sources.
-	 */
-	gic_irqs = readl_relaxed(base + GIC_DIST_CTR) & 0x1f;
-	gic_irqs = (gic_irqs + 1) * 32;
-	if (gic_irqs > 1020)
-		gic_irqs = 1020;
-
-	gic->gic_irqs = gic_irqs;
-
-	/*
-	 * Nobody would be insane enough to use PPIs on a secondary
-	 * GIC, right?
-	 */
-	if (gic == &gic_data[0]) {
-		nrppis = (32 - irq_start) & 31;
-
-		/* The GIC only supports up to 16 PPIs. */
-		if (nrppis > 16)
-			BUG();
-
-		ppi_base = gic->irq_offset + 32 - nrppis;
-	}
-
-	pr_info("Configuring GIC with %d sources (%d PPIs)\n",
-		gic_irqs, (gic == &gic_data[0]) ? nrppis : 0);
-
-	/*
 	 * Set all global interrupts to be level triggered, active low.
 	 */
 	for (i = 32; i < gic_irqs; i += 16)
@@ -332,29 +309,20 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
 		writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
 
 	/*
-	 * Limit number of interrupts registered to the platform maximum
-	 */
-	irq_limit = gic->irq_offset + gic_irqs;
-	if (WARN_ON(irq_limit > NR_IRQS))
-		irq_limit = NR_IRQS;
-
-	/*
 	 * Setup the Linux IRQ subsystem.
 	 */
-	for (i = 0; i < nrppis; i++) {
-		int ppi = i + ppi_base;
-
-		irq_set_percpu_devid(ppi);
-		irq_set_chip_and_handler(ppi, &gic_chip,
-					 handle_percpu_devid_irq);
-		irq_set_chip_data(ppi, gic);
-		set_irq_flags(ppi, IRQF_VALID | IRQF_NOAUTOEN);
-	}
-
-	for (i = irq_start + nrppis; i < irq_limit; i++) {
-		irq_set_chip_and_handler(i, &gic_chip, handle_fasteoi_irq);
-		irq_set_chip_data(i, gic);
-		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+	irq_domain_for_each_irq(domain, i, irq) {
+		if (i < 32) {
+			irq_set_percpu_devid(irq);
+			irq_set_chip_and_handler(irq, &gic_chip,
+						 handle_percpu_devid_irq);
+			set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN);
+		} else {
+			irq_set_chip_and_handler(irq, &gic_chip,
+						 handle_fasteoi_irq);
+			set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+		}
+		irq_set_chip_data(irq, gic);
 	}
 
 	writel_relaxed(1, base + GIC_DIST_CTRL);
@@ -566,23 +534,85 @@ static void __init gic_pm_init(struct gic_chip_data *gic)
 }
 #endif
 
-void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
+#ifdef CONFIG_OF
+static int gic_irq_domain_dt_translate(struct irq_domain *d,
+				       struct device_node *controller,
+				       const u32 *intspec, unsigned int intsize,
+				       unsigned long *out_hwirq, unsigned int *out_type)
+{
+	if (d->of_node != controller)
+		return -EINVAL;
+	if (intsize < 3)
+		return -EINVAL;
+
+	/* Get the interrupt number and add 16 to skip over SGIs */
+	*out_hwirq = intspec[1] + 16;
+
+	/* For SPIs, we need to add 16 more to get the GIC irq ID number */
+	if (!intspec[0])
+		*out_hwirq += 16;
+
+	*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
+	return 0;
+}
+#endif
+
+const struct irq_domain_ops gic_irq_domain_ops = {
+#ifdef CONFIG_OF
+	.dt_translate = gic_irq_domain_dt_translate,
+#endif
+};
+
+void __init gic_init(unsigned int gic_nr, int irq_start,
 	void __iomem *dist_base, void __iomem *cpu_base)
 {
 	struct gic_chip_data *gic;
+	struct irq_domain *domain;
+	int gic_irqs;
 
 	BUG_ON(gic_nr >= MAX_GIC_NR);
 
 	gic = &gic_data[gic_nr];
+	domain = &gic->domain;
 	gic->dist_base = dist_base;
 	gic->cpu_base = cpu_base;
-	gic->irq_offset = (irq_start - 1) & ~31;
 
-	if (gic_nr == 0)
+	/*
+	 * For primary GICs, skip over SGIs.
+	 * For secondary GICs, skip over PPIs, too.
+	 */
+	if (gic_nr == 0) {
 		gic_cpu_base_addr = cpu_base;
+		domain->hwirq_base = 16;
+		if (irq_start > 0)
+			irq_start = (irq_start & ~31) + 16;
+	} else
+		domain->hwirq_base = 32;
+
+	/*
+	 * Find out how many interrupts are supported.
+	 * The GIC only supports up to 1020 interrupt sources.
+	 */
+	gic_irqs = readl_relaxed(dist_base + GIC_DIST_CTR) & 0x1f;
+	gic_irqs = (gic_irqs + 1) * 32;
+	if (gic_irqs > 1020)
+		gic_irqs = 1020;
+	gic->gic_irqs = gic_irqs;
+
+	domain->nr_irq = gic_irqs - domain->hwirq_base;
+	domain->irq_base = irq_alloc_descs(irq_start, 16, domain->nr_irq,
+					   numa_node_id());
+	if (IS_ERR_VALUE(domain->irq_base)) {
+		WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",
+		     irq_start);
+		domain->irq_base = irq_start;
+	}
+	domain->priv = gic;
+	domain->ops = &gic_irq_domain_ops;
+	irq_domain_add(domain);
 
 	gic_chip.flags |= gic_arch_extn.flags;
-	gic_dist_init(gic, irq_start);
+	gic_dist_init(gic);
 	gic_cpu_init(gic);
 	gic_pm_init(gic);
 }
@@ -614,3 +644,35 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
 	writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
 }
 #endif
+
+#ifdef CONFIG_OF
+static int gic_cnt __initdata = 0;
+
+int __init gic_of_init(struct device_node *node, struct device_node *parent)
+{
+	void __iomem *cpu_base;
+	void __iomem *dist_base;
+	int irq;
+	struct irq_domain *domain = &gic_data[gic_cnt].domain;
+
+	if (WARN_ON(!node))
+		return -ENODEV;
+
+	dist_base = of_iomap(node, 0);
+	WARN(!dist_base, "unable to map gic dist registers\n");
+
+	cpu_base = of_iomap(node, 1);
+	WARN(!cpu_base, "unable to map gic cpu registers\n");
+
+	domain->of_node = of_node_get(node);
+
+	gic_init(gic_cnt, -1, dist_base, cpu_base);
+
+	if (parent) {
+		irq = irq_of_parse_and_map(node, 0);
+		gic_cascade_irq(gic_cnt, irq);
+	}
+	gic_cnt++;
+	return 0;
+}
+#endif
diff --git a/arch/arm/configs/at91sam9g45_defconfig b/arch/arm/configs/at91sam9g45_defconfig
new file mode 100644
index 0000000..c5876d2
--- /dev/null
+++ b/arch/arm/configs/at91sam9g45_defconfig
@@ -0,0 +1,214 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_AT91=y
+CONFIG_ARCH_AT91SAM9G45=y
+CONFIG_MACH_AT91SAM9M10G45EK=y
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+CONFIG_AT91_SLOW_CLOCK=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_LEDS=y
+CONFIG_LEDS_CPU=y
+CONFIG_UACCESS_WITH_MEMCPY=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=128M console=ttyS0,115200 initrd=0x71100000,25165824 root=/dev/ram0 rw"
+CONFIG_AUTO_ZRELADDR=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_DIAG is not set
+CONFIG_IPV6=y
+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_BEET is not set
+CONFIG_IPV6_SIT_6RD=y
+CONFIG_CFG80211=y
+CONFIG_LIB80211=y
+CONFIG_MAC80211=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ATMEL=y
+CONFIG_MTD_UBI=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=4
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_MISC_DEVICES=y
+CONFIG_ATMEL_PWM=y
+CONFIG_ATMEL_TCLIB=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_NET_ETHERNET=y
+CONFIG_MACB=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+CONFIG_LIBERTAS_THINFIRM=m
+CONFIG_LIBERTAS_THINFIRM_USB=m
+CONFIG_AT76C50X_USB=m
+CONFIG_USB_ZD1201=m
+CONFIG_RTL8187=m
+CONFIG_ATH_COMMON=m
+CONFIG_ATH9K=m
+CONFIG_CARL9170=m
+CONFIG_B43=m
+CONFIG_B43_PHY_N=y
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+CONFIG_LIBERTAS_SDIO=m
+CONFIG_LIBERTAS_SPI=m
+CONFIG_RT2X00=m
+CONFIG_RT2500USB=m
+CONFIG_RT73USB=m
+CONFIG_RT2800USB=m
+CONFIG_RT2800USB_RT53XX=y
+CONFIG_RT2800USB_UNKNOWN=y
+CONFIG_RTL8192CU=m
+CONFIG_WL1251=m
+CONFIG_WL1251_SDIO=m
+CONFIG_WL12XX_MENU=m
+CONFIG_WL12XX=m
+CONFIG_WL12XX_SDIO=m
+CONFIG_ZD1211RW=m
+CONFIG_MWIFIEX=m
+CONFIG_MWIFIEX_SDIO=m
+CONFIG_INPUT_POLLDEV=m
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=480
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=272
+CONFIG_INPUT_JOYDEV=y
+CONFIG_INPUT_EVDEV=y
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_QT1070=m
+CONFIG_KEYBOARD_QT2160=m
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ATMEL_MXT=m
+CONFIG_TOUCHSCREEN_ATMEL_TSADCC=y
+# CONFIG_SERIO is not set
+CONFIG_LEGACY_PTY_COUNT=4
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_GPIO=y
+CONFIG_SPI=y
+CONFIG_SPI_ATMEL=y
+# CONFIG_HWMON is not set
+# CONFIG_MFD_SUPPORT is not set
+CONFIG_FB=y
+CONFIG_FB_ATMEL=y
+CONFIG_FB_UDL=m
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_ATMEL_LCDC=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SEQUENCER=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_VERBOSE_PROCFS is not set
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_ARM is not set
+CONFIG_SND_ATMEL_AC97C=y
+# CONFIG_SND_SPI is not set
+CONFIG_SND_USB_AUDIO=m
+# CONFIG_USB_HID is not set
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_ATMEL_USBA=m
+CONFIG_USB_ZERO=m
+CONFIG_USB_AUDIO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_EEM=y
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_CDC_COMPOSITE=m
+CONFIG_USB_G_MULTI=m
+CONFIG_USB_G_MULTI_CDC=y
+CONFIG_MMC=y
+# CONFIG_MMC_BLOCK_BOUNCE is not set
+CONFIG_SDIO_UART=m
+CONFIG_MMC_ATMELMCI=y
+CONFIG_MMC_ATMELMCI_DMA=y
+CONFIG_LEDS_ATMEL_PWM=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91RM9200=y
+CONFIG_DMADEVICES=y
+CONFIG_AT_HDMAC=y
+CONFIG_DMATEST=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_FANOTIFY=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+CONFIG_SQUASHFS_EMBEDDED=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_STRIP_ASM_SYMS=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_FTRACE is not set
+CONFIG_DEBUG_USER=y
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
+# CONFIG_CRYPTO_HW is not set
diff --git a/arch/arm/configs/exynos4_defconfig b/arch/arm/configs/exynos4_defconfig
index da53ff3..cd40bb5 100644
--- a/arch/arm/configs/exynos4_defconfig
+++ b/arch/arm/configs/exynos4_defconfig
@@ -11,6 +11,7 @@ CONFIG_MACH_SMDKV310=y
 CONFIG_MACH_ARMLEX4210=y
 CONFIG_MACH_UNIVERSAL_C210=y
 CONFIG_MACH_NURI=y
+CONFIG_MACH_ORIGEN=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
diff --git a/arch/arm/configs/imx_v4_v5_defconfig b/arch/arm/configs/imx_v4_v5_defconfig
new file mode 100644
index 0000000..11a4192
--- /dev/null
+++ b/arch/arm/configs/imx_v4_v5_defconfig
@@ -0,0 +1,170 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_EXPERT=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_KPROBES=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_MXC=y
+CONFIG_ARCH_IMX_V4_V5=y
+CONFIG_ARCH_MX1ADS=y
+CONFIG_MACH_SCB9328=y
+CONFIG_MACH_MX21ADS=y
+CONFIG_MACH_MX25_3DS=y
+CONFIG_MACH_EUKREA_CPUIMX25=y
+CONFIG_MACH_MX27ADS=y
+CONFIG_MACH_PCM038=y
+CONFIG_MACH_CPUIMX27=y
+CONFIG_MACH_EUKREA_CPUIMX27_USESDHC2=y
+CONFIG_MACH_EUKREA_CPUIMX27_USEUART4=y
+CONFIG_MACH_MX27_3DS=y
+CONFIG_MACH_IMX27_VISSTRIM_M10=y
+CONFIG_MACH_IMX27LITE=y
+CONFIG_MACH_PCA100=y
+CONFIG_MACH_MXT_TD60=y
+CONFIG_MACH_IMX27IPCAM=y
+CONFIG_MXC_IRQ_PRIOR=y
+CONFIG_MXC_PWM=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_FPE_NWFPE=y
+CONFIG_FPE_NWFPE_XP=y
+CONFIG_PM_DEBUG=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
+# CONFIG_MTD_CFI_I2 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_UBI=y
+CONFIG_MISC_DEVICES=y
+CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
+CONFIG_NETDEVICES=y
+CONFIG_NET_ETHERNET=y
+CONFIG_SMC91X=y
+CONFIG_DM9000=y
+CONFIG_SMC911X=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=m
+# CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_IMX=y
+CONFIG_SERIAL_IMX_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_IMX=y
+CONFIG_SPI=y
+CONFIG_SPI_IMX=y
+CONFIG_W1=y
+CONFIG_W1_MASTER_MXC=y
+CONFIG_W1_SLAVE_THERM=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_IMX2_WDT=y
+CONFIG_MFD_MC13XXX=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_MC13783=y
+CONFIG_REGULATOR_MC13892=y
+CONFIG_FB=y
+CONFIG_FB_IMX=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_IMX_SOC=y
+CONFIG_SND_SOC_MX27VIS_AIC32X4=y
+CONFIG_SND_SOC_PHYCORE_AC97=y
+CONFIG_SND_SOC_EUKREA_TLV320=y
+CONFIG_USB_HID=m
+CONFIG_USB=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MXC=y
+CONFIG_USB_ULPI=y
+CONFIG_MMC=y
+CONFIG_MMC_MXC=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_MC13783=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PCF8563=y
+CONFIG_RTC_DRV_IMXDI=y
+CONFIG_RTC_MXC=y
+CONFIG_DMADEVICES=y
+CONFIG_IMX_SDMA=y
+CONFIG_IMX_DMA=y
+# CONFIG_IOMMU_SUPPORT is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_PROC_PAGE_MONITOR is not set
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_UBIFS_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=m
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/arm/configs/mx1_defconfig b/arch/arm/configs/mx1_defconfig
deleted file mode 100644
index c9436d0..0000000
--- a/arch/arm/configs/mx1_defconfig
+++ /dev/null
@@ -1,91 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_EXPERT=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_MXC=y
-CONFIG_ARCH_MX1=y
-CONFIG_ARCH_MX1ADS=y
-CONFIG_MACH_SCB9328=y
-CONFIG_MACH_APF9328=y
-CONFIG_MXC_IRQ_PRIOR=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="noinitrd console=ttymxc0,115200 root=/dev/mtdblock2 rw ip=off"
-CONFIG_PM=y
-CONFIG_PM_DEBUG=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_FW_LOADER=m
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_PHYSMAP=y
-# CONFIG_BLK_DEV is not set
-# CONFIG_MISC_DEVICES is not set
-CONFIG_NETDEVICES=y
-CONFIG_PHYLIB=y
-CONFIG_SMSC_PHY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_DM9000=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-CONFIG_SERIAL_IMX=y
-CONFIG_SERIAL_IMX_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_IMX=y
-CONFIG_W1=y
-CONFIG_W1_MASTER_MXC=y
-CONFIG_W1_SLAVE_THERM=y
-# CONFIG_HWMON is not set
-CONFIG_FB=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_IMX=y
-CONFIG_USB_ETH=m
-CONFIG_MMC=y
-CONFIG_MMC_MXC=y
-# CONFIG_DNOTIFY is not set
-CONFIG_INOTIFY=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-# CONFIG_ENABLE_MUST_CHECK is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/arm/configs/mx21_defconfig b/arch/arm/configs/mx21_defconfig
deleted file mode 100644
index 411f88d..0000000
--- a/arch/arm/configs/mx21_defconfig
+++ /dev/null
@@ -1,97 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_MXC=y
-CONFIG_ARCH_MX2=y
-CONFIG_MACH_MX21ADS=y
-CONFIG_MXC_PWM=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_NET=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_FW_LOADER is not set
-CONFIG_MTD=y
-CONFIG_MTD_DEBUG=y
-CONFIG_MTD_DEBUG_VERBOSE=3
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_REDBOOT_PARTS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_GEOMETRY=y
-# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_MXC=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT_MOUSEDEV is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-# CONFIG_SERIO is not set
-# CONFIG_CONSOLE_TRANSLATIONS is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=1
-CONFIG_SERIAL_IMX=y
-CONFIG_SERIAL_IMX_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_IMX=y
-CONFIG_SPI=y
-# CONFIG_HWMON is not set
-CONFIG_FB=y
-CONFIG_FB_IMX=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FONTS=y
-CONFIG_FONT_8x8=y
-CONFIG_LOGO=y
-# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
-CONFIG_MMC=y
-CONFIG_MMC_MXC=y
-# CONFIG_DNOTIFY is not set
-CONFIG_MSDOS_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/arm/configs/mx27_defconfig b/arch/arm/configs/mx27_defconfig
deleted file mode 100644
index 9ad4c656..0000000
--- a/arch/arm/configs/mx27_defconfig
+++ /dev/null
@@ -1,130 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
-# CONFIG_COMPAT_BRK is not set
-CONFIG_SLAB=y
-CONFIG_PROFILING=y
-CONFIG_OPROFILE=y
-CONFIG_KPROBES=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_MXC=y
-CONFIG_ARCH_MX2=y
-CONFIG_MACH_MX27=y
-CONFIG_MACH_MX27ADS=y
-CONFIG_MACH_PCM038=y
-CONFIG_MACH_CPUIMX27=y
-CONFIG_MACH_EUKREA_CPUIMX27_USESDHC2=y
-CONFIG_MACH_EUKREA_CPUIMX27_USEUART4=y
-CONFIG_MACH_MX27_3DS=y
-CONFIG_MACH_IMX27_VISSTRIM_M10=y
-CONFIG_MACH_IMX27LITE=y
-CONFIG_MACH_PCA100=y
-CONFIG_MACH_MXT_TD60=y
-CONFIG_MXC_IRQ_PRIOR=y
-CONFIG_MXC_PWM=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_FPE_NWFPE=y
-CONFIG_FPE_NWFPE_XP=y
-CONFIG_PM=y
-CONFIG_PM_DEBUG=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_GEOMETRY=y
-# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
-# CONFIG_MTD_CFI_I2 is not set
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_MXC=y
-CONFIG_MTD_UBI=y
-CONFIG_EEPROM_AT24=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_FEC=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT_MOUSEDEV is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_TOUCHSCREEN_ADS7846=m
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=m
-CONFIG_SERIAL_IMX=y
-CONFIG_SERIAL_IMX_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_IMX=y
-CONFIG_SPI=y
-CONFIG_SPI_IMX=y
-CONFIG_W1=y
-CONFIG_W1_MASTER_MXC=y
-CONFIG_W1_SLAVE_THERM=y
-# CONFIG_HWMON is not set
-CONFIG_FB=y
-CONFIG_FB_IMX=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FONTS=y
-CONFIG_FONT_8x8=y
-# CONFIG_HID_SUPPORT is not set
-CONFIG_USB=m
-# CONFIG_USB_DEVICE_CLASS is not set
-CONFIG_USB_ULPI=y
-CONFIG_MMC=y
-CONFIG_MMC_MXC=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_PCF8563=y
-# CONFIG_DNOTIFY is not set
-# CONFIG_PROC_PAGE_MONITOR is not set
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_UBIFS_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS=y
-CONFIG_NLS_CODEPAGE_437=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_15=m
-CONFIG_DEBUG_FS=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/arm/configs/mx3_defconfig b/arch/arm/configs/mx3_defconfig
index 7c4b30b..cb0717f 100644
--- a/arch/arm/configs/mx3_defconfig
+++ b/arch/arm/configs/mx3_defconfig
@@ -3,7 +3,6 @@ CONFIG_SYSVIPC=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
@@ -13,20 +12,21 @@ CONFIG_MODVERSIONS=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_ARCH_MXC=y
 CONFIG_MACH_MX31ADS_WM1133_EV1=y
+CONFIG_MACH_MX31LILLY=y
+CONFIG_MACH_MX31LITE=y
 CONFIG_MACH_PCM037=y
 CONFIG_MACH_PCM037_EET=y
-CONFIG_MACH_MX31LITE=y
 CONFIG_MACH_MX31_3DS=y
 CONFIG_MACH_MX31MOBOARD=y
-CONFIG_MACH_MX31LILLY=y
 CONFIG_MACH_QONG=y
-CONFIG_MACH_PCM043=y
 CONFIG_MACH_ARMADILLO5X0=y
-CONFIG_MACH_MX35_3DS=y
 CONFIG_MACH_KZM_ARM11_01=y
+CONFIG_MACH_PCM043=y
+CONFIG_MACH_MX35_3DS=y
 CONFIG_MACH_EUKREA_CPUIMX35=y
 CONFIG_MXC_IRQ_PRIOR=y
 CONFIG_MXC_PWM=y
+CONFIG_ARM_ERRATA_411920=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_PREEMPT=y
@@ -35,7 +35,6 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_CMDLINE="noinitrd console=ttymxc0,115200 root=/dev/mtdblock2 rw ip=off"
 CONFIG_VFP=y
-CONFIG_PM=y
 CONFIG_PM_DEBUG=y
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -52,7 +51,6 @@ CONFIG_IP_PNP_DHCP=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_FW_LOADER=m
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
@@ -62,24 +60,27 @@ CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_MXC=y
 CONFIG_MTD_UBI=y
 # CONFIG_BLK_DEV is not set
+CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_AT24=y
 CONFIG_NETDEVICES=y
 CONFIG_SMSC_PHY=y
 CONFIG_NET_ETHERNET=y
 CONFIG_SMSC911X=y
 CONFIG_DNET=y
-CONFIG_FEC=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_IMX=y
+# CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_8250=m
 CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 CONFIG_SERIAL_IMX=y
 CONFIG_SERIAL_IMX_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
@@ -89,12 +90,15 @@ CONFIG_W1=y
 CONFIG_W1_MASTER_MXC=y
 CONFIG_W1_SLAVE_THERM=y
 # CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_IMX2_WDT=y
 CONFIG_MFD_WM8350_I2C=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_WM8350=y
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_VIDEO_DEV=y
-# CONFIG_VIDEO_ALLOW_V4L1 is not set
+# CONFIG_RC_CORE is not set
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
 CONFIG_SOC_CAMERA=y
 CONFIG_SOC_CAMERA_MT9M001=y
 CONFIG_SOC_CAMERA_MT9M111=y
@@ -105,9 +109,26 @@ CONFIG_SOC_CAMERA_OV772X=y
 CONFIG_VIDEO_MX3=y
 # CONFIG_RADIO_ADAPTERS is not set
 CONFIG_FB=y
-# CONFIG_USB_SUPPORT is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_IMX_SOC=y
+CONFIG_SND_MXC_SOC_WM1133_EV1=y
+CONFIG_SND_SOC_PHYCORE_AC97=y
+CONFIG_SND_SOC_EUKREA_TLV320=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MXC=y
+CONFIG_USB_GADGET=m
+CONFIG_USB_FSL_USB2=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_ULPI=y
 CONFIG_MMC=y
 CONFIG_MMC_MXC=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_MXC=y
 CONFIG_DMADEVICES=y
 # CONFIG_DNOTIFY is not set
 CONFIG_TMPFS=y
@@ -119,6 +140,5 @@ CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
 # CONFIG_ENABLE_MUST_CHECK is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/arm/configs/mx51_defconfig b/arch/arm/configs/mx51_defconfig
deleted file mode 100644
index 88c5802..0000000
--- a/arch/arm/configs/mx51_defconfig
+++ /dev/null
@@ -1,170 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=18
-CONFIG_RELAY=y
-CONFIG_EXPERT=y
-# CONFIG_SLUB_DEBUG is not set
-# CONFIG_COMPAT_BRK is not set
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-# CONFIG_LBDAF is not set
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_MXC=y
-CONFIG_ARCH_MX51=y
-CONFIG_MACH_MX51_BABBAGE=y
-CONFIG_MACH_MX51_3DS=y
-CONFIG_MACH_EUKREA_CPUIMX51=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_PREEMPT_VOLUNTARY=y
-CONFIG_AEABI=y
-# CONFIG_OABI_COMPAT is not set
-CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
-CONFIG_CMDLINE="noinitrd console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.0.101:/shared/nfs ip=dhcp"
-CONFIG_VFP=y
-CONFIG_NEON=y
-CONFIG_BINFMT_MISC=m
-CONFIG_PM=y
-CONFIG_PM_DEBUG=y
-CONFIG_PM_TEST_SUSPEND=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_IPV6 is not set
-# CONFIG_WIRELESS is not set
-# CONFIG_STANDALONE is not set
-CONFIG_CONNECTOR=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=65536
-# CONFIG_MISC_DEVICES is not set
-CONFIG_SCSI=y
-# CONFIG_SCSI_PROC_FS is not set
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_SCSI_SCAN_ASYNC=y
-# CONFIG_SCSI_LOWLEVEL is not set
-CONFIG_ATA=m
-CONFIG_NETDEVICES=y
-CONFIG_MARVELL_PHY=y
-CONFIG_DAVICOM_PHY=y
-CONFIG_QSEMI_PHY=y
-CONFIG_LXT_PHY=y
-CONFIG_CICADA_PHY=y
-CONFIG_VITESSE_PHY=y
-CONFIG_SMSC_PHY=y
-CONFIG_BROADCOM_PHY=y
-CONFIG_ICPLUS_PHY=y
-CONFIG_REALTEK_PHY=y
-CONFIG_NATIONAL_PHY=y
-CONFIG_STE10XP=y
-CONFIG_LSI_ET1011C_PHY=y
-CONFIG_MDIO_BITBANG=y
-CONFIG_MDIO_GPIO=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=m
-CONFIG_FEC=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_WLAN is not set
-CONFIG_INPUT_FF_MEMLESS=m
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_EVDEV=y
-CONFIG_KEYBOARD_GPIO=y
-CONFIG_INPUT_EVBUG=m
-CONFIG_MOUSE_PS2=m
-CONFIG_MOUSE_PS2_ELANTECH=y
-CONFIG_SERIO_SERPORT=m
-CONFIG_VT_HW_CONSOLE_BINDING=y
-# CONFIG_DEVKMEM is not set
-CONFIG_SERIAL_IMX=y
-CONFIG_SERIAL_IMX_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_HW_RANDOM=y
-CONFIG_I2C=y
-# CONFIG_I2C_COMPAT is not set
-CONFIG_I2C_CHARDEV=m
-# CONFIG_I2C_HELPER_AUTO is not set
-CONFIG_I2C_ALGOBIT=m
-CONFIG_I2C_ALGOPCF=m
-CONFIG_I2C_ALGOPCA=m
-CONFIG_GPIO_SYSFS=y
-# CONFIG_HWMON is not set
-# CONFIG_HID_SUPPORT is not set
-CONFIG_USB=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_MXC=y
-CONFIG_USB_STORAGE=y
-CONFIG_MMC=y
-CONFIG_MMC_BLOCK=m
-CONFIG_MMC_SDHCI=m
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_INTF_DEV_UIE_EMUL=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT2_FS_SECURITY=y
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_EXT3_FS_SECURITY=y
-CONFIG_EXT4_FS=y
-CONFIG_EXT4_FS_POSIX_ACL=y
-CONFIG_EXT4_FS_SECURITY=y
-CONFIG_QUOTA=y
-CONFIG_QUOTA_NETLINK_INTERFACE=y
-# CONFIG_PRINT_QUOTA_WARNING is not set
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=y
-CONFIG_FUSE_FS=y
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_UDF_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_CONFIGFS_FS=m
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V3_ACL=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_DEFAULT="cp437"
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ASCII=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_UTF8=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_SCHED_DEBUG is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-# CONFIG_FTRACE is not set
-# CONFIG_ARM_UNWIND is not set
-CONFIG_DEBUG_LL=y
-CONFIG_EARLY_PRINTK=y
-CONFIG_SECURITYFS=y
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_LZO=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-# CONFIG_CRYPTO_HW is not set
-CONFIG_CRC_CCITT=m
-CONFIG_CRC_T10DIF=y
-CONFIG_CRC7=m
-CONFIG_LIBCRC32C=m
diff --git a/arch/arm/configs/mx5_defconfig b/arch/arm/configs/mx5_defconfig
new file mode 100644
index 0000000..d0d8dfe
--- /dev/null
+++ b/arch/arm/configs/mx5_defconfig
@@ -0,0 +1,184 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_KERNEL_LZO=y
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_RELAY=y
+CONFIG_EXPERT=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_ARCH_MXC=y
+CONFIG_ARCH_MX5=y
+CONFIG_MACH_MX51_BABBAGE=y
+CONFIG_MACH_MX51_3DS=y
+CONFIG_MACH_EUKREA_CPUIMX51=y
+CONFIG_MACH_EUKREA_CPUIMX51SD=y
+CONFIG_MACH_MX51_EFIKAMX=y
+CONFIG_MACH_MX51_EFIKASB=y
+CONFIG_MACH_MX53_EVK=y
+CONFIG_MACH_MX53_SMD=y
+CONFIG_MACH_MX53_LOCO=y
+CONFIG_MACH_MX53_ARD=y
+CONFIG_MXC_PWM=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_VMSPLIT_2G=y
+CONFIG_PREEMPT_VOLUNTARY=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
+CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_BINFMT_MISC=m
+CONFIG_PM_DEBUG=y
+CONFIG_PM_TEST_SUSPEND=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+CONFIG_CONNECTOR=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=65536
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_PATA_IMX=y
+CONFIG_NETDEVICES=y
+CONFIG_MII=m
+CONFIG_MARVELL_PHY=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_QSEMI_PHY=y
+CONFIG_LXT_PHY=y
+CONFIG_CICADA_PHY=y
+CONFIG_VITESSE_PHY=y
+CONFIG_SMSC_PHY=y
+CONFIG_BROADCOM_PHY=y
+CONFIG_ICPLUS_PHY=y
+CONFIG_REALTEK_PHY=y
+CONFIG_NATIONAL_PHY=y
+CONFIG_STE10XP=y
+CONFIG_LSI_ET1011C_PHY=y
+CONFIG_MICREL_PHY=y
+CONFIG_NET_ETHERNET=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_PS2_ELANTECH=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_MMA8450=y
+CONFIG_SERIO_SERPORT=m
+CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_IMX=y
+CONFIG_SERIAL_IMX_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+CONFIG_I2C_IMX=y
+CONFIG_SPI=y
+CONFIG_SPI_IMX=y
+CONFIG_GPIO_SYSFS=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_IMX2_WDT=y
+CONFIG_MFD_MC13XXX=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_MC13892=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MXC=y
+CONFIG_USB_STORAGE=y
+CONFIG_MMC=y
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_ESDHC_IMX=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_RTC_MXC=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_CONFIGFS_FS=m
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_UTF8=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_FTRACE is not set
+# CONFIG_ARM_UNWIND is not set
+CONFIG_SECURITYFS=y
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_LZO=m
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_CCITT=m
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC7=m
+CONFIG_LIBCRC32C=m
diff --git a/arch/arm/configs/mxs_defconfig b/arch/arm/configs/mxs_defconfig
index db2cb7d..6ee781b 100644
--- a/arch/arm/configs/mxs_defconfig
+++ b/arch/arm/configs/mxs_defconfig
@@ -26,6 +26,7 @@ CONFIG_MACH_MX23EVK=y
 CONFIG_MACH_MX28EVK=y
 CONFIG_MACH_STMP378X_DEVB=y
 CONFIG_MACH_TX28=y
+CONFIG_MACH_M28EVK=y
 # CONFIG_ARM_THUMB is not set
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig
index 8845f1c..1957297 100644
--- a/arch/arm/configs/tegra_defconfig
+++ b/arch/arm/configs/tegra_defconfig
@@ -25,6 +25,7 @@ CONFIG_MACH_KAEN=y
 CONFIG_MACH_PAZ00=y
 CONFIG_MACH_TRIMSLICE=y
 CONFIG_MACH_WARIO=y
+CONFIG_MACH_VENTANA=y
 CONFIG_TEGRA_DEBUG_UARTD=y
 CONFIG_ARM_ERRATA_742230=y
 CONFIG_NO_HZ=y
@@ -38,7 +39,6 @@ CONFIG_HIGHMEM=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_VFP=y
-CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -65,6 +65,7 @@ CONFIG_IPV6_TUNNEL=y
 CONFIG_IPV6_MULTIPLE_TABLES=y
 # CONFIG_WIRELESS is not set
 # CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_MISC_DEVICES=y
 CONFIG_AD525X_DPOT=y
@@ -72,34 +73,61 @@ CONFIG_AD525X_DPOT_I2C=y
 CONFIG_ICS932S401=y
 CONFIG_APDS9802ALS=y
 CONFIG_ISL29003=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
+CONFIG_NET_ETHERNET=y
 CONFIG_R8169=y
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_WLAN is not set
+CONFIG_USB_PEGASUS=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_SMSC75XX=y
+CONFIG_USB_NET_SMSC95XX=y
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_OF_PLATFORM=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 # CONFIG_I2C_COMPAT is not set
 # CONFIG_I2C_HELPER_AUTO is not set
 CONFIG_I2C_TEGRA=y
+CONFIG_SPI=y
+CONFIG_SPI_TEGRA=y
 CONFIG_SENSORS_LM90=y
 CONFIG_MFD_TPS6586X=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_TPS6586X=y
-# CONFIG_USB_SUPPORT is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_PCI is not set
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+# CONFIG_SND_USB is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_TEGRA=y
+CONFIG_SND_SOC_TEGRA_WM8903=y
+CONFIG_SND_SOC_TEGRA_TRIMSLICE=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_TEGRA=y
+CONFIG_USB_STORAGE=y
 CONFIG_MMC=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_SDHCI_TEGRA=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_TEGRA=y
 CONFIG_STAGING=y
-# CONFIG_STAGING_EXCLUDE_BUILD is not set
 CONFIG_IIO=y
 CONFIG_SENSORS_ISL29018=y
 CONFIG_SENSORS_AK8975=y
@@ -123,18 +151,15 @@ CONFIG_NLS_ISO8859_1=y
 CONFIG_PRINTK_TIME=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_SCHEDSTATS=y
 CONFIG_TIMER_STATS=y
 CONFIG_DEBUG_SLAB=y
 # CONFIG_DEBUG_PREEMPT is not set
 CONFIG_DEBUG_MUTEXES=y
-CONFIG_DEBUG_SPINLOCK_SLEEP=y
 CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_VM=y
 CONFIG_DEBUG_SG=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_DEBUG_LL=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CRYPTO_ECB=y
diff --git a/arch/arm/include/asm/device.h b/arch/arm/include/asm/device.h
index 6615f03..7aa3680 100644
--- a/arch/arm/include/asm/device.h
+++ b/arch/arm/include/asm/device.h
@@ -15,7 +15,12 @@ struct dev_archdata {
 #endif
 };
 
+struct omap_device;
+
 struct pdev_archdata {
+#ifdef CONFIG_ARCH_OMAP
+	struct omap_device *od;
+#endif
 };
 
 #endif
diff --git a/arch/arm/include/asm/hardware/cache-l2x0.h b/arch/arm/include/asm/hardware/cache-l2x0.h
index 434edcc..1db1143 100644
--- a/arch/arm/include/asm/hardware/cache-l2x0.h
+++ b/arch/arm/include/asm/hardware/cache-l2x0.h
@@ -102,7 +102,14 @@
 
 #ifndef __ASSEMBLY__
 extern void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask);
+#if defined(CONFIG_CACHE_L2X0) && defined(CONFIG_OF)
 extern int l2x0_of_init(__u32 aux_val, __u32 aux_mask);
+#else
+static inline int l2x0_of_init(__u32 aux_val, __u32 aux_mask)
+{
+	return -ENODEV;
+}
+#endif
 
 struct l2x0_regs {
 	unsigned long phy_base;
@@ -121,6 +128,6 @@ struct l2x0_regs {
 
 extern struct l2x0_regs l2x0_saved_regs;
 
-#endif
+#endif /* __ASSEMBLY__ */
 
 #endif
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index 14867e1..3e91f22 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -33,16 +33,19 @@
 #define GIC_DIST_SOFTINT		0xf00
 
 #ifndef __ASSEMBLY__
+#include <linux/irqdomain.h>
+struct device_node;
+
 extern void __iomem *gic_cpu_base_addr;
 extern struct irq_chip gic_arch_extn;
 
-void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *);
+void gic_init(unsigned int, int, void __iomem *, void __iomem *);
+int gic_of_init(struct device_node *node, struct device_node *parent);
 void gic_secondary_init(unsigned int);
 void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
 void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
 
 struct gic_chip_data {
-	unsigned int irq_offset;
 	void __iomem *dist_base;
 	void __iomem *cpu_base;
 #ifdef CONFIG_CPU_PM
@@ -52,6 +55,9 @@ struct gic_chip_data {
 	u32 __percpu *saved_ppi_enable;
 	u32 __percpu *saved_ppi_conf;
 #endif
+#ifdef CONFIG_IRQ_DOMAIN
+	struct irq_domain domain;
+#endif
 	unsigned int gic_irqs;
 };
 #endif
diff --git a/arch/arm/include/asm/hardware/it8152.h b/arch/arm/include/asm/hardware/it8152.h
index b3fea38..43cab49 100644
--- a/arch/arm/include/asm/hardware/it8152.h
+++ b/arch/arm/include/asm/hardware/it8152.h
@@ -9,7 +9,7 @@
 
 #ifndef __ASM_HARDWARE_IT8152_H
 #define __ASM_HARDWARE_IT8152_H
-extern unsigned long it8152_base_address;
+extern void __iomem *it8152_base_address;
 
 #define IT8152_IO_BASE			(it8152_base_address + 0x03e00000)
 #define IT8152_CFGREG_BASE		(it8152_base_address + 0x03f00000)
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index 2248467..a6b7991 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -182,6 +182,11 @@ config MACH_ECO920
 	help
 	  Select this if you are using the eco920 board
 
+config MACH_RSI_EWS
+	bool "RSI Embedded Webserver"
+	depends on ARCH_AT91RM9200
+	help
+	  Select this if you are using RSIs EWS board.
 endif
 
 # ----------------------------------------------------------
@@ -381,6 +386,14 @@ config MACH_GSIA18S
 	  This enables support for the GS_IA18_S board
 	  produced by GeoSIG Ltd company. This is an internet accelerograph.
 	  <http://www.geosig.com>
+
+config MACH_USB_A9G20
+	bool "CALAO USB-A9G20"
+	depends on ARCH_AT91SAM9G20
+	help
+	  Select this if you are using a Calao Systems USB-A9G20.
+	  <http://www.calao-systems.com>
+
 endif
 
 if (ARCH_AT91SAM9260 || ARCH_AT91SAM9G20)
@@ -442,6 +455,17 @@ endif
 
 # ----------------------------------------------------------
 
+comment "Generic Board Type"
+
+config MACH_AT91SAM_DT
+	bool "Atmel AT91SAM Evaluation Kits with device-tree support"
+	select USE_OF
+	help
+	  Select this if you want to experiment device-tree with
+	  an Atmel Evaluation Kit.
+
+# ----------------------------------------------------------
+
 comment "AT91 Board Options"
 
 config MTD_AT91_DATAFLASH_CARD
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index bf57e8b..242174f 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -36,12 +36,13 @@ obj-$(CONFIG_MACH_ECBAT91)	+= board-ecbat91.o
 obj-$(CONFIG_MACH_YL9200)	+= board-yl-9200.o
 obj-$(CONFIG_MACH_CPUAT91)	+= board-cpuat91.o
 obj-$(CONFIG_MACH_ECO920)	+= board-eco920.o
+obj-$(CONFIG_MACH_RSI_EWS)	+= board-rsi-ews.o
 
 # AT91SAM9260 board-specific support
 obj-$(CONFIG_MACH_AT91SAM9260EK) += board-sam9260ek.o
 obj-$(CONFIG_MACH_CAM60)	+= board-cam60.o
 obj-$(CONFIG_MACH_SAM9_L9260)	+= board-sam9-l9260.o
-obj-$(CONFIG_MACH_USB_A9260)	+= board-usb-a9260.o
+obj-$(CONFIG_MACH_USB_A9260)	+= board-usb-a926x.o
 obj-$(CONFIG_MACH_QIL_A9260)	+= board-qil-a9260.o
 obj-$(CONFIG_MACH_AFEB9260)	+= board-afeb-9260v1.o
 obj-$(CONFIG_MACH_CPU9260)	+= board-cpu9krea.o
@@ -53,7 +54,7 @@ obj-$(CONFIG_MACH_AT91SAM9G10EK) += board-sam9261ek.o
 
 # AT91SAM9263 board-specific support
 obj-$(CONFIG_MACH_AT91SAM9263EK) += board-sam9263ek.o
-obj-$(CONFIG_MACH_USB_A9263)	+= board-usb-a9263.o
+obj-$(CONFIG_MACH_USB_A9263)	+= board-usb-a926x.o
 obj-$(CONFIG_MACH_NEOCORE926)	+= board-neocore926.o
 
 # AT91SAM9RL board-specific support
@@ -67,6 +68,7 @@ obj-$(CONFIG_MACH_STAMP9G20)	+= board-stamp9g20.o
 obj-$(CONFIG_MACH_PORTUXG20)	+= board-stamp9g20.o
 obj-$(CONFIG_MACH_PCONTROL_G20)	+= board-pcontrol-g20.o board-stamp9g20.o
 obj-$(CONFIG_MACH_GSIA18S)	+= board-gsia18s.o board-stamp9g20.o
+obj-$(CONFIG_MACH_USB_A9G20)	+= board-usb-a926x.o
 
 # AT91SAM9260/AT91SAM9G20 board-specific support
 obj-$(CONFIG_MACH_SNAPPER_9260)	+= board-snapper9260.o
@@ -74,6 +76,9 @@ obj-$(CONFIG_MACH_SNAPPER_9260)	+= board-snapper9260.o
 # AT91SAM9G45 board-specific support
 obj-$(CONFIG_MACH_AT91SAM9M10G45EK) += board-sam9m10g45ek.o
 
+# AT91SAM board with device-tree
+obj-$(CONFIG_MACH_AT91SAM_DT) += board-dt.o
+
 # AT91CAP9 board-specific support
 obj-$(CONFIG_MACH_AT91CAP9ADK)	+= board-cap9adk.o
 
diff --git a/arch/arm/mach-at91/Makefile.boot b/arch/arm/mach-at91/Makefile.boot
index 9ab5a3e..8ddafad 100644
--- a/arch/arm/mach-at91/Makefile.boot
+++ b/arch/arm/mach-at91/Makefile.boot
@@ -16,3 +16,5 @@ else
 params_phys-y	:= 0x20000100
 initrd_phys-y	:= 0x20410000
 endif
+
+dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9m10g45ek.dtb usb_a9g20.dtb
diff --git a/arch/arm/mach-at91/at91cap9.c b/arch/arm/mach-at91/at91cap9.c
index bfc6844..ecdd54d 100644
--- a/arch/arm/mach-at91/at91cap9.c
+++ b/arch/arm/mach-at91/at91cap9.c
@@ -219,6 +219,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
+	/* fake hclk clock */
+	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
 };
 
 static struct clk_lookup usart_clocks_lookups[] = {
diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c
index f87f504..a4401d6 100644
--- a/arch/arm/mach-at91/at91cap9_devices.c
+++ b/arch/arm/mach-at91/at91cap9_devices.c
@@ -80,6 +80,12 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data)
 			at91_set_gpio_output(data->vbus_pin[i], 0);
 	}
 
+	/* Enable overcurrent notification */
+	for (i = 0; i < data->ports; i++) {
+		if (data->overcurrent_pin[i])
+			at91_set_gpio_input(data->overcurrent_pin[i], 1);
+	}
+
 	usbh_data = *data;
 	platform_device_register(&at91_usbh_device);
 }
diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
index f73302d..713d3bd 100644
--- a/arch/arm/mach-at91/at91rm9200.c
+++ b/arch/arm/mach-at91/at91rm9200.c
@@ -193,6 +193,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
+	/* fake hclk clock */
+	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
 };
 
 static struct clk_lookup usart_clocks_lookups[] = {
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index 978be95..01d8bbd 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -60,9 +60,17 @@ static struct platform_device at91rm9200_usbh_device = {
 
 void __init at91_add_device_usbh(struct at91_usbh_data *data)
 {
+	int i;
+
 	if (!data)
 		return;
 
+	/* Enable overcurrent notification */
+	for (i = 0; i < data->ports; i++) {
+		if (data->overcurrent_pin[i])
+			at91_set_gpio_input(data->overcurrent_pin[i], 1);
+	}
+
 	usbh_data = *data;
 	platform_device_register(&at91rm9200_usbh_device);
 }
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index cb397be..b84a9f6 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -199,6 +199,16 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("t4_clk", "atmel_tcb.1", &tc4_clk),
 	CLKDEV_CON_DEV_ID("t5_clk", "atmel_tcb.1", &tc5_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc_clk),
+	/* more usart lookup table for DT entries */
+	CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck),
+	CLKDEV_CON_DEV_ID("usart", "fffb0000.serial", &usart0_clk),
+	CLKDEV_CON_DEV_ID("usart", "fffb4000.serial", &usart1_clk),
+	CLKDEV_CON_DEV_ID("usart", "fffb8000.serial", &usart2_clk),
+	CLKDEV_CON_DEV_ID("usart", "fffd0000.serial", &usart3_clk),
+	CLKDEV_CON_DEV_ID("usart", "fffd4000.serial", &usart4_clk),
+	CLKDEV_CON_DEV_ID("usart", "fffd8000.serial", &usart5_clk),
+	/* fake hclk clock */
+	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
 };
 
 static struct clk_lookup usart_clocks_lookups[] = {
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index 3c2b580..24b6f8c 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -61,9 +61,17 @@ static struct platform_device at91_usbh_device = {
 
 void __init at91_add_device_usbh(struct at91_usbh_data *data)
 {
+	int i;
+
 	if (!data)
 		return;
 
+	/* Enable overcurrent notification */
+	for (i = 0; i < data->ports; i++) {
+		if (data->overcurrent_pin[i])
+			at91_set_gpio_input(data->overcurrent_pin[i], 1);
+	}
+
 	usbh_data = *data;
 	platform_device_register(&at91_usbh_device);
 }
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index 6c8e3b5..658a518 100644
--- a/arch/arm/mach-at91/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -129,6 +129,20 @@ static struct clk lcdc_clk = {
 	.type		= CLK_TYPE_PERIPHERAL,
 };
 
+/* HClocks */
+static struct clk hck0 = {
+	.name		= "hck0",
+	.pmc_mask	= AT91_PMC_HCK0,
+	.type		= CLK_TYPE_SYSTEM,
+	.id		= 0,
+};
+static struct clk hck1 = {
+	.name		= "hck1",
+	.pmc_mask	= AT91_PMC_HCK1,
+	.type		= CLK_TYPE_SYSTEM,
+	.id		= 1,
+};
+
 static struct clk *periph_clocks[] __initdata = {
 	&pioA_clk,
 	&pioB_clk,
@@ -161,6 +175,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
+	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &hck0),
 };
 
 static struct clk_lookup usart_clocks_lookups[] = {
@@ -199,20 +214,6 @@ static struct clk pck3 = {
 	.id		= 3,
 };
 
-/* HClocks */
-static struct clk hck0 = {
-	.name		= "hck0",
-	.pmc_mask	= AT91_PMC_HCK0,
-	.type		= CLK_TYPE_SYSTEM,
-	.id		= 0,
-};
-static struct clk hck1 = {
-	.name		= "hck1",
-	.pmc_mask	= AT91_PMC_HCK1,
-	.type		= CLK_TYPE_SYSTEM,
-	.id		= 1,
-};
-
 static void __init at91sam9261_register_clocks(void)
 {
 	int i;
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index 4e647b6..3b70b38 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -64,9 +64,17 @@ static struct platform_device at91sam9261_usbh_device = {
 
 void __init at91_add_device_usbh(struct at91_usbh_data *data)
 {
+	int i;
+
 	if (!data)
 		return;
 
+	/* Enable overcurrent notification */
+	for (i = 0; i < data->ports; i++) {
+		if (data->overcurrent_pin[i])
+			at91_set_gpio_input(data->overcurrent_pin[i], 1);
+	}
+
 	usbh_data = *data;
 	platform_device_register(&at91sam9261_usbh_device);
 }
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
index 044f3c9..f83fbb0 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -189,6 +189,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
 	CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
 	CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk),
+	/* fake hclk clock */
+	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
 };
 
 static struct clk_lookup usart_clocks_lookups[] = {
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index dd7662b..3faa1fd 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -74,6 +74,12 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data)
 			at91_set_gpio_output(data->vbus_pin[i], 0);
 	}
 
+	/* Enable overcurrent notification */
+	for (i = 0; i < data->ports; i++) {
+		if (data->overcurrent_pin[i])
+			at91_set_gpio_input(data->overcurrent_pin[i], 1);
+	}
+
 	usbh_data = *data;
 	platform_device_register(&at91_usbh_device);
 }
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
index 1532b50..318b040 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -54,6 +54,11 @@ static struct clk pioDE_clk = {
 	.pmc_mask	= 1 << AT91SAM9G45_ID_PIODE,
 	.type		= CLK_TYPE_PERIPHERAL,
 };
+static struct clk trng_clk = {
+	.name		= "trng_clk",
+	.pmc_mask	= 1 << AT91SAM9G45_ID_TRNG,
+	.type		= CLK_TYPE_PERIPHERAL,
+};
 static struct clk usart0_clk = {
 	.name		= "usart0_clk",
 	.pmc_mask	= 1 << AT91SAM9G45_ID_US0,
@@ -177,6 +182,7 @@ static struct clk *periph_clocks[] __initdata = {
 	&pioB_clk,
 	&pioC_clk,
 	&pioDE_clk,
+	&trng_clk,
 	&usart0_clk,
 	&usart1_clk,
 	&usart2_clk,
@@ -216,6 +222,15 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tcb0_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
+	CLKDEV_CON_DEV_ID(NULL, "atmel-trng", &trng_clk),
+	/* more usart lookup table for DT entries */
+	CLKDEV_CON_DEV_ID("usart", "ffffee00.serial", &mck),
+	CLKDEV_CON_DEV_ID("usart", "fff8c000.serial", &usart0_clk),
+	CLKDEV_CON_DEV_ID("usart", "fff90000.serial", &usart1_clk),
+	CLKDEV_CON_DEV_ID("usart", "fff94000.serial", &usart2_clk),
+	CLKDEV_CON_DEV_ID("usart", "fff98000.serial", &usart3_clk),
+	/* fake hclk clock */
+	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &uhphs_clk),
 };
 
 static struct clk_lookup usart_clocks_lookups[] = {
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index c3dfb1b..000b5e1 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -124,6 +124,12 @@ void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data)
 			at91_set_gpio_output(data->vbus_pin[i], 0);
 	}
 
+	/* Enable overcurrent notification */
+	for (i = 0; i < data->ports; i++) {
+		if (data->overcurrent_pin[i])
+			at91_set_gpio_input(data->overcurrent_pin[i], 1);
+	}
+
 	usbh_ohci_data = *data;
 	platform_device_register(&at91_usbh_ohci_device);
 }
@@ -1095,6 +1101,34 @@ static void __init at91_add_device_rtt(void)
 
 
 /* --------------------------------------------------------------------
+ *  TRNG
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_HW_RANDOM_ATMEL) || defined(CONFIG_HW_RANDOM_ATMEL_MODULE)
+static struct resource trng_resources[] = {
+	{
+		.start	= AT91SAM9G45_BASE_TRNG,
+		.end	= AT91SAM9G45_BASE_TRNG + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device at91sam9g45_trng_device = {
+	.name		= "atmel-trng",
+	.id		= -1,
+	.resource	= trng_resources,
+	.num_resources	= ARRAY_SIZE(trng_resources),
+};
+
+static void __init at91_add_device_trng(void)
+{
+	platform_device_register(&at91sam9g45_trng_device);
+}
+#else
+static void __init at91_add_device_trng(void) {}
+#endif
+
+/* --------------------------------------------------------------------
  *  Watchdog
  * -------------------------------------------------------------------- */
 
@@ -1583,6 +1617,7 @@ static int __init at91_add_standard_devices(void)
 	at91_add_device_hdmac();
 	at91_add_device_rtc();
 	at91_add_device_rtt();
+	at91_add_device_trng();
 	at91_add_device_watchdog();
 	at91_add_device_tc();
 	return 0;
diff --git a/arch/arm/mach-at91/board-dt.c b/arch/arm/mach-at91/board-dt.c
new file mode 100644
index 0000000..0b7d327
--- /dev/null
+++ b/arch/arm/mach-at91/board-dt.c
@@ -0,0 +1,123 @@
+/*
+ *  Setup code for AT91SAM Evaluation Kits with Device Tree support
+ *
+ *  Covers: * AT91SAM9G45-EKES  board
+ *          * AT91SAM9M10-EKES  board
+ *          * AT91SAM9M10G45-EK board
+ *
+ *  Copyright (C) 2011 Atmel,
+ *                2011 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+
+#include <mach/hardware.h>
+#include <mach/board.h>
+#include <mach/system_rev.h>
+#include <mach/at91sam9_smc.h>
+
+#include <asm/setup.h>
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include "sam9_smc.h"
+#include "generic.h"
+
+
+static void __init ek_init_early(void)
+{
+	/* Initialize processor: 12.000 MHz crystal */
+	at91_initialize(12000000);
+
+	/* DGBU on ttyS0. (Rx & Tx only) */
+	at91_register_uart(0, 0, 0);
+
+	/* set serial console to ttyS0 (ie, DBGU) */
+	at91_set_serial_console(0);
+}
+
+/* det_pin is not connected */
+static struct atmel_nand_data __initdata ek_nand_data = {
+	.ale		= 21,
+	.cle		= 22,
+	.rdy_pin	= AT91_PIN_PC8,
+	.enable_pin	= AT91_PIN_PC14,
+};
+
+static struct sam9_smc_config __initdata ek_nand_smc_config = {
+	.ncs_read_setup		= 0,
+	.nrd_setup		= 2,
+	.ncs_write_setup	= 0,
+	.nwe_setup		= 2,
+
+	.ncs_read_pulse		= 4,
+	.nrd_pulse		= 4,
+	.ncs_write_pulse	= 4,
+	.nwe_pulse		= 4,
+
+	.read_cycle		= 7,
+	.write_cycle		= 7,
+
+	.mode			= AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE,
+	.tdf_cycles		= 3,
+};
+
+static void __init ek_add_device_nand(void)
+{
+	ek_nand_data.bus_width_16 = board_have_nand_16bit();
+	/* setup bus-width (8 or 16) */
+	if (ek_nand_data.bus_width_16)
+		ek_nand_smc_config.mode |= AT91_SMC_DBW_16;
+	else
+		ek_nand_smc_config.mode |= AT91_SMC_DBW_8;
+
+	/* configure chip-select 3 (NAND) */
+	sam9_smc_configure(3, &ek_nand_smc_config);
+
+	at91_add_device_nand(&ek_nand_data);
+}
+
+static const struct of_device_id aic_of_match[] __initconst = {
+	{ .compatible = "atmel,at91rm9200-aic", },
+	{},
+};
+
+static void __init at91_dt_init_irq(void)
+{
+	irq_domain_generate_simple(aic_of_match, 0xfffff000, 0);
+	at91_init_irq_default();
+}
+
+static void __init at91_dt_device_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+
+	/* NAND */
+	ek_add_device_nand();
+}
+
+static const char *at91_dt_board_compat[] __initdata = {
+	"atmel,at91sam9m10g45ek",
+	"calao,usb-a9g20",
+	NULL
+};
+
+DT_MACHINE_START(at91sam_dt, "Atmel AT91SAM (Device Tree)")
+	/* Maintainer: Atmel */
+	.timer		= &at91sam926x_timer,
+	.map_io		= at91_map_io,
+	.init_early	= ek_init_early,
+	.init_irq	= at91_dt_init_irq,
+	.init_machine	= at91_dt_device_init,
+	.dt_compat	= at91_dt_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-rsi-ews.c b/arch/arm/mach-at91/board-rsi-ews.c
new file mode 100644
index 0000000..e927df0
--- /dev/null
+++ b/arch/arm/mach-at91/board-rsi-ews.c
@@ -0,0 +1,233 @@
+/*
+ * board-rsi-ews.c
+ *
+ *  Copyright (C)
+ *  2005 SAN People,
+ *  2008-2011 R-S-I Elektrotechnik GmbH & Co. KG
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/board.h>
+
+#include <linux/gpio.h>
+
+#include "generic.h"
+
+static void __init rsi_ews_init_early(void)
+{
+	/* Initialize processor: 18.432 MHz crystal */
+	at91_initialize(18432000);
+
+	/* Setup the LEDs */
+	at91_init_leds(AT91_PIN_PB6, AT91_PIN_PB9);
+
+	/* DBGU on ttyS0. (Rx & Tx only) */
+	/* This one is for debugging */
+	at91_register_uart(0, 0, 0);
+
+	/* USART1 on ttyS2. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
+	/* Dialin/-out modem interface */
+	at91_register_uart(AT91RM9200_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS
+			   | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
+			   | ATMEL_UART_RI);
+
+	/* USART3 on ttyS4. (Rx, Tx, RTS) */
+	/* RS485 communication */
+	at91_register_uart(AT91RM9200_ID_US3, 4, ATMEL_UART_RTS);
+
+	/* set serial console to ttyS0 (ie, DBGU) */
+	at91_set_serial_console(0);
+}
+
+/*
+ * Ethernet
+ */
+static struct at91_eth_data rsi_ews_eth_data __initdata = {
+	.phy_irq_pin	= AT91_PIN_PC4,
+	.is_rmii	= 1,
+};
+
+/*
+ * USB Host
+ */
+static struct at91_usbh_data rsi_ews_usbh_data __initdata = {
+	.ports		= 1,
+};
+
+/*
+ * SD/MC
+ */
+static struct at91_mmc_data rsi_ews_mmc_data __initdata = {
+	.slot_b		= 0,
+	.wire4		= 1,
+	.det_pin	= AT91_PIN_PB27,
+	.wp_pin		= AT91_PIN_PB29,
+};
+
+/*
+ * I2C
+ */
+static struct i2c_board_info rsi_ews_i2c_devices[] __initdata = {
+	{
+		I2C_BOARD_INFO("ds1337", 0x68),
+	},
+	{
+		I2C_BOARD_INFO("24c01", 0x50),
+	}
+};
+
+/*
+ * LEDs
+ */
+static struct gpio_led rsi_ews_leds[] = {
+	{
+		.name			= "led0",
+		.gpio			= AT91_PIN_PB6,
+		.active_low		= 0,
+	},
+	{
+		.name			= "led1",
+		.gpio			= AT91_PIN_PB7,
+		.active_low		= 0,
+	},
+	{
+		.name			= "led2",
+		.gpio			= AT91_PIN_PB8,
+		.active_low		= 0,
+	},
+	{
+		.name			= "led3",
+		.gpio			= AT91_PIN_PB9,
+		.active_low		= 0,
+	},
+};
+
+/*
+ * DataFlash
+ */
+static struct spi_board_info rsi_ews_spi_devices[] = {
+	{	/* DataFlash chip 1*/
+		.modalias	= "mtd_dataflash",
+		.chip_select	= 0,
+		.max_speed_hz	= 5 * 1000 * 1000,
+	},
+	{	/* DataFlash chip 2*/
+		.modalias	= "mtd_dataflash",
+		.chip_select	= 1,
+		.max_speed_hz	= 5 * 1000 * 1000,
+	},
+};
+
+/*
+ * NOR flash
+ */
+static struct mtd_partition rsiews_nor_partitions[] = {
+	{
+		.name		= "boot",
+		.offset		= 0,
+		.size		= 3 * SZ_128K,
+		.mask_flags	= MTD_WRITEABLE
+	},
+	{
+		.name		= "kernel",
+		.offset		= MTDPART_OFS_NXTBLK,
+		.size		= SZ_2M - (3 * SZ_128K)
+	},
+	{
+		.name		= "root",
+		.offset		= MTDPART_OFS_NXTBLK,
+		.size		= SZ_8M
+	},
+	{
+		.name		= "kernelupd",
+		.offset		= MTDPART_OFS_NXTBLK,
+		.size		= 3 * SZ_512K,
+		.mask_flags	= MTD_WRITEABLE
+	},
+	{
+		.name		= "rootupd",
+		.offset		= MTDPART_OFS_NXTBLK,
+		.size		= 9 * SZ_512K,
+		.mask_flags	= MTD_WRITEABLE
+	},
+};
+
+static struct physmap_flash_data rsiews_nor_data = {
+	.width		= 2,
+	.parts		= rsiews_nor_partitions,
+	.nr_parts	= ARRAY_SIZE(rsiews_nor_partitions),
+};
+
+#define NOR_BASE	AT91_CHIPSELECT_0
+#define NOR_SIZE	SZ_16M
+
+static struct resource nor_flash_resources[] = {
+	{
+		.start	= NOR_BASE,
+		.end	= NOR_BASE + NOR_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device rsiews_nor_flash = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+				.platform_data	= &rsiews_nor_data,
+	},
+	.resource	= nor_flash_resources,
+	.num_resources	= ARRAY_SIZE(nor_flash_resources),
+};
+
+/*
+ * Init Func
+ */
+static void __init rsi_ews_board_init(void)
+{
+	/* Serial */
+	at91_add_device_serial();
+	at91_set_gpio_output(AT91_PIN_PA21, 0);
+	/* Ethernet */
+	at91_add_device_eth(&rsi_ews_eth_data);
+	/* USB Host */
+	at91_add_device_usbh(&rsi_ews_usbh_data);
+	/* I2C */
+	at91_add_device_i2c(rsi_ews_i2c_devices,
+			ARRAY_SIZE(rsi_ews_i2c_devices));
+	/* SPI */
+	at91_add_device_spi(rsi_ews_spi_devices,
+			ARRAY_SIZE(rsi_ews_spi_devices));
+	/* MMC */
+	at91_add_device_mmc(0, &rsi_ews_mmc_data);
+	/* NOR Flash */
+	platform_device_register(&rsiews_nor_flash);
+	/* LEDs */
+	at91_gpio_leds(rsi_ews_leds, ARRAY_SIZE(rsi_ews_leds));
+}
+
+MACHINE_START(RSI_EWS, "RSI EWS")
+	/* Maintainer: Josef Holzmayr <holzmayr@rsi-elektrotechnik.de> */
+	.timer		= &at91rm9200_timer,
+	.map_io		= at91_map_io,
+	.init_early	= rsi_ews_init_early,
+	.init_irq	= at91_init_irq_default,
+	.init_machine	= rsi_ews_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-usb-a9260.c b/arch/arm/mach-at91/board-usb-a9260.c
deleted file mode 100644
index bac9b65..0000000
--- a/arch/arm/mach-at91/board-usb-a9260.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/board-usb-a9260.c
- *
- *  Copyright (C) 2005 SAN People
- *  Copyright (C) 2006 Atmel
- *  Copyright (C) 2007 Calao-systems
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/types.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/gpio_keys.h>
-#include <linux/input.h>
-#include <linux/clk.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/board.h>
-#include <mach/at91sam9_smc.h>
-#include <mach/at91_shdwc.h>
-
-#include "sam9_smc.h"
-#include "generic.h"
-
-
-static void __init ek_init_early(void)
-{
-	/* Initialize processor: 12.000 MHz crystal */
-	at91_initialize(12000000);
-
-	/* DBGU on ttyS0. (Rx & Tx only) */
-	at91_register_uart(0, 0, 0);
-
-	/* set serial console to ttyS0 (ie, DBGU) */
-	at91_set_serial_console(0);
-}
-
-/*
- * USB Host port
- */
-static struct at91_usbh_data __initdata ek_usbh_data = {
-	.ports		= 2,
-};
-
-/*
- * USB Device port
- */
-static struct at91_udc_data __initdata ek_udc_data = {
-	.vbus_pin	= AT91_PIN_PC5,
-	.pullup_pin	= 0,		/* pull-up driven by UDC */
-};
-
-/*
- * MACB Ethernet device
- */
-static struct at91_eth_data __initdata ek_macb_data = {
-	.phy_irq_pin	= AT91_PIN_PA31,
-	.is_rmii	= 1,
-};
-
-/*
- * NAND flash
- */
-static struct mtd_partition __initdata ek_nand_partition[] = {
-	{
-		.name	= "Uboot & Kernel",
-		.offset	= 0,
-		.size	= SZ_16M,
-	},
-	{
-		.name	= "Root FS",
-		.offset	= MTDPART_OFS_NXTBLK,
-		.size	= 120 * SZ_1M,
-	},
-	{
-		.name	= "FS",
-		.offset	= MTDPART_OFS_NXTBLK,
-		.size	= 120 * SZ_1M,
-	}
-};
-
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(ek_nand_partition);
-	return ek_nand_partition;
-}
-
-static struct atmel_nand_data __initdata ek_nand_data = {
-	.ale		= 21,
-	.cle		= 22,
-//	.det_pin	= ... not connected
-	.rdy_pin	= AT91_PIN_PC13,
-	.enable_pin	= AT91_PIN_PC14,
-	.partition_info	= nand_partitions,
-};
-
-static struct sam9_smc_config __initdata ek_nand_smc_config = {
-	.ncs_read_setup		= 0,
-	.nrd_setup		= 1,
-	.ncs_write_setup	= 0,
-	.nwe_setup		= 1,
-
-	.ncs_read_pulse		= 3,
-	.nrd_pulse		= 3,
-	.ncs_write_pulse	= 3,
-	.nwe_pulse		= 3,
-
-	.read_cycle		= 5,
-	.write_cycle		= 5,
-
-	.mode			= AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8,
-	.tdf_cycles		= 2,
-};
-
-static void __init ek_add_device_nand(void)
-{
-	/* configure chip-select 3 (NAND) */
-	sam9_smc_configure(3, &ek_nand_smc_config);
-
-	at91_add_device_nand(&ek_nand_data);
-}
-
-/*
- * GPIO Buttons
- */
-
-#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
-static struct gpio_keys_button ek_buttons[] = {
-	{	/* USER PUSH BUTTON */
-		.code		= KEY_ENTER,
-		.gpio		= AT91_PIN_PB10,
-		.active_low	= 1,
-		.desc		= "user_pb",
-		.wakeup		= 1,
-	}
-};
-
-static struct gpio_keys_platform_data ek_button_data = {
-	.buttons	= ek_buttons,
-	.nbuttons	= ARRAY_SIZE(ek_buttons),
-};
-
-static struct platform_device ek_button_device = {
-	.name		= "gpio-keys",
-	.id		= -1,
-	.num_resources	= 0,
-	.dev		= {
-		.platform_data	= &ek_button_data,
-	}
-};
-
-static void __init ek_add_device_buttons(void)
-{
-	at91_set_GPIO_periph(AT91_PIN_PB10, 1);	/* user push button, pull up enabled */
-	at91_set_deglitch(AT91_PIN_PB10, 1);
-
-	platform_device_register(&ek_button_device);
-}
-#else
-static void __init ek_add_device_buttons(void) {}
-#endif
-
-/*
- * LEDs
- */
-static struct gpio_led ek_leds[] = {
-	{	/* user_led (green) */
-		.name			= "user_led",
-		.gpio			= AT91_PIN_PB21,
-		.active_low		= 0,
-		.default_trigger	= "heartbeat",
-	}
-};
-
-static void __init ek_board_init(void)
-{
-	/* Serial */
-	at91_add_device_serial();
-	/* USB Host */
-	at91_add_device_usbh(&ek_usbh_data);
-	/* USB Device */
-	at91_add_device_udc(&ek_udc_data);
-	/* NAND */
-	ek_add_device_nand();
-	/* I2C */
-	at91_add_device_i2c(NULL, 0);
-	/* Ethernet */
-	at91_add_device_eth(&ek_macb_data);
-	/* Push Buttons */
-	ek_add_device_buttons();
-	/* LEDs */
-	at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
-	/* shutdown controller, wakeup button (5 msec low) */
-	at91_sys_write(AT91_SHDW_MR, AT91_SHDW_CPTWK0_(10) | AT91_SHDW_WKMODE0_LOW
-				| AT91_SHDW_RTTWKEN);
-}
-
-MACHINE_START(USB_A9260, "CALAO USB_A9260")
-	/* Maintainer: calao-systems */
-	.timer		= &at91sam926x_timer,
-	.map_io		= at91_map_io,
-	.init_early	= ek_init_early,
-	.init_irq	= at91_init_irq_default,
-	.init_machine	= ek_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board-usb-a9263.c b/arch/arm/mach-at91/board-usb-a9263.c
deleted file mode 100644
index 5bd7357..0000000
--- a/arch/arm/mach-at91/board-usb-a9263.c
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/board-usb-a9263.c
- *
- *  Copyright (C) 2005 SAN People
- *  Copyright (C) 2007 Atmel Corporation.
- *  Copyright (C) 2007 Calao-systems
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/types.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/gpio_keys.h>
-#include <linux/input.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/board.h>
-#include <mach/at91sam9_smc.h>
-#include <mach/at91_shdwc.h>
-
-#include "sam9_smc.h"
-#include "generic.h"
-
-
-static void __init ek_init_early(void)
-{
-	/* Initialize processor: 12.00 MHz crystal */
-	at91_initialize(12000000);
-
-	/* DBGU on ttyS0. (Rx & Tx only) */
-	at91_register_uart(0, 0, 0);
-
-	/* set serial console to ttyS0 (ie, DBGU) */
-	at91_set_serial_console(0);
-}
-
-/*
- * USB Host port
- */
-static struct at91_usbh_data __initdata ek_usbh_data = {
-	.ports		= 2,
-};
-
-/*
- * USB Device port
- */
-static struct at91_udc_data __initdata ek_udc_data = {
-	.vbus_pin	= AT91_PIN_PB11,
-	.pullup_pin	= 0,		/* pull-up driven by UDC */
-};
-
-/*
- * SPI devices.
- */
-static struct spi_board_info ek_spi_devices[] = {
-#if !defined(CONFIG_MMC_AT91)
-	{	/* DataFlash chip */
-		.modalias	= "mtd_dataflash",
-		.chip_select	= 0,
-		.max_speed_hz	= 15 * 1000 * 1000,
-		.bus_num	= 0,
-	}
-#endif
-};
-
-/*
- * MACB Ethernet device
- */
-static struct at91_eth_data __initdata ek_macb_data = {
-	.phy_irq_pin	= AT91_PIN_PE31,
-	.is_rmii	= 1,
-};
-
-/*
- * NAND flash
- */
-static struct mtd_partition __initdata ek_nand_partition[] = {
-	{
-		.name	= "Linux Kernel",
-		.offset	= 0,
-		.size	= SZ_16M,
-	},
-	{
-		.name	= "Root FS",
-		.offset	= MTDPART_OFS_NXTBLK,
-		.size	= 120 * SZ_1M,
-	},
-	{
-		.name	= "FS",
-		.offset	= MTDPART_OFS_NXTBLK,
-		.size	= 120 * SZ_1M,
-	}
-};
-
-static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
-{
-	*num_partitions = ARRAY_SIZE(ek_nand_partition);
-	return ek_nand_partition;
-}
-
-static struct atmel_nand_data __initdata ek_nand_data = {
-	.ale		= 21,
-	.cle		= 22,
-//	.det_pin	= ... not connected
-	.rdy_pin	= AT91_PIN_PA22,
-	.enable_pin	= AT91_PIN_PD15,
-	.partition_info	= nand_partitions,
-};
-
-static struct sam9_smc_config __initdata ek_nand_smc_config = {
-	.ncs_read_setup		= 0,
-	.nrd_setup		= 1,
-	.ncs_write_setup	= 0,
-	.nwe_setup		= 1,
-
-	.ncs_read_pulse		= 3,
-	.nrd_pulse		= 3,
-	.ncs_write_pulse	= 3,
-	.nwe_pulse		= 3,
-
-	.read_cycle		= 5,
-	.write_cycle		= 5,
-
-	.mode			= AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8,
-	.tdf_cycles		= 2,
-};
-
-static void __init ek_add_device_nand(void)
-{
-	/* configure chip-select 3 (NAND) */
-	sam9_smc_configure(3, &ek_nand_smc_config);
-
-	at91_add_device_nand(&ek_nand_data);
-}
-
-
-/*
- * GPIO Buttons
- */
-#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
-static struct gpio_keys_button ek_buttons[] = {
-	{	/* USER PUSH BUTTON */
-		.code		= KEY_ENTER,
-		.gpio		= AT91_PIN_PB10,
-		.active_low	= 1,
-		.desc		= "user_pb",
-		.wakeup		= 1,
-	}
-};
-
-static struct gpio_keys_platform_data ek_button_data = {
-	.buttons	= ek_buttons,
-	.nbuttons	= ARRAY_SIZE(ek_buttons),
-};
-
-static struct platform_device ek_button_device = {
-	.name		= "gpio-keys",
-	.id		= -1,
-	.num_resources	= 0,
-	.dev		= {
-		.platform_data	= &ek_button_data,
-	}
-};
-
-static void __init ek_add_device_buttons(void)
-{
-	at91_set_GPIO_periph(AT91_PIN_PB10, 1);	/* user push button, pull up enabled */
-	at91_set_deglitch(AT91_PIN_PB10, 1);
-
-	platform_device_register(&ek_button_device);
-}
-#else
-static void __init ek_add_device_buttons(void) {}
-#endif
-
-/*
- * LEDs
- */
-static struct gpio_led ek_leds[] = {
-	{	/* user_led (green) */
-		.name			= "user_led",
-		.gpio			= AT91_PIN_PB21,
-		.active_low		= 1,
-		.default_trigger	= "heartbeat",
-	}
-};
-
-
-static void __init ek_board_init(void)
-{
-	/* Serial */
-	at91_add_device_serial();
-	/* USB Host */
-	at91_add_device_usbh(&ek_usbh_data);
-	/* USB Device */
-	at91_add_device_udc(&ek_udc_data);
-	/* SPI */
-	at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
-	/* Ethernet */
-	at91_add_device_eth(&ek_macb_data);
-	/* NAND */
-	ek_add_device_nand();
-	/* I2C */
-	at91_add_device_i2c(NULL, 0);
-	/* Push Buttons */
-	ek_add_device_buttons();
-	/* LEDs */
-	at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
-	/* shutdown controller, wakeup button (5 msec low) */
-	at91_sys_write(AT91_SHDW_MR, AT91_SHDW_CPTWK0_(10) | AT91_SHDW_WKMODE0_LOW
-				| AT91_SHDW_RTTWKEN);
-}
-
-MACHINE_START(USB_A9263, "CALAO USB_A9263")
-	/* Maintainer: calao-systems */
-	.timer		= &at91sam926x_timer,
-	.map_io		= at91_map_io,
-	.init_early	= ek_init_early,
-	.init_irq	= at91_init_irq_default,
-	.init_machine	= ek_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board-usb-a926x.c b/arch/arm/mach-at91/board-usb-a926x.c
new file mode 100644
index 0000000..5852d3d
--- /dev/null
+++ b/arch/arm/mach-at91/board-usb-a926x.c
@@ -0,0 +1,383 @@
+/*
+ * linux/arch/arm/mach-at91/board-usb-a926x.c
+ *
+ *  Copyright (C) 2005 SAN People
+ *  Copyright (C) 2007 Atmel Corporation.
+ *  Copyright (C) 2007 Calao-systems
+ *  Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/gpio_keys.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/spi/mmc_spi.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/board.h>
+#include <mach/at91sam9_smc.h>
+#include <mach/at91_shdwc.h>
+
+#include "sam9_smc.h"
+#include "generic.h"
+
+
+static void __init ek_init_early(void)
+{
+	/* Initialize processor: 12.00 MHz crystal */
+	at91_initialize(12000000);
+
+	/* DBGU on ttyS0. (Rx & Tx only) */
+	at91_register_uart(0, 0, 0);
+
+	/* set serial console to ttyS0 (ie, DBGU) */
+	at91_set_serial_console(0);
+}
+
+/*
+ * USB Host port
+ */
+static struct at91_usbh_data __initdata ek_usbh_data = {
+	.ports		= 2,
+};
+
+/*
+ * USB Device port
+ */
+static struct at91_udc_data __initdata ek_udc_data = {
+	.vbus_pin	= AT91_PIN_PB11,
+	.pullup_pin	= 0,		/* pull-up driven by UDC */
+};
+
+static void __init ek_add_device_udc(void)
+{
+	if (machine_is_usb_a9260() || machine_is_usb_a9g20())
+		ek_udc_data.vbus_pin = AT91_PIN_PC5;
+
+	at91_add_device_udc(&ek_udc_data);
+}
+
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+#define MMC_SPI_CARD_DETECT_INT AT91_PIN_PC4
+static int at91_mmc_spi_init(struct device *dev,
+	irqreturn_t (*detect_int)(int, void *), void *data)
+{
+	/* Configure Interrupt pin as input, no pull-up */
+	at91_set_gpio_input(MMC_SPI_CARD_DETECT_INT, 0);
+	return request_irq(gpio_to_irq(MMC_SPI_CARD_DETECT_INT), detect_int,
+		IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+		"mmc-spi-detect", data);
+}
+
+static void at91_mmc_spi_exit(struct device *dev, void *data)
+{
+	free_irq(gpio_to_irq(MMC_SPI_CARD_DETECT_INT), data);
+}
+
+static struct mmc_spi_platform_data at91_mmc_spi_pdata = {
+	.init = at91_mmc_spi_init,
+	.exit = at91_mmc_spi_exit,
+	.detect_delay = 100, /* msecs */
+};
+#endif
+
+/*
+ * SPI devices.
+ */
+static struct spi_board_info usb_a9263_spi_devices[] = {
+#if !defined(CONFIG_MMC_AT91)
+	{	/* DataFlash chip */
+		.modalias	= "mtd_dataflash",
+		.chip_select	= 0,
+		.max_speed_hz	= 15 * 1000 * 1000,
+		.bus_num	= 0,
+	}
+#endif
+};
+
+static struct spi_board_info usb_a9g20_spi_devices[] = {
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+	{
+		.modalias = "mmc_spi",
+		.max_speed_hz = 20000000,	/* max spi clock (SCK) speed in HZ */
+		.bus_num = 1,
+		.chip_select = 0,
+		.platform_data = &at91_mmc_spi_pdata,
+		.mode = SPI_MODE_3,
+	},
+#endif
+};
+
+static void __init ek_add_device_spi(void)
+{
+	if (machine_is_usb_a9263())
+		at91_add_device_spi(usb_a9263_spi_devices, ARRAY_SIZE(usb_a9263_spi_devices));
+	else if (machine_is_usb_a9g20())
+		at91_add_device_spi(usb_a9g20_spi_devices, ARRAY_SIZE(usb_a9g20_spi_devices));
+}
+
+/*
+ * MACB Ethernet device
+ */
+static struct at91_eth_data __initdata ek_macb_data = {
+	.phy_irq_pin	= AT91_PIN_PE31,
+	.is_rmii	= 1,
+};
+
+static void __init ek_add_device_eth(void)
+{
+	if (machine_is_usb_a9260() || machine_is_usb_a9g20())
+		ek_macb_data.phy_irq_pin = AT91_PIN_PA31;
+
+	at91_add_device_eth(&ek_macb_data);
+}
+
+/*
+ * NAND flash
+ */
+static struct mtd_partition __initdata ek_nand_partition[] = {
+	{
+		.name	= "barebox",
+		.offset	= 0,
+		.size	= 3 * SZ_128K,
+	}, {
+		.name	= "bareboxenv",
+		.offset	= MTDPART_OFS_NXTBLK,
+		.size	= SZ_128K,
+	}, {
+		.name	= "bareboxenv2",
+		.offset	= MTDPART_OFS_NXTBLK,
+		.size	= SZ_128K,
+	}, {
+		.name	= "kernel",
+		.offset	= MTDPART_OFS_NXTBLK,
+		.size	= 4 * SZ_1M,
+	}, {
+		.name	= "rootfs",
+		.offset	= MTDPART_OFS_NXTBLK,
+		.size	= 120 * SZ_1M,
+	}, {
+		.name	= "data",
+		.offset	= MTDPART_OFS_NXTBLK,
+		.size	= MTDPART_SIZ_FULL,
+	}
+};
+
+static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
+{
+	*num_partitions = ARRAY_SIZE(ek_nand_partition);
+	return ek_nand_partition;
+}
+
+static struct atmel_nand_data __initdata ek_nand_data = {
+	.ale		= 21,
+	.cle		= 22,
+//	.det_pin	= ... not connected
+	.rdy_pin	= AT91_PIN_PA22,
+	.enable_pin	= AT91_PIN_PD15,
+	.partition_info	= nand_partitions,
+};
+
+static struct sam9_smc_config __initdata usb_a9260_nand_smc_config = {
+	.ncs_read_setup		= 0,
+	.nrd_setup		= 1,
+	.ncs_write_setup	= 0,
+	.nwe_setup		= 1,
+
+	.ncs_read_pulse		= 3,
+	.nrd_pulse		= 3,
+	.ncs_write_pulse	= 3,
+	.nwe_pulse		= 3,
+
+	.read_cycle		= 5,
+	.write_cycle		= 5,
+
+	.mode			= AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8,
+	.tdf_cycles		= 2,
+};
+
+static struct sam9_smc_config __initdata usb_a9g20_nand_smc_config = {
+	.ncs_read_setup		= 0,
+	.nrd_setup		= 2,
+	.ncs_write_setup	= 0,
+	.nwe_setup		= 2,
+
+	.ncs_read_pulse		= 4,
+	.nrd_pulse		= 4,
+	.ncs_write_pulse	= 4,
+	.nwe_pulse		= 4,
+
+	.read_cycle		= 7,
+	.write_cycle		= 7,
+
+	.mode			= AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8,
+	.tdf_cycles		= 3,
+};
+
+static void __init ek_add_device_nand(void)
+{
+	if (machine_is_usb_a9260() || machine_is_usb_a9g20()) {
+		ek_nand_data.rdy_pin	= AT91_PIN_PC13;
+		ek_nand_data.enable_pin	= AT91_PIN_PC14;
+	}
+
+	/* configure chip-select 3 (NAND) */
+	if (machine_is_usb_a9g20())
+		sam9_smc_configure(3, &usb_a9g20_nand_smc_config);
+	else
+		sam9_smc_configure(3, &usb_a9260_nand_smc_config);
+
+	at91_add_device_nand(&ek_nand_data);
+}
+
+
+/*
+ * GPIO Buttons
+ */
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+static struct gpio_keys_button ek_buttons[] = {
+	{	/* USER PUSH BUTTON */
+		.code		= KEY_ENTER,
+		.gpio		= AT91_PIN_PB10,
+		.active_low	= 1,
+		.desc		= "user_pb",
+		.wakeup		= 1,
+	}
+};
+
+static struct gpio_keys_platform_data ek_button_data = {
+	.buttons	= ek_buttons,
+	.nbuttons	= ARRAY_SIZE(ek_buttons),
+};
+
+static struct platform_device ek_button_device = {
+	.name		= "gpio-keys",
+	.id		= -1,
+	.num_resources	= 0,
+	.dev		= {
+		.platform_data	= &ek_button_data,
+	}
+};
+
+static void __init ek_add_device_buttons(void)
+{
+	at91_set_GPIO_periph(AT91_PIN_PB10, 1);	/* user push button, pull up enabled */
+	at91_set_deglitch(AT91_PIN_PB10, 1);
+
+	platform_device_register(&ek_button_device);
+}
+#else
+static void __init ek_add_device_buttons(void) {}
+#endif
+
+/*
+ * LEDs
+ */
+static struct gpio_led ek_leds[] = {
+	{	/* user_led (green) */
+		.name			= "user_led",
+		.gpio			= AT91_PIN_PB21,
+		.active_low		= 1,
+		.default_trigger	= "heartbeat",
+	}
+};
+
+static struct i2c_board_info __initdata ek_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("rv3029c2", 0x56),
+	},
+};
+
+static void __init ek_add_device_leds(void)
+{
+	if (machine_is_usb_a9260() || machine_is_usb_a9g20())
+		ek_leds[0].active_low = 0;
+
+	at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
+}
+
+static void __init ek_board_init(void)
+{
+	/* Serial */
+	at91_add_device_serial();
+	/* USB Host */
+	at91_add_device_usbh(&ek_usbh_data);
+	/* USB Device */
+	ek_add_device_udc();
+	/* SPI */
+	ek_add_device_spi();
+	/* Ethernet */
+	ek_add_device_eth();
+	/* NAND */
+	ek_add_device_nand();
+	/* Push Buttons */
+	ek_add_device_buttons();
+	/* LEDs */
+	ek_add_device_leds();
+
+	if (machine_is_usb_a9g20()) {
+		/* I2C */
+		at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
+	} else {
+		/* I2C */
+		at91_add_device_i2c(NULL, 0);
+		/* shutdown controller, wakeup button (5 msec low) */
+		at91_sys_write(AT91_SHDW_MR, AT91_SHDW_CPTWK0_(10)
+				| AT91_SHDW_WKMODE0_LOW
+				| AT91_SHDW_RTTWKEN);
+	}
+}
+
+MACHINE_START(USB_A9263, "CALAO USB_A9263")
+	/* Maintainer: calao-systems */
+	.timer		= &at91sam926x_timer,
+	.map_io		= at91_map_io,
+	.init_early	= ek_init_early,
+	.init_irq	= at91_init_irq_default,
+	.init_machine	= ek_board_init,
+MACHINE_END
+
+MACHINE_START(USB_A9260, "CALAO USB_A9260")
+	/* Maintainer: calao-systems */
+	.timer		= &at91sam926x_timer,
+	.map_io		= at91_map_io,
+	.init_early	= ek_init_early,
+	.init_irq	= at91_init_irq_default,
+	.init_machine	= ek_board_init,
+MACHINE_END
+
+MACHINE_START(USB_A9G20, "CALAO USB_A92G0")
+	/* Maintainer: Jean-Christophe PLAGNIOL-VILLARD */
+	.timer		= &at91sam926x_timer,
+	.map_io		= at91_map_io,
+	.init_early	= ek_init_early,
+	.init_irq	= at91_init_irq_default,
+	.init_machine	= ek_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h
index ed544a0..d07767f 100644
--- a/arch/arm/mach-at91/include/mach/board.h
+++ b/arch/arm/mach-at91/include/mach/board.h
@@ -98,6 +98,11 @@ extern void __init at91_add_device_eth(struct at91_eth_data *data);
 struct at91_usbh_data {
 	u8		ports;		/* number of ports on root hub */
 	u8		vbus_pin[2];	/* port power-control pin */
+	u8              vbus_pin_inverted;
+	u8              overcurrent_supported;
+	u8              overcurrent_pin[2];
+	u8              overcurrent_status[2];
+	u8              overcurrent_changed[2];
 };
 extern void __init at91_add_device_usbh(struct at91_usbh_data *data);
 extern void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data);
diff --git a/arch/arm/mach-at91/include/mach/timex.h b/arch/arm/mach-at91/include/mach/timex.h
index 31ac2d9..85820ad 100644
--- a/arch/arm/mach-at91/include/mach/timex.h
+++ b/arch/arm/mach-at91/include/mach/timex.h
@@ -64,7 +64,12 @@
 
 #elif defined(CONFIG_ARCH_AT91SAM9G20)
 
+#if defined(CONFIG_MACH_USB_A9G20)
+#define AT91SAM9_MASTER_CLOCK	133000000
+#else
 #define AT91SAM9_MASTER_CLOCK	132096000
+#endif
+
 #define CLOCK_TICK_RATE		(AT91SAM9_MASTER_CLOCK/16)
 
 #elif defined(CONFIG_ARCH_AT91SAM9G45)
diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig
index c0deaca..32d837d 100644
--- a/arch/arm/mach-davinci/Kconfig
+++ b/arch/arm/mach-davinci/Kconfig
@@ -192,6 +192,16 @@ config DA850_UI_RMII
 
 endchoice
 
+config DA850_WL12XX
+	bool "AM18x wl1271 daughter board"
+	depends on MACH_DAVINCI_DA850_EVM
+	help
+	  The wl1271 daughter card for AM18x EVMs is a combo wireless
+	  connectivity add-on card, based on the LS Research TiWi module with
+	  Texas Instruments' wl1271 solution.
+	  Say Y if you want to use a wl1271 expansion card connected to the
+	  AM18x EVM.
+
 config GPIO_PCA953X
 	default MACH_DAVINCI_DA850_EVM
 
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index 6e41cb5..ec21663 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -31,6 +31,8 @@
 #include <linux/input/tps6507x-ts.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
+#include <linux/delay.h>
+#include <linux/wl12xx.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -49,6 +51,9 @@
 #define DA850_MMCSD_CD_PIN		GPIO_TO_PIN(4, 0)
 #define DA850_MMCSD_WP_PIN		GPIO_TO_PIN(4, 1)
 
+#define DA850_WLAN_EN			GPIO_TO_PIN(6, 9)
+#define DA850_WLAN_IRQ			GPIO_TO_PIN(6, 10)
+
 #define DA850_MII_MDIO_CLKEN_PIN	GPIO_TO_PIN(2, 6)
 
 static struct mtd_partition da850evm_spiflash_part[] = {
@@ -1143,6 +1148,110 @@ static __init int da850_evm_init_cpufreq(void)
 static __init int da850_evm_init_cpufreq(void) { return 0; }
 #endif
 
+#ifdef CONFIG_DA850_WL12XX
+
+static void wl12xx_set_power(int index, bool power_on)
+{
+	static bool power_state;
+
+	pr_debug("Powering %s wl12xx", power_on ? "on" : "off");
+
+	if (power_on == power_state)
+		return;
+	power_state = power_on;
+
+	if (power_on) {
+		/* Power up sequence required for wl127x devices */
+		gpio_set_value(DA850_WLAN_EN, 1);
+		usleep_range(15000, 15000);
+		gpio_set_value(DA850_WLAN_EN, 0);
+		usleep_range(1000, 1000);
+		gpio_set_value(DA850_WLAN_EN, 1);
+		msleep(70);
+	} else {
+		gpio_set_value(DA850_WLAN_EN, 0);
+	}
+}
+
+static struct davinci_mmc_config da850_wl12xx_mmc_config = {
+	.set_power	= wl12xx_set_power,
+	.wires		= 4,
+	.max_freq	= 25000000,
+	.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_NONREMOVABLE |
+			  MMC_CAP_POWER_OFF_CARD,
+	.version	= MMC_CTLR_VERSION_2,
+};
+
+static const short da850_wl12xx_pins[] __initconst = {
+	DA850_MMCSD1_DAT_0, DA850_MMCSD1_DAT_1, DA850_MMCSD1_DAT_2,
+	DA850_MMCSD1_DAT_3, DA850_MMCSD1_CLK, DA850_MMCSD1_CMD,
+	DA850_GPIO6_9, DA850_GPIO6_10,
+	-1
+};
+
+static struct wl12xx_platform_data da850_wl12xx_wlan_data __initdata = {
+	.irq			= -1,
+	.board_ref_clock	= WL12XX_REFCLOCK_38,
+	.platform_quirks	= WL12XX_PLATFORM_QUIRK_EDGE_IRQ,
+};
+
+static __init int da850_wl12xx_init(void)
+{
+	int ret;
+
+	ret = davinci_cfg_reg_list(da850_wl12xx_pins);
+	if (ret) {
+		pr_err("wl12xx/mmc mux setup failed: %d\n", ret);
+		goto exit;
+	}
+
+	ret = da850_register_mmcsd1(&da850_wl12xx_mmc_config);
+	if (ret) {
+		pr_err("wl12xx/mmc registration failed: %d\n", ret);
+		goto exit;
+	}
+
+	ret = gpio_request_one(DA850_WLAN_EN, GPIOF_OUT_INIT_LOW, "wl12xx_en");
+	if (ret) {
+		pr_err("Could not request wl12xx enable gpio: %d\n", ret);
+		goto exit;
+	}
+
+	ret = gpio_request_one(DA850_WLAN_IRQ, GPIOF_IN, "wl12xx_irq");
+	if (ret) {
+		pr_err("Could not request wl12xx irq gpio: %d\n", ret);
+		goto free_wlan_en;
+	}
+
+	da850_wl12xx_wlan_data.irq = gpio_to_irq(DA850_WLAN_IRQ);
+
+	ret = wl12xx_set_platform_data(&da850_wl12xx_wlan_data);
+	if (ret) {
+		pr_err("Could not set wl12xx data: %d\n", ret);
+		goto free_wlan_irq;
+	}
+
+	return 0;
+
+free_wlan_irq:
+	gpio_free(DA850_WLAN_IRQ);
+
+free_wlan_en:
+	gpio_free(DA850_WLAN_EN);
+
+exit:
+	return ret;
+}
+
+#else /* CONFIG_DA850_WL12XX */
+
+static __init int da850_wl12xx_init(void)
+{
+	return 0;
+}
+
+#endif /* CONFIG_DA850_WL12XX */
+
 #define DA850EVM_SATA_REFCLKPN_RATE	(100 * 1000 * 1000)
 
 static __init void da850_evm_init(void)
@@ -1197,6 +1306,11 @@ static __init void da850_evm_init(void)
 		if (ret)
 			pr_warning("da850_evm_init: mmcsd0 registration failed:"
 					" %d\n", ret);
+
+		ret = da850_wl12xx_init();
+		if (ret)
+			pr_warning("da850_evm_init: wl12xx initialization"
+				   " failed: %d\n", ret);
 	}
 
 	davinci_serial_init(&da850_evm_uart_config);
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index 4aae015..b047f87 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -536,6 +536,13 @@ static const struct mux_config da850_pins[] = {
 	MUX_CFG(DA850, MMCSD0_DAT_3,	10,	20,	15,	2,	false)
 	MUX_CFG(DA850, MMCSD0_CLK,	10,	0,	15,	2,	false)
 	MUX_CFG(DA850, MMCSD0_CMD,	10,	4,	15,	2,	false)
+	/* MMC/SD1 function */
+	MUX_CFG(DA850, MMCSD1_DAT_0,	18,	8,	15,	2,	false)
+	MUX_CFG(DA850, MMCSD1_DAT_1,	19,	16,	15,	2,	false)
+	MUX_CFG(DA850, MMCSD1_DAT_2,	19,	12,	15,	2,	false)
+	MUX_CFG(DA850, MMCSD1_DAT_3,	19,	8,	15,	2,	false)
+	MUX_CFG(DA850, MMCSD1_CLK,	18,	12,	15,	2,	false)
+	MUX_CFG(DA850, MMCSD1_CMD,	18,	16,	15,	2,	false)
 	/* EMIF2.5/EMIFA function */
 	MUX_CFG(DA850, EMA_D_7,		9,	0,	15,	1,	false)
 	MUX_CFG(DA850, EMA_D_6,		9,	4,	15,	1,	false)
@@ -594,6 +601,8 @@ static const struct mux_config da850_pins[] = {
 	MUX_CFG(DA850, GPIO3_13,	7,	8,	15,	8,	false)
 	MUX_CFG(DA850, GPIO4_0,		10,	28,	15,	8,	false)
 	MUX_CFG(DA850, GPIO4_1,		10,	24,	15,	8,	false)
+	MUX_CFG(DA850, GPIO6_9,		13,	24,	15,	8,	false)
+	MUX_CFG(DA850, GPIO6_10,	13,	20,	15,	8,	false)
 	MUX_CFG(DA850, GPIO6_13,	13,	8,	15,	8,	false)
 	MUX_CFG(DA850, RTC_ALARM,	0,	28,	15,	2,	false)
 #endif
diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
index 2f7e719..68def71 100644
--- a/arch/arm/mach-davinci/devices-da8xx.c
+++ b/arch/arm/mach-davinci/devices-da8xx.c
@@ -136,6 +136,7 @@ static struct edma_soc_info da830_edma_cc0_info = {
 	.n_cc			= 1,
 	.queue_tc_mapping	= da8xx_queue_tc_mapping,
 	.queue_priority_mapping	= da8xx_queue_priority_mapping,
+	.default_queue		= EVENTQ_1,
 };
 
 static struct edma_soc_info *da830_edma_info[EDMA_MAX_CC] = {
@@ -151,6 +152,7 @@ static struct edma_soc_info da850_edma_cc_info[] = {
 		.n_cc			= 1,
 		.queue_tc_mapping	= da8xx_queue_tc_mapping,
 		.queue_priority_mapping	= da8xx_queue_priority_mapping,
+		.default_queue		= EVENTQ_1,
 	},
 	{
 		.n_channel		= 32,
@@ -160,6 +162,7 @@ static struct edma_soc_info da850_edma_cc_info[] = {
 		.n_cc			= 1,
 		.queue_tc_mapping	= da850_queue_tc_mapping,
 		.queue_priority_mapping	= da850_queue_priority_mapping,
+		.default_queue		= EVENTQ_0,
 	},
 };
 
diff --git a/arch/arm/mach-davinci/devices-tnetv107x.c b/arch/arm/mach-davinci/devices-tnetv107x.c
index 6162cae..29b17f7 100644
--- a/arch/arm/mach-davinci/devices-tnetv107x.c
+++ b/arch/arm/mach-davinci/devices-tnetv107x.c
@@ -80,6 +80,7 @@ static struct edma_soc_info edma_cc0_info = {
 	.n_cc			= 1,
 	.queue_tc_mapping	= edma_tc_mapping,
 	.queue_priority_mapping	= edma_priority_mapping,
+	.default_queue		= EVENTQ_1,
 };
 
 static struct edma_soc_info *tnetv107x_edma_info[EDMA_MAX_CC] = {
diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
index c143f43..fe520d4 100644
--- a/arch/arm/mach-davinci/dm355.c
+++ b/arch/arm/mach-davinci/dm355.c
@@ -591,6 +591,7 @@ static struct edma_soc_info edma_cc0_info = {
 	.n_cc			= 1,
 	.queue_tc_mapping	= queue_tc_mapping,
 	.queue_priority_mapping	= queue_priority_mapping,
+	.default_queue		= EVENTQ_1,
 };
 
 static struct edma_soc_info *dm355_edma_info[EDMA_MAX_CC] = {
diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
index 9a27466..3470983 100644
--- a/arch/arm/mach-davinci/dm644x.c
+++ b/arch/arm/mach-davinci/dm644x.c
@@ -514,6 +514,7 @@ static struct edma_soc_info edma_cc0_info = {
 	.n_cc			= 1,
 	.queue_tc_mapping	= queue_tc_mapping,
 	.queue_priority_mapping	= queue_priority_mapping,
+	.default_queue		= EVENTQ_1,
 };
 
 static struct edma_soc_info *dm644x_edma_info[EDMA_MAX_CC] = {
diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c
index 03e5f49..0b68ed5 100644
--- a/arch/arm/mach-davinci/dm646x.c
+++ b/arch/arm/mach-davinci/dm646x.c
@@ -555,6 +555,7 @@ static struct edma_soc_info edma_cc0_info = {
 	.n_cc			= 1,
 	.queue_tc_mapping	= dm646x_queue_tc_mapping,
 	.queue_priority_mapping	= dm646x_queue_priority_mapping,
+	.default_queue		= EVENTQ_1,
 };
 
 static struct edma_soc_info *dm646x_edma_info[EDMA_MAX_CC] = {
diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c
index 6b96698..da90103 100644
--- a/arch/arm/mach-davinci/dma.c
+++ b/arch/arm/mach-davinci/dma.c
@@ -1435,12 +1435,11 @@ static int __init edma_probe(struct platform_device *pdev)
 			goto fail1;
 		}
 
-		edma_cc[j] = kmalloc(sizeof(struct edma), GFP_KERNEL);
+		edma_cc[j] = kzalloc(sizeof(struct edma), GFP_KERNEL);
 		if (!edma_cc[j]) {
 			status = -ENOMEM;
 			goto fail1;
 		}
-		memset(edma_cc[j], 0, sizeof(struct edma));
 
 		edma_cc[j]->num_channels = min_t(unsigned, info[j]->n_channel,
 							EDMA_MAX_DMACH);
@@ -1450,8 +1449,6 @@ static int __init edma_probe(struct platform_device *pdev)
 							EDMA_MAX_CC);
 
 		edma_cc[j]->default_queue = info[j]->default_queue;
-		if (!edma_cc[j]->default_queue)
-			edma_cc[j]->default_queue = EVENTQ_1;
 
 		dev_dbg(&pdev->dev, "DMA REG BASE ADDR=%p\n",
 			edmacc_regs_base[j]);
diff --git a/arch/arm/mach-davinci/include/mach/mmc.h b/arch/arm/mach-davinci/include/mach/mmc.h
index d4f1e96..5ba6b22 100644
--- a/arch/arm/mach-davinci/include/mach/mmc.h
+++ b/arch/arm/mach-davinci/include/mach/mmc.h
@@ -12,6 +12,9 @@ struct davinci_mmc_config {
 	/* get_cd()/get_wp() may sleep */
 	int	(*get_cd)(int module);
 	int	(*get_ro)(int module);
+
+	void	(*set_power)(int module, bool on);
+
 	/* wires == 0 is equivalent to wires == 4 (4-bit parallel) */
 	u8	wires;
 
diff --git a/arch/arm/mach-davinci/include/mach/mux.h b/arch/arm/mach-davinci/include/mach/mux.h
index 5d4e0fe..a7e92fc 100644
--- a/arch/arm/mach-davinci/include/mach/mux.h
+++ b/arch/arm/mach-davinci/include/mach/mux.h
@@ -857,6 +857,14 @@ enum davinci_da850_index {
 	DA850_MMCSD0_CLK,
 	DA850_MMCSD0_CMD,
 
+	/* MMC/SD1 function */
+	DA850_MMCSD1_DAT_0,
+	DA850_MMCSD1_DAT_1,
+	DA850_MMCSD1_DAT_2,
+	DA850_MMCSD1_DAT_3,
+	DA850_MMCSD1_CLK,
+	DA850_MMCSD1_CMD,
+
 	/* EMIF2.5/EMIFA function */
 	DA850_EMA_D_7,
 	DA850_EMA_D_6,
@@ -916,6 +924,8 @@ enum davinci_da850_index {
 	DA850_GPIO3_13,
 	DA850_GPIO4_0,
 	DA850_GPIO4_1,
+	DA850_GPIO6_9,
+	DA850_GPIO6_10,
 	DA850_GPIO6_13,
 	DA850_RTC_ALARM,
 };
diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig
index 3a08b18..97a2493 100644
--- a/arch/arm/mach-ep93xx/Kconfig
+++ b/arch/arm/mach-ep93xx/Kconfig
@@ -182,6 +182,13 @@ config MACH_TS72XX
 	  Say 'Y' here if you want your kernel to support the
 	  Technologic Systems TS-72xx board.
 
+config MACH_VISION_EP9307
+	bool "Support Vision Engraving Systems EP9307 SoM"
+	depends on EP93XX_SDCE0_PHYS_OFFSET
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Vision Engraving Systems EP9307 SoM.
+
 choice
 	prompt "Select a UART for early kernel messages"
 
diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
index 3cedcf2..574209d 100644
--- a/arch/arm/mach-ep93xx/Makefile
+++ b/arch/arm/mach-ep93xx/Makefile
@@ -15,3 +15,4 @@ obj-$(CONFIG_MACH_MICRO9)	+= micro9.o
 obj-$(CONFIG_MACH_SIM_ONE)	+= simone.o
 obj-$(CONFIG_MACH_SNAPPER_CL15)	+= snappercl15.o
 obj-$(CONFIG_MACH_TS72XX)	+= ts72xx.o
+obj-$(CONFIG_MACH_VISION_EP9307)+= vision_ep9307.o
diff --git a/arch/arm/mach-ep93xx/vision_ep9307.c b/arch/arm/mach-ep93xx/vision_ep9307.c
new file mode 100644
index 0000000..d96e4db
--- /dev/null
+++ b/arch/arm/mach-ep93xx/vision_ep9307.c
@@ -0,0 +1,364 @@
+/*
+ * arch/arm/mach-ep93xx/vision_ep9307.c
+ * Vision Engraving Systems EP9307 SoM support.
+ *
+ * Copyright (C) 2008-2011 Vision Engraving Systems
+ * H Hartley Sweeten <hsweeten@visionengravers.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/fb.h>
+#include <linux/io.h>
+#include <linux/mtd/partitions.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/mmc_spi.h>
+#include <linux/mmc/host.h>
+
+#include <mach/hardware.h>
+#include <mach/fb.h>
+#include <mach/ep93xx_spi.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/map.h>
+#include <asm/mach/arch.h>
+
+/*************************************************************************
+ * Static I/O mappings for the FPGA
+ *************************************************************************/
+#define VISION_PHYS_BASE	EP93XX_CS7_PHYS_BASE
+#define VISION_VIRT_BASE	0xfebff000
+
+static struct map_desc vision_io_desc[] __initdata = {
+	{
+		.virtual	= VISION_VIRT_BASE,
+		.pfn		= __phys_to_pfn(VISION_PHYS_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+};
+
+static void __init vision_map_io(void)
+{
+	ep93xx_map_io();
+
+	iotable_init(vision_io_desc, ARRAY_SIZE(vision_io_desc));
+}
+
+/*************************************************************************
+ * Ethernet
+ *************************************************************************/
+static struct ep93xx_eth_data vision_eth_data __initdata = {
+	.phy_id		= 1,
+};
+
+/*************************************************************************
+ * Framebuffer
+ *************************************************************************/
+#define VISION_LCD_ENABLE	EP93XX_GPIO_LINE_EGPIO1
+
+static int vision_lcd_setup(struct platform_device *pdev)
+{
+	int err;
+
+	err = gpio_request_one(VISION_LCD_ENABLE, GPIOF_INIT_HIGH,
+				dev_name(&pdev->dev));
+	if (err)
+		return err;
+
+	ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_RAS |
+				 EP93XX_SYSCON_DEVCFG_RASONP3 |
+				 EP93XX_SYSCON_DEVCFG_EXVC);
+
+	return 0;
+}
+
+static void vision_lcd_teardown(struct platform_device *pdev)
+{
+	gpio_free(VISION_LCD_ENABLE);
+}
+
+static void vision_lcd_blank(int blank_mode, struct fb_info *info)
+{
+	if (blank_mode)
+		gpio_set_value(VISION_LCD_ENABLE, 0);
+	else
+		gpio_set_value(VISION_LCD_ENABLE, 1);
+}
+
+static struct ep93xxfb_mach_info ep93xxfb_info __initdata = {
+	.num_modes	= EP93XXFB_USE_MODEDB,
+	.bpp		= 16,
+	.flags		= EP93XXFB_USE_SDCSN0 | EP93XXFB_PCLK_FALLING,
+	.setup		= vision_lcd_setup,
+	.teardown	= vision_lcd_teardown,
+	.blank		= vision_lcd_blank,
+};
+
+
+/*************************************************************************
+ * GPIO Expanders
+ *************************************************************************/
+#define PCA9539_74_GPIO_BASE	(EP93XX_GPIO_LINE_MAX + 1)
+#define PCA9539_75_GPIO_BASE	(PCA9539_74_GPIO_BASE + 16)
+#define PCA9539_76_GPIO_BASE	(PCA9539_75_GPIO_BASE + 16)
+#define PCA9539_77_GPIO_BASE	(PCA9539_76_GPIO_BASE + 16)
+
+static struct pca953x_platform_data pca953x_74_gpio_data = {
+	.gpio_base	= PCA9539_74_GPIO_BASE,
+	.irq_base	= EP93XX_BOARD_IRQ(0),
+};
+
+static struct pca953x_platform_data pca953x_75_gpio_data = {
+	.gpio_base	= PCA9539_75_GPIO_BASE,
+	.irq_base	= -1,
+};
+
+static struct pca953x_platform_data pca953x_76_gpio_data = {
+	.gpio_base	= PCA9539_76_GPIO_BASE,
+	.irq_base	= -1,
+};
+
+static struct pca953x_platform_data pca953x_77_gpio_data = {
+	.gpio_base	= PCA9539_77_GPIO_BASE,
+	.irq_base	= -1,
+};
+
+/*************************************************************************
+ * I2C Bus
+ *************************************************************************/
+static struct i2c_gpio_platform_data vision_i2c_gpio_data __initdata = {
+	.sda_pin		= EP93XX_GPIO_LINE_EEDAT,
+	.scl_pin		= EP93XX_GPIO_LINE_EECLK,
+};
+
+static struct i2c_board_info vision_i2c_info[] __initdata = {
+	{
+		I2C_BOARD_INFO("isl1208", 0x6f),
+		.irq		= IRQ_EP93XX_EXT1,
+	}, {
+		I2C_BOARD_INFO("pca9539", 0x74),
+		.platform_data	= &pca953x_74_gpio_data,
+		.irq		= gpio_to_irq(EP93XX_GPIO_LINE_F(7)),
+	}, {
+		I2C_BOARD_INFO("pca9539", 0x75),
+		.platform_data	= &pca953x_75_gpio_data,
+	}, {
+		I2C_BOARD_INFO("pca9539", 0x76),
+		.platform_data	= &pca953x_76_gpio_data,
+	}, {
+		I2C_BOARD_INFO("pca9539", 0x77),
+		.platform_data	= &pca953x_77_gpio_data,
+	},
+};
+
+/*************************************************************************
+ * SPI Flash
+ *************************************************************************/
+#define VISION_SPI_FLASH_CS	EP93XX_GPIO_LINE_EGPIO7
+
+static struct mtd_partition vision_spi_flash_partitions[] = {
+	{
+		.name	= "SPI bootstrap",
+		.offset	= 0,
+		.size	= SZ_4K,
+	}, {
+		.name	= "Bootstrap config",
+		.offset	= MTDPART_OFS_APPEND,
+		.size	= SZ_4K,
+	}, {
+		.name	= "System config",
+		.offset	= MTDPART_OFS_APPEND,
+		.size	= MTDPART_SIZ_FULL,
+	},
+};
+
+static struct flash_platform_data vision_spi_flash_data = {
+	.name		= "SPI Flash",
+	.parts		= vision_spi_flash_partitions,
+	.nr_parts	= ARRAY_SIZE(vision_spi_flash_partitions),
+};
+
+static int vision_spi_flash_hw_setup(struct spi_device *spi)
+{
+	return gpio_request_one(VISION_SPI_FLASH_CS, GPIOF_INIT_HIGH,
+				spi->modalias);
+}
+
+static void vision_spi_flash_hw_cleanup(struct spi_device *spi)
+{
+	gpio_free(VISION_SPI_FLASH_CS);
+}
+
+static void vision_spi_flash_hw_cs_control(struct spi_device *spi, int value)
+{
+	gpio_set_value(VISION_SPI_FLASH_CS, value);
+}
+
+static struct ep93xx_spi_chip_ops vision_spi_flash_hw = {
+	.setup		= vision_spi_flash_hw_setup,
+	.cleanup	= vision_spi_flash_hw_cleanup,
+	.cs_control	= vision_spi_flash_hw_cs_control,
+};
+
+/*************************************************************************
+ * SPI SD/MMC host
+ *************************************************************************/
+#define VISION_SPI_MMC_CS	EP93XX_GPIO_LINE_G(2)
+#define VISION_SPI_MMC_WP	EP93XX_GPIO_LINE_F(0)
+#define VISION_SPI_MMC_CD	EP93XX_GPIO_LINE_EGPIO15
+
+static struct gpio vision_spi_mmc_gpios[] = {
+	{ VISION_SPI_MMC_WP, GPIOF_DIR_IN, "mmc_spi:wp" },
+	{ VISION_SPI_MMC_CD, GPIOF_DIR_IN, "mmc_spi:cd" },
+};
+
+static int vision_spi_mmc_init(struct device *pdev,
+			irqreturn_t (*func)(int, void *), void *pdata)
+{
+	int err;
+
+	err = gpio_request_array(vision_spi_mmc_gpios,
+				 ARRAY_SIZE(vision_spi_mmc_gpios));
+	if (err)
+		return err;
+
+	err = gpio_set_debounce(VISION_SPI_MMC_CD, 1);
+	if (err)
+		goto exit_err;
+
+	err = request_irq(gpio_to_irq(VISION_SPI_MMC_CD), func,
+			IRQ_TYPE_EDGE_BOTH, "mmc_spi:cd", pdata);
+	if (err)
+		goto exit_err;
+
+	return 0;
+
+exit_err:
+	gpio_free_array(vision_spi_mmc_gpios, ARRAY_SIZE(vision_spi_mmc_gpios));
+	return err;
+
+}
+
+static void vision_spi_mmc_exit(struct device *pdev, void *pdata)
+{
+	free_irq(gpio_to_irq(VISION_SPI_MMC_CD), pdata);
+	gpio_free_array(vision_spi_mmc_gpios, ARRAY_SIZE(vision_spi_mmc_gpios));
+}
+
+static int vision_spi_mmc_get_ro(struct device *pdev)
+{
+	return !!gpio_get_value(VISION_SPI_MMC_WP);
+}
+
+static int vision_spi_mmc_get_cd(struct device *pdev)
+{
+	return !gpio_get_value(VISION_SPI_MMC_CD);
+}
+
+static struct mmc_spi_platform_data vision_spi_mmc_data = {
+	.init		= vision_spi_mmc_init,
+	.exit		= vision_spi_mmc_exit,
+	.get_ro		= vision_spi_mmc_get_ro,
+	.get_cd		= vision_spi_mmc_get_cd,
+	.detect_delay	= 100,
+	.powerup_msecs	= 100,
+	.ocr_mask	= MMC_VDD_32_33 | MMC_VDD_33_34,
+};
+
+static int vision_spi_mmc_hw_setup(struct spi_device *spi)
+{
+	return gpio_request_one(VISION_SPI_MMC_CS, GPIOF_INIT_HIGH,
+				spi->modalias);
+}
+
+static void vision_spi_mmc_hw_cleanup(struct spi_device *spi)
+{
+	gpio_free(VISION_SPI_MMC_CS);
+}
+
+static void vision_spi_mmc_hw_cs_control(struct spi_device *spi, int value)
+{
+	gpio_set_value(VISION_SPI_MMC_CS, value);
+}
+
+static struct ep93xx_spi_chip_ops vision_spi_mmc_hw = {
+	.setup		= vision_spi_mmc_hw_setup,
+	.cleanup	= vision_spi_mmc_hw_cleanup,
+	.cs_control	= vision_spi_mmc_hw_cs_control,
+};
+
+/*************************************************************************
+ * SPI Bus
+ *************************************************************************/
+static struct spi_board_info vision_spi_board_info[] __initdata = {
+	{
+		.modalias		= "sst25l",
+		.platform_data		= &vision_spi_flash_data,
+		.controller_data	= &vision_spi_flash_hw,
+		.max_speed_hz		= 20000000,
+		.bus_num		= 0,
+		.chip_select		= 0,
+		.mode			= SPI_MODE_3,
+	}, {
+		.modalias		= "mmc_spi",
+		.platform_data		= &vision_spi_mmc_data,
+		.controller_data	= &vision_spi_mmc_hw,
+		.max_speed_hz		= 20000000,
+		.bus_num		= 0,
+		.chip_select		= 1,
+		.mode			= SPI_MODE_3,
+	},
+};
+
+static struct ep93xx_spi_info vision_spi_master __initdata = {
+	.num_chipselect		= ARRAY_SIZE(vision_spi_board_info),
+};
+
+/*************************************************************************
+ * Machine Initialization
+ *************************************************************************/
+static void __init vision_init_machine(void)
+{
+	ep93xx_init_devices();
+	ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_64M);
+	ep93xx_register_eth(&vision_eth_data, 1);
+	ep93xx_register_fb(&ep93xxfb_info);
+	ep93xx_register_pwm(1, 0);
+
+	/*
+	 * Request the gpio expander's interrupt gpio line now to prevent
+	 * the kernel from doing a WARN in gpiolib:gpio_ensure_requested().
+	 */
+	if (gpio_request_one(EP93XX_GPIO_LINE_F(7), GPIOF_DIR_IN,
+				"pca9539:74"))
+		pr_warn("cannot request interrupt gpio for pca9539:74\n");
+
+	ep93xx_register_i2c(&vision_i2c_gpio_data, vision_i2c_info,
+				ARRAY_SIZE(vision_i2c_info));
+	ep93xx_register_spi(&vision_spi_master, vision_spi_board_info,
+				ARRAY_SIZE(vision_spi_board_info));
+}
+
+MACHINE_START(VISION_EP9307, "Vision Engraving Systems EP9307")
+	/* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
+	.atag_offset	= 0x100,
+	.map_io		= vision_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.timer		= &ep93xx_timer,
+	.init_machine	= vision_init_machine,
+MACHINE_END
diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig
index fc1f92d..a652735 100644
--- a/arch/arm/mach-exynos4/Kconfig
+++ b/arch/arm/mach-exynos4/Kconfig
@@ -16,6 +16,16 @@ config CPU_EXYNOS4210
 	help
 	  Enable EXYNOS4210 CPU support
 
+config SOC_EXYNOS4212
+	bool
+	help
+	  Enable EXYNOS4212 SoC support
+
+config SOC_EXYNOS4412
+	bool
+	help
+	  Enable EXYNOS4412 SoC support
+
 config EXYNOS4_MCT
 	bool
 	default y
@@ -112,24 +122,11 @@ config EXYNOS4_SETUP_USB_PHY
 
 menu "EXYNOS4 Machines"
 
+comment "EXYNOS4210 Boards"
+
 config MACH_SMDKC210
 	bool "SMDKC210"
-	select CPU_EXYNOS4210
-	select S5P_DEV_FIMD0
-	select S3C_DEV_RTC
-	select S3C_DEV_WDT
-	select S3C_DEV_I2C1
-	select S3C_DEV_HSMMC
-	select S3C_DEV_HSMMC1
-	select S3C_DEV_HSMMC2
-	select S3C_DEV_HSMMC3
-	select SAMSUNG_DEV_PWM
-	select SAMSUNG_DEV_BACKLIGHT
-	select EXYNOS4_DEV_PD
-	select EXYNOS4_DEV_SYSMMU
-	select EXYNOS4_SETUP_FIMD0
-	select EXYNOS4_SETUP_I2C1
-	select EXYNOS4_SETUP_SDHCI
+	select MACH_SMDKV310
 	help
 	  Machine support for Samsung SMDKC210
 
@@ -219,6 +216,48 @@ config MACH_NURI
 	help
 	  Machine support for Samsung Mobile NURI Board.
 
+config MACH_ORIGEN
+	bool "ORIGEN"
+	select CPU_EXYNOS4210
+	select S3C_DEV_RTC
+	select S3C_DEV_WDT
+	select S3C_DEV_HSMMC2
+	select EXYNOS4_SETUP_SDHCI
+	help
+	  Machine support for ORIGEN based on Samsung EXYNOS4210
+
+comment "EXYNOS4212 Boards"
+
+config MACH_SMDK4212
+	bool "SMDK4212"
+	select SOC_EXYNOS4212
+	select S3C_DEV_HSMMC2
+	select S3C_DEV_HSMMC3
+	select S3C_DEV_I2C1
+	select S3C_DEV_I2C3
+	select S3C_DEV_I2C7
+	select S3C_DEV_RTC
+	select S3C_DEV_WDT
+	select SAMSUNG_DEV_BACKLIGHT
+	select SAMSUNG_DEV_KEYPAD
+	select SAMSUNG_DEV_PWM
+	select EXYNOS4_SETUP_I2C1
+	select EXYNOS4_SETUP_I2C3
+	select EXYNOS4_SETUP_I2C7
+	select EXYNOS4_SETUP_KEYPAD
+	select EXYNOS4_SETUP_SDHCI
+	help
+	  Machine support for Samsung SMDK4212
+
+comment "EXYNOS4412 Boards"
+
+config MACH_SMDK4412
+	bool "SMDK4412"
+	select SOC_EXYNOS4412
+	select MACH_SMDK4212
+	help
+	  Machine support for Samsung SMDK4412
+
 endmenu
 
 comment "Configuration for HSMMC bus width"
diff --git a/arch/arm/mach-exynos4/Makefile b/arch/arm/mach-exynos4/Makefile
index b7fe1d7..c9b2e1f 100644
--- a/arch/arm/mach-exynos4/Makefile
+++ b/arch/arm/mach-exynos4/Makefile
@@ -12,8 +12,10 @@ obj-				:=
 
 # Core support for EXYNOS4 system
 
-obj-$(CONFIG_CPU_EXYNOS4210)	+= cpu.o init.o clock.o irq-combiner.o
-obj-$(CONFIG_CPU_EXYNOS4210)	+= setup-i2c0.o irq-eint.o dma.o pmu.o
+obj-$(CONFIG_ARCH_EXYNOS4)	+= cpu.o init.o clock.o irq-combiner.o
+obj-$(CONFIG_ARCH_EXYNOS4)	+= setup-i2c0.o irq-eint.o dma.o pmu.o
+obj-$(CONFIG_CPU_EXYNOS4210)	+= clock-exynos4210.o
+obj-$(CONFIG_SOC_EXYNOS4212)	+= clock-exynos4212.o
 obj-$(CONFIG_PM)		+= pm.o sleep.o
 obj-$(CONFIG_CPU_IDLE)		+= cpuidle.o
 
@@ -25,11 +27,15 @@ obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
 
 # machine support
 
-obj-$(CONFIG_MACH_SMDKC210)		+= mach-smdkc210.o
+obj-$(CONFIG_MACH_SMDKC210)		+= mach-smdkv310.o
 obj-$(CONFIG_MACH_SMDKV310)		+= mach-smdkv310.o
 obj-$(CONFIG_MACH_ARMLEX4210)		+= mach-armlex4210.o
 obj-$(CONFIG_MACH_UNIVERSAL_C210)	+= mach-universal_c210.o
 obj-$(CONFIG_MACH_NURI)			+= mach-nuri.o
+obj-$(CONFIG_MACH_ORIGEN)		+= mach-origen.o
+
+obj-$(CONFIG_MACH_SMDK4212)		+= mach-smdk4x12.o
+obj-$(CONFIG_MACH_SMDK4412)		+= mach-smdk4x12.o
 
 # device support
 
diff --git a/arch/arm/mach-exynos4/clock-exynos4210.c b/arch/arm/mach-exynos4/clock-exynos4210.c
new file mode 100644
index 0000000..b9d5ef6
--- /dev/null
+++ b/arch/arm/mach-exynos4/clock-exynos4210.c
@@ -0,0 +1,139 @@
+/*
+ * linux/arch/arm/mach-exynos4/clock-exynos4210.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4210 - Clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/syscore_ops.h>
+
+#include <plat/cpu-freq.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include <plat/pll.h>
+#include <plat/s5p-clock.h>
+#include <plat/clock-clksrc.h>
+#include <plat/exynos4.h>
+#include <plat/pm.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/exynos4-clock.h>
+
+static struct sleep_save exynos4210_clock_save[] = {
+	SAVE_ITEM(S5P_CLKSRC_IMAGE),
+	SAVE_ITEM(S5P_CLKSRC_LCD1),
+	SAVE_ITEM(S5P_CLKDIV_IMAGE),
+	SAVE_ITEM(S5P_CLKDIV_LCD1),
+	SAVE_ITEM(S5P_CLKSRC_MASK_LCD1),
+	SAVE_ITEM(S5P_CLKGATE_IP_IMAGE_4210),
+	SAVE_ITEM(S5P_CLKGATE_IP_LCD1),
+	SAVE_ITEM(S5P_CLKGATE_IP_PERIR_4210),
+};
+
+static struct clksrc_clk *sysclks[] = {
+	/* nothing here yet */
+};
+
+static int exynos4_clksrc_mask_lcd1_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKSRC_MASK_LCD1, clk, enable);
+}
+
+static struct clksrc_clk clksrcs[] = {
+	{
+		.clk		= {
+			.name		= "sclk_sata",
+			.id		= -1,
+			.enable		= exynos4_clksrc_mask_fsys_ctrl,
+			.ctrlbit	= (1 << 24),
+		},
+		.sources = &clkset_mout_corebus,
+		.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 24, .size = 1 },
+		.reg_div = { .reg = S5P_CLKDIV_FSYS0, .shift = 20, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_fimd",
+			.devname	= "exynos4-fb.1",
+			.enable		= exynos4_clksrc_mask_lcd1_ctrl,
+			.ctrlbit	= (1 << 0),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_LCD1, .shift = 0, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_LCD1, .shift = 0, .size = 4 },
+	},
+};
+
+static struct clk init_clocks_off[] = {
+	{
+		.name		= "sataphy",
+		.id		= -1,
+		.parent		= &clk_aclk_133.clk,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 3),
+	}, {
+		.name		= "sata",
+		.id		= -1,
+		.parent		= &clk_aclk_133.clk,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 10),
+	}, {
+		.name		= "fimd",
+		.devname	= "exynos4-fb.1",
+		.enable		= exynos4_clk_ip_lcd1_ctrl,
+		.ctrlbit	= (1 << 0),
+	},
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int exynos4210_clock_suspend(void)
+{
+	s3c_pm_do_save(exynos4210_clock_save, ARRAY_SIZE(exynos4210_clock_save));
+
+	return 0;
+}
+
+static void exynos4210_clock_resume(void)
+{
+	s3c_pm_do_restore_core(exynos4210_clock_save, ARRAY_SIZE(exynos4210_clock_save));
+}
+
+#else
+#define exynos4210_clock_suspend NULL
+#define exynos4210_clock_resume NULL
+#endif
+
+struct syscore_ops exynos4210_clock_syscore_ops = {
+	.suspend	= exynos4210_clock_suspend,
+	.resume		= exynos4210_clock_resume,
+};
+
+void __init exynos4210_register_clocks(void)
+{
+	int ptr;
+
+	clk_mout_mpll.reg_src.reg = S5P_CLKSRC_CPU;
+	clk_mout_mpll.reg_src.shift = 8;
+	clk_mout_mpll.reg_src.size = 1;
+
+	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
+		s3c_register_clksrc(sysclks[ptr], 1);
+
+	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
+
+	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+
+	register_syscore_ops(&exynos4210_clock_syscore_ops);
+}
diff --git a/arch/arm/mach-exynos4/clock-exynos4212.c b/arch/arm/mach-exynos4/clock-exynos4212.c
new file mode 100644
index 0000000..77d5dec
--- /dev/null
+++ b/arch/arm/mach-exynos4/clock-exynos4212.c
@@ -0,0 +1,118 @@
+/*
+ * linux/arch/arm/mach-exynos4/clock-exynos4212.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4212 - Clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/syscore_ops.h>
+
+#include <plat/cpu-freq.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include <plat/pll.h>
+#include <plat/s5p-clock.h>
+#include <plat/clock-clksrc.h>
+#include <plat/exynos4.h>
+#include <plat/pm.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/exynos4-clock.h>
+
+static struct sleep_save exynos4212_clock_save[] = {
+	SAVE_ITEM(S5P_CLKSRC_IMAGE),
+	SAVE_ITEM(S5P_CLKDIV_IMAGE),
+	SAVE_ITEM(S5P_CLKGATE_IP_IMAGE_4212),
+	SAVE_ITEM(S5P_CLKGATE_IP_PERIR_4212),
+};
+
+static struct clk *clk_src_mpll_user_list[] = {
+	[0] = &clk_fin_mpll,
+	[1] = &clk_mout_mpll.clk,
+};
+
+static struct clksrc_sources clk_src_mpll_user = {
+	.sources	= clk_src_mpll_user_list,
+	.nr_sources	= ARRAY_SIZE(clk_src_mpll_user_list),
+};
+
+static struct clksrc_clk clk_mout_mpll_user = {
+	.clk = {
+		.name		= "mout_mpll_user",
+	},
+	.sources	= &clk_src_mpll_user,
+	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 24, .size = 1 },
+};
+
+static struct clksrc_clk *sysclks[] = {
+	&clk_mout_mpll_user,
+};
+
+static struct clksrc_clk clksrcs[] = {
+	/* nothing here yet */
+};
+
+static struct clk init_clocks_off[] = {
+	/* nothing here yet */
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int exynos4212_clock_suspend(void)
+{
+	s3c_pm_do_save(exynos4212_clock_save, ARRAY_SIZE(exynos4212_clock_save));
+
+	return 0;
+}
+
+static void exynos4212_clock_resume(void)
+{
+	s3c_pm_do_restore_core(exynos4212_clock_save, ARRAY_SIZE(exynos4212_clock_save));
+}
+
+#else
+#define exynos4212_clock_suspend NULL
+#define exynos4212_clock_resume NULL
+#endif
+
+struct syscore_ops exynos4212_clock_syscore_ops = {
+	.suspend	= exynos4212_clock_suspend,
+	.resume		= exynos4212_clock_resume,
+};
+
+void __init exynos4212_register_clocks(void)
+{
+	int ptr;
+
+	/* usbphy1 is removed */
+	clkset_group_list[4] = NULL;
+
+	/* mout_mpll_user is used */
+	clkset_group_list[6] = &clk_mout_mpll_user.clk;
+	clkset_aclk_top_list[0] = &clk_mout_mpll_user.clk;
+
+	clk_mout_mpll.reg_src.reg = S5P_CLKSRC_DMC;
+	clk_mout_mpll.reg_src.shift = 12;
+	clk_mout_mpll.reg_src.size = 1;
+
+	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
+		s3c_register_clksrc(sysclks[ptr], 1);
+
+	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
+
+	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+
+	register_syscore_ops(&exynos4212_clock_syscore_ops);
+}
diff --git a/arch/arm/mach-exynos4/clock.c b/arch/arm/mach-exynos4/clock.c
index 86964d2..0d59be3 100644
--- a/arch/arm/mach-exynos4/clock.c
+++ b/arch/arm/mach-exynos4/clock.c
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/syscore_ops.h>
 
 #include <plat/cpu-freq.h>
 #include <plat/clock.h>
@@ -20,26 +21,93 @@
 #include <plat/pll.h>
 #include <plat/s5p-clock.h>
 #include <plat/clock-clksrc.h>
+#include <plat/exynos4.h>
+#include <plat/pm.h>
 
 #include <mach/map.h>
 #include <mach/regs-clock.h>
 #include <mach/sysmmu.h>
-
-static struct clk clk_sclk_hdmi27m = {
+#include <mach/exynos4-clock.h>
+
+static struct sleep_save exynos4_clock_save[] = {
+	SAVE_ITEM(S5P_CLKDIV_LEFTBUS),
+	SAVE_ITEM(S5P_CLKGATE_IP_LEFTBUS),
+	SAVE_ITEM(S5P_CLKDIV_RIGHTBUS),
+	SAVE_ITEM(S5P_CLKGATE_IP_RIGHTBUS),
+	SAVE_ITEM(S5P_CLKSRC_TOP0),
+	SAVE_ITEM(S5P_CLKSRC_TOP1),
+	SAVE_ITEM(S5P_CLKSRC_CAM),
+	SAVE_ITEM(S5P_CLKSRC_TV),
+	SAVE_ITEM(S5P_CLKSRC_MFC),
+	SAVE_ITEM(S5P_CLKSRC_G3D),
+	SAVE_ITEM(S5P_CLKSRC_LCD0),
+	SAVE_ITEM(S5P_CLKSRC_MAUDIO),
+	SAVE_ITEM(S5P_CLKSRC_FSYS),
+	SAVE_ITEM(S5P_CLKSRC_PERIL0),
+	SAVE_ITEM(S5P_CLKSRC_PERIL1),
+	SAVE_ITEM(S5P_CLKDIV_CAM),
+	SAVE_ITEM(S5P_CLKDIV_TV),
+	SAVE_ITEM(S5P_CLKDIV_MFC),
+	SAVE_ITEM(S5P_CLKDIV_G3D),
+	SAVE_ITEM(S5P_CLKDIV_LCD0),
+	SAVE_ITEM(S5P_CLKDIV_MAUDIO),
+	SAVE_ITEM(S5P_CLKDIV_FSYS0),
+	SAVE_ITEM(S5P_CLKDIV_FSYS1),
+	SAVE_ITEM(S5P_CLKDIV_FSYS2),
+	SAVE_ITEM(S5P_CLKDIV_FSYS3),
+	SAVE_ITEM(S5P_CLKDIV_PERIL0),
+	SAVE_ITEM(S5P_CLKDIV_PERIL1),
+	SAVE_ITEM(S5P_CLKDIV_PERIL2),
+	SAVE_ITEM(S5P_CLKDIV_PERIL3),
+	SAVE_ITEM(S5P_CLKDIV_PERIL4),
+	SAVE_ITEM(S5P_CLKDIV_PERIL5),
+	SAVE_ITEM(S5P_CLKDIV_TOP),
+	SAVE_ITEM(S5P_CLKSRC_MASK_TOP),
+	SAVE_ITEM(S5P_CLKSRC_MASK_CAM),
+	SAVE_ITEM(S5P_CLKSRC_MASK_TV),
+	SAVE_ITEM(S5P_CLKSRC_MASK_LCD0),
+	SAVE_ITEM(S5P_CLKSRC_MASK_MAUDIO),
+	SAVE_ITEM(S5P_CLKSRC_MASK_FSYS),
+	SAVE_ITEM(S5P_CLKSRC_MASK_PERIL0),
+	SAVE_ITEM(S5P_CLKSRC_MASK_PERIL1),
+	SAVE_ITEM(S5P_CLKDIV2_RATIO),
+	SAVE_ITEM(S5P_CLKGATE_SCLKCAM),
+	SAVE_ITEM(S5P_CLKGATE_IP_CAM),
+	SAVE_ITEM(S5P_CLKGATE_IP_TV),
+	SAVE_ITEM(S5P_CLKGATE_IP_MFC),
+	SAVE_ITEM(S5P_CLKGATE_IP_G3D),
+	SAVE_ITEM(S5P_CLKGATE_IP_LCD0),
+	SAVE_ITEM(S5P_CLKGATE_IP_FSYS),
+	SAVE_ITEM(S5P_CLKGATE_IP_GPS),
+	SAVE_ITEM(S5P_CLKGATE_IP_PERIL),
+	SAVE_ITEM(S5P_CLKGATE_BLOCK),
+	SAVE_ITEM(S5P_CLKSRC_MASK_DMC),
+	SAVE_ITEM(S5P_CLKSRC_DMC),
+	SAVE_ITEM(S5P_CLKDIV_DMC0),
+	SAVE_ITEM(S5P_CLKDIV_DMC1),
+	SAVE_ITEM(S5P_CLKGATE_IP_DMC),
+	SAVE_ITEM(S5P_CLKSRC_CPU),
+	SAVE_ITEM(S5P_CLKDIV_CPU),
+	SAVE_ITEM(S5P_CLKDIV_CPU + 0x4),
+	SAVE_ITEM(S5P_CLKGATE_SCLKCPU),
+	SAVE_ITEM(S5P_CLKGATE_IP_CPU),
+};
+
+struct clk clk_sclk_hdmi27m = {
 	.name		= "sclk_hdmi27m",
 	.rate		= 27000000,
 };
 
-static struct clk clk_sclk_hdmiphy = {
+struct clk clk_sclk_hdmiphy = {
 	.name		= "sclk_hdmiphy",
 };
 
-static struct clk clk_sclk_usbphy0 = {
+struct clk clk_sclk_usbphy0 = {
 	.name		= "sclk_usbphy0",
 	.rate		= 27000000,
 };
 
-static struct clk clk_sclk_usbphy1 = {
+struct clk clk_sclk_usbphy1 = {
 	.name		= "sclk_usbphy1",
 };
 
@@ -58,12 +126,7 @@ static int exynos4_clksrc_mask_lcd0_ctrl(struct clk *clk, int enable)
 	return s5p_gatectrl(S5P_CLKSRC_MASK_LCD0, clk, enable);
 }
 
-static int exynos4_clksrc_mask_lcd1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKSRC_MASK_LCD1, clk, enable);
-}
-
-static int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable)
+int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable)
 {
 	return s5p_gatectrl(S5P_CLKSRC_MASK_FSYS, clk, enable);
 }
@@ -103,12 +166,12 @@ static int exynos4_clk_ip_lcd0_ctrl(struct clk *clk, int enable)
 	return s5p_gatectrl(S5P_CLKGATE_IP_LCD0, clk, enable);
 }
 
-static int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable)
+int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable)
 {
 	return s5p_gatectrl(S5P_CLKGATE_IP_LCD1, clk, enable);
 }
 
-static int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable)
+int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable)
 {
 	return s5p_gatectrl(S5P_CLKGATE_IP_FSYS, clk, enable);
 }
@@ -133,7 +196,7 @@ static struct clksrc_clk clk_mout_apll = {
 	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 0, .size = 1 },
 };
 
-static struct clksrc_clk clk_sclk_apll = {
+struct clksrc_clk clk_sclk_apll = {
 	.clk	= {
 		.name		= "sclk_apll",
 		.parent		= &clk_mout_apll.clk,
@@ -141,7 +204,7 @@ static struct clksrc_clk clk_sclk_apll = {
 	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 24, .size = 3 },
 };
 
-static struct clksrc_clk clk_mout_epll = {
+struct clksrc_clk clk_mout_epll = {
 	.clk	= {
 		.name		= "mout_epll",
 	},
@@ -149,12 +212,13 @@ static struct clksrc_clk clk_mout_epll = {
 	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 4, .size = 1 },
 };
 
-static struct clksrc_clk clk_mout_mpll = {
+struct clksrc_clk clk_mout_mpll = {
 	.clk = {
 		.name		= "mout_mpll",
 	},
 	.sources	= &clk_src_mpll,
-	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 8, .size = 1 },
+
+	/* reg_src will be added in each SoCs' clock */
 };
 
 static struct clk *clkset_moutcore_list[] = {
@@ -224,12 +288,12 @@ static struct clksrc_clk clk_periphclk = {
 
 /* Core list of CMU_CORE side */
 
-static struct clk *clkset_corebus_list[] = {
+struct clk *clkset_corebus_list[] = {
 	[0] = &clk_mout_mpll.clk,
 	[1] = &clk_sclk_apll.clk,
 };
 
-static struct clksrc_sources clkset_mout_corebus = {
+struct clksrc_sources clkset_mout_corebus = {
 	.sources	= clkset_corebus_list,
 	.nr_sources	= ARRAY_SIZE(clkset_corebus_list),
 };
@@ -284,12 +348,12 @@ static struct clksrc_clk clk_pclk_acp = {
 
 /* Core list of CMU_TOP side */
 
-static struct clk *clkset_aclk_top_list[] = {
+struct clk *clkset_aclk_top_list[] = {
 	[0] = &clk_mout_mpll.clk,
 	[1] = &clk_sclk_apll.clk,
 };
 
-static struct clksrc_sources clkset_aclk = {
+struct clksrc_sources clkset_aclk = {
 	.sources	= clkset_aclk_top_list,
 	.nr_sources	= ARRAY_SIZE(clkset_aclk_top_list),
 };
@@ -321,7 +385,7 @@ static struct clksrc_clk clk_aclk_160 = {
 	.reg_div	= { .reg = S5P_CLKDIV_TOP, .shift = 8, .size = 3 },
 };
 
-static struct clksrc_clk clk_aclk_133 = {
+struct clksrc_clk clk_aclk_133 = {
 	.clk	= {
 		.name		= "aclk_133",
 	},
@@ -360,7 +424,7 @@ static struct clksrc_sources clkset_sclk_vpll = {
 	.nr_sources	= ARRAY_SIZE(clkset_sclk_vpll_list),
 };
 
-static struct clksrc_clk clk_sclk_vpll = {
+struct clksrc_clk clk_sclk_vpll = {
 	.clk	= {
 		.name		= "sclk_vpll",
 	},
@@ -410,16 +474,6 @@ static struct clk init_clocks_off[] = {
 		.enable		= exynos4_clk_ip_lcd0_ctrl,
 		.ctrlbit	= (1 << 0),
 	}, {
-		.name		= "fimd",
-		.devname	= "exynos4-fb.1",
-		.enable		= exynos4_clk_ip_lcd1_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "sataphy",
-		.parent		= &clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
 		.name		= "hsmmc",
 		.devname	= "s3c-sdhci.0",
 		.parent		= &clk_aclk_133.clk,
@@ -449,11 +503,6 @@ static struct clk init_clocks_off[] = {
 		.enable		= exynos4_clk_ip_fsys_ctrl,
 		.ctrlbit	= (1 << 9),
 	}, {
-		.name		= "sata",
-		.parent		= &clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 10),
-	}, {
 		.name		= "pdma",
 		.devname	= "s3c-pl330.0",
 		.enable		= exynos4_clk_ip_fsys_ctrl,
@@ -673,7 +722,7 @@ static struct clk init_clocks[] = {
 	}
 };
 
-static struct clk *clkset_group_list[] = {
+struct clk *clkset_group_list[] = {
 	[0] = &clk_ext_xtal_mux,
 	[1] = &clk_xusbxti,
 	[2] = &clk_sclk_hdmi27m,
@@ -685,7 +734,7 @@ static struct clk *clkset_group_list[] = {
 	[8] = &clk_sclk_vpll.clk,
 };
 
-static struct clksrc_sources clkset_group = {
+struct clksrc_sources clkset_group = {
 	.sources	= clkset_group_list,
 	.nr_sources	= ARRAY_SIZE(clkset_group_list),
 };
@@ -967,25 +1016,6 @@ static struct clksrc_clk clksrcs[] = {
 		.reg_div = { .reg = S5P_CLKDIV_LCD0, .shift = 0, .size = 4 },
 	}, {
 		.clk		= {
-			.name		= "sclk_fimd",
-			.devname	= "exynos4-fb.1",
-			.enable		= exynos4_clksrc_mask_lcd1_ctrl,
-			.ctrlbit	= (1 << 0),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_LCD1, .shift = 0, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_LCD1, .shift = 0, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_sata",
-			.enable		= exynos4_clksrc_mask_fsys_ctrl,
-			.ctrlbit	= (1 << 24),
-		},
-		.sources = &clkset_mout_corebus,
-		.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 24, .size = 1 },
-		.reg_div = { .reg = S5P_CLKDIV_FSYS0, .shift = 20, .size = 4 },
-	}, {
-		.clk		= {
 			.name		= "sclk_spi",
 			.devname	= "s3c64xx-spi.0",
 			.enable		= exynos4_clksrc_mask_peril1_ctrl,
@@ -1114,7 +1144,13 @@ static int xtal_rate;
 
 static unsigned long exynos4_fout_apll_get_rate(struct clk *clk)
 {
-	return s5p_get_pll45xx(xtal_rate, __raw_readl(S5P_APLL_CON0), pll_4508);
+	if (soc_is_exynos4210())
+		return s5p_get_pll45xx(xtal_rate, __raw_readl(S5P_APLL_CON0),
+					pll_4508);
+	else if (soc_is_exynos4212() || soc_is_exynos4412())
+		return s5p_get_pll35xx(xtal_rate, __raw_readl(S5P_APLL_CON0));
+	else
+		return 0;
 }
 
 static struct clk_ops exynos4_fout_apll_ops = {
@@ -1124,10 +1160,10 @@ static struct clk_ops exynos4_fout_apll_ops = {
 void __init_or_cpufreq exynos4_setup_clocks(void)
 {
 	struct clk *xtal_clk;
-	unsigned long apll;
-	unsigned long mpll;
-	unsigned long epll;
-	unsigned long vpll;
+	unsigned long apll = 0;
+	unsigned long mpll = 0;
+	unsigned long epll = 0;
+	unsigned long vpll = 0;
 	unsigned long vpllsrc;
 	unsigned long xtal;
 	unsigned long armclk;
@@ -1151,14 +1187,29 @@ void __init_or_cpufreq exynos4_setup_clocks(void)
 
 	printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
 
-	apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON0), pll_4508);
-	mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON0), pll_4508);
-	epll = s5p_get_pll46xx(xtal, __raw_readl(S5P_EPLL_CON0),
-				__raw_readl(S5P_EPLL_CON1), pll_4600);
-
-	vpllsrc = clk_get_rate(&clk_vpllsrc.clk);
-	vpll = s5p_get_pll46xx(vpllsrc, __raw_readl(S5P_VPLL_CON0),
-				__raw_readl(S5P_VPLL_CON1), pll_4650c);
+	if (soc_is_exynos4210()) {
+		apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON0),
+					pll_4508);
+		mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON0),
+					pll_4508);
+		epll = s5p_get_pll46xx(xtal, __raw_readl(S5P_EPLL_CON0),
+					__raw_readl(S5P_EPLL_CON1), pll_4600);
+
+		vpllsrc = clk_get_rate(&clk_vpllsrc.clk);
+		vpll = s5p_get_pll46xx(vpllsrc, __raw_readl(S5P_VPLL_CON0),
+					__raw_readl(S5P_VPLL_CON1), pll_4650c);
+	} else if (soc_is_exynos4212() || soc_is_exynos4412()) {
+		apll = s5p_get_pll35xx(xtal, __raw_readl(S5P_APLL_CON0));
+		mpll = s5p_get_pll35xx(xtal, __raw_readl(S5P_MPLL_CON0));
+		epll = s5p_get_pll36xx(xtal, __raw_readl(S5P_EPLL_CON0),
+					__raw_readl(S5P_EPLL_CON1));
+
+		vpllsrc = clk_get_rate(&clk_vpllsrc.clk);
+		vpll = s5p_get_pll36xx(vpllsrc, __raw_readl(S5P_VPLL_CON0),
+					__raw_readl(S5P_VPLL_CON1));
+	} else {
+		/* nothing */
+	}
 
 	clk_fout_apll.ops = &exynos4_fout_apll_ops;
 	clk_fout_mpll.rate = mpll;
@@ -1193,6 +1244,28 @@ static struct clk *clks[] __initdata = {
 	/* Nothing here yet */
 };
 
+#ifdef CONFIG_PM_SLEEP
+static int exynos4_clock_suspend(void)
+{
+	s3c_pm_do_save(exynos4_clock_save, ARRAY_SIZE(exynos4_clock_save));
+	return 0;
+}
+
+static void exynos4_clock_resume(void)
+{
+	s3c_pm_do_restore_core(exynos4_clock_save, ARRAY_SIZE(exynos4_clock_save));
+}
+
+#else
+#define exynos4_clock_suspend NULL
+#define exynos4_clock_resume NULL
+#endif
+
+struct syscore_ops exynos4_clock_syscore_ops = {
+	.suspend	= exynos4_clock_suspend,
+	.resume		= exynos4_clock_resume,
+};
+
 void __init exynos4_register_clocks(void)
 {
 	int ptr;
@@ -1208,5 +1281,6 @@ void __init exynos4_register_clocks(void)
 	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
+	register_syscore_ops(&exynos4_clock_syscore_ops);
 	s3c_pwmclk_init();
 }
diff --git a/arch/arm/mach-exynos4/cpu.c b/arch/arm/mach-exynos4/cpu.c
index 746d6fc..a348434 100644
--- a/arch/arm/mach-exynos4/cpu.c
+++ b/arch/arm/mach-exynos4/cpu.c
@@ -32,6 +32,8 @@
 #include <mach/regs-irq.h>
 #include <mach/regs-pmu.h>
 
+unsigned int gic_bank_offset __read_mostly;
+
 extern int combiner_init(unsigned int combiner_nr, void __iomem *base,
 			 unsigned int irq_start);
 extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq);
@@ -44,11 +46,6 @@ static struct map_desc exynos4_iodesc[] __initdata = {
 		.length		= SZ_4K,
 		.type	 	= MT_DEVICE,
 	}, {
-		.virtual	= (unsigned long)S5P_VA_SYSRAM,
-		.pfn		= __phys_to_pfn(EXYNOS4_PA_SYSRAM),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
 		.virtual	= (unsigned long)S5P_VA_CMU,
 		.pfn		= __phys_to_pfn(EXYNOS4_PA_CMU),
 		.length		= SZ_128K,
@@ -121,6 +118,24 @@ static struct map_desc exynos4_iodesc[] __initdata = {
 	},
 };
 
+static struct map_desc exynos4_iodesc0[] __initdata = {
+	{
+		.virtual	= (unsigned long)S5P_VA_SYSRAM,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_SYSRAM0),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+};
+
+static struct map_desc exynos4_iodesc1[] __initdata = {
+	{
+		.virtual	= (unsigned long)S5P_VA_SYSRAM,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_SYSRAM1),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+};
+
 static void exynos4_idle(void)
 {
 	if (!need_resched())
@@ -143,6 +158,11 @@ void __init exynos4_map_io(void)
 {
 	iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
 
+	if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_0)
+		iotable_init(exynos4_iodesc0, ARRAY_SIZE(exynos4_iodesc0));
+	else
+		iotable_init(exynos4_iodesc1, ARRAY_SIZE(exynos4_iodesc1));
+
 	/* initialize device information early */
 	exynos4_default_sdhci0();
 	exynos4_default_sdhci1();
@@ -170,24 +190,37 @@ void __init exynos4_init_clocks(int xtal)
 
 	s3c24xx_register_baseclocks(xtal);
 	s5p_register_clocks(xtal);
+
+	if (soc_is_exynos4210())
+		exynos4210_register_clocks();
+	else if (soc_is_exynos4212() || soc_is_exynos4412())
+		exynos4212_register_clocks();
+
 	exynos4_register_clocks();
 	exynos4_setup_clocks();
 }
 
-static void exynos4_gic_irq_eoi(struct irq_data *d)
+static void exynos4_gic_irq_fix_base(struct irq_data *d)
 {
 	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
 
 	gic_data->cpu_base = S5P_VA_GIC_CPU +
-			    (EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());
+			    (gic_bank_offset * smp_processor_id());
+
+	gic_data->dist_base = S5P_VA_GIC_DIST +
+			    (gic_bank_offset * smp_processor_id());
 }
 
 void __init exynos4_init_irq(void)
 {
 	int irq;
 
-	gic_init(0, IRQ_SPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
-	gic_arch_extn.irq_eoi = exynos4_gic_irq_eoi;
+	gic_bank_offset = soc_is_exynos4412() ? 0x4000 : 0x8000;
+
+	gic_init(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+	gic_arch_extn.irq_eoi = exynos4_gic_irq_fix_base;
+	gic_arch_extn.irq_unmask = exynos4_gic_irq_fix_base;
+	gic_arch_extn.irq_mask = exynos4_gic_irq_fix_base;
 
 	for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
 
@@ -223,7 +256,11 @@ static int __init exynos4_l2x0_cache_init(void)
 {
 	/* TAG, Data Latency Control: 2cycle */
 	__raw_writel(0x110, S5P_VA_L2CC + L2X0_TAG_LATENCY_CTRL);
-	__raw_writel(0x110, S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL);
+
+	if (soc_is_exynos4210())
+		__raw_writel(0x110, S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL);
+	else if (soc_is_exynos4212() || soc_is_exynos4412())
+		__raw_writel(0x120, S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL);
 
 	/* L2X0 Prefetch Control */
 	__raw_writel(0x30000007, S5P_VA_L2CC + L2X0_PREFETCH_CTRL);
diff --git a/arch/arm/mach-exynos4/hotplug.c b/arch/arm/mach-exynos4/hotplug.c
index 7490789..da70e7e 100644
--- a/arch/arm/mach-exynos4/hotplug.c
+++ b/arch/arm/mach-exynos4/hotplug.c
@@ -75,7 +75,7 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
 		    :
 		    : "memory", "cc");
 
-		if (pen_release == cpu) {
+		if (pen_release == cpu_logical_map(cpu)) {
 			/*
 			 * OK, proper wakeup, we're done
 			 */
diff --git a/arch/arm/mach-exynos4/include/mach/entry-macro.S b/arch/arm/mach-exynos4/include/mach/entry-macro.S
index 006a4f4..f5e9fd8 100644
--- a/arch/arm/mach-exynos4/include/mach/entry-macro.S
+++ b/arch/arm/mach-exynos4/include/mach/entry-macro.S
@@ -17,12 +17,25 @@
 		.endm
 
 		.macro  get_irqnr_preamble, base, tmp
-		ldr	\base, =gic_cpu_base_addr
+		mov	\tmp, #0
+
+		mrc	p15, 0, \base, c0, c0, 5
+		and	\base, \base, #3
+		cmp	\base, #0
+		beq	1f
+
+		ldr	\tmp, =gic_bank_offset
+		ldr	\tmp, [\tmp]
+		cmp	\base, #1
+		beq	1f
+
+		cmp	\base, #2
+		addeq	\tmp, \tmp, \tmp
+		addne	\tmp, \tmp, \tmp, LSL #1
+
+1:		ldr	\base, =gic_cpu_base_addr
 		ldr	\base, [\base]
-		mrc     p15, 0, \tmp, c0, c0, 5
-		and     \tmp, \tmp, #3
-		cmp     \tmp, #1
-		addeq   \base, \base, #EXYNOS4_GIC_BANK_OFFSET
+		add	\base, \base, \tmp
 		.endm
 
 		.macro  arch_ret_to_user, tmp1, tmp2
diff --git a/arch/arm/mach-exynos4/include/mach/exynos4-clock.h b/arch/arm/mach-exynos4/include/mach/exynos4-clock.h
new file mode 100644
index 0000000..a07fcbf
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/exynos4-clock.h
@@ -0,0 +1,43 @@
+/*
+ * linux/arch/arm/mach-exynos4/include/mach/exynos4-clock.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Header file for exynos4 clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_CLOCK_H
+#define __ASM_ARCH_CLOCK_H __FILE__
+
+#include <linux/clk.h>
+
+extern struct clk clk_sclk_hdmi27m;
+extern struct clk clk_sclk_usbphy0;
+extern struct clk clk_sclk_usbphy1;
+extern struct clk clk_sclk_hdmiphy;
+
+extern struct clksrc_clk clk_sclk_apll;
+extern struct clksrc_clk clk_mout_mpll;
+extern struct clksrc_clk clk_aclk_133;
+extern struct clksrc_clk clk_mout_epll;
+extern struct clksrc_clk clk_sclk_vpll;
+
+extern struct clk *clkset_corebus_list[];
+extern struct clksrc_sources clkset_mout_corebus;
+
+extern struct clk *clkset_aclk_top_list[];
+extern struct clksrc_sources clkset_aclk;
+
+extern struct clk *clkset_group_list[];
+extern struct clksrc_sources clkset_group;
+
+extern int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable);
+extern int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable);
+extern int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable);
+
+#endif /* __ASM_ARCH_CLOCK_H */
diff --git a/arch/arm/mach-exynos4/include/mach/irqs.h b/arch/arm/mach-exynos4/include/mach/irqs.h
index f8952f8..2d3f6bc 100644
--- a/arch/arm/mach-exynos4/include/mach/irqs.h
+++ b/arch/arm/mach-exynos4/include/mach/irqs.h
@@ -19,6 +19,8 @@
 
 #define IRQ_PPI(x)		S5P_IRQ(x+16)
 
+#define IRQ_MCT_LOCALTIMER	IRQ_PPI(12)
+
 /* SPI: Shared Peripheral Interrupt */
 
 #define IRQ_SPI(x)		S5P_IRQ(x+32)
diff --git a/arch/arm/mach-exynos4/include/mach/map.h b/arch/arm/mach-exynos4/include/mach/map.h
index d32296d..9f97eb8 100644
--- a/arch/arm/mach-exynos4/include/mach/map.h
+++ b/arch/arm/mach-exynos4/include/mach/map.h
@@ -23,7 +23,8 @@
 
 #include <plat/map-s5p.h>
 
-#define EXYNOS4_PA_SYSRAM		0x02020000
+#define EXYNOS4_PA_SYSRAM0		0x02025000
+#define EXYNOS4_PA_SYSRAM1		0x02020000
 
 #define EXYNOS4_PA_FIMC0		0x11800000
 #define EXYNOS4_PA_FIMC1		0x11810000
@@ -61,7 +62,6 @@
 
 #define EXYNOS4_PA_GIC_CPU		0x10480000
 #define EXYNOS4_PA_GIC_DIST		0x10490000
-#define EXYNOS4_GIC_BANK_OFFSET		0x8000
 
 #define EXYNOS4_PA_COREPERI		0x10500000
 #define EXYNOS4_PA_TWD			0x10500600
diff --git a/arch/arm/mach-exynos4/include/mach/regs-clock.h b/arch/arm/mach-exynos4/include/mach/regs-clock.h
index d493fdb..6c37ebe 100644
--- a/arch/arm/mach-exynos4/include/mach/regs-clock.h
+++ b/arch/arm/mach-exynos4/include/mach/regs-clock.h
@@ -13,6 +13,7 @@
 #ifndef __ASM_ARCH_REGS_CLOCK_H
 #define __ASM_ARCH_REGS_CLOCK_H __FILE__
 
+#include <plat/cpu.h>
 #include <mach/map.h>
 
 #define S5P_CLKREG(x)			(S5P_VA_CMU + (x))
@@ -41,12 +42,20 @@
 #define S5P_CLKSRC_G3D			S5P_CLKREG(0x0C22C)
 #define S5P_CLKSRC_IMAGE		S5P_CLKREG(0x0C230)
 #define S5P_CLKSRC_LCD0			S5P_CLKREG(0x0C234)
-#define S5P_CLKSRC_LCD1			S5P_CLKREG(0x0C238)
 #define S5P_CLKSRC_MAUDIO		S5P_CLKREG(0x0C23C)
 #define S5P_CLKSRC_FSYS			S5P_CLKREG(0x0C240)
 #define S5P_CLKSRC_PERIL0		S5P_CLKREG(0x0C250)
 #define S5P_CLKSRC_PERIL1		S5P_CLKREG(0x0C254)
 
+#define S5P_CLKSRC_MASK_TOP		S5P_CLKREG(0x0C310)
+#define S5P_CLKSRC_MASK_CAM		S5P_CLKREG(0x0C320)
+#define S5P_CLKSRC_MASK_TV		S5P_CLKREG(0x0C324)
+#define S5P_CLKSRC_MASK_LCD0		S5P_CLKREG(0x0C334)
+#define S5P_CLKSRC_MASK_MAUDIO		S5P_CLKREG(0x0C33C)
+#define S5P_CLKSRC_MASK_FSYS		S5P_CLKREG(0x0C340)
+#define S5P_CLKSRC_MASK_PERIL0		S5P_CLKREG(0x0C350)
+#define S5P_CLKSRC_MASK_PERIL1		S5P_CLKREG(0x0C354)
+
 #define S5P_CLKDIV_TOP			S5P_CLKREG(0x0C510)
 #define S5P_CLKDIV_CAM			S5P_CLKREG(0x0C520)
 #define S5P_CLKDIV_TV			S5P_CLKREG(0x0C524)
@@ -54,7 +63,6 @@
 #define S5P_CLKDIV_G3D			S5P_CLKREG(0x0C52C)
 #define S5P_CLKDIV_IMAGE		S5P_CLKREG(0x0C530)
 #define S5P_CLKDIV_LCD0			S5P_CLKREG(0x0C534)
-#define S5P_CLKDIV_LCD1			S5P_CLKREG(0x0C538)
 #define S5P_CLKDIV_MAUDIO		S5P_CLKREG(0x0C53C)
 #define S5P_CLKDIV_FSYS0		S5P_CLKREG(0x0C540)
 #define S5P_CLKDIV_FSYS1		S5P_CLKREG(0x0C544)
@@ -68,16 +76,6 @@
 #define S5P_CLKDIV_PERIL5		S5P_CLKREG(0x0C564)
 #define S5P_CLKDIV2_RATIO		S5P_CLKREG(0x0C580)
 
-#define S5P_CLKSRC_MASK_TOP		S5P_CLKREG(0x0C310)
-#define S5P_CLKSRC_MASK_CAM		S5P_CLKREG(0x0C320)
-#define S5P_CLKSRC_MASK_TV		S5P_CLKREG(0x0C324)
-#define S5P_CLKSRC_MASK_LCD0		S5P_CLKREG(0x0C334)
-#define S5P_CLKSRC_MASK_LCD1		S5P_CLKREG(0x0C338)
-#define S5P_CLKSRC_MASK_MAUDIO		S5P_CLKREG(0x0C33C)
-#define S5P_CLKSRC_MASK_FSYS		S5P_CLKREG(0x0C340)
-#define S5P_CLKSRC_MASK_PERIL0		S5P_CLKREG(0x0C350)
-#define S5P_CLKSRC_MASK_PERIL1		S5P_CLKREG(0x0C354)
-
 #define S5P_CLKDIV_STAT_TOP		S5P_CLKREG(0x0C610)
 
 #define S5P_CLKGATE_SCLKCAM		S5P_CLKREG(0x0C820)
@@ -85,13 +83,20 @@
 #define S5P_CLKGATE_IP_TV		S5P_CLKREG(0x0C924)
 #define S5P_CLKGATE_IP_MFC		S5P_CLKREG(0x0C928)
 #define S5P_CLKGATE_IP_G3D		S5P_CLKREG(0x0C92C)
-#define S5P_CLKGATE_IP_IMAGE		S5P_CLKREG(0x0C930)
+#define S5P_CLKGATE_IP_IMAGE		(soc_is_exynos4210() ? \
+					S5P_CLKREG(0x0C930) : \
+					S5P_CLKREG(0x04930))
+#define S5P_CLKGATE_IP_IMAGE_4210	S5P_CLKREG(0x0C930)
+#define S5P_CLKGATE_IP_IMAGE_4212	S5P_CLKREG(0x04930)
 #define S5P_CLKGATE_IP_LCD0		S5P_CLKREG(0x0C934)
-#define S5P_CLKGATE_IP_LCD1		S5P_CLKREG(0x0C938)
 #define S5P_CLKGATE_IP_FSYS		S5P_CLKREG(0x0C940)
 #define S5P_CLKGATE_IP_GPS		S5P_CLKREG(0x0C94C)
 #define S5P_CLKGATE_IP_PERIL		S5P_CLKREG(0x0C950)
-#define S5P_CLKGATE_IP_PERIR		S5P_CLKREG(0x0C960)
+#define S5P_CLKGATE_IP_PERIR		(soc_is_exynos4210() ? \
+					S5P_CLKREG(0x0C960) : \
+					S5P_CLKREG(0x08960))
+#define S5P_CLKGATE_IP_PERIR_4210	S5P_CLKREG(0x0C960)
+#define S5P_CLKGATE_IP_PERIR_4212	S5P_CLKREG(0x08960)
 #define S5P_CLKGATE_BLOCK		S5P_CLKREG(0x0C970)
 
 #define S5P_CLKSRC_MASK_DMC		S5P_CLKREG(0x10300)
@@ -102,11 +107,17 @@
 #define S5P_CLKGATE_IP_DMC		S5P_CLKREG(0x10900)
 
 #define S5P_APLL_LOCK			S5P_CLKREG(0x14000)
-#define S5P_MPLL_LOCK			S5P_CLKREG(0x14004)
+#define S5P_MPLL_LOCK			(soc_is_exynos4210() ? \
+					S5P_CLKREG(0x14004) :  \
+					S5P_CLKREG(0x10008))
 #define S5P_APLL_CON0			S5P_CLKREG(0x14100)
 #define S5P_APLL_CON1			S5P_CLKREG(0x14104)
-#define S5P_MPLL_CON0			S5P_CLKREG(0x14108)
-#define S5P_MPLL_CON1			S5P_CLKREG(0x1410C)
+#define S5P_MPLL_CON0			(soc_is_exynos4210() ? \
+					S5P_CLKREG(0x14108) : \
+					S5P_CLKREG(0x10108))
+#define S5P_MPLL_CON1			(soc_is_exynos4210() ? \
+					S5P_CLKREG(0x1410C) : \
+					S5P_CLKREG(0x1010C))
 
 #define S5P_CLKSRC_CPU			S5P_CLKREG(0x14200)
 #define S5P_CLKMUX_STATCPU		S5P_CLKREG(0x14400)
@@ -183,6 +194,13 @@
 #define S5P_CLKDIV_BUS_GPLR_SHIFT	(4)
 #define S5P_CLKDIV_BUS_GPLR_MASK	(0x7 << S5P_CLKDIV_BUS_GPLR_SHIFT)
 
+/* Only for EXYNOS4210 */
+
+#define S5P_CLKSRC_LCD1			S5P_CLKREG(0x0C238)
+#define S5P_CLKSRC_MASK_LCD1		S5P_CLKREG(0x0C338)
+#define S5P_CLKDIV_LCD1			S5P_CLKREG(0x0C538)
+#define S5P_CLKGATE_IP_LCD1		S5P_CLKREG(0x0C938)
+
 /* Compatibility defines and inclusion */
 
 #include <mach/regs-pmu.h>
diff --git a/arch/arm/mach-exynos4/include/mach/regs-mct.h b/arch/arm/mach-exynos4/include/mach/regs-mct.h
index ca9c843..80dd02a 100644
--- a/arch/arm/mach-exynos4/include/mach/regs-mct.h
+++ b/arch/arm/mach-exynos4/include/mach/regs-mct.h
@@ -31,8 +31,9 @@
 #define EXYNOS4_MCT_G_INT_ENB		EXYNOS4_MCTREG(0x248)
 #define EXYNOS4_MCT_G_WSTAT		EXYNOS4_MCTREG(0x24C)
 
-#define EXYNOS4_MCT_L0_BASE		EXYNOS4_MCTREG(0x300)
-#define EXYNOS4_MCT_L1_BASE		EXYNOS4_MCTREG(0x400)
+#define _EXYNOS4_MCT_L_BASE		EXYNOS4_MCTREG(0x300)
+#define EXYNOS4_MCT_L_BASE(x)		(_EXYNOS4_MCT_L_BASE + (0x100 * x))
+#define EXYNOS4_MCT_L_MASK		(0xffffff00)
 
 #define MCT_L_TCNTB_OFFSET		(0x00)
 #define MCT_L_ICNTB_OFFSET		(0x08)
diff --git a/arch/arm/mach-exynos4/mach-origen.c b/arch/arm/mach-exynos4/mach-origen.c
new file mode 100644
index 0000000..b5f6f38
--- /dev/null
+++ b/arch/arm/mach-exynos4/mach-origen.c
@@ -0,0 +1,108 @@
+/* linux/arch/arm/mach-exynos4/mach-origen.c
+ *
+ * Copyright (c) 2011 Insignal Co., Ltd.
+ *		http://www.insignal.co.kr/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/serial_core.h>
+#include <linux/gpio.h>
+#include <linux/mmc/host.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/input.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <plat/regs-serial.h>
+#include <plat/exynos4.h>
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/sdhci.h>
+#include <plat/iic.h>
+
+#include <mach/map.h>
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define ORIGEN_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
+				 S3C2410_UCON_RXILEVEL |	\
+				 S3C2410_UCON_TXIRQMODE |	\
+				 S3C2410_UCON_RXIRQMODE |	\
+				 S3C2410_UCON_RXFIFO_TOI |	\
+				 S3C2443_UCON_RXERR_IRQEN)
+
+#define ORIGEN_ULCON_DEFAULT	S3C2410_LCON_CS8
+
+#define ORIGEN_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
+				 S5PV210_UFCON_TXTRIG4 |	\
+				 S5PV210_UFCON_RXTRIG4)
+
+static struct s3c2410_uartcfg origen_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport		= 0,
+		.flags		= 0,
+		.ucon		= ORIGEN_UCON_DEFAULT,
+		.ulcon		= ORIGEN_ULCON_DEFAULT,
+		.ufcon		= ORIGEN_UFCON_DEFAULT,
+	},
+	[1] = {
+		.hwport		= 1,
+		.flags		= 0,
+		.ucon		= ORIGEN_UCON_DEFAULT,
+		.ulcon		= ORIGEN_ULCON_DEFAULT,
+		.ufcon		= ORIGEN_UFCON_DEFAULT,
+	},
+	[2] = {
+		.hwport		= 2,
+		.flags		= 0,
+		.ucon		= ORIGEN_UCON_DEFAULT,
+		.ulcon		= ORIGEN_ULCON_DEFAULT,
+		.ufcon		= ORIGEN_UFCON_DEFAULT,
+	},
+	[3] = {
+		.hwport		= 3,
+		.flags		= 0,
+		.ucon		= ORIGEN_UCON_DEFAULT,
+		.ulcon		= ORIGEN_ULCON_DEFAULT,
+		.ufcon		= ORIGEN_UFCON_DEFAULT,
+	},
+};
+
+static struct s3c_sdhci_platdata origen_hsmmc2_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_GPIO,
+	.ext_cd_gpio		= EXYNOS4_GPK2(2),
+	.ext_cd_gpio_invert	= 1,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+static struct platform_device *origen_devices[] __initdata = {
+	&s3c_device_hsmmc2,
+	&s3c_device_rtc,
+	&s3c_device_wdt,
+};
+
+static void __init origen_map_io(void)
+{
+	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+	s3c24xx_init_clocks(24000000);
+	s3c24xx_init_uarts(origen_uartcfgs, ARRAY_SIZE(origen_uartcfgs));
+}
+
+static void __init origen_machine_init(void)
+{
+	s3c_sdhci2_set_platdata(&origen_hsmmc2_pdata);
+	platform_add_devices(origen_devices, ARRAY_SIZE(origen_devices));
+}
+
+MACHINE_START(ORIGEN, "ORIGEN")
+	/* Maintainer: JeongHyeon Kim <jhkim@insignal.co.kr> */
+	.atag_offset	= 0x100,
+	.init_irq	= exynos4_init_irq,
+	.map_io		= origen_map_io,
+	.init_machine	= origen_machine_init,
+	.timer		= &exynos4_timer,
+MACHINE_END
diff --git a/arch/arm/mach-exynos4/mach-smdk4x12.c b/arch/arm/mach-exynos4/mach-smdk4x12.c
new file mode 100644
index 0000000..fcf2e0e
--- /dev/null
+++ b/arch/arm/mach-exynos4/mach-smdk4x12.c
@@ -0,0 +1,302 @@
+/*
+ * linux/arch/arm/mach-exynos4/mach-smdk4x12.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/io.h>
+#include <linux/mfd/max8997.h>
+#include <linux/mmc/host.h>
+#include <linux/platform_device.h>
+#include <linux/pwm_backlight.h>
+#include <linux/regulator/machine.h>
+#include <linux/serial_core.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <plat/backlight.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/exynos4.h>
+#include <plat/gpio-cfg.h>
+#include <plat/iic.h>
+#include <plat/keypad.h>
+#include <plat/regs-serial.h>
+#include <plat/sdhci.h>
+
+#include <mach/map.h>
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define SMDK4X12_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
+				 S3C2410_UCON_RXILEVEL |	\
+				 S3C2410_UCON_TXIRQMODE |	\
+				 S3C2410_UCON_RXIRQMODE |	\
+				 S3C2410_UCON_RXFIFO_TOI |	\
+				 S3C2443_UCON_RXERR_IRQEN)
+
+#define SMDK4X12_ULCON_DEFAULT	S3C2410_LCON_CS8
+
+#define SMDK4X12_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
+				 S5PV210_UFCON_TXTRIG4 |	\
+				 S5PV210_UFCON_RXTRIG4)
+
+static struct s3c2410_uartcfg smdk4x12_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport		= 0,
+		.flags		= 0,
+		.ucon		= SMDK4X12_UCON_DEFAULT,
+		.ulcon		= SMDK4X12_ULCON_DEFAULT,
+		.ufcon		= SMDK4X12_UFCON_DEFAULT,
+	},
+	[1] = {
+		.hwport		= 1,
+		.flags		= 0,
+		.ucon		= SMDK4X12_UCON_DEFAULT,
+		.ulcon		= SMDK4X12_ULCON_DEFAULT,
+		.ufcon		= SMDK4X12_UFCON_DEFAULT,
+	},
+	[2] = {
+		.hwport		= 2,
+		.flags		= 0,
+		.ucon		= SMDK4X12_UCON_DEFAULT,
+		.ulcon		= SMDK4X12_ULCON_DEFAULT,
+		.ufcon		= SMDK4X12_UFCON_DEFAULT,
+	},
+	[3] = {
+		.hwport		= 3,
+		.flags		= 0,
+		.ucon		= SMDK4X12_UCON_DEFAULT,
+		.ulcon		= SMDK4X12_ULCON_DEFAULT,
+		.ufcon		= SMDK4X12_UFCON_DEFAULT,
+	},
+};
+
+static struct s3c_sdhci_platdata smdk4x12_hsmmc2_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_INTERNAL,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+#ifdef CONFIG_EXYNOS4_SDHCI_CH2_8BIT
+	.max_width		= 8,
+	.host_caps		= MMC_CAP_8_BIT_DATA,
+#endif
+};
+
+static struct s3c_sdhci_platdata smdk4x12_hsmmc3_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_INTERNAL,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+static struct regulator_consumer_supply max8997_buck1 =
+	REGULATOR_SUPPLY("vdd_arm", NULL);
+
+static struct regulator_consumer_supply max8997_buck2 =
+	REGULATOR_SUPPLY("vdd_int", NULL);
+
+static struct regulator_consumer_supply max8997_buck3 =
+	REGULATOR_SUPPLY("vdd_g3d", NULL);
+
+static struct regulator_init_data max8997_buck1_data = {
+	.constraints	= {
+		.name		= "VDD_ARM_SMDK4X12",
+		.min_uV		= 925000,
+		.max_uV		= 1350000,
+		.always_on	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &max8997_buck1,
+};
+
+static struct regulator_init_data max8997_buck2_data = {
+	.constraints	= {
+		.name		= "VDD_INT_SMDK4X12",
+		.min_uV		= 950000,
+		.max_uV		= 1150000,
+		.always_on	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &max8997_buck2,
+};
+
+static struct regulator_init_data max8997_buck3_data = {
+	.constraints	= {
+		.name		= "VDD_G3D_SMDK4X12",
+		.min_uV		= 950000,
+		.max_uV		= 1150000,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
+				  REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &max8997_buck3,
+};
+
+static struct max8997_regulator_data smdk4x12_max8997_regulators[] = {
+	{ MAX8997_BUCK1, &max8997_buck1_data },
+	{ MAX8997_BUCK2, &max8997_buck2_data },
+	{ MAX8997_BUCK3, &max8997_buck3_data },
+};
+
+static struct max8997_platform_data smdk4x12_max8997_pdata = {
+	.num_regulators	= ARRAY_SIZE(smdk4x12_max8997_regulators),
+	.regulators	= smdk4x12_max8997_regulators,
+
+	.buck1_voltage[0] = 1100000,	/* 1.1V */
+	.buck1_voltage[1] = 1100000,	/* 1.1V */
+	.buck1_voltage[2] = 1100000,	/* 1.1V */
+	.buck1_voltage[3] = 1100000,	/* 1.1V */
+	.buck1_voltage[4] = 1100000,	/* 1.1V */
+	.buck1_voltage[5] = 1100000,	/* 1.1V */
+	.buck1_voltage[6] = 1000000,	/* 1.0V */
+	.buck1_voltage[7] = 950000,	/* 0.95V */
+
+	.buck2_voltage[0] = 1100000,	/* 1.1V */
+	.buck2_voltage[1] = 1000000,	/* 1.0V */
+	.buck2_voltage[2] = 950000,	/* 0.95V */
+	.buck2_voltage[3] = 900000,	/* 0.9V */
+	.buck2_voltage[4] = 1100000,	/* 1.1V */
+	.buck2_voltage[5] = 1000000,	/* 1.0V */
+	.buck2_voltage[6] = 950000,	/* 0.95V */
+	.buck2_voltage[7] = 900000,	/* 0.9V */
+
+	.buck5_voltage[0] = 1100000,	/* 1.1V */
+	.buck5_voltage[1] = 1100000,	/* 1.1V */
+	.buck5_voltage[2] = 1100000,	/* 1.1V */
+	.buck5_voltage[3] = 1100000,	/* 1.1V */
+	.buck5_voltage[4] = 1100000,	/* 1.1V */
+	.buck5_voltage[5] = 1100000,	/* 1.1V */
+	.buck5_voltage[6] = 1100000,	/* 1.1V */
+	.buck5_voltage[7] = 1100000,	/* 1.1V */
+};
+
+static struct i2c_board_info smdk4x12_i2c_devs0[] __initdata = {
+	{
+		I2C_BOARD_INFO("max8997", 0x66),
+		.platform_data	= &smdk4x12_max8997_pdata,
+	}
+};
+
+static struct i2c_board_info smdk4x12_i2c_devs1[] __initdata = {
+	{ I2C_BOARD_INFO("wm8994", 0x1a), }
+};
+
+static struct i2c_board_info smdk4x12_i2c_devs3[] __initdata = {
+	/* nothing here yet */
+};
+
+static struct i2c_board_info smdk4x12_i2c_devs7[] __initdata = {
+	/* nothing here yet */
+};
+
+static struct samsung_bl_gpio_info smdk4x12_bl_gpio_info = {
+	.no = EXYNOS4_GPD0(1),
+	.func = S3C_GPIO_SFN(2),
+};
+
+static struct platform_pwm_backlight_data smdk4x12_bl_data = {
+	.pwm_id = 1,
+	.pwm_period_ns  = 1000,
+};
+
+static uint32_t smdk4x12_keymap[] __initdata = {
+	/* KEY(row, col, keycode) */
+	KEY(1, 0, KEY_D), KEY(1, 1, KEY_A), KEY(1, 2, KEY_B),
+	KEY(1, 3, KEY_E), KEY(1, 4, KEY_C)
+};
+
+static struct matrix_keymap_data smdk4x12_keymap_data __initdata = {
+	.keymap		= smdk4x12_keymap,
+	.keymap_size	= ARRAY_SIZE(smdk4x12_keymap),
+};
+
+static struct samsung_keypad_platdata smdk4x12_keypad_data __initdata = {
+	.keymap_data	= &smdk4x12_keymap_data,
+	.rows		= 2,
+	.cols		= 5,
+};
+
+static struct platform_device *smdk4x12_devices[] __initdata = {
+	&s3c_device_hsmmc2,
+	&s3c_device_hsmmc3,
+	&s3c_device_i2c0,
+	&s3c_device_i2c1,
+	&s3c_device_i2c3,
+	&s3c_device_i2c7,
+	&s3c_device_rtc,
+	&s3c_device_wdt,
+	&samsung_device_keypad,
+};
+
+static void __init smdk4x12_map_io(void)
+{
+	clk_xusbxti.rate = 24000000;
+
+	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+	s3c24xx_init_clocks(clk_xusbxti.rate);
+	s3c24xx_init_uarts(smdk4x12_uartcfgs, ARRAY_SIZE(smdk4x12_uartcfgs));
+}
+
+static void __init smdk4x12_machine_init(void)
+{
+	s3c_i2c0_set_platdata(NULL);
+	i2c_register_board_info(0, smdk4x12_i2c_devs0,
+				ARRAY_SIZE(smdk4x12_i2c_devs0));
+
+	s3c_i2c1_set_platdata(NULL);
+	i2c_register_board_info(1, smdk4x12_i2c_devs1,
+				ARRAY_SIZE(smdk4x12_i2c_devs1));
+
+	s3c_i2c3_set_platdata(NULL);
+	i2c_register_board_info(3, smdk4x12_i2c_devs3,
+				ARRAY_SIZE(smdk4x12_i2c_devs3));
+
+	s3c_i2c7_set_platdata(NULL);
+	i2c_register_board_info(7, smdk4x12_i2c_devs7,
+				ARRAY_SIZE(smdk4x12_i2c_devs7));
+
+	samsung_bl_set(&smdk4x12_bl_gpio_info, &smdk4x12_bl_data);
+
+	samsung_keypad_set_platdata(&smdk4x12_keypad_data);
+
+	s3c_sdhci2_set_platdata(&smdk4x12_hsmmc2_pdata);
+	s3c_sdhci3_set_platdata(&smdk4x12_hsmmc3_pdata);
+
+	platform_add_devices(smdk4x12_devices, ARRAY_SIZE(smdk4x12_devices));
+}
+
+MACHINE_START(SMDK4212, "SMDK4212")
+	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
+	.atag_offset	= 0x100,
+	.init_irq	= exynos4_init_irq,
+	.map_io		= smdk4x12_map_io,
+	.init_machine	= smdk4x12_machine_init,
+	.timer		= &exynos4_timer,
+MACHINE_END
+
+MACHINE_START(SMDK4412, "SMDK4412")
+	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
+	/* Maintainer: Changhwan Youn <chaos.youn@samsung.com> */
+	.atag_offset	= 0x100,
+	.init_irq	= exynos4_init_irq,
+	.map_io		= smdk4x12_map_io,
+	.init_machine	= smdk4x12_machine_init,
+	.timer		= &exynos4_timer,
+MACHINE_END
diff --git a/arch/arm/mach-exynos4/mach-smdkc210.c b/arch/arm/mach-exynos4/mach-smdkc210.c
deleted file mode 100644
index b24ddd7..0000000
--- a/arch/arm/mach-exynos4/mach-smdkc210.c
+++ /dev/null
@@ -1,309 +0,0 @@
-/* linux/arch/arm/mach-exynos4/mach-smdkc210.c
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/serial_core.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/lcd.h>
-#include <linux/mmc/host.h>
-#include <linux/platform_device.h>
-#include <linux/smsc911x.h>
-#include <linux/io.h>
-#include <linux/i2c.h>
-#include <linux/pwm_backlight.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach-types.h>
-
-#include <video/platform_lcd.h>
-
-#include <plat/regs-serial.h>
-#include <plat/regs-srom.h>
-#include <plat/regs-fb-v4.h>
-#include <plat/exynos4.h>
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/fb.h>
-#include <plat/sdhci.h>
-#include <plat/iic.h>
-#include <plat/pd.h>
-#include <plat/gpio-cfg.h>
-#include <plat/backlight.h>
-
-#include <mach/map.h>
-
-/* Following are default values for UCON, ULCON and UFCON UART registers */
-#define SMDKC210_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
-				 S3C2410_UCON_RXILEVEL |	\
-				 S3C2410_UCON_TXIRQMODE |	\
-				 S3C2410_UCON_RXIRQMODE |	\
-				 S3C2410_UCON_RXFIFO_TOI |	\
-				 S3C2443_UCON_RXERR_IRQEN)
-
-#define SMDKC210_ULCON_DEFAULT	S3C2410_LCON_CS8
-
-#define SMDKC210_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
-				 S5PV210_UFCON_TXTRIG4 |	\
-				 S5PV210_UFCON_RXTRIG4)
-
-static struct s3c2410_uartcfg smdkc210_uartcfgs[] __initdata = {
-	[0] = {
-		.hwport		= 0,
-		.flags		= 0,
-		.ucon		= SMDKC210_UCON_DEFAULT,
-		.ulcon		= SMDKC210_ULCON_DEFAULT,
-		.ufcon		= SMDKC210_UFCON_DEFAULT,
-	},
-	[1] = {
-		.hwport		= 1,
-		.flags		= 0,
-		.ucon		= SMDKC210_UCON_DEFAULT,
-		.ulcon		= SMDKC210_ULCON_DEFAULT,
-		.ufcon		= SMDKC210_UFCON_DEFAULT,
-	},
-	[2] = {
-		.hwport		= 2,
-		.flags		= 0,
-		.ucon		= SMDKC210_UCON_DEFAULT,
-		.ulcon		= SMDKC210_ULCON_DEFAULT,
-		.ufcon		= SMDKC210_UFCON_DEFAULT,
-	},
-	[3] = {
-		.hwport		= 3,
-		.flags		= 0,
-		.ucon		= SMDKC210_UCON_DEFAULT,
-		.ulcon		= SMDKC210_ULCON_DEFAULT,
-		.ufcon		= SMDKC210_UFCON_DEFAULT,
-	},
-};
-
-static struct s3c_sdhci_platdata smdkc210_hsmmc0_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.ext_cd_gpio		= EXYNOS4_GPK0(2),
-	.ext_cd_gpio_invert	= 1,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-#ifdef CONFIG_EXYNOS4_SDHCI_CH0_8BIT
-	.max_width		= 8,
-	.host_caps		= MMC_CAP_8_BIT_DATA,
-#endif
-};
-
-static struct s3c_sdhci_platdata smdkc210_hsmmc1_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.ext_cd_gpio		= EXYNOS4_GPK0(2),
-	.ext_cd_gpio_invert	= 1,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-};
-
-static struct s3c_sdhci_platdata smdkc210_hsmmc2_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.ext_cd_gpio		= EXYNOS4_GPK2(2),
-	.ext_cd_gpio_invert	= 1,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-#ifdef CONFIG_EXYNOS4_SDHCI_CH2_8BIT
-	.max_width		= 8,
-	.host_caps		= MMC_CAP_8_BIT_DATA,
-#endif
-};
-
-static struct s3c_sdhci_platdata smdkc210_hsmmc3_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.ext_cd_gpio		= EXYNOS4_GPK2(2),
-	.ext_cd_gpio_invert	= 1,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-};
-
-static void lcd_lte480wv_set_power(struct plat_lcd_data *pd,
-				   unsigned int power)
-{
-	if (power) {
-#if !defined(CONFIG_BACKLIGHT_PWM)
-		gpio_request_one(EXYNOS4_GPD0(1), GPIOF_OUT_INIT_HIGH, "GPD0");
-		gpio_free(EXYNOS4_GPD0(1));
-#endif
-		/* fire nRESET on power up */
-		gpio_request(EXYNOS4_GPX0(6), "GPX0");
-
-		gpio_direction_output(EXYNOS4_GPX0(6), 1);
-		mdelay(100);
-
-		gpio_set_value(EXYNOS4_GPX0(6), 0);
-		mdelay(10);
-
-		gpio_set_value(EXYNOS4_GPX0(6), 1);
-		mdelay(10);
-
-		gpio_free(EXYNOS4_GPX0(6));
-	} else {
-#if !defined(CONFIG_BACKLIGHT_PWM)
-		gpio_request_one(EXYNOS4_GPD0(1), GPIOF_OUT_INIT_LOW, "GPD0");
-		gpio_free(EXYNOS4_GPD0(1));
-#endif
-	}
-}
-
-static struct plat_lcd_data smdkc210_lcd_lte480wv_data = {
-	.set_power		= lcd_lte480wv_set_power,
-};
-
-static struct platform_device smdkc210_lcd_lte480wv = {
-	.name			= "platform-lcd",
-	.dev.parent		= &s5p_device_fimd0.dev,
-	.dev.platform_data	= &smdkc210_lcd_lte480wv_data,
-};
-
-static struct s3c_fb_pd_win smdkc210_fb_win0 = {
-	.win_mode = {
-		.left_margin	= 13,
-		.right_margin	= 8,
-		.upper_margin	= 7,
-		.lower_margin	= 5,
-		.hsync_len	= 3,
-		.vsync_len	= 1,
-		.xres		= 800,
-		.yres		= 480,
-	},
-	.max_bpp		= 32,
-	.default_bpp		= 24,
-};
-
-static struct s3c_fb_platdata smdkc210_lcd0_pdata __initdata = {
-	.win[0]		= &smdkc210_fb_win0,
-	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
-	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
-	.setup_gpio	= exynos4_fimd0_gpio_setup_24bpp,
-};
-
-static struct resource smdkc210_smsc911x_resources[] = {
-	[0] = {
-		.start	= EXYNOS4_PA_SROM_BANK(1),
-		.end	= EXYNOS4_PA_SROM_BANK(1) + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_EINT(5),
-		.end	= IRQ_EINT(5),
-		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
-	},
-};
-
-static struct smsc911x_platform_config smsc9215_config = {
-	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
-	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
-	.flags		= SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY,
-	.phy_interface	= PHY_INTERFACE_MODE_MII,
-	.mac		= {0x00, 0x80, 0x00, 0x23, 0x45, 0x67},
-};
-
-static struct platform_device smdkc210_smsc911x = {
-	.name		= "smsc911x",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(smdkc210_smsc911x_resources),
-	.resource	= smdkc210_smsc911x_resources,
-	.dev		= {
-		.platform_data	= &smsc9215_config,
-	},
-};
-
-static struct i2c_board_info i2c_devs1[] __initdata = {
-	{I2C_BOARD_INFO("wm8994", 0x1a),},
-};
-
-static struct platform_device *smdkc210_devices[] __initdata = {
-	&s3c_device_hsmmc0,
-	&s3c_device_hsmmc1,
-	&s3c_device_hsmmc2,
-	&s3c_device_hsmmc3,
-	&s3c_device_i2c1,
-	&s3c_device_rtc,
-	&s3c_device_wdt,
-	&exynos4_device_ac97,
-	&exynos4_device_i2s0,
-	&exynos4_device_pd[PD_MFC],
-	&exynos4_device_pd[PD_G3D],
-	&exynos4_device_pd[PD_LCD0],
-	&exynos4_device_pd[PD_LCD1],
-	&exynos4_device_pd[PD_CAM],
-	&exynos4_device_pd[PD_TV],
-	&exynos4_device_pd[PD_GPS],
-	&exynos4_device_sysmmu,
-	&samsung_asoc_dma,
-	&s5p_device_fimd0,
-	&smdkc210_lcd_lte480wv,
-	&smdkc210_smsc911x,
-};
-
-static void __init smdkc210_smsc911x_init(void)
-{
-	u32 cs1;
-
-	/* configure nCS1 width to 16 bits */
-	cs1 = __raw_readl(S5P_SROM_BW) &
-		~(S5P_SROM_BW__CS_MASK << S5P_SROM_BW__NCS1__SHIFT);
-	cs1 |= ((1 << S5P_SROM_BW__DATAWIDTH__SHIFT) |
-		(1 << S5P_SROM_BW__WAITENABLE__SHIFT) |
-		(1 << S5P_SROM_BW__BYTEENABLE__SHIFT)) <<
-		S5P_SROM_BW__NCS1__SHIFT;
-	__raw_writel(cs1, S5P_SROM_BW);
-
-	/* set timing for nCS1 suitable for ethernet chip */
-	__raw_writel((0x1 << S5P_SROM_BCX__PMC__SHIFT) |
-		     (0x9 << S5P_SROM_BCX__TACP__SHIFT) |
-		     (0xc << S5P_SROM_BCX__TCAH__SHIFT) |
-		     (0x1 << S5P_SROM_BCX__TCOH__SHIFT) |
-		     (0x6 << S5P_SROM_BCX__TACC__SHIFT) |
-		     (0x1 << S5P_SROM_BCX__TCOS__SHIFT) |
-		     (0x1 << S5P_SROM_BCX__TACS__SHIFT), S5P_SROM_BC1);
-}
-
-/* LCD Backlight data */
-static struct samsung_bl_gpio_info smdkc210_bl_gpio_info = {
-	.no = EXYNOS4_GPD0(1),
-	.func = S3C_GPIO_SFN(2),
-};
-
-static struct platform_pwm_backlight_data smdkc210_bl_data = {
-	.pwm_id = 1,
-	.pwm_period_ns  = 1000,
-};
-
-static void __init smdkc210_map_io(void)
-{
-	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
-	s3c24xx_init_clocks(24000000);
-	s3c24xx_init_uarts(smdkc210_uartcfgs, ARRAY_SIZE(smdkc210_uartcfgs));
-}
-
-static void __init smdkc210_machine_init(void)
-{
-	s3c_i2c1_set_platdata(NULL);
-	i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
-
-	smdkc210_smsc911x_init();
-
-	s3c_sdhci0_set_platdata(&smdkc210_hsmmc0_pdata);
-	s3c_sdhci1_set_platdata(&smdkc210_hsmmc1_pdata);
-	s3c_sdhci2_set_platdata(&smdkc210_hsmmc2_pdata);
-	s3c_sdhci3_set_platdata(&smdkc210_hsmmc3_pdata);
-
-	samsung_bl_set(&smdkc210_bl_gpio_info, &smdkc210_bl_data);
-	s5p_fimd0_set_platdata(&smdkc210_lcd0_pdata);
-
-	platform_add_devices(smdkc210_devices, ARRAY_SIZE(smdkc210_devices));
-}
-
-MACHINE_START(SMDKC210, "SMDKC210")
-	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-	.atag_offset	= 0x100,
-	.init_irq	= exynos4_init_irq,
-	.map_io		= smdkc210_map_io,
-	.init_machine	= smdkc210_machine_init,
-	.timer		= &exynos4_timer,
-MACHINE_END
diff --git a/arch/arm/mach-exynos4/mach-smdkv310.c b/arch/arm/mach-exynos4/mach-smdkv310.c
index d90fcdd..2c1a076 100644
--- a/arch/arm/mach-exynos4/mach-smdkv310.c
+++ b/arch/arm/mach-exynos4/mach-smdkv310.c
@@ -9,7 +9,9 @@
 */
 
 #include <linux/serial_core.h>
+#include <linux/delay.h>
 #include <linux/gpio.h>
+#include <linux/lcd.h>
 #include <linux/mmc/host.h>
 #include <linux/platform_device.h>
 #include <linux/smsc911x.h>
@@ -21,11 +23,14 @@
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
+#include <video/platform_lcd.h>
 #include <plat/regs-serial.h>
 #include <plat/regs-srom.h>
+#include <plat/regs-fb-v4.h>
 #include <plat/exynos4.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
+#include <plat/fb.h>
 #include <plat/keypad.h>
 #include <plat/sdhci.h>
 #include <plat/iic.h>
@@ -112,6 +117,67 @@ static struct s3c_sdhci_platdata smdkv310_hsmmc3_pdata __initdata = {
 	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
 };
 
+static void lcd_lte480wv_set_power(struct plat_lcd_data *pd,
+				   unsigned int power)
+{
+	if (power) {
+#if !defined(CONFIG_BACKLIGHT_PWM)
+		gpio_request_one(EXYNOS4_GPD0(1), GPIOF_OUT_INIT_HIGH, "GPD0");
+		gpio_free(EXYNOS4_GPD0(1));
+#endif
+		/* fire nRESET on power up */
+		gpio_request(EXYNOS4_GPX0(6), "GPX0");
+
+		gpio_direction_output(EXYNOS4_GPX0(6), 1);
+		mdelay(100);
+
+		gpio_set_value(EXYNOS4_GPX0(6), 0);
+		mdelay(10);
+
+		gpio_set_value(EXYNOS4_GPX0(6), 1);
+		mdelay(10);
+
+		gpio_free(EXYNOS4_GPX0(6));
+	} else {
+#if !defined(CONFIG_BACKLIGHT_PWM)
+		gpio_request_one(EXYNOS4_GPD0(1), GPIOF_OUT_INIT_LOW, "GPD0");
+		gpio_free(EXYNOS4_GPD0(1));
+#endif
+	}
+}
+
+static struct plat_lcd_data smdkv310_lcd_lte480wv_data = {
+	.set_power		= lcd_lte480wv_set_power,
+};
+
+static struct platform_device smdkv310_lcd_lte480wv = {
+	.name			= "platform-lcd",
+	.dev.parent		= &s5p_device_fimd0.dev,
+	.dev.platform_data	= &smdkv310_lcd_lte480wv_data,
+};
+
+static struct s3c_fb_pd_win smdkv310_fb_win0 = {
+	.win_mode = {
+		.left_margin	= 13,
+		.right_margin	= 8,
+		.upper_margin	= 7,
+		.lower_margin	= 5,
+		.hsync_len	= 3,
+		.vsync_len	= 1,
+		.xres		= 800,
+		.yres		= 480,
+	},
+	.max_bpp		= 32,
+	.default_bpp		= 24,
+};
+
+static struct s3c_fb_platdata smdkv310_lcd0_pdata __initdata = {
+	.win[0]		= &smdkv310_fb_win0,
+	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+	.setup_gpio	= exynos4_fimd0_gpio_setup_24bpp,
+};
+
 static struct resource smdkv310_smsc911x_resources[] = {
 	[0] = {
 		.start	= EXYNOS4_PA_SROM_BANK(1),
@@ -188,6 +254,8 @@ static struct platform_device *smdkv310_devices[] __initdata = {
 	&exynos4_device_sysmmu,
 	&samsung_asoc_dma,
 	&samsung_asoc_idma,
+	&s5p_device_fimd0,
+	&smdkv310_lcd_lte480wv,
 	&smdkv310_smsc911x,
 	&exynos4_device_ahci,
 };
@@ -248,6 +316,7 @@ static void __init smdkv310_machine_init(void)
 	samsung_keypad_set_platdata(&smdkv310_keypad_data);
 
 	samsung_bl_set(&smdkv310_bl_gpio_info, &smdkv310_bl_data);
+	s5p_fimd0_set_platdata(&smdkv310_lcd0_pdata);
 
 	platform_add_devices(smdkv310_devices, ARRAY_SIZE(smdkv310_devices));
 }
@@ -261,3 +330,12 @@ MACHINE_START(SMDKV310, "SMDKV310")
 	.init_machine	= smdkv310_machine_init,
 	.timer		= &exynos4_timer,
 MACHINE_END
+
+MACHINE_START(SMDKC210, "SMDKC210")
+	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
+	.atag_offset	= 0x100,
+	.init_irq	= exynos4_init_irq,
+	.map_io		= smdkv310_map_io,
+	.init_machine	= smdkv310_machine_init,
+	.timer		= &exynos4_timer,
+MACHINE_END
diff --git a/arch/arm/mach-exynos4/mct.c b/arch/arm/mach-exynos4/mct.c
index 582b874..f191608 100644
--- a/arch/arm/mach-exynos4/mct.c
+++ b/arch/arm/mach-exynos4/mct.c
@@ -20,19 +20,31 @@
 #include <linux/delay.h>
 #include <linux/percpu.h>
 
+#include <asm/hardware/gic.h>
+
+#include <plat/cpu.h>
+
 #include <mach/map.h>
+#include <mach/irqs.h>
 #include <mach/regs-mct.h>
 #include <asm/mach/time.h>
 
+enum {
+	MCT_INT_SPI,
+	MCT_INT_PPI
+};
+
 static unsigned long clk_cnt_per_tick;
 static unsigned long clk_rate;
+static unsigned int mct_int_type;
 
 struct mct_clock_event_device {
 	struct clock_event_device *evt;
 	void __iomem *base;
+	char name[10];
 };
 
-struct mct_clock_event_device mct_tick[2];
+struct mct_clock_event_device mct_tick[NR_CPUS];
 
 static void exynos4_mct_write(unsigned int value, void *addr)
 {
@@ -42,57 +54,53 @@ static void exynos4_mct_write(unsigned int value, void *addr)
 
 	__raw_writel(value, addr);
 
-	switch ((u32) addr) {
-	case (u32) EXYNOS4_MCT_G_TCON:
-		stat_addr = EXYNOS4_MCT_G_WSTAT;
-		mask = 1 << 16;		/* G_TCON write status */
-		break;
-	case (u32) EXYNOS4_MCT_G_COMP0_L:
-		stat_addr = EXYNOS4_MCT_G_WSTAT;
-		mask = 1 << 0;		/* G_COMP0_L write status */
-		break;
-	case (u32) EXYNOS4_MCT_G_COMP0_U:
-		stat_addr = EXYNOS4_MCT_G_WSTAT;
-		mask = 1 << 1;		/* G_COMP0_U write status */
-		break;
-	case (u32) EXYNOS4_MCT_G_COMP0_ADD_INCR:
-		stat_addr = EXYNOS4_MCT_G_WSTAT;
-		mask = 1 << 2;		/* G_COMP0_ADD_INCR write status */
-		break;
-	case (u32) EXYNOS4_MCT_G_CNT_L:
-		stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
-		mask = 1 << 0;		/* G_CNT_L write status */
-		break;
-	case (u32) EXYNOS4_MCT_G_CNT_U:
-		stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
-		mask = 1 << 1;		/* G_CNT_U write status */
-		break;
-	case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_TCON_OFFSET):
-		stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET;
-		mask = 1 << 3;		/* L0_TCON write status */
-		break;
-	case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_TCON_OFFSET):
-		stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET;
-		mask = 1 << 3;		/* L1_TCON write status */
-		break;
-	case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_TCNTB_OFFSET):
-		stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET;
-		mask = 1 << 0;		/* L0_TCNTB write status */
-		break;
-	case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_TCNTB_OFFSET):
-		stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET;
-		mask = 1 << 0;		/* L1_TCNTB write status */
-		break;
-	case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_ICNTB_OFFSET):
-		stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET;
-		mask = 1 << 1;		/* L0_ICNTB write status */
-		break;
-	case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_ICNTB_OFFSET):
-		stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET;
-		mask = 1 << 1;		/* L1_ICNTB write status */
-		break;
-	default:
-		return;
+	if (likely(addr >= EXYNOS4_MCT_L_BASE(0))) {
+		u32 base = (u32) addr & EXYNOS4_MCT_L_MASK;
+		switch ((u32) addr & ~EXYNOS4_MCT_L_MASK) {
+		case (u32) MCT_L_TCON_OFFSET:
+			stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
+			mask = 1 << 3;		/* L_TCON write status */
+			break;
+		case (u32) MCT_L_ICNTB_OFFSET:
+			stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
+			mask = 1 << 1;		/* L_ICNTB write status */
+			break;
+		case (u32) MCT_L_TCNTB_OFFSET:
+			stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
+			mask = 1 << 0;		/* L_TCNTB write status */
+			break;
+		default:
+			return;
+		}
+	} else {
+		switch ((u32) addr) {
+		case (u32) EXYNOS4_MCT_G_TCON:
+			stat_addr = EXYNOS4_MCT_G_WSTAT;
+			mask = 1 << 16;		/* G_TCON write status */
+			break;
+		case (u32) EXYNOS4_MCT_G_COMP0_L:
+			stat_addr = EXYNOS4_MCT_G_WSTAT;
+			mask = 1 << 0;		/* G_COMP0_L write status */
+			break;
+		case (u32) EXYNOS4_MCT_G_COMP0_U:
+			stat_addr = EXYNOS4_MCT_G_WSTAT;
+			mask = 1 << 1;		/* G_COMP0_U write status */
+			break;
+		case (u32) EXYNOS4_MCT_G_COMP0_ADD_INCR:
+			stat_addr = EXYNOS4_MCT_G_WSTAT;
+			mask = 1 << 2;		/* G_COMP0_ADD_INCR w status */
+			break;
+		case (u32) EXYNOS4_MCT_G_CNT_L:
+			stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
+			mask = 1 << 0;		/* G_CNT_L write status */
+			break;
+		case (u32) EXYNOS4_MCT_G_CNT_U:
+			stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
+			mask = 1 << 1;		/* G_CNT_U write status */
+			break;
+		default:
+			return;
+		}
 	}
 
 	/* Wait maximum 1 ms until written values are applied */
@@ -321,9 +329,8 @@ static inline void exynos4_tick_set_mode(enum clock_event_mode mode,
 	}
 }
 
-static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id)
+static int exynos4_mct_tick_clear(struct mct_clock_event_device *mevt)
 {
-	struct mct_clock_event_device *mevt = dev_id;
 	struct clock_event_device *evt = mevt->evt;
 
 	/*
@@ -335,7 +342,20 @@ static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id)
 		exynos4_mct_tick_stop(mevt);
 
 	/* Clear the MCT tick interrupt */
-	exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
+	if (__raw_readl(mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1) {
+		exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id)
+{
+	struct mct_clock_event_device *mevt = dev_id;
+	struct clock_event_device *evt = mevt->evt;
+
+	exynos4_mct_tick_clear(mevt);
 
 	evt->event_handler(evt);
 
@@ -360,14 +380,10 @@ static void exynos4_mct_tick_init(struct clock_event_device *evt)
 
 	mct_tick[cpu].evt = evt;
 
-	if (cpu == 0) {
-		mct_tick[cpu].base = EXYNOS4_MCT_L0_BASE;
-		evt->name = "mct_tick0";
-	} else {
-		mct_tick[cpu].base = EXYNOS4_MCT_L1_BASE;
-		evt->name = "mct_tick1";
-	}
+	mct_tick[cpu].base = EXYNOS4_MCT_L_BASE(cpu);
+	sprintf(mct_tick[cpu].name, "mct_tick%d", cpu);
 
+	evt->name = mct_tick[cpu].name;
 	evt->cpumask = cpumask_of(cpu);
 	evt->set_next_event = exynos4_tick_set_next_event;
 	evt->set_mode = exynos4_tick_set_mode;
@@ -384,15 +400,19 @@ static void exynos4_mct_tick_init(struct clock_event_device *evt)
 
 	exynos4_mct_write(0x1, mct_tick[cpu].base + MCT_L_TCNTB_OFFSET);
 
-	if (cpu == 0) {
-		mct_tick0_event_irq.dev_id = &mct_tick[cpu];
-		evt->irq = IRQ_MCT_L0;
-		setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq);
+	if (mct_int_type == MCT_INT_SPI) {
+		if (cpu == 0) {
+			mct_tick0_event_irq.dev_id = &mct_tick[cpu];
+			evt->irq = IRQ_MCT_L0;
+			setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq);
+		} else {
+			mct_tick1_event_irq.dev_id = &mct_tick[cpu];
+			evt->irq = IRQ_MCT_L1;
+			setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq);
+			irq_set_affinity(IRQ_MCT_L1, cpumask_of(1));
+		}
 	} else {
-		mct_tick1_event_irq.dev_id = &mct_tick[cpu];
-		evt->irq = IRQ_MCT_L1;
-		setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq);
-		irq_set_affinity(IRQ_MCT_L1, cpumask_of(1));
+		gic_enable_ppi(IRQ_MCT_LOCALTIMER);
 	}
 }
 
@@ -422,6 +442,11 @@ static void __init exynos4_timer_resources(void)
 
 static void __init exynos4_timer_init(void)
 {
+	if (soc_is_exynos4210())
+		mct_int_type = MCT_INT_SPI;
+	else
+		mct_int_type = MCT_INT_PPI;
+
 	exynos4_timer_resources();
 	exynos4_clocksource_init();
 	exynos4_clockevent_init();
diff --git a/arch/arm/mach-exynos4/platsmp.c b/arch/arm/mach-exynos4/platsmp.c
index 0c90896..0559540 100644
--- a/arch/arm/mach-exynos4/platsmp.c
+++ b/arch/arm/mach-exynos4/platsmp.c
@@ -30,9 +30,13 @@
 #include <mach/regs-clock.h>
 #include <mach/regs-pmu.h>
 
+#include <plat/cpu.h>
+
+extern unsigned int gic_bank_offset;
 extern void exynos4_secondary_startup(void);
 
-#define CPU1_BOOT_REG S5P_VA_SYSRAM
+#define CPU1_BOOT_REG		(samsung_rev() == EXYNOS4210_REV_1_1 ? \
+				S5P_INFORM5 : S5P_VA_SYSRAM)
 
 /*
  * control for which core is the next to come out of the secondary
@@ -64,9 +68,9 @@ static DEFINE_SPINLOCK(boot_lock);
 static void __cpuinit exynos4_gic_secondary_init(void)
 {
 	void __iomem *dist_base = S5P_VA_GIC_DIST +
-				 (EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());
+				(gic_bank_offset * smp_processor_id());
 	void __iomem *cpu_base = S5P_VA_GIC_CPU +
-				(EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());
+				(gic_bank_offset * smp_processor_id());
 	int i;
 
 	/*
@@ -128,7 +132,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 	 * Note that "pen_release" is the hardware CPU ID, whereas
 	 * "cpu" is Linux's internal ID.
 	 */
-	write_pen_release(cpu);
+	write_pen_release(cpu_logical_map(cpu));
 
 	if (!(__raw_readl(S5P_ARM_CORE1_STATUS) & S5P_CORE_LOCAL_PWR_EN)) {
 		__raw_writel(S5P_CORE_LOCAL_PWR_EN,
@@ -216,5 +220,6 @@ void __init platform_smp_prepare_cpus(unsigned int max_cpus)
 	 * until it receives a soft interrupt, and then the
 	 * secondary CPU branches to this address.
 	 */
-	__raw_writel(BSYM(virt_to_phys(exynos4_secondary_startup)), S5P_VA_SYSRAM);
+	__raw_writel(BSYM(virt_to_phys(exynos4_secondary_startup)),
+			CPU1_BOOT_REG);
 }
diff --git a/arch/arm/mach-exynos4/pm.c b/arch/arm/mach-exynos4/pm.c
index bc6ca94..62e4f43 100644
--- a/arch/arm/mach-exynos4/pm.c
+++ b/arch/arm/mach-exynos4/pm.c
@@ -41,7 +41,6 @@ static struct sleep_save exynos4_set_clksrc[] = {
 	{ .reg = S5P_CLKSRC_MASK_CAM			, .val = 0x11111111, },
 	{ .reg = S5P_CLKSRC_MASK_TV			, .val = 0x00000111, },
 	{ .reg = S5P_CLKSRC_MASK_LCD0			, .val = 0x00001111, },
-	{ .reg = S5P_CLKSRC_MASK_LCD1			, .val = 0x00001111, },
 	{ .reg = S5P_CLKSRC_MASK_MAUDIO			, .val = 0x00000001, },
 	{ .reg = S5P_CLKSRC_MASK_FSYS			, .val = 0x01011111, },
 	{ .reg = S5P_CLKSRC_MASK_PERIL0			, .val = 0x01111111, },
@@ -49,6 +48,10 @@ static struct sleep_save exynos4_set_clksrc[] = {
 	{ .reg = S5P_CLKSRC_MASK_DMC			, .val = 0x00010000, },
 };
 
+static struct sleep_save exynos4210_set_clksrc[] = {
+	{ .reg = S5P_CLKSRC_MASK_LCD1			, .val = 0x00001111, },
+};
+
 static struct sleep_save exynos4_epll_save[] = {
 	SAVE_ITEM(S5P_EPLL_CON0),
 	SAVE_ITEM(S5P_EPLL_CON1),
@@ -60,77 +63,6 @@ static struct sleep_save exynos4_vpll_save[] = {
 };
 
 static struct sleep_save exynos4_core_save[] = {
-	/* CMU side */
-	SAVE_ITEM(S5P_CLKDIV_LEFTBUS),
-	SAVE_ITEM(S5P_CLKGATE_IP_LEFTBUS),
-	SAVE_ITEM(S5P_CLKDIV_RIGHTBUS),
-	SAVE_ITEM(S5P_CLKGATE_IP_RIGHTBUS),
-	SAVE_ITEM(S5P_CLKSRC_TOP0),
-	SAVE_ITEM(S5P_CLKSRC_TOP1),
-	SAVE_ITEM(S5P_CLKSRC_CAM),
-	SAVE_ITEM(S5P_CLKSRC_TV),
-	SAVE_ITEM(S5P_CLKSRC_MFC),
-	SAVE_ITEM(S5P_CLKSRC_G3D),
-	SAVE_ITEM(S5P_CLKSRC_IMAGE),
-	SAVE_ITEM(S5P_CLKSRC_LCD0),
-	SAVE_ITEM(S5P_CLKSRC_LCD1),
-	SAVE_ITEM(S5P_CLKSRC_MAUDIO),
-	SAVE_ITEM(S5P_CLKSRC_FSYS),
-	SAVE_ITEM(S5P_CLKSRC_PERIL0),
-	SAVE_ITEM(S5P_CLKSRC_PERIL1),
-	SAVE_ITEM(S5P_CLKDIV_CAM),
-	SAVE_ITEM(S5P_CLKDIV_TV),
-	SAVE_ITEM(S5P_CLKDIV_MFC),
-	SAVE_ITEM(S5P_CLKDIV_G3D),
-	SAVE_ITEM(S5P_CLKDIV_IMAGE),
-	SAVE_ITEM(S5P_CLKDIV_LCD0),
-	SAVE_ITEM(S5P_CLKDIV_LCD1),
-	SAVE_ITEM(S5P_CLKDIV_MAUDIO),
-	SAVE_ITEM(S5P_CLKDIV_FSYS0),
-	SAVE_ITEM(S5P_CLKDIV_FSYS1),
-	SAVE_ITEM(S5P_CLKDIV_FSYS2),
-	SAVE_ITEM(S5P_CLKDIV_FSYS3),
-	SAVE_ITEM(S5P_CLKDIV_PERIL0),
-	SAVE_ITEM(S5P_CLKDIV_PERIL1),
-	SAVE_ITEM(S5P_CLKDIV_PERIL2),
-	SAVE_ITEM(S5P_CLKDIV_PERIL3),
-	SAVE_ITEM(S5P_CLKDIV_PERIL4),
-	SAVE_ITEM(S5P_CLKDIV_PERIL5),
-	SAVE_ITEM(S5P_CLKDIV_TOP),
-	SAVE_ITEM(S5P_CLKSRC_MASK_TOP),
-	SAVE_ITEM(S5P_CLKSRC_MASK_CAM),
-	SAVE_ITEM(S5P_CLKSRC_MASK_TV),
-	SAVE_ITEM(S5P_CLKSRC_MASK_LCD0),
-	SAVE_ITEM(S5P_CLKSRC_MASK_LCD1),
-	SAVE_ITEM(S5P_CLKSRC_MASK_MAUDIO),
-	SAVE_ITEM(S5P_CLKSRC_MASK_FSYS),
-	SAVE_ITEM(S5P_CLKSRC_MASK_PERIL0),
-	SAVE_ITEM(S5P_CLKSRC_MASK_PERIL1),
-	SAVE_ITEM(S5P_CLKDIV2_RATIO),
-	SAVE_ITEM(S5P_CLKGATE_SCLKCAM),
-	SAVE_ITEM(S5P_CLKGATE_IP_CAM),
-	SAVE_ITEM(S5P_CLKGATE_IP_TV),
-	SAVE_ITEM(S5P_CLKGATE_IP_MFC),
-	SAVE_ITEM(S5P_CLKGATE_IP_G3D),
-	SAVE_ITEM(S5P_CLKGATE_IP_IMAGE),
-	SAVE_ITEM(S5P_CLKGATE_IP_LCD0),
-	SAVE_ITEM(S5P_CLKGATE_IP_LCD1),
-	SAVE_ITEM(S5P_CLKGATE_IP_FSYS),
-	SAVE_ITEM(S5P_CLKGATE_IP_GPS),
-	SAVE_ITEM(S5P_CLKGATE_IP_PERIL),
-	SAVE_ITEM(S5P_CLKGATE_IP_PERIR),
-	SAVE_ITEM(S5P_CLKGATE_BLOCK),
-	SAVE_ITEM(S5P_CLKSRC_MASK_DMC),
-	SAVE_ITEM(S5P_CLKSRC_DMC),
-	SAVE_ITEM(S5P_CLKDIV_DMC0),
-	SAVE_ITEM(S5P_CLKDIV_DMC1),
-	SAVE_ITEM(S5P_CLKGATE_IP_DMC),
-	SAVE_ITEM(S5P_CLKSRC_CPU),
-	SAVE_ITEM(S5P_CLKDIV_CPU),
-	SAVE_ITEM(S5P_CLKDIV_CPU + 0x4),
-	SAVE_ITEM(S5P_CLKGATE_SCLKCPU),
-	SAVE_ITEM(S5P_CLKGATE_IP_CPU),
-
 	/* GIC side */
 	SAVE_ITEM(S5P_VA_GIC_CPU + 0x000),
 	SAVE_ITEM(S5P_VA_GIC_CPU + 0x004),
@@ -268,6 +200,9 @@ static void exynos4_pm_prepare(void)
 
 	s3c_pm_do_restore_core(exynos4_set_clksrc, ARRAY_SIZE(exynos4_set_clksrc));
 
+	if (soc_is_exynos4210())
+		s3c_pm_do_restore_core(exynos4210_set_clksrc, ARRAY_SIZE(exynos4210_set_clksrc));
+
 }
 
 static int exynos4_pm_add(struct sys_device *sysdev)
diff --git a/arch/arm/mach-highbank/Makefile b/arch/arm/mach-highbank/Makefile
new file mode 100644
index 0000000..986958a
--- /dev/null
+++ b/arch/arm/mach-highbank/Makefile
@@ -0,0 +1,6 @@
+obj-y					:= clock.o highbank.o system.o
+obj-$(CONFIG_DEBUG_HIGHBANK_UART)	+= lluart.o
+obj-$(CONFIG_SMP)			+= platsmp.o
+obj-$(CONFIG_LOCAL_TIMERS)		+= localtimer.o
+obj-$(CONFIG_HOTPLUG_CPU)		+= hotplug.o
+obj-$(CONFIG_PM_SLEEP)			+= pm.o
diff --git a/arch/arm/mach-highbank/Makefile.boot b/arch/arm/mach-highbank/Makefile.boot
new file mode 100644
index 0000000..dae9661
--- /dev/null
+++ b/arch/arm/mach-highbank/Makefile.boot
@@ -0,0 +1 @@
+zreladdr-y	:= 0x00008000
diff --git a/arch/arm/mach-highbank/clock.c b/arch/arm/mach-highbank/clock.c
new file mode 100644
index 0000000..c25a2ae
--- /dev/null
+++ b/arch/arm/mach-highbank/clock.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2011 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+
+struct clk {
+	unsigned long rate;
+};
+
+int clk_enable(struct clk *clk)
+{
+	return 0;
+}
+
+void clk_disable(struct clk *clk)
+{}
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	return clk->rate;
+}
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	return clk->rate;
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	return 0;
+}
+
+static struct clk eclk = { .rate = 200000000 };
+static struct clk pclk = { .rate = 150000000 };
+
+static struct clk_lookup lookups[] = {
+	{ .clk = &pclk, .con_id = "apb_pclk", },
+	{ .clk = &pclk, .dev_id = "sp804", },
+	{ .clk = &eclk, .dev_id = "ffe0e000.sdhci", },
+	{ .clk = &pclk, .dev_id = "fff36000.serial", },
+};
+
+void __init highbank_clocks_init(void)
+{
+	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+}
diff --git a/arch/arm/mach-highbank/core.h b/arch/arm/mach-highbank/core.h
new file mode 100644
index 0000000..7e33fc9
--- /dev/null
+++ b/arch/arm/mach-highbank/core.h
@@ -0,0 +1,9 @@
+extern void highbank_set_cpu_jump(int cpu, void *jump_addr);
+extern void highbank_clocks_init(void);
+extern void __iomem *scu_base_addr;
+#ifdef CONFIG_DEBUG_HIGHBANK_UART
+extern void highbank_lluart_map_io(void);
+#else
+static inline void highbank_lluart_map_io(void) {}
+#endif
+
diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c
new file mode 100644
index 0000000..b82dcf0
--- /dev/null
+++ b/arch/arm/mach-highbank/highbank.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2010-2011 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+
+#include <asm/cacheflush.h>
+#include <asm/unified.h>
+#include <asm/smp_scu.h>
+#include <asm/hardware/arm_timer.h>
+#include <asm/hardware/timer-sp.h>
+#include <asm/hardware/gic.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+#include <mach/irqs.h>
+
+#include "core.h"
+#include "sysregs.h"
+
+void __iomem *sregs_base;
+
+#define HB_SCU_VIRT_BASE	0xfee00000
+void __iomem *scu_base_addr = ((void __iomem *)(HB_SCU_VIRT_BASE));
+
+static struct map_desc scu_io_desc __initdata = {
+	.virtual	= HB_SCU_VIRT_BASE,
+	.pfn		= 0, /* run-time */
+	.length		= SZ_4K,
+	.type		= MT_DEVICE,
+};
+
+static void __init highbank_scu_map_io(void)
+{
+	unsigned long base;
+
+	/* Get SCU base */
+	asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
+
+	scu_io_desc.pfn = __phys_to_pfn(base);
+	iotable_init(&scu_io_desc, 1);
+}
+
+static void __init highbank_map_io(void)
+{
+	highbank_scu_map_io();
+	highbank_lluart_map_io();
+}
+
+#define HB_JUMP_TABLE_PHYS(cpu)		(0x40 + (0x10 * (cpu)))
+#define HB_JUMP_TABLE_VIRT(cpu)		phys_to_virt(HB_JUMP_TABLE_PHYS(cpu))
+
+void highbank_set_cpu_jump(int cpu, void *jump_addr)
+{
+	writel(BSYM(virt_to_phys(jump_addr)), HB_JUMP_TABLE_VIRT(cpu));
+	__cpuc_flush_dcache_area(HB_JUMP_TABLE_VIRT(cpu), 16);
+	outer_clean_range(HB_JUMP_TABLE_PHYS(cpu),
+			  HB_JUMP_TABLE_PHYS(cpu) + 15);
+}
+
+const static struct of_device_id irq_match[] = {
+	{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
+	{}
+};
+
+static void __init highbank_init_irq(void)
+{
+	of_irq_init(irq_match);
+	l2x0_of_init(0, ~0UL);
+}
+
+static void __init highbank_timer_init(void)
+{
+	int irq;
+	struct device_node *np;
+	void __iomem *timer_base;
+
+	/* Map system registers */
+	np = of_find_compatible_node(NULL, NULL, "calxeda,hb-sregs");
+	sregs_base = of_iomap(np, 0);
+	WARN_ON(!sregs_base);
+
+	np = of_find_compatible_node(NULL, NULL, "arm,sp804");
+	timer_base = of_iomap(np, 0);
+	WARN_ON(!timer_base);
+	irq = irq_of_parse_and_map(np, 0);
+
+	highbank_clocks_init();
+
+	sp804_clocksource_init(timer_base + 0x20, "timer1");
+	sp804_clockevents_init(timer_base, irq, "timer0");
+}
+
+static struct sys_timer highbank_timer = {
+	.init = highbank_timer_init,
+};
+
+static void highbank_power_off(void)
+{
+	hignbank_set_pwr_shutdown();
+	scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
+
+	while (1)
+		cpu_do_idle();
+}
+
+static void __init highbank_init(void)
+{
+	pm_power_off = highbank_power_off;
+
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *highbank_match[] __initconst = {
+	"calxeda,highbank",
+	NULL,
+};
+
+DT_MACHINE_START(HIGHBANK, "Highbank")
+	.map_io		= highbank_map_io,
+	.init_irq	= highbank_init_irq,
+	.timer		= &highbank_timer,
+	.init_machine	= highbank_init,
+	.dt_compat	= highbank_match,
+MACHINE_END
diff --git a/arch/arm/mach-highbank/hotplug.c b/arch/arm/mach-highbank/hotplug.c
new file mode 100644
index 0000000..977cebb
--- /dev/null
+++ b/arch/arm/mach-highbank/hotplug.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2011 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+
+#include <asm/smp_scu.h>
+#include <asm/cacheflush.h>
+
+#include "core.h"
+
+extern void secondary_startup(void);
+
+int platform_cpu_kill(unsigned int cpu)
+{
+	return 1;
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ */
+void platform_cpu_die(unsigned int cpu)
+{
+	flush_cache_all();
+
+	highbank_set_cpu_jump(cpu, secondary_startup);
+	scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
+
+	cpu_do_idle();
+
+	/* We should never return from idle */
+	panic("highbank: cpu %d unexpectedly exit from shutdown\n", cpu);
+}
+
+int platform_cpu_disable(unsigned int cpu)
+{
+	/*
+	 * CPU0 should not be shut down via hotplug.  cpu_idle can WFI
+	 * or a proper shutdown or hibernate should be used.
+	 */
+	return cpu == 0 ? -EPERM : 0;
+}
diff --git a/arch/arm/mach-highbank/include/mach/debug-macro.S b/arch/arm/mach-highbank/include/mach/debug-macro.S
new file mode 100644
index 0000000..cb57fe5
--- /dev/null
+++ b/arch/arm/mach-highbank/include/mach/debug-macro.S
@@ -0,0 +1,19 @@
+/*
+ * Debugging macro include header
+ *
+ *  Copyright (C) 1994-1999 Russell King
+ *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+		.macro	addruart,rp,rv,tmp
+		movw	\rv, #0x6000
+		movt	\rv, #0xfee3
+		movw	\rp, #0x6000
+		movt	\rp, #0xfff3
+		.endm
+
+#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-highbank/include/mach/entry-macro.S b/arch/arm/mach-highbank/include/mach/entry-macro.S
new file mode 100644
index 0000000..73c1129
--- /dev/null
+++ b/arch/arm/mach-highbank/include/mach/entry-macro.S
@@ -0,0 +1,7 @@
+#include <asm/hardware/entry-macro-gic.S>
+
+	.macro	disable_fiq
+	.endm
+
+	.macro	arch_ret_to_user, tmp1, tmp2
+	.endm
diff --git a/arch/arm/mach-highbank/include/mach/gpio.h b/arch/arm/mach-highbank/include/mach/gpio.h
new file mode 100644
index 0000000..40a8c17
--- /dev/null
+++ b/arch/arm/mach-highbank/include/mach/gpio.h
@@ -0,0 +1 @@
+/* empty */
diff --git a/arch/arm/mach-highbank/include/mach/io.h b/arch/arm/mach-highbank/include/mach/io.h
new file mode 100644
index 0000000..70cfa3b
--- /dev/null
+++ b/arch/arm/mach-highbank/include/mach/io.h
@@ -0,0 +1,7 @@
+#ifndef __MACH_IO_H
+#define __MACH_IO_H
+
+#define __io(a)		({ (void)(a); __typesafe_io(0); })
+#define __mem_pci(a)	(a)
+
+#endif
diff --git a/arch/arm/mach-highbank/include/mach/irqs.h b/arch/arm/mach-highbank/include/mach/irqs.h
new file mode 100644
index 0000000..9746aab
--- /dev/null
+++ b/arch/arm/mach-highbank/include/mach/irqs.h
@@ -0,0 +1,6 @@
+#ifndef __MACH_IRQS_H
+#define __MACH_IRQS_H
+
+#define NR_IRQS			192
+
+#endif
diff --git a/arch/arm/mach-highbank/include/mach/memory.h b/arch/arm/mach-highbank/include/mach/memory.h
new file mode 100644
index 0000000..40a8c17
--- /dev/null
+++ b/arch/arm/mach-highbank/include/mach/memory.h
@@ -0,0 +1 @@
+/* empty */
diff --git a/arch/arm/mach-highbank/include/mach/system.h b/arch/arm/mach-highbank/include/mach/system.h
new file mode 100644
index 0000000..7e81922
--- /dev/null
+++ b/arch/arm/mach-highbank/include/mach/system.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2010-2011 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __MACH_SYSTEM_H
+#define __MACH_SYSTEM_H
+
+static inline void arch_idle(void)
+{
+	cpu_do_idle();
+}
+
+extern void arch_reset(char mode, const char *cmd);
+
+#endif
diff --git a/arch/arm/mach-highbank/include/mach/timex.h b/arch/arm/mach-highbank/include/mach/timex.h
new file mode 100644
index 0000000..88dac7a
--- /dev/null
+++ b/arch/arm/mach-highbank/include/mach/timex.h
@@ -0,0 +1,6 @@
+#ifndef __MACH_TIMEX_H
+#define __MACH_TIMEX_H
+
+#define CLOCK_TICK_RATE		1000000
+
+#endif
diff --git a/arch/arm/mach-highbank/include/mach/uncompress.h b/arch/arm/mach-highbank/include/mach/uncompress.h
new file mode 100644
index 0000000..bbe20e6
--- /dev/null
+++ b/arch/arm/mach-highbank/include/mach/uncompress.h
@@ -0,0 +1,9 @@
+#ifndef __MACH_UNCOMPRESS_H
+#define __MACH_UNCOMPRESS_H
+
+#define putc(c)
+#define flush()
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
+
+#endif
diff --git a/arch/arm/mach-highbank/include/mach/vmalloc.h b/arch/arm/mach-highbank/include/mach/vmalloc.h
new file mode 100644
index 0000000..1969e95
--- /dev/null
+++ b/arch/arm/mach-highbank/include/mach/vmalloc.h
@@ -0,0 +1 @@
+#define VMALLOC_END		0xFEE00000UL
diff --git a/arch/arm/mach-highbank/lluart.c b/arch/arm/mach-highbank/lluart.c
new file mode 100644
index 0000000..3715750
--- /dev/null
+++ b/arch/arm/mach-highbank/lluart.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2011 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/init.h>
+#include <asm/page.h>
+#include <asm/sizes.h>
+#include <asm/mach/map.h>
+
+#define HB_DEBUG_LL_PHYS_BASE	0xfff36000
+#define HB_DEBUG_LL_VIRT_BASE	0xfee36000
+
+static struct map_desc lluart_io_desc __initdata = {
+	.virtual	= HB_DEBUG_LL_VIRT_BASE,
+	.pfn		= __phys_to_pfn(HB_DEBUG_LL_PHYS_BASE),
+	.length		= SZ_4K,
+	.type		= MT_DEVICE,
+};
+
+void __init highbank_lluart_map_io(void)
+{
+	iotable_init(&lluart_io_desc, 1);
+}
diff --git a/arch/arm/mach-highbank/localtimer.c b/arch/arm/mach-highbank/localtimer.c
new file mode 100644
index 0000000..5a00e79
--- /dev/null
+++ b/arch/arm/mach-highbank/localtimer.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2010-2011 Calxeda, Inc.
+ * Based on localtimer.c, Copyright (C) 2002 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/init.h>
+#include <linux/clockchips.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#include <asm/smp_twd.h>
+
+/*
+ * Setup the local clock events for a CPU.
+ */
+int __cpuinit local_timer_setup(struct clock_event_device *evt)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "arm,smp-twd");
+	if (!twd_base) {
+		twd_base = of_iomap(np, 0);
+		WARN_ON(!twd_base);
+	}
+	evt->irq = irq_of_parse_and_map(np, 0);
+	twd_timer_setup(evt);
+	return 0;
+}
diff --git a/arch/arm/mach-highbank/platsmp.c b/arch/arm/mach-highbank/platsmp.c
new file mode 100644
index 0000000..d01364c
--- /dev/null
+++ b/arch/arm/mach-highbank/platsmp.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2010-2011 Calxeda, Inc.
+ * Based on platsmp.c, Copyright (C) 2002 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+
+#include <asm/smp_scu.h>
+#include <asm/hardware/gic.h>
+
+#include "core.h"
+
+extern void secondary_startup(void);
+
+void __cpuinit platform_secondary_init(unsigned int cpu)
+{
+	gic_secondary_init(0);
+}
+
+int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	gic_raise_softirq(cpumask_of(cpu), 0);
+	return 0;
+}
+
+/*
+ * Initialise the CPU possible map early - this describes the CPUs
+ * which may be present or become present in the system.
+ */
+void __init smp_init_cpus(void)
+{
+	unsigned int i, ncores;
+
+	ncores = scu_get_core_count(scu_base_addr);
+
+	/* sanity check */
+	if (ncores > NR_CPUS) {
+		printk(KERN_WARNING
+		       "highbank: no. of cores (%d) greater than configured "
+		       "maximum of %d - clipping\n",
+		       ncores, NR_CPUS);
+		ncores = NR_CPUS;
+	}
+
+	for (i = 0; i < ncores; i++)
+		set_cpu_possible(i, true);
+
+	set_smp_cross_call(gic_raise_softirq);
+}
+
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+	int i;
+
+	scu_enable(scu_base_addr);
+
+	/*
+	 * Write the address of secondary startup into the jump table
+	 * The cores are in wfi and wait until they receive a soft interrupt
+	 * and a non-zero value to jump to. Then the secondary CPU branches
+	 * to this address.
+	 */
+	for (i = 1; i < max_cpus; i++)
+		highbank_set_cpu_jump(i, secondary_startup);
+}
diff --git a/arch/arm/mach-highbank/pm.c b/arch/arm/mach-highbank/pm.c
new file mode 100644
index 0000000..33b3beb
--- /dev/null
+++ b/arch/arm/mach-highbank/pm.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2011 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/suspend.h>
+
+#include <asm/proc-fns.h>
+#include <asm/smp_scu.h>
+#include <asm/suspend.h>
+
+#include "core.h"
+#include "sysregs.h"
+
+static int highbank_suspend_finish(unsigned long val)
+{
+	cpu_do_idle();
+	return 0;
+}
+
+static int highbank_pm_enter(suspend_state_t state)
+{
+	hignbank_set_pwr_suspend();
+	highbank_set_cpu_jump(0, cpu_resume);
+
+	scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
+	cpu_suspend(0, highbank_suspend_finish);
+
+	return 0;
+}
+
+static const struct platform_suspend_ops highbank_pm_ops = {
+	.enter = highbank_pm_enter,
+	.valid = suspend_valid_only_mem,
+};
+
+static int __init highbank_pm_init(void)
+{
+	suspend_set_ops(&highbank_pm_ops);
+	return 0;
+}
+module_init(highbank_pm_init);
diff --git a/arch/arm/mach-highbank/sysregs.h b/arch/arm/mach-highbank/sysregs.h
new file mode 100644
index 0000000..0e91338
--- /dev/null
+++ b/arch/arm/mach-highbank/sysregs.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2011 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _MACH_HIGHBANK__SYSREGS_H_
+#define _MACH_HIGHBANK__SYSREGS_H_
+
+#include <linux/io.h>
+
+extern void __iomem *sregs_base;
+
+#define HB_SREG_A9_PWR_REQ		0xf00
+#define HB_SREG_A9_BOOT_STAT		0xf04
+#define HB_SREG_A9_BOOT_DATA		0xf08
+
+#define HB_PWR_SUSPEND			0
+#define HB_PWR_SOFT_RESET		1
+#define HB_PWR_HARD_RESET		2
+#define HB_PWR_SHUTDOWN			3
+
+static inline void hignbank_set_pwr_suspend(void)
+{
+	writel(HB_PWR_SUSPEND, sregs_base + HB_SREG_A9_PWR_REQ);
+}
+
+static inline void hignbank_set_pwr_shutdown(void)
+{
+	writel(HB_PWR_SHUTDOWN, sregs_base + HB_SREG_A9_PWR_REQ);
+}
+
+static inline void hignbank_set_pwr_soft_reset(void)
+{
+	writel(HB_PWR_SOFT_RESET, sregs_base + HB_SREG_A9_PWR_REQ);
+}
+
+static inline void hignbank_set_pwr_hard_reset(void)
+{
+	writel(HB_PWR_HARD_RESET, sregs_base + HB_SREG_A9_PWR_REQ);
+}
+
+#endif
diff --git a/arch/arm/mach-highbank/system.c b/arch/arm/mach-highbank/system.c
new file mode 100644
index 0000000..53f0c4c
--- /dev/null
+++ b/arch/arm/mach-highbank/system.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2011 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/io.h>
+#include <asm/smp_scu.h>
+#include <asm/proc-fns.h>
+
+#include "core.h"
+#include "sysregs.h"
+
+void arch_reset(char mode, const char *cmd)
+{
+	if (mode == 'h')
+		hignbank_set_pwr_hard_reset();
+	else
+		hignbank_set_pwr_soft_reset();
+
+	scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
+	cpu_do_idle();
+}
+
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 0519dd7..5f7f9c2 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -1,10 +1,32 @@
 config IMX_HAVE_DMA_V1
 	bool
+
+config HAVE_IMX_GPC
+	bool
+
+config HAVE_IMX_MMDC
+	bool
+
+config HAVE_IMX_SRC
+	bool
+
 #
 # ARCH_MX31 and ARCH_MX35 are left for compatibility
 # Some usages assume that having one of them implies not having (e.g.) ARCH_MX2.
 # To easily distinguish good and reviewed from unreviewed usages new (and IMHO
 # more sensible) names are used: SOC_IMX31 and SOC_IMX35
+config ARCH_MX1
+	bool
+
+config MACH_MX21
+	bool
+
+config ARCH_MX25
+	bool
+
+config MACH_MX27
+	bool
+
 config ARCH_MX31
 	bool
 
@@ -13,6 +35,7 @@ config ARCH_MX35
 
 config SOC_IMX1
 	bool
+	select ARCH_MX1
 	select CPU_ARM920T
 	select IMX_HAVE_DMA_V1
 	select IMX_HAVE_IOMUX_V1
@@ -20,6 +43,7 @@ config SOC_IMX1
 
 config SOC_IMX21
 	bool
+	select MACH_MX21
 	select CPU_ARM926T
 	select ARCH_MXC_AUDMUX_V1
 	select IMX_HAVE_DMA_V1
@@ -28,6 +52,7 @@ config SOC_IMX21
 
 config SOC_IMX25
 	bool
+	select ARCH_MX25
 	select CPU_ARM926T
 	select ARCH_MXC_AUDMUX_V2
 	select ARCH_MXC_IOMUX_V3
@@ -35,6 +60,7 @@ config SOC_IMX25
 
 config SOC_IMX27
 	bool
+	select MACH_MX27
 	select CPU_ARM926T
 	select ARCH_MXC_AUDMUX_V1
 	select IMX_HAVE_DMA_V1
@@ -48,6 +74,7 @@ config SOC_IMX31
 	select ARCH_MXC_AUDMUX_V2
 	select ARCH_MX31
 	select MXC_AVIC
+	select SMP_ON_UP if SMP
 
 config SOC_IMX35
 	bool
@@ -57,9 +84,10 @@ config SOC_IMX35
 	select HAVE_EPIT
 	select ARCH_MX35
 	select MXC_AVIC
+	select SMP_ON_UP if SMP
 
 
-if ARCH_MX1
+if ARCH_IMX_V4_V5
 
 comment "MX1 platforms:"
 config MACH_MXLADS
@@ -87,30 +115,6 @@ config MACH_APF9328
 	help
 	  Say Yes here if you are using the Armadeus APF9328 development board
 
-endif
-
-if ARCH_MX2
-
-choice
-	prompt "CPUs:"
-	default MACH_MX21
-
-config MACH_MX21
-	bool "i.MX21 support"
-	help
-	  This enables support for Freescale's MX2 based i.MX21 processor.
-
-config MACH_MX27
-	bool "i.MX27 support"
-	help
-	  This enables support for Freescale's MX2 based i.MX27 processor.
-
-endchoice
-
-endif
-
-if MACH_MX21
-
 comment "MX21 platforms:"
 
 config MACH_MX21ADS
@@ -124,15 +128,12 @@ config MACH_MX21ADS
 	  Include support for MX21ADS platform. This includes specific
 	  configurations for the board and its peripherals.
 
-endif
-
-if ARCH_MX25
-
 comment "MX25 platforms:"
 
 config MACH_MX25_3DS
 	bool "Support MX25PDK (3DS) Platform"
 	select SOC_IMX25
+	select IMX_HAVE_PLATFORM_FLEXCAN
 	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
 	select IMX_HAVE_PLATFORM_IMX2_WDT
 	select IMX_HAVE_PLATFORM_IMXDI_RTC
@@ -174,10 +175,6 @@ config MACH_EUKREA_MBIMXSD25_BASEBOARD
 
 endchoice
 
-endif
-
-if MACH_MX27
-
 comment "MX27 platforms:"
 
 config MACH_MX27ADS
@@ -356,7 +353,7 @@ config MACH_IMX27IPCAM
 
 endif
 
-if ARCH_MX3
+if ARCH_IMX_V6_V7
 
 comment "MX31 platforms:"
 
@@ -449,6 +446,7 @@ config MACH_MX31_3DS
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_IPU_CORE
 	select IMX_HAVE_PLATFORM_MXC_EHCI
+	select IMX_HAVE_PLATFORM_MXC_MMC
 	select IMX_HAVE_PLATFORM_MXC_NAND
 	select IMX_HAVE_PLATFORM_SPI_IMX
 	select MXC_ULPI if USB_ULPI
@@ -485,6 +483,7 @@ config MACH_QONG
 	bool "Support Dave/DENX QongEVB-LITE platform"
 	select SOC_IMX31
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_IMX2_WDT
 	help
 	  Include support for Dave/DENX QongEVB-LITE platform. This includes
 	  specific configurations for the board and its peripherals.
@@ -605,4 +604,20 @@ config MACH_VPR200
 	  Include support for VPR200 platform. This includes specific
 	  configurations for the board and its peripherals.
 
+comment "i.MX6 family:"
+
+config SOC_IMX6Q
+	bool "i.MX6 Quad support"
+	select ARM_GIC
+	select CACHE_L2X0
+	select CPU_V7
+	select HAVE_ARM_SCU
+	select HAVE_IMX_GPC
+	select HAVE_IMX_MMDC
+	select HAVE_IMX_SRC
+	select USE_OF
+
+	help
+	  This enables support for Freescale i.MX6 Quad processor.
+
 endif
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index e9eb36d..aba7321 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -1,16 +1,15 @@
 obj-$(CONFIG_IMX_HAVE_DMA_V1) += dma-v1.o
 
-obj-$(CONFIG_ARCH_MX1) += clock-imx1.o mm-imx1.o
-obj-$(CONFIG_MACH_MX21) += clock-imx21.o mm-imx21.o
+obj-$(CONFIG_SOC_IMX1) += clock-imx1.o mm-imx1.o
+obj-$(CONFIG_SOC_IMX21) += clock-imx21.o mm-imx21.o
 
-obj-$(CONFIG_ARCH_MX25) += clock-imx25.o mm-imx25.o ehci-imx25.o
+obj-$(CONFIG_SOC_IMX25) += clock-imx25.o mm-imx25.o ehci-imx25.o cpu-imx25.o
 
-obj-$(CONFIG_MACH_MX27) += cpu-imx27.o pm-imx27.o
-obj-$(CONFIG_MACH_MX27) += clock-imx27.o mm-imx27.o ehci-imx27.o
+obj-$(CONFIG_SOC_IMX27) += cpu-imx27.o pm-imx27.o
+obj-$(CONFIG_SOC_IMX27) += clock-imx27.o mm-imx27.o ehci-imx27.o
 
-obj-$(CONFIG_SOC_IMX31) += mm-imx31.o cpu-imx31.o clock-imx31.o iomux-imx31.o ehci-imx31.o
-obj-$(CONFIG_SOC_IMX35) += mm-imx35.o cpu-imx35.o clock-imx35.o ehci-imx35.o
-obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o
+obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clock-imx31.o iomux-imx31.o ehci-imx31.o
+obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clock-imx35.o ehci-imx35.o
 
 # Support for CMOS sensor interface
 obj-$(CONFIG_MX1_VIDEO) += mx1-camera-fiq.o mx1-camera-fiq-ksym.o
@@ -61,3 +60,14 @@ obj-$(CONFIG_MACH_MX35_3DS) += mach-mx35_3ds.o
 obj-$(CONFIG_MACH_EUKREA_CPUIMX35) += mach-cpuimx35.o
 obj-$(CONFIG_MACH_EUKREA_MBIMXSD35_BASEBOARD) += eukrea_mbimxsd35-baseboard.o
 obj-$(CONFIG_MACH_VPR200) += mach-vpr200.o
+
+obj-$(CONFIG_DEBUG_LL) += lluart.o
+obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
+obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o
+obj-$(CONFIG_HAVE_IMX_SRC) += src.o
+obj-$(CONFIG_CPU_V7) += head-v7.o
+AFLAGS_head-v7.o :=-Wa,-march=armv7-a
+obj-$(CONFIG_SMP) += platsmp.o
+obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
+obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
+obj-$(CONFIG_SOC_IMX6Q) += clock-imx6q.o mach-imx6q.o pm-imx6q.o
diff --git a/arch/arm/mach-imx/Makefile.boot b/arch/arm/mach-imx/Makefile.boot
index dbe6120..22d8588 100644
--- a/arch/arm/mach-imx/Makefile.boot
+++ b/arch/arm/mach-imx/Makefile.boot
@@ -17,3 +17,7 @@ initrd_phys-$(CONFIG_MACH_MX27)	:= 0xA0800000
 zreladdr-$(CONFIG_ARCH_MX3)	+= 0x80008000
 params_phys-$(CONFIG_ARCH_MX3)	:= 0x80000100
 initrd_phys-$(CONFIG_ARCH_MX3)	:= 0x80800000
+
+zreladdr-$(CONFIG_SOC_IMX6Q)	+= 0x10008000
+params_phys-$(CONFIG_SOC_IMX6Q)	:= 0x10000100
+initrd_phys-$(CONFIG_SOC_IMX6Q)	:= 0x10800000
diff --git a/arch/arm/mach-imx/cache-l2x0.c b/arch/arm/mach-imx/cache-l2x0.c
deleted file mode 100644
index 69d1322..0000000
--- a/arch/arm/mach-imx/cache-l2x0.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2009-2010 Pengutronix
- * Sascha Hauer <s.hauer@pengutronix.de>
- * Juergen Beisert <j.beisert@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/kernel.h>
-
-#include <asm/hardware/cache-l2x0.h>
-
-#include <mach/hardware.h>
-
-static int mxc_init_l2x0(void)
-{
-	void __iomem *l2x0_base;
-	void __iomem *clkctl_base;
-
-	if (!cpu_is_mx31() && !cpu_is_mx35())
-		return 0;
-
-/*
- * First of all, we must repair broken chip settings. There are some
- * i.MX35 CPUs in the wild, comming with bogus L2 cache settings. These
- * misconfigured CPUs will run amok immediately when the L2 cache gets enabled.
- * Workaraound is to setup the correct register setting prior enabling the
- * L2 cache. This should not hurt already working CPUs, as they are using the
- * same value.
- */
-#define L2_MEM_VAL 0x10
-
-	clkctl_base = ioremap(MX35_CLKCTL_BASE_ADDR, 4096);
-	if (clkctl_base != NULL) {
-		writel(0x00000515, clkctl_base + L2_MEM_VAL);
-		iounmap(clkctl_base);
-	} else {
-		pr_err("L2 cache: Cannot fix timing. Trying to continue without\n");
-	}
-
-	l2x0_base = ioremap(MX3x_L2CC_BASE_ADDR, 4096);
-	if (IS_ERR(l2x0_base)) {
-		printk(KERN_ERR "remapping L2 cache area failed with %ld\n",
-				PTR_ERR(l2x0_base));
-		return 0;
-	}
-
-	l2x0_init(l2x0_base, 0x00030024, 0x00000000);
-
-	return 0;
-}
-arch_initcall(mxc_init_l2x0);
diff --git a/arch/arm/mach-imx/clock-imx25.c b/arch/arm/mach-imx/clock-imx25.c
index e63e235..b0fec74c 100644
--- a/arch/arm/mach-imx/clock-imx25.c
+++ b/arch/arm/mach-imx/clock-imx25.c
@@ -263,6 +263,7 @@ DEFINE_CLOCK(audmux_clk, 0, CCM_CGCR1, 0, NULL, NULL, NULL);
 DEFINE_CLOCK(csi_clk,    0, CCM_CGCR1,  4, get_rate_csi, NULL,  &csi_per_clk);
 DEFINE_CLOCK(can1_clk,	 0, CCM_CGCR1,  2, get_rate_ipg, NULL, NULL);
 DEFINE_CLOCK(can2_clk,	 1, CCM_CGCR1,  3, get_rate_ipg, NULL, NULL);
+DEFINE_CLOCK(iim_clk,    0, CCM_CGCR1, 26, NULL, NULL, NULL);
 
 #define _REGISTER_CLOCK(d, n, c)	\
 	{				\
@@ -310,6 +311,7 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK("flexcan.1", NULL, can2_clk)
 	/* i.mx25 has the i.mx35 type sdma */
 	_REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
+	_REGISTER_CLOCK(NULL, "iim", iim_clk)
 };
 
 int __init mx25_clocks_init(void)
@@ -334,6 +336,10 @@ int __init mx25_clocks_init(void)
 	/* Clock source for gpt is ahb_div */
 	__raw_writel(__raw_readl(CRM_BASE+0x64) & ~(1 << 5), CRM_BASE + 0x64);
 
+	clk_enable(&iim_clk);
+	imx_print_silicon_rev("i.MX25", mx25_revision());
+	clk_disable(&iim_clk);
+
 	mxc_timer_init(&gpt_clk, MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), 54);
 
 	return 0;
diff --git a/arch/arm/mach-imx/clock-imx27.c b/arch/arm/mach-imx/clock-imx27.c
index 6912b82..88fe00a 100644
--- a/arch/arm/mach-imx/clock-imx27.c
+++ b/arch/arm/mach-imx/clock-imx27.c
@@ -583,7 +583,7 @@ DEFINE_CLOCK(emi_clk,      0, PCCR1, 19, NULL, NULL, &ahb_clk);
 DEFINE_CLOCK(dma_clk1,     0, PCCR1, 20, NULL, NULL, &ahb_clk);
 DEFINE_CLOCK(csi_clk1,     0, PCCR1, 21, NULL, NULL, &ahb_clk);
 DEFINE_CLOCK(brom_clk,     0, PCCR1, 22, NULL, NULL, &ahb_clk);
-DEFINE_CLOCK(ata_clk,      0, PCCR1, 23, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(pata_clk,      0, PCCR1, 23, NULL, NULL, &ahb_clk);
 DEFINE_CLOCK(wdog_clk,     0, PCCR1, 24, NULL, NULL, &ipg_clk);
 DEFINE_CLOCK(usb_clk,      0, PCCR1, 25, get_rate_usb, &usb_clk1, &spll_clk);
 DEFINE_CLOCK(uart6_clk1,   0, PCCR1, 26, NULL, NULL, &ipg_clk);
@@ -666,7 +666,7 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk)
 	_REGISTER_CLOCK(NULL, "emi", emi_clk)
 	_REGISTER_CLOCK(NULL, "sahara2", sahara2_clk)
-	_REGISTER_CLOCK(NULL, "ata", ata_clk)
+	_REGISTER_CLOCK("pata_imx", NULL, pata_clk)
 	_REGISTER_CLOCK(NULL, "mstick", mstick_clk)
 	_REGISTER_CLOCK("imx2-wdt.0", NULL, wdog_clk)
 	_REGISTER_CLOCK(NULL, "gpio", gpio_clk)
@@ -751,6 +751,8 @@ int __init mx27_clocks_init(unsigned long fref)
 	clk_enable(&gpio_clk);
 	clk_enable(&emi_clk);
 	clk_enable(&iim_clk);
+	imx_print_silicon_rev("i.MX27", mx27_revision());
+	clk_disable(&iim_clk);
 
 #if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC)
 	clk_enable(&uart1_clk);
diff --git a/arch/arm/mach-imx/clock-imx31.c b/arch/arm/mach-imx/clock-imx31.c
index d973770..988a281 100644
--- a/arch/arm/mach-imx/clock-imx31.c
+++ b/arch/arm/mach-imx/clock-imx31.c
@@ -476,7 +476,7 @@ 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(pata_clk,     0, MXC_CCM_CGR0, 12, NULL, NULL, &ipg_clk);
 DEFINE_CLOCK(sdma_clk1,   0, MXC_CCM_CGR0, 14, NULL, NULL, &ahb_clk);
 DEFINE_CLOCK(cspi3_clk,   2, MXC_CCM_CGR0, 16, NULL, NULL, &ipg_clk);
 DEFINE_CLOCK(rng_clk,     0, MXC_CCM_CGR0, 18, NULL, NULL, &ipg_clk);
@@ -562,7 +562,7 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
 	_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
 	_REGISTER_CLOCK(NULL, "firi", firi_clk)
-	_REGISTER_CLOCK(NULL, "ata", ata_clk)
+	_REGISTER_CLOCK("pata_imx", NULL, pata_clk)
 	_REGISTER_CLOCK(NULL, "rtic", rtic_clk)
 	_REGISTER_CLOCK(NULL, "rng", rng_clk)
 	_REGISTER_CLOCK("imx31-sdma", NULL, sdma_clk1)
@@ -611,11 +611,11 @@ int __init mx31_clocks_init(unsigned long fref)
 	clk_enable(&gpt_clk);
 	clk_enable(&emi_clk);
 	clk_enable(&iim_clk);
+	mx31_revision();
+	clk_disable(&iim_clk);
 
 	clk_enable(&serial_pll_clk);
 
-	mx31_read_cpu_rev();
-
 	if (mx31_revision() >= IMX_CHIP_REVISION_2_0) {
 		reg = __raw_readl(MXC_CCM_PMCR1);
 		/* No PLL restart on DVFS switch; enable auto EMI handshake */
diff --git a/arch/arm/mach-imx/clock-imx35.c b/arch/arm/mach-imx/clock-imx35.c
index 88b62a0..8116f11 100644
--- a/arch/arm/mach-imx/clock-imx35.c
+++ b/arch/arm/mach-imx/clock-imx35.c
@@ -354,7 +354,7 @@ static void clk_cgr_disable(struct clk *clk)
 	}
 
 DEFINE_CLOCK(asrc_clk,   0, CCM_CGR0,  0, NULL, NULL);
-DEFINE_CLOCK(ata_clk,    0, CCM_CGR0,  2, get_rate_ipg, NULL);
+DEFINE_CLOCK(pata_clk,    0, CCM_CGR0,  2, get_rate_ipg, NULL);
 /* DEFINE_CLOCK(audmux_clk, 0, CCM_CGR0,  4, NULL, NULL); */
 DEFINE_CLOCK(can1_clk,   0, CCM_CGR0,  6, get_rate_ipg, NULL);
 DEFINE_CLOCK(can2_clk,   1, CCM_CGR0,  8, get_rate_ipg, NULL);
@@ -447,7 +447,7 @@ static struct clk nfc_clk = {
 
 static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK(NULL, "asrc", asrc_clk)
-	_REGISTER_CLOCK(NULL, "ata", ata_clk)
+	_REGISTER_CLOCK("pata_imx", NULL, pata_clk)
 	_REGISTER_CLOCK("flexcan.0", NULL, can1_clk)
 	_REGISTER_CLOCK("flexcan.1", NULL, can2_clk)
 	_REGISTER_CLOCK("imx35-cspi.0", NULL, cspi1_clk)
@@ -537,7 +537,8 @@ int __init mx35_clocks_init()
 	__raw_writel(cgr3, CCM_BASE + CCM_CGR3);
 
 	clk_enable(&iim_clk);
-	mx35_read_cpu_rev();
+	imx_print_silicon_rev("i.MX35", mx35_revision());
+	clk_disable(&iim_clk);
 
 #ifdef CONFIG_MXC_USE_EPIT
 	epit_timer_init(&epit1_clk,
diff --git a/arch/arm/mach-imx/clock-imx6q.c b/arch/arm/mach-imx/clock-imx6q.c
new file mode 100644
index 0000000..e0b926d
--- /dev/null
+++ b/arch/arm/mach-imx/clock-imx6q.c
@@ -0,0 +1,2012 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <asm/div64.h>
+#include <asm/mach/map.h>
+#include <mach/clock.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+
+#define PLL_BASE		IMX_IO_ADDRESS(MX6Q_ANATOP_BASE_ADDR)
+#define PLL1_SYS		(PLL_BASE + 0x000)
+#define PLL2_BUS		(PLL_BASE + 0x030)
+#define PLL3_USB_OTG		(PLL_BASE + 0x010)
+#define PLL4_AUDIO		(PLL_BASE + 0x070)
+#define PLL5_VIDEO		(PLL_BASE + 0x0a0)
+#define PLL6_MLB		(PLL_BASE + 0x0d0)
+#define PLL7_USB_HOST		(PLL_BASE + 0x020)
+#define PLL8_ENET		(PLL_BASE + 0x0e0)
+#define PFD_480			(PLL_BASE + 0x0f0)
+#define PFD_528			(PLL_BASE + 0x100)
+#define PLL_NUM_OFFSET		0x010
+#define PLL_DENOM_OFFSET	0x020
+
+#define PFD0			7
+#define PFD1			15
+#define PFD2			23
+#define PFD3			31
+#define PFD_FRAC_MASK		0x3f
+
+#define BM_PLL_BYPASS			(0x1 << 16)
+#define BM_PLL_ENABLE			(0x1 << 13)
+#define BM_PLL_POWER_DOWN		(0x1 << 12)
+#define BM_PLL_LOCK			(0x1 << 31)
+#define BP_PLL_SYS_DIV_SELECT		0
+#define BM_PLL_SYS_DIV_SELECT		(0x7f << 0)
+#define BP_PLL_BUS_DIV_SELECT		0
+#define BM_PLL_BUS_DIV_SELECT		(0x1 << 0)
+#define BP_PLL_USB_DIV_SELECT		0
+#define BM_PLL_USB_DIV_SELECT		(0x3 << 0)
+#define BP_PLL_AV_DIV_SELECT		0
+#define BM_PLL_AV_DIV_SELECT		(0x7f << 0)
+#define BP_PLL_ENET_DIV_SELECT		0
+#define BM_PLL_ENET_DIV_SELECT		(0x3 << 0)
+#define BM_PLL_ENET_EN_PCIE		(0x1 << 19)
+#define BM_PLL_ENET_EN_SATA		(0x1 << 20)
+
+#define CCM_BASE	IMX_IO_ADDRESS(MX6Q_CCM_BASE_ADDR)
+#define CCR		(CCM_BASE + 0x00)
+#define CCDR		(CCM_BASE + 0x04)
+#define CSR		(CCM_BASE + 0x08)
+#define CCSR		(CCM_BASE + 0x0c)
+#define CACRR		(CCM_BASE + 0x10)
+#define CBCDR		(CCM_BASE + 0x14)
+#define CBCMR		(CCM_BASE + 0x18)
+#define CSCMR1		(CCM_BASE + 0x1c)
+#define CSCMR2		(CCM_BASE + 0x20)
+#define CSCDR1		(CCM_BASE + 0x24)
+#define CS1CDR		(CCM_BASE + 0x28)
+#define CS2CDR		(CCM_BASE + 0x2c)
+#define CDCDR		(CCM_BASE + 0x30)
+#define CHSCCDR		(CCM_BASE + 0x34)
+#define CSCDR2		(CCM_BASE + 0x38)
+#define CSCDR3		(CCM_BASE + 0x3c)
+#define CSCDR4		(CCM_BASE + 0x40)
+#define CWDR		(CCM_BASE + 0x44)
+#define CDHIPR		(CCM_BASE + 0x48)
+#define CDCR		(CCM_BASE + 0x4c)
+#define CTOR		(CCM_BASE + 0x50)
+#define CLPCR		(CCM_BASE + 0x54)
+#define CISR		(CCM_BASE + 0x58)
+#define CIMR		(CCM_BASE + 0x5c)
+#define CCOSR		(CCM_BASE + 0x60)
+#define CGPR		(CCM_BASE + 0x64)
+#define CCGR0		(CCM_BASE + 0x68)
+#define CCGR1		(CCM_BASE + 0x6c)
+#define CCGR2		(CCM_BASE + 0x70)
+#define CCGR3		(CCM_BASE + 0x74)
+#define CCGR4		(CCM_BASE + 0x78)
+#define CCGR5		(CCM_BASE + 0x7c)
+#define CCGR6		(CCM_BASE + 0x80)
+#define CCGR7		(CCM_BASE + 0x84)
+#define CMEOR		(CCM_BASE + 0x88)
+
+#define CG0		0
+#define CG1		2
+#define CG2		4
+#define CG3		6
+#define CG4		8
+#define CG5		10
+#define CG6		12
+#define CG7		14
+#define CG8		16
+#define CG9		18
+#define CG10		20
+#define CG11		22
+#define CG12		24
+#define CG13		26
+#define CG14		28
+#define CG15		30
+
+#define BM_CCSR_PLL1_SW_SEL		(0x1 << 2)
+#define BM_CCSR_STEP_SEL		(0x1 << 8)
+
+#define BP_CACRR_ARM_PODF		0
+#define BM_CACRR_ARM_PODF		(0x7 << 0)
+
+#define BP_CBCDR_PERIPH2_CLK2_PODF	0
+#define BM_CBCDR_PERIPH2_CLK2_PODF	(0x7 << 0)
+#define BP_CBCDR_MMDC_CH1_AXI_PODF	3
+#define BM_CBCDR_MMDC_CH1_AXI_PODF	(0x7 << 3)
+#define BP_CBCDR_AXI_SEL		6
+#define BM_CBCDR_AXI_SEL		(0x3 << 6)
+#define BP_CBCDR_IPG_PODF		8
+#define BM_CBCDR_IPG_PODF		(0x3 << 8)
+#define BP_CBCDR_AHB_PODF		10
+#define BM_CBCDR_AHB_PODF		(0x7 << 10)
+#define BP_CBCDR_AXI_PODF		16
+#define BM_CBCDR_AXI_PODF		(0x7 << 16)
+#define BP_CBCDR_MMDC_CH0_AXI_PODF	19
+#define BM_CBCDR_MMDC_CH0_AXI_PODF	(0x7 << 19)
+#define BP_CBCDR_PERIPH_CLK_SEL		25
+#define BM_CBCDR_PERIPH_CLK_SEL		(0x1 << 25)
+#define BP_CBCDR_PERIPH2_CLK_SEL	26
+#define BM_CBCDR_PERIPH2_CLK_SEL	(0x1 << 26)
+#define BP_CBCDR_PERIPH_CLK2_PODF	27
+#define BM_CBCDR_PERIPH_CLK2_PODF	(0x7 << 27)
+
+#define BP_CBCMR_GPU2D_AXI_SEL		0
+#define BM_CBCMR_GPU2D_AXI_SEL		(0x1 << 0)
+#define BP_CBCMR_GPU3D_AXI_SEL		1
+#define BM_CBCMR_GPU3D_AXI_SEL		(0x1 << 1)
+#define BP_CBCMR_GPU3D_CORE_SEL		4
+#define BM_CBCMR_GPU3D_CORE_SEL		(0x3 << 4)
+#define BP_CBCMR_GPU3D_SHADER_SEL	8
+#define BM_CBCMR_GPU3D_SHADER_SEL	(0x3 << 8)
+#define BP_CBCMR_PCIE_AXI_SEL		10
+#define BM_CBCMR_PCIE_AXI_SEL		(0x1 << 10)
+#define BP_CBCMR_VDO_AXI_SEL		11
+#define BM_CBCMR_VDO_AXI_SEL		(0x1 << 11)
+#define BP_CBCMR_PERIPH_CLK2_SEL	12
+#define BM_CBCMR_PERIPH_CLK2_SEL	(0x3 << 12)
+#define BP_CBCMR_VPU_AXI_SEL		14
+#define BM_CBCMR_VPU_AXI_SEL		(0x3 << 14)
+#define BP_CBCMR_GPU2D_CORE_SEL		16
+#define BM_CBCMR_GPU2D_CORE_SEL		(0x3 << 16)
+#define BP_CBCMR_PRE_PERIPH_CLK_SEL	18
+#define BM_CBCMR_PRE_PERIPH_CLK_SEL	(0x3 << 18)
+#define BP_CBCMR_PERIPH2_CLK2_SEL	20
+#define BM_CBCMR_PERIPH2_CLK2_SEL	(0x1 << 20)
+#define BP_CBCMR_PRE_PERIPH2_CLK_SEL	21
+#define BM_CBCMR_PRE_PERIPH2_CLK_SEL	(0x3 << 21)
+#define BP_CBCMR_GPU2D_CORE_PODF	23
+#define BM_CBCMR_GPU2D_CORE_PODF	(0x7 << 23)
+#define BP_CBCMR_GPU3D_CORE_PODF	26
+#define BM_CBCMR_GPU3D_CORE_PODF	(0x7 << 26)
+#define BP_CBCMR_GPU3D_SHADER_PODF	29
+#define BM_CBCMR_GPU3D_SHADER_PODF	(0x7 << 29)
+
+#define BP_CSCMR1_PERCLK_PODF		0
+#define BM_CSCMR1_PERCLK_PODF		(0x3f << 0)
+#define BP_CSCMR1_SSI1_SEL		10
+#define BM_CSCMR1_SSI1_SEL		(0x3 << 10)
+#define BP_CSCMR1_SSI2_SEL		12
+#define BM_CSCMR1_SSI2_SEL		(0x3 << 12)
+#define BP_CSCMR1_SSI3_SEL		14
+#define BM_CSCMR1_SSI3_SEL		(0x3 << 14)
+#define BP_CSCMR1_USDHC1_SEL		16
+#define BM_CSCMR1_USDHC1_SEL		(0x1 << 16)
+#define BP_CSCMR1_USDHC2_SEL		17
+#define BM_CSCMR1_USDHC2_SEL		(0x1 << 17)
+#define BP_CSCMR1_USDHC3_SEL		18
+#define BM_CSCMR1_USDHC3_SEL		(0x1 << 18)
+#define BP_CSCMR1_USDHC4_SEL		19
+#define BM_CSCMR1_USDHC4_SEL		(0x1 << 19)
+#define BP_CSCMR1_EMI_PODF		20
+#define BM_CSCMR1_EMI_PODF		(0x7 << 20)
+#define BP_CSCMR1_EMI_SLOW_PODF		23
+#define BM_CSCMR1_EMI_SLOW_PODF		(0x7 << 23)
+#define BP_CSCMR1_EMI_SEL		27
+#define BM_CSCMR1_EMI_SEL		(0x3 << 27)
+#define BP_CSCMR1_EMI_SLOW_SEL		29
+#define BM_CSCMR1_EMI_SLOW_SEL		(0x3 << 29)
+
+#define BP_CSCMR2_CAN_PODF		2
+#define BM_CSCMR2_CAN_PODF		(0x3f << 2)
+#define BM_CSCMR2_LDB_DI0_IPU_DIV	(0x1 << 10)
+#define BM_CSCMR2_LDB_DI1_IPU_DIV	(0x1 << 11)
+#define BP_CSCMR2_ESAI_SEL		19
+#define BM_CSCMR2_ESAI_SEL		(0x3 << 19)
+
+#define BP_CSCDR1_UART_PODF		0
+#define BM_CSCDR1_UART_PODF		(0x3f << 0)
+#define BP_CSCDR1_USDHC1_PODF		11
+#define BM_CSCDR1_USDHC1_PODF		(0x7 << 11)
+#define BP_CSCDR1_USDHC2_PODF		16
+#define BM_CSCDR1_USDHC2_PODF		(0x7 << 16)
+#define BP_CSCDR1_USDHC3_PODF		19
+#define BM_CSCDR1_USDHC3_PODF		(0x7 << 19)
+#define BP_CSCDR1_USDHC4_PODF		22
+#define BM_CSCDR1_USDHC4_PODF		(0x7 << 22)
+#define BP_CSCDR1_VPU_AXI_PODF		25
+#define BM_CSCDR1_VPU_AXI_PODF		(0x7 << 25)
+
+#define BP_CS1CDR_SSI1_PODF		0
+#define BM_CS1CDR_SSI1_PODF		(0x3f << 0)
+#define BP_CS1CDR_SSI1_PRED		6
+#define BM_CS1CDR_SSI1_PRED		(0x7 << 6)
+#define BP_CS1CDR_ESAI_PRED		9
+#define BM_CS1CDR_ESAI_PRED		(0x7 << 9)
+#define BP_CS1CDR_SSI3_PODF		16
+#define BM_CS1CDR_SSI3_PODF		(0x3f << 16)
+#define BP_CS1CDR_SSI3_PRED		22
+#define BM_CS1CDR_SSI3_PRED		(0x7 << 22)
+#define BP_CS1CDR_ESAI_PODF		25
+#define BM_CS1CDR_ESAI_PODF		(0x7 << 25)
+
+#define BP_CS2CDR_SSI2_PODF		0
+#define BM_CS2CDR_SSI2_PODF		(0x3f << 0)
+#define BP_CS2CDR_SSI2_PRED		6
+#define BM_CS2CDR_SSI2_PRED		(0x7 << 6)
+#define BP_CS2CDR_LDB_DI0_SEL		9
+#define BM_CS2CDR_LDB_DI0_SEL		(0x7 << 9)
+#define BP_CS2CDR_LDB_DI1_SEL		12
+#define BM_CS2CDR_LDB_DI1_SEL		(0x7 << 12)
+#define BP_CS2CDR_ENFC_SEL		16
+#define BM_CS2CDR_ENFC_SEL		(0x3 << 16)
+#define BP_CS2CDR_ENFC_PRED		18
+#define BM_CS2CDR_ENFC_PRED		(0x7 << 18)
+#define BP_CS2CDR_ENFC_PODF		21
+#define BM_CS2CDR_ENFC_PODF		(0x3f << 21)
+
+#define BP_CDCDR_ASRC_SERIAL_SEL	7
+#define BM_CDCDR_ASRC_SERIAL_SEL	(0x3 << 7)
+#define BP_CDCDR_ASRC_SERIAL_PODF	9
+#define BM_CDCDR_ASRC_SERIAL_PODF	(0x7 << 9)
+#define BP_CDCDR_ASRC_SERIAL_PRED	12
+#define BM_CDCDR_ASRC_SERIAL_PRED	(0x7 << 12)
+#define BP_CDCDR_SPDIF_SEL		20
+#define BM_CDCDR_SPDIF_SEL		(0x3 << 20)
+#define BP_CDCDR_SPDIF_PODF		22
+#define BM_CDCDR_SPDIF_PODF		(0x7 << 22)
+#define BP_CDCDR_SPDIF_PRED		25
+#define BM_CDCDR_SPDIF_PRED		(0x7 << 25)
+#define BP_CDCDR_HSI_TX_PODF		29
+#define BM_CDCDR_HSI_TX_PODF		(0x7 << 29)
+#define BP_CDCDR_HSI_TX_SEL		28
+#define BM_CDCDR_HSI_TX_SEL		(0x1 << 28)
+
+#define BP_CHSCCDR_IPU1_DI0_SEL		0
+#define BM_CHSCCDR_IPU1_DI0_SEL		(0x7 << 0)
+#define BP_CHSCCDR_IPU1_DI0_PRE_PODF	3
+#define BM_CHSCCDR_IPU1_DI0_PRE_PODF	(0x7 << 3)
+#define BP_CHSCCDR_IPU1_DI0_PRE_SEL	6
+#define BM_CHSCCDR_IPU1_DI0_PRE_SEL	(0x7 << 6)
+#define BP_CHSCCDR_IPU1_DI1_SEL		9
+#define BM_CHSCCDR_IPU1_DI1_SEL		(0x7 << 9)
+#define BP_CHSCCDR_IPU1_DI1_PRE_PODF	12
+#define BM_CHSCCDR_IPU1_DI1_PRE_PODF	(0x7 << 12)
+#define BP_CHSCCDR_IPU1_DI1_PRE_SEL	15
+#define BM_CHSCCDR_IPU1_DI1_PRE_SEL	(0x7 << 15)
+
+#define BP_CSCDR2_IPU2_DI0_SEL		0
+#define BM_CSCDR2_IPU2_DI0_SEL		(0x7)
+#define BP_CSCDR2_IPU2_DI0_PRE_PODF	3
+#define BM_CSCDR2_IPU2_DI0_PRE_PODF	(0x7 << 3)
+#define BP_CSCDR2_IPU2_DI0_PRE_SEL	6
+#define BM_CSCDR2_IPU2_DI0_PRE_SEL	(0x7 << 6)
+#define BP_CSCDR2_IPU2_DI1_SEL		9
+#define BM_CSCDR2_IPU2_DI1_SEL		(0x7 << 9)
+#define BP_CSCDR2_IPU2_DI1_PRE_PODF	12
+#define BM_CSCDR2_IPU2_DI1_PRE_PODF	(0x7 << 12)
+#define BP_CSCDR2_IPU2_DI1_PRE_SEL	15
+#define BM_CSCDR2_IPU2_DI1_PRE_SEL	(0x7 << 15)
+#define BP_CSCDR2_ECSPI_CLK_PODF	19
+#define BM_CSCDR2_ECSPI_CLK_PODF	(0x3f << 19)
+
+#define BP_CSCDR3_IPU1_HSP_SEL		9
+#define BM_CSCDR3_IPU1_HSP_SEL		(0x3 << 9)
+#define BP_CSCDR3_IPU1_HSP_PODF		11
+#define BM_CSCDR3_IPU1_HSP_PODF		(0x7 << 11)
+#define BP_CSCDR3_IPU2_HSP_SEL		14
+#define BM_CSCDR3_IPU2_HSP_SEL		(0x3 << 14)
+#define BP_CSCDR3_IPU2_HSP_PODF		16
+#define BM_CSCDR3_IPU2_HSP_PODF		(0x7 << 16)
+
+#define BM_CDHIPR_AXI_PODF_BUSY		(0x1 << 0)
+#define BM_CDHIPR_AHB_PODF_BUSY		(0x1 << 1)
+#define BM_CDHIPR_MMDC_CH1_PODF_BUSY	(0x1 << 2)
+#define BM_CDHIPR_PERIPH2_SEL_BUSY	(0x1 << 3)
+#define BM_CDHIPR_MMDC_CH0_PODF_BUSY	(0x1 << 4)
+#define BM_CDHIPR_PERIPH_SEL_BUSY	(0x1 << 5)
+#define BM_CDHIPR_ARM_PODF_BUSY		(0x1 << 16)
+
+#define BP_CLPCR_LPM			0
+#define BM_CLPCR_LPM			(0x3 << 0)
+#define BM_CLPCR_BYPASS_PMIC_READY	(0x1 << 2)
+#define BM_CLPCR_ARM_CLK_DIS_ON_LPM	(0x1 << 5)
+#define BM_CLPCR_SBYOS			(0x1 << 6)
+#define BM_CLPCR_DIS_REF_OSC		(0x1 << 7)
+#define BM_CLPCR_VSTBY			(0x1 << 8)
+#define BP_CLPCR_STBY_COUNT		9
+#define BM_CLPCR_STBY_COUNT		(0x3 << 9)
+#define BM_CLPCR_COSC_PWRDOWN		(0x1 << 11)
+#define BM_CLPCR_WB_PER_AT_LPM		(0x1 << 16)
+#define BM_CLPCR_WB_CORE_AT_LPM		(0x1 << 17)
+#define BM_CLPCR_BYP_MMDC_CH0_LPM_HS	(0x1 << 19)
+#define BM_CLPCR_BYP_MMDC_CH1_LPM_HS	(0x1 << 21)
+#define BM_CLPCR_MASK_CORE0_WFI		(0x1 << 22)
+#define BM_CLPCR_MASK_CORE1_WFI		(0x1 << 23)
+#define BM_CLPCR_MASK_CORE2_WFI		(0x1 << 24)
+#define BM_CLPCR_MASK_CORE3_WFI		(0x1 << 25)
+#define BM_CLPCR_MASK_SCU_IDLE		(0x1 << 26)
+#define BM_CLPCR_MASK_L2CC_IDLE		(0x1 << 27)
+
+#define FREQ_480M	480000000
+#define FREQ_528M	528000000
+#define FREQ_594M	594000000
+#define FREQ_650M	650000000
+#define FREQ_1300M	1300000000
+
+static struct clk pll1_sys;
+static struct clk pll2_bus;
+static struct clk pll3_usb_otg;
+static struct clk pll4_audio;
+static struct clk pll5_video;
+static struct clk pll6_mlb;
+static struct clk pll7_usb_host;
+static struct clk pll8_enet;
+static struct clk apbh_dma_clk;
+static struct clk arm_clk;
+static struct clk ipg_clk;
+static struct clk ahb_clk;
+static struct clk axi_clk;
+static struct clk mmdc_ch0_axi_clk;
+static struct clk mmdc_ch1_axi_clk;
+static struct clk periph_clk;
+static struct clk periph_pre_clk;
+static struct clk periph_clk2_clk;
+static struct clk periph2_clk;
+static struct clk periph2_pre_clk;
+static struct clk periph2_clk2_clk;
+static struct clk gpu2d_core_clk;
+static struct clk gpu3d_core_clk;
+static struct clk gpu3d_shader_clk;
+static struct clk ipg_perclk;
+static struct clk emi_clk;
+static struct clk emi_slow_clk;
+static struct clk can1_clk;
+static struct clk uart_clk;
+static struct clk usdhc1_clk;
+static struct clk usdhc2_clk;
+static struct clk usdhc3_clk;
+static struct clk usdhc4_clk;
+static struct clk vpu_clk;
+static struct clk hsi_tx_clk;
+static struct clk ipu1_di0_pre_clk;
+static struct clk ipu1_di1_pre_clk;
+static struct clk ipu2_di0_pre_clk;
+static struct clk ipu2_di1_pre_clk;
+static struct clk ipu1_clk;
+static struct clk ipu2_clk;
+static struct clk ssi1_clk;
+static struct clk ssi3_clk;
+static struct clk esai_clk;
+static struct clk ssi2_clk;
+static struct clk spdif_clk;
+static struct clk asrc_serial_clk;
+static struct clk gpu2d_axi_clk;
+static struct clk gpu3d_axi_clk;
+static struct clk pcie_clk;
+static struct clk vdo_axi_clk;
+static struct clk ldb_di0_clk;
+static struct clk ldb_di1_clk;
+static struct clk ipu1_di0_clk;
+static struct clk ipu1_di1_clk;
+static struct clk ipu2_di0_clk;
+static struct clk ipu2_di1_clk;
+static struct clk enfc_clk;
+static struct clk dummy_clk = {};
+
+static unsigned long external_high_reference;
+static unsigned long external_low_reference;
+static unsigned long oscillator_reference;
+
+static unsigned long get_oscillator_reference_clock_rate(struct clk *clk)
+{
+	return oscillator_reference;
+}
+
+static unsigned long get_high_reference_clock_rate(struct clk *clk)
+{
+	return external_high_reference;
+}
+
+static unsigned long get_low_reference_clock_rate(struct clk *clk)
+{
+	return external_low_reference;
+}
+
+static struct clk ckil_clk = {
+	.get_rate = get_low_reference_clock_rate,
+};
+
+static struct clk ckih_clk = {
+	.get_rate = get_high_reference_clock_rate,
+};
+
+static struct clk osc_clk = {
+	.get_rate = get_oscillator_reference_clock_rate,
+};
+
+static inline void __iomem *pll_get_reg_addr(struct clk *pll)
+{
+	if (pll == &pll1_sys)
+		return PLL1_SYS;
+	else if (pll == &pll2_bus)
+		return PLL2_BUS;
+	else if (pll == &pll3_usb_otg)
+		return PLL3_USB_OTG;
+	else if (pll == &pll4_audio)
+		return PLL4_AUDIO;
+	else if (pll == &pll5_video)
+		return PLL5_VIDEO;
+	else if (pll == &pll6_mlb)
+		return PLL6_MLB;
+	else if (pll == &pll7_usb_host)
+		return PLL7_USB_HOST;
+	else if (pll == &pll8_enet)
+		return PLL8_ENET;
+	else
+		BUG();
+
+	return NULL;
+}
+
+static int pll_enable(struct clk *clk)
+{
+	int timeout = 0x100000;
+	void __iomem *reg;
+	u32 val;
+
+	reg = pll_get_reg_addr(clk);
+	val = readl_relaxed(reg);
+	val &= ~BM_PLL_BYPASS;
+	val &= ~BM_PLL_POWER_DOWN;
+	/* 480MHz PLLs have the opposite definition for power bit */
+	if (clk == &pll3_usb_otg || clk == &pll7_usb_host)
+		val |= BM_PLL_POWER_DOWN;
+	writel_relaxed(val, reg);
+
+	/* Wait for PLL to lock */
+	while (!(readl_relaxed(reg) & BM_PLL_LOCK) && --timeout)
+		cpu_relax();
+
+	if (unlikely(!timeout))
+		return -EBUSY;
+
+	/* Enable the PLL output now */
+	val = readl_relaxed(reg);
+	val |= BM_PLL_ENABLE;
+	writel_relaxed(val, reg);
+
+	return 0;
+}
+
+static void pll_disable(struct clk *clk)
+{
+	void __iomem *reg;
+	u32 val;
+
+	reg = pll_get_reg_addr(clk);
+	val = readl_relaxed(reg);
+	val &= ~BM_PLL_ENABLE;
+	val |= BM_PLL_BYPASS;
+	val |= BM_PLL_POWER_DOWN;
+	if (clk == &pll3_usb_otg || clk == &pll7_usb_host)
+		val &= ~BM_PLL_POWER_DOWN;
+	writel_relaxed(val, reg);
+}
+
+static unsigned long pll1_sys_get_rate(struct clk *clk)
+{
+	u32 div = (readl_relaxed(PLL1_SYS) & BM_PLL_SYS_DIV_SELECT) >>
+		  BP_PLL_SYS_DIV_SELECT;
+
+	return clk_get_rate(clk->parent) * div / 2;
+}
+
+static int pll1_sys_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 val, div;
+
+	if (rate < FREQ_650M || rate > FREQ_1300M)
+		return -EINVAL;
+
+	div = rate * 2 / clk_get_rate(clk->parent);
+	val = readl_relaxed(PLL1_SYS);
+	val &= ~BM_PLL_SYS_DIV_SELECT;
+	val |= div << BP_PLL_SYS_DIV_SELECT;
+	writel_relaxed(val, PLL1_SYS);
+
+	return 0;
+}
+
+static unsigned long pll8_enet_get_rate(struct clk *clk)
+{
+	u32 div = (readl_relaxed(PLL8_ENET) & BM_PLL_ENET_DIV_SELECT) >>
+		  BP_PLL_ENET_DIV_SELECT;
+
+	switch (div) {
+	case 0:
+		return 25000000;
+	case 1:
+		return 50000000;
+	case 2:
+		return 100000000;
+	case 3:
+		return 125000000;
+	}
+
+	return 0;
+}
+
+static int pll8_enet_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 val, div;
+
+	switch (rate) {
+	case 25000000:
+		div = 0;
+		break;
+	case 50000000:
+		div = 1;
+		break;
+	case 100000000:
+		div = 2;
+		break;
+	case 125000000:
+		div = 3;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	val = readl_relaxed(PLL8_ENET);
+	val &= ~BM_PLL_ENET_DIV_SELECT;
+	val |= div << BP_PLL_ENET_DIV_SELECT;
+	writel_relaxed(val, PLL8_ENET);
+
+	return 0;
+}
+
+static unsigned long pll_av_get_rate(struct clk *clk)
+{
+	void __iomem *reg = (clk == &pll4_audio) ? PLL4_AUDIO : PLL5_VIDEO;
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	u32 mfn = readl_relaxed(reg + PLL_NUM_OFFSET);
+	u32 mfd = readl_relaxed(reg + PLL_DENOM_OFFSET);
+	u32 div = (readl_relaxed(reg) & BM_PLL_AV_DIV_SELECT) >>
+		  BP_PLL_AV_DIV_SELECT;
+
+	return (parent_rate * div) + ((parent_rate / mfd) * mfn);
+}
+
+static int pll_av_set_rate(struct clk *clk, unsigned long rate)
+{
+	void __iomem *reg = (clk == &pll4_audio) ? PLL4_AUDIO : PLL5_VIDEO;
+	unsigned int parent_rate = clk_get_rate(clk->parent);
+	u32 val, div;
+	u32 mfn, mfd = 1000000;
+	s64 temp64;
+
+	if (rate < FREQ_650M || rate > FREQ_1300M)
+		return -EINVAL;
+
+	div = rate / parent_rate;
+	temp64 = (u64) (rate - div * parent_rate);
+	temp64 *= mfd;
+	do_div(temp64, parent_rate);
+	mfn = temp64;
+
+	val = readl_relaxed(reg);
+	val &= ~BM_PLL_AV_DIV_SELECT;
+	val |= div << BP_PLL_AV_DIV_SELECT;
+	writel_relaxed(val, reg);
+	writel_relaxed(mfn, reg + PLL_NUM_OFFSET);
+	writel_relaxed(mfd, reg + PLL_DENOM_OFFSET);
+
+	return 0;
+}
+
+static void __iomem *pll_get_div_reg_bit(struct clk *clk, u32 *bp, u32 *bm)
+{
+	void __iomem *reg;
+
+	if (clk == &pll2_bus) {
+		reg = PLL2_BUS;
+		*bp = BP_PLL_BUS_DIV_SELECT;
+		*bm = BM_PLL_BUS_DIV_SELECT;
+	} else if (clk == &pll3_usb_otg) {
+		reg = PLL3_USB_OTG;
+		*bp = BP_PLL_USB_DIV_SELECT;
+		*bm = BM_PLL_USB_DIV_SELECT;
+	} else if (clk == &pll7_usb_host) {
+		reg = PLL7_USB_HOST;
+		*bp = BP_PLL_USB_DIV_SELECT;
+		*bm = BM_PLL_USB_DIV_SELECT;
+	} else {
+		BUG();
+	}
+
+	return reg;
+}
+
+static unsigned long pll_get_rate(struct clk *clk)
+{
+	void __iomem *reg;
+	u32 div, bp, bm;
+
+	reg = pll_get_div_reg_bit(clk, &bp, &bm);
+	div = (readl_relaxed(reg) & bm) >> bp;
+
+	return (div == 1) ? clk_get_rate(clk->parent) * 22 :
+			    clk_get_rate(clk->parent) * 20;
+}
+
+static int pll_set_rate(struct clk *clk, unsigned long rate)
+{
+	void __iomem *reg;
+	u32 val, div, bp, bm;
+
+	if (rate == FREQ_528M)
+		div = 1;
+	else if (rate == FREQ_480M)
+		div = 0;
+	else
+		return -EINVAL;
+
+	reg = pll_get_div_reg_bit(clk, &bp, &bm);
+	val = readl_relaxed(reg);
+	val &= ~bm;
+	val |= div << bp;
+	writel_relaxed(val, reg);
+
+	return 0;
+}
+
+#define pll2_bus_get_rate	pll_get_rate
+#define pll2_bus_set_rate	pll_set_rate
+#define pll3_usb_otg_get_rate	pll_get_rate
+#define pll3_usb_otg_set_rate	pll_set_rate
+#define pll7_usb_host_get_rate	pll_get_rate
+#define pll7_usb_host_set_rate	pll_set_rate
+#define pll4_audio_get_rate	pll_av_get_rate
+#define pll4_audio_set_rate	pll_av_set_rate
+#define pll5_video_get_rate	pll_av_get_rate
+#define pll5_video_set_rate	pll_av_set_rate
+#define pll6_mlb_get_rate	NULL
+#define pll6_mlb_set_rate	NULL
+
+#define DEF_PLL(name)					\
+	static struct clk name = {			\
+		.enable		= pll_enable,		\
+		.disable	= pll_disable,		\
+		.get_rate	= name##_get_rate,	\
+		.set_rate	= name##_set_rate,	\
+		.parent		= &osc_clk,		\
+	}
+
+DEF_PLL(pll1_sys);
+DEF_PLL(pll2_bus);
+DEF_PLL(pll3_usb_otg);
+DEF_PLL(pll4_audio);
+DEF_PLL(pll5_video);
+DEF_PLL(pll6_mlb);
+DEF_PLL(pll7_usb_host);
+DEF_PLL(pll8_enet);
+
+static unsigned long pfd_get_rate(struct clk *clk)
+{
+	u64 tmp = (u64) clk_get_rate(clk->parent) * 18;
+	u32 frac, bp_frac;
+
+	if (apbh_dma_clk.usecount == 0)
+		apbh_dma_clk.enable(&apbh_dma_clk);
+
+	bp_frac = clk->enable_shift - 7;
+	frac = readl_relaxed(clk->enable_reg) >> bp_frac & PFD_FRAC_MASK;
+	do_div(tmp, frac);
+
+	return tmp;
+}
+
+static int pfd_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 val, frac, bp_frac;
+	u64 tmp = (u64) clk_get_rate(clk->parent) * 18;
+
+	if (apbh_dma_clk.usecount == 0)
+		apbh_dma_clk.enable(&apbh_dma_clk);
+
+	/*
+	 * Round up the divider so that we don't set a rate
+	 * higher than what is requested
+	 */
+	tmp += rate / 2;
+	do_div(tmp, rate);
+	frac = tmp;
+	frac = (frac < 12) ? 12 : frac;
+	frac = (frac > 35) ? 35 : frac;
+
+	/*
+	 * The frac field always starts from 7 bits lower
+	 * position of enable bit
+	 */
+	bp_frac = clk->enable_shift - 7;
+	val = readl_relaxed(clk->enable_reg);
+	val &= ~(PFD_FRAC_MASK << bp_frac);
+	val |= frac << bp_frac;
+	writel_relaxed(val, clk->enable_reg);
+
+	tmp = (u64) clk_get_rate(clk->parent) * 18;
+	do_div(tmp, frac);
+
+	if (apbh_dma_clk.usecount == 0)
+		apbh_dma_clk.disable(&apbh_dma_clk);
+
+	return 0;
+}
+
+static unsigned long pfd_round_rate(struct clk *clk, unsigned long rate)
+{
+	u32 frac;
+	u64 tmp;
+
+	tmp = (u64) clk_get_rate(clk->parent) * 18;
+	tmp += rate / 2;
+	do_div(tmp, rate);
+	frac = tmp;
+	frac = (frac < 12) ? 12 : frac;
+	frac = (frac > 35) ? 35 : frac;
+	tmp = (u64) clk_get_rate(clk->parent) * 18;
+	do_div(tmp, frac);
+
+	return tmp;
+}
+
+static int pfd_enable(struct clk *clk)
+{
+	u32 val;
+
+	if (apbh_dma_clk.usecount == 0)
+		apbh_dma_clk.enable(&apbh_dma_clk);
+
+	val = readl_relaxed(clk->enable_reg);
+	val &= ~(1 << clk->enable_shift);
+	writel_relaxed(val, clk->enable_reg);
+
+	if (apbh_dma_clk.usecount == 0)
+		apbh_dma_clk.disable(&apbh_dma_clk);
+
+	return 0;
+}
+
+static void pfd_disable(struct clk *clk)
+{
+	u32 val;
+
+	if (apbh_dma_clk.usecount == 0)
+		apbh_dma_clk.enable(&apbh_dma_clk);
+
+	val = readl_relaxed(clk->enable_reg);
+	val |= 1 << clk->enable_shift;
+	writel_relaxed(val, clk->enable_reg);
+
+	if (apbh_dma_clk.usecount == 0)
+		apbh_dma_clk.disable(&apbh_dma_clk);
+}
+
+#define DEF_PFD(name, er, es, p)			\
+	static struct clk name = {			\
+		.enable_reg	= er,			\
+		.enable_shift	= es,			\
+		.enable		= pfd_enable,		\
+		.disable	= pfd_disable,		\
+		.get_rate	= pfd_get_rate,		\
+		.set_rate	= pfd_set_rate,		\
+		.round_rate	= pfd_round_rate,	\
+		.parent		= p,			\
+	}
+
+DEF_PFD(pll2_pfd_352m, PFD_528, PFD0, &pll2_bus);
+DEF_PFD(pll2_pfd_594m, PFD_528, PFD1, &pll2_bus);
+DEF_PFD(pll2_pfd_400m, PFD_528, PFD2, &pll2_bus);
+DEF_PFD(pll3_pfd_720m, PFD_480, PFD0, &pll3_usb_otg);
+DEF_PFD(pll3_pfd_540m, PFD_480, PFD1, &pll3_usb_otg);
+DEF_PFD(pll3_pfd_508m, PFD_480, PFD2, &pll3_usb_otg);
+DEF_PFD(pll3_pfd_454m, PFD_480, PFD3, &pll3_usb_otg);
+
+static unsigned long pll2_200m_get_rate(struct clk *clk)
+{
+	return clk_get_rate(clk->parent) / 2;
+}
+
+static struct clk pll2_200m = {
+	.parent = &pll2_pfd_400m,
+	.get_rate = pll2_200m_get_rate,
+};
+
+static unsigned long pll3_120m_get_rate(struct clk *clk)
+{
+	return clk_get_rate(clk->parent) / 4;
+}
+
+static struct clk pll3_120m = {
+	.parent = &pll3_usb_otg,
+	.get_rate = pll3_120m_get_rate,
+};
+
+static unsigned long pll3_80m_get_rate(struct clk *clk)
+{
+	return clk_get_rate(clk->parent) / 6;
+}
+
+static struct clk pll3_80m = {
+	.parent = &pll3_usb_otg,
+	.get_rate = pll3_80m_get_rate,
+};
+
+static unsigned long pll3_60m_get_rate(struct clk *clk)
+{
+	return clk_get_rate(clk->parent) / 8;
+}
+
+static struct clk pll3_60m = {
+	.parent = &pll3_usb_otg,
+	.get_rate = pll3_60m_get_rate,
+};
+
+static int pll1_sw_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 val = readl_relaxed(CCSR);
+
+	if (parent == &pll1_sys) {
+		val &= ~BM_CCSR_PLL1_SW_SEL;
+		val &= ~BM_CCSR_STEP_SEL;
+	} else if (parent == &osc_clk) {
+		val |= BM_CCSR_PLL1_SW_SEL;
+		val &= ~BM_CCSR_STEP_SEL;
+	} else if (parent == &pll2_pfd_400m) {
+		val |= BM_CCSR_PLL1_SW_SEL;
+		val |= BM_CCSR_STEP_SEL;
+	} else {
+		return -EINVAL;
+	}
+
+	writel_relaxed(val, CCSR);
+
+	return 0;
+}
+
+static struct clk pll1_sw_clk = {
+	.parent = &pll1_sys,
+	.set_parent = pll1_sw_clk_set_parent,
+};
+
+static void calc_pred_podf_dividers(u32 div, u32 *pred, u32 *podf)
+{
+	u32 min_pred, temp_pred, old_err, err;
+
+	if (div >= 512) {
+		*pred = 8;
+		*podf = 64;
+	} else if (div >= 8) {
+		min_pred = (div - 1) / 64 + 1;
+		old_err = 8;
+		for (temp_pred = 8; temp_pred >= min_pred; temp_pred--) {
+			err = div % temp_pred;
+			if (err == 0) {
+				*pred = temp_pred;
+				break;
+			}
+			err = temp_pred - err;
+			if (err < old_err) {
+				old_err = err;
+				*pred = temp_pred;
+			}
+		}
+		*podf = (div + *pred - 1) / *pred;
+	} else if (div < 8) {
+		*pred = div;
+		*podf = 1;
+	}
+}
+
+static int _clk_enable(struct clk *clk)
+{
+	u32 reg;
+	reg = readl_relaxed(clk->enable_reg);
+	reg |= 0x3 << clk->enable_shift;
+	writel_relaxed(reg, clk->enable_reg);
+
+	return 0;
+}
+
+static void _clk_disable(struct clk *clk)
+{
+	u32 reg;
+	reg = readl_relaxed(clk->enable_reg);
+	reg &= ~(0x3 << clk->enable_shift);
+	writel_relaxed(reg, clk->enable_reg);
+}
+
+struct divider {
+	struct clk *clk;
+	void __iomem *reg;
+	u32 bp_pred;
+	u32 bm_pred;
+	u32 bp_podf;
+	u32 bm_podf;
+};
+
+#define DEF_CLK_DIV1(d, c, r, b)				\
+	static struct divider d = {				\
+		.clk = c,					\
+		.reg = r,					\
+		.bp_podf = BP_##r##_##b##_PODF,			\
+		.bm_podf = BM_##r##_##b##_PODF,			\
+	}
+
+DEF_CLK_DIV1(arm_div,		&arm_clk,		CACRR,	ARM);
+DEF_CLK_DIV1(ipg_div,		&ipg_clk,		CBCDR,	IPG);
+DEF_CLK_DIV1(ahb_div,		&ahb_clk,		CBCDR,	AHB);
+DEF_CLK_DIV1(axi_div,		&axi_clk,		CBCDR,	AXI);
+DEF_CLK_DIV1(mmdc_ch0_axi_div,	&mmdc_ch0_axi_clk,	CBCDR,	MMDC_CH0_AXI);
+DEF_CLK_DIV1(mmdc_ch1_axi_div,	&mmdc_ch1_axi_clk,	CBCDR,	MMDC_CH1_AXI);
+DEF_CLK_DIV1(periph_clk2_div,	&periph_clk2_clk,	CBCDR,	PERIPH_CLK2);
+DEF_CLK_DIV1(periph2_clk2_div,	&periph2_clk2_clk,	CBCDR,	PERIPH2_CLK2);
+DEF_CLK_DIV1(gpu2d_core_div,	&gpu2d_core_clk,	CBCMR,	GPU2D_CORE);
+DEF_CLK_DIV1(gpu3d_core_div,	&gpu3d_core_clk,	CBCMR,	GPU3D_CORE);
+DEF_CLK_DIV1(gpu3d_shader_div,	&gpu3d_shader_clk,	CBCMR,	GPU3D_SHADER);
+DEF_CLK_DIV1(ipg_perclk_div,	&ipg_perclk,		CSCMR1,	PERCLK);
+DEF_CLK_DIV1(emi_div,		&emi_clk,		CSCMR1,	EMI);
+DEF_CLK_DIV1(emi_slow_div,	&emi_slow_clk,		CSCMR1,	EMI_SLOW);
+DEF_CLK_DIV1(can_div,		&can1_clk,		CSCMR2,	CAN);
+DEF_CLK_DIV1(uart_div,		&uart_clk,		CSCDR1,	UART);
+DEF_CLK_DIV1(usdhc1_div,	&usdhc1_clk,		CSCDR1,	USDHC1);
+DEF_CLK_DIV1(usdhc2_div,	&usdhc2_clk,		CSCDR1,	USDHC2);
+DEF_CLK_DIV1(usdhc3_div,	&usdhc3_clk,		CSCDR1,	USDHC3);
+DEF_CLK_DIV1(usdhc4_div,	&usdhc4_clk,		CSCDR1,	USDHC4);
+DEF_CLK_DIV1(vpu_div,		&vpu_clk,		CSCDR1,	VPU_AXI);
+DEF_CLK_DIV1(hsi_tx_div,	&hsi_tx_clk,		CDCDR,	HSI_TX);
+DEF_CLK_DIV1(ipu1_di0_pre_div,	&ipu1_di0_pre_clk,	CHSCCDR, IPU1_DI0_PRE);
+DEF_CLK_DIV1(ipu1_di1_pre_div,	&ipu1_di1_pre_clk,	CHSCCDR, IPU1_DI1_PRE);
+DEF_CLK_DIV1(ipu2_di0_pre_div,	&ipu2_di0_pre_clk,	CSCDR2,	IPU2_DI0_PRE);
+DEF_CLK_DIV1(ipu2_di1_pre_div,	&ipu2_di1_pre_clk,	CSCDR2,	IPU2_DI1_PRE);
+DEF_CLK_DIV1(ipu1_div,		&ipu1_clk,		CSCDR3,	IPU1_HSP);
+DEF_CLK_DIV1(ipu2_div,		&ipu2_clk,		CSCDR3,	IPU2_HSP);
+
+#define DEF_CLK_DIV2(d, c, r, b)				\
+	static struct divider d = {				\
+		.clk = c,					\
+		.reg = r,					\
+		.bp_pred = BP_##r##_##b##_PRED,			\
+		.bm_pred = BM_##r##_##b##_PRED,			\
+		.bp_podf = BP_##r##_##b##_PODF,			\
+		.bm_podf = BM_##r##_##b##_PODF,			\
+	}
+
+DEF_CLK_DIV2(ssi1_div,		&ssi1_clk,		CS1CDR,	SSI1);
+DEF_CLK_DIV2(ssi3_div,		&ssi3_clk,		CS1CDR,	SSI3);
+DEF_CLK_DIV2(esai_div,		&esai_clk,		CS1CDR,	ESAI);
+DEF_CLK_DIV2(ssi2_div,		&ssi2_clk,		CS2CDR,	SSI2);
+DEF_CLK_DIV2(enfc_div,		&enfc_clk,		CS2CDR,	ENFC);
+DEF_CLK_DIV2(spdif_div,		&spdif_clk,		CDCDR,	SPDIF);
+DEF_CLK_DIV2(asrc_serial_div,	&asrc_serial_clk,	CDCDR,	ASRC_SERIAL);
+
+static struct divider *dividers[] = {
+	&arm_div,
+	&ipg_div,
+	&ahb_div,
+	&axi_div,
+	&mmdc_ch0_axi_div,
+	&mmdc_ch1_axi_div,
+	&periph_clk2_div,
+	&periph2_clk2_div,
+	&gpu2d_core_div,
+	&gpu3d_core_div,
+	&gpu3d_shader_div,
+	&ipg_perclk_div,
+	&emi_div,
+	&emi_slow_div,
+	&can_div,
+	&uart_div,
+	&usdhc1_div,
+	&usdhc2_div,
+	&usdhc3_div,
+	&usdhc4_div,
+	&vpu_div,
+	&hsi_tx_div,
+	&ipu1_di0_pre_div,
+	&ipu1_di1_pre_div,
+	&ipu2_di0_pre_div,
+	&ipu2_di1_pre_div,
+	&ipu1_div,
+	&ipu2_div,
+	&ssi1_div,
+	&ssi3_div,
+	&esai_div,
+	&ssi2_div,
+	&enfc_div,
+	&spdif_div,
+	&asrc_serial_div,
+};
+
+static unsigned long ldb_di_clk_get_rate(struct clk *clk)
+{
+	u32 val = readl_relaxed(CSCMR2);
+
+	val &= (clk == &ldb_di0_clk) ? BM_CSCMR2_LDB_DI0_IPU_DIV :
+				       BM_CSCMR2_LDB_DI1_IPU_DIV;
+	if (val)
+		return clk_get_rate(clk->parent) / 7;
+	else
+		return clk_get_rate(clk->parent) * 2 / 7;
+}
+
+static int ldb_di_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	u32 val = readl_relaxed(CSCMR2);
+
+	if (rate * 7 <= parent_rate + parent_rate / 20)
+		val |= BM_CSCMR2_LDB_DI0_IPU_DIV;
+	else
+		val &= ~BM_CSCMR2_LDB_DI0_IPU_DIV;
+
+	writel_relaxed(val, CSCMR2);
+
+	return 0;
+}
+
+static unsigned long ldb_di_clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+
+	if (rate * 7 <= parent_rate + parent_rate / 20)
+		return parent_rate / 7;
+	else
+		return 2 * parent_rate / 7;
+}
+
+static unsigned long _clk_get_rate(struct clk *clk)
+{
+	struct divider *d;
+	u32 val, pred, podf;
+	int i, num;
+
+	if (clk == &ldb_di0_clk || clk == &ldb_di1_clk)
+		return ldb_di_clk_get_rate(clk);
+
+	num = ARRAY_SIZE(dividers);
+	for (i = 0; i < num; i++)
+		if (dividers[i]->clk == clk) {
+			d = dividers[i];
+			break;
+		}
+	if (i == num)
+		return clk_get_rate(clk->parent);
+
+	val = readl_relaxed(d->reg);
+	pred = ((val & d->bm_pred) >> d->bp_pred) + 1;
+	podf = ((val & d->bm_podf) >> d->bp_podf) + 1;
+
+	return clk_get_rate(clk->parent) / (pred * podf);
+}
+
+static int clk_busy_wait(struct clk *clk)
+{
+	int timeout = 0x100000;
+	u32 bm;
+
+	if (clk == &axi_clk)
+		bm = BM_CDHIPR_AXI_PODF_BUSY;
+	else if (clk == &ahb_clk)
+		bm = BM_CDHIPR_AHB_PODF_BUSY;
+	else if (clk == &mmdc_ch0_axi_clk)
+		bm = BM_CDHIPR_MMDC_CH0_PODF_BUSY;
+	else if (clk == &periph_clk)
+		bm = BM_CDHIPR_PERIPH_SEL_BUSY;
+	else if (clk == &arm_clk)
+		bm = BM_CDHIPR_ARM_PODF_BUSY;
+	else
+		return -EINVAL;
+
+	while ((readl_relaxed(CDHIPR) & bm) && --timeout)
+		cpu_relax();
+
+	if (unlikely(!timeout))
+		return -EBUSY;
+
+	return 0;
+}
+
+static int _clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	struct divider *d;
+	u32 val, div, max_div, pred = 0, podf;
+	int i, num;
+
+	if (clk == &ldb_di0_clk || clk == &ldb_di1_clk)
+		return ldb_di_clk_set_rate(clk, rate);
+
+	num = ARRAY_SIZE(dividers);
+	for (i = 0; i < num; i++)
+		if (dividers[i]->clk == clk) {
+			d = dividers[i];
+			break;
+		}
+	if (i == num)
+		return -EINVAL;
+
+	max_div = ((d->bm_pred >> d->bp_pred) + 1) *
+		  ((d->bm_pred >> d->bp_pred) + 1);
+
+	div = parent_rate / rate;
+	if (div == 0)
+		div++;
+
+	if ((parent_rate / div != rate) || div > max_div)
+		return -EINVAL;
+
+	if (d->bm_pred) {
+		calc_pred_podf_dividers(div, &pred, &podf);
+	} else {
+		pred = 1;
+		podf = div;
+	}
+
+	val = readl_relaxed(d->reg);
+	val &= ~(d->bm_pred | d->bm_podf);
+	val |= (pred - 1) << d->bp_pred | (podf - 1) << d->bp_podf;
+	writel_relaxed(val, d->reg);
+
+	if (clk == &axi_clk || clk == &ahb_clk ||
+	    clk == &mmdc_ch0_axi_clk || clk == &arm_clk)
+		return clk_busy_wait(clk);
+
+	return 0;
+}
+
+static unsigned long _clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	u32 div = parent_rate / rate;
+	u32 div_max, pred = 0, podf;
+	struct divider *d;
+	int i, num;
+
+	if (clk == &ldb_di0_clk || clk == &ldb_di1_clk)
+		return ldb_di_clk_round_rate(clk, rate);
+
+	num = ARRAY_SIZE(dividers);
+	for (i = 0; i < num; i++)
+		if (dividers[i]->clk == clk) {
+			d = dividers[i];
+			break;
+		}
+	if (i == num)
+		return -EINVAL;
+
+	if (div == 0 || parent_rate % rate)
+		div++;
+
+	if (d->bm_pred) {
+		calc_pred_podf_dividers(div, &pred, &podf);
+		div = pred * podf;
+	} else {
+		div_max = (d->bm_podf >> d->bp_podf) + 1;
+		if (div > div_max)
+			div = div_max;
+	}
+
+	return parent_rate / div;
+}
+
+struct multiplexer {
+	struct clk *clk;
+	void __iomem *reg;
+	u32 bp;
+	u32 bm;
+	int pnum;
+	struct clk *parents[];
+};
+
+static struct multiplexer axi_mux = {
+	.clk = &axi_clk,
+	.reg = CBCDR,
+	.bp = BP_CBCDR_AXI_SEL,
+	.bm = BM_CBCDR_AXI_SEL,
+	.parents = {
+		&periph_clk,
+		&pll2_pfd_400m,
+		&pll3_pfd_540m,
+		NULL
+	},
+};
+
+static struct multiplexer periph_mux = {
+	.clk = &periph_clk,
+	.reg = CBCDR,
+	.bp = BP_CBCDR_PERIPH_CLK_SEL,
+	.bm = BM_CBCDR_PERIPH_CLK_SEL,
+	.parents = {
+		&periph_pre_clk,
+		&periph_clk2_clk,
+		NULL
+	},
+};
+
+static struct multiplexer periph_pre_mux = {
+	.clk = &periph_pre_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_PRE_PERIPH_CLK_SEL,
+	.bm = BM_CBCMR_PRE_PERIPH_CLK_SEL,
+	.parents = {
+		&pll2_bus,
+		&pll2_pfd_400m,
+		&pll2_pfd_352m,
+		&pll2_200m,
+		NULL
+	},
+};
+
+static struct multiplexer periph_clk2_mux = {
+	.clk = &periph_clk2_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_PERIPH_CLK2_SEL,
+	.bm = BM_CBCMR_PERIPH_CLK2_SEL,
+	.parents = {
+		&pll3_usb_otg,
+		&osc_clk,
+		NULL
+	},
+};
+
+static struct multiplexer periph2_mux = {
+	.clk = &periph2_clk,
+	.reg = CBCDR,
+	.bp = BP_CBCDR_PERIPH2_CLK_SEL,
+	.bm = BM_CBCDR_PERIPH2_CLK_SEL,
+	.parents = {
+		&periph2_pre_clk,
+		&periph2_clk2_clk,
+		NULL
+	},
+};
+
+static struct multiplexer periph2_pre_mux = {
+	.clk = &periph2_pre_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_PRE_PERIPH2_CLK_SEL,
+	.bm = BM_CBCMR_PRE_PERIPH2_CLK_SEL,
+	.parents = {
+		&pll2_bus,
+		&pll2_pfd_400m,
+		&pll2_pfd_352m,
+		&pll2_200m,
+		NULL
+	},
+};
+
+static struct multiplexer periph2_clk2_mux = {
+	.clk = &periph2_clk2_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_PERIPH2_CLK2_SEL,
+	.bm = BM_CBCMR_PERIPH2_CLK2_SEL,
+	.parents = {
+		&pll3_usb_otg,
+		&osc_clk,
+		NULL
+	},
+};
+
+static struct multiplexer gpu2d_axi_mux = {
+	.clk = &gpu2d_axi_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_GPU2D_AXI_SEL,
+	.bm = BM_CBCMR_GPU2D_AXI_SEL,
+	.parents = {
+		&axi_clk,
+		&ahb_clk,
+		NULL
+	},
+};
+
+static struct multiplexer gpu3d_axi_mux = {
+	.clk = &gpu3d_axi_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_GPU3D_AXI_SEL,
+	.bm = BM_CBCMR_GPU3D_AXI_SEL,
+	.parents = {
+		&axi_clk,
+		&ahb_clk,
+		NULL
+	},
+};
+
+static struct multiplexer gpu3d_core_mux = {
+	.clk = &gpu3d_core_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_GPU3D_CORE_SEL,
+	.bm = BM_CBCMR_GPU3D_CORE_SEL,
+	.parents = {
+		&mmdc_ch0_axi_clk,
+		&pll3_usb_otg,
+		&pll2_pfd_594m,
+		&pll2_pfd_400m,
+		NULL
+	},
+};
+
+static struct multiplexer gpu3d_shader_mux = {
+	.clk = &gpu3d_shader_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_GPU3D_SHADER_SEL,
+	.bm = BM_CBCMR_GPU3D_SHADER_SEL,
+	.parents = {
+		&mmdc_ch0_axi_clk,
+		&pll3_usb_otg,
+		&pll2_pfd_594m,
+		&pll3_pfd_720m,
+		NULL
+	},
+};
+
+static struct multiplexer pcie_axi_mux = {
+	.clk = &pcie_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_PCIE_AXI_SEL,
+	.bm = BM_CBCMR_PCIE_AXI_SEL,
+	.parents = {
+		&axi_clk,
+		&ahb_clk,
+		NULL
+	},
+};
+
+static struct multiplexer vdo_axi_mux = {
+	.clk = &vdo_axi_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_VDO_AXI_SEL,
+	.bm = BM_CBCMR_VDO_AXI_SEL,
+	.parents = {
+		&axi_clk,
+		&ahb_clk,
+		NULL
+	},
+};
+
+static struct multiplexer vpu_axi_mux = {
+	.clk = &vpu_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_VPU_AXI_SEL,
+	.bm = BM_CBCMR_VPU_AXI_SEL,
+	.parents = {
+		&axi_clk,
+		&pll2_pfd_400m,
+		&pll2_pfd_352m,
+		NULL
+	},
+};
+
+static struct multiplexer gpu2d_core_mux = {
+	.clk = &gpu2d_core_clk,
+	.reg = CBCMR,
+	.bp = BP_CBCMR_GPU2D_CORE_SEL,
+	.bm = BM_CBCMR_GPU2D_CORE_SEL,
+	.parents = {
+		&axi_clk,
+		&pll3_usb_otg,
+		&pll2_pfd_352m,
+		&pll2_pfd_400m,
+		NULL
+	},
+};
+
+#define DEF_SSI_MUX(id)							\
+	static struct multiplexer ssi##id##_mux = {			\
+		.clk = &ssi##id##_clk,					\
+		.reg = CSCMR1,						\
+		.bp = BP_CSCMR1_SSI##id##_SEL,				\
+		.bm = BM_CSCMR1_SSI##id##_SEL,				\
+		.parents = {						\
+			&pll3_pfd_508m,					\
+			&pll3_pfd_454m,					\
+			&pll4_audio,					\
+			NULL						\
+		},							\
+	}
+
+DEF_SSI_MUX(1);
+DEF_SSI_MUX(2);
+DEF_SSI_MUX(3);
+
+#define DEF_USDHC_MUX(id)						\
+	static struct multiplexer usdhc##id##_mux = {			\
+		.clk = &usdhc##id##_clk,				\
+		.reg = CSCMR1,						\
+		.bp = BP_CSCMR1_USDHC##id##_SEL,			\
+		.bm = BM_CSCMR1_USDHC##id##_SEL,			\
+		.parents = {						\
+			&pll2_pfd_400m,					\
+			&pll2_pfd_352m,					\
+			NULL						\
+		},							\
+	}
+
+DEF_USDHC_MUX(1);
+DEF_USDHC_MUX(2);
+DEF_USDHC_MUX(3);
+DEF_USDHC_MUX(4);
+
+static struct multiplexer emi_mux = {
+	.clk = &emi_clk,
+	.reg = CSCMR1,
+	.bp = BP_CSCMR1_EMI_SEL,
+	.bm = BM_CSCMR1_EMI_SEL,
+	.parents = {
+		&axi_clk,
+		&pll3_usb_otg,
+		&pll2_pfd_400m,
+		&pll2_pfd_352m,
+		NULL
+	},
+};
+
+static struct multiplexer emi_slow_mux = {
+	.clk = &emi_slow_clk,
+	.reg = CSCMR1,
+	.bp = BP_CSCMR1_EMI_SLOW_SEL,
+	.bm = BM_CSCMR1_EMI_SLOW_SEL,
+	.parents = {
+		&axi_clk,
+		&pll3_usb_otg,
+		&pll2_pfd_400m,
+		&pll2_pfd_352m,
+		NULL
+	},
+};
+
+static struct multiplexer esai_mux = {
+	.clk = &esai_clk,
+	.reg = CSCMR2,
+	.bp = BP_CSCMR2_ESAI_SEL,
+	.bm = BM_CSCMR2_ESAI_SEL,
+	.parents = {
+		&pll4_audio,
+		&pll3_pfd_508m,
+		&pll3_pfd_454m,
+		&pll3_usb_otg,
+		NULL
+	},
+};
+
+#define DEF_LDB_DI_MUX(id)						\
+	static struct multiplexer ldb_di##id##_mux = {			\
+		.clk = &ldb_di##id##_clk,				\
+		.reg = CS2CDR,						\
+		.bp = BP_CS2CDR_LDB_DI##id##_SEL,			\
+		.bm = BM_CS2CDR_LDB_DI##id##_SEL,			\
+		.parents = {						\
+			&pll5_video,					\
+			&pll2_pfd_352m,					\
+			&pll2_pfd_400m,					\
+			&pll3_pfd_540m,					\
+			&pll3_usb_otg,					\
+			NULL						\
+		},							\
+	}
+
+DEF_LDB_DI_MUX(0);
+DEF_LDB_DI_MUX(1);
+
+static struct multiplexer enfc_mux = {
+	.clk = &enfc_clk,
+	.reg = CS2CDR,
+	.bp = BP_CS2CDR_ENFC_SEL,
+	.bm = BM_CS2CDR_ENFC_SEL,
+	.parents = {
+		&pll2_pfd_352m,
+		&pll2_bus,
+		&pll3_usb_otg,
+		&pll2_pfd_400m,
+		NULL
+	},
+};
+
+static struct multiplexer spdif_mux = {
+	.clk = &spdif_clk,
+	.reg = CDCDR,
+	.bp = BP_CDCDR_SPDIF_SEL,
+	.bm = BM_CDCDR_SPDIF_SEL,
+	.parents = {
+		&pll4_audio,
+		&pll3_pfd_508m,
+		&pll3_pfd_454m,
+		&pll3_usb_otg,
+		NULL
+	},
+};
+
+static struct multiplexer asrc_serial_mux = {
+	.clk = &asrc_serial_clk,
+	.reg = CDCDR,
+	.bp = BP_CDCDR_ASRC_SERIAL_SEL,
+	.bm = BM_CDCDR_ASRC_SERIAL_SEL,
+	.parents = {
+		&pll4_audio,
+		&pll3_pfd_508m,
+		&pll3_pfd_454m,
+		&pll3_usb_otg,
+		NULL
+	},
+};
+
+static struct multiplexer hsi_tx_mux = {
+	.clk = &hsi_tx_clk,
+	.reg = CDCDR,
+	.bp = BP_CDCDR_HSI_TX_SEL,
+	.bm = BM_CDCDR_HSI_TX_SEL,
+	.parents = {
+		&pll3_120m,
+		&pll2_pfd_400m,
+		NULL
+	},
+};
+
+#define DEF_IPU_DI_PRE_MUX(r, i, d)					\
+	static struct multiplexer ipu##i##_di##d##_pre_mux = {		\
+		.clk = &ipu##i##_di##d##_pre_clk,			\
+		.reg = r,						\
+		.bp = BP_##r##_IPU##i##_DI##d##_PRE_SEL,		\
+		.bm = BM_##r##_IPU##i##_DI##d##_PRE_SEL,		\
+		.parents = {						\
+			&mmdc_ch0_axi_clk,				\
+			&pll3_usb_otg,					\
+			&pll5_video,					\
+			&pll2_pfd_352m,					\
+			&pll2_pfd_400m,					\
+			&pll3_pfd_540m,					\
+			NULL						\
+		},							\
+	}
+
+DEF_IPU_DI_PRE_MUX(CHSCCDR, 1, 0);
+DEF_IPU_DI_PRE_MUX(CHSCCDR, 1, 1);
+DEF_IPU_DI_PRE_MUX(CSCDR2, 2, 0);
+DEF_IPU_DI_PRE_MUX(CSCDR2, 2, 1);
+
+#define DEF_IPU_DI_MUX(r, i, d)						\
+	static struct multiplexer ipu##i##_di##d##_mux = {		\
+		.clk = &ipu##i##_di##d##_clk,				\
+		.reg = r,						\
+		.bp = BP_##r##_IPU##i##_DI##d##_SEL,			\
+		.bm = BM_##r##_IPU##i##_DI##d##_SEL,			\
+		.parents = {						\
+			&ipu##i##_di##d##_pre_clk,			\
+			&dummy_clk,					\
+			&dummy_clk,					\
+			&ldb_di0_clk,					\
+			&ldb_di1_clk,					\
+			NULL						\
+		},							\
+	}
+
+DEF_IPU_DI_MUX(CHSCCDR, 1, 0);
+DEF_IPU_DI_MUX(CHSCCDR, 1, 1);
+DEF_IPU_DI_MUX(CSCDR2, 2, 0);
+DEF_IPU_DI_MUX(CSCDR2, 2, 1);
+
+#define DEF_IPU_MUX(id)							\
+	static struct multiplexer ipu##id##_mux = {			\
+		.clk = &ipu##id##_clk,					\
+		.reg = CSCDR3,						\
+		.bp = BP_CSCDR3_IPU##id##_HSP_SEL,			\
+		.bm = BM_CSCDR3_IPU##id##_HSP_SEL,			\
+		.parents = {						\
+			&mmdc_ch0_axi_clk,				\
+			&pll2_pfd_400m,					\
+			&pll3_120m,					\
+			&pll3_pfd_540m,					\
+			NULL						\
+		},							\
+	}
+
+DEF_IPU_MUX(1);
+DEF_IPU_MUX(2);
+
+static struct multiplexer *multiplexers[] = {
+	&axi_mux,
+	&periph_mux,
+	&periph_pre_mux,
+	&periph_clk2_mux,
+	&periph2_mux,
+	&periph2_pre_mux,
+	&periph2_clk2_mux,
+	&gpu2d_axi_mux,
+	&gpu3d_axi_mux,
+	&gpu3d_core_mux,
+	&gpu3d_shader_mux,
+	&pcie_axi_mux,
+	&vdo_axi_mux,
+	&vpu_axi_mux,
+	&gpu2d_core_mux,
+	&ssi1_mux,
+	&ssi2_mux,
+	&ssi3_mux,
+	&usdhc1_mux,
+	&usdhc2_mux,
+	&usdhc3_mux,
+	&usdhc4_mux,
+	&emi_mux,
+	&emi_slow_mux,
+	&esai_mux,
+	&ldb_di0_mux,
+	&ldb_di1_mux,
+	&enfc_mux,
+	&spdif_mux,
+	&asrc_serial_mux,
+	&hsi_tx_mux,
+	&ipu1_di0_pre_mux,
+	&ipu1_di0_mux,
+	&ipu1_di1_pre_mux,
+	&ipu1_di1_mux,
+	&ipu2_di0_pre_mux,
+	&ipu2_di0_mux,
+	&ipu2_di1_pre_mux,
+	&ipu2_di1_mux,
+	&ipu1_mux,
+	&ipu2_mux,
+};
+
+static int _clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	struct multiplexer *m;
+	int i, num;
+	u32 val;
+
+	num = ARRAY_SIZE(multiplexers);
+	for (i = 0; i < num; i++)
+		if (multiplexers[i]->clk == clk) {
+			m = multiplexers[i];
+			break;
+		}
+	if (i == num)
+		return -EINVAL;
+
+	i = 0;
+	while (m->parents[i]) {
+		if (parent == m->parents[i])
+			break;
+		i++;
+	}
+	if (!m->parents[i])
+		return -EINVAL;
+
+	val = readl_relaxed(m->reg);
+	val &= ~m->bm;
+	val |= i << m->bp;
+	writel_relaxed(val, m->reg);
+
+	if (clk == &periph_clk)
+		return clk_busy_wait(clk);
+
+	return 0;
+}
+
+#define DEF_NG_CLK(name, p)				\
+	static struct clk name = {			\
+		.get_rate	= _clk_get_rate,	\
+		.set_rate	= _clk_set_rate,	\
+		.round_rate	= _clk_round_rate,	\
+		.set_parent	= _clk_set_parent,	\
+		.parent		= p,			\
+	}
+
+DEF_NG_CLK(periph_clk2_clk,	&osc_clk);
+DEF_NG_CLK(periph_pre_clk,	&pll2_bus);
+DEF_NG_CLK(periph_clk,		&periph_pre_clk);
+DEF_NG_CLK(periph2_clk2_clk,	&osc_clk);
+DEF_NG_CLK(periph2_pre_clk,	&pll2_bus);
+DEF_NG_CLK(periph2_clk,		&periph2_pre_clk);
+DEF_NG_CLK(axi_clk,		&periph_clk);
+DEF_NG_CLK(emi_clk,		&axi_clk);
+DEF_NG_CLK(arm_clk,		&pll1_sw_clk);
+DEF_NG_CLK(ahb_clk,		&periph_clk);
+DEF_NG_CLK(ipg_clk,		&ahb_clk);
+DEF_NG_CLK(ipg_perclk,		&ipg_clk);
+DEF_NG_CLK(ipu1_di0_pre_clk,	&pll3_pfd_540m);
+DEF_NG_CLK(ipu1_di1_pre_clk,	&pll3_pfd_540m);
+DEF_NG_CLK(ipu2_di0_pre_clk,	&pll3_pfd_540m);
+DEF_NG_CLK(ipu2_di1_pre_clk,	&pll3_pfd_540m);
+DEF_NG_CLK(asrc_serial_clk,	&pll3_usb_otg);
+
+#define DEF_CLK(name, er, es, p, s)			\
+	static struct clk name = {			\
+		.enable_reg	= er,			\
+		.enable_shift	= es,			\
+		.enable		= _clk_enable,		\
+		.disable	= _clk_disable,		\
+		.get_rate	= _clk_get_rate,	\
+		.set_rate	= _clk_set_rate,	\
+		.round_rate	= _clk_round_rate,	\
+		.set_parent	= _clk_set_parent,	\
+		.parent		= p,			\
+		.secondary	= s,			\
+	}
+
+DEF_CLK(aips_tz1_clk,	  CCGR0, CG0,  &ahb_clk,	  NULL);
+DEF_CLK(aips_tz2_clk,	  CCGR0, CG1,  &ahb_clk,	  NULL);
+DEF_CLK(apbh_dma_clk,	  CCGR0, CG2,  &ahb_clk,	  NULL);
+DEF_CLK(asrc_clk,	  CCGR0, CG3,  &pll4_audio,	  NULL);
+DEF_CLK(can1_serial_clk,  CCGR0, CG8,  &pll3_usb_otg,	  NULL);
+DEF_CLK(can1_clk,	  CCGR0, CG7,  &pll3_usb_otg,	  &can1_serial_clk);
+DEF_CLK(can2_serial_clk,  CCGR0, CG10, &pll3_usb_otg,	  NULL);
+DEF_CLK(can2_clk,	  CCGR0, CG9,  &pll3_usb_otg,	  &can2_serial_clk);
+DEF_CLK(ecspi1_clk,	  CCGR1, CG0,  &pll3_60m,	  NULL);
+DEF_CLK(ecspi2_clk,	  CCGR1, CG1,  &pll3_60m,	  NULL);
+DEF_CLK(ecspi3_clk,	  CCGR1, CG2,  &pll3_60m,	  NULL);
+DEF_CLK(ecspi4_clk,	  CCGR1, CG3,  &pll3_60m,	  NULL);
+DEF_CLK(ecspi5_clk,	  CCGR1, CG4,  &pll3_60m,	  NULL);
+DEF_CLK(enet_clk,	  CCGR1, CG5,  &ipg_clk,	  NULL);
+DEF_CLK(esai_clk,	  CCGR1, CG8,  &pll3_usb_otg,	  NULL);
+DEF_CLK(gpt_serial_clk,	  CCGR1, CG11, &ipg_perclk,	  NULL);
+DEF_CLK(gpt_clk,	  CCGR1, CG10, &ipg_perclk,	  &gpt_serial_clk);
+DEF_CLK(gpu2d_core_clk,	  CCGR1, CG12, &pll2_pfd_352m,	  &gpu2d_axi_clk);
+DEF_CLK(gpu3d_core_clk,	  CCGR1, CG13, &pll2_pfd_594m,	  &gpu3d_axi_clk);
+DEF_CLK(gpu3d_shader_clk, CCGR1, CG13, &pll3_pfd_720m,	  &gpu3d_axi_clk);
+DEF_CLK(hdmi_iahb_clk,	  CCGR2, CG0,  &ahb_clk,	  NULL);
+DEF_CLK(hdmi_isfr_clk,	  CCGR2, CG2,  &pll3_pfd_540m,	  &hdmi_iahb_clk);
+DEF_CLK(i2c1_clk,	  CCGR2, CG3,  &ipg_perclk,	  NULL);
+DEF_CLK(i2c2_clk,	  CCGR2, CG4,  &ipg_perclk,	  NULL);
+DEF_CLK(i2c3_clk,	  CCGR2, CG5,  &ipg_perclk,	  NULL);
+DEF_CLK(iim_clk,	  CCGR2, CG6,  &ipg_clk,	  NULL);
+DEF_CLK(enfc_clk,	  CCGR2, CG7,  &pll2_pfd_352m,	  NULL);
+DEF_CLK(ipu1_clk,	  CCGR3, CG0,  &mmdc_ch0_axi_clk, NULL);
+DEF_CLK(ipu1_di0_clk,	  CCGR3, CG1,  &ipu1_di0_pre_clk, NULL);
+DEF_CLK(ipu1_di1_clk,	  CCGR3, CG2,  &ipu1_di1_pre_clk, NULL);
+DEF_CLK(ipu2_clk,	  CCGR3, CG3,  &mmdc_ch0_axi_clk, NULL);
+DEF_CLK(ipu2_di0_clk,	  CCGR3, CG4,  &ipu2_di0_pre_clk, NULL);
+DEF_CLK(ipu2_di1_clk,	  CCGR3, CG5,  &ipu2_di1_pre_clk, NULL);
+DEF_CLK(ldb_di0_clk,	  CCGR3, CG6,  &pll3_pfd_540m,	  NULL);
+DEF_CLK(ldb_di1_clk,	  CCGR3, CG7,  &pll3_pfd_540m,	  NULL);
+DEF_CLK(hsi_tx_clk,	  CCGR3, CG8,  &pll2_pfd_400m,	  NULL);
+DEF_CLK(mlb_clk,	  CCGR3, CG9,  &pll6_mlb,	  NULL);
+DEF_CLK(mmdc_ch0_ipg_clk, CCGR3, CG12, &ipg_clk,	  NULL);
+DEF_CLK(mmdc_ch0_axi_clk, CCGR3, CG10, &periph_clk,	  &mmdc_ch0_ipg_clk);
+DEF_CLK(mmdc_ch1_ipg_clk, CCGR3, CG13, &ipg_clk,	  NULL);
+DEF_CLK(mmdc_ch1_axi_clk, CCGR3, CG11, &periph2_clk,	  &mmdc_ch1_ipg_clk);
+DEF_CLK(openvg_axi_clk,   CCGR3, CG13, &axi_clk,	  NULL);
+DEF_CLK(pwm1_clk,	  CCGR4, CG8,  &ipg_perclk,	  NULL);
+DEF_CLK(pwm2_clk,	  CCGR4, CG9,  &ipg_perclk,	  NULL);
+DEF_CLK(pwm3_clk,	  CCGR4, CG10, &ipg_perclk,	  NULL);
+DEF_CLK(pwm4_clk,	  CCGR4, CG11, &ipg_perclk,	  NULL);
+DEF_CLK(gpmi_bch_apb_clk, CCGR4, CG12, &usdhc3_clk,	  NULL);
+DEF_CLK(gpmi_bch_clk,	  CCGR4, CG13, &usdhc4_clk,	  &gpmi_bch_apb_clk);
+DEF_CLK(gpmi_apb_clk,	  CCGR4, CG15, &usdhc3_clk,	  &gpmi_bch_clk);
+DEF_CLK(gpmi_io_clk,	  CCGR4, CG14, &enfc_clk,	  &gpmi_apb_clk);
+DEF_CLK(sdma_clk,	  CCGR5, CG3,  &ahb_clk,	  NULL);
+DEF_CLK(spba_clk,	  CCGR5, CG6,  &ipg_clk,	  NULL);
+DEF_CLK(spdif_clk,	  CCGR5, CG7,  &pll3_usb_otg,	  &spba_clk);
+DEF_CLK(ssi1_clk,	  CCGR5, CG9,  &pll3_pfd_508m,	  NULL);
+DEF_CLK(ssi2_clk,	  CCGR5, CG10, &pll3_pfd_508m,	  NULL);
+DEF_CLK(ssi3_clk,	  CCGR5, CG11, &pll3_pfd_508m,	  NULL);
+DEF_CLK(uart_serial_clk,  CCGR5, CG13, &pll3_usb_otg,	  NULL);
+DEF_CLK(uart_clk,	  CCGR5, CG12, &pll3_80m,	  &uart_serial_clk);
+DEF_CLK(usboh3_clk,	  CCGR6, CG0,  &ipg_clk,	  NULL);
+DEF_CLK(usdhc1_clk,	  CCGR6, CG1,  &pll2_pfd_400m,	  NULL);
+DEF_CLK(usdhc2_clk,	  CCGR6, CG2,  &pll2_pfd_400m,	  NULL);
+DEF_CLK(usdhc3_clk,	  CCGR6, CG3,  &pll2_pfd_400m,	  NULL);
+DEF_CLK(usdhc4_clk,	  CCGR6, CG4,  &pll2_pfd_400m,	  NULL);
+DEF_CLK(emi_slow_clk,	  CCGR6, CG5,  &axi_clk,	  NULL);
+DEF_CLK(vdo_axi_clk,	  CCGR6, CG6,  &axi_clk,	  NULL);
+DEF_CLK(vpu_clk,	  CCGR6, CG7,  &axi_clk,	  NULL);
+
+static int pcie_clk_enable(struct clk *clk)
+{
+	u32 val;
+
+	val = readl_relaxed(PLL8_ENET);
+	val |= BM_PLL_ENET_EN_PCIE;
+	writel_relaxed(val, PLL8_ENET);
+
+	return _clk_enable(clk);
+}
+
+static void pcie_clk_disable(struct clk *clk)
+{
+	u32 val;
+
+	_clk_disable(clk);
+
+	val = readl_relaxed(PLL8_ENET);
+	val &= BM_PLL_ENET_EN_PCIE;
+	writel_relaxed(val, PLL8_ENET);
+}
+
+static struct clk pcie_clk = {
+	.enable_reg = CCGR4,
+	.enable_shift = CG0,
+	.enable = pcie_clk_enable,
+	.disable = pcie_clk_disable,
+	.set_parent = _clk_set_parent,
+	.parent = &axi_clk,
+	.secondary = &pll8_enet,
+};
+
+static int sata_clk_enable(struct clk *clk)
+{
+	u32 val;
+
+	val = readl_relaxed(PLL8_ENET);
+	val |= BM_PLL_ENET_EN_SATA;
+	writel_relaxed(val, PLL8_ENET);
+
+	return _clk_enable(clk);
+}
+
+static void sata_clk_disable(struct clk *clk)
+{
+	u32 val;
+
+	_clk_disable(clk);
+
+	val = readl_relaxed(PLL8_ENET);
+	val &= BM_PLL_ENET_EN_SATA;
+	writel_relaxed(val, PLL8_ENET);
+}
+
+static struct clk sata_clk = {
+	.enable_reg = CCGR5,
+	.enable_shift = CG2,
+	.enable = sata_clk_enable,
+	.disable = sata_clk_disable,
+	.parent = &ipg_clk,
+	.secondary = &pll8_enet,
+};
+
+#define _REGISTER_CLOCK(d, n, c) \
+	{ \
+		.dev_id = d, \
+		.con_id = n, \
+		.clk = &c, \
+	}
+
+static struct clk_lookup lookups[] = {
+	_REGISTER_CLOCK("2020000.uart", NULL, uart_clk),
+	_REGISTER_CLOCK("21e8000.uart", NULL, uart_clk),
+	_REGISTER_CLOCK("21ec000.uart", NULL, uart_clk),
+	_REGISTER_CLOCK("21f0000.uart", NULL, uart_clk),
+	_REGISTER_CLOCK("21f4000.uart", NULL, uart_clk),
+	_REGISTER_CLOCK("2188000.enet", NULL, enet_clk),
+	_REGISTER_CLOCK("2190000.usdhc", NULL, usdhc1_clk),
+	_REGISTER_CLOCK("2194000.usdhc", NULL, usdhc2_clk),
+	_REGISTER_CLOCK("2198000.usdhc", NULL, usdhc3_clk),
+	_REGISTER_CLOCK("219c000.usdhc", NULL, usdhc4_clk),
+	_REGISTER_CLOCK("21a0000.i2c", NULL, i2c1_clk),
+	_REGISTER_CLOCK("21a4000.i2c", NULL, i2c2_clk),
+	_REGISTER_CLOCK("21a8000.i2c", NULL, i2c3_clk),
+	_REGISTER_CLOCK("2008000.ecspi", NULL, ecspi1_clk),
+	_REGISTER_CLOCK("200c000.ecspi", NULL, ecspi2_clk),
+	_REGISTER_CLOCK("2010000.ecspi", NULL, ecspi3_clk),
+	_REGISTER_CLOCK("2014000.ecspi", NULL, ecspi4_clk),
+	_REGISTER_CLOCK("2018000.ecspi", NULL, ecspi5_clk),
+	_REGISTER_CLOCK("20ec000.sdma", NULL, sdma_clk),
+	_REGISTER_CLOCK("20bc000.wdog", NULL, dummy_clk),
+	_REGISTER_CLOCK("20c0000.wdog", NULL, dummy_clk),
+	_REGISTER_CLOCK(NULL, "ckih", ckih_clk),
+	_REGISTER_CLOCK(NULL, "ckil_clk", ckil_clk),
+	_REGISTER_CLOCK(NULL, "aips_tz1_clk", aips_tz1_clk),
+	_REGISTER_CLOCK(NULL, "aips_tz2_clk", aips_tz2_clk),
+	_REGISTER_CLOCK(NULL, "asrc_clk", asrc_clk),
+	_REGISTER_CLOCK(NULL, "can2_clk", can2_clk),
+	_REGISTER_CLOCK(NULL, "hdmi_isfr_clk", hdmi_isfr_clk),
+	_REGISTER_CLOCK(NULL, "iim_clk", iim_clk),
+	_REGISTER_CLOCK(NULL, "mlb_clk", mlb_clk),
+	_REGISTER_CLOCK(NULL, "openvg_axi_clk", openvg_axi_clk),
+	_REGISTER_CLOCK(NULL, "pwm1_clk", pwm1_clk),
+	_REGISTER_CLOCK(NULL, "pwm2_clk", pwm2_clk),
+	_REGISTER_CLOCK(NULL, "pwm3_clk", pwm3_clk),
+	_REGISTER_CLOCK(NULL, "pwm4_clk", pwm4_clk),
+	_REGISTER_CLOCK(NULL, "gpmi_io_clk", gpmi_io_clk),
+	_REGISTER_CLOCK(NULL, "usboh3_clk", usboh3_clk),
+	_REGISTER_CLOCK(NULL, "sata_clk", sata_clk),
+};
+
+int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
+{
+	u32 val = readl_relaxed(CLPCR);
+
+	val &= ~BM_CLPCR_LPM;
+	switch (mode) {
+	case WAIT_CLOCKED:
+		break;
+	case WAIT_UNCLOCKED:
+		val |= 0x1 << BP_CLPCR_LPM;
+		break;
+	case STOP_POWER_ON:
+		val |= 0x2 << BP_CLPCR_LPM;
+		break;
+	case WAIT_UNCLOCKED_POWER_OFF:
+		val |= 0x1 << BP_CLPCR_LPM;
+		val &= ~BM_CLPCR_VSTBY;
+		val &= ~BM_CLPCR_SBYOS;
+		val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
+		break;
+	case STOP_POWER_OFF:
+		val |= 0x2 << BP_CLPCR_LPM;
+		val |= 0x3 << BP_CLPCR_STBY_COUNT;
+		val |= BM_CLPCR_VSTBY;
+		val |= BM_CLPCR_SBYOS;
+		val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
+		break;
+	default:
+		return -EINVAL;
+	}
+	writel_relaxed(val, CLPCR);
+
+	return 0;
+}
+
+static struct map_desc imx6q_clock_desc[] = {
+	imx_map_entry(MX6Q, CCM, MT_DEVICE),
+	imx_map_entry(MX6Q, ANATOP, MT_DEVICE),
+};
+
+int __init mx6q_clocks_init(void)
+{
+	struct device_node *np;
+	void __iomem *base;
+	int i, irq;
+
+	iotable_init(imx6q_clock_desc, ARRAY_SIZE(imx6q_clock_desc));
+
+	/* retrieve the freqency of fixed clocks from device tree */
+	for_each_compatible_node(np, NULL, "fixed-clock") {
+		u32 rate;
+		if (of_property_read_u32(np, "clock-frequency", &rate))
+			continue;
+
+		if (of_device_is_compatible(np, "fsl,imx-ckil"))
+			external_low_reference = rate;
+		else if (of_device_is_compatible(np, "fsl,imx-ckih1"))
+			external_high_reference = rate;
+		else if (of_device_is_compatible(np, "fsl,imx-osc"))
+			oscillator_reference = rate;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(lookups); i++)
+		clkdev_add(&lookups[i]);
+
+	/* only keep necessary clocks on */
+	writel_relaxed(0x3 << CG0  | 0x3 << CG1  | 0x3 << CG2,	CCGR0);
+	writel_relaxed(0x3 << CG8  | 0x3 << CG9  | 0x3 << CG10,	CCGR2);
+	writel_relaxed(0x3 << CG10 | 0x3 << CG12,		CCGR3);
+	writel_relaxed(0x3 << CG4  | 0x3 << CG6  | 0x3 << CG7,	CCGR4);
+	writel_relaxed(0x3 << CG0,				CCGR5);
+	writel_relaxed(0,					CCGR6);
+	writel_relaxed(0,					CCGR7);
+
+	clk_enable(&uart_clk);
+	clk_enable(&mmdc_ch0_axi_clk);
+
+	clk_set_rate(&pll4_audio, FREQ_650M);
+	clk_set_rate(&pll5_video, FREQ_650M);
+	clk_set_parent(&ipu1_di0_clk, &ipu1_di0_pre_clk);
+	clk_set_parent(&ipu1_di0_pre_clk, &pll5_video);
+	clk_set_parent(&gpu3d_shader_clk, &pll2_pfd_594m);
+	clk_set_rate(&gpu3d_shader_clk, FREQ_594M);
+	clk_set_parent(&gpu3d_core_clk, &mmdc_ch0_axi_clk);
+	clk_set_rate(&gpu3d_core_clk, FREQ_528M);
+	clk_set_parent(&asrc_serial_clk, &pll3_usb_otg);
+	clk_set_rate(&asrc_serial_clk, 1500000);
+	clk_set_rate(&enfc_clk, 11000000);
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt");
+	base = of_iomap(np, 0);
+	WARN_ON(!base);
+	irq = irq_of_parse_and_map(np, 0);
+	mxc_timer_init(&gpt_clk, base, irq);
+
+	return 0;
+}
diff --git a/arch/arm/mach-imx/cpu-imx25.c b/arch/arm/mach-imx/cpu-imx25.c
new file mode 100644
index 0000000..6914bcb
--- /dev/null
+++ b/arch/arm/mach-imx/cpu-imx25.c
@@ -0,0 +1,41 @@
+/*
+ * MX25 CPU type detection
+ *
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/io.h>
+#include <mach/hardware.h>
+#include <mach/iim.h>
+
+static int mx25_cpu_rev = -1;
+
+static int mx25_read_cpu_rev(void)
+{
+	u32 rev;
+
+	rev = __raw_readl(MX25_IO_ADDRESS(MX25_IIM_BASE_ADDR + MXC_IIMSREV));
+	switch (rev) {
+	case 0x00:
+		return IMX_CHIP_REVISION_1_0;
+	case 0x01:
+		return IMX_CHIP_REVISION_1_1;
+	default:
+		return IMX_CHIP_REVISION_UNKNOWN;
+	}
+}
+
+int mx25_revision(void)
+{
+	if (mx25_cpu_rev == -1)
+		mx25_cpu_rev = mx25_read_cpu_rev();
+
+	return mx25_cpu_rev;
+}
+EXPORT_SYMBOL(mx25_revision);
diff --git a/arch/arm/mach-imx/cpu-imx27.c b/arch/arm/mach-imx/cpu-imx27.c
index 3b117be..ff38e15 100644
--- a/arch/arm/mach-imx/cpu-imx27.c
+++ b/arch/arm/mach-imx/cpu-imx27.c
@@ -26,12 +26,12 @@
 
 #include <mach/hardware.h>
 
-static int cpu_silicon_rev = -1;
-static int cpu_partnumber;
+static int mx27_cpu_rev = -1;
+static int mx27_cpu_partnumber;
 
 #define SYS_CHIP_ID             0x00    /* The offset of CHIP ID register */
 
-static void query_silicon_parameter(void)
+static int mx27_read_cpu_rev(void)
 {
 	u32 val;
 	/*
@@ -42,20 +42,18 @@ static void query_silicon_parameter(void)
 	val = __raw_readl(MX27_IO_ADDRESS(MX27_SYSCTRL_BASE_ADDR
 				+ SYS_CHIP_ID));
 
+	mx27_cpu_partnumber = (int)((val >> 12) & 0xFFFF);
+
 	switch (val >> 28) {
 	case 0:
-		cpu_silicon_rev = IMX_CHIP_REVISION_1_0;
-		break;
+		return IMX_CHIP_REVISION_1_0;
 	case 1:
-		cpu_silicon_rev = IMX_CHIP_REVISION_2_0;
-		break;
+		return IMX_CHIP_REVISION_2_0;
 	case 2:
-		cpu_silicon_rev = IMX_CHIP_REVISION_2_1;
-		break;
+		return IMX_CHIP_REVISION_2_1;
 	default:
-		cpu_silicon_rev = IMX_CHIP_REVISION_UNKNOWN;
+		return IMX_CHIP_REVISION_UNKNOWN;
 	}
-	cpu_partnumber = (int)((val >> 12) & 0xFFFF);
 }
 
 /*
@@ -65,12 +63,12 @@ static void query_silicon_parameter(void)
  */
 int mx27_revision(void)
 {
-	if (cpu_silicon_rev == -1)
-		query_silicon_parameter();
+	if (mx27_cpu_rev == -1)
+		mx27_cpu_rev = mx27_read_cpu_rev();
 
-	if (cpu_partnumber != 0x8821)
+	if (mx27_cpu_partnumber != 0x8821)
 		return -EINVAL;
 
-	return cpu_silicon_rev;
+	return mx27_cpu_rev;
 }
 EXPORT_SYMBOL(mx27_revision);
diff --git a/arch/arm/mach-imx/cpu-imx31.c b/arch/arm/mach-imx/cpu-imx31.c
index a378070..3f2345f 100644
--- a/arch/arm/mach-imx/cpu-imx31.c
+++ b/arch/arm/mach-imx/cpu-imx31.c
@@ -13,45 +13,50 @@
 #include <linux/io.h>
 #include <mach/hardware.h>
 #include <mach/iim.h>
+#include <mach/common.h>
 
-unsigned int mx31_cpu_rev;
-EXPORT_SYMBOL(mx31_cpu_rev);
+static int mx31_cpu_rev = -1;
 
 static struct {
 	u8 srev;
 	const char *name;
-	const char *v;
 	unsigned int rev;
-} mx31_cpu_type[] __initdata = {
-	{ .srev = 0x00, .name = "i.MX31(L)", .v = "1.0",  .rev = IMX_CHIP_REVISION_1_0	},
-	{ .srev = 0x10, .name = "i.MX31",    .v = "1.1",  .rev = IMX_CHIP_REVISION_1_1	},
-	{ .srev = 0x11, .name = "i.MX31L",   .v = "1.1",  .rev = IMX_CHIP_REVISION_1_1	},
-	{ .srev = 0x12, .name = "i.MX31",    .v = "1.15", .rev = IMX_CHIP_REVISION_1_1	},
-	{ .srev = 0x13, .name = "i.MX31L",   .v = "1.15", .rev = IMX_CHIP_REVISION_1_1	},
-	{ .srev = 0x14, .name = "i.MX31",    .v = "1.2",  .rev = IMX_CHIP_REVISION_1_2	},
-	{ .srev = 0x15, .name = "i.MX31L",   .v = "1.2",  .rev = IMX_CHIP_REVISION_1_2	},
-	{ .srev = 0x28, .name = "i.MX31",    .v = "2.0",  .rev = IMX_CHIP_REVISION_2_0	},
-	{ .srev = 0x29, .name = "i.MX31L",   .v = "2.0",  .rev = IMX_CHIP_REVISION_2_0	},
+} mx31_cpu_type[] = {
+	{ .srev = 0x00, .name = "i.MX31(L)", .rev = IMX_CHIP_REVISION_1_0 },
+	{ .srev = 0x10, .name = "i.MX31",    .rev = IMX_CHIP_REVISION_1_1 },
+	{ .srev = 0x11, .name = "i.MX31L",   .rev = IMX_CHIP_REVISION_1_1 },
+	{ .srev = 0x12, .name = "i.MX31",    .rev = IMX_CHIP_REVISION_1_1 },
+	{ .srev = 0x13, .name = "i.MX31L",   .rev = IMX_CHIP_REVISION_1_1 },
+	{ .srev = 0x14, .name = "i.MX31",    .rev = IMX_CHIP_REVISION_1_2 },
+	{ .srev = 0x15, .name = "i.MX31L",   .rev = IMX_CHIP_REVISION_1_2 },
+	{ .srev = 0x28, .name = "i.MX31",    .rev = IMX_CHIP_REVISION_2_0 },
+	{ .srev = 0x29, .name = "i.MX31L",   .rev = IMX_CHIP_REVISION_2_0 },
 };
 
-void __init mx31_read_cpu_rev(void)
+static int mx31_read_cpu_rev(void)
 {
 	u32 i, srev;
 
 	/* read SREV register from IIM module */
 	srev = __raw_readl(MX31_IO_ADDRESS(MX31_IIM_BASE_ADDR + MXC_IIMSREV));
+	srev &= 0xff;
 
 	for (i = 0; i < ARRAY_SIZE(mx31_cpu_type); i++)
 		if (srev == mx31_cpu_type[i].srev) {
-			printk(KERN_INFO
-				"CPU identified as %s, silicon rev %s\n",
-				mx31_cpu_type[i].name, mx31_cpu_type[i].v);
-
-			mx31_cpu_rev = mx31_cpu_type[i].rev;
-			return;
+			imx_print_silicon_rev(mx31_cpu_type[i].name,
+						mx31_cpu_type[i].rev);
+			return mx31_cpu_type[i].rev;
 		}
 
-	mx31_cpu_rev = IMX_CHIP_REVISION_UNKNOWN;
+	imx_print_silicon_rev("i.MX31", IMX_CHIP_REVISION_UNKNOWN);
+	return IMX_CHIP_REVISION_UNKNOWN;
+}
+
+int mx31_revision(void)
+{
+	if (mx31_cpu_rev == -1)
+		mx31_cpu_rev = mx31_read_cpu_rev();
 
-	printk(KERN_WARNING "Unknown CPU identifier. srev = %02x\n", srev);
+	return mx31_cpu_rev;
 }
+EXPORT_SYMBOL(mx31_revision);
diff --git a/arch/arm/mach-imx/cpu-imx35.c b/arch/arm/mach-imx/cpu-imx35.c
index 6637cd8..846e46e 100644
--- a/arch/arm/mach-imx/cpu-imx35.c
+++ b/arch/arm/mach-imx/cpu-imx35.c
@@ -13,32 +13,30 @@
 #include <mach/hardware.h>
 #include <mach/iim.h>
 
-unsigned int mx35_cpu_rev;
-EXPORT_SYMBOL(mx35_cpu_rev);
+static int mx35_cpu_rev = -1;
 
-void __init mx35_read_cpu_rev(void)
+static int mx35_read_cpu_rev(void)
 {
 	u32 rev;
-	char *srev;
 
 	rev = __raw_readl(MX35_IO_ADDRESS(MX35_IIM_BASE_ADDR + MXC_IIMSREV));
 	switch (rev) {
 	case 0x00:
-		mx35_cpu_rev = IMX_CHIP_REVISION_1_0;
-		srev = "1.0";
-		break;
+		return IMX_CHIP_REVISION_1_0;
 	case 0x10:
-		mx35_cpu_rev = IMX_CHIP_REVISION_2_0;
-		srev = "2.0";
-		break;
+		return IMX_CHIP_REVISION_2_0;
 	case 0x11:
-		mx35_cpu_rev = IMX_CHIP_REVISION_2_1;
-		srev = "2.1";
-		break;
+		return IMX_CHIP_REVISION_2_1;
 	default:
-		mx35_cpu_rev = IMX_CHIP_REVISION_UNKNOWN;
-		srev = "unknown";
+		return IMX_CHIP_REVISION_UNKNOWN;
 	}
+}
+
+int mx35_revision(void)
+{
+	if (mx35_cpu_rev == -1)
+		mx35_cpu_rev = mx35_read_cpu_rev();
 
-	printk(KERN_INFO "CPU identified as i.MX35, silicon rev %s\n", srev);
+	return mx35_cpu_rev;
 }
+EXPORT_SYMBOL(mx35_revision);
diff --git a/arch/arm/mach-imx/devices-imx27.h b/arch/arm/mach-imx/devices-imx27.h
index 7f97a3c..2f727d7 100644
--- a/arch/arm/mach-imx/devices-imx27.h
+++ b/arch/arm/mach-imx/devices-imx27.h
@@ -76,3 +76,7 @@ extern const struct imx_spi_imx_data imx27_cspi_data[];
 #define imx27_add_spi_imx0(pdata)	imx27_add_cspi(0, pdata)
 #define imx27_add_spi_imx1(pdata)	imx27_add_cspi(1, pdata)
 #define imx27_add_spi_imx2(pdata)	imx27_add_cspi(2, pdata)
+
+extern const struct imx_pata_imx_data imx27_pata_imx_data;
+#define imx27_add_pata_imx() \
+	imx_add_pata_imx(&imx27_pata_imx_data)
diff --git a/arch/arm/mach-imx/devices-imx31.h b/arch/arm/mach-imx/devices-imx31.h
index dbe940d..488e241 100644
--- a/arch/arm/mach-imx/devices-imx31.h
+++ b/arch/arm/mach-imx/devices-imx31.h
@@ -78,3 +78,7 @@ extern const struct imx_spi_imx_data imx31_cspi_data[];
 #define imx31_add_spi_imx0(pdata)	imx31_add_cspi(0, pdata)
 #define imx31_add_spi_imx1(pdata)	imx31_add_cspi(1, pdata)
 #define imx31_add_spi_imx2(pdata)	imx31_add_cspi(2, pdata)
+
+extern const struct imx_pata_imx_data imx31_pata_imx_data;
+#define imx31_add_pata_imx() \
+	imx_add_pata_imx(&imx31_pata_imx_data)
diff --git a/arch/arm/mach-imx/devices-imx35.h b/arch/arm/mach-imx/devices-imx35.h
index 234cbd3..7b99ef0 100644
--- a/arch/arm/mach-imx/devices-imx35.h
+++ b/arch/arm/mach-imx/devices-imx35.h
@@ -81,3 +81,7 @@ extern const struct imx_spi_imx_data imx35_cspi_data[];
 	imx_add_spi_imx(&imx35_cspi_data[id], pdata)
 #define imx35_add_spi_imx0(pdata)	imx35_add_cspi(0, pdata)
 #define imx35_add_spi_imx1(pdata)	imx35_add_cspi(1, pdata)
+
+extern const struct imx_pata_imx_data imx35_pata_imx_data;
+#define imx35_add_pata_imx() \
+	imx_add_pata_imx(&imx35_pata_imx_data)
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
new file mode 100644
index 0000000..e1537f9
--- /dev/null
+++ b/arch/arm/mach-imx/gpc.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <asm/hardware/gic.h>
+
+#define GPC_IMR1		0x008
+#define GPC_PGC_CPU_PDN		0x2a0
+
+#define IMR_NUM			4
+
+static void __iomem *gpc_base;
+static u32 gpc_wake_irqs[IMR_NUM];
+static u32 gpc_saved_imrs[IMR_NUM];
+
+void imx_gpc_pre_suspend(void)
+{
+	void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
+	int i;
+
+	/* Tell GPC to power off ARM core when suspend */
+	writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN);
+
+	for (i = 0; i < IMR_NUM; i++) {
+		gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4);
+		writel_relaxed(~gpc_wake_irqs[i], reg_imr1 + i * 4);
+	}
+}
+
+void imx_gpc_post_resume(void)
+{
+	void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
+	int i;
+
+	/* Keep ARM core powered on for other low-power modes */
+	writel_relaxed(0x0, gpc_base + GPC_PGC_CPU_PDN);
+
+	for (i = 0; i < IMR_NUM; i++)
+		writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4);
+}
+
+static int imx_gpc_irq_set_wake(struct irq_data *d, unsigned int on)
+{
+	unsigned int idx = d->irq / 32 - 1;
+	u32 mask;
+
+	/* Sanity check for SPI irq */
+	if (d->irq < 32)
+		return -EINVAL;
+
+	mask = 1 << d->irq % 32;
+	gpc_wake_irqs[idx] = on ? gpc_wake_irqs[idx] | mask :
+				  gpc_wake_irqs[idx] & ~mask;
+
+	return 0;
+}
+
+static void imx_gpc_irq_unmask(struct irq_data *d)
+{
+	void __iomem *reg;
+	u32 val;
+
+	/* Sanity check for SPI irq */
+	if (d->irq < 32)
+		return;
+
+	reg = gpc_base + GPC_IMR1 + (d->irq / 32 - 1) * 4;
+	val = readl_relaxed(reg);
+	val &= ~(1 << d->irq % 32);
+	writel_relaxed(val, reg);
+}
+
+static void imx_gpc_irq_mask(struct irq_data *d)
+{
+	void __iomem *reg;
+	u32 val;
+
+	/* Sanity check for SPI irq */
+	if (d->irq < 32)
+		return;
+
+	reg = gpc_base + GPC_IMR1 + (d->irq / 32 - 1) * 4;
+	val = readl_relaxed(reg);
+	val |= 1 << (d->irq % 32);
+	writel_relaxed(val, reg);
+}
+
+void __init imx_gpc_init(void)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc");
+	gpc_base = of_iomap(np, 0);
+	WARN_ON(!gpc_base);
+
+	/* Register GPC as the secondary interrupt controller behind GIC */
+	gic_arch_extn.irq_mask = imx_gpc_irq_mask;
+	gic_arch_extn.irq_unmask = imx_gpc_irq_unmask;
+	gic_arch_extn.irq_set_wake = imx_gpc_irq_set_wake;
+}
diff --git a/arch/arm/mach-imx/head-v7.S b/arch/arm/mach-imx/head-v7.S
new file mode 100644
index 0000000..6229efb
--- /dev/null
+++ b/arch/arm/mach-imx/head-v7.S
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/asm-offsets.h>
+#include <asm/hardware/cache-l2x0.h>
+
+	.section ".text.head", "ax"
+	__CPUINIT
+
+/*
+ * The secondary kernel init calls v7_flush_dcache_all before it enables
+ * the L1; however, the L1 comes out of reset in an undefined state, so
+ * the clean + invalidate performed by v7_flush_dcache_all causes a bunch
+ * of cache lines with uninitialized data and uninitialized tags to get
+ * written out to memory, which does really unpleasant things to the main
+ * processor.  We fix this by performing an invalidate, rather than a
+ * clean + invalidate, before jumping into the kernel.
+ *
+ * This funciton is cloned from arch/arm/mach-tegra/headsmp.S, and needs
+ * to be called for both secondary cores startup and primary core resume
+ * procedures.  Ideally, it should be moved into arch/arm/mm/cache-v7.S.
+ */
+ENTRY(v7_invalidate_l1)
+	mov	r0, #0
+	mcr	p15, 2, r0, c0, c0, 0
+	mrc	p15, 1, r0, c0, c0, 0
+
+	ldr	r1, =0x7fff
+	and	r2, r1, r0, lsr #13
+
+	ldr	r1, =0x3ff
+
+	and	r3, r1, r0, lsr #3	@ NumWays - 1
+	add	r2, r2, #1		@ NumSets
+
+	and	r0, r0, #0x7
+	add	r0, r0, #4	@ SetShift
+
+	clz	r1, r3		@ WayShift
+	add	r4, r3, #1	@ NumWays
+1:	sub	r2, r2, #1	@ NumSets--
+	mov	r3, r4		@ Temp = NumWays
+2:	subs	r3, r3, #1	@ Temp--
+	mov	r5, r3, lsl r1
+	mov	r6, r2, lsl r0
+	orr	r5, r5, r6	@ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
+	mcr	p15, 0, r5, c7, c6, 2
+	bgt	2b
+	cmp	r2, #0
+	bgt	1b
+	dsb
+	isb
+	mov	pc, lr
+ENDPROC(v7_invalidate_l1)
+
+#ifdef CONFIG_SMP
+ENTRY(v7_secondary_startup)
+	bl	v7_invalidate_l1
+	b	secondary_startup
+ENDPROC(v7_secondary_startup)
+#endif
+
+/*
+ * The following code is located into the .data section.  This is to
+ * allow phys_l2x0_saved_regs to be accessed with a relative load
+ * as we are running on physical address here.
+ */
+	.data
+	.align
+
+	.macro	pl310_resume
+	ldr	r2, phys_l2x0_saved_regs
+	ldr	r0, [r2, #L2X0_R_PHY_BASE]	@ get physical base of l2x0
+	ldr	r1, [r2, #L2X0_R_AUX_CTRL]	@ get aux_ctrl value
+	str	r1, [r0, #L2X0_AUX_CTRL]	@ restore aux_ctrl
+	mov	r1, #0x1
+	str	r1, [r0, #L2X0_CTRL]		@ re-enable L2
+	.endm
+
+ENTRY(v7_cpu_resume)
+	bl	v7_invalidate_l1
+	pl310_resume
+	b	cpu_resume
+ENDPROC(v7_cpu_resume)
+
+	.globl	phys_l2x0_saved_regs
+phys_l2x0_saved_regs:
+        .long   0
diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c
new file mode 100644
index 0000000..89493ab
--- /dev/null
+++ b/arch/arm/mach-imx/hotplug.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/errno.h>
+#include <asm/cacheflush.h>
+#include <mach/common.h>
+
+int platform_cpu_kill(unsigned int cpu)
+{
+	return 1;
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+void platform_cpu_die(unsigned int cpu)
+{
+	flush_cache_all();
+	imx_enable_cpu(cpu, false);
+	cpu_do_idle();
+
+	/* We should never return from idle */
+	panic("cpu %d unexpectedly exit from shutdown\n", cpu);
+}
+
+int platform_cpu_disable(unsigned int cpu)
+{
+	/*
+	 * we don't allow CPU 0 to be shutdown (it is still too special
+	 * e.g. clock tick interrupts)
+	 */
+	return cpu == 0 ? -EPERM : 0;
+}
diff --git a/arch/arm/mach-imx/lluart.c b/arch/arm/mach-imx/lluart.c
new file mode 100644
index 0000000..d4ab6f2
--- /dev/null
+++ b/arch/arm/mach-imx/lluart.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <asm/page.h>
+#include <asm/sizes.h>
+#include <asm/mach/map.h>
+#include <mach/hardware.h>
+
+static struct map_desc imx_lluart_desc = {
+#ifdef CONFIG_DEBUG_IMX6Q_UART
+	.virtual	= MX6Q_IO_P2V(MX6Q_UART4_BASE_ADDR),
+	.pfn		= __phys_to_pfn(MX6Q_UART4_BASE_ADDR),
+	.length		= MX6Q_UART4_SIZE,
+	.type		= MT_DEVICE,
+#endif
+};
+
+void __init imx_lluart_map_io(void)
+{
+	if (imx_lluart_desc.virtual)
+		iotable_init(&imx_lluart_desc, 1);
+}
diff --git a/arch/arm/mach-imx/localtimer.c b/arch/arm/mach-imx/localtimer.c
new file mode 100644
index 0000000..3a16351
--- /dev/null
+++ b/arch/arm/mach-imx/localtimer.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/clockchips.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <asm/smp_twd.h>
+
+/*
+ * Setup the local clock events for a CPU.
+ */
+int __cpuinit local_timer_setup(struct clock_event_device *evt)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "arm,smp-twd");
+	if (!twd_base) {
+		twd_base = of_iomap(np, 0);
+		WARN_ON(!twd_base);
+	}
+	evt->irq = irq_of_parse_and_map(np, 0);
+	twd_timer_setup(evt);
+
+	return 0;
+}
diff --git a/arch/arm/mach-imx/mach-apf9328.c b/arch/arm/mach-imx/mach-apf9328.c
index a404c89..1e486e6 100644
--- a/arch/arm/mach-imx/mach-apf9328.c
+++ b/arch/arm/mach-imx/mach-apf9328.c
@@ -136,6 +136,7 @@ MACHINE_START(APF9328, "Armadeus APF9328")
 	.map_io       = mx1_map_io,
 	.init_early   = imx1_init_early,
 	.init_irq     = mx1_init_irq,
+	.handle_irq   = imx1_handle_irq,
 	.timer        = &apf9328_timer,
 	.init_machine = apf9328_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-armadillo5x0.c b/arch/arm/mach-imx/mach-armadillo5x0.c
index 2152590..c9a9cf6 100644
--- a/arch/arm/mach-imx/mach-armadillo5x0.c
+++ b/arch/arm/mach-imx/mach-armadillo5x0.c
@@ -314,25 +314,19 @@ static struct mtd_partition armadillo5x0_nor_flash_partitions[] = {
 	},
 };
 
-static struct physmap_flash_data armadillo5x0_nor_flash_pdata = {
+static const struct physmap_flash_data
+		armadillo5x0_nor_flash_pdata __initconst = {
 	.width		= 2,
 	.parts		= armadillo5x0_nor_flash_partitions,
 	.nr_parts	= ARRAY_SIZE(armadillo5x0_nor_flash_partitions),
 };
 
-static struct resource armadillo5x0_nor_flash_resource = {
+static const struct resource armadillo5x0_nor_flash_resource __initconst = {
 	.flags		= IORESOURCE_MEM,
 	.start		= MX31_CS0_BASE_ADDR,
 	.end		= MX31_CS0_BASE_ADDR + SZ_64M - 1,
 };
 
-static struct platform_device armadillo5x0_nor_flash = {
-	.name			= "physmap-flash",
-	.id			= -1,
-	.num_resources		= 1,
-	.resource		= &armadillo5x0_nor_flash_resource,
-};
-
 /*
  * FB support
  */
@@ -514,8 +508,10 @@ static void __init armadillo5x0_init(void)
 	imx31_add_mx3_sdc_fb(&mx3fb_pdata);
 
 	/* Register NOR Flash */
-	mxc_register_device(&armadillo5x0_nor_flash,
-			    &armadillo5x0_nor_flash_pdata);
+	platform_device_register_resndata(NULL, "physmap-flash", -1,
+			&armadillo5x0_nor_flash_resource, 1,
+			&armadillo5x0_nor_flash_pdata,
+			sizeof(armadillo5x0_nor_flash_pdata));
 
 	/* Register NAND Flash */
 	imx31_add_mxc_nand(&armadillo5x0_nand_board_info);
@@ -562,6 +558,7 @@ MACHINE_START(ARMADILLO5X0, "Armadillo-500")
 	.map_io = mx31_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
+	.handle_irq = imx31_handle_irq,
 	.timer = &armadillo5x0_timer,
 	.init_machine = armadillo5x0_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-bug.c b/arch/arm/mach-imx/mach-bug.c
index f494705..313f62d 100644
--- a/arch/arm/mach-imx/mach-bug.c
+++ b/arch/arm/mach-imx/mach-bug.c
@@ -62,6 +62,7 @@ MACHINE_START(BUG, "BugLabs BUGBase")
 	.map_io = mx31_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
+	.handle_irq = imx31_handle_irq,
 	.timer = &bug_timer,
 	.init_machine = bug_board_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-cpuimx27.c b/arch/arm/mach-imx/mach-cpuimx27.c
index b1ec2cf..edb3730 100644
--- a/arch/arm/mach-imx/mach-cpuimx27.c
+++ b/arch/arm/mach-imx/mach-cpuimx27.c
@@ -315,6 +315,7 @@ MACHINE_START(EUKREA_CPUIMX27, "EUKREA CPUIMX27")
 	.map_io = mx27_map_io,
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
+	.handle_irq = imx27_handle_irq,
 	.timer = &eukrea_cpuimx27_timer,
 	.init_machine = eukrea_cpuimx27_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-cpuimx35.c b/arch/arm/mach-imx/mach-cpuimx35.c
index 470b654..66af2e8 100644
--- a/arch/arm/mach-imx/mach-cpuimx35.c
+++ b/arch/arm/mach-imx/mach-cpuimx35.c
@@ -66,7 +66,7 @@ static struct i2c_board_info eukrea_cpuimx35_i2c_devices[] = {
 		I2C_BOARD_INFO("tsc2007", 0x48),
 		.type		= "tsc2007",
 		.platform_data	= &tsc2007_info,
-		.irq		= gpio_to_irq(TSC2007_IRQGPIO),
+		.irq		= IMX_GPIO_TO_IRQ(TSC2007_IRQGPIO),
 	},
 };
 
@@ -198,6 +198,7 @@ MACHINE_START(EUKREA_CPUIMX35SD, "Eukrea CPUIMX35")
 	.map_io = mx35_map_io,
 	.init_early = imx35_init_early,
 	.init_irq = mx35_init_irq,
+	.handle_irq = imx35_handle_irq,
 	.timer = &eukrea_cpuimx35_timer,
 	.init_machine = eukrea_cpuimx35_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
index 9163318..ab8fbcc 100644
--- a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
+++ b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
@@ -167,6 +167,7 @@ MACHINE_START(EUKREA_CPUIMX25SD, "Eukrea CPUIMX25")
 	.map_io = mx25_map_io,
 	.init_early = imx25_init_early,
 	.init_irq = mx25_init_irq,
+	.handle_irq = imx25_handle_irq,
 	.timer = &eukrea_cpuimx25_timer,
 	.init_machine = eukrea_cpuimx25_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
index 22306ce..38eb9e4 100644
--- a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
+++ b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
@@ -279,6 +279,7 @@ MACHINE_START(IMX27_VISSTRIM_M10, "Vista Silicon Visstrim_M10")
 	.map_io = mx27_map_io,
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
+	.handle_irq = imx27_handle_irq,
 	.timer = &visstrim_m10_timer,
 	.init_machine = visstrim_m10_board_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx27ipcam.c b/arch/arm/mach-imx/mach-imx27ipcam.c
index 8da48b3..7052155 100644
--- a/arch/arm/mach-imx/mach-imx27ipcam.c
+++ b/arch/arm/mach-imx/mach-imx27ipcam.c
@@ -75,6 +75,7 @@ MACHINE_START(IMX27IPCAM, "Freescale IMX27IPCAM")
 	.map_io = mx27_map_io,
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
+	.handle_irq = imx27_handle_irq,
 	.timer = &mx27ipcam_timer,
 	.init_machine = mx27ipcam_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx27lite.c b/arch/arm/mach-imx/mach-imx27lite.c
index 21a14a2..8d6a635 100644
--- a/arch/arm/mach-imx/mach-imx27lite.c
+++ b/arch/arm/mach-imx/mach-imx27lite.c
@@ -81,6 +81,7 @@ MACHINE_START(IMX27LITE, "LogicPD i.MX27LITE")
 	.map_io = mx27_map_io,
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
+	.handle_irq = imx27_handle_irq,
 	.timer = &mx27lite_timer,
 	.init_machine = mx27lite_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
new file mode 100644
index 0000000..8bf5fa3
--- /dev/null
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/hardware/gic.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+
+static void __init imx6q_init_machine(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+
+	imx6q_pm_init();
+}
+
+static void __init imx6q_map_io(void)
+{
+	imx_lluart_map_io();
+	imx_scu_map_io();
+}
+
+static void __init imx6q_gpio_add_irq_domain(struct device_node *np,
+				struct device_node *interrupt_parent)
+{
+	static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS -
+				   32 * 7; /* imx6q gets 7 gpio ports */
+
+	irq_domain_add_simple(np, gpio_irq_base);
+	gpio_irq_base += 32;
+}
+
+static const struct of_device_id imx6q_irq_match[] __initconst = {
+	{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
+	{ .compatible = "fsl,imx6q-gpio", .data = imx6q_gpio_add_irq_domain, },
+	{ /* sentinel */ }
+};
+
+static void __init imx6q_init_irq(void)
+{
+	l2x0_of_init(0, ~0UL);
+	imx_src_init();
+	imx_gpc_init();
+	of_irq_init(imx6q_irq_match);
+}
+
+static void __init imx6q_timer_init(void)
+{
+	mx6q_clocks_init();
+}
+
+static struct sys_timer imx6q_timer = {
+	.init = imx6q_timer_init,
+};
+
+static const char *imx6q_dt_compat[] __initdata = {
+	"fsl,imx6q-sabreauto",
+	NULL,
+};
+
+DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad (Device Tree)")
+	.map_io		= imx6q_map_io,
+	.init_irq	= imx6q_init_irq,
+	.handle_irq	= imx6q_handle_irq,
+	.timer		= &imx6q_timer,
+	.init_machine	= imx6q_init_machine,
+	.dt_compat	= imx6q_dt_compat,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mach-kzm_arm11_01.c b/arch/arm/mach-imx/mach-kzm_arm11_01.c
index 7c20e9e..5f37f89 100644
--- a/arch/arm/mach-imx/mach-kzm_arm11_01.c
+++ b/arch/arm/mach-imx/mach-kzm_arm11_01.c
@@ -36,6 +36,7 @@
 
 #include <mach/clock.h>
 #include <mach/common.h>
+#include <mach/hardware.h>
 #include <mach/iomux-mx3.h>
 
 #include "devices-imx31.h"
@@ -275,6 +276,7 @@ MACHINE_START(KZM_ARM11_01, "Kyoto Microcomputer Co., Ltd. KZM-ARM11-01")
 	.map_io = kzm_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
+	.handle_irq = imx31_handle_irq,
 	.timer = &kzm_timer,
 	.init_machine = kzm_board_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx1ads.c b/arch/arm/mach-imx/mach-mx1ads.c
index 530ea08..fc49785 100644
--- a/arch/arm/mach-imx/mach-mx1ads.c
+++ b/arch/arm/mach-imx/mach-mx1ads.c
@@ -68,23 +68,16 @@ static const struct imxuart_platform_data uart1_pdata __initconst = {
  * Physmap flash
  */
 
-static struct physmap_flash_data mx1ads_flash_data = {
+static const struct physmap_flash_data mx1ads_flash_data __initconst = {
 	.width		= 4,		/* bankwidth in bytes */
 };
 
-static struct resource flash_resource = {
+static const struct resource flash_resource __initconst = {
 	.start	= MX1_CS0_PHYS,
 	.end	= MX1_CS0_PHYS + SZ_32M - 1,
 	.flags	= IORESOURCE_MEM,
 };
 
-static struct platform_device flash_device = {
-	.name	= "physmap-flash",
-	.id	= 0,
-	.resource = &flash_resource,
-	.num_resources = 1,
-};
-
 /*
  * I2C
  */
@@ -125,7 +118,9 @@ static void __init mx1ads_init(void)
 	imx1_add_imx_uart1(&uart1_pdata);
 
 	/* Physmap flash */
-	mxc_register_device(&flash_device, &mx1ads_flash_data);
+	platform_device_register_resndata(NULL, "physmap-flash", 0,
+			&flash_resource, 1,
+			&mx1ads_flash_data, sizeof(mx1ads_flash_data));
 
 	/* I2C */
 	i2c_register_board_info(0, mx1ads_i2c_devices,
@@ -149,6 +144,7 @@ MACHINE_START(MX1ADS, "Freescale MX1ADS")
 	.map_io = mx1_map_io,
 	.init_early = imx1_init_early,
 	.init_irq = mx1_init_irq,
+	.handle_irq = imx1_handle_irq,
 	.timer = &mx1ads_timer,
 	.init_machine = mx1ads_init,
 MACHINE_END
@@ -158,6 +154,7 @@ MACHINE_START(MXLADS, "Freescale MXLADS")
 	.map_io = mx1_map_io,
 	.init_early = imx1_init_early,
 	.init_irq = mx1_init_irq,
+	.handle_irq = imx1_handle_irq,
 	.timer = &mx1ads_timer,
 	.init_machine = mx1ads_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx21ads.c b/arch/arm/mach-imx/mach-mx21ads.c
index e56828d..25f8402 100644
--- a/arch/arm/mach-imx/mach-mx21ads.c
+++ b/arch/arm/mach-imx/mach-mx21ads.c
@@ -309,6 +309,7 @@ MACHINE_START(MX21ADS, "Freescale i.MX21ADS")
 	.map_io = mx21ads_map_io,
 	.init_early = imx21_init_early,
 	.init_irq = mx21_init_irq,
+	.handle_irq = imx21_handle_irq,
 	.timer = &mx21ads_timer,
 	.init_machine = mx21ads_board_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx25_3ds.c b/arch/arm/mach-imx/mach-mx25_3ds.c
index dd25ee8..88dccf1 100644
--- a/arch/arm/mach-imx/mach-mx25_3ds.c
+++ b/arch/arm/mach-imx/mach-mx25_3ds.c
@@ -43,6 +43,8 @@
 
 #include "devices-imx25.h"
 
+#define MX25PDK_CAN_PWDN	IMX_GPIO_NR(4, 6)
+
 static const struct imxuart_platform_data uart_pdata __initconst = {
 	.flags = IMXUART_HAVE_RTSCTS,
 };
@@ -108,6 +110,11 @@ static iomux_v3_cfg_t mx25pdk_pads[] = {
 	/* I2C1 */
 	MX25_PAD_I2C1_CLK__I2C1_CLK,
 	MX25_PAD_I2C1_DAT__I2C1_DAT,
+
+	/* CAN1 */
+	MX25_PAD_GPIO_A__CAN1_TX,
+	MX25_PAD_GPIO_B__CAN1_RX,
+	MX25_PAD_D14__GPIO_4_6,	/* CAN_PWDN */
 };
 
 static const struct fec_platform_data mx25_fec_pdata __initconst = {
@@ -240,6 +247,9 @@ static void __init mx25pdk_init(void)
 
 	imx25_add_sdhci_esdhc_imx(0, &mx25pdk_esdhc_pdata);
 	imx25_add_imx_i2c0(&mx25_3ds_i2c0_data);
+
+	gpio_request_one(MX25PDK_CAN_PWDN, GPIOF_OUT_INIT_LOW, "can-pwdn");
+	imx25_add_flexcan0(NULL);
 }
 
 static void __init mx25pdk_timer_init(void)
@@ -257,6 +267,7 @@ MACHINE_START(MX25_3DS, "Freescale MX25PDK (3DS)")
 	.map_io = mx25_map_io,
 	.init_early = imx25_init_early,
 	.init_irq = mx25_init_irq,
+	.handle_irq = imx25_handle_irq,
 	.timer = &mx25pdk_timer,
 	.init_machine = mx25pdk_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx27_3ds.c b/arch/arm/mach-imx/mach-mx27_3ds.c
index 3772304..cfa8417 100644
--- a/arch/arm/mach-imx/mach-mx27_3ds.c
+++ b/arch/arm/mach-imx/mach-mx27_3ds.c
@@ -357,7 +357,7 @@ static struct spi_board_info mx27_3ds_spi_devs[] __initdata = {
 		.bus_num	= 1,
 		.chip_select	= 0, /* SS0 */
 		.platform_data	= &mc13783_pdata,
-		.irq = gpio_to_irq(PMIC_INT),
+		.irq = IMX_GPIO_TO_IRQ(PMIC_INT),
 		.mode = SPI_CS_HIGH,
 	}, {
 		.modalias	= "l4f00242t03",
@@ -423,6 +423,7 @@ MACHINE_START(MX27_3DS, "Freescale MX27PDK")
 	.map_io = mx27_map_io,
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
+	.handle_irq = imx27_handle_irq,
 	.timer = &mx27pdk_timer,
 	.init_machine = mx27pdk_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx27ads.c b/arch/arm/mach-imx/mach-mx27ads.c
index 635b050..74dd573 100644
--- a/arch/arm/mach-imx/mach-mx27ads.c
+++ b/arch/arm/mach-imx/mach-mx27ads.c
@@ -348,6 +348,7 @@ MACHINE_START(MX27ADS, "Freescale i.MX27ADS")
 	.map_io = mx27ads_map_io,
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
+	.handle_irq = imx27_handle_irq,
 	.timer = &mx27ads_timer,
 	.init_machine = mx27ads_board_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx31_3ds.c b/arch/arm/mach-imx/mach-mx31_3ds.c
index 6484db5..60f1fda 100644
--- a/arch/arm/mach-imx/mach-mx31_3ds.c
+++ b/arch/arm/mach-imx/mach-mx31_3ds.c
@@ -540,7 +540,7 @@ static const struct mxc_nand_platform_data
 mx31_3ds_nand_board_info __initconst = {
 	.width		= 1,
 	.hw_ecc		= 1,
-#ifdef MACH_MX31_3DS_MXC_NAND_USE_BBT
+#ifdef CONFIG_MACH_MX31_3DS_MXC_NAND_USE_BBT
 	.flash_bbt	= 1,
 #endif
 };
@@ -766,6 +766,7 @@ MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)")
 	.map_io = mx31_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
+	.handle_irq = imx31_handle_irq,
 	.timer = &mx31_3ds_timer,
 	.init_machine = mx31_3ds_init,
 	.reserve = mx31_3ds_reserve,
diff --git a/arch/arm/mach-imx/mach-mx31ads.c b/arch/arm/mach-imx/mach-mx31ads.c
index 910c456..9cc1a49 100644
--- a/arch/arm/mach-imx/mach-mx31ads.c
+++ b/arch/arm/mach-imx/mach-mx31ads.c
@@ -539,6 +539,7 @@ MACHINE_START(MX31ADS, "Freescale MX31ADS")
 	.map_io = mx31ads_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31ads_init_irq,
+	.handle_irq = imx31_handle_irq,
 	.timer = &mx31ads_timer,
 	.init_machine = mx31ads_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx31lilly.c b/arch/arm/mach-imx/mach-mx31lilly.c
index e92eaf9..5defd8e 100644
--- a/arch/arm/mach-imx/mach-mx31lilly.c
+++ b/arch/arm/mach-imx/mach-mx31lilly.c
@@ -299,6 +299,7 @@ MACHINE_START(LILLY1131, "INCO startec LILLY-1131")
 	.map_io = mx31_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
+	.handle_irq = imx31_handle_irq,
 	.timer = &mx31lilly_timer,
 	.init_machine = mx31lilly_board_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx31lite.c b/arch/arm/mach-imx/mach-mx31lite.c
index 5242cb7..c97c26d 100644
--- a/arch/arm/mach-imx/mach-mx31lite.c
+++ b/arch/arm/mach-imx/mach-mx31lite.c
@@ -284,6 +284,7 @@ MACHINE_START(MX31LITE, "LogicPD i.MX31 SOM")
 	.map_io = mx31lite_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
+	.handle_irq = imx31_handle_irq,
 	.timer = &mx31lite_timer,
 	.init_machine = mx31lite_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx31moboard.c b/arch/arm/mach-imx/mach-mx31moboard.c
index 1d01ef2..fff7791 100644
--- a/arch/arm/mach-imx/mach-mx31moboard.c
+++ b/arch/arm/mach-imx/mach-mx31moboard.c
@@ -28,6 +28,9 @@
 #include <linux/spi/spi.h>
 #include <linux/types.h>
 #include <linux/memblock.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
 
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
@@ -490,6 +493,18 @@ err:
 
 }
 
+static void mx31moboard_poweroff(void)
+{
+	struct clk *clk = clk_get_sys("imx2-wdt.0", NULL);
+
+	if (!IS_ERR(clk))
+		clk_enable(clk);
+
+	mxc_iomux_mode(MX31_PIN_WATCHDOG_RST__WATCHDOG_RST);
+
+	__raw_writew(1 << 6 | 1 << 2, MX31_IO_ADDRESS(MX31_WDOG_BASE_ADDR));
+}
+
 static int mx31moboard_baseboard;
 core_param(mx31moboard_baseboard, mx31moboard_baseboard, int, 0444);
 
@@ -528,6 +543,8 @@ static void __init mx31moboard_init(void)
 
 	moboard_usbh2_init();
 
+	pm_power_off = mx31moboard_poweroff;
+
 	switch (mx31moboard_baseboard) {
 	case MX31NOBOARD:
 		break;
@@ -572,6 +589,7 @@ MACHINE_START(MX31MOBOARD, "EPFL Mobots mx31moboard")
 	.map_io = mx31_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
+	.handle_irq = imx31_handle_irq,
 	.timer = &mx31moboard_timer,
 	.init_machine = mx31moboard_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx35_3ds.c b/arch/arm/mach-imx/mach-mx35_3ds.c
index f2a873d..7a46202 100644
--- a/arch/arm/mach-imx/mach-mx35_3ds.c
+++ b/arch/arm/mach-imx/mach-mx35_3ds.c
@@ -221,6 +221,7 @@ MACHINE_START(MX35_3DS, "Freescale MX35PDK")
 	.map_io = mx35_map_io,
 	.init_early = imx35_init_early,
 	.init_irq = mx35_init_irq,
+	.handle_irq = imx35_handle_irq,
 	.timer = &mx35pdk_timer,
 	.init_machine = mx35_3ds_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mxt_td60.c b/arch/arm/mach-imx/mach-mxt_td60.c
index 5ec3989..125c196 100644
--- a/arch/arm/mach-imx/mach-mxt_td60.c
+++ b/arch/arm/mach-imx/mach-mxt_td60.c
@@ -271,6 +271,7 @@ MACHINE_START(MXT_TD60, "Maxtrack i-MXT TD60")
 	.map_io = mx27_map_io,
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
+	.handle_irq = imx27_handle_irq,
 	.timer = &mxt_td60_timer,
 	.init_machine = mxt_td60_board_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-pca100.c b/arch/arm/mach-imx/mach-pca100.c
index 0f6bd11..26072f4 100644
--- a/arch/arm/mach-imx/mach-pca100.c
+++ b/arch/arm/mach-imx/mach-pca100.c
@@ -439,6 +439,7 @@ MACHINE_START(PCA100, "phyCARD-i.MX27")
 	.map_io = mx27_map_io,
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
+	.handle_irq = imx27_handle_irq,
 	.init_machine = pca100_init,
 	.timer = &pca100_timer,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-pcm037.c b/arch/arm/mach-imx/mach-pcm037.c
index 186d4eb..efd6b53 100644
--- a/arch/arm/mach-imx/mach-pcm037.c
+++ b/arch/arm/mach-imx/mach-pcm037.c
@@ -693,6 +693,7 @@ MACHINE_START(PCM037, "Phytec Phycore pcm037")
 	.map_io = mx31_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
+	.handle_irq = imx31_handle_irq,
 	.timer = &pcm037_timer,
 	.init_machine = pcm037_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-pcm038.c b/arch/arm/mach-imx/mach-pcm038.c
index 091bcf8..100bc73 100644
--- a/arch/arm/mach-imx/mach-pcm038.c
+++ b/arch/arm/mach-imx/mach-pcm038.c
@@ -176,7 +176,9 @@ static struct platform_device *platform_devices[] __initdata = {
  * setup other stuffs to access the sram. */
 static void __init pcm038_init_sram(void)
 {
-	mx27_setup_weimcs(1, 0x0000d843, 0x22252521, 0x22220a00);
+	__raw_writel(0x0000d843, MX27_IO_ADDRESS(MX27_WEIM_CSCRxU(1)));
+	__raw_writel(0x22252521, MX27_IO_ADDRESS(MX27_WEIM_CSCRxL(1)));
+	__raw_writel(0x22220a00, MX27_IO_ADDRESS(MX27_WEIM_CSCRxA(1)));
 }
 
 static const struct imxi2c_platform_data pcm038_i2c1_data __initconst = {
@@ -353,6 +355,7 @@ MACHINE_START(PCM038, "phyCORE-i.MX27")
 	.map_io = mx27_map_io,
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
+	.handle_irq = imx27_handle_irq,
 	.timer = &pcm038_timer,
 	.init_machine = pcm038_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-pcm043.c b/arch/arm/mach-imx/mach-pcm043.c
index 0a4d31d..7366c2a 100644
--- a/arch/arm/mach-imx/mach-pcm043.c
+++ b/arch/arm/mach-imx/mach-pcm043.c
@@ -422,6 +422,7 @@ MACHINE_START(PCM043, "Phytec Phycore pcm043")
 	.map_io = mx35_map_io,
 	.init_early = imx35_init_early,
 	.init_irq = mx35_init_irq,
+	.handle_irq = imx35_handle_irq,
 	.timer = &pcm043_timer,
 	.init_machine = pcm043_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-qong.c b/arch/arm/mach-imx/mach-qong.c
index 9e11359..4ff5faf 100644
--- a/arch/arm/mach-imx/mach-qong.c
+++ b/arch/arm/mach-imx/mach-qong.c
@@ -190,7 +190,10 @@ static struct platform_device qong_nand_device = {
 static void __init qong_init_nand_mtd(void)
 {
 	/* init CS */
-	mx31_setup_weimcs(3, 0x00004f00, 0x20013b31, 0x00020800);
+	__raw_writel(0x00004f00, MX31_IO_ADDRESS(MX31_WEIM_CSCRxU(3)));
+	__raw_writel(0x20013b31, MX31_IO_ADDRESS(MX31_WEIM_CSCRxL(3)));
+	__raw_writel(0x00020800, MX31_IO_ADDRESS(MX31_WEIM_CSCRxA(3)));
+
 	mxc_iomux_set_gpr(MUX_SDCTL_CSD1_SEL, true);
 
 	/* enable pin */
@@ -249,6 +252,7 @@ static void __init qong_init(void)
 	mxc_init_imx_uart();
 	qong_init_nor_mtd();
 	qong_init_fpga();
+	imx31_add_imx2_wdt(NULL);
 }
 
 static void __init qong_timer_init(void)
@@ -266,6 +270,7 @@ MACHINE_START(QONG, "Dave/DENX QongEVB-LITE")
 	.map_io = mx31_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
+	.handle_irq = imx31_handle_irq,
 	.timer = &qong_timer,
 	.init_machine = qong_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-scb9328.c b/arch/arm/mach-imx/mach-scb9328.c
index 85d3284..bb6e5b2 100644
--- a/arch/arm/mach-imx/mach-scb9328.c
+++ b/arch/arm/mach-imx/mach-scb9328.c
@@ -141,6 +141,7 @@ MACHINE_START(SCB9328, "Synertronixx scb9328")
 	.map_io = mx1_map_io,
 	.init_early = imx1_init_early,
 	.init_irq = mx1_init_irq,
+	.handle_irq = imx1_handle_irq,
 	.timer = &scb9328_timer,
 	.init_machine = scb9328_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-vpr200.c b/arch/arm/mach-imx/mach-vpr200.c
index 7d8e012..6909245 100644
--- a/arch/arm/mach-imx/mach-vpr200.c
+++ b/arch/arm/mach-imx/mach-vpr200.c
@@ -162,7 +162,7 @@ static struct i2c_board_info vpr200_i2c_devices[] = {
 	}, {
 		I2C_BOARD_INFO("mc13892", 0x08),
 		.platform_data = &vpr200_pmic,
-		.irq = gpio_to_irq(GPIO_PMIC_INT),
+		.irq = IMX_GPIO_TO_IRQ(GPIO_PMIC_INT),
 	}
 };
 
@@ -319,6 +319,7 @@ MACHINE_START(VPR200, "VPR200")
 	.map_io = mx35_map_io,
 	.init_early = imx35_init_early,
 	.init_irq = mx35_init_irq,
+	.handle_irq = imx35_handle_irq,
 	.timer = &vpr200_timer,
 	.init_machine = vpr200_board_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mm-imx3.c b/arch/arm/mach-imx/mm-imx3.c
new file mode 100644
index 0000000..9f0e82e
--- /dev/null
+++ b/arch/arm/mach-imx/mm-imx3.c
@@ -0,0 +1,256 @@
+/*
+ *  Copyright (C) 1999,2000 Arm Limited
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
+ *  Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ *    - add MX31 specific definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/err.h>
+
+#include <asm/pgtable.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/mach/map.h>
+
+#include <mach/common.h>
+#include <mach/devices-common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-v3.h>
+#include <mach/irqs.h>
+
+static void imx3_idle(void)
+{
+	unsigned long reg = 0;
+	__asm__ __volatile__(
+		/* disable I and D cache */
+		"mrc p15, 0, %0, c1, c0, 0\n"
+		"bic %0, %0, #0x00001000\n"
+		"bic %0, %0, #0x00000004\n"
+		"mcr p15, 0, %0, c1, c0, 0\n"
+		/* invalidate I cache */
+		"mov %0, #0\n"
+		"mcr p15, 0, %0, c7, c5, 0\n"
+		/* clear and invalidate D cache */
+		"mov %0, #0\n"
+		"mcr p15, 0, %0, c7, c14, 0\n"
+		/* WFI */
+		"mov %0, #0\n"
+		"mcr p15, 0, %0, c7, c0, 4\n"
+		"nop\n" "nop\n" "nop\n" "nop\n"
+		"nop\n" "nop\n" "nop\n"
+		/* enable I and D cache */
+		"mrc p15, 0, %0, c1, c0, 0\n"
+		"orr %0, %0, #0x00001000\n"
+		"orr %0, %0, #0x00000004\n"
+		"mcr p15, 0, %0, c1, c0, 0\n"
+		: "=r" (reg));
+}
+
+static void __iomem *imx3_ioremap(unsigned long phys_addr, size_t size,
+				  unsigned int mtype)
+{
+	if (mtype == MT_DEVICE) {
+		/*
+		 * Access all peripherals below 0x80000000 as nonshared device
+		 * on mx3, but leave l2cc alone.  Otherwise cache corruptions
+		 * can occur.
+		 */
+		if (phys_addr < 0x80000000 &&
+				!addr_in_module(phys_addr, MX3x_L2CC))
+			mtype = MT_DEVICE_NONSHARED;
+	}
+
+	return __arm_ioremap(phys_addr, size, mtype);
+}
+
+void imx3_init_l2x0(void)
+{
+	void __iomem *l2x0_base;
+	void __iomem *clkctl_base;
+
+/*
+ * First of all, we must repair broken chip settings. There are some
+ * i.MX35 CPUs in the wild, comming with bogus L2 cache settings. These
+ * misconfigured CPUs will run amok immediately when the L2 cache gets enabled.
+ * Workaraound is to setup the correct register setting prior enabling the
+ * L2 cache. This should not hurt already working CPUs, as they are using the
+ * same value.
+ */
+#define L2_MEM_VAL 0x10
+
+	clkctl_base = ioremap(MX35_CLKCTL_BASE_ADDR, 4096);
+	if (clkctl_base != NULL) {
+		writel(0x00000515, clkctl_base + L2_MEM_VAL);
+		iounmap(clkctl_base);
+	} else {
+		pr_err("L2 cache: Cannot fix timing. Trying to continue without\n");
+	}
+
+	l2x0_base = ioremap(MX3x_L2CC_BASE_ADDR, 4096);
+	if (IS_ERR(l2x0_base)) {
+		printk(KERN_ERR "remapping L2 cache area failed with %ld\n",
+				PTR_ERR(l2x0_base));
+		return;
+	}
+
+	l2x0_init(l2x0_base, 0x00030024, 0x00000000);
+}
+
+static struct map_desc mx31_io_desc[] __initdata = {
+	imx_map_entry(MX31, X_MEMC, MT_DEVICE),
+	imx_map_entry(MX31, AVIC, MT_DEVICE_NONSHARED),
+	imx_map_entry(MX31, AIPS1, MT_DEVICE_NONSHARED),
+	imx_map_entry(MX31, AIPS2, MT_DEVICE_NONSHARED),
+	imx_map_entry(MX31, SPBA0, MT_DEVICE_NONSHARED),
+};
+
+/*
+ * This function initializes the memory map. It is called during the
+ * system startup to create static physical to virtual memory mappings
+ * for the IO modules.
+ */
+void __init mx31_map_io(void)
+{
+	iotable_init(mx31_io_desc, ARRAY_SIZE(mx31_io_desc));
+}
+
+static struct map_desc mx35_io_desc[] __initdata = {
+	imx_map_entry(MX35, X_MEMC, MT_DEVICE),
+	imx_map_entry(MX35, AVIC, MT_DEVICE_NONSHARED),
+	imx_map_entry(MX35, AIPS1, MT_DEVICE_NONSHARED),
+	imx_map_entry(MX35, AIPS2, MT_DEVICE_NONSHARED),
+	imx_map_entry(MX35, SPBA0, MT_DEVICE_NONSHARED),
+};
+
+void __init mx35_map_io(void)
+{
+	iotable_init(mx35_io_desc, ARRAY_SIZE(mx35_io_desc));
+}
+
+void __init imx31_init_early(void)
+{
+	mxc_set_cpu_type(MXC_CPU_MX31);
+	mxc_arch_reset_init(MX31_IO_ADDRESS(MX31_WDOG_BASE_ADDR));
+	imx_idle = imx3_idle;
+	imx_ioremap = imx3_ioremap;
+}
+
+void __init imx35_init_early(void)
+{
+	mxc_set_cpu_type(MXC_CPU_MX35);
+	mxc_iomux_v3_init(MX35_IO_ADDRESS(MX35_IOMUXC_BASE_ADDR));
+	mxc_arch_reset_init(MX35_IO_ADDRESS(MX35_WDOG_BASE_ADDR));
+	imx_idle = imx3_idle;
+	imx_ioremap = imx3_ioremap;
+}
+
+void __init mx31_init_irq(void)
+{
+	mxc_init_irq(MX31_IO_ADDRESS(MX31_AVIC_BASE_ADDR));
+}
+
+void __init mx35_init_irq(void)
+{
+	mxc_init_irq(MX35_IO_ADDRESS(MX35_AVIC_BASE_ADDR));
+}
+
+static struct sdma_script_start_addrs imx31_to1_sdma_script __initdata = {
+	.per_2_per_addr = 1677,
+};
+
+static struct sdma_script_start_addrs imx31_to2_sdma_script __initdata = {
+	.ap_2_ap_addr = 423,
+	.ap_2_bp_addr = 829,
+	.bp_2_ap_addr = 1029,
+};
+
+static struct sdma_platform_data imx31_sdma_pdata __initdata = {
+	.fw_name = "sdma-imx31-to2.bin",
+	.script_addrs = &imx31_to2_sdma_script,
+};
+
+void __init imx31_soc_init(void)
+{
+	int to_version = mx31_revision() >> 4;
+
+	imx3_init_l2x0();
+
+	mxc_register_gpio("imx31-gpio", 0, MX31_GPIO1_BASE_ADDR, SZ_16K, MX31_INT_GPIO1, 0);
+	mxc_register_gpio("imx31-gpio", 1, MX31_GPIO2_BASE_ADDR, SZ_16K, MX31_INT_GPIO2, 0);
+	mxc_register_gpio("imx31-gpio", 2, MX31_GPIO3_BASE_ADDR, SZ_16K, MX31_INT_GPIO3, 0);
+
+	if (to_version == 1) {
+		strncpy(imx31_sdma_pdata.fw_name, "sdma-imx31-to1.bin",
+			strlen(imx31_sdma_pdata.fw_name));
+		imx31_sdma_pdata.script_addrs = &imx31_to1_sdma_script;
+	}
+
+	imx_add_imx_sdma("imx31-sdma", MX31_SDMA_BASE_ADDR, MX31_INT_SDMA, &imx31_sdma_pdata);
+}
+
+static struct sdma_script_start_addrs imx35_to1_sdma_script __initdata = {
+	.ap_2_ap_addr = 642,
+	.uart_2_mcu_addr = 817,
+	.mcu_2_app_addr = 747,
+	.uartsh_2_mcu_addr = 1183,
+	.per_2_shp_addr = 1033,
+	.mcu_2_shp_addr = 961,
+	.ata_2_mcu_addr = 1333,
+	.mcu_2_ata_addr = 1252,
+	.app_2_mcu_addr = 683,
+	.shp_2_per_addr = 1111,
+	.shp_2_mcu_addr = 892,
+};
+
+static struct sdma_script_start_addrs imx35_to2_sdma_script __initdata = {
+	.ap_2_ap_addr = 729,
+	.uart_2_mcu_addr = 904,
+	.per_2_app_addr = 1597,
+	.mcu_2_app_addr = 834,
+	.uartsh_2_mcu_addr = 1270,
+	.per_2_shp_addr = 1120,
+	.mcu_2_shp_addr = 1048,
+	.ata_2_mcu_addr = 1429,
+	.mcu_2_ata_addr = 1339,
+	.app_2_per_addr = 1531,
+	.app_2_mcu_addr = 770,
+	.shp_2_per_addr = 1198,
+	.shp_2_mcu_addr = 979,
+};
+
+static struct sdma_platform_data imx35_sdma_pdata __initdata = {
+	.fw_name = "sdma-imx35-to2.bin",
+	.script_addrs = &imx35_to2_sdma_script,
+};
+
+void __init imx35_soc_init(void)
+{
+	int to_version = mx35_revision() >> 4;
+
+	imx3_init_l2x0();
+
+	/* i.mx35 has the i.mx31 type gpio */
+	mxc_register_gpio("imx31-gpio", 0, MX35_GPIO1_BASE_ADDR, SZ_16K, MX35_INT_GPIO1, 0);
+	mxc_register_gpio("imx31-gpio", 1, MX35_GPIO2_BASE_ADDR, SZ_16K, MX35_INT_GPIO2, 0);
+	mxc_register_gpio("imx31-gpio", 2, MX35_GPIO3_BASE_ADDR, SZ_16K, MX35_INT_GPIO3, 0);
+
+	if (to_version == 1) {
+		strncpy(imx35_sdma_pdata.fw_name, "sdma-imx35-to1.bin",
+			strlen(imx35_sdma_pdata.fw_name));
+		imx35_sdma_pdata.script_addrs = &imx35_to1_sdma_script;
+	}
+
+	imx_add_imx_sdma("imx35-sdma", MX35_SDMA_BASE_ADDR, MX35_INT_SDMA, &imx35_sdma_pdata);
+}
diff --git a/arch/arm/mach-imx/mm-imx31.c b/arch/arm/mach-imx/mm-imx31.c
deleted file mode 100644
index b7c55e7..0000000
--- a/arch/arm/mach-imx/mm-imx31.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- *  Copyright (C) 1999,2000 Arm Limited
- *  Copyright (C) 2000 Deep Blue Solutions Ltd
- *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
- *  Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- *    - add MX31 specific definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/err.h>
-
-#include <asm/pgtable.h>
-#include <asm/mach/map.h>
-
-#include <mach/common.h>
-#include <mach/devices-common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-v3.h>
-#include <mach/irqs.h>
-
-static struct map_desc mx31_io_desc[] __initdata = {
-	imx_map_entry(MX31, X_MEMC, MT_DEVICE),
-	imx_map_entry(MX31, AVIC, MT_DEVICE_NONSHARED),
-	imx_map_entry(MX31, AIPS1, MT_DEVICE_NONSHARED),
-	imx_map_entry(MX31, AIPS2, MT_DEVICE_NONSHARED),
-	imx_map_entry(MX31, SPBA0, MT_DEVICE_NONSHARED),
-};
-
-/*
- * This function initializes the memory map. It is called during the
- * system startup to create static physical to virtual memory mappings
- * for the IO modules.
- */
-void __init mx31_map_io(void)
-{
-	iotable_init(mx31_io_desc, ARRAY_SIZE(mx31_io_desc));
-}
-
-void __init imx31_init_early(void)
-{
-	mxc_set_cpu_type(MXC_CPU_MX31);
-	mxc_arch_reset_init(MX31_IO_ADDRESS(MX31_WDOG_BASE_ADDR));
-}
-
-void __init mx31_init_irq(void)
-{
-	mxc_init_irq(MX31_IO_ADDRESS(MX31_AVIC_BASE_ADDR));
-}
-
-static struct sdma_script_start_addrs imx31_to1_sdma_script __initdata = {
-	.per_2_per_addr = 1677,
-};
-
-static struct sdma_script_start_addrs imx31_to2_sdma_script __initdata = {
-	.ap_2_ap_addr = 423,
-	.ap_2_bp_addr = 829,
-	.bp_2_ap_addr = 1029,
-};
-
-static struct sdma_platform_data imx31_sdma_pdata __initdata = {
-	.fw_name = "sdma-imx31-to2.bin",
-	.script_addrs = &imx31_to2_sdma_script,
-};
-
-void __init imx31_soc_init(void)
-{
-	int to_version = mx31_revision() >> 4;
-
-	mxc_register_gpio("imx31-gpio", 0, MX31_GPIO1_BASE_ADDR, SZ_16K, MX31_INT_GPIO1, 0);
-	mxc_register_gpio("imx31-gpio", 1, MX31_GPIO2_BASE_ADDR, SZ_16K, MX31_INT_GPIO2, 0);
-	mxc_register_gpio("imx31-gpio", 2, MX31_GPIO3_BASE_ADDR, SZ_16K, MX31_INT_GPIO3, 0);
-
-	if (to_version == 1) {
-		strncpy(imx31_sdma_pdata.fw_name, "sdma-imx31-to1.bin",
-			strlen(imx31_sdma_pdata.fw_name));
-		imx31_sdma_pdata.script_addrs = &imx31_to1_sdma_script;
-	}
-
-	imx_add_imx_sdma("imx31-sdma", MX31_SDMA_BASE_ADDR, MX31_INT_SDMA, &imx31_sdma_pdata);
-}
diff --git a/arch/arm/mach-imx/mm-imx35.c b/arch/arm/mach-imx/mm-imx35.c
deleted file mode 100644
index f49bac7..0000000
--- a/arch/arm/mach-imx/mm-imx35.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- *  Copyright (C) 1999,2000 Arm Limited
- *  Copyright (C) 2000 Deep Blue Solutions Ltd
- *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
- *  Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- *    - add MX31 specific definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/err.h>
-
-#include <asm/pgtable.h>
-#include <asm/mach/map.h>
-#include <asm/hardware/cache-l2x0.h>
-
-#include <mach/common.h>
-#include <mach/devices-common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-v3.h>
-#include <mach/irqs.h>
-
-static struct map_desc mx35_io_desc[] __initdata = {
-	imx_map_entry(MX35, X_MEMC, MT_DEVICE),
-	imx_map_entry(MX35, AVIC, MT_DEVICE_NONSHARED),
-	imx_map_entry(MX35, AIPS1, MT_DEVICE_NONSHARED),
-	imx_map_entry(MX35, AIPS2, MT_DEVICE_NONSHARED),
-	imx_map_entry(MX35, SPBA0, MT_DEVICE_NONSHARED),
-};
-
-void __init mx35_map_io(void)
-{
-	iotable_init(mx35_io_desc, ARRAY_SIZE(mx35_io_desc));
-}
-
-void __init imx35_init_early(void)
-{
-	mxc_set_cpu_type(MXC_CPU_MX35);
-	mxc_iomux_v3_init(MX35_IO_ADDRESS(MX35_IOMUXC_BASE_ADDR));
-	mxc_arch_reset_init(MX35_IO_ADDRESS(MX35_WDOG_BASE_ADDR));
-}
-
-void __init mx35_init_irq(void)
-{
-	mxc_init_irq(MX35_IO_ADDRESS(MX35_AVIC_BASE_ADDR));
-}
-
-static struct sdma_script_start_addrs imx35_to1_sdma_script __initdata = {
-	.ap_2_ap_addr = 642,
-	.uart_2_mcu_addr = 817,
-	.mcu_2_app_addr = 747,
-	.uartsh_2_mcu_addr = 1183,
-	.per_2_shp_addr = 1033,
-	.mcu_2_shp_addr = 961,
-	.ata_2_mcu_addr = 1333,
-	.mcu_2_ata_addr = 1252,
-	.app_2_mcu_addr = 683,
-	.shp_2_per_addr = 1111,
-	.shp_2_mcu_addr = 892,
-};
-
-static struct sdma_script_start_addrs imx35_to2_sdma_script __initdata = {
-	.ap_2_ap_addr = 729,
-	.uart_2_mcu_addr = 904,
-	.per_2_app_addr = 1597,
-	.mcu_2_app_addr = 834,
-	.uartsh_2_mcu_addr = 1270,
-	.per_2_shp_addr = 1120,
-	.mcu_2_shp_addr = 1048,
-	.ata_2_mcu_addr = 1429,
-	.mcu_2_ata_addr = 1339,
-	.app_2_per_addr = 1531,
-	.app_2_mcu_addr = 770,
-	.shp_2_per_addr = 1198,
-	.shp_2_mcu_addr = 979,
-};
-
-static struct sdma_platform_data imx35_sdma_pdata __initdata = {
-	.fw_name = "sdma-imx35-to2.bin",
-	.script_addrs = &imx35_to2_sdma_script,
-};
-
-void __init imx35_soc_init(void)
-{
-	int to_version = mx35_revision() >> 4;
-
-	/* i.mx35 has the i.mx31 type gpio */
-	mxc_register_gpio("imx31-gpio", 0, MX35_GPIO1_BASE_ADDR, SZ_16K, MX35_INT_GPIO1, 0);
-	mxc_register_gpio("imx31-gpio", 1, MX35_GPIO2_BASE_ADDR, SZ_16K, MX35_INT_GPIO2, 0);
-	mxc_register_gpio("imx31-gpio", 2, MX35_GPIO3_BASE_ADDR, SZ_16K, MX35_INT_GPIO3, 0);
-
-	if (to_version == 1) {
-		strncpy(imx35_sdma_pdata.fw_name, "sdma-imx35-to1.bin",
-			strlen(imx35_sdma_pdata.fw_name));
-		imx35_sdma_pdata.script_addrs = &imx35_to1_sdma_script;
-	}
-
-	imx_add_imx_sdma("imx35-sdma", MX35_SDMA_BASE_ADDR, MX35_INT_SDMA, &imx35_sdma_pdata);
-}
diff --git a/arch/arm/mach-imx/mmdc.c b/arch/arm/mach-imx/mmdc.c
new file mode 100644
index 0000000..c461e98
--- /dev/null
+++ b/arch/arm/mach-imx/mmdc.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+
+#define MMDC_MAPSR		0x404
+#define BP_MMDC_MAPSR_PSD	0
+#define BP_MMDC_MAPSR_PSS	4
+
+static int __devinit imx_mmdc_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	void __iomem *mmdc_base, *reg;
+	u32 val;
+	int timeout = 0x400;
+
+	mmdc_base = of_iomap(np, 0);
+	WARN_ON(!mmdc_base);
+
+	reg = mmdc_base + MMDC_MAPSR;
+
+	/* Enable automatic power saving */
+	val = readl_relaxed(reg);
+	val &= ~(1 << BP_MMDC_MAPSR_PSD);
+	writel_relaxed(val, reg);
+
+	/* Ensure it's successfully enabled */
+	while (!(readl_relaxed(reg) & 1 << BP_MMDC_MAPSR_PSS) && --timeout)
+		cpu_relax();
+
+	if (unlikely(!timeout)) {
+		pr_warn("%s: failed to enable automatic power saving\n",
+			__func__);
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+static struct of_device_id imx_mmdc_dt_ids[] = {
+	{ .compatible = "fsl,imx6q-mmdc", },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver imx_mmdc_driver = {
+	.driver		= {
+		.name	= "imx-mmdc",
+		.owner	= THIS_MODULE,
+		.of_match_table = imx_mmdc_dt_ids,
+	},
+	.probe		= imx_mmdc_probe,
+};
+
+static int __init imx_mmdc_init(void)
+{
+	return platform_driver_register(&imx_mmdc_driver);
+}
+postcore_initcall(imx_mmdc_init);
diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c
new file mode 100644
index 0000000..ab98c6f
--- /dev/null
+++ b/arch/arm/mach-imx/platsmp.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <asm/page.h>
+#include <asm/smp_scu.h>
+#include <asm/hardware/gic.h>
+#include <asm/mach/map.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+
+static void __iomem *scu_base;
+
+static struct map_desc scu_io_desc __initdata = {
+	/* .virtual and .pfn are run-time assigned */
+	.length		= SZ_4K,
+	.type		= MT_DEVICE,
+};
+
+void __init imx_scu_map_io(void)
+{
+	unsigned long base;
+
+	/* Get SCU base */
+	asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
+
+	scu_io_desc.virtual = IMX_IO_P2V(base);
+	scu_io_desc.pfn = __phys_to_pfn(base);
+	iotable_init(&scu_io_desc, 1);
+
+	scu_base = IMX_IO_ADDRESS(base);
+}
+
+void __cpuinit platform_secondary_init(unsigned int cpu)
+{
+	/*
+	 * if any interrupts are already enabled for the primary
+	 * core (e.g. timer irq), then they will not have been enabled
+	 * for us: do so
+	 */
+	gic_secondary_init(0);
+}
+
+int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	imx_set_cpu_jump(cpu, v7_secondary_startup);
+	imx_enable_cpu(cpu, true);
+	return 0;
+}
+
+/*
+ * Initialise the CPU possible map early - this describes the CPUs
+ * which may be present or become present in the system.
+ */
+void __init smp_init_cpus(void)
+{
+	int i, ncores;
+
+	ncores = scu_get_core_count(scu_base);
+
+	for (i = 0; i < ncores; i++)
+		set_cpu_possible(i, true);
+
+	set_smp_cross_call(gic_raise_softirq);
+}
+
+void imx_smp_prepare(void)
+{
+	scu_enable(scu_base);
+}
+
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+	imx_smp_prepare();
+}
diff --git a/arch/arm/mach-imx/pm-imx27.c b/arch/arm/mach-imx/pm-imx27.c
index acf1769..e455d2f 100644
--- a/arch/arm/mach-imx/pm-imx27.c
+++ b/arch/arm/mach-imx/pm-imx27.c
@@ -11,7 +11,7 @@
 #include <linux/suspend.h>
 #include <linux/io.h>
 #include <mach/system.h>
-#include <mach/mx27.h>
+#include <mach/hardware.h>
 
 static int mx27_suspend_enter(suspend_state_t state)
 {
diff --git a/arch/arm/mach-imx/pm-imx6q.c b/arch/arm/mach-imx/pm-imx6q.c
new file mode 100644
index 0000000..f20f191
--- /dev/null
+++ b/arch/arm/mach-imx/pm-imx6q.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/suspend.h>
+#include <asm/cacheflush.h>
+#include <asm/proc-fns.h>
+#include <asm/suspend.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+
+extern unsigned long phys_l2x0_saved_regs;
+
+static int imx6q_suspend_finish(unsigned long val)
+{
+	cpu_do_idle();
+	return 0;
+}
+
+static int imx6q_pm_enter(suspend_state_t state)
+{
+	switch (state) {
+	case PM_SUSPEND_MEM:
+		imx6q_set_lpm(STOP_POWER_OFF);
+		imx_gpc_pre_suspend();
+		imx_set_cpu_jump(0, v7_cpu_resume);
+		/* Zzz ... */
+		cpu_suspend(0, imx6q_suspend_finish);
+		imx_smp_prepare();
+		imx_gpc_post_resume();
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct platform_suspend_ops imx6q_pm_ops = {
+	.enter = imx6q_pm_enter,
+	.valid = suspend_valid_only_mem,
+};
+
+void __init imx6q_pm_init(void)
+{
+	/*
+	 * The l2x0 core code provides an infrastucture to save and restore
+	 * l2x0 registers across suspend/resume cycle.  But because imx6q
+	 * retains L2 content during suspend and needs to resume L2 before
+	 * MMU is enabled, it can only utilize register saving support and
+	 * have to take care of restoring on its own.  So we save physical
+	 * address of the data structure used by l2x0 core to save registers,
+	 * and later restore the necessary ones in imx6q resume entry.
+	 */
+	phys_l2x0_saved_regs = __pa(&l2x0_saved_regs);
+
+	suspend_set_ops(&imx6q_pm_ops);
+}
diff --git a/arch/arm/mach-imx/src.c b/arch/arm/mach-imx/src.c
new file mode 100644
index 0000000..36cacbd
--- /dev/null
+++ b/arch/arm/mach-imx/src.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <asm/unified.h>
+
+#define SRC_SCR				0x000
+#define SRC_GPR1			0x020
+#define BP_SRC_SCR_CORE1_RST		14
+#define BP_SRC_SCR_CORE1_ENABLE		22
+
+static void __iomem *src_base;
+
+void imx_enable_cpu(int cpu, bool enable)
+{
+	u32 mask, val;
+
+	mask = 1 << (BP_SRC_SCR_CORE1_ENABLE + cpu - 1);
+	val = readl_relaxed(src_base + SRC_SCR);
+	val = enable ? val | mask : val & ~mask;
+	writel_relaxed(val, src_base + SRC_SCR);
+}
+
+void imx_set_cpu_jump(int cpu, void *jump_addr)
+{
+	writel_relaxed(BSYM(virt_to_phys(jump_addr)),
+		       src_base + SRC_GPR1 + cpu * 8);
+}
+
+void __init imx_src_init(void)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-src");
+	src_base = of_iomap(np, 0);
+	WARN_ON(!src_base);
+}
diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig
index 6f991c5..fd5e7b6 100644
--- a/arch/arm/mach-ixp4xx/Kconfig
+++ b/arch/arm/mach-ixp4xx/Kconfig
@@ -179,6 +179,25 @@ config MACH_GTWX5715
 		"High Speed" UART is n/c (as far as I can tell)
 		20 Pin ARM/Xscale JTAG interface on J2
 
+config MACH_DEVIXP
+	bool "Omicron DEVIXP"
+	help
+	  Say 'Y' here if you want your kernel to support the DEVIXP
+	  board from OMICRON electronics GmbH.
+
+config MACH_MICCPT
+	bool "Omicron MICCPT"
+	select PCI
+	help
+	  Say 'Y' here if you want your kernel to support the MICCPT
+	  board from OMICRON electronics GmbH.
+
+config MACH_MIC256
+	bool "Omicron MIC256"
+	help
+	  Say 'Y' here if you want your kernel to support the MIC256
+	  board from OMICRON electronics GmbH.
+
 comment "IXP4xx Options"
 
 config IXP4XX_INDIRECT_PCI
diff --git a/arch/arm/mach-ixp4xx/Makefile b/arch/arm/mach-ixp4xx/Makefile
index d807fc3..eded94c 100644
--- a/arch/arm/mach-ixp4xx/Makefile
+++ b/arch/arm/mach-ixp4xx/Makefile
@@ -10,6 +10,7 @@ obj-pci-$(CONFIG_MACH_AVILA)		+= avila-pci.o
 obj-pci-$(CONFIG_MACH_IXDPG425)		+= ixdpg425-pci.o
 obj-pci-$(CONFIG_ARCH_ADI_COYOTE)	+= coyote-pci.o
 obj-pci-$(CONFIG_MACH_GTWX5715)		+= gtwx5715-pci.o
+obj-pci-$(CONFIG_MACH_MICCPT)		+= miccpt-pci.o
 obj-pci-$(CONFIG_MACH_NSLU2)		+= nslu2-pci.o
 obj-pci-$(CONFIG_MACH_NAS100D)		+= nas100d-pci.o
 obj-pci-$(CONFIG_MACH_DSMG600)		+= dsmg600-pci.o
@@ -25,6 +26,9 @@ obj-$(CONFIG_MACH_AVILA)	+= avila-setup.o
 obj-$(CONFIG_MACH_IXDPG425)	+= coyote-setup.o
 obj-$(CONFIG_ARCH_ADI_COYOTE)	+= coyote-setup.o
 obj-$(CONFIG_MACH_GTWX5715)	+= gtwx5715-setup.o
+obj-$(CONFIG_MACH_DEVIXP)	+= omixp-setup.o
+obj-$(CONFIG_MACH_MICCPT)	+= omixp-setup.o
+obj-$(CONFIG_MACH_MIC256)	+= omixp-setup.o
 obj-$(CONFIG_MACH_NSLU2)	+= nslu2-setup.o
 obj-$(CONFIG_MACH_NAS100D)	+= nas100d-setup.o
 obj-$(CONFIG_MACH_DSMG600)      += dsmg600-setup.o
diff --git a/arch/arm/mach-ixp4xx/include/mach/uncompress.h b/arch/arm/mach-ixp4xx/include/mach/uncompress.h
index 219d7c1..eb945a9 100644
--- a/arch/arm/mach-ixp4xx/include/mach/uncompress.h
+++ b/arch/arm/mach-ixp4xx/include/mach/uncompress.h
@@ -41,7 +41,8 @@ static __inline__ void __arch_decomp_setup(unsigned long arch_id)
 	 * Some boards are using UART2 as console
 	 */
 	if (machine_is_adi_coyote() || machine_is_gtwx5715() ||
-			 machine_is_gateway7001() || machine_is_wg302v2())
+	    machine_is_gateway7001() || machine_is_wg302v2() ||
+	    machine_is_devixp() || machine_is_miccpt() || machine_is_mic256())
 		uart_base = (volatile u32*) IXP4XX_UART2_BASE_PHYS;
 	else
 		uart_base = (volatile u32*) IXP4XX_UART1_BASE_PHYS;
diff --git a/arch/arm/mach-ixp4xx/miccpt-pci.c b/arch/arm/mach-ixp4xx/miccpt-pci.c
new file mode 100644
index 0000000..ca0bae7
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/miccpt-pci.c
@@ -0,0 +1,78 @@
+/*
+ * arch/arm/mach-ixp4xx/miccpt-pci.c
+ *
+ * MICCPT board-level PCI initialization
+ *
+ * Copyright (C) 2002 Intel Corporation.
+ * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ * Copyright (C) 2006 OMICRON electronics GmbH
+ *
+ * Author: Michael Jochum <michael.jochum@omicron.at>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <asm/mach/pci.h>
+#include <asm/irq.h>
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+
+#define MAX_DEV		4
+#define IRQ_LINES	4
+
+/* PCI controller GPIO to IRQ pin mappings */
+#define INTA		1
+#define INTB		2
+#define INTC		3
+#define INTD		4
+
+
+void __init miccpt_pci_preinit(void)
+{
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);
+	ixp4xx_pci_preinit();
+}
+
+static int __init miccpt_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	static int pci_irq_table[IRQ_LINES] = {
+		IXP4XX_GPIO_IRQ(INTA),
+		IXP4XX_GPIO_IRQ(INTB),
+		IXP4XX_GPIO_IRQ(INTC),
+		IXP4XX_GPIO_IRQ(INTD)
+	};
+
+	if (slot >= 1 && slot <= MAX_DEV && pin >= 1 && pin <= IRQ_LINES)
+		return pci_irq_table[(slot + pin - 2) % 4];
+
+	return -1;
+}
+
+struct hw_pci miccpt_pci __initdata = {
+	.nr_controllers = 1,
+	.preinit	= miccpt_pci_preinit,
+	.swizzle	= pci_std_swizzle,
+	.setup		= ixp4xx_setup,
+	.scan		= ixp4xx_scan_bus,
+	.map_irq	= miccpt_map_irq,
+};
+
+int __init miccpt_pci_init(void)
+{
+	if (machine_is_miccpt())
+		pci_common_init(&miccpt_pci);
+	return 0;
+}
+
+subsys_initcall(miccpt_pci_init);
diff --git a/arch/arm/mach-ixp4xx/omixp-setup.c b/arch/arm/mach-ixp4xx/omixp-setup.c
new file mode 100644
index 0000000..3b6a81a
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/omixp-setup.c
@@ -0,0 +1,273 @@
+/*
+ * arch/arm/mach-ixp4xx/omixp-setup.c
+ *
+ * omicron ixp4xx board setup
+ *      Copyright (C) 2009 OMICRON electronics GmbH
+ *
+ * based nslu2-setup.c, ixdp425-setup.c:
+ *      Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#ifdef CONFIG_LEDS_CLASS
+#include <linux/leds.h>
+#endif
+
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+static struct resource omixp_flash_resources[] = {
+	{
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct mtd_partition omixp_partitions[] = {
+	{
+		.name =		"Recovery Bootloader",
+		.size =		0x00020000,
+		.offset =	0,
+	}, {
+		.name =		"Calibration Data",
+		.size =		0x00020000,
+		.offset =	0x00020000,
+	}, {
+		.name =		"Recovery FPGA",
+		.size =		0x00020000,
+		.offset =	0x00040000,
+	}, {
+		.name =		"Release Bootloader",
+		.size =		0x00020000,
+		.offset =	0x00060000,
+	}, {
+		.name =		"Release FPGA",
+		.size =		0x00020000,
+		.offset =	0x00080000,
+	}, {
+		.name =		"Kernel",
+		.size =		0x00160000,
+		.offset =	0x000a0000,
+	}, {
+		.name =		"Filesystem",
+		.size =		0x00C00000,
+		.offset =	0x00200000,
+	}, {
+		.name =		"Persistent Storage",
+		.size =		0x00200000,
+		.offset =	0x00E00000,
+	},
+};
+
+static struct flash_platform_data omixp_flash_data[] = {
+	{
+		.map_name	= "cfi_probe",
+		.parts		= omixp_partitions,
+		.nr_parts	= ARRAY_SIZE(omixp_partitions),
+	}, {
+		.map_name	= "cfi_probe",
+		.parts		= NULL,
+		.nr_parts	= 0,
+	},
+};
+
+static struct platform_device omixp_flash_device[] = {
+	{
+		.name		= "IXP4XX-Flash",
+		.id		= 0,
+		.dev = {
+			.platform_data = &omixp_flash_data[0],
+		},
+		.resource = &omixp_flash_resources[0],
+		.num_resources = 1,
+	}, {
+		.name		= "IXP4XX-Flash",
+		.id		= 1,
+		.dev = {
+			.platform_data = &omixp_flash_data[1],
+		},
+		.resource = &omixp_flash_resources[1],
+		.num_resources = 1,
+	},
+};
+
+/* Swap UART's - These boards have the console on UART2. The following
+ * configuration is used:
+ *      ttyS0 .. UART2
+ *      ttyS1 .. UART1
+ * This way standard images can be used with the kernel that expect
+ * the console on ttyS0.
+ */
+static struct resource omixp_uart_resources[] = {
+	{
+		.start		= IXP4XX_UART2_BASE_PHYS,
+		.end		= IXP4XX_UART2_BASE_PHYS + 0x0fff,
+		.flags		= IORESOURCE_MEM,
+	}, {
+		.start		= IXP4XX_UART1_BASE_PHYS,
+		.end		= IXP4XX_UART1_BASE_PHYS + 0x0fff,
+		.flags		= IORESOURCE_MEM,
+	},
+};
+
+static struct plat_serial8250_port omixp_uart_data[] = {
+	{
+		.mapbase	= IXP4XX_UART2_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART2,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	}, {
+		.mapbase	= IXP4XX_UART1_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART1,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	}, {
+		/* list termination */
+	}
+};
+
+static struct platform_device omixp_uart = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev.platform_data	= omixp_uart_data,
+	.num_resources		= 2,
+	.resource		= omixp_uart_resources,
+};
+
+static struct gpio_led mic256_led_pins[] = {
+	{
+		.name		= "LED-A",
+		.gpio		= 7,
+	},
+};
+
+static struct gpio_led_platform_data mic256_led_data = {
+	.num_leds		= ARRAY_SIZE(mic256_led_pins),
+	.leds			= mic256_led_pins,
+};
+
+static struct platform_device mic256_leds = {
+	.name			= "leds-gpio",
+	.id			= -1,
+	.dev.platform_data	= &mic256_led_data,
+};
+
+/* Built-in 10/100 Ethernet MAC interfaces */
+static struct eth_plat_info ixdp425_plat_eth[] = {
+	{
+		.phy		= 0,
+		.rxq		= 3,
+		.txreadyq	= 20,
+	}, {
+		.phy		= 1,
+		.rxq		= 4,
+		.txreadyq	= 21,
+	},
+};
+
+static struct platform_device ixdp425_eth[] = {
+	{
+		.name			= "ixp4xx_eth",
+		.id			= IXP4XX_ETH_NPEB,
+		.dev.platform_data	= ixdp425_plat_eth,
+	}, {
+		.name			= "ixp4xx_eth",
+		.id			= IXP4XX_ETH_NPEC,
+		.dev.platform_data	= ixdp425_plat_eth + 1,
+	},
+};
+
+
+static struct platform_device *devixp_pldev[] __initdata = {
+	&omixp_uart,
+	&omixp_flash_device[0],
+	&ixdp425_eth[0],
+	&ixdp425_eth[1],
+};
+
+static struct platform_device *mic256_pldev[] __initdata = {
+	&omixp_uart,
+	&omixp_flash_device[0],
+	&mic256_leds,
+	&ixdp425_eth[0],
+	&ixdp425_eth[1],
+};
+
+static struct platform_device *miccpt_pldev[] __initdata = {
+	&omixp_uart,
+	&omixp_flash_device[0],
+	&omixp_flash_device[1],
+	&ixdp425_eth[0],
+	&ixdp425_eth[1],
+};
+
+static void __init omixp_init(void)
+{
+	ixp4xx_sys_init();
+
+	/* 16MiB Boot Flash */
+	omixp_flash_resources[0].start = IXP4XX_EXP_BUS_BASE(0);
+	omixp_flash_resources[0].end   = IXP4XX_EXP_BUS_END(0);
+
+	/* 32 MiB Data Flash */
+	omixp_flash_resources[1].start = IXP4XX_EXP_BUS_BASE(2);
+	omixp_flash_resources[1].end   = IXP4XX_EXP_BUS_END(2);
+
+	if (machine_is_devixp())
+		platform_add_devices(devixp_pldev, ARRAY_SIZE(devixp_pldev));
+	else if (machine_is_miccpt())
+		platform_add_devices(miccpt_pldev, ARRAY_SIZE(miccpt_pldev));
+	else if (machine_is_mic256())
+		platform_add_devices(mic256_pldev, ARRAY_SIZE(mic256_pldev));
+}
+
+#ifdef CONFIG_MACH_DEVIXP
+MACHINE_START(DEVIXP, "Omicron DEVIXP")
+	.atag_offset    = 0x100,
+	.map_io		= ixp4xx_map_io,
+	.init_irq	= ixp4xx_init_irq,
+	.timer          = &ixp4xx_timer,
+	.init_machine	= omixp_init,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_MICCPT
+MACHINE_START(MICCPT, "Omicron MICCPT")
+	.atag_offset    = 0x100,
+	.map_io		= ixp4xx_map_io,
+	.init_irq	= ixp4xx_init_irq,
+	.timer          = &ixp4xx_timer,
+	.init_machine	= omixp_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_MIC256
+MACHINE_START(MIC256, "Omicron MIC256")
+	.atag_offset    = 0x100,
+	.map_io		= ixp4xx_map_io,
+	.init_irq	= ixp4xx_init_irq,
+	.timer          = &ixp4xx_timer,
+	.init_machine	= omixp_init,
+MACHINE_END
+#endif
diff --git a/arch/arm/mach-mmp/Kconfig b/arch/arm/mach-mmp/Kconfig
index 56ef5f6..323d4c9 100644
--- a/arch/arm/mach-mmp/Kconfig
+++ b/arch/arm/mach-mmp/Kconfig
@@ -77,7 +77,7 @@ config MACH_TETON_BGA
 	  Say 'Y' here if you want to support the Marvell PXA168-based
 	  Teton BGA Development Board.
 
-config MACH_SHEEVAD
+config MACH_GPLUGD
 	bool "Marvell's PXA168 GuruPlug Display (gplugD) Board"
 	select CPU_PXA168
 	help
diff --git a/arch/arm/mach-mmp/Makefile b/arch/arm/mach-mmp/Makefile
index b0ac942..8f948f9 100644
--- a/arch/arm/mach-mmp/Makefile
+++ b/arch/arm/mach-mmp/Makefile
@@ -19,4 +19,4 @@ obj-$(CONFIG_MACH_BROWNSTONE)	+= brownstone.o
 obj-$(CONFIG_MACH_FLINT)	+= flint.o
 obj-$(CONFIG_MACH_MARVELL_JASPER) += jasper.o
 obj-$(CONFIG_MACH_TETON_BGA)	+= teton_bga.o
-obj-$(CONFIG_MACH_SHEEVAD)	+= gplugd.o
+obj-$(CONFIG_MACH_GPLUGD)	+= gplugd.o
diff --git a/arch/arm/mach-mmp/clock.h b/arch/arm/mach-mmp/clock.h
index 3143e99..149b30c 100644
--- a/arch/arm/mach-mmp/clock.h
+++ b/arch/arm/mach-mmp/clock.h
@@ -30,7 +30,7 @@ extern struct clkops apmu_clk_ops;
 
 #define APBC_CLK(_name, _reg, _fnclksel, _rate)			\
 struct clk clk_##_name = {					\
-		.clk_rst	= (void __iomem *)APBC_##_reg,	\
+		.clk_rst	= APBC_##_reg,			\
 		.fnclksel	= _fnclksel,			\
 		.rate		= _rate,			\
 		.ops		= &apbc_clk_ops,		\
@@ -38,7 +38,7 @@ struct clk clk_##_name = {					\
 
 #define APBC_CLK_OPS(_name, _reg, _fnclksel, _rate, _ops)	\
 struct clk clk_##_name = {					\
-		.clk_rst	= (void __iomem *)APBC_##_reg,	\
+		.clk_rst	= APBC_##_reg,			\
 		.fnclksel	= _fnclksel,			\
 		.rate		= _rate,			\
 		.ops		= _ops,				\
@@ -46,7 +46,7 @@ struct clk clk_##_name = {					\
 
 #define APMU_CLK(_name, _reg, _eval, _rate)			\
 struct clk clk_##_name = {					\
-		.clk_rst	= (void __iomem *)APMU_##_reg,	\
+		.clk_rst	= APMU_##_reg,			\
 		.enable_val	= _eval,			\
 		.rate		= _rate,			\
 		.ops		= &apmu_clk_ops,		\
@@ -54,7 +54,7 @@ struct clk clk_##_name = {					\
 
 #define APMU_CLK_OPS(_name, _reg, _eval, _rate, _ops)		\
 struct clk clk_##_name = {					\
-		.clk_rst	= (void __iomem *)APMU_##_reg,	\
+		.clk_rst	= APMU_##_reg,			\
 		.enable_val	= _eval,			\
 		.rate		= _rate,			\
 		.ops		= _ops,				\
diff --git a/arch/arm/mach-mmp/common.c b/arch/arm/mach-mmp/common.c
index 0ec0ca8..5720674 100644
--- a/arch/arm/mach-mmp/common.c
+++ b/arch/arm/mach-mmp/common.c
@@ -27,12 +27,12 @@ EXPORT_SYMBOL(mmp_chip_id);
 static struct map_desc standard_io_desc[] __initdata = {
 	{
 		.pfn		= __phys_to_pfn(APB_PHYS_BASE),
-		.virtual	= APB_VIRT_BASE,
+		.virtual	= (unsigned long)APB_VIRT_BASE,
 		.length		= APB_PHYS_SIZE,
 		.type		= MT_DEVICE,
 	}, {
 		.pfn		= __phys_to_pfn(AXI_PHYS_BASE),
-		.virtual	= AXI_VIRT_BASE,
+		.virtual	= (unsigned long)AXI_VIRT_BASE,
 		.length		= AXI_PHYS_SIZE,
 		.type		= MT_DEVICE,
 	},
diff --git a/arch/arm/mach-mmp/gplugd.c b/arch/arm/mach-mmp/gplugd.c
index 32776f3..6915656 100644
--- a/arch/arm/mach-mmp/gplugd.c
+++ b/arch/arm/mach-mmp/gplugd.c
@@ -188,7 +188,7 @@ static void __init gplugd_init(void)
 	pxa168_add_eth(&gplugd_eth_platform_data);
 }
 
-MACHINE_START(SHEEVAD, "PXA168-based GuruPlug Display (gplugD) Platform")
+MACHINE_START(GPLUGD, "PXA168-based GuruPlug Display (gplugD) Platform")
 	.map_io		= mmp_map_io,
 	.nr_irqs	= IRQ_BOARD_START,
 	.init_irq       = pxa168_init_irq,
diff --git a/arch/arm/mach-mmp/include/mach/addr-map.h b/arch/arm/mach-mmp/include/mach/addr-map.h
index 3254089..3e404ac 100644
--- a/arch/arm/mach-mmp/include/mach/addr-map.h
+++ b/arch/arm/mach-mmp/include/mach/addr-map.h
@@ -11,6 +11,12 @@
 #ifndef __ASM_MACH_ADDR_MAP_H
 #define __ASM_MACH_ADDR_MAP_H
 
+#ifndef __ASSEMBLER__
+#define IOMEM(x)	((void __iomem *)(x))
+#else
+#define IOMEM(x)	(x)
+#endif
+
 /* APB - Application Subsystem Peripheral Bus
  *
  * NOTE: the DMA controller registers are actually on the AXI fabric #1
@@ -18,11 +24,11 @@
  * peripherals on APB, let's count it into the ABP mapping area.
  */
 #define APB_PHYS_BASE		0xd4000000
-#define APB_VIRT_BASE		0xfe000000
+#define APB_VIRT_BASE		IOMEM(0xfe000000)
 #define APB_PHYS_SIZE		0x00200000
 
 #define AXI_PHYS_BASE		0xd4200000
-#define AXI_VIRT_BASE		0xfe200000
+#define AXI_VIRT_BASE		IOMEM(0xfe200000)
 #define AXI_PHYS_SIZE		0x00200000
 
 /* Static Memory Controller - Chip Select 0 and 1 */
diff --git a/arch/arm/mach-mmp/include/mach/gpio-pxa.h b/arch/arm/mach-mmp/include/mach/gpio-pxa.h
index c017a98..d14eeaf 100644
--- a/arch/arm/mach-mmp/include/mach/gpio-pxa.h
+++ b/arch/arm/mach-mmp/include/mach/gpio-pxa.h
@@ -7,7 +7,7 @@
 #define GPIO_REGS_VIRT	(APB_VIRT_BASE + 0x19000)
 
 #define BANK_OFF(n)	(((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
-#define GPIO_REG(x)	(*((volatile u32 *)(GPIO_REGS_VIRT + (x))))
+#define GPIO_REG(x)	(GPIO_REGS_VIRT + (x))
 
 #define NR_BUILTIN_GPIO		IRQ_GPIO_NUM
 
diff --git a/arch/arm/mach-mmp/mmp2.c b/arch/arm/mach-mmp/mmp2.c
index 65d8689e..7a7e8e4 100644
--- a/arch/arm/mach-mmp/mmp2.c
+++ b/arch/arm/mach-mmp/mmp2.c
@@ -86,7 +86,8 @@ static struct mfp_addr_map mmp2_addr_map[] __initdata = {
 
 void mmp2_clear_pmic_int(void)
 {
-	unsigned long mfpr_pmic, data;
+	void __iomem *mfpr_pmic;
+	unsigned long data;
 
 	mfpr_pmic = APB_VIRT_BASE + 0x1e000 + 0x2c4;
 	data = __raw_readl(mfpr_pmic);
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 106170f..cf38e22 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010, 2011, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -8,18 +8,16 @@
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
  */
 
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
 #include <linux/memblock.h>
 
 #include <asm/mach-types.h>
@@ -70,6 +68,41 @@ static void __init msm8x60_init(void)
 {
 }
 
+#ifdef CONFIG_OF
+static struct of_dev_auxdata msm_auxdata_lookup[] __initdata = {
+	{}
+};
+
+static struct of_device_id msm_dt_gic_match[] __initdata = {
+	{ .compatible = "qcom,msm-8660-qgic", },
+	{}
+};
+
+static void __init msm8x60_dt_init(void)
+{
+	struct device_node *node;
+
+	node = of_find_matching_node_by_address(NULL, msm_dt_gic_match,
+			MSM8X60_QGIC_DIST_PHYS);
+	if (node)
+		irq_domain_add_simple(node, GIC_SPI_START);
+
+	if (of_machine_is_compatible("qcom,msm8660-surf")) {
+		printk(KERN_INFO "Init surf UART registers\n");
+		msm8x60_init_uart12dm();
+	}
+
+	of_platform_populate(NULL, of_default_bus_match_table,
+			msm_auxdata_lookup, NULL);
+}
+
+static const char *msm8x60_fluid_match[] __initdata = {
+	"qcom,msm8660-fluid",
+	"qcom,msm8660-surf",
+	NULL
+};
+#endif /* CONFIG_OF */
+
 MACHINE_START(MSM8X60_RUMI3, "QCT MSM8X60 RUMI3")
 	.fixup = msm8x60_fixup,
 	.reserve = msm8x60_reserve,
@@ -105,3 +138,14 @@ MACHINE_START(MSM8X60_FFA, "QCT MSM8X60 FFA")
 	.init_machine = msm8x60_init,
 	.timer = &msm_timer,
 MACHINE_END
+
+#ifdef CONFIG_OF
+/* TODO: General device tree support for all MSM. */
+DT_MACHINE_START(MSM_DT, "Qualcomm MSM (Flattened Device Tree)")
+	.map_io = msm8x60_map_io,
+	.init_irq = msm8x60_init_irq,
+	.init_machine = msm8x60_dt_init,
+	.timer = &msm_timer,
+	.dt_compat = msm8x60_fluid_match,
+MACHINE_END
+#endif /* CONFIG_OF */
diff --git a/arch/arm/mach-msm/hotplug.c b/arch/arm/mach-msm/hotplug.c
index 5a31f70..41c252d 100644
--- a/arch/arm/mach-msm/hotplug.c
+++ b/arch/arm/mach-msm/hotplug.c
@@ -37,7 +37,7 @@ static inline void platform_do_lowpower(unsigned int cpu)
 		    :
 		    : "memory", "cc");
 
-		if (pen_release == cpu) {
+		if (pen_release == cpu_logical_map(cpu)) {
 			/*
 			 * OK, proper wakeup, we're done
 			 */
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index 7276595..fdec58a 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -117,7 +117,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 	 * Note that "pen_release" is the hardware CPU ID, whereas
 	 * "cpu" is Linux's internal ID.
 	 */
-	pen_release = cpu;
+	pen_release = cpu_logical_map(cpu);
 	__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
 	outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
 
diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig
index b4e7c58..af0c212 100644
--- a/arch/arm/mach-mx5/Kconfig
+++ b/arch/arm/mach-mx5/Kconfig
@@ -1,8 +1,9 @@
-if ARCH_MX503 || ARCH_MX51
+if ARCH_MX5
+
 # ARCH_MX5/50/53 are left to mark places where prevent multi-soc in single
 # image. So for most time, SOC_IMX50/51/53 should be used.
 
-config ARCH_MX5
+config ARCH_MX51
 	bool
 
 config ARCH_MX50
@@ -19,7 +20,6 @@ config SOC_IMX50
 	select ARCH_MXC_IOMUX_V3
 	select ARCH_MXC_AUDMUX_V2
 	select ARCH_HAS_CPUFREQ
-	select ARCH_MX5
 	select ARCH_MX50
 
 config	SOC_IMX51
@@ -30,7 +30,7 @@ config	SOC_IMX51
 	select ARCH_MXC_IOMUX_V3
 	select ARCH_MXC_AUDMUX_V2
 	select ARCH_HAS_CPUFREQ
-	select ARCH_MX5
+	select ARCH_MX51
 
 config	SOC_IMX53
 	bool
@@ -38,10 +38,8 @@ config	SOC_IMX53
 	select ARM_L1_CACHE_SHIFT_6
 	select MXC_TZIC
 	select ARCH_MXC_IOMUX_V3
-	select ARCH_MX5
 	select ARCH_MX53
 
-if ARCH_MX50_SUPPORTED
 #comment "i.MX50 machines:"
 
 config MACH_MX50_RDP
@@ -52,22 +50,29 @@ config MACH_MX50_RDP
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
 	select IMX_HAVE_PLATFORM_SPI_IMX
-	select IMX_HAVE_PLATFORM_FEC
 	help
 	  Include support for MX50 reference design platform (RDP) board. This
 	  includes specific configurations for the board and its peripherals.
 
-endif # ARCH_MX50_SUPPORTED
-
-if ARCH_MX51
 comment "i.MX51 machines:"
 
+config MACH_IMX51_DT
+	bool "Support i.MX51 platforms from device tree"
+	select SOC_IMX51
+	select USE_OF
+	select MACH_MX51_BABBAGE
+	help
+	  Include support for Freescale i.MX51 based platforms
+	  using the device tree for discovery
+
 config MACH_MX51_BABBAGE
 	bool "Support MX51 BABBAGE platforms"
 	select SOC_IMX51
+	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
 	select IMX_HAVE_PLATFORM_IMX2_WDT
 	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_EHCI
 	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
 	select IMX_HAVE_PLATFORM_SPI_IMX
 	help
@@ -91,8 +96,10 @@ config MACH_MX51_3DS
 config MACH_EUKREA_CPUIMX51
 	bool "Support Eukrea CPUIMX51 module"
 	select SOC_IMX51
+	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
 	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_EHCI
 	select IMX_HAVE_PLATFORM_MXC_NAND
 	select IMX_HAVE_PLATFORM_SPI_IMX
 	help
@@ -119,10 +126,12 @@ endchoice
 config MACH_EUKREA_CPUIMX51SD
 	bool "Support Eukrea CPUIMX51SD module"
 	select SOC_IMX51
+	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
 	select IMX_HAVE_PLATFORM_IMX_I2C
-	select IMX_HAVE_PLATFORM_SPI_IMX
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_EHCI
 	select IMX_HAVE_PLATFORM_MXC_NAND
+	select IMX_HAVE_PLATFORM_SPI_IMX
 	help
 	  Include support for Eukrea CPUIMX51SD platform. This includes
 	  specific configurations for the module and its peripherals.
@@ -147,6 +156,8 @@ config MX51_EFIKA_COMMON
 	bool
 	select SOC_IMX51
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_EHCI
+	select IMX_HAVE_PLATFORM_PATA_IMX
 	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
 	select IMX_HAVE_PLATFORM_SPI_IMX
 	select MXC_ULPI if USB_ULPI
@@ -167,11 +178,20 @@ config MACH_MX51_EFIKASB
 	  Include support for Genesi Efika Smartbook. This includes specific
 	  configurations for the board and its peripherals.
 
-endif # ARCH_MX51
-
-if ARCH_MX53_SUPPORTED
 comment "i.MX53 machines:"
 
+config MACH_IMX53_DT
+	bool "Support i.MX53 platforms from device tree"
+	select SOC_IMX53
+	select USE_OF
+	select MACH_MX53_ARD
+	select MACH_MX53_EVK
+	select MACH_MX53_LOCO
+	select MACH_MX53_SMD
+	help
+	  Include support for Freescale i.MX53 based platforms
+	  using the device tree for discovery
+
 config MACH_MX53_EVK
 	bool "Support MX53 EVK platforms"
 	select SOC_IMX53
@@ -221,6 +241,4 @@ config MACH_MX53_ARD
 	  Include support for MX53 ARD platform. This includes specific
 	  configurations for the board and its peripherals.
 
-endif # ARCH_MX53_SUPPORTED
-
 endif
diff --git a/arch/arm/mach-mx5/Makefile b/arch/arm/mach-mx5/Makefile
index 383e7cd..0fc6080 100644
--- a/arch/arm/mach-mx5/Makefile
+++ b/arch/arm/mach-mx5/Makefile
@@ -3,8 +3,7 @@
 #
 
 # Object file lists.
-obj-y   := cpu.o mm.o clock-mx51-mx53.o devices.o ehci.o system.o
-obj-$(CONFIG_SOC_IMX50) += mm-mx50.o
+obj-y   := cpu.o mm.o clock-mx51-mx53.o ehci.o system.o
 
 obj-$(CONFIG_PM) += pm-imx5.o
 obj-$(CONFIG_CPU_FREQ_IMX)    += cpu_op-mx51.o
@@ -22,3 +21,6 @@ obj-$(CONFIG_MX51_EFIKA_COMMON) += mx51_efika.o
 obj-$(CONFIG_MACH_MX51_EFIKAMX) += board-mx51_efikamx.o
 obj-$(CONFIG_MACH_MX51_EFIKASB) += board-mx51_efikasb.o
 obj-$(CONFIG_MACH_MX50_RDP) += board-mx50_rdp.o
+
+obj-$(CONFIG_MACH_IMX51_DT) += imx51-dt.o
+obj-$(CONFIG_MACH_IMX53_DT) += imx53-dt.o
diff --git a/arch/arm/mach-mx5/board-cpuimx51.c b/arch/arm/mach-mx5/board-cpuimx51.c
index e01af94..1fc1103 100644
--- a/arch/arm/mach-mx5/board-cpuimx51.c
+++ b/arch/arm/mach-mx5/board-cpuimx51.c
@@ -22,21 +22,18 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/interrupt.h>
-#include <linux/irq.h>
 
 #include <mach/eukrea-baseboards.h>
 #include <mach/common.h>
 #include <mach/hardware.h>
 #include <mach/iomux-mx51.h>
 
-#include <asm/irq.h>
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
 #include "devices-imx51.h"
-#include "devices.h"
 
 #define CPUIMX51_USBH1_STP	IMX_GPIO_NR(1, 27)
 #define CPUIMX51_QUARTA_GPIO	IMX_GPIO_NR(3, 28)
@@ -57,7 +54,7 @@
 static struct plat_serial8250_port serial_platform_data[] = {
 	{
 		.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x400000),
-		.irq = gpio_to_irq(CPUIMX51_QUARTA_GPIO),
+		.irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTA_GPIO),
 		.irqflags = IRQF_TRIGGER_HIGH,
 		.uartclk = CPUIMX51_QUART_XTAL,
 		.regshift = CPUIMX51_QUART_REGSHIFT,
@@ -65,7 +62,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
 		.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
 	}, {
 		.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x800000),
-		.irq = gpio_to_irq(CPUIMX51_QUARTB_GPIO),
+		.irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTB_GPIO),
 		.irqflags = IRQF_TRIGGER_HIGH,
 		.uartclk = CPUIMX51_QUART_XTAL,
 		.regshift = CPUIMX51_QUART_REGSHIFT,
@@ -73,7 +70,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
 		.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
 	}, {
 		.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x1000000),
-		.irq = gpio_to_irq(CPUIMX51_QUARTC_GPIO),
+		.irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTC_GPIO),
 		.irqflags = IRQF_TRIGGER_HIGH,
 		.uartclk = CPUIMX51_QUART_XTAL,
 		.regshift = CPUIMX51_QUART_REGSHIFT,
@@ -81,7 +78,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
 		.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
 	}, {
 		.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x2000000),
-		.irq = gpio_to_irq(CPUIMX51_QUARTD_GPIO),
+		.irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTD_GPIO),
 		.irqflags = IRQF_TRIGGER_HIGH,
 		.uartclk = CPUIMX51_QUART_XTAL,
 		.regshift = CPUIMX51_QUART_REGSHIFT,
@@ -167,7 +164,7 @@ static int initialize_otg_port(struct platform_device *pdev)
 	void __iomem *usb_base;
 	void __iomem *usbother_base;
 
-	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
 	if (!usb_base)
 		return -ENOMEM;
 	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
@@ -190,7 +187,7 @@ static int initialize_usbh1_port(struct platform_device *pdev)
 	void __iomem *usb_base;
 	void __iomem *usbother_base;
 
-	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
 	if (!usb_base)
 		return -ENOMEM;
 	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
@@ -206,17 +203,17 @@ static int initialize_usbh1_port(struct platform_device *pdev)
 			MXC_EHCI_ITC_NO_THRESHOLD);
 }
 
-static struct mxc_usbh_platform_data dr_utmi_config = {
+static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
 	.init		= initialize_otg_port,
 	.portsc	= MXC_EHCI_UTMI_16BIT,
 };
 
-static struct fsl_usb2_platform_data usb_pdata = {
+static const struct fsl_usb2_platform_data usb_pdata __initconst = {
 	.operating_mode	= FSL_USB2_DR_DEVICE,
 	.phy_mode	= FSL_USB2_PHY_UTMI_WIDE,
 };
 
-static struct mxc_usbh_platform_data usbh1_config = {
+static const struct mxc_usbh_platform_data usbh1_config __initconst = {
 	.init		= initialize_usbh1_port,
 	.portsc	= MXC_EHCI_MODE_ULPI,
 };
@@ -270,12 +267,12 @@ static void __init eukrea_cpuimx51_init(void)
 				ARRAY_SIZE(eukrea_cpuimx51_i2c_devices));
 
 	if (otg_mode_host)
-		mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config);
+		imx51_add_mxc_ehci_otg(&dr_utmi_config);
 	else {
 		initialize_otg_port(NULL);
-		mxc_register_device(&mxc_usbdr_udc_device, &usb_pdata);
+		imx51_add_fsl_usb2_udc(&usb_pdata);
 	}
-	mxc_register_device(&mxc_usbh1_device, &usbh1_config);
+	imx51_add_mxc_ehci_hs(1, &usbh1_config);
 
 #ifdef CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD
 	eukrea_mbimx51_baseboard_init();
@@ -297,6 +294,7 @@ MACHINE_START(EUKREA_CPUIMX51, "Eukrea CPUIMX51 Module")
 	.map_io = mx51_map_io,
 	.init_early = imx51_init_early,
 	.init_irq = mx51_init_irq,
+	.handle_irq = imx51_handle_irq,
 	.timer = &mxc_timer,
 	.init_machine = eukrea_cpuimx51_init,
 MACHINE_END
diff --git a/arch/arm/mach-mx5/board-cpuimx51sd.c b/arch/arm/mach-mx5/board-cpuimx51sd.c
index b41fc27..52a11c1 100644
--- a/arch/arm/mach-mx5/board-cpuimx51sd.c
+++ b/arch/arm/mach-mx5/board-cpuimx51sd.c
@@ -22,7 +22,6 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/interrupt.h>
-#include <linux/irq.h>
 #include <linux/i2c-gpio.h>
 #include <linux/spi/spi.h>
 #include <linux/can/platform/mcp251x.h>
@@ -32,14 +31,12 @@
 #include <mach/hardware.h>
 #include <mach/iomux-mx51.h>
 
-#include <asm/irq.h>
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
 #include "devices-imx51.h"
-#include "devices.h"
 #include "cpu_op-mx51.h"
 
 #define USBH1_RST		IMX_GPIO_NR(2, 28)
@@ -108,7 +105,7 @@ static iomux_v3_cfg_t eukrea_cpuimx51sd_pads[] = {
 
 	/* Touchscreen */
 	/* IRQ */
-	_MX51_PAD_GPIO_NAND__GPIO_NAND | MUX_PAD_CTRL(PAD_CTL_PUS_22K_UP |
+	NEW_PAD_CTRL(MX51_PAD_GPIO_NAND__GPIO_NAND, PAD_CTL_PUS_22K_UP |
 			PAD_CTL_PKE | PAD_CTL_SRE_FAST |
 			PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
 };
@@ -129,7 +126,7 @@ static struct i2c_board_info eukrea_cpuimx51sd_i2c_devices[] = {
 		I2C_BOARD_INFO("tsc2007", 0x49),
 		.type		= "tsc2007",
 		.platform_data	= &tsc2007_info,
-		.irq		= gpio_to_irq(TSC2007_IRQGPIO),
+		.irq		= IMX_GPIO_TO_IRQ(TSC2007_IRQGPIO),
 	},
 };
 
@@ -149,7 +146,7 @@ static int initialize_otg_port(struct platform_device *pdev)
 	void __iomem *usb_base;
 	void __iomem *usbother_base;
 
-	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
 	if (!usb_base)
 		return -ENOMEM;
 	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
@@ -172,7 +169,7 @@ static int initialize_usbh1_port(struct platform_device *pdev)
 	void __iomem *usb_base;
 	void __iomem *usbother_base;
 
-	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
 	if (!usb_base)
 		return -ENOMEM;
 	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
@@ -189,17 +186,17 @@ static int initialize_usbh1_port(struct platform_device *pdev)
 			MXC_EHCI_ITC_NO_THRESHOLD);
 }
 
-static struct mxc_usbh_platform_data dr_utmi_config = {
+static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
 	.init		= initialize_otg_port,
 	.portsc	= MXC_EHCI_UTMI_16BIT,
 };
 
-static struct fsl_usb2_platform_data usb_pdata = {
+static const struct fsl_usb2_platform_data usb_pdata __initconst = {
 	.operating_mode	= FSL_USB2_DR_DEVICE,
 	.phy_mode	= FSL_USB2_PHY_UTMI_WIDE,
 };
 
-static struct mxc_usbh_platform_data usbh1_config = {
+static const struct mxc_usbh_platform_data usbh1_config __initconst = {
 	.init		= initialize_usbh1_port,
 	.portsc	= MXC_EHCI_MODE_ULPI,
 };
@@ -245,7 +242,7 @@ static struct spi_board_info cpuimx51sd_spi_device[] = {
 		.mode		= SPI_MODE_0,
 		.chip_select     = 0,
 		.platform_data   = &mcp251x_info,
-		.irq             = gpio_to_irq(CAN_IRQGPIO)
+		.irq             = IMX_GPIO_TO_IRQ(CAN_IRQGPIO)
 	},
 };
 
@@ -303,17 +300,17 @@ static void __init eukrea_cpuimx51sd_init(void)
 	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
 
 	if (otg_mode_host)
-		mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config);
+		imx51_add_mxc_ehci_otg(&dr_utmi_config);
 	else {
 		initialize_otg_port(NULL);
-		mxc_register_device(&mxc_usbdr_udc_device, &usb_pdata);
+		imx51_add_fsl_usb2_udc(&usb_pdata);
 	}
 
 	gpio_request(USBH1_RST, "usb_rst");
 	gpio_direction_output(USBH1_RST, 0);
 	msleep(20);
 	gpio_set_value(USBH1_RST, 1);
-	mxc_register_device(&mxc_usbh1_device, &usbh1_config);
+	imx51_add_mxc_ehci_hs(1, &usbh1_config);
 
 #ifdef CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD
 	eukrea_mbimxsd51_baseboard_init();
@@ -335,6 +332,7 @@ MACHINE_START(EUKREA_CPUIMX51SD, "Eukrea CPUIMX51SD")
 	.map_io = mx51_map_io,
 	.init_early = imx51_init_early,
 	.init_irq = mx51_init_irq,
+	.handle_irq = imx51_handle_irq,
 	.timer = &mxc_timer,
 	.init_machine = eukrea_cpuimx51sd_init,
 MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx50_rdp.c b/arch/arm/mach-mx5/board-mx50_rdp.c
index 7de25c6..fc3621d 100644
--- a/arch/arm/mach-mx5/board-mx50_rdp.c
+++ b/arch/arm/mach-mx5/board-mx50_rdp.c
@@ -219,6 +219,7 @@ MACHINE_START(MX50_RDP, "Freescale MX50 Reference Design Platform")
 	.map_io = mx50_map_io,
 	.init_early = imx50_init_early,
 	.init_irq = mx50_init_irq,
+	.handle_irq = imx50_handle_irq,
 	.timer = &mx50_rdp_timer,
 	.init_machine = mx50_rdp_board_init,
 MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx51_3ds.c b/arch/arm/mach-mx5/board-mx51_3ds.c
index a50174e..0578390 100644
--- a/arch/arm/mach-mx5/board-mx51_3ds.c
+++ b/arch/arm/mach-mx5/board-mx51_3ds.c
@@ -25,7 +25,6 @@
 #include <mach/3ds_debugboard.h>
 
 #include "devices-imx51.h"
-#include "devices.h"
 
 #define EXPIO_PARENT_INT	gpio_to_irq(IMX_GPIO_NR(1, 6))
 #define MX51_3DS_ECSPI2_CS	(GPIO_PORTC + 28)
@@ -173,6 +172,7 @@ MACHINE_START(MX51_3DS, "Freescale MX51 3-Stack Board")
 	.map_io = mx51_map_io,
 	.init_early = imx51_init_early,
 	.init_irq = mx51_init_irq,
+	.handle_irq = imx51_handle_irq,
 	.timer = &mx51_3ds_timer,
 	.init_machine = mx51_3ds_init,
 MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c
index 468926a..5c83760 100644
--- a/arch/arm/mach-mx5/board-mx51_babbage.c
+++ b/arch/arm/mach-mx5/board-mx51_babbage.c
@@ -24,14 +24,12 @@
 #include <mach/hardware.h>
 #include <mach/iomux-mx51.h>
 
-#include <asm/irq.h>
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
 #include "devices-imx51.h"
-#include "devices.h"
 #include "cpu_op-mx51.h"
 
 #define BABBAGE_USB_HUB_RESET	IMX_GPIO_NR(1, 7)
@@ -176,7 +174,7 @@ static const struct imxi2c_platform_data babbage_i2c_data __initconst = {
 	.bitrate = 100000,
 };
 
-static struct imxi2c_platform_data babbage_hsi2c_data = {
+static const struct imxi2c_platform_data babbage_hsi2c_data __initconst = {
 	.bitrate = 400000,
 };
 
@@ -249,7 +247,7 @@ static int initialize_otg_port(struct platform_device *pdev)
 	void __iomem *usb_base;
 	void __iomem *usbother_base;
 
-	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
 	if (!usb_base)
 		return -ENOMEM;
 	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
@@ -272,7 +270,7 @@ static int initialize_usbh1_port(struct platform_device *pdev)
 	void __iomem *usb_base;
 	void __iomem *usbother_base;
 
-	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
 	if (!usb_base)
 		return -ENOMEM;
 	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
@@ -288,17 +286,17 @@ static int initialize_usbh1_port(struct platform_device *pdev)
 			MXC_EHCI_ITC_NO_THRESHOLD);
 }
 
-static struct mxc_usbh_platform_data dr_utmi_config = {
+static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
 	.init		= initialize_otg_port,
 	.portsc	= MXC_EHCI_UTMI_16BIT,
 };
 
-static struct fsl_usb2_platform_data usb_pdata = {
+static const struct fsl_usb2_platform_data usb_pdata __initconst = {
 	.operating_mode	= FSL_USB2_DR_DEVICE,
 	.phy_mode	= FSL_USB2_PHY_UTMI_WIDE,
 };
 
-static struct mxc_usbh_platform_data usbh1_config = {
+static const struct mxc_usbh_platform_data usbh1_config __initconst = {
 	.init		= initialize_usbh1_port,
 	.portsc	= MXC_EHCI_MODE_ULPI,
 };
@@ -351,22 +349,27 @@ static const struct esdhc_platform_data mx51_babbage_sd2_data __initconst = {
 	.wp_type = ESDHC_WP_GPIO,
 };
 
+void __init imx51_babbage_common_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads,
+					 ARRAY_SIZE(mx51babbage_pads));
+}
+
 /*
  * Board specific initialization.
  */
 static void __init mx51_babbage_init(void)
 {
 	iomux_v3_cfg_t usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP;
-	iomux_v3_cfg_t power_key = _MX51_PAD_EIM_A27__GPIO2_21 |
-		MUX_PAD_CTRL(PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP);
+	iomux_v3_cfg_t power_key = NEW_PAD_CTRL(MX51_PAD_EIM_A27__GPIO2_21,
+		PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP);
 
 	imx51_soc_init();
 
 #if defined(CONFIG_CPU_FREQ_IMX)
 	get_cpu_op = mx51_get_cpu_op;
 #endif
-	mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads,
-					ARRAY_SIZE(mx51babbage_pads));
+	imx51_babbage_common_init();
 
 	imx51_add_imx_uart(0, &uart_pdata);
 	imx51_add_imx_uart(1, NULL);
@@ -381,17 +384,17 @@ static void __init mx51_babbage_init(void)
 
 	imx51_add_imx_i2c(0, &babbage_i2c_data);
 	imx51_add_imx_i2c(1, &babbage_i2c_data);
-	mxc_register_device(&mxc_hsi2c_device, &babbage_hsi2c_data);
+	imx51_add_hsi2c(&babbage_hsi2c_data);
 
 	if (otg_mode_host)
-		mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config);
+		imx51_add_mxc_ehci_otg(&dr_utmi_config);
 	else {
 		initialize_otg_port(NULL);
-		mxc_register_device(&mxc_usbdr_udc_device, &usb_pdata);
+		imx51_add_fsl_usb2_udc(&usb_pdata);
 	}
 
 	gpio_usbh1_active();
-	mxc_register_device(&mxc_usbh1_device, &usbh1_config);
+	imx51_add_mxc_ehci_hs(1, &usbh1_config);
 	/* setback USBH1_STP to be function */
 	mxc_iomux_v3_setup_pad(usbh1stp);
 	babbage_usbhub_reset();
@@ -420,6 +423,7 @@ MACHINE_START(MX51_BABBAGE, "Freescale MX51 Babbage Board")
 	.map_io = mx51_map_io,
 	.init_early = imx51_init_early,
 	.init_irq = mx51_init_irq,
+	.handle_irq = imx51_handle_irq,
 	.timer = &mx51_babbage_timer,
 	.init_machine = mx51_babbage_init,
 MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx51_efikamx.c b/arch/arm/mach-mx5/board-mx51_efikamx.c
index c36880d..a9e4866 100644
--- a/arch/arm/mach-mx5/board-mx51_efikamx.c
+++ b/arch/arm/mach-mx5/board-mx51_efikamx.c
@@ -32,14 +32,12 @@
 #include <mach/hardware.h>
 #include <mach/iomux-mx51.h>
 
-#include <asm/irq.h>
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
 #include "devices-imx51.h"
-#include "devices.h"
 #include "efika.h"
 
 #define EFIKAMX_PCBID0		IMX_GPIO_NR(3, 16)
@@ -163,6 +161,11 @@ static const struct gpio_led_platform_data
 	.num_leds = ARRAY_SIZE(mx51_efikamx_leds),
 };
 
+static struct esdhc_platform_data sd_pdata = {
+	.cd_type = ESDHC_CD_CONTROLLER,
+	.wp_type = ESDHC_WP_CONTROLLER,
+};
+
 static struct gpio_keys_button mx51_efikamx_powerkey[] = {
 	{
 		.code = KEY_POWER,
@@ -239,9 +242,11 @@ static void __init mx51_efikamx_init(void)
 
 	/* on < 1.2 boards both SD controllers are used */
 	if (system_rev < 0x12) {
-		imx51_add_sdhci_esdhc_imx(1, NULL);
+		imx51_add_sdhci_esdhc_imx(0, NULL);
+		imx51_add_sdhci_esdhc_imx(1, &sd_pdata);
 		mx51_efikamx_leds[2].default_trigger = "mmc1";
-	}
+	} else
+		imx51_add_sdhci_esdhc_imx(0, &sd_pdata);
 
 	gpio_led_register_device(-1, &mx51_efikamx_leds_data);
 	imx_add_gpio_keys(&mx51_efikamx_powerkey_data);
@@ -284,6 +289,7 @@ MACHINE_START(MX51_EFIKAMX, "Genesi EfikaMX nettop")
 	.map_io = mx51_map_io,
 	.init_early = imx51_init_early,
 	.init_irq = mx51_init_irq,
+	.handle_irq = imx51_handle_irq,
 	.timer = &mx51_efikamx_timer,
 	.init_machine = mx51_efikamx_init,
 MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx51_efikasb.c b/arch/arm/mach-mx5/board-mx51_efikasb.c
index ba5436a..38c4a3e 100644
--- a/arch/arm/mach-mx5/board-mx51_efikasb.c
+++ b/arch/arm/mach-mx5/board-mx51_efikasb.c
@@ -35,14 +35,12 @@
 #include <mach/hardware.h>
 #include <mach/iomux-mx51.h>
 
-#include <asm/irq.h>
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
 #include "devices-imx51.h"
-#include "devices.h"
 #include "efika.h"
 
 #define EFIKASB_USBH2_STP	IMX_GPIO_NR(2, 20)
@@ -56,6 +54,7 @@
 #define EFIKASB_RFKILL		IMX_GPIO_NR(3, 1)
 
 #define MX51_PAD_PWRKEY IOMUX_PAD(0x48c, 0x0f8, 1, 0x0,   0, PAD_CTL_PUS_100K_UP | PAD_CTL_PKE)
+#define MX51_PAD_SD1_CD	IOMUX_PAD(0x47c, 0x0e8, 1, __NA_, 0, MX51_ESDHC_PAD_CTRL)
 
 static iomux_v3_cfg_t mx51efikasb_pads[] = {
 	/* USB HOST2 */
@@ -97,6 +96,8 @@ static iomux_v3_cfg_t mx51efikasb_pads[] = {
 
 	/* BT */
 	MX51_PAD_EIM_A17__GPIO2_11,
+
+	MX51_PAD_SD1_CD,
 };
 
 static int initialize_usbh2_port(struct platform_device *pdev)
@@ -119,7 +120,7 @@ static int initialize_usbh2_port(struct platform_device *pdev)
 	return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_ITC_NO_THRESHOLD);
 }
 
-static struct mxc_usbh_platform_data usbh2_config = {
+static struct mxc_usbh_platform_data usbh2_config __initdata = {
 	.init   = initialize_usbh2_port,
 	.portsc = MXC_EHCI_MODE_ULPI,
 };
@@ -129,7 +130,7 @@ static void __init mx51_efikasb_usb(void)
 	usbh2_config.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
 			ULPI_OTG_DRVVBUS_EXT | ULPI_OTG_EXTVBUSIND);
 	if (usbh2_config.otg)
-		mxc_register_device(&mxc_usbh2_device, &usbh2_config);
+		imx51_add_mxc_ehci_hs(2, &usbh2_config);
 }
 
 static const struct gpio_led mx51_efikasb_leds[] __initconst = {
@@ -182,6 +183,18 @@ static const struct gpio_keys_platform_data mx51_efikasb_keys_data __initconst =
 	.nbuttons = ARRAY_SIZE(mx51_efikasb_keys),
 };
 
+static struct esdhc_platform_data sd0_pdata = {
+#define EFIKASB_SD1_CD	IMX_GPIO_NR(2, 27)
+	.cd_gpio = EFIKASB_SD1_CD,
+	.cd_type = ESDHC_CD_GPIO,
+	.wp_type = ESDHC_WP_CONTROLLER,
+};
+
+static struct esdhc_platform_data sd1_pdata = {
+	.cd_type = ESDHC_CD_CONTROLLER,
+	.wp_type = ESDHC_WP_CONTROLLER,
+};
+
 static struct regulator *pwgt1, *pwgt2;
 
 static void mx51_efikasb_power_off(void)
@@ -250,7 +263,8 @@ static void __init efikasb_board_init(void)
 
 	mx51_efikasb_board_id();
 	mx51_efikasb_usb();
-	imx51_add_sdhci_esdhc_imx(1, NULL);
+	imx51_add_sdhci_esdhc_imx(0, &sd0_pdata);
+	imx51_add_sdhci_esdhc_imx(1, &sd1_pdata);
 
 	gpio_led_register_device(-1, &mx51_efikasb_leds_data);
 	imx_add_gpio_keys(&mx51_efikasb_keys_data);
@@ -270,6 +284,7 @@ MACHINE_START(MX51_EFIKASB, "Genesi Efika Smartbook")
 	.map_io = mx51_map_io,
 	.init_early = imx51_init_early,
 	.init_irq = mx51_init_irq,
+	.handle_irq = imx51_handle_irq,
 	.init_machine =  efikasb_board_init,
 	.timer = &mx51_efikasb_timer,
 MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx53_ard.c b/arch/arm/mach-mx5/board-mx53_ard.c
index 76a67c4..0d7f0ff 100644
--- a/arch/arm/mach-mx5/board-mx53_ard.c
+++ b/arch/arm/mach-mx5/board-mx53_ard.c
@@ -134,8 +134,8 @@ static struct resource ard_smsc911x_resources[] = {
 		.flags = IORESOURCE_MEM,
 	},
 	{
-		.start =  gpio_to_irq(ARD_ETHERNET_INT_B),
-		.end =  gpio_to_irq(ARD_ETHERNET_INT_B),
+		.start =  IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B),
+		.end =  IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B),
 		.flags = IORESOURCE_IRQ,
 	},
 };
@@ -171,9 +171,6 @@ static struct imxi2c_platform_data mx53_ard_i2c3_data = {
 
 static void __init mx53_ard_io_init(void)
 {
-	mxc_iomux_v3_setup_multiple_pads(mx53_ard_pads,
-				ARRAY_SIZE(mx53_ard_pads));
-
 	gpio_request(ARD_ETHERNET_INT_B, "eth-int-b");
 	gpio_direction_input(ARD_ETHERNET_INT_B);
 
@@ -216,6 +213,13 @@ static int weim_cs_config(void)
 	return 0;
 }
 
+void __init imx53_ard_common_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx53_ard_pads,
+					 ARRAY_SIZE(mx53_ard_pads));
+	weim_cs_config();
+}
+
 static struct platform_device *devices[] __initdata = {
 	&ard_smsc_lan9220_device,
 };
@@ -225,8 +229,8 @@ static void __init mx53_ard_board_init(void)
 	imx53_soc_init();
 	imx53_add_imx_uart(0, NULL);
 
+	imx53_ard_common_init();
 	mx53_ard_io_init();
-	weim_cs_config();
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 
 	imx53_add_sdhci_esdhc_imx(0, &mx53_ard_sd1_data);
@@ -234,6 +238,7 @@ static void __init mx53_ard_board_init(void)
 	imx53_add_imx_i2c(1, &mx53_ard_i2c2_data);
 	imx53_add_imx_i2c(2, &mx53_ard_i2c3_data);
 	imx_add_gpio_keys(&ard_button_data);
+	imx53_add_ahci_imx();
 }
 
 static void __init mx53_ard_timer_init(void)
@@ -249,6 +254,7 @@ MACHINE_START(MX53_ARD, "Freescale MX53 ARD Board")
 	.map_io = mx53_map_io,
 	.init_early = imx53_init_early,
 	.init_irq = mx53_init_irq,
+	.handle_irq = imx53_handle_irq,
 	.timer = &mx53_ard_timer,
 	.init_machine = mx53_ard_board_init,
 MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx53_evk.c b/arch/arm/mach-mx5/board-mx53_evk.c
index 1b417b0..6bea31a 100644
--- a/arch/arm/mach-mx5/board-mx53_evk.c
+++ b/arch/arm/mach-mx5/board-mx53_evk.c
@@ -131,12 +131,17 @@ static const struct spi_imx_master mx53_evk_spi_data __initconst = {
 	.num_chipselect = ARRAY_SIZE(mx53_evk_spi_cs),
 };
 
+void __init imx53_evk_common_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx53_evk_pads,
+					 ARRAY_SIZE(mx53_evk_pads));
+}
+
 static void __init mx53_evk_board_init(void)
 {
 	imx53_soc_init();
+	imx53_evk_common_init();
 
-	mxc_iomux_v3_setup_multiple_pads(mx53_evk_pads,
-					ARRAY_SIZE(mx53_evk_pads));
 	mx53_evk_init_uart();
 	mx53_evk_fec_reset();
 	imx53_add_fec(&mx53_evk_fec_pdata);
@@ -167,6 +172,7 @@ MACHINE_START(MX53_EVK, "Freescale MX53 EVK Board")
 	.map_io = mx53_map_io,
 	.init_early = imx53_init_early,
 	.init_irq = mx53_init_irq,
+	.handle_irq = imx53_handle_irq,
 	.timer = &mx53_evk_timer,
 	.init_machine = mx53_evk_board_init,
 MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx53_loco.c b/arch/arm/mach-mx5/board-mx53_loco.c
index 4e1d51d..7678f77 100644
--- a/arch/arm/mach-mx5/board-mx53_loco.c
+++ b/arch/arm/mach-mx5/board-mx53_loco.c
@@ -22,6 +22,7 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/gpio.h>
+#include <linux/i2c.h>
 
 #include <mach/common.h>
 #include <mach/hardware.h>
@@ -42,6 +43,7 @@
 #define LOCO_SD3_CD			IMX_GPIO_NR(3, 11)
 #define LOCO_SD3_WP			IMX_GPIO_NR(3, 12)
 #define LOCO_SD1_CD			IMX_GPIO_NR(3, 13)
+#define LOCO_ACCEL_EN			IMX_GPIO_NR(6, 14)
 
 static iomux_v3_cfg_t mx53_loco_pads[] = {
 	/* FEC */
@@ -64,6 +66,10 @@ static iomux_v3_cfg_t mx53_loco_pads[] = {
 	MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD,
 	MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS,
 	MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD,
+	/* I2C1 */
+	MX53_PAD_CSI0_DAT8__I2C1_SDA,
+	MX53_PAD_CSI0_DAT9__I2C1_SCL,
+	MX53_PAD_NANDF_CS1__GPIO6_14,	/* Accelerometer Enable */
 	/* I2C2 */
 	MX53_PAD_KEY_COL3__I2C2_SCL,
 	MX53_PAD_KEY_ROW3__I2C2_SDA,
@@ -257,22 +263,42 @@ static const struct gpio_led_platform_data mx53loco_leds_data __initconst = {
 	.num_leds	= ARRAY_SIZE(mx53loco_leds),
 };
 
+void __init imx53_qsb_common_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx53_loco_pads,
+					 ARRAY_SIZE(mx53_loco_pads));
+}
+
+static struct i2c_board_info mx53loco_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("mma8450", 0x1C),
+	},
+};
+
 static void __init mx53_loco_board_init(void)
 {
+	int ret;
 	imx53_soc_init();
+	imx53_qsb_common_init();
 
-	mxc_iomux_v3_setup_multiple_pads(mx53_loco_pads,
-					ARRAY_SIZE(mx53_loco_pads));
 	imx53_add_imx_uart(0, NULL);
 	mx53_loco_fec_reset();
 	imx53_add_fec(&mx53_loco_fec_data);
 	imx53_add_imx2_wdt(0, NULL);
+
+	ret = gpio_request_one(LOCO_ACCEL_EN, GPIOF_OUT_INIT_HIGH, "accel_en");
+	if (ret)
+		pr_err("Cannot request ACCEL_EN pin: %d\n", ret);
+
+	i2c_register_board_info(0, mx53loco_i2c_devices,
+				ARRAY_SIZE(mx53loco_i2c_devices));
 	imx53_add_imx_i2c(0, &mx53_loco_i2c_data);
 	imx53_add_imx_i2c(1, &mx53_loco_i2c_data);
 	imx53_add_sdhci_esdhc_imx(0, &mx53_loco_sd1_data);
 	imx53_add_sdhci_esdhc_imx(2, &mx53_loco_sd3_data);
 	imx_add_gpio_keys(&loco_button_data);
 	gpio_led_register_device(-1, &mx53loco_leds_data);
+	imx53_add_ahci_imx();
 }
 
 static void __init mx53_loco_timer_init(void)
@@ -288,6 +314,7 @@ MACHINE_START(MX53_LOCO, "Freescale MX53 LOCO Board")
 	.map_io = mx53_map_io,
 	.init_early = imx53_init_early,
 	.init_irq = mx53_init_irq,
+	.handle_irq = imx53_handle_irq,
 	.timer = &mx53_loco_timer,
 	.init_machine = mx53_loco_board_init,
 MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx53_smd.c b/arch/arm/mach-mx5/board-mx53_smd.c
index bc02894..59c0845 100644
--- a/arch/arm/mach-mx5/board-mx53_smd.c
+++ b/arch/arm/mach-mx5/board-mx53_smd.c
@@ -35,6 +35,7 @@
 #include "devices-imx53.h"
 
 #define SMD_FEC_PHY_RST		IMX_GPIO_NR(7, 6)
+#define MX53_SMD_SATA_PWR_EN    IMX_GPIO_NR(3, 3)
 
 static iomux_v3_cfg_t mx53_smd_pads[] = {
 	MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
@@ -111,12 +112,30 @@ static const struct imxi2c_platform_data mx53_smd_i2c_data __initconst = {
 	.bitrate = 100000,
 };
 
+static inline void mx53_smd_ahci_pwr_on(void)
+{
+	int ret;
+
+	/* Enable SATA PWR */
+	ret = gpio_request_one(MX53_SMD_SATA_PWR_EN,
+			GPIOF_DIR_OUT | GPIOF_INIT_HIGH, "ahci-sata-pwr");
+	if (ret) {
+		pr_err("failed to enable SATA_PWR_EN: %d\n", ret);
+		return;
+	}
+}
+
+void __init imx53_smd_common_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx53_smd_pads,
+					 ARRAY_SIZE(mx53_smd_pads));
+}
+
 static void __init mx53_smd_board_init(void)
 {
 	imx53_soc_init();
+	imx53_smd_common_init();
 
-	mxc_iomux_v3_setup_multiple_pads(mx53_smd_pads,
-					ARRAY_SIZE(mx53_smd_pads));
 	mx53_smd_init_uart();
 	mx53_smd_fec_reset();
 	imx53_add_fec(&mx53_smd_fec_data);
@@ -125,6 +144,8 @@ static void __init mx53_smd_board_init(void)
 	imx53_add_sdhci_esdhc_imx(0, NULL);
 	imx53_add_sdhci_esdhc_imx(1, NULL);
 	imx53_add_sdhci_esdhc_imx(2, NULL);
+	mx53_smd_ahci_pwr_on();
+	imx53_add_ahci_imx();
 }
 
 static void __init mx53_smd_timer_init(void)
@@ -140,6 +161,7 @@ MACHINE_START(MX53_SMD, "Freescale MX53 SMD Board")
 	.map_io = mx53_map_io,
 	.init_early = imx53_init_early,
 	.init_irq = mx53_init_irq,
+	.handle_irq = imx53_handle_irq,
 	.timer = &mx53_smd_timer,
 	.init_machine = mx53_smd_board_init,
 MACHINE_END
diff --git a/arch/arm/mach-mx5/clock-mx51-mx53.c b/arch/arm/mach-mx5/clock-mx51-mx53.c
index f7bf996..2aacf41 100644
--- a/arch/arm/mach-mx5/clock-mx51-mx53.c
+++ b/arch/arm/mach-mx5/clock-mx51-mx53.c
@@ -15,6 +15,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/clkdev.h>
+#include <linux/of.h>
 
 #include <asm/div64.h>
 
@@ -1401,6 +1402,22 @@ static struct clk esdhc4_mx53_clk = {
 	.secondary = &esdhc4_ipg_clk,
 };
 
+static struct clk sata_clk = {
+	.parent = &ipg_clk,
+	.enable = _clk_max_enable,
+	.enable_reg = MXC_CCM_CCGR4,
+	.enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+	.disable = _clk_max_disable,
+};
+
+static struct clk ahci_phy_clk = {
+	.parent = &usb_phy1_clk,
+};
+
+static struct clk ahci_dma_clk = {
+	.parent = &ahb_clk,
+};
+
 DEFINE_CLOCK(mipi_esc_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG5_OFFSET, NULL, NULL, NULL, &pll2_sw_clk);
 DEFINE_CLOCK(mipi_hsc2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG4_OFFSET, NULL, NULL, &mipi_esc_clk, &pll2_sw_clk);
 DEFINE_CLOCK(mipi_hsc1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG3_OFFSET, NULL, NULL, &mipi_hsc2_clk, &pll2_sw_clk);
@@ -1418,6 +1435,10 @@ DEFINE_CLOCK(ipu_di0_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG5_OFFSET,
 DEFINE_CLOCK(ipu_di1_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG6_OFFSET,
 		NULL, NULL, &pll3_sw_clk, NULL);
 
+/* PATA */
+DEFINE_CLOCK(pata_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG0_OFFSET,
+		NULL, NULL, &ipg_clk, &spba_clk);
+
 #define _REGISTER_CLOCK(d, n, c) \
        { \
 		.dev_id = d, \
@@ -1474,6 +1495,7 @@ static struct clk_lookup mx51_lookups[] = {
 	_REGISTER_CLOCK("imx-ipuv3", "di0", ipu_di0_clk)
 	_REGISTER_CLOCK("imx-ipuv3", "di1", ipu_di1_clk)
 	_REGISTER_CLOCK(NULL, "gpc_dvfs", gpc_dvfs_clk)
+	_REGISTER_CLOCK("pata_imx", NULL, pata_clk)
 };
 
 static struct clk_lookup mx53_lookups[] = {
@@ -1507,6 +1529,10 @@ static struct clk_lookup mx53_lookups[] = {
 	_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
 	_REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
 	_REGISTER_CLOCK("imx-keypad", NULL, dummy_clk)
+	_REGISTER_CLOCK("pata_imx", NULL, pata_clk)
+	_REGISTER_CLOCK("imx53-ahci.0", "ahci", sata_clk)
+	_REGISTER_CLOCK("imx53-ahci.0", "ahci_phy", ahci_phy_clk)
+	_REGISTER_CLOCK("imx53-ahci.0", "ahci_dma", ahci_dma_clk)
 };
 
 static void clk_tree_init(void)
@@ -1548,9 +1574,8 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
 	clk_enable(&main_bus_clk);
 
 	clk_enable(&iim_clk);
-	mx51_revision();
+	imx_print_silicon_rev("i.MX51", mx51_revision());
 	clk_disable(&iim_clk);
-	mx51_display_revision();
 
 	/* move usb_phy_clk to 24MHz */
 	clk_set_parent(&usb_phy1_clk, &osc_clk);
@@ -1568,7 +1593,7 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
 
 	/* System timer */
 	mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
-		MX51_MXC_INT_GPT);
+		MX51_INT_GPT);
 	return 0;
 }
 
@@ -1592,9 +1617,8 @@ int __init mx53_clocks_init(unsigned long ckil, unsigned long osc,
 	clk_enable(&main_bus_clk);
 
 	clk_enable(&iim_clk);
-	mx53_revision();
+	imx_print_silicon_rev("i.MX53", mx53_revision());
 	clk_disable(&iim_clk);
-	mx53_display_revision();
 
 	/* Set SDHC parents to be PLL2 */
 	clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
@@ -1609,3 +1633,41 @@ int __init mx53_clocks_init(unsigned long ckil, unsigned long osc,
 		MX53_INT_GPT);
 	return 0;
 }
+
+static void __init clk_get_freq_dt(unsigned long *ckil, unsigned long *osc,
+				   unsigned long *ckih1, unsigned long *ckih2)
+{
+	struct device_node *np;
+
+	/* retrieve the freqency of fixed clocks from device tree */
+	for_each_compatible_node(np, NULL, "fixed-clock") {
+		u32 rate;
+		if (of_property_read_u32(np, "clock-frequency", &rate))
+			continue;
+
+		if (of_device_is_compatible(np, "fsl,imx-ckil"))
+			*ckil = rate;
+		else if (of_device_is_compatible(np, "fsl,imx-osc"))
+			*osc = rate;
+		else if (of_device_is_compatible(np, "fsl,imx-ckih1"))
+			*ckih1 = rate;
+		else if (of_device_is_compatible(np, "fsl,imx-ckih2"))
+			*ckih2 = rate;
+	}
+}
+
+int __init mx51_clocks_init_dt(void)
+{
+	unsigned long ckil, osc, ckih1, ckih2;
+
+	clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2);
+	return mx51_clocks_init(ckil, osc, ckih1, ckih2);
+}
+
+int __init mx53_clocks_init_dt(void)
+{
+	unsigned long ckil, osc, ckih1, ckih2;
+
+	clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2);
+	return mx53_clocks_init(ckil, osc, ckih1, ckih2);
+}
diff --git a/arch/arm/mach-mx5/cpu.c b/arch/arm/mach-mx5/cpu.c
index 86f87da..5c53282 100644
--- a/arch/arm/mach-mx5/cpu.c
+++ b/arch/arm/mach-mx5/cpu.c
@@ -18,7 +18,7 @@
 #include <mach/hardware.h>
 #include <asm/io.h>
 
-static int cpu_silicon_rev = -1;
+static int mx5_cpu_rev = -1;
 
 #define IIM_SREV 0x24
 #define MX50_HW_ADADIG_DIGPROG	0xB0
@@ -28,11 +28,14 @@ static int get_mx51_srev(void)
 	void __iomem *iim_base = MX51_IO_ADDRESS(MX51_IIM_BASE_ADDR);
 	u32 rev = readl(iim_base + IIM_SREV) & 0xff;
 
-	if (rev == 0x0)
+	switch (rev) {
+	case 0x0:
 		return IMX_CHIP_REVISION_2_0;
-	else if (rev == 0x10)
+	case 0x10:
 		return IMX_CHIP_REVISION_3_0;
-	return 0;
+	default:
+		return IMX_CHIP_REVISION_UNKNOWN;
+	}
 }
 
 /*
@@ -45,33 +48,13 @@ int mx51_revision(void)
 	if (!cpu_is_mx51())
 		return -EINVAL;
 
-	if (cpu_silicon_rev == -1)
-		cpu_silicon_rev = get_mx51_srev();
+	if (mx5_cpu_rev == -1)
+		mx5_cpu_rev = get_mx51_srev();
 
-	return cpu_silicon_rev;
+	return mx5_cpu_rev;
 }
 EXPORT_SYMBOL(mx51_revision);
 
-void mx51_display_revision(void)
-{
-	int rev;
-	char *srev;
-	rev = mx51_revision();
-
-	switch (rev) {
-	case IMX_CHIP_REVISION_2_0:
-		srev = IMX_CHIP_REVISION_2_0_STRING;
-		break;
-	case IMX_CHIP_REVISION_3_0:
-		srev = IMX_CHIP_REVISION_3_0_STRING;
-		break;
-	default:
-		srev = IMX_CHIP_REVISION_UNKNOWN_STRING;
-	}
-	printk(KERN_INFO "CPU identified as i.MX51, silicon rev %s\n", srev);
-}
-EXPORT_SYMBOL(mx51_display_revision);
-
 #ifdef CONFIG_NEON
 
 /*
@@ -121,10 +104,10 @@ int mx53_revision(void)
 	if (!cpu_is_mx53())
 		return -EINVAL;
 
-	if (cpu_silicon_rev == -1)
-		cpu_silicon_rev = get_mx53_srev();
+	if (mx5_cpu_rev == -1)
+		mx5_cpu_rev = get_mx53_srev();
 
-	return cpu_silicon_rev;
+	return mx5_cpu_rev;
 }
 EXPORT_SYMBOL(mx53_revision);
 
@@ -134,7 +117,7 @@ static int get_mx50_srev(void)
 	u32 rev;
 
 	if (!anatop) {
-		cpu_silicon_rev = -EINVAL;
+		mx5_cpu_rev = -EINVAL;
 		return 0;
 	}
 
@@ -159,36 +142,13 @@ int mx50_revision(void)
 	if (!cpu_is_mx50())
 		return -EINVAL;
 
-	if (cpu_silicon_rev == -1)
-		cpu_silicon_rev = get_mx50_srev();
+	if (mx5_cpu_rev == -1)
+		mx5_cpu_rev = get_mx50_srev();
 
-	return cpu_silicon_rev;
+	return mx5_cpu_rev;
 }
 EXPORT_SYMBOL(mx50_revision);
 
-void mx53_display_revision(void)
-{
-	int rev;
-	char *srev;
-	rev = mx53_revision();
-
-	switch (rev) {
-	case IMX_CHIP_REVISION_1_0:
-		srev = IMX_CHIP_REVISION_1_0_STRING;
-		break;
-	case IMX_CHIP_REVISION_2_0:
-		srev = IMX_CHIP_REVISION_2_0_STRING;
-		break;
-	case IMX_CHIP_REVISION_2_1:
-		srev = IMX_CHIP_REVISION_2_1_STRING;
-		break;
-	default:
-		srev = IMX_CHIP_REVISION_UNKNOWN_STRING;
-	}
-	printk(KERN_INFO "CPU identified as i.MX53, silicon rev %s\n", srev);
-}
-EXPORT_SYMBOL(mx53_display_revision);
-
 static int __init post_cpu_init(void)
 {
 	unsigned int reg;
diff --git a/arch/arm/mach-mx5/devices-imx51.h b/arch/arm/mach-mx5/devices-imx51.h
index e11bc0e..af488bc 100644
--- a/arch/arm/mach-mx5/devices-imx51.h
+++ b/arch/arm/mach-mx5/devices-imx51.h
@@ -13,9 +13,15 @@ extern const struct imx_fec_data imx51_fec_data;
 #define imx51_add_fec(pdata)	\
 	imx_add_fec(&imx51_fec_data, pdata)
 
+extern const struct imx_fsl_usb2_udc_data imx51_fsl_usb2_udc_data;
+#define imx51_add_fsl_usb2_udc(pdata)	\
+	imx_add_fsl_usb2_udc(&imx51_fsl_usb2_udc_data, pdata)
+
 extern const struct imx_imx_i2c_data imx51_imx_i2c_data[];
 #define imx51_add_imx_i2c(id, pdata)	\
 	imx_add_imx_i2c(&imx51_imx_i2c_data[id], pdata)
+#define imx51_add_hsi2c(pdata)	\
+	imx51_add_imx_i2c(2, pdata)
 
 extern const struct imx_imx_ssi_data imx51_imx_ssi_data[];
 #define imx51_add_imx_ssi(id, pdata)	\
@@ -25,6 +31,13 @@ extern const struct imx_imx_uart_1irq_data imx51_imx_uart_data[];
 #define imx51_add_imx_uart(id, pdata)	\
 	imx_add_imx_uart_1irq(&imx51_imx_uart_data[id], pdata)
 
+extern const struct imx_mxc_ehci_data imx51_mxc_ehci_otg_data;
+#define imx51_add_mxc_ehci_otg(pdata)	\
+	imx_add_mxc_ehci(&imx51_mxc_ehci_otg_data, pdata)
+extern const struct imx_mxc_ehci_data imx51_mxc_ehci_hs_data[];
+#define imx51_add_mxc_ehci_hs(id, pdata)	\
+	imx_add_mxc_ehci(&imx51_mxc_ehci_hs_data[id - 1], pdata)
+
 extern const struct imx_mxc_nand_data imx51_mxc_nand_data;
 #define imx51_add_mxc_nand(pdata)	\
 	imx_add_mxc_nand(&imx51_mxc_nand_data, pdata)
@@ -52,3 +65,7 @@ extern const struct imx_mxc_pwm_data imx51_mxc_pwm_data[];
 extern const struct imx_imx_keypad_data imx51_imx_keypad_data;
 #define imx51_add_imx_keypad(pdata)	\
 	imx_add_imx_keypad(&imx51_imx_keypad_data, pdata)
+
+extern const struct imx_pata_imx_data imx51_pata_imx_data;
+#define imx51_add_pata_imx() \
+	imx_add_pata_imx(&imx51_pata_imx_data)
diff --git a/arch/arm/mach-mx5/devices-imx53.h b/arch/arm/mach-mx5/devices-imx53.h
index c27fe8b..6e1e5d1 100644
--- a/arch/arm/mach-mx5/devices-imx53.h
+++ b/arch/arm/mach-mx5/devices-imx53.h
@@ -40,3 +40,9 @@ extern const struct imx_imx_ssi_data imx53_imx_ssi_data[];
 extern const struct imx_imx_keypad_data imx53_imx_keypad_data;
 #define imx53_add_imx_keypad(pdata)	\
 	imx_add_imx_keypad(&imx53_imx_keypad_data, pdata)
+
+extern const struct imx_pata_imx_data imx53_pata_imx_data;
+#define imx53_add_pata_imx() \
+	imx_add_pata_imx(&imx53_pata_imx_data)
+
+extern struct platform_device *__init imx53_add_ahci_imx(void);
diff --git a/arch/arm/mach-mx5/devices.c b/arch/arm/mach-mx5/devices.c
deleted file mode 100644
index 371ca8c..0000000
--- a/arch/arm/mach-mx5/devices.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright 2009 Amit Kucheria <amit.kucheria@canonical.com>
- * Copyright (C) 2010 Freescale Semiconductor, Inc.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <mach/hardware.h>
-#include <mach/imx-uart.h>
-#include <mach/irqs.h>
-
-static struct resource mxc_hsi2c_resources[] = {
-	{
-		.start = MX51_HSI2C_DMA_BASE_ADDR,
-		.end = MX51_HSI2C_DMA_BASE_ADDR + SZ_16K - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.start = MX51_MXC_INT_HS_I2C,
-		.end = MX51_MXC_INT_HS_I2C,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device mxc_hsi2c_device = {
-	.name = "imx-i2c",
-	.id = 2,
-	.num_resources = ARRAY_SIZE(mxc_hsi2c_resources),
-	.resource = mxc_hsi2c_resources
-};
-
-static u64 usb_dma_mask = DMA_BIT_MASK(32);
-
-static struct resource usbotg_resources[] = {
-	{
-		.start = MX51_OTG_BASE_ADDR,
-		.end = MX51_OTG_BASE_ADDR + 0x1ff,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.start = MX51_MXC_INT_USB_OTG,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-/* OTG gadget device */
-struct platform_device mxc_usbdr_udc_device = {
-	.name		= "fsl-usb2-udc",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(usbotg_resources),
-	.resource	= usbotg_resources,
-	.dev		= {
-		.dma_mask		= &usb_dma_mask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
-
-struct platform_device mxc_usbdr_host_device = {
-	.name = "mxc-ehci",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(usbotg_resources),
-	.resource = usbotg_resources,
-	.dev = {
-		.dma_mask = &usb_dma_mask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
-};
-
-static struct resource usbh1_resources[] = {
-	{
-		.start = MX51_OTG_BASE_ADDR + 0x200,
-		.end = MX51_OTG_BASE_ADDR + 0x200 + 0x1ff,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.start = MX51_MXC_INT_USB_H1,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device mxc_usbh1_device = {
-	.name = "mxc-ehci",
-	.id = 1,
-	.num_resources = ARRAY_SIZE(usbh1_resources),
-	.resource = usbh1_resources,
-	.dev = {
-		.dma_mask = &usb_dma_mask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
-};
-
-static struct resource usbh2_resources[] = {
-	{
-		.start = MX51_OTG_BASE_ADDR + 0x400,
-		.end = MX51_OTG_BASE_ADDR + 0x400 + 0x1ff,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.start = MX51_MXC_INT_USB_H2,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device mxc_usbh2_device = {
-	.name = "mxc-ehci",
-	.id = 2,
-	.num_resources = ARRAY_SIZE(usbh2_resources),
-	.resource = usbh2_resources,
-	.dev = {
-		.dma_mask = &usb_dma_mask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
-};
diff --git a/arch/arm/mach-mx5/devices.h b/arch/arm/mach-mx5/devices.h
deleted file mode 100644
index 55a5129..0000000
--- a/arch/arm/mach-mx5/devices.h
+++ /dev/null
@@ -1,5 +0,0 @@
-extern struct platform_device mxc_usbdr_host_device;
-extern struct platform_device mxc_usbh1_device;
-extern struct platform_device mxc_usbh2_device;
-extern struct platform_device mxc_usbdr_udc_device;
-extern struct platform_device mxc_hsi2c_device;
diff --git a/arch/arm/mach-mx5/ehci.c b/arch/arm/mach-mx5/ehci.c
index 7ce12c8..c17fa13 100644
--- a/arch/arm/mach-mx5/ehci.c
+++ b/arch/arm/mach-mx5/ehci.c
@@ -52,7 +52,7 @@ int mx51_initialize_usb_hw(int port, unsigned int flags)
 	void __iomem *usbother_base;
 	int ret = 0;
 
-	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
 	if (!usb_base) {
 		printk(KERN_ERR "%s(): ioremap failed\n", __func__);
 		return -ENOMEM;
diff --git a/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c b/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c
index bbf4564..a6a3ab8 100644
--- a/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c
+++ b/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c
@@ -28,7 +28,6 @@
 #include <asm/mach/arch.h>
 
 #include "devices-imx51.h"
-#include "devices.h"
 
 #define MBIMX51_TSC2007_GPIO	IMX_GPIO_NR(3, 30)
 #define MBIMX51_LED0		IMX_GPIO_NR(3, 5)
@@ -160,7 +159,7 @@ struct tsc2007_platform_data tsc2007_data = {
 static struct i2c_board_info mbimx51_i2c_devices[] = {
 	{
 		I2C_BOARD_INFO("tsc2007", 0x49),
-		.irq  = gpio_to_irq(MBIMX51_TSC2007_GPIO),
+		.irq  = IMX_GPIO_TO_IRQ(MBIMX51_TSC2007_GPIO),
 		.platform_data = &tsc2007_data,
 	}, {
 		I2C_BOARD_INFO("tlv320aic23", 0x1a),
diff --git a/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c
index 2619239..d817fc8 100644
--- a/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c
+++ b/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c
@@ -24,7 +24,6 @@
 
 #include <linux/gpio.h>
 #include <linux/interrupt.h>
-#include <linux/irq.h>
 #include <linux/leds.h>
 #include <linux/platform_device.h>
 #include <linux/input.h>
@@ -41,13 +40,12 @@
 #include <mach/audmux.h>
 
 #include "devices-imx51.h"
-#include "devices.h"
 
 static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = {
 	/* LED */
 	MX51_PAD_NANDF_D10__GPIO3_30,
 	/* SWITCH */
-	_MX51_PAD_NANDF_D9__GPIO3_31 | MUX_PAD_CTRL(PAD_CTL_PUS_22K_UP |
+	NEW_PAD_CTRL(MX51_PAD_NANDF_D9__GPIO3_31, PAD_CTL_PUS_22K_UP |
 			PAD_CTL_PKE | PAD_CTL_SRE_FAST |
 			PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
 	/* UART2 */
@@ -66,7 +64,7 @@ static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = {
 	MX51_PAD_SD1_DATA2__SD1_DATA2,
 	MX51_PAD_SD1_DATA3__SD1_DATA3,
 	/* SD1 CD */
-	_MX51_PAD_GPIO1_0__SD1_CD | MUX_PAD_CTRL(PAD_CTL_PUS_22K_UP |
+	NEW_PAD_CTRL(MX51_PAD_GPIO1_0__SD1_CD, PAD_CTL_PUS_22K_UP |
 			PAD_CTL_PKE | PAD_CTL_SRE_FAST |
 			PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
 };
diff --git a/arch/arm/mach-mx5/imx51-dt.c b/arch/arm/mach-mx5/imx51-dt.c
new file mode 100644
index 0000000..ccc6158
--- /dev/null
+++ b/arch/arm/mach-mx5/imx51-dt.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+#include <mach/mx51.h>
+
+/*
+ * Lookup table for attaching a specific name and platform_data pointer to
+ * devices as they get created by of_platform_populate().  Ideally this table
+ * would not exist, but the current clock implementation depends on some devices
+ * having a specific name.
+ */
+static const struct of_dev_auxdata imx51_auxdata_lookup[] __initconst = {
+	OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART1_BASE_ADDR, "imx21-uart.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART2_BASE_ADDR, "imx21-uart.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART3_BASE_ADDR, "imx21-uart.2", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-fec", MX51_FEC_BASE_ADDR, "imx27-fec.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC1_BASE_ADDR, "sdhci-esdhc-imx51.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC2_BASE_ADDR, "sdhci-esdhc-imx51.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC3_BASE_ADDR, "sdhci-esdhc-imx51.2", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC4_BASE_ADDR, "sdhci-esdhc-imx51.3", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-ecspi", MX51_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-ecspi", MX51_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-cspi", MX51_CSPI_BASE_ADDR, "imx35-cspi.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C1_BASE_ADDR, "imx-i2c.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C2_BASE_ADDR, "imx-i2c.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-sdma", MX51_SDMA_BASE_ADDR, "imx35-sdma", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-wdt", MX51_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL),
+	{ /* sentinel */ }
+};
+
+static void __init imx51_tzic_add_irq_domain(struct device_node *np,
+				struct device_node *interrupt_parent)
+{
+	irq_domain_add_simple(np, 0);
+}
+
+static void __init imx51_gpio_add_irq_domain(struct device_node *np,
+				struct device_node *interrupt_parent)
+{
+	static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS -
+				   32 * 4; /* imx51 gets 4 gpio ports */
+
+	irq_domain_add_simple(np, gpio_irq_base);
+	gpio_irq_base += 32;
+}
+
+static const struct of_device_id imx51_irq_match[] __initconst = {
+	{ .compatible = "fsl,imx51-tzic", .data = imx51_tzic_add_irq_domain, },
+	{ .compatible = "fsl,imx51-gpio", .data = imx51_gpio_add_irq_domain, },
+	{ /* sentinel */ }
+};
+
+static const struct of_device_id imx51_iomuxc_of_match[] __initconst = {
+	{ .compatible = "fsl,imx51-iomuxc-babbage", .data = imx51_babbage_common_init, },
+	{ /* sentinel */ }
+};
+
+static void __init imx51_dt_init(void)
+{
+	struct device_node *node;
+	const struct of_device_id *of_id;
+	void (*func)(void);
+
+	of_irq_init(imx51_irq_match);
+
+	node = of_find_matching_node(NULL, imx51_iomuxc_of_match);
+	if (node) {
+		of_id = of_match_node(imx51_iomuxc_of_match, node);
+		func = of_id->data;
+		func();
+		of_node_put(node);
+	}
+
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     imx51_auxdata_lookup, NULL);
+}
+
+static void __init imx51_timer_init(void)
+{
+	mx51_clocks_init_dt();
+}
+
+static struct sys_timer imx51_timer = {
+	.init = imx51_timer_init,
+};
+
+static const char *imx51_dt_board_compat[] __initdata = {
+	"fsl,imx51-babbage",
+	NULL
+};
+
+DT_MACHINE_START(IMX51_DT, "Freescale i.MX51 (Device Tree Support)")
+	.map_io		= mx51_map_io,
+	.init_early	= imx51_init_early,
+	.init_irq	= mx51_init_irq,
+	.handle_irq	= imx51_handle_irq,
+	.timer		= &imx51_timer,
+	.init_machine	= imx51_dt_init,
+	.dt_compat	= imx51_dt_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-mx5/imx53-dt.c b/arch/arm/mach-mx5/imx53-dt.c
new file mode 100644
index 0000000..ccaa0b8
--- /dev/null
+++ b/arch/arm/mach-mx5/imx53-dt.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+#include <mach/mx53.h>
+
+/*
+ * Lookup table for attaching a specific name and platform_data pointer to
+ * devices as they get created by of_platform_populate().  Ideally this table
+ * would not exist, but the current clock implementation depends on some devices
+ * having a specific name.
+ */
+static const struct of_dev_auxdata imx53_auxdata_lookup[] __initconst = {
+	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART1_BASE_ADDR, "imx21-uart.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART2_BASE_ADDR, "imx21-uart.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART3_BASE_ADDR, "imx21-uart.2", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART4_BASE_ADDR, "imx21-uart.3", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART5_BASE_ADDR, "imx21-uart.4", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-fec", MX53_FEC_BASE_ADDR, "imx25-fec.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC1_BASE_ADDR, "sdhci-esdhc-imx53.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC2_BASE_ADDR, "sdhci-esdhc-imx53.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC3_BASE_ADDR, "sdhci-esdhc-imx53.2", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC4_BASE_ADDR, "sdhci-esdhc-imx53.3", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-cspi", MX53_CSPI_BASE_ADDR, "imx35-cspi.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C1_BASE_ADDR, "imx-i2c.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C2_BASE_ADDR, "imx-i2c.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C3_BASE_ADDR, "imx-i2c.2", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-sdma", MX53_SDMA_BASE_ADDR, "imx35-sdma", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-wdt", MX53_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL),
+	{ /* sentinel */ }
+};
+
+static void __init imx53_tzic_add_irq_domain(struct device_node *np,
+				struct device_node *interrupt_parent)
+{
+	irq_domain_add_simple(np, 0);
+}
+
+static void __init imx53_gpio_add_irq_domain(struct device_node *np,
+				struct device_node *interrupt_parent)
+{
+	static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS -
+				   32 * 7; /* imx53 gets 7 gpio ports */
+
+	irq_domain_add_simple(np, gpio_irq_base);
+	gpio_irq_base += 32;
+}
+
+static const struct of_device_id imx53_irq_match[] __initconst = {
+	{ .compatible = "fsl,imx53-tzic", .data = imx53_tzic_add_irq_domain, },
+	{ .compatible = "fsl,imx53-gpio", .data = imx53_gpio_add_irq_domain, },
+	{ /* sentinel */ }
+};
+
+static const struct of_device_id imx53_iomuxc_of_match[] __initconst = {
+	{ .compatible = "fsl,imx53-iomuxc-ard", .data = imx53_ard_common_init, },
+	{ .compatible = "fsl,imx53-iomuxc-evk", .data = imx53_evk_common_init, },
+	{ .compatible = "fsl,imx53-iomuxc-qsb", .data = imx53_qsb_common_init, },
+	{ .compatible = "fsl,imx53-iomuxc-smd", .data = imx53_smd_common_init, },
+	{ /* sentinel */ }
+};
+
+static void __init imx53_dt_init(void)
+{
+	struct device_node *node;
+	const struct of_device_id *of_id;
+	void (*func)(void);
+
+	of_irq_init(imx53_irq_match);
+
+	node = of_find_matching_node(NULL, imx53_iomuxc_of_match);
+	if (node) {
+		of_id = of_match_node(imx53_iomuxc_of_match, node);
+		func = of_id->data;
+		func();
+		of_node_put(node);
+	}
+
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     imx53_auxdata_lookup, NULL);
+}
+
+static void __init imx53_timer_init(void)
+{
+	mx53_clocks_init_dt();
+}
+
+static struct sys_timer imx53_timer = {
+	.init = imx53_timer_init,
+};
+
+static const char *imx53_dt_board_compat[] __initdata = {
+	"fsl,imx53-ard",
+	"fsl,imx53-evk",
+	"fsl,imx53-qsb",
+	"fsl,imx53-smd",
+	NULL
+};
+
+DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)")
+	.map_io		= mx53_map_io,
+	.init_early	= imx53_init_early,
+	.init_irq	= mx53_init_irq,
+	.handle_irq	= imx53_handle_irq,
+	.timer		= &imx53_timer,
+	.init_machine	= imx53_dt_init,
+	.dt_compat	= imx53_dt_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-mx5/mm-mx50.c b/arch/arm/mach-mx5/mm-mx50.c
deleted file mode 100644
index 77e374c..0000000
--- a/arch/arm/mach-mx5/mm-mx50.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Create static mapping between physical to virtual memory.
- */
-
-#include <linux/mm.h>
-#include <linux/init.h>
-
-#include <asm/mach/map.h>
-
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-v3.h>
-#include <mach/irqs.h>
-
-/*
- * Define the MX50 memory map.
- */
-static struct map_desc mx50_io_desc[] __initdata = {
-	imx_map_entry(MX50, TZIC, MT_DEVICE),
-	imx_map_entry(MX50, SPBA0, MT_DEVICE),
-	imx_map_entry(MX50, AIPS1, MT_DEVICE),
-	imx_map_entry(MX50, AIPS2, MT_DEVICE),
-};
-
-/*
- * This function initializes the memory map. It is called during the
- * system startup to create static physical to virtual memory mappings
- * for the IO modules.
- */
-void __init mx50_map_io(void)
-{
-	iotable_init(mx50_io_desc, ARRAY_SIZE(mx50_io_desc));
-}
-
-void __init imx50_init_early(void)
-{
-	mxc_set_cpu_type(MXC_CPU_MX50);
-	mxc_iomux_v3_init(MX50_IO_ADDRESS(MX50_IOMUXC_BASE_ADDR));
-	mxc_arch_reset_init(MX50_IO_ADDRESS(MX50_WDOG_BASE_ADDR));
-}
-
-void __init mx50_init_irq(void)
-{
-	tzic_init_irq(MX50_IO_ADDRESS(MX50_TZIC_BASE_ADDR));
-}
-
-void __init imx50_soc_init(void)
-{
-	/* i.mx50 has the i.mx31 type gpio */
-	mxc_register_gpio("imx31-gpio", 0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH);
-	mxc_register_gpio("imx31-gpio", 1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH);
-	mxc_register_gpio("imx31-gpio", 2, MX50_GPIO3_BASE_ADDR, SZ_16K, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH);
-	mxc_register_gpio("imx31-gpio", 3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH);
-	mxc_register_gpio("imx31-gpio", 4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH);
-	mxc_register_gpio("imx31-gpio", 5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH);
-}
diff --git a/arch/arm/mach-mx5/mm.c b/arch/arm/mach-mx5/mm.c
index baea6e5..26eacc9 100644
--- a/arch/arm/mach-mx5/mm.c
+++ b/arch/arm/mach-mx5/mm.c
@@ -21,12 +21,27 @@
 #include <mach/devices-common.h>
 #include <mach/iomux-v3.h>
 
+static void imx5_idle(void)
+{
+	mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
+}
+
+/*
+ * Define the MX50 memory map.
+ */
+static struct map_desc mx50_io_desc[] __initdata = {
+	imx_map_entry(MX50, TZIC, MT_DEVICE),
+	imx_map_entry(MX50, SPBA0, MT_DEVICE),
+	imx_map_entry(MX50, AIPS1, MT_DEVICE),
+	imx_map_entry(MX50, AIPS2, MT_DEVICE),
+};
+
 /*
  * Define the MX51 memory map.
  */
 static struct map_desc mx51_io_desc[] __initdata = {
+	imx_map_entry(MX51, TZIC, MT_DEVICE),
 	imx_map_entry(MX51, IRAM, MT_DEVICE),
-	imx_map_entry(MX51, DEBUG, MT_DEVICE),
 	imx_map_entry(MX51, AIPS1, MT_DEVICE),
 	imx_map_entry(MX51, SPBA0, MT_DEVICE),
 	imx_map_entry(MX51, AIPS2, MT_DEVICE),
@@ -36,6 +51,7 @@ static struct map_desc mx51_io_desc[] __initdata = {
  * Define the MX53 memory map.
  */
 static struct map_desc mx53_io_desc[] __initdata = {
+	imx_map_entry(MX53, TZIC, MT_DEVICE),
 	imx_map_entry(MX53, AIPS1, MT_DEVICE),
 	imx_map_entry(MX53, SPBA0, MT_DEVICE),
 	imx_map_entry(MX53, AIPS2, MT_DEVICE),
@@ -46,21 +62,34 @@ static struct map_desc mx53_io_desc[] __initdata = {
  * system startup to create static physical to virtual memory mappings
  * for the IO modules.
  */
+void __init mx50_map_io(void)
+{
+	iotable_init(mx50_io_desc, ARRAY_SIZE(mx50_io_desc));
+}
+
 void __init mx51_map_io(void)
 {
 	iotable_init(mx51_io_desc, ARRAY_SIZE(mx51_io_desc));
 }
 
+void __init mx53_map_io(void)
+{
+	iotable_init(mx53_io_desc, ARRAY_SIZE(mx53_io_desc));
+}
+
+void __init imx50_init_early(void)
+{
+	mxc_set_cpu_type(MXC_CPU_MX50);
+	mxc_iomux_v3_init(MX50_IO_ADDRESS(MX50_IOMUXC_BASE_ADDR));
+	mxc_arch_reset_init(MX50_IO_ADDRESS(MX50_WDOG_BASE_ADDR));
+}
+
 void __init imx51_init_early(void)
 {
 	mxc_set_cpu_type(MXC_CPU_MX51);
 	mxc_iomux_v3_init(MX51_IO_ADDRESS(MX51_IOMUXC_BASE_ADDR));
 	mxc_arch_reset_init(MX51_IO_ADDRESS(MX51_WDOG1_BASE_ADDR));
-}
-
-void __init mx53_map_io(void)
-{
-	iotable_init(mx53_io_desc, ARRAY_SIZE(mx53_io_desc));
+	imx_idle = imx5_idle;
 }
 
 void __init imx53_init_early(void)
@@ -70,35 +99,19 @@ void __init imx53_init_early(void)
 	mxc_arch_reset_init(MX53_IO_ADDRESS(MX53_WDOG1_BASE_ADDR));
 }
 
-void __init mx51_init_irq(void)
+void __init mx50_init_irq(void)
 {
-	unsigned long tzic_addr;
-	void __iomem *tzic_virt;
-
-	if (mx51_revision() < IMX_CHIP_REVISION_2_0)
-		tzic_addr = MX51_TZIC_BASE_ADDR_TO1;
-	else
-		tzic_addr = MX51_TZIC_BASE_ADDR;
-
-	tzic_virt = ioremap(tzic_addr, SZ_16K);
-	if (!tzic_virt)
-		panic("unable to map TZIC interrupt controller\n");
+	tzic_init_irq(MX50_IO_ADDRESS(MX50_TZIC_BASE_ADDR));
+}
 
-	tzic_init_irq(tzic_virt);
+void __init mx51_init_irq(void)
+{
+	tzic_init_irq(MX51_IO_ADDRESS(MX51_TZIC_BASE_ADDR));
 }
 
 void __init mx53_init_irq(void)
 {
-	unsigned long tzic_addr;
-	void __iomem *tzic_virt;
-
-	tzic_addr = MX53_TZIC_BASE_ADDR;
-
-	tzic_virt = ioremap(tzic_addr, SZ_16K);
-	if (!tzic_virt)
-		panic("unable to map TZIC interrupt controller\n");
-
-	tzic_init_irq(tzic_virt);
+	tzic_init_irq(MX53_IO_ADDRESS(MX53_TZIC_BASE_ADDR));
 }
 
 static struct sdma_script_start_addrs imx51_sdma_script __initdata = {
@@ -138,13 +151,24 @@ static struct sdma_platform_data imx53_sdma_pdata __initdata = {
 	.script_addrs = &imx53_sdma_script,
 };
 
+void __init imx50_soc_init(void)
+{
+	/* i.mx50 has the i.mx31 type gpio */
+	mxc_register_gpio("imx31-gpio", 0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH);
+	mxc_register_gpio("imx31-gpio", 1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH);
+	mxc_register_gpio("imx31-gpio", 2, MX50_GPIO3_BASE_ADDR, SZ_16K, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH);
+	mxc_register_gpio("imx31-gpio", 3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH);
+	mxc_register_gpio("imx31-gpio", 4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH);
+	mxc_register_gpio("imx31-gpio", 5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH);
+}
+
 void __init imx51_soc_init(void)
 {
 	/* i.mx51 has the i.mx31 type gpio */
-	mxc_register_gpio("imx31-gpio", 0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO1_LOW, MX51_MXC_INT_GPIO1_HIGH);
-	mxc_register_gpio("imx31-gpio", 1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO2_LOW, MX51_MXC_INT_GPIO2_HIGH);
-	mxc_register_gpio("imx31-gpio", 2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO3_LOW, MX51_MXC_INT_GPIO3_HIGH);
-	mxc_register_gpio("imx31-gpio", 3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO4_LOW, MX51_MXC_INT_GPIO4_HIGH);
+	mxc_register_gpio("imx31-gpio", 0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_INT_GPIO1_LOW, MX51_INT_GPIO1_HIGH);
+	mxc_register_gpio("imx31-gpio", 1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_INT_GPIO2_LOW, MX51_INT_GPIO2_HIGH);
+	mxc_register_gpio("imx31-gpio", 2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_INT_GPIO3_LOW, MX51_INT_GPIO3_HIGH);
+	mxc_register_gpio("imx31-gpio", 3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_INT_GPIO4_LOW, MX51_INT_GPIO4_HIGH);
 
 	/* i.mx51 has the i.mx35 type sdma */
 	imx_add_imx_sdma("imx35-sdma", MX51_SDMA_BASE_ADDR, MX51_INT_SDMA, &imx51_sdma_pdata);
diff --git a/arch/arm/mach-mx5/mx51_efika.c b/arch/arm/mach-mx5/mx51_efika.c
index c920945..b004e17 100644
--- a/arch/arm/mach-mx5/mx51_efika.c
+++ b/arch/arm/mach-mx5/mx51_efika.c
@@ -34,14 +34,12 @@
 #include <linux/usb/ulpi.h>
 #include <mach/ulpi.h>
 
-#include <asm/irq.h>
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
 #include "devices-imx51.h"
-#include "devices.h"
 #include "efika.h"
 #include "cpu_op-mx51.h"
 
@@ -133,7 +131,7 @@ static int initialize_otg_port(struct platform_device *pdev)
 	u32 v;
 	void __iomem *usb_base;
 	void __iomem *usbother_base;
-	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
 	if (!usb_base)
 		return -ENOMEM;
 	usbother_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET);
@@ -150,7 +148,7 @@ static int initialize_otg_port(struct platform_device *pdev)
 	return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_INTERNAL_PHY);
 }
 
-static struct mxc_usbh_platform_data dr_utmi_config = {
+static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
 	.init   = initialize_otg_port,
 	.portsc = MXC_EHCI_UTMI_16BIT,
 };
@@ -170,7 +168,7 @@ static int initialize_usbh1_port(struct platform_device *pdev)
 	gpio_set_value(EFIKAMX_USBH1_STP, 1);
 	msleep(1);
 
-	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
 	socregs_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET);
 
 	/* The clock for the USBH1 ULPI port will come externally */
@@ -189,7 +187,7 @@ static int initialize_usbh1_port(struct platform_device *pdev)
 	return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_ITC_NO_THRESHOLD);
 }
 
-static struct mxc_usbh_platform_data usbh1_config = {
+static struct mxc_usbh_platform_data usbh1_config __initdata = {
 	.init   = initialize_usbh1_port,
 	.portsc = MXC_EHCI_MODE_ULPI,
 };
@@ -217,9 +215,9 @@ static void __init mx51_efika_usb(void)
 	usbh1_config.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
 			ULPI_OTG_DRVVBUS_EXT | ULPI_OTG_EXTVBUSIND);
 
-	mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config);
+	imx51_add_mxc_ehci_otg(&dr_utmi_config);
 	if (usbh1_config.otg)
-		mxc_register_device(&mxc_usbh1_device, &usbh1_config);
+		imx51_add_mxc_ehci_hs(1, &usbh1_config);
 }
 
 static struct mtd_partition mx51_efika_spi_nor_partitions[] = {
@@ -589,7 +587,7 @@ static struct spi_board_info mx51_efika_spi_board_info[] __initdata = {
 		.bus_num = 0,
 		.chip_select = 0,
 		.platform_data = &mx51_efika_mc13892_data,
-		.irq = gpio_to_irq(EFIKAMX_PMIC),
+		.irq = IMX_GPIO_TO_IRQ(EFIKAMX_PMIC),
 	},
 };
 
@@ -609,7 +607,6 @@ void __init efika_board_common_init(void)
 					ARRAY_SIZE(mx51efika_pads));
 	imx51_add_imx_uart(0, &uart_pdata);
 	mx51_efika_usb();
-	imx51_add_sdhci_esdhc_imx(0, NULL);
 
 	/* FIXME: comes from original code. check this. */
 	if (mx51_revision() < IMX_CHIP_REVISION_2_0)
@@ -627,8 +624,9 @@ void __init efika_board_common_init(void)
 		ARRAY_SIZE(mx51_efika_spi_board_info));
 	imx51_add_ecspi(0, &mx51_efika_spi_pdata);
 
+	imx51_add_pata_imx();
+
 #if defined(CONFIG_CPU_FREQ_IMX)
 	get_cpu_op = mx51_get_cpu_op;
 #endif
 }
-
diff --git a/arch/arm/mach-mx5/pm-imx5.c b/arch/arm/mach-mx5/pm-imx5.c
index e4529af..98052fc 100644
--- a/arch/arm/mach-mx5/pm-imx5.c
+++ b/arch/arm/mach-mx5/pm-imx5.c
@@ -14,14 +14,19 @@
 #include <linux/err.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
-#include <mach/system.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
 #include "crm_regs.h"
 
 static struct clk *gpc_dvfs_clk;
 
+static int mx5_suspend_prepare(void)
+{
+	return clk_enable(gpc_dvfs_clk);
+}
+
 static int mx5_suspend_enter(suspend_state_t state)
 {
-	clk_enable(gpc_dvfs_clk);
 	switch (state) {
 	case PM_SUSPEND_MEM:
 		mx5_cpu_lp_set(STOP_POWER_OFF);
@@ -42,11 +47,14 @@ static int mx5_suspend_enter(suspend_state_t state)
 		__raw_writel(0, MXC_SRPG_EMPGC1_SRPGCR);
 	}
 	cpu_do_idle();
-	clk_disable(gpc_dvfs_clk);
-
 	return 0;
 }
 
+static void mx5_suspend_finish(void)
+{
+	clk_disable(gpc_dvfs_clk);
+}
+
 static int mx5_pm_valid(suspend_state_t state)
 {
 	return (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX);
@@ -54,7 +62,9 @@ static int mx5_pm_valid(suspend_state_t state)
 
 static const struct platform_suspend_ops mx5_suspend_ops = {
 	.valid = mx5_pm_valid,
+	.prepare = mx5_suspend_prepare,
 	.enter = mx5_suspend_enter,
+	.finish = mx5_suspend_finish,
 };
 
 static int __init mx5_pm_init(void)
diff --git a/arch/arm/mach-mx5/system.c b/arch/arm/mach-mx5/system.c
index 76ae8dc..144ebeb 100644
--- a/arch/arm/mach-mx5/system.c
+++ b/arch/arm/mach-mx5/system.c
@@ -13,6 +13,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <mach/hardware.h>
+#include <mach/common.h>
 #include "crm_regs.h"
 
 /* set cpu low power mode before WFI instruction. This function is called
diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig
index 4cd0231..cf00b3e 100644
--- a/arch/arm/mach-mxs/Kconfig
+++ b/arch/arm/mach-mxs/Kconfig
@@ -23,6 +23,7 @@ config MACH_STMP378X_DEVB
 	select MXS_HAVE_AMBA_DUART
 	select MXS_HAVE_PLATFORM_AUART
 	select MXS_HAVE_PLATFORM_MXS_MMC
+	select MXS_HAVE_PLATFORM_RTC_STMP3XXX
 	help
 	  Include support for STMP378x-devb platform. This includes specific
 	  configurations for the board and its peripherals.
@@ -34,6 +35,7 @@ config MACH_MX23EVK
 	select MXS_HAVE_PLATFORM_AUART
 	select MXS_HAVE_PLATFORM_MXS_MMC
 	select MXS_HAVE_PLATFORM_MXSFB
+	select MXS_HAVE_PLATFORM_RTC_STMP3XXX
 	help
 	  Include support for MX23EVK platform. This includes specific
 	  configurations for the board and its peripherals.
@@ -48,6 +50,9 @@ config MACH_MX28EVK
 	select MXS_HAVE_PLATFORM_FLEXCAN
 	select MXS_HAVE_PLATFORM_MXS_MMC
 	select MXS_HAVE_PLATFORM_MXSFB
+	select MXS_HAVE_PLATFORM_MXS_SAIF
+	select MXS_HAVE_PLATFORM_MXS_I2C
+	select MXS_HAVE_PLATFORM_RTC_STMP3XXX
 	select MXS_OCOTP
 	help
 	  Include support for MX28EVK platform. This includes specific
@@ -63,9 +68,27 @@ config MODULE_TX28
 	select MXS_HAVE_PLATFORM_MXS_I2C
 	select MXS_HAVE_PLATFORM_MXS_MMC
 	select MXS_HAVE_PLATFORM_MXS_PWM
+	select MXS_HAVE_PLATFORM_RTC_STMP3XXX
+
+config MODULE_M28
+	bool
+	select SOC_IMX28
+	select LEDS_GPIO_REGISTER
+	select MXS_HAVE_AMBA_DUART
+	select MXS_HAVE_PLATFORM_AUART
+	select MXS_HAVE_PLATFORM_FEC
+	select MXS_HAVE_PLATFORM_FLEXCAN
+	select MXS_HAVE_PLATFORM_MXS_I2C
+	select MXS_HAVE_PLATFORM_MXS_MMC
+	select MXS_HAVE_PLATFORM_MXSFB
+	select MXS_OCOTP
 
 config MACH_TX28
 	bool "Ka-Ro TX28 module"
 	select MODULE_TX28
 
+config MACH_M28EVK
+	bool "Support DENX M28EVK Platform"
+	select MODULE_M28
+
 endif
diff --git a/arch/arm/mach-mxs/Makefile b/arch/arm/mach-mxs/Makefile
index 6c38262..8c93b24 100644
--- a/arch/arm/mach-mxs/Makefile
+++ b/arch/arm/mach-mxs/Makefile
@@ -1,15 +1,16 @@
 # Common support
-obj-y := clock.o devices.o icoll.o iomux.o system.o timer.o
+obj-y := clock.o devices.o icoll.o iomux.o system.o timer.o mm.o
 
 obj-$(CONFIG_MXS_OCOTP) += ocotp.o
 obj-$(CONFIG_PM) += pm.o
 
-obj-$(CONFIG_SOC_IMX23) += clock-mx23.o mm-mx23.o
-obj-$(CONFIG_SOC_IMX28) += clock-mx28.o mm-mx28.o
+obj-$(CONFIG_SOC_IMX23) += clock-mx23.o
+obj-$(CONFIG_SOC_IMX28) += clock-mx28.o
 
 obj-$(CONFIG_MACH_STMP378X_DEVB) += mach-stmp378x_devb.o
 obj-$(CONFIG_MACH_MX23EVK) += mach-mx23evk.o
 obj-$(CONFIG_MACH_MX28EVK) += mach-mx28evk.o
+obj-$(CONFIG_MACH_M28EVK)    += mach-m28evk.o
 obj-$(CONFIG_MODULE_TX28) += module-tx28.o
 obj-$(CONFIG_MACH_TX28)    += mach-tx28.o
 
diff --git a/arch/arm/mach-mxs/clock-mx28.c b/arch/arm/mach-mxs/clock-mx28.c
index 5dcc59d..229ae34 100644
--- a/arch/arm/mach-mxs/clock-mx28.c
+++ b/arch/arm/mach-mxs/clock-mx28.c
@@ -349,7 +349,7 @@ static int name##_set_rate(struct clk *clk, unsigned long rate)		\
 									\
 		reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##fr);	\
 		reg &= ~BM_CLKCTRL_##fr##_##fs##FRAC;			\
-		reg |= frac;						\
+		reg |= frac << BP_CLKCTRL_##fr##_##fs##FRAC;		\
 		__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##fr);	\
 	}								\
 									\
@@ -640,6 +640,8 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK(NULL, "lradc", lradc_clk)
 	_REGISTER_CLOCK(NULL, "spdif", spdif_clk)
 	_REGISTER_CLOCK("imx28-fb", NULL, lcdif_clk)
+	_REGISTER_CLOCK("mxs-saif.0", NULL, saif0_clk)
+	_REGISTER_CLOCK("mxs-saif.1", NULL, saif1_clk)
 };
 
 static int clk_misc_init(void)
@@ -708,11 +710,11 @@ static int clk_misc_init(void)
 
 	/* SAIF has to use frac div for functional operation */
 	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_SAIF0);
-	reg &= ~BM_CLKCTRL_SAIF0_DIV_FRAC_EN;
+	reg |= BM_CLKCTRL_SAIF0_DIV_FRAC_EN;
 	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_SAIF0);
 
 	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_SAIF1);
-	reg &= ~BM_CLKCTRL_SAIF1_DIV_FRAC_EN;
+	reg |= BM_CLKCTRL_SAIF1_DIV_FRAC_EN;
 	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_SAIF1);
 
 	/*
@@ -738,11 +740,17 @@ static int clk_misc_init(void)
 	__raw_writel(BM_CLKCTRL_CPU_INTERRUPT_WAIT,
 			CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU_SET);
 
-	/* Extra fec clock setting */
-	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_ENET);
-	reg &= ~BM_CLKCTRL_ENET_SLEEP;
-	reg |= BM_CLKCTRL_ENET_CLK_OUT_EN;
-	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_ENET);
+	/*
+	 * Extra fec clock setting
+	 * The DENX M28 uses an external clock source
+	 * and the clock output must not be enabled
+	 */
+	if (!machine_is_m28evk()) {
+		reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_ENET);
+		reg &= ~BM_CLKCTRL_ENET_SLEEP;
+		reg |= BM_CLKCTRL_ENET_CLK_OUT_EN;
+		__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_ENET);
+	}
 
 	/*
 	 * 480 MHz seems too high to be ssp clock source directly,
@@ -774,6 +782,8 @@ int __init mx28_clocks_init(void)
 	clk_enable(&uart_clk);
 
 	clk_set_parent(&lcdif_clk, &ref_pix_clk);
+	clk_set_parent(&saif0_clk, &pll0_clk);
+	clk_set_parent(&saif1_clk, &pll0_clk);
 
 	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
 
diff --git a/arch/arm/mach-mxs/devices-mx23.h b/arch/arm/mach-mxs/devices-mx23.h
index c6f345f..3fa651d 100644
--- a/arch/arm/mach-mxs/devices-mx23.h
+++ b/arch/arm/mach-mxs/devices-mx23.h
@@ -29,3 +29,5 @@ extern const struct mxs_mxs_mmc_data mx23_mxs_mmc_data[] __initconst;
 
 struct platform_device *__init mx23_add_mxsfb(
 		const struct mxsfb_platform_data *pdata);
+
+struct platform_device *__init mx23_add_rtc_stmp3xxx(void);
diff --git a/arch/arm/mach-mxs/devices-mx28.h b/arch/arm/mach-mxs/devices-mx28.h
index 79b9452..c888710 100644
--- a/arch/arm/mach-mxs/devices-mx28.h
+++ b/arch/arm/mach-mxs/devices-mx28.h
@@ -45,3 +45,8 @@ extern const struct mxs_mxs_mmc_data mx28_mxs_mmc_data[] __initconst;
 
 struct platform_device *__init mx28_add_mxsfb(
 		const struct mxsfb_platform_data *pdata);
+
+extern const struct mxs_saif_data mx28_saif_data[] __initconst;
+#define mx28_add_saif(id)              mxs_add_saif(&mx28_saif_data[id])
+
+struct platform_device *__init mx28_add_rtc_stmp3xxx(void);
diff --git a/arch/arm/mach-mxs/devices/Kconfig b/arch/arm/mach-mxs/devices/Kconfig
index acf9eea..18b6bf5 100644
--- a/arch/arm/mach-mxs/devices/Kconfig
+++ b/arch/arm/mach-mxs/devices/Kconfig
@@ -23,3 +23,9 @@ config MXS_HAVE_PLATFORM_MXS_PWM
 
 config MXS_HAVE_PLATFORM_MXSFB
 	bool
+
+config MXS_HAVE_PLATFORM_MXS_SAIF
+	bool
+
+config MXS_HAVE_PLATFORM_RTC_STMP3XXX
+	bool
diff --git a/arch/arm/mach-mxs/devices/Makefile b/arch/arm/mach-mxs/devices/Makefile
index 351915c..f52e3e5 100644
--- a/arch/arm/mach-mxs/devices/Makefile
+++ b/arch/arm/mach-mxs/devices/Makefile
@@ -8,3 +8,5 @@ obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_MMC) += platform-mxs-mmc.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_PWM) += platform-mxs-pwm.o
 obj-y += platform-gpio-mxs.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_MXSFB) += platform-mxsfb.o
+obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_SAIF) += platform-mxs-saif.o
+obj-$(CONFIG_MXS_HAVE_PLATFORM_RTC_STMP3XXX) += platform-rtc-stmp3xxx.o
diff --git a/arch/arm/mach-mxs/devices/platform-mxs-saif.c b/arch/arm/mach-mxs/devices/platform-mxs-saif.c
new file mode 100644
index 0000000..1ec965e
--- /dev/null
+++ b/arch/arm/mach-mxs/devices/platform-mxs-saif.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <linux/compiler.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <mach/mx23.h>
+#include <mach/mx28.h>
+#include <mach/devices-common.h>
+
+#define mxs_saif_data_entry_single(soc, _id)				\
+	{								\
+		.id = _id,						\
+		.iobase = soc ## _SAIF ## _id ## _BASE_ADDR,		\
+		.irq = soc ## _INT_SAIF ## _id,				\
+		.dma = soc ## _DMA_SAIF ## _id,				\
+		.dmairq = soc ## _INT_SAIF ## _id ##_DMA,		\
+	}
+
+#define mxs_saif_data_entry(soc, _id)					\
+	[_id] = mxs_saif_data_entry_single(soc, _id)
+
+#ifdef CONFIG_SOC_IMX28
+const struct mxs_saif_data mx28_saif_data[] __initconst = {
+	mxs_saif_data_entry(MX28, 0),
+	mxs_saif_data_entry(MX28, 1),
+};
+#endif
+
+struct platform_device *__init mxs_add_saif(const struct mxs_saif_data *data)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_4K - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		}, {
+			.start = data->dma,
+			.end = data->dma,
+			.flags = IORESOURCE_DMA,
+		}, {
+			.start = data->dmairq,
+			.end = data->dmairq,
+			.flags = IORESOURCE_IRQ,
+		},
+
+	};
+
+	return mxs_add_platform_device("mxs-saif", data->id, res,
+					ARRAY_SIZE(res), NULL, 0);
+}
diff --git a/arch/arm/mach-mxs/devices/platform-rtc-stmp3xxx.c b/arch/arm/mach-mxs/devices/platform-rtc-stmp3xxx.c
new file mode 100644
index 0000000..639eaee
--- /dev/null
+++ b/arch/arm/mach-mxs/devices/platform-rtc-stmp3xxx.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 Pengutronix, Wolfram Sang <w.sang@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <asm/sizes.h>
+#include <mach/mx23.h>
+#include <mach/mx28.h>
+#include <mach/devices-common.h>
+
+#ifdef CONFIG_SOC_IMX23
+struct platform_device *__init mx23_add_rtc_stmp3xxx(void)
+{
+	struct resource res[] = {
+		{
+			.start = MX23_RTC_BASE_ADDR,
+			.end = MX23_RTC_BASE_ADDR + SZ_8K - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = MX23_INT_RTC_ALARM,
+			.end = MX23_INT_RTC_ALARM,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return mxs_add_platform_device("stmp3xxx-rtc", 0, res, ARRAY_SIZE(res),
+					NULL, 0);
+}
+#endif /* CONFIG_SOC_IMX23 */
+
+#ifdef CONFIG_SOC_IMX28
+struct platform_device *__init mx28_add_rtc_stmp3xxx(void)
+{
+	struct resource res[] = {
+		{
+			.start = MX28_RTC_BASE_ADDR,
+			.end = MX28_RTC_BASE_ADDR + SZ_8K - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = MX28_INT_RTC_ALARM,
+			.end = MX28_INT_RTC_ALARM,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return mxs_add_platform_device("stmp3xxx-rtc", 0, res, ARRAY_SIZE(res),
+					NULL, 0);
+}
+#endif /* CONFIG_SOC_IMX28 */
diff --git a/arch/arm/mach-mxs/include/mach/debug-macro.S b/arch/arm/mach-mxs/include/mach/debug-macro.S
index 714570d..90c6b78 100644
--- a/arch/arm/mach-mxs/include/mach/debug-macro.S
+++ b/arch/arm/mach-mxs/include/mach/debug-macro.S
@@ -14,17 +14,9 @@
 #include <mach/mx23.h>
 #include <mach/mx28.h>
 
-#ifdef CONFIG_SOC_IMX23
-#ifdef UART_PADDR
-#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
-#endif
+#ifdef CONFIG_DEBUG_IMX23_UART
 #define UART_PADDR	MX23_DUART_BASE_ADDR
-#endif
-
-#ifdef CONFIG_SOC_IMX28
-#ifdef UART_PADDR
-#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
-#endif
+#elif defined (CONFIG_DEBUG_IMX28_UART)
 #define UART_PADDR	MX28_DUART_BASE_ADDR
 #endif
 
diff --git a/arch/arm/mach-mxs/include/mach/devices-common.h b/arch/arm/mach-mxs/include/mach/devices-common.h
index 812d7a8..a8080f4 100644
--- a/arch/arm/mach-mxs/include/mach/devices-common.h
+++ b/arch/arm/mach-mxs/include/mach/devices-common.h
@@ -92,3 +92,15 @@ struct platform_device *__init mxs_add_mxs_mmc(
 /* pwm */
 struct platform_device *__init mxs_add_mxs_pwm(
 		resource_size_t iobase, int id);
+
+/* saif */
+struct mxs_saif_data {
+	int id;
+	resource_size_t iobase;
+	resource_size_t irq;
+	resource_size_t dma;
+	resource_size_t dmairq;
+};
+
+struct platform_device *__init mxs_add_saif(
+		const struct mxs_saif_data *data);
diff --git a/arch/arm/mach-mxs/include/mach/gpio.h b/arch/arm/mach-mxs/include/mach/gpio.h
index bb11e63..40a8c17 100644
--- a/arch/arm/mach-mxs/include/mach/gpio.h
+++ b/arch/arm/mach-mxs/include/mach/gpio.h
@@ -1,27 +1 @@
-/*
- * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- */
-
-#ifndef __MACH_MXS_GPIO_H__
-#define __MACH_MXS_GPIO_H__
-
-#define MXS_GPIO_NR(bank, nr)	((bank) * 32 + (nr))
-
-#define irq_to_gpio(irq)	((irq) - MXS_GPIO_IRQ_START)
-
-#endif /* __MACH_MXS_GPIO_H__ */
+/* empty */
diff --git a/arch/arm/mach-mxs/include/mach/mxs.h b/arch/arm/mach-mxs/include/mach/mxs.h
index 35a89dd..0d2d2b4 100644
--- a/arch/arm/mach-mxs/include/mach/mxs.h
+++ b/arch/arm/mach-mxs/include/mach/mxs.h
@@ -33,6 +33,7 @@
 		0)
 #define cpu_is_mx28()		(					\
 		machine_is_mx28evk() ||					\
+		machine_is_m28evk() ||					\
 		machine_is_tx28() ||					\
 		0)
 
@@ -86,6 +87,8 @@
 	.type = _type,							\
 }
 
+#define MXS_GPIO_NR(bank, nr)	((bank) * 32 + (nr))
+
 #define MXS_SET_ADDR		0x4
 #define MXS_CLR_ADDR		0x8
 #define MXS_TOG_ADDR		0xc
diff --git a/arch/arm/mach-mxs/include/mach/uncompress.h b/arch/arm/mach-mxs/include/mach/uncompress.h
index 7f8bf65..6777674 100644
--- a/arch/arm/mach-mxs/include/mach/uncompress.h
+++ b/arch/arm/mach-mxs/include/mach/uncompress.h
@@ -63,6 +63,7 @@ static inline void __arch_decomp_setup(unsigned long arch_id)
 		mxs_duart_base = MX23_DUART_BASE_ADDR;
 		break;
 	case MACH_TYPE_MX28EVK:
+	case MACH_TYPE_M28EVK:
 	case MACH_TYPE_TX28:
 		mxs_duart_base = MX28_DUART_BASE_ADDR;
 		break;
diff --git a/arch/arm/mach-mxs/mach-m28evk.c b/arch/arm/mach-mxs/mach-m28evk.c
new file mode 100644
index 0000000..3b1681e
--- /dev/null
+++ b/arch/arm/mach-mxs/mach-m28evk.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright (C) 2011
+ * Stefano Babic, DENX Software Engineering, <sbabic@denx.de>
+ *
+ * based on: mach-mx28_evk.c
+ * Copyright 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/i2c.h>
+#include <linux/i2c/at24.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include <mach/common.h>
+#include <mach/iomux-mx28.h>
+
+#include "devices-mx28.h"
+
+#define M28EVK_GPIO_USERLED1	MXS_GPIO_NR(3, 16)
+#define M28EVK_GPIO_USERLED2	MXS_GPIO_NR(3, 17)
+
+#define MX28EVK_BL_ENABLE	MXS_GPIO_NR(3, 18)
+#define M28EVK_LCD_ENABLE	MXS_GPIO_NR(3, 28)
+
+#define MX28EVK_MMC0_WRITE_PROTECT	MXS_GPIO_NR(2, 12)
+#define MX28EVK_MMC1_WRITE_PROTECT	MXS_GPIO_NR(0, 28)
+
+static const iomux_cfg_t m28evk_pads[] __initconst = {
+	/* duart */
+	MX28_PAD_AUART0_CTS__DUART_RX | MXS_PAD_CTRL,
+	MX28_PAD_AUART0_RTS__DUART_TX | MXS_PAD_CTRL,
+
+	/* auart0 */
+	MX28_PAD_AUART0_RX__AUART0_RX | MXS_PAD_CTRL,
+	MX28_PAD_AUART0_TX__AUART0_TX | MXS_PAD_CTRL,
+
+	/* auart3 */
+	MX28_PAD_AUART3_RX__AUART3_RX | MXS_PAD_CTRL,
+	MX28_PAD_AUART3_TX__AUART3_TX | MXS_PAD_CTRL,
+	MX28_PAD_AUART3_CTS__AUART3_CTS | MXS_PAD_CTRL,
+	MX28_PAD_AUART3_RTS__AUART3_RTS | MXS_PAD_CTRL,
+
+#define MXS_PAD_FEC	(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP)
+	/* fec0 */
+	MX28_PAD_ENET0_MDC__ENET0_MDC | MXS_PAD_FEC,
+	MX28_PAD_ENET0_MDIO__ENET0_MDIO | MXS_PAD_FEC,
+	MX28_PAD_ENET0_RX_EN__ENET0_RX_EN | MXS_PAD_FEC,
+	MX28_PAD_ENET0_RXD0__ENET0_RXD0 | MXS_PAD_FEC,
+	MX28_PAD_ENET0_RXD1__ENET0_RXD1 | MXS_PAD_FEC,
+	MX28_PAD_ENET0_TX_EN__ENET0_TX_EN | MXS_PAD_FEC,
+	MX28_PAD_ENET0_TXD0__ENET0_TXD0 | MXS_PAD_FEC,
+	MX28_PAD_ENET0_TXD1__ENET0_TXD1 | MXS_PAD_FEC,
+	MX28_PAD_ENET_CLK__CLKCTRL_ENET | MXS_PAD_FEC,
+	/* fec1 */
+	MX28_PAD_ENET0_CRS__ENET1_RX_EN | MXS_PAD_FEC,
+	MX28_PAD_ENET0_RXD2__ENET1_RXD0 | MXS_PAD_FEC,
+	MX28_PAD_ENET0_RXD3__ENET1_RXD1 | MXS_PAD_FEC,
+	MX28_PAD_ENET0_COL__ENET1_TX_EN | MXS_PAD_FEC,
+	MX28_PAD_ENET0_TXD2__ENET1_TXD0 | MXS_PAD_FEC,
+	MX28_PAD_ENET0_TXD3__ENET1_TXD1 | MXS_PAD_FEC,
+
+	/* flexcan0 */
+	MX28_PAD_GPMI_RDY2__CAN0_TX,
+	MX28_PAD_GPMI_RDY3__CAN0_RX,
+
+	/* flexcan1 */
+	MX28_PAD_GPMI_CE2N__CAN1_TX,
+	MX28_PAD_GPMI_CE3N__CAN1_RX,
+
+	/* I2C */
+	MX28_PAD_I2C0_SCL__I2C0_SCL,
+	MX28_PAD_I2C0_SDA__I2C0_SDA,
+
+	/* mxsfb (lcdif) */
+	MX28_PAD_LCD_D00__LCD_D0 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D01__LCD_D1 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D02__LCD_D2 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D03__LCD_D3 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D04__LCD_D4 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D05__LCD_D5 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D06__LCD_D6 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D07__LCD_D7 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D08__LCD_D8 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D09__LCD_D9 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D10__LCD_D10 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D11__LCD_D11 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D12__LCD_D12 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D13__LCD_D13 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D14__LCD_D14 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D15__LCD_D15 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D16__LCD_D16 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D17__LCD_D17 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D18__LCD_D18 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D19__LCD_D19 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D20__LCD_D20 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D21__LCD_D21 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D22__LCD_D22 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D23__LCD_D23 | MXS_PAD_CTRL,
+
+	MX28_PAD_LCD_ENABLE__LCD_ENABLE	| MXS_PAD_CTRL,
+	MX28_PAD_LCD_DOTCLK__LCD_DOTCLK | MXS_PAD_CTRL,
+
+	/* mmc0 */
+	MX28_PAD_SSP0_DATA0__SSP0_D0 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA1__SSP0_D1 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA2__SSP0_D2 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA3__SSP0_D3 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA4__SSP0_D4 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA5__SSP0_D5 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA6__SSP0_D6 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA7__SSP0_D7 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_CMD__SSP0_CMD |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	MX28_PAD_SSP0_SCK__SSP0_SCK |
+		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+
+	/* mmc1 */
+	MX28_PAD_GPMI_D00__SSP1_D0 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_D01__SSP1_D1 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_D02__SSP1_D2 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_D03__SSP1_D3 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_D04__SSP1_D4 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_D05__SSP1_D5 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_D06__SSP1_D6 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_D07__SSP1_D7 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_RDY1__SSP1_CMD |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_RDY0__SSP1_CARD_DETECT |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_WRN__SSP1_SCK |
+		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	/* write protect */
+	MX28_PAD_GPMI_RESETN__GPIO_0_28 |
+		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	/* slot power enable */
+	MX28_PAD_PWM4__GPIO_3_29 |
+		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+
+	/* led */
+	MX28_PAD_PWM0__GPIO_3_16 | MXS_PAD_CTRL,
+	MX28_PAD_PWM1__GPIO_3_17 | MXS_PAD_CTRL,
+
+	/* nand */
+	MX28_PAD_GPMI_D00__GPMI_D0 |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_D01__GPMI_D1 |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_D02__GPMI_D2 |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_D03__GPMI_D3 |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_D04__GPMI_D4 |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_D05__GPMI_D5 |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_D06__GPMI_D6 |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_D07__GPMI_D7 |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_CE0N__GPMI_CE0N |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_RDY0__GPMI_READY0 |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_RDN__GPMI_RDN |
+		(MXS_PAD_12MA | MXS_PAD_1V8 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_WRN__GPMI_WRN |
+		(MXS_PAD_12MA | MXS_PAD_1V8 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_ALE__GPMI_ALE |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_CLE__GPMI_CLE |
+		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_RESETN__GPMI_RESETN |
+		(MXS_PAD_12MA | MXS_PAD_1V8 | MXS_PAD_PULLUP),
+
+	/* Backlight */
+	MX28_PAD_PWM3__GPIO_3_28 | MXS_PAD_CTRL,
+};
+
+/* led */
+static const struct gpio_led m28evk_leds[] __initconst = {
+	{
+		.name = "user-led1",
+		.default_trigger = "heartbeat",
+		.gpio = M28EVK_GPIO_USERLED1,
+	},
+	{
+		.name = "user-led2",
+		.default_trigger = "heartbeat",
+		.gpio = M28EVK_GPIO_USERLED2,
+	},
+};
+
+static const struct gpio_led_platform_data m28evk_led_data __initconst = {
+	.leds = m28evk_leds,
+	.num_leds = ARRAY_SIZE(m28evk_leds),
+};
+
+static struct fec_platform_data mx28_fec_pdata[] __initdata = {
+	{
+		/* fec0 */
+		.phy = PHY_INTERFACE_MODE_RMII,
+	}, {
+		/* fec1 */
+		.phy = PHY_INTERFACE_MODE_RMII,
+	},
+};
+
+static int __init m28evk_fec_get_mac(void)
+{
+	int i;
+	u32 val;
+	const u32 *ocotp = mxs_get_ocotp();
+
+	if (!ocotp) {
+		pr_err("%s: timeout when reading fec mac from OCOTP\n",
+			__func__);
+		return -ETIMEDOUT;
+	}
+
+	/*
+	 * OCOTP only stores the last 4 octets for each mac address,
+	 * so hard-code DENX OUI (C0:E5:4E) here.
+	 */
+	for (i = 0; i < 2; i++) {
+		val = ocotp[i * 4];
+		mx28_fec_pdata[i].mac[0] = 0xC0;
+		mx28_fec_pdata[i].mac[1] = 0xE5;
+		mx28_fec_pdata[i].mac[2] = 0x4E;
+		mx28_fec_pdata[i].mac[3] = (val >> 16) & 0xff;
+		mx28_fec_pdata[i].mac[4] = (val >> 8) & 0xff;
+		mx28_fec_pdata[i].mac[5] = (val >> 0) & 0xff;
+	}
+
+	return 0;
+}
+
+/* mxsfb (lcdif) */
+static struct fb_videomode m28evk_video_modes[] = {
+	{
+		.name		= "Ampire AM-800480R2TMQW-T01H",
+		.refresh	= 60,
+		.xres		= 800,
+		.yres		= 480,
+		.pixclock	= 30066, /* picosecond (33.26 MHz) */
+		.left_margin	= 0,
+		.right_margin	= 256,
+		.upper_margin	= 0,
+		.lower_margin	= 45,
+		.hsync_len	= 1,
+		.vsync_len	= 1,
+		.sync		= FB_SYNC_DATA_ENABLE_HIGH_ACT,
+	},
+};
+
+static const struct mxsfb_platform_data m28evk_mxsfb_pdata __initconst = {
+	.mode_list	= m28evk_video_modes,
+	.mode_count	= ARRAY_SIZE(m28evk_video_modes),
+	.default_bpp	= 16,
+	.ld_intf_width	= STMLCDIF_18BIT,
+};
+
+static struct at24_platform_data m28evk_eeprom = {
+	.byte_len = 16384,
+	.page_size = 32,
+	.flags = AT24_FLAG_ADDR16,
+};
+
+static struct i2c_board_info m28_stk5v3_i2c_boardinfo[] __initdata = {
+	{
+		I2C_BOARD_INFO("at24", 0x51),	/* E0=1, E1=0, E2=0 */
+		.platform_data = &m28evk_eeprom,
+	},
+};
+
+static struct mxs_mmc_platform_data m28evk_mmc_pdata[] __initdata = {
+	{
+		/* mmc0 */
+		.wp_gpio = MX28EVK_MMC0_WRITE_PROTECT,
+		.flags = SLOTF_8_BIT_CAPABLE,
+	}, {
+		/* mmc1 */
+		.wp_gpio = MX28EVK_MMC1_WRITE_PROTECT,
+		.flags = SLOTF_8_BIT_CAPABLE,
+	},
+};
+
+static void __init m28evk_init(void)
+{
+	mxs_iomux_setup_multiple_pads(m28evk_pads, ARRAY_SIZE(m28evk_pads));
+
+	mx28_add_duart();
+	mx28_add_auart0();
+	mx28_add_auart3();
+
+	if (!m28evk_fec_get_mac()) {
+		mx28_add_fec(0, &mx28_fec_pdata[0]);
+		mx28_add_fec(1, &mx28_fec_pdata[1]);
+	}
+
+	mx28_add_flexcan(0, NULL);
+	mx28_add_flexcan(1, NULL);
+
+	mx28_add_mxsfb(&m28evk_mxsfb_pdata);
+
+	mx28_add_mxs_mmc(0, &m28evk_mmc_pdata[0]);
+	mx28_add_mxs_mmc(1, &m28evk_mmc_pdata[1]);
+
+	gpio_led_register_device(0, &m28evk_led_data);
+
+	/* I2C */
+	mx28_add_mxs_i2c(0);
+	i2c_register_board_info(0, m28_stk5v3_i2c_boardinfo,
+			ARRAY_SIZE(m28_stk5v3_i2c_boardinfo));
+}
+
+static void __init m28evk_timer_init(void)
+{
+	mx28_clocks_init();
+}
+
+static struct sys_timer m28evk_timer = {
+	.init	= m28evk_timer_init,
+};
+
+MACHINE_START(M28EVK, "DENX M28 EVK")
+	.map_io		= mx28_map_io,
+	.init_irq	= mx28_init_irq,
+	.init_machine	= m28evk_init,
+	.timer		= &m28evk_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mxs/mach-mx23evk.c b/arch/arm/mach-mxs/mach-mx23evk.c
index 3c2de33..c325fbe 100644
--- a/arch/arm/mach-mxs/mach-mx23evk.c
+++ b/arch/arm/mach-mxs/mach-mx23evk.c
@@ -15,7 +15,6 @@
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
-#include <linux/irq.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -167,6 +166,7 @@ static void __init mx23evk_init(void)
 		gpio_set_value(MX23EVK_BL_ENABLE, 1);
 
 	mx23_add_mxsfb(&mx23evk_mxsfb_pdata);
+	mx23_add_rtc_stmp3xxx();
 }
 
 static void __init mx23evk_timer_init(void)
@@ -182,6 +182,6 @@ MACHINE_START(MX23EVK, "Freescale MX23 EVK")
 	/* Maintainer: Freescale Semiconductor, Inc. */
 	.map_io		= mx23_map_io,
 	.init_irq	= mx23_init_irq,
-	.init_machine	= mx23evk_init,
 	.timer		= &mx23evk_timer,
+	.init_machine	= mx23evk_init,
 MACHINE_END
diff --git a/arch/arm/mach-mxs/mach-mx28evk.c b/arch/arm/mach-mxs/mach-mx28evk.c
index eaaf6ff..ac2316d 100644
--- a/arch/arm/mach-mxs/mach-mx28evk.c
+++ b/arch/arm/mach-mxs/mach-mx28evk.c
@@ -16,8 +16,10 @@
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/leds.h>
-#include <linux/irq.h>
 #include <linux/clk.h>
+#include <linux/i2c.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -183,6 +185,24 @@ static const iomux_cfg_t mx28evk_pads[] __initconst = {
 
 	/* led */
 	MX28_PAD_AUART1_TX__GPIO_3_5 | MXS_PAD_CTRL,
+
+	/* I2C */
+	MX28_PAD_I2C0_SCL__I2C0_SCL |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_I2C0_SDA__I2C0_SDA |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+
+	/* saif0 & saif1 */
+	MX28_PAD_SAIF0_MCLK__SAIF0_MCLK |
+		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SAIF0_LRCLK__SAIF0_LRCLK |
+		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SAIF0_BITCLK__SAIF0_BITCLK |
+		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SAIF0_SDATA0__SAIF0_SDATA0 |
+		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SAIF1_SDATA0__SAIF1_SDATA0 |
+		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
 };
 
 /* led */
@@ -352,6 +372,55 @@ static struct mxs_mmc_platform_data mx28evk_mmc_pdata[] __initdata = {
 	},
 };
 
+static struct i2c_board_info mxs_i2c0_board_info[] __initdata = {
+	{
+		I2C_BOARD_INFO("sgtl5000", 0x0a),
+	},
+};
+
+#if defined(CONFIG_REGULATOR_FIXED_VOLTAGE) || defined(CONFIG_REGULATOR_FIXED_VOLTAGE_MODULE)
+static struct regulator_consumer_supply mx28evk_audio_consumer_supplies[] = {
+	REGULATOR_SUPPLY("VDDA", "0-000a"),
+	REGULATOR_SUPPLY("VDDIO", "0-000a"),
+};
+
+static struct regulator_init_data mx28evk_vdd_reg_init_data = {
+	.constraints	= {
+		.name	= "3V3",
+		.always_on = 1,
+	},
+	.consumer_supplies = mx28evk_audio_consumer_supplies,
+	.num_consumer_supplies = ARRAY_SIZE(mx28evk_audio_consumer_supplies),
+};
+
+static struct fixed_voltage_config mx28evk_vdd_pdata = {
+	.supply_name	= "board-3V3",
+	.microvolts	= 3300000,
+	.gpio		= -EINVAL,
+	.enabled_at_boot = 1,
+	.init_data	= &mx28evk_vdd_reg_init_data,
+};
+static struct platform_device mx28evk_voltage_regulator = {
+	.name		= "reg-fixed-voltage",
+	.id		= -1,
+	.num_resources	= 0,
+	.dev		= {
+		.platform_data	= &mx28evk_vdd_pdata,
+	},
+};
+static void __init mx28evk_add_regulators(void)
+{
+	platform_device_register(&mx28evk_voltage_regulator);
+}
+#else
+static void __init mx28evk_add_regulators(void) {}
+#endif
+
+static struct gpio mx28evk_lcd_gpios[] = {
+	{ MX28EVK_LCD_ENABLE, GPIOF_OUT_INIT_HIGH, "lcd-enable" },
+	{ MX28EVK_BL_ENABLE, GPIOF_OUT_INIT_HIGH, "bl-enable" },
+};
+
 static void __init mx28evk_init(void)
 {
 	int ret;
@@ -378,19 +447,24 @@ static void __init mx28evk_init(void)
 		mx28_add_flexcan(1, &mx28evk_flexcan_pdata[1]);
 	}
 
-	ret = gpio_request_one(MX28EVK_LCD_ENABLE, GPIOF_DIR_OUT, "lcd-enable");
+	ret = gpio_request_array(mx28evk_lcd_gpios,
+				 ARRAY_SIZE(mx28evk_lcd_gpios));
 	if (ret)
-		pr_warn("failed to request gpio lcd-enable: %d\n", ret);
+		pr_warn("failed to request gpio pins for lcd: %d\n", ret);
 	else
-		gpio_set_value(MX28EVK_LCD_ENABLE, 1);
+		mx28_add_mxsfb(&mx28evk_mxsfb_pdata);
 
-	ret = gpio_request_one(MX28EVK_BL_ENABLE, GPIOF_DIR_OUT, "bl-enable");
-	if (ret)
-		pr_warn("failed to request gpio bl-enable: %d\n", ret);
-	else
-		gpio_set_value(MX28EVK_BL_ENABLE, 1);
+	mx28_add_saif(0);
+	mx28_add_saif(1);
+
+	mx28_add_mxs_i2c(0);
+	i2c_register_board_info(0, mxs_i2c0_board_info,
+				ARRAY_SIZE(mxs_i2c0_board_info));
 
-	mx28_add_mxsfb(&mx28evk_mxsfb_pdata);
+	mx28evk_add_regulators();
+
+	mxs_add_platform_device("mxs-sgtl5000", 0, NULL, 0,
+			NULL, 0);
 
 	/* power on mmc slot by writing 0 to the gpio */
 	ret = gpio_request_one(MX28EVK_MMC0_SLOT_POWER, GPIOF_OUT_INIT_LOW,
@@ -403,7 +477,11 @@ static void __init mx28evk_init(void)
 			       "mmc1-slot-power");
 	if (ret)
 		pr_warn("failed to request gpio mmc1-slot-power: %d\n", ret);
+	else
+		mx28_add_mxs_mmc(1, &mx28evk_mmc_pdata[1]);
+
 	mx28_add_mxs_mmc(1, &mx28evk_mmc_pdata[1]);
+	mx28_add_rtc_stmp3xxx();
 
 	gpio_led_register_device(0, &mx28evk_led_data);
 }
@@ -421,6 +499,6 @@ MACHINE_START(MX28EVK, "Freescale MX28 EVK")
 	/* Maintainer: Freescale Semiconductor, Inc. */
 	.map_io		= mx28_map_io,
 	.init_irq	= mx28_init_irq,
-	.init_machine	= mx28evk_init,
 	.timer		= &mx28evk_timer,
+	.init_machine	= mx28evk_init,
 MACHINE_END
diff --git a/arch/arm/mach-mxs/mach-stmp378x_devb.c b/arch/arm/mach-mxs/mach-stmp378x_devb.c
index 7f38d82..177e531 100644
--- a/arch/arm/mach-mxs/mach-stmp378x_devb.c
+++ b/arch/arm/mach-mxs/mach-stmp378x_devb.c
@@ -19,7 +19,6 @@
 
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
-#include <linux/irq.h>
 #include <linux/spi/spi.h>
 
 #include <asm/mach-types.h>
@@ -91,6 +90,7 @@ static void __init stmp378x_dvb_init(void)
 
 	mx23_add_duart();
 	mx23_add_auart0();
+	mx23_add_rtc_stmp3xxx();
 
 	/* power on mmc slot */
 	ret = gpio_request_one(STMP378X_DEVB_MMC0_SLOT_POWER,
diff --git a/arch/arm/mach-mxs/mach-tx28.c b/arch/arm/mach-mxs/mach-tx28.c
index 515a423..9a1f0e7 100644
--- a/arch/arm/mach-mxs/mach-tx28.c
+++ b/arch/arm/mach-mxs/mach-tx28.c
@@ -161,6 +161,7 @@ static void __init tx28_stk5v3_init(void)
 	i2c_register_board_info(0, tx28_stk5v3_i2c_boardinfo,
 			ARRAY_SIZE(tx28_stk5v3_i2c_boardinfo));
 	mx28_add_mxs_mmc(0, &tx28_mmc0_pdata);
+	mx28_add_rtc_stmp3xxx();
 }
 
 static void __init tx28_timer_init(void)
@@ -175,6 +176,6 @@ static struct sys_timer tx28_timer = {
 MACHINE_START(TX28, "Ka-Ro electronics TX28 module")
 	.map_io = mx28_map_io,
 	.init_irq = mx28_init_irq,
-	.init_machine = tx28_stk5v3_init,
 	.timer = &tx28_timer,
+	.init_machine = tx28_stk5v3_init,
 MACHINE_END
diff --git a/arch/arm/mach-mxs/mm-mx23.c b/arch/arm/mach-mxs/mm-mx23.c
deleted file mode 100644
index 1b2345a..0000000
--- a/arch/arm/mach-mxs/mm-mx23.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License.  You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- *
- * Create static mapping between physical to virtual memory.
- */
-
-#include <linux/mm.h>
-#include <linux/init.h>
-
-#include <asm/mach/map.h>
-
-#include <mach/mx23.h>
-#include <mach/common.h>
-#include <mach/iomux.h>
-
-/*
- * Define the MX23 memory map.
- */
-static struct map_desc mx23_io_desc[] __initdata = {
-	mxs_map_entry(MX23, OCRAM, MT_DEVICE),
-	mxs_map_entry(MX23, IO, MT_DEVICE),
-};
-
-/*
- * This function initializes the memory map. It is called during the
- * system startup to create static physical to virtual memory mappings
- * for the IO modules.
- */
-void __init mx23_map_io(void)
-{
-	iotable_init(mx23_io_desc, ARRAY_SIZE(mx23_io_desc));
-}
-
-void __init mx23_init_irq(void)
-{
-	icoll_init_irq();
-}
diff --git a/arch/arm/mach-mxs/mm-mx28.c b/arch/arm/mach-mxs/mm-mx28.c
deleted file mode 100644
index b6e18dd..0000000
--- a/arch/arm/mach-mxs/mm-mx28.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License.  You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- *
- * Create static mapping between physical to virtual memory.
- */
-
-#include <linux/mm.h>
-#include <linux/init.h>
-
-#include <asm/mach/map.h>
-
-#include <mach/mx28.h>
-#include <mach/common.h>
-#include <mach/iomux.h>
-
-/*
- * Define the MX28 memory map.
- */
-static struct map_desc mx28_io_desc[] __initdata = {
-	mxs_map_entry(MX28, OCRAM, MT_DEVICE),
-	mxs_map_entry(MX28, IO, MT_DEVICE),
-};
-
-/*
- * This function initializes the memory map. It is called during the
- * system startup to create static physical to virtual memory mappings
- * for the IO modules.
- */
-void __init mx28_map_io(void)
-{
-	iotable_init(mx28_io_desc, ARRAY_SIZE(mx28_io_desc));
-}
-
-void __init mx28_init_irq(void)
-{
-	icoll_init_irq();
-}
diff --git a/arch/arm/mach-mxs/mm.c b/arch/arm/mach-mxs/mm.c
new file mode 100644
index 0000000..50af5ce
--- /dev/null
+++ b/arch/arm/mach-mxs/mm.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License.  You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * Create static mapping between physical to virtual memory.
+ */
+
+#include <linux/mm.h>
+#include <linux/init.h>
+
+#include <asm/mach/map.h>
+
+#include <mach/mx23.h>
+#include <mach/mx28.h>
+#include <mach/common.h>
+#include <mach/iomux.h>
+
+/*
+ * Define the MX23 memory map.
+ */
+static struct map_desc mx23_io_desc[] __initdata = {
+	mxs_map_entry(MX23, OCRAM, MT_DEVICE),
+	mxs_map_entry(MX23, IO, MT_DEVICE),
+};
+
+/*
+ * Define the MX28 memory map.
+ */
+static struct map_desc mx28_io_desc[] __initdata = {
+	mxs_map_entry(MX28, OCRAM, MT_DEVICE),
+	mxs_map_entry(MX28, IO, MT_DEVICE),
+};
+
+/*
+ * This function initializes the memory map. It is called during the
+ * system startup to create static physical to virtual memory mappings
+ * for the IO modules.
+ */
+void __init mx23_map_io(void)
+{
+	iotable_init(mx23_io_desc, ARRAY_SIZE(mx23_io_desc));
+}
+
+void __init mx23_init_irq(void)
+{
+	icoll_init_irq();
+}
+
+void __init mx28_map_io(void)
+{
+	iotable_init(mx28_io_desc, ARRAY_SIZE(mx28_io_desc));
+}
+
+void __init mx28_init_irq(void)
+{
+	icoll_init_irq();
+}
diff --git a/arch/arm/mach-nuc93x/Kconfig b/arch/arm/mach-nuc93x/Kconfig
deleted file mode 100644
index 2bc40a2..0000000
--- a/arch/arm/mach-nuc93x/Kconfig
+++ /dev/null
@@ -1,19 +0,0 @@
-if ARCH_NUC93X
-
-config CPU_NUC932
-	bool
-	help
-	  Support for NUC932 of Nuvoton NUC93X CPUs.
-
-menu "NUC932 Machines"
-
-config MACH_NUC932EVB
-	bool "Nuvoton NUC932 Evaluation Board"
-	default y
-	select CPU_NUC932
-	help
-	   Say Y here if you are using the Nuvoton NUC932EVB
-
-endmenu
-
-endif
diff --git a/arch/arm/mach-nuc93x/Makefile b/arch/arm/mach-nuc93x/Makefile
deleted file mode 100644
index 440e2de..0000000
--- a/arch/arm/mach-nuc93x/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-# Object file lists.
-
-obj-y				:= irq.o time.o dev.o cpu.o clock.o
-# NUC932 CPU support files
-
-obj-$(CONFIG_CPU_NUC932)	+= nuc932.o
-
-# machine support
-
-obj-$(CONFIG_MACH_NUC932EVB)	+= mach-nuc932evb.o
diff --git a/arch/arm/mach-nuc93x/Makefile.boot b/arch/arm/mach-nuc93x/Makefile.boot
deleted file mode 100644
index 6c3d421..0000000
--- a/arch/arm/mach-nuc93x/Makefile.boot
+++ /dev/null
@@ -1,3 +0,0 @@
-zreladdr-y	+= 0x00008000
-params_phys-y	:= 0x00000100
-
diff --git a/arch/arm/mach-nuc93x/clock.c b/arch/arm/mach-nuc93x/clock.c
deleted file mode 100644
index 0521efb..0000000
--- a/arch/arm/mach-nuc93x/clock.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * linux/arch/arm/mach-nuc93x/clock.c
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/string.h>
-#include <linux/clk.h>
-#include <linux/spinlock.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-
-#include "clock.h"
-
-static DEFINE_SPINLOCK(clocks_lock);
-
-int clk_enable(struct clk *clk)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&clocks_lock, flags);
-	if (clk->enabled++ == 0)
-		(clk->enable)(clk, 1);
-	spin_unlock_irqrestore(&clocks_lock, flags);
-
-	return 0;
-}
-EXPORT_SYMBOL(clk_enable);
-
-void clk_disable(struct clk *clk)
-{
-	unsigned long flags;
-
-	WARN_ON(clk->enabled == 0);
-
-	spin_lock_irqsave(&clocks_lock, flags);
-	if (--clk->enabled == 0)
-		(clk->enable)(clk, 0);
-	spin_unlock_irqrestore(&clocks_lock, flags);
-}
-EXPORT_SYMBOL(clk_disable);
-
-unsigned long clk_get_rate(struct clk *clk)
-{
-	return 27000000;
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-void nuc93x_clk_enable(struct clk *clk, int enable)
-{
-	unsigned int clocks = clk->cken;
-	unsigned long clken;
-
-	clken = __raw_readl(NUC93X_VA_CLKPWR);
-
-	if (enable)
-		clken |= clocks;
-	else
-		clken &= ~clocks;
-
-	__raw_writel(clken, NUC93X_VA_CLKPWR);
-}
-
-void clks_register(struct clk_lookup *clks, size_t num)
-{
-	int i;
-
-	for (i = 0; i < num; i++)
-		clkdev_add(&clks[i]);
-}
diff --git a/arch/arm/mach-nuc93x/clock.h b/arch/arm/mach-nuc93x/clock.h
deleted file mode 100644
index 4de1f1d..0000000
--- a/arch/arm/mach-nuc93x/clock.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * linux/arch/arm/mach-nuc93x/clock.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License.
- */
-
-#include <linux/clkdev.h>
-
-void nuc93x_clk_enable(struct clk *clk, int enable);
-void clks_register(struct clk_lookup *clks, size_t num);
-
-struct clk {
-	unsigned long		cken;
-	unsigned int		enabled;
-	void			(*enable)(struct clk *, int enable);
-};
-
-#define DEFINE_CLK(_name, _ctrlbit)			\
-struct clk clk_##_name = {				\
-		.enable	= nuc93x_clk_enable,		\
-		.cken	= (1 << _ctrlbit),		\
-	}
-
-#define DEF_CLKLOOK(_clk, _devname, _conname)		\
-	{						\
-		.clk		= _clk,			\
-		.dev_id		= _devname,		\
-		.con_id		= _conname,		\
-	}
-
diff --git a/arch/arm/mach-nuc93x/cpu.c b/arch/arm/mach-nuc93x/cpu.c
deleted file mode 100644
index f6ff5d8..0000000
--- a/arch/arm/mach-nuc93x/cpu.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * linux/arch/arm/mach-nuc93x/cpu.c
- *
- * Copyright (c) 2009 Nuvoton corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * NUC93x series cpu common support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation;version 2 of the License.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/serial_8250.h>
-#include <linux/delay.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-#include <asm/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/regs-serial.h>
-#include <mach/regs-clock.h>
-#include <mach/regs-ebi.h>
-
-#include "cpu.h"
-#include "clock.h"
-
-/* Initial IO mappings */
-
-static struct map_desc nuc93x_iodesc[] __initdata = {
-	IODESC_ENT(IRQ),
-	IODESC_ENT(GCR),
-	IODESC_ENT(UART),
-	IODESC_ENT(TIMER),
-	IODESC_ENT(EBI),
-};
-
-/* Initial nuc932 clock declarations. */
-static DEFINE_CLK(audio, 2);
-static DEFINE_CLK(sd, 3);
-static DEFINE_CLK(jpg, 4);
-static DEFINE_CLK(video, 5);
-static DEFINE_CLK(vpost, 6);
-static DEFINE_CLK(2d, 7);
-static DEFINE_CLK(gpu, 8);
-static DEFINE_CLK(gdma, 9);
-static DEFINE_CLK(adc, 10);
-static DEFINE_CLK(uart, 11);
-static DEFINE_CLK(spi, 12);
-static DEFINE_CLK(pwm, 13);
-static DEFINE_CLK(timer, 14);
-static DEFINE_CLK(wdt, 15);
-static DEFINE_CLK(ac97, 16);
-static DEFINE_CLK(i2s, 16);
-static DEFINE_CLK(usbck, 17);
-static DEFINE_CLK(usb48, 18);
-static DEFINE_CLK(usbh, 19);
-static DEFINE_CLK(i2c, 20);
-static DEFINE_CLK(ext, 0);
-
-static struct clk_lookup nuc932_clkregs[] = {
-       DEF_CLKLOOK(&clk_audio, "nuc932-audio", NULL),
-       DEF_CLKLOOK(&clk_sd, "nuc932-sd", NULL),
-       DEF_CLKLOOK(&clk_jpg, "nuc932-jpg", "NULL"),
-       DEF_CLKLOOK(&clk_video, "nuc932-video", "NULL"),
-       DEF_CLKLOOK(&clk_vpost, "nuc932-vpost", NULL),
-       DEF_CLKLOOK(&clk_2d, "nuc932-2d", NULL),
-       DEF_CLKLOOK(&clk_gpu, "nuc932-gpu", NULL),
-       DEF_CLKLOOK(&clk_gdma, "nuc932-gdma", "NULL"),
-       DEF_CLKLOOK(&clk_adc, "nuc932-adc", NULL),
-       DEF_CLKLOOK(&clk_uart, NULL, "uart"),
-       DEF_CLKLOOK(&clk_spi, "nuc932-spi", NULL),
-       DEF_CLKLOOK(&clk_pwm, "nuc932-pwm", NULL),
-       DEF_CLKLOOK(&clk_timer, NULL, "timer"),
-       DEF_CLKLOOK(&clk_wdt, "nuc932-wdt", NULL),
-       DEF_CLKLOOK(&clk_ac97, "nuc932-ac97", NULL),
-       DEF_CLKLOOK(&clk_i2s, "nuc932-i2s", NULL),
-       DEF_CLKLOOK(&clk_usbck, "nuc932-usbck", NULL),
-       DEF_CLKLOOK(&clk_usb48, "nuc932-usb48", NULL),
-       DEF_CLKLOOK(&clk_usbh, "nuc932-usbh", NULL),
-       DEF_CLKLOOK(&clk_i2c, "nuc932-i2c", NULL),
-       DEF_CLKLOOK(&clk_ext, NULL, "ext"),
-};
-
-/* Initial serial platform data */
-
-struct plat_serial8250_port nuc93x_uart_data[] = {
-	NUC93X_8250PORT(UART0),
-	{},
-};
-
-struct platform_device nuc93x_serial_device = {
-	.name			= "serial8250",
-	.id			= PLAT8250_DEV_PLATFORM,
-	.dev			= {
-		.platform_data	= nuc93x_uart_data,
-	},
-};
-
-/*Init NUC93x evb io*/
-
-void __init nuc93x_map_io(struct map_desc *mach_desc, int mach_size)
-{
-	unsigned long idcode = 0x0;
-
-	iotable_init(mach_desc, mach_size);
-	iotable_init(nuc93x_iodesc, ARRAY_SIZE(nuc93x_iodesc));
-
-	idcode = __raw_readl(NUC93XPDID);
-	if (idcode == NUC932_CPUID)
-		printk(KERN_INFO "CPU type 0x%08lx is NUC910\n", idcode);
-	else
-		printk(KERN_ERR "CPU type detect error!\n");
-
-}
-
-/*Init NUC93x clock*/
-
-void __init nuc93x_init_clocks(void)
-{
-	clks_register(nuc932_clkregs, ARRAY_SIZE(nuc932_clkregs));
-}
-
diff --git a/arch/arm/mach-nuc93x/cpu.h b/arch/arm/mach-nuc93x/cpu.h
deleted file mode 100644
index 9def28197..0000000
--- a/arch/arm/mach-nuc93x/cpu.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/cpu.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Header file for NUC93X CPU support
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#define IODESC_ENT(y)					\
-{							\
-	.virtual = (unsigned long)NUC93X_VA_##y,	\
-	.pfn     = __phys_to_pfn(NUC93X_PA_##y),	\
-	.length  = NUC93X_SZ_##y,			\
-	.type    = MT_DEVICE,				\
-}
-
-#define NUC93X_8250PORT(name)					\
-{								\
-	.membase	= name##_BA,				\
-	.mapbase	= name##_PA,				\
-	.irq		= IRQ_##name,				\
-	.uartclk	= 57139200,				\
-	.regshift	= 2,					\
-	.iotype		= UPIO_MEM,				\
-	.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,	\
-}
-
-/*Cpu identifier register*/
-
-#define NUC93XPDID	NUC93X_VA_GCR
-#define NUC932_CPUID	0x29550091
-
-/* extern file from cpu.c */
-
-extern void nuc93x_clock_source(struct device *dev, unsigned char *src);
-extern void nuc93x_init_clocks(void);
-extern void nuc93x_map_io(struct map_desc *mach_desc, int mach_size);
-extern void nuc93x_board_init(struct platform_device **device, int size);
-extern struct platform_device nuc93x_serial_device;
-
diff --git a/arch/arm/mach-nuc93x/dev.c b/arch/arm/mach-nuc93x/dev.c
deleted file mode 100644
index a962ae9..0000000
--- a/arch/arm/mach-nuc93x/dev.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * linux/arch/arm/mach-nuc93x/dev.c
- *
- * Copyright (C) 2009 Nuvoton corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation;version 2 of the License.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-#include <asm/mach-types.h>
-
-#include "cpu.h"
-
-/*Here should be your evb resourse,such as LCD*/
-
-static struct platform_device *nuc93x_public_dev[] __initdata = {
-	&nuc93x_serial_device,
-};
-
-/* Provide adding specific CPU platform devices API */
-
-void __init nuc93x_board_init(struct platform_device **device, int size)
-{
-	platform_add_devices(device, size);
-	platform_add_devices(nuc93x_public_dev, ARRAY_SIZE(nuc93x_public_dev));
-}
-
diff --git a/arch/arm/mach-nuc93x/include/mach/entry-macro.S b/arch/arm/mach-nuc93x/include/mach/entry-macro.S
deleted file mode 100644
index 1352cbd..0000000
--- a/arch/arm/mach-nuc93x/include/mach/entry-macro.S
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/entry-macro.S
- *
- * This file is licensed under  the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- *
- */
-
-#include <mach/hardware.h>
-#include <mach/regs-irq.h>
-
-	.macro  get_irqnr_preamble, base, tmp
-	.endm
-
-	.macro  arch_ret_to_user, tmp1, tmp2
-	.endm
-
-	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
-
-		mov	\base, #AIC_BA
-
-		ldr	\irqnr, [ \base, #AIC_IPER]
-		ldr	\irqnr, [ \base, #AIC_ISNR]
-		cmp	\irqnr, #0
-
-	.endm
-
-	/* currently don't need an disable_fiq macro */
-
-	.macro	disable_fiq
-	.endm
diff --git a/arch/arm/mach-nuc93x/include/mach/hardware.h b/arch/arm/mach-nuc93x/include/mach/hardware.h
deleted file mode 100644
index fb5c6fc..0000000
--- a/arch/arm/mach-nuc93x/include/mach/hardware.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/hardware.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-#include <asm/sizes.h>
-#include <mach/map.h>
-
-#endif /* __ASM_ARCH_HARDWARE_H */
diff --git a/arch/arm/mach-nuc93x/include/mach/io.h b/arch/arm/mach-nuc93x/include/mach/io.h
deleted file mode 100644
index 72e5051..0000000
--- a/arch/arm/mach-nuc93x/include/mach/io.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/io.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT	0xffffffff
-
-/*
- * 1:1 mapping for ioremapped regions.
- */
-
-#define __mem_pci(a)	(a)
-#define __io(a)		__typesafe_io(a)
-
-#endif
diff --git a/arch/arm/mach-nuc93x/include/mach/irqs.h b/arch/arm/mach-nuc93x/include/mach/irqs.h
deleted file mode 100644
index 7c4aa71..0000000
--- a/arch/arm/mach-nuc93x/include/mach/irqs.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/irqs.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation;version 2 of the License.
- *
- */
-
-#ifndef __ASM_ARCH_IRQS_H
-#define __ASM_ARCH_IRQS_H
-
-#define NUC93X_IRQ(x)	(x)
-
-/* Main cpu interrupts */
-
-#define IRQ_WDT		NUC93X_IRQ(1)
-#define IRQ_IRQ0	NUC93X_IRQ(2)
-#define IRQ_IRQ1	NUC93X_IRQ(3)
-#define IRQ_IRQ2	NUC93X_IRQ(4)
-#define IRQ_IRQ3	NUC93X_IRQ(5)
-#define IRQ_USBH	NUC93X_IRQ(6)
-#define IRQ_APU		NUC93X_IRQ(7)
-#define IRQ_VPOST	NUC93X_IRQ(8)
-#define IRQ_ADC		NUC93X_IRQ(9)
-#define IRQ_UART0	NUC93X_IRQ(10)
-#define IRQ_TIMER0	NUC93X_IRQ(11)
-#define IRQ_GPU0	NUC93X_IRQ(12)
-#define IRQ_GPU1	NUC93X_IRQ(13)
-#define IRQ_GPU2	NUC93X_IRQ(14)
-#define IRQ_GPU3	NUC93X_IRQ(15)
-#define IRQ_GPU4	NUC93X_IRQ(16)
-#define IRQ_VIN		NUC93X_IRQ(17)
-#define IRQ_USBD	NUC93X_IRQ(18)
-#define IRQ_VRAMLD	NUC93X_IRQ(19)
-#define IRQ_GDMA0	NUC93X_IRQ(20)
-#define IRQ_GDMA1	NUC93X_IRQ(21)
-#define IRQ_SDIO	NUC93X_IRQ(22)
-#define IRQ_FMI		NUC93X_IRQ(22)
-#define IRQ_JPEG	NUC93X_IRQ(23)
-#define IRQ_SPI0	NUC93X_IRQ(24)
-#define IRQ_SPI1	NUC93X_IRQ(25)
-#define IRQ_RTC		NUC93X_IRQ(26)
-#define IRQ_PWM0	NUC93X_IRQ(27)
-#define IRQ_PWM1	NUC93X_IRQ(28)
-#define IRQ_PWM2	NUC93X_IRQ(29)
-#define IRQ_PWM3	NUC93X_IRQ(30)
-#define IRQ_I2SAC97	NUC93X_IRQ(31)
-#define IRQ_CAP0	IRQ_PWM0
-#define IRQ_CAP1	IRQ_PWM1
-#define IRQ_CAP2	IRQ_PWM2
-#define IRQ_CAP3	IRQ_PWM3
-#define NR_IRQS		(IRQ_I2SAC97 + 1)
-
-#endif /* __ASM_ARCH_IRQ_H */
diff --git a/arch/arm/mach-nuc93x/include/mach/map.h b/arch/arm/mach-nuc93x/include/mach/map.h
deleted file mode 100644
index fd0b5e8..0000000
--- a/arch/arm/mach-nuc93x/include/mach/map.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/map.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation;version 2 of the License.
- *
- */
-
-#ifndef __ASM_ARCH_MAP_H
-#define __ASM_ARCH_MAP_H
-
-#define MAP_OFFSET	(0xfff00000)
-#define CLK_OFFSET	(0x10)
-
-#ifndef __ASSEMBLY__
-#define NUC93X_ADDR(x)	((void __iomem *)(0xF0000000 + ((x)&(~MAP_OFFSET))))
-#else
-#define NUC93X_ADDR(x)	(0xF0000000 + ((x)&(~MAP_OFFSET)))
-#endif
-
- /*
-  * nuc932 hardware register definition
-  */
-
-#define NUC93X_PA_IRQ		(0xFFF83000)
-#define NUC93X_PA_GCR		(0xFFF00000)
-#define NUC93X_PA_EBI		(0xFFF01000)
-#define NUC93X_PA_UART		(0xFFF80000)
-#define NUC93X_PA_TIMER		(0xFFF81000)
-#define NUC93X_PA_GPIO		(0xFFF84000)
-#define NUC93X_PA_GDMA		(0xFFF03000)
-#define NUC93X_PA_USBHOST	(0xFFF0d000)
-#define NUC93X_PA_I2C		(0xFFF89000)
-#define NUC93X_PA_LCD		(0xFFF06000)
-#define NUC93X_PA_GE		(0xFFF05000)
-#define NUC93X_PA_ADC		(0xFFF85000)
-#define NUC93X_PA_RTC		(0xFFF87000)
-#define NUC93X_PA_PWM		(0xFFF82000)
-#define NUC93X_PA_ACTL		(0xFFF0a000)
-#define NUC93X_PA_USBDEV	(0xFFF0C000)
-#define NUC93X_PA_JEPEG		(0xFFF0e000)
-#define NUC93X_PA_CACHE_T	(0xFFF60000)
-#define NUC93X_PA_VRAM		(0xFFF0b000)
-#define NUC93X_PA_DMAC		(0xFFF09000)
-#define NUC93X_PA_I2SM		(0xFFF08000)
-#define NUC93X_PA_CACHE		(0xFFF02000)
-#define NUC93X_PA_GPU		(0xFFF04000)
-#define NUC93X_PA_VIDEOIN	(0xFFF07000)
-#define NUC93X_PA_SPI0		(0xFFF86000)
-#define NUC93X_PA_SPI1		(0xFFF88000)
-
- /*
-  * nuc932 virtual address mapping.
-  * interrupt controller is the first thing we put in, to make
-  * the assembly code for the irq detection easier
-  */
-
-#define NUC93X_VA_IRQ		NUC93X_ADDR(0x00000000)
-#define NUC93X_SZ_IRQ		SZ_4K
-
-#define NUC93X_VA_GCR		NUC93X_ADDR(NUC93X_PA_IRQ)
-#define NUC93X_VA_CLKPWR	(NUC93X_VA_GCR+CLK_OFFSET)
-#define NUC93X_SZ_GCR		SZ_4K
-
-/* EBI management */
-
-#define NUC93X_VA_EBI		NUC93X_ADDR(NUC93X_PA_EBI)
-#define NUC93X_SZ_EBI		SZ_4K
-
-/* UARTs */
-
-#define NUC93X_VA_UART		NUC93X_ADDR(NUC93X_PA_UART)
-#define NUC93X_SZ_UART		SZ_4K
-
-/* Timers */
-
-#define NUC93X_VA_TIMER	NUC93X_ADDR(NUC93X_PA_TIMER)
-#define NUC93X_SZ_TIMER	SZ_4K
-
-/* GPIO ports */
-
-#define NUC93X_VA_GPIO		NUC93X_ADDR(NUC93X_PA_GPIO)
-#define NUC93X_SZ_GPIO		SZ_4K
-
-/* GDMA control */
-
-#define NUC93X_VA_GDMA		NUC93X_ADDR(NUC93X_PA_GDMA)
-#define NUC93X_SZ_GDMA		SZ_4K
-
-/* I2C hardware controller */
-
-#define NUC93X_VA_I2C		NUC93X_ADDR(NUC93X_PA_I2C)
-#define NUC93X_SZ_I2C		SZ_4K
-
-/* LCD controller*/
-
-#define NUC93X_VA_LCD		NUC93X_ADDR(NUC93X_PA_LCD)
-#define NUC93X_SZ_LCD		SZ_4K
-
-/* 2D controller*/
-
-#define NUC93X_VA_GE		NUC93X_ADDR(NUC93X_PA_GE)
-#define NUC93X_SZ_GE		SZ_4K
-
-/* ADC */
-
-#define NUC93X_VA_ADC		NUC93X_ADDR(NUC93X_PA_ADC)
-#define NUC93X_SZ_ADC		SZ_4K
-
-/* RTC */
-
-#define NUC93X_VA_RTC		NUC93X_ADDR(NUC93X_PA_RTC)
-#define NUC93X_SZ_RTC		SZ_4K
-
-/* Pulse Width Modulation(PWM) Registers */
-
-#define NUC93X_VA_PWM		NUC93X_ADDR(NUC93X_PA_PWM)
-#define NUC93X_SZ_PWM		SZ_4K
-
-/* Audio Controller controller */
-
-#define NUC93X_VA_ACTL		NUC93X_ADDR(NUC93X_PA_ACTL)
-#define NUC93X_SZ_ACTL		SZ_4K
-
-/* USB Device port */
-
-#define NUC93X_VA_USBDEV	NUC93X_ADDR(NUC93X_PA_USBDEV)
-#define NUC93X_SZ_USBDEV	SZ_4K
-
-/* USB host controller*/
-#define NUC93X_VA_USBHOST	NUC93X_ADDR(NUC93X_PA_USBHOST)
-#define NUC93X_SZ_USBHOST	SZ_4K
-
-#endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-nuc93x/include/mach/regs-clock.h b/arch/arm/mach-nuc93x/include/mach/regs-clock.h
deleted file mode 100644
index 5cb2954..0000000
--- a/arch/arm/mach-nuc93x/include/mach/regs-clock.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/regs-clock.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation;version 2 of the License.
- *
- */
-
-#ifndef __ASM_ARCH_REGS_CLOCK_H
-#define __ASM_ARCH_REGS_CLOCK_H
-
-/* Clock Control Registers  */
-#define CLK_BA		NUC93X_VA_CLKPWR
-#define REG_CLKEN	(CLK_BA + 0x00)
-#define REG_CLKSEL	(CLK_BA + 0x04)
-#define REG_CLKDIV	(CLK_BA + 0x08)
-#define REG_PLLCON0	(CLK_BA + 0x0C)
-#define REG_PLLCON1	(CLK_BA + 0x10)
-#define REG_PMCON	(CLK_BA + 0x14)
-#define REG_IRQWAKECON	(CLK_BA + 0x18)
-#define REG_IRQWAKEFLAG	(CLK_BA + 0x1C)
-#define REG_IPSRST	(CLK_BA + 0x20)
-#define REG_CLKEN1	(CLK_BA + 0x24)
-#define REG_CLKDIV1	(CLK_BA + 0x28)
-
-/* Define PLL freq setting */
-#define PLL_DISABLE		0x12B63
-#define	PLL_66MHZ		0x2B63
-#define	PLL_100MHZ		0x4F64
-#define PLL_120MHZ		0x4F63
-#define	PLL_166MHZ		0x4124
-#define	PLL_200MHZ		0x4F24
-
-/* Define AHB:CPUFREQ ratio */
-#define	AHB_CPUCLK_1_1		0x00
-#define	AHB_CPUCLK_1_2		0x01
-#define	AHB_CPUCLK_1_4		0x02
-#define	AHB_CPUCLK_1_8		0x03
-
-/* Define APB:AHB ratio */
-#define APB_AHB_1_2		0x01
-#define APB_AHB_1_4		0x02
-#define APB_AHB_1_8		0x03
-
-/* Define clock skew */
-#define DEFAULTSKEW		0x48
-
-#endif /*  __ASM_ARCH_REGS_CLOCK_H */
diff --git a/arch/arm/mach-nuc93x/include/mach/regs-ebi.h b/arch/arm/mach-nuc93x/include/mach/regs-ebi.h
deleted file mode 100644
index 3c72550..0000000
--- a/arch/arm/mach-nuc93x/include/mach/regs-ebi.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/regs-ebi.h
- *
- * Copyright (c) 2009 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation;version 2 of the License.
- *
- */
-
-#ifndef __ASM_ARCH_REGS_EBI_H
-#define __ASM_ARCH_REGS_EBI_H
-
-/* EBI Control Registers */
-
-#define EBI_BA		NUC93X_VA_EBI
-#define REG_EBICON	(EBI_BA + 0x00)
-#define REG_ROMCON	(EBI_BA + 0x04)
-#define REG_SDCONF0	(EBI_BA + 0x08)
-#define REG_SDCONF1	(EBI_BA + 0x0C)
-#define REG_SDTIME0	(EBI_BA + 0x10)
-#define REG_SDTIME1	(EBI_BA + 0x14)
-#define REG_EXT0CON	(EBI_BA + 0x18)
-#define REG_EXT1CON	(EBI_BA + 0x1C)
-#define REG_EXT2CON	(EBI_BA + 0x20)
-#define REG_EXT3CON	(EBI_BA + 0x24)
-#define REG_EXT4CON	(EBI_BA + 0x28)
-#define REG_CKSKEW	(EBI_BA + 0x2C)
-
-#endif /*  __ASM_ARCH_REGS_EBI_H */
diff --git a/arch/arm/mach-nuc93x/include/mach/regs-irq.h b/arch/arm/mach-nuc93x/include/mach/regs-irq.h
deleted file mode 100644
index 2302159..0000000
--- a/arch/arm/mach-nuc93x/include/mach/regs-irq.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/regs-irq.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef ___ASM_ARCH_REGS_IRQ_H
-#define ___ASM_ARCH_REGS_IRQ_H
-
-/* Advance Interrupt Controller (AIC) Registers */
-
-#define AIC_BA    		NUC93X_VA_IRQ
-
-#define REG_AIC_IRQSC		(AIC_BA+0x80)
-#define REG_AIC_GEN		(AIC_BA+0x84)
-#define REG_AIC_GASR		(AIC_BA+0x88)
-#define REG_AIC_GSCR		(AIC_BA+0x8C)
-#define REG_AIC_IRSR		(AIC_BA+0x100)
-#define REG_AIC_IASR		(AIC_BA+0x104)
-#define REG_AIC_ISR		(AIC_BA+0x108)
-#define REG_AIC_IPER		(AIC_BA+0x10C)
-#define REG_AIC_ISNR		(AIC_BA+0x110)
-#define REG_AIC_IMR		(AIC_BA+0x114)
-#define REG_AIC_OISR		(AIC_BA+0x118)
-#define REG_AIC_MECR		(AIC_BA+0x120)
-#define REG_AIC_MDCR		(AIC_BA+0x124)
-#define REG_AIC_SSCR		(AIC_BA+0x128)
-#define REG_AIC_SCCR		(AIC_BA+0x12C)
-#define REG_AIC_EOSCR		(AIC_BA+0x130)
-#define AIC_IPER		(0x10C)
-#define AIC_ISNR		(0x110)
-
-#endif /* ___ASM_ARCH_REGS_IRQ_H */
diff --git a/arch/arm/mach-nuc93x/include/mach/regs-serial.h b/arch/arm/mach-nuc93x/include/mach/regs-serial.h
deleted file mode 100644
index 767a047..0000000
--- a/arch/arm/mach-nuc93x/include/mach/regs-serial.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/regs-serial.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef __ASM_ARM_REGS_SERIAL_H
-#define __ASM_ARM_REGS_SERIAL_H
-
-#define UART0_BA	NUC93X_VA_UART
-#define UART1_BA	(NUC93X_VA_UART+0x100)
-
-#define UART0_PA	NUC93X_PA_UART
-#define UART1_PA	(NUC93X_PA_UART+0x100)
-
-
-#ifndef __ASSEMBLY__
-
-struct nuc93x_uart_clksrc {
-	const char	*name;
-	unsigned int	divisor;
-	unsigned int	min_baud;
-	unsigned int	max_baud;
-};
-
-struct nuc93x_uartcfg {
-	unsigned char	hwport;
-	unsigned char	unused;
-	unsigned short	flags;
-	unsigned long	uart_flags;
-
-	unsigned long	ucon;
-	unsigned long	ulcon;
-	unsigned long	ufcon;
-
-	struct nuc93x_uart_clksrc *clocks;
-	unsigned int	clocks_size;
-};
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* __ASM_ARM_REGS_SERIAL_H */
-
diff --git a/arch/arm/mach-nuc93x/include/mach/regs-timer.h b/arch/arm/mach-nuc93x/include/mach/regs-timer.h
deleted file mode 100644
index 394be96..0000000
--- a/arch/arm/mach-nuc93x/include/mach/regs-timer.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/regs-timer.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef __ASM_ARCH_REGS_TIMER_H
-#define __ASM_ARCH_REGS_TIMER_H
-
-/* Timer Registers */
-
-#define TMR_BA			NUC93X_VA_TIMER
-#define REG_TCSR0		(TMR_BA+0x00)
-#define REG_TICR0		(TMR_BA+0x08)
-#define REG_TDR0		(TMR_BA+0x10)
-#define REG_TISR		(TMR_BA+0x18)
-#define REG_WTCR		(TMR_BA+0x1C)
-
-#endif /*  __ASM_ARCH_REGS_TIMER_H */
diff --git a/arch/arm/mach-nuc93x/include/mach/system.h b/arch/arm/mach-nuc93x/include/mach/system.h
deleted file mode 100644
index d26bd9a..0000000
--- a/arch/arm/mach-nuc93x/include/mach/system.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * arch/arm/machnuc93x/include/mach/system.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * Based on arch/arm/mach-s3c2410/include/mach/system.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#include <asm/proc-fns.h>
-
-static void arch_idle(void)
-{
-}
-
-static void arch_reset(char mode, const char *cmd)
-{
-	cpu_reset(0);
-}
-
diff --git a/arch/arm/mach-nuc93x/include/mach/timex.h b/arch/arm/mach-nuc93x/include/mach/timex.h
deleted file mode 100644
index 0c719cc..0000000
--- a/arch/arm/mach-nuc93x/include/mach/timex.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/timex.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * Based on arch/arm/mach-s3c2410/include/mach/timex.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef __ASM_ARCH_TIMEX_H
-#define __ASM_ARCH_TIMEX_H
-
-/* CLOCK_TICK_RATE Now, I don't use it. */
-
-#define CLOCK_TICK_RATE 27000000
-
-#endif /* __ASM_ARCH_TIMEX_H */
diff --git a/arch/arm/mach-nuc93x/include/mach/uncompress.h b/arch/arm/mach-nuc93x/include/mach/uncompress.h
deleted file mode 100644
index 381cb9b..0000000
--- a/arch/arm/mach-nuc93x/include/mach/uncompress.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/uncompress.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * Based on arch/arm/mach-s3c2410/include/mach/uncompress.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef __ASM_ARCH_UNCOMPRESS_H
-#define __ASM_ARCH_UNCOMPRESS_H
-
-/* Defines for UART registers */
-
-#include <mach/regs-serial.h>
-#include <mach/map.h>
-#include <linux/serial_reg.h>
-
-#define arch_decomp_wdog()
-
-#define TX_DONE	(UART_LSR_TEMT | UART_LSR_THRE)
-static u32 * const uart_base = (u32 *)UART0_PA;
-
-static void putc(int ch)
-{
-	/* Check THRE and TEMT bits before we transmit the character.
-	 */
-	while ((uart_base[UART_LSR] & TX_DONE) != TX_DONE)
-		barrier();
-
-	*uart_base = ch;
-}
-
-static inline void flush(void)
-{
-}
-
-static void arch_decomp_setup(void)
-{
-}
-
-#endif/* __ASM_NUC93X_UNCOMPRESS_H */
diff --git a/arch/arm/mach-nuc93x/include/mach/vmalloc.h b/arch/arm/mach-nuc93x/include/mach/vmalloc.h
deleted file mode 100644
index 7d11a5f..0000000
--- a/arch/arm/mach-nuc93x/include/mach/vmalloc.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/include/mach/vmalloc.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * Based on arch/arm/mach-s3c2410/include/mach/vmalloc.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef __ASM_ARCH_VMALLOC_H
-#define __ASM_ARCH_VMALLOC_H
-
-#define VMALLOC_END	  0xE0000000UL
-
-#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-nuc93x/irq.c b/arch/arm/mach-nuc93x/irq.c
deleted file mode 100644
index aa279f2..0000000
--- a/arch/arm/mach-nuc93x/irq.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * linux/arch/arm/mach-nuc93x/irq.c
- *
- * Copyright (c) 2008 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation;version 2 of the License.
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/ptrace.h>
-#include <linux/sysdev.h>
-#include <linux/io.h>
-
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/regs-irq.h>
-
-static void nuc93x_irq_mask(struct irq_data *d)
-{
-	__raw_writel(1 << d->irq, REG_AIC_MDCR);
-}
-
-/*
- * By the w90p910 spec,any irq,only write 1
- * to REG_AIC_EOSCR for ACK
- */
-
-static void nuc93x_irq_ack(struct irq_data *d)
-{
-	__raw_writel(0x01, REG_AIC_EOSCR);
-}
-
-static void nuc93x_irq_unmask(struct irq_data *d)
-{
-	__raw_writel(1 << d->irq, REG_AIC_MECR);
-
-}
-
-static struct irq_chip nuc93x_irq_chip = {
-	.irq_ack	= nuc93x_irq_ack,
-	.irq_mask	= nuc93x_irq_mask,
-	.irq_unmask	= nuc93x_irq_unmask,
-};
-
-void __init nuc93x_init_irq(void)
-{
-	int irqno;
-
-	__raw_writel(0xFFFFFFFE, REG_AIC_MDCR);
-
-	for (irqno = IRQ_WDT; irqno <= NR_IRQS; irqno++) {
-		irq_set_chip_and_handler(irqno, &nuc93x_irq_chip,
-					 handle_level_irq);
-		set_irq_flags(irqno, IRQF_VALID);
-	}
-}
diff --git a/arch/arm/mach-nuc93x/mach-nuc932evb.c b/arch/arm/mach-nuc93x/mach-nuc932evb.c
deleted file mode 100644
index 1f741b1..0000000
--- a/arch/arm/mach-nuc93x/mach-nuc932evb.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * linux/arch/arm/mach-w90x900/mach-nuc910evb.c
- *
- * Based on mach-s3c2410/mach-smdk2410.c by Jonas Dietsche
- *
- * Copyright (C) 2008 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation;version 2 of the License.
- *
- */
-
-#include <linux/platform_device.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach-types.h>
-#include <mach/map.h>
-
-#include "nuc932.h"
-
-static void __init nuc932evb_map_io(void)
-{
-	nuc932_map_io();
-	nuc932_init_clocks();
-	nuc932_init_uartclk();
-}
-
-static void __init nuc932evb_init(void)
-{
-	nuc932_board_init();
-}
-
-MACHINE_START(NUC932EVB, "NUC932EVB")
-	/* Maintainer: Wan ZongShun */
-	.map_io		= nuc932evb_map_io,
-	.init_irq	= nuc93x_init_irq,
-	.init_machine	= nuc932evb_init,
-	.timer		= &nuc93x_timer,
-MACHINE_END
diff --git a/arch/arm/mach-nuc93x/nuc932.c b/arch/arm/mach-nuc93x/nuc932.c
deleted file mode 100644
index 3966ead..0000000
--- a/arch/arm/mach-nuc93x/nuc932.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * linux/arch/arm/mach-nuc93x/nuc932.c
- *
- * Copyright (c) 2009 Nuvoton corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * NUC932 cpu support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation;version 2 of the License.
- *
- */
-
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-
-#include <asm/mach/map.h>
-#include <mach/hardware.h>
-
-#include "cpu.h"
-#include "clock.h"
-
-/* define specific CPU platform device */
-
-static struct platform_device *nuc932_dev[] __initdata = {
-};
-
-/* define specific CPU platform io map */
-
-static struct map_desc nuc932evb_iodesc[] __initdata = {
-};
-
-/*Init NUC932 evb io*/
-
-void __init nuc932_map_io(void)
-{
-	nuc93x_map_io(nuc932evb_iodesc, ARRAY_SIZE(nuc932evb_iodesc));
-}
-
-/*Init NUC932 clock*/
-
-void __init nuc932_init_clocks(void)
-{
-	nuc93x_init_clocks();
-}
-
-/*enable NUC932 uart clock*/
-
-void __init nuc932_init_uartclk(void)
-{
-	struct clk *ck_uart = clk_get(NULL, "uart");
-	BUG_ON(IS_ERR(ck_uart));
-
-	clk_enable(ck_uart);
-}
-
-/*Init NUC932 board info*/
-
-void __init nuc932_board_init(void)
-{
-	nuc93x_board_init(nuc932_dev, ARRAY_SIZE(nuc932_dev));
-}
diff --git a/arch/arm/mach-nuc93x/nuc932.h b/arch/arm/mach-nuc93x/nuc932.h
deleted file mode 100644
index 9a66edd..0000000
--- a/arch/arm/mach-nuc93x/nuc932.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * arch/arm/mach-nuc93x/nuc932.h
- *
- * Copyright (c) 2008 Nuvoton corporation
- *
- * Header file for NUC93x CPU support
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-struct map_desc;
-struct sys_timer;
-
-/* core initialisation functions */
-
-extern void nuc93x_init_irq(void);
-extern struct sys_timer nuc93x_timer;
-
-/* extern file from nuc932.c */
-
-extern void nuc932_board_init(void);
-extern void nuc932_init_clocks(void);
-extern void nuc932_map_io(void);
-extern void nuc932_init_uartclk(void);
diff --git a/arch/arm/mach-nuc93x/time.c b/arch/arm/mach-nuc93x/time.c
deleted file mode 100644
index f9807c0..0000000
--- a/arch/arm/mach-nuc93x/time.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * linux/arch/arm/mach-nuc93x/time.c
- *
- * Copyright (c) 2009 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/leds.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/time.h>
-
-#include <mach/system.h>
-#include <mach/map.h>
-#include <mach/regs-timer.h>
-
-#define RESETINT	0x01
-#define PERIOD		(0x01 << 27)
-#define ONESHOT		(0x00 << 27)
-#define COUNTEN		(0x01 << 30)
-#define INTEN		(0x01 << 29)
-
-#define TICKS_PER_SEC	100
-#define PRESCALE	0x63 /* Divider = prescale + 1 */
-
-unsigned int timer0_load;
-
-static unsigned long nuc93x_gettimeoffset(void)
-{
-	return 0;
-}
-
-/*IRQ handler for the timer*/
-
-static irqreturn_t nuc93x_timer_interrupt(int irq, void *dev_id)
-{
-	timer_tick();
-	__raw_writel(0x01, REG_TISR); /* clear TIF0 */
-	return IRQ_HANDLED;
-}
-
-static struct irqaction nuc93x_timer_irq = {
-	.name		= "nuc93x Timer Tick",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= nuc93x_timer_interrupt,
-};
-
-/*Set up timer reg.*/
-
-static void nuc93x_timer_setup(void)
-{
-	struct clk *ck_ext = clk_get(NULL, "ext");
-	struct clk *ck_timer = clk_get(NULL, "timer");
-	unsigned int rate, val = 0;
-
-	BUG_ON(IS_ERR(ck_ext) || IS_ERR(ck_timer));
-
-	clk_enable(ck_timer);
-	rate = clk_get_rate(ck_ext);
-	clk_put(ck_ext);
-	rate = rate / (PRESCALE + 0x01);
-
-	 /* set a known state */
-	__raw_writel(0x00, REG_TCSR0);
-	__raw_writel(RESETINT, REG_TISR);
-
-	timer0_load = (rate / TICKS_PER_SEC);
-	__raw_writel(timer0_load, REG_TICR0);
-
-	val |= (PERIOD | COUNTEN | INTEN | PRESCALE);
-	__raw_writel(val, REG_TCSR0);
-
-}
-
-static void __init nuc93x_timer_init(void)
-{
-	nuc93x_timer_setup();
-	setup_irq(IRQ_TIMER0, &nuc93x_timer_irq);
-}
-
-struct sys_timer nuc93x_timer = {
-	.init		= nuc93x_timer_init,
-	.offset		= nuc93x_gettimeoffset,
-	.resume		= nuc93x_timer_setup
-};
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
index 5b114d1..11c85cd 100644
--- a/arch/arm/mach-omap1/Makefile
+++ b/arch/arm/mach-omap1/Makefile
@@ -4,7 +4,7 @@
 
 # Common support
 obj-y := io.o id.o sram.o time.o irq.o mux.o flash.o serial.o devices.o dma.o
-obj-y += clock.o clock_data.o opp_data.o reset.o pm_bus.o
+obj-y += clock.o clock_data.o opp_data.o reset.o pm_bus.o timer.o
 
 obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
 
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index 4ea60e2..1f1db76 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -134,12 +134,6 @@ void ams_delta_latch2_write(u16 mask, u16 value)
 	*(volatile __u16 *) AMS_DELTA_LATCH2_VIRT = ams_delta_latch2_reg;
 }
 
-static void __init ams_delta_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 static struct map_desc ams_delta_io_desc[] __initdata = {
 	/* AMS_DELTA_LATCH1 */
 	{
@@ -378,17 +372,13 @@ static int __init ams_delta_modem_init(void)
 }
 arch_initcall(ams_delta_modem_init);
 
-static void __init ams_delta_map_io(void)
-{
-	omap1_map_common_io();
-}
-
 MACHINE_START(AMS_DELTA, "Amstrad E3 (Delta)")
 	/* Maintainer: Jonathan McDowell <noodles@earth.li> */
 	.atag_offset	= 0x100,
-	.map_io		= ams_delta_map_io,
+	.map_io		= omap15xx_map_io,
+	.init_early	= omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= ams_delta_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= ams_delta_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c
index 31e089b..2317827 100644
--- a/arch/arm/mach-omap1/board-fsample.c
+++ b/arch/arm/mach-omap1/board-fsample.c
@@ -296,6 +296,39 @@ static struct omap_board_config_kernel fsample_config[] __initdata = {
 
 static void __init omap_fsample_init(void)
 {
+	/* Early, board-dependent init */
+
+	/*
+	 * Hold GSM Reset until needed
+	 */
+	omap_writew(omap_readw(OMAP7XX_DSP_M_CTL) & ~1, OMAP7XX_DSP_M_CTL);
+
+	/*
+	 * UARTs -> done automagically by 8250 driver
+	 */
+
+	/*
+	 * CSx timings, GPIO Mux ... setup
+	 */
+
+	/* Flash: CS0 timings setup */
+	omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_0);
+	omap_writel(0x00000088, OMAP7XX_FLASH_ACFG_0);
+
+	/*
+	 * Ethernet support through the debug board
+	 * CS1 timings setup
+	 */
+	omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_1);
+	omap_writel(0x00000000, OMAP7XX_FLASH_ACFG_1);
+
+	/*
+	 * Configure MPU_EXT_NIRQ IO in IO_CONF9 register,
+	 * It is used as the Ethernet controller interrupt
+	 */
+	omap_writel(omap_readl(OMAP7XX_IO_CONF_9) & 0x1FFFFFFF,
+			OMAP7XX_IO_CONF_9);
+
 	fsample_init_smc91x();
 
 	if (gpio_request(FSAMPLE_NAND_RB_GPIO_PIN, "NAND ready") < 0)
@@ -325,12 +358,6 @@ static void __init omap_fsample_init(void)
 	omap_register_i2c_bus(1, 100, NULL, 0);
 }
 
-static void __init omap_fsample_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 /* Only FPGA needs to be mapped here. All others are done with ioremap */
 static struct map_desc omap_fsample_io_desc[] __initdata = {
 	{
@@ -349,49 +376,18 @@ static struct map_desc omap_fsample_io_desc[] __initdata = {
 
 static void __init omap_fsample_map_io(void)
 {
-	omap1_map_common_io();
+	omap15xx_map_io();
 	iotable_init(omap_fsample_io_desc,
 		     ARRAY_SIZE(omap_fsample_io_desc));
-
-	/* Early, board-dependent init */
-
-	/*
-	 * Hold GSM Reset until needed
-	 */
-	omap_writew(omap_readw(OMAP7XX_DSP_M_CTL) & ~1, OMAP7XX_DSP_M_CTL);
-
-	/*
-	 * UARTs -> done automagically by 8250 driver
-	 */
-
-	/*
-	 * CSx timings, GPIO Mux ... setup
-	 */
-
-	/* Flash: CS0 timings setup */
-	omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_0);
-	omap_writel(0x00000088, OMAP7XX_FLASH_ACFG_0);
-
-	/*
-	 * Ethernet support through the debug board
-	 * CS1 timings setup
-	 */
-	omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_1);
-	omap_writel(0x00000000, OMAP7XX_FLASH_ACFG_1);
-
-	/*
-	 * Configure MPU_EXT_NIRQ IO in IO_CONF9 register,
-	 * It is used as the Ethernet controller interrupt
-	 */
-	omap_writel(omap_readl(OMAP7XX_IO_CONF_9) & 0x1FFFFFFF, OMAP7XX_IO_CONF_9);
 }
 
 MACHINE_START(OMAP_FSAMPLE, "OMAP730 F-Sample")
 /* Maintainer: Brian Swetland <swetland@google.com> */
 	.atag_offset	= 0x100,
 	.map_io		= omap_fsample_map_io,
+	.init_early	= omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_fsample_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_fsample_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c
index 05c6e9d..dc5b75d 100644
--- a/arch/arm/mach-omap1/board-generic.c
+++ b/arch/arm/mach-omap1/board-generic.c
@@ -27,12 +27,6 @@
 #include <plat/board.h>
 #include <plat/common.h>
 
-static void __init omap_generic_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 /* assume no Mini-AB port */
 
 #ifdef CONFIG_ARCH_OMAP15XX
@@ -86,17 +80,13 @@ static void __init omap_generic_init(void)
 	omap_register_i2c_bus(1, 100, NULL, 0);
 }
 
-static void __init omap_generic_map_io(void)
-{
-	omap1_map_common_io();
-}
-
 MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710")
 	/* Maintainer: Tony Lindgren <tony@atomide.com> */
 	.atag_offset	= 0x100,
-	.map_io		= omap_generic_map_io,
+	.map_io		= omap16xx_map_io,
+	.init_early	= omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_generic_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_generic_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
index c2e2791..b334b14 100644
--- a/arch/arm/mach-omap1/board-h2.c
+++ b/arch/arm/mach-omap1/board-h2.c
@@ -372,12 +372,6 @@ static struct i2c_board_info __initdata h2_i2c_board_info[] = {
 	},
 };
 
-static void __init h2_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 static struct omap_usb_config h2_usb_config __initdata = {
 	/* usb1 has a Mini-AB port and external isp1301 transceiver */
 	.otg		= 2,
@@ -453,17 +447,13 @@ static void __init h2_init(void)
 	h2_mmc_init();
 }
 
-static void __init h2_map_io(void)
-{
-	omap1_map_common_io();
-}
-
 MACHINE_START(OMAP_H2, "TI-H2")
 	/* Maintainer: Imre Deak <imre.deak@nokia.com> */
 	.atag_offset	= 0x100,
-	.map_io		= h2_map_io,
+	.map_io		= omap16xx_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= h2_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= h2_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index 8f5b6af..74ebe72 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -435,23 +435,13 @@ static void __init h3_init(void)
 	h3_mmc_init();
 }
 
-static void __init h3_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
-static void __init h3_map_io(void)
-{
-	omap1_map_common_io();
-}
-
 MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board")
 	/* Maintainer: Texas Instruments, Inc. */
 	.atag_offset	= 0x100,
-	.map_io		= h3_map_io,
+	.map_io		= omap16xx_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= h3_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= h3_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-htcherald.c b/arch/arm/mach-omap1/board-htcherald.c
index fcd1a3c..3e91baa 100644
--- a/arch/arm/mach-omap1/board-htcherald.c
+++ b/arch/arm/mach-omap1/board-htcherald.c
@@ -499,7 +499,7 @@ static void __init htcherald_lcd_init(void)
 
 static void __init htcherald_map_io(void)
 {
-	omap1_map_common_io();
+	omap7xx_map_io();
 
 	/*
 	 * The LCD panel must be disabled and DMA turned off here, as doing
@@ -600,20 +600,14 @@ static void __init htcherald_init(void)
 #endif
 }
 
-static void __init htcherald_init_irq(void)
-{
-	printk(KERN_INFO "htcherald_init_irq.\n");
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 MACHINE_START(HERALD, "HTC Herald")
 	/* Maintainer: Cory Maccarrone <darkstar6262@gmail.com> */
 	/* Maintainer: wing-linux.sourceforge.net */
 	.atag_offset    = 0x100,
 	.map_io         = htcherald_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq       = htcherald_init_irq,
+	.init_irq       = omap1_init_irq,
 	.init_machine   = htcherald_init,
 	.timer          = &omap1_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
index c2234ca..273153d 100644
--- a/arch/arm/mach-omap1/board-innovator.c
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -288,12 +288,6 @@ static void __init innovator_init_smc91x(void)
 	}
 }
 
-static void __init innovator_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 #ifdef CONFIG_ARCH_OMAP15XX
 static struct omap_usb_config innovator1510_usb_config __initdata = {
 	/* for bundled non-standard host and peripheral cables */
@@ -438,30 +432,32 @@ static void __init innovator_init(void)
 	innovator_mmc_init();
 }
 
+/*
+ * REVISIT: Assume 15xx for now, we don't want to do revision check
+ * until later on. The right way to fix this is to set up a different
+ * machine_id for 16xx Innovator, or use device tree.
+ */
 static void __init innovator_map_io(void)
 {
-	omap1_map_common_io();
+	omap15xx_map_io();
 
-#ifdef CONFIG_ARCH_OMAP15XX
-	if (cpu_is_omap1510()) {
-		iotable_init(innovator1510_io_desc, ARRAY_SIZE(innovator1510_io_desc));
-		udelay(10);	/* Delay needed for FPGA */
-
-		/* Dump the Innovator FPGA rev early - useful info for support. */
-		printk("Innovator FPGA Rev %d.%d Board Rev %d\n",
-		       fpga_read(OMAP1510_FPGA_REV_HIGH),
-		       fpga_read(OMAP1510_FPGA_REV_LOW),
-		       fpga_read(OMAP1510_FPGA_BOARD_REV));
-	}
-#endif
+	iotable_init(innovator1510_io_desc, ARRAY_SIZE(innovator1510_io_desc));
+	udelay(10);	/* Delay needed for FPGA */
+
+	/* Dump the Innovator FPGA rev early - useful info for support. */
+	pr_debug("Innovator FPGA Rev %d.%d Board Rev %d\n",
+			fpga_read(OMAP1510_FPGA_REV_HIGH),
+			fpga_read(OMAP1510_FPGA_REV_LOW),
+			fpga_read(OMAP1510_FPGA_BOARD_REV));
 }
 
 MACHINE_START(OMAP_INNOVATOR, "TI-Innovator")
 	/* Maintainer: MontaVista Software, Inc. */
 	.atag_offset	= 0x100,
 	.map_io		= innovator_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= innovator_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= innovator_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
index 02789c5..6798b84 100644
--- a/arch/arm/mach-omap1/board-nokia770.c
+++ b/arch/arm/mach-omap1/board-nokia770.c
@@ -38,21 +38,6 @@
 
 #define ADS7846_PENDOWN_GPIO	15
 
-static void __init omap_nokia770_init_irq(void)
-{
-	/* On Nokia 770, the SleepX signal is masked with an
-	 * MPUIO line by default.  It has to be unmasked for it
-	 * to become functional */
-
-	/* SleepX mask direction */
-	omap_writew((omap_readw(0xfffb5008) & ~2), 0xfffb5008);
-	/* Unmask SleepX signal */
-	omap_writew((omap_readw(0xfffb5004) & ~2), 0xfffb5004);
-
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 static const unsigned int nokia770_keymap[] = {
 	KEY(1, 0, GROUP_0 | KEY_UP),
 	KEY(2, 0, GROUP_1 | KEY_F5),
@@ -245,6 +230,15 @@ static inline void nokia770_mmc_init(void)
 
 static void __init omap_nokia770_init(void)
 {
+	/* On Nokia 770, the SleepX signal is masked with an
+	 * MPUIO line by default.  It has to be unmasked for it
+	 * to become functional */
+
+	/* SleepX mask direction */
+	omap_writew((omap_readw(0xfffb5008) & ~2), 0xfffb5008);
+	/* Unmask SleepX signal */
+	omap_writew((omap_readw(0xfffb5004) & ~2), 0xfffb5004);
+
 	platform_add_devices(nokia770_devices, ARRAY_SIZE(nokia770_devices));
 	spi_register_board_info(nokia770_spi_board_info,
 				ARRAY_SIZE(nokia770_spi_board_info));
@@ -257,16 +251,12 @@ static void __init omap_nokia770_init(void)
 	nokia770_mmc_init();
 }
 
-static void __init omap_nokia770_map_io(void)
-{
-	omap1_map_common_io();
-}
-
 MACHINE_START(NOKIA770, "Nokia 770")
 	.atag_offset	= 0x100,
-	.map_io		= omap_nokia770_map_io,
+	.map_io		= omap16xx_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_nokia770_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_nokia770_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index e4dca1d..c385927 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -278,12 +278,6 @@ static void __init osk_init_cf(void)
 	irq_set_irq_type(gpio_to_irq(62), IRQ_TYPE_EDGE_FALLING);
 }
 
-static void __init osk_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 static struct omap_usb_config osk_usb_config __initdata = {
 	/* has usb host connector (A) ... for development it can also
 	 * be used, with a NONSTANDARD gender-bending cable/dongle, as
@@ -575,17 +569,13 @@ static void __init osk_init(void)
 	osk_mistral_init();
 }
 
-static void __init osk_map_io(void)
-{
-	omap1_map_common_io();
-}
-
 MACHINE_START(OMAP_OSK, "TI-OSK")
 	/* Maintainer: Dirk Behme <dirk.behme@de.bosch.com> */
 	.atag_offset	= 0x100,
-	.map_io		= osk_map_io,
+	.map_io		= omap16xx_map_io,
+	.init_early	= omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= osk_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= osk_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c
index 50c4e39..f9c44cb 100644
--- a/arch/arm/mach-omap1/board-palmte.c
+++ b/arch/arm/mach-omap1/board-palmte.c
@@ -58,12 +58,6 @@
 #define PALMTE_MMC2_GPIO	OMAP_MPUIO(7)
 #define PALMTE_MMC3_GPIO	OMAP_MPUIO(11)
 
-static void __init omap_palmte_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 static const unsigned int palmte_keymap[] = {
 	KEY(0, 0, KEY_F1),		/* Calendar */
 	KEY(1, 0, KEY_F2),		/* Contacts */
@@ -268,16 +262,12 @@ static void __init omap_palmte_init(void)
 	omap_register_i2c_bus(1, 100, NULL, 0);
 }
 
-static void __init omap_palmte_map_io(void)
-{
-	omap1_map_common_io();
-}
-
 MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E")
 	.atag_offset	= 0x100,
-	.map_io		= omap_palmte_map_io,
+	.map_io		= omap15xx_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_palmte_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_palmte_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-palmtt.c b/arch/arm/mach-omap1/board-palmtt.c
index 273771c..11a9853 100644
--- a/arch/arm/mach-omap1/board-palmtt.c
+++ b/arch/arm/mach-omap1/board-palmtt.c
@@ -263,12 +263,6 @@ static struct spi_board_info __initdata palmtt_boardinfo[] = {
 	}
 };
 
-static void __init omap_palmtt_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 static struct omap_usb_config palmtt_usb_config __initdata = {
 	.register_dev	= 1,
 	.hmc_mode	= 0,
@@ -315,16 +309,12 @@ static void __init omap_palmtt_init(void)
 	omap_register_i2c_bus(1, 100, NULL, 0);
 }
 
-static void __init omap_palmtt_map_io(void)
-{
-	omap1_map_common_io();
-}
-
 MACHINE_START(OMAP_PALMTT, "OMAP1510 based Palm Tungsten|T")
 	.atag_offset	= 0x100,
-	.map_io		= omap_palmtt_map_io,
+	.map_io		= omap15xx_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_palmtt_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_palmtt_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-palmz71.c b/arch/arm/mach-omap1/board-palmz71.c
index de36ade..c6fe61d 100644
--- a/arch/arm/mach-omap1/board-palmz71.c
+++ b/arch/arm/mach-omap1/board-palmz71.c
@@ -57,13 +57,6 @@
 #define PALMZ71_SLIDER_GPIO	OMAP_MPUIO(3)
 #define PALMZ71_MMC_IN_GPIO	OMAP_MPUIO(4)
 
-static void __init
-omap_palmz71_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
 static const unsigned int palmz71_keymap[] = {
 	KEY(0, 0, KEY_F1),
 	KEY(1, 0, KEY_F2),
@@ -334,17 +327,12 @@ omap_palmz71_init(void)
 	palmz71_gpio_setup(0);
 }
 
-static void __init
-omap_palmz71_map_io(void)
-{
-	omap1_map_common_io();
-}
-
 MACHINE_START(OMAP_PALMZ71, "OMAP310 based Palm Zire71")
 	.atag_offset	= 0x100,
-	.map_io		= omap_palmz71_map_io,
+	.map_io		= omap15xx_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_palmz71_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_palmz71_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c
index 04b1bef..203ae07 100644
--- a/arch/arm/mach-omap1/board-perseus2.c
+++ b/arch/arm/mach-omap1/board-perseus2.c
@@ -264,6 +264,39 @@ static void __init perseus2_init_smc91x(void)
 
 static void __init omap_perseus2_init(void)
 {
+	/* Early, board-dependent init */
+
+	/*
+	 * Hold GSM Reset until needed
+	 */
+	omap_writew(omap_readw(OMAP7XX_DSP_M_CTL) & ~1, OMAP7XX_DSP_M_CTL);
+
+	/*
+	 * UARTs -> done automagically by 8250 driver
+	 */
+
+	/*
+	 * CSx timings, GPIO Mux ... setup
+	 */
+
+	/* Flash: CS0 timings setup */
+	omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_0);
+	omap_writel(0x00000088, OMAP7XX_FLASH_ACFG_0);
+
+	/*
+	 * Ethernet support through the debug board
+	 * CS1 timings setup
+	 */
+	omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_1);
+	omap_writel(0x00000000, OMAP7XX_FLASH_ACFG_1);
+
+	/*
+	 * Configure MPU_EXT_NIRQ IO in IO_CONF9 register,
+	 * It is used as the Ethernet controller interrupt
+	 */
+	omap_writel(omap_readl(OMAP7XX_IO_CONF_9) & 0x1FFFFFFF,
+				OMAP7XX_IO_CONF_9);
+
 	perseus2_init_smc91x();
 
 	if (gpio_request(P2_NAND_RB_GPIO_PIN, "NAND ready") < 0)
@@ -293,11 +326,6 @@ static void __init omap_perseus2_init(void)
 	omap_register_i2c_bus(1, 100, NULL, 0);
 }
 
-static void __init omap_perseus2_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
 /* Only FPGA needs to be mapped here. All others are done with ioremap */
 static struct map_desc omap_perseus2_io_desc[] __initdata = {
 	{
@@ -310,49 +338,18 @@ static struct map_desc omap_perseus2_io_desc[] __initdata = {
 
 static void __init omap_perseus2_map_io(void)
 {
-	omap1_map_common_io();
+	omap7xx_map_io();
 	iotable_init(omap_perseus2_io_desc,
 		     ARRAY_SIZE(omap_perseus2_io_desc));
-
-	/* Early, board-dependent init */
-
-	/*
-	 * Hold GSM Reset until needed
-	 */
-	omap_writew(omap_readw(OMAP7XX_DSP_M_CTL) & ~1, OMAP7XX_DSP_M_CTL);
-
-	/*
-	 * UARTs -> done automagically by 8250 driver
-	 */
-
-	/*
-	 * CSx timings, GPIO Mux ... setup
-	 */
-
-	/* Flash: CS0 timings setup */
-	omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_0);
-	omap_writel(0x00000088, OMAP7XX_FLASH_ACFG_0);
-
-	/*
-	 * Ethernet support through the debug board
-	 * CS1 timings setup
-	 */
-	omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_1);
-	omap_writel(0x00000000, OMAP7XX_FLASH_ACFG_1);
-
-	/*
-	 * Configure MPU_EXT_NIRQ IO in IO_CONF9 register,
-	 * It is used as the Ethernet controller interrupt
-	 */
-	omap_writel(omap_readl(OMAP7XX_IO_CONF_9) & 0x1FFFFFFF, OMAP7XX_IO_CONF_9);
 }
 
 MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2")
 	/* Maintainer: Kevin Hilman <kjh@hilman.org> */
 	.atag_offset	= 0x100,
 	.map_io		= omap_perseus2_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_perseus2_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_perseus2_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-sx1.c b/arch/arm/mach-omap1/board-sx1.c
index 2bea941..667a7cb 100644
--- a/arch/arm/mach-omap1/board-sx1.c
+++ b/arch/arm/mach-omap1/board-sx1.c
@@ -406,24 +406,13 @@ static void __init omap_sx1_init(void)
 	gpio_direction_output(11, 0);	/*A_SWITCH = 0 */
 	gpio_direction_output(15, 0);	/*A_USB_ON = 0 */
 }
-/*----------------------------------------*/
-static void __init omap_sx1_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-/*----------------------------------------*/
-
-static void __init omap_sx1_map_io(void)
-{
-	omap1_map_common_io();
-}
 
 MACHINE_START(SX1, "OMAP310 based Siemens SX1")
 	.atag_offset	= 0x100,
-	.map_io		= omap_sx1_map_io,
+	.map_io		= omap15xx_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_sx1_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_sx1_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c
index 940faed..2a6545b 100644
--- a/arch/arm/mach-omap1/board-voiceblue.c
+++ b/arch/arm/mach-omap1/board-voiceblue.c
@@ -159,17 +159,6 @@ static struct omap_usb_config voiceblue_usb_config __initdata = {
 static struct omap_board_config_kernel voiceblue_config[] = {
 };
 
-static void __init voiceblue_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap1_init_irq();
-}
-
-static void __init voiceblue_map_io(void)
-{
-	omap1_map_common_io();
-}
-
 #define MACHINE_PANICED		1
 #define MACHINE_REBOOTING	2
 #define MACHINE_REBOOT		4
@@ -302,9 +291,10 @@ static void __init voiceblue_init(void)
 MACHINE_START(VOICEBLUE, "VoiceBlue OMAP5910")
 	/* Maintainer: Ladislav Michl <michl@2n.cz> */
 	.atag_offset	= 0x100,
-	.map_io		= voiceblue_map_io,
+	.map_io		= omap15xx_map_io,
+	.init_early     = omap1_init_early,
 	.reserve	= omap_reserve,
-	.init_irq	= voiceblue_init_irq,
+	.init_irq	= omap1_init_irq,
 	.init_machine	= voiceblue_init,
 	.timer		= &omap1_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c
index 7c50ecf..48ef988 100644
--- a/arch/arm/mach-omap1/devices.c
+++ b/arch/arm/mach-omap1/devices.c
@@ -22,6 +22,7 @@
 #include <mach/hardware.h>
 #include <asm/mach/map.h>
 
+#include <plat/common.h>
 #include <plat/tc.h>
 #include <plat/board.h>
 #include <plat/mux.h>
@@ -291,6 +292,8 @@ static int __init omap1_init_devices(void)
 	if (!cpu_class_is_omap1())
 		return -ENODEV;
 
+	omap_sram_init();
+
 	/* please keep these calls, and their implementations above,
 	 * in alphabetical order so they're easier to sort through.
 	 */
diff --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c
index 1cfa1b6..7969cfd 100644
--- a/arch/arm/mach-omap1/io.c
+++ b/arch/arm/mach-omap1/io.c
@@ -21,7 +21,6 @@
 #include "clock.h"
 
 extern void omap_check_revision(void);
-extern void omap_sram_init(void);
 
 /*
  * The machine specific code may provide the extra mapping besides the
@@ -85,51 +84,45 @@ static struct map_desc omap16xx_io_desc[] __initdata = {
 #endif
 
 /*
- * Maps common IO regions for omap1. This should only get called from
- * board specific init.
+ * Maps common IO regions for omap1
  */
-void __init omap1_map_common_io(void)
+static void __init omap1_map_common_io(void)
 {
 	iotable_init(omap_io_desc, ARRAY_SIZE(omap_io_desc));
-
-	/* Normally devicemaps_init() would flush caches and tlb after
-	 * mdesc->map_io(), but we must also do it here because of the CPU
-	 * revision check below.
-	 */
-	local_flush_tlb_all();
-	flush_cache_all();
-
-	/* We want to check CPU revision early for cpu_is_omapxxxx() macros.
-	 * IO space mapping must be initialized before we can do that.
-	 */
-	omap_check_revision();
+}
 
 #if defined (CONFIG_ARCH_OMAP730) || defined (CONFIG_ARCH_OMAP850)
-	if (cpu_is_omap7xx()) {
-		iotable_init(omap7xx_io_desc, ARRAY_SIZE(omap7xx_io_desc));
-	}
+void __init omap7xx_map_io(void)
+{
+	omap1_map_common_io();
+	iotable_init(omap7xx_io_desc, ARRAY_SIZE(omap7xx_io_desc));
+}
 #endif
+
 #ifdef CONFIG_ARCH_OMAP15XX
-	if (cpu_is_omap15xx()) {
-		iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc));
-	}
-#endif
-#if defined(CONFIG_ARCH_OMAP16XX)
-	if (cpu_is_omap16xx()) {
-		iotable_init(omap16xx_io_desc, ARRAY_SIZE(omap16xx_io_desc));
-	}
+void __init omap15xx_map_io(void)
+{
+	omap1_map_common_io();
+	iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc));
+}
 #endif
 
-	omap_sram_init();
-	omap_init_consistent_dma_size();
+#if defined(CONFIG_ARCH_OMAP16XX)
+void __init omap16xx_map_io(void)
+{
+	omap1_map_common_io();
+	iotable_init(omap16xx_io_desc, ARRAY_SIZE(omap16xx_io_desc));
 }
+#endif
 
 /*
- * Common low-level hardware init for omap1. This should only get called from
- * board specific init.
+ * Common low-level hardware init for omap1.
  */
-void __init omap1_init_common_hw(void)
+void omap1_init_early(void)
 {
+	omap_check_revision();
+	omap_ioremap_init();
+
 	/* REVISIT: Refer to OMAP5910 Errata, Advisory SYS_1: "Timeout Abort
 	 * on a Posted Write in the TIPB Bridge".
 	 */
@@ -139,8 +132,8 @@ void __init omap1_init_common_hw(void)
 	/* Must init clocks early to assure that timer interrupt works
 	 */
 	omap1_clk_init();
-
 	omap1_mux_init();
+	omap_init_consistent_dma_size();
 }
 
 /*
diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c
index ab7395d..91f9abb 100644
--- a/arch/arm/mach-omap1/mcbsp.c
+++ b/arch/arm/mach-omap1/mcbsp.c
@@ -31,6 +31,7 @@
 static int dsp_use;
 static struct clk *api_clk;
 static struct clk *dsp_clk;
+static struct platform_device **omap_mcbsp_devices;
 
 static void omap1_mcbsp_request(unsigned int id)
 {
@@ -78,6 +79,17 @@ static struct omap_mcbsp_ops omap1_mcbsp_ops = {
 	.free		= omap1_mcbsp_free,
 };
 
+#define OMAP7XX_MCBSP1_BASE	0xfffb1000
+#define OMAP7XX_MCBSP2_BASE	0xfffb1800
+
+#define OMAP1510_MCBSP1_BASE	0xe1011800
+#define OMAP1510_MCBSP2_BASE	0xfffb1000
+#define OMAP1510_MCBSP3_BASE	0xe1017000
+
+#define OMAP1610_MCBSP1_BASE	0xe1011800
+#define OMAP1610_MCBSP2_BASE	0xfffb1000
+#define OMAP1610_MCBSP3_BASE	0xe1017000
+
 #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
 struct resource omap7xx_mcbsp_res[][6] = {
 	{
@@ -369,6 +381,39 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
 #define OMAP16XX_MCBSP_COUNT		0
 #endif
 
+static void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
+			struct omap_mcbsp_platform_data *config, int size)
+{
+	int i;
+
+	omap_mcbsp_devices = kzalloc(size * sizeof(struct platform_device *),
+				     GFP_KERNEL);
+	if (!omap_mcbsp_devices) {
+		printk(KERN_ERR "Could not register McBSP devices\n");
+		return;
+	}
+
+	for (i = 0; i < size; i++) {
+		struct platform_device *new_mcbsp;
+		int ret;
+
+		new_mcbsp = platform_device_alloc("omap-mcbsp", i + 1);
+		if (!new_mcbsp)
+			continue;
+		platform_device_add_resources(new_mcbsp, &res[i * res_count],
+					res_count);
+		config[i].reg_size = 2;
+		config[i].reg_step = 2;
+		new_mcbsp->dev.platform_data = &config[i];
+		ret = platform_device_add(new_mcbsp);
+		if (ret) {
+			platform_device_put(new_mcbsp);
+			continue;
+		}
+		omap_mcbsp_devices[i] = new_mcbsp;
+	}
+}
+
 static int __init omap1_mcbsp_init(void)
 {
 	if (!cpu_class_is_omap1())
diff --git a/arch/arm/mach-omap1/timer.c b/arch/arm/mach-omap1/timer.c
new file mode 100644
index 0000000..6e90665
--- /dev/null
+++ b/arch/arm/mach-omap1/timer.c
@@ -0,0 +1,173 @@
+/**
+ * OMAP1 Dual-Mode Timers - platform device registration
+ *
+ * Contains first level initialization routines which internally
+ * generates timer device information and registers with linux
+ * device model. It also has low level function to chnage the timer
+ * input clock source.
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Tarun Kanti DebBarma <tarun.kanti@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#include <mach/irqs.h>
+
+#include <plat/dmtimer.h>
+
+#define OMAP1610_GPTIMER1_BASE		0xfffb1400
+#define OMAP1610_GPTIMER2_BASE		0xfffb1c00
+#define OMAP1610_GPTIMER3_BASE		0xfffb2400
+#define OMAP1610_GPTIMER4_BASE		0xfffb2c00
+#define OMAP1610_GPTIMER5_BASE		0xfffb3400
+#define OMAP1610_GPTIMER6_BASE		0xfffb3c00
+#define OMAP1610_GPTIMER7_BASE		0xfffb7400
+#define OMAP1610_GPTIMER8_BASE		0xfffbd400
+
+#define OMAP1_DM_TIMER_COUNT		8
+
+static int omap1_dm_timer_set_src(struct platform_device *pdev,
+				int source)
+{
+	int n = (pdev->id - 1) << 1;
+	u32 l;
+
+	l = __raw_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
+	l |= source << n;
+	__raw_writel(l, MOD_CONF_CTRL_1);
+
+	return 0;
+}
+
+
+int __init omap1_dm_timer_init(void)
+{
+	int i;
+	int ret;
+	struct dmtimer_platform_data *pdata;
+	struct platform_device *pdev;
+
+	if (!cpu_is_omap16xx())
+		return 0;
+
+	for (i = 1; i <= OMAP1_DM_TIMER_COUNT; i++) {
+		struct resource res[2];
+		u32 base, irq;
+
+		switch (i) {
+		case 1:
+			base = OMAP1610_GPTIMER1_BASE;
+			irq = INT_1610_GPTIMER1;
+			break;
+		case 2:
+			base = OMAP1610_GPTIMER2_BASE;
+			irq = INT_1610_GPTIMER2;
+			break;
+		case 3:
+			base = OMAP1610_GPTIMER3_BASE;
+			irq = INT_1610_GPTIMER3;
+			break;
+		case 4:
+			base = OMAP1610_GPTIMER4_BASE;
+			irq = INT_1610_GPTIMER4;
+			break;
+		case 5:
+			base = OMAP1610_GPTIMER5_BASE;
+			irq = INT_1610_GPTIMER5;
+			break;
+		case 6:
+			base = OMAP1610_GPTIMER6_BASE;
+			irq = INT_1610_GPTIMER6;
+			break;
+		case 7:
+			base = OMAP1610_GPTIMER7_BASE;
+			irq = INT_1610_GPTIMER7;
+			break;
+		case 8:
+			base = OMAP1610_GPTIMER8_BASE;
+			irq = INT_1610_GPTIMER8;
+			break;
+		default:
+			/*
+			 * not supposed to reach here.
+			 * this is to remove warning.
+			 */
+			return -EINVAL;
+		}
+
+		pdev = platform_device_alloc("omap_timer", i);
+		if (!pdev) {
+			pr_err("%s: Failed to device alloc for dmtimer%d\n",
+				__func__, i);
+			return -ENOMEM;
+		}
+
+		memset(res, 0, 2 * sizeof(struct resource));
+		res[0].start = base;
+		res[0].end = base + 0x46;
+		res[0].flags = IORESOURCE_MEM;
+		res[1].start = irq;
+		res[1].end = irq;
+		res[1].flags = IORESOURCE_IRQ;
+		ret = platform_device_add_resources(pdev, res,
+				ARRAY_SIZE(res));
+		if (ret) {
+			dev_err(&pdev->dev, "%s: Failed to add resources.\n",
+				__func__);
+			goto err_free_pdev;
+		}
+
+		pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+		if (!pdata) {
+			dev_err(&pdev->dev, "%s: Failed to allocate pdata.\n",
+				__func__);
+			ret = -ENOMEM;
+			goto err_free_pdata;
+		}
+
+		pdata->set_timer_src = omap1_dm_timer_set_src;
+		pdata->needs_manual_reset = 1;
+
+		ret = platform_device_add_data(pdev, pdata, sizeof(*pdata));
+		if (ret) {
+			dev_err(&pdev->dev, "%s: Failed to add platform data.\n",
+				__func__);
+			goto err_free_pdata;
+		}
+
+		ret = platform_device_add(pdev);
+		if (ret) {
+			dev_err(&pdev->dev, "%s: Failed to add platform device.\n",
+				__func__);
+			goto err_free_pdata;
+		}
+
+		dev_dbg(&pdev->dev, " Registered.\n");
+	}
+
+	return 0;
+
+err_free_pdata:
+	kfree(pdata);
+
+err_free_pdev:
+	platform_device_unregister(pdev);
+
+	return ret;
+}
+arch_initcall(omap1_dm_timer_init);
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 89bfb49..497e9dc 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -108,9 +108,13 @@ comment "OMAP Board Type"
 	depends on ARCH_OMAP2PLUS
 
 config MACH_OMAP_GENERIC
-	bool "Generic OMAP board"
-	depends on ARCH_OMAP2
+	bool "Generic OMAP2+ board"
+	depends on ARCH_OMAP2PLUS
+	select USE_OF
 	default y
+	help
+	  Support for generic TI OMAP2+ boards using Flattened Device Tree.
+	  More information at Documentation/devicetree
 
 config MACH_OMAP2_TUSB6010
 	bool
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 7317a2b..69ab1c0 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -89,14 +89,13 @@ obj-$(CONFIG_ARCH_OMAP4)		+= prcm.o cm2xxx_3xxx.o cminst44xx.o \
 					   vp44xx_data.o
 
 # OMAP voltage domains
-ifeq ($(CONFIG_PM),y)
-voltagedomain-common			:= voltage.o
-obj-$(CONFIG_ARCH_OMAP2)		+= $(voltagedomain-common)
+voltagedomain-common			:= voltage.o vc.o vp.o
+obj-$(CONFIG_ARCH_OMAP2)		+= $(voltagedomain-common) \
+					   voltagedomains2xxx_data.o
 obj-$(CONFIG_ARCH_OMAP3)		+= $(voltagedomain-common) \
 					   voltagedomains3xxx_data.o
 obj-$(CONFIG_ARCH_OMAP4)		+= $(voltagedomain-common) \
 					   voltagedomains44xx_data.o
-endif
 
 # OMAP powerdomain framework
 powerdomain-common			+= powerdomain.o powerdomain-common.o
@@ -116,9 +115,12 @@ obj-$(CONFIG_ARCH_OMAP4)		+= $(powerdomain-common) \
 obj-$(CONFIG_ARCH_OMAP2)		+= clockdomain.o \
 					   clockdomain2xxx_3xxx.o \
 					   clockdomains2xxx_3xxx_data.o
+obj-$(CONFIG_SOC_OMAP2420)		+= clockdomains2420_data.o
+obj-$(CONFIG_SOC_OMAP2430)		+= clockdomains2430_data.o
 obj-$(CONFIG_ARCH_OMAP3)		+= clockdomain.o \
 					   clockdomain2xxx_3xxx.o \
-					   clockdomains2xxx_3xxx_data.o
+					   clockdomains2xxx_3xxx_data.o \
+					   clockdomains3xxx_data.o
 obj-$(CONFIG_ARCH_OMAP4)		+= clockdomain.o \
 					   clockdomain44xx.o \
 					   clockdomains44xx_data.o
@@ -185,75 +187,62 @@ endif
 # Specific board support
 obj-$(CONFIG_MACH_OMAP_GENERIC)		+= board-generic.o
 obj-$(CONFIG_MACH_OMAP_H4)		+= board-h4.o
-obj-$(CONFIG_MACH_OMAP_2430SDP)		+= board-2430sdp.o \
-					   hsmmc.o
+obj-$(CONFIG_MACH_OMAP_2430SDP)		+= board-2430sdp.o
 obj-$(CONFIG_MACH_OMAP_APOLLON)		+= board-apollon.o
-obj-$(CONFIG_MACH_OMAP3_BEAGLE)		+= board-omap3beagle.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_DEVKIT8000)     	+= board-devkit8000.o \
-                                           hsmmc.o
-obj-$(CONFIG_MACH_OMAP_LDP)		+= board-ldp.o \
-					   board-flash.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_OMAP3530_LV_SOM)      += board-omap3logic.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_OMAP3_TORPEDO)        += board-omap3logic.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_OVERO)		+= board-overo.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_OMAP3EVM)		+= board-omap3evm.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_OMAP3_PANDORA)	+= board-omap3pandora.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_OMAP_3430SDP)		+= board-3430sdp.o \
-					   hsmmc.o \
-					   board-flash.o
+obj-$(CONFIG_MACH_OMAP3_BEAGLE)		+= board-omap3beagle.o
+obj-$(CONFIG_MACH_DEVKIT8000)     	+= board-devkit8000.o
+obj-$(CONFIG_MACH_OMAP_LDP)		+= board-ldp.o
+obj-$(CONFIG_MACH_OMAP3530_LV_SOM)      += board-omap3logic.o
+obj-$(CONFIG_MACH_OMAP3_TORPEDO)        += board-omap3logic.o
+obj-$(CONFIG_MACH_ENCORE)		+= board-omap3encore.o
+obj-$(CONFIG_MACH_OVERO)		+= board-overo.o
+obj-$(CONFIG_MACH_OMAP3EVM)		+= board-omap3evm.o
+obj-$(CONFIG_MACH_OMAP3_PANDORA)	+= board-omap3pandora.o
+obj-$(CONFIG_MACH_OMAP_3430SDP)		+= board-3430sdp.o
 obj-$(CONFIG_MACH_NOKIA_N8X0)		+= board-n8x0.o
 obj-$(CONFIG_MACH_NOKIA_RM680)		+= board-rm680.o \
-					   sdram-nokia.o \
-					   hsmmc.o
+					   sdram-nokia.o
 obj-$(CONFIG_MACH_NOKIA_RX51)		+= board-rx51.o \
 					   sdram-nokia.o \
 					   board-rx51-peripherals.o \
-					   board-rx51-video.o \
-					   hsmmc.o
+					   board-rx51-video.o
 obj-$(CONFIG_MACH_OMAP_ZOOM2)		+= board-zoom.o \
 					   board-zoom-peripherals.o \
 					   board-zoom-display.o \
-					   board-flash.o \
-					   hsmmc.o \
 					   board-zoom-debugboard.o
 obj-$(CONFIG_MACH_OMAP_ZOOM3)		+= board-zoom.o \
 					   board-zoom-peripherals.o \
 					   board-zoom-display.o \
-					   board-flash.o \
-					   hsmmc.o \
 					   board-zoom-debugboard.o
 obj-$(CONFIG_MACH_OMAP_3630SDP)		+= board-3630sdp.o \
 					   board-zoom-peripherals.o \
-					   board-zoom-display.o \
-					   board-flash.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_CM_T35)		+= board-cm-t35.o \
-					   hsmmc.o
+					   board-zoom-display.o
+obj-$(CONFIG_MACH_CM_T35)		+= board-cm-t35.o
 obj-$(CONFIG_MACH_CM_T3517)		+= board-cm-t3517.o
-obj-$(CONFIG_MACH_IGEP0020)		+= board-igep0020.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_OMAP3_TOUCHBOOK)	+= board-omap3touchbook.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_OMAP_4430SDP)		+= board-4430sdp.o \
-					   hsmmc.o
-obj-$(CONFIG_MACH_OMAP4_PANDA)		+= board-omap4panda.o \
-					   hsmmc.o
+obj-$(CONFIG_MACH_IGEP0020)		+= board-igep0020.o
+obj-$(CONFIG_MACH_OMAP3_TOUCHBOOK)	+= board-omap3touchbook.o
+obj-$(CONFIG_MACH_OMAP_4430SDP)		+= board-4430sdp.o
+obj-$(CONFIG_MACH_OMAP4_PANDA)		+= board-omap4panda.o
+
+obj-$(CONFIG_MACH_PCM049)		+= board-omap4pcm049.o
 
 obj-$(CONFIG_MACH_OMAP3517EVM)		+= board-am3517evm.o
 
 obj-$(CONFIG_MACH_CRANEBOARD)		+= board-am3517crane.o
 
-obj-$(CONFIG_MACH_SBC3530)		+= board-omap3stalker.o \
-					   hsmmc.o
+obj-$(CONFIG_MACH_SBC3530)		+= board-omap3stalker.o
 obj-$(CONFIG_MACH_TI8168EVM)		+= board-ti8168evm.o
+
 # Platform specific device init code
+
+omap-flash-$(CONFIG_MTD_NAND_OMAP2)	:= board-flash.o
+omap-flash-$(CONFIG_MTD_ONENAND_OMAP2)	:= board-flash.o
+obj-y					+= $(omap-flash-y) $(omap-flash-m)
+
+omap-hsmmc-$(CONFIG_MMC_OMAP_HS)	:= hsmmc.o
+obj-y					+= $(omap-hsmmc-m) $(omap-hsmmc-y)
+
+
 usbfs-$(CONFIG_ARCH_OMAP_OTG)		:= usb-fs.o
 obj-y					+= $(usbfs-m) $(usbfs-y)
 obj-y					+= usb-musb.o
diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index f8ce84b..d704f0a 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -192,12 +192,6 @@ static inline void board_smc91x_init(void)
 
 #endif
 
-static void __init omap_2430sdp_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
-
 static struct regulator_consumer_supply sdp2430_vmmc1_supplies[] = {
 	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
 };
@@ -284,6 +278,7 @@ static void __init omap_2430sdp_init(void)
 
 	platform_add_devices(sdp2430_devices, ARRAY_SIZE(sdp2430_devices));
 	omap_serial_init();
+	omap_sdrc_init(NULL, NULL);
 	omap2_hsmmc_init(mmc);
 	omap2_usbfs_init(&sdp2430_usb_config);
 
@@ -299,18 +294,12 @@ static void __init omap_2430sdp_init(void)
 	sdp2430_display_init();
 }
 
-static void __init omap_2430sdp_map_io(void)
-{
-	omap2_set_globals_243x();
-	omap243x_map_common_io();
-}
-
 MACHINE_START(OMAP_2430SDP, "OMAP2430 sdp2430 board")
 	/* Maintainer: Syed Khasim - Texas Instruments Inc */
 	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
-	.map_io		= omap_2430sdp_map_io,
-	.init_early	= omap_2430sdp_init_early,
+	.map_io		= omap243x_map_io,
+	.init_early	= omap2430_init_early,
 	.init_irq	= omap2_init_irq,
 	.init_machine	= omap_2430sdp_init,
 	.timer		= &omap2_timer,
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index 204bedd..77142c1 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -224,12 +224,6 @@ static struct omap_dss_board_info sdp3430_dss_data = {
 static struct omap_board_config_kernel sdp3430_config[] __initdata = {
 };
 
-static void __init omap_3430sdp_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(hyb18m512160af6_sdrc_params, NULL);
-}
-
 static struct omap2_hsmmc_info mmc[] = {
 	{
 		.mmc		= 1,
@@ -718,6 +712,7 @@ static void __init omap_3430sdp_init(void)
 		gpio_pendown = SDP3430_TS_GPIO_IRQ_SDPV1;
 	omap_ads7846_init(1, gpio_pendown, 310, NULL);
 	board_serial_init();
+	omap_sdrc_init(hyb18m512160af6_sdrc_params, NULL);
 	usb_musb_init(NULL);
 	board_smc91x_init();
 	board_flash_init(sdp_flash_partitions, chip_sel_3430, 0);
@@ -731,7 +726,7 @@ MACHINE_START(OMAP_3430SDP, "OMAP3430 3430SDP board")
 	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= omap_3430sdp_init_early,
+	.init_early	= omap3430_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= omap_3430sdp_init,
 	.timer		= &omap3_timer,
diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c
index 8b5b5aa..f552305 100644
--- a/arch/arm/mach-omap2/board-3630sdp.c
+++ b/arch/arm/mach-omap2/board-3630sdp.c
@@ -70,13 +70,6 @@ static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
 static struct omap_board_config_kernel sdp_config[] __initdata = {
 };
 
-static void __init omap_sdp_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(h8mbx00u0mer0em_sdrc_params,
-				  h8mbx00u0mer0em_sdrc_params);
-}
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
@@ -207,6 +200,8 @@ static void __init omap_sdp_init(void)
 	omap_board_config = sdp_config;
 	omap_board_config_size = ARRAY_SIZE(sdp_config);
 	zoom_peripherals_init();
+	omap_sdrc_init(h8mbx00u0mer0em_sdrc_params,
+				  h8mbx00u0mer0em_sdrc_params);
 	zoom_display_init();
 	board_smc91x_init();
 	board_flash_init(sdp_flash_partitions, chip_sel_sdp, NAND_BUSWIDTH_16);
@@ -218,7 +213,7 @@ MACHINE_START(OMAP_3630SDP, "OMAP 3630SDP board")
 	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= omap_sdp_init_early,
+	.init_early	= omap3630_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= omap_sdp_init,
 	.timer		= &omap3_timer,
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 484cec5..5156468 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -133,7 +133,7 @@ static const int sdp4430_keymap[] = {
 	KEY(7, 6, KEY_OK),
 	KEY(7, 7, KEY_DOWN),
 };
-static struct omap_device_pad keypad_pads[] __initdata = {
+static struct omap_device_pad keypad_pads[] = {
 	{	.name   = "kpd_col1.kpd_col1",
 		.enable = OMAP_WAKEUP_EN | OMAP_MUX_MODE1,
 	},
@@ -379,12 +379,6 @@ static struct platform_device *sdp4430_devices[] __initdata = {
 	&sdp4430_vbat,
 };
 
-static void __init omap_4430sdp_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
-
 static struct omap_musb_board_data musb_board_data = {
 	.interface_type		= MUSB_INTERFACE_UTMI,
 	.mode			= MUSB_OTG,
@@ -961,6 +955,7 @@ static void __init omap_4430sdp_init(void)
 	omap_sfh7741prox_init();
 	platform_add_devices(sdp4430_devices, ARRAY_SIZE(sdp4430_devices));
 	board_serial_init();
+	omap_sdrc_init(NULL, NULL);
 	omap4_sdp4430_wifi_init();
 	omap4_twl6030_hsmmc_init(mmc);
 
@@ -982,18 +977,12 @@ static void __init omap_4430sdp_init(void)
 	omap_4430sdp_display_init();
 }
 
-static void __init omap_4430sdp_map_io(void)
-{
-	omap2_set_globals_443x();
-	omap44xx_map_common_io();
-}
-
 MACHINE_START(OMAP_4430SDP, "OMAP4430 4430SDP board")
 	/* Maintainer: Santosh Shilimkar - Texas Instruments Inc */
 	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
-	.map_io		= omap_4430sdp_map_io,
-	.init_early	= omap_4430sdp_init_early,
+	.map_io		= omap4_map_io,
+	.init_early	= omap4430_init_early,
 	.init_irq	= gic_init_irq,
 	.init_machine	= omap_4430sdp_init,
 	.timer		= &omap4_timer,
diff --git a/arch/arm/mach-omap2/board-am3517crane.c b/arch/arm/mach-omap2/board-am3517crane.c
index db110fd..7834536 100644
--- a/arch/arm/mach-omap2/board-am3517crane.c
+++ b/arch/arm/mach-omap2/board-am3517crane.c
@@ -47,12 +47,6 @@ static struct omap_board_mux board_mux[] __initdata = {
 };
 #endif
 
-static void __init am3517_crane_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
-
 static struct usbhs_omap_board_data usbhs_bdata __initdata = {
 	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
 	.port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
@@ -70,6 +64,7 @@ static void __init am3517_crane_init(void)
 
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap_serial_init();
+	omap_sdrc_init(NULL, NULL);
 
 	omap_board_config = am3517_crane_config;
 	omap_board_config_size = ARRAY_SIZE(am3517_crane_config);
@@ -101,7 +96,7 @@ MACHINE_START(CRANEBOARD, "AM3517/05 CRANEBOARD")
 	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= am3517_crane_init_early,
+	.init_early	= am35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= am3517_crane_init,
 	.timer		= &omap3_timer,
diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c
index ab10f75..d314f03 100644
--- a/arch/arm/mach-omap2/board-am3517evm.c
+++ b/arch/arm/mach-omap2/board-am3517evm.c
@@ -362,11 +362,6 @@ static struct omap_dss_board_info am3517_evm_dss_data = {
 /*
  * Board initialization
  */
-static void __init am3517_evm_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
 
 static struct omap_musb_board_data musb_board_data = {
 	.interface_type         = MUSB_INTERFACE_ULPI,
@@ -469,6 +464,7 @@ static void __init am3517_evm_init(void)
 	am3517_evm_i2c_init();
 	omap_display_init(&am3517_evm_dss_data);
 	omap_serial_init();
+	omap_sdrc_init(NULL, NULL);
 
 	/* Configure GPIO for EHCI port */
 	omap_mux_init_gpio(57, OMAP_PIN_OUTPUT);
@@ -493,7 +489,7 @@ MACHINE_START(OMAP3517EVM, "OMAP3517/AM3517 EVM")
 	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= am3517_evm_init_early,
+	.init_early	= am35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= am3517_evm_init,
 	.timer		= &omap3_timer,
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
index ad55351..de8134b 100644
--- a/arch/arm/mach-omap2/board-apollon.c
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -284,12 +284,6 @@ static struct omap_dss_board_info apollon_dss_data = {
 	.default_device	= &apollon_lcd_device,
 };
 
-static void __init omap_apollon_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
-
 static struct gpio apollon_gpio_leds[] __initdata = {
 	{ LED0_GPIO13, GPIOF_OUT_INIT_LOW, "LED0" }, /* LED0 - AA10 */
 	{ LED1_GPIO14, GPIOF_OUT_INIT_LOW, "LED1" }, /* LED1 - AA6  */
@@ -349,22 +343,16 @@ static void __init omap_apollon_init(void)
 	 */
 	platform_add_devices(apollon_devices, ARRAY_SIZE(apollon_devices));
 	omap_serial_init();
-
+	omap_sdrc_init(NULL, NULL);
 	omap_display_init(&apollon_dss_data);
 }
 
-static void __init omap_apollon_map_io(void)
-{
-	omap2_set_globals_242x();
-	omap242x_map_common_io();
-}
-
 MACHINE_START(OMAP_APOLLON, "OMAP24xx Apollon")
 	/* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
 	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
-	.map_io		= omap_apollon_map_io,
-	.init_early	= omap_apollon_init_early,
+	.map_io		= omap242x_map_io,
+	.init_early	= omap2420_init_early,
 	.init_irq	= omap2_init_irq,
 	.init_machine	= omap_apollon_init,
 	.timer		= &omap2_timer,
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index 6e0f0d2..bd1bcac 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -471,13 +471,6 @@ static void __init cm_t35_init_i2c(void)
 	omap3_pmic_init("tps65930", &cm_t35_twldata);
 }
 
-static void __init cm_t35_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
-			     mt46h32m32lf6_sdrc_params);
-}
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	/* nCS and IRQ for CM-T35 ethernet */
@@ -610,6 +603,8 @@ static void __init cm_t3x_common_init(void)
 	omap_board_config_size = ARRAY_SIZE(cm_t35_config);
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CUS);
 	omap_serial_init();
+	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
+			     mt46h32m32lf6_sdrc_params);
 	cm_t35_init_i2c();
 	omap_ads7846_init(1, CM_T35_GPIO_PENDOWN, 0, NULL);
 	cm_t35_init_ethernet();
@@ -637,7 +632,7 @@ MACHINE_START(CM_T35, "Compulab CM-T35")
 	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= cm_t35_init_early,
+	.init_early	= omap35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= cm_t35_init,
 	.timer		= &omap3_timer,
@@ -647,7 +642,7 @@ MACHINE_START(CM_T3730, "Compulab CM-T3730")
 	.atag_offset    = 0x100,
 	.reserve        = omap_reserve,
 	.map_io         = omap3_map_io,
-	.init_early     = cm_t35_init_early,
+	.init_early     = omap3630_init_early,
 	.init_irq       = omap3_init_irq,
 	.init_machine   = cm_t3730_init,
 	.timer          = &omap3_timer,
diff --git a/arch/arm/mach-omap2/board-cm-t3517.c b/arch/arm/mach-omap2/board-cm-t3517.c
index aed9c29..3f4dc66 100644
--- a/arch/arm/mach-omap2/board-cm-t3517.c
+++ b/arch/arm/mach-omap2/board-cm-t3517.c
@@ -251,12 +251,6 @@ static inline void cm_t3517_init_nand(void) {}
 static struct omap_board_config_kernel cm_t3517_config[] __initdata = {
 };
 
-static void __init cm_t3517_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	/* GPIO186 - Green LED */
@@ -289,6 +283,7 @@ static void __init cm_t3517_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap_serial_init();
+	omap_sdrc_init(NULL, NULL);
 	omap_board_config = cm_t3517_config;
 	omap_board_config_size = ARRAY_SIZE(cm_t3517_config);
 	cm_t3517_init_leds();
@@ -302,7 +297,7 @@ MACHINE_START(CM_T3517, "Compulab CM-T3517")
 	.atag_offset	= 0x100,
 	.reserve        = omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= cm_t3517_init_early,
+	.init_early	= am35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= cm_t3517_init,
 	.timer		= &omap3_timer,
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index d9bfe54..4291894 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -397,19 +397,6 @@ static struct platform_device keys_gpio = {
 	},
 };
 
-
-static void __init devkit8000_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
-				  mt46h32m32lf6_sdrc_params);
-}
-
-static void __init devkit8000_init_irq(void)
-{
-	omap3_init_irq();
-}
-
 #define OMAP_DM9000_BASE	0x2c000000
 
 static struct resource omap_dm9000_resources[] = {
@@ -645,6 +632,8 @@ static void __init devkit8000_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CUS);
 	omap_serial_init();
+	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
+				  mt46h32m32lf6_sdrc_params);
 
 	omap_dm9000_init();
 
@@ -670,8 +659,8 @@ MACHINE_START(DEVKIT8000, "OMAP3 Devkit8000")
 	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= devkit8000_init_early,
-	.init_irq	= devkit8000_init_irq,
+	.init_early	= omap35xx_init_early,
+	.init_irq	= omap3_init_irq,
 	.init_machine	= devkit8000_init,
 	.timer		= &omap3_secure_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index aa1b0cb..30a6f52 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -148,11 +148,6 @@ __init board_nand_init(struct mtd_partition *nand_parts,
 	board_nand_data.gpmc_irq = OMAP_GPMC_IRQ_BASE + cs;
 	gpmc_nand_init(&board_nand_data);
 }
-#else
-void
-__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs, int nand_type)
-{
-}
 #endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */
 
 /**
diff --git a/arch/arm/mach-omap2/board-flash.h b/arch/arm/mach-omap2/board-flash.h
index c240a3f..d25503a 100644
--- a/arch/arm/mach-omap2/board-flash.h
+++ b/arch/arm/mach-omap2/board-flash.h
@@ -24,7 +24,26 @@ struct flash_partitions {
 	int nr_parts;
 };
 
+#if defined(CONFIG_MTD_NAND_OMAP2) || \
+		defined(CONFIG_MTD_NAND_OMAP2_MODULE) || \
+		defined(CONFIG_MTD_ONENAND_OMAP2) || \
+		defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
 extern void board_flash_init(struct flash_partitions [],
 				char chip_sel[][GPMC_CS_NUM], int nand_type);
+#else
+static inline void board_flash_init(struct flash_partitions part[],
+				char chip_sel[][GPMC_CS_NUM], int nand_type)
+{
+}
+#endif
+
+#if defined(CONFIG_MTD_NAND_OMAP2) || \
+		defined(CONFIG_MTD_NAND_OMAP2_MODULE)
 extern void board_nand_init(struct mtd_partition *nand_parts,
 					u8 nr_parts, u8 cs, int nand_type);
+#else
+static inline void board_nand_init(struct mtd_partition *nand_parts,
+					u8 nr_parts, u8 cs, int nand_type)
+{
+}
+#endif
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index 4431ad3..0cc9094 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -1,75 +1,157 @@
 /*
- * linux/arch/arm/mach-omap2/board-generic.c
- *
  * Copyright (C) 2005 Nokia Corporation
  * Author: Paul Mundt <paul.mundt@nokia.com>
  *
- * Modified from mach-omap/omap1/board-generic.c
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
  *
- * Code for generic OMAP2 board. Should work on many OMAP2 systems where
- * the bootloader passes the board-specific data to the kernel.
- * Do not put any board specific code to this file; create a new machine
- * type if you need custom low-level initializations.
+ * Modified from the original mach-omap/omap2/board-generic.c did by Paul
+ * to support the OMAP2+ device tree boards with an unique board file.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <linux/gpio.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/of_platform.h>
+#include <linux/irqdomain.h>
+#include <linux/i2c/twl.h>
 
 #include <mach/hardware.h>
-#include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <asm/mach/map.h>
 
-#include <plat/usb.h>
 #include <plat/board.h>
 #include <plat/common.h>
+#include <mach/omap4-common.h>
+#include "common-board-devices.h"
+
+/*
+ * XXX: Still needed to boot until the i2c & twl driver is adapted to
+ * device-tree
+ */
+static struct twl4030_platform_data sdp4430_twldata = {
+	.irq_base	= TWL6030_IRQ_BASE,
+	.irq_end	= TWL6030_IRQ_END,
+};
 
-static struct omap_board_config_kernel generic_config[] = {
+static void __init omap4_i2c_init(void)
+{
+	omap4_pmic_init("twl6030", &sdp4430_twldata);
+}
+
+static struct twl4030_platform_data beagle_twldata = {
+	.irq_base	= TWL4030_IRQ_BASE,
+	.irq_end	= TWL4030_IRQ_END,
 };
 
-static void __init omap_generic_init_early(void)
+static void __init omap3_i2c_init(void)
 {
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
+	omap3_pmic_init("twl4030", &beagle_twldata);
 }
 
+static struct of_device_id omap_dt_match_table[] __initdata = {
+	{ .compatible = "simple-bus", },
+	{ .compatible = "ti,omap-infra", },
+	{ }
+};
+
+static struct of_device_id intc_match[] __initdata = {
+	{ .compatible = "ti,omap3-intc", },
+	{ .compatible = "arm,cortex-a9-gic", },
+	{ }
+};
+
 static void __init omap_generic_init(void)
 {
+	struct device_node *node = of_find_matching_node(NULL, intc_match);
+	if (node)
+		irq_domain_add_simple(node, 0);
+
 	omap_serial_init();
-	omap_board_config = generic_config;
-	omap_board_config_size = ARRAY_SIZE(generic_config);
+	omap_sdrc_init(NULL, NULL);
+
+	of_platform_populate(NULL, omap_dt_match_table, NULL, NULL);
+}
+
+static void __init omap4_init(void)
+{
+	omap4_i2c_init();
+	omap_generic_init();
 }
 
-static void __init omap_generic_map_io(void)
+static void __init omap3_init(void)
 {
-	if (cpu_is_omap242x()) {
-		omap2_set_globals_242x();
-		omap242x_map_common_io();
-	} else if (cpu_is_omap243x()) {
-		omap2_set_globals_243x();
-		omap243x_map_common_io();
-	} else if (cpu_is_omap34xx()) {
-		omap2_set_globals_3xxx();
-		omap34xx_map_common_io();
-	} else if (cpu_is_omap44xx()) {
-		omap2_set_globals_443x();
-		omap44xx_map_common_io();
-	}
+	omap3_i2c_init();
+	omap_generic_init();
 }
 
-/* XXX This machine entry name should be updated */
-MACHINE_START(OMAP_GENERIC, "Generic OMAP24xx")
-	/* Maintainer: Paul Mundt <paul.mundt@nokia.com> */
+#if defined(CONFIG_SOC_OMAP2420)
+static const char *omap242x_boards_compat[] __initdata = {
+	"ti,omap2420",
+	NULL,
+};
+
+DT_MACHINE_START(OMAP242X_DT, "Generic OMAP2420 (Flattened Device Tree)")
+	.atag_offset	= 0x100,
+	.reserve	= omap_reserve,
+	.map_io		= omap242x_map_io,
+	.init_early	= omap2420_init_early,
+	.init_irq	= omap2_init_irq,
+	.init_machine	= omap_generic_init,
+	.timer		= &omap2_timer,
+	.dt_compat	= omap242x_boards_compat,
+MACHINE_END
+#endif
+
+#if defined(CONFIG_SOC_OMAP2430)
+static const char *omap243x_boards_compat[] __initdata = {
+	"ti,omap2430",
+	NULL,
+};
+
+DT_MACHINE_START(OMAP243X_DT, "Generic OMAP2430 (Flattened Device Tree)")
 	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
-	.map_io		= omap_generic_map_io,
-	.init_early	= omap_generic_init_early,
+	.map_io		= omap243x_map_io,
+	.init_early	= omap2430_init_early,
 	.init_irq	= omap2_init_irq,
 	.init_machine	= omap_generic_init,
 	.timer		= &omap2_timer,
+	.dt_compat	= omap243x_boards_compat,
+MACHINE_END
+#endif
+
+#if defined(CONFIG_ARCH_OMAP3)
+static const char *omap3_boards_compat[] __initdata = {
+	"ti,omap3",
+	NULL,
+};
+
+DT_MACHINE_START(OMAP3_DT, "Generic OMAP3 (Flattened Device Tree)")
+	.atag_offset	= 0x100,
+	.reserve	= omap_reserve,
+	.map_io		= omap3_map_io,
+	.init_early	= omap3430_init_early,
+	.init_irq	= omap3_init_irq,
+	.init_machine	= omap3_init,
+	.timer		= &omap3_timer,
+	.dt_compat	= omap3_boards_compat,
+MACHINE_END
+#endif
+
+#if defined(CONFIG_ARCH_OMAP4)
+static const char *omap4_boards_compat[] __initdata = {
+	"ti,omap4",
+	NULL,
+};
+
+DT_MACHINE_START(OMAP4_DT, "Generic OMAP4 (Flattened Device Tree)")
+	.atag_offset	= 0x100,
+	.reserve	= omap_reserve,
+	.map_io		= omap4_map_io,
+	.init_early	= omap4430_init_early,
+	.init_irq	= gic_init_irq,
+	.init_machine	= omap4_init,
+	.timer		= &omap4_timer,
+	.dt_compat	= omap4_boards_compat,
 MACHINE_END
+#endif
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index 8fcf796..c12666e 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -300,17 +300,6 @@ static struct omap_usb_config h4_usb_config __initdata = {
 	.hmc_mode	= 0x00,		/* 0:dev|otg 1:disable 2:disable */
 };
 
-static void __init omap_h4_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
-
-static void __init omap_h4_init_irq(void)
-{
-	omap2_init_irq();
-}
-
 static struct at24_platform_data m24c01 = {
 	.byte_len	= SZ_1K / 8,
 	.page_size	= 16,
@@ -378,24 +367,19 @@ static void __init omap_h4_init(void)
 	platform_add_devices(h4_devices, ARRAY_SIZE(h4_devices));
 	omap2_usbfs_init(&h4_usb_config);
 	omap_serial_init();
+	omap_sdrc_init(NULL, NULL);
 	h4_init_flash();
 
 	omap_display_init(&h4_dss_data);
 }
 
-static void __init omap_h4_map_io(void)
-{
-	omap2_set_globals_242x();
-	omap242x_map_common_io();
-}
-
 MACHINE_START(OMAP_H4, "OMAP2420 H4 board")
 	/* Maintainer: Paul Mundt <paul.mundt@nokia.com> */
 	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
-	.map_io		= omap_h4_map_io,
-	.init_early	= omap_h4_init_early,
-	.init_irq	= omap_h4_init_irq,
+	.map_io		= omap242x_map_io,
+	.init_early	= omap2420_init_early,
+	.init_irq	= omap2_init_irq,
 	.init_machine	= omap_h4_init,
 	.timer		= &omap2_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index 96f9ef3..d0a3f78 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -491,13 +491,6 @@ static struct platform_device *igep_devices[] __initdata = {
 	&igep_vwlan_device,
 };
 
-static void __init igep_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(m65kxxxxam_sdrc_params,
-				  m65kxxxxam_sdrc_params);
-}
-
 static int igep2_keymap[] = {
 	KEY(0, 0, KEY_LEFT),
 	KEY(0, 1, KEY_RIGHT),
@@ -650,6 +643,8 @@ static void __init igep_init(void)
 	igep_i2c_init();
 	platform_add_devices(igep_devices, ARRAY_SIZE(igep_devices));
 	omap_serial_init();
+	omap_sdrc_init(m65kxxxxam_sdrc_params,
+				  m65kxxxxam_sdrc_params);
 	usb_musb_init(NULL);
 
 	igep_flash_init();
@@ -675,7 +670,7 @@ MACHINE_START(IGEP0020, "IGEP v2 board")
 	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= igep_init_early,
+	.init_early	= omap35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= igep_init,
 	.timer		= &omap3_timer,
@@ -685,7 +680,7 @@ MACHINE_START(IGEP0030, "IGEP OMAP3 module")
 	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= igep_init_early,
+	.init_early	= omap35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= igep_init,
 	.timer		= &omap3_timer,
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index f8f8a68..e179da0 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -251,12 +251,6 @@ static void __init ldp_display_init(void)
 	omap_display_init(&ldp_dss_data);
 }
 
-static void __init omap_ldp_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
-
 static int ldp_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio)
 {
 	int r;
@@ -425,6 +419,7 @@ static void __init omap_ldp_init(void)
 	platform_add_devices(ldp_devices, ARRAY_SIZE(ldp_devices));
 	omap_ads7846_init(1, 54, 310, NULL);
 	omap_serial_init();
+	omap_sdrc_init(NULL, NULL);
 	usb_musb_init(NULL);
 	board_nand_init(ldp_nand_partitions,
 		ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS, 0);
@@ -437,7 +432,7 @@ MACHINE_START(OMAP_LDP, "OMAP LDP board")
 	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= omap_ldp_init_early,
+	.init_early	= omap3430_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= omap_ldp_init,
 	.timer		= &omap3_timer,
diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
index 6ce7481..e9d5f4a 100644
--- a/arch/arm/mach-omap2/board-n8x0.c
+++ b/arch/arm/mach-omap2/board-n8x0.c
@@ -616,18 +616,6 @@ static struct i2c_board_info n810_i2c_board_info_2[] __initdata = {
 	},
 };
 
-static void __init n8x0_map_io(void)
-{
-	omap2_set_globals_242x();
-	omap242x_map_common_io();
-}
-
-static void __init n8x0_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	/* I2S codec port pins for McBSP block */
@@ -689,6 +677,7 @@ static void __init n8x0_init_machine(void)
 		i2c_register_board_info(2, n810_i2c_board_info_2,
 					ARRAY_SIZE(n810_i2c_board_info_2));
 	board_serial_init();
+	omap_sdrc_init(NULL, NULL);
 	gpmc_onenand_init(board_onenand_data);
 	n8x0_mmc_init();
 	n8x0_usb_init();
@@ -697,8 +686,8 @@ static void __init n8x0_init_machine(void)
 MACHINE_START(NOKIA_N800, "Nokia N800")
 	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
-	.map_io		= n8x0_map_io,
-	.init_early	= n8x0_init_early,
+	.map_io		= omap242x_map_io,
+	.init_early	= omap2420_init_early,
 	.init_irq	= omap2_init_irq,
 	.init_machine	= n8x0_init_machine,
 	.timer		= &omap2_timer,
@@ -707,8 +696,8 @@ MACHINE_END
 MACHINE_START(NOKIA_N810, "Nokia N810")
 	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
-	.map_io		= n8x0_map_io,
-	.init_early	= n8x0_init_early,
+	.map_io		= omap242x_map_io,
+	.init_early	= omap2420_init_early,
 	.init_irq	= omap2_init_irq,
 	.init_machine	= n8x0_init_machine,
 	.timer		= &omap2_timer,
@@ -717,8 +706,8 @@ MACHINE_END
 MACHINE_START(NOKIA_N810_WIMAX, "Nokia N810 WiMAX")
 	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
-	.map_io		= n8x0_map_io,
-	.init_early	= n8x0_init_early,
+	.map_io		= omap242x_map_io,
+	.init_early	= omap2420_init_early,
 	.init_irq	= omap2_init_irq,
 	.init_machine	= n8x0_init_machine,
 	.timer		= &omap2_timer,
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 928933b..70261bc 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -444,18 +444,6 @@ static struct platform_device keys_gpio = {
 	},
 };
 
-static void __init omap3_beagle_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
-				  mt46h32m32lf6_sdrc_params);
-}
-
-static void __init omap3_beagle_init_irq(void)
-{
-	omap3_init_irq();
-}
-
 static struct platform_device *omap3_beagle_devices[] __initdata = {
 	&leds_gpio,
 	&keys_gpio,
@@ -493,8 +481,8 @@ static void __init beagle_opp_init(void)
 	if (cpu_is_omap3630()) {
 		struct device *mpu_dev, *iva_dev;
 
-		mpu_dev = omap2_get_mpuss_device();
-		iva_dev = omap2_get_iva_device();
+		mpu_dev = omap_device_get_by_hwmod_name("mpu");
+		iva_dev = omap_device_get_by_hwmod_name("iva");
 
 		if (!mpu_dev || !iva_dev) {
 			pr_err("%s: Aiee.. no mpu/dsp devices? %p %p\n",
@@ -534,6 +522,8 @@ static void __init omap3_beagle_init(void)
 			ARRAY_SIZE(omap3_beagle_devices));
 	omap_display_init(&beagle_dss_data);
 	omap_serial_init();
+	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
+				  mt46h32m32lf6_sdrc_params);
 
 	omap_mux_init_gpio(170, OMAP_PIN_INPUT);
 	/* REVISIT leave DVI powered down until it's needed ... */
@@ -560,8 +550,8 @@ MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
 	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= omap3_beagle_init_early,
-	.init_irq	= omap3_beagle_init_irq,
+	.init_early	= omap3_init_early,
+	.init_irq	= omap3_init_irq,
 	.init_machine	= omap3_beagle_init,
 	.timer		= &omap3_secure_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index 0d5a9e4..2d24e28 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -519,12 +519,6 @@ static int __init omap3_evm_i2c_init(void)
 static struct omap_board_config_kernel omap3_evm_config[] __initdata = {
 };
 
-static void __init omap3_evm_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(mt46h32m32lf6_sdrc_params, NULL);
-}
-
 static struct usbhs_omap_board_data usbhs_bdata __initdata = {
 
 	.port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
@@ -639,6 +633,7 @@ static void __init omap3_evm_init(void)
 	omap_display_init(&omap3_evm_dss_data);
 
 	omap_serial_init();
+	omap_sdrc_init(mt46h32m32lf6_sdrc_params, NULL);
 
 	/* OMAP3EVM uses ISP1504 phy and so register nop transceiver */
 	usb_nop_xceiv_register();
@@ -683,7 +678,7 @@ MACHINE_START(OMAP3EVM, "OMAP3 EVM")
 	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= omap3_evm_init_early,
+	.init_early	= omap35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= omap3_evm_init,
 	.timer		= &omap3_timer,
diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c
index 01354a2..7c0f193 100644
--- a/arch/arm/mach-omap2/board-omap3logic.c
+++ b/arch/arm/mach-omap2/board-omap3logic.c
@@ -182,12 +182,6 @@ static inline void __init board_smsc911x_init(void)
 	gpmc_smsc911x_init(&board_smsc911x_data);
 }
 
-static void __init omap3logic_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
@@ -200,6 +194,7 @@ static void __init omap3logic_init(void)
 	omap3torpedo_fix_pbias_voltage();
 	omap3logic_i2c_init();
 	omap_serial_init();
+	omap_sdrc_init(NULL, NULL);
 	board_mmc_init();
 	board_smsc911x_init();
 
@@ -211,7 +206,7 @@ static void __init omap3logic_init(void)
 MACHINE_START(OMAP3_TORPEDO, "Logic OMAP3 Torpedo board")
 	.atag_offset	= 0x100,
 	.map_io		= omap3_map_io,
-	.init_early	= omap3logic_init_early,
+	.init_early	= omap35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= omap3logic_init,
 	.timer		= &omap3_timer,
@@ -220,7 +215,7 @@ MACHINE_END
 MACHINE_START(OMAP3530_LV_SOM, "OMAP Logic 3530 LV SOM board")
 	.atag_offset	= 0x100,
 	.map_io		= omap3_map_io,
-	.init_early	= omap3logic_init_early,
+	.init_early	= omap35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= omap3logic_init,
 	.timer		= &omap3_timer,
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index cca523e..f7811f4 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -525,13 +525,6 @@ static struct spi_board_info omap3pandora_spi_board_info[] __initdata = {
 	}
 };
 
-static void __init omap3pandora_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
-				  mt46h32m32lf6_sdrc_params);
-}
-
 static void __init pandora_wl1251_init(void)
 {
 	struct wl12xx_platform_data pandora_wl1251_pdata;
@@ -593,6 +586,8 @@ static void __init omap3pandora_init(void)
 			ARRAY_SIZE(omap3pandora_devices));
 	omap_display_init(&pandora_dss_data);
 	omap_serial_init();
+	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
+				  mt46h32m32lf6_sdrc_params);
 	spi_register_board_info(omap3pandora_spi_board_info,
 			ARRAY_SIZE(omap3pandora_spi_board_info));
 	omap_ads7846_init(1, OMAP3_PANDORA_TS_GPIO, 0, NULL);
@@ -609,7 +604,7 @@ MACHINE_START(OMAP3_PANDORA, "Pandora Handheld Console")
 	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= omap3pandora_init_early,
+	.init_early	= omap35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= omap3pandora_init,
 	.timer		= &omap3_timer,
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index 4732589..ddb7d66 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -394,17 +394,6 @@ static int __init omap3_stalker_i2c_init(void)
 static struct omap_board_config_kernel omap3_stalker_config[] __initdata = {
 };
 
-static void __init omap3_stalker_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(mt46h32m32lf6_sdrc_params, NULL);
-}
-
-static void __init omap3_stalker_init_irq(void)
-{
-	omap3_init_irq();
-}
-
 static struct platform_device *omap3_stalker_devices[] __initdata = {
 	&keys_gpio,
 };
@@ -444,6 +433,7 @@ static void __init omap3_stalker_init(void)
 	omap_display_init(&omap3_stalker_dss_data);
 
 	omap_serial_init();
+	omap_sdrc_init(mt46h32m32lf6_sdrc_params, NULL);
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
 	omap_ads7846_init(1, OMAP3_STALKER_TS_GPIO, 310, NULL);
@@ -462,8 +452,8 @@ MACHINE_START(SBC3530, "OMAP3 STALKER")
 	/* Maintainer: Jason Lam -lzg@ema-tech.com */
 	.atag_offset		= 0x100,
 	.map_io			= omap3_map_io,
-	.init_early		= omap3_stalker_init_early,
-	.init_irq		= omap3_stalker_init_irq,
+	.init_early		= omap35xx_init_early,
+	.init_irq		= omap3_init_irq,
 	.init_machine		= omap3_stalker_init,
 	.timer			= &omap3_secure_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index abb6891..a2d0d19 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -311,18 +311,6 @@ static struct omap_board_mux board_mux[] __initdata = {
 };
 #endif
 
-static void __init omap3_touchbook_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
-				  mt46h32m32lf6_sdrc_params);
-}
-
-static void __init omap3_touchbook_init_irq(void)
-{
-	omap3_init_irq();
-}
-
 static struct platform_device *omap3_touchbook_devices[] __initdata = {
 	&leds_gpio,
 	&keys_gpio,
@@ -367,6 +355,8 @@ static void __init omap3_touchbook_init(void)
 	platform_add_devices(omap3_touchbook_devices,
 			ARRAY_SIZE(omap3_touchbook_devices));
 	omap_serial_init();
+	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
+				  mt46h32m32lf6_sdrc_params);
 
 	omap_mux_init_gpio(170, OMAP_PIN_INPUT);
 	/* REVISIT leave DVI powered down until it's needed ... */
@@ -389,8 +379,8 @@ MACHINE_START(TOUCHBOOK, "OMAP3 touchbook Board")
 	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= omap3_touchbook_init_early,
-	.init_irq	= omap3_touchbook_init_irq,
+	.init_early	= omap3430_init_early,
+	.init_irq	= omap3_init_irq,
 	.init_machine	= omap3_touchbook_init,
 	.timer		= &omap3_secure_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index ed38d8f..a8c2c42 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -95,12 +95,6 @@ static struct platform_device *panda_devices[] __initdata = {
 	&wl1271_device,
 };
 
-static void __init omap4_panda_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
-
 static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
 	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
 	.port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
@@ -569,24 +563,19 @@ static void __init omap4_panda_init(void)
 	platform_add_devices(panda_devices, ARRAY_SIZE(panda_devices));
 	platform_device_register(&omap_vwlan_device);
 	board_serial_init();
+	omap_sdrc_init(NULL, NULL);
 	omap4_twl6030_hsmmc_init(mmc);
 	omap4_ehci_init();
 	usb_musb_init(&musb_board_data);
 	omap4_panda_display_init();
 }
 
-static void __init omap4_panda_map_io(void)
-{
-	omap2_set_globals_443x();
-	omap44xx_map_common_io();
-}
-
 MACHINE_START(OMAP4_PANDA, "OMAP4 Panda board")
 	/* Maintainer: David Anders - Texas Instruments Inc */
 	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
-	.map_io		= omap4_panda_map_io,
-	.init_early	= omap4_panda_init_early,
+	.map_io		= omap4_map_io,
+	.init_early	= omap4430_init_early,
 	.init_irq	= gic_init_irq,
 	.init_machine	= omap4_panda_init,
 	.timer		= &omap4_timer,
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index ec0f60c..4cf7aea 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -479,13 +479,6 @@ static int __init overo_spi_init(void)
 	return 0;
 }
 
-static void __init overo_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
-				  mt46h32m32lf6_sdrc_params);
-}
-
 static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
 	.port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
 	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
@@ -515,6 +508,8 @@ static void __init overo_init(void)
 	overo_i2c_init();
 	omap_display_init(&overo_dss_data);
 	omap_serial_init();
+	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
+				  mt46h32m32lf6_sdrc_params);
 	omap_nand_flash_init(0, overo_nand_partitions,
 			     ARRAY_SIZE(overo_nand_partitions));
 	usb_musb_init(NULL);
@@ -565,7 +560,7 @@ MACHINE_START(OVERO, "Gumstix Overo")
 	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= overo_init_early,
+	.init_early	= omap35xx_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= overo_init,
 	.timer		= &omap3_timer,
diff --git a/arch/arm/mach-omap2/board-rm680.c b/arch/arm/mach-omap2/board-rm680.c
index 9a8ce23..616fb39 100644
--- a/arch/arm/mach-omap2/board-rm680.c
+++ b/arch/arm/mach-omap2/board-rm680.c
@@ -123,15 +123,6 @@ static void __init rm680_peripherals_init(void)
 	omap2_hsmmc_init(mmc);
 }
 
-static void __init rm680_init_early(void)
-{
-	struct omap_sdrc_params *sdrc_params;
-
-	omap2_init_common_infrastructure();
-	sdrc_params = nokia_get_sdram_timings();
-	omap2_init_common_devices(sdrc_params, sdrc_params);
-}
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
@@ -140,23 +131,23 @@ static struct omap_board_mux board_mux[] __initdata = {
 
 static void __init rm680_init(void)
 {
+	struct omap_sdrc_params *sdrc_params;
+
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap_serial_init();
+
+	sdrc_params = nokia_get_sdram_timings();
+	omap_sdrc_init(sdrc_params, sdrc_params);
+
 	usb_musb_init(NULL);
 	rm680_peripherals_init();
 }
 
-static void __init rm680_map_io(void)
-{
-	omap2_set_globals_3xxx();
-	omap34xx_map_common_io();
-}
-
 MACHINE_START(NOKIA_RM680, "Nokia RM-680 board")
 	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
-	.map_io		= rm680_map_io,
-	.init_early	= rm680_init_early,
+	.map_io		= omap3_map_io,
+	.init_early	= omap3630_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= rm680_init,
 	.timer		= &omap3_timer,
diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c
index faa2a8e..4af7c4b 100644
--- a/arch/arm/mach-omap2/board-rx51.c
+++ b/arch/arm/mach-omap2/board-rx51.c
@@ -79,15 +79,6 @@ static struct cpuidle_params rx51_cpuidle_params[] = {
 	{7505 + 15274, 484329, 1},
 };
 
-static void __init rx51_init_early(void)
-{
-	struct omap_sdrc_params *sdrc_params;
-
-	omap2_init_common_infrastructure();
-	sdrc_params = nokia_get_sdram_timings();
-	omap2_init_common_devices(sdrc_params, sdrc_params);
-}
-
 extern void __init rx51_peripherals_init(void);
 
 #ifdef CONFIG_OMAP_MUX
@@ -104,9 +95,15 @@ static struct omap_musb_board_data musb_board_data = {
 
 static void __init rx51_init(void)
 {
+	struct omap_sdrc_params *sdrc_params;
+
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap3_pm_init_cpuidle(rx51_cpuidle_params);
 	omap_serial_init();
+
+	sdrc_params = nokia_get_sdram_timings();
+	omap_sdrc_init(sdrc_params, sdrc_params);
+
 	usb_musb_init(&musb_board_data);
 	rx51_peripherals_init();
 
@@ -117,12 +114,6 @@ static void __init rx51_init(void)
 	platform_device_register(&leds_gpio);
 }
 
-static void __init rx51_map_io(void)
-{
-	omap2_set_globals_3xxx();
-	omap34xx_map_common_io();
-}
-
 static void __init rx51_reserve(void)
 {
 	rx51_video_mem_init();
@@ -133,8 +124,8 @@ MACHINE_START(NOKIA_RX51, "Nokia RX-51 board")
 	/* Maintainer: Lauri Leukkunen <lauri.leukkunen@nokia.com> */
 	.atag_offset	= 0x100,
 	.reserve	= rx51_reserve,
-	.map_io		= rx51_map_io,
-	.init_early	= rx51_init_early,
+	.map_io		= omap3_map_io,
+	.init_early	= omap3430_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= rx51_init,
 	.timer		= &omap3_timer,
diff --git a/arch/arm/mach-omap2/board-ti8168evm.c b/arch/arm/mach-omap2/board-ti8168evm.c
index e41958a..e6ee884 100644
--- a/arch/arm/mach-omap2/board-ti8168evm.c
+++ b/arch/arm/mach-omap2/board-ti8168evm.c
@@ -27,22 +27,16 @@
 static struct omap_board_config_kernel ti8168_evm_config[] __initdata = {
 };
 
-static void __init ti8168_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	omap2_init_common_devices(NULL, NULL);
-}
-
 static void __init ti8168_evm_init(void)
 {
 	omap_serial_init();
+	omap_sdrc_init(NULL, NULL);
 	omap_board_config = ti8168_evm_config;
 	omap_board_config_size = ARRAY_SIZE(ti8168_evm_config);
 }
 
 static void __init ti8168_evm_map_io(void)
 {
-	omap2_set_globals_ti816x();
 	omapti816x_map_common_io();
 }
 
@@ -50,7 +44,7 @@ MACHINE_START(TI8168EVM, "ti8168evm")
 	/* Maintainer: Texas Instruments */
 	.atag_offset	= 0x100,
 	.map_io		= ti8168_evm_map_io,
-	.init_early	= ti8168_init_early,
+	.init_early	= ti816x_init_early,
 	.init_irq	= ti816x_init_irq,
 	.timer		= &omap3_timer,
 	.init_machine	= ti8168_evm_init,
diff --git a/arch/arm/mach-omap2/board-zoom.c b/arch/arm/mach-omap2/board-zoom.c
index 72f1db4..be6684d 100644
--- a/arch/arm/mach-omap2/board-zoom.c
+++ b/arch/arm/mach-omap2/board-zoom.c
@@ -34,17 +34,6 @@
 
 #define ZOOM3_EHCI_RESET_GPIO		64
 
-static void __init omap_zoom_init_early(void)
-{
-	omap2_init_common_infrastructure();
-	if (machine_is_omap_zoom2())
-		omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
-					  mt46h32m32lf6_sdrc_params);
-	else if (machine_is_omap_zoom3())
-		omap2_init_common_devices(h8mbx00u0mer0em_sdrc_params,
-					  h8mbx00u0mer0em_sdrc_params);
-}
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	/* WLAN IRQ - GPIO 162 */
@@ -129,6 +118,14 @@ static void __init omap_zoom_init(void)
 						ZOOM_NAND_CS, NAND_BUSWIDTH_16);
 	zoom_debugboard_init();
 	zoom_peripherals_init();
+
+	if (machine_is_omap_zoom2())
+		omap_sdrc_init(mt46h32m32lf6_sdrc_params,
+					  mt46h32m32lf6_sdrc_params);
+	else if (machine_is_omap_zoom3())
+		omap_sdrc_init(h8mbx00u0mer0em_sdrc_params,
+					  h8mbx00u0mer0em_sdrc_params);
+
 	zoom_display_init();
 }
 
@@ -136,7 +133,7 @@ MACHINE_START(OMAP_ZOOM2, "OMAP Zoom2 board")
 	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= omap_zoom_init_early,
+	.init_early	= omap3430_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= omap_zoom_init,
 	.timer		= &omap3_timer,
@@ -146,7 +143,7 @@ MACHINE_START(OMAP_ZOOM3, "OMAP Zoom3 board")
 	.atag_offset	= 0x100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_early	= omap_zoom_init_early,
+	.init_early	= omap3630_init_early,
 	.init_irq	= omap3_init_irq,
 	.init_machine	= omap_zoom_init,
 	.timer		= &omap3_timer,
diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c
index debc040..14a6277 100644
--- a/arch/arm/mach-omap2/clock2420_data.c
+++ b/arch/arm/mach-omap2/clock2420_data.c
@@ -1898,6 +1898,54 @@ static struct omap_clk omap2420_clks[] = {
 	CLK(NULL,	"pka_ick",	&pka_ick,	CK_242X),
 	CLK(NULL,	"usb_fck",	&usb_fck,	CK_242X),
 	CLK("musb-hdrc",	"fck",	&osc_ck,	CK_242X),
+	CLK("omap_timer.1",	"fck",	&gpt1_fck,	CK_242X),
+	CLK("omap_timer.2",	"fck",	&gpt2_fck,	CK_242X),
+	CLK("omap_timer.3",	"fck",	&gpt3_fck,	CK_242X),
+	CLK("omap_timer.4",	"fck",	&gpt4_fck,	CK_242X),
+	CLK("omap_timer.5",	"fck",	&gpt5_fck,	CK_242X),
+	CLK("omap_timer.6",	"fck",	&gpt6_fck,	CK_242X),
+	CLK("omap_timer.7",	"fck",	&gpt7_fck,	CK_242X),
+	CLK("omap_timer.8",	"fck",	&gpt8_fck,	CK_242X),
+	CLK("omap_timer.9",	"fck",	&gpt9_fck,	CK_242X),
+	CLK("omap_timer.10",	"fck",	&gpt10_fck,	CK_242X),
+	CLK("omap_timer.11",	"fck",	&gpt11_fck,	CK_242X),
+	CLK("omap_timer.12",	"fck",	&gpt12_fck,	CK_242X),
+	CLK("omap_timer.1",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.2",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.3",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.4",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.5",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.6",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.7",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.8",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.9",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.10",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.11",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.12",	"32k_ck",	&func_32k_ck,	CK_243X),
+	CLK("omap_timer.1",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.2",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.3",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.4",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.5",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.6",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.7",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.8",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.9",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.10",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.11",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.12",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.1",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.2",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.3",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.4",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.5",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.6",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.7",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.8",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.9",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.10",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.11",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.12",	"alt_ck",	&alt_ck,	CK_243X),
 };
 
 /*
diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c
index 96a942e..ea6717c 100644
--- a/arch/arm/mach-omap2/clock2430_data.c
+++ b/arch/arm/mach-omap2/clock2430_data.c
@@ -1998,6 +1998,54 @@ static struct omap_clk omap2430_clks[] = {
 	CLK(NULL,	"mdm_intc_ick",	&mdm_intc_ick,	CK_243X),
 	CLK("omap_hsmmc.0", "mmchsdb_fck",	&mmchsdb1_fck,	CK_243X),
 	CLK("omap_hsmmc.1", "mmchsdb_fck",	&mmchsdb2_fck,	CK_243X),
+	CLK("omap_timer.1",     "fck",  &gpt1_fck,      CK_243X),
+	CLK("omap_timer.2",     "fck",  &gpt2_fck,      CK_243X),
+	CLK("omap_timer.3",     "fck",  &gpt3_fck,      CK_243X),
+	CLK("omap_timer.4",     "fck",  &gpt4_fck,      CK_243X),
+	CLK("omap_timer.5",     "fck",  &gpt5_fck,      CK_243X),
+	CLK("omap_timer.6",     "fck",  &gpt6_fck,      CK_243X),
+	CLK("omap_timer.7",     "fck",  &gpt7_fck,      CK_243X),
+	CLK("omap_timer.8",     "fck",  &gpt8_fck,      CK_243X),
+	CLK("omap_timer.9",     "fck",  &gpt9_fck,      CK_243X),
+	CLK("omap_timer.10",    "fck",  &gpt10_fck,     CK_243X),
+	CLK("omap_timer.11",    "fck",  &gpt11_fck,     CK_243X),
+	CLK("omap_timer.12",    "fck",  &gpt12_fck,     CK_243X),
+	CLK("omap_timer.1",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.2",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.3",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.4",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.5",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.6",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.7",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.8",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.9",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.10",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.11",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.12",	"32k_ck",  &func_32k_ck,   CK_243X),
+	CLK("omap_timer.1",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.2",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.3",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.4",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.5",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.6",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.7",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.8",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.9",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.10",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.11",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.12",	"sys_ck",	&sys_ck,	CK_243X),
+	CLK("omap_timer.1",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.2",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.3",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.4",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.5",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.6",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.7",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.8",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.9",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.10",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.11",	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap_timer.12",	"alt_ck",	&alt_ck,	CK_243X),
 };
 
 /*
diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
index b9b8446..65dd363 100644
--- a/arch/arm/mach-omap2/clock3xxx_data.c
+++ b/arch/arm/mach-omap2/clock3xxx_data.c
@@ -3464,6 +3464,42 @@ static struct omap_clk omap3xxx_clks[] = {
 	CLK("musb-am35x",	"fck",		&hsotgusb_fck_am35xx,	CK_AM35XX),
 	CLK(NULL,	"hecc_ck",	&hecc_ck,	CK_AM35XX),
 	CLK(NULL,	"uart4_ick",	&uart4_ick_am35xx,	CK_AM35XX),
+	CLK("omap_timer.1",	"fck",	&gpt1_fck,	CK_3XXX),
+	CLK("omap_timer.2",	"fck",	&gpt2_fck,	CK_3XXX),
+	CLK("omap_timer.3",	"fck",	&gpt3_fck,	CK_3XXX),
+	CLK("omap_timer.4",	"fck",	&gpt4_fck,	CK_3XXX),
+	CLK("omap_timer.5",	"fck",	&gpt5_fck,	CK_3XXX),
+	CLK("omap_timer.6",	"fck",	&gpt6_fck,	CK_3XXX),
+	CLK("omap_timer.7",	"fck",	&gpt7_fck,	CK_3XXX),
+	CLK("omap_timer.8",	"fck",	&gpt8_fck,	CK_3XXX),
+	CLK("omap_timer.9",	"fck",	&gpt9_fck,	CK_3XXX),
+	CLK("omap_timer.10",    "fck",  &gpt10_fck,     CK_3XXX),
+	CLK("omap_timer.11",    "fck",  &gpt11_fck,     CK_3XXX),
+	CLK("omap_timer.12",    "fck",  &gpt12_fck,     CK_3XXX),
+	CLK("omap_timer.1",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.2",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.3",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.4",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.5",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.6",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.7",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.8",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.9",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.10",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.11",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.12",	"32k_ck",	&omap_32k_fck,  CK_3XXX),
+	CLK("omap_timer.1",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.2",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.3",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.4",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.5",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.6",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.7",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.8",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.9",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.10",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.11",	"sys_ck",	&sys_ck,	CK_3XXX),
+	CLK("omap_timer.12",	"sys_ck",	&sys_ck,	CK_3XXX),
 };
 
 
@@ -3472,7 +3508,16 @@ int __init omap3xxx_clk_init(void)
 	struct omap_clk *c;
 	u32 cpu_clkflg = 0;
 
-	if (cpu_is_omap3517()) {
+	/*
+	 * 3505 must be tested before 3517, since 3517 returns true
+	 * for both AM3517 chips and AM3517 family chips, which
+	 * includes 3505.  Unfortunately there's no obvious family
+	 * test for 3517/3505 :-(
+	 */
+	if (cpu_is_omap3505()) {
+		cpu_mask = RATE_IN_34XX;
+		cpu_clkflg = CK_3505;
+	} else if (cpu_is_omap3517()) {
 		cpu_mask = RATE_IN_34XX;
 		cpu_clkflg = CK_3517;
 	} else if (cpu_is_omap3505()) {
diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index c0b6fbd..946bf04 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -3363,6 +3363,39 @@ static struct omap_clk omap44xx_clks[] = {
 	CLK("usbhs-omap.0",	"usbhost_ick",		&dummy_ck,		CK_443X),
 	CLK("usbhs-omap.0",	"usbtll_fck",		&dummy_ck,	CK_443X),
 	CLK("omap_wdt",	"ick",				&dummy_ck,	CK_443X),
+	CLK("omap_timer.1",	"fck",			&timer1_fck,	CK_443X),
+	CLK("omap_timer.2",	"fck",			&timer2_fck,	CK_443X),
+	CLK("omap_timer.3",	"fck",			&timer3_fck,	CK_443X),
+	CLK("omap_timer.4",	"fck",			&timer4_fck,	CK_443X),
+	CLK("omap_timer.5",	"fck",			&timer5_fck,	CK_443X),
+	CLK("omap_timer.6",	"fck",			&timer6_fck,	CK_443X),
+	CLK("omap_timer.7",	"fck",			&timer7_fck,	CK_443X),
+	CLK("omap_timer.8",	"fck",			&timer8_fck,	CK_443X),
+	CLK("omap_timer.9",	"fck",			&timer9_fck,	CK_443X),
+	CLK("omap_timer.10",	"fck",			&timer10_fck,	CK_443X),
+	CLK("omap_timer.11",	"fck",			&timer11_fck,	CK_443X),
+	CLK("omap_timer.1",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.2",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.3",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.4",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.5",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.6",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.7",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.8",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.9",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.10",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.11",	"32k_ck",	&sys_32k_ck,	CK_443X),
+	CLK("omap_timer.1",	"sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.2",	"sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.3",	"sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.4",	"sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.9",	"sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.10",	"sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.11",	"sys_ck",	&sys_clkin_ck,	CK_443X),
+	CLK("omap_timer.5",	"sys_ck",	&syc_clk_div_ck,	CK_443X),
+	CLK("omap_timer.6",	"sys_ck",	&syc_clk_div_ck,	CK_443X),
+	CLK("omap_timer.7",	"sys_ck",	&syc_clk_div_ck,	CK_443X),
+	CLK("omap_timer.8",	"sys_ck",	&syc_clk_div_ck,	CK_443X),
 };
 
 int __init omap4xxx_clk_init(void)
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 8f08906..8480ee4 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -73,9 +73,6 @@ static int _clkdm_register(struct clockdomain *clkdm)
 	if (!clkdm || !clkdm->name)
 		return -EINVAL;
 
-	if (!omap_chip_is(clkdm->omap_chip))
-		return -EINVAL;
-
 	pwrdm = pwrdm_lookup(clkdm->pwrdm.name);
 	if (!pwrdm) {
 		pr_err("clockdomain: %s: powerdomain %s does not exist\n",
@@ -105,13 +102,10 @@ static struct clkdm_dep *_clkdm_deps_lookup(struct clockdomain *clkdm,
 {
 	struct clkdm_dep *cd;
 
-	if (!clkdm || !deps || !omap_chip_is(clkdm->omap_chip))
+	if (!clkdm || !deps)
 		return ERR_PTR(-EINVAL);
 
 	for (cd = deps; cd->clkdm_name; cd++) {
-		if (!omap_chip_is(cd->omap_chip))
-			continue;
-
 		if (!cd->clkdm && cd->clkdm_name)
 			cd->clkdm = _clkdm_lookup(cd->clkdm_name);
 
@@ -148,9 +142,6 @@ static void _autodep_lookup(struct clkdm_autodep *autodep)
 	if (!autodep)
 		return;
 
-	if (!omap_chip_is(autodep->omap_chip))
-		return;
-
 	clkdm = clkdm_lookup(autodep->clkdm.name);
 	if (!clkdm) {
 		pr_err("clockdomain: autodeps: clockdomain %s does not exist\n",
@@ -182,9 +173,6 @@ void _clkdm_add_autodeps(struct clockdomain *clkdm)
 		if (IS_ERR(autodep->clkdm.ptr))
 			continue;
 
-		if (!omap_chip_is(autodep->omap_chip))
-			continue;
-
 		pr_debug("clockdomain: adding %s sleepdep/wkdep for "
 			 "clkdm %s\n", autodep->clkdm.ptr->name,
 			 clkdm->name);
@@ -216,9 +204,6 @@ void _clkdm_del_autodeps(struct clockdomain *clkdm)
 		if (IS_ERR(autodep->clkdm.ptr))
 			continue;
 
-		if (!omap_chip_is(autodep->omap_chip))
-			continue;
-
 		pr_debug("clockdomain: removing %s sleepdep/wkdep for "
 			 "clkdm %s\n", autodep->clkdm.ptr->name,
 			 clkdm->name);
@@ -243,8 +228,6 @@ static void _resolve_clkdm_deps(struct clockdomain *clkdm,
 	struct clkdm_dep *cd;
 
 	for (cd = clkdm_deps; cd && cd->clkdm_name; cd++) {
-		if (!omap_chip_is(cd->omap_chip))
-			continue;
 		if (cd->clkdm)
 			continue;
 		cd->clkdm = _clkdm_lookup(cd->clkdm_name);
@@ -257,43 +240,113 @@ static void _resolve_clkdm_deps(struct clockdomain *clkdm,
 /* Public functions */
 
 /**
- * clkdm_init - set up the clockdomain layer
- * @clkdms: optional pointer to an array of clockdomains to register
- * @init_autodeps: optional pointer to an array of autodeps to register
- * @custom_funcs: func pointers for arch specific implementations
- *
- * Set up internal state.  If a pointer to an array of clockdomains
- * @clkdms was supplied, loop through the list of clockdomains,
- * register all that are available on the current platform. Similarly,
- * if a pointer to an array of clockdomain autodependencies
- * @init_autodeps was provided, register those.  No return value.
+ * clkdm_register_platform_funcs - register clockdomain implementation fns
+ * @co: func pointers for arch specific implementations
+ *
+ * Register the list of function pointers used to implement the
+ * clockdomain functions on different OMAP SoCs.  Should be called
+ * before any other clkdm_register*() function.  Returns -EINVAL if
+ * @co is null, -EEXIST if platform functions have already been
+ * registered, or 0 upon success.
+ */
+int clkdm_register_platform_funcs(struct clkdm_ops *co)
+{
+	if (!co)
+		return -EINVAL;
+
+	if (arch_clkdm)
+		return -EEXIST;
+
+	arch_clkdm = co;
+
+	return 0;
+};
+
+/**
+ * clkdm_register_clkdms - register SoC clockdomains
+ * @cs: pointer to an array of struct clockdomain to register
+ *
+ * Register the clockdomains available on a particular OMAP SoC.  Must
+ * be called after clkdm_register_platform_funcs().  May be called
+ * multiple times.  Returns -EACCES if called before
+ * clkdm_register_platform_funcs(); -EINVAL if the argument @cs is
+ * null; or 0 upon success.
  */
-void clkdm_init(struct clockdomain **clkdms,
-		struct clkdm_autodep *init_autodeps,
-		struct clkdm_ops *custom_funcs)
+int clkdm_register_clkdms(struct clockdomain **cs)
 {
 	struct clockdomain **c = NULL;
-	struct clockdomain *clkdm;
-	struct clkdm_autodep *autodep = NULL;
 
-	if (!custom_funcs)
-		WARN(1, "No custom clkdm functions registered\n");
-	else
-		arch_clkdm = custom_funcs;
+	if (!arch_clkdm)
+		return -EACCES;
+
+	if (!cs)
+		return -EINVAL;
+
+	for (c = cs; *c; c++)
+		_clkdm_register(*c);
+
+	return 0;
+}
+
+/**
+ * clkdm_register_autodeps - register autodeps (if required)
+ * @ia: pointer to a static array of struct clkdm_autodep to register
+ *
+ * Register clockdomain "automatic dependencies."  These are
+ * clockdomain wakeup and sleep dependencies that are automatically
+ * added whenever the first clock inside a clockdomain is enabled, and
+ * removed whenever the last clock inside a clockdomain is disabled.
+ * These are currently only used on OMAP3 devices, and are deprecated,
+ * since they waste energy.  However, until the OMAP2/3 IP block
+ * enable/disable sequence can be converted to match the OMAP4
+ * sequence, they are needed.
+ *
+ * Must be called only after all of the SoC clockdomains are
+ * registered, since the function will resolve autodep clockdomain
+ * names into clockdomain pointers.
+ *
+ * The struct clkdm_autodep @ia array must be static, as this function
+ * does not copy the array elements.
+ *
+ * Returns -EACCES if called before any clockdomains have been
+ * registered, -EINVAL if called with a null @ia argument, -EEXIST if
+ * autodeps have already been registered, or 0 upon success.
+ */
+int clkdm_register_autodeps(struct clkdm_autodep *ia)
+{
+	struct clkdm_autodep *a = NULL;
 
-	if (clkdms)
-		for (c = clkdms; *c; c++)
-			_clkdm_register(*c);
+	if (list_empty(&clkdm_list))
+		return -EACCES;
+
+	if (!ia)
+		return -EINVAL;
 
-	autodeps = init_autodeps;
 	if (autodeps)
-		for (autodep = autodeps; autodep->clkdm.ptr; autodep++)
-			_autodep_lookup(autodep);
+		return -EEXIST;
+
+	autodeps = ia;
+	for (a = autodeps; a->clkdm.ptr; a++)
+		_autodep_lookup(a);
+
+	return 0;
+}
+
+/**
+ * clkdm_complete_init - set up the clockdomain layer
+ *
+ * Put all clockdomains into software-supervised mode; PM code should
+ * later enable hardware-supervised mode as appropriate.  Must be
+ * called after clkdm_register_clkdms().  Returns -EACCES if called
+ * before clkdm_register_clkdms(), or 0 upon success.
+ */
+int clkdm_complete_init(void)
+{
+	struct clockdomain *clkdm;
+
+	if (list_empty(&clkdm_list))
+		return -EACCES;
 
-	/*
-	 * Put all clockdomains into software-supervised mode; PM code
-	 * should later enable hardware-supervised mode as appropriate
-	 */
 	list_for_each_entry(clkdm, &clkdm_list, node) {
 		if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
 			clkdm_wakeup(clkdm);
@@ -306,6 +359,8 @@ void clkdm_init(struct clockdomain **clkdms,
 		_resolve_clkdm_deps(clkdm, clkdm->sleepdep_srcs);
 		clkdm_clear_all_sleepdeps(clkdm);
 	}
+
+	return 0;
 }
 
 /**
diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h
index 1e50c88..f7b5860 100644
--- a/arch/arm/mach-omap2/clockdomain.h
+++ b/arch/arm/mach-omap2/clockdomain.h
@@ -45,7 +45,6 @@
 /**
  * struct clkdm_autodep - clkdm deps to add when entering/exiting hwsup mode
  * @clkdm: clockdomain to add wkdep+sleepdep on - set name member only
- * @omap_chip: OMAP chip types that this autodep is valid on
  *
  * A clockdomain that should have wkdeps and sleepdeps added when a
  * clockdomain should stay active in hwsup mode; and conversely,
@@ -60,14 +59,12 @@ struct clkdm_autodep {
 		const char *name;
 		struct clockdomain *ptr;
 	} clkdm;
-	const struct omap_chip_id omap_chip;
 };
 
 /**
  * struct clkdm_dep - encode dependencies between clockdomains
  * @clkdm_name: clockdomain name
  * @clkdm: pointer to the struct clockdomain of @clkdm_name
- * @omap_chip: OMAP chip types that this dependency is valid on
  * @wkdep_usecount: Number of wakeup dependencies causing this clkdm to wake
  * @sleepdep_usecount: Number of sleep deps that could prevent clkdm from idle
  *
@@ -81,7 +78,6 @@ struct clkdm_dep {
 	struct clockdomain *clkdm;
 	atomic_t wkdep_usecount;
 	atomic_t sleepdep_usecount;
-	const struct omap_chip_id omap_chip;
 };
 
 /* Possible flags for struct clockdomain._flags */
@@ -101,7 +97,6 @@ struct clkdm_dep {
  * @clkdm_offs: (OMAP4 only) CM clockdomain register offset
  * @wkdep_srcs: Clockdomains that can be told to wake this powerdomain up
  * @sleepdep_srcs: Clockdomains that can be told to keep this clkdm from inact
- * @omap_chip: OMAP chip types that this clockdomain is valid on
  * @usecount: Usecount tracking
  * @node: list_head to link all clockdomains together
  *
@@ -126,7 +121,6 @@ struct clockdomain {
 	const u16 clkdm_offs;
 	struct clkdm_dep *wkdep_srcs;
 	struct clkdm_dep *sleepdep_srcs;
-	const struct omap_chip_id omap_chip;
 	atomic_t usecount;
 	struct list_head node;
 	spinlock_t lock;
@@ -166,8 +160,11 @@ struct clkdm_ops {
 	int	(*clkdm_clk_disable)(struct clockdomain *clkdm);
 };
 
-void clkdm_init(struct clockdomain **clkdms, struct clkdm_autodep *autodeps,
-			struct clkdm_ops *custom_funcs);
+int clkdm_register_platform_funcs(struct clkdm_ops *co);
+int clkdm_register_autodeps(struct clkdm_autodep *ia);
+int clkdm_register_clkdms(struct clockdomain **c);
+int clkdm_complete_init(void);
+
 struct clockdomain *clkdm_lookup(const char *name);
 
 int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user),
@@ -195,7 +192,8 @@ int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk);
 int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh);
 int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh);
 
-extern void __init omap2xxx_clockdomains_init(void);
+extern void __init omap242x_clockdomains_init(void);
+extern void __init omap243x_clockdomains_init(void);
 extern void __init omap3xxx_clockdomains_init(void);
 extern void __init omap44xx_clockdomains_init(void);
 extern void _clkdm_add_autodeps(struct clockdomain *clkdm);
@@ -205,4 +203,10 @@ extern struct clkdm_ops omap2_clkdm_operations;
 extern struct clkdm_ops omap3_clkdm_operations;
 extern struct clkdm_ops omap4_clkdm_operations;
 
+extern struct clkdm_dep gfx_24xx_wkdeps[];
+extern struct clkdm_dep dsp_24xx_wkdeps[];
+extern struct clockdomain wkup_common_clkdm;
+extern struct clockdomain prm_common_clkdm;
+extern struct clockdomain cm_common_clkdm;
+
 #endif
diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
index f740edb..a0d68db 100644
--- a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
@@ -52,8 +52,6 @@ static int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
 	u32 mask = 0;
 
 	for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
-		if (!omap_chip_is(cd->omap_chip))
-			continue;
 		if (!cd->clkdm)
 			continue; /* only happens if data is erroneous */
 
@@ -98,8 +96,6 @@ static int omap3_clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
 	u32 mask = 0;
 
 	for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) {
-		if (!omap_chip_is(cd->omap_chip))
-			continue;
 		if (!cd->clkdm)
 			continue; /* only happens if data is erroneous */
 
diff --git a/arch/arm/mach-omap2/clockdomain44xx.c b/arch/arm/mach-omap2/clockdomain44xx.c
index b43706a..935c7f0 100644
--- a/arch/arm/mach-omap2/clockdomain44xx.c
+++ b/arch/arm/mach-omap2/clockdomain44xx.c
@@ -52,8 +52,6 @@ static int omap4_clkdm_clear_all_wkup_sleep_deps(struct clockdomain *clkdm)
 	u32 mask = 0;
 
 	for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
-		if (!omap_chip_is(cd->omap_chip))
-			continue;
 		if (!cd->clkdm)
 			continue; /* only happens if data is erroneous */
 
diff --git a/arch/arm/mach-omap2/clockdomains2420_data.c b/arch/arm/mach-omap2/clockdomains2420_data.c
new file mode 100644
index 0000000..0ab8e46
--- /dev/null
+++ b/arch/arm/mach-omap2/clockdomains2420_data.c
@@ -0,0 +1,154 @@
+/*
+ * OMAP2420 clockdomains
+ *
+ * Copyright (C) 2008-2011 Texas Instruments, Inc.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Paul Walmsley, Jouni Högander
+ *
+ * This file contains clockdomains and clockdomain wakeup dependencies
+ * for OMAP2420 chips.  Some notes:
+ *
+ * A useful validation rule for struct clockdomain: Any clockdomain
+ * referenced by a wkdep_srcs must have a dep_bit assigned.  So
+ * wkdep_srcs are really just software-controllable dependencies.
+ * Non-software-controllable dependencies do exist, but they are not
+ * encoded below (yet).
+ *
+ * 24xx does not support programmable sleep dependencies (SLEEPDEP)
+ *
+ * The overly-specific dep_bit names are due to a bit name collision
+ * with CM_FCLKEN_{DSP,IVA2}.  The DSP/IVA2 PM_WKDEP and CM_SLEEPDEP shift
+ * value are the same for all powerdomains: 2
+ *
+ * XXX should dep_bit be a mask, so we can test to see if it is 0 as a
+ * sanity check?
+ * XXX encode hardware fixed wakeup dependencies -- esp. for 3430 CORE
+ */
+
+/*
+ * To-Do List
+ * -> Port the Sleep/Wakeup dependencies for the domains
+ *    from the Power domain framework
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+#include "clockdomain.h"
+#include "prm2xxx_3xxx.h"
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-24xx.h"
+#include "prm-regbits-24xx.h"
+
+/*
+ * Clockdomain dependencies for wkdeps
+ *
+ * XXX Hardware dependencies (e.g., dependencies that cannot be
+ * changed in software) are not included here yet, but should be.
+ */
+
+/* Wakeup dependency source arrays */
+
+/* 2420-specific possible wakeup dependencies */
+
+/* 2420 PM_WKDEP_MPU: CORE, DSP, WKUP */
+static struct clkdm_dep mpu_2420_wkdeps[] = {
+	{ .clkdm_name = "core_l3_clkdm" },
+	{ .clkdm_name = "core_l4_clkdm" },
+	{ .clkdm_name = "dsp_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
+	{ NULL },
+};
+
+/* 2420 PM_WKDEP_CORE: DSP, GFX, MPU, WKUP */
+static struct clkdm_dep core_2420_wkdeps[] = {
+	{ .clkdm_name = "dsp_clkdm" },
+	{ .clkdm_name = "gfx_clkdm" },
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
+	{ NULL },
+};
+
+/*
+ * 2420-only clockdomains
+ */
+
+static struct clockdomain mpu_2420_clkdm = {
+	.name		= "mpu_clkdm",
+	.pwrdm		= { .name = "mpu_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP,
+	.wkdep_srcs	= mpu_2420_wkdeps,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK,
+};
+
+static struct clockdomain iva1_2420_clkdm = {
+	.name		= "iva1_clkdm",
+	.pwrdm		= { .name = "dsp_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.dep_bit	= OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT,
+	.wkdep_srcs	= dsp_24xx_wkdeps,
+	.clktrctrl_mask = OMAP2420_AUTOSTATE_IVA_MASK,
+};
+
+static struct clockdomain dsp_2420_clkdm = {
+	.name		= "dsp_clkdm",
+	.pwrdm		= { .name = "dsp_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSP_MASK,
+};
+
+static struct clockdomain gfx_2420_clkdm = {
+	.name		= "gfx_clkdm",
+	.pwrdm		= { .name = "gfx_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.wkdep_srcs	= gfx_24xx_wkdeps,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_GFX_MASK,
+};
+
+static struct clockdomain core_l3_2420_clkdm = {
+	.name		= "core_l3_clkdm",
+	.pwrdm		= { .name = "core_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP,
+	.wkdep_srcs	= core_2420_wkdeps,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_L3_MASK,
+};
+
+static struct clockdomain core_l4_2420_clkdm = {
+	.name		= "core_l4_clkdm",
+	.pwrdm		= { .name = "core_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP,
+	.wkdep_srcs	= core_2420_wkdeps,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_L4_MASK,
+};
+
+static struct clockdomain dss_2420_clkdm = {
+	.name		= "dss_clkdm",
+	.pwrdm		= { .name = "core_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSS_MASK,
+};
+
+static struct clockdomain *clockdomains_omap242x[] __initdata = {
+	&wkup_common_clkdm,
+	&cm_common_clkdm,
+	&prm_common_clkdm,
+	&mpu_2420_clkdm,
+	&iva1_2420_clkdm,
+	&dsp_2420_clkdm,
+	&gfx_2420_clkdm,
+	&core_l3_2420_clkdm,
+	&core_l4_2420_clkdm,
+	&dss_2420_clkdm,
+	NULL,
+};
+
+void __init omap242x_clockdomains_init(void)
+{
+	if (!cpu_is_omap242x())
+		return;
+
+	clkdm_register_platform_funcs(&omap2_clkdm_operations);
+	clkdm_register_clkdms(clockdomains_omap242x);
+	clkdm_complete_init();
+}
diff --git a/arch/arm/mach-omap2/clockdomains2430_data.c b/arch/arm/mach-omap2/clockdomains2430_data.c
new file mode 100644
index 0000000..3645ed0
--- /dev/null
+++ b/arch/arm/mach-omap2/clockdomains2430_data.c
@@ -0,0 +1,181 @@
+/*
+ * OMAP2xxx clockdomains
+ *
+ * Copyright (C) 2008-2009 Texas Instruments, Inc.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Paul Walmsley, Jouni Högander
+ *
+ * This file contains clockdomains and clockdomain wakeup dependencies
+ * for OMAP2xxx chips.  Some notes:
+ *
+ * A useful validation rule for struct clockdomain: Any clockdomain
+ * referenced by a wkdep_srcs must have a dep_bit assigned.  So
+ * wkdep_srcs are really just software-controllable dependencies.
+ * Non-software-controllable dependencies do exist, but they are not
+ * encoded below (yet).
+ *
+ * 24xx does not support programmable sleep dependencies (SLEEPDEP)
+ *
+ * The overly-specific dep_bit names are due to a bit name collision
+ * with CM_FCLKEN_{DSP,IVA2}.  The DSP/IVA2 PM_WKDEP and CM_SLEEPDEP shift
+ * value are the same for all powerdomains: 2
+ *
+ * XXX should dep_bit be a mask, so we can test to see if it is 0 as a
+ * sanity check?
+ * XXX encode hardware fixed wakeup dependencies -- esp. for 3430 CORE
+ */
+
+/*
+ * To-Do List
+ * -> Port the Sleep/Wakeup dependencies for the domains
+ *    from the Power domain framework
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+#include "clockdomain.h"
+#include "prm2xxx_3xxx.h"
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-24xx.h"
+#include "prm-regbits-24xx.h"
+
+/*
+ * Clockdomain dependencies for wkdeps
+ *
+ * XXX Hardware dependencies (e.g., dependencies that cannot be
+ * changed in software) are not included here yet, but should be.
+ */
+
+/* Wakeup dependency source arrays */
+
+/* 2430-specific possible wakeup dependencies */
+
+/* 2430 PM_WKDEP_CORE: DSP, GFX, MPU, WKUP, MDM */
+static struct clkdm_dep core_2430_wkdeps[] = {
+	{ .clkdm_name = "dsp_clkdm" },
+	{ .clkdm_name = "gfx_clkdm" },
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
+	{ .clkdm_name = "mdm_clkdm" },
+	{ NULL },
+};
+
+/* 2430 PM_WKDEP_MPU: CORE, DSP, WKUP, MDM */
+static struct clkdm_dep mpu_2430_wkdeps[] = {
+	{ .clkdm_name = "core_l3_clkdm" },
+	{ .clkdm_name = "core_l4_clkdm" },
+	{ .clkdm_name = "dsp_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
+	{ .clkdm_name = "mdm_clkdm" },
+	{ NULL },
+};
+
+/* 2430 PM_WKDEP_MDM: CORE, MPU, WKUP */
+static struct clkdm_dep mdm_2430_wkdeps[] = {
+	{ .clkdm_name = "core_l3_clkdm" },
+	{ .clkdm_name = "core_l4_clkdm" },
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
+	{ NULL },
+};
+
+/*
+ * 2430-only clockdomains
+ */
+
+static struct clockdomain mpu_2430_clkdm = {
+	.name		= "mpu_clkdm",
+	.pwrdm		= { .name = "mpu_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.wkdep_srcs	= mpu_2430_wkdeps,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK,
+};
+
+/* Another case of bit name collisions between several registers: EN_MDM */
+static struct clockdomain mdm_clkdm = {
+	.name		= "mdm_clkdm",
+	.pwrdm		= { .name = "mdm_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.dep_bit	= OMAP2430_PM_WKDEP_MPU_EN_MDM_SHIFT,
+	.wkdep_srcs	= mdm_2430_wkdeps,
+	.clktrctrl_mask = OMAP2430_AUTOSTATE_MDM_MASK,
+};
+
+static struct clockdomain dsp_2430_clkdm = {
+	.name		= "dsp_clkdm",
+	.pwrdm		= { .name = "dsp_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.dep_bit	= OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT,
+	.wkdep_srcs	= dsp_24xx_wkdeps,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSP_MASK,
+};
+
+static struct clockdomain gfx_2430_clkdm = {
+	.name		= "gfx_clkdm",
+	.pwrdm		= { .name = "gfx_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.wkdep_srcs	= gfx_24xx_wkdeps,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_GFX_MASK,
+};
+
+/*
+ * XXX add usecounting for clkdm dependencies, otherwise the presence
+ * of a single dep bit for core_l3_24xx_clkdm and core_l4_24xx_clkdm
+ * could cause trouble
+ */
+static struct clockdomain core_l3_2430_clkdm = {
+	.name		= "core_l3_clkdm",
+	.pwrdm		= { .name = "core_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP,
+	.dep_bit	= OMAP24XX_EN_CORE_SHIFT,
+	.wkdep_srcs	= core_2430_wkdeps,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_L3_MASK,
+};
+
+/*
+ * XXX add usecounting for clkdm dependencies, otherwise the presence
+ * of a single dep bit for core_l3_24xx_clkdm and core_l4_24xx_clkdm
+ * could cause trouble
+ */
+static struct clockdomain core_l4_2430_clkdm = {
+	.name		= "core_l4_clkdm",
+	.pwrdm		= { .name = "core_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP,
+	.dep_bit	= OMAP24XX_EN_CORE_SHIFT,
+	.wkdep_srcs	= core_2430_wkdeps,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_L4_MASK,
+};
+
+static struct clockdomain dss_2430_clkdm = {
+	.name		= "dss_clkdm",
+	.pwrdm		= { .name = "core_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP,
+	.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSS_MASK,
+};
+
+static struct clockdomain *clockdomains_omap243x[] __initdata = {
+	&wkup_common_clkdm,
+	&cm_common_clkdm,
+	&prm_common_clkdm,
+	&mpu_2430_clkdm,
+	&mdm_clkdm,
+	&dsp_2430_clkdm,
+	&gfx_2430_clkdm,
+	&core_l3_2430_clkdm,
+	&core_l4_2430_clkdm,
+	&dss_2430_clkdm,
+	NULL,
+};
+
+void __init omap243x_clockdomains_init(void)
+{
+	if (!cpu_is_omap243x())
+		return;
+
+	clkdm_register_platform_funcs(&omap2_clkdm_operations);
+	clkdm_register_clkdms(clockdomains_omap243x);
+	clkdm_complete_init();
+}
+
diff --git a/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c b/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c
index 13bde95..0a6a048 100644
--- a/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c
+++ b/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c
@@ -1,7 +1,7 @@
 /*
- * OMAP2/3 clockdomains
+ * OMAP2/3 clockdomain common data
  *
- * Copyright (C) 2008-2009 Texas Instruments, Inc.
+ * Copyright (C) 2008-2011 Texas Instruments, Inc.
  * Copyright (C) 2008-2010 Nokia Corporation
  *
  * Paul Walmsley, Jouni Högander
@@ -51,374 +51,28 @@
  * changed in software) are not included here yet, but should be.
  */
 
-/* OMAP2/3-common wakeup dependencies */
-
-/*
- * 2420/2430 PM_WKDEP_GFX: CORE, MPU, WKUP
- * 3430ES1 PM_WKDEP_GFX: adds IVA2, removes CORE
- * 3430ES2 PM_WKDEP_SGX: adds IVA2, removes CORE
- * These can share data since they will never be present simultaneously
- * on the same device.
- */
-static struct clkdm_dep gfx_sgx_wkdeps[] = {
-	{
-		.clkdm_name = "core_l3_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "core_l4_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "iva2_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
-					    CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "wkup_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
-					    CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-
-/* 24XX-specific possible dependencies */
-
-#ifdef CONFIG_ARCH_OMAP2
-
 /* Wakeup dependency source arrays */
 
-/* 2420/2430 PM_WKDEP_DSP: CORE, MPU, WKUP */
-static struct clkdm_dep dsp_24xx_wkdeps[] = {
-	{
-		.clkdm_name = "core_l3_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "core_l4_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "wkup_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{ NULL },
-};
-
-/*
- * 2420 PM_WKDEP_MPU: CORE, DSP, WKUP
- * 2430 adds MDM
- */
-static struct clkdm_dep mpu_24xx_wkdeps[] = {
-	{
-		.clkdm_name = "core_l3_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "core_l4_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "dsp_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "wkup_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "mdm_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
-	},
-	{ NULL },
-};
-
-/*
- * 2420 PM_WKDEP_CORE: DSP, GFX, MPU, WKUP
- * 2430 adds MDM
- */
-static struct clkdm_dep core_24xx_wkdeps[] = {
-	{
-		.clkdm_name = "dsp_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "gfx_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "wkup_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "mdm_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
-	},
-	{ NULL },
-};
-
-#endif /* CONFIG_ARCH_OMAP2 */
-
-/* 2430-specific possible wakeup dependencies */
+/* 2xxx-specific possible dependencies */
 
-#ifdef CONFIG_SOC_OMAP2430
-
-/* 2430 PM_WKDEP_MDM: CORE, MPU, WKUP */
-static struct clkdm_dep mdm_2430_wkdeps[] = {
-	{
-		.clkdm_name = "core_l3_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "core_l4_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.clkdm_name = "wkup_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{ NULL },
-};
-
-#endif /* CONFIG_SOC_OMAP2430 */
-
-
-/* OMAP3-specific possible dependencies */
-
-#ifdef CONFIG_ARCH_OMAP3
-
-/* 3430: PM_WKDEP_PER: CORE, IVA2, MPU, WKUP */
-static struct clkdm_dep per_wkdeps[] = {
-	{
-		.clkdm_name = "core_l3_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "core_l4_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "iva2_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "wkup_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-/* 3430ES2: PM_WKDEP_USBHOST: CORE, IVA2, MPU, WKUP */
-static struct clkdm_dep usbhost_wkdeps[] = {
-	{
-		.clkdm_name = "core_l3_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "core_l4_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "iva2_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "wkup_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
+/* 2xxx PM_WKDEP_GFX: CORE, MPU, WKUP */
+struct clkdm_dep gfx_24xx_wkdeps[] = {
+	{ .clkdm_name = "core_l3_clkdm" },
+	{ .clkdm_name = "core_l4_clkdm" },
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
 	{ NULL },
 };
 
-/* 3430 PM_WKDEP_MPU: CORE, IVA2, DSS, PER */
-static struct clkdm_dep mpu_3xxx_wkdeps[] = {
-	{
-		.clkdm_name = "core_l3_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "core_l4_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "iva2_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "dss_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "per_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
+/* 2xxx PM_WKDEP_DSP: CORE, MPU, WKUP */
+struct clkdm_dep dsp_24xx_wkdeps[] = {
+	{ .clkdm_name = "core_l3_clkdm" },
+	{ .clkdm_name = "core_l4_clkdm" },
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
 	{ NULL },
 };
 
-/* 3430 PM_WKDEP_IVA2: CORE, MPU, WKUP, DSS, PER */
-static struct clkdm_dep iva2_wkdeps[] = {
-	{
-		.clkdm_name = "core_l3_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "core_l4_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "wkup_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "dss_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "per_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-
-/* 3430 PM_WKDEP_CAM: IVA2, MPU, WKUP */
-static struct clkdm_dep cam_wkdeps[] = {
-	{
-		.clkdm_name = "iva2_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "wkup_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-/* 3430 PM_WKDEP_DSS: IVA2, MPU, WKUP */
-static struct clkdm_dep dss_wkdeps[] = {
-	{
-		.clkdm_name = "iva2_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "wkup_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-/* 3430: PM_WKDEP_NEON: MPU */
-static struct clkdm_dep neon_wkdeps[] = {
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-
-/* Sleep dependency source arrays for OMAP3-specific clkdms */
-
-/* 3430: CM_SLEEPDEP_DSS: MPU, IVA */
-static struct clkdm_dep dss_sleepdeps[] = {
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "iva2_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-/* 3430: CM_SLEEPDEP_PER: MPU, IVA */
-static struct clkdm_dep per_sleepdeps[] = {
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "iva2_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-/* 3430ES2: CM_SLEEPDEP_USBHOST: MPU, IVA */
-static struct clkdm_dep usbhost_sleepdeps[] = {
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm_name = "iva2_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-/* 3430: CM_SLEEPDEP_CAM: MPU */
-static struct clkdm_dep cam_sleepdeps[] = {
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-/*
- * 3430ES1: CM_SLEEPDEP_GFX: MPU
- * 3430ES2: CM_SLEEPDEP_SGX: MPU
- * These can share data since they will never be present simultaneously
- * on the same device.
- */
-static struct clkdm_dep gfx_sgx_sleepdeps[] = {
-	{
-		.clkdm_name = "mpu_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-#endif /* CONFIG_ARCH_OMAP3 */
-
 
 /*
  * OMAP2/3-common clockdomains
@@ -430,439 +84,18 @@ static struct clkdm_dep gfx_sgx_sleepdeps[] = {
  */
 
 /* This is an implicit clockdomain - it is never defined as such in TRM */
-static struct clockdomain wkup_clkdm = {
+struct clockdomain wkup_common_clkdm = {
 	.name		= "wkup_clkdm",
 	.pwrdm		= { .name = "wkup_pwrdm" },
 	.dep_bit	= OMAP_EN_WKUP_SHIFT,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
 };
 
-static struct clockdomain prm_clkdm = {
+struct clockdomain prm_common_clkdm = {
 	.name		= "prm_clkdm",
 	.pwrdm		= { .name = "wkup_pwrdm" },
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
 };
 
-static struct clockdomain cm_clkdm = {
+struct clockdomain cm_common_clkdm = {
 	.name		= "cm_clkdm",
 	.pwrdm		= { .name = "core_pwrdm" },
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
 };
-
-/*
- * 2420-only clockdomains
- */
-
-#if defined(CONFIG_SOC_OMAP2420)
-
-static struct clockdomain mpu_2420_clkdm = {
-	.name		= "mpu_clkdm",
-	.pwrdm		= { .name = "mpu_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP,
-	.wkdep_srcs	= mpu_24xx_wkdeps,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-};
-
-static struct clockdomain iva1_2420_clkdm = {
-	.name		= "iva1_clkdm",
-	.pwrdm		= { .name = "dsp_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.dep_bit	= OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT,
-	.wkdep_srcs	= dsp_24xx_wkdeps,
-	.clktrctrl_mask = OMAP2420_AUTOSTATE_IVA_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-};
-
-static struct clockdomain dsp_2420_clkdm = {
-	.name		= "dsp_clkdm",
-	.pwrdm		= { .name = "dsp_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSP_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-};
-
-static struct clockdomain gfx_2420_clkdm = {
-	.name		= "gfx_clkdm",
-	.pwrdm		= { .name = "gfx_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.wkdep_srcs	= gfx_sgx_wkdeps,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_GFX_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-};
-
-static struct clockdomain core_l3_2420_clkdm = {
-	.name		= "core_l3_clkdm",
-	.pwrdm		= { .name = "core_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP,
-	.wkdep_srcs	= core_24xx_wkdeps,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_L3_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-};
-
-static struct clockdomain core_l4_2420_clkdm = {
-	.name		= "core_l4_clkdm",
-	.pwrdm		= { .name = "core_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP,
-	.wkdep_srcs	= core_24xx_wkdeps,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_L4_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-};
-
-static struct clockdomain dss_2420_clkdm = {
-	.name		= "dss_clkdm",
-	.pwrdm		= { .name = "core_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSS_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-};
-
-#endif   /* CONFIG_SOC_OMAP2420 */
-
-
-/*
- * 2430-only clockdomains
- */
-
-#if defined(CONFIG_SOC_OMAP2430)
-
-static struct clockdomain mpu_2430_clkdm = {
-	.name		= "mpu_clkdm",
-	.pwrdm		= { .name = "mpu_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.wkdep_srcs	= mpu_24xx_wkdeps,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-};
-
-/* Another case of bit name collisions between several registers: EN_MDM */
-static struct clockdomain mdm_clkdm = {
-	.name		= "mdm_clkdm",
-	.pwrdm		= { .name = "mdm_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.dep_bit	= OMAP2430_PM_WKDEP_MPU_EN_MDM_SHIFT,
-	.wkdep_srcs	= mdm_2430_wkdeps,
-	.clktrctrl_mask = OMAP2430_AUTOSTATE_MDM_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-};
-
-static struct clockdomain dsp_2430_clkdm = {
-	.name		= "dsp_clkdm",
-	.pwrdm		= { .name = "dsp_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.dep_bit	= OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT,
-	.wkdep_srcs	= dsp_24xx_wkdeps,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSP_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-};
-
-static struct clockdomain gfx_2430_clkdm = {
-	.name		= "gfx_clkdm",
-	.pwrdm		= { .name = "gfx_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.wkdep_srcs	= gfx_sgx_wkdeps,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_GFX_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-};
-
-/*
- * XXX add usecounting for clkdm dependencies, otherwise the presence
- * of a single dep bit for core_l3_24xx_clkdm and core_l4_24xx_clkdm
- * could cause trouble
- */
-static struct clockdomain core_l3_2430_clkdm = {
-	.name		= "core_l3_clkdm",
-	.pwrdm		= { .name = "core_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP,
-	.dep_bit	= OMAP24XX_EN_CORE_SHIFT,
-	.wkdep_srcs	= core_24xx_wkdeps,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_L3_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-};
-
-/*
- * XXX add usecounting for clkdm dependencies, otherwise the presence
- * of a single dep bit for core_l3_24xx_clkdm and core_l4_24xx_clkdm
- * could cause trouble
- */
-static struct clockdomain core_l4_2430_clkdm = {
-	.name		= "core_l4_clkdm",
-	.pwrdm		= { .name = "core_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP,
-	.dep_bit	= OMAP24XX_EN_CORE_SHIFT,
-	.wkdep_srcs	= core_24xx_wkdeps,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_L4_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-};
-
-static struct clockdomain dss_2430_clkdm = {
-	.name		= "dss_clkdm",
-	.pwrdm		= { .name = "core_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP,
-	.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSS_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-};
-
-#endif    /* CONFIG_SOC_OMAP2430 */
-
-
-/*
- * OMAP3 clockdomains
- */
-
-#if defined(CONFIG_ARCH_OMAP3)
-
-static struct clockdomain mpu_3xxx_clkdm = {
-	.name		= "mpu_clkdm",
-	.pwrdm		= { .name = "mpu_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP | CLKDM_CAN_FORCE_WAKEUP,
-	.dep_bit	= OMAP3430_EN_MPU_SHIFT,
-	.wkdep_srcs	= mpu_3xxx_wkdeps,
-	.clktrctrl_mask = OMAP3430_CLKTRCTRL_MPU_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain neon_clkdm = {
-	.name		= "neon_clkdm",
-	.pwrdm		= { .name = "neon_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.wkdep_srcs	= neon_wkdeps,
-	.clktrctrl_mask = OMAP3430_CLKTRCTRL_NEON_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain iva2_clkdm = {
-	.name		= "iva2_clkdm",
-	.pwrdm		= { .name = "iva2_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.dep_bit	= OMAP3430_PM_WKDEP_MPU_EN_IVA2_SHIFT,
-	.wkdep_srcs	= iva2_wkdeps,
-	.clktrctrl_mask = OMAP3430_CLKTRCTRL_IVA2_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain gfx_3430es1_clkdm = {
-	.name		= "gfx_clkdm",
-	.pwrdm		= { .name = "gfx_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.wkdep_srcs	= gfx_sgx_wkdeps,
-	.sleepdep_srcs	= gfx_sgx_sleepdeps,
-	.clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_GFX_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1),
-};
-
-static struct clockdomain sgx_clkdm = {
-	.name		= "sgx_clkdm",
-	.pwrdm		= { .name = "sgx_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.wkdep_srcs	= gfx_sgx_wkdeps,
-	.sleepdep_srcs	= gfx_sgx_sleepdeps,
-	.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
-};
-
-/*
- * The die-to-die clockdomain was documented in the 34xx ES1 TRM, but
- * then that information was removed from the 34xx ES2+ TRM.  It is
- * unclear whether the core is still there, but the clockdomain logic
- * is there, and must be programmed to an appropriate state if the
- * CORE clockdomain is to become inactive.
- */
-static struct clockdomain d2d_clkdm = {
-	.name		= "d2d_clkdm",
-	.pwrdm		= { .name = "core_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_D2D_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-/*
- * XXX add usecounting for clkdm dependencies, otherwise the presence
- * of a single dep bit for core_l3_3xxx_clkdm and core_l4_3xxx_clkdm
- * could cause trouble
- */
-static struct clockdomain core_l3_3xxx_clkdm = {
-	.name		= "core_l3_clkdm",
-	.pwrdm		= { .name = "core_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP,
-	.dep_bit	= OMAP3430_EN_CORE_SHIFT,
-	.clktrctrl_mask = OMAP3430_CLKTRCTRL_L3_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-/*
- * XXX add usecounting for clkdm dependencies, otherwise the presence
- * of a single dep bit for core_l3_3xxx_clkdm and core_l4_3xxx_clkdm
- * could cause trouble
- */
-static struct clockdomain core_l4_3xxx_clkdm = {
-	.name		= "core_l4_clkdm",
-	.pwrdm		= { .name = "core_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP,
-	.dep_bit	= OMAP3430_EN_CORE_SHIFT,
-	.clktrctrl_mask = OMAP3430_CLKTRCTRL_L4_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-/* Another case of bit name collisions between several registers: EN_DSS */
-static struct clockdomain dss_3xxx_clkdm = {
-	.name		= "dss_clkdm",
-	.pwrdm		= { .name = "dss_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.dep_bit	= OMAP3430_PM_WKDEP_MPU_EN_DSS_SHIFT,
-	.wkdep_srcs	= dss_wkdeps,
-	.sleepdep_srcs	= dss_sleepdeps,
-	.clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain cam_clkdm = {
-	.name		= "cam_clkdm",
-	.pwrdm		= { .name = "cam_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.wkdep_srcs	= cam_wkdeps,
-	.sleepdep_srcs	= cam_sleepdeps,
-	.clktrctrl_mask = OMAP3430_CLKTRCTRL_CAM_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain usbhost_clkdm = {
-	.name		= "usbhost_clkdm",
-	.pwrdm		= { .name = "usbhost_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.wkdep_srcs	= usbhost_wkdeps,
-	.sleepdep_srcs	= usbhost_sleepdeps,
-	.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_USBHOST_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
-};
-
-static struct clockdomain per_clkdm = {
-	.name		= "per_clkdm",
-	.pwrdm		= { .name = "per_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
-	.dep_bit	= OMAP3430_EN_PER_SHIFT,
-	.wkdep_srcs	= per_wkdeps,
-	.sleepdep_srcs	= per_sleepdeps,
-	.clktrctrl_mask = OMAP3430_CLKTRCTRL_PER_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-/*
- * Disable hw supervised mode for emu_clkdm, because emu_pwrdm is
- * switched of even if sdti is in use
- */
-static struct clockdomain emu_clkdm = {
-	.name		= "emu_clkdm",
-	.pwrdm		= { .name = "emu_pwrdm" },
-	.flags		= /* CLKDM_CAN_ENABLE_AUTO |  */CLKDM_CAN_SWSUP,
-	.clktrctrl_mask = OMAP3430_CLKTRCTRL_EMU_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain dpll1_clkdm = {
-	.name		= "dpll1_clkdm",
-	.pwrdm		= { .name = "dpll1_pwrdm" },
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain dpll2_clkdm = {
-	.name		= "dpll2_clkdm",
-	.pwrdm		= { .name = "dpll2_pwrdm" },
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain dpll3_clkdm = {
-	.name		= "dpll3_clkdm",
-	.pwrdm		= { .name = "dpll3_pwrdm" },
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain dpll4_clkdm = {
-	.name		= "dpll4_clkdm",
-	.pwrdm		= { .name = "dpll4_pwrdm" },
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-static struct clockdomain dpll5_clkdm = {
-	.name		= "dpll5_clkdm",
-	.pwrdm		= { .name = "dpll5_pwrdm" },
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
-};
-
-#endif   /* CONFIG_ARCH_OMAP3 */
-
-/*
- * Clockdomain hwsup dependencies (OMAP3 only)
- */
-
-static struct clkdm_autodep clkdm_autodeps[] = {
-	{
-		.clkdm	   = { .name = "mpu_clkdm" },
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm	   = { .name = "iva2_clkdm" },
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.clkdm	   = { .name = NULL },
-	}
-};
-
-static struct clockdomain *clockdomains_omap2[] __initdata = {
-	&wkup_clkdm,
-	&cm_clkdm,
-	&prm_clkdm,
-
-#ifdef CONFIG_SOC_OMAP2420
-	&mpu_2420_clkdm,
-	&iva1_2420_clkdm,
-	&dsp_2420_clkdm,
-	&gfx_2420_clkdm,
-	&core_l3_2420_clkdm,
-	&core_l4_2420_clkdm,
-	&dss_2420_clkdm,
-#endif
-
-#ifdef CONFIG_SOC_OMAP2430
-	&mpu_2430_clkdm,
-	&mdm_clkdm,
-	&dsp_2430_clkdm,
-	&gfx_2430_clkdm,
-	&core_l3_2430_clkdm,
-	&core_l4_2430_clkdm,
-	&dss_2430_clkdm,
-#endif
-
-#ifdef CONFIG_ARCH_OMAP3
-	&mpu_3xxx_clkdm,
-	&neon_clkdm,
-	&iva2_clkdm,
-	&gfx_3430es1_clkdm,
-	&sgx_clkdm,
-	&d2d_clkdm,
-	&core_l3_3xxx_clkdm,
-	&core_l4_3xxx_clkdm,
-	&dss_3xxx_clkdm,
-	&cam_clkdm,
-	&usbhost_clkdm,
-	&per_clkdm,
-	&emu_clkdm,
-	&dpll1_clkdm,
-	&dpll2_clkdm,
-	&dpll3_clkdm,
-	&dpll4_clkdm,
-	&dpll5_clkdm,
-#endif
-	NULL,
-};
-
-void __init omap2xxx_clockdomains_init(void)
-{
-	clkdm_init(clockdomains_omap2, clkdm_autodeps, &omap2_clkdm_operations);
-}
-
-void __init omap3xxx_clockdomains_init(void)
-{
-	clkdm_init(clockdomains_omap2, clkdm_autodeps, &omap3_clkdm_operations);
-}
diff --git a/arch/arm/mach-omap2/clockdomains3xxx_data.c b/arch/arm/mach-omap2/clockdomains3xxx_data.c
new file mode 100644
index 0000000..b84e138
--- /dev/null
+++ b/arch/arm/mach-omap2/clockdomains3xxx_data.c
@@ -0,0 +1,398 @@
+/*
+ * OMAP3xxx clockdomains
+ *
+ * Copyright (C) 2008-2011 Texas Instruments, Inc.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Paul Walmsley, Jouni Högander
+ *
+ * This file contains clockdomains and clockdomain wakeup/sleep
+ * dependencies for the OMAP3xxx chips.  Some notes:
+ *
+ * A useful validation rule for struct clockdomain: Any clockdomain
+ * referenced by a wkdep_srcs or sleepdep_srcs array must have a
+ * dep_bit assigned.  So wkdep_srcs/sleepdep_srcs are really just
+ * software-controllable dependencies.  Non-software-controllable
+ * dependencies do exist, but they are not encoded below (yet).
+ *
+ * The overly-specific dep_bit names are due to a bit name collision
+ * with CM_FCLKEN_{DSP,IVA2}.  The DSP/IVA2 PM_WKDEP and CM_SLEEPDEP shift
+ * value are the same for all powerdomains: 2
+ *
+ * XXX should dep_bit be a mask, so we can test to see if it is 0 as a
+ * sanity check?
+ * XXX encode hardware fixed wakeup dependencies -- esp. for 3430 CORE
+ */
+
+/*
+ * To-Do List
+ * -> Port the Sleep/Wakeup dependencies for the domains
+ *    from the Power domain framework
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+#include "clockdomain.h"
+#include "prm2xxx_3xxx.h"
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-34xx.h"
+#include "prm-regbits-34xx.h"
+
+/*
+ * Clockdomain dependencies for wkdeps/sleepdeps
+ *
+ * XXX Hardware dependencies (e.g., dependencies that cannot be
+ * changed in software) are not included here yet, but should be.
+ */
+
+/* OMAP3-specific possible dependencies */
+
+/*
+ * 3430ES1 PM_WKDEP_GFX: adds IVA2, removes CORE
+ * 3430ES2 PM_WKDEP_SGX: adds IVA2, removes CORE
+ */
+static struct clkdm_dep gfx_sgx_3xxx_wkdeps[] = {
+	{ .clkdm_name = "iva2_clkdm", },
+	{ .clkdm_name = "mpu_clkdm", },
+	{ .clkdm_name = "wkup_clkdm", },
+	{ NULL },
+};
+
+/* 3430: PM_WKDEP_PER: CORE, IVA2, MPU, WKUP */
+static struct clkdm_dep per_wkdeps[] = {
+	{ .clkdm_name = "core_l3_clkdm" },
+	{ .clkdm_name = "core_l4_clkdm" },
+	{ .clkdm_name = "iva2_clkdm" },
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
+	{ NULL },
+};
+
+/* 3430ES2: PM_WKDEP_USBHOST: CORE, IVA2, MPU, WKUP */
+static struct clkdm_dep usbhost_wkdeps[] = {
+	{ .clkdm_name = "core_l3_clkdm" },
+	{ .clkdm_name = "core_l4_clkdm" },
+	{ .clkdm_name = "iva2_clkdm" },
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
+	{ NULL },
+};
+
+/* 3430 PM_WKDEP_MPU: CORE, IVA2, DSS, PER */
+static struct clkdm_dep mpu_3xxx_wkdeps[] = {
+	{ .clkdm_name = "core_l3_clkdm" },
+	{ .clkdm_name = "core_l4_clkdm" },
+	{ .clkdm_name = "iva2_clkdm" },
+	{ .clkdm_name = "dss_clkdm" },
+	{ .clkdm_name = "per_clkdm" },
+	{ NULL },
+};
+
+/* 3430 PM_WKDEP_IVA2: CORE, MPU, WKUP, DSS, PER */
+static struct clkdm_dep iva2_wkdeps[] = {
+	{ .clkdm_name = "core_l3_clkdm" },
+	{ .clkdm_name = "core_l4_clkdm" },
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
+	{ .clkdm_name = "dss_clkdm" },
+	{ .clkdm_name = "per_clkdm" },
+	{ NULL },
+};
+
+/* 3430 PM_WKDEP_CAM: IVA2, MPU, WKUP */
+static struct clkdm_dep cam_wkdeps[] = {
+	{ .clkdm_name = "iva2_clkdm" },
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
+	{ NULL },
+};
+
+/* 3430 PM_WKDEP_DSS: IVA2, MPU, WKUP */
+static struct clkdm_dep dss_wkdeps[] = {
+	{ .clkdm_name = "iva2_clkdm" },
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "wkup_clkdm" },
+	{ NULL },
+};
+
+/* 3430: PM_WKDEP_NEON: MPU */
+static struct clkdm_dep neon_wkdeps[] = {
+	{ .clkdm_name = "mpu_clkdm" },
+	{ NULL },
+};
+
+/* Sleep dependency source arrays for OMAP3-specific clkdms */
+
+/* 3430: CM_SLEEPDEP_DSS: MPU, IVA */
+static struct clkdm_dep dss_sleepdeps[] = {
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "iva2_clkdm" },
+	{ NULL },
+};
+
+/* 3430: CM_SLEEPDEP_PER: MPU, IVA */
+static struct clkdm_dep per_sleepdeps[] = {
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "iva2_clkdm" },
+	{ NULL },
+};
+
+/* 3430ES2: CM_SLEEPDEP_USBHOST: MPU, IVA */
+static struct clkdm_dep usbhost_sleepdeps[] = {
+	{ .clkdm_name = "mpu_clkdm" },
+	{ .clkdm_name = "iva2_clkdm" },
+	{ NULL },
+};
+
+/* 3430: CM_SLEEPDEP_CAM: MPU */
+static struct clkdm_dep cam_sleepdeps[] = {
+	{ .clkdm_name = "mpu_clkdm" },
+	{ NULL },
+};
+
+/*
+ * 3430ES1: CM_SLEEPDEP_GFX: MPU
+ * 3430ES2: CM_SLEEPDEP_SGX: MPU
+ * These can share data since they will never be present simultaneously
+ * on the same device.
+ */
+static struct clkdm_dep gfx_sgx_sleepdeps[] = {
+	{ .clkdm_name = "mpu_clkdm" },
+	{ NULL },
+};
+
+/*
+ * OMAP3 clockdomains
+ */
+
+static struct clockdomain mpu_3xxx_clkdm = {
+	.name		= "mpu_clkdm",
+	.pwrdm		= { .name = "mpu_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP | CLKDM_CAN_FORCE_WAKEUP,
+	.dep_bit	= OMAP3430_EN_MPU_SHIFT,
+	.wkdep_srcs	= mpu_3xxx_wkdeps,
+	.clktrctrl_mask = OMAP3430_CLKTRCTRL_MPU_MASK,
+};
+
+static struct clockdomain neon_clkdm = {
+	.name		= "neon_clkdm",
+	.pwrdm		= { .name = "neon_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.wkdep_srcs	= neon_wkdeps,
+	.clktrctrl_mask = OMAP3430_CLKTRCTRL_NEON_MASK,
+};
+
+static struct clockdomain iva2_clkdm = {
+	.name		= "iva2_clkdm",
+	.pwrdm		= { .name = "iva2_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.dep_bit	= OMAP3430_PM_WKDEP_MPU_EN_IVA2_SHIFT,
+	.wkdep_srcs	= iva2_wkdeps,
+	.clktrctrl_mask = OMAP3430_CLKTRCTRL_IVA2_MASK,
+};
+
+static struct clockdomain gfx_3430es1_clkdm = {
+	.name		= "gfx_clkdm",
+	.pwrdm		= { .name = "gfx_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.wkdep_srcs	= gfx_sgx_3xxx_wkdeps,
+	.sleepdep_srcs	= gfx_sgx_sleepdeps,
+	.clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_GFX_MASK,
+};
+
+static struct clockdomain sgx_clkdm = {
+	.name		= "sgx_clkdm",
+	.pwrdm		= { .name = "sgx_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.wkdep_srcs	= gfx_sgx_3xxx_wkdeps,
+	.sleepdep_srcs	= gfx_sgx_sleepdeps,
+	.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK,
+};
+
+/*
+ * The die-to-die clockdomain was documented in the 34xx ES1 TRM, but
+ * then that information was removed from the 34xx ES2+ TRM.  It is
+ * unclear whether the core is still there, but the clockdomain logic
+ * is there, and must be programmed to an appropriate state if the
+ * CORE clockdomain is to become inactive.
+ */
+static struct clockdomain d2d_clkdm = {
+	.name		= "d2d_clkdm",
+	.pwrdm		= { .name = "core_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_D2D_MASK,
+};
+
+/*
+ * XXX add usecounting for clkdm dependencies, otherwise the presence
+ * of a single dep bit for core_l3_3xxx_clkdm and core_l4_3xxx_clkdm
+ * could cause trouble
+ */
+static struct clockdomain core_l3_3xxx_clkdm = {
+	.name		= "core_l3_clkdm",
+	.pwrdm		= { .name = "core_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP,
+	.dep_bit	= OMAP3430_EN_CORE_SHIFT,
+	.clktrctrl_mask = OMAP3430_CLKTRCTRL_L3_MASK,
+};
+
+/*
+ * XXX add usecounting for clkdm dependencies, otherwise the presence
+ * of a single dep bit for core_l3_3xxx_clkdm and core_l4_3xxx_clkdm
+ * could cause trouble
+ */
+static struct clockdomain core_l4_3xxx_clkdm = {
+	.name		= "core_l4_clkdm",
+	.pwrdm		= { .name = "core_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP,
+	.dep_bit	= OMAP3430_EN_CORE_SHIFT,
+	.clktrctrl_mask = OMAP3430_CLKTRCTRL_L4_MASK,
+};
+
+/* Another case of bit name collisions between several registers: EN_DSS */
+static struct clockdomain dss_3xxx_clkdm = {
+	.name		= "dss_clkdm",
+	.pwrdm		= { .name = "dss_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.dep_bit	= OMAP3430_PM_WKDEP_MPU_EN_DSS_SHIFT,
+	.wkdep_srcs	= dss_wkdeps,
+	.sleepdep_srcs	= dss_sleepdeps,
+	.clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK,
+};
+
+static struct clockdomain cam_clkdm = {
+	.name		= "cam_clkdm",
+	.pwrdm		= { .name = "cam_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.wkdep_srcs	= cam_wkdeps,
+	.sleepdep_srcs	= cam_sleepdeps,
+	.clktrctrl_mask = OMAP3430_CLKTRCTRL_CAM_MASK,
+};
+
+static struct clockdomain usbhost_clkdm = {
+	.name		= "usbhost_clkdm",
+	.pwrdm		= { .name = "usbhost_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.wkdep_srcs	= usbhost_wkdeps,
+	.sleepdep_srcs	= usbhost_sleepdeps,
+	.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_USBHOST_MASK,
+};
+
+static struct clockdomain per_clkdm = {
+	.name		= "per_clkdm",
+	.pwrdm		= { .name = "per_pwrdm" },
+	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.dep_bit	= OMAP3430_EN_PER_SHIFT,
+	.wkdep_srcs	= per_wkdeps,
+	.sleepdep_srcs	= per_sleepdeps,
+	.clktrctrl_mask = OMAP3430_CLKTRCTRL_PER_MASK,
+};
+
+/*
+ * Disable hw supervised mode for emu_clkdm, because emu_pwrdm is
+ * switched of even if sdti is in use
+ */
+static struct clockdomain emu_clkdm = {
+	.name		= "emu_clkdm",
+	.pwrdm		= { .name = "emu_pwrdm" },
+	.flags		= /* CLKDM_CAN_ENABLE_AUTO |  */CLKDM_CAN_SWSUP,
+	.clktrctrl_mask = OMAP3430_CLKTRCTRL_EMU_MASK,
+};
+
+static struct clockdomain dpll1_clkdm = {
+	.name		= "dpll1_clkdm",
+	.pwrdm		= { .name = "dpll1_pwrdm" },
+};
+
+static struct clockdomain dpll2_clkdm = {
+	.name		= "dpll2_clkdm",
+	.pwrdm		= { .name = "dpll2_pwrdm" },
+};
+
+static struct clockdomain dpll3_clkdm = {
+	.name		= "dpll3_clkdm",
+	.pwrdm		= { .name = "dpll3_pwrdm" },
+};
+
+static struct clockdomain dpll4_clkdm = {
+	.name		= "dpll4_clkdm",
+	.pwrdm		= { .name = "dpll4_pwrdm" },
+};
+
+static struct clockdomain dpll5_clkdm = {
+	.name		= "dpll5_clkdm",
+	.pwrdm		= { .name = "dpll5_pwrdm" },
+};
+
+/*
+ * Clockdomain hwsup dependencies
+ */
+
+static struct clkdm_autodep clkdm_autodeps[] = {
+	{
+		.clkdm = { .name = "mpu_clkdm" },
+	},
+	{
+		.clkdm = { .name = "iva2_clkdm" },
+	},
+	{
+		.clkdm = { .name = NULL },
+	}
+};
+
+/*
+ *
+ */
+
+static struct clockdomain *clockdomains_omap3430_common[] __initdata = {
+	&wkup_common_clkdm,
+	&cm_common_clkdm,
+	&prm_common_clkdm,
+	&mpu_3xxx_clkdm,
+	&neon_clkdm,
+	&iva2_clkdm,
+	&d2d_clkdm,
+	&core_l3_3xxx_clkdm,
+	&core_l4_3xxx_clkdm,
+	&dss_3xxx_clkdm,
+	&cam_clkdm,
+	&per_clkdm,
+	&emu_clkdm,
+	&dpll1_clkdm,
+	&dpll2_clkdm,
+	&dpll3_clkdm,
+	&dpll4_clkdm,
+	NULL
+};
+
+static struct clockdomain *clockdomains_omap3430es1[] __initdata = {
+	&gfx_3430es1_clkdm,
+	NULL,
+};
+
+static struct clockdomain *clockdomains_omap3430es2plus[] __initdata = {
+	&sgx_clkdm,
+	&dpll5_clkdm,
+	&usbhost_clkdm,
+	NULL,
+};
+
+void __init omap3xxx_clockdomains_init(void)
+{
+	struct clockdomain **sc;
+
+	if (!cpu_is_omap34xx())
+		return;
+
+	clkdm_register_platform_funcs(&omap3_clkdm_operations);
+	clkdm_register_clkdms(clockdomains_omap3430_common);
+
+	sc = (omap_rev() == OMAP3430_REV_ES1_0) ? clockdomains_omap3430es1 :
+		clockdomains_omap3430es2plus;
+
+	clkdm_register_clkdms(sc);
+
+	clkdm_register_autodeps(clkdm_autodeps);
+	clkdm_complete_init();
+}
diff --git a/arch/arm/mach-omap2/clockdomains44xx_data.c b/arch/arm/mach-omap2/clockdomains44xx_data.c
index dccc651..9299ac2 100644
--- a/arch/arm/mach-omap2/clockdomains44xx_data.c
+++ b/arch/arm/mach-omap2/clockdomains44xx_data.c
@@ -34,350 +34,122 @@
 /* Static Dependencies for OMAP4 Clock Domains */
 
 static struct clkdm_dep d2d_wkup_sleep_deps[] = {
-	{
-		.clkdm_name	 = "abe_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "ivahd_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_1_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_2_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_emif_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_init_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_cfg_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_per_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
+	{ .clkdm_name = "abe_clkdm" },
+	{ .clkdm_name = "ivahd_clkdm" },
+	{ .clkdm_name = "l3_1_clkdm" },
+	{ .clkdm_name = "l3_2_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
+	{ .clkdm_name = "l3_init_clkdm" },
+	{ .clkdm_name = "l4_cfg_clkdm" },
+	{ .clkdm_name = "l4_per_clkdm" },
 	{ NULL },
 };
 
 static struct clkdm_dep ducati_wkup_sleep_deps[] = {
-	{
-		.clkdm_name	 = "abe_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "ivahd_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_1_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_2_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_dss_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_emif_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_gfx_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_init_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_cfg_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_per_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_secure_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_wkup_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "tesla_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
+	{ .clkdm_name = "abe_clkdm" },
+	{ .clkdm_name = "ivahd_clkdm" },
+	{ .clkdm_name = "l3_1_clkdm" },
+	{ .clkdm_name = "l3_2_clkdm" },
+	{ .clkdm_name = "l3_dss_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
+	{ .clkdm_name = "l3_gfx_clkdm" },
+	{ .clkdm_name = "l3_init_clkdm" },
+	{ .clkdm_name = "l4_cfg_clkdm" },
+	{ .clkdm_name = "l4_per_clkdm" },
+	{ .clkdm_name = "l4_secure_clkdm" },
+	{ .clkdm_name = "l4_wkup_clkdm" },
+	{ .clkdm_name = "tesla_clkdm" },
 	{ NULL },
 };
 
 static struct clkdm_dep iss_wkup_sleep_deps[] = {
-	{
-		.clkdm_name	 = "ivahd_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_1_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_emif_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
+	{ .clkdm_name = "ivahd_clkdm" },
+	{ .clkdm_name = "l3_1_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
 	{ NULL },
 };
 
 static struct clkdm_dep ivahd_wkup_sleep_deps[] = {
-	{
-		.clkdm_name	 = "l3_1_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_emif_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
+	{ .clkdm_name = "l3_1_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
 	{ NULL },
 };
 
 static struct clkdm_dep l3_dma_wkup_sleep_deps[] = {
-	{
-		.clkdm_name	 = "abe_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "ducati_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "ivahd_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_1_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_dss_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_emif_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_init_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_cfg_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_per_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_secure_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_wkup_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
+	{ .clkdm_name = "abe_clkdm" },
+	{ .clkdm_name = "ducati_clkdm" },
+	{ .clkdm_name = "ivahd_clkdm" },
+	{ .clkdm_name = "l3_1_clkdm" },
+	{ .clkdm_name = "l3_dss_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
+	{ .clkdm_name = "l3_init_clkdm" },
+	{ .clkdm_name = "l4_cfg_clkdm" },
+	{ .clkdm_name = "l4_per_clkdm" },
+	{ .clkdm_name = "l4_secure_clkdm" },
+	{ .clkdm_name = "l4_wkup_clkdm" },
 	{ NULL },
 };
 
 static struct clkdm_dep l3_dss_wkup_sleep_deps[] = {
-	{
-		.clkdm_name	 = "ivahd_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_2_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_emif_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
+	{ .clkdm_name = "ivahd_clkdm" },
+	{ .clkdm_name = "l3_2_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
 	{ NULL },
 };
 
 static struct clkdm_dep l3_gfx_wkup_sleep_deps[] = {
-	{
-		.clkdm_name	 = "ivahd_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_1_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_emif_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
+	{ .clkdm_name = "ivahd_clkdm" },
+	{ .clkdm_name = "l3_1_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
 	{ NULL },
 };
 
 static struct clkdm_dep l3_init_wkup_sleep_deps[] = {
-	{
-		.clkdm_name	 = "abe_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "ivahd_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_emif_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_cfg_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_per_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_secure_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_wkup_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
+	{ .clkdm_name = "abe_clkdm" },
+	{ .clkdm_name = "ivahd_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
+	{ .clkdm_name = "l4_cfg_clkdm" },
+	{ .clkdm_name = "l4_per_clkdm" },
+	{ .clkdm_name = "l4_secure_clkdm" },
+	{ .clkdm_name = "l4_wkup_clkdm" },
 	{ NULL },
 };
 
 static struct clkdm_dep l4_secure_wkup_sleep_deps[] = {
-	{
-		.clkdm_name	 = "l3_1_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_emif_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_per_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
+	{ .clkdm_name = "l3_1_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
+	{ .clkdm_name = "l4_per_clkdm" },
 	{ NULL },
 };
 
 static struct clkdm_dep mpu_wkup_sleep_deps[] = {
-	{
-		.clkdm_name	 = "abe_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "ducati_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "ivahd_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_1_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_2_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_dss_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_emif_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_gfx_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_init_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_cfg_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_per_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_secure_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_wkup_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "tesla_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
+	{ .clkdm_name = "abe_clkdm" },
+	{ .clkdm_name = "ducati_clkdm" },
+	{ .clkdm_name = "ivahd_clkdm" },
+	{ .clkdm_name = "l3_1_clkdm" },
+	{ .clkdm_name = "l3_2_clkdm" },
+	{ .clkdm_name = "l3_dss_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
+	{ .clkdm_name = "l3_gfx_clkdm" },
+	{ .clkdm_name = "l3_init_clkdm" },
+	{ .clkdm_name = "l4_cfg_clkdm" },
+	{ .clkdm_name = "l4_per_clkdm" },
+	{ .clkdm_name = "l4_secure_clkdm" },
+	{ .clkdm_name = "l4_wkup_clkdm" },
+	{ .clkdm_name = "tesla_clkdm" },
 	{ NULL },
 };
 
 static struct clkdm_dep tesla_wkup_sleep_deps[] = {
-	{
-		.clkdm_name	 = "abe_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "ivahd_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_1_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_2_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_emif_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l3_init_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_cfg_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_per_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
-	{
-		.clkdm_name	 = "l4_wkup_clkdm",
-		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
-	},
+	{ .clkdm_name = "abe_clkdm" },
+	{ .clkdm_name = "ivahd_clkdm" },
+	{ .clkdm_name = "l3_1_clkdm" },
+	{ .clkdm_name = "l3_2_clkdm" },
+	{ .clkdm_name = "l3_emif_clkdm" },
+	{ .clkdm_name = "l3_init_clkdm" },
+	{ .clkdm_name = "l4_cfg_clkdm" },
+	{ .clkdm_name = "l4_per_clkdm" },
+	{ .clkdm_name = "l4_wkup_clkdm" },
 	{ NULL },
 };
 
@@ -388,7 +160,6 @@ static struct clockdomain l4_cefuse_44xx_clkdm = {
 	.cm_inst	  = OMAP4430_CM2_CEFUSE_INST,
 	.clkdm_offs	  = OMAP4430_CM2_CEFUSE_CEFUSE_CDOFFS,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l4_cfg_44xx_clkdm = {
@@ -399,7 +170,6 @@ static struct clockdomain l4_cfg_44xx_clkdm = {
 	.clkdm_offs	  = OMAP4430_CM2_CORE_L4CFG_CDOFFS,
 	.dep_bit	  = OMAP4430_L4CFG_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain tesla_44xx_clkdm = {
@@ -412,7 +182,6 @@ static struct clockdomain tesla_44xx_clkdm = {
 	.wkdep_srcs	  = tesla_wkup_sleep_deps,
 	.sleepdep_srcs	  = tesla_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l3_gfx_44xx_clkdm = {
@@ -425,7 +194,6 @@ static struct clockdomain l3_gfx_44xx_clkdm = {
 	.wkdep_srcs	  = l3_gfx_wkup_sleep_deps,
 	.sleepdep_srcs	  = l3_gfx_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain ivahd_44xx_clkdm = {
@@ -438,7 +206,6 @@ static struct clockdomain ivahd_44xx_clkdm = {
 	.wkdep_srcs	  = ivahd_wkup_sleep_deps,
 	.sleepdep_srcs	  = ivahd_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l4_secure_44xx_clkdm = {
@@ -451,7 +218,6 @@ static struct clockdomain l4_secure_44xx_clkdm = {
 	.wkdep_srcs	  = l4_secure_wkup_sleep_deps,
 	.sleepdep_srcs	  = l4_secure_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l4_per_44xx_clkdm = {
@@ -462,7 +228,6 @@ static struct clockdomain l4_per_44xx_clkdm = {
 	.clkdm_offs	  = OMAP4430_CM2_L4PER_L4PER_CDOFFS,
 	.dep_bit	  = OMAP4430_L4PER_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain abe_44xx_clkdm = {
@@ -473,7 +238,6 @@ static struct clockdomain abe_44xx_clkdm = {
 	.clkdm_offs	  = OMAP4430_CM1_ABE_ABE_CDOFFS,
 	.dep_bit	  = OMAP4430_ABE_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l3_instr_44xx_clkdm = {
@@ -482,7 +246,6 @@ static struct clockdomain l3_instr_44xx_clkdm = {
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_CORE_INST,
 	.clkdm_offs	  = OMAP4430_CM2_CORE_L3INSTR_CDOFFS,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l3_init_44xx_clkdm = {
@@ -495,7 +258,6 @@ static struct clockdomain l3_init_44xx_clkdm = {
 	.wkdep_srcs	  = l3_init_wkup_sleep_deps,
 	.sleepdep_srcs	  = l3_init_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain d2d_44xx_clkdm = {
@@ -507,7 +269,6 @@ static struct clockdomain d2d_44xx_clkdm = {
 	.wkdep_srcs	  = d2d_wkup_sleep_deps,
 	.sleepdep_srcs	  = d2d_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain mpu0_44xx_clkdm = {
@@ -517,7 +278,6 @@ static struct clockdomain mpu0_44xx_clkdm = {
 	.cm_inst	  = OMAP4430_PRCM_MPU_CPU0_INST,
 	.clkdm_offs	  = OMAP4430_PRCM_MPU_CPU0_CPU0_CDOFFS,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain mpu1_44xx_clkdm = {
@@ -527,7 +287,6 @@ static struct clockdomain mpu1_44xx_clkdm = {
 	.cm_inst	  = OMAP4430_PRCM_MPU_CPU1_INST,
 	.clkdm_offs	  = OMAP4430_PRCM_MPU_CPU1_CPU1_CDOFFS,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l3_emif_44xx_clkdm = {
@@ -538,7 +297,6 @@ static struct clockdomain l3_emif_44xx_clkdm = {
 	.clkdm_offs	  = OMAP4430_CM2_CORE_MEMIF_CDOFFS,
 	.dep_bit	  = OMAP4430_MEMIF_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l4_ao_44xx_clkdm = {
@@ -548,7 +306,6 @@ static struct clockdomain l4_ao_44xx_clkdm = {
 	.cm_inst	  = OMAP4430_CM2_ALWAYS_ON_INST,
 	.clkdm_offs	  = OMAP4430_CM2_ALWAYS_ON_ALWON_CDOFFS,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain ducati_44xx_clkdm = {
@@ -561,7 +318,6 @@ static struct clockdomain ducati_44xx_clkdm = {
 	.wkdep_srcs	  = ducati_wkup_sleep_deps,
 	.sleepdep_srcs	  = ducati_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain mpu_44xx_clkdm = {
@@ -573,7 +329,6 @@ static struct clockdomain mpu_44xx_clkdm = {
 	.wkdep_srcs	  = mpu_wkup_sleep_deps,
 	.sleepdep_srcs	  = mpu_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l3_2_44xx_clkdm = {
@@ -584,7 +339,6 @@ static struct clockdomain l3_2_44xx_clkdm = {
 	.clkdm_offs	  = OMAP4430_CM2_CORE_L3_2_CDOFFS,
 	.dep_bit	  = OMAP4430_L3_2_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l3_1_44xx_clkdm = {
@@ -595,7 +349,6 @@ static struct clockdomain l3_1_44xx_clkdm = {
 	.clkdm_offs	  = OMAP4430_CM2_CORE_L3_1_CDOFFS,
 	.dep_bit	  = OMAP4430_L3_1_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain iss_44xx_clkdm = {
@@ -607,7 +360,6 @@ static struct clockdomain iss_44xx_clkdm = {
 	.wkdep_srcs	  = iss_wkup_sleep_deps,
 	.sleepdep_srcs	  = iss_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l3_dss_44xx_clkdm = {
@@ -620,7 +372,6 @@ static struct clockdomain l3_dss_44xx_clkdm = {
 	.wkdep_srcs	  = l3_dss_wkup_sleep_deps,
 	.sleepdep_srcs	  = l3_dss_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l4_wkup_44xx_clkdm = {
@@ -631,7 +382,6 @@ static struct clockdomain l4_wkup_44xx_clkdm = {
 	.clkdm_offs	  = OMAP4430_PRM_WKUP_CM_WKUP_CDOFFS,
 	.dep_bit	  = OMAP4430_L4WKUP_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain emu_sys_44xx_clkdm = {
@@ -641,7 +391,6 @@ static struct clockdomain emu_sys_44xx_clkdm = {
 	.cm_inst	  = OMAP4430_PRM_EMU_CM_INST,
 	.clkdm_offs	  = OMAP4430_PRM_EMU_CM_EMU_CDOFFS,
 	.flags		  = CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct clockdomain l3_dma_44xx_clkdm = {
@@ -653,7 +402,6 @@ static struct clockdomain l3_dma_44xx_clkdm = {
 	.wkdep_srcs	  = l3_dma_wkup_sleep_deps,
 	.sleepdep_srcs	  = l3_dma_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* As clockdomains are added or removed above, this list must also be changed */
@@ -685,7 +433,10 @@ static struct clockdomain *clockdomains_omap44xx[] __initdata = {
 	NULL
 };
 
+
 void __init omap44xx_clockdomains_init(void)
 {
-	clkdm_init(clockdomains_omap44xx, NULL, &omap4_clkdm_operations);
+	clkdm_register_platform_funcs(&omap4_clkdm_operations);
+	clkdm_register_clkdms(clockdomains_omap44xx);
+	clkdm_complete_init();
 }
diff --git a/arch/arm/mach-omap2/common.c b/arch/arm/mach-omap2/common.c
index 3f20cbb..110e5b9 100644
--- a/arch/arm/mach-omap2/common.c
+++ b/arch/arm/mach-omap2/common.c
@@ -45,17 +45,22 @@ static void __init __omap2_set_globals(struct omap_globals *omap2_globals)
 static struct omap_globals omap242x_globals = {
 	.class	= OMAP242X_CLASS,
 	.tap	= OMAP2_L4_IO_ADDRESS(0x48014000),
-	.sdrc	= OMAP2420_SDRC_BASE,
-	.sms	= OMAP2420_SMS_BASE,
-	.ctrl	= OMAP242X_CTRL_BASE,
-	.prm	= OMAP2420_PRM_BASE,
-	.cm	= OMAP2420_CM_BASE,
+	.sdrc	= OMAP2_L3_IO_ADDRESS(OMAP2420_SDRC_BASE),
+	.sms	= OMAP2_L3_IO_ADDRESS(OMAP2420_SMS_BASE),
+	.ctrl	= OMAP2_L4_IO_ADDRESS(OMAP242X_CTRL_BASE),
+	.prm	= OMAP2_L4_IO_ADDRESS(OMAP2420_PRM_BASE),
+	.cm	= OMAP2_L4_IO_ADDRESS(OMAP2420_CM_BASE),
 };
 
 void __init omap2_set_globals_242x(void)
 {
 	__omap2_set_globals(&omap242x_globals);
 }
+
+void __init omap242x_map_io(void)
+{
+	omap242x_map_common_io();
+}
 #endif
 
 #if defined(CONFIG_SOC_OMAP2430)
@@ -63,17 +68,22 @@ void __init omap2_set_globals_242x(void)
 static struct omap_globals omap243x_globals = {
 	.class	= OMAP243X_CLASS,
 	.tap	= OMAP2_L4_IO_ADDRESS(0x4900a000),
-	.sdrc	= OMAP243X_SDRC_BASE,
-	.sms	= OMAP243X_SMS_BASE,
-	.ctrl	= OMAP243X_CTRL_BASE,
-	.prm	= OMAP2430_PRM_BASE,
-	.cm	= OMAP2430_CM_BASE,
+	.sdrc	= OMAP2_L3_IO_ADDRESS(OMAP243X_SDRC_BASE),
+	.sms	= OMAP2_L3_IO_ADDRESS(OMAP243X_SMS_BASE),
+	.ctrl	= OMAP2_L4_IO_ADDRESS(OMAP243X_CTRL_BASE),
+	.prm	= OMAP2_L4_IO_ADDRESS(OMAP2430_PRM_BASE),
+	.cm	= OMAP2_L4_IO_ADDRESS(OMAP2430_CM_BASE),
 };
 
 void __init omap2_set_globals_243x(void)
 {
 	__omap2_set_globals(&omap243x_globals);
 }
+
+void __init omap243x_map_io(void)
+{
+	omap243x_map_common_io();
+}
 #endif
 
 #if defined(CONFIG_ARCH_OMAP3)
@@ -81,11 +91,11 @@ void __init omap2_set_globals_243x(void)
 static struct omap_globals omap3_globals = {
 	.class	= OMAP343X_CLASS,
 	.tap	= OMAP2_L4_IO_ADDRESS(0x4830A000),
-	.sdrc	= OMAP343X_SDRC_BASE,
-	.sms	= OMAP343X_SMS_BASE,
-	.ctrl	= OMAP343X_CTRL_BASE,
-	.prm	= OMAP3430_PRM_BASE,
-	.cm	= OMAP3430_CM_BASE,
+	.sdrc	= OMAP2_L3_IO_ADDRESS(OMAP343X_SDRC_BASE),
+	.sms	= OMAP2_L3_IO_ADDRESS(OMAP343X_SMS_BASE),
+	.ctrl	= OMAP2_L4_IO_ADDRESS(OMAP343X_CTRL_BASE),
+	.prm	= OMAP2_L4_IO_ADDRESS(OMAP3430_PRM_BASE),
+	.cm	= OMAP2_L4_IO_ADDRESS(OMAP3430_CM_BASE),
 };
 
 void __init omap2_set_globals_3xxx(void)
@@ -95,7 +105,6 @@ void __init omap2_set_globals_3xxx(void)
 
 void __init omap3_map_io(void)
 {
-	omap2_set_globals_3xxx();
 	omap34xx_map_common_io();
 }
 
@@ -110,9 +119,9 @@ void __init omap3_map_io(void)
 static struct omap_globals ti816x_globals = {
 	.class  = OMAP343X_CLASS,
 	.tap    = OMAP2_L4_IO_ADDRESS(TI816X_TAP_BASE),
-	.ctrl   = TI816X_CTRL_BASE,
-	.prm    = TI816X_PRCM_BASE,
-	.cm     = TI816X_PRCM_BASE,
+	.ctrl   = OMAP2_L4_IO_ADDRESS(TI816X_CTRL_BASE),
+	.prm    = OMAP2_L4_IO_ADDRESS(TI816X_PRCM_BASE),
+	.cm     = OMAP2_L4_IO_ADDRESS(TI816X_PRCM_BASE),
 };
 
 void __init omap2_set_globals_ti816x(void)
@@ -125,11 +134,11 @@ void __init omap2_set_globals_ti816x(void)
 static struct omap_globals omap4_globals = {
 	.class	= OMAP443X_CLASS,
 	.tap	= OMAP2_L4_IO_ADDRESS(OMAP443X_SCM_BASE),
-	.ctrl	= OMAP443X_SCM_BASE,
-	.ctrl_pad	= OMAP443X_CTRL_BASE,
-	.prm	= OMAP4430_PRM_BASE,
-	.cm	= OMAP4430_CM_BASE,
-	.cm2	= OMAP4430_CM2_BASE,
+	.ctrl	= OMAP2_L4_IO_ADDRESS(OMAP443X_SCM_BASE),
+	.ctrl_pad	= OMAP2_L4_IO_ADDRESS(OMAP443X_CTRL_BASE),
+	.prm	= OMAP2_L4_IO_ADDRESS(OMAP4430_PRM_BASE),
+	.cm	= OMAP2_L4_IO_ADDRESS(OMAP4430_CM_BASE),
+	.cm2	= OMAP2_L4_IO_ADDRESS(OMAP4430_CM2_BASE),
 };
 
 void __init omap2_set_globals_443x(void)
@@ -138,5 +147,10 @@ void __init omap2_set_globals_443x(void)
 	omap2_set_globals_control(&omap4_globals);
 	omap2_set_globals_prcm(&omap4_globals);
 }
+
+void __init omap4_map_io(void)
+{
+	omap44xx_map_common_io();
+}
 #endif
 
diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c
index aab884f..e34d27f 100644
--- a/arch/arm/mach-omap2/control.c
+++ b/arch/arm/mach-omap2/control.c
@@ -149,17 +149,11 @@ static struct omap3_control_regs control_context;
 
 void __init omap2_set_globals_control(struct omap_globals *omap2_globals)
 {
-	/* Static mapping, never released */
-	if (omap2_globals->ctrl) {
-		omap2_ctrl_base = ioremap(omap2_globals->ctrl, SZ_4K);
-		WARN_ON(!omap2_ctrl_base);
-	}
+	if (omap2_globals->ctrl)
+		omap2_ctrl_base = omap2_globals->ctrl;
 
-	/* Static mapping, never released */
-	if (omap2_globals->ctrl_pad) {
-		omap4_ctrl_pad_base = ioremap(omap2_globals->ctrl_pad, SZ_4K);
-		WARN_ON(!omap4_ctrl_pad_base);
-	}
+	if (omap2_globals->ctrl_pad)
+		omap4_ctrl_pad_base = omap2_globals->ctrl_pad;
 }
 
 void __iomem *omap_ctrl_base_get(void)
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index ae8ea5b..68ec031 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -16,6 +16,7 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/slab.h>
+#include <linux/of.h>
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
@@ -43,7 +44,7 @@ static int __init omap3_l3_init(void)
 {
 	int l;
 	struct omap_hwmod *oh;
-	struct omap_device *od;
+	struct platform_device *pdev;
 	char oh_name[L3_MODULES_MAX_LEN];
 
 	/*
@@ -60,12 +61,12 @@ static int __init omap3_l3_init(void)
 	if (!oh)
 		pr_err("could not look up %s\n", oh_name);
 
-	od = omap_device_build("omap_l3_smx", 0, oh, NULL, 0,
+	pdev = omap_device_build("omap_l3_smx", 0, oh, NULL, 0,
 							   NULL, 0, 0);
 
-	WARN(IS_ERR(od), "could not build omap_device for %s\n", oh_name);
+	WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name);
 
-	return IS_ERR(od) ? PTR_ERR(od) : 0;
+	return IS_ERR(pdev) ? PTR_ERR(pdev) : 0;
 }
 postcore_initcall(omap3_l3_init);
 
@@ -73,9 +74,13 @@ static int __init omap4_l3_init(void)
 {
 	int l, i;
 	struct omap_hwmod *oh[3];
-	struct omap_device *od;
+	struct platform_device *pdev;
 	char oh_name[L3_MODULES_MAX_LEN];
 
+	/* If dtb is there, the devices will be created dynamically */
+	if (of_have_populated_dt())
+		return -ENODEV;
+
 	/*
 	 * To avoid code running on other OMAPs in
 	 * multi-omap builds
@@ -91,12 +96,12 @@ static int __init omap4_l3_init(void)
 			pr_err("could not look up %s\n", oh_name);
 	}
 
-	od = omap_device_build_ss("omap_l3_noc", 0, oh, 3, NULL,
+	pdev = omap_device_build_ss("omap_l3_noc", 0, oh, 3, NULL,
 						     0, NULL, 0, 0);
 
-	WARN(IS_ERR(od), "could not build omap_device for %s\n", oh_name);
+	WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name);
 
-	return IS_ERR(od) ? PTR_ERR(od) : 0;
+	return IS_ERR(pdev) ? PTR_ERR(pdev) : 0;
 }
 postcore_initcall(omap4_l3_init);
 
@@ -220,18 +225,10 @@ static inline void omap_init_camera(void)
 #endif
 }
 
-struct omap_device_pm_latency omap_keyboard_latency[] = {
-	{
-		.deactivate_func = omap_device_idle_hwmods,
-		.activate_func   = omap_device_enable_hwmods,
-		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-};
-
 int __init omap4_keyboard_init(struct omap4_keypad_platform_data
 			*sdp4430_keypad_data, struct omap_board_data *bdata)
 {
-	struct omap_device *od;
+	struct platform_device *pdev;
 	struct omap_hwmod *oh;
 	struct omap4_keypad_platform_data *keypad_data;
 	unsigned int id = -1;
@@ -246,15 +243,13 @@ int __init omap4_keyboard_init(struct omap4_keypad_platform_data
 
 	keypad_data = sdp4430_keypad_data;
 
-	od = omap_device_build(name, id, oh, keypad_data,
-			sizeof(struct omap4_keypad_platform_data),
-			omap_keyboard_latency,
-			ARRAY_SIZE(omap_keyboard_latency), 0);
+	pdev = omap_device_build(name, id, oh, keypad_data,
+			sizeof(struct omap4_keypad_platform_data), NULL, 0, 0);
 
-	if (IS_ERR(od)) {
+	if (IS_ERR(pdev)) {
 		WARN(1, "Can't build omap_device for %s:%s.\n",
 						name, oh->name);
-		return PTR_ERR(od);
+		return PTR_ERR(pdev);
 	}
 	oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);
 
@@ -262,18 +257,10 @@ int __init omap4_keyboard_init(struct omap4_keypad_platform_data
 }
 
 #if defined(CONFIG_OMAP_MBOX_FWK) || defined(CONFIG_OMAP_MBOX_FWK_MODULE)
-static struct omap_device_pm_latency mbox_latencies[] = {
-	[0] = {
-		.activate_func = omap_device_enable_hwmods,
-		.deactivate_func = omap_device_idle_hwmods,
-		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-};
-
 static inline void omap_init_mbox(void)
 {
 	struct omap_hwmod *oh;
-	struct omap_device *od;
+	struct platform_device *pdev;
 
 	oh = omap_hwmod_lookup("mailbox");
 	if (!oh) {
@@ -281,10 +268,9 @@ static inline void omap_init_mbox(void)
 		return;
 	}
 
-	od = omap_device_build("omap-mailbox", -1, oh, NULL, 0,
-				mbox_latencies, ARRAY_SIZE(mbox_latencies), 0);
-	WARN(IS_ERR(od), "%s: could not build device, err %ld\n",
-						__func__, PTR_ERR(od));
+	pdev = omap_device_build("omap-mailbox", -1, oh, NULL, 0, NULL, 0, 0);
+	WARN(IS_ERR(pdev), "%s: could not build device, err %ld\n",
+						__func__, PTR_ERR(pdev));
 }
 #else
 static inline void omap_init_mbox(void) { }
@@ -365,17 +351,9 @@ static inline void omap_init_mcpdm(void) {}
 
 #include <plat/mcspi.h>
 
-struct omap_device_pm_latency omap_mcspi_latency[] = {
-	[0] = {
-		.deactivate_func = omap_device_idle_hwmods,
-		.activate_func   = omap_device_enable_hwmods,
-		.flags		 = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-};
-
 static int omap_mcspi_init(struct omap_hwmod *oh, void *unused)
 {
-	struct omap_device *od;
+	struct platform_device *pdev;
 	char *name = "omap2_mcspi";
 	struct omap2_mcspi_platform_config *pdata;
 	static int spi_num;
@@ -402,10 +380,9 @@ static int omap_mcspi_init(struct omap_hwmod *oh, void *unused)
 	}
 
 	spi_num++;
-	od = omap_device_build(name, spi_num, oh, pdata,
-				sizeof(*pdata),	omap_mcspi_latency,
-				ARRAY_SIZE(omap_mcspi_latency), 0);
-	WARN(IS_ERR(od), "Can't build omap_device for %s:%s\n",
+	pdev = omap_device_build(name, spi_num, oh, pdata,
+				sizeof(*pdata),	NULL, 0, 0);
+	WARN(IS_ERR(pdev), "Can't build omap_device for %s:%s\n",
 				name, oh->name);
 	kfree(pdata);
 	return 0;
@@ -730,18 +707,10 @@ static int __init omap2_init_devices(void)
 arch_initcall(omap2_init_devices);
 
 #if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE)
-static struct omap_device_pm_latency omap_wdt_latency[] = {
-	[0] = {
-		.deactivate_func = omap_device_idle_hwmods,
-		.activate_func   = omap_device_enable_hwmods,
-		.flags		 = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-};
-
 static int __init omap_init_wdt(void)
 {
 	int id = -1;
-	struct omap_device *od;
+	struct platform_device *pdev;
 	struct omap_hwmod *oh;
 	char *oh_name = "wd_timer2";
 	char *dev_name = "omap_wdt";
@@ -755,10 +724,8 @@ static int __init omap_init_wdt(void)
 		return -EINVAL;
 	}
 
-	od = omap_device_build(dev_name, id, oh, NULL, 0,
-				omap_wdt_latency,
-				ARRAY_SIZE(omap_wdt_latency), 0);
-	WARN(IS_ERR(od), "Can't build omap_device for %s:%s.\n",
+	pdev = omap_device_build(dev_name, id, oh, NULL, 0, NULL, 0, 0);
+	WARN(IS_ERR(pdev), "Can't build omap_device for %s:%s.\n",
 				dev_name, oh->name);
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index 62510ec..4036821 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -37,14 +37,6 @@ static struct platform_device omap_display_device = {
 	},
 };
 
-static struct omap_device_pm_latency omap_dss_latency[] = {
-	[0] = {
-		.deactivate_func        = omap_device_idle_hwmods,
-		.activate_func          = omap_device_enable_hwmods,
-		.flags			= OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-};
-
 struct omap_dss_hwmod_data {
 	const char *oh_name;
 	const char *dev_name;
@@ -127,7 +119,7 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
 {
 	int r = 0;
 	struct omap_hwmod *oh;
-	struct omap_device *od;
+	struct platform_device *pdev;
 	int i, oh_count;
 	struct omap_display_platform_data pdata;
 	const struct omap_dss_hwmod_data *curr_dss_hwmod;
@@ -162,13 +154,12 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
 			return -ENODEV;
 		}
 
-		od = omap_device_build(curr_dss_hwmod[i].dev_name,
+		pdev = omap_device_build(curr_dss_hwmod[i].dev_name,
 				curr_dss_hwmod[i].id, oh, &pdata,
 				sizeof(struct omap_display_platform_data),
-				omap_dss_latency,
-				ARRAY_SIZE(omap_dss_latency), 0);
+				NULL, 0, 0);
 
-		if (WARN((IS_ERR(od)), "Could not build omap_device for %s\n",
+		if (WARN((IS_ERR(pdev)), "Could not build omap_device for %s\n",
 				curr_dss_hwmod[i].oh_name))
 			return -ENODEV;
 	}
diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index c9ff0e7..a59a45a 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -87,14 +87,6 @@ static u16 reg_map[] = {
 	[CCDN]			= 0xd8,
 };
 
-static struct omap_device_pm_latency omap2_dma_latency[] = {
-	{
-		.deactivate_func = omap_device_idle_hwmods,
-		.activate_func	 = omap_device_enable_hwmods,
-		.flags		 = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-};
-
 static void __iomem *dma_base;
 static inline void dma_write(u32 val, int reg, int lch)
 {
@@ -228,7 +220,7 @@ static u32 configure_dma_errata(void)
 /* One time initializations */
 static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
 {
-	struct omap_device			*od;
+	struct platform_device			*pdev;
 	struct omap_system_dma_plat_info	*p;
 	struct resource				*mem;
 	char					*name = "omap_dma_system";
@@ -258,23 +250,22 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
 
 	p->errata		= configure_dma_errata();
 
-	od = omap_device_build(name, 0, oh, p, sizeof(*p),
-			omap2_dma_latency, ARRAY_SIZE(omap2_dma_latency), 0);
+	pdev = omap_device_build(name, 0, oh, p, sizeof(*p), NULL, 0, 0);
 	kfree(p);
-	if (IS_ERR(od)) {
+	if (IS_ERR(pdev)) {
 		pr_err("%s: Can't build omap_device for %s:%s.\n",
 			__func__, name, oh->name);
-		return PTR_ERR(od);
+		return PTR_ERR(pdev);
 	}
 
-	mem = platform_get_resource(&od->pdev, IORESOURCE_MEM, 0);
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!mem) {
-		dev_err(&od->pdev.dev, "%s: no mem resource\n", __func__);
+		dev_err(&pdev->dev, "%s: no mem resource\n", __func__);
 		return -EINVAL;
 	}
 	dma_base = ioremap(mem->start, resource_size(mem));
 	if (!dma_base) {
-		dev_err(&od->pdev.dev, "%s: ioremap fail\n", __func__);
+		dev_err(&pdev->dev, "%s: ioremap fail\n", __func__);
 		return -ENOMEM;
 	}
 
@@ -283,7 +274,7 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
 					(d->lch_count), GFP_KERNEL);
 
 	if (!d->chan) {
-		dev_err(&od->pdev.dev, "%s: kzalloc fail\n", __func__);
+		dev_err(&pdev->dev, "%s: kzalloc fail\n", __func__);
 		return -ENOMEM;
 	}
 	return 0;
diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c
index 2765cdc..8cbfbc2 100644
--- a/arch/arm/mach-omap2/gpio.c
+++ b/arch/arm/mach-omap2/gpio.c
@@ -24,17 +24,9 @@
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
 
-static struct omap_device_pm_latency omap_gpio_latency[] = {
-	[0] = {
-		.deactivate_func = omap_device_idle_hwmods,
-		.activate_func   = omap_device_enable_hwmods,
-		.flags		 = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-};
-
 static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused)
 {
-	struct omap_device *od;
+	struct platform_device *pdev;
 	struct omap_gpio_platform_data *pdata;
 	struct omap_gpio_dev_attr *dev_attr;
 	char *name = "omap_gpio";
@@ -107,19 +99,17 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused)
 		return -EINVAL;
 	}
 
-	od = omap_device_build(name, id - 1, oh, pdata,
-				sizeof(*pdata),	omap_gpio_latency,
-				ARRAY_SIZE(omap_gpio_latency),
-				false);
+	pdev = omap_device_build(name, id - 1, oh, pdata,
+				sizeof(*pdata),	NULL, 0, false);
 	kfree(pdata);
 
-	if (IS_ERR(od)) {
+	if (IS_ERR(pdev)) {
 		WARN(1, "Can't build omap_device for %s:%s.\n",
 					name, oh->name);
-		return PTR_ERR(od);
+		return PTR_ERR(pdev);
 	}
 
-	omap_device_disable_idle_on_suspend(od);
+	omap_device_disable_idle_on_suspend(pdev);
 
 	gpio_bank_count++;
 	return 0;
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index 097a42d..7708584 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -409,31 +409,17 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
 	return 0;
 }
 
-static struct omap_device_pm_latency omap_hsmmc_latency[] = {
-	[0] = {
-		.deactivate_func = omap_device_idle_hwmods,
-		.activate_func	 = omap_device_enable_hwmods,
-		.flags		 = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-	/*
-	 * XXX There should also be an entry here to power off/on the
-	 * MMC regulators/PBIAS cells, etc.
-	 */
-};
-
 #define MAX_OMAP_MMC_HWMOD_NAME_LEN		16
 
 void __init omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr)
 {
 	struct omap_hwmod *oh;
-	struct omap_device *od;
-	struct omap_device_pm_latency *ohl;
+	struct platform_device *pdev;
 	char oh_name[MAX_OMAP_MMC_HWMOD_NAME_LEN];
 	struct omap_mmc_platform_data *mmc_data;
 	struct omap_mmc_dev_attr *mmc_dev_attr;
 	char *name;
 	int l;
-	int ohl_cnt = 0;
 
 	mmc_data = kzalloc(sizeof(struct omap_mmc_platform_data), GFP_KERNEL);
 	if (!mmc_data) {
@@ -448,8 +434,6 @@ void __init omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr)
 	omap_hsmmc_mux(mmc_data, (ctrl_nr - 1));
 
 	name = "omap_hsmmc";
-	ohl = omap_hsmmc_latency;
-	ohl_cnt = ARRAY_SIZE(omap_hsmmc_latency);
 
 	l = snprintf(oh_name, MAX_OMAP_MMC_HWMOD_NAME_LEN,
 		     "mmc%d", ctrl_nr);
@@ -467,9 +451,9 @@ void __init omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr)
 		mmc_data->controller_flags = mmc_dev_attr->flags;
 	}
 
-	od = omap_device_build(name, ctrl_nr - 1, oh, mmc_data,
-		sizeof(struct omap_mmc_platform_data), ohl, ohl_cnt, false);
-	if (IS_ERR(od)) {
+	pdev = omap_device_build(name, ctrl_nr - 1, oh, mmc_data,
+		sizeof(struct omap_mmc_platform_data), NULL, 0, false);
+	if (IS_ERR(pdev)) {
 		WARN(1, "Can't build omap_device for %s:%s.\n", name, oh->name);
 		kfree(mmc_data->slots[0].name);
 		goto done;
@@ -478,7 +462,7 @@ void __init omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr)
 	 * return device handle to board setup code
 	 * required to populate for regulator framework structure
 	 */
-	hsmmcinfo->dev = &od->pdev.dev;
+	hsmmcinfo->dev = &pdev->dev;
 
 done:
 	kfree(mmc_data);
diff --git a/arch/arm/mach-omap2/hwspinlock.c b/arch/arm/mach-omap2/hwspinlock.c
index 06d4a80..36e2109 100644
--- a/arch/arm/mach-omap2/hwspinlock.c
+++ b/arch/arm/mach-omap2/hwspinlock.c
@@ -23,19 +23,11 @@
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
 
-struct omap_device_pm_latency omap_spinlock_latency[] = {
-	{
-		.deactivate_func = omap_device_idle_hwmods,
-		.activate_func   = omap_device_enable_hwmods,
-		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	}
-};
-
 int __init hwspinlocks_init(void)
 {
 	int retval = 0;
 	struct omap_hwmod *oh;
-	struct omap_device *od;
+	struct platform_device *pdev;
 	const char *oh_name = "spinlock";
 	const char *dev_name = "omap_hwspinlock";
 
@@ -48,13 +40,11 @@ int __init hwspinlocks_init(void)
 	if (oh == NULL)
 		return -EINVAL;
 
-	od = omap_device_build(dev_name, 0, oh, NULL, 0,
-				omap_spinlock_latency,
-				ARRAY_SIZE(omap_spinlock_latency), false);
-	if (IS_ERR(od)) {
+	pdev = omap_device_build(dev_name, 0, oh, NULL, 0, NULL, 0, false);
+	if (IS_ERR(pdev)) {
 		pr_err("Can't build omap_device for %s:%s\n", dev_name,
 								oh_name);
-		retval = PTR_ERR(od);
+		retval = PTR_ERR(pdev);
 	}
 
 	return retval;
diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
index 37efb86..d27daf9 100644
--- a/arch/arm/mach-omap2/id.c
+++ b/arch/arm/mach-omap2/id.c
@@ -28,7 +28,6 @@
 
 #include "control.h"
 
-static struct omap_chip_id omap_chip;
 static unsigned int omap_revision;
 
 u32 omap_features;
@@ -39,19 +38,6 @@ unsigned int omap_rev(void)
 }
 EXPORT_SYMBOL(omap_rev);
 
-/**
- * omap_chip_is - test whether currently running OMAP matches a chip type
- * @oc: omap_chip_t to test against
- *
- * Test whether the currently-running OMAP chip matches the supplied
- * chip type 'oc'.  Returns 1 upon a match; 0 upon failure.
- */
-int omap_chip_is(struct omap_chip_id oci)
-{
-	return (oci.oc & omap_chip.oc) ? 1 : 0;
-}
-EXPORT_SYMBOL(omap_chip_is);
-
 int omap_type(void)
 {
 	u32 val = 0;
@@ -242,14 +228,12 @@ static void __init ti816x_check_features(void)
 	omap_features = OMAP3_HAS_NEON;
 }
 
-static void __init omap3_check_revision(void)
+static void __init omap3_check_revision(const char **cpu_rev)
 {
 	u32 cpuid, idcode;
 	u16 hawkeye;
 	u8 rev;
 
-	omap_chip.oc = CHIP_IS_OMAP3430;
-
 	/*
 	 * We cannot access revision registers on ES1.0.
 	 * If the processor type is Cortex-A8 and the revision is 0x0
@@ -258,7 +242,7 @@ static void __init omap3_check_revision(void)
 	cpuid = read_cpuid(CPUID_ID);
 	if ((((cpuid >> 4) & 0xfff) == 0xc08) && ((cpuid & 0xf) == 0x0)) {
 		omap_revision = OMAP3430_REV_ES1_0;
-		omap_chip.oc |= CHIP_IS_OMAP3430ES1;
+		*cpu_rev = "1.0";
 		return;
 	}
 
@@ -279,77 +263,85 @@ static void __init omap3_check_revision(void)
 		case 0: /* Take care of early samples */
 		case 1:
 			omap_revision = OMAP3430_REV_ES2_0;
-			omap_chip.oc |= CHIP_IS_OMAP3430ES2;
+			*cpu_rev = "2.0";
 			break;
 		case 2:
 			omap_revision = OMAP3430_REV_ES2_1;
-			omap_chip.oc |= CHIP_IS_OMAP3430ES2;
+			*cpu_rev = "2.1";
 			break;
 		case 3:
 			omap_revision = OMAP3430_REV_ES3_0;
-			omap_chip.oc |= CHIP_IS_OMAP3430ES3_0;
+			*cpu_rev = "3.0";
 			break;
 		case 4:
 			omap_revision = OMAP3430_REV_ES3_1;
-			omap_chip.oc |= CHIP_IS_OMAP3430ES3_1;
+			*cpu_rev = "3.1";
 			break;
 		case 7:
 		/* FALLTHROUGH */
 		default:
 			/* Use the latest known revision as default */
 			omap_revision = OMAP3430_REV_ES3_1_2;
-
-			/* REVISIT: Add CHIP_IS_OMAP3430ES3_1_2? */
-			omap_chip.oc |= CHIP_IS_OMAP3430ES3_1;
+			*cpu_rev = "3.1.2";
 		}
 		break;
 	case 0xb868:
-		/* Handle OMAP35xx/AM35xx devices
+		/*
+		 * Handle OMAP/AM 3505/3517 devices
 		 *
-		 * Set the device to be OMAP3505 here. Actual device
+		 * Set the device to be OMAP3517 here. Actual device
 		 * is identified later based on the features.
-		 *
-		 * REVISIT: AM3505/AM3517 should have their own CHIP_IS
 		 */
-		omap_revision = OMAP3505_REV(rev);
-		omap_chip.oc |= CHIP_IS_OMAP3430ES3_1;
+		switch (rev) {
+		case 0:
+			omap_revision = OMAP3517_REV_ES1_0;
+			*cpu_rev = "1.0";
+			break;
+		case 1:
+		/* FALLTHROUGH */
+		default:
+			omap_revision = OMAP3517_REV_ES1_1;
+			*cpu_rev = "1.1";
+		}
 		break;
 	case 0xb891:
 		/* Handle 36xx devices */
-		omap_chip.oc |= CHIP_IS_OMAP3630ES1;
 
 		switch(rev) {
 		case 0: /* Take care of early samples */
 			omap_revision = OMAP3630_REV_ES1_0;
+			*cpu_rev = "1.0";
 			break;
 		case 1:
 			omap_revision = OMAP3630_REV_ES1_1;
-			omap_chip.oc |= CHIP_IS_OMAP3630ES1_1;
+			*cpu_rev = "1.1";
 			break;
 		case 2:
+		/* FALLTHROUGH */
 		default:
-			omap_revision =  OMAP3630_REV_ES1_2;
-			omap_chip.oc |= CHIP_IS_OMAP3630ES1_2;
+			omap_revision = OMAP3630_REV_ES1_2;
+			*cpu_rev = "1.2";
 		}
 		break;
 	case 0xb81e:
-		omap_chip.oc = CHIP_IS_TI816X;
-
 		switch (rev) {
 		case 0:
 			omap_revision = TI8168_REV_ES1_0;
+			*cpu_rev = "1.0";
 			break;
 		case 1:
+		/* FALLTHROUGH */
+		default:
 			omap_revision = TI8168_REV_ES1_1;
+			*cpu_rev = "1.1";
 			break;
-		default:
-			omap_revision =  TI8168_REV_ES1_1;
 		}
 		break;
 	default:
-		/* Unknown default to latest silicon rev as default*/
-		omap_revision =  OMAP3630_REV_ES1_2;
-		omap_chip.oc |= CHIP_IS_OMAP3630ES1_2;
+		/* Unknown default to latest silicon rev as default */
+		omap_revision = OMAP3630_REV_ES1_2;
+		*cpu_rev = "1.2";
+		pr_warn("Warning: unknown chip type; assuming OMAP3630ES1.2\n");
 	}
 }
 
@@ -382,24 +374,20 @@ static void __init omap4_check_revision(void)
 		switch (rev) {
 		case 0:
 			omap_revision = OMAP4430_REV_ES1_0;
-			omap_chip.oc |= CHIP_IS_OMAP4430ES1;
 			break;
 		case 1:
 		default:
 			omap_revision = OMAP4430_REV_ES2_0;
-			omap_chip.oc |= CHIP_IS_OMAP4430ES2;
 		}
 		break;
 	case 0xb95c:
 		switch (rev) {
 		case 3:
 			omap_revision = OMAP4430_REV_ES2_1;
-			omap_chip.oc |= CHIP_IS_OMAP4430ES2_1;
 			break;
 		case 4:
 		default:
 			omap_revision = OMAP4430_REV_ES2_2;
-			omap_chip.oc |= CHIP_IS_OMAP4430ES2_2;
 		}
 		break;
 	case 0xb94e:
@@ -407,14 +395,12 @@ static void __init omap4_check_revision(void)
 		case 0:
 		default:
 			omap_revision = OMAP4460_REV_ES1_0;
-			omap_chip.oc |= CHIP_IS_OMAP4460ES1_0;
 			break;
 		}
 		break;
 	default:
 		/* Unknown default to latest silicon rev as default */
 		omap_revision = OMAP4430_REV_ES2_2;
-		omap_chip.oc |= CHIP_IS_OMAP4430ES2_2;
 	}
 
 	pr_info("OMAP%04x ES%d.%d\n", omap_rev() >> 16,
@@ -425,94 +411,33 @@ static void __init omap4_check_revision(void)
 	if (omap3_has_ ##feat())		\
 		printk(#feat" ");
 
-static void __init omap3_cpuinfo(void)
+static void __init omap3_cpuinfo(const char *cpu_rev)
 {
-	u8 rev = GET_OMAP_REVISION();
-	char cpu_name[16], cpu_rev[16];
+	const char *cpu_name;
 
-	/* OMAP3430 and OMAP3530 are assumed to be same.
+	/*
+	 * OMAP3430 and OMAP3530 are assumed to be same.
 	 *
 	 * OMAP3525, OMAP3515 and OMAP3503 can be detected only based
 	 * on available features. Upon detection, update the CPU id
 	 * and CPU class bits.
 	 */
 	if (cpu_is_omap3630()) {
-		strcpy(cpu_name, "OMAP3630");
-	} else if (cpu_is_omap3505()) {
-		/*
-		 * AM35xx devices
-		 */
-		if (omap3_has_sgx()) {
-			omap_revision = OMAP3517_REV(rev);
-			strcpy(cpu_name, "AM3517");
-		} else {
-			/* Already set in omap3_check_revision() */
-			strcpy(cpu_name, "AM3505");
-		}
+		cpu_name = "OMAP3630";
+	} else if (cpu_is_omap3517()) {
+		/* AM35xx devices */
+		cpu_name = (omap3_has_sgx()) ? "AM3517" : "AM3505";
 	} else if (cpu_is_ti816x()) {
-		strcpy(cpu_name, "TI816X");
+		cpu_name = "TI816X";
 	} else if (omap3_has_iva() && omap3_has_sgx()) {
 		/* OMAP3430, OMAP3525, OMAP3515, OMAP3503 devices */
-		strcpy(cpu_name, "OMAP3430/3530");
+		cpu_name = "OMAP3430/3530";
 	} else if (omap3_has_iva()) {
-		omap_revision = OMAP3525_REV(rev);
-		strcpy(cpu_name, "OMAP3525");
+		cpu_name = "OMAP3525";
 	} else if (omap3_has_sgx()) {
-		omap_revision = OMAP3515_REV(rev);
-		strcpy(cpu_name, "OMAP3515");
+		cpu_name = "OMAP3515";
 	} else {
-		omap_revision = OMAP3503_REV(rev);
-		strcpy(cpu_name, "OMAP3503");
-	}
-
-	if (cpu_is_omap3630() || cpu_is_ti816x()) {
-		switch (rev) {
-		case OMAP_REVBITS_00:
-			strcpy(cpu_rev, "1.0");
-			break;
-		case OMAP_REVBITS_01:
-			strcpy(cpu_rev, "1.1");
-			break;
-		case OMAP_REVBITS_02:
-			/* FALLTHROUGH */
-		default:
-			/* Use the latest known revision as default */
-			strcpy(cpu_rev, "1.2");
-		}
-	} else if (cpu_is_omap3505() || cpu_is_omap3517()) {
-		switch (rev) {
-		case OMAP_REVBITS_00:
-			strcpy(cpu_rev, "1.0");
-			break;
-		case OMAP_REVBITS_01:
-			/* FALLTHROUGH */
-		default:
-			/* Use the latest known revision as default */
-			strcpy(cpu_rev, "1.1");
-		}
-	} else {
-		switch (rev) {
-		case OMAP_REVBITS_00:
-			strcpy(cpu_rev, "1.0");
-			break;
-		case OMAP_REVBITS_01:
-			strcpy(cpu_rev, "2.0");
-			break;
-		case OMAP_REVBITS_02:
-			strcpy(cpu_rev, "2.1");
-			break;
-		case OMAP_REVBITS_03:
-			strcpy(cpu_rev, "3.0");
-			break;
-		case OMAP_REVBITS_04:
-			strcpy(cpu_rev, "3.1");
-			break;
-		case OMAP_REVBITS_05:
-			/* FALLTHROUGH */
-		default:
-			/* Use the latest known revision as default */
-			strcpy(cpu_rev, "3.1.2");
-		}
+		cpu_name = "OMAP3503";
 	}
 
 	/* Print verbose information */
@@ -533,6 +458,8 @@ static void __init omap3_cpuinfo(void)
  */
 void __init omap2_check_revision(void)
 {
+	const char *cpu_rev;
+
 	/*
 	 * At this point we have an idea about the processor revision set
 	 * earlier with omap2_set_globals_tap().
@@ -540,7 +467,7 @@ void __init omap2_check_revision(void)
 	if (cpu_is_omap24xx()) {
 		omap24xx_check_revision();
 	} else if (cpu_is_omap34xx()) {
-		omap3_check_revision();
+		omap3_check_revision(&cpu_rev);
 
 		/* TI816X doesn't have feature register */
 		if (!cpu_is_ti816x())
@@ -548,7 +475,7 @@ void __init omap2_check_revision(void)
 		else
 			ti816x_check_features();
 
-		omap3_cpuinfo();
+		omap3_cpuinfo(cpu_rev);
 		return;
 	} else if (cpu_is_omap44xx()) {
 		omap4_check_revision();
@@ -557,22 +484,6 @@ void __init omap2_check_revision(void)
 	} else {
 		pr_err("OMAP revision unknown, please fix!\n");
 	}
-
-	/*
-	 * OK, now we know the exact revision. Initialize omap_chip bits
-	 * for powerdowmain and clockdomain code.
-	 */
-	if (cpu_is_omap243x()) {
-		/* Currently only supports 2430ES2.1 and 2430-all */
-		omap_chip.oc |= CHIP_IS_OMAP2430;
-		return;
-	} else if (cpu_is_omap242x()) {
-		/* Currently only supports 2420ES2.1.1 and 2420-all */
-		omap_chip.oc |= CHIP_IS_OMAP2420;
-		return;
-	}
-
-	pr_err("Uninitialized omap_chip, please fix!\n");
 }
 
 /*
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index d6d01cb..a5d8dce 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -34,14 +34,16 @@
 #include "clock2xxx.h"
 #include "clock3xxx.h"
 #include "clock44xx.h"
-#include "io.h"
 
+#include <plat/common.h>
 #include <plat/omap-pm.h>
+#include "voltage.h"
 #include "powerdomain.h"
 
 #include "clockdomain.h"
 #include <plat/omap_hwmod.h>
 #include <plat/multi.h>
+#include <plat/common.h>
 
 /*
  * The machine specific code may provide the extra mapping besides the
@@ -238,26 +240,11 @@ static struct map_desc omap44xx_io_desc[] __initdata = {
 };
 #endif
 
-static void __init _omap2_map_common_io(void)
-{
-	/* Normally devicemaps_init() would flush caches and tlb after
-	 * mdesc->map_io(), but we must also do it here because of the CPU
-	 * revision check below.
-	 */
-	local_flush_tlb_all();
-	flush_cache_all();
-
-	omap2_check_revision();
-	omap_sram_init();
-	omap_init_consistent_dma_size();
-}
-
 #ifdef CONFIG_SOC_OMAP2420
 void __init omap242x_map_common_io(void)
 {
 	iotable_init(omap24xx_io_desc, ARRAY_SIZE(omap24xx_io_desc));
 	iotable_init(omap242x_io_desc, ARRAY_SIZE(omap242x_io_desc));
-	_omap2_map_common_io();
 }
 #endif
 
@@ -266,7 +253,6 @@ void __init omap243x_map_common_io(void)
 {
 	iotable_init(omap24xx_io_desc, ARRAY_SIZE(omap24xx_io_desc));
 	iotable_init(omap243x_io_desc, ARRAY_SIZE(omap243x_io_desc));
-	_omap2_map_common_io();
 }
 #endif
 
@@ -274,7 +260,6 @@ void __init omap243x_map_common_io(void)
 void __init omap34xx_map_common_io(void)
 {
 	iotable_init(omap34xx_io_desc, ARRAY_SIZE(omap34xx_io_desc));
-	_omap2_map_common_io();
 }
 #endif
 
@@ -282,7 +267,6 @@ void __init omap34xx_map_common_io(void)
 void __init omapti816x_map_common_io(void)
 {
 	iotable_init(omapti816x_io_desc, ARRAY_SIZE(omapti816x_io_desc));
-	_omap2_map_common_io();
 }
 #endif
 
@@ -290,7 +274,6 @@ void __init omapti816x_map_common_io(void)
 void __init omap44xx_map_common_io(void)
 {
 	iotable_init(omap44xx_io_desc, ARRAY_SIZE(omap44xx_io_desc));
-	_omap2_map_common_io();
 }
 #endif
 
@@ -336,29 +319,16 @@ static int _set_hwmod_postsetup_state(struct omap_hwmod *oh, void *data)
 /* See irq.c, omap4-common.c and entry-macro.S */
 void __iomem *omap_irq_base;
 
-void __init omap2_init_common_infrastructure(void)
+static void __init omap_common_init_early(void)
 {
-	u8 postsetup_state;
+	omap2_check_revision();
+	omap_ioremap_init();
+	omap_init_consistent_dma_size();
+}
 
-	if (cpu_is_omap242x()) {
-		omap2xxx_powerdomains_init();
-		omap2xxx_clockdomains_init();
-		omap2420_hwmod_init();
-	} else if (cpu_is_omap243x()) {
-		omap2xxx_powerdomains_init();
-		omap2xxx_clockdomains_init();
-		omap2430_hwmod_init();
-	} else if (cpu_is_omap34xx()) {
-		omap3xxx_powerdomains_init();
-		omap3xxx_clockdomains_init();
-		omap3xxx_hwmod_init();
-	} else if (cpu_is_omap44xx()) {
-		omap44xx_powerdomains_init();
-		omap44xx_clockdomains_init();
-		omap44xx_hwmod_init();
-	} else {
-		pr_err("Could not init hwmod data - unknown SoC\n");
-        }
+static void __init omap_hwmod_init_postsetup(void)
+{
+	u8 postsetup_state;
 
 	/* Set the default postsetup state for all hwmods */
 #ifdef CONFIG_PM_RUNTIME
@@ -376,7 +346,7 @@ void __init omap2_init_common_infrastructure(void)
 	 * omap_hwmod_late_init(), so boards that desire full watchdog
 	 * coverage of kernel initialization can reprogram the
 	 * postsetup_state between the calls to
-	 * omap2_init_common_infra() and omap2_init_common_devices().
+	 * omap2_init_common_infra() and omap_sdrc_init().
 	 *
 	 * XXX ideally we could detect whether the MPU WDT was currently
 	 * enabled here and make this conditional
@@ -387,27 +357,101 @@ void __init omap2_init_common_infrastructure(void)
 				     &postsetup_state);
 
 	omap_pm_if_early_init();
+}
 
-	if (cpu_is_omap2420())
-		omap2420_clk_init();
-	else if (cpu_is_omap2430())
-		omap2430_clk_init();
-	else if (cpu_is_omap34xx())
-		omap3xxx_clk_init();
-	else if (cpu_is_omap44xx())
-		omap4xxx_clk_init();
-	else
-		pr_err("Could not init clock framework - unknown SoC\n");
+void __init omap2420_init_early(void)
+{
+	omap2_set_globals_242x();
+	omap_common_init_early();
+	omap2xxx_voltagedomains_init();
+	omap242x_powerdomains_init();
+	omap242x_clockdomains_init();
+	omap2420_hwmod_init();
+	omap_hwmod_init_postsetup();
+	omap2420_clk_init();
 }
 
-void __init omap2_init_common_devices(struct omap_sdrc_params *sdrc_cs0,
+void __init omap2430_init_early(void)
+{
+	omap2_set_globals_243x();
+	omap_common_init_early();
+	omap2xxx_voltagedomains_init();
+	omap243x_powerdomains_init();
+	omap243x_clockdomains_init();
+	omap2430_hwmod_init();
+	omap_hwmod_init_postsetup();
+	omap2430_clk_init();
+}
+
+/*
+ * Currently only board-omap3beagle.c should call this because of the
+ * same machine_id for 34xx and 36xx beagle.. Will get fixed with DT.
+ */
+void __init omap3_init_early(void)
+{
+	omap2_set_globals_3xxx();
+	omap_common_init_early();
+	omap3xxx_voltagedomains_init();
+	omap3xxx_powerdomains_init();
+	omap3xxx_clockdomains_init();
+	omap3xxx_hwmod_init();
+	omap_hwmod_init_postsetup();
+	omap3xxx_clk_init();
+}
+
+void __init omap3430_init_early(void)
+{
+	omap3_init_early();
+}
+
+void __init omap35xx_init_early(void)
+{
+	omap3_init_early();
+}
+
+void __init omap3630_init_early(void)
+{
+	omap3_init_early();
+}
+
+void __init am35xx_init_early(void)
+{
+	omap3_init_early();
+}
+
+void __init ti816x_init_early(void)
+{
+	omap2_set_globals_ti816x();
+	omap_common_init_early();
+	omap3xxx_voltagedomains_init();
+	omap3xxx_powerdomains_init();
+	omap3xxx_clockdomains_init();
+	omap3xxx_hwmod_init();
+	omap_hwmod_init_postsetup();
+	omap3xxx_clk_init();
+}
+
+void __init omap4430_init_early(void)
+{
+	omap2_set_globals_443x();
+	omap_common_init_early();
+	omap44xx_voltagedomains_init();
+	omap44xx_powerdomains_init();
+	omap44xx_clockdomains_init();
+	omap44xx_hwmod_init();
+	omap_hwmod_init_postsetup();
+	omap4xxx_clk_init();
+}
+
+void __init omap_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
 				      struct omap_sdrc_params *sdrc_cs1)
 {
+	omap_sram_init();
+
 	if (cpu_is_omap24xx() || omap3_has_sdrc()) {
 		omap2_sdrc_init(sdrc_cs0, sdrc_cs1);
 		_omap2_init_reprogram_sdrc();
 	}
-
 }
 
 /*
diff --git a/arch/arm/mach-omap2/io.h b/arch/arm/mach-omap2/io.h
index fd230c6..e69de29 100644
--- a/arch/arm/mach-omap2/io.h
+++ b/arch/arm/mach-omap2/io.h
@@ -1,7 +0,0 @@
-
-#ifndef __MACH_OMAP2_IO_H__
-#define __MACH_OMAP2_IO_H__
-
-extern int __init omap_sram_init(void);
-
-#endif /*  __MACH_OMAP2_IO_H__ */
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c
index 3a12f75..65f1be6 100644
--- a/arch/arm/mach-omap2/irq.c
+++ b/arch/arm/mach-omap2/irq.c
@@ -165,8 +165,8 @@ static void __init omap_init_irq(u32 base, int nr_irqs)
 
 		omap_irq_bank_init_one(bank);
 
-		for (i = 0, j = 0; i < bank->nr_irqs; i += 32, j += 0x20)
-			omap_alloc_gc(bank->base_reg + j, i, 32);
+		for (j = 0; j < bank->nr_irqs; j += 32)
+			omap_alloc_gc(bank->base_reg + j, j, 32);
 
 		nr_of_irqs += bank->nr_irqs;
 		nr_banks++;
diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c
index 4a6ef6a..292eee3 100644
--- a/arch/arm/mach-omap2/mcbsp.c
+++ b/arch/arm/mach-omap2/mcbsp.c
@@ -27,66 +27,69 @@
 
 #include "control.h"
 
-/* McBSP internal signal muxing functions */
+/*
+ * FIXME: Find a mechanism to enable/disable runtime the McBSP ICLK autoidle.
+ * Sidetone needs non-gated ICLK and sidetone autoidle is broken.
+ */
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-34xx.h"
 
-void omap2_mcbsp1_mux_clkr_src(u8 mux)
+/* McBSP internal signal muxing function */
+static int omap2_mcbsp1_mux_rx_clk(struct device *dev, const char *signal,
+				   const char *src)
 {
 	u32 v;
 
 	v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
-	if (mux == CLKR_SRC_CLKR)
-		v &= ~OMAP2_MCBSP1_CLKR_MASK;
-	else if (mux == CLKR_SRC_CLKX)
-		v |= OMAP2_MCBSP1_CLKR_MASK;
-	omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
-}
-EXPORT_SYMBOL(omap2_mcbsp1_mux_clkr_src);
 
-void omap2_mcbsp1_mux_fsr_src(u8 mux)
-{
-	u32 v;
+	if (!strcmp(signal, "clkr")) {
+		if (!strcmp(src, "clkr"))
+			v &= ~OMAP2_MCBSP1_CLKR_MASK;
+		else if (!strcmp(src, "clkx"))
+			v |= OMAP2_MCBSP1_CLKR_MASK;
+		else
+			return -EINVAL;
+	} else if (!strcmp(signal, "fsr")) {
+		if (!strcmp(src, "fsr"))
+			v &= ~OMAP2_MCBSP1_FSR_MASK;
+		else if (!strcmp(src, "fsx"))
+			v |= OMAP2_MCBSP1_FSR_MASK;
+		else
+			return -EINVAL;
+	} else {
+		return -EINVAL;
+	}
 
-	v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
-	if (mux == FSR_SRC_FSR)
-		v &= ~OMAP2_MCBSP1_FSR_MASK;
-	else if (mux == FSR_SRC_FSX)
-		v |= OMAP2_MCBSP1_FSR_MASK;
 	omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
+
+	return 0;
 }
-EXPORT_SYMBOL(omap2_mcbsp1_mux_fsr_src);
 
 /* McBSP CLKS source switching function */
-
-int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id)
+static int omap2_mcbsp_set_clk_src(struct device *dev, struct clk *clk,
+				   const char *src)
 {
-	struct omap_mcbsp *mcbsp;
 	struct clk *fck_src;
 	char *fck_src_name;
 	int r;
 
-	if (!omap_mcbsp_check_valid_id(id)) {
-		pr_err("%s: Invalid id (%d)\n", __func__, id + 1);
-		return -EINVAL;
-	}
-	mcbsp = id_to_mcbsp_ptr(id);
-
-	if (fck_src_id == MCBSP_CLKS_PAD_SRC)
+	if (!strcmp(src, "clks_ext"))
 		fck_src_name = "pad_fck";
-	else if (fck_src_id == MCBSP_CLKS_PRCM_SRC)
+	else if (!strcmp(src, "clks_fclk"))
 		fck_src_name = "prcm_fck";
 	else
 		return -EINVAL;
 
-	fck_src = clk_get(mcbsp->dev, fck_src_name);
+	fck_src = clk_get(dev, fck_src_name);
 	if (IS_ERR_OR_NULL(fck_src)) {
 		pr_err("omap-mcbsp: %s: could not clk_get() %s\n", "clks",
 		       fck_src_name);
 		return -EINVAL;
 	}
 
-	pm_runtime_put_sync(mcbsp->dev);
+	pm_runtime_put_sync(dev);
 
-	r = clk_set_parent(mcbsp->fclk, fck_src);
+	r = clk_set_parent(clk, fck_src);
 	if (IS_ERR_VALUE(r)) {
 		pr_err("omap-mcbsp: %s: could not clk_set_parent() to %s\n",
 		       "clks", fck_src_name);
@@ -94,21 +97,30 @@ int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id)
 		return -EINVAL;
 	}
 
-	pm_runtime_get_sync(mcbsp->dev);
+	pm_runtime_get_sync(dev);
 
 	clk_put(fck_src);
 
 	return 0;
 }
-EXPORT_SYMBOL(omap2_mcbsp_set_clks_src);
 
-struct omap_device_pm_latency omap2_mcbsp_latency[] = {
-	{
-		.deactivate_func = omap_device_idle_hwmods,
-		.activate_func   = omap_device_enable_hwmods,
-		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-};
+static int omap3_enable_st_clock(unsigned int id, bool enable)
+{
+	unsigned int w;
+
+	/*
+	 * Sidetone uses McBSP ICLK - which must not idle when sidetones
+	 * are enabled or sidetones start sounding ugly.
+	 */
+	w = omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
+	if (enable)
+		w &= ~(1 << (id - 2));
+	else
+		w |= 1 << (id - 2);
+	omap2_cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE);
+
+	return 0;
+}
 
 static int omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
 {
@@ -116,7 +128,7 @@ static int omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
 	char *name = "omap-mcbsp";
 	struct omap_hwmod *oh_device[2];
 	struct omap_mcbsp_platform_data *pdata = NULL;
-	struct omap_device *od;
+	struct platform_device *pdev;
 
 	sscanf(oh->name, "mcbsp%d", &id);
 
@@ -126,7 +138,13 @@ static int omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
 		return -ENOMEM;
 	}
 
-	pdata->mcbsp_config_type = oh->class->rev;
+	pdata->reg_step = 4;
+	if (oh->class->rev < MCBSP_CONFIG_TYPE2) {
+		pdata->reg_size = 2;
+	} else {
+		pdata->reg_size = 4;
+		pdata->has_ccr = true;
+	}
 
 	if (oh->class->rev == MCBSP_CONFIG_TYPE3) {
 		if (id == 2)
@@ -137,22 +155,28 @@ static int omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
 			pdata->buffer_size = 0x80;
 	}
 
+	if (oh->class->rev >= MCBSP_CONFIG_TYPE3)
+		pdata->has_wakeup = true;
+
 	oh_device[0] = oh;
 
 	if (oh->dev_attr) {
 		oh_device[1] = omap_hwmod_lookup((
 		(struct omap_mcbsp_dev_attr *)(oh->dev_attr))->sidetone);
+		pdata->enable_st_clock = omap3_enable_st_clock;
 		count++;
 	}
-	od = omap_device_build_ss(name, id, oh_device, count, pdata,
-				sizeof(*pdata), omap2_mcbsp_latency,
-				ARRAY_SIZE(omap2_mcbsp_latency), false);
+	pdev = omap_device_build_ss(name, id, oh_device, count, pdata,
+				sizeof(*pdata), NULL, 0, false);
 	kfree(pdata);
-	if (IS_ERR(od))  {
+	if (IS_ERR(pdev))  {
 		pr_err("%s: Can't build omap_device for %s:%s.\n", __func__,
 					name, oh->name);
-		return PTR_ERR(od);
+		return PTR_ERR(pdev);
 	}
+	pdata->set_clk_src = omap2_mcbsp_set_clk_src;
+	if (id == 1)
+		pdata->mux_signal = omap2_mcbsp1_mux_rx_clk;
 	omap_mcbsp_count++;
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
index 889464d..4412ddb 100644
--- a/arch/arm/mach-omap2/omap-smp.c
+++ b/arch/arm/mach-omap2/omap-smp.c
@@ -102,8 +102,11 @@ void __init smp_init_cpus(void)
 {
 	unsigned int i, ncores;
 
-	/* Never released */
-	scu_base = ioremap(OMAP44XX_SCU_BASE, SZ_256);
+	/*
+	 * Currently we can't call ioremap here because
+	 * SoC detection won't work until after init_early.
+	 */
+	scu_base =  OMAP2_L4_IO_ADDRESS(OMAP44XX_SCU_BASE);
 	BUG_ON(!scu_base);
 
 	ncores = scu_get_core_count(scu_base);
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 84cc0bd..d713807 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -1954,9 +1954,6 @@ int __init omap_hwmod_register(struct omap_hwmod **ohs)
 
 	i = 0;
 	do {
-		if (!omap_chip_is(ohs[i]->omap_chip))
-			continue;
-
 		r = _register(ohs[i]);
 		WARN(r, "omap_hwmod: %s: _register returned %d\n", ohs[i]->name,
 		     r);
diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index a015c69..6d72062 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -100,7 +100,6 @@ static struct omap_hwmod omap2420_l3_main_hwmod = {
 	.masters_cnt	= ARRAY_SIZE(omap2420_l3_main_masters),
 	.slaves		= omap2420_l3_main_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_l3_main_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -206,7 +205,6 @@ static struct omap_hwmod omap2420_l4_core_hwmod = {
 	.masters_cnt	= ARRAY_SIZE(omap2420_l4_core_masters),
 	.slaves		= omap2420_l4_core_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_l4_core_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -227,7 +225,6 @@ static struct omap_hwmod omap2420_l4_wkup_hwmod = {
 	.masters_cnt	= ARRAY_SIZE(omap2420_l4_wkup_masters),
 	.slaves		= omap2420_l4_wkup_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_l4_wkup_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -243,7 +240,6 @@ static struct omap_hwmod omap2420_mpu_hwmod = {
 	.main_clk	= "mpu_ck",
 	.masters	= omap2420_mpu_masters,
 	.masters_cnt	= ARRAY_SIZE(omap2420_mpu_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /*
@@ -271,7 +267,16 @@ static struct omap_hwmod omap2420_iva_hwmod = {
 	.class		= &iva_hwmod_class,
 	.masters	= omap2420_iva_masters,
 	.masters_cnt	= ARRAY_SIZE(omap2420_iva_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
+};
+
+/* always-on timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
+	.timer_capability       = OMAP_TIMER_ALWON,
+};
+
+/* pwm timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
+	.timer_capability       = OMAP_TIMER_HAS_PWM,
 };
 
 /* timer1 */
@@ -314,10 +319,10 @@ static struct omap_hwmod omap2420_timer1_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT1_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer1_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer2 */
@@ -351,10 +356,10 @@ static struct omap_hwmod omap2420_timer2_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT2_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer2_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer3 */
@@ -388,10 +393,10 @@ static struct omap_hwmod omap2420_timer3_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT3_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer3_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer4 */
@@ -425,10 +430,10 @@ static struct omap_hwmod omap2420_timer4_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT4_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer4_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer5 */
@@ -462,10 +467,10 @@ static struct omap_hwmod omap2420_timer5_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT5_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer5_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 
@@ -500,10 +505,10 @@ static struct omap_hwmod omap2420_timer6_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT6_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer6_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer6_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer7 */
@@ -537,10 +542,10 @@ static struct omap_hwmod omap2420_timer7_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT7_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer7_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer7_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer8 */
@@ -574,10 +579,10 @@ static struct omap_hwmod omap2420_timer8_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT8_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2420_timer8_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer8_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer9 */
@@ -611,10 +616,10 @@ static struct omap_hwmod omap2420_timer9_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT9_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2420_timer9_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer9_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer10 */
@@ -648,10 +653,10 @@ static struct omap_hwmod omap2420_timer10_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT10_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2420_timer10_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer10_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer11 */
@@ -685,10 +690,10 @@ static struct omap_hwmod omap2420_timer11_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT11_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2420_timer11_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer11_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* timer12 */
@@ -722,10 +727,10 @@ static struct omap_hwmod omap2420_timer12_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT12_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2420_timer12_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_timer12_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
 /* l4_wkup -> wd_timer2 */
@@ -766,7 +771,6 @@ static struct omap_hwmod omap2420_wd_timer2_hwmod = {
 	},
 	.slaves		= omap2420_wd_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_wd_timer2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* UART1 */
@@ -792,7 +796,6 @@ static struct omap_hwmod omap2420_uart1_hwmod = {
 	.slaves		= omap2420_uart1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_uart1_slaves),
 	.class		= &omap2_uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* UART2 */
@@ -818,7 +821,6 @@ static struct omap_hwmod omap2420_uart2_hwmod = {
 	.slaves		= omap2420_uart2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_uart2_slaves),
 	.class		= &omap2_uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* UART3 */
@@ -844,7 +846,6 @@ static struct omap_hwmod omap2420_uart3_hwmod = {
 	.slaves		= omap2420_uart3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_uart3_slaves),
 	.class		= &omap2_uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* dss */
@@ -898,7 +899,6 @@ static struct omap_hwmod omap2420_dss_core_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap2420_dss_slaves),
 	.masters	= omap2420_dss_masters,
 	.masters_cnt	= ARRAY_SIZE(omap2420_dss_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -938,7 +938,6 @@ static struct omap_hwmod omap2420_dss_dispc_hwmod = {
 	},
 	.slaves		= omap2420_dss_dispc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_dss_dispc_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -975,7 +974,6 @@ static struct omap_hwmod omap2420_dss_rfbi_hwmod = {
 	},
 	.slaves		= omap2420_dss_rfbi_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_dss_rfbi_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -1013,7 +1011,6 @@ static struct omap_hwmod omap2420_dss_venc_hwmod = {
 	},
 	.slaves		= omap2420_dss_venc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_dss_venc_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -1064,7 +1061,6 @@ static struct omap_hwmod omap2420_i2c1_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap2420_i2c1_slaves),
 	.class		= &i2c_class,
 	.dev_attr	= &i2c_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 	.flags		= HWMOD_16BIT_REG,
 };
 
@@ -1092,7 +1088,6 @@ static struct omap_hwmod omap2420_i2c2_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap2420_i2c2_slaves),
 	.class		= &i2c_class,
 	.dev_attr	= &i2c_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 	.flags		= HWMOD_16BIT_REG,
 };
 
@@ -1197,7 +1192,6 @@ static struct omap_hwmod omap2420_gpio1_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap2420_gpio1_slaves),
 	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* gpio2 */
@@ -1223,7 +1217,6 @@ static struct omap_hwmod omap2420_gpio2_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap2420_gpio2_slaves),
 	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* gpio3 */
@@ -1249,7 +1242,6 @@ static struct omap_hwmod omap2420_gpio3_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap2420_gpio3_slaves),
 	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* gpio4 */
@@ -1275,7 +1267,6 @@ static struct omap_hwmod omap2420_gpio4_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap2420_gpio4_slaves),
 	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* dma attributes */
@@ -1322,7 +1313,6 @@ static struct omap_hwmod omap2420_dma_system_hwmod = {
 	.masters	= omap2420_dma_system_masters,
 	.masters_cnt	= ARRAY_SIZE(omap2420_dma_system_masters),
 	.dev_attr	= &dma_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -1363,7 +1353,6 @@ static struct omap_hwmod omap2420_mailbox_hwmod = {
 	},
 	.slaves		= omap2420_mailbox_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_mailbox_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* mcspi1 */
@@ -1393,7 +1382,6 @@ static struct omap_hwmod omap2420_mcspi1_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap2420_mcspi1_slaves),
 	.class		= &omap2xxx_mcspi_class,
 	.dev_attr	= &omap_mcspi1_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* mcspi2 */
@@ -1423,7 +1411,6 @@ static struct omap_hwmod omap2420_mcspi2_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap2420_mcspi2_slaves),
 	.class		= &omap2xxx_mcspi_class,
 	.dev_attr	= &omap_mcspi2_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /*
@@ -1473,7 +1460,6 @@ static struct omap_hwmod omap2420_mcbsp1_hwmod = {
 	},
 	.slaves		= omap2420_mcbsp1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_mcbsp1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 /* mcbsp2 */
@@ -1514,7 +1500,6 @@ static struct omap_hwmod omap2420_mcbsp2_hwmod = {
 	},
 	.slaves		= omap2420_mcbsp2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_mcbsp2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
 static __initdata struct omap_hwmod *omap2420_hwmods[] = {
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index 408193d..a2580d0 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -110,7 +110,6 @@ static struct omap_hwmod omap2430_l3_main_hwmod = {
 	.masters_cnt	= ARRAY_SIZE(omap2430_l3_main_masters),
 	.slaves		= omap2430_l3_main_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_l3_main_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -250,7 +249,6 @@ static struct omap_hwmod omap2430_l4_core_hwmod = {
 	.masters_cnt	= ARRAY_SIZE(omap2430_l4_core_masters),
 	.slaves		= omap2430_l4_core_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_l4_core_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -301,7 +299,6 @@ static struct omap_hwmod omap2430_l4_wkup_hwmod = {
 	.masters_cnt	= ARRAY_SIZE(omap2430_l4_wkup_masters),
 	.slaves		= omap2430_l4_wkup_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_l4_wkup_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -317,7 +314,6 @@ static struct omap_hwmod omap2430_mpu_hwmod = {
 	.main_clk	= "mpu_ck",
 	.masters	= omap2430_mpu_masters,
 	.masters_cnt	= ARRAY_SIZE(omap2430_mpu_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /*
@@ -345,7 +341,16 @@ static struct omap_hwmod omap2430_iva_hwmod = {
 	.class		= &iva_hwmod_class,
 	.masters	= omap2430_iva_masters,
 	.masters_cnt	= ARRAY_SIZE(omap2430_iva_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
+};
+
+/* always-on timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
+	.timer_capability       = OMAP_TIMER_ALWON,
+};
+
+/* pwm timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
+	.timer_capability       = OMAP_TIMER_HAS_PWM,
 };
 
 /* timer1 */
@@ -388,10 +393,10 @@ static struct omap_hwmod omap2430_timer1_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT1_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer1_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer2 */
@@ -425,10 +430,10 @@ static struct omap_hwmod omap2430_timer2_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT2_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer2_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer3 */
@@ -462,10 +467,10 @@ static struct omap_hwmod omap2430_timer3_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT3_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer3_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer4 */
@@ -499,10 +504,10 @@ static struct omap_hwmod omap2430_timer4_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT4_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer4_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer5 */
@@ -536,10 +541,10 @@ static struct omap_hwmod omap2430_timer5_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT5_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer5_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer6 */
@@ -573,10 +578,10 @@ static struct omap_hwmod omap2430_timer6_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT6_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer6_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer6_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer7 */
@@ -610,10 +615,10 @@ static struct omap_hwmod omap2430_timer7_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT7_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer7_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer7_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer8 */
@@ -647,10 +652,10 @@ static struct omap_hwmod omap2430_timer8_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT8_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap2430_timer8_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer8_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer9 */
@@ -684,10 +689,10 @@ static struct omap_hwmod omap2430_timer9_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT9_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2430_timer9_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer9_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer10 */
@@ -721,10 +726,10 @@ static struct omap_hwmod omap2430_timer10_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT10_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2430_timer10_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer10_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer11 */
@@ -758,10 +763,10 @@ static struct omap_hwmod omap2430_timer11_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT11_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2430_timer11_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer11_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* timer12 */
@@ -795,10 +800,10 @@ static struct omap_hwmod omap2430_timer12_hwmod = {
 			.idlest_idle_bit = OMAP24XX_ST_GPT12_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap2430_timer12_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_timer12_slaves),
 	.class		= &omap2xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /* l4_wkup -> wd_timer2 */
@@ -839,7 +844,6 @@ static struct omap_hwmod omap2430_wd_timer2_hwmod = {
 	},
 	.slaves		= omap2430_wd_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_wd_timer2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* UART1 */
@@ -865,7 +869,6 @@ static struct omap_hwmod omap2430_uart1_hwmod = {
 	.slaves		= omap2430_uart1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_uart1_slaves),
 	.class		= &omap2_uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* UART2 */
@@ -891,7 +894,6 @@ static struct omap_hwmod omap2430_uart2_hwmod = {
 	.slaves		= omap2430_uart2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_uart2_slaves),
 	.class		= &omap2_uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* UART3 */
@@ -917,7 +919,6 @@ static struct omap_hwmod omap2430_uart3_hwmod = {
 	.slaves		= omap2430_uart3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_uart3_slaves),
 	.class		= &omap2_uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* dss */
@@ -965,7 +966,6 @@ static struct omap_hwmod omap2430_dss_core_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap2430_dss_slaves),
 	.masters	= omap2430_dss_masters,
 	.masters_cnt	= ARRAY_SIZE(omap2430_dss_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -999,7 +999,6 @@ static struct omap_hwmod omap2430_dss_dispc_hwmod = {
 	},
 	.slaves		= omap2430_dss_dispc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_dss_dispc_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -1030,7 +1029,6 @@ static struct omap_hwmod omap2430_dss_rfbi_hwmod = {
 	},
 	.slaves		= omap2430_dss_rfbi_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_dss_rfbi_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -1062,7 +1060,6 @@ static struct omap_hwmod omap2430_dss_venc_hwmod = {
 	},
 	.slaves		= omap2430_dss_venc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_dss_venc_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -1123,7 +1120,6 @@ static struct omap_hwmod omap2430_i2c1_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap2430_i2c1_slaves),
 	.class		= &i2c_class,
 	.dev_attr	= &i2c_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* I2C2 */
@@ -1151,7 +1147,6 @@ static struct omap_hwmod omap2430_i2c2_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap2430_i2c2_slaves),
 	.class		= &i2c_class,
 	.dev_attr	= &i2c_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* l4_wkup -> gpio1 */
@@ -1273,7 +1268,6 @@ static struct omap_hwmod omap2430_gpio1_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio1_slaves),
 	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* gpio2 */
@@ -1299,7 +1293,6 @@ static struct omap_hwmod omap2430_gpio2_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio2_slaves),
 	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* gpio3 */
@@ -1325,7 +1318,6 @@ static struct omap_hwmod omap2430_gpio3_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio3_slaves),
 	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* gpio4 */
@@ -1351,7 +1343,6 @@ static struct omap_hwmod omap2430_gpio4_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio4_slaves),
 	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* gpio5 */
@@ -1382,7 +1373,6 @@ static struct omap_hwmod omap2430_gpio5_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio5_slaves),
 	.class		= &omap2xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* dma attributes */
@@ -1429,7 +1419,6 @@ static struct omap_hwmod omap2430_dma_system_hwmod = {
 	.masters	= omap2430_dma_system_masters,
 	.masters_cnt	= ARRAY_SIZE(omap2430_dma_system_masters),
 	.dev_attr	= &dma_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -1469,7 +1458,6 @@ static struct omap_hwmod omap2430_mailbox_hwmod = {
 	},
 	.slaves		= omap2430_mailbox_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mailbox_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* mcspi1 */
@@ -1499,7 +1487,6 @@ static struct omap_hwmod omap2430_mcspi1_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mcspi1_slaves),
 	.class		= &omap2xxx_mcspi_class,
 	.dev_attr	= &omap_mcspi1_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* mcspi2 */
@@ -1529,7 +1516,6 @@ static struct omap_hwmod omap2430_mcspi2_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mcspi2_slaves),
 	.class		= &omap2xxx_mcspi_class,
 	.dev_attr	= &omap_mcspi2_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* mcspi3 */
@@ -1572,7 +1558,6 @@ static struct omap_hwmod omap2430_mcspi3_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mcspi3_slaves),
 	.class		= &omap2xxx_mcspi_class,
 	.dev_attr	= &omap_mcspi3_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /*
@@ -1628,7 +1613,6 @@ static struct omap_hwmod omap2430_usbhsotg_hwmod = {
 	 */
 	.flags		= HWMOD_NO_OCP_AUTOIDLE | HWMOD_SWSUP_SIDLE
 				| HWMOD_SWSUP_MSTANDBY,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
 /*
@@ -1689,7 +1673,6 @@ static struct omap_hwmod omap2430_mcbsp1_hwmod = {
 	},
 	.slaves		= omap2430_mcbsp1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mcbsp1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* mcbsp2 */
@@ -1731,7 +1714,6 @@ static struct omap_hwmod omap2430_mcbsp2_hwmod = {
 	},
 	.slaves		= omap2430_mcbsp2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mcbsp2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* mcbsp3 */
@@ -1783,7 +1765,6 @@ static struct omap_hwmod omap2430_mcbsp3_hwmod = {
 	},
 	.slaves		= omap2430_mcbsp3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mcbsp3_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* mcbsp4 */
@@ -1841,7 +1822,6 @@ static struct omap_hwmod omap2430_mcbsp4_hwmod = {
 	},
 	.slaves		= omap2430_mcbsp4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mcbsp4_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* mcbsp5 */
@@ -1899,7 +1879,6 @@ static struct omap_hwmod omap2430_mcbsp5_hwmod = {
 	},
 	.slaves		= omap2430_mcbsp5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mcbsp5_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* MMC/SD/SDIO common */
@@ -1966,7 +1945,6 @@ static struct omap_hwmod omap2430_mmc1_hwmod = {
 	.slaves		= omap2430_mmc1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mmc1_slaves),
 	.class		= &omap2430_mmc_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 /* MMC/SD/SDIO2 */
@@ -2010,7 +1988,6 @@ static struct omap_hwmod omap2430_mmc2_hwmod = {
 	.slaves		= omap2430_mmc2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_mmc2_slaves),
 	.class		= &omap2430_mmc_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
 static __initdata struct omap_hwmod *omap2430_hwmods[] = {
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 25bf43b..3008e16 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -156,7 +156,6 @@ static struct omap_hwmod omap3xxx_l3_main_hwmod = {
 	.masters_cnt	= ARRAY_SIZE(omap3xxx_l3_main_masters),
 	.slaves		= omap3xxx_l3_main_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_l3_main_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -459,7 +458,6 @@ static struct omap_hwmod omap3xxx_l4_core_hwmod = {
 	.class		= &l4_hwmod_class,
 	.slaves		= omap3xxx_l4_core_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_l4_core_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -474,7 +472,6 @@ static struct omap_hwmod omap3xxx_l4_per_hwmod = {
 	.class		= &l4_hwmod_class,
 	.slaves		= omap3xxx_l4_per_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_l4_per_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -489,7 +486,6 @@ static struct omap_hwmod omap3xxx_l4_wkup_hwmod = {
 	.class		= &l4_hwmod_class,
 	.slaves		= omap3xxx_l4_wkup_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_l4_wkup_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -505,7 +501,6 @@ static struct omap_hwmod omap3xxx_mpu_hwmod = {
 	.main_clk	= "arm_fck",
 	.masters	= omap3xxx_mpu_masters,
 	.masters_cnt	= ARRAY_SIZE(omap3xxx_mpu_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /*
@@ -533,7 +528,6 @@ static struct omap_hwmod omap3xxx_iva_hwmod = {
 	.class		= &iva_hwmod_class,
 	.masters	= omap3xxx_iva_masters,
 	.masters_cnt	= ARRAY_SIZE(omap3xxx_iva_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
 /* timer class */
@@ -570,6 +564,21 @@ static struct omap_hwmod_class omap3xxx_timer_hwmod_class = {
 	.rev =  OMAP_TIMER_IP_VERSION_1,
 };
 
+/* secure timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_secure_dev_attr = {
+	.timer_capability       = OMAP_TIMER_SECURE,
+};
+
+/* always-on timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
+	.timer_capability       = OMAP_TIMER_ALWON,
+};
+
+/* pwm timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
+	.timer_capability       = OMAP_TIMER_HAS_PWM,
+};
+
 /* timer1 */
 static struct omap_hwmod omap3xxx_timer1_hwmod;
 
@@ -610,10 +619,10 @@ static struct omap_hwmod omap3xxx_timer1_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT1_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap3xxx_timer1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer1_slaves),
 	.class		= &omap3xxx_timer_1ms_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
 /* timer2 */
@@ -656,10 +665,10 @@ static struct omap_hwmod omap3xxx_timer2_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT2_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap3xxx_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer2_slaves),
 	.class		= &omap3xxx_timer_1ms_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
 /* timer3 */
@@ -702,10 +711,10 @@ static struct omap_hwmod omap3xxx_timer3_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT3_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap3xxx_timer3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer3_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
 /* timer4 */
@@ -748,10 +757,10 @@ static struct omap_hwmod omap3xxx_timer4_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT4_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap3xxx_timer4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer4_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
 /* timer5 */
@@ -794,10 +803,10 @@ static struct omap_hwmod omap3xxx_timer5_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT5_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap3xxx_timer5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer5_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
 /* timer6 */
@@ -840,10 +849,10 @@ static struct omap_hwmod omap3xxx_timer6_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT6_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap3xxx_timer6_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer6_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
 /* timer7 */
@@ -886,10 +895,10 @@ static struct omap_hwmod omap3xxx_timer7_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT7_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap3xxx_timer7_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer7_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
 /* timer8 */
@@ -932,10 +941,10 @@ static struct omap_hwmod omap3xxx_timer8_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT8_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap3xxx_timer8_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer8_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
 /* timer9 */
@@ -978,10 +987,10 @@ static struct omap_hwmod omap3xxx_timer9_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT9_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap3xxx_timer9_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer9_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
 /* timer10 */
@@ -1015,10 +1024,10 @@ static struct omap_hwmod omap3xxx_timer10_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT10_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap3xxx_timer10_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer10_slaves),
 	.class		= &omap3xxx_timer_1ms_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
 /* timer11 */
@@ -1052,10 +1061,10 @@ static struct omap_hwmod omap3xxx_timer11_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT11_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap3xxx_timer11_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer11_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
 /* timer12*/
@@ -1102,10 +1111,10 @@ static struct omap_hwmod omap3xxx_timer12_hwmod = {
 			.idlest_idle_bit = OMAP3430_ST_GPT12_SHIFT,
 		},
 	},
+	.dev_attr	= &capability_secure_dev_attr,
 	.slaves		= omap3xxx_timer12_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer12_slaves),
 	.class		= &omap3xxx_timer_hwmod_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
 /* l4_wkup -> wd_timer2 */
@@ -1182,7 +1191,6 @@ static struct omap_hwmod omap3xxx_wd_timer2_hwmod = {
 	},
 	.slaves		= omap3xxx_wd_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_wd_timer2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	/*
 	 * XXX: Use software supervised mode, HW supervised smartidle seems to
 	 * block CORE power domain idle transitions. Maybe a HW bug in wdt2?
@@ -1213,7 +1221,6 @@ static struct omap_hwmod omap3xxx_uart1_hwmod = {
 	.slaves		= omap3xxx_uart1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_uart1_slaves),
 	.class		= &omap2_uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* UART2 */
@@ -1239,7 +1246,6 @@ static struct omap_hwmod omap3xxx_uart2_hwmod = {
 	.slaves		= omap3xxx_uart2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_uart2_slaves),
 	.class		= &omap2_uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* UART3 */
@@ -1265,7 +1271,6 @@ static struct omap_hwmod omap3xxx_uart3_hwmod = {
 	.slaves		= omap3xxx_uart3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_uart3_slaves),
 	.class		= &omap2_uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* UART4 */
@@ -1302,7 +1307,6 @@ static struct omap_hwmod omap3xxx_uart4_hwmod = {
 	.slaves		= omap3xxx_uart4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_uart4_slaves),
 	.class		= &omap2_uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
 };
 
 static struct omap_hwmod_class i2c_class = {
@@ -1390,7 +1394,6 @@ static struct omap_hwmod omap3430es1_dss_core_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap3430es1_dss_slaves),
 	.masters	= omap3xxx_dss_masters,
 	.masters_cnt	= ARRAY_SIZE(omap3xxx_dss_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -1415,8 +1418,6 @@ static struct omap_hwmod omap3xxx_dss_core_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dss_slaves),
 	.masters	= omap3xxx_dss_masters,
 	.masters_cnt	= ARRAY_SIZE(omap3xxx_dss_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2 |
-				CHIP_IS_OMAP3630ES1 | CHIP_GE_OMAP3630ES1_1),
 };
 
 /* l4_core -> dss_dispc */
@@ -1454,9 +1455,6 @@ static struct omap_hwmod omap3xxx_dss_dispc_hwmod = {
 	},
 	.slaves		= omap3xxx_dss_dispc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dss_dispc_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
-				CHIP_GE_OMAP3430ES2 | CHIP_IS_OMAP3630ES1 |
-				CHIP_GE_OMAP3630ES1_1),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -1518,9 +1516,6 @@ static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = {
 	},
 	.slaves		= omap3xxx_dss_dsi1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dss_dsi1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
-				CHIP_GE_OMAP3430ES2 | CHIP_IS_OMAP3630ES1 |
-				CHIP_GE_OMAP3630ES1_1),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -1558,9 +1553,6 @@ static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = {
 	},
 	.slaves		= omap3xxx_dss_rfbi_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dss_rfbi_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
-				CHIP_GE_OMAP3430ES2 | CHIP_IS_OMAP3630ES1 |
-				CHIP_GE_OMAP3630ES1_1),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -1599,9 +1591,6 @@ static struct omap_hwmod omap3xxx_dss_venc_hwmod = {
 	},
 	.slaves		= omap3xxx_dss_venc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dss_venc_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
-				CHIP_GE_OMAP3430ES2 | CHIP_IS_OMAP3630ES1 |
-				CHIP_GE_OMAP3630ES1_1),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -1637,7 +1626,6 @@ static struct omap_hwmod omap3xxx_i2c1_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_i2c1_slaves),
 	.class		= &i2c_class,
 	.dev_attr	= &i2c1_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* I2C2 */
@@ -1672,7 +1660,6 @@ static struct omap_hwmod omap3xxx_i2c2_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_i2c2_slaves),
 	.class		= &i2c_class,
 	.dev_attr	= &i2c2_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* I2C3 */
@@ -1718,7 +1705,6 @@ static struct omap_hwmod omap3xxx_i2c3_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_i2c3_slaves),
 	.class		= &i2c_class,
 	.dev_attr	= &i2c3_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* l4_wkup -> gpio1 */
@@ -1880,7 +1866,6 @@ static struct omap_hwmod omap3xxx_gpio1_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_gpio1_slaves),
 	.class		= &omap3xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* gpio2 */
@@ -1912,7 +1897,6 @@ static struct omap_hwmod omap3xxx_gpio2_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_gpio2_slaves),
 	.class		= &omap3xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* gpio3 */
@@ -1944,7 +1928,6 @@ static struct omap_hwmod omap3xxx_gpio3_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_gpio3_slaves),
 	.class		= &omap3xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* gpio4 */
@@ -1976,7 +1959,6 @@ static struct omap_hwmod omap3xxx_gpio4_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_gpio4_slaves),
 	.class		= &omap3xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* gpio5 */
@@ -2013,7 +1995,6 @@ static struct omap_hwmod omap3xxx_gpio5_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_gpio5_slaves),
 	.class		= &omap3xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* gpio6 */
@@ -2050,7 +2031,6 @@ static struct omap_hwmod omap3xxx_gpio6_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_gpio6_slaves),
 	.class		= &omap3xxx_gpio_hwmod_class,
 	.dev_attr	= &gpio_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* dma_system -> L3 */
@@ -2134,7 +2114,6 @@ static struct omap_hwmod omap3xxx_dma_system_hwmod = {
 	.masters	= omap3xxx_dma_system_masters,
 	.masters_cnt	= ARRAY_SIZE(omap3xxx_dma_system_masters),
 	.dev_attr	= &dma_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -2207,7 +2186,6 @@ static struct omap_hwmod omap3xxx_mcbsp1_hwmod = {
 	},
 	.slaves		= omap3xxx_mcbsp1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* mcbsp2 */
@@ -2264,7 +2242,6 @@ static struct omap_hwmod omap3xxx_mcbsp2_hwmod = {
 	.slaves		= omap3xxx_mcbsp2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp2_slaves),
 	.dev_attr	= &omap34xx_mcbsp2_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* mcbsp3 */
@@ -2321,7 +2298,6 @@ static struct omap_hwmod omap3xxx_mcbsp3_hwmod = {
 	.slaves		= omap3xxx_mcbsp3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp3_slaves),
 	.dev_attr	= &omap34xx_mcbsp3_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* mcbsp4 */
@@ -2379,7 +2355,6 @@ static struct omap_hwmod omap3xxx_mcbsp4_hwmod = {
 	},
 	.slaves		= omap3xxx_mcbsp4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp4_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* mcbsp5 */
@@ -2437,7 +2412,6 @@ static struct omap_hwmod omap3xxx_mcbsp5_hwmod = {
 	},
 	.slaves		= omap3xxx_mcbsp5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp5_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 /* 'mcbsp sidetone' class */
 
@@ -2498,7 +2472,6 @@ static struct omap_hwmod omap3xxx_mcbsp2_sidetone_hwmod = {
 	},
 	.slaves		= omap3xxx_mcbsp2_sidetone_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp2_sidetone_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* mcbsp3_sidetone */
@@ -2547,7 +2520,6 @@ static struct omap_hwmod omap3xxx_mcbsp3_sidetone_hwmod = {
 	},
 	.slaves		= omap3xxx_mcbsp3_sidetone_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp3_sidetone_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 
@@ -2597,7 +2569,7 @@ static struct omap_hwmod omap34xx_sr1_hwmod = {
 	.name		= "sr1_hwmod",
 	.class		= &omap34xx_smartreflex_hwmod_class,
 	.main_clk	= "sr1_fck",
-	.vdd_name	= "mpu",
+	.vdd_name	= "mpu_iva",
 	.prcm		= {
 		.omap2 = {
 			.prcm_reg_id = 1,
@@ -2609,9 +2581,6 @@ static struct omap_hwmod omap34xx_sr1_hwmod = {
 	},
 	.slaves		= omap3_sr1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3_sr1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2 |
-					CHIP_IS_OMAP3430ES3_0 |
-					CHIP_IS_OMAP3430ES3_1),
 	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
@@ -2619,7 +2588,7 @@ static struct omap_hwmod omap36xx_sr1_hwmod = {
 	.name		= "sr1_hwmod",
 	.class		= &omap36xx_smartreflex_hwmod_class,
 	.main_clk	= "sr1_fck",
-	.vdd_name	= "mpu",
+	.vdd_name	= "mpu_iva",
 	.prcm		= {
 		.omap2 = {
 			.prcm_reg_id = 1,
@@ -2631,7 +2600,6 @@ static struct omap_hwmod omap36xx_sr1_hwmod = {
 	},
 	.slaves		= omap3_sr1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3_sr1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
 };
 
 /* SR2 */
@@ -2655,9 +2623,6 @@ static struct omap_hwmod omap34xx_sr2_hwmod = {
 	},
 	.slaves		= omap3_sr2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3_sr2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2 |
-					CHIP_IS_OMAP3430ES3_0 |
-					CHIP_IS_OMAP3430ES3_1),
 	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
@@ -2677,7 +2642,6 @@ static struct omap_hwmod omap36xx_sr2_hwmod = {
 	},
 	.slaves		= omap3_sr2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3_sr2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
 };
 
 /*
@@ -2745,7 +2709,6 @@ static struct omap_hwmod omap3xxx_mailbox_hwmod = {
 	},
 	.slaves		= omap3xxx_mailbox_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mailbox_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* l4 core -> mcspi1 interface */
@@ -2843,7 +2806,6 @@ static struct omap_hwmod omap34xx_mcspi1 = {
 	.slaves_cnt	= ARRAY_SIZE(omap34xx_mcspi1_slaves),
 	.class		= &omap34xx_mcspi_class,
 	.dev_attr       = &omap_mcspi1_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* mcspi2 */
@@ -2873,7 +2835,6 @@ static struct omap_hwmod omap34xx_mcspi2 = {
 	.slaves_cnt	= ARRAY_SIZE(omap34xx_mcspi2_slaves),
 	.class		= &omap34xx_mcspi_class,
 	.dev_attr       = &omap_mcspi2_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* mcspi3 */
@@ -2916,7 +2877,6 @@ static struct omap_hwmod omap34xx_mcspi3 = {
 	.slaves_cnt	= ARRAY_SIZE(omap34xx_mcspi3_slaves),
 	.class		= &omap34xx_mcspi_class,
 	.dev_attr       = &omap_mcspi3_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* SPI4 */
@@ -2957,7 +2917,6 @@ static struct omap_hwmod omap34xx_mcspi4 = {
 	.slaves_cnt	= ARRAY_SIZE(omap34xx_mcspi4_slaves),
 	.class		= &omap34xx_mcspi_class,
 	.dev_attr       = &omap_mcspi4_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /*
@@ -3014,7 +2973,6 @@ static struct omap_hwmod omap3xxx_usbhsotg_hwmod = {
 	 */
 	.flags		= HWMOD_NO_OCP_AUTOIDLE | HWMOD_SWSUP_SIDLE
 				| HWMOD_SWSUP_MSTANDBY,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
 /* usb_otg_hs */
@@ -3042,7 +3000,6 @@ static struct omap_hwmod am35xx_usbhsotg_hwmod = {
 	.slaves		= am35xx_usbhsotg_slaves,
 	.slaves_cnt	= ARRAY_SIZE(am35xx_usbhsotg_slaves),
 	.class		= &am35xx_usbotg_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES3_1)
 };
 
 /* MMC/SD/SDIO common */
@@ -3108,7 +3065,6 @@ static struct omap_hwmod omap3xxx_mmc1_hwmod = {
 	.slaves		= omap3xxx_mmc1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mmc1_slaves),
 	.class		= &omap34xx_mmc_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* MMC/SD/SDIO2 */
@@ -3151,7 +3107,6 @@ static struct omap_hwmod omap3xxx_mmc2_hwmod = {
 	.slaves		= omap3xxx_mmc2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mmc2_slaves),
 	.class		= &omap34xx_mmc_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 /* MMC/SD/SDIO3 */
@@ -3193,7 +3148,6 @@ static struct omap_hwmod omap3xxx_mmc3_hwmod = {
 	.slaves		= omap3xxx_mmc3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mmc3_slaves),
 	.class		= &omap34xx_mmc_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
@@ -3224,10 +3178,7 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
 	&omap3xxx_uart1_hwmod,
 	&omap3xxx_uart2_hwmod,
 	&omap3xxx_uart3_hwmod,
-	&omap3xxx_uart4_hwmod,
 	/* dss class */
-	&omap3430es1_dss_core_hwmod,
-	&omap3xxx_dss_core_hwmod,
 	&omap3xxx_dss_dispc_hwmod,
 	&omap3xxx_dss_dsi1_hwmod,
 	&omap3xxx_dss_rfbi_hwmod,
@@ -3239,9 +3190,6 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
 	&omap3xxx_i2c3_hwmod,
 	&omap34xx_sr1_hwmod,
 	&omap34xx_sr2_hwmod,
-	&omap36xx_sr1_hwmod,
-	&omap36xx_sr2_hwmod,
-
 
 	/* gpio class */
 	&omap3xxx_gpio1_hwmod,
@@ -3272,16 +3220,96 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
 	&omap34xx_mcspi3,
 	&omap34xx_mcspi4,
 
-	/* usbotg class */
+	NULL,
+};
+
+/* 3430ES1-only hwmods */
+static __initdata struct omap_hwmod *omap3430es1_hwmods[] = {
+	&omap3430es1_dss_core_hwmod,
+	NULL
+};
+
+/* 3430ES2+-only hwmods */
+static __initdata struct omap_hwmod *omap3430es2plus_hwmods[] = {
+	&omap3xxx_dss_core_hwmod,
 	&omap3xxx_usbhsotg_hwmod,
+	NULL
+};
 
-	/* usbotg for am35x */
-	&am35xx_usbhsotg_hwmod,
+/* 34xx-only hwmods (all ES revisions) */
+static __initdata struct omap_hwmod *omap34xx_hwmods[] = {
+	&omap34xx_sr1_hwmod,
+	&omap34xx_sr2_hwmod,
+	NULL
+};
 
-	NULL,
+/* 36xx-only hwmods (all ES revisions) */
+static __initdata struct omap_hwmod *omap36xx_hwmods[] = {
+	&omap3xxx_uart4_hwmod,
+	&omap3xxx_dss_core_hwmod,
+	&omap36xx_sr1_hwmod,
+	&omap36xx_sr2_hwmod,
+	&omap3xxx_usbhsotg_hwmod,
+	NULL
+};
+
+static __initdata struct omap_hwmod *am35xx_hwmods[] = {
+	&omap3xxx_dss_core_hwmod, /* XXX ??? */
+	&am35xx_usbhsotg_hwmod,
+	NULL
 };
 
 int __init omap3xxx_hwmod_init(void)
 {
-	return omap_hwmod_register(omap3xxx_hwmods);
+	int r;
+	struct omap_hwmod **h = NULL;
+	unsigned int rev;
+
+	/* Register hwmods common to all OMAP3 */
+	r = omap_hwmod_register(omap3xxx_hwmods);
+	if (!r)
+		return r;
+
+	rev = omap_rev();
+
+	/*
+	 * Register hwmods common to individual OMAP3 families, all
+	 * silicon revisions (e.g., 34xx, or AM3505/3517, or 36xx)
+	 * All possible revisions should be included in this conditional.
+	 */
+	if (rev == OMAP3430_REV_ES1_0 || rev == OMAP3430_REV_ES2_0 ||
+	    rev == OMAP3430_REV_ES2_1 || rev == OMAP3430_REV_ES3_0 ||
+	    rev == OMAP3430_REV_ES3_1 || rev == OMAP3430_REV_ES3_1_2) {
+		h = omap34xx_hwmods;
+	} else if (rev == OMAP3517_REV_ES1_0 || rev == OMAP3517_REV_ES1_1) {
+		h = am35xx_hwmods;
+	} else if (rev == OMAP3630_REV_ES1_0 || rev == OMAP3630_REV_ES1_1 ||
+		   rev == OMAP3630_REV_ES1_2) {
+		h = omap36xx_hwmods;
+	} else {
+		WARN(1, "OMAP3 hwmod family init: unknown chip type\n");
+		return -EINVAL;
+	};
+
+	r = omap_hwmod_register(h);
+	if (!r)
+		return r;
+
+	/*
+	 * Register hwmods specific to certain ES levels of a
+	 * particular family of silicon (e.g., 34xx ES1.0)
+	 */
+	h = NULL;
+	if (rev == OMAP3430_REV_ES1_0) {
+		h = omap3430es1_hwmods;
+	} else if (rev == OMAP3430_REV_ES2_0 || rev == OMAP3430_REV_ES2_1 ||
+		   rev == OMAP3430_REV_ES3_0 || rev == OMAP3430_REV_ES3_1 ||
+		   rev == OMAP3430_REV_ES3_1_2) {
+		h = omap3430es2plus_hwmods;
+	};
+
+	if (h)
+		r = omap_hwmod_register(h);
+
+	return r;
 }
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 79325c6..7695e5d 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -29,6 +29,7 @@
 #include <plat/mcbsp.h>
 #include <plat/mmc.h>
 #include <plat/i2c.h>
+#include <plat/dmtimer.h>
 
 #include "omap_hwmod_common_data.h"
 
@@ -133,7 +134,6 @@ static struct omap_hwmod omap44xx_dmm_hwmod = {
 	.slaves		= omap44xx_dmm_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dmm_slaves),
 	.mpu_irqs	= omap44xx_dmm_irqs,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -189,7 +189,6 @@ static struct omap_hwmod omap44xx_emif_fw_hwmod = {
 	},
 	.slaves		= omap44xx_emif_fw_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_emif_fw_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -236,7 +235,6 @@ static struct omap_hwmod omap44xx_l3_instr_hwmod = {
 	},
 	.slaves		= omap44xx_l3_instr_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l3_instr_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* l3_main_1 */
@@ -336,7 +334,6 @@ static struct omap_hwmod omap44xx_l3_main_1_hwmod = {
 	},
 	.slaves		= omap44xx_l3_main_1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l3_main_1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* l3_main_2 */
@@ -438,7 +435,6 @@ static struct omap_hwmod omap44xx_l3_main_2_hwmod = {
 	},
 	.slaves		= omap44xx_l3_main_2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l3_main_2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* l3_main_3 */
@@ -496,7 +492,6 @@ static struct omap_hwmod omap44xx_l3_main_3_hwmod = {
 	},
 	.slaves		= omap44xx_l3_main_3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l3_main_3_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -559,7 +554,6 @@ static struct omap_hwmod omap44xx_l4_abe_hwmod = {
 	},
 	.slaves		= omap44xx_l4_abe_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l4_abe_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* l4_cfg */
@@ -588,7 +582,6 @@ static struct omap_hwmod omap44xx_l4_cfg_hwmod = {
 	},
 	.slaves		= omap44xx_l4_cfg_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l4_cfg_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* l4_per */
@@ -617,7 +610,6 @@ static struct omap_hwmod omap44xx_l4_per_hwmod = {
 	},
 	.slaves		= omap44xx_l4_per_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l4_per_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* l4_wkup */
@@ -646,7 +638,6 @@ static struct omap_hwmod omap44xx_l4_wkup_hwmod = {
 	},
 	.slaves		= omap44xx_l4_wkup_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l4_wkup_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -677,7 +668,6 @@ static struct omap_hwmod omap44xx_mpu_private_hwmod = {
 	.clkdm_name	= "mpuss_clkdm",
 	.slaves		= omap44xx_mpu_private_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mpu_private_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -828,7 +818,6 @@ static struct omap_hwmod omap44xx_aess_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_aess_slaves),
 	.masters	= omap44xx_aess_masters,
 	.masters_cnt	= ARRAY_SIZE(omap44xx_aess_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -856,7 +845,6 @@ static struct omap_hwmod omap44xx_bandgap_hwmod = {
 	},
 	.opt_clks	= bandgap_opt_clks,
 	.opt_clks_cnt	= ARRAY_SIZE(bandgap_opt_clks),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -917,7 +905,6 @@ static struct omap_hwmod omap44xx_counter_32k_hwmod = {
 	},
 	.slaves		= omap44xx_counter_32k_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_counter_32k_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -1005,7 +992,6 @@ static struct omap_hwmod omap44xx_dma_system_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dma_system_slaves),
 	.masters	= omap44xx_dma_system_masters,
 	.masters_cnt	= ARRAY_SIZE(omap44xx_dma_system_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -1098,7 +1084,6 @@ static struct omap_hwmod omap44xx_dmic_hwmod = {
 	},
 	.slaves		= omap44xx_dmic_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dmic_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -1164,7 +1149,6 @@ static struct omap_hwmod omap44xx_dsp_c0_hwmod = {
 			.rstctrl_offs = OMAP4_RM_TESLA_RSTCTRL_OFFSET,
 		},
 	},
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct omap_hwmod omap44xx_dsp_hwmod = {
@@ -1187,7 +1171,6 @@ static struct omap_hwmod omap44xx_dsp_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dsp_slaves),
 	.masters	= omap44xx_dsp_masters,
 	.masters_cnt	= ARRAY_SIZE(omap44xx_dsp_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -1278,7 +1261,6 @@ static struct omap_hwmod omap44xx_dss_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_slaves),
 	.masters	= omap44xx_dss_masters,
 	.masters_cnt	= ARRAY_SIZE(omap44xx_dss_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -1381,7 +1363,6 @@ static struct omap_hwmod omap44xx_dss_dispc_hwmod = {
 	.opt_clks_cnt	= ARRAY_SIZE(dss_dispc_opt_clks),
 	.slaves		= omap44xx_dss_dispc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -1480,7 +1461,6 @@ static struct omap_hwmod omap44xx_dss_dsi1_hwmod = {
 	.opt_clks_cnt	= ARRAY_SIZE(dss_dsi1_opt_clks),
 	.slaves		= omap44xx_dss_dsi1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* dss_dsi2 */
@@ -1558,7 +1538,6 @@ static struct omap_hwmod omap44xx_dss_dsi2_hwmod = {
 	.opt_clks_cnt	= ARRAY_SIZE(dss_dsi2_opt_clks),
 	.slaves		= omap44xx_dss_dsi2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_dsi2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -1656,7 +1635,6 @@ static struct omap_hwmod omap44xx_dss_hdmi_hwmod = {
 	.opt_clks_cnt	= ARRAY_SIZE(dss_hdmi_opt_clks),
 	.slaves		= omap44xx_dss_hdmi_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -1748,7 +1726,6 @@ static struct omap_hwmod omap44xx_dss_rfbi_hwmod = {
 	.opt_clks_cnt	= ARRAY_SIZE(dss_rfbi_opt_clks),
 	.slaves		= omap44xx_dss_rfbi_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_rfbi_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -1817,7 +1794,6 @@ static struct omap_hwmod omap44xx_dss_venc_hwmod = {
 	},
 	.slaves		= omap44xx_dss_venc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_venc_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -1901,7 +1877,6 @@ static struct omap_hwmod omap44xx_gpio1_hwmod = {
 	.dev_attr	= &gpio_dev_attr,
 	.slaves		= omap44xx_gpio1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* gpio2 */
@@ -1957,7 +1932,6 @@ static struct omap_hwmod omap44xx_gpio2_hwmod = {
 	.dev_attr	= &gpio_dev_attr,
 	.slaves		= omap44xx_gpio2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* gpio3 */
@@ -2013,7 +1987,6 @@ static struct omap_hwmod omap44xx_gpio3_hwmod = {
 	.dev_attr	= &gpio_dev_attr,
 	.slaves		= omap44xx_gpio3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio3_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* gpio4 */
@@ -2069,7 +2042,6 @@ static struct omap_hwmod omap44xx_gpio4_hwmod = {
 	.dev_attr	= &gpio_dev_attr,
 	.slaves		= omap44xx_gpio4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio4_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* gpio5 */
@@ -2125,7 +2097,6 @@ static struct omap_hwmod omap44xx_gpio5_hwmod = {
 	.dev_attr	= &gpio_dev_attr,
 	.slaves		= omap44xx_gpio5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio5_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* gpio6 */
@@ -2181,7 +2152,6 @@ static struct omap_hwmod omap44xx_gpio6_hwmod = {
 	.dev_attr	= &gpio_dev_attr,
 	.slaves		= omap44xx_gpio6_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio6_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -2261,7 +2231,6 @@ static struct omap_hwmod omap44xx_hsi_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_hsi_slaves),
 	.masters	= omap44xx_hsi_masters,
 	.masters_cnt	= ARRAY_SIZE(omap44xx_hsi_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -2345,7 +2314,6 @@ static struct omap_hwmod omap44xx_i2c1_hwmod = {
 	.slaves		= omap44xx_i2c1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_i2c1_slaves),
 	.dev_attr	= &i2c_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* i2c2 */
@@ -2402,7 +2370,6 @@ static struct omap_hwmod omap44xx_i2c2_hwmod = {
 	.slaves		= omap44xx_i2c2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_i2c2_slaves),
 	.dev_attr	= &i2c_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* i2c3 */
@@ -2459,7 +2426,6 @@ static struct omap_hwmod omap44xx_i2c3_hwmod = {
 	.slaves		= omap44xx_i2c3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_i2c3_slaves),
 	.dev_attr	= &i2c_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* i2c4 */
@@ -2516,7 +2482,6 @@ static struct omap_hwmod omap44xx_i2c4_hwmod = {
 	.slaves		= omap44xx_i2c4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_i2c4_slaves),
 	.dev_attr	= &i2c_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -2577,7 +2542,6 @@ static struct omap_hwmod omap44xx_ipu_c0_hwmod = {
 			.rstctrl_offs = OMAP4_RM_DUCATI_RSTCTRL_OFFSET,
 		},
 	},
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* Pseudo hwmod for reset control purpose only */
@@ -2593,7 +2557,6 @@ static struct omap_hwmod omap44xx_ipu_c1_hwmod = {
 			.rstctrl_offs = OMAP4_RM_DUCATI_RSTCTRL_OFFSET,
 		},
 	},
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct omap_hwmod omap44xx_ipu_hwmod = {
@@ -2616,7 +2579,6 @@ static struct omap_hwmod omap44xx_ipu_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_ipu_slaves),
 	.masters	= omap44xx_ipu_masters,
 	.masters_cnt	= ARRAY_SIZE(omap44xx_ipu_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -2706,7 +2668,6 @@ static struct omap_hwmod omap44xx_iss_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_iss_slaves),
 	.masters	= omap44xx_iss_masters,
 	.masters_cnt	= ARRAY_SIZE(omap44xx_iss_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -2781,7 +2742,6 @@ static struct omap_hwmod omap44xx_iva_seq0_hwmod = {
 			.rstctrl_offs = OMAP4_RM_IVAHD_RSTCTRL_OFFSET,
 		},
 	},
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* Pseudo hwmod for reset control purpose only */
@@ -2797,7 +2757,6 @@ static struct omap_hwmod omap44xx_iva_seq1_hwmod = {
 			.rstctrl_offs = OMAP4_RM_IVAHD_RSTCTRL_OFFSET,
 		},
 	},
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static struct omap_hwmod omap44xx_iva_hwmod = {
@@ -2820,7 +2779,6 @@ static struct omap_hwmod omap44xx_iva_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_iva_slaves),
 	.masters	= omap44xx_iva_masters,
 	.masters_cnt	= ARRAY_SIZE(omap44xx_iva_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -2890,7 +2848,6 @@ static struct omap_hwmod omap44xx_kbd_hwmod = {
 	},
 	.slaves		= omap44xx_kbd_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_kbd_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -2956,7 +2913,6 @@ static struct omap_hwmod omap44xx_mailbox_hwmod = {
 	},
 	.slaves		= omap44xx_mailbox_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mailbox_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -3051,7 +3007,6 @@ static struct omap_hwmod omap44xx_mcbsp1_hwmod = {
 	},
 	.slaves		= omap44xx_mcbsp1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcbsp1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* mcbsp2 */
@@ -3127,7 +3082,6 @@ static struct omap_hwmod omap44xx_mcbsp2_hwmod = {
 	},
 	.slaves		= omap44xx_mcbsp2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcbsp2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* mcbsp3 */
@@ -3203,7 +3157,6 @@ static struct omap_hwmod omap44xx_mcbsp3_hwmod = {
 	},
 	.slaves		= omap44xx_mcbsp3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcbsp3_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* mcbsp4 */
@@ -3258,7 +3211,6 @@ static struct omap_hwmod omap44xx_mcbsp4_hwmod = {
 	},
 	.slaves		= omap44xx_mcbsp4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcbsp4_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -3353,7 +3305,6 @@ static struct omap_hwmod omap44xx_mcpdm_hwmod = {
 	},
 	.slaves		= omap44xx_mcpdm_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcpdm_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -3442,7 +3393,6 @@ static struct omap_hwmod omap44xx_mcspi1_hwmod = {
 	.dev_attr	= &mcspi1_dev_attr,
 	.slaves		= omap44xx_mcspi1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcspi1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* mcspi2 */
@@ -3505,7 +3455,6 @@ static struct omap_hwmod omap44xx_mcspi2_hwmod = {
 	.dev_attr	= &mcspi2_dev_attr,
 	.slaves		= omap44xx_mcspi2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcspi2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* mcspi3 */
@@ -3568,7 +3517,6 @@ static struct omap_hwmod omap44xx_mcspi3_hwmod = {
 	.dev_attr	= &mcspi3_dev_attr,
 	.slaves		= omap44xx_mcspi3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcspi3_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* mcspi4 */
@@ -3629,7 +3577,6 @@ static struct omap_hwmod omap44xx_mcspi4_hwmod = {
 	.dev_attr	= &mcspi4_dev_attr,
 	.slaves		= omap44xx_mcspi4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcspi4_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -3718,7 +3665,6 @@ static struct omap_hwmod omap44xx_mmc1_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mmc1_slaves),
 	.masters	= omap44xx_mmc1_masters,
 	.masters_cnt	= ARRAY_SIZE(omap44xx_mmc1_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* mmc2 */
@@ -3779,7 +3725,6 @@ static struct omap_hwmod omap44xx_mmc2_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mmc2_slaves),
 	.masters	= omap44xx_mmc2_masters,
 	.masters_cnt	= ARRAY_SIZE(omap44xx_mmc2_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* mmc3 */
@@ -3834,7 +3779,6 @@ static struct omap_hwmod omap44xx_mmc3_hwmod = {
 	},
 	.slaves		= omap44xx_mmc3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mmc3_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* mmc4 */
@@ -3890,7 +3834,6 @@ static struct omap_hwmod omap44xx_mmc4_hwmod = {
 	},
 	.slaves		= omap44xx_mmc4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mmc4_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* mmc5 */
@@ -3945,7 +3888,6 @@ static struct omap_hwmod omap44xx_mmc5_hwmod = {
 	},
 	.slaves		= omap44xx_mmc5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_mmc5_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -3987,7 +3929,6 @@ static struct omap_hwmod omap44xx_mpu_hwmod = {
 	},
 	.masters	= omap44xx_mpu_masters,
 	.masters_cnt	= ARRAY_SIZE(omap44xx_mpu_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -4063,7 +4004,6 @@ static struct omap_hwmod omap44xx_smartreflex_core_hwmod = {
 	},
 	.slaves		= omap44xx_smartreflex_core_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_smartreflex_core_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* smartreflex_iva */
@@ -4112,7 +4052,6 @@ static struct omap_hwmod omap44xx_smartreflex_iva_hwmod = {
 	},
 	.slaves		= omap44xx_smartreflex_iva_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_smartreflex_iva_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* smartreflex_mpu */
@@ -4161,7 +4100,6 @@ static struct omap_hwmod omap44xx_smartreflex_mpu_hwmod = {
 	},
 	.slaves		= omap44xx_smartreflex_mpu_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_smartreflex_mpu_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -4224,7 +4162,6 @@ static struct omap_hwmod omap44xx_spinlock_hwmod = {
 	},
 	.slaves		= omap44xx_spinlock_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_spinlock_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -4265,6 +4202,16 @@ static struct omap_hwmod_class omap44xx_timer_hwmod_class = {
 	.sysc	= &omap44xx_timer_sysc,
 };
 
+/* always-on timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_alwon_dev_attr = {
+	.timer_capability	= OMAP_TIMER_ALWON,
+};
+
+/* pwm timers dev attribute */
+static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
+	.timer_capability	= OMAP_TIMER_HAS_PWM,
+};
+
 /* timer1 */
 static struct omap_hwmod omap44xx_timer1_hwmod;
 static struct omap_hwmod_irq_info omap44xx_timer1_irqs[] = {
@@ -4308,9 +4255,9 @@ static struct omap_hwmod omap44xx_timer1_hwmod = {
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* timer2 */
@@ -4356,9 +4303,9 @@ static struct omap_hwmod omap44xx_timer2_hwmod = {
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* timer3 */
@@ -4404,9 +4351,9 @@ static struct omap_hwmod omap44xx_timer3_hwmod = {
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer3_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* timer4 */
@@ -4452,9 +4399,9 @@ static struct omap_hwmod omap44xx_timer4_hwmod = {
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer4_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* timer5 */
@@ -4519,9 +4466,9 @@ static struct omap_hwmod omap44xx_timer5_hwmod = {
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer5_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer5_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* timer6 */
@@ -4587,9 +4534,9 @@ static struct omap_hwmod omap44xx_timer6_hwmod = {
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer6_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer6_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* timer7 */
@@ -4654,9 +4601,9 @@ static struct omap_hwmod omap44xx_timer7_hwmod = {
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_alwon_dev_attr,
 	.slaves		= omap44xx_timer7_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer7_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* timer8 */
@@ -4721,9 +4668,9 @@ static struct omap_hwmod omap44xx_timer8_hwmod = {
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap44xx_timer8_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer8_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* timer9 */
@@ -4769,9 +4716,9 @@ static struct omap_hwmod omap44xx_timer9_hwmod = {
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap44xx_timer9_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer9_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* timer10 */
@@ -4817,9 +4764,9 @@ static struct omap_hwmod omap44xx_timer10_hwmod = {
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap44xx_timer10_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer10_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* timer11 */
@@ -4865,9 +4812,9 @@ static struct omap_hwmod omap44xx_timer11_hwmod = {
 			.modulemode   = MODULEMODE_SWCTRL,
 		},
 	},
+	.dev_attr	= &capability_pwm_dev_attr,
 	.slaves		= omap44xx_timer11_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer11_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -4944,7 +4891,6 @@ static struct omap_hwmod omap44xx_uart1_hwmod = {
 	},
 	.slaves		= omap44xx_uart1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_uart1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* uart2 */
@@ -4999,7 +4945,6 @@ static struct omap_hwmod omap44xx_uart2_hwmod = {
 	},
 	.slaves		= omap44xx_uart2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_uart2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* uart3 */
@@ -5055,7 +5000,6 @@ static struct omap_hwmod omap44xx_uart3_hwmod = {
 	},
 	.slaves		= omap44xx_uart3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_uart3_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* uart4 */
@@ -5110,7 +5054,6 @@ static struct omap_hwmod omap44xx_uart4_hwmod = {
 	},
 	.slaves		= omap44xx_uart4_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_uart4_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -5195,7 +5138,6 @@ static struct omap_hwmod omap44xx_usb_otg_hs_hwmod = {
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_usb_otg_hs_slaves),
 	.masters	= omap44xx_usb_otg_hs_masters,
 	.masters_cnt	= ARRAY_SIZE(omap44xx_usb_otg_hs_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
@@ -5266,7 +5208,6 @@ static struct omap_hwmod omap44xx_wd_timer2_hwmod = {
 	},
 	.slaves		= omap44xx_wd_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_wd_timer2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /* wd_timer3 */
@@ -5333,7 +5274,6 @@ static struct omap_hwmod omap44xx_wd_timer3_hwmod = {
 	},
 	.slaves		= omap44xx_wd_timer3_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_wd_timer3_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
diff --git a/arch/arm/mach-omap2/omap_l3_noc.c b/arch/arm/mach-omap2/omap_l3_noc.c
index 7b9f190..c8b1bef 100644
--- a/arch/arm/mach-omap2/omap_l3_noc.c
+++ b/arch/arm/mach-omap2/omap_l3_noc.c
@@ -1,25 +1,25 @@
 /*
-  * OMAP4XXX L3 Interconnect error handling driver
-  *
-  * Copyright (C) 2011 Texas Corporation
-  *	Santosh Shilimkar <santosh.shilimkar@ti.com>
-  *	Sricharan <r.sricharan@ti.com>
-  *
-  * This program is free software; you can redistribute it and/or modify
-  * it under the terms of the GNU General Public License as published by
-  * the Free Software Foundation; either version 2 of the License, or
-  * (at your option) any later version.
-  *
-  * This program is distributed in the hope that it will be useful,
-  * but WITHOUT ANY WARRANTY; without even the implied warranty of
-  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  * GNU General Public License for more details.
-  *
-  * You should have received a copy of the GNU General Public License
-  * along with this program; if not, write to the Free Software
-  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-  * USA
-  */
+ * OMAP4XXX L3 Interconnect error handling driver
+ *
+ * Copyright (C) 2011 Texas Corporation
+ *	Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *	Sricharan <r.sricharan@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
@@ -55,12 +55,12 @@
 static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
 {
 
-	struct omap4_l3		*l3 = _l3;
-	int inttype, i, j;
+	struct omap4_l3 *l3 = _l3;
+	int inttype, i, k;
 	int err_src = 0;
-	u32 std_err_main_addr, std_err_main, err_reg;
-	u32 base, slave_addr, clear;
-	char *source_name;
+	u32 std_err_main, err_reg, clear, masterid;
+	void __iomem *base, *l3_targ_base;
+	char *target_name, *master_name = "UN IDENTIFIED";
 
 	/* Get the Type of interrupt */
 	inttype = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR;
@@ -70,43 +70,50 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
 		 * Read the regerr register of the clock domain
 		 * to determine the source
 		 */
-		base = (u32)l3->l3_base[i];
-		err_reg =  readl(base + l3_flagmux[i] + (inttype << 3));
+		base = l3->l3_base[i];
+		err_reg = __raw_readl(base + l3_flagmux[i] +
+					+ L3_FLAGMUX_REGERR0 + (inttype << 3));
 
 		/* Get the corresponding error and analyse */
 		if (err_reg) {
 			/* Identify the source from control status register */
-			for (j = 0; !(err_reg & (1 << j)); j++)
-									;
+			err_src = __ffs(err_reg);
 
-			err_src = j;
 			/* Read the stderrlog_main_source from clk domain */
-			std_err_main_addr = base + *(l3_targ[i] + err_src);
-			std_err_main = readl(std_err_main_addr);
+			l3_targ_base = base + *(l3_targ[i] + err_src);
+			std_err_main =  __raw_readl(l3_targ_base +
+					L3_TARG_STDERRLOG_MAIN);
+			masterid = __raw_readl(l3_targ_base +
+					L3_TARG_STDERRLOG_MSTADDR);
 
 			switch (std_err_main & CUSTOM_ERROR) {
 			case STANDARD_ERROR:
-				source_name =
-				l3_targ_stderrlog_main_name[i][err_src];
-
-				slave_addr = std_err_main_addr +
-						L3_SLAVE_ADDRESS_OFFSET;
-				WARN(true, "L3 standard error: SOURCE:%s at address 0x%x\n",
-					source_name, readl(slave_addr));
+				target_name =
+					l3_targ_inst_name[i][err_src];
+				WARN(true, "L3 standard error: TARGET:%s at address 0x%x\n",
+					target_name,
+					__raw_readl(l3_targ_base +
+						L3_TARG_STDERRLOG_SLVOFSLSB));
 				/* clear the std error log*/
 				clear = std_err_main | CLEAR_STDERR_LOG;
-				writel(clear, std_err_main_addr);
+				writel(clear, l3_targ_base +
+					L3_TARG_STDERRLOG_MAIN);
 				break;
 
 			case CUSTOM_ERROR:
-				source_name =
-				l3_targ_stderrlog_main_name[i][err_src];
-
-				WARN(true, "CUSTOM SRESP error with SOURCE:%s\n",
-							source_name);
+				target_name =
+					l3_targ_inst_name[i][err_src];
+				for (k = 0; k < NUM_OF_L3_MASTERS; k++) {
+					if (masterid == l3_masters[k].id)
+						master_name =
+							l3_masters[k].name;
+				}
+				WARN(true, "L3 custom error: MASTER:%s TARGET:%s\n",
+					master_name, target_name);
 				/* clear the std error log*/
 				clear = std_err_main | CLEAR_STDERR_LOG;
-				writel(clear, std_err_main_addr);
+				writel(clear, l3_targ_base +
+					L3_TARG_STDERRLOG_MAIN);
 				break;
 
 			default:
@@ -120,12 +127,11 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
 	return IRQ_HANDLED;
 }
 
-static int __init omap4_l3_probe(struct platform_device *pdev)
+static int __devinit omap4_l3_probe(struct platform_device *pdev)
 {
-	static struct omap4_l3		*l3;
-	struct resource		*res;
-	int			ret;
-	int			irq;
+	static struct omap4_l3 *l3;
+	struct resource	*res;
+	int ret;
 
 	l3 = kzalloc(sizeof(*l3), GFP_KERNEL);
 	if (!l3)
@@ -177,27 +183,25 @@ static int __init omap4_l3_probe(struct platform_device *pdev)
 	/*
 	 * Setup interrupt Handlers
 	 */
-	irq = platform_get_irq(pdev, 0);
-	ret = request_irq(irq,
+	l3->debug_irq = platform_get_irq(pdev, 0);
+	ret = request_irq(l3->debug_irq,
 			l3_interrupt_handler,
 			IRQF_DISABLED, "l3-dbg-irq", l3);
 	if (ret) {
 		pr_crit("L3: request_irq failed to register for 0x%x\n",
-					 OMAP44XX_IRQ_L3_DBG);
+						OMAP44XX_IRQ_L3_DBG);
 		goto err3;
 	}
-	l3->debug_irq = irq;
 
-	irq = platform_get_irq(pdev, 1);
-	ret = request_irq(irq,
+	l3->app_irq = platform_get_irq(pdev, 1);
+	ret = request_irq(l3->app_irq,
 			l3_interrupt_handler,
 			IRQF_DISABLED, "l3-app-irq", l3);
 	if (ret) {
 		pr_crit("L3: request_irq failed to register for 0x%x\n",
-					 OMAP44XX_IRQ_L3_APP);
+						OMAP44XX_IRQ_L3_APP);
 		goto err4;
 	}
-	l3->app_irq = irq;
 
 	return 0;
 
@@ -214,9 +218,9 @@ err0:
 	return ret;
 }
 
-static int __exit omap4_l3_remove(struct platform_device *pdev)
+static int __devexit omap4_l3_remove(struct platform_device *pdev)
 {
-	struct omap4_l3         *l3 = platform_get_drvdata(pdev);
+	struct omap4_l3 *l3 = platform_get_drvdata(pdev);
 
 	free_irq(l3->app_irq, l3);
 	free_irq(l3->debug_irq, l3);
@@ -228,16 +232,29 @@ static int __exit omap4_l3_remove(struct platform_device *pdev)
 	return 0;
 }
 
+#if defined(CONFIG_OF)
+static const struct of_device_id l3_noc_match[] = {
+	{.compatible = "ti,omap4-l3-noc", },
+	{},
+}
+MODULE_DEVICE_TABLE(of, l3_noc_match);
+#else
+#define l3_noc_match NULL
+#endif
+
 static struct platform_driver omap4_l3_driver = {
-	.remove		= __exit_p(omap4_l3_remove),
+	.probe		= omap4_l3_probe,
+	.remove		= __devexit_p(omap4_l3_remove),
 	.driver		= {
-	.name		= "omap_l3_noc",
+		.name		= "omap_l3_noc",
+		.owner		= THIS_MODULE,
+		.of_match_table = l3_noc_match,
 	},
 };
 
 static int __init omap4_l3_init(void)
 {
-	return platform_driver_probe(&omap4_l3_driver, omap4_l3_probe);
+	return platform_driver_register(&omap4_l3_driver);
 }
 postcore_initcall_sync(omap4_l3_init);
 
diff --git a/arch/arm/mach-omap2/omap_l3_noc.h b/arch/arm/mach-omap2/omap_l3_noc.h
index 359b833..90b5098 100644
--- a/arch/arm/mach-omap2/omap_l3_noc.h
+++ b/arch/arm/mach-omap2/omap_l3_noc.h
@@ -1,132 +1,162 @@
- /*
-  * OMAP4XXX L3 Interconnect  error handling driver header
-  *
-  * Copyright (C) 2011 Texas Corporation
-  *	Santosh Shilimkar <santosh.shilimkar@ti.com>
-  *	sricharan <r.sricharan@ti.com>
-  *
-  * This program is free software; you can redistribute it and/or modify
-  * it under the terms of the GNU General Public License as published by
-  * the Free Software Foundation; either version 2 of the License, or
-  * (at your option) any later version.
-  *
-  * This program is distributed in the hope that it will be useful,
-  * but WITHOUT ANY WARRANTY; without even the implied warranty of
-  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  * GNU General Public License for more details.
-  *
-  * You should have received a copy of the GNU General Public License
-  * along with this program; if not, write to the Free Software
-  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-  * USA
-  */
+/*
+ * OMAP4XXX L3 Interconnect  error handling driver header
+ *
+ * Copyright (C) 2011 Texas Corporation
+ *	Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *	sricharan <r.sricharan@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
 #ifndef __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
 #define __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
 
-/*
- * L3 register offsets
- */
 #define L3_MODULES			3
 #define CLEAR_STDERR_LOG		(1 << 31)
 #define CUSTOM_ERROR			0x2
 #define STANDARD_ERROR			0x0
 #define INBAND_ERROR			0x0
-#define EMIF_KERRLOG_OFFSET		0x10
-#define L3_SLAVE_ADDRESS_OFFSET		0x14
-#define LOGICAL_ADDR_ERRORLOG		0x4
 #define L3_APPLICATION_ERROR		0x0
 #define L3_DEBUG_ERROR			0x1
 
-u32 l3_flagmux[L3_MODULES] = {
-	0x50C,
-	0x100C,
-	0X020C
+/* L3 TARG register offsets */
+#define L3_TARG_STDERRLOG_MAIN		0x48
+#define L3_TARG_STDERRLOG_SLVOFSLSB	0x5c
+#define L3_TARG_STDERRLOG_MSTADDR	0x68
+#define L3_FLAGMUX_REGERR0		0xc
+
+#define NUM_OF_L3_MASTERS	(sizeof(l3_masters)/sizeof(l3_masters[0]))
+
+static u32 l3_flagmux[L3_MODULES] = {
+	0x500,
+	0x1000,
+	0X0200
 };
 
-/*
- * L3 Target standard Error register offsets
- */
-u32 l3_targ_stderrlog_main_clk1[] = {
-	0x148, /* DMM1 */
-	0x248, /* DMM2 */
-	0x348, /* ABE */
-	0x448, /* L4CFG */
-	0x648  /* CLK2 PWR DISC */
+/* L3 Target standard Error register offsets */
+static u32 l3_targ_inst_clk1[] = {
+	0x100, /* DMM1 */
+	0x200, /* DMM2 */
+	0x300, /* ABE */
+	0x400, /* L4CFG */
+	0x600  /* CLK2 PWR DISC */
 };
 
-u32 l3_targ_stderrlog_main_clk2[] = {
-	0x548,		/* CORTEX M3 */
-	0x348,		/* DSS */
-	0x148,		/* GPMC */
-	0x448,		/* ISS */
-	0x748,		/* IVAHD */
-	0xD48,		/* missing in TRM  corresponds to AES1*/
-	0x948,		/* L4 PER0*/
-	0x248,		/* OCMRAM */
-	0x148,		/* missing in TRM corresponds to GPMC sERROR*/
-	0x648,		/* SGX */
-	0x848,		/* SL2 */
-	0x1648,		/* C2C */
-	0x1148,		/* missing in TRM corresponds PWR DISC CLK1*/
-	0xF48,		/* missing in TRM corrsponds to SHA1*/
-	0xE48,		/* missing in TRM corresponds to AES2*/
-	0xC48,		/* L4 PER3 */
-	0xA48,		/* L4 PER1*/
-	0xB48		/* L4 PER2*/
+static u32 l3_targ_inst_clk2[] = {
+	0x500, /* CORTEX M3 */
+	0x300, /* DSS */
+	0x100, /* GPMC */
+	0x400, /* ISS */
+	0x700, /* IVAHD */
+	0xD00, /* missing in TRM  corresponds to AES1*/
+	0x900, /* L4 PER0*/
+	0x200, /* OCMRAM */
+	0x100, /* missing in TRM corresponds to GPMC sERROR*/
+	0x600, /* SGX */
+	0x800, /* SL2 */
+	0x1600, /* C2C */
+	0x1100,	/* missing in TRM corresponds PWR DISC CLK1*/
+	0xF00, /* missing in TRM corrsponds to SHA1*/
+	0xE00, /* missing in TRM corresponds to AES2*/
+	0xC00, /* L4 PER3 */
+	0xA00, /* L4 PER1*/
+	0xB00 /* L4 PER2*/
 };
 
-u32 l3_targ_stderrlog_main_clk3[] = {
-	0x0148	/* EMUSS */
+static u32 l3_targ_inst_clk3[] = {
+	0x0100	/* EMUSS */
 };
 
-char *l3_targ_stderrlog_main_name[L3_MODULES][18] = {
+static struct l3_masters_data {
+	u32 id;
+	char name[10];
+} l3_masters[] = {
+	{ 0x0 , "MPU"},
+	{ 0x10, "CS_ADP"},
+	{ 0x14, "xxx"},
+	{ 0x20, "DSP"},
+	{ 0x30, "IVAHD"},
+	{ 0x40, "ISS"},
+	{ 0x44, "DucatiM3"},
+	{ 0x48, "FaceDetect"},
+	{ 0x50, "SDMA_Rd"},
+	{ 0x54, "SDMA_Wr"},
+	{ 0x58, "xxx"},
+	{ 0x5C, "xxx"},
+	{ 0x60, "SGX"},
+	{ 0x70, "DSS"},
+	{ 0x80, "C2C"},
+	{ 0x88, "xxx"},
+	{ 0x8C, "xxx"},
+	{ 0x90, "HSI"},
+	{ 0xA0, "MMC1"},
+	{ 0xA4, "MMC2"},
+	{ 0xA8, "MMC6"},
+	{ 0xB0, "UNIPRO1"},
+	{ 0xC0, "USBHOSTHS"},
+	{ 0xC4, "USBOTGHS"},
+	{ 0xC8, "USBHOSTFS"}
+};
+
+static char *l3_targ_inst_name[L3_MODULES][18] = {
 	{
-	"DMM1",
-	"DMM2",
-	"ABE",
-	"L4CFG",
-	"CLK2 PWR DISC",
+		"DMM1",
+		"DMM2",
+		"ABE",
+		"L4CFG",
+		"CLK2 PWR DISC",
 	},
 	{
-	"CORTEX M3" ,
-	"DSS ",
-	"GPMC ",
-	"ISS ",
-	"IVAHD ",
-	"AES1",
-	"L4 PER0",
-	"OCMRAM ",
-	"GPMC sERROR",
-	"SGX ",
-	"SL2 ",
-	"C2C ",
-	"PWR DISC CLK1",
-	"SHA1",
-	"AES2",
-	"L4 PER3",
-	"L4 PER1",
-	"L4 PER2",
+		"CORTEX M3" ,
+		"DSS ",
+		"GPMC ",
+		"ISS ",
+		"IVAHD ",
+		"AES1",
+		"L4 PER0",
+		"OCMRAM ",
+		"GPMC sERROR",
+		"SGX ",
+		"SL2 ",
+		"C2C ",
+		"PWR DISC CLK1",
+		"SHA1",
+		"AES2",
+		"L4 PER3",
+		"L4 PER1",
+		"L4 PER2",
 	},
 	{
-	"EMUSS",
+		"EMUSS",
 	},
 };
 
-u32 *l3_targ[L3_MODULES] = {
-	l3_targ_stderrlog_main_clk1,
-	l3_targ_stderrlog_main_clk2,
-	l3_targ_stderrlog_main_clk3,
+static u32 *l3_targ[L3_MODULES] = {
+	l3_targ_inst_clk1,
+	l3_targ_inst_clk2,
+	l3_targ_inst_clk3,
 };
 
 struct omap4_l3 {
-	struct device	*dev;
-	struct clk	*ick;
+	struct device *dev;
+	struct clk *ick;
 
 	/* memory base */
-	void __iomem *l3_base[4];
+	void __iomem *l3_base[L3_MODULES];
 
-	int		debug_irq;
-	int		app_irq;
+	int debug_irq;
+	int app_irq;
 };
-
 #endif
diff --git a/arch/arm/mach-omap2/omap_l3_smx.c b/arch/arm/mach-omap2/omap_l3_smx.c
index 873c0e3..a05a62f 100644
--- a/arch/arm/mach-omap2/omap_l3_smx.c
+++ b/arch/arm/mach-omap2/omap_l3_smx.c
@@ -1,26 +1,26 @@
- /*
-  * OMAP3XXX L3 Interconnect Driver
-  *
-  * Copyright (C) 2011 Texas Corporation
-  *	Felipe Balbi <balbi@ti.com>
-  *	Santosh Shilimkar <santosh.shilimkar@ti.com>
-  *	Sricharan <r.sricharan@ti.com>
-  *
-  * This program is free software; you can redistribute it and/or modify
-  * it under the terms of the GNU General Public License as published by
-  * the Free Software Foundation; either version 2 of the License, or
-  * (at your option) any later version.
-  *
-  * This program is distributed in the hope that it will be useful,
-  * but WITHOUT ANY WARRANTY; without even the implied warranty of
-  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  * GNU General Public License for more details.
-  *
-  * You should have received a copy of the GNU General Public License
-  * along with this program; if not, write to the Free Software
-  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-  * USA
-  */
+/*
+ * OMAP3XXX L3 Interconnect Driver
+ *
+ * Copyright (C) 2011 Texas Corporation
+ *	Felipe Balbi <balbi@ti.com>
+ *	Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *	Sricharan <r.sricharan@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
@@ -135,7 +135,7 @@ static char *omap3_l3_initiator_string(u8 initid)
 	}
 }
 
-/**
+/*
  * omap3_l3_block_irq - handles a register block's irq
  * @l3: struct omap3_l3 *
  * @base: register block base address
@@ -150,30 +150,29 @@ static char *omap3_l3_initiator_string(u8 initid)
 static irqreturn_t omap3_l3_block_irq(struct omap3_l3 *l3,
 					u64 error, int error_addr)
 {
-	u8                      code = omap3_l3_decode_error_code(error);
-	u8                      initid = omap3_l3_decode_initid(error);
-	u8                      multi = error & L3_ERROR_LOG_MULTI;
-	u32			address = omap3_l3_decode_addr(error_addr);
+	u8 code = omap3_l3_decode_error_code(error);
+	u8 initid = omap3_l3_decode_initid(error);
+	u8 multi = error & L3_ERROR_LOG_MULTI;
+	u32 address = omap3_l3_decode_addr(error_addr);
 
 	WARN(true, "%s seen by %s %s at address %x\n",
-				 omap3_l3_code_string(code),
-			  omap3_l3_initiator_string(initid),
-			     multi ? "Multiple Errors" : "",
-						   address);
+			omap3_l3_code_string(code),
+			omap3_l3_initiator_string(initid),
+			multi ? "Multiple Errors" : "", address);
 
 	return IRQ_HANDLED;
 }
 
 static irqreturn_t omap3_l3_app_irq(int irq, void *_l3)
 {
-	struct omap3_l3         *l3 = _l3;
-	u64                     status, clear;
-	u64                     error;
-	u64			error_addr;
-	u64			err_source = 0;
-	void			__iomem *base;
-	int			int_type;
-	irqreturn_t             ret = IRQ_NONE;
+	struct omap3_l3 *l3 = _l3;
+	u64 status, clear;
+	u64 error;
+	u64 error_addr;
+	u64 err_source = 0;
+	void __iomem *base;
+	int int_type;
+	irqreturn_t ret = IRQ_NONE;
 
 	int_type = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR;
 	if (!int_type) {
@@ -191,14 +190,12 @@ static irqreturn_t omap3_l3_app_irq(int irq, void *_l3)
 	}
 
 	/* identify the error source */
-	for (err_source = 0; !(status & (1 << err_source)); err_source++)
-									;
+	err_source = __ffs(status);
 
-	base = l3->rt + *(omap3_l3_bases[int_type] + err_source);
+	base = l3->rt + omap3_l3_bases[int_type][err_source];
 	error = omap3_l3_readll(base, L3_ERROR_LOG);
 	if (error) {
 		error_addr = omap3_l3_readll(base, L3_ERROR_LOG_ADDR);
-
 		ret |= omap3_l3_block_irq(l3, error, error_addr);
 	}
 
@@ -215,9 +212,9 @@ static irqreturn_t omap3_l3_app_irq(int irq, void *_l3)
 
 static int __init omap3_l3_probe(struct platform_device *pdev)
 {
-	struct omap3_l3         *l3;
-	struct resource         *res;
-	int                     ret;
+	struct omap3_l3 *l3;
+	struct resource *res;
+	int ret;
 
 	l3 = kzalloc(sizeof(*l3), GFP_KERNEL);
 	if (!l3)
diff --git a/arch/arm/mach-omap2/omap_l3_smx.h b/arch/arm/mach-omap2/omap_l3_smx.h
index ba2ed9a..4f3cebc 100644
--- a/arch/arm/mach-omap2/omap_l3_smx.h
+++ b/arch/arm/mach-omap2/omap_l3_smx.h
@@ -1,26 +1,26 @@
- /*
-  * OMAP3XXX L3 Interconnect Driver header
-  *
-  * Copyright (C) 2011 Texas Corporation
-  *	Felipe Balbi <balbi@ti.com>
-  *	Santosh Shilimkar <santosh.shilimkar@ti.com>
-  *	sricharan <r.sricharan@ti.com>
-  *
-  * This program is free software; you can redistribute it and/or modify
-  * it under the terms of the GNU General Public License as published by
-  * the Free Software Foundation; either version 2 of the License, or
-  * (at your option) any later version.
-  *
-  * This program is distributed in the hope that it will be useful,
-  * but WITHOUT ANY WARRANTY; without even the implied warranty of
-  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  * GNU General Public License for more details.
-  *
-  * You should have received a copy of the GNU General Public License
-  * along with this program; if not, write to the Free Software
-  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-  * USA
-  */
+/*
+ * OMAP3XXX L3 Interconnect Driver header
+ *
+ * Copyright (C) 2011 Texas Corporation
+ *	Felipe Balbi <balbi@ti.com>
+ *	Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *	sricharan <r.sricharan@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
 #ifndef __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
 #define __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
 
@@ -40,7 +40,7 @@
 #define L3_SI_CONTROL			0x020
 #define L3_SI_FLAG_STATUS_0		0x510
 
-const u64 shift = 1;
+static const u64 shift = 1;
 
 #define L3_STATUS_0_MPUIA_BRST		(shift << 0)
 #define L3_STATUS_0_MPUIA_RSP		(shift << 1)
@@ -78,32 +78,32 @@ const u64 shift = 1;
 #define L3_STATUS_0_L4EMUTA_REQ		(shift << 60)
 #define L3_STATUS_0_MAD2DTA_REQ		(shift << 61)
 
-#define L3_STATUS_0_TIMEOUT_MASK	(L3_STATUS_0_MPUIA_BRST         \
-					| L3_STATUS_0_MPUIA_RSP         \
-					| L3_STATUS_0_IVAIA_BRST        \
-					| L3_STATUS_0_IVAIA_RSP         \
-					| L3_STATUS_0_SGXIA_BRST        \
-					| L3_STATUS_0_SGXIA_RSP         \
-					| L3_STATUS_0_CAMIA_BRST        \
-					| L3_STATUS_0_CAMIA_RSP         \
-					| L3_STATUS_0_DISPIA_BRST       \
-					| L3_STATUS_0_DISPIA_RSP        \
-					| L3_STATUS_0_DMARDIA_BRST      \
-					| L3_STATUS_0_DMARDIA_RSP       \
-					| L3_STATUS_0_DMAWRIA_BRST      \
-					| L3_STATUS_0_DMAWRIA_RSP       \
-					| L3_STATUS_0_USBOTGIA_BRST     \
-					| L3_STATUS_0_USBOTGIA_RSP      \
-					| L3_STATUS_0_USBHOSTIA_BRST    \
-					| L3_STATUS_0_SMSTA_REQ         \
-					| L3_STATUS_0_GPMCTA_REQ        \
-					| L3_STATUS_0_OCMRAMTA_REQ      \
-					| L3_STATUS_0_OCMROMTA_REQ      \
-					| L3_STATUS_0_IVATA_REQ         \
-					| L3_STATUS_0_SGXTA_REQ         \
-					| L3_STATUS_0_L4CORETA_REQ      \
-					| L3_STATUS_0_L4PERTA_REQ       \
-					| L3_STATUS_0_L4EMUTA_REQ       \
+#define L3_STATUS_0_TIMEOUT_MASK	(L3_STATUS_0_MPUIA_BRST		\
+					| L3_STATUS_0_MPUIA_RSP		\
+					| L3_STATUS_0_IVAIA_BRST	\
+					| L3_STATUS_0_IVAIA_RSP		\
+					| L3_STATUS_0_SGXIA_BRST	\
+					| L3_STATUS_0_SGXIA_RSP		\
+					| L3_STATUS_0_CAMIA_BRST	\
+					| L3_STATUS_0_CAMIA_RSP		\
+					| L3_STATUS_0_DISPIA_BRST	\
+					| L3_STATUS_0_DISPIA_RSP	\
+					| L3_STATUS_0_DMARDIA_BRST	\
+					| L3_STATUS_0_DMARDIA_RSP	\
+					| L3_STATUS_0_DMAWRIA_BRST	\
+					| L3_STATUS_0_DMAWRIA_RSP	\
+					| L3_STATUS_0_USBOTGIA_BRST	\
+					| L3_STATUS_0_USBOTGIA_RSP	\
+					| L3_STATUS_0_USBHOSTIA_BRST	\
+					| L3_STATUS_0_SMSTA_REQ		\
+					| L3_STATUS_0_GPMCTA_REQ	\
+					| L3_STATUS_0_OCMRAMTA_REQ	\
+					| L3_STATUS_0_OCMROMTA_REQ	\
+					| L3_STATUS_0_IVATA_REQ		\
+					| L3_STATUS_0_SGXTA_REQ		\
+					| L3_STATUS_0_L4CORETA_REQ	\
+					| L3_STATUS_0_L4PERTA_REQ	\
+					| L3_STATUS_0_L4EMUTA_REQ	\
 					| L3_STATUS_0_MAD2DTA_REQ)
 
 #define L3_SI_FLAG_STATUS_1		0x530
@@ -137,19 +137,19 @@ const u64 shift = 1;
 
 enum omap3_l3_initiator_id {
 	/* LCD has 1 ID */
-	OMAP_L3_LCD	        = 29,
+	OMAP_L3_LCD = 29,
 	/* SAD2D has 1 ID */
-	OMAP_L3_SAD2D		= 28,
+	OMAP_L3_SAD2D = 28,
 	/* MPU has 5 IDs */
-	OMAP_L3_IA_MPU_SS_1     = 27,
-	OMAP_L3_IA_MPU_SS_2     = 26,
-	OMAP_L3_IA_MPU_SS_3     = 25,
-	OMAP_L3_IA_MPU_SS_4     = 24,
-	OMAP_L3_IA_MPU_SS_5     = 23,
+	OMAP_L3_IA_MPU_SS_1 = 27,
+	OMAP_L3_IA_MPU_SS_2 = 26,
+	OMAP_L3_IA_MPU_SS_3 = 25,
+	OMAP_L3_IA_MPU_SS_4 = 24,
+	OMAP_L3_IA_MPU_SS_5 = 23,
 	/* IVA2.2 SS has 3 IDs*/
-	OMAP_L3_IA_IVA_SS_1     = 22,
-	OMAP_L3_IA_IVA_SS_2     = 21,
-	OMAP_L3_IA_IVA_SS_3     = 20,
+	OMAP_L3_IA_IVA_SS_1 = 22,
+	OMAP_L3_IA_IVA_SS_2 = 21,
+	OMAP_L3_IA_IVA_SS_3 = 20,
 	/* IVA 2.2 SS DMA has 6 IDS */
 	OMAP_L3_IA_IVA_SS_DMA_1 = 19,
 	OMAP_L3_IA_IVA_SS_DMA_2 = 18,
@@ -158,25 +158,25 @@ enum omap3_l3_initiator_id {
 	OMAP_L3_IA_IVA_SS_DMA_5 = 15,
 	OMAP_L3_IA_IVA_SS_DMA_6 = 14,
 	/* SGX has 1 ID */
-	OMAP_L3_IA_SGX		= 13,
+	OMAP_L3_IA_SGX = 13,
 	/* CAM has 3 ID */
-	OMAP_L3_IA_CAM_1	= 12,
-	OMAP_L3_IA_CAM_2	= 11,
-	OMAP_L3_IA_CAM_3	= 10,
+	OMAP_L3_IA_CAM_1 = 12,
+	OMAP_L3_IA_CAM_2 = 11,
+	OMAP_L3_IA_CAM_3 = 10,
 	/* DAP has 1 ID */
-	OMAP_L3_IA_DAP		= 9,
+	OMAP_L3_IA_DAP = 9,
 	/* SDMA WR has 2 IDs */
-	OMAP_L3_SDMA_WR_1	= 8,
-	OMAP_L3_SDMA_WR_2	= 7,
+	OMAP_L3_SDMA_WR_1 = 8,
+	OMAP_L3_SDMA_WR_2 = 7,
 	/* SDMA RD has 4 IDs */
-	OMAP_L3_SDMA_RD_1	= 6,
-	OMAP_L3_SDMA_RD_2	= 5,
-	OMAP_L3_SDMA_RD_3	= 4,
-	OMAP_L3_SDMA_RD_4	= 3,
+	OMAP_L3_SDMA_RD_1 = 6,
+	OMAP_L3_SDMA_RD_2 = 5,
+	OMAP_L3_SDMA_RD_3 = 4,
+	OMAP_L3_SDMA_RD_4 = 3,
 	/* HSUSB OTG has 1 ID */
-	OMAP_L3_USBOTG		= 2,
+	OMAP_L3_USBOTG = 2,
 	/* HSUSB HOST has 1 ID */
-	OMAP_L3_USBHOST		= 1,
+	OMAP_L3_USBHOST = 1,
 };
 
 enum omap3_l3_code {
@@ -192,21 +192,21 @@ enum omap3_l3_code {
 };
 
 struct omap3_l3 {
-	struct device   *dev;
-	struct clk      *ick;
+	struct device *dev;
+	struct clk *ick;
 
 	/* memory base*/
-	void __iomem    *rt;
+	void __iomem *rt;
 
-	int             debug_irq;
-	int             app_irq;
+	int debug_irq;
+	int app_irq;
 
 	/* true when and inband functional error occurs */
-	unsigned        inband:1;
+	unsigned inband:1;
 };
 
 /* offsets for l3 agents in order with the Flag status register */
-unsigned int __iomem omap3_l3_app_bases[] = {
+static unsigned int omap3_l3_app_bases[] = {
 	/* MPU IA */
 	0x1400,
 	0x1400,
@@ -305,7 +305,7 @@ unsigned int __iomem omap3_l3_app_bases[] = {
 	0,
 };
 
-unsigned int __iomem omap3_l3_debug_bases[] = {
+static unsigned int omap3_l3_debug_bases[] = {
 	/* MPU DATA IA */
 	0x1400,
 	/* RESERVED */
@@ -321,7 +321,7 @@ unsigned int __iomem omap3_l3_debug_bases[] = {
 	/* REST RESERVED */
 };
 
-u32 *omap3_l3_bases[] = {
+static u32 *omap3_l3_bases[] = {
 	omap3_l3_app_bases,
 	omap3_l3_debug_bases,
 };
diff --git a/arch/arm/mach-omap2/omap_twl.c b/arch/arm/mach-omap2/omap_twl.c
index 07d6140..f515a1a 100644
--- a/arch/arm/mach-omap2/omap_twl.c
+++ b/arch/arm/mach-omap2/omap_twl.c
@@ -42,8 +42,11 @@
 
 #define OMAP4_SRI2C_SLAVE_ADDR		0x12
 #define OMAP4_VDD_MPU_SR_VOLT_REG	0x55
+#define OMAP4_VDD_MPU_SR_CMD_REG	0x56
 #define OMAP4_VDD_IVA_SR_VOLT_REG	0x5B
+#define OMAP4_VDD_IVA_SR_CMD_REG	0x5C
 #define OMAP4_VDD_CORE_SR_VOLT_REG	0x61
+#define OMAP4_VDD_CORE_SR_CMD_REG	0x62
 
 #define OMAP4_VP_CONFIG_ERROROFFSET	0x00
 #define OMAP4_VP_VSTEPMIN_VSTEPMIN	0x01
@@ -95,6 +98,8 @@ static unsigned long twl6030_vsel_to_uv(const u8 vsel)
 		is_offset_valid = true;
 	}
 
+	if (!vsel)
+		return 0;
 	/*
 	 * There is no specific formula for voltage to vsel
 	 * conversion above 1.3V. There are special hardcoded
@@ -106,9 +111,9 @@ static unsigned long twl6030_vsel_to_uv(const u8 vsel)
 		return 1350000;
 
 	if (smps_offset & 0x8)
-		return ((((vsel - 1) * 125) + 7000)) * 100;
+		return ((((vsel - 1) * 1266) + 70900)) * 10;
 	else
-		return ((((vsel - 1) * 125) + 6000)) * 100;
+		return ((((vsel - 1) * 1266) + 60770)) * 10;
 }
 
 static u8 twl6030_uv_to_vsel(unsigned long uv)
@@ -127,6 +132,8 @@ static u8 twl6030_uv_to_vsel(unsigned long uv)
 		is_offset_valid = true;
 	}
 
+	if (!uv)
+		return 0x00;
 	/*
 	 * There is no specific formula for voltage to vsel
 	 * conversion above 1.3V. There are special hardcoded
@@ -134,16 +141,21 @@ static u8 twl6030_uv_to_vsel(unsigned long uv)
 	 * hardcoding only for 1.35 V which is used for 1GH OPP for
 	 * OMAP4430.
 	 */
-	if (uv == 1350000)
+	if (uv > twl6030_vsel_to_uv(0x39)) {
+		if (uv == 1350000)
+			return 0x3A;
+		pr_err("%s:OUT OF RANGE! non mapped vsel for %ld Vs max %ld\n",
+			__func__, uv, twl6030_vsel_to_uv(0x39));
 		return 0x3A;
+	}
 
 	if (smps_offset & 0x8)
-		return DIV_ROUND_UP(uv - 700000, 12500) + 1;
+		return DIV_ROUND_UP(uv - 709000, 12660) + 1;
 	else
-		return DIV_ROUND_UP(uv - 600000, 12500) + 1;
+		return DIV_ROUND_UP(uv - 607700, 12660) + 1;
 }
 
-static struct omap_volt_pmic_info omap3_mpu_volt_info = {
+static struct omap_voltdm_pmic omap3_mpu_pmic = {
 	.slew_rate		= 4000,
 	.step_size		= 12500,
 	.on_volt		= 1200000,
@@ -158,12 +170,13 @@ static struct omap_volt_pmic_info omap3_mpu_volt_info = {
 	.vp_vddmax		= OMAP3430_VP1_VLIMITTO_VDDMAX,
 	.vp_timeout_us		= OMAP3_VP_VLIMITTO_TIMEOUT_US,
 	.i2c_slave_addr		= OMAP3_SRI2C_SLAVE_ADDR,
-	.pmic_reg		= OMAP3_VDD_MPU_SR_CONTROL_REG,
+	.volt_reg_addr		= OMAP3_VDD_MPU_SR_CONTROL_REG,
+	.i2c_high_speed		= true,
 	.vsel_to_uv		= twl4030_vsel_to_uv,
 	.uv_to_vsel		= twl4030_uv_to_vsel,
 };
 
-static struct omap_volt_pmic_info omap3_core_volt_info = {
+static struct omap_voltdm_pmic omap3_core_pmic = {
 	.slew_rate		= 4000,
 	.step_size		= 12500,
 	.on_volt                = 1200000,
@@ -178,18 +191,19 @@ static struct omap_volt_pmic_info omap3_core_volt_info = {
 	.vp_vddmax		= OMAP3430_VP2_VLIMITTO_VDDMAX,
 	.vp_timeout_us		= OMAP3_VP_VLIMITTO_TIMEOUT_US,
 	.i2c_slave_addr		= OMAP3_SRI2C_SLAVE_ADDR,
-	.pmic_reg		= OMAP3_VDD_CORE_SR_CONTROL_REG,
+	.volt_reg_addr		= OMAP3_VDD_CORE_SR_CONTROL_REG,
+	.i2c_high_speed		= true,
 	.vsel_to_uv		= twl4030_vsel_to_uv,
 	.uv_to_vsel		= twl4030_uv_to_vsel,
 };
 
-static struct omap_volt_pmic_info omap4_mpu_volt_info = {
+static struct omap_voltdm_pmic omap4_mpu_pmic = {
 	.slew_rate		= 4000,
-	.step_size		= 12500,
-	.on_volt		= 1350000,
-	.onlp_volt		= 1350000,
-	.ret_volt		= 837500,
-	.off_volt		= 600000,
+	.step_size		= 12660,
+	.on_volt		= 1375000,
+	.onlp_volt		= 1375000,
+	.ret_volt		= 830000,
+	.off_volt		= 0,
 	.volt_setup_time	= 0,
 	.vp_erroroffset		= OMAP4_VP_CONFIG_ERROROFFSET,
 	.vp_vstepmin		= OMAP4_VP_VSTEPMIN_VSTEPMIN,
@@ -198,18 +212,20 @@ static struct omap_volt_pmic_info omap4_mpu_volt_info = {
 	.vp_vddmax		= OMAP4_VP_MPU_VLIMITTO_VDDMAX,
 	.vp_timeout_us		= OMAP4_VP_VLIMITTO_TIMEOUT_US,
 	.i2c_slave_addr		= OMAP4_SRI2C_SLAVE_ADDR,
-	.pmic_reg		= OMAP4_VDD_MPU_SR_VOLT_REG,
+	.volt_reg_addr		= OMAP4_VDD_MPU_SR_VOLT_REG,
+	.cmd_reg_addr		= OMAP4_VDD_MPU_SR_CMD_REG,
+	.i2c_high_speed		= true,
 	.vsel_to_uv		= twl6030_vsel_to_uv,
 	.uv_to_vsel		= twl6030_uv_to_vsel,
 };
 
-static struct omap_volt_pmic_info omap4_iva_volt_info = {
+static struct omap_voltdm_pmic omap4_iva_pmic = {
 	.slew_rate		= 4000,
-	.step_size		= 12500,
-	.on_volt		= 1100000,
-	.onlp_volt		= 1100000,
-	.ret_volt		= 837500,
-	.off_volt		= 600000,
+	.step_size		= 12660,
+	.on_volt		= 1188000,
+	.onlp_volt		= 1188000,
+	.ret_volt		= 830000,
+	.off_volt		= 0,
 	.volt_setup_time	= 0,
 	.vp_erroroffset		= OMAP4_VP_CONFIG_ERROROFFSET,
 	.vp_vstepmin		= OMAP4_VP_VSTEPMIN_VSTEPMIN,
@@ -218,18 +234,20 @@ static struct omap_volt_pmic_info omap4_iva_volt_info = {
 	.vp_vddmax		= OMAP4_VP_IVA_VLIMITTO_VDDMAX,
 	.vp_timeout_us		= OMAP4_VP_VLIMITTO_TIMEOUT_US,
 	.i2c_slave_addr		= OMAP4_SRI2C_SLAVE_ADDR,
-	.pmic_reg		= OMAP4_VDD_IVA_SR_VOLT_REG,
+	.volt_reg_addr		= OMAP4_VDD_IVA_SR_VOLT_REG,
+	.cmd_reg_addr		= OMAP4_VDD_IVA_SR_CMD_REG,
+	.i2c_high_speed		= true,
 	.vsel_to_uv		= twl6030_vsel_to_uv,
 	.uv_to_vsel		= twl6030_uv_to_vsel,
 };
 
-static struct omap_volt_pmic_info omap4_core_volt_info = {
+static struct omap_voltdm_pmic omap4_core_pmic = {
 	.slew_rate		= 4000,
-	.step_size		= 12500,
-	.on_volt		= 1100000,
-	.onlp_volt		= 1100000,
-	.ret_volt		= 837500,
-	.off_volt		= 600000,
+	.step_size		= 12660,
+	.on_volt		= 1200000,
+	.onlp_volt		= 1200000,
+	.ret_volt		= 830000,
+	.off_volt		= 0,
 	.volt_setup_time	= 0,
 	.vp_erroroffset		= OMAP4_VP_CONFIG_ERROROFFSET,
 	.vp_vstepmin		= OMAP4_VP_VSTEPMIN_VSTEPMIN,
@@ -238,7 +256,8 @@ static struct omap_volt_pmic_info omap4_core_volt_info = {
 	.vp_vddmax		= OMAP4_VP_CORE_VLIMITTO_VDDMAX,
 	.vp_timeout_us		= OMAP4_VP_VLIMITTO_TIMEOUT_US,
 	.i2c_slave_addr		= OMAP4_SRI2C_SLAVE_ADDR,
-	.pmic_reg		= OMAP4_VDD_CORE_SR_VOLT_REG,
+	.volt_reg_addr		= OMAP4_VDD_CORE_SR_VOLT_REG,
+	.cmd_reg_addr		= OMAP4_VDD_CORE_SR_CMD_REG,
 	.vsel_to_uv		= twl6030_vsel_to_uv,
 	.uv_to_vsel		= twl6030_uv_to_vsel,
 };
@@ -250,14 +269,14 @@ int __init omap4_twl_init(void)
 	if (!cpu_is_omap44xx())
 		return -ENODEV;
 
-	voltdm = omap_voltage_domain_lookup("mpu");
-	omap_voltage_register_pmic(voltdm, &omap4_mpu_volt_info);
+	voltdm = voltdm_lookup("mpu");
+	omap_voltage_register_pmic(voltdm, &omap4_mpu_pmic);
 
-	voltdm = omap_voltage_domain_lookup("iva");
-	omap_voltage_register_pmic(voltdm, &omap4_iva_volt_info);
+	voltdm = voltdm_lookup("iva");
+	omap_voltage_register_pmic(voltdm, &omap4_iva_pmic);
 
-	voltdm = omap_voltage_domain_lookup("core");
-	omap_voltage_register_pmic(voltdm, &omap4_core_volt_info);
+	voltdm = voltdm_lookup("core");
+	omap_voltage_register_pmic(voltdm, &omap4_core_pmic);
 
 	return 0;
 }
@@ -270,10 +289,10 @@ int __init omap3_twl_init(void)
 		return -ENODEV;
 
 	if (cpu_is_omap3630()) {
-		omap3_mpu_volt_info.vp_vddmin = OMAP3630_VP1_VLIMITTO_VDDMIN;
-		omap3_mpu_volt_info.vp_vddmax = OMAP3630_VP1_VLIMITTO_VDDMAX;
-		omap3_core_volt_info.vp_vddmin = OMAP3630_VP2_VLIMITTO_VDDMIN;
-		omap3_core_volt_info.vp_vddmax = OMAP3630_VP2_VLIMITTO_VDDMAX;
+		omap3_mpu_pmic.vp_vddmin = OMAP3630_VP1_VLIMITTO_VDDMIN;
+		omap3_mpu_pmic.vp_vddmax = OMAP3630_VP1_VLIMITTO_VDDMAX;
+		omap3_core_pmic.vp_vddmin = OMAP3630_VP2_VLIMITTO_VDDMIN;
+		omap3_core_pmic.vp_vddmax = OMAP3630_VP2_VLIMITTO_VDDMAX;
 	}
 
 	/*
@@ -288,11 +307,11 @@ int __init omap3_twl_init(void)
 	if (!twl_sr_enable_autoinit)
 		omap3_twl_set_sr_bit(true);
 
-	voltdm = omap_voltage_domain_lookup("mpu");
-	omap_voltage_register_pmic(voltdm, &omap3_mpu_volt_info);
+	voltdm = voltdm_lookup("mpu_iva");
+	omap_voltage_register_pmic(voltdm, &omap3_mpu_pmic);
 
-	voltdm = omap_voltage_domain_lookup("core");
-	omap_voltage_register_pmic(voltdm, &omap3_core_volt_info);
+	voltdm = voltdm_lookup("core");
+	omap_voltage_register_pmic(voltdm, &omap3_core_pmic);
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/opp.c b/arch/arm/mach-omap2/opp.c
index ab8b35b..9262a6b 100644
--- a/arch/arm/mach-omap2/opp.c
+++ b/arch/arm/mach-omap2/opp.c
@@ -69,7 +69,7 @@ int __init omap_init_opp_table(struct omap_opp_def *opp_def,
 				opp_def->hwmod_name, i);
 			return -EINVAL;
 		}
-		dev = &oh->od->pdev.dev;
+		dev = &oh->od->pdev->dev;
 
 		r = opp_add(dev, opp_def->freq, opp_def->u_volt);
 		if (r) {
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 472bf22..2ab7a9e 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -26,54 +26,21 @@
 
 static struct omap_device_pm_latency *pm_lats;
 
-static struct device *mpu_dev;
-static struct device *iva_dev;
-static struct device *l3_dev;
-static struct device *dsp_dev;
-
-struct device *omap2_get_mpuss_device(void)
-{
-	WARN_ON_ONCE(!mpu_dev);
-	return mpu_dev;
-}
-
-struct device *omap2_get_iva_device(void)
-{
-	WARN_ON_ONCE(!iva_dev);
-	return iva_dev;
-}
-
-struct device *omap2_get_l3_device(void)
-{
-	WARN_ON_ONCE(!l3_dev);
-	return l3_dev;
-}
-
-struct device *omap4_get_dsp_device(void)
-{
-	WARN_ON_ONCE(!dsp_dev);
-	return dsp_dev;
-}
-EXPORT_SYMBOL(omap4_get_dsp_device);
-
-/* static int _init_omap_device(struct omap_hwmod *oh, void *user) */
-static int _init_omap_device(char *name, struct device **new_dev)
+static int _init_omap_device(char *name)
 {
 	struct omap_hwmod *oh;
-	struct omap_device *od;
+	struct platform_device *pdev;
 
 	oh = omap_hwmod_lookup(name);
 	if (WARN(!oh, "%s: could not find omap_hwmod for %s\n",
 		 __func__, name))
 		return -ENODEV;
 
-	od = omap_device_build(oh->name, 0, oh, NULL, 0, pm_lats, 0, false);
-	if (WARN(IS_ERR(od), "%s: could not build omap_device for %s\n",
+	pdev = omap_device_build(oh->name, 0, oh, NULL, 0, pm_lats, 0, false);
+	if (WARN(IS_ERR(pdev), "%s: could not build omap_device for %s\n",
 		 __func__, name))
 		return -ENODEV;
 
-	*new_dev = &od->pdev.dev;
-
 	return 0;
 }
 
@@ -82,16 +49,16 @@ static int _init_omap_device(char *name, struct device **new_dev)
  */
 static void omap2_init_processor_devices(void)
 {
-	_init_omap_device("mpu", &mpu_dev);
+	_init_omap_device("mpu");
 	if (omap3_has_iva())
-		_init_omap_device("iva", &iva_dev);
+		_init_omap_device("iva");
 
 	if (cpu_is_omap44xx()) {
-		_init_omap_device("l3_main_1", &l3_dev);
-		_init_omap_device("dsp", &dsp_dev);
-		_init_omap_device("iva", &iva_dev);
+		_init_omap_device("l3_main_1");
+		_init_omap_device("dsp");
+		_init_omap_device("iva");
 	} else {
-		_init_omap_device("l3_main", &l3_dev);
+		_init_omap_device("l3_main");
 	}
 }
 
@@ -136,8 +103,8 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
 
 	ret = pwrdm_set_next_pwrst(pwrdm, state);
 	if (ret) {
-		printk(KERN_ERR "Unable to set state of powerdomain: %s\n",
-		       pwrdm->name);
+		pr_err("%s: unable to set state of powerdomain: %s\n",
+		       __func__, pwrdm->name);
 		goto err;
 	}
 
@@ -161,37 +128,44 @@ err:
 }
 
 /*
- * This API is to be called during init to put the various voltage
+ * This API is to be called during init to set the various voltage
  * domains to the voltage as per the opp table. Typically we boot up
  * at the nominal voltage. So this function finds out the rate of
  * the clock associated with the voltage domain, finds out the correct
- * opp entry and puts the voltage domain to the voltage specifies
+ * opp entry and sets the voltage domain to the voltage specified
  * in the opp entry
  */
 static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name,
-						struct device *dev)
+					 const char *oh_name)
 {
 	struct voltagedomain *voltdm;
 	struct clk *clk;
 	struct opp *opp;
 	unsigned long freq, bootup_volt;
+	struct device *dev;
+
+	if (!vdd_name || !clk_name || !oh_name) {
+		pr_err("%s: invalid parameters\n", __func__);
+		goto exit;
+	}
 
-	if (!vdd_name || !clk_name || !dev) {
-		printk(KERN_ERR "%s: Invalid parameters!\n", __func__);
+	dev = omap_device_get_by_hwmod_name(oh_name);
+	if (IS_ERR(dev)) {
+		pr_err("%s: Unable to get dev pointer for hwmod %s\n",
+			__func__, oh_name);
 		goto exit;
 	}
 
-	voltdm = omap_voltage_domain_lookup(vdd_name);
+	voltdm = voltdm_lookup(vdd_name);
 	if (IS_ERR(voltdm)) {
-		printk(KERN_ERR "%s: Unable to get vdd pointer for vdd_%s\n",
+		pr_err("%s: unable to get vdd pointer for vdd_%s\n",
 			__func__, vdd_name);
 		goto exit;
 	}
 
 	clk =  clk_get(NULL, clk_name);
 	if (IS_ERR(clk)) {
-		printk(KERN_ERR "%s: unable to get clk %s\n",
-			__func__, clk_name);
+		pr_err("%s: unable to get clk %s\n", __func__, clk_name);
 		goto exit;
 	}
 
@@ -200,24 +174,23 @@ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name,
 
 	opp = opp_find_freq_ceil(dev, &freq);
 	if (IS_ERR(opp)) {
-		printk(KERN_ERR "%s: unable to find boot up OPP for vdd_%s\n",
+		pr_err("%s: unable to find boot up OPP for vdd_%s\n",
 			__func__, vdd_name);
 		goto exit;
 	}
 
 	bootup_volt = opp_get_voltage(opp);
 	if (!bootup_volt) {
-		printk(KERN_ERR "%s: unable to find voltage corresponding"
+		pr_err("%s: unable to find voltage corresponding "
 			"to the bootup OPP for vdd_%s\n", __func__, vdd_name);
 		goto exit;
 	}
 
-	omap_voltage_scale_vdd(voltdm, bootup_volt);
+	voltdm_scale(voltdm, bootup_volt);
 	return 0;
 
 exit:
-	printk(KERN_ERR "%s: Unable to put vdd_%s to its init voltage\n\n",
-		__func__, vdd_name);
+	pr_err("%s: unable to set vdd_%s\n", __func__, vdd_name);
 	return -EINVAL;
 }
 
@@ -226,8 +199,8 @@ static void __init omap3_init_voltages(void)
 	if (!cpu_is_omap34xx())
 		return;
 
-	omap2_set_init_voltage("mpu", "dpll1_ck", mpu_dev);
-	omap2_set_init_voltage("core", "l3_ick", l3_dev);
+	omap2_set_init_voltage("mpu_iva", "dpll1_ck", "mpu");
+	omap2_set_init_voltage("core", "l3_ick", "l3_main");
 }
 
 static void __init omap4_init_voltages(void)
@@ -235,14 +208,15 @@ static void __init omap4_init_voltages(void)
 	if (!cpu_is_omap44xx())
 		return;
 
-	omap2_set_init_voltage("mpu", "dpll_mpu_ck", mpu_dev);
-	omap2_set_init_voltage("core", "l3_div_ck", l3_dev);
-	omap2_set_init_voltage("iva", "dpll_iva_m5x2_ck", iva_dev);
+	omap2_set_init_voltage("mpu", "dpll_mpu_ck", "mpu");
+	omap2_set_init_voltage("core", "l3_div_ck", "l3_main_1");
+	omap2_set_init_voltage("iva", "dpll_iva_m5x2_ck", "iva");
 }
 
 static int __init omap2_common_pm_init(void)
 {
-	omap2_init_processor_devices();
+	if (!of_have_populated_dt())
+		omap2_init_processor_devices();
 	omap_pm_if_init();
 
 	return 0;
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index bf089e7..cf0c216 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -53,8 +53,6 @@
 #include "powerdomain.h"
 #include "clockdomain.h"
 
-static int omap2_pm_debug;
-
 #ifdef CONFIG_SUSPEND
 static suspend_state_t suspend_state = PM_SUSPEND_ON;
 static inline bool is_suspending(void)
@@ -96,7 +94,6 @@ static int omap2_fclks_active(void)
 static void omap2_enter_full_retention(void)
 {
 	u32 l;
-	struct timespec ts_preidle, ts_postidle, ts_idle;
 
 	/* There is 1 reference hold for all children of the oscillator
 	 * clock, the following will remove it. If no one else uses the
@@ -124,10 +121,6 @@ static void omap2_enter_full_retention(void)
 
 	omap2_gpio_prepare_for_idle(0);
 
-	if (omap2_pm_debug) {
-		getnstimeofday(&ts_preidle);
-	}
-
 	/* One last check for pending IRQs to avoid extra latency due
 	 * to sleeping unnecessarily. */
 	if (omap_irq_pending())
@@ -155,13 +148,6 @@ static void omap2_enter_full_retention(void)
 		console_unlock();
 
 no_sleep:
-	if (omap2_pm_debug) {
-		unsigned long long tmp;
-
-		getnstimeofday(&ts_postidle);
-		ts_idle = timespec_sub(ts_postidle, ts_preidle);
-		tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
-	}
 	omap2_gpio_resume_after_idle();
 
 	clk_enable(osc_ck);
@@ -219,7 +205,6 @@ static int omap2_allow_mpu_retention(void)
 static void omap2_enter_mpu_retention(void)
 {
 	int only_idle = 0;
-	struct timespec ts_preidle, ts_postidle, ts_idle;
 
 	/* Putting MPU into the WFI state while a transfer is active
 	 * seems to cause the I2C block to timeout. Why? Good question. */
@@ -246,19 +231,7 @@ static void omap2_enter_mpu_retention(void)
 		only_idle = 1;
 	}
 
-	if (omap2_pm_debug) {
-		getnstimeofday(&ts_preidle);
-	}
-
 	omap2_sram_idle();
-
-	if (omap2_pm_debug) {
-		unsigned long long tmp;
-
-		getnstimeofday(&ts_postidle);
-		ts_idle = timespec_sub(ts_postidle, ts_preidle);
-		tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
-	}
 }
 
 static int omap2_can_sleep(void)
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 7255d9b..c8cbd00 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -55,7 +55,7 @@
 static suspend_state_t suspend_state = PM_SUSPEND_ON;
 static inline bool is_suspending(void)
 {
-	return (suspend_state != PM_SUSPEND_ON);
+	return (suspend_state != PM_SUSPEND_ON) && console_suspend_enabled;
 }
 #else
 static inline bool is_suspending(void)
diff --git a/arch/arm/mach-omap2/powerdomain-common.c b/arch/arm/mach-omap2/powerdomain-common.c
index 171fccd..f97afff 100644
--- a/arch/arm/mach-omap2/powerdomain-common.c
+++ b/arch/arm/mach-omap2/powerdomain-common.c
@@ -1,9 +1,8 @@
 /*
- *  linux/arch/arm/mach-omap2/powerdomain-common.c
- *  Contains common powerdomain framework functions
+ * Common powerdomain framework functions
  *
- *  Copyright (C) 2010 Texas Instruments, Inc.
- *  Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2010-2011 Texas Instruments, Inc.
+ * Copyright (C) 2010 Nokia Corporation
  *
  * Derived from mach-omap2/powerdomain.c written by Paul Walmsley
  *
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index ef71fdd..5164d58 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -1,7 +1,7 @@
 /*
  * OMAP powerdomain control
  *
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2008, 2011 Texas Instruments, Inc.
  * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Written by Paul Walmsley
@@ -77,13 +77,11 @@ static struct powerdomain *_pwrdm_lookup(const char *name)
 static int _pwrdm_register(struct powerdomain *pwrdm)
 {
 	int i;
+	struct voltagedomain *voltdm;
 
 	if (!pwrdm || !pwrdm->name)
 		return -EINVAL;
 
-	if (!omap_chip_is(pwrdm->omap_chip))
-		return -EINVAL;
-
 	if (cpu_is_omap44xx() &&
 	    pwrdm->prcm_partition == OMAP4430_INVALID_PRCM_PARTITION) {
 		pr_err("powerdomain: %s: missing OMAP4 PRCM partition ID\n",
@@ -94,6 +92,16 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
 	if (_pwrdm_lookup(pwrdm->name))
 		return -EEXIST;
 
+	voltdm = voltdm_lookup(pwrdm->voltdm.name);
+	if (!voltdm) {
+		pr_err("powerdomain: %s: voltagedomain %s does not exist\n",
+		       pwrdm->name, pwrdm->voltdm.name);
+		return -EINVAL;
+	}
+	pwrdm->voltdm.ptr = voltdm;
+	INIT_LIST_HEAD(&pwrdm->voltdm_node);
+	voltdm_add_pwrdm(voltdm, pwrdm);
+
 	list_add(&pwrdm->node, &pwrdm_list);
 
 	/* Initialize the powerdomain's state counter */
@@ -194,36 +202,76 @@ static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused)
 /* Public functions */
 
 /**
- * pwrdm_init - set up the powerdomain layer
- * @pwrdms: array of struct powerdomain pointers to register
- * @custom_funcs: func pointers for arch specific implementations
+ * pwrdm_register_platform_funcs - register powerdomain implementation fns
+ * @po: func pointers for arch specific implementations
  *
- * Loop through the array of powerdomains @pwrdms, registering all
- * that are available on the current CPU.  Also, program all
- * powerdomain target state as ON; this is to prevent domains from
- * hitting low power states (if bootloader has target states set to
- * something other than ON) and potentially even losing context while
- * PM is not fully initialized.  The PM late init code can then program
- * the desired target state for all the power domains.  No return
- * value.
+ * Register the list of function pointers used to implement the
+ * powerdomain functions on different OMAP SoCs.  Should be called
+ * before any other pwrdm_register*() function.  Returns -EINVAL if
+ * @po is null, -EEXIST if platform functions have already been
+ * registered, or 0 upon success.
  */
-void pwrdm_init(struct powerdomain **pwrdms, struct pwrdm_ops *custom_funcs)
+int pwrdm_register_platform_funcs(struct pwrdm_ops *po)
+{
+	if (!po)
+		return -EINVAL;
+
+	if (arch_pwrdm)
+		return -EEXIST;
+
+	arch_pwrdm = po;
+
+	return 0;
+}
+
+/**
+ * pwrdm_register_pwrdms - register SoC powerdomains
+ * @ps: pointer to an array of struct powerdomain to register
+ *
+ * Register the powerdomains available on a particular OMAP SoC.  Must
+ * be called after pwrdm_register_platform_funcs().  May be called
+ * multiple times.  Returns -EACCES if called before
+ * pwrdm_register_platform_funcs(); -EINVAL if the argument @ps is
+ * null; or 0 upon success.
+ */
+int pwrdm_register_pwrdms(struct powerdomain **ps)
 {
 	struct powerdomain **p = NULL;
-	struct powerdomain *temp_p;
 
-	if (!custom_funcs)
-		WARN(1, "powerdomain: No custom pwrdm functions registered\n");
-	else
-		arch_pwrdm = custom_funcs;
+	if (!arch_pwrdm)
+		return -EEXIST;
 
-	if (pwrdms) {
-		for (p = pwrdms; *p; p++)
-			_pwrdm_register(*p);
-	}
+	if (!ps)
+		return -EINVAL;
+
+	for (p = ps; *p; p++)
+		_pwrdm_register(*p);
+
+	return 0;
+}
+
+/**
+ * pwrdm_complete_init - set up the powerdomain layer
+ *
+ * Do whatever is necessary to initialize registered powerdomains and
+ * powerdomain code.  Currently, this programs the next power state
+ * for each powerdomain to ON.  This prevents powerdomains from
+ * unexpectedly losing context or entering high wakeup latency modes
+ * with non-power-management-enabled kernels.  Must be called after
+ * pwrdm_register_pwrdms().  Returns -EACCES if called before
+ * pwrdm_register_pwrdms(), or 0 upon success.
+ */
+int pwrdm_complete_init(void)
+{
+	struct powerdomain *temp_p;
+
+	if (list_empty(&pwrdm_list))
+		return -EACCES;
 
 	list_for_each_entry(temp_p, &pwrdm_list, node)
 		pwrdm_set_next_pwrst(temp_p, PWRDM_POWER_ON);
+
+	return 0;
 }
 
 /**
@@ -390,6 +438,18 @@ int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
 }
 
 /**
+ * pwrdm_get_voltdm - return a ptr to the voltdm that this pwrdm resides in
+ * @pwrdm: struct powerdomain *
+ *
+ * Return a pointer to the struct voltageomain that the specified powerdomain
+ * @pwrdm exists in.
+ */
+struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm)
+{
+	return pwrdm->voltdm.ptr;
+}
+
+/**
  * pwrdm_get_mem_bank_count - get number of memory banks in this powerdomain
  * @pwrdm: struct powerdomain *
  *
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index d23d979..42e6dd8 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -24,6 +24,8 @@
 
 #include <plat/cpu.h>
 
+#include "voltage.h"
+
 /* Powerdomain basic power states */
 #define PWRDM_POWER_OFF		0x0
 #define PWRDM_POWER_RET		0x1
@@ -78,7 +80,7 @@ struct powerdomain;
 /**
  * struct powerdomain - OMAP powerdomain
  * @name: Powerdomain name
- * @omap_chip: represents the OMAP chip types containing this pwrdm
+ * @voltdm: voltagedomain containing this powerdomain
  * @prcm_offs: the address offset from CM_BASE/PRM_BASE
  * @prcm_partition: (OMAP4 only) the PRCM partition ID containing @prcm_offs
  * @pwrsts: Possible powerdomain power states
@@ -89,6 +91,7 @@ struct powerdomain;
  * @pwrsts_mem_on: Possible memory bank pwrstates when pwrdm in ON
  * @pwrdm_clkdms: Clockdomains in this powerdomain
  * @node: list_head linking all powerdomains
+ * @voltdm_node: list_head linking all powerdomains in a voltagedomain
  * @state:
  * @state_counter:
  * @timer:
@@ -98,7 +101,10 @@ struct powerdomain;
  */
 struct powerdomain {
 	const char *name;
-	const struct omap_chip_id omap_chip;
+	union {
+		const char *name;
+		struct voltagedomain *ptr;
+	} voltdm;
 	const s16 prcm_offs;
 	const u8 pwrsts;
 	const u8 pwrsts_logic_ret;
@@ -109,6 +115,7 @@ struct powerdomain {
 	const u8 prcm_partition;
 	struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS];
 	struct list_head node;
+	struct list_head voltdm_node;
 	int state;
 	unsigned state_counter[PWRDM_MAX_PWRSTS];
 	unsigned ret_logic_off_counter;
@@ -162,7 +169,9 @@ struct pwrdm_ops {
 	int	(*pwrdm_wait_transition)(struct powerdomain *pwrdm);
 };
 
-void pwrdm_init(struct powerdomain **pwrdm_list, struct pwrdm_ops *custom_funcs);
+int pwrdm_register_platform_funcs(struct pwrdm_ops *custom_funcs);
+int pwrdm_register_pwrdms(struct powerdomain **pwrdm_list);
+int pwrdm_complete_init(void);
 
 struct powerdomain *pwrdm_lookup(const char *name);
 
@@ -176,6 +185,7 @@ int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
 int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
 			 int (*fn)(struct powerdomain *pwrdm,
 				   struct clockdomain *clkdm));
+struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm);
 
 int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
 
@@ -210,7 +220,8 @@ int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
 u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
 bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
 
-extern void omap2xxx_powerdomains_init(void);
+extern void omap242x_powerdomains_init(void);
+extern void omap243x_powerdomains_init(void);
 extern void omap3xxx_powerdomains_init(void);
 extern void omap44xx_powerdomains_init(void);
 
diff --git a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
index cf600e2..6a17e4c 100644
--- a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
@@ -1,7 +1,7 @@
 /*
  * OMAP2 and OMAP3 powerdomain control
  *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
  * Copyright (C) 2007-2009 Nokia Corporation
  *
  * Derived from mach-omap2/powerdomain.c written by Paul Walmsley
diff --git a/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c b/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c
index 4210c33..d3a5399 100644
--- a/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c
+++ b/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c
@@ -1,7 +1,7 @@
 /*
  * OMAP2/3 common powerdomain definitions
  *
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2008, 2011 Texas Instruments, Inc.
  * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Paul Walmsley, Jouni Högander
@@ -12,20 +12,6 @@
  */
 
 /*
- * To Do List
- * -> Move the Sleep/Wakeup dependencies from Power Domain framework to
- *    Clock Domain Framework
- */
-
-/*
- * This file contains all of the powerdomains that have some element
- * of software control for the OMAP24xx and OMAP34xx chips.
- *
- * This is not an exhaustive listing of powerdomains on the chips; only
- * powerdomains that can be controlled in software.
- */
-
-/*
  * The names for the DSP/IVA2 powerdomains are confusing.
  *
  * Most OMAP chips have an on-board DSP.
@@ -59,8 +45,6 @@
 struct powerdomain gfx_omap2_pwrdm = {
 	.name		  = "gfx_pwrdm",
 	.prcm_offs	  = GFX_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
-					   CHIP_IS_OMAP3430ES1),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 1,
@@ -70,11 +54,12 @@ struct powerdomain gfx_omap2_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.voltdm           = { .name = "core" },
 };
 
 struct powerdomain wkup_omap2_pwrdm = {
 	.name		= "wkup_pwrdm",
 	.prcm_offs	= WKUP_MOD,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
 	.pwrsts		= PWRSTS_ON,
+	.voltdm         = { .name = "wakeup" },
 };
diff --git a/arch/arm/mach-omap2/powerdomains2xxx_data.c b/arch/arm/mach-omap2/powerdomains2xxx_data.c
index cc389fb..2385c1f 100644
--- a/arch/arm/mach-omap2/powerdomains2xxx_data.c
+++ b/arch/arm/mach-omap2/powerdomains2xxx_data.c
@@ -1,7 +1,7 @@
 /*
  * OMAP2XXX powerdomain definitions
  *
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2008, 2011 Texas Instruments, Inc.
  * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Paul Walmsley, Jouni Högander
@@ -28,7 +28,6 @@
 static struct powerdomain dsp_pwrdm = {
 	.name		  = "dsp_pwrdm",
 	.prcm_offs	  = OMAP24XX_DSP_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 1,
@@ -38,12 +37,12 @@ static struct powerdomain dsp_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,
 	},
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain mpu_24xx_pwrdm = {
 	.name		  = "mpu_pwrdm",
 	.prcm_offs	  = MPU_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 1,
@@ -53,12 +52,12 @@ static struct powerdomain mpu_24xx_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,
 	},
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain core_24xx_pwrdm = {
 	.name		  = "core_pwrdm",
 	.prcm_offs	  = CORE_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.banks		  = 3,
 	.pwrsts_mem_ret	  = {
@@ -71,6 +70,7 @@ static struct powerdomain core_24xx_pwrdm = {
 		[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
 		[2] = PWRSTS_OFF_RET_ON, /* MEM3ONSTATE */
 	},
+	.voltdm           = { .name = "core" },
 };
 
 
@@ -78,14 +78,11 @@ static struct powerdomain core_24xx_pwrdm = {
  * 2430-specific powerdomains
  */
 
-#ifdef CONFIG_SOC_OMAP2430
-
 /* XXX 2430 KILLDOMAINWKUP bit?  No current users apparently */
 
 static struct powerdomain mdm_pwrdm = {
 	.name		  = "mdm_pwrdm",
 	.prcm_offs	  = OMAP2430_MDM_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 1,
@@ -95,29 +92,44 @@ static struct powerdomain mdm_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.voltdm           = { .name = "core" },
 };
 
-#endif     /* CONFIG_SOC_OMAP2430 */
-
-/* As powerdomains are added or removed above, this list must also be changed */
-static struct powerdomain *powerdomains_omap2xxx[] __initdata = {
+/*
+ *
+ */
 
+static struct powerdomain *powerdomains_omap24xx[] __initdata = {
 	&wkup_omap2_pwrdm,
 	&gfx_omap2_pwrdm,
-
-#ifdef CONFIG_ARCH_OMAP2
 	&dsp_pwrdm,
 	&mpu_24xx_pwrdm,
 	&core_24xx_pwrdm,
-#endif
+	NULL
+};
 
-#ifdef CONFIG_SOC_OMAP2430
+static struct powerdomain *powerdomains_omap2430[] __initdata = {
 	&mdm_pwrdm,
-#endif
 	NULL
 };
 
-void __init omap2xxx_powerdomains_init(void)
+void __init omap242x_powerdomains_init(void)
+{
+	if (!cpu_is_omap2420())
+		return;
+
+	pwrdm_register_platform_funcs(&omap2_pwrdm_operations);
+	pwrdm_register_pwrdms(powerdomains_omap24xx);
+	pwrdm_complete_init();
+}
+
+void __init omap243x_powerdomains_init(void)
 {
-	pwrdm_init(powerdomains_omap2xxx, &omap2_pwrdm_operations);
+	if (!cpu_is_omap2430())
+		return;
+
+	pwrdm_register_platform_funcs(&omap2_pwrdm_operations);
+	pwrdm_register_pwrdms(powerdomains_omap24xx);
+	pwrdm_register_pwrdms(powerdomains_omap2430);
+	pwrdm_complete_init();
 }
diff --git a/arch/arm/mach-omap2/powerdomains3xxx_data.c b/arch/arm/mach-omap2/powerdomains3xxx_data.c
index 469a920..8ef26da 100644
--- a/arch/arm/mach-omap2/powerdomains3xxx_data.c
+++ b/arch/arm/mach-omap2/powerdomains3xxx_data.c
@@ -1,7 +1,7 @@
 /*
  * OMAP3 powerdomain definitions
  *
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2008, 2011 Texas Instruments, Inc.
  * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Paul Walmsley, Jouni Högander
@@ -14,6 +14,8 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 
+#include <plat/cpu.h>
+
 #include "powerdomain.h"
 #include "powerdomains2xxx_3xxx_data.h"
 
@@ -27,8 +29,6 @@
  * 34XX-specific powerdomains, dependencies
  */
 
-#ifdef CONFIG_ARCH_OMAP3
-
 /*
  * Powerdomains
  */
@@ -36,7 +36,6 @@
 static struct powerdomain iva2_pwrdm = {
 	.name		  = "iva2_pwrdm",
 	.prcm_offs	  = OMAP3430_IVA2_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 4,
@@ -52,12 +51,12 @@ static struct powerdomain iva2_pwrdm = {
 		[2] = PWRSTS_OFF_ON,
 		[3] = PWRSTS_ON,
 	},
+	.voltdm           = { .name = "mpu_iva" },
 };
 
 static struct powerdomain mpu_3xxx_pwrdm = {
 	.name		  = "mpu_pwrdm",
 	.prcm_offs	  = MPU_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.flags		  = PWRDM_HAS_MPU_QUIRK,
@@ -68,6 +67,7 @@ static struct powerdomain mpu_3xxx_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_OFF_ON,
 	},
+	.voltdm           = { .name = "mpu_iva" },
 };
 
 /*
@@ -83,10 +83,6 @@ static struct powerdomain mpu_3xxx_pwrdm = {
 static struct powerdomain core_3xxx_pre_es3_1_pwrdm = {
 	.name		  = "core_pwrdm",
 	.prcm_offs	  = CORE_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
-					   CHIP_IS_OMAP3430ES2 |
-					   CHIP_IS_OMAP3430ES3_0 |
-					   CHIP_IS_OMAP3630ES1),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 2,
@@ -98,13 +94,12 @@ static struct powerdomain core_3xxx_pre_es3_1_pwrdm = {
 		[0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
 		[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
 	},
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain core_3xxx_es3_1_pwrdm = {
 	.name		  = "core_pwrdm",
 	.prcm_offs	  = CORE_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES3_1 |
-					  CHIP_GE_OMAP3630ES1_1),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	/*
@@ -121,11 +116,11 @@ static struct powerdomain core_3xxx_es3_1_pwrdm = {
 		[0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
 		[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
 	},
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain dss_pwrdm = {
 	.name		  = "dss_pwrdm",
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.prcm_offs	  = OMAP3430_DSS_MOD,
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_RET,
@@ -136,6 +131,7 @@ static struct powerdomain dss_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.voltdm           = { .name = "core" },
 };
 
 /*
@@ -146,7 +142,6 @@ static struct powerdomain dss_pwrdm = {
 static struct powerdomain sgx_pwrdm = {
 	.name		  = "sgx_pwrdm",
 	.prcm_offs	  = OMAP3430ES2_SGX_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
 	/* XXX This is accurate for 3430 SGX, but what about GFX? */
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.pwrsts_logic_ret = PWRSTS_RET,
@@ -157,11 +152,11 @@ static struct powerdomain sgx_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain cam_pwrdm = {
 	.name		  = "cam_pwrdm",
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.prcm_offs	  = OMAP3430_CAM_MOD,
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_RET,
@@ -172,12 +167,12 @@ static struct powerdomain cam_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain per_pwrdm = {
 	.name		  = "per_pwrdm",
 	.prcm_offs	  = OMAP3430_PER_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 1,
@@ -187,26 +182,26 @@ static struct powerdomain per_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain emu_pwrdm = {
 	.name		= "emu_pwrdm",
 	.prcm_offs	= OMAP3430_EMU_MOD,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain neon_pwrdm = {
 	.name		  = "neon_pwrdm",
 	.prcm_offs	  = OMAP3430_NEON_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_RET,
+	.voltdm           = { .name = "mpu_iva" },
 };
 
 static struct powerdomain usbhost_pwrdm = {
 	.name		  = "usbhost_pwrdm",
 	.prcm_offs	  = OMAP3430ES2_USBHOST_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_RET,
 	/*
@@ -223,65 +218,103 @@ static struct powerdomain usbhost_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain dpll1_pwrdm = {
 	.name		= "dpll1_pwrdm",
 	.prcm_offs	= MPU_MOD,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+	.voltdm           = { .name = "mpu_iva" },
 };
 
 static struct powerdomain dpll2_pwrdm = {
 	.name		= "dpll2_pwrdm",
 	.prcm_offs	= OMAP3430_IVA2_MOD,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+	.voltdm           = { .name = "mpu_iva" },
 };
 
 static struct powerdomain dpll3_pwrdm = {
 	.name		= "dpll3_pwrdm",
 	.prcm_offs	= PLL_MOD,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain dpll4_pwrdm = {
 	.name		= "dpll4_pwrdm",
 	.prcm_offs	= PLL_MOD,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+	.voltdm           = { .name = "core" },
 };
 
 static struct powerdomain dpll5_pwrdm = {
 	.name		= "dpll5_pwrdm",
 	.prcm_offs	= PLL_MOD,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
+	.voltdm           = { .name = "core" },
 };
 
 /* As powerdomains are added or removed above, this list must also be changed */
-static struct powerdomain *powerdomains_omap3xxx[] __initdata = {
-
+static struct powerdomain *powerdomains_omap3430_common[] __initdata = {
 	&wkup_omap2_pwrdm,
-	&gfx_omap2_pwrdm,
 	&iva2_pwrdm,
 	&mpu_3xxx_pwrdm,
 	&neon_pwrdm,
-	&core_3xxx_pre_es3_1_pwrdm,
-	&core_3xxx_es3_1_pwrdm,
 	&cam_pwrdm,
 	&dss_pwrdm,
 	&per_pwrdm,
 	&emu_pwrdm,
-	&sgx_pwrdm,
-	&usbhost_pwrdm,
 	&dpll1_pwrdm,
 	&dpll2_pwrdm,
 	&dpll3_pwrdm,
 	&dpll4_pwrdm,
+	NULL
+};
+
+static struct powerdomain *powerdomains_omap3430es1[] __initdata = {
+	&gfx_omap2_pwrdm,
+	&core_3xxx_pre_es3_1_pwrdm,
+	NULL
+};
+
+/* also includes 3630ES1.0 */
+static struct powerdomain *powerdomains_omap3430es2_es3_0[] __initdata = {
+	&core_3xxx_pre_es3_1_pwrdm,
+	&sgx_pwrdm,
+	&usbhost_pwrdm,
 	&dpll5_pwrdm,
-#endif
 	NULL
 };
 
+/* also includes 3630ES1.1+ */
+static struct powerdomain *powerdomains_omap3430es3_1plus[] __initdata = {
+	&core_3xxx_es3_1_pwrdm,
+	&sgx_pwrdm,
+	&usbhost_pwrdm,
+	&dpll5_pwrdm,
+	NULL
+};
 
 void __init omap3xxx_powerdomains_init(void)
 {
-	pwrdm_init(powerdomains_omap3xxx, &omap3_pwrdm_operations);
+	unsigned int rev;
+
+	if (!cpu_is_omap34xx())
+		return;
+
+	pwrdm_register_platform_funcs(&omap3_pwrdm_operations);
+	pwrdm_register_pwrdms(powerdomains_omap3430_common);
+
+	rev = omap_rev();
+
+	if (rev == OMAP3430_REV_ES1_0)
+		pwrdm_register_pwrdms(powerdomains_omap3430es1);
+	else if (rev == OMAP3430_REV_ES2_0 || rev == OMAP3430_REV_ES2_1 ||
+		 rev == OMAP3430_REV_ES3_0 || rev == OMAP3630_REV_ES1_0)
+		pwrdm_register_pwrdms(powerdomains_omap3430es2_es3_0);
+	else if (rev == OMAP3430_REV_ES3_1 || rev == OMAP3430_REV_ES3_1_2 ||
+		 rev == OMAP3517_REV_ES1_0 || rev == OMAP3517_REV_ES1_1 ||
+		 rev == OMAP3630_REV_ES1_1 || rev == OMAP3630_REV_ES1_2)
+		pwrdm_register_pwrdms(powerdomains_omap3430es3_1plus);
+	else
+		WARN(1, "OMAP3 powerdomain init: unknown chip type\n");
+
+	pwrdm_complete_init();
 }
diff --git a/arch/arm/mach-omap2/powerdomains44xx_data.c b/arch/arm/mach-omap2/powerdomains44xx_data.c
index 247e794..704664c 100644
--- a/arch/arm/mach-omap2/powerdomains44xx_data.c
+++ b/arch/arm/mach-omap2/powerdomains44xx_data.c
@@ -33,9 +33,9 @@
 /* core_44xx_pwrdm: CORE power domain */
 static struct powerdomain core_44xx_pwrdm = {
 	.name		  = "core_pwrdm",
+	.voltdm		  = { .name = "core" },
 	.prcm_offs	  = OMAP4430_PRM_CORE_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 5,
@@ -59,9 +59,9 @@ static struct powerdomain core_44xx_pwrdm = {
 /* gfx_44xx_pwrdm: 3D accelerator power domain */
 static struct powerdomain gfx_44xx_pwrdm = {
 	.name		  = "gfx_pwrdm",
+	.voltdm		  = { .name = "core" },
 	.prcm_offs	  = OMAP4430_PRM_GFX_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
@@ -76,9 +76,9 @@ static struct powerdomain gfx_44xx_pwrdm = {
 /* abe_44xx_pwrdm: Audio back end power domain */
 static struct powerdomain abe_44xx_pwrdm = {
 	.name		  = "abe_pwrdm",
+	.voltdm		  = { .name = "iva" },
 	.prcm_offs	  = OMAP4430_PRM_ABE_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF,
 	.banks		  = 2,
@@ -96,9 +96,9 @@ static struct powerdomain abe_44xx_pwrdm = {
 /* dss_44xx_pwrdm: Display subsystem power domain */
 static struct powerdomain dss_44xx_pwrdm = {
 	.name		  = "dss_pwrdm",
+	.voltdm		  = { .name = "core" },
 	.prcm_offs	  = OMAP4430_PRM_DSS_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF,
 	.banks		  = 1,
@@ -114,9 +114,9 @@ static struct powerdomain dss_44xx_pwrdm = {
 /* tesla_44xx_pwrdm: Tesla processor power domain */
 static struct powerdomain tesla_44xx_pwrdm = {
 	.name		  = "tesla_pwrdm",
+	.voltdm		  = { .name = "iva" },
 	.prcm_offs	  = OMAP4430_PRM_TESLA_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 3,
@@ -136,9 +136,9 @@ static struct powerdomain tesla_44xx_pwrdm = {
 /* wkup_44xx_pwrdm: Wake-up power domain */
 static struct powerdomain wkup_44xx_pwrdm = {
 	.name		  = "wkup_pwrdm",
+	.voltdm		  = { .name = "wakeup" },
 	.prcm_offs	  = OMAP4430_PRM_WKUP_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_ON,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
@@ -152,9 +152,9 @@ static struct powerdomain wkup_44xx_pwrdm = {
 /* cpu0_44xx_pwrdm: MPU0 processor and Neon coprocessor power domain */
 static struct powerdomain cpu0_44xx_pwrdm = {
 	.name		  = "cpu0_pwrdm",
+	.voltdm		  = { .name = "mpu" },
 	.prcm_offs	  = OMAP4430_PRCM_MPU_CPU0_INST,
 	.prcm_partition	  = OMAP4430_PRCM_MPU_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 1,
@@ -169,9 +169,9 @@ static struct powerdomain cpu0_44xx_pwrdm = {
 /* cpu1_44xx_pwrdm: MPU1 processor and Neon coprocessor power domain */
 static struct powerdomain cpu1_44xx_pwrdm = {
 	.name		  = "cpu1_pwrdm",
+	.voltdm		  = { .name = "mpu" },
 	.prcm_offs	  = OMAP4430_PRCM_MPU_CPU1_INST,
 	.prcm_partition	  = OMAP4430_PRCM_MPU_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 1,
@@ -186,9 +186,9 @@ static struct powerdomain cpu1_44xx_pwrdm = {
 /* emu_44xx_pwrdm: Emulation power domain */
 static struct powerdomain emu_44xx_pwrdm = {
 	.name		  = "emu_pwrdm",
+	.voltdm		  = { .name = "wakeup" },
 	.prcm_offs	  = OMAP4430_PRM_EMU_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
@@ -202,9 +202,9 @@ static struct powerdomain emu_44xx_pwrdm = {
 /* mpu_44xx_pwrdm: Modena processor and the Neon coprocessor power domain */
 static struct powerdomain mpu_44xx_pwrdm = {
 	.name		  = "mpu_pwrdm",
+	.voltdm		  = { .name = "mpu" },
 	.prcm_offs	  = OMAP4430_PRM_MPU_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 3,
@@ -223,9 +223,9 @@ static struct powerdomain mpu_44xx_pwrdm = {
 /* ivahd_44xx_pwrdm: IVA-HD power domain */
 static struct powerdomain ivahd_44xx_pwrdm = {
 	.name		  = "ivahd_pwrdm",
+	.voltdm		  = { .name = "iva" },
 	.prcm_offs	  = OMAP4430_PRM_IVAHD_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF,
 	.banks		  = 4,
@@ -247,9 +247,9 @@ static struct powerdomain ivahd_44xx_pwrdm = {
 /* cam_44xx_pwrdm: Camera subsystem power domain */
 static struct powerdomain cam_44xx_pwrdm = {
 	.name		  = "cam_pwrdm",
+	.voltdm		  = { .name = "core" },
 	.prcm_offs	  = OMAP4430_PRM_CAM_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
@@ -264,9 +264,9 @@ static struct powerdomain cam_44xx_pwrdm = {
 /* l3init_44xx_pwrdm: L3 initators pheripherals power domain  */
 static struct powerdomain l3init_44xx_pwrdm = {
 	.name		  = "l3init_pwrdm",
+	.voltdm		  = { .name = "core" },
 	.prcm_offs	  = OMAP4430_PRM_L3INIT_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 1,
@@ -282,9 +282,9 @@ static struct powerdomain l3init_44xx_pwrdm = {
 /* l4per_44xx_pwrdm: Target peripherals power domain */
 static struct powerdomain l4per_44xx_pwrdm = {
 	.name		  = "l4per_pwrdm",
+	.voltdm		  = { .name = "core" },
 	.prcm_offs	  = OMAP4430_PRM_L4PER_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 2,
@@ -305,18 +305,18 @@ static struct powerdomain l4per_44xx_pwrdm = {
  */
 static struct powerdomain always_on_core_44xx_pwrdm = {
 	.name		  = "always_on_core_pwrdm",
+	.voltdm		  = { .name = "core" },
 	.prcm_offs	  = OMAP4430_PRM_ALWAYS_ON_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_ON,
 };
 
 /* cefuse_44xx_pwrdm: Customer efuse controller power domain */
 static struct powerdomain cefuse_44xx_pwrdm = {
 	.name		  = "cefuse_pwrdm",
+	.voltdm		  = { .name = "core" },
 	.prcm_offs	  = OMAP4430_PRM_CEFUSE_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -352,5 +352,7 @@ static struct powerdomain *powerdomains_omap44xx[] __initdata = {
 
 void __init omap44xx_powerdomains_init(void)
 {
-	pwrdm_init(powerdomains_omap44xx, &omap4_pwrdm_operations);
+	pwrdm_register_platform_funcs(&omap4_pwrdm_operations);
+	pwrdm_register_pwrdms(powerdomains_omap44xx);
+	pwrdm_complete_init();
 }
diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
index 2e40a5c..8db5f03 100644
--- a/arch/arm/mach-omap2/prcm.c
+++ b/arch/arm/mach-omap2/prcm.c
@@ -151,17 +151,10 @@ int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, u8 idlest,
 
 void __init omap2_set_globals_prcm(struct omap_globals *omap2_globals)
 {
-	/* Static mapping, never released */
-	if (omap2_globals->prm) {
-		prm_base = ioremap(omap2_globals->prm, SZ_8K);
-		WARN_ON(!prm_base);
-	}
-	if (omap2_globals->cm) {
-		cm_base = ioremap(omap2_globals->cm, SZ_8K);
-		WARN_ON(!cm_base);
-	}
-	if (omap2_globals->cm2) {
-		cm2_base = ioremap(omap2_globals->cm2, SZ_8K);
-		WARN_ON(!cm2_base);
-	}
+	if (omap2_globals->prm)
+		prm_base = omap2_globals->prm;
+	if (omap2_globals->cm)
+		cm_base = omap2_globals->cm;
+	if (omap2_globals->cm2)
+		cm2_base = omap2_globals->cm2;
 }
diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.c b/arch/arm/mach-omap2/prm2xxx_3xxx.c
index 051213f..f02d87f 100644
--- a/arch/arm/mach-omap2/prm2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/prm2xxx_3xxx.c
@@ -20,6 +20,8 @@
 #include <plat/cpu.h>
 #include <plat/prcm.h>
 
+#include "vp.h"
+
 #include "prm2xxx_3xxx.h"
 #include "cm2xxx_3xxx.h"
 #include "prm-regbits-24xx.h"
@@ -156,3 +158,57 @@ int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift)
 
 	return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
 }
+
+/* PRM VP */
+
+/*
+ * struct omap3_vp - OMAP3 VP register access description.
+ * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg
+ */
+struct omap3_vp {
+	u32 tranxdone_status;
+};
+
+static struct omap3_vp omap3_vp[] = {
+	[OMAP3_VP_VDD_MPU_ID] = {
+		.tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK,
+	},
+	[OMAP3_VP_VDD_CORE_ID] = {
+		.tranxdone_status = OMAP3430_VP2_TRANXDONE_ST_MASK,
+	},
+};
+
+#define MAX_VP_ID ARRAY_SIZE(omap3_vp);
+
+u32 omap3_prm_vp_check_txdone(u8 vp_id)
+{
+	struct omap3_vp *vp = &omap3_vp[vp_id];
+	u32 irqstatus;
+
+	irqstatus = omap2_prm_read_mod_reg(OCP_MOD,
+					   OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+	return irqstatus & vp->tranxdone_status;
+}
+
+void omap3_prm_vp_clear_txdone(u8 vp_id)
+{
+	struct omap3_vp *vp = &omap3_vp[vp_id];
+
+	omap2_prm_write_mod_reg(vp->tranxdone_status,
+				OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+}
+
+u32 omap3_prm_vcvp_read(u8 offset)
+{
+	return omap2_prm_read_mod_reg(OMAP3430_GR_MOD, offset);
+}
+
+void omap3_prm_vcvp_write(u32 val, u8 offset)
+{
+	omap2_prm_write_mod_reg(val, OMAP3430_GR_MOD, offset);
+}
+
+u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset)
+{
+	return omap2_prm_rmw_mod_reg_bits(mask, bits, OMAP3430_GR_MOD, offset);
+}
diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.h b/arch/arm/mach-omap2/prm2xxx_3xxx.h
index a1fc62a..cef533d 100644
--- a/arch/arm/mach-omap2/prm2xxx_3xxx.h
+++ b/arch/arm/mach-omap2/prm2xxx_3xxx.h
@@ -303,7 +303,19 @@ extern int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift);
 extern int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift);
 extern int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift);
 
+/* OMAP3-specific VP functions */
+u32 omap3_prm_vp_check_txdone(u8 vp_id);
+void omap3_prm_vp_clear_txdone(u8 vp_id);
+
+/*
+ * OMAP3 access functions for voltage controller (VC) and
+ * voltage proccessor (VP) in the PRM.
+ */
+extern u32 omap3_prm_vcvp_read(u8 offset);
+extern void omap3_prm_vcvp_write(u32 val, u8 offset);
+extern u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset);
 #endif	/* CONFIG_ARCH_OMAP4 */
+
 #endif
 
 /*
diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c
index 0016555..495a31a 100644
--- a/arch/arm/mach-omap2/prm44xx.c
+++ b/arch/arm/mach-omap2/prm44xx.c
@@ -21,8 +21,11 @@
 #include <plat/cpu.h>
 #include <plat/prcm.h>
 
+#include "vp.h"
 #include "prm44xx.h"
 #include "prm-regbits-44xx.h"
+#include "prcm44xx.h"
+#include "prminst44xx.h"
 
 /* PRM low-level functions */
 
@@ -50,3 +53,71 @@ u32 omap4_prm_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 reg)
 
 	return v;
 }
+
+/* PRM VP */
+
+/*
+ * struct omap4_vp - OMAP4 VP register access description.
+ * @irqstatus_mpu: offset to IRQSTATUS_MPU register for VP
+ * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg
+ */
+struct omap4_vp {
+	u32 irqstatus_mpu;
+	u32 tranxdone_status;
+};
+
+static struct omap4_vp omap4_vp[] = {
+	[OMAP4_VP_VDD_MPU_ID] = {
+		.irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET,
+		.tranxdone_status = OMAP4430_VP_MPU_TRANXDONE_ST_MASK,
+	},
+	[OMAP4_VP_VDD_IVA_ID] = {
+		.irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
+		.tranxdone_status = OMAP4430_VP_IVA_TRANXDONE_ST_MASK,
+	},
+	[OMAP4_VP_VDD_CORE_ID] = {
+		.irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
+		.tranxdone_status = OMAP4430_VP_CORE_TRANXDONE_ST_MASK,
+	},
+};
+
+u32 omap4_prm_vp_check_txdone(u8 vp_id)
+{
+	struct omap4_vp *vp = &omap4_vp[vp_id];
+	u32 irqstatus;
+
+	irqstatus = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
+						OMAP4430_PRM_OCP_SOCKET_INST,
+						vp->irqstatus_mpu);
+	return irqstatus & vp->tranxdone_status;
+}
+
+void omap4_prm_vp_clear_txdone(u8 vp_id)
+{
+	struct omap4_vp *vp = &omap4_vp[vp_id];
+
+	omap4_prminst_write_inst_reg(vp->tranxdone_status,
+				     OMAP4430_PRM_PARTITION,
+				     OMAP4430_PRM_OCP_SOCKET_INST,
+				     vp->irqstatus_mpu);
+};
+
+u32 omap4_prm_vcvp_read(u8 offset)
+{
+	return omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
+					   OMAP4430_PRM_DEVICE_INST, offset);
+}
+
+void omap4_prm_vcvp_write(u32 val, u8 offset)
+{
+	omap4_prminst_write_inst_reg(val, OMAP4430_PRM_PARTITION,
+				     OMAP4430_PRM_DEVICE_INST, offset);
+}
+
+u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset)
+{
+	return omap4_prminst_rmw_inst_reg_bits(mask, bits,
+					       OMAP4430_PRM_PARTITION,
+					       OMAP4430_PRM_DEVICE_INST,
+					       offset);
+}
diff --git a/arch/arm/mach-omap2/prm44xx.h b/arch/arm/mach-omap2/prm44xx.h
index 7dfa379..3d66ccd 100644
--- a/arch/arm/mach-omap2/prm44xx.h
+++ b/arch/arm/mach-omap2/prm44xx.h
@@ -751,6 +751,18 @@ extern u32 omap4_prm_read_inst_reg(s16 inst, u16 idx);
 extern void omap4_prm_write_inst_reg(u32 val, s16 inst, u16 idx);
 extern u32 omap4_prm_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx);
 
+/* OMAP4-specific VP functions */
+u32 omap4_prm_vp_check_txdone(u8 vp_id);
+void omap4_prm_vp_clear_txdone(u8 vp_id);
+
+/*
+ * OMAP4 access functions for voltage controller (VC) and
+ * voltage proccessor (VP) in the PRM.
+ */
+extern u32 omap4_prm_vcvp_read(u8 offset);
+extern void omap4_prm_vcvp_write(u32 val, u8 offset);
+extern u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset);
+
 # endif
 
 #endif
diff --git a/arch/arm/mach-omap2/sdrc.c b/arch/arm/mach-omap2/sdrc.c
index da6f3a6..8f27828 100644
--- a/arch/arm/mach-omap2/sdrc.c
+++ b/arch/arm/mach-omap2/sdrc.c
@@ -117,15 +117,10 @@ int omap2_sdrc_get_params(unsigned long r,
 
 void __init omap2_set_globals_sdrc(struct omap_globals *omap2_globals)
 {
-	/* Static mapping, never released */
-	if (omap2_globals->sdrc) {
-		omap2_sdrc_base = ioremap(omap2_globals->sdrc, SZ_64K);
-		WARN_ON(!omap2_sdrc_base);
-	}
-	if (omap2_globals->sms) {
-		omap2_sms_base = ioremap(omap2_globals->sms, SZ_64K);
-		WARN_ON(!omap2_sms_base);
-	}
+	if (omap2_globals->sdrc)
+		omap2_sdrc_base = omap2_globals->sdrc;
+	if (omap2_globals->sms)
+		omap2_sms_base = omap2_globals->sms;
 }
 
 /**
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 466fc722..9992dbf 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -107,28 +107,6 @@ struct omap_uart_state {
 static LIST_HEAD(uart_list);
 static u8 num_uarts;
 
-static int uart_idle_hwmod(struct omap_device *od)
-{
-	omap_hwmod_idle(od->hwmods[0]);
-
-	return 0;
-}
-
-static int uart_enable_hwmod(struct omap_device *od)
-{
-	omap_hwmod_enable(od->hwmods[0]);
-
-	return 0;
-}
-
-static struct omap_device_pm_latency omap_uart_latency[] = {
-	{
-		.deactivate_func = uart_idle_hwmod,
-		.activate_func	 = uart_enable_hwmod,
-		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-};
-
 static inline unsigned int __serial_read_reg(struct uart_port *up,
 					     int offset)
 {
@@ -711,7 +689,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
 {
 	struct omap_uart_state *uart;
 	struct omap_hwmod *oh;
-	struct omap_device *od;
+	struct platform_device *pdev;
 	void *pdata = NULL;
 	u32 pdata_size = 0;
 	char *name;
@@ -799,20 +777,19 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
 	if (WARN_ON(!oh))
 		return;
 
-	od = omap_device_build(name, uart->num, oh, pdata, pdata_size,
-			       omap_uart_latency,
-			       ARRAY_SIZE(omap_uart_latency), false);
-	WARN(IS_ERR(od), "Could not build omap_device for %s: %s.\n",
+	pdev = omap_device_build(name, uart->num, oh, pdata, pdata_size,
+				 NULL, 0, false);
+	WARN(IS_ERR(pdev), "Could not build omap_device for %s: %s.\n",
 	     name, oh->name);
 
-	omap_device_disable_idle_on_suspend(od);
+	omap_device_disable_idle_on_suspend(pdev);
 	oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);
 
 	uart->irq = oh->mpu_irqs[0].irq;
 	uart->regshift = 2;
 	uart->mapbase = oh->slaves[0]->addr->pa_start;
 	uart->membase = omap_hwmod_get_mpu_rt_va(oh);
-	uart->pdev = &od->pdev;
+	uart->pdev = pdev;
 
 	oh->dev_attr = uart;
 
@@ -846,8 +823,8 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
 
 	if ((cpu_is_omap34xx() && uart->padconf) ||
 	    (uart->wk_en && uart->wk_mask)) {
-		device_init_wakeup(&od->pdev.dev, true);
-		DEV_CREATE_FILE(&od->pdev.dev, &dev_attr_sleep_timeout);
+		device_init_wakeup(&pdev->dev, true);
+		DEV_CREATE_FILE(&pdev->dev, &dev_attr_sleep_timeout);
 	}
 
 	/* Enable the MDR1 errata for OMAP3 */
diff --git a/arch/arm/mach-omap2/smartreflex-class3.c b/arch/arm/mach-omap2/smartreflex-class3.c
index f438cf4..53d9d0a 100644
--- a/arch/arm/mach-omap2/smartreflex-class3.c
+++ b/arch/arm/mach-omap2/smartreflex-class3.c
@@ -15,7 +15,7 @@
 
 static int sr_class3_enable(struct voltagedomain *voltdm)
 {
-	unsigned long volt = omap_voltage_get_nom_volt(voltdm);
+	unsigned long volt = voltdm_get_voltage(voltdm);
 
 	if (!volt) {
 		pr_warning("%s: Curr voltage unknown. Cannot enable sr_%s\n",
@@ -32,7 +32,7 @@ static int sr_class3_disable(struct voltagedomain *voltdm, int is_volt_reset)
 	omap_vp_disable(voltdm);
 	sr_disable(voltdm);
 	if (is_volt_reset)
-		omap_voltage_reset(voltdm);
+		voltdm_reset(voltdm);
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index f49804f..0347b93 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -62,6 +62,7 @@ static LIST_HEAD(sr_list);
 
 static struct omap_sr_class_data *sr_class;
 static struct omap_sr_pmic_data *sr_pmic_data;
+static struct dentry		*sr_dbg_dir;
 
 static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32 value)
 {
@@ -826,9 +827,10 @@ static int __init omap_sr_probe(struct platform_device *pdev)
 	struct omap_sr *sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
 	struct omap_sr_data *pdata = pdev->dev.platform_data;
 	struct resource *mem, *irq;
-	struct dentry *vdd_dbg_dir, *nvalue_dir;
+	struct dentry *nvalue_dir;
 	struct omap_volt_data *volt_data;
 	int i, ret = 0;
+	char *name;
 
 	if (!sr_info) {
 		dev_err(&pdev->dev, "%s: unable to allocate sr_info\n",
@@ -899,18 +901,25 @@ static int __init omap_sr_probe(struct platform_device *pdev)
 	}
 
 	dev_info(&pdev->dev, "%s: SmartReflex driver initialized\n", __func__);
+	if (!sr_dbg_dir) {
+		sr_dbg_dir = debugfs_create_dir("smartreflex", NULL);
+		if (!sr_dbg_dir) {
+			ret = PTR_ERR(sr_dbg_dir);
+			pr_err("%s:sr debugfs dir creation failed(%d)\n",
+				__func__, ret);
+			goto err_iounmap;
+		}
+	}
 
-	/*
-	 * If the voltage domain debugfs directory is not created, do
-	 * not try to create rest of the debugfs entries.
-	 */
-	vdd_dbg_dir = omap_voltage_get_dbgdir(sr_info->voltdm);
-	if (!vdd_dbg_dir) {
-		ret = -EINVAL;
+	name = kasprintf(GFP_KERNEL, "sr_%s", sr_info->voltdm->name);
+	if (!name) {
+		dev_err(&pdev->dev, "%s: Unable to alloc debugfs name\n",
+			__func__);
+		ret = -ENOMEM;
 		goto err_iounmap;
 	}
-
-	sr_info->dbg_dir = debugfs_create_dir("smartreflex", vdd_dbg_dir);
+	sr_info->dbg_dir = debugfs_create_dir(name, sr_dbg_dir);
+	kfree(name);
 	if (IS_ERR(sr_info->dbg_dir)) {
 		dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n",
 			__func__);
diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c
index 10d3c5e..9f43fcc 100644
--- a/arch/arm/mach-omap2/sr_device.c
+++ b/arch/arm/mach-omap2/sr_device.c
@@ -31,14 +31,6 @@
 
 static bool sr_enable_on_init;
 
-static struct omap_device_pm_latency omap_sr_latency[] = {
-	{
-		.deactivate_func = omap_device_idle_hwmods,
-		.activate_func	 = omap_device_enable_hwmods,
-		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST
-	},
-};
-
 /* Read EFUSE values from control registers for OMAP3430 */
 static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
 				struct omap_sr_data *sr_data)
@@ -80,7 +72,7 @@ static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
 static int sr_dev_init(struct omap_hwmod *oh, void *user)
 {
 	struct omap_sr_data *sr_data;
-	struct omap_device *od;
+	struct platform_device *pdev;
 	struct omap_volt_data *volt_data;
 	char *name = "smartreflex";
 	static int i;
@@ -102,7 +94,7 @@ static int sr_dev_init(struct omap_hwmod *oh, void *user)
 	sr_data->senn_mod = 0x1;
 	sr_data->senp_mod = 0x1;
 
-	sr_data->voltdm = omap_voltage_domain_lookup(oh->vdd_name);
+	sr_data->voltdm = voltdm_lookup(oh->vdd_name);
 	if (IS_ERR(sr_data->voltdm)) {
 		pr_err("%s: Unable to get voltage domain pointer for VDD %s\n",
 			__func__, oh->vdd_name);
@@ -120,10 +112,9 @@ static int sr_dev_init(struct omap_hwmod *oh, void *user)
 
 	sr_data->enable_on_init = sr_enable_on_init;
 
-	od = omap_device_build(name, i, oh, sr_data, sizeof(*sr_data),
-			       omap_sr_latency,
-			       ARRAY_SIZE(omap_sr_latency), 0);
-	if (IS_ERR(od))
+	pdev = omap_device_build(name, i, oh, sr_data, sizeof(*sr_data),
+				 NULL, 0, 0);
+	if (IS_ERR(pdev))
 		pr_warning("%s: Could not build omap_device for %s: %s.\n\n",
 			__func__, name, oh->name);
 exit:
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index cf1de7d..e49fc7b 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -35,6 +35,7 @@
 #include <linux/irq.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
+#include <linux/slab.h>
 
 #include <asm/mach/time.h>
 #include <plat/dmtimer.h>
@@ -42,6 +43,10 @@
 #include <asm/sched_clock.h>
 #include <plat/common.h>
 #include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
+#include <plat/omap-pm.h>
+
+#include "powerdomain.h"
 
 /* Parent clocks, eventually these will come from the clock framework */
 
@@ -67,7 +72,7 @@
 /* MAX_GPTIMER_ID: number of GPTIMERs on the chip */
 #define MAX_GPTIMER_ID		12
 
-u32 sys_timer_reserved;
+static u32 sys_timer_reserved;
 
 /* Clockevent code */
 
@@ -78,7 +83,7 @@ static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id)
 {
 	struct clock_event_device *evt = &clockevent_gpt;
 
-	__omap_dm_timer_write_status(clkev.io_base, OMAP_TIMER_INT_OVERFLOW);
+	__omap_dm_timer_write_status(&clkev, OMAP_TIMER_INT_OVERFLOW);
 
 	evt->event_handler(evt);
 	return IRQ_HANDLED;
@@ -93,7 +98,7 @@ static struct irqaction omap2_gp_timer_irq = {
 static int omap2_gp_timer_set_next_event(unsigned long cycles,
 					 struct clock_event_device *evt)
 {
-	__omap_dm_timer_load_start(clkev.io_base, OMAP_TIMER_CTRL_ST,
+	__omap_dm_timer_load_start(&clkev, OMAP_TIMER_CTRL_ST,
 						0xffffffff - cycles, 1);
 
 	return 0;
@@ -104,16 +109,16 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
 {
 	u32 period;
 
-	__omap_dm_timer_stop(clkev.io_base, 1, clkev.rate);
+	__omap_dm_timer_stop(&clkev, 1, clkev.rate);
 
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
 		period = clkev.rate / HZ;
 		period -= 1;
 		/* Looks like we need to first set the load value separately */
-		__omap_dm_timer_write(clkev.io_base, OMAP_TIMER_LOAD_REG,
+		__omap_dm_timer_write(&clkev, OMAP_TIMER_LOAD_REG,
 					0xffffffff - period, 1);
-		__omap_dm_timer_load_start(clkev.io_base,
+		__omap_dm_timer_load_start(&clkev,
 					OMAP_TIMER_CTRL_AR | OMAP_TIMER_CTRL_ST,
 						0xffffffff - period, 1);
 		break;
@@ -189,7 +194,8 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
 			clk_put(src);
 		}
 	}
-	__omap_dm_timer_reset(timer->io_base, 1, 1);
+	__omap_dm_timer_init_regs(timer);
+	__omap_dm_timer_reset(timer, 1, 1);
 	timer->posted = 1;
 
 	timer->rate = clk_get_rate(timer->fclk);
@@ -210,7 +216,7 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,
 	omap2_gp_timer_irq.dev_id = (void *)&clkev;
 	setup_irq(clkev.irq, &omap2_gp_timer_irq);
 
-	__omap_dm_timer_int_enable(clkev.io_base, OMAP_TIMER_INT_OVERFLOW);
+	__omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
 
 	clockevent_gpt.mult = div_sc(clkev.rate, NSEC_PER_SEC,
 				     clockevent_gpt.shift);
@@ -251,7 +257,7 @@ static struct omap_dm_timer clksrc;
 static DEFINE_CLOCK_DATA(cd);
 static cycle_t clocksource_read_cycles(struct clocksource *cs)
 {
-	return (cycle_t)__omap_dm_timer_read_counter(clksrc.io_base, 1);
+	return (cycle_t)__omap_dm_timer_read_counter(&clksrc, 1);
 }
 
 static struct clocksource clocksource_gpt = {
@@ -266,7 +272,7 @@ static void notrace dmtimer_update_sched_clock(void)
 {
 	u32 cyc;
 
-	cyc = __omap_dm_timer_read_counter(clksrc.io_base, 1);
+	cyc = __omap_dm_timer_read_counter(&clksrc, 1);
 
 	update_sched_clock(&cd, cyc, (u32)~0);
 }
@@ -276,7 +282,7 @@ unsigned long long notrace sched_clock(void)
 	u32 cyc = 0;
 
 	if (clksrc.reserved)
-		cyc = __omap_dm_timer_read_counter(clksrc.io_base, 1);
+		cyc = __omap_dm_timer_read_counter(&clksrc, 1);
 
 	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
 }
@@ -293,7 +299,7 @@ static void __init omap2_gp_clocksource_init(int gptimer_id,
 	pr_info("OMAP clocksource: GPTIMER%d at %lu Hz\n",
 		gptimer_id, clksrc.rate);
 
-	__omap_dm_timer_load_start(clksrc.io_base,
+	__omap_dm_timer_load_start(&clksrc,
 			OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
 	init_sched_clock(&cd, dmtimer_update_sched_clock, 32, clksrc.rate);
 
@@ -341,3 +347,167 @@ static void __init omap4_timer_init(void)
 }
 OMAP_SYS_TIMER(4)
 #endif
+
+/**
+ * omap2_dm_timer_set_src - change the timer input clock source
+ * @pdev:	timer platform device pointer
+ * @source:	array index of parent clock source
+ */
+static int omap2_dm_timer_set_src(struct platform_device *pdev, int source)
+{
+	int ret;
+	struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
+	struct clk *fclk, *parent;
+	char *parent_name = NULL;
+
+	fclk = clk_get(&pdev->dev, "fck");
+	if (IS_ERR_OR_NULL(fclk)) {
+		dev_err(&pdev->dev, "%s: %d: clk_get() FAILED\n",
+				__func__, __LINE__);
+		return -EINVAL;
+	}
+
+	switch (source) {
+	case OMAP_TIMER_SRC_SYS_CLK:
+		parent_name = "sys_ck";
+		break;
+
+	case OMAP_TIMER_SRC_32_KHZ:
+		parent_name = "32k_ck";
+		break;
+
+	case OMAP_TIMER_SRC_EXT_CLK:
+		if (pdata->timer_ip_version == OMAP_TIMER_IP_VERSION_1) {
+			parent_name = "alt_ck";
+			break;
+		}
+		dev_err(&pdev->dev, "%s: %d: invalid clk src.\n",
+			__func__, __LINE__);
+		clk_put(fclk);
+		return -EINVAL;
+	}
+
+	parent = clk_get(&pdev->dev, parent_name);
+	if (IS_ERR_OR_NULL(parent)) {
+		dev_err(&pdev->dev, "%s: %d: clk_get() %s FAILED\n",
+			__func__, __LINE__, parent_name);
+		clk_put(fclk);
+		return -EINVAL;
+	}
+
+	ret = clk_set_parent(fclk, parent);
+	if (IS_ERR_VALUE(ret)) {
+		dev_err(&pdev->dev, "%s: clk_set_parent() to %s FAILED\n",
+			__func__, parent_name);
+		ret = -EINVAL;
+	}
+
+	clk_put(parent);
+	clk_put(fclk);
+
+	return ret;
+}
+
+struct omap_device_pm_latency omap2_dmtimer_latency[] = {
+	{
+		.deactivate_func = omap_device_idle_hwmods,
+		.activate_func   = omap_device_enable_hwmods,
+		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+	},
+};
+
+/**
+ * omap_timer_init - build and register timer device with an
+ * associated timer hwmod
+ * @oh:	timer hwmod pointer to be used to build timer device
+ * @user:	parameter that can be passed from calling hwmod API
+ *
+ * Called by omap_hwmod_for_each_by_class to register each of the timer
+ * devices present in the system. The number of timer devices is known
+ * by parsing through the hwmod database for a given class name. At the
+ * end of function call memory is allocated for timer device and it is
+ * registered to the framework ready to be proved by the driver.
+ */
+static int __init omap_timer_init(struct omap_hwmod *oh, void *unused)
+{
+	int id;
+	int ret = 0;
+	char *name = "omap_timer";
+	struct dmtimer_platform_data *pdata;
+	struct platform_device *pdev;
+	struct omap_timer_capability_dev_attr *timer_dev_attr;
+	struct powerdomain *pwrdm;
+
+	pr_debug("%s: %s\n", __func__, oh->name);
+
+	/* on secure device, do not register secure timer */
+	timer_dev_attr = oh->dev_attr;
+	if (omap_type() != OMAP2_DEVICE_TYPE_GP && timer_dev_attr)
+		if (timer_dev_attr->timer_capability == OMAP_TIMER_SECURE)
+			return ret;
+
+	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+	if (!pdata) {
+		pr_err("%s: No memory for [%s]\n", __func__, oh->name);
+		return -ENOMEM;
+	}
+
+	/*
+	 * Extract the IDs from name field in hwmod database
+	 * and use the same for constructing ids' for the
+	 * timer devices. In a way, we are avoiding usage of
+	 * static variable witin the function to do the same.
+	 * CAUTION: We have to be careful and make sure the
+	 * name in hwmod database does not change in which case
+	 * we might either make corresponding change here or
+	 * switch back static variable mechanism.
+	 */
+	sscanf(oh->name, "timer%2d", &id);
+
+	pdata->set_timer_src = omap2_dm_timer_set_src;
+	pdata->timer_ip_version = oh->class->rev;
+
+	/* Mark clocksource and clockevent timers as reserved */
+	if ((sys_timer_reserved >> (id - 1)) & 0x1)
+		pdata->reserved = 1;
+
+	pwrdm = omap_hwmod_get_pwrdm(oh);
+	pdata->loses_context = pwrdm_can_ever_lose_context(pwrdm);
+#ifdef CONFIG_PM
+	pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count;
+#endif
+	pdev = omap_device_build(name, id, oh, pdata, sizeof(*pdata),
+			omap2_dmtimer_latency,
+			ARRAY_SIZE(omap2_dmtimer_latency),
+			0);
+
+	if (IS_ERR(pdev)) {
+		pr_err("%s: Can't build omap_device for %s: %s.\n",
+			__func__, name, oh->name);
+		ret = -EINVAL;
+	}
+
+	kfree(pdata);
+
+	return ret;
+}
+
+/**
+ * omap2_dm_timer_init - top level regular device initialization
+ *
+ * Uses dedicated hwmod api to parse through hwmod database for
+ * given class name and then build and register the timer device.
+ */
+static int __init omap2_dm_timer_init(void)
+{
+	int ret;
+
+	ret = omap_hwmod_for_each_by_class("timer", omap_timer_init, NULL);
+	if (unlikely(ret)) {
+		pr_err("%s: device registration failed.\n", __func__);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+arch_initcall(omap2_dm_timer_init);
diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c
index 19e4dac..47fb5d6 100644
--- a/arch/arm/mach-omap2/usb-musb.c
+++ b/arch/arm/mach-omap2/usb-musb.c
@@ -60,14 +60,6 @@ static struct musb_hdrc_platform_data musb_plat = {
 
 static u64 musb_dmamask = DMA_BIT_MASK(32);
 
-static struct omap_device_pm_latency omap_musb_latency[] = {
-	{
-		.deactivate_func	= omap_device_idle_hwmods,
-		.activate_func		= omap_device_enable_hwmods,
-		.flags			= OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-};
-
 static void usb_musb_mux_init(struct omap_musb_board_data *board_data)
 {
 	switch (board_data->interface_type) {
@@ -115,7 +107,6 @@ static struct omap_musb_board_data musb_default_board_data = {
 void __init usb_musb_init(struct omap_musb_board_data *musb_board_data)
 {
 	struct omap_hwmod		*oh;
-	struct omap_device		*od;
 	struct platform_device		*pdev;
 	struct device			*dev;
 	int				bus_id = -1;
@@ -145,22 +136,19 @@ void __init usb_musb_init(struct omap_musb_board_data *musb_board_data)
 		name = "musb-omap2430";
 	}
 
-	oh = omap_hwmod_lookup(oh_name);
-	if (!oh) {
-		pr_err("Could not look up %s\n", oh_name);
-		return;
-	}
+        oh = omap_hwmod_lookup(oh_name);
+        if (WARN(!oh, "%s: could not find omap_hwmod for %s\n",
+                 __func__, oh_name))
+                return;
 
-	od = omap_device_build(name, bus_id, oh, &musb_plat,
-			       sizeof(musb_plat), omap_musb_latency,
-			       ARRAY_SIZE(omap_musb_latency), false);
-	if (IS_ERR(od)) {
+	pdev = omap_device_build(name, bus_id, oh, &musb_plat,
+			       sizeof(musb_plat), NULL, 0, false);
+	if (IS_ERR(pdev)) {
 		pr_err("Could not build omap_device for %s %s\n",
 						name, oh_name);
 		return;
 	}
 
-	pdev = &od->pdev;
 	dev = &pdev->dev;
 	get_device(dev);
 	dev->dma_mask = &musb_dmamask;
diff --git a/arch/arm/mach-omap2/vc.c b/arch/arm/mach-omap2/vc.c
new file mode 100644
index 0000000..031d116
--- /dev/null
+++ b/arch/arm/mach-omap2/vc.c
@@ -0,0 +1,367 @@
+/*
+ * OMAP Voltage Controller (VC) interface
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+
+#include <plat/cpu.h>
+
+#include "voltage.h"
+#include "vc.h"
+#include "prm-regbits-34xx.h"
+#include "prm-regbits-44xx.h"
+#include "prm44xx.h"
+
+/**
+ * struct omap_vc_channel_cfg - describe the cfg_channel bitfield
+ * @sa: bit for slave address
+ * @rav: bit for voltage configuration register
+ * @rac: bit for command configuration register
+ * @racen: enable bit for RAC
+ * @cmd: bit for command value set selection
+ *
+ * Channel configuration bits, common for OMAP3+
+ * OMAP3 register: PRM_VC_CH_CONF
+ * OMAP4 register: PRM_VC_CFG_CHANNEL
+ * OMAP5 register: PRM_VC_SMPS_<voltdm>_CONFIG
+ */
+struct omap_vc_channel_cfg {
+	u8 sa;
+	u8 rav;
+	u8 rac;
+	u8 racen;
+	u8 cmd;
+};
+
+static struct omap_vc_channel_cfg vc_default_channel_cfg = {
+	.sa    = BIT(0),
+	.rav   = BIT(1),
+	.rac   = BIT(2),
+	.racen = BIT(3),
+	.cmd   = BIT(4),
+};
+
+/*
+ * On OMAP3+, all VC channels have the above default bitfield
+ * configuration, except the OMAP4 MPU channel.  This appears
+ * to be a freak accident as every other VC channel has the
+ * default configuration, thus creating a mutant channel config.
+ */
+static struct omap_vc_channel_cfg vc_mutant_channel_cfg = {
+	.sa    = BIT(0),
+	.rav   = BIT(2),
+	.rac   = BIT(3),
+	.racen = BIT(4),
+	.cmd   = BIT(1),
+};
+
+static struct omap_vc_channel_cfg *vc_cfg_bits;
+#define CFG_CHANNEL_MASK 0x1f
+
+/**
+ * omap_vc_config_channel - configure VC channel to PMIC mappings
+ * @voltdm: pointer to voltagdomain defining the desired VC channel
+ *
+ * Configures the VC channel to PMIC mappings for the following
+ * PMIC settings
+ * - i2c slave address (SA)
+ * - voltage configuration address (RAV)
+ * - command configuration address (RAC) and enable bit (RACEN)
+ * - command values for ON, ONLP, RET and OFF (CMD)
+ *
+ * This function currently only allows flexible configuration of the
+ * non-default channel.  Starting with OMAP4, there are more than 2
+ * channels, with one defined as the default (on OMAP4, it's MPU.)
+ * Only the non-default channel can be configured.
+ */
+static int omap_vc_config_channel(struct voltagedomain *voltdm)
+{
+	struct omap_vc_channel *vc = voltdm->vc;
+
+	/*
+	 * For default channel, the only configurable bit is RACEN.
+	 * All others must stay at zero (see function comment above.)
+	 */
+	if (vc->flags & OMAP_VC_CHANNEL_DEFAULT)
+		vc->cfg_channel &= vc_cfg_bits->racen;
+
+	voltdm->rmw(CFG_CHANNEL_MASK << vc->cfg_channel_sa_shift,
+		    vc->cfg_channel << vc->cfg_channel_sa_shift,
+		    vc->cfg_channel_reg);
+
+	return 0;
+}
+
+/* Voltage scale and accessory APIs */
+int omap_vc_pre_scale(struct voltagedomain *voltdm,
+		      unsigned long target_volt,
+		      u8 *target_vsel, u8 *current_vsel)
+{
+	struct omap_vc_channel *vc = voltdm->vc;
+	u32 vc_cmdval;
+
+	/* Check if sufficient pmic info is available for this vdd */
+	if (!voltdm->pmic) {
+		pr_err("%s: Insufficient pmic info to scale the vdd_%s\n",
+			__func__, voltdm->name);
+		return -EINVAL;
+	}
+
+	if (!voltdm->pmic->uv_to_vsel) {
+		pr_err("%s: PMIC function to convert voltage in uV to"
+			"vsel not registered. Hence unable to scale voltage"
+			"for vdd_%s\n", __func__, voltdm->name);
+		return -ENODATA;
+	}
+
+	if (!voltdm->read || !voltdm->write) {
+		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
+			__func__, voltdm->name);
+		return -EINVAL;
+	}
+
+	*target_vsel = voltdm->pmic->uv_to_vsel(target_volt);
+	*current_vsel = voltdm->pmic->uv_to_vsel(voltdm->nominal_volt);
+
+	/* Setting the ON voltage to the new target voltage */
+	vc_cmdval = voltdm->read(vc->cmdval_reg);
+	vc_cmdval &= ~vc->common->cmd_on_mask;
+	vc_cmdval |= (*target_vsel << vc->common->cmd_on_shift);
+	voltdm->write(vc_cmdval, vc->cmdval_reg);
+
+	omap_vp_update_errorgain(voltdm, target_volt);
+
+	return 0;
+}
+
+void omap_vc_post_scale(struct voltagedomain *voltdm,
+			unsigned long target_volt,
+			u8 target_vsel, u8 current_vsel)
+{
+	u32 smps_steps = 0, smps_delay = 0;
+
+	smps_steps = abs(target_vsel - current_vsel);
+	/* SMPS slew rate / step size. 2us added as buffer. */
+	smps_delay = ((smps_steps * voltdm->pmic->step_size) /
+			voltdm->pmic->slew_rate) + 2;
+	udelay(smps_delay);
+}
+
+/* vc_bypass_scale - VC bypass method of voltage scaling */
+int omap_vc_bypass_scale(struct voltagedomain *voltdm,
+			 unsigned long target_volt)
+{
+	struct omap_vc_channel *vc = voltdm->vc;
+	u32 loop_cnt = 0, retries_cnt = 0;
+	u32 vc_valid, vc_bypass_val_reg, vc_bypass_value;
+	u8 target_vsel, current_vsel;
+	int ret;
+
+	ret = omap_vc_pre_scale(voltdm, target_volt, &target_vsel, &current_vsel);
+	if (ret)
+		return ret;
+
+	vc_valid = vc->common->valid;
+	vc_bypass_val_reg = vc->common->bypass_val_reg;
+	vc_bypass_value = (target_vsel << vc->common->data_shift) |
+		(vc->volt_reg_addr << vc->common->regaddr_shift) |
+		(vc->i2c_slave_addr << vc->common->slaveaddr_shift);
+
+	voltdm->write(vc_bypass_value, vc_bypass_val_reg);
+	voltdm->write(vc_bypass_value | vc_valid, vc_bypass_val_reg);
+
+	vc_bypass_value = voltdm->read(vc_bypass_val_reg);
+	/*
+	 * Loop till the bypass command is acknowledged from the SMPS.
+	 * NOTE: This is legacy code. The loop count and retry count needs
+	 * to be revisited.
+	 */
+	while (!(vc_bypass_value & vc_valid)) {
+		loop_cnt++;
+
+		if (retries_cnt > 10) {
+			pr_warning("%s: Retry count exceeded\n", __func__);
+			return -ETIMEDOUT;
+		}
+
+		if (loop_cnt > 50) {
+			retries_cnt++;
+			loop_cnt = 0;
+			udelay(10);
+		}
+		vc_bypass_value = voltdm->read(vc_bypass_val_reg);
+	}
+
+	omap_vc_post_scale(voltdm, target_volt, target_vsel, current_vsel);
+	return 0;
+}
+
+static void __init omap3_vfsm_init(struct voltagedomain *voltdm)
+{
+	/*
+	 * Voltage Manager FSM parameters init
+	 * XXX This data should be passed in from the board file
+	 */
+	voltdm->write(OMAP3_CLKSETUP, OMAP3_PRM_CLKSETUP_OFFSET);
+	voltdm->write(OMAP3_VOLTOFFSET, OMAP3_PRM_VOLTOFFSET_OFFSET);
+	voltdm->write(OMAP3_VOLTSETUP2, OMAP3_PRM_VOLTSETUP2_OFFSET);
+}
+
+static void __init omap3_vc_init_channel(struct voltagedomain *voltdm)
+{
+	static bool is_initialized;
+
+	if (is_initialized)
+		return;
+
+	omap3_vfsm_init(voltdm);
+
+	is_initialized = true;
+}
+
+
+/* OMAP4 specific voltage init functions */
+static void __init omap4_vc_init_channel(struct voltagedomain *voltdm)
+{
+	static bool is_initialized;
+	u32 vc_val;
+
+	if (is_initialized)
+		return;
+
+	/* XXX These are magic numbers and do not belong! */
+	vc_val = (0x60 << OMAP4430_SCLL_SHIFT | 0x26 << OMAP4430_SCLH_SHIFT);
+	voltdm->write(vc_val, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET);
+
+	is_initialized = true;
+}
+
+/**
+ * omap_vc_i2c_init - initialize I2C interface to PMIC
+ * @voltdm: voltage domain containing VC data
+ *
+ * Use PMIC supplied seetings for I2C high-speed mode and
+ * master code (if set) and program the VC I2C configuration
+ * register.
+ *
+ * The VC I2C configuration is common to all VC channels,
+ * so this function only configures I2C for the first VC
+ * channel registers.  All other VC channels will use the
+ * same configuration.
+ */
+static void __init omap_vc_i2c_init(struct voltagedomain *voltdm)
+{
+	struct omap_vc_channel *vc = voltdm->vc;
+	static bool initialized;
+	static bool i2c_high_speed;
+	u8 mcode;
+
+	if (initialized) {
+		if (voltdm->pmic->i2c_high_speed != i2c_high_speed)
+			pr_warn("%s: I2C config for all channels must match.",
+				__func__);
+		return;
+	}
+
+	i2c_high_speed = voltdm->pmic->i2c_high_speed;
+	if (i2c_high_speed)
+		voltdm->rmw(vc->common->i2c_cfg_hsen_mask,
+			    vc->common->i2c_cfg_hsen_mask,
+			    vc->common->i2c_cfg_reg);
+
+	mcode = voltdm->pmic->i2c_mcode;
+	if (mcode)
+		voltdm->rmw(vc->common->i2c_mcode_mask,
+			    mcode << __ffs(vc->common->i2c_mcode_mask),
+			    vc->common->i2c_cfg_reg);
+
+	initialized = true;
+}
+
+void __init omap_vc_init_channel(struct voltagedomain *voltdm)
+{
+	struct omap_vc_channel *vc = voltdm->vc;
+	u8 on_vsel, onlp_vsel, ret_vsel, off_vsel;
+	u32 val;
+
+	if (!voltdm->pmic || !voltdm->pmic->uv_to_vsel) {
+		pr_err("%s: PMIC info requried to configure vc for"
+			"vdd_%s not populated.Hence cannot initialize vc\n",
+			__func__, voltdm->name);
+		return;
+	}
+
+	if (!voltdm->read || !voltdm->write) {
+		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
+			__func__, voltdm->name);
+		return;
+	}
+
+	vc->cfg_channel = 0;
+	if (vc->flags & OMAP_VC_CHANNEL_CFG_MUTANT)
+		vc_cfg_bits = &vc_mutant_channel_cfg;
+	else
+		vc_cfg_bits = &vc_default_channel_cfg;
+
+	/* get PMIC/board specific settings */
+	vc->i2c_slave_addr = voltdm->pmic->i2c_slave_addr;
+	vc->volt_reg_addr = voltdm->pmic->volt_reg_addr;
+	vc->cmd_reg_addr = voltdm->pmic->cmd_reg_addr;
+	vc->setup_time = voltdm->pmic->volt_setup_time;
+
+	/* Configure the i2c slave address for this VC */
+	voltdm->rmw(vc->smps_sa_mask,
+		    vc->i2c_slave_addr << __ffs(vc->smps_sa_mask),
+		    vc->smps_sa_reg);
+	vc->cfg_channel |= vc_cfg_bits->sa;
+
+	/*
+	 * Configure the PMIC register addresses.
+	 */
+	voltdm->rmw(vc->smps_volra_mask,
+		    vc->volt_reg_addr << __ffs(vc->smps_volra_mask),
+		    vc->smps_volra_reg);
+	vc->cfg_channel |= vc_cfg_bits->rav;
+
+	if (vc->cmd_reg_addr) {
+		voltdm->rmw(vc->smps_cmdra_mask,
+			    vc->cmd_reg_addr << __ffs(vc->smps_cmdra_mask),
+			    vc->smps_cmdra_reg);
+		vc->cfg_channel |= vc_cfg_bits->rac | vc_cfg_bits->racen;
+	}
+
+	/* Set up the on, inactive, retention and off voltage */
+	on_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->on_volt);
+	onlp_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->onlp_volt);
+	ret_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->ret_volt);
+	off_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->off_volt);
+	val = ((on_vsel << vc->common->cmd_on_shift) |
+	       (onlp_vsel << vc->common->cmd_onlp_shift) |
+	       (ret_vsel << vc->common->cmd_ret_shift) |
+	       (off_vsel << vc->common->cmd_off_shift));
+	voltdm->write(val, vc->cmdval_reg);
+	vc->cfg_channel |= vc_cfg_bits->cmd;
+
+	/* Channel configuration */
+	omap_vc_config_channel(voltdm);
+
+	/* Configure the setup times */
+	voltdm->rmw(voltdm->vfsm->voltsetup_mask,
+		    vc->setup_time << __ffs(voltdm->vfsm->voltsetup_mask),
+		    voltdm->vfsm->voltsetup_reg);
+
+	omap_vc_i2c_init(voltdm);
+
+	if (cpu_is_omap34xx())
+		omap3_vc_init_channel(voltdm);
+	else if (cpu_is_omap44xx())
+		omap4_vc_init_channel(voltdm);
+}
+
diff --git a/arch/arm/mach-omap2/vc.h b/arch/arm/mach-omap2/vc.h
index e776777..478bf6b 100644
--- a/arch/arm/mach-omap2/vc.h
+++ b/arch/arm/mach-omap2/vc.h
@@ -19,12 +19,12 @@
 
 #include <linux/kernel.h>
 
+struct voltagedomain;
+
 /**
- * struct omap_vc_common_data - per-VC register/bitfield data
+ * struct omap_vc_common - per-VC register/bitfield data
  * @cmd_on_mask: ON bitmask in PRM_VC_CMD_VAL* register
  * @valid: VALID bitmask in PRM_VC_BYPASS_VAL register
- * @smps_sa_reg: Offset of PRM_VC_SMPS_SA reg from PRM start
- * @smps_volra_reg: Offset of PRM_VC_SMPS_VOL_RA reg from PRM start
  * @bypass_val_reg: Offset of PRM_VC_BYPASS_VAL reg from PRM start
  * @data_shift: DATA field shift in PRM_VC_BYPASS_VAL register
  * @slaveaddr_shift: SLAVEADDR field shift in PRM_VC_BYPASS_VAL register
@@ -33,15 +33,16 @@
  * @cmd_onlp_shift: ONLP field shift in PRM_VC_CMD_VAL_* register
  * @cmd_ret_shift: RET field shift in PRM_VC_CMD_VAL_* register
  * @cmd_off_shift: OFF field shift in PRM_VC_CMD_VAL_* register
+ * @i2c_cfg_reg: I2C configuration register offset
+ * @i2c_cfg_hsen_mask: high-speed mode bit field mask in I2C config register
+ * @i2c_mcode_mask: MCODE field mask for I2C config register
  *
  * XXX One of cmd_on_mask and cmd_on_shift are not needed
  * XXX VALID should probably be a shift, not a mask
  */
-struct omap_vc_common_data {
+struct omap_vc_common {
 	u32 cmd_on_mask;
 	u32 valid;
-	u8 smps_sa_reg;
-	u8 smps_volra_reg;
 	u8 bypass_val_reg;
 	u8 data_shift;
 	u8 slaveaddr_shift;
@@ -50,34 +51,75 @@ struct omap_vc_common_data {
 	u8 cmd_onlp_shift;
 	u8 cmd_ret_shift;
 	u8 cmd_off_shift;
+	u8 i2c_cfg_reg;
+	u8 i2c_cfg_hsen_mask;
+	u8 i2c_mcode_mask;
 };
 
+/* omap_vc_channel.flags values */
+#define OMAP_VC_CHANNEL_DEFAULT BIT(0)
+#define OMAP_VC_CHANNEL_CFG_MUTANT BIT(1)
+
 /**
- * struct omap_vc_instance_data - VC per-instance data
- * @vc_common: pointer to VC common data for this platform
- * @smps_sa_mask: SA* bitmask in the PRM_VC_SMPS_SA register
- * @smps_volra_mask: VOLRA* bitmask in the PRM_VC_VOL_RA register
- * @smps_sa_shift: SA* field shift in the PRM_VC_SMPS_SA register
- * @smps_volra_shift: VOLRA* field shift in the PRM_VC_VOL_RA register
+ * struct omap_vc_channel - VC per-instance data
+ * @i2c_slave_addr: I2C slave address of PMIC for this VC channel
+ * @volt_reg_addr: voltage configuration register address
+ * @cmd_reg_addr: command configuration register address
+ * @setup_time: setup time (in sys_clk cycles) of regulator for this channel
+ * @cfg_channel: current value of VC channel configuration register
+ * @i2c_high_speed: whether or not to use I2C high-speed mode
  *
- * XXX It is not necessary to have both a *_mask and a *_shift -
- *     remove one
+ * @common: pointer to VC common data for this platform
+ * @smps_sa_mask: i2c slave address bitmask in the PRM_VC_SMPS_SA register
+ * @smps_volra_mask: VOLRA* bitmask in the PRM_VC_VOL_RA register
+ * @smps_cmdra_mask: CMDRA* bitmask in the PRM_VC_CMD_RA register
+ * @cmdval_reg: register for on/ret/off voltage level values for this channel
+ * @smps_sa_reg: Offset of PRM_VC_SMPS_SA reg from PRM start
+ * @smps_volra_reg: Offset of PRM_VC_SMPS_VOL_RA reg from PRM start
+ * @smps_cmdra_reg: Offset of PRM_VC_SMPS_CMD_RA reg from PRM start
+ * @cfg_channel_reg: VC channel configuration register
+ * @cfg_channel_sa_shift: bit shift for slave address cfg_channel register
+ * @flags: VC channel-specific flags (optional)
  */
-struct omap_vc_instance_data {
-	const struct omap_vc_common_data *vc_common;
+struct omap_vc_channel {
+	/* channel state */
+	u16 i2c_slave_addr;
+	u16 volt_reg_addr;
+	u16 cmd_reg_addr;
+	u16 setup_time;
+	u8 cfg_channel;
+	bool i2c_high_speed;
+
+	/* register access data */
+	const struct omap_vc_common *common;
 	u32 smps_sa_mask;
 	u32 smps_volra_mask;
+	u32 smps_cmdra_mask;
 	u8 cmdval_reg;
-	u8 smps_sa_shift;
-	u8 smps_volra_shift;
+	u8 smps_sa_reg;
+	u8 smps_volra_reg;
+	u8 smps_cmdra_reg;
+	u8 cfg_channel_reg;
+	u8 cfg_channel_sa_shift;
+	u8 flags;
 };
 
-extern struct omap_vc_instance_data omap3_vc1_data;
-extern struct omap_vc_instance_data omap3_vc2_data;
+extern struct omap_vc_channel omap3_vc_mpu;
+extern struct omap_vc_channel omap3_vc_core;
+
+extern struct omap_vc_channel omap4_vc_mpu;
+extern struct omap_vc_channel omap4_vc_iva;
+extern struct omap_vc_channel omap4_vc_core;
 
-extern struct omap_vc_instance_data omap4_vc_mpu_data;
-extern struct omap_vc_instance_data omap4_vc_iva_data;
-extern struct omap_vc_instance_data omap4_vc_core_data;
+void omap_vc_init_channel(struct voltagedomain *voltdm);
+int omap_vc_pre_scale(struct voltagedomain *voltdm,
+		      unsigned long target_volt,
+		      u8 *target_vsel, u8 *current_vsel);
+void omap_vc_post_scale(struct voltagedomain *voltdm,
+			unsigned long target_volt,
+			u8 target_vsel, u8 current_vsel);
+int omap_vc_bypass_scale(struct voltagedomain *voltdm,
+			 unsigned long target_volt);
 
 #endif
 
diff --git a/arch/arm/mach-omap2/vc3xxx_data.c b/arch/arm/mach-omap2/vc3xxx_data.c
index f37dc4b..cfe348e 100644
--- a/arch/arm/mach-omap2/vc3xxx_data.c
+++ b/arch/arm/mach-omap2/vc3xxx_data.c
@@ -29,9 +29,7 @@
  * VC data common to 34xx/36xx chips
  * XXX This stuff presumably belongs in the vc3xxx.c or vc.c file.
  */
-static struct omap_vc_common_data omap3_vc_common = {
-	.smps_sa_reg	 = OMAP3_PRM_VC_SMPS_SA_OFFSET,
-	.smps_volra_reg	 = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET,
+static struct omap_vc_common omap3_vc_common = {
 	.bypass_val_reg	 = OMAP3_PRM_VC_BYPASS_VAL_OFFSET,
 	.data_shift	 = OMAP3430_DATA_SHIFT,
 	.slaveaddr_shift = OMAP3430_SLAVEADDR_SHIFT,
@@ -42,22 +40,33 @@ static struct omap_vc_common_data omap3_vc_common = {
 	.cmd_onlp_shift	 = OMAP3430_VC_CMD_ONLP_SHIFT,
 	.cmd_ret_shift	 = OMAP3430_VC_CMD_RET_SHIFT,
 	.cmd_off_shift	 = OMAP3430_VC_CMD_OFF_SHIFT,
+	.i2c_cfg_hsen_mask = OMAP3430_HSEN_MASK,
+	.i2c_cfg_reg	 = OMAP3_PRM_VC_I2C_CFG_OFFSET,
+	.i2c_mcode_mask	 = OMAP3430_MCODE_MASK,
 };
 
-struct omap_vc_instance_data omap3_vc1_data = {
-	.vc_common = &omap3_vc_common,
+struct omap_vc_channel omap3_vc_mpu = {
+	.common = &omap3_vc_common,
+	.smps_sa_reg	 = OMAP3_PRM_VC_SMPS_SA_OFFSET,
+	.smps_volra_reg	 = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET,
+	.smps_cmdra_reg	 = OMAP3_PRM_VC_SMPS_CMD_RA_OFFSET,
+	.cfg_channel_reg = OMAP3_PRM_VC_CH_CONF_OFFSET,
 	.cmdval_reg = OMAP3_PRM_VC_CMD_VAL_0_OFFSET,
-	.smps_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA0_SHIFT,
 	.smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA0_MASK,
-	.smps_volra_shift = OMAP3430_VOLRA0_SHIFT,
 	.smps_volra_mask = OMAP3430_VOLRA0_MASK,
+	.smps_cmdra_mask = OMAP3430_CMDRA0_MASK,
+	.cfg_channel_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA0_SHIFT,
 };
 
-struct omap_vc_instance_data omap3_vc2_data = {
-	.vc_common = &omap3_vc_common,
+struct omap_vc_channel omap3_vc_core = {
+	.common = &omap3_vc_common,
+	.smps_sa_reg	 = OMAP3_PRM_VC_SMPS_SA_OFFSET,
+	.smps_volra_reg	 = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET,
+	.smps_cmdra_reg	 = OMAP3_PRM_VC_SMPS_CMD_RA_OFFSET,
+	.cfg_channel_reg = OMAP3_PRM_VC_CH_CONF_OFFSET,
 	.cmdval_reg = OMAP3_PRM_VC_CMD_VAL_1_OFFSET,
-	.smps_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA1_SHIFT,
 	.smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA1_MASK,
-	.smps_volra_shift = OMAP3430_VOLRA1_SHIFT,
 	.smps_volra_mask = OMAP3430_VOLRA1_MASK,
+	.smps_cmdra_mask = OMAP3430_CMDRA1_MASK,
+	.cfg_channel_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA1_SHIFT,
 };
diff --git a/arch/arm/mach-omap2/vc44xx_data.c b/arch/arm/mach-omap2/vc44xx_data.c
index a98da8d..2740a96 100644
--- a/arch/arm/mach-omap2/vc44xx_data.c
+++ b/arch/arm/mach-omap2/vc44xx_data.c
@@ -30,9 +30,7 @@
  * VC data common to 44xx chips
  * XXX This stuff presumably belongs in the vc3xxx.c or vc.c file.
  */
-static const struct omap_vc_common_data omap4_vc_common = {
-	.smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET,
-	.smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET,
+static const struct omap_vc_common omap4_vc_common = {
 	.bypass_val_reg = OMAP4_PRM_VC_VAL_BYPASS_OFFSET,
 	.data_shift = OMAP4430_DATA_SHIFT,
 	.slaveaddr_shift = OMAP4430_SLAVEADDR_SHIFT,
@@ -43,33 +41,49 @@ static const struct omap_vc_common_data omap4_vc_common = {
 	.cmd_onlp_shift = OMAP4430_ONLP_SHIFT,
 	.cmd_ret_shift = OMAP4430_RET_SHIFT,
 	.cmd_off_shift = OMAP4430_OFF_SHIFT,
+	.i2c_cfg_reg = OMAP4_PRM_VC_CFG_I2C_MODE_OFFSET,
+	.i2c_cfg_hsen_mask = OMAP4430_HSMODEEN_MASK,
+	.i2c_mcode_mask	 = OMAP4430_HSMCODE_MASK,
 };
 
 /* VC instance data for each controllable voltage line */
-struct omap_vc_instance_data omap4_vc_mpu_data = {
-	.vc_common = &omap4_vc_common,
+struct omap_vc_channel omap4_vc_mpu = {
+	.flags = OMAP_VC_CHANNEL_DEFAULT | OMAP_VC_CHANNEL_CFG_MUTANT,
+	.common = &omap4_vc_common,
+	.smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET,
+	.smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET,
+	.smps_cmdra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_CMD_OFFSET,
+	.cfg_channel_reg = OMAP4_PRM_VC_CFG_CHANNEL_OFFSET,
 	.cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_MPU_L_OFFSET,
-	.smps_sa_shift = OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_SHIFT,
 	.smps_sa_mask = OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_MASK,
-	.smps_volra_shift = OMAP4430_VOLRA_VDD_MPU_L_SHIFT,
 	.smps_volra_mask = OMAP4430_VOLRA_VDD_MPU_L_MASK,
+	.smps_cmdra_mask = OMAP4430_CMDRA_VDD_MPU_L_MASK,
+	.cfg_channel_sa_shift = OMAP4430_SA_VDD_MPU_L_SHIFT,
 };
 
-struct omap_vc_instance_data omap4_vc_iva_data = {
-	.vc_common = &omap4_vc_common,
+struct omap_vc_channel omap4_vc_iva = {
+	.common = &omap4_vc_common,
+	.smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET,
+	.smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET,
+	.smps_cmdra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_CMD_OFFSET,
+	.cfg_channel_reg = OMAP4_PRM_VC_CFG_CHANNEL_OFFSET,
 	.cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_IVA_L_OFFSET,
-	.smps_sa_shift = OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_SHIFT,
 	.smps_sa_mask = OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_MASK,
-	.smps_volra_shift = OMAP4430_VOLRA_VDD_IVA_L_SHIFT,
 	.smps_volra_mask = OMAP4430_VOLRA_VDD_IVA_L_MASK,
+	.smps_cmdra_mask = OMAP4430_CMDRA_VDD_IVA_L_MASK,
+	.cfg_channel_sa_shift = OMAP4430_SA_VDD_IVA_L_SHIFT,
 };
 
-struct omap_vc_instance_data omap4_vc_core_data = {
-	.vc_common = &omap4_vc_common,
+struct omap_vc_channel omap4_vc_core = {
+	.common = &omap4_vc_common,
+	.smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET,
+	.smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET,
+	.smps_cmdra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_CMD_OFFSET,
+	.cfg_channel_reg = OMAP4_PRM_VC_CFG_CHANNEL_OFFSET,
 	.cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_CORE_L_OFFSET,
-	.smps_sa_shift = OMAP4430_SA_VDD_CORE_L_0_6_SHIFT,
 	.smps_sa_mask = OMAP4430_SA_VDD_CORE_L_0_6_MASK,
-	.smps_volra_shift = OMAP4430_VOLRA_VDD_CORE_L_SHIFT,
 	.smps_volra_mask = OMAP4430_VOLRA_VDD_CORE_L_MASK,
+	.smps_cmdra_mask = OMAP4430_CMDRA_VDD_CORE_L_MASK,
+	.cfg_channel_sa_shift = OMAP4430_SA_VDD_CORE_L_SHIFT,
 };
 
diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
index 9ef3789..64070ac 100644
--- a/arch/arm/mach-omap2/voltage.c
+++ b/arch/arm/mach-omap2/voltage.c
@@ -21,10 +21,10 @@
 
 #include <linux/delay.h>
 #include <linux/io.h>
-#include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/debugfs.h>
 #include <linux/slab.h>
+#include <linux/clk.h>
 
 #include <plat/common.h>
 
@@ -36,839 +36,88 @@
 #include "control.h"
 
 #include "voltage.h"
+#include "powerdomain.h"
 
 #include "vc.h"
 #include "vp.h"
 
-#define VOLTAGE_DIR_SIZE	16
-
-
-static struct omap_vdd_info **vdd_info;
-
-/*
- * Number of scalable voltage domains.
- */
-static int nr_scalable_vdd;
-
-/* XXX document */
-static s16 prm_mod_offs;
-static s16 prm_irqst_ocp_mod_offs;
-
-static struct dentry *voltage_dir;
-
-/* Init function pointers */
-static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
-					unsigned long target_volt);
-
-static u32 omap3_voltage_read_reg(u16 mod, u8 offset)
-{
-	return omap2_prm_read_mod_reg(mod, offset);
-}
-
-static void omap3_voltage_write_reg(u32 val, u16 mod, u8 offset)
-{
-	omap2_prm_write_mod_reg(val, mod, offset);
-}
-
-static u32 omap4_voltage_read_reg(u16 mod, u8 offset)
-{
-	return omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
-					mod, offset);
-}
-
-static void omap4_voltage_write_reg(u32 val, u16 mod, u8 offset)
-{
-	omap4_prminst_write_inst_reg(val, OMAP4430_PRM_PARTITION, mod, offset);
-}
-
-static int __init _config_common_vdd_data(struct omap_vdd_info *vdd)
-{
-	char *sys_ck_name;
-	struct clk *sys_ck;
-	u32 sys_clk_speed, timeout_val, waittime;
-
-	/*
-	 * XXX Clockfw should handle this, or this should be in a
-	 * struct record
-	 */
-	if (cpu_is_omap24xx() || cpu_is_omap34xx())
-		sys_ck_name = "sys_ck";
-	else if (cpu_is_omap44xx())
-		sys_ck_name = "sys_clkin_ck";
-	else
-		return -EINVAL;
-
-	/*
-	 * Sys clk rate is require to calculate vp timeout value and
-	 * smpswaittimemin and smpswaittimemax.
-	 */
-	sys_ck = clk_get(NULL, sys_ck_name);
-	if (IS_ERR(sys_ck)) {
-		pr_warning("%s: Could not get the sys clk to calculate"
-			"various vdd_%s params\n", __func__, vdd->voltdm.name);
-		return -EINVAL;
-	}
-	sys_clk_speed = clk_get_rate(sys_ck);
-	clk_put(sys_ck);
-	/* Divide to avoid overflow */
-	sys_clk_speed /= 1000;
-
-	/* Generic voltage parameters */
-	vdd->volt_scale = vp_forceupdate_scale_voltage;
-	vdd->vp_enabled = false;
-
-	vdd->vp_rt_data.vpconfig_erroroffset =
-		(vdd->pmic_info->vp_erroroffset <<
-		 vdd->vp_data->vp_common->vpconfig_erroroffset_shift);
-
-	timeout_val = (sys_clk_speed * vdd->pmic_info->vp_timeout_us) / 1000;
-	vdd->vp_rt_data.vlimitto_timeout = timeout_val;
-	vdd->vp_rt_data.vlimitto_vddmin = vdd->pmic_info->vp_vddmin;
-	vdd->vp_rt_data.vlimitto_vddmax = vdd->pmic_info->vp_vddmax;
-
-	waittime = ((vdd->pmic_info->step_size / vdd->pmic_info->slew_rate) *
-				sys_clk_speed) / 1000;
-	vdd->vp_rt_data.vstepmin_smpswaittimemin = waittime;
-	vdd->vp_rt_data.vstepmax_smpswaittimemax = waittime;
-	vdd->vp_rt_data.vstepmin_stepmin = vdd->pmic_info->vp_vstepmin;
-	vdd->vp_rt_data.vstepmax_stepmax = vdd->pmic_info->vp_vstepmax;
-
-	return 0;
-}
-
-/* Voltage debugfs support */
-static int vp_volt_debug_get(void *data, u64 *val)
-{
-	struct omap_vdd_info *vdd = (struct omap_vdd_info *) data;
-	u8 vsel;
-
-	if (!vdd) {
-		pr_warning("Wrong paramater passed\n");
-		return -EINVAL;
-	}
-
-	vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage);
-
-	if (!vdd->pmic_info->vsel_to_uv) {
-		pr_warning("PMIC function to convert vsel to voltage"
-			"in uV not registerd\n");
-		return -EINVAL;
-	}
-
-	*val = vdd->pmic_info->vsel_to_uv(vsel);
-	return 0;
-}
-
-static int nom_volt_debug_get(void *data, u64 *val)
-{
-	struct omap_vdd_info *vdd = (struct omap_vdd_info *) data;
-
-	if (!vdd) {
-		pr_warning("Wrong paramater passed\n");
-		return -EINVAL;
-	}
-
-	*val = omap_voltage_get_nom_volt(&vdd->voltdm);
-
-	return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(vp_volt_debug_fops, vp_volt_debug_get, NULL, "%llu\n");
-DEFINE_SIMPLE_ATTRIBUTE(nom_volt_debug_fops, nom_volt_debug_get, NULL,
-								"%llu\n");
-static void vp_latch_vsel(struct omap_vdd_info *vdd)
-{
-	u32 vpconfig;
-	unsigned long uvdc;
-	char vsel;
-
-	uvdc = omap_voltage_get_nom_volt(&vdd->voltdm);
-	if (!uvdc) {
-		pr_warning("%s: unable to find current voltage for vdd_%s\n",
-			__func__, vdd->voltdm.name);
-		return;
-	}
-
-	if (!vdd->pmic_info || !vdd->pmic_info->uv_to_vsel) {
-		pr_warning("%s: PMIC function to convert voltage in uV to"
-			" vsel not registered\n", __func__);
-		return;
-	}
-
-	vsel = vdd->pmic_info->uv_to_vsel(uvdc);
-
-	vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
-	vpconfig &= ~(vdd->vp_data->vp_common->vpconfig_initvoltage_mask |
-			vdd->vp_data->vp_common->vpconfig_initvdd);
-	vpconfig |= vsel << vdd->vp_data->vp_common->vpconfig_initvoltage_shift;
-
-	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
-
-	/* Trigger initVDD value copy to voltage processor */
-	vdd->write_reg((vpconfig | vdd->vp_data->vp_common->vpconfig_initvdd),
-		       prm_mod_offs, vdd->vp_data->vpconfig);
-
-	/* Clear initVDD copy trigger bit */
-	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
-}
-
-/* Generic voltage init functions */
-static void __init vp_init(struct omap_vdd_info *vdd)
-{
-	u32 vp_val;
-
-	if (!vdd->read_reg || !vdd->write_reg) {
-		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
-			__func__, vdd->voltdm.name);
-		return;
-	}
-
-	vp_val = vdd->vp_rt_data.vpconfig_erroroffset |
-		(vdd->vp_rt_data.vpconfig_errorgain <<
-		vdd->vp_data->vp_common->vpconfig_errorgain_shift) |
-		vdd->vp_data->vp_common->vpconfig_timeouten;
-	vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vpconfig);
-
-	vp_val = ((vdd->vp_rt_data.vstepmin_smpswaittimemin <<
-		vdd->vp_data->vp_common->vstepmin_smpswaittimemin_shift) |
-		(vdd->vp_rt_data.vstepmin_stepmin <<
-		vdd->vp_data->vp_common->vstepmin_stepmin_shift));
-	vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vstepmin);
-
-	vp_val = ((vdd->vp_rt_data.vstepmax_smpswaittimemax <<
-		vdd->vp_data->vp_common->vstepmax_smpswaittimemax_shift) |
-		(vdd->vp_rt_data.vstepmax_stepmax <<
-		vdd->vp_data->vp_common->vstepmax_stepmax_shift));
-	vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vstepmax);
-
-	vp_val = ((vdd->vp_rt_data.vlimitto_vddmax <<
-		vdd->vp_data->vp_common->vlimitto_vddmax_shift) |
-		(vdd->vp_rt_data.vlimitto_vddmin <<
-		vdd->vp_data->vp_common->vlimitto_vddmin_shift) |
-		(vdd->vp_rt_data.vlimitto_timeout <<
-		vdd->vp_data->vp_common->vlimitto_timeout_shift));
-	vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vlimitto);
-}
-
-static void __init vdd_debugfs_init(struct omap_vdd_info *vdd)
-{
-	char *name;
-
-	name = kzalloc(VOLTAGE_DIR_SIZE, GFP_KERNEL);
-	if (!name) {
-		pr_warning("%s: Unable to allocate memory for debugfs"
-			" directory name for vdd_%s",
-			__func__, vdd->voltdm.name);
-		return;
-	}
-	strcpy(name, "vdd_");
-	strcat(name, vdd->voltdm.name);
-
-	vdd->debug_dir = debugfs_create_dir(name, voltage_dir);
-	kfree(name);
-	if (IS_ERR(vdd->debug_dir)) {
-		pr_warning("%s: Unable to create debugfs directory for"
-			" vdd_%s\n", __func__, vdd->voltdm.name);
-		vdd->debug_dir = NULL;
-		return;
-	}
-
-	(void) debugfs_create_x16("vp_errorgain", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_rt_data.vpconfig_errorgain));
-	(void) debugfs_create_x16("vp_smpswaittimemin", S_IRUGO,
-				vdd->debug_dir,
-				&(vdd->vp_rt_data.vstepmin_smpswaittimemin));
-	(void) debugfs_create_x8("vp_stepmin", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_rt_data.vstepmin_stepmin));
-	(void) debugfs_create_x16("vp_smpswaittimemax", S_IRUGO,
-				vdd->debug_dir,
-				&(vdd->vp_rt_data.vstepmax_smpswaittimemax));
-	(void) debugfs_create_x8("vp_stepmax", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_rt_data.vstepmax_stepmax));
-	(void) debugfs_create_x8("vp_vddmax", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_rt_data.vlimitto_vddmax));
-	(void) debugfs_create_x8("vp_vddmin", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_rt_data.vlimitto_vddmin));
-	(void) debugfs_create_x16("vp_timeout", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_rt_data.vlimitto_timeout));
-	(void) debugfs_create_file("curr_vp_volt", S_IRUGO, vdd->debug_dir,
-				(void *) vdd, &vp_volt_debug_fops);
-	(void) debugfs_create_file("curr_nominal_volt", S_IRUGO,
-				vdd->debug_dir, (void *) vdd,
-				&nom_volt_debug_fops);
-}
-
-/* Voltage scale and accessory APIs */
-static int _pre_volt_scale(struct omap_vdd_info *vdd,
-		unsigned long target_volt, u8 *target_vsel, u8 *current_vsel)
-{
-	struct omap_volt_data *volt_data;
-	const struct omap_vc_common_data *vc_common;
-	const struct omap_vp_common_data *vp_common;
-	u32 vc_cmdval, vp_errgain_val;
-
-	vc_common = vdd->vc_data->vc_common;
-	vp_common = vdd->vp_data->vp_common;
-
-	/* Check if suffiecient pmic info is available for this vdd */
-	if (!vdd->pmic_info) {
-		pr_err("%s: Insufficient pmic info to scale the vdd_%s\n",
-			__func__, vdd->voltdm.name);
-		return -EINVAL;
-	}
-
-	if (!vdd->pmic_info->uv_to_vsel) {
-		pr_err("%s: PMIC function to convert voltage in uV to"
-			"vsel not registered. Hence unable to scale voltage"
-			"for vdd_%s\n", __func__, vdd->voltdm.name);
-		return -ENODATA;
-	}
-
-	if (!vdd->read_reg || !vdd->write_reg) {
-		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
-			__func__, vdd->voltdm.name);
-		return -EINVAL;
-	}
-
-	/* Get volt_data corresponding to target_volt */
-	volt_data = omap_voltage_get_voltdata(&vdd->voltdm, target_volt);
-	if (IS_ERR(volt_data))
-		volt_data = NULL;
-
-	*target_vsel = vdd->pmic_info->uv_to_vsel(target_volt);
-	*current_vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage);
-
-	/* Setting the ON voltage to the new target voltage */
-	vc_cmdval = vdd->read_reg(prm_mod_offs, vdd->vc_data->cmdval_reg);
-	vc_cmdval &= ~vc_common->cmd_on_mask;
-	vc_cmdval |= (*target_vsel << vc_common->cmd_on_shift);
-	vdd->write_reg(vc_cmdval, prm_mod_offs, vdd->vc_data->cmdval_reg);
-
-	/* Setting vp errorgain based on the voltage */
-	if (volt_data) {
-		vp_errgain_val = vdd->read_reg(prm_mod_offs,
-					       vdd->vp_data->vpconfig);
-		vdd->vp_rt_data.vpconfig_errorgain = volt_data->vp_errgain;
-		vp_errgain_val &= ~vp_common->vpconfig_errorgain_mask;
-		vp_errgain_val |= vdd->vp_rt_data.vpconfig_errorgain <<
-			vp_common->vpconfig_errorgain_shift;
-		vdd->write_reg(vp_errgain_val, prm_mod_offs,
-			       vdd->vp_data->vpconfig);
-	}
-
-	return 0;
-}
-
-static void _post_volt_scale(struct omap_vdd_info *vdd,
-		unsigned long target_volt, u8 target_vsel, u8 current_vsel)
-{
-	u32 smps_steps = 0, smps_delay = 0;
-
-	smps_steps = abs(target_vsel - current_vsel);
-	/* SMPS slew rate / step size. 2us added as buffer. */
-	smps_delay = ((smps_steps * vdd->pmic_info->step_size) /
-			vdd->pmic_info->slew_rate) + 2;
-	udelay(smps_delay);
-
-	vdd->curr_volt = target_volt;
-}
-
-/* vc_bypass_scale_voltage - VC bypass method of voltage scaling */
-static int vc_bypass_scale_voltage(struct omap_vdd_info *vdd,
-		unsigned long target_volt)
-{
-	u32 loop_cnt = 0, retries_cnt = 0;
-	u32 vc_valid, vc_bypass_val_reg, vc_bypass_value;
-	u8 target_vsel, current_vsel;
-	int ret;
-
-	ret = _pre_volt_scale(vdd, target_volt, &target_vsel, &current_vsel);
-	if (ret)
-		return ret;
-
-	vc_valid = vdd->vc_data->vc_common->valid;
-	vc_bypass_val_reg = vdd->vc_data->vc_common->bypass_val_reg;
-	vc_bypass_value = (target_vsel << vdd->vc_data->vc_common->data_shift) |
-			(vdd->pmic_info->pmic_reg <<
-			vdd->vc_data->vc_common->regaddr_shift) |
-			(vdd->pmic_info->i2c_slave_addr <<
-			vdd->vc_data->vc_common->slaveaddr_shift);
-
-	vdd->write_reg(vc_bypass_value, prm_mod_offs, vc_bypass_val_reg);
-	vdd->write_reg(vc_bypass_value | vc_valid, prm_mod_offs,
-		       vc_bypass_val_reg);
-
-	vc_bypass_value = vdd->read_reg(prm_mod_offs, vc_bypass_val_reg);
-	/*
-	 * Loop till the bypass command is acknowledged from the SMPS.
-	 * NOTE: This is legacy code. The loop count and retry count needs
-	 * to be revisited.
-	 */
-	while (!(vc_bypass_value & vc_valid)) {
-		loop_cnt++;
-
-		if (retries_cnt > 10) {
-			pr_warning("%s: Retry count exceeded\n", __func__);
-			return -ETIMEDOUT;
-		}
-
-		if (loop_cnt > 50) {
-			retries_cnt++;
-			loop_cnt = 0;
-			udelay(10);
-		}
-		vc_bypass_value = vdd->read_reg(prm_mod_offs,
-						vc_bypass_val_reg);
-	}
-
-	_post_volt_scale(vdd, target_volt, target_vsel, current_vsel);
-	return 0;
-}
-
-/* VP force update method of voltage scaling */
-static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
-		unsigned long target_volt)
-{
-	u32 vpconfig;
-	u8 target_vsel, current_vsel, prm_irqst_reg;
-	int ret, timeout = 0;
-
-	ret = _pre_volt_scale(vdd, target_volt, &target_vsel, &current_vsel);
-	if (ret)
-		return ret;
-
-	prm_irqst_reg = vdd->vp_data->prm_irqst_data->prm_irqst_reg;
-
-	/*
-	 * Clear all pending TransactionDone interrupt/status. Typical latency
-	 * is <3us
-	 */
-	while (timeout++ < VP_TRANXDONE_TIMEOUT) {
-		vdd->write_reg(vdd->vp_data->prm_irqst_data->tranxdone_status,
-			       prm_irqst_ocp_mod_offs, prm_irqst_reg);
-		if (!(vdd->read_reg(prm_irqst_ocp_mod_offs, prm_irqst_reg) &
-		      vdd->vp_data->prm_irqst_data->tranxdone_status))
-			break;
-		udelay(1);
-	}
-	if (timeout >= VP_TRANXDONE_TIMEOUT) {
-		pr_warning("%s: vdd_%s TRANXDONE timeout exceeded."
-			"Voltage change aborted", __func__, vdd->voltdm.name);
-		return -ETIMEDOUT;
-	}
-
-	/* Configure for VP-Force Update */
-	vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
-	vpconfig &= ~(vdd->vp_data->vp_common->vpconfig_initvdd |
-			vdd->vp_data->vp_common->vpconfig_forceupdate |
-			vdd->vp_data->vp_common->vpconfig_initvoltage_mask);
-	vpconfig |= ((target_vsel <<
-			vdd->vp_data->vp_common->vpconfig_initvoltage_shift));
-	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
-
-	/* Trigger initVDD value copy to voltage processor */
-	vpconfig |= vdd->vp_data->vp_common->vpconfig_initvdd;
-	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
-
-	/* Force update of voltage */
-	vpconfig |= vdd->vp_data->vp_common->vpconfig_forceupdate;
-	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
-
-	/*
-	 * Wait for TransactionDone. Typical latency is <200us.
-	 * Depends on SMPSWAITTIMEMIN/MAX and voltage change
-	 */
-	timeout = 0;
-	omap_test_timeout((vdd->read_reg(prm_irqst_ocp_mod_offs, prm_irqst_reg) &
-			   vdd->vp_data->prm_irqst_data->tranxdone_status),
-			  VP_TRANXDONE_TIMEOUT, timeout);
-	if (timeout >= VP_TRANXDONE_TIMEOUT)
-		pr_err("%s: vdd_%s TRANXDONE timeout exceeded."
-			"TRANXDONE never got set after the voltage update\n",
-			__func__, vdd->voltdm.name);
-
-	_post_volt_scale(vdd, target_volt, target_vsel, current_vsel);
-
-	/*
-	 * Disable TransactionDone interrupt , clear all status, clear
-	 * control registers
-	 */
-	timeout = 0;
-	while (timeout++ < VP_TRANXDONE_TIMEOUT) {
-		vdd->write_reg(vdd->vp_data->prm_irqst_data->tranxdone_status,
-			       prm_irqst_ocp_mod_offs, prm_irqst_reg);
-		if (!(vdd->read_reg(prm_irqst_ocp_mod_offs, prm_irqst_reg) &
-		      vdd->vp_data->prm_irqst_data->tranxdone_status))
-			break;
-		udelay(1);
-	}
-
-	if (timeout >= VP_TRANXDONE_TIMEOUT)
-		pr_warning("%s: vdd_%s TRANXDONE timeout exceeded while trying"
-			"to clear the TRANXDONE status\n",
-			__func__, vdd->voltdm.name);
-
-	vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
-	/* Clear initVDD copy trigger bit */
-	vpconfig &= ~vdd->vp_data->vp_common->vpconfig_initvdd;
-	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
-	/* Clear force bit */
-	vpconfig &= ~vdd->vp_data->vp_common->vpconfig_forceupdate;
-	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
-
-	return 0;
-}
-
-static void __init omap3_vfsm_init(struct omap_vdd_info *vdd)
-{
-	/*
-	 * Voltage Manager FSM parameters init
-	 * XXX This data should be passed in from the board file
-	 */
-	vdd->write_reg(OMAP3_CLKSETUP, prm_mod_offs, OMAP3_PRM_CLKSETUP_OFFSET);
-	vdd->write_reg(OMAP3_VOLTOFFSET, prm_mod_offs,
-		       OMAP3_PRM_VOLTOFFSET_OFFSET);
-	vdd->write_reg(OMAP3_VOLTSETUP2, prm_mod_offs,
-		       OMAP3_PRM_VOLTSETUP2_OFFSET);
-}
-
-static void __init omap3_vc_init(struct omap_vdd_info *vdd)
-{
-	static bool is_initialized;
-	u8 on_vsel, onlp_vsel, ret_vsel, off_vsel;
-	u32 vc_val;
-
-	if (is_initialized)
-		return;
-
-	/* Set up the on, inactive, retention and off voltage */
-	on_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->on_volt);
-	onlp_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->onlp_volt);
-	ret_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->ret_volt);
-	off_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->off_volt);
-	vc_val	= ((on_vsel << vdd->vc_data->vc_common->cmd_on_shift) |
-		(onlp_vsel << vdd->vc_data->vc_common->cmd_onlp_shift) |
-		(ret_vsel << vdd->vc_data->vc_common->cmd_ret_shift) |
-		(off_vsel << vdd->vc_data->vc_common->cmd_off_shift));
-	vdd->write_reg(vc_val, prm_mod_offs, vdd->vc_data->cmdval_reg);
-
-	/*
-	 * Generic VC parameters init
-	 * XXX This data should be abstracted out
-	 */
-	vdd->write_reg(OMAP3430_CMD1_MASK | OMAP3430_RAV1_MASK, prm_mod_offs,
-			OMAP3_PRM_VC_CH_CONF_OFFSET);
-	vdd->write_reg(OMAP3430_MCODE_SHIFT | OMAP3430_HSEN_MASK, prm_mod_offs,
-			OMAP3_PRM_VC_I2C_CFG_OFFSET);
-
-	omap3_vfsm_init(vdd);
-
-	is_initialized = true;
-}
-
-
-/* OMAP4 specific voltage init functions */
-static void __init omap4_vc_init(struct omap_vdd_info *vdd)
-{
-	static bool is_initialized;
-	u32 vc_val;
-
-	if (is_initialized)
-		return;
-
-	/* TODO: Configure setup times and CMD_VAL values*/
-
-	/*
-	 * Generic VC parameters init
-	 * XXX This data should be abstracted out
-	 */
-	vc_val = (OMAP4430_RAV_VDD_MPU_L_MASK | OMAP4430_CMD_VDD_MPU_L_MASK |
-		  OMAP4430_RAV_VDD_IVA_L_MASK | OMAP4430_CMD_VDD_IVA_L_MASK |
-		  OMAP4430_RAV_VDD_CORE_L_MASK | OMAP4430_CMD_VDD_CORE_L_MASK);
-	vdd->write_reg(vc_val, prm_mod_offs, OMAP4_PRM_VC_CFG_CHANNEL_OFFSET);
-
-	/* XXX These are magic numbers and do not belong! */
-	vc_val = (0x60 << OMAP4430_SCLL_SHIFT | 0x26 << OMAP4430_SCLH_SHIFT);
-	vdd->write_reg(vc_val, prm_mod_offs, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET);
-
-	is_initialized = true;
-}
-
-static void __init omap_vc_init(struct omap_vdd_info *vdd)
-{
-	u32 vc_val;
-
-	if (!vdd->pmic_info || !vdd->pmic_info->uv_to_vsel) {
-		pr_err("%s: PMIC info requried to configure vc for"
-			"vdd_%s not populated.Hence cannot initialize vc\n",
-			__func__, vdd->voltdm.name);
-		return;
-	}
-
-	if (!vdd->read_reg || !vdd->write_reg) {
-		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
-			__func__, vdd->voltdm.name);
-		return;
-	}
-
-	/* Set up the SMPS_SA(i2c slave address in VC */
-	vc_val = vdd->read_reg(prm_mod_offs,
-			       vdd->vc_data->vc_common->smps_sa_reg);
-	vc_val &= ~vdd->vc_data->smps_sa_mask;
-	vc_val |= vdd->pmic_info->i2c_slave_addr << vdd->vc_data->smps_sa_shift;
-	vdd->write_reg(vc_val, prm_mod_offs,
-		       vdd->vc_data->vc_common->smps_sa_reg);
-
-	/* Setup the VOLRA(pmic reg addr) in VC */
-	vc_val = vdd->read_reg(prm_mod_offs,
-			       vdd->vc_data->vc_common->smps_volra_reg);
-	vc_val &= ~vdd->vc_data->smps_volra_mask;
-	vc_val |= vdd->pmic_info->pmic_reg << vdd->vc_data->smps_volra_shift;
-	vdd->write_reg(vc_val, prm_mod_offs,
-		       vdd->vc_data->vc_common->smps_volra_reg);
-
-	/* Configure the setup times */
-	vc_val = vdd->read_reg(prm_mod_offs, vdd->vfsm->voltsetup_reg);
-	vc_val &= ~vdd->vfsm->voltsetup_mask;
-	vc_val |= vdd->pmic_info->volt_setup_time <<
-			vdd->vfsm->voltsetup_shift;
-	vdd->write_reg(vc_val, prm_mod_offs, vdd->vfsm->voltsetup_reg);
-
-	if (cpu_is_omap34xx())
-		omap3_vc_init(vdd);
-	else if (cpu_is_omap44xx())
-		omap4_vc_init(vdd);
-}
-
-static int __init omap_vdd_data_configure(struct omap_vdd_info *vdd)
-{
-	int ret = -EINVAL;
-
-	if (!vdd->pmic_info) {
-		pr_err("%s: PMIC info requried to configure vdd_%s not"
-			"populated.Hence cannot initialize vdd_%s\n",
-			__func__, vdd->voltdm.name, vdd->voltdm.name);
-		goto ovdc_out;
-	}
-
-	if (IS_ERR_VALUE(_config_common_vdd_data(vdd)))
-		goto ovdc_out;
-
-	if (cpu_is_omap34xx()) {
-		vdd->read_reg = omap3_voltage_read_reg;
-		vdd->write_reg = omap3_voltage_write_reg;
-		ret = 0;
-	} else if (cpu_is_omap44xx()) {
-		vdd->read_reg = omap4_voltage_read_reg;
-		vdd->write_reg = omap4_voltage_write_reg;
-		ret = 0;
-	}
-
-ovdc_out:
-	return ret;
-}
+static LIST_HEAD(voltdm_list);
 
 /* Public functions */
 /**
- * omap_voltage_get_nom_volt() - Gets the current non-auto-compensated voltage
- * @voltdm:	pointer to the VDD for which current voltage info is needed
+ * voltdm_get_voltage() - Gets the current non-auto-compensated voltage
+ * @voltdm:	pointer to the voltdm for which current voltage info is needed
  *
- * API to get the current non-auto-compensated voltage for a VDD.
- * Returns 0 in case of error else returns the current voltage for the VDD.
+ * API to get the current non-auto-compensated voltage for a voltage domain.
+ * Returns 0 in case of error else returns the current voltage.
  */
-unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm)
+unsigned long voltdm_get_voltage(struct voltagedomain *voltdm)
 {
-	struct omap_vdd_info *vdd;
-
 	if (!voltdm || IS_ERR(voltdm)) {
 		pr_warning("%s: VDD specified does not exist!\n", __func__);
 		return 0;
 	}
 
-	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-
-	return vdd->curr_volt;
+	return voltdm->nominal_volt;
 }
 
 /**
- * omap_vp_get_curr_volt() - API to get the current vp voltage.
- * @voltdm:	pointer to the VDD.
- *
- * This API returns the current voltage for the specified voltage processor
- */
-unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm)
-{
-	struct omap_vdd_info *vdd;
-	u8 curr_vsel;
-
-	if (!voltdm || IS_ERR(voltdm)) {
-		pr_warning("%s: VDD specified does not exist!\n", __func__);
-		return 0;
-	}
-
-	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-	if (!vdd->read_reg) {
-		pr_err("%s: No read API for reading vdd_%s regs\n",
-			__func__, voltdm->name);
-		return 0;
-	}
-
-	curr_vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage);
-
-	if (!vdd->pmic_info || !vdd->pmic_info->vsel_to_uv) {
-		pr_warning("%s: PMIC function to convert vsel to voltage"
-			"in uV not registerd\n", __func__);
-		return 0;
-	}
-
-	return vdd->pmic_info->vsel_to_uv(curr_vsel);
-}
-
-/**
- * omap_vp_enable() - API to enable a particular VP
- * @voltdm:	pointer to the VDD whose VP is to be enabled.
- *
- * This API enables a particular voltage processor. Needed by the smartreflex
- * class drivers.
- */
-void omap_vp_enable(struct voltagedomain *voltdm)
-{
-	struct omap_vdd_info *vdd;
-	u32 vpconfig;
-
-	if (!voltdm || IS_ERR(voltdm)) {
-		pr_warning("%s: VDD specified does not exist!\n", __func__);
-		return;
-	}
-
-	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-	if (!vdd->read_reg || !vdd->write_reg) {
-		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
-			__func__, voltdm->name);
-		return;
-	}
-
-	/* If VP is already enabled, do nothing. Return */
-	if (vdd->vp_enabled)
-		return;
-
-	vp_latch_vsel(vdd);
-
-	/* Enable VP */
-	vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
-	vpconfig |= vdd->vp_data->vp_common->vpconfig_vpenable;
-	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
-	vdd->vp_enabled = true;
-}
-
-/**
- * omap_vp_disable() - API to disable a particular VP
- * @voltdm:	pointer to the VDD whose VP is to be disabled.
- *
- * This API disables a particular voltage processor. Needed by the smartreflex
- * class drivers.
- */
-void omap_vp_disable(struct voltagedomain *voltdm)
-{
-	struct omap_vdd_info *vdd;
-	u32 vpconfig;
-	int timeout;
-
-	if (!voltdm || IS_ERR(voltdm)) {
-		pr_warning("%s: VDD specified does not exist!\n", __func__);
-		return;
-	}
-
-	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-	if (!vdd->read_reg || !vdd->write_reg) {
-		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
-			__func__, voltdm->name);
-		return;
-	}
-
-	/* If VP is already disabled, do nothing. Return */
-	if (!vdd->vp_enabled) {
-		pr_warning("%s: Trying to disable VP for vdd_%s when"
-			"it is already disabled\n", __func__, voltdm->name);
-		return;
-	}
-
-	/* Disable VP */
-	vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
-	vpconfig &= ~vdd->vp_data->vp_common->vpconfig_vpenable;
-	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
-
-	/*
-	 * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us
-	 */
-	omap_test_timeout((vdd->read_reg(prm_mod_offs, vdd->vp_data->vstatus)),
-				VP_IDLE_TIMEOUT, timeout);
-
-	if (timeout >= VP_IDLE_TIMEOUT)
-		pr_warning("%s: vdd_%s idle timedout\n",
-			__func__, voltdm->name);
-
-	vdd->vp_enabled = false;
-
-	return;
-}
-
-/**
- * omap_voltage_scale_vdd() - API to scale voltage of a particular
- *				voltage domain.
- * @voltdm:	pointer to the VDD which is to be scaled.
- * @target_volt:	The target voltage of the voltage domain
+ * voltdm_scale() - API to scale voltage of a particular voltage domain.
+ * @voltdm: pointer to the voltage domain which is to be scaled.
+ * @target_volt: The target voltage of the voltage domain
  *
  * This API should be called by the kernel to do the voltage scaling
- * for a particular voltage domain during dvfs or any other situation.
+ * for a particular voltage domain during DVFS.
  */
-int omap_voltage_scale_vdd(struct voltagedomain *voltdm,
-		unsigned long target_volt)
+int voltdm_scale(struct voltagedomain *voltdm,
+		 unsigned long target_volt)
 {
-	struct omap_vdd_info *vdd;
+	int ret;
 
 	if (!voltdm || IS_ERR(voltdm)) {
 		pr_warning("%s: VDD specified does not exist!\n", __func__);
 		return -EINVAL;
 	}
 
-	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-
-	if (!vdd->volt_scale) {
+	if (!voltdm->scale) {
 		pr_err("%s: No voltage scale API registered for vdd_%s\n",
 			__func__, voltdm->name);
 		return -ENODATA;
 	}
 
-	return vdd->volt_scale(vdd, target_volt);
+	ret = voltdm->scale(voltdm, target_volt);
+	if (!ret)
+		voltdm->nominal_volt = target_volt;
+
+	return ret;
 }
 
 /**
- * omap_voltage_reset() - Resets the voltage of a particular voltage domain
- *			to that of the current OPP.
- * @voltdm:	pointer to the VDD whose voltage is to be reset.
+ * voltdm_reset() - Resets the voltage of a particular voltage domain
+ *		    to that of the current OPP.
+ * @voltdm: pointer to the voltage domain whose voltage is to be reset.
  *
  * This API finds out the correct voltage the voltage domain is supposed
  * to be at and resets the voltage to that level. Should be used especially
  * while disabling any voltage compensation modules.
  */
-void omap_voltage_reset(struct voltagedomain *voltdm)
+void voltdm_reset(struct voltagedomain *voltdm)
 {
-	unsigned long target_uvdc;
+	unsigned long target_volt;
 
 	if (!voltdm || IS_ERR(voltdm)) {
 		pr_warning("%s: VDD specified does not exist!\n", __func__);
 		return;
 	}
 
-	target_uvdc = omap_voltage_get_nom_volt(voltdm);
-	if (!target_uvdc) {
+	target_volt = voltdm_get_voltage(voltdm);
+	if (!target_volt) {
 		pr_err("%s: unable to find current voltage for vdd_%s\n",
 			__func__, voltdm->name);
 		return;
 	}
 
-	omap_voltage_scale_vdd(voltdm, target_uvdc);
+	voltdm_scale(voltdm, target_volt);
 }
 
 /**
@@ -884,18 +133,14 @@ void omap_voltage_reset(struct voltagedomain *voltdm)
  *
  */
 void omap_voltage_get_volttable(struct voltagedomain *voltdm,
-		struct omap_volt_data **volt_data)
+				struct omap_volt_data **volt_data)
 {
-	struct omap_vdd_info *vdd;
-
 	if (!voltdm || IS_ERR(voltdm)) {
 		pr_warning("%s: VDD specified does not exist!\n", __func__);
 		return;
 	}
 
-	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-
-	*volt_data = vdd->volt_data;
+	*volt_data = voltdm->volt_data;
 }
 
 /**
@@ -914,9 +159,8 @@ void omap_voltage_get_volttable(struct voltagedomain *voltdm,
  * domain or if there is no matching entry.
  */
 struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
-		unsigned long volt)
+						 unsigned long volt)
 {
-	struct omap_vdd_info *vdd;
 	int i;
 
 	if (!voltdm || IS_ERR(voltdm)) {
@@ -924,17 +168,15 @@ struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
 		return ERR_PTR(-EINVAL);
 	}
 
-	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-
-	if (!vdd->volt_data) {
+	if (!voltdm->volt_data) {
 		pr_warning("%s: voltage table does not exist for vdd_%s\n",
 			__func__, voltdm->name);
 		return ERR_PTR(-ENODATA);
 	}
 
-	for (i = 0; vdd->volt_data[i].volt_nominal != 0; i++) {
-		if (vdd->volt_data[i].volt_nominal == volt)
-			return &vdd->volt_data[i];
+	for (i = 0; voltdm->volt_data[i].volt_nominal != 0; i++) {
+		if (voltdm->volt_data[i].volt_nominal == volt)
+			return &voltdm->volt_data[i];
 	}
 
 	pr_notice("%s: Unable to match the current voltage with the voltage"
@@ -947,54 +189,25 @@ struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
  * omap_voltage_register_pmic() - API to register PMIC specific data
  * @voltdm:	pointer to the VDD for which the PMIC specific data is
  *		to be registered
- * @pmic_info:	the structure containing pmic info
+ * @pmic:	the structure containing pmic info
  *
  * This API is to be called by the SOC/PMIC file to specify the
- * pmic specific info as present in omap_volt_pmic_info structure.
+ * pmic specific info as present in omap_voltdm_pmic structure.
  */
 int omap_voltage_register_pmic(struct voltagedomain *voltdm,
-		struct omap_volt_pmic_info *pmic_info)
+			       struct omap_voltdm_pmic *pmic)
 {
-	struct omap_vdd_info *vdd;
-
 	if (!voltdm || IS_ERR(voltdm)) {
 		pr_warning("%s: VDD specified does not exist!\n", __func__);
 		return -EINVAL;
 	}
 
-	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-
-	vdd->pmic_info = pmic_info;
+	voltdm->pmic = pmic;
 
 	return 0;
 }
 
 /**
- * omap_voltage_get_dbgdir() - API to get pointer to the debugfs directory
- *				corresponding to a voltage domain.
- *
- * @voltdm:	pointer to the VDD whose debug directory is required.
- *
- * This API returns pointer to the debugfs directory corresponding
- * to the voltage domain. Should be used by drivers requiring to
- * add any debug entry for a particular voltage domain. Returns NULL
- * in case of error.
- */
-struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm)
-{
-	struct omap_vdd_info *vdd;
-
-	if (!voltdm || IS_ERR(voltdm)) {
-		pr_warning("%s: VDD specified does not exist!\n", __func__);
-		return NULL;
-	}
-
-	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-
-	return vdd->debug_dir;
-}
-
-/**
  * omap_change_voltscale_method() - API to change the voltage scaling method.
  * @voltdm:	pointer to the VDD whose voltage scaling method
  *		has to be changed.
@@ -1005,23 +218,19 @@ struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm)
  * defined in voltage.h
  */
 void omap_change_voltscale_method(struct voltagedomain *voltdm,
-		int voltscale_method)
+				  int voltscale_method)
 {
-	struct omap_vdd_info *vdd;
-
 	if (!voltdm || IS_ERR(voltdm)) {
 		pr_warning("%s: VDD specified does not exist!\n", __func__);
 		return;
 	}
 
-	vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
-
 	switch (voltscale_method) {
 	case VOLTSCALE_VPFORCEUPDATE:
-		vdd->volt_scale = vp_forceupdate_scale_voltage;
+		voltdm->scale = omap_vp_forceupdate_scale;
 		return;
 	case VOLTSCALE_VCBYPASS:
-		vdd->volt_scale = vc_bypass_scale_voltage;
+		voltdm->scale = omap_vc_bypass_scale;
 		return;
 	default:
 		pr_warning("%s: Trying to change the method of voltage scaling"
@@ -1030,77 +239,192 @@ void omap_change_voltscale_method(struct voltagedomain *voltdm,
 }
 
 /**
- * omap_voltage_domain_lookup() - API to get the voltage domain pointer
- * @name:	Name of the voltage domain
+ * omap_voltage_late_init() - Init the various voltage parameters
  *
- * This API looks up in the global vdd_info struct for the
- * existence of voltage domain <name>. If it exists, the API returns
- * a pointer to the voltage domain structure corresponding to the
- * VDD<name>. Else retuns error pointer.
+ * This API is to be called in the later stages of the
+ * system boot to init the voltage controller and
+ * voltage processors.
  */
-struct voltagedomain *omap_voltage_domain_lookup(char *name)
+int __init omap_voltage_late_init(void)
 {
-	int i;
+	struct voltagedomain *voltdm;
 
-	if (!vdd_info) {
-		pr_err("%s: Voltage driver init not yet happened.Faulting!\n",
+	if (list_empty(&voltdm_list)) {
+		pr_err("%s: Voltage driver support not added\n",
 			__func__);
-		return ERR_PTR(-EINVAL);
+		return -EINVAL;
 	}
 
-	if (!name) {
-		pr_err("%s: No name to get the votage domain!\n", __func__);
-		return ERR_PTR(-EINVAL);
+	list_for_each_entry(voltdm, &voltdm_list, node) {
+		struct clk *sys_ck;
+
+		if (!voltdm->scalable)
+			continue;
+
+		sys_ck = clk_get(NULL, voltdm->sys_clk.name);
+		if (IS_ERR(sys_ck)) {
+			pr_warning("%s: Could not get sys clk.\n", __func__);
+			return -EINVAL;
+		}
+		voltdm->sys_clk.rate = clk_get_rate(sys_ck);
+		WARN_ON(!voltdm->sys_clk.rate);
+		clk_put(sys_ck);
+
+		if (voltdm->vc) {
+			voltdm->scale = omap_vc_bypass_scale;
+			omap_vc_init_channel(voltdm);
+		}
+
+		if (voltdm->vp) {
+			voltdm->scale = omap_vp_forceupdate_scale;
+			omap_vp_init(voltdm);
+		}
 	}
 
-	for (i = 0; i < nr_scalable_vdd; i++) {
-		if (!(strcmp(name, vdd_info[i]->voltdm.name)))
-			return &vdd_info[i]->voltdm;
+	return 0;
+}
+
+static struct voltagedomain *_voltdm_lookup(const char *name)
+{
+	struct voltagedomain *voltdm, *temp_voltdm;
+
+	voltdm = NULL;
+
+	list_for_each_entry(temp_voltdm, &voltdm_list, node) {
+		if (!strcmp(name, temp_voltdm->name)) {
+			voltdm = temp_voltdm;
+			break;
+		}
 	}
 
-	return ERR_PTR(-EINVAL);
+	return voltdm;
 }
 
 /**
- * omap_voltage_late_init() - Init the various voltage parameters
+ * voltdm_add_pwrdm - add a powerdomain to a voltagedomain
+ * @voltdm: struct voltagedomain * to add the powerdomain to
+ * @pwrdm: struct powerdomain * to associate with a voltagedomain
  *
- * This API is to be called in the later stages of the
- * system boot to init the voltage controller and
- * voltage processors.
+ * Associate the powerdomain @pwrdm with a voltagedomain @voltdm.  This
+ * enables the use of voltdm_for_each_pwrdm().  Returns -EINVAL if
+ * presented with invalid pointers; -ENOMEM if memory could not be allocated;
+ * or 0 upon success.
  */
-int __init omap_voltage_late_init(void)
+int voltdm_add_pwrdm(struct voltagedomain *voltdm, struct powerdomain *pwrdm)
 {
-	int i;
+	if (!voltdm || !pwrdm)
+		return -EINVAL;
 
-	if (!vdd_info) {
-		pr_err("%s: Voltage driver support not added\n",
-			__func__);
+	pr_debug("voltagedomain: associating powerdomain %s with voltagedomain "
+		 "%s\n", pwrdm->name, voltdm->name);
+
+	list_add(&pwrdm->voltdm_node, &voltdm->pwrdm_list);
+
+	return 0;
+}
+
+/**
+ * voltdm_for_each_pwrdm - call function for each pwrdm in a voltdm
+ * @voltdm: struct voltagedomain * to iterate over
+ * @fn: callback function *
+ *
+ * Call the supplied function @fn for each powerdomain in the
+ * voltagedomain @voltdm.  Returns -EINVAL if presented with invalid
+ * pointers; or passes along the last return value of the callback
+ * function, which should be 0 for success or anything else to
+ * indicate failure.
+ */
+int voltdm_for_each_pwrdm(struct voltagedomain *voltdm,
+			  int (*fn)(struct voltagedomain *voltdm,
+				    struct powerdomain *pwrdm))
+{
+	struct powerdomain *pwrdm;
+	int ret = 0;
+
+	if (!fn)
 		return -EINVAL;
-	}
 
-	voltage_dir = debugfs_create_dir("voltage", NULL);
-	if (IS_ERR(voltage_dir))
-		pr_err("%s: Unable to create voltage debugfs main dir\n",
-			__func__);
-	for (i = 0; i < nr_scalable_vdd; i++) {
-		if (omap_vdd_data_configure(vdd_info[i]))
-			continue;
-		omap_vc_init(vdd_info[i]);
-		vp_init(vdd_info[i]);
-		vdd_debugfs_init(vdd_info[i]);
+	list_for_each_entry(pwrdm, &voltdm->pwrdm_list, voltdm_node)
+		ret = (*fn)(voltdm, pwrdm);
+
+	return ret;
+}
+
+/**
+ * voltdm_for_each - call function on each registered voltagedomain
+ * @fn: callback function *
+ *
+ * Call the supplied function @fn for each registered voltagedomain.
+ * The callback function @fn can return anything but 0 to bail out
+ * early from the iterator.  Returns the last return value of the
+ * callback function, which should be 0 for success or anything else
+ * to indicate failure; or -EINVAL if the function pointer is null.
+ */
+int voltdm_for_each(int (*fn)(struct voltagedomain *voltdm, void *user),
+		    void *user)
+{
+	struct voltagedomain *temp_voltdm;
+	int ret = 0;
+
+	if (!fn)
+		return -EINVAL;
+
+	list_for_each_entry(temp_voltdm, &voltdm_list, node) {
+		ret = (*fn)(temp_voltdm, user);
+		if (ret)
+			break;
 	}
 
-	return 0;
+	return ret;
 }
 
-/* XXX document */
-int __init omap_voltage_early_init(s16 prm_mod, s16 prm_irqst_ocp_mod,
-				   struct omap_vdd_info *omap_vdd_array[],
-				   u8 omap_vdd_count)
+static int _voltdm_register(struct voltagedomain *voltdm)
 {
-	prm_mod_offs = prm_mod;
-	prm_irqst_ocp_mod_offs = prm_irqst_ocp_mod;
-	vdd_info = omap_vdd_array;
-	nr_scalable_vdd = omap_vdd_count;
+	if (!voltdm || !voltdm->name)
+		return -EINVAL;
+
+	INIT_LIST_HEAD(&voltdm->pwrdm_list);
+	list_add(&voltdm->node, &voltdm_list);
+
+	pr_debug("voltagedomain: registered %s\n", voltdm->name);
+
 	return 0;
 }
+
+/**
+ * voltdm_lookup - look up a voltagedomain by name, return a pointer
+ * @name: name of voltagedomain
+ *
+ * Find a registered voltagedomain by its name @name.  Returns a pointer
+ * to the struct voltagedomain if found, or NULL otherwise.
+ */
+struct voltagedomain *voltdm_lookup(const char *name)
+{
+	struct voltagedomain *voltdm ;
+
+	if (!name)
+		return NULL;
+
+	voltdm = _voltdm_lookup(name);
+
+	return voltdm;
+}
+
+/**
+ * voltdm_init - set up the voltagedomain layer
+ * @voltdm_list: array of struct voltagedomain pointers to register
+ *
+ * Loop through the array of voltagedomains @voltdm_list, registering all
+ * that are available on the current CPU. If voltdm_list is supplied
+ * and not null, all of the referenced voltagedomains will be
+ * registered.  No return value.
+ */
+void voltdm_init(struct voltagedomain **voltdms)
+{
+	struct voltagedomain **v;
+
+	if (voltdms) {
+		for (v = voltdms; *v; v++)
+			_voltdm_register(*v);
+	}
+}
diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h
index e9f5408..16a1b09 100644
--- a/arch/arm/mach-omap2/voltage.h
+++ b/arch/arm/mach-omap2/voltage.h
@@ -19,6 +19,8 @@
 #include "vc.h"
 #include "vp.h"
 
+struct powerdomain;
+
 /* XXX document */
 #define VOLTSCALE_VPFORCEUPDATE		1
 #define VOLTSCALE_VCBYPASS		2
@@ -32,29 +34,60 @@
 #define OMAP3_VOLTSETUP2	0xff
 
 /**
- * struct omap_vfsm_instance_data - per-voltage manager FSM register/bitfield
+ * struct omap_vfsm_instance - per-voltage manager FSM register/bitfield
  * data
  * @voltsetup_mask: SETUP_TIME* bitmask in the PRM_VOLTSETUP* register
  * @voltsetup_reg: register offset of PRM_VOLTSETUP from PRM base
- * @voltsetup_shift: SETUP_TIME* field shift in the PRM_VOLTSETUP* register
  *
  * XXX What about VOLTOFFSET/VOLTCTRL?
- * XXX It is not necessary to have both a _mask and a _shift for the same
- *     bitfield - remove one!
  */
-struct omap_vfsm_instance_data {
+struct omap_vfsm_instance {
 	u32 voltsetup_mask;
 	u8 voltsetup_reg;
-	u8 voltsetup_shift;
 };
 
 /**
  * struct voltagedomain - omap voltage domain global structure.
- * @name:	Name of the voltage domain which can be used as a unique
- *		identifier.
+ * @name: Name of the voltage domain which can be used as a unique identifier.
+ * @scalable: Whether or not this voltage domain is scalable
+ * @node: list_head linking all voltage domains
+ * @pwrdm_list: list_head linking all powerdomains in this voltagedomain
+ * @vc: pointer to VC channel associated with this voltagedomain
+ * @vp: pointer to VP associated with this voltagedomain
+ * @read: read a VC/VP register
+ * @write: write a VC/VP register
+ * @read: read-modify-write a VC/VP register
+ * @sys_clk: system clock name/frequency, used for various timing calculations
+ * @scale: function used to scale the voltage of the voltagedomain
+ * @nominal_volt: current nominal voltage for this voltage domain
+ * @volt_data: voltage table having the distinct voltages supported
+ *             by the domain and other associated per voltage data.
  */
 struct voltagedomain {
 	char *name;
+	bool scalable;
+	struct list_head node;
+	struct list_head pwrdm_list;
+	struct omap_vc_channel *vc;
+	const struct omap_vfsm_instance *vfsm;
+	struct omap_vp_instance *vp;
+	struct omap_voltdm_pmic *pmic;
+
+	/* VC/VP register access functions: SoC specific */
+	u32 (*read) (u8 offset);
+	void (*write) (u32 val, u8 offset);
+	u32 (*rmw)(u32 mask, u32 bits, u8 offset);
+
+	union {
+		const char *name;
+		u32 rate;
+	} sys_clk;
+
+	int (*scale) (struct voltagedomain *voltdm,
+		      unsigned long target_volt);
+
+	u32 nominal_volt;
+	struct omap_volt_data *volt_data;
 };
 
 /**
@@ -77,13 +110,18 @@ struct omap_volt_data {
 };
 
 /**
- * struct omap_volt_pmic_info - PMIC specific data required by voltage driver.
+ * struct omap_voltdm_pmic - PMIC specific data required by voltage driver.
  * @slew_rate:	PMIC slew rate (in uv/us)
  * @step_size:	PMIC voltage step size (in uv)
+ * @i2c_slave_addr: I2C slave address of PMIC
+ * @volt_reg_addr: voltage configuration register address
+ * @cmd_reg_addr: command (on, on-LP, ret, off) configuration register address
+ * @i2c_high_speed: whether VC uses I2C high-speed mode to PMIC
+ * @i2c_mcode: master code value for I2C high-speed preamble transmission
  * @vsel_to_uv:	PMIC API to convert vsel value to actual voltage in uV.
  * @uv_to_vsel:	PMIC API to convert voltage in uV to vsel value.
  */
-struct omap_volt_pmic_info {
+struct omap_voltdm_pmic {
 	int slew_rate;
 	int step_size;
 	u32 on_volt;
@@ -91,94 +129,44 @@ struct omap_volt_pmic_info {
 	u32 ret_volt;
 	u32 off_volt;
 	u16 volt_setup_time;
+	u16 i2c_slave_addr;
+	u16 volt_reg_addr;
+	u16 cmd_reg_addr;
 	u8 vp_erroroffset;
 	u8 vp_vstepmin;
 	u8 vp_vstepmax;
 	u8 vp_vddmin;
 	u8 vp_vddmax;
 	u8 vp_timeout_us;
-	u8 i2c_slave_addr;
-	u8 pmic_reg;
+	bool i2c_high_speed;
+	u8 i2c_mcode;
 	unsigned long (*vsel_to_uv) (const u8 vsel);
 	u8 (*uv_to_vsel) (unsigned long uV);
 };
 
-/**
- * omap_vdd_info - Per Voltage Domain info
- *
- * @volt_data		: voltage table having the distinct voltages supported
- *			  by the domain and other associated per voltage data.
- * @pmic_info		: pmic specific parameters which should be populted by
- *			  the pmic drivers.
- * @vp_data		: the register values, shifts, masks for various
- *			  vp registers
- * @vp_rt_data          : VP data derived at runtime, not predefined
- * @vc_data		: structure containing various various vc registers,
- *			  shifts, masks etc.
- * @vfsm                : voltage manager FSM data
- * @voltdm		: pointer to the voltage domain structure
- * @debug_dir		: debug directory for this voltage domain.
- * @curr_volt		: current voltage for this vdd.
- * @vp_enabled		: flag to keep track of whether vp is enabled or not
- * @volt_scale		: API to scale the voltage of the vdd.
- */
-struct omap_vdd_info {
-	struct omap_volt_data *volt_data;
-	struct omap_volt_pmic_info *pmic_info;
-	struct omap_vp_instance_data *vp_data;
-	struct omap_vp_runtime_data vp_rt_data;
-	struct omap_vc_instance_data *vc_data;
-	const struct omap_vfsm_instance_data *vfsm;
-	struct voltagedomain voltdm;
-	struct dentry *debug_dir;
-	u32 curr_volt;
-	bool vp_enabled;
-	u32 (*read_reg) (u16 mod, u8 offset);
-	void (*write_reg) (u32 val, u16 mod, u8 offset);
-	int (*volt_scale) (struct omap_vdd_info *vdd,
-		unsigned long target_volt);
-};
-
-unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm);
-void omap_vp_enable(struct voltagedomain *voltdm);
-void omap_vp_disable(struct voltagedomain *voltdm);
-int omap_voltage_scale_vdd(struct voltagedomain *voltdm,
-		unsigned long target_volt);
-void omap_voltage_reset(struct voltagedomain *voltdm);
 void omap_voltage_get_volttable(struct voltagedomain *voltdm,
 		struct omap_volt_data **volt_data);
 struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
 		unsigned long volt);
-unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm);
-struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm);
-int __init omap_voltage_early_init(s16 prm_mod, s16 prm_irqst_mod,
-				   struct omap_vdd_info *omap_vdd_array[],
-				   u8 omap_vdd_count);
-#ifdef CONFIG_PM
 int omap_voltage_register_pmic(struct voltagedomain *voltdm,
-		struct omap_volt_pmic_info *pmic_info);
+			       struct omap_voltdm_pmic *pmic);
 void omap_change_voltscale_method(struct voltagedomain *voltdm,
 		int voltscale_method);
-/* API to get the voltagedomain pointer */
-struct voltagedomain *omap_voltage_domain_lookup(char *name);
-
 int omap_voltage_late_init(void);
-#else
-static inline int omap_voltage_register_pmic(struct voltagedomain *voltdm,
-		struct omap_volt_pmic_info *pmic_info)
-{
-	return -EINVAL;
-}
-static inline  void omap_change_voltscale_method(struct voltagedomain *voltdm,
-		int voltscale_method) {}
-static inline int omap_voltage_late_init(void)
-{
-	return -EINVAL;
-}
-static inline struct voltagedomain *omap_voltage_domain_lookup(char *name)
-{
-	return ERR_PTR(-EINVAL);
-}
-#endif
 
+extern void omap2xxx_voltagedomains_init(void);
+extern void omap3xxx_voltagedomains_init(void);
+extern void omap44xx_voltagedomains_init(void);
+
+struct voltagedomain *voltdm_lookup(const char *name);
+void voltdm_init(struct voltagedomain **voltdm_list);
+int voltdm_add_pwrdm(struct voltagedomain *voltdm, struct powerdomain *pwrdm);
+int voltdm_for_each(int (*fn)(struct voltagedomain *voltdm, void *user),
+		    void *user);
+int voltdm_for_each_pwrdm(struct voltagedomain *voltdm,
+			  int (*fn)(struct voltagedomain *voltdm,
+				    struct powerdomain *pwrdm));
+int voltdm_scale(struct voltagedomain *voltdm, unsigned long target_volt);
+void voltdm_reset(struct voltagedomain *voltdm);
+unsigned long voltdm_get_voltage(struct voltagedomain *voltdm);
 #endif
diff --git a/arch/arm/mach-omap2/voltagedomains2xxx_data.c b/arch/arm/mach-omap2/voltagedomains2xxx_data.c
new file mode 100644
index 0000000..7a41349
--- /dev/null
+++ b/arch/arm/mach-omap2/voltagedomains2xxx_data.c
@@ -0,0 +1,32 @@
+/*
+ * OMAP3 voltage domain data
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include "voltage.h"
+
+static struct voltagedomain omap2_voltdm_core = {
+	.name = "core",
+};
+
+static struct voltagedomain omap2_voltdm_wkup = {
+	.name = "wakeup",
+};
+
+static struct voltagedomain *voltagedomains_omap2[] __initdata = {
+	&omap2_voltdm_core,
+	&omap2_voltdm_wkup,
+	NULL,
+};
+
+void __init omap2xxx_voltagedomains_init(void)
+{
+	voltdm_init(voltagedomains_omap2);
+}
diff --git a/arch/arm/mach-omap2/voltagedomains3xxx_data.c b/arch/arm/mach-omap2/voltagedomains3xxx_data.c
index def230f..071101d 100644
--- a/arch/arm/mach-omap2/voltagedomains3xxx_data.c
+++ b/arch/arm/mach-omap2/voltagedomains3xxx_data.c
@@ -31,65 +31,70 @@
  * VDD data
  */
 
-static const struct omap_vfsm_instance_data omap3_vdd1_vfsm_data = {
+static const struct omap_vfsm_instance omap3_vdd1_vfsm = {
 	.voltsetup_reg = OMAP3_PRM_VOLTSETUP1_OFFSET,
-	.voltsetup_shift = OMAP3430_SETUP_TIME1_SHIFT,
 	.voltsetup_mask = OMAP3430_SETUP_TIME1_MASK,
 };
 
-static struct omap_vdd_info omap3_vdd1_info = {
-	.vp_data = &omap3_vp1_data,
-	.vc_data = &omap3_vc1_data,
-	.vfsm = &omap3_vdd1_vfsm_data,
-	.voltdm = {
-		.name = "mpu",
-	},
-};
-
-static const struct omap_vfsm_instance_data omap3_vdd2_vfsm_data = {
+static const struct omap_vfsm_instance omap3_vdd2_vfsm = {
 	.voltsetup_reg = OMAP3_PRM_VOLTSETUP1_OFFSET,
-	.voltsetup_shift = OMAP3430_SETUP_TIME2_SHIFT,
 	.voltsetup_mask = OMAP3430_SETUP_TIME2_MASK,
 };
 
-static struct omap_vdd_info omap3_vdd2_info = {
-	.vp_data = &omap3_vp2_data,
-	.vc_data = &omap3_vc2_data,
-	.vfsm = &omap3_vdd2_vfsm_data,
-	.voltdm = {
-		.name = "core",
-	},
+static struct voltagedomain omap3_voltdm_mpu = {
+	.name = "mpu_iva",
+	.scalable = true,
+	.read = omap3_prm_vcvp_read,
+	.write = omap3_prm_vcvp_write,
+	.rmw = omap3_prm_vcvp_rmw,
+	.vc = &omap3_vc_mpu,
+	.vfsm = &omap3_vdd1_vfsm,
+	.vp = &omap3_vp_mpu,
 };
 
-/* OMAP3 VDD structures */
-static struct omap_vdd_info *omap3_vdd_info[] = {
-	&omap3_vdd1_info,
-	&omap3_vdd2_info,
+static struct voltagedomain omap3_voltdm_core = {
+	.name = "core",
+	.scalable = true,
+	.read = omap3_prm_vcvp_read,
+	.write = omap3_prm_vcvp_write,
+	.rmw = omap3_prm_vcvp_rmw,
+	.vc = &omap3_vc_core,
+	.vfsm = &omap3_vdd2_vfsm,
+	.vp = &omap3_vp_core,
 };
 
-/* OMAP3 specific voltage init functions */
-static int __init omap3xxx_voltage_early_init(void)
-{
-	s16 prm_mod = OMAP3430_GR_MOD;
-	s16 prm_irqst_ocp_mod = OCP_MOD;
+static struct voltagedomain omap3_voltdm_wkup = {
+	.name = "wakeup",
+};
 
-	if (!cpu_is_omap34xx())
-		return 0;
+static struct voltagedomain *voltagedomains_omap3[] __initdata = {
+	&omap3_voltdm_mpu,
+	&omap3_voltdm_core,
+	&omap3_voltdm_wkup,
+	NULL,
+};
+
+static const char *sys_clk_name __initdata = "sys_ck";
+
+void __init omap3xxx_voltagedomains_init(void)
+{
+	struct voltagedomain *voltdm;
+	int i;
 
 	/*
 	 * XXX Will depend on the process, validation, and binning
 	 * for the currently-running IC
 	 */
 	if (cpu_is_omap3630()) {
-		omap3_vdd1_info.volt_data = omap36xx_vddmpu_volt_data;
-		omap3_vdd2_info.volt_data = omap36xx_vddcore_volt_data;
+		omap3_voltdm_mpu.volt_data = omap36xx_vddmpu_volt_data;
+		omap3_voltdm_core.volt_data = omap36xx_vddcore_volt_data;
 	} else {
-		omap3_vdd1_info.volt_data = omap34xx_vddmpu_volt_data;
-		omap3_vdd2_info.volt_data = omap34xx_vddcore_volt_data;
+		omap3_voltdm_mpu.volt_data = omap34xx_vddmpu_volt_data;
+		omap3_voltdm_core.volt_data = omap34xx_vddcore_volt_data;
 	}
 
-	return omap_voltage_early_init(prm_mod, prm_irqst_ocp_mod,
-				       omap3_vdd_info,
-				       ARRAY_SIZE(omap3_vdd_info));
+	for (i = 0; voltdm = voltagedomains_omap3[i], voltdm; i++)
+		voltdm->sys_clk.name = sys_clk_name;
+
+	voltdm_init(voltagedomains_omap3);
 };
-core_initcall(omap3xxx_voltage_early_init);
diff --git a/arch/arm/mach-omap2/voltagedomains44xx_data.c b/arch/arm/mach-omap2/voltagedomains44xx_data.c
index cb64996..c4584e9 100644
--- a/arch/arm/mach-omap2/voltagedomains44xx_data.c
+++ b/arch/arm/mach-omap2/voltagedomains44xx_data.c
@@ -32,71 +32,80 @@
 #include "vc.h"
 #include "vp.h"
 
-static const struct omap_vfsm_instance_data omap4_vdd_mpu_vfsm_data = {
+static const struct omap_vfsm_instance omap4_vdd_mpu_vfsm = {
 	.voltsetup_reg = OMAP4_PRM_VOLTSETUP_MPU_RET_SLEEP_OFFSET,
 };
 
-static struct omap_vdd_info omap4_vdd_mpu_info = {
-	.vp_data = &omap4_vp_mpu_data,
-	.vc_data = &omap4_vc_mpu_data,
-	.vfsm = &omap4_vdd_mpu_vfsm_data,
-	.voltdm = {
-		.name = "mpu",
-	},
+static const struct omap_vfsm_instance omap4_vdd_iva_vfsm = {
+	.voltsetup_reg = OMAP4_PRM_VOLTSETUP_IVA_RET_SLEEP_OFFSET,
 };
 
-static const struct omap_vfsm_instance_data omap4_vdd_iva_vfsm_data = {
-	.voltsetup_reg = OMAP4_PRM_VOLTSETUP_IVA_RET_SLEEP_OFFSET,
+static const struct omap_vfsm_instance omap4_vdd_core_vfsm = {
+	.voltsetup_reg = OMAP4_PRM_VOLTSETUP_CORE_RET_SLEEP_OFFSET,
 };
 
-static struct omap_vdd_info omap4_vdd_iva_info = {
-	.vp_data = &omap4_vp_iva_data,
-	.vc_data = &omap4_vc_iva_data,
-	.vfsm = &omap4_vdd_iva_vfsm_data,
-	.voltdm = {
-		.name = "iva",
-	},
+static struct voltagedomain omap4_voltdm_mpu = {
+	.name = "mpu",
+	.scalable = true,
+	.read = omap4_prm_vcvp_read,
+	.write = omap4_prm_vcvp_write,
+	.rmw = omap4_prm_vcvp_rmw,
+	.vc = &omap4_vc_mpu,
+	.vfsm = &omap4_vdd_mpu_vfsm,
+	.vp = &omap4_vp_mpu,
 };
 
-static const struct omap_vfsm_instance_data omap4_vdd_core_vfsm_data = {
-	.voltsetup_reg = OMAP4_PRM_VOLTSETUP_CORE_RET_SLEEP_OFFSET,
+static struct voltagedomain omap4_voltdm_iva = {
+	.name = "iva",
+	.scalable = true,
+	.read = omap4_prm_vcvp_read,
+	.write = omap4_prm_vcvp_write,
+	.rmw = omap4_prm_vcvp_rmw,
+	.vc = &omap4_vc_iva,
+	.vfsm = &omap4_vdd_iva_vfsm,
+	.vp = &omap4_vp_iva,
 };
 
-static struct omap_vdd_info omap4_vdd_core_info = {
-	.vp_data = &omap4_vp_core_data,
-	.vc_data = &omap4_vc_core_data,
-	.vfsm = &omap4_vdd_core_vfsm_data,
-	.voltdm = {
-		.name = "core",
-	},
+static struct voltagedomain omap4_voltdm_core = {
+	.name = "core",
+	.scalable = true,
+	.read = omap4_prm_vcvp_read,
+	.write = omap4_prm_vcvp_write,
+	.rmw = omap4_prm_vcvp_rmw,
+	.vc = &omap4_vc_core,
+	.vfsm = &omap4_vdd_core_vfsm,
+	.vp = &omap4_vp_core,
 };
 
-/* OMAP4 VDD structures */
-static struct omap_vdd_info *omap4_vdd_info[] = {
-	&omap4_vdd_mpu_info,
-	&omap4_vdd_iva_info,
-	&omap4_vdd_core_info,
+static struct voltagedomain omap4_voltdm_wkup = {
+	.name = "wakeup",
 };
 
-/* OMAP4 specific voltage init functions */
-static int __init omap44xx_voltage_early_init(void)
-{
-	s16 prm_mod = OMAP4430_PRM_DEVICE_INST;
-	s16 prm_irqst_ocp_mod = OMAP4430_PRM_OCP_SOCKET_INST;
+static struct voltagedomain *voltagedomains_omap4[] __initdata = {
+	&omap4_voltdm_mpu,
+	&omap4_voltdm_iva,
+	&omap4_voltdm_core,
+	&omap4_voltdm_wkup,
+	NULL,
+};
+
+static const char *sys_clk_name __initdata = "sys_clkin_ck";
 
-	if (!cpu_is_omap44xx())
-		return 0;
+void __init omap44xx_voltagedomains_init(void)
+{
+	struct voltagedomain *voltdm;
+	int i;
 
 	/*
 	 * XXX Will depend on the process, validation, and binning
 	 * for the currently-running IC
 	 */
-	omap4_vdd_mpu_info.volt_data = omap44xx_vdd_mpu_volt_data;
-	omap4_vdd_iva_info.volt_data = omap44xx_vdd_iva_volt_data;
-	omap4_vdd_core_info.volt_data = omap44xx_vdd_core_volt_data;
+	omap4_voltdm_mpu.volt_data = omap44xx_vdd_mpu_volt_data;
+	omap4_voltdm_iva.volt_data = omap44xx_vdd_iva_volt_data;
+	omap4_voltdm_core.volt_data = omap44xx_vdd_core_volt_data;
+
+	for (i = 0; voltdm = voltagedomains_omap4[i], voltdm; i++)
+		voltdm->sys_clk.name = sys_clk_name;
 
-	return omap_voltage_early_init(prm_mod, prm_irqst_ocp_mod,
-				       omap4_vdd_info,
-				       ARRAY_SIZE(omap4_vdd_info));
+	voltdm_init(voltagedomains_omap4);
 };
-core_initcall(omap44xx_voltage_early_init);
diff --git a/arch/arm/mach-omap2/vp.c b/arch/arm/mach-omap2/vp.c
new file mode 100644
index 0000000..66bd700
--- /dev/null
+++ b/arch/arm/mach-omap2/vp.c
@@ -0,0 +1,278 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <plat/common.h>
+
+#include "voltage.h"
+#include "vp.h"
+#include "prm-regbits-34xx.h"
+#include "prm-regbits-44xx.h"
+#include "prm44xx.h"
+
+static u32 _vp_set_init_voltage(struct voltagedomain *voltdm, u32 volt)
+{
+	struct omap_vp_instance *vp = voltdm->vp;
+	u32 vpconfig;
+	char vsel;
+
+	vsel = voltdm->pmic->uv_to_vsel(volt);
+
+	vpconfig = voltdm->read(vp->vpconfig);
+	vpconfig &= ~(vp->common->vpconfig_initvoltage_mask |
+		      vp->common->vpconfig_forceupdate |
+		      vp->common->vpconfig_initvdd);
+	vpconfig |= vsel << __ffs(vp->common->vpconfig_initvoltage_mask);
+	voltdm->write(vpconfig, vp->vpconfig);
+
+	/* Trigger initVDD value copy to voltage processor */
+	voltdm->write((vpconfig | vp->common->vpconfig_initvdd),
+		       vp->vpconfig);
+
+	/* Clear initVDD copy trigger bit */
+	voltdm->write(vpconfig, vp->vpconfig);
+
+	return vpconfig;
+}
+
+/* Generic voltage init functions */
+void __init omap_vp_init(struct voltagedomain *voltdm)
+{
+	struct omap_vp_instance *vp = voltdm->vp;
+	u32 val, sys_clk_rate, timeout, waittime;
+	u32 vddmin, vddmax, vstepmin, vstepmax;
+
+	if (!voltdm->read || !voltdm->write) {
+		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
+			__func__, voltdm->name);
+		return;
+	}
+
+	vp->enabled = false;
+
+	/* Divide to avoid overflow */
+	sys_clk_rate = voltdm->sys_clk.rate / 1000;
+
+	timeout = (sys_clk_rate * voltdm->pmic->vp_timeout_us) / 1000;
+	vddmin = voltdm->pmic->vp_vddmin;
+	vddmax = voltdm->pmic->vp_vddmax;
+
+	waittime = ((voltdm->pmic->step_size / voltdm->pmic->slew_rate) *
+		    sys_clk_rate) / 1000;
+	vstepmin = voltdm->pmic->vp_vstepmin;
+	vstepmax = voltdm->pmic->vp_vstepmax;
+
+	/*
+	 * VP_CONFIG: error gain is not set here, it will be updated
+	 * on each scale, based on OPP.
+	 */
+	val = (voltdm->pmic->vp_erroroffset <<
+	       __ffs(voltdm->vp->common->vpconfig_erroroffset_mask)) |
+		vp->common->vpconfig_timeouten;
+	voltdm->write(val, vp->vpconfig);
+
+	/* VSTEPMIN */
+	val = (waittime << vp->common->vstepmin_smpswaittimemin_shift) |
+		(vstepmin <<  vp->common->vstepmin_stepmin_shift);
+	voltdm->write(val, vp->vstepmin);
+
+	/* VSTEPMAX */
+	val = (vstepmax << vp->common->vstepmax_stepmax_shift) |
+		(waittime << vp->common->vstepmax_smpswaittimemax_shift);
+	voltdm->write(val, vp->vstepmax);
+
+	/* VLIMITTO */
+	val = (vddmax << vp->common->vlimitto_vddmax_shift) |
+		(vddmin << vp->common->vlimitto_vddmin_shift) |
+		(timeout <<  vp->common->vlimitto_timeout_shift);
+	voltdm->write(val, vp->vlimitto);
+}
+
+int omap_vp_update_errorgain(struct voltagedomain *voltdm,
+			     unsigned long target_volt)
+{
+	struct omap_volt_data *volt_data;
+
+	if (!voltdm->vp)
+		return -EINVAL;
+
+	/* Get volt_data corresponding to target_volt */
+	volt_data = omap_voltage_get_voltdata(voltdm, target_volt);
+	if (IS_ERR(volt_data))
+		return -EINVAL;
+
+	/* Setting vp errorgain based on the voltage */
+	voltdm->rmw(voltdm->vp->common->vpconfig_errorgain_mask,
+		    volt_data->vp_errgain <<
+		    __ffs(voltdm->vp->common->vpconfig_errorgain_mask),
+		    voltdm->vp->vpconfig);
+
+	return 0;
+}
+
+/* VP force update method of voltage scaling */
+int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
+			      unsigned long target_volt)
+{
+	struct omap_vp_instance *vp = voltdm->vp;
+	u32 vpconfig;
+	u8 target_vsel, current_vsel;
+	int ret, timeout = 0;
+
+	ret = omap_vc_pre_scale(voltdm, target_volt, &target_vsel, &current_vsel);
+	if (ret)
+		return ret;
+
+	/*
+	 * Clear all pending TransactionDone interrupt/status. Typical latency
+	 * is <3us
+	 */
+	while (timeout++ < VP_TRANXDONE_TIMEOUT) {
+		vp->common->ops->clear_txdone(vp->id);
+		if (!vp->common->ops->check_txdone(vp->id))
+			break;
+		udelay(1);
+	}
+	if (timeout >= VP_TRANXDONE_TIMEOUT) {
+		pr_warning("%s: vdd_%s TRANXDONE timeout exceeded."
+			"Voltage change aborted", __func__, voltdm->name);
+		return -ETIMEDOUT;
+	}
+
+	vpconfig = _vp_set_init_voltage(voltdm, target_volt);
+
+	/* Force update of voltage */
+	voltdm->write(vpconfig | vp->common->vpconfig_forceupdate,
+		      voltdm->vp->vpconfig);
+
+	/*
+	 * Wait for TransactionDone. Typical latency is <200us.
+	 * Depends on SMPSWAITTIMEMIN/MAX and voltage change
+	 */
+	timeout = 0;
+	omap_test_timeout(vp->common->ops->check_txdone(vp->id),
+			  VP_TRANXDONE_TIMEOUT, timeout);
+	if (timeout >= VP_TRANXDONE_TIMEOUT)
+		pr_err("%s: vdd_%s TRANXDONE timeout exceeded."
+			"TRANXDONE never got set after the voltage update\n",
+			__func__, voltdm->name);
+
+	omap_vc_post_scale(voltdm, target_volt, target_vsel, current_vsel);
+
+	/*
+	 * Disable TransactionDone interrupt , clear all status, clear
+	 * control registers
+	 */
+	timeout = 0;
+	while (timeout++ < VP_TRANXDONE_TIMEOUT) {
+		vp->common->ops->clear_txdone(vp->id);
+		if (!vp->common->ops->check_txdone(vp->id))
+			break;
+		udelay(1);
+	}
+
+	if (timeout >= VP_TRANXDONE_TIMEOUT)
+		pr_warning("%s: vdd_%s TRANXDONE timeout exceeded while trying"
+			"to clear the TRANXDONE status\n",
+			__func__, voltdm->name);
+
+	/* Clear force bit */
+	voltdm->write(vpconfig, vp->vpconfig);
+
+	return 0;
+}
+
+/**
+ * omap_vp_enable() - API to enable a particular VP
+ * @voltdm:	pointer to the VDD whose VP is to be enabled.
+ *
+ * This API enables a particular voltage processor. Needed by the smartreflex
+ * class drivers.
+ */
+void omap_vp_enable(struct voltagedomain *voltdm)
+{
+	struct omap_vp_instance *vp;
+	u32 vpconfig, volt;
+
+	if (!voltdm || IS_ERR(voltdm)) {
+		pr_warning("%s: VDD specified does not exist!\n", __func__);
+		return;
+	}
+
+	vp = voltdm->vp;
+	if (!voltdm->read || !voltdm->write) {
+		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
+			__func__, voltdm->name);
+		return;
+	}
+
+	/* If VP is already enabled, do nothing. Return */
+	if (vp->enabled)
+		return;
+
+	volt = voltdm_get_voltage(voltdm);
+	if (!volt) {
+		pr_warning("%s: unable to find current voltage for %s\n",
+			   __func__, voltdm->name);
+		return;
+	}
+
+	vpconfig = _vp_set_init_voltage(voltdm, volt);
+
+	/* Enable VP */
+	vpconfig |= vp->common->vpconfig_vpenable;
+	voltdm->write(vpconfig, vp->vpconfig);
+
+	vp->enabled = true;
+}
+
+/**
+ * omap_vp_disable() - API to disable a particular VP
+ * @voltdm:	pointer to the VDD whose VP is to be disabled.
+ *
+ * This API disables a particular voltage processor. Needed by the smartreflex
+ * class drivers.
+ */
+void omap_vp_disable(struct voltagedomain *voltdm)
+{
+	struct omap_vp_instance *vp;
+	u32 vpconfig;
+	int timeout;
+
+	if (!voltdm || IS_ERR(voltdm)) {
+		pr_warning("%s: VDD specified does not exist!\n", __func__);
+		return;
+	}
+
+	vp = voltdm->vp;
+	if (!voltdm->read || !voltdm->write) {
+		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
+			__func__, voltdm->name);
+		return;
+	}
+
+	/* If VP is already disabled, do nothing. Return */
+	if (!vp->enabled) {
+		pr_warning("%s: Trying to disable VP for vdd_%s when"
+			"it is already disabled\n", __func__, voltdm->name);
+		return;
+	}
+
+	/* Disable VP */
+	vpconfig = voltdm->read(vp->vpconfig);
+	vpconfig &= ~vp->common->vpconfig_vpenable;
+	voltdm->write(vpconfig, vp->vpconfig);
+
+	/*
+	 * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us
+	 */
+	omap_test_timeout((voltdm->read(vp->vstatus)),
+			  VP_IDLE_TIMEOUT, timeout);
+
+	if (timeout >= VP_IDLE_TIMEOUT)
+		pr_warning("%s: vdd_%s idle timedout\n",
+			__func__, voltdm->name);
+
+	vp->enabled = false;
+
+	return;
+}
diff --git a/arch/arm/mach-omap2/vp.h b/arch/arm/mach-omap2/vp.h
index 7ce134f..7c155d2 100644
--- a/arch/arm/mach-omap2/vp.h
+++ b/arch/arm/mach-omap2/vp.h
@@ -19,44 +19,60 @@
 
 #include <linux/kernel.h>
 
+struct voltagedomain;
+
+/*
+ * Voltage Processor (VP) identifiers
+ */
+#define OMAP3_VP_VDD_MPU_ID 0
+#define OMAP3_VP_VDD_CORE_ID 1
+#define OMAP4_VP_VDD_CORE_ID 0
+#define OMAP4_VP_VDD_IVA_ID 1
+#define OMAP4_VP_VDD_MPU_ID 2
+
 /* XXX document */
 #define VP_IDLE_TIMEOUT		200
 #define VP_TRANXDONE_TIMEOUT	300
 
+/**
+ * struct omap_vp_ops - per-VP operations
+ * @check_txdone: check for VP transaction done
+ * @clear_txdone: clear VP transaction done status
+ */
+struct omap_vp_ops {
+	u32 (*check_txdone)(u8 vp_id);
+	void (*clear_txdone)(u8 vp_id);
+};
 
 /**
- * struct omap_vp_common_data - register data common to all VDDs
+ * struct omap_vp_common - register data common to all VDDs
+ * @vpconfig_erroroffset_mask: ERROROFFSET bitmask in the PRM_VP*_CONFIG reg
  * @vpconfig_errorgain_mask: ERRORGAIN bitmask in the PRM_VP*_CONFIG reg
  * @vpconfig_initvoltage_mask: INITVOLTAGE bitmask in the PRM_VP*_CONFIG reg
- * @vpconfig_timeouten_mask: TIMEOUT bitmask in the PRM_VP*_CONFIG reg
+ * @vpconfig_timeouten: TIMEOUT bitmask in the PRM_VP*_CONFIG reg
  * @vpconfig_initvdd: INITVDD bitmask in the PRM_VP*_CONFIG reg
  * @vpconfig_forceupdate: FORCEUPDATE bitmask in the PRM_VP*_CONFIG reg
  * @vpconfig_vpenable: VPENABLE bitmask in the PRM_VP*_CONFIG reg
  * @vpconfig_erroroffset_shift: ERROROFFSET field shift in PRM_VP*_CONFIG reg
  * @vpconfig_errorgain_shift: ERRORGAIN field shift in PRM_VP*_CONFIG reg
  * @vpconfig_initvoltage_shift: INITVOLTAGE field shift in PRM_VP*_CONFIG reg
- * @vpconfig_stepmin_shift: VSTEPMIN field shift in the PRM_VP*_VSTEPMIN reg
- * @vpconfig_smpswaittimemin_shift: SMPSWAITTIMEMIN field shift in PRM_VP*_VSTEPMIN reg
- * @vpconfig_stepmax_shift: VSTEPMAX field shift in the PRM_VP*_VSTEPMAX reg
- * @vpconfig_smpswaittimemax_shift: SMPSWAITTIMEMAX field shift in PRM_VP*_VSTEPMAX reg
- * @vpconfig_vlimitto_vddmin_shift: VDDMIN field shift in PRM_VP*_VLIMITTO reg
- * @vpconfig_vlimitto_vddmax_shift: VDDMAX field shift in PRM_VP*_VLIMITTO reg
- * @vpconfig_vlimitto_timeout_shift: TIMEOUT field shift in PRM_VP*_VLIMITTO reg
- *
- * XXX It it not necessary to have both a mask and a shift for the same
- *     bitfield - remove one
- * XXX Many of these fields are wrongly named -- e.g., vpconfig_smps* -- fix!
+ * @vstepmin_stepmin_shift: VSTEPMIN field shift in the PRM_VP*_VSTEPMIN reg
+ * @vstepmin_smpswaittimemin_shift: SMPSWAITTIMEMIN field shift in PRM_VP*_VSTEPMIN reg
+ * @vstepmax_stepmax_shift: VSTEPMAX field shift in the PRM_VP*_VSTEPMAX reg
+ * @vstepmax_smpswaittimemax_shift: SMPSWAITTIMEMAX field shift in PRM_VP*_VSTEPMAX reg
+ * @vlimitto_vddmin_shift: VDDMIN field shift in PRM_VP*_VLIMITTO reg
+ * @vlimitto_vddmax_shift: VDDMAX field shift in PRM_VP*_VLIMITTO reg
+ * @vlimitto_timeout_shift: TIMEOUT field shift in PRM_VP*_VLIMITTO reg
+ * @vpvoltage_mask: VPVOLTAGE field mask in PRM_VP*_VOLTAGE reg
  */
-struct omap_vp_common_data {
+struct omap_vp_common {
+	u32 vpconfig_erroroffset_mask;
 	u32 vpconfig_errorgain_mask;
 	u32 vpconfig_initvoltage_mask;
-	u32 vpconfig_timeouten;
-	u32 vpconfig_initvdd;
-	u32 vpconfig_forceupdate;
-	u32 vpconfig_vpenable;
-	u8 vpconfig_erroroffset_shift;
-	u8 vpconfig_errorgain_shift;
-	u8 vpconfig_initvoltage_shift;
+	u8 vpconfig_timeouten;
+	u8 vpconfig_initvdd;
+	u8 vpconfig_forceupdate;
+	u8 vpconfig_vpenable;
 	u8 vstepmin_stepmin_shift;
 	u8 vstepmin_smpswaittimemin_shift;
 	u8 vstepmax_stepmax_shift;
@@ -64,80 +80,49 @@ struct omap_vp_common_data {
 	u8 vlimitto_vddmin_shift;
 	u8 vlimitto_vddmax_shift;
 	u8 vlimitto_timeout_shift;
-};
+	u8 vpvoltage_mask;
 
-/**
- * struct omap_vp_prm_irqst_data - PRM_IRQSTATUS_MPU.VP_TRANXDONE_ST data
- * @prm_irqst_reg: reg offset for PRM_IRQSTATUS_MPU from top of PRM
- * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg
- *
- * XXX prm_irqst_reg does not belong here
- * XXX Note that on OMAP3, VP_TRANXDONE interrupt may not work due to a
- *     hardware bug
- * XXX This structure is probably not needed
- */
-struct omap_vp_prm_irqst_data {
-	u8 prm_irqst_reg;
-	u32 tranxdone_status;
+	const struct omap_vp_ops *ops;
 };
 
 /**
- * struct omap_vp_instance_data - VP register offsets (per-VDD)
- * @vp_common: pointer to struct omap_vp_common_data * for this SoC
- * @prm_irqst_data: pointer to struct omap_vp_prm_irqst_data for this VDD
+ * struct omap_vp_instance - VP register offsets (per-VDD)
+ * @common: pointer to struct omap_vp_common * for this SoC
  * @vpconfig: PRM_VP*_CONFIG reg offset from PRM start
  * @vstepmin: PRM_VP*_VSTEPMIN reg offset from PRM start
  * @vlimitto: PRM_VP*_VLIMITTO reg offset from PRM start
  * @vstatus: PRM_VP*_VSTATUS reg offset from PRM start
  * @voltage: PRM_VP*_VOLTAGE reg offset from PRM start
+ * @id: Unique identifier for VP instance.
+ * @enabled: flag to keep track of whether vp is enabled or not
  *
  * XXX vp_common is probably not needed since it is per-SoC
  */
-struct omap_vp_instance_data {
-	const struct omap_vp_common_data *vp_common;
-	const struct omap_vp_prm_irqst_data *prm_irqst_data;
+struct omap_vp_instance {
+	const struct omap_vp_common *common;
 	u8 vpconfig;
 	u8 vstepmin;
 	u8 vstepmax;
 	u8 vlimitto;
 	u8 vstatus;
 	u8 voltage;
+	u8 id;
+	bool enabled;
 };
 
-/**
- * struct omap_vp_runtime_data - VP data populated at runtime by code
- * @vpconfig_erroroffset: value of ERROROFFSET bitfield in PRM_VP*_CONFIG
- * @vpconfig_errorgain: value of ERRORGAIN bitfield in PRM_VP*_CONFIG
- * @vstepmin_smpswaittimemin: value of SMPSWAITTIMEMIN bitfield in PRM_VP*_VSTEPMIN
- * @vstepmax_smpswaittimemax: value of SMPSWAITTIMEMAX bitfield in PRM_VP*_VSTEPMAX
- * @vlimitto_timeout: value of TIMEOUT bitfield in PRM_VP*_VLIMITTO
- * @vstepmin_stepmin: value of VSTEPMIN bitfield in PRM_VP*_VSTEPMIN
- * @vstepmax_stepmax: value of VSTEPMAX bitfield in PRM_VP*_VSTEPMAX
- * @vlimitto_vddmin: value of VDDMIN bitfield in PRM_VP*_VLIMITTO
- * @vlimitto_vddmax: value of VDDMAX bitfield in PRM_VP*_VLIMITTO
- *
- * XXX Is this structure really needed?  Why not just program the
- * device directly?  They are in PRM space, therefore in the WKUP
- * powerdomain, so register contents should not be lost in off-mode.
- * XXX Some of these fields are incorrectly named, e.g., vstep*
- */
-struct omap_vp_runtime_data {
-	u32 vpconfig_erroroffset;
-	u16 vpconfig_errorgain;
-	u16 vstepmin_smpswaittimemin;
-	u16 vstepmax_smpswaittimemax;
-	u16 vlimitto_timeout;
-	u8 vstepmin_stepmin;
-	u8 vstepmax_stepmax;
-	u8 vlimitto_vddmin;
-	u8 vlimitto_vddmax;
-};
+extern struct omap_vp_instance omap3_vp_mpu;
+extern struct omap_vp_instance omap3_vp_core;
 
-extern struct omap_vp_instance_data omap3_vp1_data;
-extern struct omap_vp_instance_data omap3_vp2_data;
+extern struct omap_vp_instance omap4_vp_mpu;
+extern struct omap_vp_instance omap4_vp_iva;
+extern struct omap_vp_instance omap4_vp_core;
 
-extern struct omap_vp_instance_data omap4_vp_mpu_data;
-extern struct omap_vp_instance_data omap4_vp_iva_data;
-extern struct omap_vp_instance_data omap4_vp_core_data;
+void omap_vp_init(struct voltagedomain *voltdm);
+void omap_vp_enable(struct voltagedomain *voltdm);
+void omap_vp_disable(struct voltagedomain *voltdm);
+int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
+			      unsigned long target_volt);
+int omap_vp_update_errorgain(struct voltagedomain *voltdm,
+			     unsigned long target_volt);
 
 #endif
diff --git a/arch/arm/mach-omap2/vp3xxx_data.c b/arch/arm/mach-omap2/vp3xxx_data.c
index 6452170..260c554 100644
--- a/arch/arm/mach-omap2/vp3xxx_data.c
+++ b/arch/arm/mach-omap2/vp3xxx_data.c
@@ -25,16 +25,20 @@
 #include "voltage.h"
 
 #include "vp.h"
+#include "prm2xxx_3xxx.h"
+
+static const struct omap_vp_ops omap3_vp_ops = {
+	.check_txdone = omap3_prm_vp_check_txdone,
+	.clear_txdone = omap3_prm_vp_clear_txdone,
+};
 
 /*
  * VP data common to 34xx/36xx chips
  * XXX This stuff presumably belongs in the vp3xxx.c or vp.c file.
  */
-static const struct omap_vp_common_data omap3_vp_common = {
-	.vpconfig_erroroffset_shift = OMAP3430_ERROROFFSET_SHIFT,
+static const struct omap_vp_common omap3_vp_common = {
+	.vpconfig_erroroffset_mask = OMAP3430_ERROROFFSET_MASK,
 	.vpconfig_errorgain_mask = OMAP3430_ERRORGAIN_MASK,
-	.vpconfig_errorgain_shift = OMAP3430_ERRORGAIN_SHIFT,
-	.vpconfig_initvoltage_shift = OMAP3430_INITVOLTAGE_SHIFT,
 	.vpconfig_initvoltage_mask = OMAP3430_INITVOLTAGE_MASK,
 	.vpconfig_timeouten = OMAP3430_TIMEOUTEN_MASK,
 	.vpconfig_initvdd = OMAP3430_INITVDD_MASK,
@@ -47,36 +51,29 @@ static const struct omap_vp_common_data omap3_vp_common = {
 	.vlimitto_vddmin_shift = OMAP3430_VDDMIN_SHIFT,
 	.vlimitto_vddmax_shift = OMAP3430_VDDMAX_SHIFT,
 	.vlimitto_timeout_shift = OMAP3430_TIMEOUT_SHIFT,
-};
+	.vpvoltage_mask = OMAP3430_VPVOLTAGE_MASK,
 
-static const struct omap_vp_prm_irqst_data omap3_vp1_prm_irqst_data = {
-	.prm_irqst_reg = OMAP3_PRM_IRQSTATUS_MPU_OFFSET,
-	.tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK,
+	.ops = &omap3_vp_ops,
 };
 
-struct omap_vp_instance_data omap3_vp1_data = {
-	.vp_common = &omap3_vp_common,
+struct omap_vp_instance omap3_vp_mpu = {
+	.id = OMAP3_VP_VDD_MPU_ID,
+	.common = &omap3_vp_common,
 	.vpconfig = OMAP3_PRM_VP1_CONFIG_OFFSET,
 	.vstepmin = OMAP3_PRM_VP1_VSTEPMIN_OFFSET,
 	.vstepmax = OMAP3_PRM_VP1_VSTEPMAX_OFFSET,
 	.vlimitto = OMAP3_PRM_VP1_VLIMITTO_OFFSET,
 	.vstatus = OMAP3_PRM_VP1_STATUS_OFFSET,
 	.voltage = OMAP3_PRM_VP1_VOLTAGE_OFFSET,
-	.prm_irqst_data = &omap3_vp1_prm_irqst_data,
-};
-
-static const struct omap_vp_prm_irqst_data omap3_vp2_prm_irqst_data = {
-	.prm_irqst_reg = OMAP3_PRM_IRQSTATUS_MPU_OFFSET,
-	.tranxdone_status = OMAP3430_VP2_TRANXDONE_ST_MASK,
 };
 
-struct omap_vp_instance_data omap3_vp2_data = {
-	.vp_common = &omap3_vp_common,
+struct omap_vp_instance omap3_vp_core = {
+	.id = OMAP3_VP_VDD_CORE_ID,
+	.common = &omap3_vp_common,
 	.vpconfig = OMAP3_PRM_VP2_CONFIG_OFFSET,
 	.vstepmin = OMAP3_PRM_VP2_VSTEPMIN_OFFSET,
 	.vstepmax = OMAP3_PRM_VP2_VSTEPMAX_OFFSET,
 	.vlimitto = OMAP3_PRM_VP2_VLIMITTO_OFFSET,
 	.vstatus = OMAP3_PRM_VP2_STATUS_OFFSET,
 	.voltage = OMAP3_PRM_VP2_VOLTAGE_OFFSET,
-	.prm_irqst_data = &omap3_vp2_prm_irqst_data,
 };
diff --git a/arch/arm/mach-omap2/vp44xx_data.c b/arch/arm/mach-omap2/vp44xx_data.c
index 65d1ad6..b4e7704 100644
--- a/arch/arm/mach-omap2/vp44xx_data.c
+++ b/arch/arm/mach-omap2/vp44xx_data.c
@@ -27,15 +27,18 @@
 
 #include "vp.h"
 
+static const struct omap_vp_ops omap4_vp_ops = {
+	.check_txdone = omap4_prm_vp_check_txdone,
+	.clear_txdone = omap4_prm_vp_clear_txdone,
+};
+
 /*
  * VP data common to 44xx chips
  * XXX This stuff presumably belongs in the vp44xx.c or vp.c file.
  */
-static const struct omap_vp_common_data omap4_vp_common = {
-	.vpconfig_erroroffset_shift = OMAP4430_ERROROFFSET_SHIFT,
+static const struct omap_vp_common omap4_vp_common = {
+	.vpconfig_erroroffset_mask = OMAP4430_ERROROFFSET_MASK,
 	.vpconfig_errorgain_mask = OMAP4430_ERRORGAIN_MASK,
-	.vpconfig_errorgain_shift = OMAP4430_ERRORGAIN_SHIFT,
-	.vpconfig_initvoltage_shift = OMAP4430_INITVOLTAGE_SHIFT,
 	.vpconfig_initvoltage_mask = OMAP4430_INITVOLTAGE_MASK,
 	.vpconfig_timeouten = OMAP4430_TIMEOUTEN_MASK,
 	.vpconfig_initvdd = OMAP4430_INITVDD_MASK,
@@ -48,53 +51,39 @@ static const struct omap_vp_common_data omap4_vp_common = {
 	.vlimitto_vddmin_shift = OMAP4430_VDDMIN_SHIFT,
 	.vlimitto_vddmax_shift = OMAP4430_VDDMAX_SHIFT,
 	.vlimitto_timeout_shift = OMAP4430_TIMEOUT_SHIFT,
+	.vpvoltage_mask = OMAP4430_VPVOLTAGE_MASK,
+	.ops = &omap4_vp_ops,
 };
 
-static const struct omap_vp_prm_irqst_data omap4_vp_mpu_prm_irqst_data = {
-	.prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET,
-	.tranxdone_status = OMAP4430_VP_MPU_TRANXDONE_ST_MASK,
-};
-
-struct omap_vp_instance_data omap4_vp_mpu_data = {
-	.vp_common = &omap4_vp_common,
+struct omap_vp_instance omap4_vp_mpu = {
+	.id = OMAP4_VP_VDD_MPU_ID,
+	.common = &omap4_vp_common,
 	.vpconfig = OMAP4_PRM_VP_MPU_CONFIG_OFFSET,
 	.vstepmin = OMAP4_PRM_VP_MPU_VSTEPMIN_OFFSET,
 	.vstepmax = OMAP4_PRM_VP_MPU_VSTEPMAX_OFFSET,
 	.vlimitto = OMAP4_PRM_VP_MPU_VLIMITTO_OFFSET,
 	.vstatus = OMAP4_PRM_VP_MPU_STATUS_OFFSET,
 	.voltage = OMAP4_PRM_VP_MPU_VOLTAGE_OFFSET,
-	.prm_irqst_data = &omap4_vp_mpu_prm_irqst_data,
 };
 
-static const struct omap_vp_prm_irqst_data omap4_vp_iva_prm_irqst_data = {
-	.prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
-	.tranxdone_status = OMAP4430_VP_IVA_TRANXDONE_ST_MASK,
-};
-
-struct omap_vp_instance_data omap4_vp_iva_data = {
-	.vp_common = &omap4_vp_common,
+struct omap_vp_instance omap4_vp_iva = {
+	.id = OMAP4_VP_VDD_IVA_ID,
+	.common = &omap4_vp_common,
 	.vpconfig = OMAP4_PRM_VP_IVA_CONFIG_OFFSET,
 	.vstepmin = OMAP4_PRM_VP_IVA_VSTEPMIN_OFFSET,
 	.vstepmax = OMAP4_PRM_VP_IVA_VSTEPMAX_OFFSET,
 	.vlimitto = OMAP4_PRM_VP_IVA_VLIMITTO_OFFSET,
 	.vstatus = OMAP4_PRM_VP_IVA_STATUS_OFFSET,
 	.voltage = OMAP4_PRM_VP_IVA_VOLTAGE_OFFSET,
-	.prm_irqst_data = &omap4_vp_iva_prm_irqst_data,
-};
-
-static const struct omap_vp_prm_irqst_data omap4_vp_core_prm_irqst_data = {
-	.prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
-	.tranxdone_status = OMAP4430_VP_CORE_TRANXDONE_ST_MASK,
 };
 
-struct omap_vp_instance_data omap4_vp_core_data = {
-	.vp_common = &omap4_vp_common,
+struct omap_vp_instance omap4_vp_core = {
+	.id = OMAP4_VP_VDD_CORE_ID,
+	.common = &omap4_vp_common,
 	.vpconfig = OMAP4_PRM_VP_CORE_CONFIG_OFFSET,
 	.vstepmin = OMAP4_PRM_VP_CORE_VSTEPMIN_OFFSET,
 	.vstepmax = OMAP4_PRM_VP_CORE_VSTEPMAX_OFFSET,
 	.vlimitto = OMAP4_PRM_VP_CORE_VLIMITTO_OFFSET,
 	.vstatus = OMAP4_PRM_VP_CORE_STATUS_OFFSET,
 	.voltage = OMAP4_PRM_VP_CORE_VOLTAGE_OFFSET,
-	.prm_irqst_data = &omap4_vp_core_prm_irqst_data,
 };
-
diff --git a/arch/arm/mach-picoxcell/Makefile b/arch/arm/mach-picoxcell/Makefile
new file mode 100644
index 0000000..c550b63
--- /dev/null
+++ b/arch/arm/mach-picoxcell/Makefile
@@ -0,0 +1,3 @@
+obj-y	:= common.o
+obj-y	+= time.o
+obj-y	+= io.o
diff --git a/arch/arm/mach-picoxcell/Makefile.boot b/arch/arm/mach-picoxcell/Makefile.boot
new file mode 100644
index 0000000..b327175
--- /dev/null
+++ b/arch/arm/mach-picoxcell/Makefile.boot
@@ -0,0 +1 @@
+zreladdr-y := 0x00008000
diff --git a/arch/arm/mach-picoxcell/common.c b/arch/arm/mach-picoxcell/common.c
new file mode 100644
index 0000000..34d0834
--- /dev/null
+++ b/arch/arm/mach-picoxcell/common.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * All enquiries to support@picochip.com
+ */
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+
+#include <asm/mach/arch.h>
+#include <asm/hardware/vic.h>
+
+#include <mach/map.h>
+#include <mach/picoxcell_soc.h>
+
+#include "common.h"
+
+static void __init picoxcell_init_machine(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *picoxcell_dt_match[] = {
+	"picochip,pc3x2",
+	"picochip,pc3x3",
+	NULL
+};
+
+static const struct of_device_id vic_of_match[] __initconst = {
+	{ .compatible = "arm,pl192-vic" },
+	{ /* Sentinel */ }
+};
+
+static void __init picoxcell_init_irq(void)
+{
+	vic_init(IO_ADDRESS(PICOXCELL_VIC0_BASE), 0, ~0, 0);
+	vic_init(IO_ADDRESS(PICOXCELL_VIC1_BASE), 32, ~0, 0);
+	irq_domain_generate_simple(vic_of_match, PICOXCELL_VIC0_BASE, 0);
+	irq_domain_generate_simple(vic_of_match, PICOXCELL_VIC1_BASE, 32);
+}
+
+DT_MACHINE_START(PICOXCELL, "Picochip picoXcell")
+	.map_io		= picoxcell_map_io,
+	.nr_irqs	= ARCH_NR_IRQS,
+	.init_irq	= picoxcell_init_irq,
+	.timer		= &picoxcell_timer,
+	.init_machine	= picoxcell_init_machine,
+	.dt_compat	= picoxcell_dt_match,
+MACHINE_END
diff --git a/arch/arm/mach-picoxcell/common.h b/arch/arm/mach-picoxcell/common.h
new file mode 100644
index 0000000..5263f0f
--- /dev/null
+++ b/arch/arm/mach-picoxcell/common.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * All enquiries to support@picochip.com
+ */
+#ifndef __PICOXCELL_COMMON_H__
+#define __PICOXCELL_COMMON_H__
+
+#include <asm/mach/time.h>
+
+extern struct sys_timer picoxcell_timer;
+extern void picoxcell_map_io(void);
+
+#endif /* __PICOXCELL_COMMON_H__ */
diff --git a/arch/arm/mach-picoxcell/include/mach/debug-macro.S b/arch/arm/mach-picoxcell/include/mach/debug-macro.S
new file mode 100644
index 0000000..8f2c234
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/debug-macro.S
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Derived from arch/arm/mach-davinci/include/mach/debug-macro.S to use 32-bit
+ * accesses to the 8250.
+ */
+#include <linux/serial_reg.h>
+#include <mach/hardware.h>
+#include <mach/map.h>
+
+#define UART_SHIFT 2
+
+		.macro	addruart, rp, rv
+		ldr	\rv, =PHYS_TO_IO(PICOXCELL_UART1_BASE)
+		ldr	\rp, =PICOXCELL_UART1_BASE
+		.endm
+
+		.macro	senduart,rd,rx
+		str	\rd, [\rx, #UART_TX << UART_SHIFT]
+		.endm
+
+		.macro	busyuart,rd,rx
+1002:		ldr	\rd, [\rx, #UART_LSR << UART_SHIFT]
+		and	\rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
+		teq	\rd, #UART_LSR_TEMT | UART_LSR_THRE
+		bne	1002b
+		.endm
+
+		/* The UART's don't have any flow control IO's wired up. */
+		.macro	waituart,rd,rx
+		.endm
diff --git a/arch/arm/mach-picoxcell/include/mach/entry-macro.S b/arch/arm/mach-picoxcell/include/mach/entry-macro.S
new file mode 100644
index 0000000..a6b09f7
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/entry-macro.S
@@ -0,0 +1,19 @@
+/*
+ * entry-macro.S
+ *
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * Low-level IRQ helper macros for picoXcell platforms
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#define VA_VIC0		IO_ADDRESS(PICOXCELL_VIC0_BASE)
+#define VA_VIC1		IO_ADDRESS(PICOXCELL_VIC1_BASE)
+
+#include <asm/entry-macro-vic2.S>
diff --git a/arch/arm/mach-picoxcell/include/mach/gpio.h b/arch/arm/mach-picoxcell/include/mach/gpio.h
new file mode 100644
index 0000000..40a8c17
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/gpio.h
@@ -0,0 +1 @@
+/* empty */
diff --git a/arch/arm/mach-picoxcell/include/mach/hardware.h b/arch/arm/mach-picoxcell/include/mach/hardware.h
new file mode 100644
index 0000000..70ff581
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/hardware.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This file contains the hardware definitions of the picoXcell SoC devices.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <mach/picoxcell_soc.h>
+
+#endif
diff --git a/arch/arm/mach-picoxcell/include/mach/io.h b/arch/arm/mach-picoxcell/include/mach/io.h
new file mode 100644
index 0000000..7573ec7
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/io.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+/* No ioports, but needed for driver compatibility. */
+#define __io(a)			__typesafe_io(a)
+/* No PCI possible on picoxcell. */
+#define __mem_pci(a)		(a)
+
+#endif /* __ASM_ARM_ARCH_IO_H */
diff --git a/arch/arm/mach-picoxcell/include/mach/irqs.h b/arch/arm/mach-picoxcell/include/mach/irqs.h
new file mode 100644
index 0000000..4d13ed9
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/irqs.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This file contains the hardware definitions of the picoXcell SoC devices.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __MACH_IRQS_H
+#define __MACH_IRQS_H
+
+#define ARCH_NR_IRQS			64
+#define NR_IRQS				(128 + ARCH_NR_IRQS)
+
+#define IRQ_VIC0_BASE			0
+#define IRQ_VIC1_BASE			32
+
+#endif /* __MACH_IRQS_H */
diff --git a/arch/arm/mach-picoxcell/include/mach/map.h b/arch/arm/mach-picoxcell/include/mach/map.h
new file mode 100644
index 0000000..c06afad
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/map.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __PICOXCELL_MAP_H__
+#define __PICOXCELL_MAP_H__
+
+#define PHYS_TO_IO(x)		(((x) & 0x00ffffff) | 0xfe000000)
+
+#ifdef __ASSEMBLY__
+#define IO_ADDRESS(x)		PHYS_TO_IO((x))
+#else
+#define IO_ADDRESS(x)		(void __iomem __force *)(PHYS_TO_IO((x)))
+#endif
+
+#endif /* __PICOXCELL_MAP_H__ */
diff --git a/arch/arm/mach-picoxcell/include/mach/memory.h b/arch/arm/mach-picoxcell/include/mach/memory.h
new file mode 100644
index 0000000..40a8c17
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/memory.h
@@ -0,0 +1 @@
+/* empty */
diff --git a/arch/arm/mach-picoxcell/include/mach/picoxcell_soc.h b/arch/arm/mach-picoxcell/include/mach/picoxcell_soc.h
new file mode 100644
index 0000000..5566fc8
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/picoxcell_soc.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This file contains the hardware definitions of the picoXcell SoC devices.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __PICOXCELL_SOC_H__
+#define __PICOXCELL_SOC_H__
+
+#define PICOXCELL_UART1_BASE		0x80230000
+#define PICOXCELL_PERIPH_BASE		0x80000000
+#define PICOXCELL_PERIPH_LENGTH		SZ_4M
+#define PICOXCELL_VIC0_BASE		0x80060000
+#define PICOXCELL_VIC1_BASE		0x80064000
+
+#endif /* __PICOXCELL_SOC_H__ */
diff --git a/arch/arm/mach-picoxcell/include/mach/system.h b/arch/arm/mach-picoxcell/include/mach/system.h
new file mode 100644
index 0000000..67c589b
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/system.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+static inline void arch_idle(void)
+{
+	/*
+	 * This should do all the clock switching and wait for interrupt
+	 * tricks.
+	 */
+	cpu_do_idle();
+}
+
+static inline void arch_reset(int mode, const char *cmd)
+{
+	/* Watchdog reset to go here. */
+}
+
+#endif /* __ASM_ARCH_SYSTEM_H */
diff --git a/arch/arm/mach-picoxcell/include/mach/timex.h b/arch/arm/mach-picoxcell/include/mach/timex.h
new file mode 100644
index 0000000..6c540a6
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/timex.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __TIMEX_H__
+#define __TIMEX_H__
+
+/* Bogus value to allow the kernel to compile. */
+#define CLOCK_TICK_RATE		1000000
+
+#endif /* __TIMEX_H__ */
+
diff --git a/arch/arm/mach-picoxcell/include/mach/uncompress.h b/arch/arm/mach-picoxcell/include/mach/uncompress.h
new file mode 100644
index 0000000..b60b19d
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/uncompress.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#define putc(c)
+#define flush()
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff --git a/arch/arm/mach-picoxcell/include/mach/vmalloc.h b/arch/arm/mach-picoxcell/include/mach/vmalloc.h
new file mode 100644
index 0000000..0216cc4
--- /dev/null
+++ b/arch/arm/mach-picoxcell/include/mach/vmalloc.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#define VMALLOC_END	0xfe000000UL
diff --git a/arch/arm/mach-picoxcell/io.c b/arch/arm/mach-picoxcell/io.c
new file mode 100644
index 0000000..39e9b9e
--- /dev/null
+++ b/arch/arm/mach-picoxcell/io.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * All enquiries to support@picochip.com
+ */
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/of.h>
+
+#include <asm/mach/map.h>
+
+#include <mach/map.h>
+#include <mach/picoxcell_soc.h>
+
+#include "common.h"
+
+void __init picoxcell_map_io(void)
+{
+	struct map_desc io_map = {
+		.virtual	= PHYS_TO_IO(PICOXCELL_PERIPH_BASE),
+		.pfn		= __phys_to_pfn(PICOXCELL_PERIPH_BASE),
+		.length		= PICOXCELL_PERIPH_LENGTH,
+		.type		= MT_DEVICE,
+	};
+
+	iotable_init(&io_map, 1);
+}
diff --git a/arch/arm/mach-picoxcell/time.c b/arch/arm/mach-picoxcell/time.c
new file mode 100644
index 0000000..90a554f
--- /dev/null
+++ b/arch/arm/mach-picoxcell/time.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * All enquiries to support@picochip.com
+ */
+#include <linux/dw_apb_timer.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/sched.h>
+
+#include <asm/mach/time.h>
+#include <asm/sched_clock.h>
+
+#include "common.h"
+
+static void timer_get_base_and_rate(struct device_node *np,
+				    void __iomem **base, u32 *rate)
+{
+	*base = of_iomap(np, 0);
+
+	if (!*base)
+		panic("Unable to map regs for %s", np->name);
+
+	if (of_property_read_u32(np, "clock-freq", rate))
+		panic("No clock-freq property for %s", np->name);
+}
+
+static void picoxcell_add_clockevent(struct device_node *event_timer)
+{
+	void __iomem *iobase;
+	struct dw_apb_clock_event_device *ced;
+	u32 irq, rate;
+
+	irq = irq_of_parse_and_map(event_timer, 0);
+	if (irq == NO_IRQ)
+		panic("No IRQ for clock event timer");
+
+	timer_get_base_and_rate(event_timer, &iobase, &rate);
+
+	ced = dw_apb_clockevent_init(0, event_timer->name, 300, iobase, irq,
+				     rate);
+	if (!ced)
+		panic("Unable to initialise clockevent device");
+
+	dw_apb_clockevent_register(ced);
+}
+
+static void picoxcell_add_clocksource(struct device_node *source_timer)
+{
+	void __iomem *iobase;
+	struct dw_apb_clocksource *cs;
+	u32 rate;
+
+	timer_get_base_and_rate(source_timer, &iobase, &rate);
+
+	cs = dw_apb_clocksource_init(300, source_timer->name, iobase, rate);
+	if (!cs)
+		panic("Unable to initialise clocksource device");
+
+	dw_apb_clocksource_start(cs);
+	dw_apb_clocksource_register(cs);
+}
+
+static DEFINE_CLOCK_DATA(cd);
+static void __iomem *sched_io_base;
+
+unsigned long long notrace sched_clock(void)
+{
+	cycle_t cyc = sched_io_base ? __raw_readl(sched_io_base) : 0;
+
+	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
+}
+
+static void notrace picoxcell_update_sched_clock(void)
+{
+	cycle_t cyc = sched_io_base ? __raw_readl(sched_io_base) : 0;
+
+	update_sched_clock(&cd, cyc, (u32)~0);
+}
+
+static const struct of_device_id picoxcell_rtc_ids[] __initconst = {
+	{ .compatible = "picochip,pc3x2-rtc" },
+	{ /* Sentinel */ },
+};
+
+static void picoxcell_init_sched_clock(void)
+{
+	struct device_node *sched_timer;
+	u32 rate;
+
+	sched_timer = of_find_matching_node(NULL, picoxcell_rtc_ids);
+	if (!sched_timer)
+		panic("No RTC for sched clock to use");
+
+	timer_get_base_and_rate(sched_timer, &sched_io_base, &rate);
+	of_node_put(sched_timer);
+
+	init_sched_clock(&cd, picoxcell_update_sched_clock, 32, rate);
+}
+
+static const struct of_device_id picoxcell_timer_ids[] __initconst = {
+	{ .compatible = "picochip,pc3x2-timer" },
+	{},
+};
+
+static void __init picoxcell_timer_init(void)
+{
+	struct device_node *event_timer, *source_timer;
+
+	event_timer = of_find_matching_node(NULL, picoxcell_timer_ids);
+	if (!event_timer)
+		panic("No timer for clockevent");
+	picoxcell_add_clockevent(event_timer);
+
+	source_timer = of_find_matching_node(event_timer, picoxcell_timer_ids);
+	if (!source_timer)
+		panic("No timer for clocksource");
+	picoxcell_add_clocksource(source_timer);
+
+	of_node_put(source_timer);
+
+	picoxcell_init_sched_clock();
+}
+
+struct sys_timer picoxcell_timer = {
+	.init = picoxcell_timer_init,
+};
diff --git a/arch/arm/mach-prima2/Makefile b/arch/arm/mach-prima2/Makefile
index 7af7fc0..13dd160 100644
--- a/arch/arm/mach-prima2/Makefile
+++ b/arch/arm/mach-prima2/Makefile
@@ -3,5 +3,7 @@ obj-y += irq.o
 obj-y += clock.o
 obj-y += rstc.o
 obj-y += prima2.o
+obj-y += rtciobrg.o
 obj-$(CONFIG_DEBUG_LL) += lluart.o
 obj-$(CONFIG_CACHE_L2X0) += l2x0.o
+obj-$(CONFIG_SUSPEND) += pm.o sleep.o
diff --git a/arch/arm/mach-prima2/clock.c b/arch/arm/mach-prima2/clock.c
index 615a4e7..aebad7e 100644
--- a/arch/arm/mach-prima2/clock.c
+++ b/arch/arm/mach-prima2/clock.c
@@ -350,10 +350,10 @@ static struct clk_lookup onchip_clks[] = {
 		.clk = &clk_mem,
 	}, {
 		.dev_id = "sys",
-			.clk = &clk_sys,
+		.clk = &clk_sys,
 	}, {
 		.dev_id = "io",
-			.clk = &clk_io,
+		.clk = &clk_io,
 	},
 };
 
diff --git a/arch/arm/mach-prima2/irq.c b/arch/arm/mach-prima2/irq.c
index 7af254d..d93ceef 100644
--- a/arch/arm/mach-prima2/irq.c
+++ b/arch/arm/mach-prima2/irq.c
@@ -13,6 +13,8 @@
 #include <asm/mach/irq.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/irqdomain.h>
+#include <linux/syscore_ops.h>
 
 #define SIRFSOC_INT_RISC_MASK0          0x0018
 #define SIRFSOC_INT_RISC_MASK1          0x001C
@@ -66,7 +68,48 @@ void __init sirfsoc_of_irq_init(void)
 	if (!sirfsoc_intc_base)
 		panic("unable to map intc cpu registers\n");
 
+	irq_domain_add_simple(np, 0);
+
 	of_node_put(np);
 
 	sirfsoc_irq_init();
 }
+
+struct sirfsoc_irq_status {
+	u32 mask0;
+	u32 mask1;
+	u32 level0;
+	u32 level1;
+};
+
+static struct sirfsoc_irq_status sirfsoc_irq_st;
+
+static int sirfsoc_irq_suspend(void)
+{
+	sirfsoc_irq_st.mask0 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK0);
+	sirfsoc_irq_st.mask1 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1);
+	sirfsoc_irq_st.level0 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0);
+	sirfsoc_irq_st.level1 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1);
+
+	return 0;
+}
+
+static void sirfsoc_irq_resume(void)
+{
+	writel_relaxed(sirfsoc_irq_st.mask0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK0);
+	writel_relaxed(sirfsoc_irq_st.mask1, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1);
+	writel_relaxed(sirfsoc_irq_st.level0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0);
+	writel_relaxed(sirfsoc_irq_st.level1, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1);
+}
+
+static struct syscore_ops sirfsoc_irq_syscore_ops = {
+	.suspend	= sirfsoc_irq_suspend,
+	.resume		= sirfsoc_irq_resume,
+};
+
+static int __init sirfsoc_irq_pm_init(void)
+{
+	register_syscore_ops(&sirfsoc_irq_syscore_ops);
+	return 0;
+}
+device_initcall(sirfsoc_irq_pm_init);
diff --git a/arch/arm/mach-prima2/l2x0.c b/arch/arm/mach-prima2/l2x0.c
index 66c6387..c998377 100644
--- a/arch/arm/mach-prima2/l2x0.c
+++ b/arch/arm/mach-prima2/l2x0.c
@@ -8,51 +8,24 @@
 
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/errno.h>
 #include <linux/of.h>
-#include <linux/of_address.h>
 #include <asm/hardware/cache-l2x0.h>
 
-#define L2X0_ADDR_FILTERING_START       0xC00
-#define L2X0_ADDR_FILTERING_END         0xC04
-
-static struct of_device_id l2x_ids[]  = {
-	{ .compatible = "arm,pl310-cache" },
+static struct of_device_id prima2_l2x0_ids[]  = {
+	{ .compatible = "sirf,prima2-pl310-cache" },
+	{},
 };
 
-static int __init sirfsoc_of_l2x_init(void)
+static int __init sirfsoc_l2x0_init(void)
 {
 	struct device_node *np;
-	void __iomem *sirfsoc_l2x_base;
-
-	np = of_find_matching_node(NULL, l2x_ids);
-	if (!np)
-		panic("unable to find compatible l2x node in dtb\n");
-
-	sirfsoc_l2x_base = of_iomap(np, 0);
-	if (!sirfsoc_l2x_base)
-		panic("unable to map l2x cpu registers\n");
-
-	of_node_put(np);
-
-	if (!(readl_relaxed(sirfsoc_l2x_base + L2X0_CTRL) & 1)) {
-		/*
-		 * set the physical memory windows L2 cache will cover
-		 */
-		writel_relaxed(PHYS_OFFSET + 1024 * 1024 * 1024,
-			sirfsoc_l2x_base + L2X0_ADDR_FILTERING_END);
-		writel_relaxed(PHYS_OFFSET | 0x1,
-			sirfsoc_l2x_base + L2X0_ADDR_FILTERING_START);
 
-		writel_relaxed(0,
-			sirfsoc_l2x_base + L2X0_TAG_LATENCY_CTRL);
-		writel_relaxed(0,
-			sirfsoc_l2x_base + L2X0_DATA_LATENCY_CTRL);
+	np = of_find_matching_node(NULL, prima2_l2x0_ids);
+	if (np) {
+		pr_info("Initializing prima2 L2 cache\n");
+		return l2x0_of_init(0x40000, 0);
 	}
-	l2x0_init((void __iomem *)sirfsoc_l2x_base, 0x00040000,
-		0x00000000);
 
 	return 0;
 }
-early_initcall(sirfsoc_of_l2x_init);
+early_initcall(sirfsoc_l2x0_init);
diff --git a/arch/arm/mach-prima2/pm.c b/arch/arm/mach-prima2/pm.c
new file mode 100644
index 0000000..cb53160
--- /dev/null
+++ b/arch/arm/mach-prima2/pm.c
@@ -0,0 +1,150 @@
+/*
+ * power management entry for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/kernel.h>
+#include <linux/suspend.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/io.h>
+#include <linux/rtc/sirfsoc_rtciobrg.h>
+#include <asm/suspend.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#include "pm.h"
+
+/*
+ * suspend asm codes will access these to make DRAM become self-refresh and
+ * system sleep
+ */
+u32 sirfsoc_pwrc_base;
+void __iomem *sirfsoc_memc_base;
+
+static void sirfsoc_set_wakeup_source(void)
+{
+	u32 pwr_trigger_en_reg;
+	pwr_trigger_en_reg = sirfsoc_rtc_iobrg_readl(sirfsoc_pwrc_base +
+		SIRFSOC_PWRC_TRIGGER_EN);
+#define X_ON_KEY_B (1 << 0)
+	sirfsoc_rtc_iobrg_writel(pwr_trigger_en_reg | X_ON_KEY_B,
+		sirfsoc_pwrc_base + SIRFSOC_PWRC_TRIGGER_EN);
+}
+
+static void sirfsoc_set_sleep_mode(u32 mode)
+{
+	u32 sleep_mode = sirfsoc_rtc_iobrg_readl(sirfsoc_pwrc_base +
+		SIRFSOC_PWRC_PDN_CTRL);
+	sleep_mode &= ~(SIRFSOC_SLEEP_MODE_MASK << 1);
+	sleep_mode |= mode << 1;
+	sirfsoc_rtc_iobrg_writel(sleep_mode, sirfsoc_pwrc_base +
+		SIRFSOC_PWRC_PDN_CTRL);
+}
+
+static int sirfsoc_pre_suspend_power_off(void)
+{
+	u32 wakeup_entry = virt_to_phys(cpu_resume);
+
+	sirfsoc_rtc_iobrg_writel(wakeup_entry, sirfsoc_pwrc_base +
+		SIRFSOC_PWRC_SCRATCH_PAD1);
+
+	sirfsoc_set_wakeup_source();
+
+	sirfsoc_set_sleep_mode(SIRFSOC_DEEP_SLEEP_MODE);
+
+	return 0;
+}
+
+static int sirfsoc_pm_enter(suspend_state_t state)
+{
+	switch (state) {
+	case PM_SUSPEND_MEM:
+		sirfsoc_pre_suspend_power_off();
+
+		outer_flush_all();
+		outer_disable();
+		/* go zzz */
+		cpu_suspend(0, sirfsoc_finish_suspend);
+		outer_resume();
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static const struct platform_suspend_ops sirfsoc_pm_ops = {
+	.enter = sirfsoc_pm_enter,
+	.valid = suspend_valid_only_mem,
+};
+
+static int __init sirfsoc_pm_init(void)
+{
+	suspend_set_ops(&sirfsoc_pm_ops);
+	return 0;
+}
+late_initcall(sirfsoc_pm_init);
+
+static const struct of_device_id pwrc_ids[] = {
+	{ .compatible = "sirf,prima2-pwrc" },
+	{}
+};
+
+static int __init sirfsoc_of_pwrc_init(void)
+{
+	struct device_node *np;
+
+	np = of_find_matching_node(NULL, pwrc_ids);
+	if (!np)
+		panic("unable to find compatible pwrc node in dtb\n");
+
+	/*
+	 * pwrc behind rtciobrg is not located in memory space
+	 * though the property is named reg. reg only means base
+	 * offset for pwrc. then of_iomap is not suitable here.
+	 */
+	if (of_property_read_u32(np, "reg", &sirfsoc_pwrc_base))
+		panic("unable to find base address of pwrc node in dtb\n");
+
+	of_node_put(np);
+
+	return 0;
+}
+postcore_initcall(sirfsoc_of_pwrc_init);
+
+static const struct of_device_id memc_ids[] = {
+	{ .compatible = "sirf,prima2-memc" },
+	{}
+};
+
+static int __devinit sirfsoc_memc_probe(struct platform_device *op)
+{
+	struct device_node *np = op->dev.of_node;
+
+	sirfsoc_memc_base = of_iomap(np, 0);
+	if (!sirfsoc_memc_base)
+		panic("unable to map memc registers\n");
+
+	return 0;
+}
+
+static struct platform_driver sirfsoc_memc_driver = {
+	.probe		= sirfsoc_memc_probe,
+	.driver = {
+		.name = "sirfsoc-memc",
+		.owner = THIS_MODULE,
+		.of_match_table	= memc_ids,
+	},
+};
+
+static int __init sirfsoc_memc_init(void)
+{
+	return platform_driver_register(&sirfsoc_memc_driver);
+}
+postcore_initcall(sirfsoc_memc_init);
diff --git a/arch/arm/mach-prima2/pm.h b/arch/arm/mach-prima2/pm.h
new file mode 100644
index 0000000..bae6d77
--- /dev/null
+++ b/arch/arm/mach-prima2/pm.h
@@ -0,0 +1,29 @@
+/*
+ * arch/arm/mach-prima2/pm.h
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef _MACH_PRIMA2_PM_H_
+#define _MACH_PRIMA2_PM_H_
+
+#define SIRFSOC_PWR_SLEEPFORCE		0x01
+
+#define SIRFSOC_SLEEP_MODE_MASK         0x3
+#define SIRFSOC_DEEP_SLEEP_MODE         0x1
+
+#define SIRFSOC_PWRC_PDN_CTRL           0x0
+#define SIRFSOC_PWRC_PON_OFF            0x4
+#define SIRFSOC_PWRC_TRIGGER_EN         0x8
+#define SIRFSOC_PWRC_PIN_STATUS         0x14
+#define SIRFSOC_PWRC_SCRATCH_PAD1       0x18
+#define SIRFSOC_PWRC_SCRATCH_PAD2       0x1C
+
+#ifndef __ASSEMBLY__
+extern int sirfsoc_finish_suspend(unsigned long);
+#endif
+
+#endif
+
diff --git a/arch/arm/mach-prima2/prima2.c b/arch/arm/mach-prima2/prima2.c
index ee33c3d..ef555c0 100644
--- a/arch/arm/mach-prima2/prima2.c
+++ b/arch/arm/mach-prima2/prima2.c
@@ -1,5 +1,5 @@
 /*
- * Defines machines for CSR SiRFprimaII 
+ * Defines machines for CSR SiRFprimaII
  *
  * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
  *
diff --git a/arch/arm/mach-prima2/rtciobrg.c b/arch/arm/mach-prima2/rtciobrg.c
new file mode 100644
index 0000000..9d80f1e
--- /dev/null
+++ b/arch/arm/mach-prima2/rtciobrg.c
@@ -0,0 +1,139 @@
+/*
+ * RTC I/O Bridge interfaces for CSR SiRFprimaII
+ * ARM access the registers of SYSRTC, GPSRTC and PWRC through this module
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+
+#define SIRFSOC_CPUIOBRG_CTRL           0x00
+#define SIRFSOC_CPUIOBRG_WRBE           0x04
+#define SIRFSOC_CPUIOBRG_ADDR           0x08
+#define SIRFSOC_CPUIOBRG_DATA           0x0c
+
+/*
+ * suspend asm codes will access this address to make system deepsleep
+ * after DRAM becomes self-refresh
+ */
+void __iomem *sirfsoc_rtciobrg_base;
+static DEFINE_SPINLOCK(rtciobrg_lock);
+
+/*
+ * symbols without lock are only used by suspend asm codes
+ * and these symbols are not exported too
+ */
+void sirfsoc_rtc_iobrg_wait_sync(void)
+{
+	while (readl_relaxed(sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_CTRL))
+		cpu_relax();
+}
+
+void sirfsoc_rtc_iobrg_besyncing(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&rtciobrg_lock, flags);
+
+	sirfsoc_rtc_iobrg_wait_sync();
+
+	spin_unlock_irqrestore(&rtciobrg_lock, flags);
+}
+EXPORT_SYMBOL_GPL(sirfsoc_rtc_iobrg_besyncing);
+
+u32 __sirfsoc_rtc_iobrg_readl(u32 addr)
+{
+	sirfsoc_rtc_iobrg_wait_sync();
+
+	writel_relaxed(0x00, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_WRBE);
+	writel_relaxed(addr, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_ADDR);
+	writel_relaxed(0x01, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_CTRL);
+
+	sirfsoc_rtc_iobrg_wait_sync();
+
+	return readl_relaxed(sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_DATA);
+}
+
+u32 sirfsoc_rtc_iobrg_readl(u32 addr)
+{
+	unsigned long flags, val;
+
+	spin_lock_irqsave(&rtciobrg_lock, flags);
+
+	val = __sirfsoc_rtc_iobrg_readl(addr);
+
+	spin_unlock_irqrestore(&rtciobrg_lock, flags);
+
+	return val;
+}
+EXPORT_SYMBOL_GPL(sirfsoc_rtc_iobrg_readl);
+
+void sirfsoc_rtc_iobrg_pre_writel(u32 val, u32 addr)
+{
+	sirfsoc_rtc_iobrg_wait_sync();
+
+	writel_relaxed(0xf1, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_WRBE);
+	writel_relaxed(addr, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_ADDR);
+
+	writel_relaxed(val, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_DATA);
+}
+
+void sirfsoc_rtc_iobrg_writel(u32 val, u32 addr)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&rtciobrg_lock, flags);
+
+	sirfsoc_rtc_iobrg_pre_writel(val, addr);
+
+	writel_relaxed(0x01, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_CTRL);
+
+	sirfsoc_rtc_iobrg_wait_sync();
+
+	spin_unlock_irqrestore(&rtciobrg_lock, flags);
+}
+EXPORT_SYMBOL_GPL(sirfsoc_rtc_iobrg_writel);
+
+static const struct of_device_id rtciobrg_ids[] = {
+	{ .compatible = "sirf,prima2-rtciobg" },
+	{}
+};
+
+static int __devinit sirfsoc_rtciobrg_probe(struct platform_device *op)
+{
+	struct device_node *np = op->dev.of_node;
+
+	sirfsoc_rtciobrg_base = of_iomap(np, 0);
+	if (!sirfsoc_rtciobrg_base)
+		panic("unable to map rtc iobrg registers\n");
+
+	return 0;
+}
+
+static struct platform_driver sirfsoc_rtciobrg_driver = {
+	.probe		= sirfsoc_rtciobrg_probe,
+	.driver = {
+		.name = "sirfsoc-rtciobrg",
+		.owner = THIS_MODULE,
+		.of_match_table	= rtciobrg_ids,
+	},
+};
+
+static int __init sirfsoc_rtciobrg_init(void)
+{
+	return platform_driver_register(&sirfsoc_rtciobrg_driver);
+}
+postcore_initcall(sirfsoc_rtciobrg_init);
+
+MODULE_AUTHOR("Zhiwu Song <zhiwu.song@csr.com>, "
+		"Barry Song <baohua.song@csr.com>");
+MODULE_DESCRIPTION("CSR SiRFprimaII rtc io bridge");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-prima2/sleep.S b/arch/arm/mach-prima2/sleep.S
new file mode 100644
index 0000000..0745abc
--- /dev/null
+++ b/arch/arm/mach-prima2/sleep.S
@@ -0,0 +1,64 @@
+/*
+ * sleep mode for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/linkage.h>
+#include <asm/ptrace.h>
+#include <asm/assembler.h>
+
+#include "pm.h"
+
+#define DENALI_CTL_22_OFF	0x58
+#define DENALI_CTL_112_OFF	0x1c0
+
+	.text
+
+ENTRY(sirfsoc_finish_suspend)
+	@ r5: 	mem controller
+	ldr     r0, =sirfsoc_memc_base
+	ldr	r5, [r0]
+	@ r6: 	pwrc base offset
+	ldr     r0, =sirfsoc_pwrc_base
+	ldr	r6, [r0]
+	@ r7: 	rtc iobrg controller
+	ldr     r0, =sirfsoc_rtciobrg_base
+	ldr	r7, [r0]
+
+	@ Read the power control register and set the
+	@ sleep force bit.
+	add	r0, r6, #SIRFSOC_PWRC_PDN_CTRL
+	bl	__sirfsoc_rtc_iobrg_readl
+	orr	r0,r0,#SIRFSOC_PWR_SLEEPFORCE
+	add	r1, r6, #SIRFSOC_PWRC_PDN_CTRL
+	bl	sirfsoc_rtc_iobrg_pre_writel
+	mov	r1, #0x1
+
+	@ read the MEM ctl register and set the self
+	@ refresh bit
+
+	ldr	r2, [r5, #DENALI_CTL_22_OFF]
+	orr	r2, r2, #0x1
+
+	@ Following code has to run from cache since
+	@ the RAM is going to self refresh mode
+	.align 5
+	str	r2, [r5, #DENALI_CTL_22_OFF]
+
+1:
+	ldr	r4, [r5, #DENALI_CTL_112_OFF]
+	tst	r4, #0x1
+	bne	1b
+
+	@ write SLEEPFORCE through rtc iobridge
+
+	str	r1, [r7]
+	@ wait rtc io bridge sync
+1:
+	ldr	r3, [r7]
+	tst	r3, #0x01
+	bne	1b
+	b .
diff --git a/arch/arm/mach-prima2/timer.c b/arch/arm/mach-prima2/timer.c
index ed7ec48..b7a6091 100644
--- a/arch/arm/mach-prima2/timer.c
+++ b/arch/arm/mach-prima2/timer.c
@@ -40,6 +40,17 @@
 
 #define SIRFSOC_TIMER_LATCH_BIT	 BIT(0)
 
+#define SIRFSOC_TIMER_REG_CNT 11
+
+static const u32 sirfsoc_timer_reg_list[SIRFSOC_TIMER_REG_CNT] = {
+	SIRFSOC_TIMER_MATCH_0, SIRFSOC_TIMER_MATCH_1, SIRFSOC_TIMER_MATCH_2,
+	SIRFSOC_TIMER_MATCH_3, SIRFSOC_TIMER_MATCH_4, SIRFSOC_TIMER_MATCH_5,
+	SIRFSOC_TIMER_INT_EN, SIRFSOC_TIMER_WATCHDOG_EN, SIRFSOC_TIMER_DIV,
+	SIRFSOC_TIMER_LATCHED_LO, SIRFSOC_TIMER_LATCHED_HI,
+};
+
+static u32 sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT];
+
 static void __iomem *sirfsoc_timer_base;
 static void __init sirfsoc_of_timer_map(void);
 
@@ -106,6 +117,27 @@ static void sirfsoc_timer_set_mode(enum clock_event_mode mode,
 	}
 }
 
+static void sirfsoc_clocksource_suspend(struct clocksource *cs)
+{
+	int i;
+
+	writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
+
+	for (i = 0; i < SIRFSOC_TIMER_REG_CNT; i++)
+		sirfsoc_timer_reg_val[i] = readl_relaxed(sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
+}
+
+static void sirfsoc_clocksource_resume(struct clocksource *cs)
+{
+	int i;
+
+	for (i = 0; i < SIRFSOC_TIMER_REG_CNT; i++)
+		writel_relaxed(sirfsoc_timer_reg_val[i], sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
+
+	writel_relaxed(sirfsoc_timer_reg_val[i - 2], sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_LO);
+	writel_relaxed(sirfsoc_timer_reg_val[i - 1], sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_HI);
+}
+
 static struct clock_event_device sirfsoc_clockevent = {
 	.name = "sirfsoc_clockevent",
 	.rating = 200,
@@ -120,6 +152,8 @@ static struct clocksource sirfsoc_clocksource = {
 	.mask = CLOCKSOURCE_MASK(64),
 	.flags = CLOCK_SOURCE_IS_CONTINUOUS,
 	.read = sirfsoc_timer_read,
+	.suspend = sirfsoc_clocksource_suspend,
+	.resume = sirfsoc_clocksource_resume,
 };
 
 static struct irqaction sirfsoc_timer_irq = {
@@ -133,14 +167,14 @@ static struct irqaction sirfsoc_timer_irq = {
 /* Overwrite weak default sched_clock with more precise one */
 unsigned long long notrace sched_clock(void)
 {
-	static int is_mapped = 0;
+	static int is_mapped;
 
 	/*
 	 * sched_clock is called earlier than .init of sys_timer
 	 * if we map timer memory in .init of sys_timer, system
 	 * will panic due to illegal memory access
 	 */
-	if(!is_mapped) {
+	if (!is_mapped) {
 		sirfsoc_of_timer_map();
 		is_mapped = 1;
 	}
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index cd19309..61d3c72 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -2,6 +2,27 @@ if ARCH_PXA
 
 menu "Intel PXA2xx/PXA3xx Implementations"
 
+config ARCH_PXA_V7
+	bool "ARMv7 (PXA95x) based systems"
+
+if ARCH_PXA_V7
+comment "Marvell Dev Platforms (sorted by hardware release time)"
+config MACH_TAVOREVB3
+	bool "PXA95x Development Platform (aka TavorEVB III)"
+	select CPU_PXA955
+
+config MACH_SAARB
+	bool "PXA955 Handheld Platform (aka SAARB)"
+	select CPU_PXA955
+endif
+
+config PXA_V7_MACH_AUTO
+	def_bool y
+	depends on ARCH_PXA_V7
+	depends on !MACH_SAARB
+	select MACH_TAVOREVB3
+
+if !ARCH_PXA_V7
 comment "Intel/Marvell Dev Platforms (sorted by hardware release time)"
 
 config ARCH_LUBBOCK
@@ -41,19 +62,11 @@ config MACH_TAVOREVB
 	select PXA3xx
 	select CPU_PXA930
 
-config MACH_TAVOREVB3
-	bool "PXA95x Development Platform (aka TavorEVB III)"
-	select CPU_PXA950
-
 config MACH_SAAR
 	bool "PXA930 Handheld Platform (aka SAAR)"
 	select PXA3xx
 	select CPU_PXA930
 
-config MACH_SAARB
-	bool "PXA955 Handheld Platform (aka SAARB)"
-	select CPU_PXA955
-
 comment "Third Party Dev Platforms (sorted by vendor name)"
 
 config ARCH_PXA_IDP
@@ -414,6 +427,7 @@ config MACH_CENTRO
 	bool "Palm Centro 685 (GSM)"
 	default y
 	depends on ARCH_PXA_PALM
+	select MACH_PALM27X
 	select PXA27x
 	select IWMMXT
 	select PALM_TREO
@@ -425,6 +439,7 @@ config MACH_TREO680
 	bool "Palm Treo 680"
 	default y
 	depends on ARCH_PXA_PALM
+	select MACH_PALM27X
 	select PXA27x
 	select IWMMXT
 	select PALM_TREO
@@ -436,15 +451,18 @@ config MACH_RAUMFELD_RC
 	bool "Raumfeld Controller"
 	select PXA3xx
 	select CPU_PXA300
+	select POWER_SUPPLY
 	select HAVE_PWM
 
 config MACH_RAUMFELD_CONNECTOR
 	bool "Raumfeld Connector"
+	select POWER_SUPPLY
 	select PXA3xx
 	select CPU_PXA300
 
 config MACH_RAUMFELD_SPEAKER
 	bool "Raumfeld Speaker"
+	select POWER_SUPPLY
 	select PXA3xx
 	select CPU_PXA300
 
@@ -598,7 +616,7 @@ config MACH_ZIPIT2
 	bool "Zipit Z2 Handheld"
 	select PXA27x
 	select HAVE_PWM
-
+endif
 endmenu
 
 config PXA25x
@@ -688,6 +706,8 @@ config SHARPSL_PM
 config SHARPSL_PM_MAX1111
 	bool
 	select HWMON
+	select SPI
+	select SPI_MASTER
 	select SENSORS_MAX1111
 
 config PXA_HAVE_ISA_IRQS
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index cc39d17..be0f7df 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -19,7 +19,7 @@ endif
 obj-$(CONFIG_PXA25x)		+= mfp-pxa2xx.o clock-pxa2xx.o pxa2xx.o pxa25x.o
 obj-$(CONFIG_PXA27x)		+= mfp-pxa2xx.o clock-pxa2xx.o pxa2xx.o pxa27x.o
 obj-$(CONFIG_PXA3xx)		+= mfp-pxa3xx.o clock-pxa3xx.o pxa3xx.o smemc.o pxa3xx-ulpi.o
-obj-$(CONFIG_PXA95x)		+= mfp-pxa3xx.o clock-pxa3xx.o pxa95x.o smemc.o
+obj-$(CONFIG_PXA95x)		+= mfp-pxa3xx.o clock-pxa3xx.o pxa3xx.o pxa95x.o smemc.o
 obj-$(CONFIG_CPU_PXA300)	+= pxa300.o
 obj-$(CONFIG_CPU_PXA320)	+= pxa320.o
 obj-$(CONFIG_CPU_PXA930)	+= pxa930.o
diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c
index 7765d67..fc0b854 100644
--- a/arch/arm/mach-pxa/balloon3.c
+++ b/arch/arm/mach-pxa/balloon3.c
@@ -591,7 +591,7 @@ static void balloon3_nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ct
 				BALLOON3_NAND_CONTROL_REG);
 		if (balloon3_ctl_set)
 			__raw_writel(balloon3_ctl_set,
-				BALLOON3_NAND_CONTROL_REG |
+				BALLOON3_NAND_CONTROL_REG +
 				BALLOON3_FPGA_SETnCLR);
 	}
 
@@ -608,7 +608,7 @@ static void balloon3_nand_select_chip(struct mtd_info *mtd, int chip)
 	__raw_writew(
 		BALLOON3_NAND_CONTROL_FLCE0 | BALLOON3_NAND_CONTROL_FLCE1 |
 		BALLOON3_NAND_CONTROL_FLCE2 | BALLOON3_NAND_CONTROL_FLCE3,
-		BALLOON3_NAND_CONTROL_REG | BALLOON3_FPGA_SETnCLR);
+		BALLOON3_NAND_CONTROL_REG + BALLOON3_FPGA_SETnCLR);
 
 	/* Deassert correct nCE line */
 	__raw_writew(BALLOON3_NAND_CONTROL_FLCE0 << chip,
@@ -626,7 +626,7 @@ static int balloon3_nand_probe(struct platform_device *pdev)
 	int ret;
 
 	__raw_writew(BALLOON3_NAND_CONTROL2_16BIT,
-		BALLOON3_NAND_CONTROL2_REG | BALLOON3_FPGA_SETnCLR);
+		BALLOON3_NAND_CONTROL2_REG + BALLOON3_FPGA_SETnCLR);
 
 	ver = __raw_readw(BALLOON3_FPGA_VER);
 	if (ver < 0x4f08)
@@ -649,7 +649,7 @@ static int balloon3_nand_probe(struct platform_device *pdev)
 		BALLOON3_NAND_CONTROL_FLCE0 | BALLOON3_NAND_CONTROL_FLCE1 |
 		BALLOON3_NAND_CONTROL_FLCE2 | BALLOON3_NAND_CONTROL_FLCE3 |
 		BALLOON3_NAND_CONTROL_FLWP,
-		BALLOON3_NAND_CONTROL_REG | BALLOON3_FPGA_SETnCLR);
+		BALLOON3_NAND_CONTROL_REG + BALLOON3_FPGA_SETnCLR);
 	return 0;
 
 err2:
@@ -807,7 +807,7 @@ static void __init balloon3_init(void)
 
 static struct map_desc balloon3_io_desc[] __initdata = {
 	{	/* CPLD/FPGA */
-		.virtual	=  BALLOON3_FPGA_VIRT,
+		.virtual	= (unsigned long)BALLOON3_FPGA_VIRT,
 		.pfn		= __phys_to_pfn(BALLOON3_FPGA_PHYS),
 		.length		= BALLOON3_FPGA_LENGTH,
 		.type		= MT_DEVICE,
diff --git a/arch/arm/mach-pxa/cm-x2xx-pci.c b/arch/arm/mach-pxa/cm-x2xx-pci.c
index 6bf479d..ebd9259 100644
--- a/arch/arm/mach-pxa/cm-x2xx-pci.c
+++ b/arch/arm/mach-pxa/cm-x2xx-pci.c
@@ -26,7 +26,7 @@
 
 #include <asm/hardware/it8152.h>
 
-unsigned long it8152_base_address;
+void __iomem *it8152_base_address;
 static int cmx2xx_it8152_irq_gpio;
 
 static void cmx2xx_it8152_irq_demux(unsigned int irq, struct irq_desc *desc)
diff --git a/arch/arm/mach-pxa/cm-x2xx.c b/arch/arm/mach-pxa/cm-x2xx.c
index 349896c..f2e4190 100644
--- a/arch/arm/mach-pxa/cm-x2xx.c
+++ b/arch/arm/mach-pxa/cm-x2xx.c
@@ -39,7 +39,7 @@ extern void cmx270_init(void);
 #define CMX2XX_NR_IRQS		(IRQ_BOARD_START + 40)
 
 /* virtual addresses for statically mapped regions */
-#define CMX2XX_VIRT_BASE	(0xe8000000)
+#define CMX2XX_VIRT_BASE	(void __iomem *)(0xe8000000)
 #define CMX2XX_IT8152_VIRT	(CMX2XX_VIRT_BASE)
 
 /* physical address if local-bus attached devices */
@@ -482,7 +482,7 @@ static void __init cmx2xx_init_irq(void)
 /* Map PCI companion statically */
 static struct map_desc cmx2xx_io_desc[] __initdata = {
 	[0] = { /* PCI bridge */
-		.virtual	= CMX2XX_IT8152_VIRT,
+		.virtual	= (unsigned long)CMX2XX_IT8152_VIRT,
 		.pfn		= __phys_to_pfn(PXA_CS4_PHYS),
 		.length		= SZ_64M,
 		.type		= MT_DEVICE
diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
index d2da301..3a7387f 100644
--- a/arch/arm/mach-pxa/cm-x300.c
+++ b/arch/arm/mach-pxa/cm-x300.c
@@ -775,7 +775,6 @@ static struct gpio cm_x300_wi2wi_gpios[] __initdata = {
 
 static void __init cm_x300_init_wi2wi(void)
 {
-	int bt_reset, wlan_en;
 	int err;
 
 	if (system_rev < 130) {
@@ -791,12 +790,11 @@ static void __init cm_x300_init_wi2wi(void)
 	}
 
 	udelay(10);
-	gpio_set_value(bt_reset, 0);
+	gpio_set_value(cm_x300_wi2wi_gpios[1].gpio, 0);
 	udelay(10);
-	gpio_set_value(bt_reset, 1);
+	gpio_set_value(cm_x300_wi2wi_gpios[1].gpio, 1);
 
-	gpio_free(wlan_en);
-	gpio_free(bt_reset);
+	gpio_free_array(ARRAY_AND_SIZE(cm_x300_wi2wi_gpios));
 }
 
 /* MFP */
diff --git a/arch/arm/mach-pxa/include/mach/addr-map.h b/arch/arm/mach-pxa/include/mach/addr-map.h
index f4c0365..bbf9df3 100644
--- a/arch/arm/mach-pxa/include/mach/addr-map.h
+++ b/arch/arm/mach-pxa/include/mach/addr-map.h
@@ -20,7 +20,7 @@
  * Peripheral Bus
  */
 #define PERIPH_PHYS		0x40000000
-#define PERIPH_VIRT		0xf2000000
+#define PERIPH_VIRT		IOMEM(0xf2000000)
 #define PERIPH_SIZE		0x02000000
 
 /*
@@ -28,21 +28,21 @@
  */
 #define PXA2XX_SMEMC_PHYS	0x48000000
 #define PXA3XX_SMEMC_PHYS	0x4a000000
-#define SMEMC_VIRT		0xf6000000
+#define SMEMC_VIRT		IOMEM(0xf6000000)
 #define SMEMC_SIZE		0x00100000
 
 /*
  * Dynamic Memory Controller (only on PXA3xx)
  */
 #define DMEMC_PHYS		0x48100000
-#define DMEMC_VIRT		0xf6100000
+#define DMEMC_VIRT		IOMEM(0xf6100000)
 #define DMEMC_SIZE		0x00100000
 
 /*
  * Internal Memory Controller (PXA27x and later)
  */
 #define IMEMC_PHYS		0x58000000
-#define IMEMC_VIRT		0xfe000000
+#define IMEMC_VIRT		IOMEM(0xfe000000)
 #define IMEMC_SIZE		0x00100000
 
 #endif /* __ASM_MACH_ADDR_MAP_H */
diff --git a/arch/arm/mach-pxa/include/mach/balloon3.h b/arch/arm/mach-pxa/include/mach/balloon3.h
index 7074e76..6d7eab3 100644
--- a/arch/arm/mach-pxa/include/mach/balloon3.h
+++ b/arch/arm/mach-pxa/include/mach/balloon3.h
@@ -23,7 +23,7 @@ enum balloon3_features {
 };
 
 #define BALLOON3_FPGA_PHYS	PXA_CS4_PHYS
-#define BALLOON3_FPGA_VIRT	(0xf1000000)	/* as per balloon2 */
+#define BALLOON3_FPGA_VIRT	IOMEM(0xf1000000)	/* as per balloon2 */
 #define BALLOON3_FPGA_LENGTH	0x01000000
 
 #define	BALLOON3_FPGA_SETnCLR		(0x1000)
diff --git a/arch/arm/mach-pxa/include/mach/gpio-pxa.h b/arch/arm/mach-pxa/include/mach/gpio-pxa.h
index 41b4c93..576868f 100644
--- a/arch/arm/mach-pxa/include/mach/gpio-pxa.h
+++ b/arch/arm/mach-pxa/include/mach/gpio-pxa.h
@@ -25,7 +25,7 @@
 #define GPIO_REGS_VIRT	io_p2v(0x40E00000)
 
 #define BANK_OFF(n)	(((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
-#define GPIO_REG(x)	(*(volatile u32 *)(GPIO_REGS_VIRT + (x)))
+#define GPIO_REG(x)	(GPIO_REGS_VIRT + (x))
 
 /* GPIO Pin Level Registers */
 #define GPLR0		GPIO_REG(BANK_OFF(0) + 0x00)
diff --git a/arch/arm/mach-pxa/include/mach/hardware.h b/arch/arm/mach-pxa/include/mach/hardware.h
index de63ca3..8184669 100644
--- a/arch/arm/mach-pxa/include/mach/hardware.h
+++ b/arch/arm/mach-pxa/include/mach/hardware.h
@@ -36,22 +36,23 @@
  * Note that not all PXA2xx chips implement all those addresses, and the
  * kernel only maps the minimum needed range of this mapping.
  */
-#define io_p2v(x) (0xf2000000 + ((x) & 0x01ffffff) + (((x) & 0x1c000000) >> 1))
 #define io_v2p(x) (0x3c000000 + ((x) & 0x01ffffff) + (((x) & 0x0e000000) << 1))
+#define io_p2v(x) IOMEM(0xf2000000 + ((x) & 0x01ffffff) + (((x) & 0x1c000000) >> 1))
 
 #ifndef __ASSEMBLY__
-
-# define __REG(x)	(*((volatile u32 *)io_p2v(x)))
+# define IOMEM(x) ((void __iomem *)(x))
+# define __REG(x)	(*((volatile u32 __iomem *)io_p2v(x)))
 
 /* With indexed regs we don't want to feed the index through io_p2v()
    especially if it is a variable, otherwise horrible code will result. */
 # define __REG2(x,y)	\
-	(*(volatile u32 *)((u32)&__REG(x) + (y)))
+	(*(volatile u32 __iomem*)((u32)&__REG(x) + (y)))
 
 # define __PREG(x)	(io_v2p((u32)&(x)))
 
 #else
 
+# define IOMEM(x)	x 
 # define __REG(x)	io_p2v(x)
 # define __PREG(x)	io_v2p(x)
 
diff --git a/arch/arm/mach-pxa/include/mach/lpd270.h b/arch/arm/mach-pxa/include/mach/lpd270.h
index cd07009..4edc712 100644
--- a/arch/arm/mach-pxa/include/mach/lpd270.h
+++ b/arch/arm/mach-pxa/include/mach/lpd270.h
@@ -13,13 +13,13 @@
 #define __ASM_ARCH_LPD270_H
 
 #define LPD270_CPLD_PHYS	PXA_CS2_PHYS
-#define LPD270_CPLD_VIRT	0xf0000000
+#define LPD270_CPLD_VIRT	IOMEM(0xf0000000)
 #define LPD270_CPLD_SIZE	0x00100000
 
 #define LPD270_ETH_PHYS		(PXA_CS2_PHYS + 0x01000000)
 
 /* CPLD registers  */
-#define LPD270_CPLD_REG(x)	((unsigned long)(LPD270_CPLD_VIRT + (x)))
+#define LPD270_CPLD_REG(x)	(LPD270_CPLD_VIRT + (x))
 #define LPD270_CONTROL		LPD270_CPLD_REG(0x00)
 #define LPD270_PERIPHERAL0	LPD270_CPLD_REG(0x04)
 #define LPD270_PERIPHERAL1	LPD270_CPLD_REG(0x08)
diff --git a/arch/arm/mach-pxa/include/mach/mtd-xip.h b/arch/arm/mach-pxa/include/mach/mtd-xip.h
index 297387e..990d2bf 100644
--- a/arch/arm/mach-pxa/include/mach/mtd-xip.h
+++ b/arch/arm/mach-pxa/include/mach/mtd-xip.h
@@ -16,7 +16,6 @@
 #define __ARCH_PXA_MTD_XIP_H__
 
 #include <mach/regs-ost.h>
-#include <mach/regs-intc.h>
 
 #define xip_irqpending()	(ICIP & ICMR)
 
diff --git a/arch/arm/mach-pxa/include/mach/palm27x.h b/arch/arm/mach-pxa/include/mach/palm27x.h
index 0a5e5ea..f80bbe2 100644
--- a/arch/arm/mach-pxa/include/mach/palm27x.h
+++ b/arch/arm/mach-pxa/include/mach/palm27x.h
@@ -34,7 +34,7 @@ extern struct pxafb_mode_info palm_320x320_new_lcd_mode;
 extern void __init palm27x_lcd_init(int power,
 					struct pxafb_mode_info *mode);
 #else
-static inline void palm27x_lcd_init(int power, struct pxafb_mode_info *mode) {}
+#define palm27x_lcd_init(power, mode)	do {} while (0)
 #endif
 
 #if	defined(CONFIG_USB_GADGET_PXA27X) || \
diff --git a/arch/arm/mach-pxa/include/mach/palmtx.h b/arch/arm/mach-pxa/include/mach/palmtx.h
index 10abc4f..7074a6e 100644
--- a/arch/arm/mach-pxa/include/mach/palmtx.h
+++ b/arch/arm/mach-pxa/include/mach/palmtx.h
@@ -71,7 +71,7 @@
 
 /* Various addresses  */
 #define PALMTX_PCMCIA_PHYS	0x28000000
-#define PALMTX_PCMCIA_VIRT	0xf0000000
+#define PALMTX_PCMCIA_VIRT	IOMEM(0xf0000000)
 #define PALMTX_PCMCIA_SIZE	0x100000
 
 #define PALMTX_PHYS_RAM_START	0xa0000000
@@ -84,8 +84,8 @@
 
 #define PALMTX_NAND_ALE_PHYS	(PALMTX_PHYS_NAND_START | (1 << 24))
 #define PALMTX_NAND_CLE_PHYS	(PALMTX_PHYS_NAND_START | (1 << 25))
-#define PALMTX_NAND_ALE_VIRT	0xff100000
-#define PALMTX_NAND_CLE_VIRT	0xff200000
+#define PALMTX_NAND_ALE_VIRT	IOMEM(0xff100000)
+#define PALMTX_NAND_CLE_VIRT	IOMEM(0xff200000)
 
 /* TOUCHSCREEN */
 #define AC97_LINK_FRAME			21
diff --git a/arch/arm/mach-pxa/include/mach/pxa27x.h b/arch/arm/mach-pxa/include/mach/pxa27x.h
index b9b1bdc..7cff640 100644
--- a/arch/arm/mach-pxa/include/mach/pxa27x.h
+++ b/arch/arm/mach-pxa/include/mach/pxa27x.h
@@ -1,6 +1,7 @@
 #ifndef __MACH_PXA27x_H
 #define __MACH_PXA27x_H
 
+#include <linux/suspend.h>
 #include <mach/hardware.h>
 #include <mach/pxa2xx-regs.h>
 #include <mach/mfp-pxa27x.h>
@@ -21,6 +22,7 @@
 extern void __init pxa27x_map_io(void);
 extern void __init pxa27x_init_irq(void);
 extern int __init pxa27x_set_pwrmode(unsigned int mode);
+extern void pxa27x_cpu_pm_enter(suspend_state_t state);
 
 #define pxa27x_handle_irq	ichp_handle_irq
 
diff --git a/arch/arm/mach-pxa/include/mach/pxa95x.h b/arch/arm/mach-pxa/include/mach/pxa95x.h
new file mode 100644
index 0000000..cbb097c
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/pxa95x.h
@@ -0,0 +1,7 @@
+#ifndef __MACH_PXA95X_H
+#define __MACH_PXA95X_H
+
+#include <mach/pxa3xx.h>
+#include <mach/mfp-pxa930.h>
+
+#endif /* __MACH_PXA95X_H */
diff --git a/arch/arm/mach-pxa/include/mach/pxafb.h b/arch/arm/mach-pxa/include/mach/pxafb.h
index 01a45ac..486b4c5 100644
--- a/arch/arm/mach-pxa/include/mach/pxafb.h
+++ b/arch/arm/mach-pxa/include/mach/pxafb.h
@@ -158,5 +158,18 @@ struct pxafb_mach_info {
 void pxa_set_fb_info(struct device *, struct pxafb_mach_info *);
 unsigned long pxafb_get_hsync_time(struct device *dev);
 
+#ifdef CONFIG_FB_PXA_SMARTPANEL
 extern int pxafb_smart_queue(struct fb_info *info, uint16_t *cmds, int);
 extern int pxafb_smart_flush(struct fb_info *info);
+#else
+static inline int pxafb_smart_queue(struct fb_info *info,
+				    uint16_t *cmds, int n)
+{
+	return 0;
+}
+
+static inline int pxafb_smart_flush(struct fb_info *info)
+{
+	return 0;
+}
+#endif
diff --git a/arch/arm/mach-pxa/include/mach/smemc.h b/arch/arm/mach-pxa/include/mach/smemc.h
index 654adc9..b7de471 100644
--- a/arch/arm/mach-pxa/include/mach/smemc.h
+++ b/arch/arm/mach-pxa/include/mach/smemc.h
@@ -13,7 +13,7 @@
 
 #define PXA2XX_SMEMC_BASE	0x48000000
 #define PXA3XX_SMEMC_BASE	0x4a000000
-#define SMEMC_VIRT		0xf6000000
+#define SMEMC_VIRT		IOMEM(0xf6000000)
 
 #define MDCNFG		(SMEMC_VIRT + 0x00)  /* SDRAM Configuration Register 0 */
 #define MDREFR		(SMEMC_VIRT + 0x04)  /* SDRAM Refresh Control Register */
diff --git a/arch/arm/mach-pxa/include/mach/zeus.h b/arch/arm/mach-pxa/include/mach/zeus.h
index 0641f31..56024f8 100644
--- a/arch/arm/mach-pxa/include/mach/zeus.h
+++ b/arch/arm/mach-pxa/include/mach/zeus.h
@@ -68,7 +68,7 @@
  * Be gentle, and remap that over 32kB...
  */
 
-#define ZEUS_CPLD		(0xf0000000)
+#define ZEUS_CPLD		IOMEM(0xf0000000)
 #define ZEUS_CPLD_VERSION	(ZEUS_CPLD + 0x0000)
 #define ZEUS_CPLD_ISA_IRQ	(ZEUS_CPLD + 0x1000)
 #define ZEUS_CPLD_CONTROL	(ZEUS_CPLD + 0x2000)
@@ -76,7 +76,7 @@
 /* CPLD register bits */
 #define ZEUS_CPLD_CONTROL_CF_RST        0x01
 
-#define ZEUS_PC104IO		(0xf1000000)
+#define ZEUS_PC104IO		IOMEM(0xf1000000)
 
 #define ZEUS_SRAM_SIZE		(256 * 1024)
 
diff --git a/arch/arm/mach-pxa/include/mach/zylonite.h b/arch/arm/mach-pxa/include/mach/zylonite.h
index ea24998..ecca976 100644
--- a/arch/arm/mach-pxa/include/mach/zylonite.h
+++ b/arch/arm/mach-pxa/include/mach/zylonite.h
@@ -19,7 +19,7 @@ extern int wm9713_irq;
 extern int lcd_id;
 extern int lcd_orientation;
 
-#ifdef CONFIG_CPU_PXA300
+#ifdef CONFIG_MACH_ZYLONITE300
 extern void zylonite_pxa300_init(void);
 #else
 static inline void zylonite_pxa300_init(void)
@@ -29,7 +29,7 @@ static inline void zylonite_pxa300_init(void)
 }
 #endif
 
-#ifdef CONFIG_CPU_PXA320
+#ifdef CONFIG_MACH_ZYLONITE320
 extern void zylonite_pxa320_init(void);
 #else
 static inline void zylonite_pxa320_init(void)
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
index 8d9200f..532c5d3 100644
--- a/arch/arm/mach-pxa/irq.c
+++ b/arch/arm/mach-pxa/irq.c
@@ -26,7 +26,7 @@
 
 #include "generic.h"
 
-#define IRQ_BASE		(void __iomem *)io_p2v(0x40d00000)
+#define IRQ_BASE		io_p2v(0x40d00000)
 
 #define ICIP			(0x000)
 #define ICMR			(0x004)
@@ -64,7 +64,7 @@ static inline void __iomem *irq_base(int i)
 		0x40d00130,
 	};
 
-	return (void __iomem *)io_p2v(phys_base[i]);
+	return io_p2v(phys_base[i]);
 }
 
 void pxa_mask_irq(struct irq_data *d)
diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c
index 64540d9..1dd5302 100644
--- a/arch/arm/mach-pxa/lpd270.c
+++ b/arch/arm/mach-pxa/lpd270.c
@@ -479,7 +479,7 @@ static void __init lpd270_init(void)
 
 static struct map_desc lpd270_io_desc[] __initdata = {
 	{
-		.virtual	= LPD270_CPLD_VIRT,
+		.virtual	= (unsigned long)LPD270_CPLD_VIRT,
 		.pfn		= __phys_to_pfn(LPD270_CPLD_PHYS),
 		.length		= LPD270_CPLD_SIZE,
 		.type		= MT_DEVICE,
diff --git a/arch/arm/mach-pxa/palmtreo.c b/arch/arm/mach-pxa/palmtreo.c
index 7346fbf..94e9708 100644
--- a/arch/arm/mach-pxa/palmtreo.c
+++ b/arch/arm/mach-pxa/palmtreo.c
@@ -423,6 +423,7 @@ static void __init palmphone_common_init(void)
 	palmtreo_leds_init();
 }
 
+#ifdef CONFIG_MACH_TREO680
 static void __init treo680_init(void)
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(treo680_pin_config));
@@ -430,7 +431,9 @@ static void __init treo680_init(void)
 	palm27x_mmc_init(GPIO_NR_TREO_SD_DETECT_N, GPIO_NR_TREO680_SD_READONLY,
 			GPIO_NR_TREO680_SD_POWER, 0);
 }
+#endif
 
+#ifdef CONFIG_MACH_CENTRO
 static void __init centro_init(void)
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(centro685_pin_config));
@@ -438,7 +441,9 @@ static void __init centro_init(void)
 	palm27x_mmc_init(GPIO_NR_TREO_SD_DETECT_N, -1,
 			GPIO_NR_CENTRO_SD_POWER, 1);
 }
+#endif
 
+#ifdef CONFIG_MACH_TREO680
 MACHINE_START(TREO680, "Palm Treo 680")
 	.atag_offset    = 0x100,
 	.map_io         = pxa27x_map_io,
@@ -448,7 +453,9 @@ MACHINE_START(TREO680, "Palm Treo 680")
 	.timer          = &pxa_timer,
 	.init_machine   = treo680_init,
 MACHINE_END
+#endif
 
+#ifdef CONFIG_MACH_CENTRO
 MACHINE_START(CENTRO, "Palm Centro 685")
 	.atag_offset    = 0x100,
 	.map_io         = pxa27x_map_io,
@@ -458,3 +465,4 @@ MACHINE_START(CENTRO, "Palm Centro 685")
 	.timer          = &pxa_timer,
 	.init_machine	= centro_init,
 MACHINE_END
+#endif
diff --git a/arch/arm/mach-pxa/palmtx.c b/arch/arm/mach-pxa/palmtx.c
index 2b9e76f..4e3e459 100644
--- a/arch/arm/mach-pxa/palmtx.c
+++ b/arch/arm/mach-pxa/palmtx.c
@@ -247,7 +247,7 @@ static void palmtx_nand_cmd_ctl(struct mtd_info *mtd, int cmd,
 				 unsigned int ctrl)
 {
 	struct nand_chip *this = mtd->priv;
-	unsigned long nandaddr = (unsigned long)this->IO_ADDR_W;
+	char __iomem *nandaddr = this->IO_ADDR_W;
 
 	if (cmd == NAND_CMD_NONE)
 		return;
@@ -315,17 +315,17 @@ static inline void palmtx_nand_init(void) {}
  ******************************************************************************/
 static struct map_desc palmtx_io_desc[] __initdata = {
 {
-	.virtual	= PALMTX_PCMCIA_VIRT,
+	.virtual	= (unsigned long)PALMTX_PCMCIA_VIRT,
 	.pfn		= __phys_to_pfn(PALMTX_PCMCIA_PHYS),
 	.length		= PALMTX_PCMCIA_SIZE,
 	.type		= MT_DEVICE,
 }, {
-	.virtual	= PALMTX_NAND_ALE_VIRT,
+	.virtual	= (unsigned long)PALMTX_NAND_ALE_VIRT,
 	.pfn		= __phys_to_pfn(PALMTX_NAND_ALE_PHYS),
 	.length		= SZ_1M,
 	.type		= MT_DEVICE,
 }, {
-	.virtual	= PALMTX_NAND_CLE_VIRT,
+	.virtual	= (unsigned long)PALMTX_NAND_CLE_VIRT,
 	.pfn		= __phys_to_pfn(PALMTX_NAND_CLE_PHYS),
 	.length		= SZ_1M,
 	.type		= MT_DEVICE,
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index 8746e10..f05f948 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -325,7 +325,7 @@ void __init pxa26x_init_irq(void)
 
 static struct map_desc pxa25x_io_desc[] __initdata = {
 	{	/* Mem Ctl */
-		.virtual	= SMEMC_VIRT,
+		.virtual	= (unsigned long)SMEMC_VIRT,
 		.pfn		= __phys_to_pfn(PXA2XX_SMEMC_BASE),
 		.length		= 0x00200000,
 		.type		= MT_DEVICE
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 2bb5cf8..bc5a98e 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -391,7 +391,7 @@ void __init pxa27x_init_irq(void)
 
 static struct map_desc pxa27x_io_desc[] __initdata = {
 	{	/* Mem Ctl */
-		.virtual	= SMEMC_VIRT,
+		.virtual	= (unsigned long)SMEMC_VIRT,
 		.pfn		= __phys_to_pfn(PXA2XX_SMEMC_BASE),
 		.length		= 0x00200000,
 		.type		= MT_DEVICE
diff --git a/arch/arm/mach-pxa/pxa3xx-ulpi.c b/arch/arm/mach-pxa/pxa3xx-ulpi.c
index ce7168b..e28dfb8 100644
--- a/arch/arm/mach-pxa/pxa3xx-ulpi.c
+++ b/arch/arm/mach-pxa/pxa3xx-ulpi.c
@@ -265,6 +265,7 @@ int pxa3xx_u2d_start_hc(struct usb_bus *host)
 
 	return err;
 }
+EXPORT_SYMBOL_GPL(pxa3xx_u2d_start_hc);
 
 void pxa3xx_u2d_stop_hc(struct usb_bus *host)
 {
@@ -277,6 +278,7 @@ void pxa3xx_u2d_stop_hc(struct usb_bus *host)
 
 	clk_disable(u2d->clk);
 }
+EXPORT_SYMBOL_GPL(pxa3xx_u2d_stop_hc);
 
 static int pxa3xx_u2d_probe(struct platform_device *pdev)
 {
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index f940a13..0737c59 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -393,7 +393,7 @@ void __init pxa3xx_init_irq(void)
 
 static struct map_desc pxa3xx_io_desc[] __initdata = {
 	{	/* Mem Ctl */
-		.virtual	= SMEMC_VIRT,
+		.virtual	= (unsigned long)SMEMC_VIRT,
 		.pfn		= __phys_to_pfn(PXA3XX_SMEMC_BASE),
 		.length		= 0x00200000,
 		.type		= MT_DEVICE
diff --git a/arch/arm/mach-pxa/saarb.c b/arch/arm/mach-pxa/saarb.c
index 3c988b6f..3e999e3 100644
--- a/arch/arm/mach-pxa/saarb.c
+++ b/arch/arm/mach-pxa/saarb.c
@@ -24,6 +24,7 @@
 #include <mach/hardware.h>
 #include <mach/mfp.h>
 #include <mach/mfp-pxa930.h>
+#include <mach/pxa95x.h>
 
 #include "generic.h"
 
diff --git a/arch/arm/mach-pxa/z2.c b/arch/arm/mach-pxa/z2.c
index 84ed72d..ead32c9 100644
--- a/arch/arm/mach-pxa/z2.c
+++ b/arch/arm/mach-pxa/z2.c
@@ -686,7 +686,8 @@ static void z2_power_off(void)
 	 */
 	PSPR = 0x0;
 	local_irq_disable();
-	pxa27x_cpu_suspend(PWRMODE_DEEPSLEEP, PHYS_OFFSET - PAGE_OFFSET);
+	pxa27x_set_pwrmode(PWRMODE_DEEPSLEEP);
+	pxa27x_cpu_pm_enter(PM_SUSPEND_MEM);
 }
 #else
 #define z2_power_off   NULL
diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c
index c424e7d..498b83b 100644
--- a/arch/arm/mach-pxa/zeus.c
+++ b/arch/arm/mach-pxa/zeus.c
@@ -860,25 +860,25 @@ static void __init zeus_init(void)
 
 static struct map_desc zeus_io_desc[] __initdata = {
 	{
-		.virtual = ZEUS_CPLD_VERSION,
+		.virtual = (unsigned long)ZEUS_CPLD_VERSION,
 		.pfn     = __phys_to_pfn(ZEUS_CPLD_VERSION_PHYS),
 		.length  = 0x1000,
 		.type    = MT_DEVICE,
 	},
 	{
-		.virtual = ZEUS_CPLD_ISA_IRQ,
+		.virtual = (unsigned long)ZEUS_CPLD_ISA_IRQ,
 		.pfn     = __phys_to_pfn(ZEUS_CPLD_ISA_IRQ_PHYS),
 		.length  = 0x1000,
 		.type    = MT_DEVICE,
 	},
 	{
-		.virtual = ZEUS_CPLD_CONTROL,
+		.virtual = (unsigned long)ZEUS_CPLD_CONTROL,
 		.pfn     = __phys_to_pfn(ZEUS_CPLD_CONTROL_PHYS),
 		.length  = 0x1000,
 		.type    = MT_DEVICE,
 	},
 	{
-		.virtual = ZEUS_PC104IO,
+		.virtual = (unsigned long)ZEUS_PC104IO,
 		.pfn     = __phys_to_pfn(ZEUS_PC104IO_PHYS),
 		.length  = 0x00800000,
 		.type    = MT_DEVICE,
diff --git a/arch/arm/mach-realview/hotplug.c b/arch/arm/mach-realview/hotplug.c
index a87523d..ac1aed2 100644
--- a/arch/arm/mach-realview/hotplug.c
+++ b/arch/arm/mach-realview/hotplug.c
@@ -69,7 +69,7 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
 		    :
 		    : "memory", "cc");
 
-		if (pen_release == cpu) {
+		if (pen_release == cpu_logical_map(cpu)) {
 			/*
 			 * OK, proper wakeup, we're done
 			 */
diff --git a/arch/arm/mach-realview/include/mach/debug-macro.S b/arch/arm/mach-realview/include/mach/debug-macro.S
index fb4901c..8cc372d 100644
--- a/arch/arm/mach-realview/include/mach/debug-macro.S
+++ b/arch/arm/mach-realview/include/mach/debug-macro.S
@@ -10,23 +10,10 @@
  * published by the Free Software Foundation.
  */
 
-#if defined(CONFIG_MACH_REALVIEW_EB) || \
-    defined(CONFIG_MACH_REALVIEW_PB11MP) || \
-    defined(CONFIG_MACH_REALVIEW_PBA8) || \
-    defined(CONFIG_MACH_REALVIEW_PBX)
-#ifndef DEBUG_LL_UART_OFFSET
+#ifdef CONFIG_DEBUG_REALVIEW_STD_PORT
 #define DEBUG_LL_UART_OFFSET	0x00009000
-#elif DEBUG_LL_UART_OFFSET != 0x00009000
-#warning "DEBUG_LL_UART_OFFSET already defined to a different value"
-#endif
-#endif
-
-#ifdef CONFIG_MACH_REALVIEW_PB1176
-#ifndef DEBUG_LL_UART_OFFSET
+#elif defined(CONFIG_DEBUG_REALVIEW_PB1176_PORT)
 #define DEBUG_LL_UART_OFFSET	0x0010c000
-#elif DEBUG_LL_UART_OFFSET != 0x0010c000
-#warning "DEBUG_LL_UART_OFFSET already defined to a different value"
-#endif
 #endif
 
 #ifndef DEBUG_LL_UART_OFFSET
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
index 7245a55..3700cf3 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/arch/arm/mach-s3c2410/Kconfig
@@ -8,7 +8,6 @@ config CPU_S3C2410
 	select CPU_ARM920T
 	select S3C_GPIO_PULL_UP
 	select S3C2410_CLOCK
-	select S3C2410_GPIO
 	select CPU_LLSERIAL_S3C2410
 	select S3C2410_PM if PM
 	select S3C2410_CPUFREQ if CPU_FREQ_S3C24XX
@@ -28,11 +27,6 @@ config S3C2410_PM
 	help
 	  Power Management code common to S3C2410 and better
 
-config S3C2410_GPIO
-	bool
-	help
-	  GPIO code for S3C2410 and similar processors
-
 config SIMTEC_NOR
 	bool
 	help
diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
index 8169535..782fd81 100644
--- a/arch/arm/mach-s3c2410/Makefile
+++ b/arch/arm/mach-s3c2410/Makefile
@@ -13,7 +13,6 @@ obj-$(CONFIG_CPU_S3C2410)	+= s3c2410.o
 obj-$(CONFIG_CPU_S3C2410_DMA)	+= dma.o
 obj-$(CONFIG_CPU_S3C2410_DMA)	+= dma.o
 obj-$(CONFIG_S3C2410_PM)	+= pm.o sleep.o
-obj-$(CONFIG_S3C2410_GPIO)	+= gpio.o
 obj-$(CONFIG_S3C2410_CPUFREQ)	+= cpu-freq.o
 obj-$(CONFIG_S3C2410_PLLTABLE)	+= pll.o
 
diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c
index 0d8e043..dbe43df 100644
--- a/arch/arm/mach-s3c2410/dma.c
+++ b/arch/arm/mach-s3c2410/dma.c
@@ -47,38 +47,26 @@ static struct s3c24xx_dma_map __initdata s3c2410_dma_mappings[] = {
 		.channels[0]	= S3C2410_DCON_CH0_SDI | DMA_CH_VALID,
 		.channels[2]	= S3C2410_DCON_CH2_SDI | DMA_CH_VALID,
 		.channels[3]	= S3C2410_DCON_CH3_SDI | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
-		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
 	},
 	[DMACH_SPI0] = {
 		.name		= "spi0",
 		.channels[1]	= S3C2410_DCON_CH1_SPI | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_SPI + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + S3C2410_SPRDAT,
 	},
 	[DMACH_SPI1] = {
 		.name		= "spi1",
 		.channels[3]	= S3C2410_DCON_CH3_SPI | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
 	},
 	[DMACH_UART0] = {
 		.name		= "uart0",
 		.channels[0]	= S3C2410_DCON_CH0_UART0 | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
 	},
 	[DMACH_UART1] = {
 		.name		= "uart1",
 		.channels[1]	= S3C2410_DCON_CH1_UART1 | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
 	},
       	[DMACH_UART2] = {
 		.name		= "uart2",
 		.channels[3]	= S3C2410_DCON_CH3_UART2 | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
 	},
 	[DMACH_TIMER] = {
 		.name		= "timer",
@@ -90,12 +78,10 @@ static struct s3c24xx_dma_map __initdata s3c2410_dma_mappings[] = {
 		.name		= "i2s-sdi",
 		.channels[1]	= S3C2410_DCON_CH1_I2SSDI | DMA_CH_VALID,
 		.channels[2]	= S3C2410_DCON_CH2_I2SSDI | DMA_CH_VALID,
-		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
 	},
 	[DMACH_I2S_OUT] = {
 		.name		= "i2s-sdo",
 		.channels[2]	= S3C2410_DCON_CH2_I2SSDO | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
 	},
 	[DMACH_USB_EP1] = {
 		.name		= "usb-ep1",
diff --git a/arch/arm/mach-s3c2410/gpio.c b/arch/arm/mach-s3c2410/gpio.c
deleted file mode 100644
index 9664e01..0000000
--- a/arch/arm/mach-s3c2410/gpio.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/gpio.c
- *
- * Copyright (c) 2004-2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 GPIO support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/gpio-fns.h>
-#include <asm/irq.h>
-
-#include <mach/regs-gpio.h>
-
-int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
-			   unsigned int config)
-{
-	void __iomem *reg = S3C24XX_EINFLT0;
-	unsigned long flags;
-	unsigned long val;
-
-	if (pin < S3C2410_GPG(8) || pin > S3C2410_GPG(15))
-		return -EINVAL;
-
-	config &= 0xff;
-
-	pin -= S3C2410_GPG(8);
-	reg += pin & ~3;
-
-	local_irq_save(flags);
-
-	/* update filter width and clock source */
-
-	val = __raw_readl(reg);
-	val &= ~(0xff << ((pin & 3) * 8));
-	val |= config << ((pin & 3) * 8);
-	__raw_writel(val, reg);
-
-	/* update filter enable */
-
-	val = __raw_readl(S3C24XX_EXTINT2);
-	val &= ~(1 << ((pin * 4) + 3));
-	val |= on << ((pin * 4) + 3);
-	__raw_writel(val, S3C24XX_EXTINT2);
-
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_irqfilter);
diff --git a/arch/arm/mach-s3c2410/include/mach/map.h b/arch/arm/mach-s3c2410/include/mach/map.h
index 425552d..4cf495f 100644
--- a/arch/arm/mach-s3c2410/include/mach/map.h
+++ b/arch/arm/mach-s3c2410/include/mach/map.h
@@ -14,9 +14,53 @@
 #define __ASM_ARCH_MAP_H
 
 #include <plat/map-base.h>
-#include <plat/map.h>
 
-#define S3C2410_ADDR(x)		S3C_ADDR(x)
+/*
+ * S3C2410 UART offset is 0x4000 but the other SoCs are 0x400.
+ * So need to define it, and here is to avoid redefinition warning.
+ */
+#define S3C_UART_OFFSET		(0x4000)
+
+#include <plat/map-s3c.h>
+
+/*
+ * interrupt controller is the first thing we put in, to make
+ * the assembly code for the irq detection easier
+ */
+#define S3C2410_PA_IRQ		(0x4A000000)
+#define S3C24XX_SZ_IRQ		SZ_1M
+
+/* memory controller registers */
+#define S3C2410_PA_MEMCTRL	(0x48000000)
+#define S3C24XX_SZ_MEMCTRL	SZ_1M
+
+/* UARTs */
+#define S3C_VA_UARTx(uart)	(S3C_VA_UART + ((uart * S3C_UART_OFFSET)))
+
+/* Timers */
+#define S3C2410_PA_TIMER	(0x51000000)
+#define S3C24XX_SZ_TIMER	SZ_1M
+
+/* Clock and Power management */
+#define S3C24XX_SZ_CLKPWR	SZ_1M
+
+/* USB Device port */
+#define S3C2410_PA_USBDEV	(0x52000000)
+#define S3C24XX_SZ_USBDEV	SZ_1M
+
+/* Watchdog */
+#define S3C2410_PA_WATCHDOG	(0x53000000)
+#define S3C24XX_SZ_WATCHDOG	SZ_1M
+
+/* Standard size definitions for peripheral blocks. */
+
+#define S3C24XX_SZ_UART		SZ_1M
+#define S3C24XX_SZ_IIS		SZ_1M
+#define S3C24XX_SZ_ADC		SZ_1M
+#define S3C24XX_SZ_SPI		SZ_1M
+#define S3C24XX_SZ_SDI		SZ_1M
+#define S3C24XX_SZ_NAND		SZ_1M
+#define S3C24XX_SZ_GPIO		SZ_1M
 
 /* USB host controller */
 #define S3C2410_PA_USBHOST (0x49000000)
@@ -75,10 +119,8 @@
 
 /* S3C2412 memory and IO controls */
 #define S3C2412_PA_SSMC	(0x4F000000)
-#define S3C2412_VA_SSMC	S3C_ADDR_CPU(0x00000000)
 
 #define S3C2412_PA_EBI	(0x48800000)
-#define S3C2412_VA_EBI	S3C_ADDR_CPU(0x00010000)
 
 /* physical addresses of all the chip-select areas */
 
@@ -100,12 +142,10 @@
 #define S3C24XX_PA_DMA      S3C2410_PA_DMA
 #define S3C24XX_PA_CLKPWR   S3C2410_PA_CLKPWR
 #define S3C24XX_PA_LCD      S3C2410_PA_LCD
-#define S3C24XX_PA_UART     S3C2410_PA_UART
 #define S3C24XX_PA_TIMER    S3C2410_PA_TIMER
 #define S3C24XX_PA_USBDEV   S3C2410_PA_USBDEV
 #define S3C24XX_PA_WATCHDOG S3C2410_PA_WATCHDOG
 #define S3C24XX_PA_IIS      S3C2410_PA_IIS
-#define S3C24XX_PA_GPIO     S3C2410_PA_GPIO
 #define S3C24XX_PA_RTC      S3C2410_PA_RTC
 #define S3C24XX_PA_ADC      S3C2410_PA_ADC
 #define S3C24XX_PA_SPI      S3C2410_PA_SPI
diff --git a/arch/arm/mach-s3c2412/Kconfig b/arch/arm/mach-s3c2412/Kconfig
index c2cf4e5..b8b9029 100644
--- a/arch/arm/mach-s3c2412/Kconfig
+++ b/arch/arm/mach-s3c2412/Kconfig
@@ -9,7 +9,6 @@ config CPU_S3C2412
 	select CPU_LLSERIAL_S3C2440
 	select S3C2412_PM if PM
 	select S3C2412_DMA if S3C2410_DMA
-	select S3C2410_GPIO
 	help
 	  Support for the S3C2412 and S3C2413 SoCs from the S3C24XX line
 
diff --git a/arch/arm/mach-s3c2412/Makefile b/arch/arm/mach-s3c2412/Makefile
index 6c48a91..7e4d95f 100644
--- a/arch/arm/mach-s3c2412/Makefile
+++ b/arch/arm/mach-s3c2412/Makefile
@@ -12,7 +12,6 @@ obj-				:=
 obj-$(CONFIG_CPU_S3C2412)	+= s3c2412.o
 obj-$(CONFIG_CPU_S3C2412)	+= irq.o
 obj-$(CONFIG_CPU_S3C2412)	+= clock.o
-obj-$(CONFIG_CPU_S3C2412)	+= gpio.o
 obj-$(CONFIG_S3C2412_DMA)	+= dma.o
 obj-$(CONFIG_S3C2412_PM)	+= pm.o
 obj-$(CONFIG_S3C2412_PM_SLEEP)	+= sleep.o
diff --git a/arch/arm/mach-s3c2412/dma.c b/arch/arm/mach-s3c2412/dma.c
index 7abecfc..c61e326 100644
--- a/arch/arm/mach-s3c2412/dma.c
+++ b/arch/arm/mach-s3c2412/dma.c
@@ -50,64 +50,46 @@ static struct s3c24xx_dma_map __initdata s3c2412_dma_mappings[] = {
 		.name		= "sdi",
 		.channels	= MAP(S3C2412_DMAREQSEL_SDI),
 		.channels_rx	= MAP(S3C2412_DMAREQSEL_SDI),
-		.hw_addr.to	= S3C2410_PA_SDI + S3C2410_SDIDATA,
-		.hw_addr.from	= S3C2410_PA_SDI + S3C2410_SDIDATA,
 	},
 	[DMACH_SPI0] = {
 		.name		= "spi0",
 		.channels	= MAP(S3C2412_DMAREQSEL_SPI0TX),
 		.channels_rx	= MAP(S3C2412_DMAREQSEL_SPI0RX),
-		.hw_addr.to	= S3C2410_PA_SPI + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + S3C2410_SPRDAT,
 	},
 	[DMACH_SPI1] = {
 		.name		= "spi1",
 		.channels	= MAP(S3C2412_DMAREQSEL_SPI1TX),
 		.channels_rx	= MAP(S3C2412_DMAREQSEL_SPI1RX),
-		.hw_addr.to	= S3C2410_PA_SPI + S3C2412_SPI1 + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + S3C2412_SPI1  + S3C2410_SPRDAT,
 	},
 	[DMACH_UART0] = {
 		.name		= "uart0",
 		.channels	= MAP(S3C2412_DMAREQSEL_UART0_0),
 		.channels_rx	= MAP(S3C2412_DMAREQSEL_UART0_0),
-		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
 	},
 	[DMACH_UART1] = {
 		.name		= "uart1",
 		.channels	= MAP(S3C2412_DMAREQSEL_UART1_0),
 		.channels_rx	= MAP(S3C2412_DMAREQSEL_UART1_0),
-		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
 	},
       	[DMACH_UART2] = {
 		.name		= "uart2",
 		.channels	= MAP(S3C2412_DMAREQSEL_UART2_0),
 		.channels_rx	= MAP(S3C2412_DMAREQSEL_UART2_0),
-		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
 	},
 	[DMACH_UART0_SRC2] = {
 		.name		= "uart0",
 		.channels	= MAP(S3C2412_DMAREQSEL_UART0_1),
 		.channels_rx	= MAP(S3C2412_DMAREQSEL_UART0_1),
-		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
 	},
 	[DMACH_UART1_SRC2] = {
 		.name		= "uart1",
 		.channels	= MAP(S3C2412_DMAREQSEL_UART1_1),
 		.channels_rx	= MAP(S3C2412_DMAREQSEL_UART1_1),
-		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
 	},
       	[DMACH_UART2_SRC2] = {
 		.name		= "uart2",
 		.channels	= MAP(S3C2412_DMAREQSEL_UART2_1),
 		.channels_rx	= MAP(S3C2412_DMAREQSEL_UART2_1),
-		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
 	},
 	[DMACH_TIMER] = {
 		.name		= "timer",
diff --git a/arch/arm/mach-s3c2412/gpio.c b/arch/arm/mach-s3c2412/gpio.c
deleted file mode 100644
index 3404a87..0000000
--- a/arch/arm/mach-s3c2412/gpio.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/* linux/arch/arm/mach-s3c2412/gpio.c
- *
- * Copyright (c) 2007 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * http://armlinux.simtec.co.uk/.
- *
- * S3C2412/S3C2413 specific GPIO 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/module.h>
-#include <linux/interrupt.h>
-#include <linux/gpio.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include <mach/regs-gpio.h>
-#include <mach/hardware.h>
-
-#include <plat/gpio-core.h>
-
-int s3c2412_gpio_set_sleepcfg(unsigned int pin, unsigned int state)
-{
-	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-	unsigned long offs = pin - chip->chip.base;
-	unsigned long flags;
-	unsigned long slpcon;
-
-	offs *= 2;
-
-	if (pin < S3C2410_GPB(0))
-		return -EINVAL;
-
-	if (pin >= S3C2410_GPF(0) &&
-	    pin <= S3C2410_GPG(16))
-		return -EINVAL;
-
-	if (pin > S3C2410_GPH(16))
-		return -EINVAL;
-
-	local_irq_save(flags);
-
-	slpcon = __raw_readl(chip->base + 0x0C);
-
-	slpcon &= ~(3 << offs);
-	slpcon |= state << offs;
-
-	__raw_writel(slpcon, chip->base + 0x0C);
-
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-EXPORT_SYMBOL(s3c2412_gpio_set_sleepcfg);
diff --git a/arch/arm/mach-s3c2440/Kconfig b/arch/arm/mach-s3c2440/Kconfig
index 50825a3..c461fb8 100644
--- a/arch/arm/mach-s3c2440/Kconfig
+++ b/arch/arm/mach-s3c2440/Kconfig
@@ -8,7 +8,6 @@ config CPU_S3C2440
 	select S3C_GPIO_PULL_UP
 	select S3C2410_CLOCK
 	select S3C2410_PM if PM
-	select S3C2410_GPIO
 	select S3C2440_DMA if S3C2410_DMA
 	select CPU_S3C244X
 	select CPU_LLSERIAL_S3C2440
@@ -20,7 +19,6 @@ config CPU_S3C2442
 	select CPU_ARM920T
 	select S3C_GPIO_PULL_DOWN
 	select S3C2410_CLOCK
-	select S3C2410_GPIO
 	select S3C2410_PM if PM
 	select CPU_S3C244X
 	select CPU_LLSERIAL_S3C2440
diff --git a/arch/arm/mach-s3c2440/dma.c b/arch/arm/mach-s3c2440/dma.c
index 3b0529f..0e73f8f 100644
--- a/arch/arm/mach-s3c2440/dma.c
+++ b/arch/arm/mach-s3c2440/dma.c
@@ -48,38 +48,26 @@ static struct s3c24xx_dma_map __initdata s3c2440_dma_mappings[] = {
 		.channels[1]	= S3C2440_DCON_CH1_SDI | DMA_CH_VALID,
 		.channels[2]	= S3C2410_DCON_CH2_SDI | DMA_CH_VALID,
 		.channels[3]	= S3C2410_DCON_CH3_SDI | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
-		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
 	},
 	[DMACH_SPI0] = {
 		.name		= "spi0",
 		.channels[1]	= S3C2410_DCON_CH1_SPI | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_SPI + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + S3C2410_SPRDAT,
 	},
 	[DMACH_SPI1] = {
 		.name		= "spi1",
 		.channels[3]	= S3C2410_DCON_CH3_SPI | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
 	},
 	[DMACH_UART0] = {
 		.name		= "uart0",
 		.channels[0]	= S3C2410_DCON_CH0_UART0 | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
 	},
 	[DMACH_UART1] = {
 		.name		= "uart1",
 		.channels[1]	= S3C2410_DCON_CH1_UART1 | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
 	},
       	[DMACH_UART2] = {
 		.name		= "uart2",
 		.channels[3]	= S3C2410_DCON_CH3_UART2 | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
 	},
 	[DMACH_TIMER] = {
 		.name		= "timer",
@@ -91,31 +79,26 @@ static struct s3c24xx_dma_map __initdata s3c2440_dma_mappings[] = {
 		.name		= "i2s-sdi",
 		.channels[1]	= S3C2410_DCON_CH1_I2SSDI | DMA_CH_VALID,
 		.channels[2]	= S3C2410_DCON_CH2_I2SSDI | DMA_CH_VALID,
-		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
 	},
 	[DMACH_I2S_OUT] = {
 		.name		= "i2s-sdo",
 		.channels[0]	= S3C2440_DCON_CH0_I2SSDO | DMA_CH_VALID,
 		.channels[2]	= S3C2410_DCON_CH2_I2SSDO | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
 	},
 	[DMACH_PCM_IN] = {
 		.name		= "pcm-in",
 		.channels[0]	= S3C2440_DCON_CH0_PCMIN | DMA_CH_VALID,
 		.channels[2]	= S3C2440_DCON_CH2_PCMIN | DMA_CH_VALID,
-		.hw_addr.from	= S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
 	},
 	[DMACH_PCM_OUT] = {
 		.name		= "pcm-out",
 		.channels[1]	= S3C2440_DCON_CH1_PCMOUT | DMA_CH_VALID,
 		.channels[3]	= S3C2440_DCON_CH3_PCMOUT | DMA_CH_VALID,
-		.hw_addr.to	= S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
 	},
 	[DMACH_MIC_IN] = {
 		.name		= "mic-in",
 		.channels[2]	= S3C2440_DCON_CH2_MICIN | DMA_CH_VALID,
 		.channels[3]	= S3C2440_DCON_CH3_MICIN | DMA_CH_VALID,
-		.hw_addr.from	= S3C2440_PA_AC97 + S3C_AC97_MIC_DATA,
 	},
 	[DMACH_USB_EP1] = {
 		.name		= "usb-ep1",
diff --git a/arch/arm/mach-s3c2443/dma.c b/arch/arm/mach-s3c2443/dma.c
index 3f65868..fe52151 100644
--- a/arch/arm/mach-s3c2443/dma.c
+++ b/arch/arm/mach-s3c2443/dma.c
@@ -54,68 +54,46 @@ static struct s3c24xx_dma_map __initdata s3c2443_dma_mappings[] = {
 	[DMACH_SDI] = {
 		.name		= "sdi",
 		.channels	= MAP(S3C2443_DMAREQSEL_SDI),
-		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
-		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
 	},
 	[DMACH_SPI0] = {
 		.name		= "spi0",
 		.channels	= MAP(S3C2443_DMAREQSEL_SPI0TX),
-		.hw_addr.to	= S3C2410_PA_SPI + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + S3C2410_SPRDAT,
 	},
 	[DMACH_SPI1] = {
 		.name		= "spi1",
 		.channels	= MAP(S3C2443_DMAREQSEL_SPI1TX),
-		.hw_addr.to	= S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
 	},
 	[DMACH_UART0] = {
 		.name		= "uart0",
 		.channels	= MAP(S3C2443_DMAREQSEL_UART0_0),
-		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
 	},
 	[DMACH_UART1] = {
 		.name		= "uart1",
 		.channels	= MAP(S3C2443_DMAREQSEL_UART1_0),
-		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
 	},
       	[DMACH_UART2] = {
 		.name		= "uart2",
 		.channels	= MAP(S3C2443_DMAREQSEL_UART2_0),
-		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
 	},
       	[DMACH_UART3] = {
 		.name		= "uart3",
 		.channels	= MAP(S3C2443_DMAREQSEL_UART3_0),
-		.hw_addr.to	= S3C2443_PA_UART3 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2443_PA_UART3 + S3C2410_URXH,
 	},
 	[DMACH_UART0_SRC2] = {
 		.name		= "uart0",
 		.channels	= MAP(S3C2443_DMAREQSEL_UART0_1),
-		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
 	},
 	[DMACH_UART1_SRC2] = {
 		.name		= "uart1",
 		.channels	= MAP(S3C2443_DMAREQSEL_UART1_1),
-		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
 	},
       	[DMACH_UART2_SRC2] = {
 		.name		= "uart2",
 		.channels	= MAP(S3C2443_DMAREQSEL_UART2_1),
-		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
 	},
       	[DMACH_UART3_SRC2] = {
 		.name		= "uart3",
 		.channels	= MAP(S3C2443_DMAREQSEL_UART3_1),
-		.hw_addr.to	= S3C2443_PA_UART3 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2443_PA_UART3 + S3C2410_URXH,
 	},
 	[DMACH_TIMER] = {
 		.name		= "timer",
@@ -124,27 +102,22 @@ static struct s3c24xx_dma_map __initdata s3c2443_dma_mappings[] = {
 	[DMACH_I2S_IN] = {
 		.name		= "i2s-sdi",
 		.channels	= MAP(S3C2443_DMAREQSEL_I2SRX),
-		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
 	},
 	[DMACH_I2S_OUT] = {
 		.name		= "i2s-sdo",
 		.channels	= MAP(S3C2443_DMAREQSEL_I2STX),
-		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
 	},
 	[DMACH_PCM_IN] = {
 		.name		= "pcm-in",
 		.channels	= MAP(S3C2443_DMAREQSEL_PCMIN),
-		.hw_addr.from	= S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
 	},
 	[DMACH_PCM_OUT] = {
 		.name		= "pcm-out",
 		.channels	= MAP(S3C2443_DMAREQSEL_PCMOUT),
-		.hw_addr.to	= S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
 	},
 	[DMACH_MIC_IN] = {
 		.name		= "mic-in",
 		.channels	= MAP(S3C2443_DMAREQSEL_MICIN),
-		.hw_addr.from	= S3C2440_PA_AC97 + S3C_AC97_MIC_DATA,
 	},
 };
 
diff --git a/arch/arm/mach-s3c64xx/cpu.c b/arch/arm/mach-s3c64xx/cpu.c
index 8dc0576..c704783 100644
--- a/arch/arm/mach-s3c64xx/cpu.c
+++ b/arch/arm/mach-s3c64xx/cpu.c
@@ -44,16 +44,16 @@ static const char name_s3c6410[] = "S3C6410";
 
 static struct cpu_table cpu_ids[] __initdata = {
 	{
-		.idcode		= 0x36400000,
-		.idmask		= 0xfffff000,
+		.idcode		= S3C6400_CPU_ID,
+		.idmask		= S3C64XX_CPU_MASK,
 		.map_io		= s3c6400_map_io,
 		.init_clocks	= s3c6400_init_clocks,
 		.init_uarts	= s3c6400_init_uarts,
 		.init		= s3c6400_init,
 		.name		= name_s3c6400,
 	}, {
-		.idcode		= 0x36410100,
-		.idmask		= 0xffffff00,
+		.idcode		= S3C6410_CPU_ID,
+		.idmask		= S3C64XX_CPU_MASK,
 		.map_io		= s3c6410_map_io,
 		.init_clocks	= s3c6410_init_clocks,
 		.init_uarts	= s3c6410_init_uarts,
@@ -141,23 +141,15 @@ void __init s3c6400_common_init_uarts(struct s3c2410_uartcfg *cfg, int no)
 
 void __init s3c64xx_init_io(struct map_desc *mach_desc, int size)
 {
-	unsigned long idcode;
-
 	/* initialise the io descriptors we need for initialisation */
 	iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));
 	iotable_init(mach_desc, size);
 	init_consistent_dma_size(SZ_8M);
 
-	idcode = __raw_readl(S3C_VA_SYS + 0x118);
-	if (!idcode) {
-		/* S3C6400 has the ID register in a different place,
-		 * and needs a write before it can be read. */
-
-		__raw_writel(0x0, S3C_VA_SYS + 0xA1C);
-		idcode = __raw_readl(S3C_VA_SYS + 0xA1C);
-	}
+	/* detect cpu id */
+	s3c64xx_init_cpu();
 
-	s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids));
+	s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
 }
 
 static __init int s3c64xx_sysdev_init(void)
diff --git a/arch/arm/mach-s3c64xx/include/mach/map.h b/arch/arm/mach-s3c64xx/include/mach/map.h
index a1f13f0..23a1d71 100644
--- a/arch/arm/mach-s3c64xx/include/mach/map.h
+++ b/arch/arm/mach-s3c64xx/include/mach/map.h
@@ -16,6 +16,7 @@
 #define __ASM_ARCH_MAP_H __FILE__
 
 #include <plat/map-base.h>
+#include <plat/map-s3c.h>
 
 /*
  * Post-mux Chip Select Regions Xm0CSn_
@@ -83,7 +84,6 @@
 #define S3C64XX_PA_IIC1		(0x7F00F000)
 
 #define S3C64XX_PA_GPIO		(0x7F008000)
-#define S3C64XX_VA_GPIO		S3C_ADDR_CPU(0x00000000)
 #define S3C64XX_SZ_GPIO		SZ_4K
 
 #define S3C64XX_PA_SDRAM	(0x50000000)
@@ -94,16 +94,10 @@
 #define S3C64XX_PA_VIC1		(0x71300000)
 
 #define S3C64XX_PA_MODEM	(0x74108000)
-#define S3C64XX_VA_MODEM	S3C_ADDR_CPU(0x00100000)
 
 #define S3C64XX_PA_USBHOST	(0x74300000)
 
 #define S3C64XX_PA_USB_HSPHY	(0x7C100000)
-#define S3C64XX_VA_USB_HSPHY	S3C_ADDR_CPU(0x00200000)
-
-/* place VICs close together */
-#define VA_VIC0			(S3C_VA_IRQ + 0x00)
-#define VA_VIC1			(S3C_VA_IRQ + 0x10000)
 
 /* compatibiltiy defines. */
 #define S3C_PA_TIMER		S3C64XX_PA_TIMER
@@ -119,7 +113,6 @@
 #define S3C_PA_FB		S3C64XX_PA_FB
 #define S3C_PA_USBHOST		S3C64XX_PA_USBHOST
 #define S3C_PA_USB_HSOTG	S3C64XX_PA_USB_HSOTG
-#define S3C_VA_USB_HSPHY	S3C64XX_VA_USB_HSPHY
 #define S3C_PA_RTC		S3C64XX_PA_RTC
 #define S3C_PA_WDT		S3C64XX_PA_WATCHDOG
 
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c
index 4c76e08..8065803 100644
--- a/arch/arm/mach-s3c64xx/mach-crag6410.c
+++ b/arch/arm/mach-s3c64xx/mach-crag6410.c
@@ -329,9 +329,6 @@ static struct platform_device *crag6410_devices[] __initdata = {
 	&s3c_device_fb,
 	&s3c_device_ohci,
 	&s3c_device_usb_hsotg,
-	&s3c_device_adc,
-	&s3c_device_rtc,
-	&s3c_device_ts,
 	&s3c_device_timer[0],
 	&s3c64xx_device_iis0,
 	&s3c64xx_device_iis1,
diff --git a/arch/arm/mach-s3c64xx/mach-mini6410.c b/arch/arm/mach-s3c64xx/mach-mini6410.c
index e91f63f..fb8969a 100644
--- a/arch/arm/mach-s3c64xx/mach-mini6410.c
+++ b/arch/arm/mach-s3c64xx/mach-mini6410.c
@@ -205,12 +205,6 @@ static struct platform_device mini6410_lcd_powerdev = {
 	.dev.platform_data	= &mini6410_lcd_power_data,
 };
 
-static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
-	.delay			= 10000,
-	.presc			= 49,
-	.oversampling_shift	= 2,
-};
-
 static struct platform_device *mini6410_devices[] __initdata = {
 	&mini6410_device_eth,
 	&s3c_device_hsmmc0,
@@ -319,7 +313,7 @@ static void __init mini6410_machine_init(void)
 
 	s3c_nand_set_platdata(&mini6410_nand_info);
 	s3c_fb_set_platdata(&mini6410_lcd_pdata);
-	s3c24xx_ts_set_platdata(&s3c_ts_platform);
+	s3c24xx_ts_set_platdata(NULL);
 
 	/* configure nCS1 width to 16 bits */
 
diff --git a/arch/arm/mach-s3c64xx/mach-real6410.c b/arch/arm/mach-s3c64xx/mach-real6410.c
index 10870cb..93170d4 100644
--- a/arch/arm/mach-s3c64xx/mach-real6410.c
+++ b/arch/arm/mach-s3c64xx/mach-real6410.c
@@ -198,12 +198,6 @@ static struct platform_device *real6410_devices[] __initdata = {
 	&s3c_device_ohci,
 };
 
-static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
-	.delay			= 10000,
-	.presc			= 49,
-	.oversampling_shift	= 2,
-};
-
 static void __init real6410_map_io(void)
 {
 	u32 tmp;
@@ -300,7 +294,7 @@ static void __init real6410_machine_init(void)
 
 	s3c_fb_set_platdata(&real6410_lcd_pdata);
 	s3c_nand_set_platdata(&real6410_nand_info);
-	s3c24xx_ts_set_platdata(&s3c_ts_platform);
+	s3c24xx_ts_set_platdata(NULL);
 
 	/* configure nCS1 width to 16 bits */
 
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c
index 7b66ede..5f147c3 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6410.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c
@@ -619,12 +619,6 @@ static struct i2c_board_info i2c_devs1[] __initdata = {
 	{ I2C_BOARD_INFO("24c128", 0x57), },	/* Samsung S524AD0XD1 */
 };
 
-static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
-	.delay			= 10000,
-	.presc			= 49,
-	.oversampling_shift	= 2,
-};
-
 /* LCD Backlight data */
 static struct samsung_bl_gpio_info smdk6410_bl_gpio_info = {
 	.no = S3C64XX_GPF(15),
@@ -666,7 +660,7 @@ static void __init smdk6410_machine_init(void)
 
 	samsung_keypad_set_platdata(&smdk6410_keypad_data);
 
-	s3c24xx_ts_set_platdata(&s3c_ts_platform);
+	s3c24xx_ts_set_platdata(NULL);
 
 	/* configure nCS1 width to 16 bits */
 
diff --git a/arch/arm/mach-s5p64x0/dev-spi.c b/arch/arm/mach-s5p64x0/dev-spi.c
index ac825e8..1fd9c79 100644
--- a/arch/arm/mach-s5p64x0/dev-spi.c
+++ b/arch/arm/mach-s5p64x0/dev-spi.c
@@ -21,6 +21,7 @@
 #include <mach/regs-clock.h>
 #include <mach/spi-clocks.h>
 
+#include <plat/cpu.h>
 #include <plat/s3c64xx-spi.h>
 #include <plat/gpio-cfg.h>
 
@@ -185,11 +186,8 @@ struct platform_device s5p64x0_device_spi1 = {
 
 void __init s5p64x0_spi_set_info(int cntrlr, int src_clk_nr, int num_cs)
 {
-	unsigned int id;
 	struct s3c64xx_spi_info *pd;
 
-	id = __raw_readl(S5P64X0_SYS_ID) & 0xFF000;
-
 	/* Reject invalid configuration */
 	if (!num_cs || src_clk_nr < 0
 			|| src_clk_nr > S5P64X0_SPI_SRCCLK_SCLK) {
@@ -199,7 +197,7 @@ void __init s5p64x0_spi_set_info(int cntrlr, int src_clk_nr, int num_cs)
 
 	switch (cntrlr) {
 	case 0:
-		if (id == 0x50000)
+		if (soc_is_s5p6450())
 			pd = &s5p6450_spi0_pdata;
 		else
 			pd = &s5p6440_spi0_pdata;
@@ -207,7 +205,7 @@ void __init s5p64x0_spi_set_info(int cntrlr, int src_clk_nr, int num_cs)
 		s5p64x0_device_spi0.dev.platform_data = pd;
 		break;
 	case 1:
-		if (id == 0x50000)
+		if (soc_is_s5p6450())
 			pd = &s5p6450_spi1_pdata;
 		else
 			pd = &s5p6440_spi1_pdata;
diff --git a/arch/arm/mach-s5p64x0/dma.c b/arch/arm/mach-s5p64x0/dma.c
index d7ad944..0e5b3e6 100644
--- a/arch/arm/mach-s5p64x0/dma.c
+++ b/arch/arm/mach-s5p64x0/dma.c
@@ -28,6 +28,7 @@
 #include <mach/irqs.h>
 #include <mach/regs-clock.h>
 
+#include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/s3c-pl330-pdata.h>
 
@@ -133,11 +134,7 @@ static struct platform_device s5p64x0_device_pdma = {
 
 static int __init s5p64x0_dma_init(void)
 {
-	unsigned int id;
-
-	id = __raw_readl(S5P64X0_SYS_ID) & 0xFF000;
-
-	if (id == 0x50000)
+	if (soc_is_s5p6450())
 		s5p64x0_device_pdma.dev.platform_data = &s5p6450_pdma_pdata;
 	else
 		s5p64x0_device_pdma.dev.platform_data = &s5p6440_pdma_pdata;
diff --git a/arch/arm/mach-s5p64x0/gpiolib.c b/arch/arm/mach-s5p64x0/gpiolib.c
index e7fb3b0..700dac6 100644
--- a/arch/arm/mach-s5p64x0/gpiolib.c
+++ b/arch/arm/mach-s5p64x0/gpiolib.c
@@ -19,6 +19,7 @@
 #include <mach/regs-gpio.h>
 #include <mach/regs-clock.h>
 
+#include <plat/cpu.h>
 #include <plat/gpio-core.h>
 #include <plat/gpio-cfg.h>
 #include <plat/gpio-cfg-helpers.h>
@@ -473,14 +474,10 @@ static void __init s5p64x0_gpio_add_rbank_4bit2(struct s3c_gpio_chip *chip,
 
 static int __init s5p64x0_gpiolib_init(void)
 {
-	unsigned int chipid;
-
-	chipid = __raw_readl(S5P64X0_SYS_ID);
-
 	s5p64x0_gpiolib_set_cfg(s5p64x0_gpio_cfgs,
 				ARRAY_SIZE(s5p64x0_gpio_cfgs));
 
-	if ((chipid & 0xff000) == 0x50000) {
+	if (soc_is_s5p6450()) {
 		samsung_gpiolib_add_2bit_chips(s5p6450_gpio_2bit,
 					ARRAY_SIZE(s5p6450_gpio_2bit));
 
diff --git a/arch/arm/mach-s5p64x0/irq-eint.c b/arch/arm/mach-s5p64x0/irq-eint.c
index fe7380f..494e1a8 100644
--- a/arch/arm/mach-s5p64x0/irq-eint.c
+++ b/arch/arm/mach-s5p64x0/irq-eint.c
@@ -17,6 +17,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 
+#include <plat/cpu.h>
 #include <plat/regs-irqtype.h>
 #include <plat/gpio-cfg.h>
 
@@ -67,7 +68,7 @@ static int s5p64x0_irq_eint_set_type(struct irq_data *data, unsigned int type)
 	__raw_writel(ctrl, S5P64X0_EINT0CON0);
 
 	/* Configure the GPIO pin for 6450 or 6440 based on CPU ID */
-	if (0x50000 == (__raw_readl(S5P64X0_SYS_ID) & 0xFF000))
+	if (soc_is_s5p6450())
 		s3c_gpio_cfgpin(S5P6450_GPN(offs), S3C_GPIO_SFN(2));
 	else
 		s3c_gpio_cfgpin(S5P6440_GPN(offs), S3C_GPIO_SFN(2));
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6440.c b/arch/arm/mach-s5p64x0/mach-smdk6440.c
index 3b84e9b..88857f5 100644
--- a/arch/arm/mach-s5p64x0/mach-smdk6440.c
+++ b/arch/arm/mach-s5p64x0/mach-smdk6440.c
@@ -129,12 +129,6 @@ static struct i2c_board_info smdk6440_i2c_devs1[] __initdata = {
 	/* To be populated */
 };
 
-static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
-	.delay			= 10000,
-	.presc			= 49,
-	.oversampling_shift	= 2,
-};
-
 /* LCD Backlight data */
 static struct samsung_bl_gpio_info smdk6440_bl_gpio_info = {
 	.no = S5P6440_GPF(15),
@@ -155,7 +149,7 @@ static void __init smdk6440_map_io(void)
 
 static void __init smdk6440_machine_init(void)
 {
-	s3c24xx_ts_set_platdata(&s3c_ts_platform);
+	s3c24xx_ts_set_platdata(NULL);
 
 	s3c_i2c0_set_platdata(&s5p6440_i2c0_data);
 	s3c_i2c1_set_platdata(&s5p6440_i2c1_data);
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6450.c b/arch/arm/mach-s5p64x0/mach-smdk6450.c
index d99d29b..e1b277b 100644
--- a/arch/arm/mach-s5p64x0/mach-smdk6450.c
+++ b/arch/arm/mach-s5p64x0/mach-smdk6450.c
@@ -148,12 +148,6 @@ static struct i2c_board_info smdk6450_i2c_devs1[] __initdata = {
 	{ I2C_BOARD_INFO("24c128", 0x57), },/* Samsung S524AD0XD1 EEPROM */
 };
 
-static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
-	.delay			= 10000,
-	.presc			= 49,
-	.oversampling_shift	= 2,
-};
-
 /* LCD Backlight data */
 static struct samsung_bl_gpio_info smdk6450_bl_gpio_info = {
 	.no = S5P6450_GPF(15),
@@ -174,7 +168,7 @@ static void __init smdk6450_map_io(void)
 
 static void __init smdk6450_machine_init(void)
 {
-	s3c24xx_ts_set_platdata(&s3c_ts_platform);
+	s3c24xx_ts_set_platdata(NULL);
 
 	s3c_i2c0_set_platdata(&s5p6450_i2c0_data);
 	s3c_i2c1_set_platdata(&s5p6450_i2c1_data);
diff --git a/arch/arm/mach-s5pc100/mach-smdkc100.c b/arch/arm/mach-s5pc100/mach-smdkc100.c
index 688f45b..26f5c91 100644
--- a/arch/arm/mach-s5pc100/mach-smdkc100.c
+++ b/arch/arm/mach-s5pc100/mach-smdkc100.c
@@ -203,12 +203,6 @@ static struct platform_device *smdkc100_devices[] __initdata = {
 	&s5pc100_device_spdif,
 };
 
-static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
-	.delay			= 10000,
-	.presc			= 49,
-	.oversampling_shift	= 2,
-};
-
 /* LCD Backlight data */
 static struct samsung_bl_gpio_info smdkc100_bl_gpio_info = {
 	.no = S5PC100_GPD(0),
@@ -228,7 +222,7 @@ static void __init smdkc100_map_io(void)
 
 static void __init smdkc100_machine_init(void)
 {
-	s3c24xx_ts_set_platdata(&s3c_ts_platform);
+	s3c24xx_ts_set_platdata(NULL);
 
 	/* I2C */
 	s3c_i2c0_set_platdata(NULL);
diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig
index 69dd87c..aaeb44a 100644
--- a/arch/arm/mach-s5pv210/Kconfig
+++ b/arch/arm/mach-s5pv210/Kconfig
@@ -14,7 +14,6 @@ config CPU_S5PV210
 	select S3C_PL330_DMA
 	select S5P_EXT_INT
 	select S5P_HRT
-	select S5PV210_PM if PM
 	help
 	  Enable S5PV210 CPU support
 
@@ -169,9 +168,4 @@ config MACH_TORBRECK
 
 endmenu
 
-config S5PV210_PM
-	bool
-	help
-	  Power Management code common to S5PV210
-
 endif
diff --git a/arch/arm/mach-s5pv210/Makefile b/arch/arm/mach-s5pv210/Makefile
index 599a3c0..ef7e466 100644
--- a/arch/arm/mach-s5pv210/Makefile
+++ b/arch/arm/mach-s5pv210/Makefile
@@ -14,7 +14,7 @@ obj-				:=
 
 obj-$(CONFIG_CPU_S5PV210)	+= cpu.o init.o clock.o dma.o
 obj-$(CONFIG_CPU_S5PV210)	+= setup-i2c0.o
-obj-$(CONFIG_S5PV210_PM)	+= pm.o sleep.o
+obj-$(CONFIG_PM)		+= pm.o sleep.o
 
 # machine support
 
diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c
index e73e3b6d..a9106c3 100644
--- a/arch/arm/mach-s5pv210/mach-smdkv210.c
+++ b/arch/arm/mach-s5pv210/mach-smdkv210.c
@@ -265,12 +265,6 @@ static struct i2c_board_info smdkv210_i2c_devs2[] __initdata = {
 	/* To Be Updated */
 };
 
-static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
-	.delay			= 10000,
-	.presc			= 49,
-	.oversampling_shift	= 2,
-};
-
 /* LCD Backlight data */
 static struct samsung_bl_gpio_info smdkv210_bl_gpio_info = {
 	.no = S5PV210_GPD0(3),
@@ -296,7 +290,7 @@ static void __init smdkv210_machine_init(void)
 	smdkv210_dm9000_init();
 
 	samsung_keypad_set_platdata(&smdkv210_keypad_data);
-	s3c24xx_ts_set_platdata(&s3c_ts_platform);
+	s3c24xx_ts_set_platdata(NULL);
 
 	s3c_i2c0_set_platdata(NULL);
 	s3c_i2c1_set_platdata(NULL);
diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c
index 3ffdbc9..be1ade7 100644
--- a/arch/arm/mach-shmobile/smp-sh73a0.c
+++ b/arch/arm/mach-shmobile/smp-sh73a0.c
@@ -74,6 +74,8 @@ void __cpuinit sh73a0_secondary_init(unsigned int cpu)
 
 int __cpuinit sh73a0_boot_secondary(unsigned int cpu)
 {
+	cpu = cpu_logical_map(cpu);
+
 	/* enable cache coherency */
 	modify_scu_cpu_psr(0, 3 << (cpu * 8));
 
@@ -87,6 +89,8 @@ int __cpuinit sh73a0_boot_secondary(unsigned int cpu)
 
 void __init sh73a0_smp_prepare_cpus(void)
 {
+	int cpu = cpu_logical_map(0);
+
 	scu_enable(scu_base_addr());
 
 	/* Map the reset vector (in headsmp.S) */
@@ -94,5 +98,5 @@ void __init sh73a0_smp_prepare_cpus(void)
 	__raw_writel(__pa(shmobile_secondary_vector), __io(SBAR));
 
 	/* enable cache coherency on CPU0 */
-	modify_scu_cpu_psr(0, 3 << (0 * 8));
+	modify_scu_cpu_psr(0, 3 << (cpu * 8));
 }
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index d82ebab..91aff7c 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -69,6 +69,12 @@ config MACH_WARIO
        help
          Support for the Wario version of Seaboard
 
+config MACH_VENTANA
+       bool "Ventana board"
+       select MACH_TEGRA_DT
+       help
+         Support for the nVidia Ventana development platform
+
 choice
         prompt "Low-level debug console UART"
         default TEGRA_DEBUG_UART_NONE
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index f11b910..91a07e1 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -31,6 +31,7 @@ obj-${CONFIG_MACH_SEABOARD}             += board-seaboard-pinmux.o
 
 obj-${CONFIG_MACH_TEGRA_DT}             += board-dt.o
 obj-${CONFIG_MACH_TEGRA_DT}             += board-harmony-pinmux.o
+obj-${CONFIG_MACH_TEGRA_DT}             += board-seaboard-pinmux.o
 
 obj-${CONFIG_MACH_TRIMSLICE}            += board-trimslice.o
 obj-${CONFIG_MACH_TRIMSLICE}            += board-trimslice-pinmux.o
diff --git a/arch/arm/mach-tegra/Makefile.boot b/arch/arm/mach-tegra/Makefile.boot
index 5e870d2..bd12c9f 100644
--- a/arch/arm/mach-tegra/Makefile.boot
+++ b/arch/arm/mach-tegra/Makefile.boot
@@ -4,3 +4,4 @@ initrd_phys-$(CONFIG_ARCH_TEGRA_2x_SOC)	:= 0x00800000
 
 dtb-$(CONFIG_MACH_HARMONY) += tegra-harmony.dtb
 dtb-$(CONFIG_MACH_SEABOARD) += tegra-seaboard.dtb
+dtb-$(CONFIG_MACH_VENTANA) += tegra-ventana.dtb
diff --git a/arch/arm/mach-tegra/board-dt.c b/arch/arm/mach-tegra/board-dt.c
index 9f47e04..d368f8d 100644
--- a/arch/arm/mach-tegra/board-dt.c
+++ b/arch/arm/mach-tegra/board-dt.c
@@ -47,7 +47,7 @@
 
 void harmony_pinmux_init(void);
 void seaboard_pinmux_init(void);
-
+void ventana_pinmux_init(void);
 
 struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC1_BASE, "sdhci-tegra.0", NULL),
@@ -80,9 +80,19 @@ static struct of_device_id tegra_dt_gic_match[] __initdata = {
 	{}
 };
 
+static struct {
+	char *machine;
+	void (*init)(void);
+} pinmux_configs[] = {
+	{ "nvidia,harmony", harmony_pinmux_init },
+	{ "nvidia,seaboard", seaboard_pinmux_init },
+	{ "nvidia,ventana", ventana_pinmux_init },
+};
+
 static void __init tegra_dt_init(void)
 {
 	struct device_node *node;
+	int i;
 
 	node = of_find_matching_node_by_address(NULL, tegra_dt_gic_match,
 						TEGRA_ARM_INT_DIST_BASE);
@@ -91,10 +101,15 @@ static void __init tegra_dt_init(void)
 
 	tegra_clk_init_from_table(tegra_dt_clk_init_table);
 
-	if (of_machine_is_compatible("nvidia,harmony"))
-		harmony_pinmux_init();
-	else if (of_machine_is_compatible("nvidia,seaboard"))
-		seaboard_pinmux_init();
+	for (i = 0; i < ARRAY_SIZE(pinmux_configs); i++) {
+		if (of_machine_is_compatible(pinmux_configs[i].machine)) {
+			pinmux_configs[i].init();
+			break;
+		}
+	}
+
+	WARN(i == ARRAY_SIZE(pinmux_configs),
+		"Unknown platform! Pinmuxing not initialized\n");
 
 	/*
 	 * Finished with the static registrations now; fill in the missing
@@ -106,6 +121,7 @@ static void __init tegra_dt_init(void)
 static const char * tegra_dt_board_compat[] = {
 	"nvidia,harmony",
 	"nvidia,seaboard",
+	"nvidia,ventana",
 	NULL
 };
 
diff --git a/arch/arm/mach-tegra/board-harmony-pinmux.c b/arch/arm/mach-tegra/board-harmony-pinmux.c
index 4d63e2e..e99b456 100644
--- a/arch/arm/mach-tegra/board-harmony-pinmux.c
+++ b/arch/arm/mach-tegra/board-harmony-pinmux.c
@@ -20,6 +20,7 @@
 
 #include "gpio-names.h"
 #include "board-harmony.h"
+#include "devices.h"
 
 static struct tegra_pingroup_config harmony_pinmux[] = {
 	{TEGRA_PINGROUP_ATA,   TEGRA_MUX_IDE,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
@@ -140,6 +141,11 @@ static struct tegra_pingroup_config harmony_pinmux[] = {
 	{TEGRA_PINGROUP_XM2D,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
 };
 
+static struct platform_device *pinmux_devices[] = {
+	&tegra_gpio_device,
+	&tegra_pinmux_device,
+};
+
 static struct tegra_gpio_table gpio_table[] = {
 	{ .gpio = TEGRA_GPIO_SD2_CD,		.enable = true	},
 	{ .gpio = TEGRA_GPIO_SD2_WP,		.enable = true	},
@@ -155,6 +161,8 @@ static struct tegra_gpio_table gpio_table[] = {
 
 void harmony_pinmux_init(void)
 {
+	platform_add_devices(pinmux_devices, ARRAY_SIZE(pinmux_devices));
+
 	tegra_pinmux_config_table(harmony_pinmux, ARRAY_SIZE(harmony_pinmux));
 
 	tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
diff --git a/arch/arm/mach-tegra/board-harmony-power.c b/arch/arm/mach-tegra/board-harmony-power.c
index 5ad8b2f..21d1285 100644
--- a/arch/arm/mach-tegra/board-harmony-power.c
+++ b/arch/arm/mach-tegra/board-harmony-power.c
@@ -18,10 +18,11 @@
 #include <linux/i2c.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
-
+#include <linux/io.h>
 #include <linux/regulator/machine.h>
 #include <linux/mfd/tps6586x.h>
 
+#include <mach/iomap.h>
 #include <mach/irqs.h>
 
 #include "board-harmony.h"
@@ -113,6 +114,16 @@ static struct i2c_board_info __initdata harmony_regulators[] = {
 
 int __init harmony_regulator_init(void)
 {
+	void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
+	u32 pmc_ctrl;
+
+	/*
+	 * Configure the power management controller to trigger PMU
+	 * interrupts when low
+	 */
+	pmc_ctrl = readl(pmc + PMC_CTRL);
+	writel(pmc_ctrl | PMC_CTRL_INTR_LOW, pmc + PMC_CTRL);
+
 	i2c_register_board_info(3, harmony_regulators, 1);
 
 	return 0;
diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c
index 93c793f..f0bdc5e 100644
--- a/arch/arm/mach-tegra/board-harmony.c
+++ b/arch/arm/mach-tegra/board-harmony.c
@@ -49,7 +49,8 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
 		.membase	= IO_ADDRESS(TEGRA_UARTD_BASE),
 		.mapbase	= TEGRA_UARTD_BASE,
 		.irq		= INT_UARTD,
-		.flags		= UPF_BOOT_AUTOCONF,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
+		.type		= PORT_TEGRA,
 		.iotype		= UPIO_MEM,
 		.regshift	= 2,
 		.uartclk	= 216000000,
@@ -117,6 +118,7 @@ static struct platform_device *harmony_devices[] __initdata = {
 	&tegra_sdhci_device1,
 	&tegra_sdhci_device2,
 	&tegra_sdhci_device4,
+	&tegra_ehci3_device,
 	&tegra_i2s_device1,
 	&tegra_das_device,
 	&tegra_pcm_device,
@@ -140,6 +142,7 @@ static __initdata struct tegra_clk_init_table harmony_clk_init_table[] = {
 	{ "pll_a_out0",	"pll_a",	11289600,	true },
 	{ "cdev1",	NULL,		0,		true },
 	{ "i2s1",	"pll_a_out0",	11289600,	false},
+	{ "usb3",	"clk_m",	12000000,	true },
 	{ NULL,		NULL,		0,		0},
 };
 
diff --git a/arch/arm/mach-tegra/board-paz00-pinmux.c b/arch/arm/mach-tegra/board-paz00-pinmux.c
index bdd2627..fb20894 100644
--- a/arch/arm/mach-tegra/board-paz00-pinmux.c
+++ b/arch/arm/mach-tegra/board-paz00-pinmux.c
@@ -20,6 +20,7 @@
 
 #include "gpio-names.h"
 #include "board-paz00.h"
+#include "devices.h"
 
 static struct tegra_pingroup_config paz00_pinmux[] = {
 	{TEGRA_PINGROUP_ATA,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
@@ -140,15 +141,25 @@ static struct tegra_pingroup_config paz00_pinmux[] = {
 	{TEGRA_PINGROUP_XM2D,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
 };
 
+static struct platform_device *pinmux_devices[] = {
+	&tegra_gpio_device,
+	&tegra_pinmux_device,
+};
+
 static struct tegra_gpio_table gpio_table[] = {
 	{ .gpio = TEGRA_GPIO_SD1_CD,	.enable = true },
 	{ .gpio = TEGRA_GPIO_SD1_WP,	.enable = true },
 	{ .gpio = TEGRA_GPIO_SD1_POWER,	.enable = true },
 	{ .gpio = TEGRA_ULPI_RST,	.enable = true },
+	{ .gpio = TEGRA_WIFI_PWRN,	.enable = true },
+	{ .gpio = TEGRA_WIFI_RST,	.enable = true },
+	{ .gpio = TEGRA_WIFI_LED,	.enable = true },
 };
 
 void paz00_pinmux_init(void)
 {
+	platform_add_devices(pinmux_devices, ARRAY_SIZE(pinmux_devices));
+
 	tegra_pinmux_config_table(paz00_pinmux, ARRAY_SIZE(paz00_pinmux));
 
 	tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c
index fbc9e0e..55c55ba 100644
--- a/arch/arm/mach-tegra/board-paz00.c
+++ b/arch/arm/mach-tegra/board-paz00.c
@@ -26,6 +26,8 @@
 #include <linux/pda_power.h>
 #include <linux/io.h>
 #include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/rfkill-gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -35,7 +37,6 @@
 #include <mach/iomap.h>
 #include <mach/irqs.h>
 #include <mach/sdhci.h>
-#include <mach/gpio.h>
 
 #include "board.h"
 #include "board-paz00.h"
@@ -45,10 +46,22 @@
 
 static struct plat_serial8250_port debug_uart_platform_data[] = {
 	{
+		/* serial port on JP1 */
+		.membase	= IO_ADDRESS(TEGRA_UARTA_BASE),
+		.mapbase	= TEGRA_UARTA_BASE,
+		.irq		= INT_UARTA,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
+		.type		= PORT_TEGRA,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= 216000000,
+	}, {
+		/* serial port on mini-pcie */
 		.membase	= IO_ADDRESS(TEGRA_UARTD_BASE),
 		.mapbase	= TEGRA_UARTD_BASE,
 		.irq		= INT_UARTD,
-		.flags		= UPF_BOOT_AUTOCONF,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
+		.type		= PORT_TEGRA,
 		.iotype		= UPIO_MEM,
 		.regshift	= 2,
 		.uartclk	= 216000000,
@@ -65,10 +78,48 @@ static struct platform_device debug_uart = {
 	},
 };
 
+static struct rfkill_gpio_platform_data wifi_rfkill_platform_data = {
+	.name		= "wifi_rfkill",
+	.reset_gpio	= TEGRA_WIFI_RST,
+	.shutdown_gpio	= TEGRA_WIFI_PWRN,
+	.type	= RFKILL_TYPE_WLAN,
+};
+
+static struct platform_device wifi_rfkill_device = {
+	.name	= "rfkill_gpio",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &wifi_rfkill_platform_data,
+	},
+};
+
+static struct gpio_led gpio_leds[] = {
+	{
+		.name			= "wifi-led",
+		.default_trigger	= "rfkill0",
+		.gpio			= TEGRA_WIFI_LED,
+	},
+};
+
+static struct gpio_led_platform_data gpio_led_info = {
+	.leds		= gpio_leds,
+	.num_leds	= ARRAY_SIZE(gpio_leds),
+};
+
+static struct platform_device leds_gpio = {
+	.name	= "leds-gpio",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &gpio_led_info,
+        },
+};
+
 static struct platform_device *paz00_devices[] __initdata = {
 	&debug_uart,
-	&tegra_sdhci_device1,
 	&tegra_sdhci_device4,
+	&tegra_sdhci_device1,
+	&wifi_rfkill_device,
+	&leds_gpio,
 };
 
 static void paz00_i2c_init(void)
@@ -94,7 +145,14 @@ static void __init tegra_paz00_fixup(struct tag *tags, char **cmdline,
 
 static __initdata struct tegra_clk_init_table paz00_clk_init_table[] = {
 	/* name		parent		rate		enabled */
+	{ "uarta",	"pll_p",	216000000,	true },
 	{ "uartd",	"pll_p",	216000000,	true },
+
+	{ "pll_p_out4",	"pll_p",	24000000,	true },
+	{ "usbd",	"clk_m",	12000000,	false },
+	{ "usb2",	"clk_m",	12000000,	false },
+	{ "usb3",	"clk_m",	12000000,	false },
+
 	{ NULL,		NULL,		0,		0},
 };
 
diff --git a/arch/arm/mach-tegra/board-paz00.h b/arch/arm/mach-tegra/board-paz00.h
index 42ce863..8aff06e 100644
--- a/arch/arm/mach-tegra/board-paz00.h
+++ b/arch/arm/mach-tegra/board-paz00.h
@@ -19,11 +19,19 @@
 
 #include <mach/gpio-tegra.h>
 
+/* SDCARD */
 #define TEGRA_GPIO_SD1_CD		TEGRA_GPIO_PV5
 #define TEGRA_GPIO_SD1_WP		TEGRA_GPIO_PH1
 #define TEGRA_GPIO_SD1_POWER		TEGRA_GPIO_PT3
+
+/* ULPI */
 #define TEGRA_ULPI_RST			TEGRA_GPIO_PV0
 
+/* WIFI */
+#define TEGRA_WIFI_PWRN			TEGRA_GPIO_PK5
+#define TEGRA_WIFI_RST			TEGRA_GPIO_PD1
+#define TEGRA_WIFI_LED			TEGRA_GPIO_PD0
+
 void paz00_pinmux_init(void);
 
 #endif
diff --git a/arch/arm/mach-tegra/board-seaboard-pinmux.c b/arch/arm/mach-tegra/board-seaboard-pinmux.c
index 0bda495..fbce31d 100644
--- a/arch/arm/mach-tegra/board-seaboard-pinmux.c
+++ b/arch/arm/mach-tegra/board-seaboard-pinmux.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2010 NVIDIA Corporation
+ * Copyright (C) 2010,2011 NVIDIA Corporation
+ * Copyright (C) 2011 Google, Inc.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -21,6 +22,7 @@
 
 #include "gpio-names.h"
 #include "board-seaboard.h"
+#include "devices.h"
 
 #define DEFAULT_DRIVE(_name)					\
 	{							\
@@ -49,7 +51,7 @@ static __initdata struct tegra_pingroup_config seaboard_pinmux[] = {
 	{TEGRA_PINGROUP_CRTP,  TEGRA_MUX_CRT,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_CSUS,  TEGRA_MUX_VI_SENSOR_CLK, TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_DAP1,  TEGRA_MUX_DAP1,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
-	{TEGRA_PINGROUP_DAP2,  TEGRA_MUX_DAP2,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DAP2,  TEGRA_MUX_DAP2,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
 	{TEGRA_PINGROUP_DAP3,  TEGRA_MUX_DAP3,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_DAP4,  TEGRA_MUX_DAP4,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
 	{TEGRA_PINGROUP_DDC,   TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
@@ -133,7 +135,7 @@ static __initdata struct tegra_pingroup_config seaboard_pinmux[] = {
 	{TEGRA_PINGROUP_SPDO,  TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
 	{TEGRA_PINGROUP_SPIA,  TEGRA_MUX_GMI,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_SPIB,  TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
-	{TEGRA_PINGROUP_SPIC,  TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIC,  TEGRA_MUX_GMI,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
 	{TEGRA_PINGROUP_SPID,  TEGRA_MUX_SPI1,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_SPIE,  TEGRA_MUX_SPI1,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_SPIF,  TEGRA_MUX_SPI1,          TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
@@ -157,24 +159,83 @@ static __initdata struct tegra_pingroup_config seaboard_pinmux[] = {
 	{TEGRA_PINGROUP_XM2D,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
 };
 
+static __initdata struct tegra_pingroup_config ventana_pinmux[] = {
+	{TEGRA_PINGROUP_DAP3, TEGRA_MUX_DAP3,     TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DDC,  TEGRA_MUX_RSVD2,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DTA,  TEGRA_MUX_VI,       TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DTB,  TEGRA_MUX_VI,       TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DTC,  TEGRA_MUX_VI,       TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DTD,  TEGRA_MUX_VI,       TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GMD,  TEGRA_MUX_SFLASH,   TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LPW0, TEGRA_MUX_RSVD4,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LPW2, TEGRA_MUX_RSVD4,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LSC1, TEGRA_MUX_RSVD4,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LSCK, TEGRA_MUX_RSVD4,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LSDA, TEGRA_MUX_RSVD4,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_PTA,  TEGRA_MUX_RSVD2,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SLXC, TEGRA_MUX_SDIO3,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SLXK, TEGRA_MUX_SDIO3,    TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SPIA, TEGRA_MUX_GMI,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIC, TEGRA_MUX_GMI,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIG, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+};
 
+static struct platform_device *pinmux_devices[] = {
+	&tegra_gpio_device,
+	&tegra_pinmux_device,
+};
 
-
-static struct tegra_gpio_table gpio_table[] = {
+static struct tegra_gpio_table common_gpio_table[] = {
 	{ .gpio = TEGRA_GPIO_SD2_CD,		.enable = true },
 	{ .gpio = TEGRA_GPIO_SD2_WP,		.enable = true },
 	{ .gpio = TEGRA_GPIO_SD2_POWER,		.enable = true },
 	{ .gpio = TEGRA_GPIO_LIDSWITCH,		.enable = true },
 	{ .gpio = TEGRA_GPIO_POWERKEY,		.enable = true },
 	{ .gpio = TEGRA_GPIO_ISL29018_IRQ,	.enable = true },
+	{ .gpio = TEGRA_GPIO_CDC_IRQ,		.enable = true },
+	{ .gpio = TEGRA_GPIO_USB1,		.enable = true },
 };
 
-void __init seaboard_pinmux_init(void)
+static void __init update_pinmux(struct tegra_pingroup_config *newtbl, int size)
+{
+	int i, j;
+	struct tegra_pingroup_config *new_pingroup, *base_pingroup;
+
+	/* Update base seaboard pinmux table with secondary board
+	 * specific pinmux table table.
+	 */
+	for (i = 0; i < size; i++) {
+		new_pingroup = &newtbl[i];
+		for (j = 0; j < ARRAY_SIZE(seaboard_pinmux); j++) {
+			base_pingroup = &seaboard_pinmux[j];
+			if (new_pingroup->pingroup == base_pingroup->pingroup) {
+				*base_pingroup = *new_pingroup;
+				break;
+			}
+		}
+	}
+}
+
+void __init seaboard_common_pinmux_init(void)
 {
+	platform_add_devices(pinmux_devices, ARRAY_SIZE(pinmux_devices));
+
 	tegra_pinmux_config_table(seaboard_pinmux, ARRAY_SIZE(seaboard_pinmux));
 
 	tegra_drive_pinmux_config_table(seaboard_drive_pinmux,
 					ARRAY_SIZE(seaboard_drive_pinmux));
 
-	tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
+	tegra_gpio_config(common_gpio_table, ARRAY_SIZE(common_gpio_table));
+}
+
+void __init seaboard_pinmux_init(void)
+{
+	seaboard_common_pinmux_init();
 }
+
+void __init ventana_pinmux_init(void)
+{
+	update_pinmux(ventana_pinmux, ARRAY_SIZE(ventana_pinmux));
+	seaboard_common_pinmux_init();
+}
+
diff --git a/arch/arm/mach-tegra/board-seaboard.c b/arch/arm/mach-tegra/board-seaboard.c
index 9e98ac7..bf13ea3 100644
--- a/arch/arm/mach-tegra/board-seaboard.c
+++ b/arch/arm/mach-tegra/board-seaboard.c
@@ -25,9 +25,12 @@
 #include <linux/gpio.h>
 #include <linux/gpio_keys.h>
 
+#include <sound/wm8903.h>
+
 #include <mach/iomap.h>
 #include <mach/irqs.h>
 #include <mach/sdhci.h>
+#include <mach/tegra_wm8903_pdata.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -41,7 +44,8 @@
 static struct plat_serial8250_port debug_uart_platform_data[] = {
 	{
 		/* Memory and IRQ filled in before registration */
-		.flags		= UPF_BOOT_AUTOCONF,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
+		.type		= PORT_TEGRA,
 		.iotype		= UPIO_MEM,
 		.regshift	= 2,
 		.uartclk	= 216000000,
@@ -62,6 +66,12 @@ static __initdata struct tegra_clk_init_table seaboard_clk_init_table[] = {
 	/* name		parent		rate		enabled */
 	{ "uartb",	"pll_p",	216000000,	true},
 	{ "uartd",	"pll_p",	216000000,	true},
+	{ "pll_a",	"pll_p_out1",	56448000,	true },
+	{ "pll_a_out0",	"pll_a",	11289600,	true },
+	{ "cdev1",	NULL,		0,		true },
+	{ "i2s1",	"pll_a_out0",	11289600,	false},
+	{ "usbd",	"clk_m",	12000000,	true},
+	{ "usb3",	"clk_m",	12000000,	true},
 	{ NULL,		NULL,		0,		0},
 };
 
@@ -117,6 +127,22 @@ static struct tegra_sdhci_platform_data sdhci_pdata4 = {
 	.is_8bit	= 1,
 };
 
+static struct tegra_wm8903_platform_data seaboard_audio_pdata = {
+	.gpio_spkr_en		= TEGRA_GPIO_SPKR_EN,
+	.gpio_hp_det		= TEGRA_GPIO_HP_DET,
+	.gpio_hp_mute		= -1,
+	.gpio_int_mic_en	= -1,
+	.gpio_ext_mic_en	= -1,
+};
+
+static struct platform_device seaboard_audio_device = {
+	.name	= "tegra-snd-wm8903",
+	.id	= 0,
+	.dev	= {
+		.platform_data  = &seaboard_audio_pdata,
+	},
+};
+
 static struct platform_device *seaboard_devices[] __initdata = {
 	&debug_uart,
 	&tegra_pmu_device,
@@ -124,6 +150,10 @@ static struct platform_device *seaboard_devices[] __initdata = {
 	&tegra_sdhci_device3,
 	&tegra_sdhci_device1,
 	&seaboard_gpio_keys_device,
+	&tegra_i2s_device1,
+	&tegra_das_device,
+	&tegra_pcm_device,
+	&seaboard_audio_device,
 };
 
 static struct i2c_board_info __initdata isl29018_device = {
@@ -135,12 +165,56 @@ static struct i2c_board_info __initdata adt7461_device = {
 	I2C_BOARD_INFO("adt7461", 0x4c),
 };
 
+static struct wm8903_platform_data wm8903_pdata = {
+	.irq_active_low = 0,
+	.micdet_cfg = 0,
+	.micdet_delay = 100,
+	.gpio_base = SEABOARD_GPIO_WM8903(0),
+	.gpio_cfg = {
+		WM8903_GPIO_NO_CONFIG,
+		WM8903_GPIO_NO_CONFIG,
+		0,
+		WM8903_GPIO_NO_CONFIG,
+		WM8903_GPIO_NO_CONFIG,
+	},
+};
+
+static struct i2c_board_info __initdata wm8903_device = {
+	I2C_BOARD_INFO("wm8903", 0x1a),
+	.platform_data = &wm8903_pdata,
+	.irq = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_CDC_IRQ),
+};
+
+static int seaboard_ehci_init(void)
+{
+	int gpio_status;
+
+	gpio_status = gpio_request(TEGRA_GPIO_USB1, "VBUS_USB1");
+	if (gpio_status < 0) {
+		pr_err("VBUS_USB1 request GPIO FAILED\n");
+		WARN_ON(1);
+	}
+
+	gpio_status = gpio_direction_output(TEGRA_GPIO_USB1, 1);
+	if (gpio_status < 0) {
+		pr_err("VBUS_USB1 request GPIO DIRECTION FAILED\n");
+		WARN_ON(1);
+	}
+	gpio_set_value(TEGRA_GPIO_USB1, 1);
+
+	platform_device_register(&tegra_ehci1_device);
+	platform_device_register(&tegra_ehci3_device);
+
+	return 0;
+}
+
 static void __init seaboard_i2c_init(void)
 {
 	gpio_request(TEGRA_GPIO_ISL29018_IRQ, "isl29018");
 	gpio_direction_input(TEGRA_GPIO_ISL29018_IRQ);
 
 	i2c_register_board_info(0, &isl29018_device, 1);
+	i2c_register_board_info(0, &wm8903_device, 1);
 
 	i2c_register_board_info(3, &adt7461_device, 1);
 
@@ -161,6 +235,8 @@ static void __init seaboard_common_init(void)
 	tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4;
 
 	platform_add_devices(seaboard_devices, ARRAY_SIZE(seaboard_devices));
+
+	seaboard_ehci_init();
 }
 
 static void __init tegra_seaboard_init(void)
@@ -182,6 +258,9 @@ static void __init tegra_kaen_init(void)
 	debug_uart_platform_data[0].mapbase = TEGRA_UARTB_BASE;
 	debug_uart_platform_data[0].irq = INT_UARTB;
 
+	seaboard_audio_pdata.gpio_hp_mute = TEGRA_GPIO_KAEN_HP_MUTE;
+	tegra_gpio_enable(TEGRA_GPIO_KAEN_HP_MUTE);
+
 	seaboard_common_init();
 
 	seaboard_i2c_init();
diff --git a/arch/arm/mach-tegra/board-seaboard.h b/arch/arm/mach-tegra/board-seaboard.h
index 15b6c57..4c45d4c 100644
--- a/arch/arm/mach-tegra/board-seaboard.h
+++ b/arch/arm/mach-tegra/board-seaboard.h
@@ -19,6 +19,9 @@
 
 #include <mach/gpio-tegra.h>
 
+#define SEABOARD_GPIO_TPS6586X(_x_)	(TEGRA_NR_GPIOS + (_x_))
+#define SEABOARD_GPIO_WM8903(_x_)	(SEABOARD_GPIO_TPS6586X(4) + (_x_))
+
 #define TEGRA_GPIO_SD2_CD		TEGRA_GPIO_PI5
 #define TEGRA_GPIO_SD2_WP		TEGRA_GPIO_PH1
 #define TEGRA_GPIO_SD2_POWER		TEGRA_GPIO_PI6
@@ -33,10 +36,11 @@
 #define TEGRA_GPIO_MAGNETOMETER		TEGRA_GPIO_PN5
 #define TEGRA_GPIO_ISL29018_IRQ		TEGRA_GPIO_PZ2
 #define TEGRA_GPIO_AC_ONLINE		TEGRA_GPIO_PV3
-
-#define TPS_GPIO_BASE			TEGRA_NR_GPIOS
-
-#define TPS_GPIO_WWAN_PWR		(TPS_GPIO_BASE + 2)
+#define TEGRA_GPIO_WWAN_PWR		SEABOARD_GPIO_TPS6586X(2)
+#define TEGRA_GPIO_CDC_IRQ		TEGRA_GPIO_PX3
+#define TEGRA_GPIO_SPKR_EN		SEABOARD_GPIO_WM8903(2)
+#define TEGRA_GPIO_HP_DET		TEGRA_GPIO_PX1
+#define TEGRA_GPIO_KAEN_HP_MUTE		TEGRA_GPIO_PA5
 
 void seaboard_pinmux_init(void);
 
diff --git a/arch/arm/mach-tegra/board-trimslice-pinmux.c b/arch/arm/mach-tegra/board-trimslice-pinmux.c
index bcb1916..4969dd2 100644
--- a/arch/arm/mach-tegra/board-trimslice-pinmux.c
+++ b/arch/arm/mach-tegra/board-trimslice-pinmux.c
@@ -21,6 +21,7 @@
 
 #include "gpio-names.h"
 #include "board-trimslice.h"
+#include "devices.h"
 
 static __initdata struct tegra_pingroup_config trimslice_pinmux[] = {
 	{TEGRA_PINGROUP_ATA,   TEGRA_MUX_IDE,           TEGRA_PUPD_NORMAL,	TEGRA_TRI_TRISTATE},
@@ -141,6 +142,11 @@ static __initdata struct tegra_pingroup_config trimslice_pinmux[] = {
 	{TEGRA_PINGROUP_XM2D,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
 };
 
+static struct platform_device *pinmux_devices[] = {
+	&tegra_gpio_device,
+	&tegra_pinmux_device,
+};
+
 static struct tegra_gpio_table gpio_table[] = {
 	{ .gpio = TRIMSLICE_GPIO_SD4_CD, .enable = true	}, /* mmc4 cd */
 	{ .gpio = TRIMSLICE_GPIO_SD4_WP, .enable = true	}, /* mmc4 wp */
@@ -151,6 +157,7 @@ static struct tegra_gpio_table gpio_table[] = {
 
 void __init trimslice_pinmux_init(void)
 {
+	platform_add_devices(pinmux_devices, ARRAY_SIZE(pinmux_devices));
 	tegra_pinmux_config_table(trimslice_pinmux, ARRAY_SIZE(trimslice_pinmux));
 	tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
 }
diff --git a/arch/arm/mach-tegra/board-trimslice.c b/arch/arm/mach-tegra/board-trimslice.c
index e3d9ec2..1a6617b 100644
--- a/arch/arm/mach-tegra/board-trimslice.c
+++ b/arch/arm/mach-tegra/board-trimslice.c
@@ -32,7 +32,6 @@
 
 #include <mach/iomap.h>
 #include <mach/sdhci.h>
-#include <mach/gpio.h>
 
 #include "board.h"
 #include "clock.h"
@@ -46,7 +45,8 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
 		.membase	= IO_ADDRESS(TEGRA_UARTA_BASE),
 		.mapbase	= TEGRA_UARTA_BASE,
 		.irq		= INT_UARTA,
-		.flags		= UPF_BOOT_AUTOCONF,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
+		.type		= PORT_TEGRA,
 		.iotype		= UPIO_MEM,
 		.regshift	= 2,
 		.uartclk	= 216000000,
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
index d5e3f89..690b888 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -61,7 +61,7 @@ static __initdata struct tegra_clk_init_table common_clk_init_table[] = {
 	{ NULL,		NULL,		0,		0},
 };
 
-void __init tegra_init_cache(void)
+static void __init tegra_init_cache(void)
 {
 #ifdef CONFIG_CACHE_L2X0
 	void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000;
diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c
index 0e0fd4d..bb5ce39 100644
--- a/arch/arm/mach-tegra/cpu-tegra.c
+++ b/arch/arm/mach-tegra/cpu-tegra.c
@@ -56,12 +56,12 @@ static unsigned long target_cpu_speed[NUM_CPUS];
 static DEFINE_MUTEX(tegra_cpu_lock);
 static bool is_suspended;
 
-int tegra_verify_speed(struct cpufreq_policy *policy)
+static int tegra_verify_speed(struct cpufreq_policy *policy)
 {
 	return cpufreq_frequency_table_verify(policy, freq_table);
 }
 
-unsigned int tegra_getspeed(unsigned int cpu)
+static unsigned int tegra_getspeed(unsigned int cpu)
 {
 	unsigned long rate;
 
@@ -129,7 +129,7 @@ static int tegra_target(struct cpufreq_policy *policy,
 		       unsigned int target_freq,
 		       unsigned int relation)
 {
-	int idx;
+	unsigned int idx;
 	unsigned int freq;
 	int ret = 0;
 
diff --git a/arch/arm/mach-tegra/devices.c b/arch/arm/mach-tegra/devices.c
index 57e35d2..7a2a02d 100644
--- a/arch/arm/mach-tegra/devices.c
+++ b/arch/arm/mach-tegra/devices.c
@@ -29,7 +29,93 @@
 #include <mach/iomap.h>
 #include <mach/dma.h>
 #include <mach/usb_phy.h>
+
 #include "gpio-names.h"
+#include "devices.h"
+
+static struct resource gpio_resource[] = {
+	[0] = {
+		.start	= TEGRA_GPIO_BASE,
+		.end	= TEGRA_GPIO_BASE + TEGRA_GPIO_SIZE-1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= INT_GPIO1,
+		.end	= INT_GPIO1,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= INT_GPIO2,
+		.end	= INT_GPIO2,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[3] = {
+		.start	= INT_GPIO3,
+		.end	= INT_GPIO3,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[4] = {
+		.start	= INT_GPIO4,
+		.end	= INT_GPIO4,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[5] = {
+		.start	= INT_GPIO5,
+		.end	= INT_GPIO5,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[6] = {
+		.start	= INT_GPIO6,
+		.end	= INT_GPIO6,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[7] = {
+		.start	= INT_GPIO7,
+		.end	= INT_GPIO7,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device tegra_gpio_device = {
+	.name		= "tegra-gpio",
+	.id		= -1,
+	.resource	= gpio_resource,
+	.num_resources	= ARRAY_SIZE(gpio_resource),
+};
+
+static struct resource pinmux_resource[] = {
+	[0] = {
+		/* Tri-state registers */
+		.start	= TEGRA_APB_MISC_BASE + 0x14,
+		.end	= TEGRA_APB_MISC_BASE + 0x20 + 3,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		/* Mux registers */
+		.start	= TEGRA_APB_MISC_BASE + 0x80,
+		.end	= TEGRA_APB_MISC_BASE + 0x9c + 3,
+		.flags	= IORESOURCE_MEM,
+	},
+	[2] = {
+		/* Pull-up/down registers */
+		.start	= TEGRA_APB_MISC_BASE + 0xa0,
+		.end	= TEGRA_APB_MISC_BASE + 0xb0 + 3,
+		.flags	= IORESOURCE_MEM,
+	},
+	[3] = {
+		/* Pad control registers */
+		.start	= TEGRA_APB_MISC_BASE + 0x868,
+		.end	= TEGRA_APB_MISC_BASE + 0x90c + 3,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+struct platform_device tegra_pinmux_device = {
+	.name		= "tegra-pinmux",
+	.id		= -1,
+	.resource	= pinmux_resource,
+	.num_resources	= ARRAY_SIZE(pinmux_resource),
+};
 
 static struct resource i2c_resource1[] = {
 	[0] = {
diff --git a/arch/arm/mach-tegra/devices.h b/arch/arm/mach-tegra/devices.h
index 4a7dc0a..873ecb2 100644
--- a/arch/arm/mach-tegra/devices.h
+++ b/arch/arm/mach-tegra/devices.h
@@ -21,6 +21,8 @@
 
 #include <linux/platform_device.h>
 
+extern struct platform_device tegra_gpio_device;
+extern struct platform_device tegra_pinmux_device;
 extern struct platform_device tegra_sdhci_device1;
 extern struct platform_device tegra_sdhci_device2;
 extern struct platform_device tegra_sdhci_device3;
diff --git a/arch/arm/mach-tegra/dma.c b/arch/arm/mach-tegra/dma.c
index f4ef5eb..c0cf967 100644
--- a/arch/arm/mach-tegra/dma.c
+++ b/arch/arm/mach-tegra/dma.c
@@ -105,13 +105,17 @@
 
 #define NV_DMA_MAX_TRASFER_SIZE 0x10000
 
-const unsigned int ahb_addr_wrap_table[8] = {
+static const unsigned int ahb_addr_wrap_table[8] = {
 	0, 32, 64, 128, 256, 512, 1024, 2048
 };
 
-const unsigned int apb_addr_wrap_table[8] = {0, 1, 2, 4, 8, 16, 32, 64};
+static const unsigned int apb_addr_wrap_table[8] = {
+	0, 1, 2, 4, 8, 16, 32, 64
+};
 
-const unsigned int bus_width_table[5] = {8, 16, 32, 64, 128};
+static const unsigned int bus_width_table[5] = {
+	8, 16, 32, 64, 128
+};
 
 #define TEGRA_DMA_NAME_SIZE 16
 struct tegra_dma_channel {
@@ -157,7 +161,7 @@ void tegra_dma_dequeue(struct tegra_dma_channel *ch)
 	return;
 }
 
-void tegra_dma_stop(struct tegra_dma_channel *ch)
+static void tegra_dma_stop(struct tegra_dma_channel *ch)
 {
 	u32 csr;
 	u32 status;
@@ -174,7 +178,7 @@ void tegra_dma_stop(struct tegra_dma_channel *ch)
 		writel(status, ch->addr + APB_DMA_CHAN_STA);
 }
 
-int tegra_dma_cancel(struct tegra_dma_channel *ch)
+static int tegra_dma_cancel(struct tegra_dma_channel *ch)
 {
 	u32 csr;
 	unsigned long irq_flags;
diff --git a/arch/arm/mach-tegra/include/mach/io.h b/arch/arm/mach-tegra/include/mach/io.h
index 4cea223..35a011f 100644
--- a/arch/arm/mach-tegra/include/mach/io.h
+++ b/arch/arm/mach-tegra/include/mach/io.h
@@ -33,20 +33,26 @@
  *
  */
 
+#ifdef __ASSEMBLY__
+#define IOMEM(x)	(x)
+#else
+#define IOMEM(x)	((void __force __iomem *)(x))
+#endif
+
 #define IO_IRAM_PHYS	0x40000000
-#define IO_IRAM_VIRT	0xFE400000
+#define IO_IRAM_VIRT	IOMEM(0xFE400000)
 #define IO_IRAM_SIZE	SZ_256K
 
 #define IO_CPU_PHYS     0x50040000
-#define IO_CPU_VIRT     0xFE000000
+#define IO_CPU_VIRT     IOMEM(0xFE000000)
 #define IO_CPU_SIZE	SZ_16K
 
 #define IO_PPSB_PHYS	0x60000000
-#define IO_PPSB_VIRT	0xFE200000
+#define IO_PPSB_VIRT	IOMEM(0xFE200000)
 #define IO_PPSB_SIZE	SZ_1M
 
 #define IO_APB_PHYS	0x70000000
-#define IO_APB_VIRT	0xFE300000
+#define IO_APB_VIRT	IOMEM(0xFE300000)
 #define IO_APB_SIZE	SZ_1M
 
 #define IO_TO_VIRT_BETWEEN(p, st, sz)	((p) >= (st) && (p) < ((st) + (sz)))
@@ -61,7 +67,7 @@
 		IO_TO_VIRT_XLATE((n), IO_CPU_PHYS, IO_CPU_VIRT) :	\
 	IO_TO_VIRT_BETWEEN((n), IO_IRAM_PHYS, IO_IRAM_SIZE) ?		\
 		IO_TO_VIRT_XLATE((n), IO_IRAM_PHYS, IO_IRAM_VIRT) :	\
-	0)
+	NULL)
 
 #ifndef __ASSEMBLER__
 
@@ -71,7 +77,7 @@
 void __iomem *tegra_ioremap(unsigned long phys, size_t size, unsigned int type);
 void tegra_iounmap(volatile void __iomem *addr);
 
-#define IO_ADDRESS(n) ((void __iomem *) IO_TO_VIRT(n))
+#define IO_ADDRESS(n) (IO_TO_VIRT(n))
 
 #ifdef CONFIG_TEGRA_PCI
 extern void __iomem *tegra_pcie_io_base;
diff --git a/arch/arm/mach-tegra/include/mach/pinmux.h b/arch/arm/mach-tegra/include/mach/pinmux.h
index defd877..bb7dfdb 100644
--- a/arch/arm/mach-tegra/include/mach/pinmux.h
+++ b/arch/arm/mach-tegra/include/mach/pinmux.h
@@ -199,6 +199,7 @@ struct tegra_drive_pingroup_config {
 
 struct tegra_drive_pingroup_desc {
 	const char *name;
+	s16 reg_bank;
 	s16 reg;
 };
 
@@ -207,6 +208,9 @@ struct tegra_pingroup_desc {
 	int funcs[4];
 	int func_safe;
 	int vddio;
+	s16 tri_bank;	/* Register bank the tri_reg exists within */
+	s16 mux_bank;	/* Register bank the mux_reg exists within */
+	s16 pupd_bank;	/* Register bank the pupd_reg exists within */
 	s16 tri_reg; 	/* offset into the TRISTATE_REG_* register bank */
 	s16 mux_reg;	/* offset into the PIN_MUX_CTL_* register bank */
 	s16 pupd_reg;	/* offset into the PULL_UPDOWN_REG_* register bank */
diff --git a/arch/arm/mach-tegra/include/mach/powergate.h b/arch/arm/mach-tegra/include/mach/powergate.h
index 401d1b7..39c396d 100644
--- a/arch/arm/mach-tegra/include/mach/powergate.h
+++ b/arch/arm/mach-tegra/include/mach/powergate.h
@@ -31,7 +31,6 @@
 
 int tegra_powergate_power_on(int id);
 int tegra_powergate_power_off(int id);
-bool tegra_powergate_is_powered(int id);
 int tegra_powergate_remove_clamping(int id);
 
 /* Must be called with clk disabled, and returns with clk enabled */
diff --git a/arch/arm/mach-tegra/io.c b/arch/arm/mach-tegra/io.c
index ea50fe2..5489f8b 100644
--- a/arch/arm/mach-tegra/io.c
+++ b/arch/arm/mach-tegra/io.c
@@ -31,25 +31,25 @@
 
 static struct map_desc tegra_io_desc[] __initdata = {
 	{
-		.virtual = IO_PPSB_VIRT,
+		.virtual = (unsigned long)IO_PPSB_VIRT,
 		.pfn = __phys_to_pfn(IO_PPSB_PHYS),
 		.length = IO_PPSB_SIZE,
 		.type = MT_DEVICE,
 	},
 	{
-		.virtual = IO_APB_VIRT,
+		.virtual = (unsigned long)IO_APB_VIRT,
 		.pfn = __phys_to_pfn(IO_APB_PHYS),
 		.length = IO_APB_SIZE,
 		.type = MT_DEVICE,
 	},
 	{
-		.virtual = IO_CPU_VIRT,
+		.virtual = (unsigned long)IO_CPU_VIRT,
 		.pfn = __phys_to_pfn(IO_CPU_PHYS),
 		.length = IO_CPU_SIZE,
 		.type = MT_DEVICE,
 	},
 	{
-		.virtual = IO_IRAM_VIRT,
+		.virtual = (unsigned long)IO_IRAM_VIRT,
 		.pfn = __phys_to_pfn(IO_IRAM_PHYS),
 		.length = IO_IRAM_SIZE,
 		.type = MT_DEVICE,
diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c
index f1f699d..f5aa173 100644
--- a/arch/arm/mach-tegra/pcie.c
+++ b/arch/arm/mach-tegra/pcie.c
@@ -41,6 +41,8 @@
 #include <mach/clk.h>
 #include <mach/powergate.h>
 
+#include "board.h"
+
 /* register definitions */
 #define AFI_OFFSET	0x3800
 #define PADS_OFFSET	0x3000
@@ -150,9 +152,9 @@
 static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
 
 #define pmc_writel(value, reg) \
-	__raw_writel(value, (u32)reg_pmc_base + (reg))
+	__raw_writel(value, reg_pmc_base + (reg))
 #define pmc_readl(reg) \
-	__raw_readl((u32)reg_pmc_base + (reg))
+	__raw_readl(reg_pmc_base + (reg))
 
 /*
  * Tegra2 defines 1GB in the AXI address map for PCIe.
@@ -460,7 +462,7 @@ static struct pci_bus __init *tegra_pcie_scan_bus(int nr,
 	struct tegra_pcie_port *pp;
 
 	if (nr >= tegra_pcie.num_ports)
-		return 0;
+		return NULL;
 
 	pp = tegra_pcie.port + nr;
 	pp->root_bus_nr = sys->busnr;
diff --git a/arch/arm/mach-tegra/pinmux-t2-tables.c b/arch/arm/mach-tegra/pinmux-t2-tables.c
index a475367..a0dc2bc 100644
--- a/arch/arm/mach-tegra/pinmux-t2-tables.c
+++ b/arch/arm/mach-tegra/pinmux-t2-tables.c
@@ -31,10 +31,16 @@
 #include <mach/pinmux.h>
 #include <mach/suspend.h>
 
+#define TRISTATE_REG_A		0x14
+#define PIN_MUX_CTL_REG_A	0x80
+#define PULLUPDOWN_REG_A	0xa0
+#define PINGROUP_REG_A		0x868
+
 #define DRIVE_PINGROUP(pg_name, r)				\
 	[TEGRA_DRIVE_PINGROUP_ ## pg_name] = {			\
 		.name = #pg_name,				\
-		.reg = r					\
+		.reg_bank = 3,					\
+		.reg = ((r) - PINGROUP_REG_A)			\
 	}
 
 const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE_PINGROUP] = {
@@ -90,11 +96,14 @@ const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE
 			TEGRA_MUX_ ## f3,			\
 		},						\
 		.func_safe = TEGRA_MUX_ ## f_safe,		\
-		.tri_reg = tri_r,				\
+		.tri_bank = 0,					\
+		.tri_reg = ((tri_r) - TRISTATE_REG_A),		\
 		.tri_bit = tri_b,				\
-		.mux_reg = mux_r,				\
+		.mux_bank = 1,					\
+		.mux_reg = ((mux_r) - PIN_MUX_CTL_REG_A),	\
 		.mux_bit = mux_b,				\
-		.pupd_reg = pupd_r,				\
+		.pupd_bank = 2,				\
+		.pupd_reg = ((pupd_r) - PULLUPDOWN_REG_A),	\
 		.pupd_bit = pupd_b,				\
 	}
 
@@ -217,62 +226,3 @@ const struct tegra_pingroup_desc tegra_soc_pingroups[TEGRA_MAX_PINGROUP] = {
 	PINGROUP(XM2C,  DDR,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xA8, 30),
 	PINGROUP(XM2D,  DDR,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xA8, 28),
 };
-
-#ifdef CONFIG_PM
-#define TRISTATE_REG_A         0x14
-#define TRISTATE_REG_NUM       4
-#define PIN_MUX_CTL_REG_A      0x80
-#define PIN_MUX_CTL_REG_NUM    8
-#define PULLUPDOWN_REG_A       0xa0
-#define PULLUPDOWN_REG_NUM     5
-
-static u32 pinmux_reg[TRISTATE_REG_NUM + PIN_MUX_CTL_REG_NUM +
-		      PULLUPDOWN_REG_NUM +
-		      ARRAY_SIZE(tegra_soc_drive_pingroups)];
-
-static inline unsigned long pg_readl(unsigned long offset)
-{
-	return readl(IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
-}
-
-static inline void pg_writel(unsigned long value, unsigned long offset)
-{
-	writel(value, IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
-}
-
-void tegra_pinmux_suspend(void)
-{
-	unsigned int i;
-	u32 *ctx = pinmux_reg;
-
-	for (i = 0; i < PIN_MUX_CTL_REG_NUM; i++)
-		*ctx++ = pg_readl(PIN_MUX_CTL_REG_A + i*4);
-
-	for (i = 0; i < PULLUPDOWN_REG_NUM; i++)
-		*ctx++ = pg_readl(PULLUPDOWN_REG_A + i*4);
-
-	for (i = 0; i < TRISTATE_REG_NUM; i++)
-		*ctx++ = pg_readl(TRISTATE_REG_A + i*4);
-
-	for (i = 0; i < ARRAY_SIZE(tegra_soc_drive_pingroups); i++)
-		*ctx++ = pg_readl(tegra_soc_drive_pingroups[i].reg);
-}
-
-void tegra_pinmux_resume(void)
-{
-	unsigned int i;
-	u32 *ctx = pinmux_reg;
-
-	for (i = 0; i < PIN_MUX_CTL_REG_NUM; i++)
-		pg_writel(*ctx++, PIN_MUX_CTL_REG_A + i*4);
-
-	for (i = 0; i < PULLUPDOWN_REG_NUM; i++)
-		pg_writel(*ctx++, PULLUPDOWN_REG_A + i*4);
-
-	for (i = 0; i < TRISTATE_REG_NUM; i++)
-		pg_writel(*ctx++, TRISTATE_REG_A + i*4);
-
-	for (i = 0; i < ARRAY_SIZE(tegra_soc_drive_pingroups); i++)
-		pg_writel(*ctx++, tegra_soc_drive_pingroups[i].reg);
-}
-#endif
diff --git a/arch/arm/mach-tegra/pinmux.c b/arch/arm/mach-tegra/pinmux.c
index f80d507..1d20165 100644
--- a/arch/arm/mach-tegra/pinmux.c
+++ b/arch/arm/mach-tegra/pinmux.c
@@ -20,6 +20,7 @@
 #include <linux/errno.h>
 #include <linux/spinlock.h>
 #include <linux/io.h>
+#include <linux/platform_device.h>
 
 #include <mach/iomap.h>
 #include <mach/pinmux.h>
@@ -169,15 +170,17 @@ static const char *pupd_name(unsigned long val)
 	}
 }
 
+static int nbanks;
+static void __iomem **regs;
 
-static inline unsigned long pg_readl(unsigned long offset)
+static inline u32 pg_readl(u32 bank, u32 reg)
 {
-	return readl(IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
+	return readl(regs[bank] + reg);
 }
 
-static inline void pg_writel(unsigned long value, unsigned long offset)
+static inline void pg_writel(u32 val, u32 bank, u32 reg)
 {
-	writel(value, IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
+	writel(val, regs[bank] + reg);
 }
 
 static int tegra_pinmux_set_func(const struct tegra_pingroup_config *config)
@@ -217,10 +220,10 @@ static int tegra_pinmux_set_func(const struct tegra_pingroup_config *config)
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(pingroups[pg].mux_reg);
+	reg = pg_readl(pingroups[pg].mux_bank, pingroups[pg].mux_reg);
 	reg &= ~(0x3 << pingroups[pg].mux_bit);
 	reg |= mux << pingroups[pg].mux_bit;
-	pg_writel(reg, pingroups[pg].mux_reg);
+	pg_writel(reg, pingroups[pg].mux_bank, pingroups[pg].mux_reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -241,11 +244,11 @@ int tegra_pinmux_set_tristate(enum tegra_pingroup pg,
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(pingroups[pg].tri_reg);
+	reg = pg_readl(pingroups[pg].tri_bank, pingroups[pg].tri_reg);
 	reg &= ~(0x1 << pingroups[pg].tri_bit);
 	if (tristate)
 		reg |= 1 << pingroups[pg].tri_bit;
-	pg_writel(reg, pingroups[pg].tri_reg);
+	pg_writel(reg, pingroups[pg].tri_bank, pingroups[pg].tri_reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -272,10 +275,10 @@ int tegra_pinmux_set_pullupdown(enum tegra_pingroup pg,
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(pingroups[pg].pupd_reg);
+	reg = pg_readl(pingroups[pg].pupd_bank, pingroups[pg].pupd_reg);
 	reg &= ~(0x3 << pingroups[pg].pupd_bit);
 	reg |= pupd << pingroups[pg].pupd_bit;
-	pg_writel(reg, pingroups[pg].pupd_reg);
+	pg_writel(reg, pingroups[pg].pupd_bank, pingroups[pg].pupd_reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -362,12 +365,12 @@ static int tegra_drive_pinmux_set_hsm(enum tegra_drive_pingroup pg,
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(drive_pingroups[pg].reg);
+	reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 	if (hsm == TEGRA_HSM_ENABLE)
 		reg |= (1 << 2);
 	else
 		reg &= ~(1 << 2);
-	pg_writel(reg, drive_pingroups[pg].reg);
+	pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -387,12 +390,12 @@ static int tegra_drive_pinmux_set_schmitt(enum tegra_drive_pingroup pg,
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(drive_pingroups[pg].reg);
+	reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 	if (schmitt == TEGRA_SCHMITT_ENABLE)
 		reg |= (1 << 3);
 	else
 		reg &= ~(1 << 3);
-	pg_writel(reg, drive_pingroups[pg].reg);
+	pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -412,10 +415,10 @@ static int tegra_drive_pinmux_set_drive(enum tegra_drive_pingroup pg,
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(drive_pingroups[pg].reg);
+	reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 	reg &= ~(0x3 << 4);
 	reg |= drive << 4;
-	pg_writel(reg, drive_pingroups[pg].reg);
+	pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -435,10 +438,10 @@ static int tegra_drive_pinmux_set_pull_down(enum tegra_drive_pingroup pg,
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(drive_pingroups[pg].reg);
+	reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 	reg &= ~(0x1f << 12);
 	reg |= pull_down << 12;
-	pg_writel(reg, drive_pingroups[pg].reg);
+	pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -458,10 +461,10 @@ static int tegra_drive_pinmux_set_pull_up(enum tegra_drive_pingroup pg,
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(drive_pingroups[pg].reg);
+	reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 	reg &= ~(0x1f << 12);
 	reg |= pull_up << 12;
-	pg_writel(reg, drive_pingroups[pg].reg);
+	pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -481,10 +484,10 @@ static int tegra_drive_pinmux_set_slew_rising(enum tegra_drive_pingroup pg,
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(drive_pingroups[pg].reg);
+	reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 	reg &= ~(0x3 << 28);
 	reg |= slew_rising << 28;
-	pg_writel(reg, drive_pingroups[pg].reg);
+	pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -504,10 +507,10 @@ static int tegra_drive_pinmux_set_slew_falling(enum tegra_drive_pingroup pg,
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(drive_pingroups[pg].reg);
+	reg = pg_readl(drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 	reg &= ~(0x3 << 30);
 	reg |= slew_falling << 30;
-	pg_writel(reg, drive_pingroups[pg].reg);
+	pg_writel(reg, drive_pingroups[pg].reg_bank, drive_pingroups[pg].reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -665,6 +668,99 @@ void tegra_pinmux_config_pullupdown_table(const struct tegra_pingroup_config *co
 	}
 }
 
+static int __devinit tegra_pinmux_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	int i;
+	int config_bad = 0;
+
+	for (i = 0; ; i++) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		if (!res)
+			break;
+	}
+	nbanks = i;
+
+	for (i = 0; i < TEGRA_MAX_PINGROUP; i++) {
+		if (pingroups[i].tri_bank >= nbanks) {
+			dev_err(&pdev->dev, "pingroup %d: bad tri_bank\n", i);
+			config_bad = 1;
+		}
+
+		if (pingroups[i].mux_bank >= nbanks) {
+			dev_err(&pdev->dev, "pingroup %d: bad mux_bank\n", i);
+			config_bad = 1;
+		}
+
+		if (pingroups[i].pupd_bank >= nbanks) {
+			dev_err(&pdev->dev, "pingroup %d: bad pupd_bank\n", i);
+			config_bad = 1;
+		}
+	}
+
+	for (i = 0; i < TEGRA_MAX_DRIVE_PINGROUP; i++) {
+		if (drive_pingroups[i].reg_bank >= nbanks) {
+			dev_err(&pdev->dev,
+				"drive pingroup %d: bad reg_bank\n", i);
+			config_bad = 1;
+		}
+	}
+
+	if (config_bad)
+		return -ENODEV;
+
+	regs = devm_kzalloc(&pdev->dev, nbanks * sizeof(*regs), GFP_KERNEL);
+	if (!regs) {
+		dev_err(&pdev->dev, "Can't alloc regs pointer\n");
+		return -ENODEV;
+	}
+
+	for (i = 0; i < nbanks; i++) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		if (!res) {
+			dev_err(&pdev->dev, "Missing MEM resource\n");
+			return -ENODEV;
+		}
+
+		if (!devm_request_mem_region(&pdev->dev, res->start,
+					    resource_size(res),
+					    dev_name(&pdev->dev))) {
+			dev_err(&pdev->dev,
+				"Couldn't request MEM resource %d\n", i);
+			return -ENODEV;
+		}
+
+		regs[i] = devm_ioremap(&pdev->dev, res->start,
+					resource_size(res));
+		if (!regs) {
+			dev_err(&pdev->dev, "Couldn't ioremap regs %d\n", i);
+			return -ENODEV;
+		}
+	}
+
+	return 0;
+}
+
+static struct of_device_id tegra_pinmux_of_match[] __devinitdata = {
+	{ .compatible = "nvidia,tegra20-pinmux", },
+	{ },
+};
+
+static struct platform_driver tegra_pinmux_driver = {
+	.driver		= {
+		.name	= "tegra-pinmux",
+		.owner	= THIS_MODULE,
+		.of_match_table = tegra_pinmux_of_match,
+	},
+	.probe		= tegra_pinmux_probe,
+};
+
+static int __init tegra_pinmux_init(void)
+{
+	return platform_driver_register(&tegra_pinmux_driver);
+}
+postcore_initcall(tegra_pinmux_init);
+
 #ifdef	CONFIG_DEBUG_FS
 
 #include <linux/debugfs.h>
@@ -684,6 +780,7 @@ static int dbg_pinmux_show(struct seq_file *s, void *unused)
 	int len;
 
 	for (i = 0; i < TEGRA_MAX_PINGROUP; i++) {
+		unsigned long reg;
 		unsigned long tri;
 		unsigned long mux;
 		unsigned long pupd;
@@ -696,8 +793,9 @@ static int dbg_pinmux_show(struct seq_file *s, void *unused)
 			seq_printf(s, "TEGRA_MUX_NONE");
 			len = strlen("NONE");
 		} else {
-			mux = (pg_readl(pingroups[i].mux_reg) >>
-			       pingroups[i].mux_bit) & 0x3;
+			reg = pg_readl(pingroups[i].mux_bank,
+					pingroups[i].mux_reg);
+			mux = (reg >> pingroups[i].mux_bit) & 0x3;
 			if (pingroups[i].funcs[mux] == TEGRA_MUX_RSVD) {
 				seq_printf(s, "TEGRA_MUX_RSVD%1lu", mux+1);
 				len = 5;
@@ -713,8 +811,9 @@ static int dbg_pinmux_show(struct seq_file *s, void *unused)
 			seq_printf(s, "TEGRA_PUPD_NORMAL");
 			len = strlen("NORMAL");
 		} else {
-			pupd = (pg_readl(pingroups[i].pupd_reg) >>
-				pingroups[i].pupd_bit) & 0x3;
+			reg = pg_readl(pingroups[i].pupd_bank,
+					pingroups[i].pupd_reg);
+			pupd = (reg >> pingroups[i].pupd_bit) & 0x3;
 			seq_printf(s, "TEGRA_PUPD_%s", pupd_name(pupd));
 			len = strlen(pupd_name(pupd));
 		}
@@ -723,8 +822,9 @@ static int dbg_pinmux_show(struct seq_file *s, void *unused)
 		if (pingroups[i].tri_reg < 0) {
 			seq_printf(s, "TEGRA_TRI_NORMAL");
 		} else {
-			tri = (pg_readl(pingroups[i].tri_reg) >>
-			       pingroups[i].tri_bit) & 0x1;
+			reg = pg_readl(pingroups[i].tri_bank,
+					pingroups[i].tri_reg);
+			tri = (reg >> pingroups[i].tri_bit) & 0x1;
 
 			seq_printf(s, "TEGRA_TRI_%s", tri_name(tri));
 		}
@@ -759,7 +859,8 @@ static int dbg_drive_pinmux_show(struct seq_file *s, void *unused)
 		dbg_pad_field(s, 7 - len);
 
 
-		reg = pg_readl(drive_pingroups[i].reg);
+		reg = pg_readl(drive_pingroups[i].reg_bank,
+				drive_pingroups[i].reg);
 		if (HSM_EN(reg)) {
 			seq_printf(s, "TEGRA_HSM_ENABLE");
 			len = 16;
diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c
index 3cee9aa..9483064 100644
--- a/arch/arm/mach-tegra/powergate.c
+++ b/arch/arm/mach-tegra/powergate.c
@@ -89,12 +89,11 @@ int tegra_powergate_power_off(int id)
 	return tegra_powergate_set(id, false);
 }
 
-bool tegra_powergate_is_powered(int id)
+static bool tegra_powergate_is_powered(int id)
 {
 	u32 status;
 
-	if (id < 0 || id >= TEGRA_NUM_POWERGATE)
-		return -EINVAL;
+	WARN_ON(id < 0 || id >= TEGRA_NUM_POWERGATE);
 
 	status = pmc_read(PWRGATE_STATUS) & (1 << id);
 	return !!status;
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c
index 0fe9b3e..371869d 100644
--- a/arch/arm/mach-tegra/tegra2_clocks.c
+++ b/arch/arm/mach-tegra/tegra2_clocks.c
@@ -166,13 +166,13 @@ static DEFINE_SPINLOCK(clock_register_lock);
 static int tegra_periph_clk_enable_refcount[3 * 32];
 
 #define clk_writel(value, reg) \
-	__raw_writel(value, (u32)reg_clk_base + (reg))
+	__raw_writel(value, reg_clk_base + (reg))
 #define clk_readl(reg) \
-	__raw_readl((u32)reg_clk_base + (reg))
+	__raw_readl(reg_clk_base + (reg))
 #define pmc_writel(value, reg) \
-	__raw_writel(value, (u32)reg_pmc_base + (reg))
+	__raw_writel(value, reg_pmc_base + (reg))
 #define pmc_readl(reg) \
-	__raw_readl((u32)reg_pmc_base + (reg))
+	__raw_readl(reg_pmc_base + (reg))
 
 unsigned long clk_measure_input_freq(void)
 {
@@ -918,7 +918,7 @@ static struct clk_ops tegra_pll_div_ops = {
 static void tegra2_periph_clk_init(struct clk *c)
 {
 	u32 val = clk_readl(c->reg);
-	const struct clk_mux_sel *mux = 0;
+	const struct clk_mux_sel *mux = NULL;
 	const struct clk_mux_sel *sel;
 	if (c->flags & MUX) {
 		for (sel = c->inputs; sel->input != NULL; sel++) {
@@ -1459,7 +1459,7 @@ static struct clk tegra_pll_s = {
 static struct clk_mux_sel tegra_clk_m_sel[] = {
 	{ .input = &tegra_clk_32k, .value = 0},
 	{ .input = &tegra_pll_s,  .value = 1},
-	{ 0, 0},
+	{ NULL , 0},
 };
 
 static struct clk tegra_clk_m = {
@@ -1861,7 +1861,7 @@ static const struct audio_sources {
 	{ .name = "ext_audio_clk1", .value = 6 },
 	{ .name = "ext_vimclk", .value = 7 },
 #endif
-	{ 0, 0 }
+	{ NULL, 0 }
 };
 
 static struct clk tegra_clk_audio = {
@@ -1885,7 +1885,7 @@ static struct clk tegra_clk_audio_2x = {
 	},
 };
 
-struct clk_lookup tegra_audio_clk_lookups[] = {
+static struct clk_lookup tegra_audio_clk_lookups[] = {
 	{ .con_id = "audio", .clk = &tegra_clk_audio },
 	{ .con_id = "audio_2x", .clk = &tegra_clk_audio_2x }
 };
@@ -1926,7 +1926,7 @@ static struct clk_mux_sel mux_cclk[] = {
 	{ .input = &tegra_pll_p_out3,	.value = 6},
 	{ .input = &tegra_clk_d,	.value = 7},
 	{ .input = &tegra_pll_x,	.value = 8},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_sclk[] = {
@@ -1938,7 +1938,7 @@ static struct clk_mux_sel mux_sclk[] = {
 	{ .input = &tegra_clk_d,	.value = 5},
 	{ .input = &tegra_clk_32k,	.value = 6},
 	{ .input = &tegra_pll_m_out1,	.value = 7},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk tegra_clk_cclk = {
@@ -2009,7 +2009,7 @@ static struct clk_mux_sel mux_pllm_pllc_pllp_plla[] = {
 	{ .input = &tegra_pll_c, .value = 1},
 	{ .input = &tegra_pll_p, .value = 2},
 	{ .input = &tegra_pll_a_out0, .value = 3},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_pllm_pllc_pllp_clkm[] = {
@@ -2017,7 +2017,7 @@ static struct clk_mux_sel mux_pllm_pllc_pllp_clkm[] = {
 	{ .input = &tegra_pll_c, .value = 1},
 	{ .input = &tegra_pll_p, .value = 2},
 	{ .input = &tegra_clk_m, .value = 3},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_pllp_pllc_pllm_clkm[] = {
@@ -2025,7 +2025,7 @@ static struct clk_mux_sel mux_pllp_pllc_pllm_clkm[] = {
 	{ .input = &tegra_pll_c, .value = 1},
 	{ .input = &tegra_pll_m, .value = 2},
 	{ .input = &tegra_clk_m, .value = 3},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_pllaout0_audio2x_pllp_clkm[] = {
@@ -2033,7 +2033,7 @@ static struct clk_mux_sel mux_pllaout0_audio2x_pllp_clkm[] = {
 	{.input = &tegra_clk_audio_2x, .value = 1},
 	{.input = &tegra_pll_p, .value = 2},
 	{.input = &tegra_clk_m, .value = 3},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_pllp_plld_pllc_clkm[] = {
@@ -2041,7 +2041,7 @@ static struct clk_mux_sel mux_pllp_plld_pllc_clkm[] = {
 	{.input = &tegra_pll_d_out0, .value = 1},
 	{.input = &tegra_pll_c, .value = 2},
 	{.input = &tegra_clk_m, .value = 3},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_pllp_pllc_audio_clkm_clk32[] = {
@@ -2050,39 +2050,39 @@ static struct clk_mux_sel mux_pllp_pllc_audio_clkm_clk32[] = {
 	{.input = &tegra_clk_audio,     .value = 2},
 	{.input = &tegra_clk_m,     .value = 3},
 	{.input = &tegra_clk_32k,   .value = 4},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_pllp_pllc_pllm[] = {
 	{.input = &tegra_pll_p,     .value = 0},
 	{.input = &tegra_pll_c,     .value = 1},
 	{.input = &tegra_pll_m,     .value = 2},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_clk_m[] = {
 	{ .input = &tegra_clk_m, .value = 0},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_pllp_out3[] = {
 	{ .input = &tegra_pll_p_out3, .value = 0},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_plld[] = {
 	{ .input = &tegra_pll_d, .value = 0},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_clk_32k[] = {
 	{ .input = &tegra_clk_32k, .value = 0},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk_mux_sel mux_pclk[] = {
 	{ .input = &tegra_clk_pclk, .value = 0},
-	{ 0, 0},
+	{ NULL, 0},
 };
 
 static struct clk tegra_clk_emc = {
@@ -2125,7 +2125,7 @@ static struct clk tegra_clk_emc = {
 		.parent = _parent,			\
 	}
 
-struct clk tegra_list_clks[] = {
+static struct clk tegra_list_clks[] = {
 	PERIPH_CLK("apbdma",	"tegra-dma",		NULL,	34,	0,	108000000, mux_pclk,			0),
 	PERIPH_CLK("rtc",	"rtc-tegra",		NULL,	4,	0,	32768,     mux_clk_32k,			PERIPH_NO_RESET),
 	PERIPH_CLK("timer",	"timer",		NULL,	5,	0,	26000000,  mux_clk_m,			0),
@@ -2221,7 +2221,7 @@ struct clk tegra_list_clks[] = {
  * configuration.  List those here to register them twice in the clock lookup
  * table under two names.
  */
-struct clk_duplicate tegra_clk_duplicates[] = {
+static struct clk_duplicate tegra_clk_duplicates[] = {
 	CLK_DUPLICATE("uarta",	"tegra_uart.0",	NULL),
 	CLK_DUPLICATE("uartb",	"tegra_uart.1",	NULL),
 	CLK_DUPLICATE("uartc",	"tegra_uart.2",	NULL),
@@ -2252,7 +2252,7 @@ struct clk_duplicate tegra_clk_duplicates[] = {
 		.clk = ck,	\
 	}
 
-struct clk *tegra_ptr_clks[] = {
+static struct clk *tegra_ptr_clks[] = {
 	&tegra_clk_32k,
 	&tegra_pll_s,
 	&tegra_clk_m,
diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c
index 9035042..e2272d2 100644
--- a/arch/arm/mach-tegra/timer.c
+++ b/arch/arm/mach-tegra/timer.c
@@ -62,9 +62,9 @@ static struct timespec persistent_ts;
 static u64 persistent_ms, last_persistent_ms;
 
 #define timer_writel(value, reg) \
-	__raw_writel(value, (u32)timer_reg_base + (reg))
+	__raw_writel(value, timer_reg_base + (reg))
 #define timer_readl(reg) \
-	__raw_readl((u32)timer_reg_base + (reg))
+	__raw_readl(timer_reg_base + (reg))
 
 static int tegra_timer_set_next_event(unsigned long cycles,
 					 struct clock_event_device *evt)
@@ -133,7 +133,7 @@ static void notrace tegra_update_sched_clock(void)
  * tegra_rtc driver could be executing to avoid race conditions
  * on the RTC shadow register
  */
-u64 tegra_rtc_read_ms(void)
+static u64 tegra_rtc_read_ms(void)
 {
 	u32 ms = readl(rtc_base + RTC_MILLISECONDS);
 	u32 s = readl(rtc_base + RTC_SHADOW_SECONDS);
diff --git a/arch/arm/mach-u300/Kconfig b/arch/arm/mach-u300/Kconfig
index d6e5d30..1cbcd4f 100644
--- a/arch/arm/mach-u300/Kconfig
+++ b/arch/arm/mach-u300/Kconfig
@@ -51,39 +51,12 @@ config MACH_U300_BS365
 
 endchoice
 
-choice
-	prompt "Memory configuration"
-	default MACH_U300_SINGLE_RAM
-	---help---
-	You have to config the kernel according to the physical memory
-	configuration.
-
-config MACH_U300_SINGLE_RAM
-	bool "Single RAM"
-	help
-		Select this if you want support for Single RAM phones.
-
-config MACH_U300_DUAL_RAM
-	bool "Dual RAM"
-	help
-		Select this if you want support for Dual RAM phones.
-		This is two RAM memories on different EMIFs.
-endchoice
-
 config U300_DEBUG
 	bool "Debug support for U300"
 	depends on PM
 	help
 		Debug support for U300 in sysfs, procfs etc.
 
-config MACH_U300_SEMI_IS_SHARED
-	bool "The SEMI is used by both the access and application side"
-	depends on MACH_U300
-	help
-		This makes it possible to use the SEMI (Shared External
-		Memory Interface) from both from access and application
-		side.
-
 config MACH_U300_SPIDUMMY
 	bool "SSP/SPI dummy chip"
 	select SPI
@@ -96,25 +69,6 @@ config MACH_U300_SPIDUMMY
 		you don't need it. Selecting this will activate the
 		SPI framework and ARM PL022 support.
 
-comment "All the settings below must match the bootloader's settings"
-
-config MACH_U300_ACCESS_MEM_SIZE
-       int "Access CPU memory allocation"
-       range 7 25
-       depends on MACH_U300_SINGLE_RAM
-       default 13
-       help
-		How much memory in MiB that the Access side CPU has allocated
-
-config MACH_U300_2MB_ALIGNMENT_FIX
-       bool "2MiB alignment fix"
-       depends on MACH_U300_SINGLE_RAM
-       default y
-       help
-		If yes and the Access side CPU has allocated an odd size in
-		MiB, this fix gives you one MiB extra that would otherwise be
-		lost due to Linux 2 MiB alignment policy.
-
 endmenu
 
 endif
diff --git a/arch/arm/mach-u300/Makefile.boot b/arch/arm/mach-u300/Makefile.boot
index 69357af..87811de 100644
--- a/arch/arm/mach-u300/Makefile.boot
+++ b/arch/arm/mach-u300/Makefile.boot
@@ -1,15 +1,4 @@
-# Note: the following conditions must always be true:
-#   ZRELADDR == virt_to_phys(TEXTADDR)
-#   PARAMS_PHYS must be within 4MB of ZRELADDR
-#   INITRD_PHYS must be in RAM
-
-ifdef CONFIG_MACH_U300_SINGLE_RAM
-     zreladdr-y	+= 0x28E08000
-  params_phys-y	:= 0x28E00100
-else
-     zreladdr-y	+= 0x48008000
-  params_phys-y	:= 0x48000100
-endif
-
+   zreladdr-y	+= 0x48008000
+params_phys-y	:= 0x48000100
 # This isn't used.
-#initrd_phys-y	:= 0x29800000
+#initrd_phys-y	:= 0x48800000
diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c
index f4ad6d2..ac0791e 100644
--- a/arch/arm/mach-u300/core.c
+++ b/arch/arm/mach-u300/core.c
@@ -72,25 +72,6 @@ static struct map_desc u300_io_desc[] __initdata = {
 		.length		= SZ_32K,
 		.type		= MT_DEVICE,
 	},
-	{
-		.virtual	= 0xffff2000, /* TCM memory */
-		.pfn		= __phys_to_pfn(0xffff2000),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	},
-
-	/*
-	 * This overlaps with the IRQ vectors etc at 0xffff0000, so these
-	 * may have to be moved to 0x00000000 in order to use the ROM.
-	 */
-	/*
-	{
-		.virtual	= U300_BOOTROM_VIRT_BASE,
-		.pfn		= __phys_to_pfn(U300_BOOTROM_PHYS_BASE),
-		.length		= SZ_64K,
-		.type		= MT_ROM,
-	},
-	*/
 };
 
 void __init u300_map_io(void)
@@ -367,51 +348,6 @@ static struct resource wdog_resources[] = {
 	}
 };
 
-/* TODO: These should be protected by suitable #ifdef's */
-static struct resource ave_resources[] = {
-	{
-		.name  = "AVE3e I/O Area",
-		.start = U300_VIDEOENC_BASE,
-		.end   = U300_VIDEOENC_BASE + SZ_512K - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name  = "AVE3e IRQ0",
-		.start = IRQ_U300_VIDEO_ENC_0,
-		.end   = IRQ_U300_VIDEO_ENC_0,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name  = "AVE3e IRQ1",
-		.start = IRQ_U300_VIDEO_ENC_1,
-		.end   = IRQ_U300_VIDEO_ENC_1,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name  = "AVE3e Physmem Area",
-		.start = 0, /* 0 will be remapped to reserved memory */
-		.end   = SZ_1M - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	/*
-	 * The AVE3e requires two regions of 256MB that it considers
-	 * "invisible". The hardware will not be able to access these
-	 * addresses, so they should never point to system RAM.
-	 */
-	{
-		.name  = "AVE3e Reserved 0",
-		.start = 0xd0000000,
-		.end   = 0xd0000000 + SZ_256M - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name  = "AVE3e Reserved 1",
-		.start = 0xe0000000,
-		.end   = 0xe0000000 + SZ_256M - 1,
-		.flags = IORESOURCE_MEM,
-	},
-};
-
 static struct resource dma_resource[] = {
 	{
 		.start = U300_DMAC_BASE,
@@ -1650,13 +1586,6 @@ static struct platform_device nand_device = {
 	},
 };
 
-static struct platform_device ave_device = {
-	.name = "video_enc",
-	.id = -1,
-	.num_resources = ARRAY_SIZE(ave_resources),
-	.resource = ave_resources,
-};
-
 static struct platform_device dma_device = {
 	.name		= "coh901318",
 	.id		= -1,
@@ -1747,7 +1676,6 @@ static struct platform_device *platform_devs[] __initdata = {
 	&gpio_device,
 	&nand_device,
 	&wdog_device,
-	&ave_device,
 	&pinmux_device,
 };
 
@@ -1945,17 +1873,10 @@ void __init u300_init_devices(void)
 	/* Register subdevices on the SPI bus */
 	u300_spi_register_board_devices();
 
-#ifndef CONFIG_MACH_U300_SEMI_IS_SHARED
-	/*
-	 * Enable SEMI self refresh. Self-refresh of the SDRAM is entered when
-	 * both subsystems are requesting this mode.
-	 * If we not share the Acc SDRAM, this is never the case. Therefore
-	 * enable it here from the App side.
-	 */
+	/* Enable SEMI self refresh */
 	val = readw(U300_SYSCON_VBASE + U300_SYSCON_SMCR) |
 		U300_SYSCON_SMCR_SEMI_SREFREQ_ENABLE;
 	writew(val, U300_SYSCON_VBASE + U300_SYSCON_SMCR);
-#endif /* CONFIG_MACH_U300_SEMI_IS_SHARED */
 }
 
 static int core_module_init(void)
diff --git a/arch/arm/mach-u300/include/mach/memory.h b/arch/arm/mach-u300/include/mach/memory.h
index 7034bae..c808f34 100644
--- a/arch/arm/mach-u300/include/mach/memory.h
+++ b/arch/arm/mach-u300/include/mach/memory.h
@@ -13,25 +13,7 @@
 #ifndef __MACH_MEMORY_H
 #define __MACH_MEMORY_H
 
-#ifdef CONFIG_MACH_U300_DUAL_RAM
-
-#define PLAT_PHYS_OFFSET		UL(0x48000000)
-#define BOOT_PARAMS_OFFSET		0x100
-
-#else
-
-#ifdef CONFIG_MACH_U300_2MB_ALIGNMENT_FIX
-#define PLAT_PHYS_OFFSET (0x28000000 + \
-	     (CONFIG_MACH_U300_ACCESS_MEM_SIZE - \
-	     (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024)
-#define BOOT_PARAMS_OFFSET (0x100 + \
-	     (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1)*1024*1024*2)
-#else
-#define PLAT_PHYS_OFFSET (0x28000000 + \
-	     (CONFIG_MACH_U300_ACCESS_MEM_SIZE +	\
-	     (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024)
-#define BOOT_PARAMS_OFFSET 0x100
-#endif
-#endif
+#define PLAT_PHYS_OFFSET	UL(0x48000000)
+#define BOOT_PARAMS_OFFSET	0x100
 
 #endif
diff --git a/arch/arm/mach-u300/u300.c b/arch/arm/mach-u300/u300.c
index 80e7305..89422ee 100644
--- a/arch/arm/mach-u300/u300.c
+++ b/arch/arm/mach-u300/u300.c
@@ -23,21 +23,6 @@
 #include <asm/mach/arch.h>
 #include <asm/memory.h>
 
-static void __init u300_reserve(void)
-{
-	/*
-	 * U300 - This platform family can share physical memory
-	 * between two ARM cpus, one running Linux and the other
-	 * running another OS.
-	 */
-#ifdef CONFIG_MACH_U300_SINGLE_RAM
-#if ((CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1) == 1) && \
-	CONFIG_MACH_U300_2MB_ALIGNMENT_FIX
-        memblock_reserve(PHYS_OFFSET, 0x00100000);
-#endif
-#endif
-}
-
 static void __init u300_init_machine(void)
 {
 	u300_init_devices();
@@ -63,7 +48,6 @@ MACHINE_START(U300, MACH_U300_STRING)
 	/* Maintainer: Linus Walleij <linus.walleij@stericsson.com> */
 	.atag_offset	= BOOT_PARAMS_OFFSET,
 	.map_io		= u300_map_io,
-	.reserve	= u300_reserve,
 	.init_irq	= u300_init_irq,
 	.timer		= &u300_timer,
 	.init_machine	= u300_init_machine,
diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile
index 1694916..6bd2f45 100644
--- a/arch/arm/mach-ux500/Makefile
+++ b/arch/arm/mach-ux500/Makefile
@@ -3,7 +3,8 @@
 #
 
 obj-y				:= clock.o cpu.o devices.o devices-common.o \
-				   id.o usb.o
+				   id.o usb.o timer.o
+obj-$(CONFIG_CACHE_L2X0)	+= cache-l2x0.o
 obj-$(CONFIG_UX500_SOC_DB5500)	+= cpu-db5500.o dma-db5500.o
 obj-$(CONFIG_UX500_SOC_DB8500)	+= cpu-db8500.o devices-db8500.o
 obj-$(CONFIG_MACH_U8500)	+= board-mop500.o board-mop500-sdi.o \
diff --git a/arch/arm/mach-ux500/board-mop500-pins.c b/arch/arm/mach-ux500/board-mop500-pins.c
index 15b23e4..74bfcff 100644
--- a/arch/arm/mach-ux500/board-mop500-pins.c
+++ b/arch/arm/mach-ux500/board-mop500-pins.c
@@ -153,7 +153,7 @@ static pin_cfg_t mop500_pins_default[] = {
 	GPIO7_U1_RTSn	| PIN_OUTPUT_HIGH,
 };
 
-static pin_cfg_t mop500_pins_hrefv60[] = {
+static pin_cfg_t hrefv60_pins[] = {
 	/* WLAN */
 	GPIO4_GPIO		| PIN_INPUT_PULLUP,/* WLAN_IRQ */
 	GPIO85_GPIO		| PIN_OUTPUT_LOW,/* WLAN_ENA */
@@ -279,14 +279,26 @@ static pin_cfg_t snowball_pins[] = {
 void __init mop500_pins_init(void)
 {
 	nmk_config_pins(mop500_pins_common,
-				ARRAY_SIZE(mop500_pins_common));
-	if (machine_is_hrefv60())
-		nmk_config_pins(mop500_pins_hrefv60,
-				ARRAY_SIZE(mop500_pins_hrefv60));
-	else if (machine_is_snowball())
-		nmk_config_pins(snowball_pins,
-				ARRAY_SIZE(snowball_pins));
-	else
-		nmk_config_pins(mop500_pins_default,
-				ARRAY_SIZE(mop500_pins_default));
+			ARRAY_SIZE(mop500_pins_common));
+
+	nmk_config_pins(mop500_pins_default,
+			ARRAY_SIZE(mop500_pins_default));
+}
+
+void __init snowball_pins_init(void)
+{
+	nmk_config_pins(mop500_pins_common,
+			ARRAY_SIZE(mop500_pins_common));
+
+	nmk_config_pins(snowball_pins,
+			ARRAY_SIZE(snowball_pins));
+}
+
+void __init hrefv60_pins_init(void)
+{
+	nmk_config_pins(mop500_pins_common,
+			ARRAY_SIZE(mop500_pins_common));
+
+	nmk_config_pins(hrefv60_pins,
+			ARRAY_SIZE(hrefv60_pins));
 }
diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c
index d0cb9e5..6826fae 100644
--- a/arch/arm/mach-ux500/board-mop500-sdi.c
+++ b/arch/arm/mach-ux500/board-mop500-sdi.c
@@ -216,30 +216,48 @@ void __init mop500_sdi_init(void)
 	/* PoP:ed eMMC on top of DB8500 v1.0 has problems with high speed */
 	if (!cpu_is_u8500v10())
 		mop500_sdi2_data.capabilities |= MMC_CAP_MMC_HIGHSPEED;
-	/* sdi2 on snowball is in ATL_B mode for FSMC (LAN) */
-	if (!machine_is_snowball())
-		db8500_add_sdi2(&mop500_sdi2_data, periphid);
+
+	db8500_add_sdi2(&mop500_sdi2_data, periphid);
 
 	/* On-board eMMC */
 	db8500_add_sdi4(&mop500_sdi4_data, periphid);
 
-	if (machine_is_hrefv60() || machine_is_snowball()) {
-		if (machine_is_hrefv60()) {
-			mop500_sdi0_data.gpio_cd = HREFV60_SDMMC_CD_GPIO;
-			sdi0_en = HREFV60_SDMMC_EN_GPIO;
-			sdi0_vsel = HREFV60_SDMMC_1V8_3V_GPIO;
-		} else if (machine_is_snowball()) {
-			mop500_sdi0_data.gpio_cd = SNOWBALL_SDMMC_CD_GPIO;
-			mop500_sdi0_data.cd_invert = true;
-			sdi0_en = SNOWBALL_SDMMC_EN_GPIO;
-			sdi0_vsel = SNOWBALL_SDMMC_1V8_3V_GPIO;
-		}
-		sdi0_configure();
-	}
-
 	/*
 	 * On boards with the TC35892 GPIO expander, sdi0 will finally
 	 * be added when the TC35892 initializes and calls
 	 * mop500_sdi_tc35892_init() above.
 	 */
 }
+
+void __init snowball_sdi_init(void)
+{
+	u32 periphid = 0x10480180;
+
+	mop500_sdi2_data.capabilities |= MMC_CAP_MMC_HIGHSPEED;
+
+	/* On-board eMMC */
+	db8500_add_sdi4(&mop500_sdi4_data, periphid);
+
+	mop500_sdi0_data.gpio_cd = SNOWBALL_SDMMC_CD_GPIO;
+	mop500_sdi0_data.cd_invert = true;
+	sdi0_en = SNOWBALL_SDMMC_EN_GPIO;
+	sdi0_vsel = SNOWBALL_SDMMC_1V8_3V_GPIO;
+	sdi0_configure();
+}
+
+void __init hrefv60_sdi_init(void)
+{
+	u32 periphid = 0x10480180;
+
+	mop500_sdi2_data.capabilities |= MMC_CAP_MMC_HIGHSPEED;
+
+	db8500_add_sdi2(&mop500_sdi2_data, periphid);
+
+	/* On-board eMMC */
+	db8500_add_sdi4(&mop500_sdi4_data, periphid);
+
+	mop500_sdi0_data.gpio_cd = HREFV60_SDMMC_CD_GPIO;
+	sdi0_en = HREFV60_SDMMC_EN_GPIO;
+	sdi0_vsel = HREFV60_SDMMC_1V8_3V_GPIO;
+	sdi0_configure();
+}
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index f67b83d..bdd7b80 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -604,28 +604,72 @@ static void __init mop500_init_machine(void)
 {
 	int i2c0_devs;
 
+	mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR;
+
+	u8500_init_devices();
+
+	mop500_pins_init();
+
+	platform_add_devices(mop500_platform_devs,
+			ARRAY_SIZE(mop500_platform_devs));
+
+	mop500_i2c_init();
+	mop500_sdi_init();
+	mop500_spi_init();
+	mop500_uart_init();
+
+	i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
+
+	i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs);
+	i2c_register_board_info(2, mop500_i2c2_devices,
+				ARRAY_SIZE(mop500_i2c2_devices));
+
+	/* This board has full regulator constraints */
+	regulator_has_full_constraints();
+}
+
+static void __init snowball_init_machine(void)
+{
+	int i2c0_devs;
+
+	u8500_init_devices();
+
+	snowball_pins_init();
+
+	platform_add_devices(snowball_platform_devs,
+			ARRAY_SIZE(snowball_platform_devs));
+
+	mop500_i2c_init();
+	snowball_sdi_init();
+	mop500_spi_init();
+	mop500_uart_init();
+
+	i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
+	i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs);
+	i2c_register_board_info(2, mop500_i2c2_devices,
+				ARRAY_SIZE(mop500_i2c2_devices));
+
+	/* This board has full regulator constraints */
+	regulator_has_full_constraints();
+}
+
+static void __init hrefv60_init_machine(void)
+{
+	int i2c0_devs;
+
 	/*
 	 * The HREFv60 board removed a GPIO expander and routed
 	 * all these GPIO pins to the internal GPIO controller
 	 * instead.
 	 */
-	if (!machine_is_snowball()) {
-		if (machine_is_hrefv60())
-			mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO;
-		else
-			mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR;
-	}
+	mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO;
 
 	u8500_init_devices();
 
-	mop500_pins_init();
+	hrefv60_pins_init();
 
-	if (machine_is_snowball())
-		platform_add_devices(snowball_platform_devs,
-					ARRAY_SIZE(snowball_platform_devs));
-	else
-		platform_add_devices(mop500_platform_devs,
-					ARRAY_SIZE(mop500_platform_devs));
+	platform_add_devices(mop500_platform_devs,
+			ARRAY_SIZE(mop500_platform_devs));
 
 	mop500_i2c_init();
 	mop500_sdi_init();
@@ -633,8 +677,8 @@ static void __init mop500_init_machine(void)
 	mop500_uart_init();
 
 	i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
-	if (machine_is_hrefv60())
-		i2c0_devs -= NUM_PRE_V60_I2C0_DEVICES;
+
+	i2c0_devs -= NUM_PRE_V60_I2C0_DEVICES;
 
 	i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs);
 	i2c_register_board_info(2, mop500_i2c2_devices,
@@ -659,7 +703,7 @@ MACHINE_START(HREFV60, "ST-Ericsson U8500 Platform HREFv60+")
 	.map_io		= u8500_map_io,
 	.init_irq	= ux500_init_irq,
 	.timer		= &ux500_timer,
-	.init_machine	= mop500_init_machine,
+	.init_machine	= hrefv60_init_machine,
 MACHINE_END
 
 MACHINE_START(SNOWBALL, "Calao Systems Snowball platform")
@@ -668,5 +712,5 @@ MACHINE_START(SNOWBALL, "Calao Systems Snowball platform")
 	.init_irq	= ux500_init_irq,
 	/* we re-use nomadik timer here */
 	.timer		= &ux500_timer,
-	.init_machine	= mop500_init_machine,
+	.init_machine	= snowball_init_machine,
 MACHINE_END
diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h
index ee77a89..de18a2a 100644
--- a/arch/arm/mach-ux500/board-mop500.h
+++ b/arch/arm/mach-ux500/board-mop500.h
@@ -40,10 +40,13 @@
 struct i2c_board_info;
 
 extern void mop500_sdi_init(void);
+extern void snowball_sdi_init(void);
 extern void mop500_sdi_tc35892_init(void);
 void __init mop500_u8500uib_init(void);
 void __init mop500_stuib_init(void);
 void __init mop500_pins_init(void);
+void __init hrefv60_pins_init(void);
+void __init snowball_pins_init(void);
 
 void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info,
 		unsigned n);
diff --git a/arch/arm/mach-ux500/cache-l2x0.c b/arch/arm/mach-ux500/cache-l2x0.c
new file mode 100644
index 0000000..122ddde
--- /dev/null
+++ b/arch/arm/mach-ux500/cache-l2x0.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/io.h>
+#include <asm/cacheflush.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <mach/hardware.h>
+#include <mach/id.h>
+
+static void __iomem *l2x0_base;
+
+static inline void ux500_cache_wait(void __iomem *reg, unsigned long mask)
+{
+	/* wait for the operation to complete */
+	while (readl_relaxed(reg) & mask)
+		cpu_relax();
+}
+
+static inline void ux500_cache_sync(void)
+{
+	writel_relaxed(0, l2x0_base + L2X0_CACHE_SYNC);
+	ux500_cache_wait(l2x0_base + L2X0_CACHE_SYNC, 1);
+}
+
+/*
+ * The L2 cache cannot be turned off in the non-secure world.
+ * Dummy until a secure service is in place.
+ */
+static void ux500_l2x0_disable(void)
+{
+}
+
+/*
+ * This is only called when doing a kexec, just after turning off the L2
+ * and L1 cache, and it is surrounded by a spinlock in the generic version.
+ * However, we're not really turning off the L2 cache right now and the
+ * PL310 does not support exclusive accesses (used to implement the spinlock).
+ * So, the invalidation needs to be done without the spinlock.
+ */
+static void ux500_l2x0_inv_all(void)
+{
+	uint32_t l2x0_way_mask = (1<<16) - 1;	/* Bitmask of active ways */
+
+	/* invalidate all ways */
+	writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY);
+	ux500_cache_wait(l2x0_base + L2X0_INV_WAY, l2x0_way_mask);
+	ux500_cache_sync();
+}
+
+static int __init ux500_l2x0_unlock(void)
+{
+	int i;
+
+	/*
+	 * Unlock Data and Instruction Lock if locked. Ux500 U-Boot versions
+	 * apparently locks both caches before jumping to the kernel. The
+	 * l2x0 core will not touch the unlock registers if the l2x0 is
+	 * already enabled, so we do it right here instead. The PL310 has
+	 * 8 sets of registers, one per possible CPU.
+	 */
+	for (i = 0; i < 8; i++) {
+		writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_D_BASE +
+			       i * L2X0_LOCKDOWN_STRIDE);
+		writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_I_BASE +
+			       i * L2X0_LOCKDOWN_STRIDE);
+	}
+	return 0;
+}
+
+static int __init ux500_l2x0_init(void)
+{
+	if (cpu_is_u5500())
+		l2x0_base = __io_address(U5500_L2CC_BASE);
+	else if (cpu_is_u8500())
+		l2x0_base = __io_address(U8500_L2CC_BASE);
+	else
+		ux500_unknown_soc();
+
+	/* Unlock before init */
+	ux500_l2x0_unlock();
+
+	/* 64KB way size, 8 way associativity, force WA */
+	l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff);
+
+	/* Override invalidate function */
+	outer_cache.disable = ux500_l2x0_disable;
+	outer_cache.inv_all = ux500_l2x0_inv_all;
+
+	return 0;
+}
+
+early_initcall(ux500_l2x0_init);
diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c
index 1da23bb..1405d0e 100644
--- a/arch/arm/mach-ux500/cpu.c
+++ b/arch/arm/mach-ux500/cpu.c
@@ -10,14 +10,12 @@
 #include <linux/clk.h>
 #include <linux/mfd/db8500-prcmu.h>
 #include <linux/mfd/db5500-prcmu.h>
+#include <linux/clksrc-dbx500-prcmu.h>
 
-#include <asm/cacheflush.h>
-#include <asm/hardware/cache-l2x0.h>
 #include <asm/hardware/gic.h>
 #include <asm/mach/map.h>
 #include <asm/localtimer.h>
 
-#include <plat/mtu.h>
 #include <mach/hardware.h>
 #include <mach/setup.h>
 #include <mach/devices.h>
@@ -26,10 +24,6 @@
 
 void __iomem *_PRCMU_BASE;
 
-#ifdef CONFIG_CACHE_L2X0
-static void __iomem *l2x0_base;
-#endif
-
 void __init ux500_init_irq(void)
 {
 	void __iomem *dist_base;
@@ -56,93 +50,3 @@ void __init ux500_init_irq(void)
 		prcmu_early_init();
 	clk_init();
 }
-
-#ifdef CONFIG_CACHE_L2X0
-static inline void ux500_cache_wait(void __iomem *reg, unsigned long mask)
-{
-	/* wait for the operation to complete */
-	while (readl_relaxed(reg) & mask)
-		;
-}
-
-static inline void ux500_cache_sync(void)
-{
-	void __iomem *base = l2x0_base;
-
-	writel_relaxed(0, base + L2X0_CACHE_SYNC);
-	ux500_cache_wait(base + L2X0_CACHE_SYNC, 1);
-}
-
-/*
- * The L2 cache cannot be turned off in the non-secure world.
- * Dummy until a secure service is in place.
- */
-static void ux500_l2x0_disable(void)
-{
-}
-
-/*
- * This is only called when doing a kexec, just after turning off the L2
- * and L1 cache, and it is surrounded by a spinlock in the generic version.
- * However, we're not really turning off the L2 cache right now and the
- * PL310 does not support exclusive accesses (used to implement the spinlock).
- * So, the invalidation needs to be done without the spinlock.
- */
-static void ux500_l2x0_inv_all(void)
-{
-	void __iomem *base = l2x0_base;
-	uint32_t l2x0_way_mask = (1<<16) - 1;	/* Bitmask of active ways */
-
-	/* invalidate all ways */
-	writel_relaxed(l2x0_way_mask, base + L2X0_INV_WAY);
-	ux500_cache_wait(base + L2X0_INV_WAY, l2x0_way_mask);
-	ux500_cache_sync();
-}
-
-static int ux500_l2x0_init(void)
-{
-	if (cpu_is_u5500())
-		l2x0_base = __io_address(U5500_L2CC_BASE);
-	else if (cpu_is_u8500())
-		l2x0_base = __io_address(U8500_L2CC_BASE);
-	else
-		ux500_unknown_soc();
-
-	/* 64KB way size, 8 way associativity, force WA */
-	l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff);
-
-	/* Override invalidate function */
-	outer_cache.disable = ux500_l2x0_disable;
-	outer_cache.inv_all = ux500_l2x0_inv_all;
-
-	return 0;
-}
-early_initcall(ux500_l2x0_init);
-#endif
-
-static void __init ux500_timer_init(void)
-{
-#ifdef CONFIG_LOCAL_TIMERS
-	/* Setup the local timer base */
-	if (cpu_is_u5500())
-		twd_base = __io_address(U5500_TWD_BASE);
-	else if (cpu_is_u8500())
-		twd_base = __io_address(U8500_TWD_BASE);
-	else
-		ux500_unknown_soc();
-#endif
-	if (cpu_is_u5500())
-		mtu_base = __io_address(U5500_MTU0_BASE);
-	else if (cpu_is_u8500ed())
-		mtu_base = __io_address(U8500_MTU0_BASE_ED);
-	else if (cpu_is_u8500())
-		mtu_base = __io_address(U8500_MTU0_BASE);
-	else
-		ux500_unknown_soc();
-
-	nmdk_timer_init();
-}
-
-struct sys_timer ux500_timer = {
-	.init	= ux500_timer_init,
-};
diff --git a/arch/arm/mach-ux500/hotplug.c b/arch/arm/mach-ux500/hotplug.c
index dd8037e..572015e 100644
--- a/arch/arm/mach-ux500/hotplug.c
+++ b/arch/arm/mach-ux500/hotplug.c
@@ -24,7 +24,7 @@ static inline void platform_do_lowpower(unsigned int cpu)
 	for (;;) {
 		__asm__ __volatile__("dsb\n\t" "wfi\n\t"
 				: : : "memory");
-		if (pen_release == cpu) {
+		if (pen_release == cpu_logical_map(cpu)) {
 			/*
 			 * OK, proper wakeup, we're done
 			 */
diff --git a/arch/arm/mach-ux500/include/mach/db5500-regs.h b/arch/arm/mach-ux500/include/mach/db5500-regs.h
index 6ad9832..994b5fe 100644
--- a/arch/arm/mach-ux500/include/mach/db5500-regs.h
+++ b/arch/arm/mach-ux500/include/mach/db5500-regs.h
@@ -61,6 +61,8 @@
 #define U5500_SCR_BASE		(U5500_PER4_BASE + 0x5000)
 #define U5500_DMC_BASE		(U5500_PER4_BASE + 0x6000)
 #define U5500_PRCMU_BASE	(U5500_PER4_BASE + 0x7000)
+#define U5500_PRCMU_TIMER_3_BASE (U5500_PER4_BASE + 0x07338)
+#define U5500_PRCMU_TIMER_4_BASE (U5500_PER4_BASE + 0x07450)
 #define U5500_MSP1_BASE		(U5500_PER4_BASE + 0x9000)
 #define U5500_GPIO2_BASE	(U5500_PER4_BASE + 0xA000)
 #define U5500_CDETECT_BASE	(U5500_PER4_BASE + 0xF000)
diff --git a/arch/arm/mach-ux500/include/mach/db8500-regs.h b/arch/arm/mach-ux500/include/mach/db8500-regs.h
index 0499971..751b0e6 100644
--- a/arch/arm/mach-ux500/include/mach/db8500-regs.h
+++ b/arch/arm/mach-ux500/include/mach/db8500-regs.h
@@ -102,10 +102,13 @@
 #define U8500_SCR_BASE		(U8500_PER4_BASE + 0x05000)
 #define U8500_DMC_BASE		(U8500_PER4_BASE + 0x06000)
 #define U8500_PRCMU_BASE	(U8500_PER4_BASE + 0x07000)
+#define U8500_PRCMU_TIMER_3_BASE (U8500_PER4_BASE + 0x07338)
+#define U8500_PRCMU_TIMER_4_BASE (U8500_PER4_BASE + 0x07450)
 #define U8500_PRCMU_TCDM_BASE_V1 (U8500_PER4_BASE + 0x0f000)
 #define U8500_PRCMU_TCDM_BASE	(U8500_PER4_BASE + 0x68000)
 #define U8500_PRCMU_TCPM_BASE   (U8500_PER4_BASE + 0x60000)
 
+
 /* per3 base addresses */
 #define U8500_FSMC_BASE		(U8500_PER3_BASE + 0x0000)
 #define U8500_SSP0_BASE		(U8500_PER3_BASE + 0x2000)
diff --git a/arch/arm/mach-ux500/include/mach/uncompress.h b/arch/arm/mach-ux500/include/mach/uncompress.h
index 7dd0807..6fb3c4b 100644
--- a/arch/arm/mach-ux500/include/mach/uncompress.h
+++ b/arch/arm/mach-ux500/include/mach/uncompress.h
@@ -51,15 +51,9 @@ static void flush(void)
 static inline void arch_decomp_setup(void)
 {
 	/* Check in run time if we run on an U8500 or U5500 */
-	if (machine_is_u8500() ||
-	    machine_is_svp8500v1() ||
-	    machine_is_svp8500v2() ||
-	    machine_is_hrefv60()   ||
-	    machine_is_snowball())
-		ux500_uart_base = U8500_UART2_BASE;
-	else if (machine_is_u5500())
+	if (machine_is_u5500())
 		ux500_uart_base = U5500_UART0_BASE;
-	else /* not much can be done to help here */
+	else
 		ux500_uart_base = U8500_UART2_BASE;
 }
 
diff --git a/arch/arm/mach-ux500/pins-db8500.h b/arch/arm/mach-ux500/pins-db8500.h
index f923764..8b1d1a7 100644
--- a/arch/arm/mach-ux500/pins-db8500.h
+++ b/arch/arm/mach-ux500/pins-db8500.h
@@ -35,40 +35,40 @@
 
 #define GPIO4_GPIO		PIN_CFG(4, GPIO)
 #define GPIO4_U1_RXD		PIN_CFG(4, ALT_A)
-#define GPIO4_I2C4_SCL		PIN_CFG_PULL(4, ALT_B, UP)
+#define GPIO4_I2C4_SCL		PIN_CFG_INPUT(4, ALT_B, PULLUP)
 #define GPIO4_IP_TRSTn		PIN_CFG(4, ALT_C)
 
 #define GPIO5_GPIO		PIN_CFG(5, GPIO)
 #define GPIO5_U1_TXD		PIN_CFG(5, ALT_A)
-#define GPIO5_I2C4_SDA		PIN_CFG_PULL(5, ALT_B, UP)
+#define GPIO5_I2C4_SDA		PIN_CFG_INPUT(5, ALT_B, PULLUP)
 #define GPIO5_IP_GPIO6		PIN_CFG(5, ALT_C)
 
 #define GPIO6_GPIO		PIN_CFG(6, GPIO)
 #define GPIO6_U1_CTSn		PIN_CFG(6, ALT_A)
-#define GPIO6_I2C1_SCL		PIN_CFG_PULL(6, ALT_B, UP)
+#define GPIO6_I2C1_SCL		PIN_CFG_INPUT(6, ALT_B, PULLUP)
 #define GPIO6_IP_GPIO0		PIN_CFG(6, ALT_C)
 
 #define GPIO7_GPIO		PIN_CFG(7, GPIO)
 #define GPIO7_U1_RTSn		PIN_CFG(7, ALT_A)
-#define GPIO7_I2C1_SDA		PIN_CFG_PULL(7, ALT_B, UP)
+#define GPIO7_I2C1_SDA		PIN_CFG_INPUT(7, ALT_B, PULLUP)
 #define GPIO7_IP_GPIO1		PIN_CFG(7, ALT_C)
 
 #define GPIO8_GPIO		PIN_CFG(8, GPIO)
-#define GPIO8_IPI2C_SDA		PIN_CFG_PULL(8, ALT_A, UP)
-#define GPIO8_I2C2_SDA		PIN_CFG_PULL(8, ALT_B, UP)
+#define GPIO8_IPI2C_SDA		PIN_CFG_INPUT(8, ALT_A, PULLUP)
+#define GPIO8_I2C2_SDA		PIN_CFG_INPUT(8, ALT_B, PULLUP)
 
 #define GPIO9_GPIO		PIN_CFG(9, GPIO)
-#define GPIO9_IPI2C_SCL		PIN_CFG_PULL(9, ALT_A, UP)
-#define GPIO9_I2C2_SCL		PIN_CFG_PULL(9, ALT_B, UP)
+#define GPIO9_IPI2C_SCL		PIN_CFG_INPUT(9, ALT_A, PULLUP)
+#define GPIO9_I2C2_SCL		PIN_CFG_INPUT(9, ALT_B, PULLUP)
 
 #define GPIO10_GPIO		PIN_CFG(10, GPIO)
-#define GPIO10_IPI2C_SDA	PIN_CFG_PULL(10, ALT_A, UP)
-#define GPIO10_I2C2_SDA		PIN_CFG_PULL(10, ALT_B, UP)
+#define GPIO10_IPI2C_SDA	PIN_CFG_INPUT(10, ALT_A, PULLUP)
+#define GPIO10_I2C2_SDA		PIN_CFG_INPUT(10, ALT_B, PULLUP)
 #define GPIO10_IP_GPIO3		PIN_CFG(10, ALT_C)
 
 #define GPIO11_GPIO		PIN_CFG(11, GPIO)
-#define GPIO11_IPI2C_SCL	PIN_CFG_PULL(11, ALT_A, UP)
-#define GPIO11_I2C2_SCL		PIN_CFG_PULL(11, ALT_B, UP)
+#define GPIO11_IPI2C_SCL	PIN_CFG_INPUT(11, ALT_A, PULLUP)
+#define GPIO11_I2C2_SCL		PIN_CFG_INPUT(11, ALT_B, PULLUP)
 #define GPIO11_IP_GPIO2		PIN_CFG(11, ALT_C)
 
 #define GPIO12_GPIO		PIN_CFG(12, GPIO)
@@ -87,66 +87,66 @@
 
 #define GPIO16_GPIO		PIN_CFG(16, GPIO)
 #define GPIO16_MSP0_RFS		PIN_CFG(16, ALT_A)
-#define GPIO16_I2C1_SCL		PIN_CFG_PULL(16, ALT_B, UP)
+#define GPIO16_I2C1_SCL		PIN_CFG_INPUT(16, ALT_B, PULLUP)
 #define GPIO16_SLIM0_DAT	PIN_CFG(16, ALT_C)
 
 #define GPIO17_GPIO		PIN_CFG(17, GPIO)
 #define GPIO17_MSP0_RCK		PIN_CFG(17, ALT_A)
-#define GPIO17_I2C1_SDA		PIN_CFG_PULL(17, ALT_B, UP)
+#define GPIO17_I2C1_SDA		PIN_CFG_INPUT(17, ALT_B, PULLUP)
 #define GPIO17_SLIM0_CLK	PIN_CFG(17, ALT_C)
 
 #define GPIO18_GPIO		PIN_CFG(18, GPIO)
-#define GPIO18_MC0_CMDDIR	PIN_CFG_PULL(18, ALT_A, UP)
+#define GPIO18_MC0_CMDDIR	PIN_CFG_INPUT(18, ALT_A, PULLUP)
 #define GPIO18_U2_RXD		PIN_CFG(18, ALT_B)
 #define GPIO18_MS_IEP		PIN_CFG(18, ALT_C)
 
 #define GPIO19_GPIO		PIN_CFG(19, GPIO)
-#define GPIO19_MC0_DAT0DIR	PIN_CFG_PULL(19, ALT_A, UP)
+#define GPIO19_MC0_DAT0DIR	PIN_CFG_INPUT(19, ALT_A, PULLUP)
 #define GPIO19_U2_TXD		PIN_CFG(19, ALT_B)
 #define GPIO19_MS_DAT0DIR	PIN_CFG(19, ALT_C)
 
 #define GPIO20_GPIO		PIN_CFG(20, GPIO)
-#define GPIO20_MC0_DAT2DIR	PIN_CFG_PULL(20, ALT_A, UP)
+#define GPIO20_MC0_DAT2DIR	PIN_CFG_INPUT(20, ALT_A, PULLUP)
 #define GPIO20_UARTMOD_TXD	PIN_CFG(20, ALT_B)
 #define GPIO20_IP_TRIGOUT	PIN_CFG(20, ALT_C)
 
 #define GPIO21_GPIO		PIN_CFG(21, GPIO)
-#define GPIO21_MC0_DAT31DIR	PIN_CFG_PULL(21, ALT_A, UP)
+#define GPIO21_MC0_DAT31DIR	PIN_CFG_INPUT(21, ALT_A, PULLUP)
 #define GPIO21_MSP0_SCK		PIN_CFG(21, ALT_B)
 #define GPIO21_MS_DAT31DIR	PIN_CFG(21, ALT_C)
 
 #define GPIO22_GPIO		PIN_CFG(22, GPIO)
-#define GPIO22_MC0_FBCLK	PIN_CFG_PULL(22, ALT_A, UP)
+#define GPIO22_MC0_FBCLK	PIN_CFG_INPUT(22, ALT_A, PULLUP)
 #define GPIO22_UARTMOD_RXD	PIN_CFG(22, ALT_B)
 #define GPIO22_MS_FBCLK		PIN_CFG(22, ALT_C)
 
 #define GPIO23_GPIO		PIN_CFG(23, GPIO)
-#define GPIO23_MC0_CLK		PIN_CFG_PULL(23, ALT_A, UP)
+#define GPIO23_MC0_CLK		PIN_CFG_INPUT(23, ALT_A, PULLUP)
 #define GPIO23_STMMOD_CLK	PIN_CFG(23, ALT_B)
 #define GPIO23_MS_CLK		PIN_CFG(23, ALT_C)
 
 #define GPIO24_GPIO		PIN_CFG(24, GPIO)
-#define GPIO24_MC0_CMD		PIN_CFG_PULL(24, ALT_A, UP)
+#define GPIO24_MC0_CMD		PIN_CFG_INPUT(24, ALT_A, PULLUP)
 #define GPIO24_UARTMOD_RXD	PIN_CFG(24, ALT_B)
 #define GPIO24_MS_BS		PIN_CFG(24, ALT_C)
 
 #define GPIO25_GPIO		PIN_CFG(25, GPIO)
-#define GPIO25_MC0_DAT0		PIN_CFG_PULL(25, ALT_A, UP)
+#define GPIO25_MC0_DAT0		PIN_CFG_INPUT(25, ALT_A, PULLUP)
 #define GPIO25_STMMOD_DAT0	PIN_CFG(25, ALT_B)
 #define GPIO25_MS_DAT0		PIN_CFG(25, ALT_C)
 
 #define GPIO26_GPIO		PIN_CFG(26, GPIO)
-#define GPIO26_MC0_DAT1		PIN_CFG_PULL(26, ALT_A, UP)
+#define GPIO26_MC0_DAT1		PIN_CFG_INPUT(26, ALT_A, PULLUP)
 #define GPIO26_STMMOD_DAT1	PIN_CFG(26, ALT_B)
 #define GPIO26_MS_DAT1		PIN_CFG(26, ALT_C)
 
 #define GPIO27_GPIO		PIN_CFG(27, GPIO)
-#define GPIO27_MC0_DAT2		PIN_CFG_PULL(27, ALT_A, UP)
+#define GPIO27_MC0_DAT2		PIN_CFG_INPUT(27, ALT_A, PULLUP)
 #define GPIO27_STMMOD_DAT2	PIN_CFG(27, ALT_B)
 #define GPIO27_MS_DAT2		PIN_CFG(27, ALT_C)
 
 #define GPIO28_GPIO		PIN_CFG(28, GPIO)
-#define GPIO28_MC0_DAT3		PIN_CFG_PULL(28, ALT_A, UP)
+#define GPIO28_MC0_DAT3		PIN_CFG_INPUT(28, ALT_A, PULLUP)
 #define GPIO28_STMMOD_DAT3	PIN_CFG(28, ALT_B)
 #define GPIO28_MS_DAT3		PIN_CFG(28, ALT_C)
 
@@ -357,48 +357,48 @@
 #define GPIO97_MC5_DAT7		PIN_CFG(97, ALT_C)
 
 #define GPIO128_GPIO		PIN_CFG(128, GPIO)
-#define GPIO128_MC2_CLK		PIN_CFG_PULL(128, ALT_A, UP)
+#define GPIO128_MC2_CLK		PIN_CFG_INPUT(128, ALT_A, PULLUP)
 #define GPIO128_SM_CKO		PIN_CFG(128, ALT_B)
 
 #define GPIO129_GPIO		PIN_CFG(129, GPIO)
-#define GPIO129_MC2_CMD		PIN_CFG_PULL(129, ALT_A, UP)
+#define GPIO129_MC2_CMD		PIN_CFG_INPUT(129, ALT_A, PULLUP)
 #define GPIO129_SM_WAIT0n	PIN_CFG(129, ALT_B)
 
 #define GPIO130_GPIO		PIN_CFG(130, GPIO)
-#define GPIO130_MC2_FBCLK	PIN_CFG_PULL(130, ALT_A, UP)
+#define GPIO130_MC2_FBCLK	PIN_CFG_INPUT(130, ALT_A, PULLUP)
 #define GPIO130_SM_FBCLK	PIN_CFG(130, ALT_B)
 #define GPIO130_MC2_RSTN	PIN_CFG(130, ALT_C)
 
 #define GPIO131_GPIO		PIN_CFG(131, GPIO)
-#define GPIO131_MC2_DAT0	PIN_CFG_PULL(131, ALT_A, UP)
+#define GPIO131_MC2_DAT0	PIN_CFG_INPUT(131, ALT_A, PULLUP)
 #define GPIO131_SM_ADQ8		PIN_CFG(131, ALT_B)
 
 #define GPIO132_GPIO		PIN_CFG(132, GPIO)
-#define GPIO132_MC2_DAT1	PIN_CFG_PULL(132, ALT_A, UP)
+#define GPIO132_MC2_DAT1	PIN_CFG_INPUT(132, ALT_A, PULLUP)
 #define GPIO132_SM_ADQ9		PIN_CFG(132, ALT_B)
 
 #define GPIO133_GPIO		PIN_CFG(133, GPIO)
-#define GPIO133_MC2_DAT2	PIN_CFG_PULL(133, ALT_A, UP)
+#define GPIO133_MC2_DAT2	PIN_CFG_INPUT(133, ALT_A, PULLUP)
 #define GPIO133_SM_ADQ10	PIN_CFG(133, ALT_B)
 
 #define GPIO134_GPIO		PIN_CFG(134, GPIO)
-#define GPIO134_MC2_DAT3	PIN_CFG_PULL(134, ALT_A, UP)
+#define GPIO134_MC2_DAT3	PIN_CFG_INPUT(134, ALT_A, PULLUP)
 #define GPIO134_SM_ADQ11	PIN_CFG(134, ALT_B)
 
 #define GPIO135_GPIO		PIN_CFG(135, GPIO)
-#define GPIO135_MC2_DAT4	PIN_CFG_PULL(135, ALT_A, UP)
+#define GPIO135_MC2_DAT4	PIN_CFG_INPUT(135, ALT_A, PULLUP)
 #define GPIO135_SM_ADQ12	PIN_CFG(135, ALT_B)
 
 #define GPIO136_GPIO		PIN_CFG(136, GPIO)
-#define GPIO136_MC2_DAT5	PIN_CFG_PULL(136, ALT_A, UP)
+#define GPIO136_MC2_DAT5	PIN_CFG_INPUT(136, ALT_A, PULLUP)
 #define GPIO136_SM_ADQ13	PIN_CFG(136, ALT_B)
 
 #define GPIO137_GPIO		PIN_CFG(137, GPIO)
-#define GPIO137_MC2_DAT6	PIN_CFG_PULL(137, ALT_A, UP)
+#define GPIO137_MC2_DAT6	PIN_CFG_INPUT(137, ALT_A, PULLUP)
 #define GPIO137_SM_ADQ14	PIN_CFG(137, ALT_B)
 
 #define GPIO138_GPIO		PIN_CFG(138, GPIO)
-#define GPIO138_MC2_DAT7	PIN_CFG_PULL(138, ALT_A, UP)
+#define GPIO138_MC2_DAT7	PIN_CFG_INPUT(138, ALT_A, PULLUP)
 #define GPIO138_SM_ADQ15	PIN_CFG(138, ALT_B)
 
 #define GPIO139_GPIO		PIN_CFG(139, GPIO)
@@ -434,10 +434,10 @@
 #define GPIO146_SSP0_TXD	PIN_CFG(146, ALT_A)
 
 #define GPIO147_GPIO		PIN_CFG(147, GPIO)
-#define GPIO147_I2C0_SCL	PIN_CFG_PULL(147, ALT_A, UP)
+#define GPIO147_I2C0_SCL	PIN_CFG_INPUT(147, ALT_A, PULLUP)
 
 #define GPIO148_GPIO		PIN_CFG(148, GPIO)
-#define GPIO148_I2C0_SDA	PIN_CFG_PULL(148, ALT_A, UP)
+#define GPIO148_I2C0_SDA	PIN_CFG_INPUT(148, ALT_A, PULLUP)
 
 #define GPIO149_GPIO		PIN_CFG(149, GPIO)
 #define GPIO149_IP_GPIO0	PIN_CFG(149, ALT_A)
@@ -459,82 +459,82 @@
 #define GPIO152_KP_O9		PIN_CFG(152, ALT_C)
 
 #define GPIO153_GPIO		PIN_CFG(153, GPIO)
-#define GPIO153_KP_I7		PIN_CFG_PULL(153, ALT_A, DOWN)
+#define GPIO153_KP_I7		PIN_CFG_INPUT(153, ALT_A, PULLDOWN)
 #define GPIO153_LCD_D24		PIN_CFG(153, ALT_B)
 #define GPIO153_U2_RXD		PIN_CFG(153, ALT_C)
 
 #define GPIO154_GPIO		PIN_CFG(154, GPIO)
-#define GPIO154_KP_I6		PIN_CFG_PULL(154, ALT_A, DOWN)
+#define GPIO154_KP_I6		PIN_CFG_INPUT(154, ALT_A, PULLDOWN)
 #define GPIO154_LCD_D25		PIN_CFG(154, ALT_B)
 #define GPIO154_U2_TXD		PIN_CFG(154, ALT_C)
 
 #define GPIO155_GPIO		PIN_CFG(155, GPIO)
-#define GPIO155_KP_I5		PIN_CFG_PULL(155, ALT_A, DOWN)
+#define GPIO155_KP_I5		PIN_CFG_INPUT(155, ALT_A, PULLDOWN)
 #define GPIO155_LCD_D26		PIN_CFG(155, ALT_B)
 #define GPIO155_STMAPE_CLK	PIN_CFG(155, ALT_C)
 
 #define GPIO156_GPIO		PIN_CFG(156, GPIO)
-#define GPIO156_KP_I4		PIN_CFG_PULL(156, ALT_A, DOWN)
+#define GPIO156_KP_I4		PIN_CFG_INPUT(156, ALT_A, PULLDOWN)
 #define GPIO156_LCD_D27		PIN_CFG(156, ALT_B)
 #define GPIO156_STMAPE_DAT3	PIN_CFG(156, ALT_C)
 
 #define GPIO157_GPIO		PIN_CFG(157, GPIO)
-#define GPIO157_KP_O7		PIN_CFG_PULL(157, ALT_A, UP)
+#define GPIO157_KP_O7		PIN_CFG_INPUT(157, ALT_A, PULLUP)
 #define GPIO157_LCD_D28		PIN_CFG(157, ALT_B)
 #define GPIO157_STMAPE_DAT2	PIN_CFG(157, ALT_C)
 
 #define GPIO158_GPIO		PIN_CFG(158, GPIO)
-#define GPIO158_KP_O6		PIN_CFG_PULL(158, ALT_A, UP)
+#define GPIO158_KP_O6		PIN_CFG_INPUT(158, ALT_A, PULLUP)
 #define GPIO158_LCD_D29		PIN_CFG(158, ALT_B)
 #define GPIO158_STMAPE_DAT1	PIN_CFG(158, ALT_C)
 
 #define GPIO159_GPIO		PIN_CFG(159, GPIO)
-#define GPIO159_KP_O5		PIN_CFG_PULL(159, ALT_A, UP)
+#define GPIO159_KP_O5		PIN_CFG_INPUT(159, ALT_A, PULLUP)
 #define GPIO159_LCD_D30		PIN_CFG(159, ALT_B)
 #define GPIO159_STMAPE_DAT0	PIN_CFG(159, ALT_C)
 
 #define GPIO160_GPIO		PIN_CFG(160, GPIO)
-#define GPIO160_KP_O4		PIN_CFG_PULL(160, ALT_A, UP)
+#define GPIO160_KP_O4		PIN_CFG_INPUT(160, ALT_A, PULLUP)
 #define GPIO160_LCD_D31		PIN_CFG(160, ALT_B)
 #define GPIO160_NONE		PIN_CFG(160, ALT_C)
 
 #define GPIO161_GPIO		PIN_CFG(161, GPIO)
-#define GPIO161_KP_I3		PIN_CFG_PULL(161, ALT_A, DOWN)
+#define GPIO161_KP_I3		PIN_CFG_INPUT(161, ALT_A, PULLDOWN)
 #define GPIO161_LCD_D32		PIN_CFG(161, ALT_B)
 #define GPIO161_UARTMOD_RXD	PIN_CFG(161, ALT_C)
 
 #define GPIO162_GPIO		PIN_CFG(162, GPIO)
-#define GPIO162_KP_I2		PIN_CFG_PULL(162, ALT_A, DOWN)
+#define GPIO162_KP_I2		PIN_CFG_INPUT(162, ALT_A, PULLDOWN)
 #define GPIO162_LCD_D33		PIN_CFG(162, ALT_B)
 #define GPIO162_UARTMOD_TXD	PIN_CFG(162, ALT_C)
 
 #define GPIO163_GPIO		PIN_CFG(163, GPIO)
-#define GPIO163_KP_I1		PIN_CFG_PULL(163, ALT_A, DOWN)
+#define GPIO163_KP_I1		PIN_CFG_INPUT(163, ALT_A, PULLDOWN)
 #define GPIO163_LCD_D34		PIN_CFG(163, ALT_B)
 #define GPIO163_STMMOD_CLK	PIN_CFG(163, ALT_C)
 
 #define GPIO164_GPIO		PIN_CFG(164, GPIO)
-#define GPIO164_KP_I0		PIN_CFG_PULL(164, ALT_A, UP)
+#define GPIO164_KP_I0		PIN_CFG_INPUT(164, ALT_A, PULLUP)
 #define GPIO164_LCD_D35		PIN_CFG(164, ALT_B)
 #define GPIO164_STMMOD_DAT3	PIN_CFG(164, ALT_C)
 
 #define GPIO165_GPIO		PIN_CFG(165, GPIO)
-#define GPIO165_KP_O3		PIN_CFG_PULL(165, ALT_A, UP)
+#define GPIO165_KP_O3		PIN_CFG_INPUT(165, ALT_A, PULLUP)
 #define GPIO165_LCD_D36		PIN_CFG(165, ALT_B)
 #define GPIO165_STMMOD_DAT2	PIN_CFG(165, ALT_C)
 
 #define GPIO166_GPIO		PIN_CFG(166, GPIO)
-#define GPIO166_KP_O2		PIN_CFG_PULL(166, ALT_A, UP)
+#define GPIO166_KP_O2		PIN_CFG_INPUT(166, ALT_A, PULLUP)
 #define GPIO166_LCD_D37		PIN_CFG(166, ALT_B)
 #define GPIO166_STMMOD_DAT1	PIN_CFG(166, ALT_C)
 
 #define GPIO167_GPIO		PIN_CFG(167, GPIO)
-#define GPIO167_KP_O1		PIN_CFG_PULL(167, ALT_A, UP)
+#define GPIO167_KP_O1		PIN_CFG_INPUT(167, ALT_A, PULLUP)
 #define GPIO167_LCD_D38		PIN_CFG(167, ALT_B)
 #define GPIO167_STMMOD_DAT0	PIN_CFG(167, ALT_C)
 
 #define GPIO168_GPIO		PIN_CFG(168, GPIO)
-#define GPIO168_KP_O0		PIN_CFG_PULL(168, ALT_A, UP)
+#define GPIO168_KP_O0		PIN_CFG_INPUT(168, ALT_A, PULLUP)
 #define GPIO168_LCD_D39		PIN_CFG(168, ALT_B)
 #define GPIO168_NONE		PIN_CFG(168, ALT_C)
 
@@ -569,39 +569,39 @@
 #define GPIO196_MSP2_RXD	PIN_CFG(196, ALT_A)
 
 #define GPIO197_GPIO		PIN_CFG(197, GPIO)
-#define GPIO197_MC4_DAT3	PIN_CFG_PULL(197, ALT_A, UP)
+#define GPIO197_MC4_DAT3	PIN_CFG_INPUT(197, ALT_A, PULLUP)
 
 #define GPIO198_GPIO		PIN_CFG(198, GPIO)
-#define GPIO198_MC4_DAT2	PIN_CFG_PULL(198, ALT_A, UP)
+#define GPIO198_MC4_DAT2	PIN_CFG_INPUT(198, ALT_A, PULLUP)
 
 #define GPIO199_GPIO		PIN_CFG(199, GPIO)
-#define GPIO199_MC4_DAT1	PIN_CFG_PULL(199, ALT_A, UP)
+#define GPIO199_MC4_DAT1	PIN_CFG_INPUT(199, ALT_A, PULLUP)
 
 #define GPIO200_GPIO		PIN_CFG(200, GPIO)
-#define GPIO200_MC4_DAT0	PIN_CFG_PULL(200, ALT_A, UP)
+#define GPIO200_MC4_DAT0	PIN_CFG_INPUT(200, ALT_A, PULLUP)
 
 #define GPIO201_GPIO		PIN_CFG(201, GPIO)
-#define GPIO201_MC4_CMD		PIN_CFG_PULL(201, ALT_A, UP)
+#define GPIO201_MC4_CMD		PIN_CFG_INPUT(201, ALT_A, PULLUP)
 
 #define GPIO202_GPIO		PIN_CFG(202, GPIO)
-#define GPIO202_MC4_FBCLK	PIN_CFG_PULL(202, ALT_A, UP)
+#define GPIO202_MC4_FBCLK	PIN_CFG_INPUT(202, ALT_A, PULLUP)
 #define GPIO202_PWL		PIN_CFG(202, ALT_B)
 #define GPIO202_MC4_RSTN	PIN_CFG(202, ALT_C)
 
 #define GPIO203_GPIO		PIN_CFG(203, GPIO)
-#define GPIO203_MC4_CLK		PIN_CFG_PULL(203, ALT_A, UP)
+#define GPIO203_MC4_CLK		PIN_CFG_INPUT(203, ALT_A, PULLUP)
 
 #define GPIO204_GPIO		PIN_CFG(204, GPIO)
-#define GPIO204_MC4_DAT7	PIN_CFG_PULL(204, ALT_A, UP)
+#define GPIO204_MC4_DAT7	PIN_CFG_INPUT(204, ALT_A, PULLUP)
 
 #define GPIO205_GPIO		PIN_CFG(205, GPIO)
-#define GPIO205_MC4_DAT6	PIN_CFG_PULL(205, ALT_A, UP)
+#define GPIO205_MC4_DAT6	PIN_CFG_INPUT(205, ALT_A, PULLUP)
 
 #define GPIO206_GPIO		PIN_CFG(206, GPIO)
-#define GPIO206_MC4_DAT5	PIN_CFG_PULL(206, ALT_A, UP)
+#define GPIO206_MC4_DAT5	PIN_CFG_INPUT(206, ALT_A, PULLUP)
 
 #define GPIO207_GPIO		PIN_CFG(207, GPIO)
-#define GPIO207_MC4_DAT4	PIN_CFG_PULL(207, ALT_A, UP)
+#define GPIO207_MC4_DAT4	PIN_CFG_INPUT(207, ALT_A, PULLUP)
 
 #define GPIO208_GPIO		PIN_CFG(208, GPIO)
 #define GPIO208_MC1_CLK		PIN_CFG(208, ALT_A)
@@ -632,21 +632,25 @@
 #define GPIO215_MC1_CMDDIR	PIN_CFG(215, ALT_A)
 #define GPIO215_MC3_DAT2DIR	PIN_CFG(215, ALT_B)
 #define GPIO215_CLKOUT1		PIN_CFG(215, ALT_C)
+#define GPIO215_SPI2_TXD	PIN_CFG(215, ALT_C)
 
 #define GPIO216_GPIO		PIN_CFG(216, GPIO)
 #define GPIO216_MC1_DAT2DIR	PIN_CFG(216, ALT_A)
 #define GPIO216_MC3_CMDDIR	PIN_CFG(216, ALT_B)
-#define GPIO216_I2C3_SDA	PIN_CFG_PULL(216, ALT_C, UP)
+#define GPIO216_I2C3_SDA	PIN_CFG_INPUT(216, ALT_C, PULLUP)
+#define GPIO216_SPI2_FRM	PIN_CFG(216, ALT_C)
 
 #define GPIO217_GPIO		PIN_CFG(217, GPIO)
 #define GPIO217_MC1_DAT0DIR	PIN_CFG(217, ALT_A)
 #define GPIO217_MC3_DAT31DIR	PIN_CFG(217, ALT_B)
 #define GPIO217_CLKOUT2		PIN_CFG(217, ALT_C)
+#define GPIO217_SPI2_CLK	PIN_CFG(217, ALT_C)
 
 #define GPIO218_GPIO		PIN_CFG(218, GPIO)
 #define GPIO218_MC1_DAT31DIR	PIN_CFG(218, ALT_A)
 #define GPIO218_MC3_DAT0DIR	PIN_CFG(218, ALT_B)
-#define GPIO218_I2C3_SCL	PIN_CFG_PULL(218, ALT_C, UP)
+#define GPIO218_I2C3_SCL	PIN_CFG_INPUT(218, ALT_C, PULLUP)
+#define GPIO218_SPI2_RXD	PIN_CFG(218, ALT_C)
 
 #define GPIO219_GPIO		PIN_CFG(219, GPIO)
 #define GPIO219_HSIR_FLA0	PIN_CFG(219, ALT_A)
@@ -694,12 +698,12 @@
 #define GPIO229_GPIO		PIN_CFG(229, GPIO)
 #define GPIO229_CLKOUT1		PIN_CFG(229, ALT_A)
 #define GPIO229_PWL		PIN_CFG(229, ALT_B)
-#define GPIO229_I2C3_SDA	PIN_CFG_PULL(229, ALT_C, UP)
+#define GPIO229_I2C3_SDA	PIN_CFG_INPUT(229, ALT_C, PULLUP)
 
 #define GPIO230_GPIO		PIN_CFG(230, GPIO)
 #define GPIO230_CLKOUT2		PIN_CFG(230, ALT_A)
 #define GPIO230_PWL		PIN_CFG(230, ALT_B)
-#define GPIO230_I2C3_SCL	PIN_CFG_PULL(230, ALT_C, UP)
+#define GPIO230_I2C3_SCL	PIN_CFG_INPUT(230, ALT_C, PULLUP)
 
 #define GPIO256_GPIO		PIN_CFG(256, GPIO)
 #define GPIO256_USB_NXT		PIN_CFG(256, ALT_A)
diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c
index eb51991..a19e398 100644
--- a/arch/arm/mach-ux500/platsmp.c
+++ b/arch/arm/mach-ux500/platsmp.c
@@ -96,7 +96,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 	 * the holding pen - release it, then wait for it to flag
 	 * that it has been released by resetting pen_release.
 	 */
-	write_pen_release(cpu);
+	write_pen_release(cpu_logical_map(cpu));
 
 	gic_raise_softirq(cpumask_of(cpu), 1);
 
diff --git a/arch/arm/mach-ux500/timer.c b/arch/arm/mach-ux500/timer.c
new file mode 100644
index 0000000..aea467d
--- /dev/null
+++ b/arch/arm/mach-ux500/timer.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Mattias Wallin <mattias.wallin@stericsson.com> for ST-Ericsson
+ */
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/clksrc-dbx500-prcmu.h>
+
+#include <asm/localtimer.h>
+
+#include <plat/mtu.h>
+
+#include <mach/setup.h>
+#include <mach/hardware.h>
+
+static void __init ux500_timer_init(void)
+{
+	void __iomem *prcmu_timer_base;
+
+	if (cpu_is_u5500()) {
+#ifdef CONFIG_LOCAL_TIMERS
+		twd_base = __io_address(U5500_TWD_BASE);
+#endif
+		mtu_base = __io_address(U5500_MTU0_BASE);
+		prcmu_timer_base = __io_address(U5500_PRCMU_TIMER_3_BASE);
+	} else if (cpu_is_u8500()) {
+#ifdef CONFIG_LOCAL_TIMERS
+		twd_base = __io_address(U8500_TWD_BASE);
+#endif
+		mtu_base = __io_address(U8500_MTU0_BASE);
+		prcmu_timer_base = __io_address(U8500_PRCMU_TIMER_4_BASE);
+	} else {
+		ux500_unknown_soc();
+	}
+
+	/*
+	 * Here we register the timerblocks active in the system.
+	 * Localtimers (twd) is started when both cpu is up and running.
+	 * MTU register a clocksource, clockevent and sched_clock.
+	 * Since the MTU is located in the VAPE power domain
+	 * it will be cleared in sleep which makes it unsuitable.
+	 * We however need it as a timer tick (clockevent)
+	 * during boot to calibrate delay until twd is started.
+	 * RTC-RTT have problems as timer tick during boot since it is
+	 * depending on delay which is not yet calibrated. RTC-RTT is in the
+	 * always-on powerdomain and is used as clockevent instead of twd when
+	 * sleeping.
+	 * The PRCMU timer 4(3 for DB5500) register a clocksource and
+	 * sched_clock with higher rating then MTU since is always-on.
+	 *
+	 */
+
+	nmdk_timer_init();
+	clksrc_dbx500_prcmu_init(prcmu_timer_base);
+}
+
+static void ux500_timer_reset(void)
+{
+	nmdk_clkevt_reset();
+	nmdk_clksrc_reset();
+}
+
+struct sys_timer ux500_timer = {
+	.init		= ux500_timer_init,
+	.resume		= ux500_timer_reset,
+};
diff --git a/arch/arm/mach-vexpress/hotplug.c b/arch/arm/mach-vexpress/hotplug.c
index 3668cf9..813ee08 100644
--- a/arch/arm/mach-vexpress/hotplug.c
+++ b/arch/arm/mach-vexpress/hotplug.c
@@ -65,7 +65,7 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
 	for (;;) {
 		wfi();
 
-		if (pen_release == cpu) {
+		if (pen_release == cpu_logical_map(cpu)) {
 			/*
 			 * OK, proper wakeup, we're done
 			 */
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 88633fe..67f75a0 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -819,10 +819,10 @@ config CACHE_FEROCEON_L2_WRITETHROUGH
 config CACHE_L2X0
 	bool "Enable the L2x0 outer cache controller"
 	depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \
-		   REALVIEW_EB_A9MP || SOC_IMX35 || SOC_IMX31 || MACH_REALVIEW_PBX || \
+		   REALVIEW_EB_A9MP || ARCH_IMX_V6_V7 || MACH_REALVIEW_PBX || \
 		   ARCH_NOMADIK || ARCH_OMAP4 || ARCH_EXYNOS4 || ARCH_TEGRA || \
 		   ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_SHMOBILE || \
-		   ARCH_PRIMA2 || ARCH_ZYNQ || ARCH_CNS3XXX
+		   ARCH_PRIMA2 || ARCH_ZYNQ || ARCH_CNS3XXX || ARCH_HIGHBANK
 	default y
 	select OUTER_CACHE
 	select OUTER_CACHE_SYNC
diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig
index 4c8fdbc..a08a951 100644
--- a/arch/arm/plat-mxc/Kconfig
+++ b/arch/arm/plat-mxc/Kconfig
@@ -4,50 +4,34 @@ source "arch/arm/plat-mxc/devices/Kconfig"
 
 menu "Freescale MXC Implementations"
 
-config ARCH_MX50_SUPPORTED
-	bool
-
-config ARCH_MX53_SUPPORTED
-	bool
-
 choice
 	prompt "Freescale CPU family:"
-	default ARCH_MX3
-
-config ARCH_MX1
-	bool "MX1-based"
-	help
-	  This enables support for systems based on the Freescale i.MX1 family
-
-config ARCH_MX2
-	bool "MX2-based"
-	help
-	  This enables support for systems based on the Freescale i.MX2 family
+	default ARCH_IMX_V6_V7
 
-config ARCH_MX25
-	bool "MX25-based"
+config ARCH_IMX_V4_V5
+	bool "i.MX1, i.MX21, i.MX25, i.MX27"
+	select AUTO_ZRELADDR
+	select ARM_PATCH_PHYS_VIRT
 	help
-	  This enables support for systems based on the Freescale i.MX25 family
+	  This enables support for systems based on the Freescale i.MX ARMv4
+	  and ARMv5 SoCs
 
-config ARCH_MX3
-	bool "MX3-based"
+config ARCH_IMX_V6_V7
+	bool "i.MX3, i.MX6"
+	select AUTO_ZRELADDR if !ZBOOT_ROM
+	select ARM_PATCH_PHYS_VIRT
 	help
-	  This enables support for systems based on the Freescale i.MX3 family
+	  This enables support for systems based on the Freescale i.MX3 and i.MX6
+	  family.
 
-config ARCH_MX503
-	bool "i.MX50 + i.MX53"
-	select ARCH_MX50_SUPPORTED
-	select ARCH_MX53_SUPPORTED
+config ARCH_MX5
+	bool "i.MX50, i.MX51, i.MX53"
+	select AUTO_ZRELADDR
+	select ARM_PATCH_PHYS_VIRT
 	help
 	  This enables support for machines using Freescale's i.MX50 and i.MX53
 	  processors.
 
-config ARCH_MX51
-	bool "i.MX51"
-	select ARCH_MX51_SUPPORTED
-	help
-	  This enables support for systems based on the Freescale i.MX51 family
-
 endchoice
 
 source "arch/arm/mach-imx/Kconfig"
diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile
index d53c35f..b9f0f5f 100644
--- a/arch/arm/plat-mxc/Makefile
+++ b/arch/arm/plat-mxc/Makefile
@@ -5,7 +5,7 @@
 # Common support
 obj-y := clock.o time.o devices.o cpu.o system.o irq-common.o
 
-# MX51 uses the TZIC interrupt controller, older platforms use AVIC
+obj-$(CONFIG_ARM_GIC) += gic.o
 obj-$(CONFIG_MXC_TZIC) += tzic.o
 obj-$(CONFIG_MXC_AVIC) += avic.o
 
diff --git a/arch/arm/plat-mxc/audmux-v2.c b/arch/arm/plat-mxc/audmux-v2.c
index 175e364..8cced35 100644
--- a/arch/arm/plat-mxc/audmux-v2.c
+++ b/arch/arm/plat-mxc/audmux-v2.c
@@ -187,18 +187,11 @@ EXPORT_SYMBOL_GPL(mxc_audmux_v2_configure_port);
 static int mxc_audmux_v2_init(void)
 {
 	int ret;
-#if defined(CONFIG_ARCH_MX5)
 	if (cpu_is_mx51()) {
 		audmux_base = MX51_IO_ADDRESS(MX51_AUDMUX_BASE_ADDR);
-		ret = 0;
-		return ret;
-	}
-#endif
-#if defined(CONFIG_ARCH_MX3)
-	if (cpu_is_mx31())
+	} else if (cpu_is_mx31()) {
 		audmux_base = MX31_IO_ADDRESS(MX31_AUDMUX_BASE_ADDR);
-
-	else if (cpu_is_mx35()) {
+	} else if (cpu_is_mx35()) {
 		audmux_clk = clk_get(NULL, "audmux");
 		if (IS_ERR(audmux_clk)) {
 			ret = PTR_ERR(audmux_clk);
@@ -207,10 +200,7 @@ static int mxc_audmux_v2_init(void)
 			return ret;
 		}
 		audmux_base = MX35_IO_ADDRESS(MX35_AUDMUX_BASE_ADDR);
-	}
-#endif
-#if defined(CONFIG_SOC_IMX25)
-	if (cpu_is_mx25()) {
+	} else if (cpu_is_mx25()) {
 		audmux_clk = clk_get(NULL, "audmux");
 		if (IS_ERR(audmux_clk)) {
 			ret = PTR_ERR(audmux_clk);
@@ -220,7 +210,7 @@ static int mxc_audmux_v2_init(void)
 		}
 		audmux_base = MX25_IO_ADDRESS(MX25_AUDMUX_BASE_ADDR);
 	}
-#endif /* if defined(CONFIG_SOC_IMX25) */
+
 	audmux_debugfs_init();
 
 	return 0;
diff --git a/arch/arm/plat-mxc/avic.c b/arch/arm/plat-mxc/avic.c
index 55d2534..8875fb4 100644
--- a/arch/arm/plat-mxc/avic.c
+++ b/arch/arm/plat-mxc/avic.c
@@ -50,6 +50,8 @@
 
 void __iomem *avic_base;
 
+static u32 avic_saved_mask_reg[2];
+
 #ifdef CONFIG_MXC_IRQ_PRIOR
 static int avic_irq_set_priority(unsigned char irq, unsigned char prio)
 {
@@ -90,24 +92,8 @@ static int avic_set_irq_fiq(unsigned int irq, unsigned int type)
 }
 #endif /* CONFIG_FIQ */
 
-/* Disable interrupt number "irq" in the AVIC */
-static void mxc_mask_irq(struct irq_data *d)
-{
-	__raw_writel(d->irq, avic_base + AVIC_INTDISNUM);
-}
 
-/* Enable interrupt number "irq" in the AVIC */
-static void mxc_unmask_irq(struct irq_data *d)
-{
-	__raw_writel(d->irq, avic_base + AVIC_INTENNUM);
-}
-
-static struct mxc_irq_chip mxc_avic_chip = {
-	.base = {
-		.irq_ack = mxc_mask_irq,
-		.irq_mask = mxc_mask_irq,
-		.irq_unmask = mxc_unmask_irq,
-	},
+static struct mxc_extra_irq avic_extra_irq = {
 #ifdef CONFIG_MXC_IRQ_PRIOR
 	.set_priority = avic_irq_set_priority,
 #endif
@@ -116,6 +102,68 @@ static struct mxc_irq_chip mxc_avic_chip = {
 #endif
 };
 
+#ifdef CONFIG_PM
+static void avic_irq_suspend(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct irq_chip_type *ct = gc->chip_types;
+	int idx = gc->irq_base >> 5;
+
+	avic_saved_mask_reg[idx] = __raw_readl(avic_base + ct->regs.mask);
+	__raw_writel(gc->wake_active, avic_base + ct->regs.mask);
+}
+
+static void avic_irq_resume(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct irq_chip_type *ct = gc->chip_types;
+	int idx = gc->irq_base >> 5;
+
+	__raw_writel(avic_saved_mask_reg[idx], avic_base + ct->regs.mask);
+}
+
+#else
+#define avic_irq_suspend NULL
+#define avic_irq_resume NULL
+#endif
+
+static __init void avic_init_gc(unsigned int irq_start)
+{
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
+	int idx = irq_start >> 5;
+
+	gc = irq_alloc_generic_chip("mxc-avic", 1, irq_start, avic_base,
+				    handle_level_irq);
+	gc->private = &avic_extra_irq;
+	gc->wake_enabled = IRQ_MSK(32);
+
+	ct = gc->chip_types;
+	ct->chip.irq_mask = irq_gc_mask_clr_bit;
+	ct->chip.irq_unmask = irq_gc_mask_set_bit;
+	ct->chip.irq_ack = irq_gc_mask_clr_bit;
+	ct->chip.irq_set_wake = irq_gc_set_wake;
+	ct->chip.irq_suspend = avic_irq_suspend;
+	ct->chip.irq_resume = avic_irq_resume;
+	ct->regs.mask = !idx ? AVIC_INTENABLEL : AVIC_INTENABLEH;
+	ct->regs.ack = ct->regs.mask;
+
+	irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0);
+}
+
+asmlinkage void __exception_irq_entry avic_handle_irq(struct pt_regs *regs)
+{
+	u32 nivector;
+
+	do {
+		nivector = __raw_readl(avic_base + AVIC_NIVECSR) >> 16;
+		if (nivector == 0xffff)
+			break;
+
+		handle_IRQ(nivector, regs);
+	} while (1);
+}
+
 /*
  * This function initializes the AVIC hardware and disables all the
  * interrupts. It registers the interrupt enable and disable functions
@@ -140,11 +188,9 @@ void __init mxc_init_irq(void __iomem *irqbase)
 	/* all IRQ no FIQ */
 	__raw_writel(0, avic_base + AVIC_INTTYPEH);
 	__raw_writel(0, avic_base + AVIC_INTTYPEL);
-	for (i = 0; i < AVIC_NUM_IRQS; i++) {
-		irq_set_chip_and_handler(i, &mxc_avic_chip.base,
-					 handle_level_irq);
-		set_irq_flags(i, IRQF_VALID);
-	}
+
+	for (i = 0; i < AVIC_NUM_IRQS; i += 32)
+		avic_init_gc(i);
 
 	/* Set default priority value (0) for all IRQ's */
 	for (i = 0; i < 8; i++)
@@ -157,4 +203,3 @@ void __init mxc_init_irq(void __iomem *irqbase)
 
 	printk(KERN_INFO "MXC IRQ initialized\n");
 }
-
diff --git a/arch/arm/plat-mxc/cpu.c b/arch/arm/plat-mxc/cpu.c
index 386e0d5..f5b7e0f 100644
--- a/arch/arm/plat-mxc/cpu.c
+++ b/arch/arm/plat-mxc/cpu.c
@@ -1,5 +1,6 @@
 
 #include <linux/module.h>
+#include <mach/hardware.h>
 
 unsigned int __mxc_cpu_type;
 EXPORT_SYMBOL(__mxc_cpu_type);
@@ -9,3 +10,11 @@ void mxc_set_cpu_type(unsigned int type)
 	__mxc_cpu_type = type;
 }
 
+void imx_print_silicon_rev(const char *cpu, int srev)
+{
+	if (srev == IMX_CHIP_REVISION_UNKNOWN)
+		pr_info("CPU identified as %s, unknown revision\n", cpu);
+	else
+		pr_info("CPU identified as %s, silicon rev %d.%d\n",
+				cpu, (srev >> 4) & 0xf, srev & 0xf);
+}
diff --git a/arch/arm/plat-mxc/devices.c b/arch/arm/plat-mxc/devices.c
index a34b2ae..4d55a7a 100644
--- a/arch/arm/plat-mxc/devices.c
+++ b/arch/arm/plat-mxc/devices.c
@@ -23,20 +23,6 @@
 #include <linux/platform_device.h>
 #include <mach/common.h>
 
-int __init mxc_register_device(struct platform_device *pdev, void *data)
-{
-	int ret;
-
-	pdev->dev.platform_data = data;
-
-	ret = platform_device_register(pdev);
-	if (ret)
-		pr_debug("Unable to register platform device '%s': %d\n",
-			 pdev->name, ret);
-
-	return ret;
-}
-
 struct device mxc_aips_bus = {
 	.init_name	= "mxc_aips",
 	.parent		= &platform_bus,
diff --git a/arch/arm/plat-mxc/devices/Kconfig b/arch/arm/plat-mxc/devices/Kconfig
index bd294ad..cb3e3ee 100644
--- a/arch/arm/plat-mxc/devices/Kconfig
+++ b/arch/arm/plat-mxc/devices/Kconfig
@@ -1,6 +1,6 @@
 config IMX_HAVE_PLATFORM_FEC
 	bool
-	default y if ARCH_MX25 || SOC_IMX27 || SOC_IMX35 || SOC_IMX51 || SOC_IMX53
+	default y if ARCH_MX25 || SOC_IMX27 || SOC_IMX35 || SOC_IMX50 || SOC_IMX51 || SOC_IMX53
 
 config IMX_HAVE_PLATFORM_FLEXCAN
 	select HAVE_CAN_FLEXCAN if CAN
@@ -31,6 +31,9 @@ config IMX_HAVE_PLATFORM_IMX_I2C
 config IMX_HAVE_PLATFORM_IMX_KEYPAD
 	bool
 
+config IMX_HAVE_PLATFORM_PATA_IMX
+	bool
+
 config IMX_HAVE_PLATFORM_IMX_SSI
 	bool
 
@@ -76,3 +79,7 @@ config IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
 
 config IMX_HAVE_PLATFORM_SPI_IMX
 	bool
+
+config IMX_HAVE_PLATFORM_AHCI
+	bool
+	default y if ARCH_MX53
diff --git a/arch/arm/plat-mxc/devices/Makefile b/arch/arm/plat-mxc/devices/Makefile
index b41bf97..c11ac84 100644
--- a/arch/arm/plat-mxc/devices/Makefile
+++ b/arch/arm/plat-mxc/devices/Makefile
@@ -10,6 +10,7 @@ obj-y += platform-imx-dma.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_FB) += platform-imx-fb.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_I2C) += platform-imx-i2c.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_KEYPAD) += platform-imx-keypad.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_PATA_IMX) += platform-pata_imx.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_SSI) += platform-imx-ssi.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_UART) += platform-imx-uart.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_UDC) += platform-imx_udc.o
@@ -25,3 +26,4 @@ obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_RTC) += platform-mxc_rtc.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_W1) += platform-mxc_w1.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX) += platform-sdhci-esdhc-imx.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_SPI_IMX) +=  platform-spi_imx.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_AHCI) +=  platform-ahci-imx.o
diff --git a/arch/arm/plat-mxc/devices/platform-ahci-imx.c b/arch/arm/plat-mxc/devices/platform-ahci-imx.c
new file mode 100644
index 0000000..d8a56ae
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-ahci-imx.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <asm/sizes.h>
+#include <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_ahci_imx_data_entry_single(soc, _devid)		\
+	{								\
+		.devid = _devid,					\
+		.iobase = soc ## _SATA_BASE_ADDR,			\
+		.irq = soc ## _INT_SATA,				\
+	}
+
+#ifdef CONFIG_SOC_IMX53
+const struct imx_ahci_imx_data imx53_ahci_imx_data __initconst =
+	imx_ahci_imx_data_entry_single(MX53, "imx53-ahci");
+#endif
+
+enum {
+	HOST_CAP = 0x00,
+	HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */
+	HOST_PORTS_IMPL	= 0x0c,
+	HOST_TIMER1MS = 0xe0, /* Timer 1-ms */
+};
+
+static struct clk *sata_clk, *sata_ref_clk;
+
+/* AHCI module Initialization, if return 0, initialization is successful. */
+static int imx_sata_init(struct device *dev, void __iomem *addr)
+{
+	u32 tmpdata;
+	int ret = 0;
+	struct clk *clk;
+
+	sata_clk = clk_get(dev, "ahci");
+	if (IS_ERR(sata_clk)) {
+		dev_err(dev, "no sata clock.\n");
+		return PTR_ERR(sata_clk);
+	}
+	ret = clk_enable(sata_clk);
+	if (ret) {
+		dev_err(dev, "can't enable sata clock.\n");
+		goto put_sata_clk;
+	}
+
+	/* Get the AHCI SATA PHY CLK */
+	sata_ref_clk = clk_get(dev, "ahci_phy");
+	if (IS_ERR(sata_ref_clk)) {
+		dev_err(dev, "no sata ref clock.\n");
+		ret = PTR_ERR(sata_ref_clk);
+		goto release_sata_clk;
+	}
+	ret = clk_enable(sata_ref_clk);
+	if (ret) {
+		dev_err(dev, "can't enable sata ref clock.\n");
+		goto put_sata_ref_clk;
+	}
+
+	/* Get the AHB clock rate, and configure the TIMER1MS reg later */
+	clk = clk_get(dev, "ahci_dma");
+	if (IS_ERR(clk)) {
+		dev_err(dev, "no dma clock.\n");
+		ret = PTR_ERR(clk);
+		goto release_sata_ref_clk;
+	}
+	tmpdata = clk_get_rate(clk) / 1000;
+	clk_put(clk);
+
+	writel(tmpdata, addr + HOST_TIMER1MS);
+
+	tmpdata = readl(addr + HOST_CAP);
+	if (!(tmpdata & HOST_CAP_SSS)) {
+		tmpdata |= HOST_CAP_SSS;
+		writel(tmpdata, addr + HOST_CAP);
+	}
+
+	if (!(readl(addr + HOST_PORTS_IMPL) & 0x1))
+		writel((readl(addr + HOST_PORTS_IMPL) | 0x1),
+			addr + HOST_PORTS_IMPL);
+
+	return 0;
+
+release_sata_ref_clk:
+	clk_disable(sata_ref_clk);
+put_sata_ref_clk:
+	clk_put(sata_ref_clk);
+release_sata_clk:
+	clk_disable(sata_clk);
+put_sata_clk:
+	clk_put(sata_clk);
+
+	return ret;
+}
+
+static void imx_sata_exit(struct device *dev)
+{
+	clk_disable(sata_ref_clk);
+	clk_put(sata_ref_clk);
+
+	clk_disable(sata_clk);
+	clk_put(sata_clk);
+
+}
+struct platform_device *__init imx_add_ahci_imx(
+		const struct imx_ahci_imx_data *data,
+		const struct ahci_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_4K - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return imx_add_platform_device_dmamask(data->devid, 0,
+			res, ARRAY_SIZE(res),
+			pdata, sizeof(*pdata),  DMA_BIT_MASK(32));
+}
+
+struct platform_device *__init imx53_add_ahci_imx(void)
+{
+	struct ahci_platform_data pdata = {
+		.init = imx_sata_init,
+		.exit = imx_sata_exit,
+	};
+
+	return imx_add_ahci_imx(&imx53_ahci_imx_data, &pdata);
+}
diff --git a/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c b/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c
index 23ce08e..848038f 100644
--- a/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c
+++ b/arch/arm/plat-mxc/devices/platform-fsl-usb2-udc.c
@@ -36,6 +36,11 @@ const struct imx_fsl_usb2_udc_data imx35_fsl_usb2_udc_data __initconst =
 	imx_fsl_usb2_udc_data_entry_single(MX35);
 #endif /* ifdef CONFIG_SOC_IMX35 */
 
+#ifdef CONFIG_SOC_IMX51
+const struct imx_fsl_usb2_udc_data imx51_fsl_usb2_udc_data __initconst =
+	imx_fsl_usb2_udc_data_entry_single(MX51);
+#endif
+
 struct platform_device *__init imx_add_fsl_usb2_udc(
 		const struct imx_fsl_usb2_udc_data *data,
 		const struct fsl_usb2_platform_data *pdata)
diff --git a/arch/arm/plat-mxc/devices/platform-imx-i2c.c b/arch/arm/plat-mxc/devices/platform-imx-i2c.c
index afe60f7..19ad580 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-i2c.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-i2c.c
@@ -85,6 +85,12 @@ const struct imx_imx_i2c_data imx51_imx_i2c_data[] __initconst = {
 	imx_imx_i2c_data_entry(MX51, _id, _hwid, SZ_4K)
 	imx51_imx_i2c_data_entry(0, 1),
 	imx51_imx_i2c_data_entry(1, 2),
+	{
+		.id = 2,
+		.iobase = MX51_HSI2C_DMA_BASE_ADDR,
+		.iosize = SZ_16K,
+		.irq = MX51_INT_HS_I2C,
+	},
 };
 #endif /* ifdef CONFIG_SOC_IMX51 */
 
diff --git a/arch/arm/plat-mxc/devices/platform-mxc-ehci.c b/arch/arm/plat-mxc/devices/platform-mxc-ehci.c
index e1763e0..35851d8 100644
--- a/arch/arm/plat-mxc/devices/platform-mxc-ehci.c
+++ b/arch/arm/plat-mxc/devices/platform-mxc-ehci.c
@@ -49,6 +49,15 @@ const struct imx_mxc_ehci_data imx35_mxc_ehci_hs_data __initconst =
 	imx_mxc_ehci_data_entry_single(MX35, 1, HS);
 #endif /* ifdef CONFIG_SOC_IMX35 */
 
+#ifdef CONFIG_SOC_IMX51
+const struct imx_mxc_ehci_data imx51_mxc_ehci_otg_data __initconst =
+	imx_mxc_ehci_data_entry_single(MX51, 0, OTG);
+const struct imx_mxc_ehci_data imx51_mxc_ehci_hs_data[] __initconst = {
+	imx_mxc_ehci_data_entry_single(MX51, 1, HS1),
+	imx_mxc_ehci_data_entry_single(MX51, 2, HS2),
+};
+#endif /* ifdef CONFIG_SOC_IMX51 */
+
 struct platform_device *__init imx_add_mxc_ehci(
 		const struct imx_mxc_ehci_data *data,
 		const struct mxc_usbh_platform_data *pdata)
diff --git a/arch/arm/plat-mxc/devices/platform-pata_imx.c b/arch/arm/plat-mxc/devices/platform-pata_imx.c
new file mode 100644
index 0000000..70e2f2a
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-pata_imx.c
@@ -0,0 +1,59 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_pata_imx_data_entry_single(soc, _size)			\
+	{								\
+		.iobase = soc ## _ATA_BASE_ADDR,			\
+		.iosize = _size,					\
+		.irq = soc ## _INT_ATA,					\
+	}
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_pata_imx_data imx27_pata_imx_data __initconst =
+	imx_pata_imx_data_entry_single(MX27, SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX27 */
+
+#ifdef CONFIG_SOC_IMX31
+const struct imx_pata_imx_data imx31_pata_imx_data __initconst =
+	imx_pata_imx_data_entry_single(MX31, SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+#ifdef CONFIG_SOC_IMX35
+const struct imx_pata_imx_data imx35_pata_imx_data __initconst =
+	imx_pata_imx_data_entry_single(MX35, SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX35 */
+
+#ifdef CONFIG_SOC_IMX51
+const struct imx_pata_imx_data imx51_pata_imx_data __initconst =
+	imx_pata_imx_data_entry_single(MX51, SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX51 */
+
+#ifdef CONFIG_SOC_IMX53
+const struct imx_pata_imx_data imx53_pata_imx_data __initconst =
+	imx_pata_imx_data_entry_single(MX53, SZ_16K);
+#endif /* ifdef CONFIG_SOC_IMX53 */
+
+struct platform_device *__init imx_add_pata_imx(
+		const struct imx_pata_imx_data *data)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + data->iosize - 1,
+			.flags = IORESOURCE_MEM,
+		},
+		{
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+	return imx_add_platform_device("pata_imx", -1,
+			res, ARRAY_SIZE(res), NULL, 0);
+}
+
diff --git a/arch/arm/plat-mxc/gic.c b/arch/arm/plat-mxc/gic.c
new file mode 100644
index 0000000..b3b8eed
--- /dev/null
+++ b/arch/arm/plat-mxc/gic.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/io.h>
+#include <asm/exception.h>
+#include <asm/localtimer.h>
+#include <asm/hardware/gic.h>
+#ifdef CONFIG_SMP
+#include <asm/smp.h>
+#endif
+
+asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
+{
+	u32 irqstat, irqnr;
+
+	do {
+		irqstat = readl_relaxed(gic_cpu_base_addr + GIC_CPU_INTACK);
+		irqnr = irqstat & 0x3ff;
+		if (irqnr == 1023)
+			break;
+
+		if (irqnr > 29 && irqnr < 1021)
+			handle_IRQ(irqnr, regs);
+#ifdef CONFIG_SMP
+		else if (irqnr < 16) {
+			writel_relaxed(irqstat, gic_cpu_base_addr +
+						GIC_CPU_EOI);
+			handle_IPI(irqnr, regs);
+		}
+#endif
+#ifdef CONFIG_LOCAL_TIMERS
+		else if (irqnr == 29) {
+			writel_relaxed(irqstat, gic_cpu_base_addr +
+						GIC_CPU_EOI);
+			handle_local_timer(regs);
+		}
+#endif
+	} while (1);
+}
diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h
index 4e3d978..83b745a 100644
--- a/arch/arm/plat-mxc/include/mach/common.h
+++ b/arch/arm/plat-mxc/include/mach/common.h
@@ -13,6 +13,7 @@
 
 struct platform_device;
 struct clk;
+enum mxc_cpu_pwr_mode;
 
 extern void mx1_map_io(void);
 extern void mx21_map_io(void);
@@ -64,12 +65,72 @@ extern int mx51_clocks_init(unsigned long ckil, unsigned long osc,
 			unsigned long ckih1, unsigned long ckih2);
 extern int mx53_clocks_init(unsigned long ckil, unsigned long osc,
 			unsigned long ckih1, unsigned long ckih2);
+extern int mx51_clocks_init_dt(void);
+extern int mx53_clocks_init_dt(void);
+extern int mx6q_clocks_init(void);
 extern struct platform_device *mxc_register_gpio(char *name, int id,
 	resource_size_t iobase, resource_size_t iosize, int irq, int irq_high);
-extern int mxc_register_device(struct platform_device *pdev, void *data);
 extern void mxc_set_cpu_type(unsigned int type);
 extern void mxc_arch_reset_init(void __iomem *);
 extern void mx51_efikamx_reset(void);
 extern int mx53_revision(void);
 extern int mx53_display_revision(void);
+
+enum mxc_cpu_pwr_mode {
+	WAIT_CLOCKED,		/* wfi only */
+	WAIT_UNCLOCKED,		/* WAIT */
+	WAIT_UNCLOCKED_POWER_OFF,	/* WAIT + SRPG */
+	STOP_POWER_ON,		/* just STOP */
+	STOP_POWER_OFF,		/* STOP + SRPG */
+};
+
+extern void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode);
+extern void (*imx_idle)(void);
+extern void imx_print_silicon_rev(const char *cpu, int srev);
+
+void avic_handle_irq(struct pt_regs *);
+void tzic_handle_irq(struct pt_regs *);
+void gic_handle_irq(struct pt_regs *);
+
+#define imx1_handle_irq avic_handle_irq
+#define imx21_handle_irq avic_handle_irq
+#define imx25_handle_irq avic_handle_irq
+#define imx27_handle_irq avic_handle_irq
+#define imx31_handle_irq avic_handle_irq
+#define imx35_handle_irq avic_handle_irq
+#define imx50_handle_irq tzic_handle_irq
+#define imx51_handle_irq tzic_handle_irq
+#define imx53_handle_irq tzic_handle_irq
+#define imx6q_handle_irq gic_handle_irq
+
+extern void imx_enable_cpu(int cpu, bool enable);
+extern void imx_set_cpu_jump(int cpu, void *jump_addr);
+#ifdef CONFIG_DEBUG_LL
+extern void imx_lluart_map_io(void);
+#else
+static inline void imx_lluart_map_io(void) {}
+#endif
+extern void v7_cpu_resume(void);
+extern u32 *pl310_get_save_ptr(void);
+#ifdef CONFIG_SMP
+extern void v7_secondary_startup(void);
+extern void imx_scu_map_io(void);
+extern void imx_smp_prepare(void);
+#else
+static inline void imx_scu_map_io(void) {}
+static inline void imx_smp_prepare(void) {}
+#endif
+extern void imx_enable_cpu(int cpu, bool enable);
+extern void imx_set_cpu_jump(int cpu, void *jump_addr);
+extern void imx_src_init(void);
+extern void imx_gpc_init(void);
+extern void imx_gpc_pre_suspend(void);
+extern void imx_gpc_post_resume(void);
+extern void imx51_babbage_common_init(void);
+extern void imx53_ard_common_init(void);
+extern void imx53_evk_common_init(void);
+extern void imx53_qsb_common_init(void);
+extern void imx53_smd_common_init(void);
+extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
+extern void imx6q_pm_init(void);
 #endif
diff --git a/arch/arm/plat-mxc/include/mach/debug-macro.S b/arch/arm/plat-mxc/include/mach/debug-macro.S
index a304593..6e192c4 100644
--- a/arch/arm/plat-mxc/include/mach/debug-macro.S
+++ b/arch/arm/plat-mxc/include/mach/debug-macro.S
@@ -12,44 +12,20 @@
  */
 #include <mach/hardware.h>
 
-#ifdef CONFIG_SOC_IMX1
+#ifdef CONFIG_DEBUG_IMX1_UART
 #define UART_PADDR	MX1_UART1_BASE_ADDR
-#endif
-
-#ifdef CONFIG_SOC_IMX25
-#ifdef UART_PADDR
-#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
-#endif
+#elif defined (CONFIG_DEBUG_IMX25_UART)
 #define UART_PADDR	MX25_UART1_BASE_ADDR
-#endif
-
-#if defined(CONFIG_SOC_IMX21) || defined (CONFIG_SOC_IMX27)
-#ifdef UART_PADDR
-#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
-#endif
+#elif defined (CONFIG_DEBUG_IMX21_IMX27_UART)
 #define UART_PADDR	MX2x_UART1_BASE_ADDR
-#endif
-
-#if defined(CONFIG_SOC_IMX31) || defined(CONFIG_SOC_IMX35)
-#ifdef UART_PADDR
-#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
-#endif
+#elif defined (CONFIG_DEBUG_IMX31_IMX35_UART)
 #define UART_PADDR	MX3x_UART1_BASE_ADDR
-#endif
-
-#ifdef CONFIG_SOC_IMX51
-#ifdef UART_PADDR
-#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
-#endif
+#elif defined (CONFIG_DEBUG_IMX51_UART)
 #define UART_PADDR	MX51_UART1_BASE_ADDR
-#endif
-
-/* iMX50/53 have same addresses, but not iMX51 */
-#if defined(CONFIG_SOC_IMX50) || defined(CONFIG_SOC_IMX53)
-#ifdef UART_PADDR
-#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
-#endif
+#elif defined (CONFIG_DEBUG_IMX50_IMX53_UART)
 #define UART_PADDR	MX53_UART1_BASE_ADDR
+#elif defined (CONFIG_DEBUG_IMX6Q_UART)
+#define UART_PADDR	MX6Q_UART4_BASE_ADDR
 #endif
 
 #define UART_VADDR	IMX_IO_ADDRESS(UART_PADDR)
diff --git a/arch/arm/plat-mxc/include/mach/devices-common.h b/arch/arm/plat-mxc/include/mach/devices-common.h
index 543525d..def9ba5 100644
--- a/arch/arm/plat-mxc/include/mach/devices-common.h
+++ b/arch/arm/plat-mxc/include/mach/devices-common.h
@@ -263,6 +263,14 @@ struct platform_device *__init imx_add_mxc_nand(
 		const struct imx_mxc_nand_data *data,
 		const struct mxc_nand_platform_data *pdata);
 
+struct imx_pata_imx_data {
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_pata_imx(
+		const struct imx_pata_imx_data *data);
+
 struct imx_mxc_pwm_data {
 	int id;
 	resource_size_t iobase;
@@ -313,3 +321,13 @@ struct platform_device *__init imx_add_spi_imx(
 struct platform_device *imx_add_imx_dma(void);
 struct platform_device *imx_add_imx_sdma(char *name,
 	resource_size_t iobase, int irq, struct sdma_platform_data *pdata);
+
+#include <linux/ahci_platform.h>
+struct imx_ahci_imx_data {
+	const char *devid;
+	resource_size_t iobase;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_ahci_imx(
+		const struct imx_ahci_imx_data *data,
+		const struct ahci_platform_data *pdata);
diff --git a/arch/arm/plat-mxc/include/mach/entry-macro.S b/arch/arm/plat-mxc/include/mach/entry-macro.S
index 066d464..9fe0dfc 100644
--- a/arch/arm/plat-mxc/include/mach/entry-macro.S
+++ b/arch/arm/plat-mxc/include/mach/entry-macro.S
@@ -9,72 +9,22 @@
  * published by the Free Software Foundation.
  */
 
-#include <mach/hardware.h>
+/* Unused, we use CONFIG_MULTI_IRQ_HANDLER */
 
-#define AVIC_NIMASK	0x04
-
-	@ this macro disables fast irq (not implemented)
 	.macro	disable_fiq
 	.endm
 
 	.macro  get_irqnr_preamble, base, tmp
-#ifndef CONFIG_MXC_TZIC
-	ldr	\base, =avic_base
-	ldr	\base, [\base]
-#ifdef CONFIG_MXC_IRQ_PRIOR
-	ldr	r4, [\base, #AVIC_NIMASK]
-#endif
-#elif defined CONFIG_MXC_TZIC
-	ldr	\base, =tzic_base
-	ldr	\base, [\base]
-#endif /* CONFIG_MXC_TZIC */
 	.endm
 
 	.macro  arch_ret_to_user, tmp1, tmp2
 	.endm
 
-	@ this macro checks which interrupt occurred
-	@ and returns its number in irqnr
-	@ and returns if an interrupt occurred in irqstat
 	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
-#ifndef CONFIG_MXC_TZIC
-	@ Load offset & priority of the highest priority
-	@ interrupt pending from AVIC_NIVECSR
-	ldr	\irqstat, [\base, #0x40]
-	@ Shift to get the decoded IRQ number, using ASR so
-	@ 'no interrupt pending' becomes 0xffffffff
-	mov	\irqnr, \irqstat, asr #16
-	@ set zero flag if IRQ + 1 == 0
-	adds	\tmp, \irqnr, #1
-#ifdef CONFIG_MXC_IRQ_PRIOR
-	bicne	\tmp, \irqstat, #0xFFFFFFE0
-	strne	\tmp, [\base, #AVIC_NIMASK]
-	streq	r4, [\base, #AVIC_NIMASK]
-#endif
-#elif defined CONFIG_MXC_TZIC
-	@ Load offset & priority of the highest priority
-	@ interrupt pending.
-	@ 0x080 is INTSEC0 register
-	@ 0xD80 is HIPND0 register
-	mov     \irqnr, #0
-1000:	add	\irqstat, \base, \irqnr, lsr #3
-	ldr	\tmp, [\irqstat, #0xd80]
-	ldr	\irqstat, [\irqstat, #0x080]
-	ands	\tmp, \tmp, \irqstat
-	bne	1001f
-	add	\irqnr, \irqnr, #32
-	cmp     \irqnr, #128
-	blo     1000b
-	b       2001f
-1001:	mov     \irqstat, #1
-1002:	tst     \tmp, \irqstat
-	bne     2002f
-	movs    \tmp, \tmp, lsr #1
-	addne   \irqnr, \irqnr, #1
-	bne     1002b
-2001:
-	mov  \irqnr, #0
-2002:
-	movs \irqnr, \irqnr
-#endif
+	.endm
+
+	.macro test_for_ipi, irqnr, irqstat, base, tmp
+	.endm
+
+	.macro test_for_ltirq, irqnr, irqstat, base, tmp
 	.endm
diff --git a/arch/arm/plat-mxc/include/mach/gpio.h b/arch/arm/plat-mxc/include/mach/gpio.h
index 3e1ffc8..40a8c17 100644
--- a/arch/arm/plat-mxc/include/mach/gpio.h
+++ b/arch/arm/plat-mxc/include/mach/gpio.h
@@ -1,33 +1 @@
-/*
- * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-#ifndef __ASM_ARCH_MXC_GPIO_H__
-#define __ASM_ARCH_MXC_GPIO_H__
-
-#include <linux/spinlock.h>
-#include <mach/hardware.h>
-
-
-/* There's a off-by-one betweem the gpio bank number and the gpiochip */
-/* range e.g. GPIO_1_5 is gpio 5 under linux */
-#define IMX_GPIO_NR(bank, nr)		(((bank) - 1) * 32 + (nr))
-
-#define gpio_to_irq(gpio)	(MXC_GPIO_IRQ_START + (gpio))
-#define irq_to_gpio(irq)	((irq) - MXC_GPIO_IRQ_START)
-
-#endif
+/* empty */
diff --git a/arch/arm/plat-mxc/include/mach/hardware.h b/arch/arm/plat-mxc/include/mach/hardware.h
index a8bfd56..a599f01 100644
--- a/arch/arm/plat-mxc/include/mach/hardware.h
+++ b/arch/arm/plat-mxc/include/mach/hardware.h
@@ -81,11 +81,21 @@
  *	AIPS1	0x53f00000+0x100000	->	0xf5700000+0x100000
  *	AIPS2	0x63f00000+0x100000	->	0xf5300000+0x100000
  * mx51:
+ *	TZIC	0xe0000000+0x004000	->	0xf5000000+0x004000
  *	IRAM	0x1ffe0000+0x020000	->	0xf4fe0000+0x020000
- *	DEBUG	0x60000000+0x100000	->	0xf5000000+0x100000
  *	SPBA0	0x70000000+0x100000	->	0xf5400000+0x100000
  *	AIPS1	0x73f00000+0x100000	->	0xf5700000+0x100000
  *	AIPS2	0x83f00000+0x100000	->	0xf4300000+0x100000
+ * mx53:
+ *	TZIC	0x0fffc000+0x004000	->	0xf4bfc000+0x004000
+ *	SPBA0	0x50000000+0x100000	->	0xf5400000+0x100000
+ *	AIPS1	0x53f00000+0x100000	->	0xf5700000+0x100000
+ *	AIPS2	0x63f00000+0x100000	->	0xf5300000+0x100000
+ * mx6q:
+ *	SCU	0x00a00000+0x001000	->	0xf4000000+0x001000
+ *	CCM	0x020c4000+0x004000	->	0xf42c4000+0x004000
+ *	ANATOP	0x020c8000+0x001000	->	0xf42c8000+0x001000
+ *	UART4	0x021f0000+0x004000	->	0xf42f0000+0x004000
  */
 #define IMX_IO_P2V(x)	(						\
 			0xf4000000 +					\
@@ -97,6 +107,7 @@
 
 #include <mach/mxc.h>
 
+#include <mach/mx6q.h>
 #include <mach/mx50.h>
 #include <mach/mx51.h>
 #include <mach/mx53.h>
@@ -116,4 +127,10 @@
 	.type = _type,							\
 }
 
+/* There's a off-by-one betweem the gpio bank number and the gpiochip */
+/* range e.g. GPIO_1_5 is gpio 5 under linux */
+#define IMX_GPIO_NR(bank, nr)		(((bank) - 1) * 32 + (nr))
+
+#define IMX_GPIO_TO_IRQ(gpio)	(MXC_GPIO_IRQ_START + (gpio))
+
 #endif /* __ASM_ARCH_MXC_HARDWARE_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/i2c.h b/arch/arm/plat-mxc/include/mach/i2c.h
index 4a5dc5c..375cdd0 100644
--- a/arch/arm/plat-mxc/include/mach/i2c.h
+++ b/arch/arm/plat-mxc/include/mach/i2c.h
@@ -11,14 +11,10 @@
 
 /**
  * struct imxi2c_platform_data - structure of platform data for MXC I2C driver
- * @init:	Initialise gpio's and other board specific things
- * @exit:	Free everything initialised by @init
  * @bitrate:	Bus speed measured in Hz
  *
  **/
 struct imxi2c_platform_data {
-	int (*init)(struct device *dev);
-	void (*exit)(struct device *dev);
 	int bitrate;
 };
 
diff --git a/arch/arm/plat-mxc/include/mach/io.h b/arch/arm/plat-mxc/include/mach/io.h
index 4347a87..338300b 100644
--- a/arch/arm/plat-mxc/include/mach/io.h
+++ b/arch/arm/plat-mxc/include/mach/io.h
@@ -14,32 +14,22 @@
 /* Allow IO space to be anywhere in the memory */
 #define IO_SPACE_LIMIT 0xffffffff
 
-#if defined(CONFIG_SOC_IMX31) || defined(CONFIG_SOC_IMX35)
-#include <mach/hardware.h>
-
 #define __arch_ioremap __imx_ioremap
 #define __arch_iounmap __iounmap
 
 #define addr_in_module(addr, mod) \
 	((unsigned long)(addr) - mod ## _BASE_ADDR < mod ## _SIZE)
 
+extern void __iomem *(*imx_ioremap)(unsigned long, size_t, unsigned int);
+
 static inline void __iomem *
 __imx_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype)
 {
-	if (mtype == MT_DEVICE && (cpu_is_mx31() || cpu_is_mx35())) {
-		/*
-		 * Access all peripherals below 0x80000000 as nonshared device
-		 * on mx3, but leave l2cc alone.  Otherwise cache corruptions
-		 * can occur.
-		 */
-		if (phys_addr < 0x80000000 &&
-				!addr_in_module(phys_addr, MX3x_L2CC))
-			mtype = MT_DEVICE_NONSHARED;
-	}
-
-	return __arm_ioremap(phys_addr, size, mtype);
+	if (imx_ioremap != NULL)
+		return imx_ioremap(phys_addr, size, mtype);
+	else
+		return __arm_ioremap(phys_addr, size, mtype);
 }
-#endif
 
 /* io address mapping macro */
 #define __io(a)		__typesafe_io(a)
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx3.h b/arch/arm/plat-mxc/include/mach/iomux-mx3.h
index c92f0b1..63f22a0 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx3.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx3.h
@@ -735,6 +735,7 @@ enum iomux_pins {
 #define MX31_PIN_KEY_COL5_KEY_COL5	IOMUX_MODE(MX31_PIN_KEY_COL5, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_KEY_COL6_KEY_COL6	IOMUX_MODE(MX31_PIN_KEY_COL6, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_KEY_COL7_KEY_COL7	IOMUX_MODE(MX31_PIN_KEY_COL7, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_WATCHDOG_RST__WATCHDOG_RST	IOMUX_MODE(MX31_PIN_WATCHDOG_RST, IOMUX_CONFIG_FUNC)
 
 
 /*
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx51.h b/arch/arm/plat-mxc/include/mach/iomux-mx51.h
index df6acc0..c7f5169a 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx51.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx51.h
@@ -14,6 +14,8 @@
 #define __MACH_IOMUX_MX51_H__
 
 #include <mach/iomux-v3.h>
+#define __NA_	0x000
+
 
 /* Pad control groupings */
 #define MX51_UART_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_DSE_HIGH | \
@@ -47,1521 +49,765 @@
 
 /* Raw pin modes without pad control */
 /*							  PAD    MUX ALT INPSE PATH PADCTRL */
-#define _MX51_PAD_EIM_D16__AUD4_RXFS		IOMUX_PAD(0x3f0, 0x5c, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D16__AUD5_TXD		IOMUX_PAD(0x3f0, 0x5c, 7, 0x08d8, 0, 0)
-#define _MX51_PAD_EIM_D16__EIM_D16		IOMUX_PAD(0x3f0, 0x5c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D16__GPIO2_0		IOMUX_PAD(0x3f0, 0x5c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D16__I2C1_SDA		IOMUX_PAD(0x3f0, 0x5c, 0x14, 0x09b4, 0, 0)
-#define _MX51_PAD_EIM_D16__UART2_CTS		IOMUX_PAD(0x3f0, 0x5c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D16__USBH2_DATA0		IOMUX_PAD(0x3f0, 0x5c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D17__AUD5_RXD		IOMUX_PAD(0x3f4, 0x60, 7, 0x08d4, 0, 0)
-#define _MX51_PAD_EIM_D17__EIM_D17		IOMUX_PAD(0x3f4, 0x60, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D17__GPIO2_1		IOMUX_PAD(0x3f4, 0x60, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D17__UART2_RXD		IOMUX_PAD(0x3f4, 0x60, 3, 0x09ec, 0, 0)
-#define _MX51_PAD_EIM_D17__UART3_CTS		IOMUX_PAD(0x3f4, 0x60, 4, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D17__USBH2_DATA1		IOMUX_PAD(0x3f4, 0x60, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D18__AUD5_TXC		IOMUX_PAD(0x3f8, 0x64, 7, 0x08e4, 0, 0)
-#define _MX51_PAD_EIM_D18__EIM_D18		IOMUX_PAD(0x3f8, 0x64, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D18__GPIO2_2		IOMUX_PAD(0x3f8, 0x64, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D18__UART2_TXD		IOMUX_PAD(0x3f8, 0x64, 3, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D18__UART3_RTS		IOMUX_PAD(0x3f8, 0x64, 4, 0x09f0, 1, 0)
-#define _MX51_PAD_EIM_D18__USBH2_DATA2		IOMUX_PAD(0x3f8, 0x64, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D19__AUD4_RXC		IOMUX_PAD(0x3fc, 0x68, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D19__AUD5_TXFS		IOMUX_PAD(0x3fc, 0x68, 7, 0x08e8, 0, 0)
-#define _MX51_PAD_EIM_D19__EIM_D19		IOMUX_PAD(0x3fc, 0x68, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D19__GPIO2_3		IOMUX_PAD(0x3fc, 0x68, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D19__I2C1_SCL		IOMUX_PAD(0x3fc, 0x68, 0x14, 0x09b0, 0, 0)
-#define _MX51_PAD_EIM_D19__UART2_RTS		IOMUX_PAD(0x3fc, 0x68, 3, 0x09e8, 1, 0)
-#define _MX51_PAD_EIM_D19__USBH2_DATA3		IOMUX_PAD(0x3fc, 0x68, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D20__AUD4_TXD		IOMUX_PAD(0x400, 0x6c, 5, 0x08c8, 0, 0)
-#define _MX51_PAD_EIM_D20__EIM_D20		IOMUX_PAD(0x400, 0x6c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D20__GPIO2_4		IOMUX_PAD(0x400, 0x6c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D20__SRTC_ALARM_DEB	IOMUX_PAD(0x400, 0x6c, 4, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D20__USBH2_DATA4		IOMUX_PAD(0x400, 0x6c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D21__AUD4_RXD		IOMUX_PAD(0x404, 0x70, 5, 0x08c4, 0, 0)
-#define _MX51_PAD_EIM_D21__EIM_D21		IOMUX_PAD(0x404, 0x70, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D21__GPIO2_5		IOMUX_PAD(0x404, 0x70, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D21__SRTC_ALARM_DEB	IOMUX_PAD(0x404, 0x70, 3, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D21__USBH2_DATA5		IOMUX_PAD(0x404, 0x70, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D22__AUD4_TXC		IOMUX_PAD(0x408, 0x74, 5, 0x08cc, 0, 0)
-#define _MX51_PAD_EIM_D22__EIM_D22		IOMUX_PAD(0x408, 0x74, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D22__GPIO2_6		IOMUX_PAD(0x408, 0x74, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D22__USBH2_DATA6		IOMUX_PAD(0x408, 0x74, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D23__AUD4_TXFS		IOMUX_PAD(0x40c, 0x78, 5, 0x08d0, 0, 0)
-#define _MX51_PAD_EIM_D23__EIM_D23		IOMUX_PAD(0x40c, 0x78, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D23__GPIO2_7		IOMUX_PAD(0x40c, 0x78, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D23__SPDIF_OUT1		IOMUX_PAD(0x40c, 0x78, 4, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D23__USBH2_DATA7		IOMUX_PAD(0x40c, 0x78, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D24__AUD6_RXFS		IOMUX_PAD(0x410, 0x7c, 5, 0x08f8, 0, 0)
-#define _MX51_PAD_EIM_D24__EIM_D24		IOMUX_PAD(0x410, 0x7c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D24__GPIO2_8		IOMUX_PAD(0x410, 0x7c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D24__I2C2_SDA		IOMUX_PAD(0x410, 0x7c, 0x14, 0x09bc, 0, 0)
-#define _MX51_PAD_EIM_D24__UART3_CTS		IOMUX_PAD(0x410, 0x7c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D24__USBOTG_DATA0		IOMUX_PAD(0x410, 0x7c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D25__EIM_D25		IOMUX_PAD(0x414, 0x80, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D25__KEY_COL6		IOMUX_PAD(0x414, 0x80, 1, 0x09c8, 0, 0)
-#define _MX51_PAD_EIM_D25__UART2_CTS		IOMUX_PAD(0x414, 0x80, 4, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D25__UART3_RXD		IOMUX_PAD(0x414, 0x80, 3, 0x09f4, 0, 0)
-#define _MX51_PAD_EIM_D25__USBOTG_DATA1		IOMUX_PAD(0x414, 0x80, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D26__EIM_D26		IOMUX_PAD(0x418, 0x84, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D26__KEY_COL7		IOMUX_PAD(0x418, 0x84, 1, 0x09cc, 0, 0)
-#define _MX51_PAD_EIM_D26__UART2_RTS		IOMUX_PAD(0x418, 0x84, 4, 0x09e8, 3, 0)
-#define _MX51_PAD_EIM_D26__UART3_TXD		IOMUX_PAD(0x418, 0x84, 3, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D26__USBOTG_DATA2		IOMUX_PAD(0x418, 0x84, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D27__AUD6_RXC		IOMUX_PAD(0x41c, 0x88, 5, 0x08f4, 0, 0)
-#define _MX51_PAD_EIM_D27__EIM_D27		IOMUX_PAD(0x41c, 0x88, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D27__GPIO2_9		IOMUX_PAD(0x41c, 0x88, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D27__I2C2_SCL		IOMUX_PAD(0x41c, 0x88, 0x14, 0x09b8, 0, 0)
-#define _MX51_PAD_EIM_D27__UART3_RTS		IOMUX_PAD(0x41c, 0x88, 3, 0x09f0, 3, 0)
-#define _MX51_PAD_EIM_D27__USBOTG_DATA3		IOMUX_PAD(0x41c, 0x88, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D28__AUD6_TXD		IOMUX_PAD(0x420, 0x8c, 5, 0x08f0, 0, 0)
-#define _MX51_PAD_EIM_D28__EIM_D28		IOMUX_PAD(0x420, 0x8c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D28__KEY_ROW4		IOMUX_PAD(0x420, 0x8c, 1, 0x09d0, 0, 0)
-#define _MX51_PAD_EIM_D28__USBOTG_DATA4		IOMUX_PAD(0x420, 0x8c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D29__AUD6_RXD		IOMUX_PAD(0x424, 0x90, 5, 0x08ec, 0, 0)
-#define _MX51_PAD_EIM_D29__EIM_D29		IOMUX_PAD(0x424, 0x90, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D29__KEY_ROW5		IOMUX_PAD(0x424, 0x90, 1, 0x09d4, 0, 0)
-#define _MX51_PAD_EIM_D29__USBOTG_DATA5		IOMUX_PAD(0x424, 0x90, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D30__AUD6_TXC		IOMUX_PAD(0x428, 0x94, 5, 0x08fc, 0, 0)
-#define _MX51_PAD_EIM_D30__EIM_D30		IOMUX_PAD(0x428, 0x94, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D30__KEY_ROW6		IOMUX_PAD(0x428, 0x94, 1, 0x09d8, 0, 0)
-#define _MX51_PAD_EIM_D30__USBOTG_DATA6		IOMUX_PAD(0x428, 0x94, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D31__AUD6_TXFS		IOMUX_PAD(0x42c, 0x98, 5, 0x0900, 0, 0)
-#define _MX51_PAD_EIM_D31__EIM_D31		IOMUX_PAD(0x42c, 0x98, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_D31__KEY_ROW7		IOMUX_PAD(0x42c, 0x98, 1, 0x09dc, 0, 0)
-#define _MX51_PAD_EIM_D31__USBOTG_DATA7		IOMUX_PAD(0x42c, 0x98, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A16__EIM_A16		IOMUX_PAD(0x430, 0x9c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A16__GPIO2_10		IOMUX_PAD(0x430, 0x9c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A16__OSC_FREQ_SEL0	IOMUX_PAD(0x430, 0x9c, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A17__EIM_A17		IOMUX_PAD(0x434, 0xa0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A17__GPIO2_11		IOMUX_PAD(0x434, 0xa0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A17__OSC_FREQ_SEL1	IOMUX_PAD(0x434, 0xa0, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A18__BOOT_LPB0		IOMUX_PAD(0x438, 0xa4, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A18__EIM_A18		IOMUX_PAD(0x438, 0xa4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A18__GPIO2_12		IOMUX_PAD(0x438, 0xa4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A19__BOOT_LPB1		IOMUX_PAD(0x43c, 0xa8, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A19__EIM_A19		IOMUX_PAD(0x43c, 0xa8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A19__GPIO2_13		IOMUX_PAD(0x43c, 0xa8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A20__BOOT_UART_SRC0	IOMUX_PAD(0x440, 0xac, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A20__EIM_A20		IOMUX_PAD(0x440, 0xac, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A20__GPIO2_14		IOMUX_PAD(0x440, 0xac, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A21__BOOT_UART_SRC1	IOMUX_PAD(0x444, 0xb0, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A21__EIM_A21		IOMUX_PAD(0x444, 0xb0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A21__GPIO2_15		IOMUX_PAD(0x444, 0xb0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A22__EIM_A22		IOMUX_PAD(0x448, 0xb4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A22__GPIO2_16		IOMUX_PAD(0x448, 0xb4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A23__BOOT_HPN_EN		IOMUX_PAD(0x44c, 0xb8, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A23__EIM_A23		IOMUX_PAD(0x44c, 0xb8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A23__GPIO2_17		IOMUX_PAD(0x44c, 0xb8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A24__EIM_A24		IOMUX_PAD(0x450, 0xbc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A24__GPIO2_18		IOMUX_PAD(0x450, 0xbc, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A24__USBH2_CLK		IOMUX_PAD(0x450, 0xbc, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A25__DISP1_PIN4		IOMUX_PAD(0x454, 0xc0, 6, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A25__EIM_A25		IOMUX_PAD(0x454, 0xc0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A25__GPIO2_19		IOMUX_PAD(0x454, 0xc0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A25__USBH2_DIR		IOMUX_PAD(0x454, 0xc0, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A26__CSI1_DATA_EN		IOMUX_PAD(0x458, 0xc4, 5, 0x09a0, 0, 0)
-#define _MX51_PAD_EIM_A26__DISP2_EXT_CLK	IOMUX_PAD(0x458, 0xc4, 6, 0x0908, 0, 0)
-#define _MX51_PAD_EIM_A26__EIM_A26		IOMUX_PAD(0x458, 0xc4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A26__GPIO2_20		IOMUX_PAD(0x458, 0xc4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A26__USBH2_STP		IOMUX_PAD(0x458, 0xc4, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A27__CSI2_DATA_EN		IOMUX_PAD(0x45c, 0xc8, 5, 0x099c, 0, 0)
-#define _MX51_PAD_EIM_A27__DISP1_PIN1		IOMUX_PAD(0x45c, 0xc8, 6, 0x09a4, 0, 0)
-#define _MX51_PAD_EIM_A27__EIM_A27		IOMUX_PAD(0x45c, 0xc8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A27__GPIO2_21		IOMUX_PAD(0x45c, 0xc8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_A27__USBH2_NXT		IOMUX_PAD(0x45c, 0xc8, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB0__EIM_EB0		IOMUX_PAD(0x460, 0xcc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB1__EIM_EB1		IOMUX_PAD(0x464, 0xd0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB2__AUD5_RXFS		IOMUX_PAD(0x468, 0xd4, 6, 0x08e0, 0, 0)
-#define _MX51_PAD_EIM_EB2__CSI1_D2		IOMUX_PAD(0x468, 0xd4, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB2__EIM_EB2		IOMUX_PAD(0x468, 0xd4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB2__FEC_MDIO		IOMUX_PAD(0x468, 0xd4, 3, 0x0954, 0, 0)
-#define _MX51_PAD_EIM_EB2__GPIO2_22		IOMUX_PAD(0x468, 0xd4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB2__GPT_CMPOUT1		IOMUX_PAD(0x468, 0xd4, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB3__AUD5_RXC		IOMUX_PAD(0x46c, 0xd8, 6, 0x08dc, 0, 0)
-#define _MX51_PAD_EIM_EB3__CSI1_D3		IOMUX_PAD(0x46c, 0xd8, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB3__EIM_EB3		IOMUX_PAD(0x46c, 0xd8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB3__FEC_RDATA1		IOMUX_PAD(0x46c, 0xd8, 3, 0x095c, 0, 0)
-#define _MX51_PAD_EIM_EB3__GPIO2_23		IOMUX_PAD(0x46c, 0xd8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_EB3__GPT_CMPOUT2		IOMUX_PAD(0x46c, 0xd8, 7, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_OE__EIM_OE		IOMUX_PAD(0x470, 0xdc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_OE__GPIO2_24		IOMUX_PAD(0x470, 0xdc, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS0__EIM_CS0		IOMUX_PAD(0x474, 0xe0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS0__GPIO2_25		IOMUX_PAD(0x474, 0xe0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS1__EIM_CS1		IOMUX_PAD(0x478, 0xe4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS1__GPIO2_26		IOMUX_PAD(0x478, 0xe4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS2__AUD5_TXD		IOMUX_PAD(0x47c, 0xe8, 6, 0x08d8, 1, 0)
-#define _MX51_PAD_EIM_CS2__CSI1_D4		IOMUX_PAD(0x47c, 0xe8, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS2__EIM_CS2		IOMUX_PAD(0x47c, 0xe8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS2__FEC_RDATA2		IOMUX_PAD(0x47c, 0xe8, 3, 0x0960, 0, 0)
-#define _MX51_PAD_EIM_CS2__GPIO2_27		IOMUX_PAD(0x47c, 0xe8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS2__USBOTG_STP		IOMUX_PAD(0x47c, 0xe8, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS3__AUD5_RXD		IOMUX_PAD(0x480, 0xec, 6, 0x08d4, 1, 0)
-#define _MX51_PAD_EIM_CS3__CSI1_D5		IOMUX_PAD(0x480, 0xec, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS3__EIM_CS3		IOMUX_PAD(0x480, 0xec, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS3__FEC_RDATA3		IOMUX_PAD(0x480, 0xec, 3, 0x0964, 0, 0)
-#define _MX51_PAD_EIM_CS3__GPIO2_28		IOMUX_PAD(0x480, 0xec, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS3__USBOTG_NXT		IOMUX_PAD(0x480, 0xec, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS4__AUD5_TXC		IOMUX_PAD(0x484, 0xf0, 6, 0x08e4, 1, 0)
-#define _MX51_PAD_EIM_CS4__CSI1_D6		IOMUX_PAD(0x484, 0xf0, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS4__EIM_CS4		IOMUX_PAD(0x484, 0xf0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS4__FEC_RX_ER		IOMUX_PAD(0x484, 0xf0, 3, 0x0970, 0, 0)
-#define _MX51_PAD_EIM_CS4__GPIO2_29		IOMUX_PAD(0x484, 0xf0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS4__USBOTG_CLK		IOMUX_PAD(0x484, 0xf0, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS5__AUD5_TXFS		IOMUX_PAD(0x488, 0xf4, 6, 0x08e8, 1, 0)
-#define _MX51_PAD_EIM_CS5__CSI1_D7		IOMUX_PAD(0x488, 0xf4, 5, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS5__DISP1_EXT_CLK	IOMUX_PAD(0x488, 0xf4, 4, 0x0904, 0, 0)
-#define _MX51_PAD_EIM_CS5__EIM_CS5		IOMUX_PAD(0x488, 0xf4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS5__FEC_CRS		IOMUX_PAD(0x488, 0xf4, 3, 0x0950, 0, 0)
-#define _MX51_PAD_EIM_CS5__GPIO2_30		IOMUX_PAD(0x488, 0xf4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CS5__USBOTG_DIR		IOMUX_PAD(0x488, 0xf4, 2, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DTACK__EIM_DTACK		IOMUX_PAD(0x48c, 0xf8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DTACK__GPIO2_31		IOMUX_PAD(0x48c, 0xf8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_LBA__EIM_LBA		IOMUX_PAD(0x494, 0xfc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_LBA__GPIO3_1		IOMUX_PAD(0x494, 0xfc, 1, 0x0978, 0, 0)
-#define _MX51_PAD_EIM_CRE__EIM_CRE		IOMUX_PAD(0x4a0, 0x100, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_CRE__GPIO3_2		IOMUX_PAD(0x4a0, 0x100, 1, 0x097c, 0, 0)
-#define _MX51_PAD_DRAM_CS1__DRAM_CS1		IOMUX_PAD(0x4d0, 0x104, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_WE_B__GPIO3_3		IOMUX_PAD(0x4e4, 0x108, 3, 0x0980, 0, 0)
-#define _MX51_PAD_NANDF_WE_B__NANDF_WE_B	IOMUX_PAD(0x4e4, 0x108, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_WE_B__PATA_DIOW		IOMUX_PAD(0x4e4, 0x108, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_WE_B__SD3_DATA0		IOMUX_PAD(0x4e4, 0x108, 2, 0x093c, 0, 0)
-#define _MX51_PAD_NANDF_RE_B__GPIO3_4		IOMUX_PAD(0x4e8, 0x10c, 3, 0x0984, 0, 0)
-#define _MX51_PAD_NANDF_RE_B__NANDF_RE_B	IOMUX_PAD(0x4e8, 0x10c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RE_B__PATA_DIOR		IOMUX_PAD(0x4e8, 0x10c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RE_B__SD3_DATA1		IOMUX_PAD(0x4e8, 0x10c, 2, 0x0940, 0, 0)
-#define _MX51_PAD_NANDF_ALE__GPIO3_5		IOMUX_PAD(0x4ec, 0x110, 3, 0x0988, 0, 0)
-#define _MX51_PAD_NANDF_ALE__NANDF_ALE		IOMUX_PAD(0x4ec, 0x110, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_ALE__PATA_BUFFER_EN	IOMUX_PAD(0x4ec, 0x110, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CLE__GPIO3_6		IOMUX_PAD(0x4f0, 0x114, 3, 0x098c, 0, 0)
-#define _MX51_PAD_NANDF_CLE__NANDF_CLE		IOMUX_PAD(0x4f0, 0x114, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CLE__PATA_RESET_B	IOMUX_PAD(0x4f0, 0x114, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_WP_B__GPIO3_7		IOMUX_PAD(0x4f4, 0x118, 3, 0x0990, 0, 0)
-#define _MX51_PAD_NANDF_WP_B__NANDF_WP_B	IOMUX_PAD(0x4f4, 0x118, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_WP_B__PATA_DMACK	IOMUX_PAD(0x4f4, 0x118, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_WP_B__SD3_DATA2		IOMUX_PAD(0x4f4, 0x118, 2, 0x0944, 0, 0)
-#define _MX51_PAD_NANDF_RB0__ECSPI2_SS1		IOMUX_PAD(0x4f8, 0x11c, 5, 0x0930, 0, 0)
-#define _MX51_PAD_NANDF_RB0__GPIO3_8		IOMUX_PAD(0x4f8, 0x11c, 3, 0x0994, 0, 0)
-#define _MX51_PAD_NANDF_RB0__NANDF_RB0		IOMUX_PAD(0x4f8, 0x11c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB0__PATA_DMARQ		IOMUX_PAD(0x4f8, 0x11c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB0__SD3_DATA3		IOMUX_PAD(0x4f8, 0x11c, 2, 0x0948, 0, 0)
-#define _MX51_PAD_NANDF_RB1__CSPI_MOSI		IOMUX_PAD(0x4fc, 0x120, 6, 0x091c, 0, 0)
-#define _MX51_PAD_NANDF_RB1__ECSPI2_RDY		IOMUX_PAD(0x4fc, 0x120, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB1__GPIO3_9		IOMUX_PAD(0x4fc, 0x120, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB1__NANDF_RB1		IOMUX_PAD(0x4fc, 0x120, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB1__PATA_IORDY		IOMUX_PAD(0x4fc, 0x120, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB1__SD4_CMD		IOMUX_PAD(0x4fc, 0x120, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB2__DISP2_WAIT		IOMUX_PAD(0x500, 0x124, 5, 0x09a8, 0, 0)
-#define _MX51_PAD_NANDF_RB2__ECSPI2_SCLK	IOMUX_PAD(0x500, 0x124, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB2__FEC_COL		IOMUX_PAD(0x500, 0x124, 1, 0x094c, 0, 0)
-#define _MX51_PAD_NANDF_RB2__GPIO3_10		IOMUX_PAD(0x500, 0x124, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB2__NANDF_RB2		IOMUX_PAD(0x500, 0x124, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB2__USBH3_H3_DP	IOMUX_PAD(0x500, 0x124, 7, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB2__USBH3_NXT		IOMUX_PAD(0x500, 0x124, 6, 0x0a20, 0, 0)
-#define _MX51_PAD_NANDF_RB3__DISP1_WAIT		IOMUX_PAD(0x504, 0x128, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB3__ECSPI2_MISO	IOMUX_PAD(0x504, 0x128, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB3__FEC_RX_CLK		IOMUX_PAD(0x504, 0x128, 1, 0x0968, 0, 0)
-#define _MX51_PAD_NANDF_RB3__GPIO3_11		IOMUX_PAD(0x504, 0x128, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB3__NANDF_RB3		IOMUX_PAD(0x504, 0x128, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RB3__USBH3_CLK		IOMUX_PAD(0x504, 0x128, 6, 0x09f8, 0, 0)
-#define _MX51_PAD_NANDF_RB3__USBH3_H3_DM	IOMUX_PAD(0x504, 0x128, 7, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO_NAND__GPIO_NAND		IOMUX_PAD(0x514, 0x12c, 0, 0x0998, 0, 0)
-#define _MX51_PAD_GPIO_NAND__PATA_INTRQ		IOMUX_PAD(0x514, 0x12c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS0__GPIO3_16		IOMUX_PAD(0x518, 0x130, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS0__NANDF_CS0		IOMUX_PAD(0x518, 0x130, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS1__GPIO3_17		IOMUX_PAD(0x51c, 0x134, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS1__NANDF_CS1		IOMUX_PAD(0x51c, 0x134, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS2__CSPI_SCLK		IOMUX_PAD(0x520, 0x138, 6, 0x0914, 0, 0)
-#define _MX51_PAD_NANDF_CS2__FEC_TX_ER		IOMUX_PAD(0x520, 0x138, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS2__GPIO3_18		IOMUX_PAD(0x520, 0x138, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS2__NANDF_CS2		IOMUX_PAD(0x520, 0x138, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS2__PATA_CS_0		IOMUX_PAD(0x520, 0x138, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS2__SD4_CLK		IOMUX_PAD(0x520, 0x138, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS2__USBH3_H1_DP	IOMUX_PAD(0x520, 0x138, 7, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS3__FEC_MDC		IOMUX_PAD(0x524, 0x13c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS3__GPIO3_19		IOMUX_PAD(0x524, 0x13c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS3__NANDF_CS3		IOMUX_PAD(0x524, 0x13c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS3__PATA_CS_1		IOMUX_PAD(0x524, 0x13c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS3__SD4_DAT0		IOMUX_PAD(0x524, 0x13c, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS3__USBH3_H1_DM	IOMUX_PAD(0x524, 0x13c, 7, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS4__FEC_TDATA1		IOMUX_PAD(0x528, 0x140, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS4__GPIO3_20		IOMUX_PAD(0x528, 0x140, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS4__NANDF_CS4		IOMUX_PAD(0x528, 0x140, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS4__PATA_DA_0		IOMUX_PAD(0x528, 0x140, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS4__SD4_DAT1		IOMUX_PAD(0x528, 0x140, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS4__USBH3_STP		IOMUX_PAD(0x528, 0x140, 7, 0x0a24, 0, 0)
-#define _MX51_PAD_NANDF_CS5__FEC_TDATA2		IOMUX_PAD(0x52c, 0x144, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS5__GPIO3_21		IOMUX_PAD(0x52c, 0x144, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS5__NANDF_CS5		IOMUX_PAD(0x52c, 0x144, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS5__PATA_DA_1		IOMUX_PAD(0x52c, 0x144, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS5__SD4_DAT2		IOMUX_PAD(0x52c, 0x144, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS5__USBH3_DIR		IOMUX_PAD(0x52c, 0x144, 7, 0x0a1c, 0, 0)
-#define _MX51_PAD_NANDF_CS6__CSPI_SS3		IOMUX_PAD(0x530, 0x148, 7, 0x0928, 0, 0)
-#define _MX51_PAD_NANDF_CS6__FEC_TDATA3		IOMUX_PAD(0x530, 0x148, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS6__GPIO3_22		IOMUX_PAD(0x530, 0x148, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS6__NANDF_CS6		IOMUX_PAD(0x530, 0x148, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS6__PATA_DA_2		IOMUX_PAD(0x530, 0x148, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS6__SD4_DAT3		IOMUX_PAD(0x530, 0x148, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS7__FEC_TX_EN		IOMUX_PAD(0x534, 0x14c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS7__GPIO3_23		IOMUX_PAD(0x534, 0x14c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS7__NANDF_CS7		IOMUX_PAD(0x534, 0x14c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_CS7__SD3_CLK		IOMUX_PAD(0x534, 0x14c, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RDY_INT__ECSPI2_SS0	IOMUX_PAD(0x538, 0x150, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK	IOMUX_PAD(0x538, 0x150, 1, 0x0974, 0, 0)
-#define _MX51_PAD_NANDF_RDY_INT__GPIO3_24	IOMUX_PAD(0x538, 0x150, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_RDY_INT__NANDF_RDY_INT	IOMUX_PAD(0x538, 0x150, 0, 0x0938, 0, 0)
-#define _MX51_PAD_NANDF_RDY_INT__SD3_CMD	IOMUX_PAD(0x538, 0x150, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D15__ECSPI2_MOSI	IOMUX_PAD(0x53c, 0x154, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D15__GPIO3_25		IOMUX_PAD(0x53c, 0x154, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D15__NANDF_D15		IOMUX_PAD(0x53c, 0x154, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D15__PATA_DATA15	IOMUX_PAD(0x53c, 0x154, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D15__SD3_DAT7		IOMUX_PAD(0x53c, 0x154, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D14__ECSPI2_SS3		IOMUX_PAD(0x540, 0x158, 2, 0x0934, 0, 0)
-#define _MX51_PAD_NANDF_D14__GPIO3_26		IOMUX_PAD(0x540, 0x158, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D14__NANDF_D14		IOMUX_PAD(0x540, 0x158, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D14__PATA_DATA14	IOMUX_PAD(0x540, 0x158, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D14__SD3_DAT6		IOMUX_PAD(0x540, 0x158, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D13__ECSPI2_SS2		IOMUX_PAD(0x544, 0x15c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D13__GPIO3_27		IOMUX_PAD(0x544, 0x15c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D13__NANDF_D13		IOMUX_PAD(0x544, 0x15c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D13__PATA_DATA13	IOMUX_PAD(0x544, 0x15c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D13__SD3_DAT5		IOMUX_PAD(0x544, 0x15c, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D12__ECSPI2_SS1		IOMUX_PAD(0x548, 0x160, 2, 0x0930, 1, 0)
-#define _MX51_PAD_NANDF_D12__GPIO3_28		IOMUX_PAD(0x548, 0x160, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D12__NANDF_D12		IOMUX_PAD(0x548, 0x160, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D12__PATA_DATA12	IOMUX_PAD(0x548, 0x160, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D12__SD3_DAT4		IOMUX_PAD(0x548, 0x160, 5, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D11__FEC_RX_DV		IOMUX_PAD(0x54c, 0x164, 2, 0x096c, 0, 0)
-#define _MX51_PAD_NANDF_D11__GPIO3_29		IOMUX_PAD(0x54c, 0x164, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D11__NANDF_D11		IOMUX_PAD(0x54c, 0x164, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D11__PATA_DATA11	IOMUX_PAD(0x54c, 0x164, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D11__SD3_DATA3		IOMUX_PAD(0x54c, 0x164, 5, 0x0948, 1, 0)
-#define _MX51_PAD_NANDF_D10__GPIO3_30		IOMUX_PAD(0x550, 0x168, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D10__NANDF_D10		IOMUX_PAD(0x550, 0x168, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D10__PATA_DATA10	IOMUX_PAD(0x550, 0x168, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D10__SD3_DATA2		IOMUX_PAD(0x550, 0x168, 5, 0x0944, 1, 0)
-#define _MX51_PAD_NANDF_D9__FEC_RDATA0		IOMUX_PAD(0x554, 0x16c, 0x12, 0x0958, 0, 0)
-#define _MX51_PAD_NANDF_D9__GPIO3_31		IOMUX_PAD(0x554, 0x16c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D9__NANDF_D9		IOMUX_PAD(0x554, 0x16c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D9__PATA_DATA9		IOMUX_PAD(0x554, 0x16c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D9__SD3_DATA1		IOMUX_PAD(0x554, 0x16c, 5, 0x0940, 1, 0)
-#define _MX51_PAD_NANDF_D8__FEC_TDATA0		IOMUX_PAD(0x558, 0x170, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D8__GPIO4_0		IOMUX_PAD(0x558, 0x170, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D8__NANDF_D8		IOMUX_PAD(0x558, 0x170, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D8__PATA_DATA8		IOMUX_PAD(0x558, 0x170, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D8__SD3_DATA0		IOMUX_PAD(0x558, 0x170, 5, 0x093c, 1, 0)
-#define _MX51_PAD_NANDF_D7__GPIO4_1		IOMUX_PAD(0x55c, 0x174, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D7__NANDF_D7		IOMUX_PAD(0x55c, 0x174, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D7__PATA_DATA7		IOMUX_PAD(0x55c, 0x174, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D7__USBH3_DATA0		IOMUX_PAD(0x55c, 0x174, 5, 0x09fc, 0, 0)
-#define _MX51_PAD_NANDF_D6__GPIO4_2		IOMUX_PAD(0x560, 0x178, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D6__NANDF_D6		IOMUX_PAD(0x560, 0x178, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D6__PATA_DATA6		IOMUX_PAD(0x560, 0x178, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D6__SD4_LCTL		IOMUX_PAD(0x560, 0x178, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D6__USBH3_DATA1		IOMUX_PAD(0x560, 0x178, 5, 0x0a00, 0, 0)
-#define _MX51_PAD_NANDF_D5__GPIO4_3		IOMUX_PAD(0x564, 0x17c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D5__NANDF_D5		IOMUX_PAD(0x564, 0x17c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D5__PATA_DATA5		IOMUX_PAD(0x564, 0x17c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D5__SD4_WP		IOMUX_PAD(0x564, 0x17c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D5__USBH3_DATA2		IOMUX_PAD(0x564, 0x17c, 5, 0x0a04, 0, 0)
-#define _MX51_PAD_NANDF_D4__GPIO4_4		IOMUX_PAD(0x568, 0x180, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D4__NANDF_D4		IOMUX_PAD(0x568, 0x180, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D4__PATA_DATA4		IOMUX_PAD(0x568, 0x180, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D4__SD4_CD		IOMUX_PAD(0x568, 0x180, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D4__USBH3_DATA3		IOMUX_PAD(0x568, 0x180, 5, 0x0a08, 0, 0)
-#define _MX51_PAD_NANDF_D3__GPIO4_5		IOMUX_PAD(0x56c, 0x184, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D3__NANDF_D3		IOMUX_PAD(0x56c, 0x184, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D3__PATA_DATA3		IOMUX_PAD(0x56c, 0x184, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D3__SD4_DAT4		IOMUX_PAD(0x56c, 0x184, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D3__USBH3_DATA4		IOMUX_PAD(0x56c, 0x184, 5, 0x0a0c, 0, 0)
-#define _MX51_PAD_NANDF_D2__GPIO4_6		IOMUX_PAD(0x570, 0x188, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D2__NANDF_D2		IOMUX_PAD(0x570, 0x188, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D2__PATA_DATA2		IOMUX_PAD(0x570, 0x188, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D2__SD4_DAT5		IOMUX_PAD(0x570, 0x188, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D2__USBH3_DATA5		IOMUX_PAD(0x570, 0x188, 5, 0x0a10, 0, 0)
-#define _MX51_PAD_NANDF_D1__GPIO4_7		IOMUX_PAD(0x574, 0x18c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D1__NANDF_D1		IOMUX_PAD(0x574, 0x18c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D1__PATA_DATA1		IOMUX_PAD(0x574, 0x18c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D1__SD4_DAT6		IOMUX_PAD(0x574, 0x18c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D1__USBH3_DATA6		IOMUX_PAD(0x574, 0x18c, 5, 0x0a14, 0, 0)
-#define _MX51_PAD_NANDF_D0__GPIO4_8		IOMUX_PAD(0x578, 0x190, 3, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D0__NANDF_D0		IOMUX_PAD(0x578, 0x190, 0, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D0__PATA_DATA0		IOMUX_PAD(0x578, 0x190, 1, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D0__SD4_DAT7		IOMUX_PAD(0x578, 0x190, 2, 0x0000, 0, 0)
-#define _MX51_PAD_NANDF_D0__USBH3_DATA7		IOMUX_PAD(0x578, 0x190, 5, 0x0a18, 0, 0)
-#define _MX51_PAD_CSI1_D8__CSI1_D8		IOMUX_PAD(0x57c, 0x194, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D8__GPIO3_12		IOMUX_PAD(0x57c, 0x194, 3, 0x0998, 1, 0)
-#define _MX51_PAD_CSI1_D9__CSI1_D9		IOMUX_PAD(0x580, 0x198, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D9__GPIO3_13		IOMUX_PAD(0x580, 0x198, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D10__CSI1_D10		IOMUX_PAD(0x584, 0x19c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D11__CSI1_D11		IOMUX_PAD(0x588, 0x1a0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D12__CSI1_D12		IOMUX_PAD(0x58c, 0x1a4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D13__CSI1_D13		IOMUX_PAD(0x590, 0x1a8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D14__CSI1_D14		IOMUX_PAD(0x594, 0x1ac, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D15__CSI1_D15		IOMUX_PAD(0x598, 0x1b0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D16__CSI1_D16		IOMUX_PAD(0x59c, 0x1b4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D17__CSI1_D17		IOMUX_PAD(0x5a0, 0x1b8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D18__CSI1_D18		IOMUX_PAD(0x5a4, 0x1bc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_D19__CSI1_D19		IOMUX_PAD(0x5a8, 0x1c0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_VSYNC__CSI1_VSYNC	IOMUX_PAD(0x5ac, 0x1c4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_VSYNC__GPIO3_14		IOMUX_PAD(0x5ac, 0x1c4, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_HSYNC__CSI1_HSYNC	IOMUX_PAD(0x5b0, 0x1c8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_HSYNC__GPIO3_15		IOMUX_PAD(0x5b0, 0x1c8, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_PIXCLK__CSI1_PIXCLK	IOMUX_PAD(0x5b4, 0x000, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI1_MCLK__CSI1_MCLK		IOMUX_PAD(0x5b8, 0x000, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D12__CSI2_D12		IOMUX_PAD(0x5bc, 0x1cc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D12__GPIO4_9		IOMUX_PAD(0x5bc, 0x1cc, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D13__CSI2_D13		IOMUX_PAD(0x5c0, 0x1d0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D13__GPIO4_10		IOMUX_PAD(0x5c0, 0x1d0, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D14__CSI2_D14		IOMUX_PAD(0x5c4, 0x1d4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D15__CSI2_D15		IOMUX_PAD(0x5c8, 0x1d8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D16__CSI2_D16		IOMUX_PAD(0x5cc, 0x1dc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D17__CSI2_D17		IOMUX_PAD(0x5d0, 0x1e0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D18__CSI2_D18		IOMUX_PAD(0x5d4, 0x1e4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D18__GPIO4_11		IOMUX_PAD(0x5d4, 0x1e4, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D19__CSI2_D19		IOMUX_PAD(0x5d8, 0x1e8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_D19__GPIO4_12		IOMUX_PAD(0x5d8, 0x1e8, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_VSYNC__CSI2_VSYNC	IOMUX_PAD(0x5dc, 0x1ec, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_VSYNC__GPIO4_13		IOMUX_PAD(0x5dc, 0x1ec, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_HSYNC__CSI2_HSYNC	IOMUX_PAD(0x5e0, 0x1f0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_HSYNC__GPIO4_14		IOMUX_PAD(0x5e0, 0x1f0, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_PIXCLK__CSI2_PIXCLK	IOMUX_PAD(0x5e4, 0x1f4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSI2_PIXCLK__GPIO4_15		IOMUX_PAD(0x5e4, 0x1f4, 3, 0x0000, 0, 0)
-#define _MX51_PAD_I2C1_CLK__GPIO4_16		IOMUX_PAD(0x5e8, 0x1f8, 3, 0x0000, 0, 0)
-#define _MX51_PAD_I2C1_CLK__I2C1_CLK		IOMUX_PAD(0x5e8, 0x1f8, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_I2C1_DAT__GPIO4_17		IOMUX_PAD(0x5ec, 0x1fc, 3, 0x0000, 0, 0)
-#define _MX51_PAD_I2C1_DAT__I2C1_DAT		IOMUX_PAD(0x5ec, 0x1fc, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_TXD__AUD3_TXD		IOMUX_PAD(0x5f0, 0x200, 0, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_TXD__GPIO4_18		IOMUX_PAD(0x5f0, 0x200, 3, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_RXD__AUD3_RXD		IOMUX_PAD(0x5f4, 0x204, 0, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_RXD__GPIO4_19		IOMUX_PAD(0x5f4, 0x204, 3, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_RXD__UART3_RXD	IOMUX_PAD(0x5f4, 0x204, 1, 0x09f4, 2, 0)
-#define _MX51_PAD_AUD3_BB_CK__AUD3_TXC		IOMUX_PAD(0x5f8, 0x208, 0, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_CK__GPIO4_20		IOMUX_PAD(0x5f8, 0x208, 3, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_FS__AUD3_TXFS		IOMUX_PAD(0x5fc, 0x20c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_FS__GPIO4_21		IOMUX_PAD(0x5fc, 0x20c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_AUD3_BB_FS__UART3_TXD		IOMUX_PAD(0x5fc, 0x20c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI	IOMUX_PAD(0x600, 0x210, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_MOSI__GPIO4_22		IOMUX_PAD(0x600, 0x210, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_MOSI__I2C1_SDA		IOMUX_PAD(0x600, 0x210, 0x11, 0x09b4, 1, 0)
-#define _MX51_PAD_CSPI1_MISO__AUD4_RXD		IOMUX_PAD(0x604, 0x214, 1, 0x08c4, 1, 0)
-#define _MX51_PAD_CSPI1_MISO__ECSPI1_MISO	IOMUX_PAD(0x604, 0x214, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_MISO__GPIO4_23		IOMUX_PAD(0x604, 0x214, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_SS0__AUD4_TXC		IOMUX_PAD(0x608, 0x218, 1, 0x08cc, 1, 0)
-#define _MX51_PAD_CSPI1_SS0__ECSPI1_SS0		IOMUX_PAD(0x608, 0x218, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_SS0__GPIO4_24		IOMUX_PAD(0x608, 0x218, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_SS1__AUD4_TXD		IOMUX_PAD(0x60c, 0x21c, 1, 0x08c8, 1, 0)
-#define _MX51_PAD_CSPI1_SS1__ECSPI1_SS1		IOMUX_PAD(0x60c, 0x21c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_SS1__GPIO4_25		IOMUX_PAD(0x60c, 0x21c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_RDY__AUD4_TXFS		IOMUX_PAD(0x610, 0x220, 1, 0x08d0, 1, 0)
-#define _MX51_PAD_CSPI1_RDY__ECSPI1_RDY		IOMUX_PAD(0x610, 0x220, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_RDY__GPIO4_26		IOMUX_PAD(0x610, 0x220, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK	IOMUX_PAD(0x614, 0x224, 0, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_SCLK__GPIO4_27		IOMUX_PAD(0x614, 0x224, 3, 0x0000, 0, 0)
-#define _MX51_PAD_CSPI1_SCLK__I2C1_SCL		IOMUX_PAD(0x614, 0x224, 0x11, 0x09b0, 1, 0)
-#define _MX51_PAD_UART1_RXD__GPIO4_28		IOMUX_PAD(0x618, 0x228, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART1_RXD__UART1_RXD		IOMUX_PAD(0x618, 0x228, 0, 0x09e4, 0, 0)
-#define _MX51_PAD_UART1_TXD__GPIO4_29		IOMUX_PAD(0x61c, 0x22c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART1_TXD__PWM2_PWMO		IOMUX_PAD(0x61c, 0x22c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_UART1_TXD__UART1_TXD		IOMUX_PAD(0x61c, 0x22c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_UART1_RTS__GPIO4_30		IOMUX_PAD(0x620, 0x230, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART1_RTS__UART1_RTS		IOMUX_PAD(0x620, 0x230, 0, 0x09e0, 0, 0)
-#define _MX51_PAD_UART1_CTS__GPIO4_31		IOMUX_PAD(0x624, 0x234, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART1_CTS__UART1_CTS		IOMUX_PAD(0x624, 0x234, 0, 0x0000, 0, 0)
-#define _MX51_PAD_UART2_RXD__FIRI_TXD		IOMUX_PAD(0x628, 0x238, 1, 0x0000, 0, 0)
-#define _MX51_PAD_UART2_RXD__GPIO1_20		IOMUX_PAD(0x628, 0x238, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART2_RXD__UART2_RXD		IOMUX_PAD(0x628, 0x238, 0, 0x09ec, 2, 0)
-#define _MX51_PAD_UART2_TXD__FIRI_RXD		IOMUX_PAD(0x62c, 0x23c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_UART2_TXD__GPIO1_21		IOMUX_PAD(0x62c, 0x23c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART2_TXD__UART2_TXD		IOMUX_PAD(0x62c, 0x23c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_UART3_RXD__CSI1_D0		IOMUX_PAD(0x630, 0x240, 2, 0x0000, 0, 0)
-#define _MX51_PAD_UART3_RXD__GPIO1_22		IOMUX_PAD(0x630, 0x240, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART3_RXD__UART1_DTR		IOMUX_PAD(0x630, 0x240, 0, 0x0000, 0, 0)
-#define _MX51_PAD_UART3_RXD__UART3_RXD		IOMUX_PAD(0x630, 0x240, 1, 0x09f4, 4, 0)
-#define _MX51_PAD_UART3_TXD__CSI1_D1		IOMUX_PAD(0x634, 0x244, 2, 0x0000, 0, 0)
-#define _MX51_PAD_UART3_TXD__GPIO1_23		IOMUX_PAD(0x634, 0x244, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART3_TXD__UART1_DSR		IOMUX_PAD(0x634, 0x244, 0, 0x0000, 0, 0)
-#define _MX51_PAD_UART3_TXD__UART3_TXD		IOMUX_PAD(0x634, 0x244, 1, 0x0000, 0, 0)
-#define _MX51_PAD_OWIRE_LINE__GPIO1_24		IOMUX_PAD(0x638, 0x248, 3, 0x0000, 0, 0)
-#define _MX51_PAD_OWIRE_LINE__OWIRE_LINE	IOMUX_PAD(0x638, 0x248, 0, 0x0000, 0, 0)
-#define _MX51_PAD_OWIRE_LINE__SPDIF_OUT		IOMUX_PAD(0x638, 0x248, 6, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_ROW0__KEY_ROW0		IOMUX_PAD(0x63c, 0x24c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_ROW1__KEY_ROW1		IOMUX_PAD(0x640, 0x250, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_ROW2__KEY_ROW2		IOMUX_PAD(0x644, 0x254, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_ROW3__KEY_ROW3		IOMUX_PAD(0x648, 0x258, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL0__KEY_COL0		IOMUX_PAD(0x64c, 0x25c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL0__PLL1_BYP		IOMUX_PAD(0x64c, 0x25c, 7, 0x090c, 0, 0)
-#define _MX51_PAD_KEY_COL1__KEY_COL1		IOMUX_PAD(0x650, 0x260, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL1__PLL2_BYP		IOMUX_PAD(0x650, 0x260, 7, 0x0910, 0, 0)
-#define _MX51_PAD_KEY_COL2__KEY_COL2		IOMUX_PAD(0x654, 0x264, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL2__PLL3_BYP		IOMUX_PAD(0x654, 0x264, 7, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL3__KEY_COL3		IOMUX_PAD(0x658, 0x268, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL4__I2C2_SCL		IOMUX_PAD(0x65c, 0x26c, 0x13, 0x09b8, 1, 0)
-#define _MX51_PAD_KEY_COL4__KEY_COL4		IOMUX_PAD(0x65c, 0x26c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL4__SPDIF_OUT1		IOMUX_PAD(0x65c, 0x26c, 6, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL4__UART1_RI		IOMUX_PAD(0x65c, 0x26c, 1, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL4__UART3_RTS		IOMUX_PAD(0x65c, 0x26c, 2, 0x09f0, 4, 0)
-#define _MX51_PAD_KEY_COL5__I2C2_SDA		IOMUX_PAD(0x660, 0x270, 0x13, 0x09bc, 1, 0)
-#define _MX51_PAD_KEY_COL5__KEY_COL5		IOMUX_PAD(0x660, 0x270, 0, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL5__UART1_DCD		IOMUX_PAD(0x660, 0x270, 1, 0x0000, 0, 0)
-#define _MX51_PAD_KEY_COL5__UART3_CTS		IOMUX_PAD(0x660, 0x270, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_CLK__CSPI_SCLK		IOMUX_PAD(0x678, 0x278, 1, 0x0914, 1, 0)
-#define _MX51_PAD_USBH1_CLK__GPIO1_25		IOMUX_PAD(0x678, 0x278, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_CLK__I2C2_SCL		IOMUX_PAD(0x678, 0x278, 0x15, 0x09b8, 2, 0)
-#define _MX51_PAD_USBH1_CLK__USBH1_CLK		IOMUX_PAD(0x678, 0x278, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DIR__CSPI_MOSI		IOMUX_PAD(0x67c, 0x27c, 1, 0x091c, 1, 0)
-#define _MX51_PAD_USBH1_DIR__GPIO1_26		IOMUX_PAD(0x67c, 0x27c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DIR__I2C2_SDA		IOMUX_PAD(0x67c, 0x27c, 0x15, 0x09bc, 2, 0)
-#define _MX51_PAD_USBH1_DIR__USBH1_DIR		IOMUX_PAD(0x67c, 0x27c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_STP__CSPI_RDY		IOMUX_PAD(0x680, 0x280, 1, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_STP__GPIO1_27		IOMUX_PAD(0x680, 0x280, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_STP__UART3_RXD		IOMUX_PAD(0x680, 0x280, 5, 0x09f4, 6, 0)
-#define _MX51_PAD_USBH1_STP__USBH1_STP		IOMUX_PAD(0x680, 0x280, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_NXT__CSPI_MISO		IOMUX_PAD(0x684, 0x284, 1, 0x0918, 0, 0)
-#define _MX51_PAD_USBH1_NXT__GPIO1_28		IOMUX_PAD(0x684, 0x284, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_NXT__UART3_TXD		IOMUX_PAD(0x684, 0x284, 5, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_NXT__USBH1_NXT		IOMUX_PAD(0x684, 0x284, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA0__GPIO1_11		IOMUX_PAD(0x688, 0x288, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA0__UART2_CTS	IOMUX_PAD(0x688, 0x288, 1, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA0__USBH1_DATA0	IOMUX_PAD(0x688, 0x288, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA1__GPIO1_12		IOMUX_PAD(0x68c, 0x28c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA1__UART2_RXD	IOMUX_PAD(0x68c, 0x28c, 1, 0x09ec, 4, 0)
-#define _MX51_PAD_USBH1_DATA1__USBH1_DATA1	IOMUX_PAD(0x68c, 0x28c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA2__GPIO1_13		IOMUX_PAD(0x690, 0x290, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA2__UART2_TXD	IOMUX_PAD(0x690, 0x290, 1, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA2__USBH1_DATA2	IOMUX_PAD(0x690, 0x290, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA3__GPIO1_14		IOMUX_PAD(0x694, 0x294, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA3__UART2_RTS	IOMUX_PAD(0x694, 0x294, 1, 0x09e8, 5, 0)
-#define _MX51_PAD_USBH1_DATA3__USBH1_DATA3	IOMUX_PAD(0x694, 0x294, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA4__CSPI_SS0		IOMUX_PAD(0x698, 0x298, 1, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA4__GPIO1_15		IOMUX_PAD(0x698, 0x298, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA4__USBH1_DATA4	IOMUX_PAD(0x698, 0x298, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA5__CSPI_SS1		IOMUX_PAD(0x69c, 0x29c, 1, 0x0920, 0, 0)
-#define _MX51_PAD_USBH1_DATA5__GPIO1_16		IOMUX_PAD(0x69c, 0x29c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA5__USBH1_DATA5	IOMUX_PAD(0x69c, 0x29c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA6__CSPI_SS3		IOMUX_PAD(0x6a0, 0x2a0, 1, 0x0928, 1, 0)
-#define _MX51_PAD_USBH1_DATA6__GPIO1_17		IOMUX_PAD(0x6a0, 0x2a0, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA6__USBH1_DATA6	IOMUX_PAD(0x6a0, 0x2a0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA7__ECSPI1_SS3	IOMUX_PAD(0x6a4, 0x2a4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA7__ECSPI2_SS3	IOMUX_PAD(0x6a4, 0x2a4, 5, 0x0934, 1, 0)
-#define _MX51_PAD_USBH1_DATA7__GPIO1_18		IOMUX_PAD(0x6a4, 0x2a4, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA7__USBH1_DATA7	IOMUX_PAD(0x6a4, 0x2a4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN11__DI1_PIN11		IOMUX_PAD(0x6a8, 0x2a8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN11__ECSPI1_SS2		IOMUX_PAD(0x6a8, 0x2a8, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN11__GPIO3_0		IOMUX_PAD(0x6a8, 0x2a8, 4, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN12__DI1_PIN12		IOMUX_PAD(0x6ac, 0x2ac, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN12__GPIO3_1		IOMUX_PAD(0x6ac, 0x2ac, 4, 0x0978, 1, 0)
-#define _MX51_PAD_DI1_PIN13__DI1_PIN13		IOMUX_PAD(0x6b0, 0x2b0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN13__GPIO3_2		IOMUX_PAD(0x6b0, 0x2b0, 4, 0x097c, 1, 0)
-#define _MX51_PAD_DI1_D0_CS__DI1_D0_CS		IOMUX_PAD(0x6b4, 0x2b4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_D0_CS__GPIO3_3		IOMUX_PAD(0x6b4, 0x2b4, 4, 0x0980, 1, 0)
-#define _MX51_PAD_DI1_D1_CS__DI1_D1_CS		IOMUX_PAD(0x6b8, 0x2b8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_D1_CS__DISP1_PIN14	IOMUX_PAD(0x6b8, 0x2b8, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_D1_CS__DISP1_PIN5		IOMUX_PAD(0x6b8, 0x2b8, 3, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_D1_CS__GPIO3_4		IOMUX_PAD(0x6b8, 0x2b8, 4, 0x0984, 1, 0)
-#define _MX51_PAD_DISPB2_SER_DIN__DISP1_PIN1	IOMUX_PAD(0x6bc, 0x2bc, 2, 0x09a4, 1, 0)
-#define _MX51_PAD_DISPB2_SER_DIN__DISPB2_SER_DIN	IOMUX_PAD(0x6bc, 0x2bc, 0, 0x09c4, 0, 0)
-#define _MX51_PAD_DISPB2_SER_DIN__GPIO3_5	IOMUX_PAD(0x6bc, 0x2bc, 4, 0x0988, 1, 0)
-#define _MX51_PAD_DISPB2_SER_DIO__DISP1_PIN6	IOMUX_PAD(0x6c0, 0x2c0, 3, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_DIO__DISPB2_SER_DIO	IOMUX_PAD(0x6c0, 0x2c0, 0, 0x09c4, 1, 0)
-#define _MX51_PAD_DISPB2_SER_DIO__GPIO3_6	IOMUX_PAD(0x6c0, 0x2c0, 4, 0x098c, 1, 0)
-#define _MX51_PAD_DISPB2_SER_CLK__DISP1_PIN17	IOMUX_PAD(0x6c4, 0x2c4, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_CLK__DISP1_PIN7	IOMUX_PAD(0x6c4, 0x2c4, 3, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_CLK__DISPB2_SER_CLK	IOMUX_PAD(0x6c4, 0x2c4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_CLK__GPIO3_7	IOMUX_PAD(0x6c4, 0x2c4, 4, 0x0990, 1, 0)
-#define _MX51_PAD_DISPB2_SER_RS__DISP1_EXT_CLK	IOMUX_PAD(0x6c8, 0x2c8, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_RS__DISP1_PIN16	IOMUX_PAD(0x6c8, 0x2c8, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_RS__DISP1_PIN8	IOMUX_PAD(0x6c8, 0x2c8, 3, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS	IOMUX_PAD(0x6c8, 0x2c8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS	IOMUX_PAD(0x6c8, 0x2c8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISPB2_SER_RS__GPIO3_8	IOMUX_PAD(0x6c8, 0x2c8, 4, 0x0994, 1, 0)
-#define _MX51_PAD_DISP1_DAT0__DISP1_DAT0	IOMUX_PAD(0x6cc, 0x2cc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT1__DISP1_DAT1	IOMUX_PAD(0x6d0, 0x2d0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT2__DISP1_DAT2	IOMUX_PAD(0x6d4, 0x2d4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT3__DISP1_DAT3	IOMUX_PAD(0x6d8, 0x2d8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT4__DISP1_DAT4	IOMUX_PAD(0x6dc, 0x2dc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT5__DISP1_DAT5	IOMUX_PAD(0x6e0, 0x2e0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT6__BOOT_USB_SRC	IOMUX_PAD(0x6e4, 0x2e4, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT6__DISP1_DAT6	IOMUX_PAD(0x6e4, 0x2e4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT7__BOOT_EEPROM_CFG	IOMUX_PAD(0x6e8, 0x2e8, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT7__DISP1_DAT7	IOMUX_PAD(0x6e8, 0x2e8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT8__BOOT_SRC0		IOMUX_PAD(0x6ec, 0x2ec, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT8__DISP1_DAT8	IOMUX_PAD(0x6ec, 0x2ec, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT9__BOOT_SRC1		IOMUX_PAD(0x6f0, 0x2f0, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT9__DISP1_DAT9	IOMUX_PAD(0x6f0, 0x2f0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT10__BOOT_SPARE_SIZE	IOMUX_PAD(0x6f4, 0x2f4, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT10__DISP1_DAT10	IOMUX_PAD(0x6f4, 0x2f4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT11__BOOT_LPB_FREQ2	IOMUX_PAD(0x6f8, 0x2f8, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT11__DISP1_DAT11	IOMUX_PAD(0x6f8, 0x2f8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT12__BOOT_MLC_SEL	IOMUX_PAD(0x6fc, 0x2fc, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT12__DISP1_DAT12	IOMUX_PAD(0x6fc, 0x2fc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT13__BOOT_MEM_CTL0	IOMUX_PAD(0x700, 0x300, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT13__DISP1_DAT13	IOMUX_PAD(0x700, 0x300, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT14__BOOT_MEM_CTL1	IOMUX_PAD(0x704, 0x304, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT14__DISP1_DAT14	IOMUX_PAD(0x704, 0x304, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT15__BOOT_BUS_WIDTH	IOMUX_PAD(0x708, 0x308, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT15__DISP1_DAT15	IOMUX_PAD(0x708, 0x308, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT16__BOOT_PAGE_SIZE0	IOMUX_PAD(0x70c, 0x30c, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT16__DISP1_DAT16	IOMUX_PAD(0x70c, 0x30c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT17__BOOT_PAGE_SIZE1	IOMUX_PAD(0x710, 0x310, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT17__DISP1_DAT17	IOMUX_PAD(0x710, 0x310, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT18__BOOT_WEIM_MUXED0	IOMUX_PAD(0x714, 0x314, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT18__DISP1_DAT18	IOMUX_PAD(0x714, 0x314, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT18__DISP2_PIN11	IOMUX_PAD(0x714, 0x314, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT18__DISP2_PIN5	IOMUX_PAD(0x714, 0x314, 4, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT19__BOOT_WEIM_MUXED1	IOMUX_PAD(0x718, 0x318, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT19__DISP1_DAT19	IOMUX_PAD(0x718, 0x318, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT19__DISP2_PIN12	IOMUX_PAD(0x718, 0x318, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT19__DISP2_PIN6	IOMUX_PAD(0x718, 0x318, 4, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT20__BOOT_MEM_TYPE0	IOMUX_PAD(0x71c, 0x31c, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT20__DISP1_DAT20	IOMUX_PAD(0x71c, 0x31c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT20__DISP2_PIN13	IOMUX_PAD(0x71c, 0x31c, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT20__DISP2_PIN7	IOMUX_PAD(0x71c, 0x31c, 4, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT21__BOOT_MEM_TYPE1	IOMUX_PAD(0x720, 0x320, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT21__DISP1_DAT21	IOMUX_PAD(0x720, 0x320, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT21__DISP2_PIN14	IOMUX_PAD(0x720, 0x320, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT21__DISP2_PIN8	IOMUX_PAD(0x720, 0x320, 4, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT22__BOOT_LPB_FREQ0	IOMUX_PAD(0x724, 0x324, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT22__DISP1_DAT22	IOMUX_PAD(0x724, 0x324, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT22__DISP2_D0_CS	IOMUX_PAD(0x724, 0x324, 6, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT22__DISP2_DAT16	IOMUX_PAD(0x724, 0x324, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT23__BOOT_LPB_FREQ1	IOMUX_PAD(0x728, 0x328, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT23__DISP1_DAT23	IOMUX_PAD(0x728, 0x328, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT23__DISP2_D1_CS	IOMUX_PAD(0x728, 0x328, 6, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT23__DISP2_DAT17	IOMUX_PAD(0x728, 0x328, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP1_DAT23__DISP2_SER_CS	IOMUX_PAD(0x728, 0x328, 4, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN3__DI1_PIN3		IOMUX_PAD(0x72c, 0x32c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI1_PIN2__DI1_PIN2		IOMUX_PAD(0x734, 0x330, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI_GP2__DISP1_SER_CLK		IOMUX_PAD(0x740, 0x338, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI_GP2__DISP2_WAIT		IOMUX_PAD(0x740, 0x338, 2, 0x09a8, 1, 0)
-#define _MX51_PAD_DI_GP3__CSI1_DATA_EN		IOMUX_PAD(0x744, 0x33c, 3, 0x09a0, 1, 0)
-#define _MX51_PAD_DI_GP3__DISP1_SER_DIO		IOMUX_PAD(0x744, 0x33c, 0, 0x09c0, 0, 0)
-#define _MX51_PAD_DI_GP3__FEC_TX_ER		IOMUX_PAD(0x744, 0x33c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DI2_PIN4__CSI2_DATA_EN	IOMUX_PAD(0x748, 0x340, 3, 0x099c, 1, 0)
-#define _MX51_PAD_DI2_PIN4__DI2_PIN4		IOMUX_PAD(0x748, 0x340, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI2_PIN4__FEC_CRS		IOMUX_PAD(0x748, 0x340, 2, 0x0950, 1, 0)
-#define _MX51_PAD_DI2_PIN2__DI2_PIN2		IOMUX_PAD(0x74c, 0x344, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI2_PIN2__FEC_MDC		IOMUX_PAD(0x74c, 0x344, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DI2_PIN3__DI2_PIN3		IOMUX_PAD(0x750, 0x348, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI2_PIN3__FEC_MDIO		IOMUX_PAD(0x750, 0x348, 2, 0x0954, 1, 0)
-#define _MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK	IOMUX_PAD(0x754, 0x34c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DI2_DISP_CLK__FEC_RDATA1	IOMUX_PAD(0x754, 0x34c, 2, 0x095c, 1, 0)
-#define _MX51_PAD_DI_GP4__DI2_PIN15		IOMUX_PAD(0x758, 0x350, 4, 0x0000, 0, 0)
-#define _MX51_PAD_DI_GP4__DISP1_SER_DIN		IOMUX_PAD(0x758, 0x350, 0, 0x09c0, 1, 0)
-#define _MX51_PAD_DI_GP4__DISP2_PIN1		IOMUX_PAD(0x758, 0x350, 3, 0x0000, 0, 0)
-#define _MX51_PAD_DI_GP4__FEC_RDATA2		IOMUX_PAD(0x758, 0x350, 2, 0x0960, 1, 0)
-#define _MX51_PAD_DISP2_DAT0__DISP2_DAT0	IOMUX_PAD(0x75c, 0x354, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT0__FEC_RDATA3	IOMUX_PAD(0x75c, 0x354, 2, 0x0964, 1, 0)
-#define _MX51_PAD_DISP2_DAT0__KEY_COL6		IOMUX_PAD(0x75c, 0x354, 4, 0x09c8, 1, 0)
-#define _MX51_PAD_DISP2_DAT0__UART3_RXD		IOMUX_PAD(0x75c, 0x354, 5, 0x09f4, 8, 0)
-#define _MX51_PAD_DISP2_DAT0__USBH3_CLK		IOMUX_PAD(0x75c, 0x354, 3, 0x09f8, 1, 0)
-#define _MX51_PAD_DISP2_DAT1__DISP2_DAT1	IOMUX_PAD(0x760, 0x358, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT1__FEC_RX_ER		IOMUX_PAD(0x760, 0x358, 2, 0x0970, 1, 0)
-#define _MX51_PAD_DISP2_DAT1__KEY_COL7		IOMUX_PAD(0x760, 0x358, 4, 0x09cc, 1, 0)
-#define _MX51_PAD_DISP2_DAT1__UART3_TXD		IOMUX_PAD(0x760, 0x358, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT1__USBH3_DIR		IOMUX_PAD(0x760, 0x358, 3, 0x0a1c, 1, 0)
-#define _MX51_PAD_DISP2_DAT2__DISP2_DAT2	IOMUX_PAD(0x764, 0x35c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT3__DISP2_DAT3	IOMUX_PAD(0x768, 0x360, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT4__DISP2_DAT4	IOMUX_PAD(0x76c, 0x364, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT5__DISP2_DAT5	IOMUX_PAD(0x770, 0x368, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT6__DISP2_DAT6	IOMUX_PAD(0x774, 0x36c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT6__FEC_TDATA1	IOMUX_PAD(0x774, 0x36c, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT6__GPIO1_19		IOMUX_PAD(0x774, 0x36c, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT6__KEY_ROW4		IOMUX_PAD(0x774, 0x36c, 4, 0x09d0, 1, 0)
-#define _MX51_PAD_DISP2_DAT6__USBH3_STP		IOMUX_PAD(0x774, 0x36c, 3, 0x0a24, 1, 0)
-#define _MX51_PAD_DISP2_DAT7__DISP2_DAT7	IOMUX_PAD(0x778, 0x370, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT7__FEC_TDATA2	IOMUX_PAD(0x778, 0x370, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT7__GPIO1_29		IOMUX_PAD(0x778, 0x370, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT7__KEY_ROW5		IOMUX_PAD(0x778, 0x370, 4, 0x09d4, 1, 0)
-#define _MX51_PAD_DISP2_DAT7__USBH3_NXT		IOMUX_PAD(0x778, 0x370, 3, 0x0a20, 1, 0)
-#define _MX51_PAD_DISP2_DAT8__DISP2_DAT8	IOMUX_PAD(0x77c, 0x374, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT8__FEC_TDATA3	IOMUX_PAD(0x77c, 0x374, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT8__GPIO1_30		IOMUX_PAD(0x77c, 0x374, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT8__KEY_ROW6		IOMUX_PAD(0x77c, 0x374, 4, 0x09d8, 1, 0)
-#define _MX51_PAD_DISP2_DAT8__USBH3_DATA0	IOMUX_PAD(0x77c, 0x374, 3, 0x09fc, 1, 0)
-#define _MX51_PAD_DISP2_DAT9__AUD6_RXC		IOMUX_PAD(0x780, 0x378, 4, 0x08f4, 1, 0)
-#define _MX51_PAD_DISP2_DAT9__DISP2_DAT9	IOMUX_PAD(0x780, 0x378, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT9__FEC_TX_EN		IOMUX_PAD(0x780, 0x378, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT9__GPIO1_31		IOMUX_PAD(0x780, 0x378, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT9__USBH3_DATA1	IOMUX_PAD(0x780, 0x378, 3, 0x0a00, 1, 0)
-#define _MX51_PAD_DISP2_DAT10__DISP2_DAT10	IOMUX_PAD(0x784, 0x37c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT10__DISP2_SER_CS	IOMUX_PAD(0x784, 0x37c, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT10__FEC_COL		IOMUX_PAD(0x784, 0x37c, 2, 0x094c, 1, 0)
-#define _MX51_PAD_DISP2_DAT10__KEY_ROW7		IOMUX_PAD(0x784, 0x37c, 4, 0x09dc, 1, 0)
-#define _MX51_PAD_DISP2_DAT10__USBH3_DATA2	IOMUX_PAD(0x784, 0x37c, 3, 0x0a04, 1, 0)
-#define _MX51_PAD_DISP2_DAT11__AUD6_TXD		IOMUX_PAD(0x788, 0x380, 4, 0x08f0, 1, 0)
-#define _MX51_PAD_DISP2_DAT11__DISP2_DAT11	IOMUX_PAD(0x788, 0x380, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT11__FEC_RX_CLK	IOMUX_PAD(0x788, 0x380, 2, 0x0968, 1, 0)
-#define _MX51_PAD_DISP2_DAT11__GPIO1_10		IOMUX_PAD(0x788, 0x380, 7, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT11__USBH3_DATA3	IOMUX_PAD(0x788, 0x380, 3, 0x0a08, 1, 0)
-#define _MX51_PAD_DISP2_DAT12__AUD6_RXD		IOMUX_PAD(0x78c, 0x384, 4, 0x08ec, 1, 0)
-#define _MX51_PAD_DISP2_DAT12__DISP2_DAT12	IOMUX_PAD(0x78c, 0x384, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT12__FEC_RX_DV	IOMUX_PAD(0x78c, 0x384, 2, 0x096c, 1, 0)
-#define _MX51_PAD_DISP2_DAT12__USBH3_DATA4	IOMUX_PAD(0x78c, 0x384, 3, 0x0a0c, 1, 0)
-#define _MX51_PAD_DISP2_DAT13__AUD6_TXC		IOMUX_PAD(0x790, 0x388, 4, 0x08fc, 1, 0)
-#define _MX51_PAD_DISP2_DAT13__DISP2_DAT13	IOMUX_PAD(0x790, 0x388, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT13__FEC_TX_CLK	IOMUX_PAD(0x790, 0x388, 2, 0x0974, 1, 0)
-#define _MX51_PAD_DISP2_DAT13__USBH3_DATA5	IOMUX_PAD(0x790, 0x388, 3, 0x0a10, 1, 0)
-#define _MX51_PAD_DISP2_DAT14__AUD6_TXFS	IOMUX_PAD(0x794, 0x38c, 4, 0x0900, 1, 0)
-#define _MX51_PAD_DISP2_DAT14__DISP2_DAT14	IOMUX_PAD(0x794, 0x38c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT14__FEC_RDATA0	IOMUX_PAD(0x794, 0x38c, 2, 0x0958, 1, 0)
-#define _MX51_PAD_DISP2_DAT14__USBH3_DATA6	IOMUX_PAD(0x794, 0x38c, 3, 0x0a14, 1, 0)
-#define _MX51_PAD_DISP2_DAT15__AUD6_RXFS	IOMUX_PAD(0x798, 0x390, 4, 0x08f8, 1, 0)
-#define _MX51_PAD_DISP2_DAT15__DISP1_SER_CS	IOMUX_PAD(0x798, 0x390, 5, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT15__DISP2_DAT15	IOMUX_PAD(0x798, 0x390, 0, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT15__FEC_TDATA0	IOMUX_PAD(0x798, 0x390, 2, 0x0000, 0, 0)
-#define _MX51_PAD_DISP2_DAT15__USBH3_DATA7	IOMUX_PAD(0x798, 0x390, 3, 0x0a18, 1, 0)
-#define _MX51_PAD_SD1_CMD__AUD5_RXFS		IOMUX_PAD(0x79c, 0x394, 1, 0x08e0, 1, 0)
-#define _MX51_PAD_SD1_CMD__CSPI_MOSI		IOMUX_PAD(0x79c, 0x394, 2, 0x091c, 2, 0)
-#define _MX51_PAD_SD1_CMD__SD1_CMD		IOMUX_PAD(0x79c, 0x394, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_SD1_CLK__AUD5_RXC		IOMUX_PAD(0x7a0, 0x398, 1, 0x08dc, 1, 0)
-#define _MX51_PAD_SD1_CLK__CSPI_SCLK		IOMUX_PAD(0x7a0, 0x398, 2, 0x0914, 2, 0)
-#define _MX51_PAD_SD1_CLK__SD1_CLK		IOMUX_PAD(0x7a0, 0x398, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_SD1_DATA0__AUD5_TXD		IOMUX_PAD(0x7a4, 0x39c, 1, 0x08d8, 2, 0)
-#define _MX51_PAD_SD1_DATA0__CSPI_MISO		IOMUX_PAD(0x7a4, 0x39c, 2, 0x0918, 1, 0)
-#define _MX51_PAD_SD1_DATA0__SD1_DATA0		IOMUX_PAD(0x7a4, 0x39c, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA0__EIM_DA0		IOMUX_PAD(0x000, 0x01c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA1__EIM_DA1		IOMUX_PAD(0x000, 0x020, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA2__EIM_DA2		IOMUX_PAD(0x000, 0x024, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA3__EIM_DA3		IOMUX_PAD(0x000, 0x028, 0, 0x0000, 0, 0)
-#define _MX51_PAD_SD1_DATA1__AUD5_RXD		IOMUX_PAD(0x7a8, 0x3a0, 1, 0x08d4, 2, 0)
-#define _MX51_PAD_SD1_DATA1__SD1_DATA1		IOMUX_PAD(0x7a8, 0x3a0, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA4__EIM_DA4		IOMUX_PAD(0x000, 0x02c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA5__EIM_DA5		IOMUX_PAD(0x000, 0x030, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA6__EIM_DA6		IOMUX_PAD(0x000, 0x034, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA7__EIM_DA7		IOMUX_PAD(0x000, 0x038, 0, 0x0000, 0, 0)
-#define _MX51_PAD_SD1_DATA2__AUD5_TXC		IOMUX_PAD(0x7ac, 0x3a4, 1, 0x08e4, 2, 0)
-#define _MX51_PAD_SD1_DATA2__SD1_DATA2		IOMUX_PAD(0x7ac, 0x3a4, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA10__EIM_DA10		IOMUX_PAD(0x000, 0x044, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA11__EIM_DA11		IOMUX_PAD(0x000, 0x048, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA8__EIM_DA8		IOMUX_PAD(0x000, 0x03c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA9__EIM_DA9		IOMUX_PAD(0x000, 0x040, 0, 0x0000, 0, 0)
-#define _MX51_PAD_SD1_DATA3__AUD5_TXFS		IOMUX_PAD(0x7b0, 0x3a8, 1, 0x08e8, 2, 0)
-#define _MX51_PAD_SD1_DATA3__CSPI_SS1		IOMUX_PAD(0x7b0, 0x3a8, 2, 0x0920, 1, 0)
-#define _MX51_PAD_SD1_DATA3__SD1_DATA3		IOMUX_PAD(0x7b0, 0x3a8, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_0__CSPI_SS2		IOMUX_PAD(0x7b4, 0x3ac, 2, 0x0924, 0, 0)
-#define _MX51_PAD_GPIO1_0__GPIO1_0		IOMUX_PAD(0x7b4, 0x3ac, 1, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_0__SD1_CD		IOMUX_PAD(0x7b4, 0x3ac, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_1__CSPI_MISO		IOMUX_PAD(0x7b8, 0x3b0, 2, 0x0918, 2, 0)
-#define _MX51_PAD_GPIO1_1__GPIO1_1		IOMUX_PAD(0x7b8, 0x3b0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_1__SD1_WP		IOMUX_PAD(0x7b8, 0x3b0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA12__EIM_DA12		IOMUX_PAD(0x000, 0x04c, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA13__EIM_DA13		IOMUX_PAD(0x000, 0x050, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA14__EIM_DA14		IOMUX_PAD(0x000, 0x054, 0, 0x0000, 0, 0)
-#define _MX51_PAD_EIM_DA15__EIM_DA15		IOMUX_PAD(0x000, 0x058, 0, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_CMD__CSPI_MOSI		IOMUX_PAD(0x000, 0x3b4, 2, 0x091c, 3, 0)
-#define _MX51_PAD_SD2_CMD__I2C1_SCL		IOMUX_PAD(0x7bc, 0x3b4, 0x11, 0x09b0, 2, 0)
-#define _MX51_PAD_SD2_CMD__SD2_CMD		IOMUX_PAD(0x7bc, 0x3b4, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_CLK__CSPI_SCLK		IOMUX_PAD(0x7c0, 0x3b8, 2, 0x0914, 3, 0)
-#define _MX51_PAD_SD2_CLK__I2C1_SDA		IOMUX_PAD(0x7c0, 0x3b8, 0x11, 0x09b4, 2, 0)
-#define _MX51_PAD_SD2_CLK__SD2_CLK		IOMUX_PAD(0x7c0, 0x3b8, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA0__CSPI_MISO		IOMUX_PAD(0x7c4, 0x3bc, 2, 0x0918, 3, 0)
-#define _MX51_PAD_SD2_DATA0__SD1_DAT4		IOMUX_PAD(0x7c4, 0x3bc, 1, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA0__SD2_DATA0		IOMUX_PAD(0x7c4, 0x3bc, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA1__SD1_DAT5		IOMUX_PAD(0x7c8, 0x3c0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA1__SD2_DATA1		IOMUX_PAD(0x7c8, 0x3c0, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA1__USBH3_H2_DP	IOMUX_PAD(0x7c8, 0x3c0, 2, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA2__SD1_DAT6		IOMUX_PAD(0x7cc, 0x3c4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA2__SD2_DATA2		IOMUX_PAD(0x7cc, 0x3c4, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA2__USBH3_H2_DM	IOMUX_PAD(0x7cc, 0x3c4, 2, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA3__CSPI_SS2		IOMUX_PAD(0x7d0, 0x3c8, 2, 0x0924, 1, 0)
-#define _MX51_PAD_SD2_DATA3__SD1_DAT7		IOMUX_PAD(0x7d0, 0x3c8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_SD2_DATA3__SD2_DATA3		IOMUX_PAD(0x7d0, 0x3c8, 0x10, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_2__CCM_OUT_2		IOMUX_PAD(0x7d4, 0x3cc, 5, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_2__GPIO1_2		IOMUX_PAD(0x7d4, 0x3cc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_2__I2C2_SCL		IOMUX_PAD(0x7d4, 0x3cc, 0x12, 0x09b8, 3, 0)
-#define _MX51_PAD_GPIO1_2__PLL1_BYP		IOMUX_PAD(0x7d4, 0x3cc, 7, 0x090c, 1, 0)
-#define _MX51_PAD_GPIO1_2__PWM1_PWMO		IOMUX_PAD(0x7d4, 0x3cc, 1, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_3__GPIO1_3		IOMUX_PAD(0x7d8, 0x3d0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_3__I2C2_SDA		IOMUX_PAD(0x7d8, 0x3d0, 0x12, 0x09bc, 3, 0)
-#define _MX51_PAD_GPIO1_3__PLL2_BYP		IOMUX_PAD(0x7d8, 0x3d0, 7, 0x0910, 1, 0)
-#define _MX51_PAD_GPIO1_3__PWM2_PWMO		IOMUX_PAD(0x7d8, 0x3d0, 1, 0x0000, 0, 0)
-#define _MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ	IOMUX_PAD(0x7fc, 0x3d4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_PMIC_INT_REQ__PMIC_PMU_IRQ_B	IOMUX_PAD(0x7fc, 0x3d4, 1, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_4__DISP2_EXT_CLK	IOMUX_PAD(0x804, 0x3d8, 4, 0x0908, 1, 0)
-#define _MX51_PAD_GPIO1_4__EIM_RDY		IOMUX_PAD(0x804, 0x3d8, 3, 0x0938, 1, 0)
-#define _MX51_PAD_GPIO1_4__GPIO1_4		IOMUX_PAD(0x804, 0x3d8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_4__WDOG1_WDOG_B		IOMUX_PAD(0x804, 0x3d8, 2, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_5__CSI2_MCLK		IOMUX_PAD(0x808, 0x3dc, 6, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_5__DISP2_PIN16		IOMUX_PAD(0x808, 0x3dc, 3, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_5__GPIO1_5		IOMUX_PAD(0x808, 0x3dc, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_5__WDOG2_WDOG_B		IOMUX_PAD(0x808, 0x3dc, 2, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_6__DISP2_PIN17		IOMUX_PAD(0x80c, 0x3e0, 4, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_6__GPIO1_6		IOMUX_PAD(0x80c, 0x3e0, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_6__REF_EN_B		IOMUX_PAD(0x80c, 0x3e0, 3, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_7__CCM_OUT_0		IOMUX_PAD(0x810, 0x3e4, 3, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_7__GPIO1_7		IOMUX_PAD(0x810, 0x3e4, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_7__SD2_WP		IOMUX_PAD(0x810, 0x3e4, 6, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_7__SPDIF_OUT1		IOMUX_PAD(0x810, 0x3e4, 2, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_8__CSI2_DATA_EN		IOMUX_PAD(0x814, 0x3e8, 2, 0x099c, 2, 0)
-#define _MX51_PAD_GPIO1_8__GPIO1_8		IOMUX_PAD(0x814, 0x3e8, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_8__SD2_CD		IOMUX_PAD(0x814, 0x3e8, 6, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_8__USBH3_PWR		IOMUX_PAD(0x814, 0x3e8, 1, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_9__CCM_OUT_1		IOMUX_PAD(0x818, 0x3ec, 3, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_9__DISP2_D1_CS		IOMUX_PAD(0x818, 0x3ec, 2, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_9__DISP2_SER_CS		IOMUX_PAD(0x818, 0x3ec, 7, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_9__GPIO1_9		IOMUX_PAD(0x818, 0x3ec, 0, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_9__SD2_LCTL		IOMUX_PAD(0x818, 0x3ec, 6, 0x0000, 0, 0)
-#define _MX51_PAD_GPIO1_9__USBH3_OC		IOMUX_PAD(0x818, 0x3ec, 1, 0x0000, 0, 0)
 
 /* The same pins as above but with the default pad control values applied */
-#define MX51_PAD_EIM_D16__AUD4_RXFS		(_MX51_PAD_EIM_D16__AUD4_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D16__AUD5_TXD		(_MX51_PAD_EIM_D16__AUD5_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D16__EIM_D16		(_MX51_PAD_EIM_D16__EIM_D16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D16__GPIO2_0		(_MX51_PAD_EIM_D16__GPIO2_0 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D16__I2C1_SDA		(_MX51_PAD_EIM_D16__I2C1_SDA | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_EIM_D16__UART2_CTS		(_MX51_PAD_EIM_D16__UART2_CTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D16__USBH2_DATA0		(_MX51_PAD_EIM_D16__USBH2_DATA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D17__AUD5_RXD		(_MX51_PAD_EIM_D17__AUD5_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D17__EIM_D17		(_MX51_PAD_EIM_D17__EIM_D17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D17__GPIO2_1		(_MX51_PAD_EIM_D17__GPIO2_1 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D17__UART2_RXD		(_MX51_PAD_EIM_D17__UART2_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D17__UART3_CTS		(_MX51_PAD_EIM_D17__UART3_CTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D17__USBH2_DATA1		(_MX51_PAD_EIM_D17__USBH2_DATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D18__AUD5_TXC		(_MX51_PAD_EIM_D18__AUD5_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D18__EIM_D18		(_MX51_PAD_EIM_D18__EIM_D18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D18__GPIO2_2		(_MX51_PAD_EIM_D18__GPIO2_2 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D18__UART2_TXD		(_MX51_PAD_EIM_D18__UART2_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D18__UART3_RTS		(_MX51_PAD_EIM_D18__UART3_RTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D18__USBH2_DATA2		(_MX51_PAD_EIM_D18__USBH2_DATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D19__AUD4_RXC		(_MX51_PAD_EIM_D19__AUD4_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D19__AUD5_TXFS		(_MX51_PAD_EIM_D19__AUD5_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D19__EIM_D19		(_MX51_PAD_EIM_D19__EIM_D19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D19__GPIO2_3		(_MX51_PAD_EIM_D19__GPIO2_3 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D19__I2C1_SCL		(_MX51_PAD_EIM_D19__I2C1_SCL | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_EIM_D19__UART2_RTS		(_MX51_PAD_EIM_D19__UART2_RTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D19__USBH2_DATA3		(_MX51_PAD_EIM_D19__USBH2_DATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D20__AUD4_TXD		(_MX51_PAD_EIM_D20__AUD4_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D20__EIM_D20		(_MX51_PAD_EIM_D20__EIM_D20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D20__GPIO2_4		(_MX51_PAD_EIM_D20__GPIO2_4 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D20__SRTC_ALARM_DEB	(_MX51_PAD_EIM_D20__SRTC_ALARM_DEB | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D20__USBH2_DATA4		(_MX51_PAD_EIM_D20__USBH2_DATA4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D21__AUD4_RXD		(_MX51_PAD_EIM_D21__AUD4_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D21__EIM_D21		(_MX51_PAD_EIM_D21__EIM_D21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D21__GPIO2_5		(_MX51_PAD_EIM_D21__GPIO2_5 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D21__SRTC_ALARM_DEB	(_MX51_PAD_EIM_D21__SRTC_ALARM_DEB | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D21__USBH2_DATA5		(_MX51_PAD_EIM_D21__USBH2_DATA5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D22__AUD4_TXC		(_MX51_PAD_EIM_D22__AUD4_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D22__EIM_D22		(_MX51_PAD_EIM_D22__EIM_D22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D22__GPIO2_6		(_MX51_PAD_EIM_D22__GPIO2_6 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D22__USBH2_DATA6		(_MX51_PAD_EIM_D22__USBH2_DATA6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D23__AUD4_TXFS		(_MX51_PAD_EIM_D23__AUD4_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D23__EIM_D23		(_MX51_PAD_EIM_D23__EIM_D23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D23__GPIO2_7		(_MX51_PAD_EIM_D23__GPIO2_7 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D23__SPDIF_OUT1		(_MX51_PAD_EIM_D23__SPDIF_OUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D23__USBH2_DATA7		(_MX51_PAD_EIM_D23__USBH2_DATA7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D24__AUD6_RXFS		(_MX51_PAD_EIM_D24__AUD6_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D24__EIM_D24		(_MX51_PAD_EIM_D24__EIM_D24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D24__GPIO2_8		(_MX51_PAD_EIM_D24__GPIO2_8 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D24__I2C2_SDA		(_MX51_PAD_EIM_D24__I2C2_SDA | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_EIM_D24__UART3_CTS		(_MX51_PAD_EIM_D24__UART3_CTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D24__USBOTG_DATA0		(_MX51_PAD_EIM_D24__USBOTG_DATA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D25__EIM_D25		(_MX51_PAD_EIM_D25__EIM_D25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D25__KEY_COL6		(_MX51_PAD_EIM_D25__KEY_COL6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D25__UART2_CTS		(_MX51_PAD_EIM_D25__UART2_CTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D25__UART3_RXD		(_MX51_PAD_EIM_D25__UART3_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D25__USBOTG_DATA1		(_MX51_PAD_EIM_D25__USBOTG_DATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D26__EIM_D26		(_MX51_PAD_EIM_D26__EIM_D26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D26__KEY_COL7		(_MX51_PAD_EIM_D26__KEY_COL7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D26__UART2_RTS		(_MX51_PAD_EIM_D26__UART2_RTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D26__UART3_TXD		(_MX51_PAD_EIM_D26__UART3_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D26__USBOTG_DATA2		(_MX51_PAD_EIM_D26__USBOTG_DATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D27__AUD6_RXC		(_MX51_PAD_EIM_D27__AUD6_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D27__EIM_D27		(_MX51_PAD_EIM_D27__EIM_D27 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D27__GPIO2_9		(_MX51_PAD_EIM_D27__GPIO2_9 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_D27__I2C2_SCL		(_MX51_PAD_EIM_D27__I2C2_SCL | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_EIM_D27__UART3_RTS		(_MX51_PAD_EIM_D27__UART3_RTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_EIM_D27__USBOTG_DATA3		(_MX51_PAD_EIM_D27__USBOTG_DATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D28__AUD6_TXD		(_MX51_PAD_EIM_D28__AUD6_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D28__EIM_D28		(_MX51_PAD_EIM_D28__EIM_D28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D28__KEY_ROW4		(_MX51_PAD_EIM_D28__KEY_ROW4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D28__USBOTG_DATA4		(_MX51_PAD_EIM_D28__USBOTG_DATA4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D29__AUD6_RXD		(_MX51_PAD_EIM_D29__AUD6_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D29__EIM_D29		(_MX51_PAD_EIM_D29__EIM_D29 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D29__KEY_ROW5		(_MX51_PAD_EIM_D29__KEY_ROW5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D29__USBOTG_DATA5		(_MX51_PAD_EIM_D29__USBOTG_DATA5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D30__AUD6_TXC		(_MX51_PAD_EIM_D30__AUD6_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D30__EIM_D30		(_MX51_PAD_EIM_D30__EIM_D30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D30__KEY_ROW6		(_MX51_PAD_EIM_D30__KEY_ROW6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D30__USBOTG_DATA6		(_MX51_PAD_EIM_D30__USBOTG_DATA6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D31__AUD6_TXFS		(_MX51_PAD_EIM_D31__AUD6_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D31__EIM_D31		(_MX51_PAD_EIM_D31__EIM_D31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D31__KEY_ROW7		(_MX51_PAD_EIM_D31__KEY_ROW7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_D31__USBOTG_DATA7		(_MX51_PAD_EIM_D31__USBOTG_DATA7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A16__EIM_A16		(_MX51_PAD_EIM_A16__EIM_A16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A16__GPIO2_10		(_MX51_PAD_EIM_A16__GPIO2_10 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A16__OSC_FREQ_SEL0		(_MX51_PAD_EIM_A16__OSC_FREQ_SEL0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A17__EIM_A17		(_MX51_PAD_EIM_A17__EIM_A17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A17__GPIO2_11		(_MX51_PAD_EIM_A17__GPIO2_11 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A17__OSC_FREQ_SEL1		(_MX51_PAD_EIM_A17__OSC_FREQ_SEL1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A18__BOOT_LPB0		(_MX51_PAD_EIM_A18__BOOT_LPB0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A18__EIM_A18		(_MX51_PAD_EIM_A18__EIM_A18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A18__GPIO2_12		(_MX51_PAD_EIM_A18__GPIO2_12 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A19__BOOT_LPB1		(_MX51_PAD_EIM_A19__BOOT_LPB1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A19__EIM_A19		(_MX51_PAD_EIM_A19__EIM_A19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A19__GPIO2_13		(_MX51_PAD_EIM_A19__GPIO2_13 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A20__BOOT_UART_SRC0	(_MX51_PAD_EIM_A20__BOOT_UART_SRC0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A20__EIM_A20		(_MX51_PAD_EIM_A20__EIM_A20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A20__GPIO2_14		(_MX51_PAD_EIM_A20__GPIO2_14 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A21__BOOT_UART_SRC1	(_MX51_PAD_EIM_A21__BOOT_UART_SRC1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A21__EIM_A21		(_MX51_PAD_EIM_A21__EIM_A21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A21__GPIO2_15		(_MX51_PAD_EIM_A21__GPIO2_15 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A22__EIM_A22		(_MX51_PAD_EIM_A22__EIM_A22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A22__GPIO2_16		(_MX51_PAD_EIM_A22__GPIO2_16 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A23__BOOT_HPN_EN		(_MX51_PAD_EIM_A23__BOOT_HPN_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A23__EIM_A23		(_MX51_PAD_EIM_A23__EIM_A23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A23__GPIO2_17		(_MX51_PAD_EIM_A23__GPIO2_17 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A24__EIM_A24		(_MX51_PAD_EIM_A24__EIM_A24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A24__GPIO2_18		(_MX51_PAD_EIM_A24__GPIO2_18 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A24__USBH2_CLK		(_MX51_PAD_EIM_A24__USBH2_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A25__DISP1_PIN4		(_MX51_PAD_EIM_A25__DISP1_PIN4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A25__EIM_A25		(_MX51_PAD_EIM_A25__EIM_A25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A25__GPIO2_19		(_MX51_PAD_EIM_A25__GPIO2_19 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A25__USBH2_DIR		(_MX51_PAD_EIM_A25__USBH2_DIR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A26__CSI1_DATA_EN		(_MX51_PAD_EIM_A26__CSI1_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A26__DISP2_EXT_CLK		(_MX51_PAD_EIM_A26__DISP2_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A26__EIM_A26		(_MX51_PAD_EIM_A26__EIM_A26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A26__GPIO2_20		(_MX51_PAD_EIM_A26__GPIO2_20 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A26__USBH2_STP		(_MX51_PAD_EIM_A26__USBH2_STP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A27__CSI2_DATA_EN		(_MX51_PAD_EIM_A27__CSI2_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A27__DISP1_PIN1		(_MX51_PAD_EIM_A27__DISP1_PIN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A27__EIM_A27		(_MX51_PAD_EIM_A27__EIM_A27 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_A27__GPIO2_21		(_MX51_PAD_EIM_A27__GPIO2_21 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_A27__USBH2_NXT		(_MX51_PAD_EIM_A27__USBH2_NXT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB0__EIM_EB0		(_MX51_PAD_EIM_EB0__EIM_EB0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB1__EIM_EB1		(_MX51_PAD_EIM_EB1__EIM_EB1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB2__AUD5_RXFS		(_MX51_PAD_EIM_EB2__AUD5_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB2__CSI1_D2		(_MX51_PAD_EIM_EB2__CSI1_D2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB2__EIM_EB2		(_MX51_PAD_EIM_EB2__EIM_EB2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB2__FEC_MDIO		(_MX51_PAD_EIM_EB2__FEC_MDIO | \
+#define MX51_PAD_EIM_D16__AUD4_RXFS		IOMUX_PAD(0x3f0, 0x05c, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D16__AUD5_TXD		IOMUX_PAD(0x3f0, 0x05c, 7, 0x8d8, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D16__EIM_D16		IOMUX_PAD(0x3f0, 0x05c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D16__GPIO2_0		IOMUX_PAD(0x3f0, 0x05c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D16__I2C1_SDA		IOMUX_PAD(0x3f0, 0x05c, 0x14, 0x9b4, 0, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_EIM_D16__UART2_CTS		IOMUX_PAD(0x3f0, 0x05c, 3, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D16__USBH2_DATA0		IOMUX_PAD(0x3f0, 0x05c, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D17__AUD5_RXD		IOMUX_PAD(0x3f4, 0x060, 7, 0x8d4, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D17__EIM_D17		IOMUX_PAD(0x3f4, 0x060, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D17__GPIO2_1		IOMUX_PAD(0x3f4, 0x060, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D17__UART2_RXD		IOMUX_PAD(0x3f4, 0x060, 3, 0x9ec, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D17__UART3_CTS		IOMUX_PAD(0x3f4, 0x060, 4, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D17__USBH2_DATA1		IOMUX_PAD(0x3f4, 0x060, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D18__AUD5_TXC		IOMUX_PAD(0x3f8, 0x064, 7, 0x8e4, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D18__EIM_D18		IOMUX_PAD(0x3f8, 0x064, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D18__GPIO2_2		IOMUX_PAD(0x3f8, 0x064, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D18__UART2_TXD		IOMUX_PAD(0x3f8, 0x064, 3, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D18__UART3_RTS		IOMUX_PAD(0x3f8, 0x064, 4, 0x9f0, 1, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D18__USBH2_DATA2		IOMUX_PAD(0x3f8, 0x064, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D19__AUD4_RXC		IOMUX_PAD(0x3fc, 0x068, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D19__AUD5_TXFS		IOMUX_PAD(0x3fc, 0x068, 7, 0x8e8, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D19__EIM_D19		IOMUX_PAD(0x3fc, 0x068, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D19__GPIO2_3		IOMUX_PAD(0x3fc, 0x068, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D19__I2C1_SCL		IOMUX_PAD(0x3fc, 0x068, 0x14, 0x9b0, 0, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_EIM_D19__UART2_RTS		IOMUX_PAD(0x3fc, 0x068, 3, 0x9e8, 1, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D19__USBH2_DATA3		IOMUX_PAD(0x3fc, 0x068, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D20__AUD4_TXD		IOMUX_PAD(0x400, 0x06c, 5, 0x8c8, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D20__EIM_D20		IOMUX_PAD(0x400, 0x06c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D20__GPIO2_4		IOMUX_PAD(0x400, 0x06c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D20__SRTC_ALARM_DEB	IOMUX_PAD(0x400, 0x06c, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D20__USBH2_DATA4		IOMUX_PAD(0x400, 0x06c, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D21__AUD4_RXD		IOMUX_PAD(0x404, 0x070, 5, 0x8c4, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D21__EIM_D21		IOMUX_PAD(0x404, 0x070, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D21__GPIO2_5		IOMUX_PAD(0x404, 0x070, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D21__SRTC_ALARM_DEB	IOMUX_PAD(0x404, 0x070, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D21__USBH2_DATA5		IOMUX_PAD(0x404, 0x070, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D22__AUD4_TXC		IOMUX_PAD(0x408, 0x074, 5, 0x8cc, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D22__EIM_D22		IOMUX_PAD(0x408, 0x074, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D22__GPIO2_6		IOMUX_PAD(0x408, 0x074, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D22__USBH2_DATA6		IOMUX_PAD(0x408, 0x074, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D23__AUD4_TXFS		IOMUX_PAD(0x40c, 0x078, 5, 0x8d0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D23__EIM_D23		IOMUX_PAD(0x40c, 0x078, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D23__GPIO2_7		IOMUX_PAD(0x40c, 0x078, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D23__SPDIF_OUT1		IOMUX_PAD(0x40c, 0x078, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D23__USBH2_DATA7		IOMUX_PAD(0x40c, 0x078, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D24__AUD6_RXFS		IOMUX_PAD(0x410, 0x07c, 5, 0x8f8, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D24__EIM_D24		IOMUX_PAD(0x410, 0x07c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D24__GPIO2_8		IOMUX_PAD(0x410, 0x07c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D24__I2C2_SDA		IOMUX_PAD(0x410, 0x07c, 0x14, 0x9bc, 0, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_EIM_D24__UART3_CTS		IOMUX_PAD(0x410, 0x07c, 3, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D24__USBOTG_DATA0		IOMUX_PAD(0x410, 0x07c, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D25__EIM_D25		IOMUX_PAD(0x414, 0x080, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D25__KEY_COL6		IOMUX_PAD(0x414, 0x080, 1, 0x9c8, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D25__UART2_CTS		IOMUX_PAD(0x414, 0x080, 4, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D25__UART3_RXD		IOMUX_PAD(0x414, 0x080, 3, 0x9f4, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D25__USBOTG_DATA1		IOMUX_PAD(0x414, 0x080, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D26__EIM_D26		IOMUX_PAD(0x418, 0x084, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D26__KEY_COL7		IOMUX_PAD(0x418, 0x084, 1, 0x9cc, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D26__UART2_RTS		IOMUX_PAD(0x418, 0x084, 4, 0x9e8, 3, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D26__UART3_TXD		IOMUX_PAD(0x418, 0x084, 3, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D26__USBOTG_DATA2		IOMUX_PAD(0x418, 0x084, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D27__AUD6_RXC		IOMUX_PAD(0x41c, 0x088, 5, 0x8f4, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D27__EIM_D27		IOMUX_PAD(0x41c, 0x088, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D27__GPIO2_9		IOMUX_PAD(0x41c, 0x088, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_D27__I2C2_SCL		IOMUX_PAD(0x41c, 0x088, 0x14, 0x9b8, 0, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_EIM_D27__UART3_RTS		IOMUX_PAD(0x41c, 0x088, 3, 0x9f0, 3, MX51_UART_PAD_CTRL)
+#define MX51_PAD_EIM_D27__USBOTG_DATA3		IOMUX_PAD(0x41c, 0x088, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D28__AUD6_TXD		IOMUX_PAD(0x420, 0x08c, 5, 0x8f0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D28__EIM_D28		IOMUX_PAD(0x420, 0x08c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D28__KEY_ROW4		IOMUX_PAD(0x420, 0x08c, 1, 0x9d0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D28__USBOTG_DATA4		IOMUX_PAD(0x420, 0x08c, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D29__AUD6_RXD		IOMUX_PAD(0x424, 0x090, 5, 0x8ec, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D29__EIM_D29		IOMUX_PAD(0x424, 0x090, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D29__KEY_ROW5		IOMUX_PAD(0x424, 0x090, 1, 0x9d4, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D29__USBOTG_DATA5		IOMUX_PAD(0x424, 0x090, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D30__AUD6_TXC		IOMUX_PAD(0x428, 0x094, 5, 0x8fc, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D30__EIM_D30		IOMUX_PAD(0x428, 0x094, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D30__KEY_ROW6		IOMUX_PAD(0x428, 0x094, 1, 0x9d8, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D30__USBOTG_DATA6		IOMUX_PAD(0x428, 0x094, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D31__AUD6_TXFS		IOMUX_PAD(0x42c, 0x098, 5, 0x900, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D31__EIM_D31		IOMUX_PAD(0x42c, 0x098, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D31__KEY_ROW7		IOMUX_PAD(0x42c, 0x098, 1, 0x9dc, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D31__USBOTG_DATA7		IOMUX_PAD(0x42c, 0x098, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A16__EIM_A16		IOMUX_PAD(0x430, 0x09c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A16__GPIO2_10		IOMUX_PAD(0x430, 0x09c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A16__OSC_FREQ_SEL0		IOMUX_PAD(0x430, 0x09c, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A17__EIM_A17		IOMUX_PAD(0x434, 0x0a0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A17__GPIO2_11		IOMUX_PAD(0x434, 0x0a0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A17__OSC_FREQ_SEL1		IOMUX_PAD(0x434, 0x0a0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A18__BOOT_LPB0		IOMUX_PAD(0x438, 0x0a4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A18__EIM_A18		IOMUX_PAD(0x438, 0x0a4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A18__GPIO2_12		IOMUX_PAD(0x438, 0x0a4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A19__BOOT_LPB1		IOMUX_PAD(0x43c, 0x0a8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A19__EIM_A19		IOMUX_PAD(0x43c, 0x0a8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A19__GPIO2_13		IOMUX_PAD(0x43c, 0x0a8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A20__BOOT_UART_SRC0	IOMUX_PAD(0x440, 0x0ac, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A20__EIM_A20		IOMUX_PAD(0x440, 0x0ac, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A20__GPIO2_14		IOMUX_PAD(0x440, 0x0ac, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A21__BOOT_UART_SRC1	IOMUX_PAD(0x444, 0x0b0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A21__EIM_A21		IOMUX_PAD(0x444, 0x0b0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A21__GPIO2_15		IOMUX_PAD(0x444, 0x0b0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A22__EIM_A22		IOMUX_PAD(0x448, 0x0b4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A22__GPIO2_16		IOMUX_PAD(0x448, 0x0b4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A23__BOOT_HPN_EN		IOMUX_PAD(0x44c, 0x0b8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A23__EIM_A23		IOMUX_PAD(0x44c, 0x0b8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A23__GPIO2_17		IOMUX_PAD(0x44c, 0x0b8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A24__EIM_A24		IOMUX_PAD(0x450, 0x0bc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A24__GPIO2_18		IOMUX_PAD(0x450, 0x0bc, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A24__USBH2_CLK		IOMUX_PAD(0x450, 0x0bc, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A25__DISP1_PIN4		IOMUX_PAD(0x454, 0x0c0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A25__EIM_A25		IOMUX_PAD(0x454, 0x0c0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A25__GPIO2_19		IOMUX_PAD(0x454, 0x0c0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A25__USBH2_DIR		IOMUX_PAD(0x454, 0x0c0, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A26__CSI1_DATA_EN		IOMUX_PAD(0x458, 0x0c4, 5, 0x9a0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A26__DISP2_EXT_CLK		IOMUX_PAD(0x458, 0x0c4, 6, 0x908, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A26__EIM_A26		IOMUX_PAD(0x458, 0x0c4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A26__GPIO2_20		IOMUX_PAD(0x458, 0x0c4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A26__USBH2_STP		IOMUX_PAD(0x458, 0x0c4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A27__CSI2_DATA_EN		IOMUX_PAD(0x45c, 0x0c8, 5, 0x99c, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A27__DISP1_PIN1		IOMUX_PAD(0x45c, 0x0c8, 6, 0x9a4, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A27__EIM_A27		IOMUX_PAD(0x45c, 0x0c8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_A27__GPIO2_21		IOMUX_PAD(0x45c, 0x0c8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_A27__USBH2_NXT		IOMUX_PAD(0x45c, 0x0c8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB0__EIM_EB0		IOMUX_PAD(0x460, 0x0cc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB1__EIM_EB1		IOMUX_PAD(0x464, 0x0d0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB2__AUD5_RXFS		IOMUX_PAD(0x468, 0x0d4, 6, 0x8e0, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB2__CSI1_D2		IOMUX_PAD(0x468, 0x0d4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB2__EIM_EB2		IOMUX_PAD(0x468, 0x0d4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB2__FEC_MDIO		(IOMUX_PAD(0x468, 0x0d4, 3, 0x954, 0, 0) | \
 		MUX_PAD_CTRL(PAD_CTL_PUS_22K_UP | PAD_CTL_PKE | PAD_CTL_SRE_FAST | \
 		PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS))
-#define MX51_PAD_EIM_EB2__GPIO2_22		(_MX51_PAD_EIM_EB2__GPIO2_22 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_EB2__GPT_CMPOUT1		(_MX51_PAD_EIM_EB2__GPT_CMPOUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB3__AUD5_RXC		(_MX51_PAD_EIM_EB3__AUD5_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB3__CSI1_D3		(_MX51_PAD_EIM_EB3__CSI1_D3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB3__EIM_EB3		(_MX51_PAD_EIM_EB3__EIM_EB3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB3__FEC_RDATA1		(_MX51_PAD_EIM_EB3__FEC_RDATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_EB3__GPIO2_23		(_MX51_PAD_EIM_EB3__GPIO2_23 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_EB3__GPT_CMPOUT2		(_MX51_PAD_EIM_EB3__GPT_CMPOUT2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_OE__EIM_OE			(_MX51_PAD_EIM_OE__EIM_OE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_OE__GPIO2_24		(_MX51_PAD_EIM_OE__GPIO2_24 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CS0__EIM_CS0		(_MX51_PAD_EIM_CS0__EIM_CS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS0__GPIO2_25		(_MX51_PAD_EIM_CS0__GPIO2_25 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CS1__EIM_CS1		(_MX51_PAD_EIM_CS1__EIM_CS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS1__GPIO2_26		(_MX51_PAD_EIM_CS1__GPIO2_26 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CS2__AUD5_TXD		(_MX51_PAD_EIM_CS2__AUD5_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS2__CSI1_D4		(_MX51_PAD_EIM_CS2__CSI1_D4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS2__EIM_CS2		(_MX51_PAD_EIM_CS2__EIM_CS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS2__FEC_RDATA2		(_MX51_PAD_EIM_CS2__FEC_RDATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS2__GPIO2_27		(_MX51_PAD_EIM_CS2__GPIO2_27 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CS2__USBOTG_STP		(_MX51_PAD_EIM_CS2__USBOTG_STP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS3__AUD5_RXD		(_MX51_PAD_EIM_CS3__AUD5_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS3__CSI1_D5		(_MX51_PAD_EIM_CS3__CSI1_D5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS3__EIM_CS3		(_MX51_PAD_EIM_CS3__EIM_CS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS3__FEC_RDATA3		(_MX51_PAD_EIM_CS3__FEC_RDATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS3__GPIO2_28		(_MX51_PAD_EIM_CS3__GPIO2_28 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CS3__USBOTG_NXT		(_MX51_PAD_EIM_CS3__USBOTG_NXT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS4__AUD5_TXC		(_MX51_PAD_EIM_CS4__AUD5_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS4__CSI1_D6		(_MX51_PAD_EIM_CS4__CSI1_D6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS4__EIM_CS4		(_MX51_PAD_EIM_CS4__EIM_CS4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS4__FEC_RX_ER		(_MX51_PAD_EIM_CS4__FEC_RX_ER | MUX_PAD_CTRL(MX51_PAD_CTRL_2))
-#define MX51_PAD_EIM_CS4__GPIO2_29		(_MX51_PAD_EIM_CS4__GPIO2_29 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CS4__USBOTG_CLK		(_MX51_PAD_EIM_CS4__USBOTG_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS5__AUD5_TXFS		(_MX51_PAD_EIM_CS5__AUD5_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS5__CSI1_D7		(_MX51_PAD_EIM_CS5__CSI1_D7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS5__DISP1_EXT_CLK		(_MX51_PAD_EIM_CS5__DISP1_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS5__EIM_CS5		(_MX51_PAD_EIM_CS5__EIM_CS5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CS5__FEC_CRS		(_MX51_PAD_EIM_CS5__FEC_CRS | MUX_PAD_CTRL(MX51_PAD_CTRL_2))
-#define MX51_PAD_EIM_CS5__GPIO2_30		(_MX51_PAD_EIM_CS5__GPIO2_30 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CS5__USBOTG_DIR		(_MX51_PAD_EIM_CS5__USBOTG_DIR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DTACK__EIM_DTACK		(_MX51_PAD_EIM_DTACK__EIM_DTACK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DTACK__GPIO2_31		(_MX51_PAD_EIM_DTACK__GPIO2_31 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_LBA__EIM_LBA		(_MX51_PAD_EIM_LBA__EIM_LBA | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_LBA__GPIO3_1		(_MX51_PAD_EIM_LBA__GPIO3_1 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_EIM_CRE__EIM_CRE		(_MX51_PAD_EIM_CRE__EIM_CRE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_CRE__GPIO3_2		(_MX51_PAD_EIM_CRE__GPIO3_2 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DRAM_CS1__DRAM_CS1		(_MX51_PAD_DRAM_CS1__DRAM_CS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_WE_B__GPIO3_3		(_MX51_PAD_NANDF_WE_B__GPIO3_3 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_WE_B__NANDF_WE_B		(_MX51_PAD_NANDF_WE_B__NANDF_WE_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_WE_B__PATA_DIOW		(_MX51_PAD_NANDF_WE_B__PATA_DIOW | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_WE_B__SD3_DATA0		(_MX51_PAD_NANDF_WE_B__SD3_DATA0 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_NANDF_RE_B__GPIO3_4		(_MX51_PAD_NANDF_RE_B__GPIO3_4 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_RE_B__NANDF_RE_B		(_MX51_PAD_NANDF_RE_B__NANDF_RE_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RE_B__PATA_DIOR		(_MX51_PAD_NANDF_RE_B__PATA_DIOR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RE_B__SD3_DATA1		(_MX51_PAD_NANDF_RE_B__SD3_DATA1 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_NANDF_ALE__GPIO3_5		(_MX51_PAD_NANDF_ALE__GPIO3_5 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_ALE__NANDF_ALE		(_MX51_PAD_NANDF_ALE__NANDF_ALE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_ALE__PATA_BUFFER_EN	(_MX51_PAD_NANDF_ALE__PATA_BUFFER_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CLE__GPIO3_6		(_MX51_PAD_NANDF_CLE__GPIO3_6 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_CLE__NANDF_CLE		(_MX51_PAD_NANDF_CLE__NANDF_CLE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CLE__PATA_RESET_B	(_MX51_PAD_NANDF_CLE__PATA_RESET_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_WP_B__GPIO3_7		(_MX51_PAD_NANDF_WP_B__GPIO3_7 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_WP_B__NANDF_WP_B		(_MX51_PAD_NANDF_WP_B__NANDF_WP_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_WP_B__PATA_DMACK		(_MX51_PAD_NANDF_WP_B__PATA_DMACK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_WP_B__SD3_DATA2		(_MX51_PAD_NANDF_WP_B__SD3_DATA2 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_NANDF_RB0__ECSPI2_SS1		(_MX51_PAD_NANDF_RB0__ECSPI2_SS1 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_RB0__GPIO3_8		(_MX51_PAD_NANDF_RB0__GPIO3_8 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB0__NANDF_RB0		(_MX51_PAD_NANDF_RB0__NANDF_RB0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB0__PATA_DMARQ		(_MX51_PAD_NANDF_RB0__PATA_DMARQ | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB0__SD3_DATA3		(_MX51_PAD_NANDF_RB0__SD3_DATA3 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_NANDF_RB1__CSPI_MOSI		(_MX51_PAD_NANDF_RB1__CSPI_MOSI | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_RB1__ECSPI2_RDY		(_MX51_PAD_NANDF_RB1__ECSPI2_RDY | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_RB1__GPIO3_9		(_MX51_PAD_NANDF_RB1__GPIO3_9 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB1__NANDF_RB1		(_MX51_PAD_NANDF_RB1__NANDF_RB1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB1__PATA_IORDY		(_MX51_PAD_NANDF_RB1__PATA_IORDY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB1__SD4_CMD		(_MX51_PAD_NANDF_RB1__SD4_CMD | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_NANDF_RB2__DISP2_WAIT		(_MX51_PAD_NANDF_RB2__DISP2_WAIT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB2__ECSPI2_SCLK		(_MX51_PAD_NANDF_RB2__ECSPI2_SCLK | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_RB2__FEC_COL		(_MX51_PAD_NANDF_RB2__FEC_COL | MUX_PAD_CTRL(MX51_PAD_CTRL_2))
-#define MX51_PAD_NANDF_RB2__GPIO3_10		(_MX51_PAD_NANDF_RB2__GPIO3_10 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB2__NANDF_RB2		(_MX51_PAD_NANDF_RB2__NANDF_RB2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB2__USBH3_H3_DP		(_MX51_PAD_NANDF_RB2__USBH3_H3_DP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB2__USBH3_NXT		(_MX51_PAD_NANDF_RB2__USBH3_NXT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB3__DISP1_WAIT		(_MX51_PAD_NANDF_RB3__DISP1_WAIT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB3__ECSPI2_MISO		(_MX51_PAD_NANDF_RB3__ECSPI2_MISO | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_RB3__FEC_RX_CLK		(_MX51_PAD_NANDF_RB3__FEC_RX_CLK | MUX_PAD_CTRL(MX51_PAD_CTRL_2))
-#define MX51_PAD_NANDF_RB3__GPIO3_11		(_MX51_PAD_NANDF_RB3__GPIO3_11 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB3__NANDF_RB3		(_MX51_PAD_NANDF_RB3__NANDF_RB3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB3__USBH3_CLK		(_MX51_PAD_NANDF_RB3__USBH3_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB3__USBH3_H3_DM		(_MX51_PAD_NANDF_RB3__USBH3_H3_DM | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO_NAND__GPIO_NAND		(_MX51_PAD_GPIO_NAND__GPIO_NAND | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_GPIO_NAND__PATA_INTRQ		(_MX51_PAD_GPIO_NAND__PATA_INTRQ | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS0__GPIO3_16		(_MX51_PAD_NANDF_CS0__GPIO3_16 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS0__NANDF_CS0		(_MX51_PAD_NANDF_CS0__NANDF_CS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS1__GPIO3_17		(_MX51_PAD_NANDF_CS1__GPIO3_17 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS1__NANDF_CS1		(_MX51_PAD_NANDF_CS1__NANDF_CS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS2__CSPI_SCLK		(_MX51_PAD_NANDF_CS2__CSPI_SCLK | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_CS2__FEC_TX_ER		(_MX51_PAD_NANDF_CS2__FEC_TX_ER | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_NANDF_CS2__GPIO3_18		(_MX51_PAD_NANDF_CS2__GPIO3_18 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS2__NANDF_CS2		(_MX51_PAD_NANDF_CS2__NANDF_CS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS2__PATA_CS_0		(_MX51_PAD_NANDF_CS2__PATA_CS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS2__SD4_CLK		(_MX51_PAD_NANDF_CS2__SD4_CLK | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS))
-#define MX51_PAD_NANDF_CS2__USBH3_H1_DP		(_MX51_PAD_NANDF_CS2__USBH3_H1_DP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS3__FEC_MDC		(_MX51_PAD_NANDF_CS3__FEC_MDC | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_NANDF_CS3__GPIO3_19		(_MX51_PAD_NANDF_CS3__GPIO3_19 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS3__NANDF_CS3		(_MX51_PAD_NANDF_CS3__NANDF_CS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS3__PATA_CS_1		(_MX51_PAD_NANDF_CS3__PATA_CS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS3__SD4_DAT0		(_MX51_PAD_NANDF_CS3__SD4_DAT0 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_NANDF_CS3__USBH3_H1_DM		(_MX51_PAD_NANDF_CS3__USBH3_H1_DM | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS4__FEC_TDATA1		(_MX51_PAD_NANDF_CS4__FEC_TDATA1 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_NANDF_CS4__GPIO3_20		(_MX51_PAD_NANDF_CS4__GPIO3_20 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS4__NANDF_CS4		(_MX51_PAD_NANDF_CS4__NANDF_CS4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS4__PATA_DA_0		(_MX51_PAD_NANDF_CS4__PATA_DA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS4__SD4_DAT1		(_MX51_PAD_NANDF_CS4__SD4_DAT1 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_NANDF_CS4__USBH3_STP		(_MX51_PAD_NANDF_CS4__USBH3_STP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS5__FEC_TDATA2		(_MX51_PAD_NANDF_CS5__FEC_TDATA2 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_NANDF_CS5__GPIO3_21		(_MX51_PAD_NANDF_CS5__GPIO3_21 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS5__NANDF_CS5		(_MX51_PAD_NANDF_CS5__NANDF_CS5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS5__PATA_DA_1		(_MX51_PAD_NANDF_CS5__PATA_DA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS5__SD4_DAT2		(_MX51_PAD_NANDF_CS5__SD4_DAT2 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_NANDF_CS5__USBH3_DIR		(_MX51_PAD_NANDF_CS5__USBH3_DIR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS6__CSPI_SS3		(_MX51_PAD_NANDF_CS6__CSPI_SS3 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_CS6__FEC_TDATA3		(_MX51_PAD_NANDF_CS6__FEC_TDATA3 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_NANDF_CS6__GPIO3_22		(_MX51_PAD_NANDF_CS6__GPIO3_22 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS6__NANDF_CS6		(_MX51_PAD_NANDF_CS6__NANDF_CS6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS6__PATA_DA_2		(_MX51_PAD_NANDF_CS6__PATA_DA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS6__SD4_DAT3		(_MX51_PAD_NANDF_CS6__SD4_DAT3 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_NANDF_CS7__FEC_TX_EN		(_MX51_PAD_NANDF_CS7__FEC_TX_EN | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_NANDF_CS7__GPIO3_23		(_MX51_PAD_NANDF_CS7__GPIO3_23 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS7__NANDF_CS7		(_MX51_PAD_NANDF_CS7__NANDF_CS7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS7__SD3_CLK		(_MX51_PAD_NANDF_CS7__SD3_CLK | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS))
-#define MX51_PAD_NANDF_RDY_INT__ECSPI2_SS0	(_MX51_PAD_NANDF_RDY_INT__ECSPI2_SS0 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK	(_MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK | MUX_PAD_CTRL(MX51_PAD_CTRL_4))
-#define MX51_PAD_NANDF_RDY_INT__GPIO3_24	(_MX51_PAD_NANDF_RDY_INT__GPIO3_24 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_RDY_INT__NANDF_RDY_INT	(_MX51_PAD_NANDF_RDY_INT__NANDF_RDY_INT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RDY_INT__SD3_CMD		(_MX51_PAD_NANDF_RDY_INT__SD3_CMD | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_NANDF_D15__ECSPI2_MOSI		(_MX51_PAD_NANDF_D15__ECSPI2_MOSI | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_D15__GPIO3_25		(_MX51_PAD_NANDF_D15__GPIO3_25 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D15__NANDF_D15		(_MX51_PAD_NANDF_D15__NANDF_D15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D15__PATA_DATA15		(_MX51_PAD_NANDF_D15__PATA_DATA15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D15__SD3_DAT7		(_MX51_PAD_NANDF_D15__SD3_DAT7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D14__ECSPI2_SS3		(_MX51_PAD_NANDF_D14__ECSPI2_SS3 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_D14__GPIO3_26		(_MX51_PAD_NANDF_D14__GPIO3_26 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D14__NANDF_D14		(_MX51_PAD_NANDF_D14__NANDF_D14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D14__PATA_DATA14		(_MX51_PAD_NANDF_D14__PATA_DATA14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D14__SD3_DAT6		(_MX51_PAD_NANDF_D14__SD3_DAT6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D13__ECSPI2_SS2		(_MX51_PAD_NANDF_D13__ECSPI2_SS2 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_D13__GPIO3_27		(_MX51_PAD_NANDF_D13__GPIO3_27 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D13__NANDF_D13		(_MX51_PAD_NANDF_D13__NANDF_D13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D13__PATA_DATA13		(_MX51_PAD_NANDF_D13__PATA_DATA13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D13__SD3_DAT5		(_MX51_PAD_NANDF_D13__SD3_DAT5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D12__ECSPI2_SS1		(_MX51_PAD_NANDF_D12__ECSPI2_SS1 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_NANDF_D12__GPIO3_28		(_MX51_PAD_NANDF_D12__GPIO3_28 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D12__NANDF_D12		(_MX51_PAD_NANDF_D12__NANDF_D12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D12__PATA_DATA12		(_MX51_PAD_NANDF_D12__PATA_DATA12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D12__SD3_DAT4		(_MX51_PAD_NANDF_D12__SD3_DAT4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D11__FEC_RX_DV		(_MX51_PAD_NANDF_D11__FEC_RX_DV | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D11__GPIO3_29		(_MX51_PAD_NANDF_D11__GPIO3_29 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D11__NANDF_D11		(_MX51_PAD_NANDF_D11__NANDF_D11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D11__PATA_DATA11		(_MX51_PAD_NANDF_D11__PATA_DATA11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D11__SD3_DATA3		(_MX51_PAD_NANDF_D11__SD3_DATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D10__GPIO3_30		(_MX51_PAD_NANDF_D10__GPIO3_30 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D10__NANDF_D10		(_MX51_PAD_NANDF_D10__NANDF_D10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D10__PATA_DATA10		(_MX51_PAD_NANDF_D10__PATA_DATA10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D10__SD3_DATA2		(_MX51_PAD_NANDF_D10__SD3_DATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D9__FEC_RDATA0		(_MX51_PAD_NANDF_D9__FEC_RDATA0 | MUX_PAD_CTRL(MX51_PAD_CTRL_4))
-#define MX51_PAD_NANDF_D9__GPIO3_31		(_MX51_PAD_NANDF_D9__GPIO3_31 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D9__NANDF_D9		(_MX51_PAD_NANDF_D9__NANDF_D9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D9__PATA_DATA9		(_MX51_PAD_NANDF_D9__PATA_DATA9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D9__SD3_DATA1		(_MX51_PAD_NANDF_D9__SD3_DATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D8__FEC_TDATA0		(_MX51_PAD_NANDF_D8__FEC_TDATA0 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_NANDF_D8__GPIO4_0		(_MX51_PAD_NANDF_D8__GPIO4_0 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D8__NANDF_D8		(_MX51_PAD_NANDF_D8__NANDF_D8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D8__PATA_DATA8		(_MX51_PAD_NANDF_D8__PATA_DATA8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D8__SD3_DATA0		(_MX51_PAD_NANDF_D8__SD3_DATA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D7__GPIO4_1		(_MX51_PAD_NANDF_D7__GPIO4_1 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D7__NANDF_D7		(_MX51_PAD_NANDF_D7__NANDF_D7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D7__PATA_DATA7		(_MX51_PAD_NANDF_D7__PATA_DATA7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D7__USBH3_DATA0		(_MX51_PAD_NANDF_D7__USBH3_DATA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D6__GPIO4_2		(_MX51_PAD_NANDF_D6__GPIO4_2 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D6__NANDF_D6		(_MX51_PAD_NANDF_D6__NANDF_D6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D6__PATA_DATA6		(_MX51_PAD_NANDF_D6__PATA_DATA6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D6__SD4_LCTL		(_MX51_PAD_NANDF_D6__SD4_LCTL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D6__USBH3_DATA1		(_MX51_PAD_NANDF_D6__USBH3_DATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D5__GPIO4_3		(_MX51_PAD_NANDF_D5__GPIO4_3 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D5__NANDF_D5		(_MX51_PAD_NANDF_D5__NANDF_D5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D5__PATA_DATA5		(_MX51_PAD_NANDF_D5__PATA_DATA5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D5__SD4_WP		(_MX51_PAD_NANDF_D5__SD4_WP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D5__USBH3_DATA2		(_MX51_PAD_NANDF_D5__USBH3_DATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D4__GPIO4_4		(_MX51_PAD_NANDF_D4__GPIO4_4 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D4__NANDF_D4		(_MX51_PAD_NANDF_D4__NANDF_D4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D4__PATA_DATA4		(_MX51_PAD_NANDF_D4__PATA_DATA4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D4__SD4_CD		(_MX51_PAD_NANDF_D4__SD4_CD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D4__USBH3_DATA3		(_MX51_PAD_NANDF_D4__USBH3_DATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D3__GPIO4_5		(_MX51_PAD_NANDF_D3__GPIO4_5 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D3__NANDF_D3		(_MX51_PAD_NANDF_D3__NANDF_D3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D3__PATA_DATA3		(_MX51_PAD_NANDF_D3__PATA_DATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D3__SD4_DAT4		(_MX51_PAD_NANDF_D3__SD4_DAT4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D3__USBH3_DATA4		(_MX51_PAD_NANDF_D3__USBH3_DATA4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D2__GPIO4_6		(_MX51_PAD_NANDF_D2__GPIO4_6 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D2__NANDF_D2		(_MX51_PAD_NANDF_D2__NANDF_D2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D2__PATA_DATA2		(_MX51_PAD_NANDF_D2__PATA_DATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D2__SD4_DAT5		(_MX51_PAD_NANDF_D2__SD4_DAT5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D2__USBH3_DATA5		(_MX51_PAD_NANDF_D2__USBH3_DATA5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D1__GPIO4_7		(_MX51_PAD_NANDF_D1__GPIO4_7 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D1__NANDF_D1		(_MX51_PAD_NANDF_D1__NANDF_D1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D1__PATA_DATA1		(_MX51_PAD_NANDF_D1__PATA_DATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D1__SD4_DAT6		(_MX51_PAD_NANDF_D1__SD4_DAT6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D1__USBH3_DATA6		(_MX51_PAD_NANDF_D1__USBH3_DATA6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D0__GPIO4_8		(_MX51_PAD_NANDF_D0__GPIO4_8 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_NANDF_D0__NANDF_D0		(_MX51_PAD_NANDF_D0__NANDF_D0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D0__PATA_DATA0		(_MX51_PAD_NANDF_D0__PATA_DATA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D0__SD4_DAT7		(_MX51_PAD_NANDF_D0__SD4_DAT7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_D0__USBH3_DATA7		(_MX51_PAD_NANDF_D0__USBH3_DATA7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D8__CSI1_D8		(_MX51_PAD_CSI1_D8__CSI1_D8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D8__GPIO3_12		(_MX51_PAD_CSI1_D8__GPIO3_12 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI1_D9__CSI1_D9		(_MX51_PAD_CSI1_D9__CSI1_D9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D9__GPIO3_13		(_MX51_PAD_CSI1_D9__GPIO3_13 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI1_D10__CSI1_D10		(_MX51_PAD_CSI1_D10__CSI1_D10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D11__CSI1_D11		(_MX51_PAD_CSI1_D11__CSI1_D11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D12__CSI1_D12		(_MX51_PAD_CSI1_D12__CSI1_D12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D13__CSI1_D13		(_MX51_PAD_CSI1_D13__CSI1_D13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D14__CSI1_D14		(_MX51_PAD_CSI1_D14__CSI1_D14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D15__CSI1_D15		(_MX51_PAD_CSI1_D15__CSI1_D15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D16__CSI1_D16		(_MX51_PAD_CSI1_D16__CSI1_D16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D17__CSI1_D17		(_MX51_PAD_CSI1_D17__CSI1_D17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D18__CSI1_D18		(_MX51_PAD_CSI1_D18__CSI1_D18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_D19__CSI1_D19		(_MX51_PAD_CSI1_D19__CSI1_D19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_VSYNC__CSI1_VSYNC		(_MX51_PAD_CSI1_VSYNC__CSI1_VSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_VSYNC__GPIO3_14		(_MX51_PAD_CSI1_VSYNC__GPIO3_14 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI1_HSYNC__CSI1_HSYNC		(_MX51_PAD_CSI1_HSYNC__CSI1_HSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_HSYNC__GPIO3_15		(_MX51_PAD_CSI1_HSYNC__GPIO3_15 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI1_PIXCLK__CSI1_PIXCLK	(_MX51_PAD_CSI1_PIXCLK__CSI1_PIXCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI1_MCLK__CSI1_MCLK		(_MX51_PAD_CSI1_MCLK__CSI1_MCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D12__CSI2_D12		(_MX51_PAD_CSI2_D12__CSI2_D12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D12__GPIO4_9		(_MX51_PAD_CSI2_D12__GPIO4_9 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI2_D13__CSI2_D13		(_MX51_PAD_CSI2_D13__CSI2_D13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D13__GPIO4_10		(_MX51_PAD_CSI2_D13__GPIO4_10 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI2_D14__CSI2_D14		(_MX51_PAD_CSI2_D14__CSI2_D14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D15__CSI2_D15		(_MX51_PAD_CSI2_D15__CSI2_D15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D16__CSI2_D16		(_MX51_PAD_CSI2_D16__CSI2_D16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D17__CSI2_D17		(_MX51_PAD_CSI2_D17__CSI2_D17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D18__CSI2_D18		(_MX51_PAD_CSI2_D18__CSI2_D18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D18__GPIO4_11		(_MX51_PAD_CSI2_D18__GPIO4_11 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI2_D19__CSI2_D19		(_MX51_PAD_CSI2_D19__CSI2_D19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_D19__GPIO4_12		(_MX51_PAD_CSI2_D19__GPIO4_12 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI2_VSYNC__CSI2_VSYNC		(_MX51_PAD_CSI2_VSYNC__CSI2_VSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_VSYNC__GPIO4_13		(_MX51_PAD_CSI2_VSYNC__GPIO4_13 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI2_HSYNC__CSI2_HSYNC		(_MX51_PAD_CSI2_HSYNC__CSI2_HSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_HSYNC__GPIO4_14		(_MX51_PAD_CSI2_HSYNC__GPIO4_14 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSI2_PIXCLK__CSI2_PIXCLK	(_MX51_PAD_CSI2_PIXCLK__CSI2_PIXCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSI2_PIXCLK__GPIO4_15		(_MX51_PAD_CSI2_PIXCLK__GPIO4_15 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_I2C1_CLK__GPIO4_16		(_MX51_PAD_I2C1_CLK__GPIO4_16 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_I2C1_CLK__I2C1_CLK		(_MX51_PAD_I2C1_CLK__I2C1_CLK | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_I2C1_DAT__GPIO4_17		(_MX51_PAD_I2C1_DAT__GPIO4_17 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_I2C1_DAT__I2C1_DAT		(_MX51_PAD_I2C1_DAT__I2C1_DAT | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_TXD__AUD3_TXD		(_MX51_PAD_AUD3_BB_TXD__AUD3_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_TXD__GPIO4_18		(_MX51_PAD_AUD3_BB_TXD__GPIO4_18 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_RXD__AUD3_RXD		(_MX51_PAD_AUD3_BB_RXD__AUD3_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_RXD__GPIO4_19		(_MX51_PAD_AUD3_BB_RXD__GPIO4_19 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_RXD__UART3_RXD		(_MX51_PAD_AUD3_BB_RXD__UART3_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_CK__AUD3_TXC		(_MX51_PAD_AUD3_BB_CK__AUD3_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_CK__GPIO4_20		(_MX51_PAD_AUD3_BB_CK__GPIO4_20 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_FS__AUD3_TXFS		(_MX51_PAD_AUD3_BB_FS__AUD3_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_FS__GPIO4_21		(_MX51_PAD_AUD3_BB_FS__GPIO4_21 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_AUD3_BB_FS__UART3_TXD		(_MX51_PAD_AUD3_BB_FS__UART3_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI	(_MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_CSPI1_MOSI__GPIO4_22		(_MX51_PAD_CSPI1_MOSI__GPIO4_22 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSPI1_MOSI__I2C1_SDA		(_MX51_PAD_CSPI1_MOSI__I2C1_SDA | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_CSPI1_MISO__AUD4_RXD		(_MX51_PAD_CSPI1_MISO__AUD4_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSPI1_MISO__ECSPI1_MISO	(_MX51_PAD_CSPI1_MISO__ECSPI1_MISO | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_CSPI1_MISO__GPIO4_23		(_MX51_PAD_CSPI1_MISO__GPIO4_23 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSPI1_SS0__AUD4_TXC		(_MX51_PAD_CSPI1_SS0__AUD4_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSPI1_SS0__ECSPI1_SS0		(_MX51_PAD_CSPI1_SS0__ECSPI1_SS0 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_CSPI1_SS0__GPIO4_24		(_MX51_PAD_CSPI1_SS0__GPIO4_24 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSPI1_SS1__AUD4_TXD		(_MX51_PAD_CSPI1_SS1__AUD4_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSPI1_SS1__ECSPI1_SS1		(_MX51_PAD_CSPI1_SS1__ECSPI1_SS1 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_CSPI1_SS1__GPIO4_25		(_MX51_PAD_CSPI1_SS1__GPIO4_25 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSPI1_RDY__AUD4_TXFS		(_MX51_PAD_CSPI1_RDY__AUD4_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_CSPI1_RDY__ECSPI1_RDY		(_MX51_PAD_CSPI1_RDY__ECSPI1_RDY | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_CSPI1_RDY__GPIO4_26		(_MX51_PAD_CSPI1_RDY__GPIO4_26 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK	(_MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_CSPI1_SCLK__GPIO4_27		(_MX51_PAD_CSPI1_SCLK__GPIO4_27 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_CSPI1_SCLK__I2C1_SCL		(_MX51_PAD_CSPI1_SCLK__I2C1_SCL | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_UART1_RXD__GPIO4_28		(_MX51_PAD_UART1_RXD__GPIO4_28 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART1_RXD__UART1_RXD		(_MX51_PAD_UART1_RXD__UART1_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART1_TXD__GPIO4_29		(_MX51_PAD_UART1_TXD__GPIO4_29 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART1_TXD__PWM2_PWMO		(_MX51_PAD_UART1_TXD__PWM2_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_UART1_TXD__UART1_TXD		(_MX51_PAD_UART1_TXD__UART1_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART1_RTS__GPIO4_30		(_MX51_PAD_UART1_RTS__GPIO4_30 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART1_RTS__UART1_RTS		(_MX51_PAD_UART1_RTS__UART1_RTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART1_CTS__GPIO4_31		(_MX51_PAD_UART1_CTS__GPIO4_31 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART1_CTS__UART1_CTS		(_MX51_PAD_UART1_CTS__UART1_CTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART2_RXD__FIRI_TXD		(_MX51_PAD_UART2_RXD__FIRI_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_UART2_RXD__GPIO1_20		(_MX51_PAD_UART2_RXD__GPIO1_20 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART2_RXD__UART2_RXD		(_MX51_PAD_UART2_RXD__UART2_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART2_TXD__FIRI_RXD		(_MX51_PAD_UART2_TXD__FIRI_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_UART2_TXD__GPIO1_21		(_MX51_PAD_UART2_TXD__GPIO1_21 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART2_TXD__UART2_TXD		(_MX51_PAD_UART2_TXD__UART2_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART3_RXD__CSI1_D0		(_MX51_PAD_UART3_RXD__CSI1_D0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_UART3_RXD__GPIO1_22		(_MX51_PAD_UART3_RXD__GPIO1_22 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART3_RXD__UART1_DTR		(_MX51_PAD_UART3_RXD__UART1_DTR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_UART3_RXD__UART3_RXD		(_MX51_PAD_UART3_RXD__UART3_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART3_TXD__CSI1_D1		(_MX51_PAD_UART3_TXD__CSI1_D1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_UART3_TXD__GPIO1_23		(_MX51_PAD_UART3_TXD__GPIO1_23 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_UART3_TXD__UART1_DSR		(_MX51_PAD_UART3_TXD__UART1_DSR | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_UART3_TXD__UART3_TXD		(_MX51_PAD_UART3_TXD__UART3_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_OWIRE_LINE__GPIO1_24		(_MX51_PAD_OWIRE_LINE__GPIO1_24 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_OWIRE_LINE__OWIRE_LINE		(_MX51_PAD_OWIRE_LINE__OWIRE_LINE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_OWIRE_LINE__SPDIF_OUT		(_MX51_PAD_OWIRE_LINE__SPDIF_OUT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_ROW0__KEY_ROW0		(_MX51_PAD_KEY_ROW0__KEY_ROW0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_ROW1__KEY_ROW1		(_MX51_PAD_KEY_ROW1__KEY_ROW1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_ROW2__KEY_ROW2		(_MX51_PAD_KEY_ROW2__KEY_ROW2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_ROW3__KEY_ROW3		(_MX51_PAD_KEY_ROW3__KEY_ROW3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL0__KEY_COL0		(_MX51_PAD_KEY_COL0__KEY_COL0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL0__PLL1_BYP		(_MX51_PAD_KEY_COL0__PLL1_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL1__KEY_COL1		(_MX51_PAD_KEY_COL1__KEY_COL1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL1__PLL2_BYP		(_MX51_PAD_KEY_COL1__PLL2_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL2__KEY_COL2		(_MX51_PAD_KEY_COL2__KEY_COL2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL2__PLL3_BYP		(_MX51_PAD_KEY_COL2__PLL3_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL3__KEY_COL3		(_MX51_PAD_KEY_COL3__KEY_COL3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL4__I2C2_SCL		(_MX51_PAD_KEY_COL4__I2C2_SCL | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_KEY_COL4__KEY_COL4		(_MX51_PAD_KEY_COL4__KEY_COL4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL4__SPDIF_OUT1		(_MX51_PAD_KEY_COL4__SPDIF_OUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL4__UART1_RI		(_MX51_PAD_KEY_COL4__UART1_RI | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_KEY_COL4__UART3_RTS		(_MX51_PAD_KEY_COL4__UART3_RTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_KEY_COL5__I2C2_SDA		(_MX51_PAD_KEY_COL5__I2C2_SDA | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_KEY_COL5__KEY_COL5		(_MX51_PAD_KEY_COL5__KEY_COL5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_KEY_COL5__UART1_DCD		(_MX51_PAD_KEY_COL5__UART1_DCD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_KEY_COL5__UART3_CTS		(_MX51_PAD_KEY_COL5__UART3_CTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_USBH1_CLK__CSPI_SCLK		(_MX51_PAD_USBH1_CLK__CSPI_SCLK | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_CLK__GPIO1_25		(_MX51_PAD_USBH1_CLK__GPIO1_25 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_CLK__I2C2_SCL		(_MX51_PAD_USBH1_CLK__I2C2_SCL | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_USBH1_CLK__USBH1_CLK		(_MX51_PAD_USBH1_CLK__USBH1_CLK | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DIR__CSPI_MOSI		(_MX51_PAD_USBH1_DIR__CSPI_MOSI | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_DIR__GPIO1_26		(_MX51_PAD_USBH1_DIR__GPIO1_26 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DIR__I2C2_SDA		(_MX51_PAD_USBH1_DIR__I2C2_SDA | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_USBH1_DIR__USBH1_DIR		(_MX51_PAD_USBH1_DIR__USBH1_DIR | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_STP__CSPI_RDY		(_MX51_PAD_USBH1_STP__CSPI_RDY | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_STP__GPIO1_27		(_MX51_PAD_USBH1_STP__GPIO1_27 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_STP__UART3_RXD		(_MX51_PAD_USBH1_STP__UART3_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_USBH1_STP__USBH1_STP		(_MX51_PAD_USBH1_STP__USBH1_STP | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_NXT__CSPI_MISO		(_MX51_PAD_USBH1_NXT__CSPI_MISO | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_NXT__GPIO1_28		(_MX51_PAD_USBH1_NXT__GPIO1_28 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_NXT__UART3_TXD		(_MX51_PAD_USBH1_NXT__UART3_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_USBH1_NXT__USBH1_NXT		(_MX51_PAD_USBH1_NXT__USBH1_NXT | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA0__GPIO1_11		(_MX51_PAD_USBH1_DATA0__GPIO1_11 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA0__UART2_CTS		(_MX51_PAD_USBH1_DATA0__UART2_CTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA0__USBH1_DATA0	(_MX51_PAD_USBH1_DATA0__USBH1_DATA0 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA1__GPIO1_12		(_MX51_PAD_USBH1_DATA1__GPIO1_12 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA1__UART2_RXD		(_MX51_PAD_USBH1_DATA1__UART2_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA1__USBH1_DATA1	(_MX51_PAD_USBH1_DATA1__USBH1_DATA1 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA2__GPIO1_13		(_MX51_PAD_USBH1_DATA2__GPIO1_13 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA2__UART2_TXD		(_MX51_PAD_USBH1_DATA2__UART2_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA2__USBH1_DATA2	(_MX51_PAD_USBH1_DATA2__USBH1_DATA2 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA3__GPIO1_14		(_MX51_PAD_USBH1_DATA3__GPIO1_14 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA3__UART2_RTS		(_MX51_PAD_USBH1_DATA3__UART2_RTS | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA3__USBH1_DATA3	(_MX51_PAD_USBH1_DATA3__USBH1_DATA3 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA4__CSPI_SS0		(_MX51_PAD_USBH1_DATA4__CSPI_SS0 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA4__GPIO1_15		(_MX51_PAD_USBH1_DATA4__GPIO1_15 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA4__USBH1_DATA4	(_MX51_PAD_USBH1_DATA4__USBH1_DATA4 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA5__CSPI_SS1		(_MX51_PAD_USBH1_DATA5__CSPI_SS1 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA5__GPIO1_16		(_MX51_PAD_USBH1_DATA5__GPIO1_16 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA5__USBH1_DATA5	(_MX51_PAD_USBH1_DATA5__USBH1_DATA5 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA6__CSPI_SS3		(_MX51_PAD_USBH1_DATA6__CSPI_SS3 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA6__GPIO1_17		(_MX51_PAD_USBH1_DATA6__GPIO1_17 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA6__USBH1_DATA6	(_MX51_PAD_USBH1_DATA6__USBH1_DATA6 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA7__ECSPI1_SS3	(_MX51_PAD_USBH1_DATA7__ECSPI1_SS3 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA7__ECSPI2_SS3	(_MX51_PAD_USBH1_DATA7__ECSPI2_SS3 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA7__GPIO1_18		(_MX51_PAD_USBH1_DATA7__GPIO1_18 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_USBH1_DATA7__USBH1_DATA7	(_MX51_PAD_USBH1_DATA7__USBH1_DATA7 | MUX_PAD_CTRL(MX51_USBH1_PAD_CTRL))
-#define MX51_PAD_DI1_PIN11__DI1_PIN11		(_MX51_PAD_DI1_PIN11__DI1_PIN11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_PIN11__ECSPI1_SS2		(_MX51_PAD_DI1_PIN11__ECSPI1_SS2 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_DI1_PIN11__GPIO3_0		(_MX51_PAD_DI1_PIN11__GPIO3_0 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DI1_PIN12__DI1_PIN12		(_MX51_PAD_DI1_PIN12__DI1_PIN12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_PIN12__GPIO3_1		(_MX51_PAD_DI1_PIN12__GPIO3_1 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DI1_PIN13__DI1_PIN13		(_MX51_PAD_DI1_PIN13__DI1_PIN13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_PIN13__GPIO3_2		(_MX51_PAD_DI1_PIN13__GPIO3_2 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DI1_D0_CS__DI1_D0_CS		(_MX51_PAD_DI1_D0_CS__DI1_D0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_D0_CS__GPIO3_3		(_MX51_PAD_DI1_D0_CS__GPIO3_3 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DI1_D1_CS__DI1_D1_CS		(_MX51_PAD_DI1_D1_CS__DI1_D1_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_D1_CS__DISP1_PIN14		(_MX51_PAD_DI1_D1_CS__DISP1_PIN14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_D1_CS__DISP1_PIN5		(_MX51_PAD_DI1_D1_CS__DISP1_PIN5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_D1_CS__GPIO3_4		(_MX51_PAD_DI1_D1_CS__GPIO3_4 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_DIN__DISP1_PIN1	(_MX51_PAD_DISPB2_SER_DIN__DISP1_PIN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_DIN__DISPB2_SER_DIN	(_MX51_PAD_DISPB2_SER_DIN__DISPB2_SER_DIN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_DIN__GPIO3_5	(_MX51_PAD_DISPB2_SER_DIN__GPIO3_5 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_DIO__DISP1_PIN6	(_MX51_PAD_DISPB2_SER_DIO__DISP1_PIN6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_DIO__DISPB2_SER_DIO	(_MX51_PAD_DISPB2_SER_DIO__DISPB2_SER_DIO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_DIO__GPIO3_6	(_MX51_PAD_DISPB2_SER_DIO__GPIO3_6 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_CLK__DISP1_PIN17	(_MX51_PAD_DISPB2_SER_CLK__DISP1_PIN17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_CLK__DISP1_PIN7	(_MX51_PAD_DISPB2_SER_CLK__DISP1_PIN7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_CLK__DISPB2_SER_CLK	(_MX51_PAD_DISPB2_SER_CLK__DISPB2_SER_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_CLK__GPIO3_7	(_MX51_PAD_DISPB2_SER_CLK__GPIO3_7 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_RS__DISP1_EXT_CLK	(_MX51_PAD_DISPB2_SER_RS__DISP1_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_RS__DISP1_PIN16	(_MX51_PAD_DISPB2_SER_RS__DISP1_PIN16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_RS__DISP1_PIN8	(_MX51_PAD_DISPB2_SER_RS__DISP1_PIN8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS	(_MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS	(_MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISPB2_SER_RS__GPIO3_8		(_MX51_PAD_DISPB2_SER_RS__GPIO3_8 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT0__DISP1_DAT0		(_MX51_PAD_DISP1_DAT0__DISP1_DAT0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT1__DISP1_DAT1		(_MX51_PAD_DISP1_DAT1__DISP1_DAT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT2__DISP1_DAT2		(_MX51_PAD_DISP1_DAT2__DISP1_DAT2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT3__DISP1_DAT3		(_MX51_PAD_DISP1_DAT3__DISP1_DAT3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT4__DISP1_DAT4		(_MX51_PAD_DISP1_DAT4__DISP1_DAT4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT5__DISP1_DAT5		(_MX51_PAD_DISP1_DAT5__DISP1_DAT5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT6__BOOT_USB_SRC	(_MX51_PAD_DISP1_DAT6__BOOT_USB_SRC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT6__DISP1_DAT6		(_MX51_PAD_DISP1_DAT6__DISP1_DAT6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT7__BOOT_EEPROM_CFG	(_MX51_PAD_DISP1_DAT7__BOOT_EEPROM_CFG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT7__DISP1_DAT7		(_MX51_PAD_DISP1_DAT7__DISP1_DAT7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT8__BOOT_SRC0		(_MX51_PAD_DISP1_DAT8__BOOT_SRC0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT8__DISP1_DAT8		(_MX51_PAD_DISP1_DAT8__DISP1_DAT8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT9__BOOT_SRC1		(_MX51_PAD_DISP1_DAT9__BOOT_SRC1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT9__DISP1_DAT9		(_MX51_PAD_DISP1_DAT9__DISP1_DAT9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT10__BOOT_SPARE_SIZE	(_MX51_PAD_DISP1_DAT10__BOOT_SPARE_SIZE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT10__DISP1_DAT10	(_MX51_PAD_DISP1_DAT10__DISP1_DAT10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT11__BOOT_LPB_FREQ2	(_MX51_PAD_DISP1_DAT11__BOOT_LPB_FREQ2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT11__DISP1_DAT11	(_MX51_PAD_DISP1_DAT11__DISP1_DAT11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT12__BOOT_MLC_SEL	(_MX51_PAD_DISP1_DAT12__BOOT_MLC_SEL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT12__DISP1_DAT12	(_MX51_PAD_DISP1_DAT12__DISP1_DAT12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT13__BOOT_MEM_CTL0	(_MX51_PAD_DISP1_DAT13__BOOT_MEM_CTL0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT13__DISP1_DAT13	(_MX51_PAD_DISP1_DAT13__DISP1_DAT13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT14__BOOT_MEM_CTL1	(_MX51_PAD_DISP1_DAT14__BOOT_MEM_CTL1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT14__DISP1_DAT14	(_MX51_PAD_DISP1_DAT14__DISP1_DAT14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT15__BOOT_BUS_WIDTH	(_MX51_PAD_DISP1_DAT15__BOOT_BUS_WIDTH | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT15__DISP1_DAT15	(_MX51_PAD_DISP1_DAT15__DISP1_DAT15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT16__BOOT_PAGE_SIZE0	(_MX51_PAD_DISP1_DAT16__BOOT_PAGE_SIZE0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT16__DISP1_DAT16	(_MX51_PAD_DISP1_DAT16__DISP1_DAT16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT17__BOOT_PAGE_SIZE1	(_MX51_PAD_DISP1_DAT17__BOOT_PAGE_SIZE1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT17__DISP1_DAT17	(_MX51_PAD_DISP1_DAT17__DISP1_DAT17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT18__BOOT_WEIM_MUXED0	(_MX51_PAD_DISP1_DAT18__BOOT_WEIM_MUXED0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT18__DISP1_DAT18	(_MX51_PAD_DISP1_DAT18__DISP1_DAT18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT18__DISP2_PIN11	(_MX51_PAD_DISP1_DAT18__DISP2_PIN11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT18__DISP2_PIN5	(_MX51_PAD_DISP1_DAT18__DISP2_PIN5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT19__BOOT_WEIM_MUXED1	(_MX51_PAD_DISP1_DAT19__BOOT_WEIM_MUXED1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT19__DISP1_DAT19	(_MX51_PAD_DISP1_DAT19__DISP1_DAT19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT19__DISP2_PIN12	(_MX51_PAD_DISP1_DAT19__DISP2_PIN12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT19__DISP2_PIN6	(_MX51_PAD_DISP1_DAT19__DISP2_PIN6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT20__BOOT_MEM_TYPE0	(_MX51_PAD_DISP1_DAT20__BOOT_MEM_TYPE0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT20__DISP1_DAT20	(_MX51_PAD_DISP1_DAT20__DISP1_DAT20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT20__DISP2_PIN13	(_MX51_PAD_DISP1_DAT20__DISP2_PIN13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT20__DISP2_PIN7	(_MX51_PAD_DISP1_DAT20__DISP2_PIN7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT21__BOOT_MEM_TYPE1	(_MX51_PAD_DISP1_DAT21__BOOT_MEM_TYPE1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT21__DISP1_DAT21	(_MX51_PAD_DISP1_DAT21__DISP1_DAT21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT21__DISP2_PIN14	(_MX51_PAD_DISP1_DAT21__DISP2_PIN14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT21__DISP2_PIN8	(_MX51_PAD_DISP1_DAT21__DISP2_PIN8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT22__BOOT_LPB_FREQ0	(_MX51_PAD_DISP1_DAT22__BOOT_LPB_FREQ0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT22__DISP1_DAT22	(_MX51_PAD_DISP1_DAT22__DISP1_DAT22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT22__DISP2_D0_CS	(_MX51_PAD_DISP1_DAT22__DISP2_D0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT22__DISP2_DAT16	(_MX51_PAD_DISP1_DAT22__DISP2_DAT16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT23__BOOT_LPB_FREQ1	(_MX51_PAD_DISP1_DAT23__BOOT_LPB_FREQ1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT23__DISP1_DAT23	(_MX51_PAD_DISP1_DAT23__DISP1_DAT23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT23__DISP2_D1_CS	(_MX51_PAD_DISP1_DAT23__DISP2_D1_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT23__DISP2_DAT17	(_MX51_PAD_DISP1_DAT23__DISP2_DAT17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP1_DAT23__DISP2_SER_CS	(_MX51_PAD_DISP1_DAT23__DISP2_SER_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_PIN3__DI1_PIN3		(_MX51_PAD_DI1_PIN3__DI1_PIN3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI1_PIN2__DI1_PIN2		(_MX51_PAD_DI1_PIN2__DI1_PIN2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP2__DISP1_SER_CLK		(_MX51_PAD_DI_GP2__DISP1_SER_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP2__DISP2_WAIT		(_MX51_PAD_DI_GP2__DISP2_WAIT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP3__CSI1_DATA_EN		(_MX51_PAD_DI_GP3__CSI1_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP3__DISP1_SER_DIO		(_MX51_PAD_DI_GP3__DISP1_SER_DIO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP3__FEC_TX_ER		(_MX51_PAD_DI_GP3__FEC_TX_ER | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_DI2_PIN4__CSI2_DATA_EN		(_MX51_PAD_DI2_PIN4__CSI2_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI2_PIN4__DI2_PIN4		(_MX51_PAD_DI2_PIN4__DI2_PIN4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI2_PIN4__FEC_CRS		(_MX51_PAD_DI2_PIN4__FEC_CRS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI2_PIN2__DI2_PIN2		(_MX51_PAD_DI2_PIN2__DI2_PIN2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI2_PIN2__FEC_MDC		(_MX51_PAD_DI2_PIN2__FEC_MDC | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_DI2_PIN3__DI2_PIN3		(_MX51_PAD_DI2_PIN3__DI2_PIN3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI2_PIN3__FEC_MDIO		(_MX51_PAD_DI2_PIN3__FEC_MDIO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK	(_MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI2_DISP_CLK__FEC_RDATA1	(_MX51_PAD_DI2_DISP_CLK__FEC_RDATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP4__DI2_PIN15		(_MX51_PAD_DI_GP4__DI2_PIN15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP4__DISP1_SER_DIN		(_MX51_PAD_DI_GP4__DISP1_SER_DIN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP4__DISP2_PIN1		(_MX51_PAD_DI_GP4__DISP2_PIN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DI_GP4__FEC_RDATA2		(_MX51_PAD_DI_GP4__FEC_RDATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT0__DISP2_DAT0		(_MX51_PAD_DISP2_DAT0__DISP2_DAT0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT0__FEC_RDATA3		(_MX51_PAD_DISP2_DAT0__FEC_RDATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT0__KEY_COL6		(_MX51_PAD_DISP2_DAT0__KEY_COL6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT0__UART3_RXD		(_MX51_PAD_DISP2_DAT0__UART3_RXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT0__USBH3_CLK		(_MX51_PAD_DISP2_DAT0__USBH3_CLK | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT1__DISP2_DAT1		(_MX51_PAD_DISP2_DAT1__DISP2_DAT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT1__FEC_RX_ER		(_MX51_PAD_DISP2_DAT1__FEC_RX_ER | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT1__KEY_COL7		(_MX51_PAD_DISP2_DAT1__KEY_COL7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT1__UART3_TXD		(_MX51_PAD_DISP2_DAT1__UART3_TXD | MUX_PAD_CTRL(MX51_UART_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT1__USBH3_DIR		(_MX51_PAD_DISP2_DAT1__USBH3_DIR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT2__DISP2_DAT2		(_MX51_PAD_DISP2_DAT2__DISP2_DAT2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT3__DISP2_DAT3		(_MX51_PAD_DISP2_DAT3__DISP2_DAT3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT4__DISP2_DAT4		(_MX51_PAD_DISP2_DAT4__DISP2_DAT4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT5__DISP2_DAT5		(_MX51_PAD_DISP2_DAT5__DISP2_DAT5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT6__DISP2_DAT6		(_MX51_PAD_DISP2_DAT6__DISP2_DAT6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT6__FEC_TDATA1		(_MX51_PAD_DISP2_DAT6__FEC_TDATA1 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_DISP2_DAT6__GPIO1_19		(_MX51_PAD_DISP2_DAT6__GPIO1_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT6__KEY_ROW4		(_MX51_PAD_DISP2_DAT6__KEY_ROW4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT6__USBH3_STP		(_MX51_PAD_DISP2_DAT6__USBH3_STP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT7__DISP2_DAT7		(_MX51_PAD_DISP2_DAT7__DISP2_DAT7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT7__FEC_TDATA2		(_MX51_PAD_DISP2_DAT7__FEC_TDATA2 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_DISP2_DAT7__GPIO1_29		(_MX51_PAD_DISP2_DAT7__GPIO1_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT7__KEY_ROW5		(_MX51_PAD_DISP2_DAT7__KEY_ROW5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT7__USBH3_NXT		(_MX51_PAD_DISP2_DAT7__USBH3_NXT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT8__DISP2_DAT8		(_MX51_PAD_DISP2_DAT8__DISP2_DAT8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT8__FEC_TDATA3		(_MX51_PAD_DISP2_DAT8__FEC_TDATA3 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_DISP2_DAT8__GPIO1_30		(_MX51_PAD_DISP2_DAT8__GPIO1_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT8__KEY_ROW6		(_MX51_PAD_DISP2_DAT8__KEY_ROW6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT8__USBH3_DATA0	(_MX51_PAD_DISP2_DAT8__USBH3_DATA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT9__AUD6_RXC		(_MX51_PAD_DISP2_DAT9__AUD6_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT9__DISP2_DAT9		(_MX51_PAD_DISP2_DAT9__DISP2_DAT9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT9__FEC_TX_EN		(_MX51_PAD_DISP2_DAT9__FEC_TX_EN | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_DISP2_DAT9__GPIO1_31		(_MX51_PAD_DISP2_DAT9__GPIO1_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT9__USBH3_DATA1	(_MX51_PAD_DISP2_DAT9__USBH3_DATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT10__DISP2_DAT10	(_MX51_PAD_DISP2_DAT10__DISP2_DAT10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT10__DISP2_SER_CS	(_MX51_PAD_DISP2_DAT10__DISP2_SER_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT10__FEC_COL		(_MX51_PAD_DISP2_DAT10__FEC_COL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT10__KEY_ROW7		(_MX51_PAD_DISP2_DAT10__KEY_ROW7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT10__USBH3_DATA2	(_MX51_PAD_DISP2_DAT10__USBH3_DATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT11__AUD6_TXD		(_MX51_PAD_DISP2_DAT11__AUD6_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT11__DISP2_DAT11	(_MX51_PAD_DISP2_DAT11__DISP2_DAT11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT11__FEC_RX_CLK	(_MX51_PAD_DISP2_DAT11__FEC_RX_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT11__GPIO1_10		(_MX51_PAD_DISP2_DAT11__GPIO1_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT11__USBH3_DATA3	(_MX51_PAD_DISP2_DAT11__USBH3_DATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT12__AUD6_RXD		(_MX51_PAD_DISP2_DAT12__AUD6_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT12__DISP2_DAT12	(_MX51_PAD_DISP2_DAT12__DISP2_DAT12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT12__FEC_RX_DV		(_MX51_PAD_DISP2_DAT12__FEC_RX_DV | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT12__USBH3_DATA4	(_MX51_PAD_DISP2_DAT12__USBH3_DATA4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT13__AUD6_TXC		(_MX51_PAD_DISP2_DAT13__AUD6_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT13__DISP2_DAT13	(_MX51_PAD_DISP2_DAT13__DISP2_DAT13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT13__FEC_TX_CLK	(_MX51_PAD_DISP2_DAT13__FEC_TX_CLK | MUX_PAD_CTRL(MX51_PAD_CTRL_4))
-#define MX51_PAD_DISP2_DAT13__USBH3_DATA5	(_MX51_PAD_DISP2_DAT13__USBH3_DATA5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT14__AUD6_TXFS		(_MX51_PAD_DISP2_DAT14__AUD6_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT14__DISP2_DAT14	(_MX51_PAD_DISP2_DAT14__DISP2_DAT14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT14__FEC_RDATA0	(_MX51_PAD_DISP2_DAT14__FEC_RDATA0 | MUX_PAD_CTRL(MX51_PAD_CTRL_4))
-#define MX51_PAD_DISP2_DAT14__USBH3_DATA6	(_MX51_PAD_DISP2_DAT14__USBH3_DATA6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT15__AUD6_RXFS		(_MX51_PAD_DISP2_DAT15__AUD6_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT15__DISP1_SER_CS	(_MX51_PAD_DISP2_DAT15__DISP1_SER_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT15__DISP2_DAT15	(_MX51_PAD_DISP2_DAT15__DISP2_DAT15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_DISP2_DAT15__FEC_TDATA0	(_MX51_PAD_DISP2_DAT15__FEC_TDATA0 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
-#define MX51_PAD_DISP2_DAT15__USBH3_DATA7	(_MX51_PAD_DISP2_DAT15__USBH3_DATA7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_CMD__AUD5_RXFS		(_MX51_PAD_SD1_CMD__AUD5_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_CMD__CSPI_MOSI		(_MX51_PAD_SD1_CMD__CSPI_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_CMD__SD1_CMD		(_MX51_PAD_SD1_CMD__SD1_CMD | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_SD1_CLK__AUD5_RXC		(_MX51_PAD_SD1_CLK__AUD5_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_CLK__CSPI_SCLK		(_MX51_PAD_SD1_CLK__CSPI_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_CLK__SD1_CLK		(_MX51_PAD_SD1_CLK__SD1_CLK | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS))
-#define MX51_PAD_SD1_DATA0__AUD5_TXD		(_MX51_PAD_SD1_DATA0__AUD5_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_DATA0__CSPI_MISO		(_MX51_PAD_SD1_DATA0__CSPI_MISO | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_SD1_DATA0__SD1_DATA0		(_MX51_PAD_SD1_DATA0__SD1_DATA0 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_EIM_DA0__EIM_DA0		(_MX51_PAD_EIM_DA0__EIM_DA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA1__EIM_DA1		(_MX51_PAD_EIM_DA1__EIM_DA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA2__EIM_DA2		(_MX51_PAD_EIM_DA2__EIM_DA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA3__EIM_DA3		(_MX51_PAD_EIM_DA3__EIM_DA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_DATA1__AUD5_RXD		(_MX51_PAD_SD1_DATA1__AUD5_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_DATA1__SD1_DATA1		(_MX51_PAD_SD1_DATA1__SD1_DATA1 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_EIM_DA4__EIM_DA4		(_MX51_PAD_EIM_DA4__EIM_DA4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA5__EIM_DA5		(_MX51_PAD_EIM_DA5__EIM_DA5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA6__EIM_DA6		(_MX51_PAD_EIM_DA6__EIM_DA6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA7__EIM_DA7		(_MX51_PAD_EIM_DA7__EIM_DA7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_DATA2__AUD5_TXC		(_MX51_PAD_SD1_DATA2__AUD5_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_DATA2__SD1_DATA2		(_MX51_PAD_SD1_DATA2__SD1_DATA2 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_EIM_DA10__EIM_DA10		(_MX51_PAD_EIM_DA10__EIM_DA10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA11__EIM_DA11		(_MX51_PAD_EIM_DA11__EIM_DA11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA8__EIM_DA8		(_MX51_PAD_EIM_DA8__EIM_DA8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA9__EIM_DA9		(_MX51_PAD_EIM_DA9__EIM_DA9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_DATA3__AUD5_TXFS		(_MX51_PAD_SD1_DATA3__AUD5_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_DATA3__CSPI_SS1		(_MX51_PAD_SD1_DATA3__CSPI_SS1 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_SD1_DATA3__SD1_DATA3		(_MX51_PAD_SD1_DATA3__SD1_DATA3 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_GPIO1_0__CSPI_SS2		(_MX51_PAD_GPIO1_0__CSPI_SS2 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_GPIO1_0__GPIO1_0		(_MX51_PAD_GPIO1_0__GPIO1_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_0__SD1_CD		(_MX51_PAD_GPIO1_0__SD1_CD | MUX_PAD_CTRL(MX51_ESDHC_PAD_CTRL))
-#define MX51_PAD_GPIO1_1__CSPI_MISO		(_MX51_PAD_GPIO1_1__CSPI_MISO | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_GPIO1_1__GPIO1_1		(_MX51_PAD_GPIO1_1__GPIO1_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_1__SD1_WP		(_MX51_PAD_GPIO1_1__SD1_WP | MUX_PAD_CTRL(MX51_ESDHC_PAD_CTRL))
-#define MX51_PAD_EIM_DA12__EIM_DA12		(_MX51_PAD_EIM_DA12__EIM_DA12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA13__EIM_DA13		(_MX51_PAD_EIM_DA13__EIM_DA13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA14__EIM_DA14		(_MX51_PAD_EIM_DA14__EIM_DA14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_EIM_DA15__EIM_DA15		(_MX51_PAD_EIM_DA15__EIM_DA15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD2_CMD__CSPI_MOSI		(_MX51_PAD_SD2_CMD__CSPI_MOSI | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_SD2_CMD__I2C1_SCL		(_MX51_PAD_SD2_CMD__I2C1_SCL | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_SD2_CMD__SD2_CMD		(_MX51_PAD_SD2_CMD__SD2_CMD | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_SD2_CLK__CSPI_SCLK		(_MX51_PAD_SD2_CLK__CSPI_SCLK | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_SD2_CLK__I2C1_SDA		(_MX51_PAD_SD2_CLK__I2C1_SDA | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_SD2_CLK__SD2_CLK		(_MX51_PAD_SD2_CLK__SD2_CLK | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS))
-#define MX51_PAD_SD2_DATA0__CSPI_MISO		(_MX51_PAD_SD2_DATA0__CSPI_MISO | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_SD2_DATA0__SD1_DAT4		(_MX51_PAD_SD2_DATA0__SD1_DAT4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD2_DATA0__SD2_DATA0		(_MX51_PAD_SD2_DATA0__SD2_DATA0 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_SD2_DATA1__SD1_DAT5		(_MX51_PAD_SD2_DATA1__SD1_DAT5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD2_DATA1__SD2_DATA1		(_MX51_PAD_SD2_DATA1__SD2_DATA1 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_SD2_DATA1__USBH3_H2_DP		(_MX51_PAD_SD2_DATA1__USBH3_H2_DP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD2_DATA2__SD1_DAT6		(_MX51_PAD_SD2_DATA2__SD1_DAT6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD2_DATA2__SD2_DATA2		(_MX51_PAD_SD2_DATA2__SD2_DATA2 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_SD2_DATA2__USBH3_H2_DM		(_MX51_PAD_SD2_DATA2__USBH3_H2_DM | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD2_DATA3__CSPI_SS2		(_MX51_PAD_SD2_DATA3__CSPI_SS2 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_SD2_DATA3__SD1_DAT7		(_MX51_PAD_SD2_DATA3__SD1_DAT7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD2_DATA3__SD2_DATA3		(_MX51_PAD_SD2_DATA3__SD2_DATA3 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
-#define MX51_PAD_GPIO1_2__CCM_OUT_2		(_MX51_PAD_GPIO1_2__CCM_OUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_2__GPIO1_2		(_MX51_PAD_GPIO1_2__GPIO1_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_2__I2C2_SCL		(_MX51_PAD_GPIO1_2__I2C2_SCL | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_GPIO1_2__PLL1_BYP		(_MX51_PAD_GPIO1_2__PLL1_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_2__PWM1_PWMO		(_MX51_PAD_GPIO1_2__PWM1_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_3__GPIO1_3		(_MX51_PAD_GPIO1_3__GPIO1_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_3__I2C2_SDA		(_MX51_PAD_GPIO1_3__I2C2_SDA | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
-#define MX51_PAD_GPIO1_3__PLL2_BYP		(_MX51_PAD_GPIO1_3__PLL2_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_3__PWM2_PWMO		(_MX51_PAD_GPIO1_3__PWM2_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ	(_MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_PMIC_INT_REQ__PMIC_PMU_IRQ_B	(_MX51_PAD_PMIC_INT_REQ__PMIC_PMU_IRQ_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_4__DISP2_EXT_CLK		(_MX51_PAD_GPIO1_4__DISP2_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_4__EIM_RDY		(_MX51_PAD_GPIO1_4__EIM_RDY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_4__GPIO1_4		(_MX51_PAD_GPIO1_4__GPIO1_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_4__WDOG1_WDOG_B		(_MX51_PAD_GPIO1_4__WDOG1_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_5__CSI2_MCLK		(_MX51_PAD_GPIO1_5__CSI2_MCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_5__DISP2_PIN16		(_MX51_PAD_GPIO1_5__DISP2_PIN16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_5__GPIO1_5		(_MX51_PAD_GPIO1_5__GPIO1_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_5__WDOG2_WDOG_B		(_MX51_PAD_GPIO1_5__WDOG2_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_6__DISP2_PIN17		(_MX51_PAD_GPIO1_6__DISP2_PIN17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_6__GPIO1_6		(_MX51_PAD_GPIO1_6__GPIO1_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_6__REF_EN_B		(_MX51_PAD_GPIO1_6__REF_EN_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_7__CCM_OUT_0		(_MX51_PAD_GPIO1_7__CCM_OUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_7__GPIO1_7		(_MX51_PAD_GPIO1_7__GPIO1_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_7__SD2_WP		(_MX51_PAD_GPIO1_7__SD2_WP | MUX_PAD_CTRL(MX51_ESDHC_PAD_CTRL))
-#define MX51_PAD_GPIO1_7__SPDIF_OUT1		(_MX51_PAD_GPIO1_7__SPDIF_OUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_8__CSI2_DATA_EN		(_MX51_PAD_GPIO1_8__CSI2_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_8__GPIO1_8		(_MX51_PAD_GPIO1_8__GPIO1_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_8__SD2_CD		(_MX51_PAD_GPIO1_8__SD2_CD | MUX_PAD_CTRL(MX51_ESDHC_PAD_CTRL))
-#define MX51_PAD_GPIO1_8__USBH3_PWR		(_MX51_PAD_GPIO1_8__USBH3_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_9__CCM_OUT_1		(_MX51_PAD_GPIO1_9__CCM_OUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_9__DISP2_D1_CS		(_MX51_PAD_GPIO1_9__DISP2_D1_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_9__DISP2_SER_CS		(_MX51_PAD_GPIO1_9__DISP2_SER_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_9__GPIO1_9		(_MX51_PAD_GPIO1_9__GPIO1_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_9__SD2_LCTL		(_MX51_PAD_GPIO1_9__SD2_LCTL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_GPIO1_9__USBH3_OC		(_MX51_PAD_GPIO1_9__USBH3_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_EIM_EB2__GPIO2_22		IOMUX_PAD(0x468, 0x0d4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_EB2__GPT_CMPOUT1		IOMUX_PAD(0x468, 0x0d4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__AUD5_RXC		IOMUX_PAD(0x46c, 0x0d8, 6, 0x8dc, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__CSI1_D3		IOMUX_PAD(0x46c, 0x0d8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__EIM_EB3		IOMUX_PAD(0x46c, 0x0d8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__FEC_RDATA1		IOMUX_PAD(0x46c, 0x0d8, 3, 0x95c, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__GPIO2_23		IOMUX_PAD(0x46c, 0x0d8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_EB3__GPT_CMPOUT2		IOMUX_PAD(0x46c, 0x0d8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_OE__EIM_OE			IOMUX_PAD(0x470, 0x0dc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_OE__GPIO2_24		IOMUX_PAD(0x470, 0x0dc, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS0__EIM_CS0		IOMUX_PAD(0x474, 0x0e0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS0__GPIO2_25		IOMUX_PAD(0x474, 0x0e0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS1__EIM_CS1		IOMUX_PAD(0x478, 0x0e4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS1__GPIO2_26		IOMUX_PAD(0x478, 0x0e4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__AUD5_TXD		IOMUX_PAD(0x47c, 0x0e8, 6, 0x8d8, 1, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__CSI1_D4		IOMUX_PAD(0x47c, 0x0e8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__EIM_CS2		IOMUX_PAD(0x47c, 0x0e8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__FEC_RDATA2		IOMUX_PAD(0x47c, 0x0e8, 3, 0x960, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__GPIO2_27		IOMUX_PAD(0x47c, 0x0e8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS2__USBOTG_STP		IOMUX_PAD(0x47c, 0x0e8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__AUD5_RXD		IOMUX_PAD(0x480, 0x0ec, 6, 0x8d4, 1, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__CSI1_D5		IOMUX_PAD(0x480, 0x0ec, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__EIM_CS3		IOMUX_PAD(0x480, 0x0ec, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__FEC_RDATA3		IOMUX_PAD(0x480, 0x0ec, 3, 0x964, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__GPIO2_28		IOMUX_PAD(0x480, 0x0ec, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS3__USBOTG_NXT		IOMUX_PAD(0x480, 0x0ec, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS4__AUD5_TXC		IOMUX_PAD(0x484, 0x0f0, 6, 0x8e4, 1, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS4__CSI1_D6		IOMUX_PAD(0x484, 0x0f0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS4__EIM_CS4		IOMUX_PAD(0x484, 0x0f0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS4__FEC_RX_ER		IOMUX_PAD(0x484, 0x0f0, 3, 0x970, 0, MX51_PAD_CTRL_2)
+#define MX51_PAD_EIM_CS4__GPIO2_29		IOMUX_PAD(0x484, 0x0f0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS4__USBOTG_CLK		IOMUX_PAD(0x484, 0x0f0, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__AUD5_TXFS		IOMUX_PAD(0x488, 0x0f4, 6, 0x8e8, 1, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__CSI1_D7		IOMUX_PAD(0x488, 0x0f4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__DISP1_EXT_CLK		IOMUX_PAD(0x488, 0x0f4, 4, 0x904, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__EIM_CS5		IOMUX_PAD(0x488, 0x0f4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__FEC_CRS		IOMUX_PAD(0x488, 0x0f4, 3, 0x950, 0, MX51_PAD_CTRL_2)
+#define MX51_PAD_EIM_CS5__GPIO2_30		IOMUX_PAD(0x488, 0x0f4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CS5__USBOTG_DIR		IOMUX_PAD(0x488, 0x0f4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DTACK__EIM_DTACK		IOMUX_PAD(0x48c, 0x0f8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DTACK__GPIO2_31		IOMUX_PAD(0x48c, 0x0f8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_LBA__EIM_LBA		IOMUX_PAD(0x494, 0x0fc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_LBA__GPIO3_1		IOMUX_PAD(0x494, 0x0fc, 1, 0x978, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_EIM_CRE__EIM_CRE		IOMUX_PAD(0x4a0, 0x100, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_CRE__GPIO3_2		IOMUX_PAD(0x4a0, 0x100, 1, 0x97c, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DRAM_CS1__DRAM_CS1		IOMUX_PAD(0x4d0, 0x104, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_WE_B__GPIO3_3		IOMUX_PAD(0x4e4, 0x108, 3, 0x980, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_WE_B__NANDF_WE_B		IOMUX_PAD(0x4e4, 0x108, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_WE_B__PATA_DIOW		IOMUX_PAD(0x4e4, 0x108, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_WE_B__SD3_DATA0		IOMUX_PAD(0x4e4, 0x108, 2, 0x93c, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_RE_B__GPIO3_4		IOMUX_PAD(0x4e8, 0x10c, 3, 0x984, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_RE_B__NANDF_RE_B		IOMUX_PAD(0x4e8, 0x10c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RE_B__PATA_DIOR		IOMUX_PAD(0x4e8, 0x10c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RE_B__SD3_DATA1		IOMUX_PAD(0x4e8, 0x10c, 2, 0x940, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_ALE__GPIO3_5		IOMUX_PAD(0x4ec, 0x110, 3, 0x988, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_ALE__NANDF_ALE		IOMUX_PAD(0x4ec, 0x110, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_ALE__PATA_BUFFER_EN	IOMUX_PAD(0x4ec, 0x110, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CLE__GPIO3_6		IOMUX_PAD(0x4f0, 0x114, 3, 0x98c, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CLE__NANDF_CLE		IOMUX_PAD(0x4f0, 0x114, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CLE__PATA_RESET_B	IOMUX_PAD(0x4f0, 0x114, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_WP_B__GPIO3_7		IOMUX_PAD(0x4f4, 0x118, 3, 0x990, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_WP_B__NANDF_WP_B		IOMUX_PAD(0x4f4, 0x118, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_WP_B__PATA_DMACK		IOMUX_PAD(0x4f4, 0x118, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_WP_B__SD3_DATA2		IOMUX_PAD(0x4f4, 0x118, 2, 0x944, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB0__ECSPI2_SS1		IOMUX_PAD(0x4f8, 0x11c, 5, 0x930, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB0__GPIO3_8		IOMUX_PAD(0x4f8, 0x11c, 3, 0x994, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB0__NANDF_RB0		IOMUX_PAD(0x4f8, 0x11c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB0__PATA_DMARQ		IOMUX_PAD(0x4f8, 0x11c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB0__SD3_DATA3		IOMUX_PAD(0x4f8, 0x11c, 2, 0x948, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__CSPI_MOSI		IOMUX_PAD(0x4fc, 0x120, 6, 0x91c, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__ECSPI2_RDY		IOMUX_PAD(0x4fc, 0x120, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__GPIO3_9		IOMUX_PAD(0x4fc, 0x120, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__NANDF_RB1		IOMUX_PAD(0x4fc, 0x120, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__PATA_IORDY		IOMUX_PAD(0x4fc, 0x120, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__SD4_CMD		IOMUX_PAD(0x4fc, 0x120, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__DISP2_WAIT		IOMUX_PAD(0x500, 0x124, 5, 0x9a8, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__ECSPI2_SCLK		IOMUX_PAD(0x500, 0x124, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__FEC_COL		IOMUX_PAD(0x500, 0x124, 1, 0x94c, 0, MX51_PAD_CTRL_2)
+#define MX51_PAD_NANDF_RB2__GPIO3_10		IOMUX_PAD(0x500, 0x124, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__NANDF_RB2		IOMUX_PAD(0x500, 0x124, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__USBH3_H3_DP		IOMUX_PAD(0x500, 0x124, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__USBH3_NXT		IOMUX_PAD(0x500, 0x124, 6, 0xa20, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__DISP1_WAIT		IOMUX_PAD(0x504, 0x128, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__ECSPI2_MISO		IOMUX_PAD(0x504, 0x128, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__FEC_RX_CLK		IOMUX_PAD(0x504, 0x128, 1, 0x968, 0, MX51_PAD_CTRL_2)
+#define MX51_PAD_NANDF_RB3__GPIO3_11		IOMUX_PAD(0x504, 0x128, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__NANDF_RB3		IOMUX_PAD(0x504, 0x128, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__USBH3_CLK		IOMUX_PAD(0x504, 0x128, 6, 0x9f8, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB3__USBH3_H3_DM		IOMUX_PAD(0x504, 0x128, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_NAND__GPIO_NAND		IOMUX_PAD(0x514, 0x12c, 0, 0x998, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_GPIO_NAND__PATA_INTRQ		IOMUX_PAD(0x514, 0x12c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS0__GPIO3_16		IOMUX_PAD(0x518, 0x130, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS0__NANDF_CS0		IOMUX_PAD(0x518, 0x130, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS1__GPIO3_17		IOMUX_PAD(0x51c, 0x134, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS1__NANDF_CS1		IOMUX_PAD(0x51c, 0x134, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS2__CSPI_SCLK		IOMUX_PAD(0x520, 0x138, 6, 0x914, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_CS2__FEC_TX_ER		IOMUX_PAD(0x520, 0x138, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_CS2__GPIO3_18		IOMUX_PAD(0x520, 0x138, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS2__NANDF_CS2		IOMUX_PAD(0x520, 0x138, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS2__PATA_CS_0		IOMUX_PAD(0x520, 0x138, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS2__SD4_CLK		IOMUX_PAD(0x520, 0x138, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
+#define MX51_PAD_NANDF_CS2__USBH3_H1_DP		IOMUX_PAD(0x520, 0x138, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS3__FEC_MDC		IOMUX_PAD(0x524, 0x13c, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_CS3__GPIO3_19		IOMUX_PAD(0x524, 0x13c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS3__NANDF_CS3		IOMUX_PAD(0x524, 0x13c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS3__PATA_CS_1		IOMUX_PAD(0x524, 0x13c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS3__SD4_DAT0		IOMUX_PAD(0x524, 0x13c, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_CS3__USBH3_H1_DM		IOMUX_PAD(0x524, 0x13c, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS4__FEC_TDATA1		IOMUX_PAD(0x528, 0x140, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_CS4__GPIO3_20		IOMUX_PAD(0x528, 0x140, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS4__NANDF_CS4		IOMUX_PAD(0x528, 0x140, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS4__PATA_DA_0		IOMUX_PAD(0x528, 0x140, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS4__SD4_DAT1		IOMUX_PAD(0x528, 0x140, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_CS4__USBH3_STP		IOMUX_PAD(0x528, 0x140, 7, 0xa24, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS5__FEC_TDATA2		IOMUX_PAD(0x52c, 0x144, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_CS5__GPIO3_21		IOMUX_PAD(0x52c, 0x144, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS5__NANDF_CS5		IOMUX_PAD(0x52c, 0x144, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS5__PATA_DA_1		IOMUX_PAD(0x52c, 0x144, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS5__SD4_DAT2		IOMUX_PAD(0x52c, 0x144, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_CS5__USBH3_DIR		IOMUX_PAD(0x52c, 0x144, 7, 0xa1c, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS6__CSPI_SS3		IOMUX_PAD(0x530, 0x148, 7, 0x928, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_CS6__FEC_TDATA3		IOMUX_PAD(0x530, 0x148, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_CS6__GPIO3_22		IOMUX_PAD(0x530, 0x148, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS6__NANDF_CS6		IOMUX_PAD(0x530, 0x148, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS6__PATA_DA_2		IOMUX_PAD(0x530, 0x148, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS6__SD4_DAT3		IOMUX_PAD(0x530, 0x148, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_CS7__FEC_TX_EN		IOMUX_PAD(0x534, 0x14c, 1, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_CS7__GPIO3_23		IOMUX_PAD(0x534, 0x14c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS7__NANDF_CS7		IOMUX_PAD(0x534, 0x14c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_CS7__SD3_CLK		IOMUX_PAD(0x534, 0x14c, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
+#define MX51_PAD_NANDF_RDY_INT__ECSPI2_SS0	IOMUX_PAD(0x538, 0x150, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK	IOMUX_PAD(0x538, 0x150, 1, 0x974, 0, MX51_PAD_CTRL_4)
+#define MX51_PAD_NANDF_RDY_INT__GPIO3_24	IOMUX_PAD(0x538, 0x150, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_RDY_INT__NANDF_RDY_INT	IOMUX_PAD(0x538, 0x150, 0, 0x938, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RDY_INT__SD3_CMD		IOMUX_PAD(0x538, 0x150, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_NANDF_D15__ECSPI2_MOSI		IOMUX_PAD(0x53c, 0x154, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_D15__GPIO3_25		IOMUX_PAD(0x53c, 0x154, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D15__NANDF_D15		IOMUX_PAD(0x53c, 0x154, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D15__PATA_DATA15		IOMUX_PAD(0x53c, 0x154, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D15__SD3_DAT7		IOMUX_PAD(0x53c, 0x154, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D14__ECSPI2_SS3		IOMUX_PAD(0x540, 0x158, 2, 0x934, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_D14__GPIO3_26		IOMUX_PAD(0x540, 0x158, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D14__NANDF_D14		IOMUX_PAD(0x540, 0x158, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D14__PATA_DATA14		IOMUX_PAD(0x540, 0x158, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D14__SD3_DAT6		IOMUX_PAD(0x540, 0x158, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D13__ECSPI2_SS2		IOMUX_PAD(0x544, 0x15c, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_D13__GPIO3_27		IOMUX_PAD(0x544, 0x15c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D13__NANDF_D13		IOMUX_PAD(0x544, 0x15c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D13__PATA_DATA13		IOMUX_PAD(0x544, 0x15c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D13__SD3_DAT5		IOMUX_PAD(0x544, 0x15c, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D12__ECSPI2_SS1		IOMUX_PAD(0x548, 0x160, 2, 0x930, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_NANDF_D12__GPIO3_28		IOMUX_PAD(0x548, 0x160, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D12__NANDF_D12		IOMUX_PAD(0x548, 0x160, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D12__PATA_DATA12		IOMUX_PAD(0x548, 0x160, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D12__SD3_DAT4		IOMUX_PAD(0x548, 0x160, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D11__FEC_RX_DV		IOMUX_PAD(0x54c, 0x164, 2, 0x96c, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D11__GPIO3_29		IOMUX_PAD(0x54c, 0x164, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D11__NANDF_D11		IOMUX_PAD(0x54c, 0x164, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D11__PATA_DATA11		IOMUX_PAD(0x54c, 0x164, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D11__SD3_DATA3		IOMUX_PAD(0x54c, 0x164, 5, 0x948, 1, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D10__GPIO3_30		IOMUX_PAD(0x550, 0x168, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D10__NANDF_D10		IOMUX_PAD(0x550, 0x168, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D10__PATA_DATA10		IOMUX_PAD(0x550, 0x168, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D10__SD3_DATA2		IOMUX_PAD(0x550, 0x168, 5, 0x944, 1, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D9__FEC_RDATA0		IOMUX_PAD(0x554, 0x16c, 0x12, 0x958, 0, MX51_PAD_CTRL_4)
+#define MX51_PAD_NANDF_D9__GPIO3_31		IOMUX_PAD(0x554, 0x16c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D9__NANDF_D9		IOMUX_PAD(0x554, 0x16c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D9__PATA_DATA9		IOMUX_PAD(0x554, 0x16c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D9__SD3_DATA1		IOMUX_PAD(0x554, 0x16c, 5, 0x940, 1, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D8__FEC_TDATA0		IOMUX_PAD(0x558, 0x170, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_NANDF_D8__GPIO4_0		IOMUX_PAD(0x558, 0x170, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D8__NANDF_D8		IOMUX_PAD(0x558, 0x170, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D8__PATA_DATA8		IOMUX_PAD(0x558, 0x170, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D8__SD3_DATA0		IOMUX_PAD(0x558, 0x170, 5, 0x93c, 1, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D7__GPIO4_1		IOMUX_PAD(0x55c, 0x174, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D7__NANDF_D7		IOMUX_PAD(0x55c, 0x174, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D7__PATA_DATA7		IOMUX_PAD(0x55c, 0x174, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D7__USBH3_DATA0		IOMUX_PAD(0x55c, 0x174, 5, 0x9fc, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D6__GPIO4_2		IOMUX_PAD(0x560, 0x178, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D6__NANDF_D6		IOMUX_PAD(0x560, 0x178, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D6__PATA_DATA6		IOMUX_PAD(0x560, 0x178, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D6__SD4_LCTL		IOMUX_PAD(0x560, 0x178, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D6__USBH3_DATA1		IOMUX_PAD(0x560, 0x178, 5, 0xa00, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D5__GPIO4_3		IOMUX_PAD(0x564, 0x17c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D5__NANDF_D5		IOMUX_PAD(0x564, 0x17c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D5__PATA_DATA5		IOMUX_PAD(0x564, 0x17c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D5__SD4_WP		IOMUX_PAD(0x564, 0x17c, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D5__USBH3_DATA2		IOMUX_PAD(0x564, 0x17c, 5, 0xa04, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D4__GPIO4_4		IOMUX_PAD(0x568, 0x180, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D4__NANDF_D4		IOMUX_PAD(0x568, 0x180, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D4__PATA_DATA4		IOMUX_PAD(0x568, 0x180, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D4__SD4_CD		IOMUX_PAD(0x568, 0x180, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D4__USBH3_DATA3		IOMUX_PAD(0x568, 0x180, 5, 0xa08, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D3__GPIO4_5		IOMUX_PAD(0x56c, 0x184, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D3__NANDF_D3		IOMUX_PAD(0x56c, 0x184, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D3__PATA_DATA3		IOMUX_PAD(0x56c, 0x184, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D3__SD4_DAT4		IOMUX_PAD(0x56c, 0x184, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D3__USBH3_DATA4		IOMUX_PAD(0x56c, 0x184, 5, 0xa0c, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D2__GPIO4_6		IOMUX_PAD(0x570, 0x188, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D2__NANDF_D2		IOMUX_PAD(0x570, 0x188, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D2__PATA_DATA2		IOMUX_PAD(0x570, 0x188, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D2__SD4_DAT5		IOMUX_PAD(0x570, 0x188, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D2__USBH3_DATA5		IOMUX_PAD(0x570, 0x188, 5, 0xa10, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D1__GPIO4_7		IOMUX_PAD(0x574, 0x18c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D1__NANDF_D1		IOMUX_PAD(0x574, 0x18c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D1__PATA_DATA1		IOMUX_PAD(0x574, 0x18c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D1__SD4_DAT6		IOMUX_PAD(0x574, 0x18c, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D1__USBH3_DATA6		IOMUX_PAD(0x574, 0x18c, 5, 0xa14, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D0__GPIO4_8		IOMUX_PAD(0x578, 0x190, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_NANDF_D0__NANDF_D0		IOMUX_PAD(0x578, 0x190, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D0__PATA_DATA0		IOMUX_PAD(0x578, 0x190, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D0__SD4_DAT7		IOMUX_PAD(0x578, 0x190, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_D0__USBH3_DATA7		IOMUX_PAD(0x578, 0x190, 5, 0xa18, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D8__CSI1_D8		IOMUX_PAD(0x57c, 0x194, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D8__GPIO3_12		IOMUX_PAD(0x57c, 0x194, 3, 0x998, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI1_D9__CSI1_D9		IOMUX_PAD(0x580, 0x198, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D9__GPIO3_13		IOMUX_PAD(0x580, 0x198, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI1_D10__CSI1_D10		IOMUX_PAD(0x584, 0x19c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D11__CSI1_D11		IOMUX_PAD(0x588, 0x1a0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D12__CSI1_D12		IOMUX_PAD(0x58c, 0x1a4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D13__CSI1_D13		IOMUX_PAD(0x590, 0x1a8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D14__CSI1_D14		IOMUX_PAD(0x594, 0x1ac, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D15__CSI1_D15		IOMUX_PAD(0x598, 0x1b0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D16__CSI1_D16		IOMUX_PAD(0x59c, 0x1b4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D17__CSI1_D17		IOMUX_PAD(0x5a0, 0x1b8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D18__CSI1_D18		IOMUX_PAD(0x5a4, 0x1bc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_D19__CSI1_D19		IOMUX_PAD(0x5a8, 0x1c0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_VSYNC__CSI1_VSYNC		IOMUX_PAD(0x5ac, 0x1c4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_VSYNC__GPIO3_14		IOMUX_PAD(0x5ac, 0x1c4, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI1_HSYNC__CSI1_HSYNC		IOMUX_PAD(0x5b0, 0x1c8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_HSYNC__GPIO3_15		IOMUX_PAD(0x5b0, 0x1c8, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI1_PIXCLK__CSI1_PIXCLK	IOMUX_PAD(0x5b4, __NA_, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_MCLK__CSI1_MCLK		IOMUX_PAD(0x5b8, __NA_, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D12__CSI2_D12		IOMUX_PAD(0x5bc, 0x1cc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D12__GPIO4_9		IOMUX_PAD(0x5bc, 0x1cc, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI2_D13__CSI2_D13		IOMUX_PAD(0x5c0, 0x1d0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D13__GPIO4_10		IOMUX_PAD(0x5c0, 0x1d0, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI2_D14__CSI2_D14		IOMUX_PAD(0x5c4, 0x1d4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D15__CSI2_D15		IOMUX_PAD(0x5c8, 0x1d8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D16__CSI2_D16		IOMUX_PAD(0x5cc, 0x1dc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D17__CSI2_D17		IOMUX_PAD(0x5d0, 0x1e0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D18__CSI2_D18		IOMUX_PAD(0x5d4, 0x1e4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D18__GPIO4_11		IOMUX_PAD(0x5d4, 0x1e4, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI2_D19__CSI2_D19		IOMUX_PAD(0x5d8, 0x1e8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_D19__GPIO4_12		IOMUX_PAD(0x5d8, 0x1e8, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI2_VSYNC__CSI2_VSYNC		IOMUX_PAD(0x5dc, 0x1ec, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_VSYNC__GPIO4_13		IOMUX_PAD(0x5dc, 0x1ec, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI2_HSYNC__CSI2_HSYNC		IOMUX_PAD(0x5e0, 0x1f0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_HSYNC__GPIO4_14		IOMUX_PAD(0x5e0, 0x1f0, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSI2_PIXCLK__CSI2_PIXCLK	IOMUX_PAD(0x5e4, 0x1f4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_PIXCLK__GPIO4_15		IOMUX_PAD(0x5e4, 0x1f4, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_I2C1_CLK__GPIO4_16		IOMUX_PAD(0x5e8, 0x1f8, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_I2C1_CLK__I2C1_CLK		IOMUX_PAD(0x5e8, 0x1f8, 0x10, __NA_, 0, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_I2C1_DAT__GPIO4_17		IOMUX_PAD(0x5ec, 0x1fc, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_I2C1_DAT__I2C1_DAT		IOMUX_PAD(0x5ec, 0x1fc, 0x10, __NA_, 0, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_TXD__AUD3_TXD		IOMUX_PAD(0x5f0, 0x200, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_TXD__GPIO4_18		IOMUX_PAD(0x5f0, 0x200, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_RXD__AUD3_RXD		IOMUX_PAD(0x5f4, 0x204, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_RXD__GPIO4_19		IOMUX_PAD(0x5f4, 0x204, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_RXD__UART3_RXD		IOMUX_PAD(0x5f4, 0x204, 1, 0x9f4, 2, MX51_UART_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_CK__AUD3_TXC		IOMUX_PAD(0x5f8, 0x208, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_CK__GPIO4_20		IOMUX_PAD(0x5f8, 0x208, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_FS__AUD3_TXFS		IOMUX_PAD(0x5fc, 0x20c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_FS__GPIO4_21		IOMUX_PAD(0x5fc, 0x20c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_AUD3_BB_FS__UART3_TXD		IOMUX_PAD(0x5fc, 0x20c, 1, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI	IOMUX_PAD(0x600, 0x210, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_CSPI1_MOSI__GPIO4_22		IOMUX_PAD(0x600, 0x210, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSPI1_MOSI__I2C1_SDA		IOMUX_PAD(0x600, 0x210, 0x11, 0x9b4, 1, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_CSPI1_MISO__AUD4_RXD		IOMUX_PAD(0x604, 0x214, 1, 0x8c4, 1, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_MISO__ECSPI1_MISO	IOMUX_PAD(0x604, 0x214, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_CSPI1_MISO__GPIO4_23		IOMUX_PAD(0x604, 0x214, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS0__AUD4_TXC		IOMUX_PAD(0x608, 0x218, 1, 0x8cc, 1, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS0__ECSPI1_SS0		IOMUX_PAD(0x608, 0x218, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS0__GPIO4_24		IOMUX_PAD(0x608, 0x218, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS1__AUD4_TXD		IOMUX_PAD(0x60c, 0x21c, 1, 0x8c8, 1, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS1__ECSPI1_SS1		IOMUX_PAD(0x60c, 0x21c, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_CSPI1_SS1__GPIO4_25		IOMUX_PAD(0x60c, 0x21c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSPI1_RDY__AUD4_TXFS		IOMUX_PAD(0x610, 0x220, 1, 0x8d0, 1, NO_PAD_CTRL)
+#define MX51_PAD_CSPI1_RDY__ECSPI1_RDY		IOMUX_PAD(0x610, 0x220, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_CSPI1_RDY__GPIO4_26		IOMUX_PAD(0x610, 0x220, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK	IOMUX_PAD(0x614, 0x224, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_CSPI1_SCLK__GPIO4_27		IOMUX_PAD(0x614, 0x224, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_CSPI1_SCLK__I2C1_SCL		IOMUX_PAD(0x614, 0x224, 0x11, 0x9b0, 1, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_UART1_RXD__GPIO4_28		IOMUX_PAD(0x618, 0x228, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART1_RXD__UART1_RXD		IOMUX_PAD(0x618, 0x228, 0, 0x9e4, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART1_TXD__GPIO4_29		IOMUX_PAD(0x61c, 0x22c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART1_TXD__PWM2_PWMO		IOMUX_PAD(0x61c, 0x22c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_UART1_TXD__UART1_TXD		IOMUX_PAD(0x61c, 0x22c, 0, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART1_RTS__GPIO4_30		IOMUX_PAD(0x620, 0x230, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART1_RTS__UART1_RTS		IOMUX_PAD(0x620, 0x230, 0, 0x9e0, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART1_CTS__GPIO4_31		IOMUX_PAD(0x624, 0x234, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART1_CTS__UART1_CTS		IOMUX_PAD(0x624, 0x234, 0, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART2_RXD__FIRI_TXD		IOMUX_PAD(0x628, 0x238, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_UART2_RXD__GPIO1_20		IOMUX_PAD(0x628, 0x238, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART2_RXD__UART2_RXD		IOMUX_PAD(0x628, 0x238, 0, 0x9ec, 2, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART2_TXD__FIRI_RXD		IOMUX_PAD(0x62c, 0x23c, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_UART2_TXD__GPIO1_21		IOMUX_PAD(0x62c, 0x23c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART2_TXD__UART2_TXD		IOMUX_PAD(0x62c, 0x23c, 0, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART3_RXD__CSI1_D0		IOMUX_PAD(0x630, 0x240, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_UART3_RXD__GPIO1_22		IOMUX_PAD(0x630, 0x240, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART3_RXD__UART1_DTR		IOMUX_PAD(0x630, 0x240, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_UART3_RXD__UART3_RXD		IOMUX_PAD(0x630, 0x240, 1, 0x9f4, 4, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART3_TXD__CSI1_D1		IOMUX_PAD(0x634, 0x244, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_UART3_TXD__GPIO1_23		IOMUX_PAD(0x634, 0x244, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_UART3_TXD__UART1_DSR		IOMUX_PAD(0x634, 0x244, 0, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_UART3_TXD__UART3_TXD		IOMUX_PAD(0x634, 0x244, 1, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_OWIRE_LINE__GPIO1_24		IOMUX_PAD(0x638, 0x248, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_OWIRE_LINE__OWIRE_LINE		IOMUX_PAD(0x638, 0x248, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_OWIRE_LINE__SPDIF_OUT		IOMUX_PAD(0x638, 0x248, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_ROW0__KEY_ROW0		IOMUX_PAD(0x63c, 0x24c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_ROW1__KEY_ROW1		IOMUX_PAD(0x640, 0x250, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_ROW2__KEY_ROW2		IOMUX_PAD(0x644, 0x254, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_ROW3__KEY_ROW3		IOMUX_PAD(0x648, 0x258, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL0__KEY_COL0		IOMUX_PAD(0x64c, 0x25c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL0__PLL1_BYP		IOMUX_PAD(0x64c, 0x25c, 7, 0x90c, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL1__KEY_COL1		IOMUX_PAD(0x650, 0x260, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL1__PLL2_BYP		IOMUX_PAD(0x650, 0x260, 7, 0x910, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL2__KEY_COL2		IOMUX_PAD(0x654, 0x264, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL2__PLL3_BYP		IOMUX_PAD(0x654, 0x264, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL3__KEY_COL3		IOMUX_PAD(0x658, 0x268, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL4__I2C2_SCL		IOMUX_PAD(0x65c, 0x26c, 0x13, 0x9b8, 1, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_KEY_COL4__KEY_COL4		IOMUX_PAD(0x65c, 0x26c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL4__SPDIF_OUT1		IOMUX_PAD(0x65c, 0x26c, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL4__UART1_RI		IOMUX_PAD(0x65c, 0x26c, 1, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_KEY_COL4__UART3_RTS		IOMUX_PAD(0x65c, 0x26c, 2, 0x9f0, 4, MX51_UART_PAD_CTRL)
+#define MX51_PAD_KEY_COL5__I2C2_SDA		IOMUX_PAD(0x660, 0x270, 0x13, 0x9bc, 1, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_KEY_COL5__KEY_COL5		IOMUX_PAD(0x660, 0x270, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_KEY_COL5__UART1_DCD		IOMUX_PAD(0x660, 0x270, 1, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_KEY_COL5__UART3_CTS		IOMUX_PAD(0x660, 0x270, 2, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_CLK__CSPI_SCLK		IOMUX_PAD(0x678, 0x278, 1, 0x914, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_CLK__GPIO1_25		IOMUX_PAD(0x678, 0x278, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_CLK__I2C2_SCL		IOMUX_PAD(0x678, 0x278, 0x15, 0x9b8, 2, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_USBH1_CLK__USBH1_CLK		IOMUX_PAD(0x678, 0x278, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DIR__CSPI_MOSI		IOMUX_PAD(0x67c, 0x27c, 1, 0x91c, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_DIR__GPIO1_26		IOMUX_PAD(0x67c, 0x27c, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DIR__I2C2_SDA		IOMUX_PAD(0x67c, 0x27c, 0x15, 0x9bc, 2, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_USBH1_DIR__USBH1_DIR		IOMUX_PAD(0x67c, 0x27c, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_STP__CSPI_RDY		IOMUX_PAD(0x680, 0x280, 1, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_STP__GPIO1_27		IOMUX_PAD(0x680, 0x280, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_STP__UART3_RXD		IOMUX_PAD(0x680, 0x280, 5, 0x9f4, 6, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_STP__USBH1_STP		IOMUX_PAD(0x680, 0x280, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_NXT__CSPI_MISO		IOMUX_PAD(0x684, 0x284, 1, 0x918, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_NXT__GPIO1_28		IOMUX_PAD(0x684, 0x284, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_NXT__UART3_TXD		IOMUX_PAD(0x684, 0x284, 5, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_NXT__USBH1_NXT		IOMUX_PAD(0x684, 0x284, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA0__GPIO1_11		IOMUX_PAD(0x688, 0x288, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA0__UART2_CTS		IOMUX_PAD(0x688, 0x288, 1, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA0__USBH1_DATA0	IOMUX_PAD(0x688, 0x288, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA1__GPIO1_12		IOMUX_PAD(0x68c, 0x28c, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA1__UART2_RXD		IOMUX_PAD(0x68c, 0x28c, 1, 0x9ec, 4, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA1__USBH1_DATA1	IOMUX_PAD(0x68c, 0x28c, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA2__GPIO1_13		IOMUX_PAD(0x690, 0x290, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA2__UART2_TXD		IOMUX_PAD(0x690, 0x290, 1, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA2__USBH1_DATA2	IOMUX_PAD(0x690, 0x290, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA3__GPIO1_14		IOMUX_PAD(0x694, 0x294, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA3__UART2_RTS		IOMUX_PAD(0x694, 0x294, 1, 0x9e8, 5, MX51_UART_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA3__USBH1_DATA3	IOMUX_PAD(0x694, 0x294, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA4__CSPI_SS0		IOMUX_PAD(0x698, 0x298, 1, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA4__GPIO1_15		IOMUX_PAD(0x698, 0x298, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA4__USBH1_DATA4	IOMUX_PAD(0x698, 0x298, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA5__CSPI_SS1		IOMUX_PAD(0x69c, 0x29c, 1, 0x920, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA5__GPIO1_16		IOMUX_PAD(0x69c, 0x29c, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA5__USBH1_DATA5	IOMUX_PAD(0x69c, 0x29c, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA6__CSPI_SS3		IOMUX_PAD(0x6a0, 0x2a0, 1, 0x928, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA6__GPIO1_17		IOMUX_PAD(0x6a0, 0x2a0, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA6__USBH1_DATA6	IOMUX_PAD(0x6a0, 0x2a0, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA7__ECSPI1_SS3	IOMUX_PAD(0x6a4, 0x2a4, 1, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA7__ECSPI2_SS3	IOMUX_PAD(0x6a4, 0x2a4, 5, 0x934, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA7__GPIO1_18		IOMUX_PAD(0x6a4, 0x2a4, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_USBH1_DATA7__USBH1_DATA7	IOMUX_PAD(0x6a4, 0x2a4, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
+#define MX51_PAD_DI1_PIN11__DI1_PIN11		IOMUX_PAD(0x6a8, 0x2a8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN11__ECSPI1_SS2		IOMUX_PAD(0x6a8, 0x2a8, 7, __NA_, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_DI1_PIN11__GPIO3_0		IOMUX_PAD(0x6a8, 0x2a8, 4, __NA_, 0, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN12__DI1_PIN12		IOMUX_PAD(0x6ac, 0x2ac, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN12__GPIO3_1		IOMUX_PAD(0x6ac, 0x2ac, 4, 0x978, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN13__DI1_PIN13		IOMUX_PAD(0x6b0, 0x2b0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN13__GPIO3_2		IOMUX_PAD(0x6b0, 0x2b0, 4, 0x97c, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DI1_D0_CS__DI1_D0_CS		IOMUX_PAD(0x6b4, 0x2b4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_D0_CS__GPIO3_3		IOMUX_PAD(0x6b4, 0x2b4, 4, 0x980, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DI1_D1_CS__DI1_D1_CS		IOMUX_PAD(0x6b8, 0x2b8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_D1_CS__DISP1_PIN14		IOMUX_PAD(0x6b8, 0x2b8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_D1_CS__DISP1_PIN5		IOMUX_PAD(0x6b8, 0x2b8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_D1_CS__GPIO3_4		IOMUX_PAD(0x6b8, 0x2b8, 4, 0x984, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIN__DISP1_PIN1	IOMUX_PAD(0x6bc, 0x2bc, 2, 0x9a4, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIN__DISPB2_SER_DIN	IOMUX_PAD(0x6bc, 0x2bc, 0, 0x9c4, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIN__GPIO3_5	IOMUX_PAD(0x6bc, 0x2bc, 4, 0x988, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIO__DISP1_PIN6	IOMUX_PAD(0x6c0, 0x2c0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIO__DISPB2_SER_DIO	IOMUX_PAD(0x6c0, 0x2c0, 0, 0x9c4, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_DIO__GPIO3_6	IOMUX_PAD(0x6c0, 0x2c0, 4, 0x98c, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_CLK__DISP1_PIN17	IOMUX_PAD(0x6c4, 0x2c4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_CLK__DISP1_PIN7	IOMUX_PAD(0x6c4, 0x2c4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_CLK__DISPB2_SER_CLK	IOMUX_PAD(0x6c4, 0x2c4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_CLK__GPIO3_7	IOMUX_PAD(0x6c4, 0x2c4, 4, 0x990, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__DISP1_EXT_CLK	IOMUX_PAD(0x6c8, 0x2c8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__DISP1_PIN16	IOMUX_PAD(0x6c8, 0x2c8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__DISP1_PIN8	IOMUX_PAD(0x6c8, 0x2c8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS	IOMUX_PAD(0x6c8, 0x2c8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS	IOMUX_PAD(0x6c8, 0x2c8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISPB2_SER_RS__GPIO3_8		IOMUX_PAD(0x6c8, 0x2c8, 4, 0x994, 1, MX51_GPIO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT0__DISP1_DAT0		IOMUX_PAD(0x6cc, 0x2cc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT1__DISP1_DAT1		IOMUX_PAD(0x6d0, 0x2d0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT2__DISP1_DAT2		IOMUX_PAD(0x6d4, 0x2d4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT3__DISP1_DAT3		IOMUX_PAD(0x6d8, 0x2d8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT4__DISP1_DAT4		IOMUX_PAD(0x6dc, 0x2dc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT5__DISP1_DAT5		IOMUX_PAD(0x6e0, 0x2e0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT6__BOOT_USB_SRC	IOMUX_PAD(0x6e4, 0x2e4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT6__DISP1_DAT6		IOMUX_PAD(0x6e4, 0x2e4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT7__BOOT_EEPROM_CFG	IOMUX_PAD(0x6e8, 0x2e8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT7__DISP1_DAT7		IOMUX_PAD(0x6e8, 0x2e8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT8__BOOT_SRC0		IOMUX_PAD(0x6ec, 0x2ec, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT8__DISP1_DAT8		IOMUX_PAD(0x6ec, 0x2ec, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT9__BOOT_SRC1		IOMUX_PAD(0x6f0, 0x2f0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT9__DISP1_DAT9		IOMUX_PAD(0x6f0, 0x2f0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT10__BOOT_SPARE_SIZE	IOMUX_PAD(0x6f4, 0x2f4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT10__DISP1_DAT10	IOMUX_PAD(0x6f4, 0x2f4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT11__BOOT_LPB_FREQ2	IOMUX_PAD(0x6f8, 0x2f8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT11__DISP1_DAT11	IOMUX_PAD(0x6f8, 0x2f8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT12__BOOT_MLC_SEL	IOMUX_PAD(0x6fc, 0x2fc, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT12__DISP1_DAT12	IOMUX_PAD(0x6fc, 0x2fc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT13__BOOT_MEM_CTL0	IOMUX_PAD(0x700, 0x300, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT13__DISP1_DAT13	IOMUX_PAD(0x700, 0x300, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT14__BOOT_MEM_CTL1	IOMUX_PAD(0x704, 0x304, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT14__DISP1_DAT14	IOMUX_PAD(0x704, 0x304, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT15__BOOT_BUS_WIDTH	IOMUX_PAD(0x708, 0x308, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT15__DISP1_DAT15	IOMUX_PAD(0x708, 0x308, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT16__BOOT_PAGE_SIZE0	IOMUX_PAD(0x70c, 0x30c, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT16__DISP1_DAT16	IOMUX_PAD(0x70c, 0x30c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT17__BOOT_PAGE_SIZE1	IOMUX_PAD(0x710, 0x310, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT17__DISP1_DAT17	IOMUX_PAD(0x710, 0x310, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT18__BOOT_WEIM_MUXED0	IOMUX_PAD(0x714, 0x314, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT18__DISP1_DAT18	IOMUX_PAD(0x714, 0x314, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT18__DISP2_PIN11	IOMUX_PAD(0x714, 0x314, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT18__DISP2_PIN5	IOMUX_PAD(0x714, 0x314, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT19__BOOT_WEIM_MUXED1	IOMUX_PAD(0x718, 0x318, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT19__DISP1_DAT19	IOMUX_PAD(0x718, 0x318, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT19__DISP2_PIN12	IOMUX_PAD(0x718, 0x318, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT19__DISP2_PIN6	IOMUX_PAD(0x718, 0x318, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT20__BOOT_MEM_TYPE0	IOMUX_PAD(0x71c, 0x31c, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT20__DISP1_DAT20	IOMUX_PAD(0x71c, 0x31c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT20__DISP2_PIN13	IOMUX_PAD(0x71c, 0x31c, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT20__DISP2_PIN7	IOMUX_PAD(0x71c, 0x31c, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT21__BOOT_MEM_TYPE1	IOMUX_PAD(0x720, 0x320, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT21__DISP1_DAT21	IOMUX_PAD(0x720, 0x320, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT21__DISP2_PIN14	IOMUX_PAD(0x720, 0x320, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT21__DISP2_PIN8	IOMUX_PAD(0x720, 0x320, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT22__BOOT_LPB_FREQ0	IOMUX_PAD(0x724, 0x324, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT22__DISP1_DAT22	IOMUX_PAD(0x724, 0x324, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT22__DISP2_D0_CS	IOMUX_PAD(0x724, 0x324, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT22__DISP2_DAT16	IOMUX_PAD(0x724, 0x324, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT23__BOOT_LPB_FREQ1	IOMUX_PAD(0x728, 0x328, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT23__DISP1_DAT23	IOMUX_PAD(0x728, 0x328, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT23__DISP2_D1_CS	IOMUX_PAD(0x728, 0x328, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT23__DISP2_DAT17	IOMUX_PAD(0x728, 0x328, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP1_DAT23__DISP2_SER_CS	IOMUX_PAD(0x728, 0x328, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN3__DI1_PIN3		IOMUX_PAD(0x72c, 0x32c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN2__DI1_PIN2		IOMUX_PAD(0x734, 0x330, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP2__DISP1_SER_CLK		IOMUX_PAD(0x740, 0x338, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP2__DISP2_WAIT		IOMUX_PAD(0x740, 0x338, 2, 0x9a8, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP3__CSI1_DATA_EN		IOMUX_PAD(0x744, 0x33c, 3, 0x9a0, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP3__DISP1_SER_DIO		IOMUX_PAD(0x744, 0x33c, 0, 0x9c0, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP3__FEC_TX_ER		IOMUX_PAD(0x744, 0x33c, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DI2_PIN4__CSI2_DATA_EN		IOMUX_PAD(0x748, 0x340, 3, 0x99c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI2_PIN4__DI2_PIN4		IOMUX_PAD(0x748, 0x340, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI2_PIN4__FEC_CRS		IOMUX_PAD(0x748, 0x340, 2, 0x950, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI2_PIN2__DI2_PIN2		IOMUX_PAD(0x74c, 0x344, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI2_PIN2__FEC_MDC		IOMUX_PAD(0x74c, 0x344, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DI2_PIN3__DI2_PIN3		IOMUX_PAD(0x750, 0x348, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI2_PIN3__FEC_MDIO		IOMUX_PAD(0x750, 0x348, 2, 0x954, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK	IOMUX_PAD(0x754, 0x34c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI2_DISP_CLK__FEC_RDATA1	IOMUX_PAD(0x754, 0x34c, 2, 0x95c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP4__DI2_PIN15		IOMUX_PAD(0x758, 0x350, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP4__DISP1_SER_DIN		IOMUX_PAD(0x758, 0x350, 0, 0x9c0, 1, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP4__DISP2_PIN1		IOMUX_PAD(0x758, 0x350, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI_GP4__FEC_RDATA2		IOMUX_PAD(0x758, 0x350, 2, 0x960, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT0__DISP2_DAT0		IOMUX_PAD(0x75c, 0x354, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT0__FEC_RDATA3		IOMUX_PAD(0x75c, 0x354, 2, 0x964, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT0__KEY_COL6		IOMUX_PAD(0x75c, 0x354, 4, 0x9c8, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT0__UART3_RXD		IOMUX_PAD(0x75c, 0x354, 5, 0x9f4, 8, MX51_UART_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT0__USBH3_CLK		IOMUX_PAD(0x75c, 0x354, 3, 0x9f8, 1, MX51_UART_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT1__DISP2_DAT1		IOMUX_PAD(0x760, 0x358, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT1__FEC_RX_ER		IOMUX_PAD(0x760, 0x358, 2, 0x970, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT1__KEY_COL7		IOMUX_PAD(0x760, 0x358, 4, 0x9cc, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT1__UART3_TXD		IOMUX_PAD(0x760, 0x358, 5, __NA_, 0, MX51_UART_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT1__USBH3_DIR		IOMUX_PAD(0x760, 0x358, 3, 0xa1c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT2__DISP2_DAT2		IOMUX_PAD(0x764, 0x35c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT3__DISP2_DAT3		IOMUX_PAD(0x768, 0x360, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT4__DISP2_DAT4		IOMUX_PAD(0x76c, 0x364, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT5__DISP2_DAT5		IOMUX_PAD(0x770, 0x368, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT6__DISP2_DAT6		IOMUX_PAD(0x774, 0x36c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT6__FEC_TDATA1		IOMUX_PAD(0x774, 0x36c, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DISP2_DAT6__GPIO1_19		IOMUX_PAD(0x774, 0x36c, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT6__KEY_ROW4		IOMUX_PAD(0x774, 0x36c, 4, 0x9d0, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT6__USBH3_STP		IOMUX_PAD(0x774, 0x36c, 3, 0xa24, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT7__DISP2_DAT7		IOMUX_PAD(0x778, 0x370, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT7__FEC_TDATA2		IOMUX_PAD(0x778, 0x370, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DISP2_DAT7__GPIO1_29		IOMUX_PAD(0x778, 0x370, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT7__KEY_ROW5		IOMUX_PAD(0x778, 0x370, 4, 0x9d4, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT7__USBH3_NXT		IOMUX_PAD(0x778, 0x370, 3, 0xa20, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT8__DISP2_DAT8		IOMUX_PAD(0x77c, 0x374, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT8__FEC_TDATA3		IOMUX_PAD(0x77c, 0x374, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DISP2_DAT8__GPIO1_30		IOMUX_PAD(0x77c, 0x374, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT8__KEY_ROW6		IOMUX_PAD(0x77c, 0x374, 4, 0x9d8, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT8__USBH3_DATA0	IOMUX_PAD(0x77c, 0x374, 3, 0x9fc, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT9__AUD6_RXC		IOMUX_PAD(0x780, 0x378, 4, 0x8f4, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT9__DISP2_DAT9		IOMUX_PAD(0x780, 0x378, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT9__FEC_TX_EN		IOMUX_PAD(0x780, 0x378, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DISP2_DAT9__GPIO1_31		IOMUX_PAD(0x780, 0x378, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT9__USBH3_DATA1	IOMUX_PAD(0x780, 0x378, 3, 0xa00, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT10__DISP2_DAT10	IOMUX_PAD(0x784, 0x37c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT10__DISP2_SER_CS	IOMUX_PAD(0x784, 0x37c, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT10__FEC_COL		IOMUX_PAD(0x784, 0x37c, 2, 0x94c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT10__KEY_ROW7		IOMUX_PAD(0x784, 0x37c, 4, 0x9dc, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT10__USBH3_DATA2	IOMUX_PAD(0x784, 0x37c, 3, 0xa04, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT11__AUD6_TXD		IOMUX_PAD(0x788, 0x380, 4, 0x8f0, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT11__DISP2_DAT11	IOMUX_PAD(0x788, 0x380, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT11__FEC_RX_CLK	IOMUX_PAD(0x788, 0x380, 2, 0x968, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT11__GPIO1_10		IOMUX_PAD(0x788, 0x380, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT11__USBH3_DATA3	IOMUX_PAD(0x788, 0x380, 3, 0xa08, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT12__AUD6_RXD		IOMUX_PAD(0x78c, 0x384, 4, 0x8ec, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT12__DISP2_DAT12	IOMUX_PAD(0x78c, 0x384, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT12__FEC_RX_DV		IOMUX_PAD(0x78c, 0x384, 2, 0x96c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT12__USBH3_DATA4	IOMUX_PAD(0x78c, 0x384, 3, 0xa0c, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT13__AUD6_TXC		IOMUX_PAD(0x790, 0x388, 4, 0x8fc, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT13__DISP2_DAT13	IOMUX_PAD(0x790, 0x388, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT13__FEC_TX_CLK	IOMUX_PAD(0x790, 0x388, 2, 0x974, 1, MX51_PAD_CTRL_4)
+#define MX51_PAD_DISP2_DAT13__USBH3_DATA5	IOMUX_PAD(0x790, 0x388, 3, 0xa10, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT14__AUD6_TXFS		IOMUX_PAD(0x794, 0x38c, 4, 0x900, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT14__DISP2_DAT14	IOMUX_PAD(0x794, 0x38c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT14__FEC_RDATA0	IOMUX_PAD(0x794, 0x38c, 2, 0x958, 1, MX51_PAD_CTRL_4)
+#define MX51_PAD_DISP2_DAT14__USBH3_DATA6	IOMUX_PAD(0x794, 0x38c, 3, 0xa14, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT15__AUD6_RXFS		IOMUX_PAD(0x798, 0x390, 4, 0x8f8, 1, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT15__DISP1_SER_CS	IOMUX_PAD(0x798, 0x390, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT15__DISP2_DAT15	IOMUX_PAD(0x798, 0x390, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DISP2_DAT15__FEC_TDATA0	IOMUX_PAD(0x798, 0x390, 2, __NA_, 0, MX51_PAD_CTRL_5)
+#define MX51_PAD_DISP2_DAT15__USBH3_DATA7	IOMUX_PAD(0x798, 0x390, 3, 0xa18, 1, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CMD__AUD5_RXFS		IOMUX_PAD(0x79c, 0x394, 1, 0x8e0, 1, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CMD__CSPI_MOSI		IOMUX_PAD(0x79c, 0x394, 2, 0x91c, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CMD__SD1_CMD		IOMUX_PAD(0x79c, 0x394, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD1_CLK__AUD5_RXC		IOMUX_PAD(0x7a0, 0x398, 1, 0x8dc, 1, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CLK__CSPI_SCLK		IOMUX_PAD(0x7a0, 0x398, 2, 0x914, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CLK__SD1_CLK		IOMUX_PAD(0x7a0, 0x398, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
+#define MX51_PAD_SD1_DATA0__AUD5_TXD		IOMUX_PAD(0x7a4, 0x39c, 1, 0x8d8, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA0__CSPI_MISO		IOMUX_PAD(0x7a4, 0x39c, 2, 0x918, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD1_DATA0__SD1_DATA0		IOMUX_PAD(0x7a4, 0x39c, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_EIM_DA0__EIM_DA0		IOMUX_PAD(__NA_, 0x01c, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA1__EIM_DA1		IOMUX_PAD(__NA_, 0x020, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA2__EIM_DA2		IOMUX_PAD(__NA_, 0x024, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA3__EIM_DA3		IOMUX_PAD(__NA_, 0x028, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA1__AUD5_RXD		IOMUX_PAD(0x7a8, 0x3a0, 1, 0x8d4, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA1__SD1_DATA1		IOMUX_PAD(0x7a8, 0x3a0, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_EIM_DA4__EIM_DA4		IOMUX_PAD(__NA_, 0x02c, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA5__EIM_DA5		IOMUX_PAD(__NA_, 0x030, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA6__EIM_DA6		IOMUX_PAD(__NA_, 0x034, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA7__EIM_DA7		IOMUX_PAD(__NA_, 0x038, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA2__AUD5_TXC		IOMUX_PAD(0x7ac, 0x3a4, 1, 0x8e4, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA2__SD1_DATA2		IOMUX_PAD(0x7ac, 0x3a4, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_EIM_DA10__EIM_DA10		IOMUX_PAD(__NA_, 0x044, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA11__EIM_DA11		IOMUX_PAD(__NA_, 0x048, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA8__EIM_DA8		IOMUX_PAD(__NA_, 0x03c, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA9__EIM_DA9		IOMUX_PAD(__NA_, 0x040, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA3__AUD5_TXFS		IOMUX_PAD(0x7b0, 0x3a8, 1, 0x8e8, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA3__CSPI_SS1		IOMUX_PAD(0x7b0, 0x3a8, 2, 0x920, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD1_DATA3__SD1_DATA3		IOMUX_PAD(0x7b0, 0x3a8, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_GPIO1_0__CSPI_SS2		IOMUX_PAD(0x7b4, 0x3ac, 2, 0x924, 0, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_GPIO1_0__GPIO1_0		IOMUX_PAD(0x7b4, 0x3ac, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_0__SD1_CD		IOMUX_PAD(0x7b4, 0x3ac, 0, __NA_, 0, MX51_ESDHC_PAD_CTRL)
+#define MX51_PAD_GPIO1_1__CSPI_MISO		IOMUX_PAD(0x7b8, 0x3b0, 2, 0x918, 2, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_GPIO1_1__GPIO1_1		IOMUX_PAD(0x7b8, 0x3b0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_1__SD1_WP		IOMUX_PAD(0x7b8, 0x3b0, 0, __NA_, 0, MX51_ESDHC_PAD_CTRL)
+#define MX51_PAD_EIM_DA12__EIM_DA12		IOMUX_PAD(__NA_, 0x04c, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA13__EIM_DA13		IOMUX_PAD(__NA_, 0x050, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA14__EIM_DA14		IOMUX_PAD(__NA_, 0x054, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_DA15__EIM_DA15		IOMUX_PAD(__NA_, 0x058, 0, 0x000, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_CMD__CSPI_MOSI		IOMUX_PAD(__NA_, 0x3b4, 2, 0x91c, 3, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD2_CMD__I2C1_SCL		IOMUX_PAD(0x7bc, 0x3b4, 0x11, 0x9b0, 2, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_SD2_CMD__SD2_CMD		IOMUX_PAD(0x7bc, 0x3b4, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_CLK__CSPI_SCLK		IOMUX_PAD(0x7c0, 0x3b8, 2, 0x914, 3, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD2_CLK__I2C1_SDA		IOMUX_PAD(0x7c0, 0x3b8, 0x11, 0x9b4, 2, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_SD2_CLK__SD2_CLK		IOMUX_PAD(0x7c0, 0x3b8, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
+#define MX51_PAD_SD2_DATA0__CSPI_MISO		IOMUX_PAD(0x7c4, 0x3bc, 2, 0x918, 3, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA0__SD1_DAT4		IOMUX_PAD(0x7c4, 0x3bc, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA0__SD2_DATA0		IOMUX_PAD(0x7c4, 0x3bc, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA1__SD1_DAT5		IOMUX_PAD(0x7c8, 0x3c0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA1__SD2_DATA1		IOMUX_PAD(0x7c8, 0x3c0, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA1__USBH3_H2_DP		IOMUX_PAD(0x7c8, 0x3c0, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA2__SD1_DAT6		IOMUX_PAD(0x7cc, 0x3c4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA2__SD2_DATA2		IOMUX_PAD(0x7cc, 0x3c4, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA2__USBH3_H2_DM		IOMUX_PAD(0x7cc, 0x3c4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA3__CSPI_SS2		IOMUX_PAD(0x7d0, 0x3c8, 2, 0x924, 1, MX51_ECSPI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA3__SD1_DAT7		IOMUX_PAD(0x7d0, 0x3c8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA3__SD2_DATA3		IOMUX_PAD(0x7d0, 0x3c8, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_GPIO1_2__CCM_OUT_2		IOMUX_PAD(0x7d4, 0x3cc, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_2__GPIO1_2		IOMUX_PAD(0x7d4, 0x3cc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_2__I2C2_SCL		IOMUX_PAD(0x7d4, 0x3cc, 0x12, 0x9b8, 3, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_GPIO1_2__PLL1_BYP		IOMUX_PAD(0x7d4, 0x3cc, 7, 0x90c, 1, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_2__PWM1_PWMO		IOMUX_PAD(0x7d4, 0x3cc, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_3__GPIO1_3		IOMUX_PAD(0x7d8, 0x3d0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_3__I2C2_SDA		IOMUX_PAD(0x7d8, 0x3d0, 0x12, 0x9bc, 3, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_GPIO1_3__PLL2_BYP		IOMUX_PAD(0x7d8, 0x3d0, 7, 0x910, 1, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_3__PWM2_PWMO		IOMUX_PAD(0x7d8, 0x3d0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ	IOMUX_PAD(0x7fc, 0x3d4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_PMIC_INT_REQ__PMIC_PMU_IRQ_B	IOMUX_PAD(0x7fc, 0x3d4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_4__DISP2_EXT_CLK		IOMUX_PAD(0x804, 0x3d8, 4, 0x908, 1, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_4__EIM_RDY		IOMUX_PAD(0x804, 0x3d8, 3, 0x938, 1, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_4__GPIO1_4		IOMUX_PAD(0x804, 0x3d8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_4__WDOG1_WDOG_B		IOMUX_PAD(0x804, 0x3d8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_5__CSI2_MCLK		IOMUX_PAD(0x808, 0x3dc, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_5__DISP2_PIN16		IOMUX_PAD(0x808, 0x3dc, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_5__GPIO1_5		IOMUX_PAD(0x808, 0x3dc, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_5__WDOG2_WDOG_B		IOMUX_PAD(0x808, 0x3dc, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_6__DISP2_PIN17		IOMUX_PAD(0x80c, 0x3e0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_6__GPIO1_6		IOMUX_PAD(0x80c, 0x3e0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_6__REF_EN_B		IOMUX_PAD(0x80c, 0x3e0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_7__CCM_OUT_0		IOMUX_PAD(0x810, 0x3e4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_7__GPIO1_7		IOMUX_PAD(0x810, 0x3e4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_7__SD2_WP		IOMUX_PAD(0x810, 0x3e4, 6, __NA_, 0, MX51_ESDHC_PAD_CTRL)
+#define MX51_PAD_GPIO1_7__SPDIF_OUT1		IOMUX_PAD(0x810, 0x3e4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_8__CSI2_DATA_EN		IOMUX_PAD(0x814, 0x3e8, 2, 0x99c, 2, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_8__GPIO1_8		IOMUX_PAD(0x814, 0x3e8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_8__SD2_CD		IOMUX_PAD(0x814, 0x3e8, 6, __NA_, 0, MX51_ESDHC_PAD_CTRL)
+#define MX51_PAD_GPIO1_8__USBH3_PWR		IOMUX_PAD(0x814, 0x3e8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__CCM_OUT_1		IOMUX_PAD(0x818, 0x3ec, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__DISP2_D1_CS		IOMUX_PAD(0x818, 0x3ec, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__DISP2_SER_CS		IOMUX_PAD(0x818, 0x3ec, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__GPIO1_9		IOMUX_PAD(0x818, 0x3ec, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__SD2_LCTL		IOMUX_PAD(0x818, 0x3ec, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__USBH3_OC		IOMUX_PAD(0x818, 0x3ec, 1, __NA_, 0, NO_PAD_CTRL)
 
 #endif /* __MACH_IOMUX_MX51_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx53.h b/arch/arm/plat-mxc/include/mach/iomux-mx53.h
index 5408fd1..527f8fe 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx53.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx53.h
@@ -23,2359 +23,1197 @@
 
 /* These 2 defines are for pins that may not have a mux register, but could
  * have a pad setting register, and vice-versa. */
-#define NON_PAD_I	0x00
+#define __NA_	0x00
 
 #define MX53_UART_PAD_CTRL		(PAD_CTL_PKE | PAD_CTL_PUE |	\
 		PAD_CTL_DSE_HIGH | PAD_CTL_SRE_FAST | PAD_CTL_HYS)
 #define MX53_SDHC_PAD_CTRL 	(PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | \
 				PAD_CTL_PUS_47K_UP | PAD_CTL_DSE_HIGH | \
 				PAD_CTL_SRE_FAST)
-#define PAD_CTRL_I2C	(PAD_CTL_SRE_FAST | PAD_CTL_ODE | PAD_CTL_PKE | \
-			PAD_CTL_PUE | PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP \
-			| PAD_CTL_HYS)
 
-#define _MX53_PAD_GPIO_19__KPP_COL_5		IOMUX_PAD(0x348, 0x20, 0, 0x840, 0, 0)
-#define _MX53_PAD_GPIO_19__GPIO4_5		IOMUX_PAD(0x348, 0x20, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_19__CCM_CLKO		IOMUX_PAD(0x348, 0x20, 2, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_19__SPDIF_OUT1	IOMUX_PAD(0x348, 0x20, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_19__RTC_CE_RTC_EXT_TRIG2	IOMUX_PAD(0x348, 0x20, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_19__ECSPI1_RDY	IOMUX_PAD(0x348, 0x20, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_19__FEC_TDATA_3	IOMUX_PAD(0x348, 0x20, 6, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_19__SRC_INT_BOOT	IOMUX_PAD(0x348, 0x20,7, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL0__KPP_COL_0	IOMUX_PAD(0x34C, 0x24, 0, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL0__GPIO4_6		IOMUX_PAD(0x34C, 0x24, 1, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC	IOMUX_PAD(0x34C, 0x24, 2, 0x758, 0, 0)
-#define _MX53_PAD_KEY_COL0__UART4_TXD_MUX	IOMUX_PAD(0x34C, 0x24, 4, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL0__ECSPI1_SCLK	IOMUX_PAD(0x34C, 0x24, 5, 0x79C, 0, 0)
-#define _MX53_PAD_KEY_COL0__FEC_RDATA_3	IOMUX_PAD(0x34C, 0x24, 6, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL0__SRC_ANY_PU_RST	IOMUX_PAD(0x34C, 0x24, 7, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW0__KPP_ROW_0	IOMUX_PAD(0x350, 0x28, 0, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW0__GPIO4_7		IOMUX_PAD(0x350, 0x28, 1, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD	IOMUX_PAD(0x350, 0x28, 2, 0x74C, 0, 0)
-#define _MX53_PAD_KEY_ROW0__UART4_RXD_MUX	IOMUX_PAD(0x350, 0x28, 4, 0x890, 1, 0)
-#define _MX53_PAD_KEY_ROW0__ECSPI1_MOSI	IOMUX_PAD(0x350, 0x28, 5, 0x7A4, 0, 0)
-#define _MX53_PAD_KEY_ROW0__FEC_TX_ER	IOMUX_PAD(0x350, 0x28, 6, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL1__KPP_COL_1	IOMUX_PAD(0x354, 0x2C, 0, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL1__GPIO4_8		IOMUX_PAD(0x354, 0x2C, 1, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS	IOMUX_PAD(0x354, 0x2C, 2, 0x75C, 0, 0)
-#define _MX53_PAD_KEY_COL1__UART5_TXD_MUX	IOMUX_PAD(0x354, 0x2C, 4, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL1__ECSPI1_MISO	IOMUX_PAD(0x354, 0x2C, 5, 0x7A0, 0, 0)
-#define _MX53_PAD_KEY_COL1__FEC_RX_CLK	IOMUX_PAD(0x354, 0x2C, 6, 0x808, 0, 0)
-#define _MX53_PAD_KEY_COL1__USBPHY1_TXREADY	IOMUX_PAD(0x354, 0x2C, 7, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW1__KPP_ROW_1	IOMUX_PAD(0x358, 0x30, 0, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW1__GPIO4_9		IOMUX_PAD(0x358, 0x30, 1, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD	IOMUX_PAD(0x358, 0x30, 2, 0x748, 0, 0)
-#define _MX53_PAD_KEY_ROW1__UART5_RXD_MUX	IOMUX_PAD(0x358, 0x30, 4, 0x898, 1, 0)
-#define _MX53_PAD_KEY_ROW1__ECSPI1_SS0	IOMUX_PAD(0x358, 0x30, 5, 0x7A8, 0, 0)
-#define _MX53_PAD_KEY_ROW1__FEC_COL		IOMUX_PAD(0x358, 0x30, 6, 0x800, 0, 0)
-#define _MX53_PAD_KEY_ROW1__USBPHY1_RXVALID	IOMUX_PAD(0x358, 0x30, 7, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL2__KPP_COL_2	IOMUX_PAD(0x35C, 0x34, 0, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL2__GPIO4_10		IOMUX_PAD(0x35C, 0x34, 1, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL2__CAN1_TXCAN	IOMUX_PAD(0x35C, 0x34, 2, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL2__FEC_MDIO		IOMUX_PAD(0x35C, 0x34, 4, 0x804, 0, 0)
-#define _MX53_PAD_KEY_COL2__ECSPI1_SS1	IOMUX_PAD(0x35C, 0x34, 5, 0x7AC, 0, 0)
-#define _MX53_PAD_KEY_COL2__FEC_RDATA_2	IOMUX_PAD(0x35C, 0x34, 6, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL2__USBPHY1_RXACTIVE	IOMUX_PAD(0x35C, 0x34, 7, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW2__KPP_ROW_2	IOMUX_PAD(0x360, 0x38, 0, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW2__GPIO4_11	IOMUX_PAD(0x360, 0x38, 1, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW2__CAN1_RXCAN	IOMUX_PAD(0x360, 0x38, 2, 0x760, 0, 0)
-#define _MX53_PAD_KEY_ROW2__FEC_MDC		IOMUX_PAD(0x360, 0x38, 4, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW2__ECSPI1_SS2	IOMUX_PAD(0x360, 0x38, 5, 0x7B0, 0, 0)
-#define _MX53_PAD_KEY_ROW2__FEC_TDATA_2	IOMUX_PAD(0x360, 0x38, 6, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW2__USBPHY1_RXERROR	IOMUX_PAD(0x360, 0x38, 7, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL3__KPP_COL_3	IOMUX_PAD(0x364, 0x3C, 0, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL3__GPIO4_12		IOMUX_PAD(0x364, 0x3C, 1, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL3__USBOH3_H2_DP	IOMUX_PAD(0x364, 0x3C, 2, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL3__SPDIF_IN1	IOMUX_PAD(0x364, 0x3C, 3, 0x870, 0, 0)
-#define _MX53_PAD_KEY_COL3__I2C2_SCL		IOMUX_PAD(0x364, 0x3C, 4 | IOMUX_CONFIG_SION, 0x81C, 0, 0)
-#define _MX53_PAD_KEY_COL3__ECSPI1_SS3	IOMUX_PAD(0x364, 0x3C, 5, 0x7B4, 0, 0)
-#define _MX53_PAD_KEY_COL3__FEC_CRS		IOMUX_PAD(0x364, 0x3C, 6, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL3__USBPHY1_SIECLOCK	IOMUX_PAD(0x364, 0x3C, 7, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW3__KPP_ROW_3	IOMUX_PAD(0x368, 0x40, 0, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW3__GPIO4_13	IOMUX_PAD(0x368, 0x40, 1, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW3__USBOH3_H2_DM	IOMUX_PAD(0x368, 0x40, 2, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW3__CCM_ASRC_EXT_CLK	IOMUX_PAD(0x368, 0x40, 3, 0x768, 0, 0)
-#define _MX53_PAD_KEY_ROW3__I2C2_SDA	IOMUX_PAD(0x368, 0x40, 4 | IOMUX_CONFIG_SION, 0x820, 0, 0)
-#define _MX53_PAD_KEY_ROW3__OSC32K_32K_OUT	IOMUX_PAD(0x368, 0x40, 5, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW3__CCM_PLL4_BYP	IOMUX_PAD(0x368, 0x40, 6, 0x77C, 0, 0)
-#define _MX53_PAD_KEY_ROW3__USBPHY1_LINESTATE_0	IOMUX_PAD(0x368, 0x40, 7, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL4__KPP_COL_4	IOMUX_PAD(0x36C, 0x44, 0, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL4__GPIO4_14		IOMUX_PAD(0x36C, 0x44, 1, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL4__CAN2_TXCAN	IOMUX_PAD(0x36C, 0x44, 2, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL4__IPU_SISG_4	IOMUX_PAD(0x36C, 0x44, 3, 0x0, 0, 0)
-#define _MX53_PAD_KEY_COL4__UART5_RTS	IOMUX_PAD(0x36C, 0x44, 4, 0x894, 0, 0)
-#define _MX53_PAD_KEY_COL4__USBOH3_USBOTG_OC	IOMUX_PAD(0x36C, 0x44, 5, 0x89C, 0, 0)
-#define _MX53_PAD_KEY_COL4__USBPHY1_LINESTATE_1	IOMUX_PAD(0x36C, 0x44, 7, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW4__KPP_ROW_4	IOMUX_PAD(0x370, 0x48, 0, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW4__GPIO4_15	IOMUX_PAD(0x370, 0x48, 1, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW4__CAN2_RXCAN	IOMUX_PAD(0x370, 0x48, 2, 0x764, 0, 0)
-#define _MX53_PAD_KEY_ROW4__IPU_SISG_5	IOMUX_PAD(0x370, 0x48, 3, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW4__UART5_CTS	IOMUX_PAD(0x370, 0x48, 4, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW4__USBOH3_USBOTG_PWR	IOMUX_PAD(0x370, 0x48, 5, 0x0, 0, 0)
-#define _MX53_PAD_KEY_ROW4__USBPHY1_VBUSVALID	IOMUX_PAD(0x370, 0x48, 7, 0x0, 0, 0)
-#define _MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK	IOMUX_PAD(0x378, 0x4C, 0, 0x0, 0, 0)
-#define _MX53_PAD_DI0_DISP_CLK__GPIO4_16		IOMUX_PAD(0x378, 0x4C, 1, 0x0, 0, 0)
-#define _MX53_PAD_DI0_DISP_CLK__USBOH3_USBH2_DIR	IOMUX_PAD(0x378, 0x4C, 2, 0x0, 0, 0)
-#define _MX53_PAD_DI0_DISP_CLK__SDMA_DEBUG_CORE_STATE_0	IOMUX_PAD(0x378, 0x4C, 5, 0x0, 0, 0)
-#define _MX53_PAD_DI0_DISP_CLK__EMI_EMI_DEBUG_0	IOMUX_PAD(0x378, 0x4C, 6, 0x0, 0, 0)
-#define _MX53_PAD_DI0_DISP_CLK__USBPHY1_AVALID	IOMUX_PAD(0x378, 0x4C, 7, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN15__IPU_DI0_PIN15		IOMUX_PAD(0x37C, 0x50, 0, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN15__GPIO4_17		IOMUX_PAD(0x37C, 0x50, 1, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN15__AUDMUX_AUD6_TXC	IOMUX_PAD(0x37C, 0x50, 2, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN15__SDMA_DEBUG_CORE_STATE_1	IOMUX_PAD(0x37C, 0x50, 5, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN15__EMI_EMI_DEBUG_1	IOMUX_PAD(0x37C, 0x50, 6, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN15__USBPHY1_BVALID		IOMUX_PAD(0x37C, 0x50, 7, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN2__IPU_DI0_PIN2		IOMUX_PAD(0x380, 0x54, 0, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN2__GPIO4_18			IOMUX_PAD(0x380, 0x54, 1, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN2__AUDMUX_AUD6_TXD	IOMUX_PAD(0x380, 0x54, 2, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN2__SDMA_DEBUG_CORE_STATE_2	IOMUX_PAD(0x380, 0x54, 5, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN2__EMI_EMI_DEBUG_2		IOMUX_PAD(0x380, 0x54, 6, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN2__USBPHY1_ENDSESSION	IOMUX_PAD(0x380, 0x54, 7, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN3__IPU_DI0_PIN3		IOMUX_PAD(0x384, 0x58, 0, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN3__GPIO4_19			IOMUX_PAD(0x384, 0x58, 1, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS	IOMUX_PAD(0x384, 0x58, 2, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN3__SDMA_DEBUG_CORE_STATE_3	IOMUX_PAD(0x384, 0x58, 5, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN3__EMI_EMI_DEBUG_3		IOMUX_PAD(0x384, 0x58, 6, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN3__USBPHY1_IDDIG		IOMUX_PAD(0x384, 0x58, 7, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN4__IPU_DI0_PIN4		IOMUX_PAD(0x388, 0x5C, 0, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN4__GPIO4_20			IOMUX_PAD(0x388, 0x5C, 1, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN4__AUDMUX_AUD6_RXD	IOMUX_PAD(0x388, 0x5C, 2, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN4__ESDHC1_WP		IOMUX_PAD(0x388, 0x5C, 3, 0x7FC, 0, 0)
-#define _MX53_PAD_DI0_PIN4__SDMA_DEBUG_YIELD	IOMUX_PAD(0x388, 0x5C, 5, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN4__EMI_EMI_DEBUG_4		IOMUX_PAD(0x388, 0x5C, 6, 0x0, 0, 0)
-#define _MX53_PAD_DI0_PIN4__USBPHY1_HOSTDISCONNECT	IOMUX_PAD(0x388, 0x5C, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0	IOMUX_PAD(0x38C, 0x60, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT0__GPIO4_21		IOMUX_PAD(0x38C, 0x60, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT0__CSPI_SCLK		IOMUX_PAD(0x38C, 0x60, 2, 0x780, 0, 0)
-#define _MX53_PAD_DISP0_DAT0__USBOH3_USBH2_DATA_0	IOMUX_PAD(0x38C, 0x60, 3, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT0__SDMA_DEBUG_CORE_RUN	IOMUX_PAD(0x38C, 0x60, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT0__EMI_EMI_DEBUG_5	IOMUX_PAD(0x38C, 0x60, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT0__USBPHY2_TXREADY	IOMUX_PAD(0x38C, 0x60, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1	IOMUX_PAD(0x390, 0x64, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT1__GPIO4_22		IOMUX_PAD(0x390, 0x64, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT1__CSPI_MOSI		IOMUX_PAD(0x390, 0x64, 2, 0x788, 0, 0)
-#define _MX53_PAD_DISP0_DAT1__USBOH3_USBH2_DATA_1	IOMUX_PAD(0x390, 0x64, 3, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT1__SDMA_DEBUG_EVENT_CHANNEL_SEL	IOMUX_PAD(0x390, 0x64, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT1__EMI_EMI_DEBUG_6	IOMUX_PAD(0x390, 0x64, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT1__USBPHY2_RXVALID	IOMUX_PAD(0x390, 0x64, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2	IOMUX_PAD(0x394, 0x68, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT2__GPIO4_23		IOMUX_PAD(0x394, 0x68, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT2__CSPI_MISO		IOMUX_PAD(0x394, 0x68, 2, 0x784, 0, 0)
-#define _MX53_PAD_DISP0_DAT2__USBOH3_USBH2_DATA_2	IOMUX_PAD(0x394, 0x68, 3, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT2__SDMA_DEBUG_MODE	IOMUX_PAD(0x394, 0x68, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT2__EMI_EMI_DEBUG_7	IOMUX_PAD(0x394, 0x68, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT2__USBPHY2_RXACTIVE	IOMUX_PAD(0x394, 0x68, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3	IOMUX_PAD(0x398, 0x6C, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT3__GPIO4_24		IOMUX_PAD(0x398, 0x6C, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT3__CSPI_SS0		IOMUX_PAD(0x398, 0x6C, 2, 0x78C, 0, 0)
-#define _MX53_PAD_DISP0_DAT3__USBOH3_USBH2_DATA_3	IOMUX_PAD(0x398, 0x6C, 3, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT3__SDMA_DEBUG_BUS_ERROR	IOMUX_PAD(0x398, 0x6C, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT3__EMI_EMI_DEBUG_8	IOMUX_PAD(0x398, 0x6C, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT3__USBPHY2_RXERROR	IOMUX_PAD(0x398, 0x6C, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4	IOMUX_PAD(0x39C, 0x70, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT4__GPIO4_25		IOMUX_PAD(0x39C, 0x70, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT4__CSPI_SS1		IOMUX_PAD(0x39C, 0x70, 2, 0x790, 0, 0)
-#define _MX53_PAD_DISP0_DAT4__USBOH3_USBH2_DATA_4	IOMUX_PAD(0x39C, 0x70, 3, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB	IOMUX_PAD(0x39C, 0x70, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT4__EMI_EMI_DEBUG_9	IOMUX_PAD(0x39C, 0x70, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT4__USBPHY2_SIECLOCK	IOMUX_PAD(0x39C, 0x70, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5	IOMUX_PAD(0x3A0, 0x74, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT5__GPIO4_26		IOMUX_PAD(0x3A0, 0x74, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT5__CSPI_SS2		IOMUX_PAD(0x3A0, 0x74, 2, 0x794, 0, 0)
-#define _MX53_PAD_DISP0_DAT5__USBOH3_USBH2_DATA_5	IOMUX_PAD(0x3A0, 0x74, 3, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT5__SDMA_DEBUG_MATCHED_DMBUS	IOMUX_PAD(0x3A0, 0x74, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT5__EMI_EMI_DEBUG_10	IOMUX_PAD(0x3A0, 0x74, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT5__USBPHY2_LINESTATE_0	IOMUX_PAD(0x3A0, 0x74, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6	IOMUX_PAD(0x3A4, 0x78, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT6__GPIO4_27		IOMUX_PAD(0x3A4, 0x78, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT6__CSPI_SS3		IOMUX_PAD(0x3A4, 0x78, 2, 0x798, 0, 0)
-#define _MX53_PAD_DISP0_DAT6__USBOH3_USBH2_DATA_6	IOMUX_PAD(0x3A4, 0x78, 3, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT6__SDMA_DEBUG_RTBUFFER_WRITE	IOMUX_PAD(0x3A4, 0x78, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT6__EMI_EMI_DEBUG_11	IOMUX_PAD(0x3A4, 0x78, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT6__USBPHY2_LINESTATE_1	IOMUX_PAD(0x3A4, 0x78, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7	IOMUX_PAD(0x3A8, 0x7C, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT7__GPIO4_28		IOMUX_PAD(0x3A8, 0x7C, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT7__CSPI_RDY		IOMUX_PAD(0x3A8, 0x7C, 2, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT7__USBOH3_USBH2_DATA_7	IOMUX_PAD(0x3A8, 0x7C, 3, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT7__SDMA_DEBUG_EVENT_CHANNEL_0	IOMUX_PAD(0x3A8, 0x7C, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT7__EMI_EMI_DEBUG_12	IOMUX_PAD(0x3A8, 0x7C, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT7__USBPHY2_VBUSVALID	IOMUX_PAD(0x3A8, 0x7C, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8	IOMUX_PAD(0x3AC, 0x80, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT8__GPIO4_29		IOMUX_PAD(0x3AC, 0x80, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT8__PWM1_PWMO		IOMUX_PAD(0x3AC, 0x80, 2, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT8__WDOG1_WDOG_B	IOMUX_PAD(0x3AC, 0x80, 3, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT8__SDMA_DEBUG_EVENT_CHANNEL_1	IOMUX_PAD(0x3AC, 0x80, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT8__EMI_EMI_DEBUG_13	IOMUX_PAD(0x3AC, 0x80, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT8__USBPHY2_AVALID	IOMUX_PAD(0x3AC, 0x80, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9	IOMUX_PAD(0x3B0, 0x84, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT9__GPIO4_30		IOMUX_PAD(0x3B0, 0x84, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT9__PWM2_PWMO		IOMUX_PAD(0x3B0, 0x84, 2, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT9__WDOG2_WDOG_B	IOMUX_PAD(0x3B0, 0x84, 3, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT9__SDMA_DEBUG_EVENT_CHANNEL_2		IOMUX_PAD(0x3B0, 0x84, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT9__EMI_EMI_DEBUG_14	IOMUX_PAD(0x3B0, 0x84, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT9__USBPHY2_VSTATUS_0	IOMUX_PAD(0x3B0, 0x84, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10	IOMUX_PAD(0x3B4, 0x88, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT10__GPIO4_31		IOMUX_PAD(0x3B4, 0x88, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT10__USBOH3_USBH2_STP	IOMUX_PAD(0x3B4, 0x88, 2, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT10__SDMA_DEBUG_EVENT_CHANNEL_3	IOMUX_PAD(0x3B4, 0x88, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT10__EMI_EMI_DEBUG_15	IOMUX_PAD(0x3B4, 0x88, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT10__USBPHY2_VSTATUS_1	IOMUX_PAD(0x3B4, 0x88, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11	IOMUX_PAD(0x3B8, 0x8C, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT11__GPIO5_5		IOMUX_PAD(0x3B8, 0x8C, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT11__USBOH3_USBH2_NXT	IOMUX_PAD(0x3B8, 0x8C, 2, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT11__SDMA_DEBUG_EVENT_CHANNEL_4	IOMUX_PAD(0x3B8, 0x8C, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT11__EMI_EMI_DEBUG_16	IOMUX_PAD(0x3B8, 0x8C, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT11__USBPHY2_VSTATUS_2	IOMUX_PAD(0x3B8, 0x8C, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12	IOMUX_PAD(0x3BC, 0x90, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT12__GPIO5_6		IOMUX_PAD(0x3BC, 0x90, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT12__USBOH3_USBH2_CLK	IOMUX_PAD(0x3BC, 0x90, 2, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT12__SDMA_DEBUG_EVENT_CHANNEL_5	IOMUX_PAD(0x3BC, 0x90, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT12__EMI_EMI_DEBUG_17	IOMUX_PAD(0x3BC, 0x90, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT12__USBPHY2_VSTATUS_3	IOMUX_PAD(0x3BC, 0x90, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13	IOMUX_PAD(0x3C0, 0x94, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT13__GPIO5_7		IOMUX_PAD(0x3C0, 0x94, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS	IOMUX_PAD(0x3C0, 0x94, 3, 0x754, 0, 0)
-#define _MX53_PAD_DISP0_DAT13__SDMA_DEBUG_EVT_CHN_LINES_0	IOMUX_PAD(0x3C0, 0x94, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT13__EMI_EMI_DEBUG_18	IOMUX_PAD(0x3C0, 0x94, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT13__USBPHY2_VSTATUS_4	IOMUX_PAD(0x3C0, 0x94, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14	IOMUX_PAD(0x3C4, 0x98, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT14__GPIO5_8		IOMUX_PAD(0x3C4, 0x98, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC	IOMUX_PAD(0x3C4, 0x98, 3, 0x750, 0, 0)
-#define _MX53_PAD_DISP0_DAT14__SDMA_DEBUG_EVT_CHN_LINES_1	IOMUX_PAD(0x3C4, 0x98, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT14__EMI_EMI_DEBUG_19	IOMUX_PAD(0x3C4, 0x98, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT14__USBPHY2_VSTATUS_5	IOMUX_PAD(0x3C4, 0x98, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15	IOMUX_PAD(0x3C8, 0x9C, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT15__GPIO5_9		IOMUX_PAD(0x3C8, 0x9C, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT15__ECSPI1_SS1		IOMUX_PAD(0x3C8, 0x9C, 2, 0x7AC, 1, 0)
-#define _MX53_PAD_DISP0_DAT15__ECSPI2_SS1		IOMUX_PAD(0x3C8, 0x9C, 3, 0x7C8, 0, 0)
-#define _MX53_PAD_DISP0_DAT15__SDMA_DEBUG_EVT_CHN_LINES_2	IOMUX_PAD(0x3C8, 0x9C, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT15__EMI_EMI_DEBUG_20	IOMUX_PAD(0x3C8, 0x9C, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT15__USBPHY2_VSTATUS_6	IOMUX_PAD(0x3C8, 0x9C, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16	IOMUX_PAD(0x3CC, 0xA0, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT16__GPIO5_10		IOMUX_PAD(0x3CC, 0xA0, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT16__ECSPI2_MOSI		IOMUX_PAD(0x3CC, 0xA0, 2, 0x7C0, 0, 0)
-#define _MX53_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC	IOMUX_PAD(0x3CC, 0xA0, 3, 0x758, 1, 0)
-#define _MX53_PAD_DISP0_DAT16__SDMA_EXT_EVENT_0	IOMUX_PAD(0x3CC, 0xA0, 4, 0x868, 0, 0)
-#define _MX53_PAD_DISP0_DAT16__SDMA_DEBUG_EVT_CHN_LINES_3	IOMUX_PAD(0x3CC, 0xA0, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT16__EMI_EMI_DEBUG_21	IOMUX_PAD(0x3CC, 0xA0, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT16__USBPHY2_VSTATUS_7	IOMUX_PAD(0x3CC, 0xA0, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17	IOMUX_PAD(0x3D0, 0xA4, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT17__GPIO5_11		IOMUX_PAD(0x3D0, 0xA4, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT17__ECSPI2_MISO		IOMUX_PAD(0x3D0, 0xA4, 2, 0x7BC, 0, 0)
-#define _MX53_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD	IOMUX_PAD(0x3D0, 0xA4, 3, 0x74C, 1, 0)
-#define _MX53_PAD_DISP0_DAT17__SDMA_EXT_EVENT_1	IOMUX_PAD(0x3D0, 0xA4, 4, 0x86C, 0, 0)
-#define _MX53_PAD_DISP0_DAT17__SDMA_DEBUG_EVT_CHN_LINES_4	IOMUX_PAD(0x3D0, 0xA4, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT17__EMI_EMI_DEBUG_22	IOMUX_PAD(0x3D0, 0xA4, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18	IOMUX_PAD(0x3D4, 0xA8, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT18__GPIO5_12		IOMUX_PAD(0x3D4, 0xA8, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT18__ECSPI2_SS0		IOMUX_PAD(0x3D4, 0xA8, 2, 0x7C4, 0, 0)
-#define _MX53_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS	IOMUX_PAD(0x3D4, 0xA8, 3, 0x75C, 1, 0)
-#define _MX53_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS	IOMUX_PAD(0x3D4, 0xA8, 4, 0x73C, 0, 0)
-#define _MX53_PAD_DISP0_DAT18__SDMA_DEBUG_EVT_CHN_LINES_5	IOMUX_PAD(0x3D4, 0xA8, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT18__EMI_EMI_DEBUG_23	IOMUX_PAD(0x3D4, 0xA8, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT18__EMI_WEIM_CS_2	IOMUX_PAD(0x3D4, 0xA8, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19	IOMUX_PAD(0x3D8, 0xAC, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT19__GPIO5_13		IOMUX_PAD(0x3D8, 0xAC, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT19__ECSPI2_SCLK		IOMUX_PAD(0x3D8, 0xAC, 2, 0x7B8, 0, 0)
-#define _MX53_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD	IOMUX_PAD(0x3D8, 0xAC, 3, 0x748, 1, 0)
-#define _MX53_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC	IOMUX_PAD(0x3D8, 0xAC, 4, 0x738, 0, 0)
-#define _MX53_PAD_DISP0_DAT19__SDMA_DEBUG_EVT_CHN_LINES_6	IOMUX_PAD(0x3D8, 0xAC, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT19__EMI_EMI_DEBUG_24	IOMUX_PAD(0x3D8, 0xAC, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT19__EMI_WEIM_CS_3	IOMUX_PAD(0x3D8, 0xAC, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20	IOMUX_PAD(0x3DC, 0xB0, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT20__GPIO5_14		IOMUX_PAD(0x3DC, 0xB0, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT20__ECSPI1_SCLK		IOMUX_PAD(0x3DC, 0xB0, 2, 0x79C, 1, 0)
-#define _MX53_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC	IOMUX_PAD(0x3DC, 0xB0, 3, 0x740, 0, 0)
-#define _MX53_PAD_DISP0_DAT20__SDMA_DEBUG_EVT_CHN_LINES_7	IOMUX_PAD(0x3DC, 0xB0, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT20__EMI_EMI_DEBUG_25	IOMUX_PAD(0x3DC, 0xB0, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT20__SATA_PHY_TDI		IOMUX_PAD(0x3DC, 0xB0, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21	IOMUX_PAD(0x3E0, 0xB4, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT21__GPIO5_15		IOMUX_PAD(0x3E0, 0xB4, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT21__ECSPI1_MOSI		IOMUX_PAD(0x3E0, 0xB4, 2, 0x7A4, 1, 0)
-#define _MX53_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD	IOMUX_PAD(0x3E0, 0xB4, 3, 0x734, 0, 0)
-#define _MX53_PAD_DISP0_DAT21__SDMA_DEBUG_BUS_DEVICE_0	IOMUX_PAD(0x3E0, 0xB4, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT21__EMI_EMI_DEBUG_26	IOMUX_PAD(0x3E0, 0xB4, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT21__SATA_PHY_TDO	IOMUX_PAD(0x3E0, 0xB4, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22	IOMUX_PAD(0x3E4, 0xB8, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT22__GPIO5_16		IOMUX_PAD(0x3E4, 0xB8, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT22__ECSPI1_MISO		IOMUX_PAD(0x3E4, 0xB8, 2, 0x7A0, 1, 0)
-#define _MX53_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS	IOMUX_PAD(0x3E4, 0xB8, 3, 0x744, 0, 0)
-#define _MX53_PAD_DISP0_DAT22__SDMA_DEBUG_BUS_DEVICE_1	IOMUX_PAD(0x3E4, 0xB8, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT22__EMI_EMI_DEBUG_27	IOMUX_PAD(0x3E4, 0xB8, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT22__SATA_PHY_TCK	IOMUX_PAD(0x3E4, 0xB8, 7, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23	IOMUX_PAD(0x3E8, 0xBC, 0, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT23__GPIO5_17		IOMUX_PAD(0x3E8, 0xBC, 1, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT23__ECSPI1_SS0		IOMUX_PAD(0x3E8, 0xBC, 2, 0x7A8, 1, 0)
-#define _MX53_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD	IOMUX_PAD(0x3E8, 0xBC, 3, 0x730, 0, 0)
-#define _MX53_PAD_DISP0_DAT23__SDMA_DEBUG_BUS_DEVICE_2	IOMUX_PAD(0x3E8, 0xBC, 5, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT23__EMI_EMI_DEBUG_28	IOMUX_PAD(0x3E8, 0xBC, 6, 0x0, 0, 0)
-#define _MX53_PAD_DISP0_DAT23__SATA_PHY_TMS	IOMUX_PAD(0x3E8, 0xBC, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK	IOMUX_PAD(0x3EC, 0xC0, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_PIXCLK__GPIO5_18		IOMUX_PAD(0x3EC, 0xC0, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0	IOMUX_PAD(0x3EC, 0xC0, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_PIXCLK__EMI_EMI_DEBUG_29	IOMUX_PAD(0x3EC, 0xC0, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC		IOMUX_PAD(0x3F0, 0xC4, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_MCLK__GPIO5_19		IOMUX_PAD(0x3F0, 0xC4, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_MCLK__CCM_CSI0_MCLK		IOMUX_PAD(0x3F0, 0xC4, 2, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1	IOMUX_PAD(0x3F0, 0xC4, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_MCLK__EMI_EMI_DEBUG_30	IOMUX_PAD(0x3F0, 0xC4, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_MCLK__TPIU_TRCTL		IOMUX_PAD(0x3F0, 0xC4, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN	IOMUX_PAD(0x3F4, 0xC8, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DATA_EN__GPIO5_20		IOMUX_PAD(0x3F4, 0xC8, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2	IOMUX_PAD(0x3F4, 0xC8, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DATA_EN__EMI_EMI_DEBUG_31	IOMUX_PAD(0x3F4, 0xC8, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DATA_EN__TPIU_TRCLK		IOMUX_PAD(0x3F4, 0xC8, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC	IOMUX_PAD(0x3F8, 0xCC, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_VSYNC__GPIO5_21		IOMUX_PAD(0x3F8, 0xCC, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3	IOMUX_PAD(0x3F8, 0xCC, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_VSYNC__EMI_EMI_DEBUG_32	IOMUX_PAD(0x3F8, 0xCC, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_VSYNC__TPIU_TRACE_0		IOMUX_PAD(0x3F8, 0xCC, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT4__IPU_CSI0_D_4		IOMUX_PAD(0x3FC, 0xD0, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT4__GPIO5_22		IOMUX_PAD(0x3FC, 0xD0, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT4__KPP_COL_5		IOMUX_PAD(0x3FC, 0xD0, 2, 0x840, 1, 0)
-#define _MX53_PAD_CSI0_DAT4__ECSPI1_SCLK		IOMUX_PAD(0x3FC, 0xD0, 3, 0x79C, 2, 0)
-#define _MX53_PAD_CSI0_DAT4__USBOH3_USBH3_STP	IOMUX_PAD(0x3FC, 0xD0, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC	IOMUX_PAD(0x3FC, 0xD0, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT4__EMI_EMI_DEBUG_33	IOMUX_PAD(0x3FC, 0xD0, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT4__TPIU_TRACE_1		IOMUX_PAD(0x3FC, 0xD0, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT5__IPU_CSI0_D_5		IOMUX_PAD(0x400, 0xD4, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT5__GPIO5_23		IOMUX_PAD(0x400, 0xD4, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT5__KPP_ROW_5		IOMUX_PAD(0x400, 0xD4, 2, 0x84C, 0, 0)
-#define _MX53_PAD_CSI0_DAT5__ECSPI1_MOSI		IOMUX_PAD(0x400, 0xD4, 3, 0x7A4, 2, 0)
-#define _MX53_PAD_CSI0_DAT5__USBOH3_USBH3_NXT	IOMUX_PAD(0x400, 0xD4, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD	IOMUX_PAD(0x400, 0xD4, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT5__EMI_EMI_DEBUG_34	IOMUX_PAD(0x400, 0xD4, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT5__TPIU_TRACE_2		IOMUX_PAD(0x400, 0xD4, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT6__IPU_CSI0_D_6		IOMUX_PAD(0x404, 0xD8, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT6__GPIO5_24		IOMUX_PAD(0x404, 0xD8, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT6__KPP_COL_6		IOMUX_PAD(0x404, 0xD8, 2, 0x844, 0, 0)
-#define _MX53_PAD_CSI0_DAT6__ECSPI1_MISO		IOMUX_PAD(0x404, 0xD8, 3, 0x7A0, 2, 0)
-#define _MX53_PAD_CSI0_DAT6__USBOH3_USBH3_CLK	IOMUX_PAD(0x404, 0xD8, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS	IOMUX_PAD(0x404, 0xD8, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT6__EMI_EMI_DEBUG_35	IOMUX_PAD(0x404, 0xD8, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT6__TPIU_TRACE_3		IOMUX_PAD(0x404, 0xD8, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT7__IPU_CSI0_D_7		IOMUX_PAD(0x408, 0xDC, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT7__GPIO5_25		IOMUX_PAD(0x408, 0xDC, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT7__KPP_ROW_6		IOMUX_PAD(0x408, 0xDC, 2, 0x850, 0, 0)
-#define _MX53_PAD_CSI0_DAT7__ECSPI1_SS0		IOMUX_PAD(0x408, 0xDC, 3, 0x7A8, 2, 0)
-#define _MX53_PAD_CSI0_DAT7__USBOH3_USBH3_DIR	IOMUX_PAD(0x408, 0xDC, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD	IOMUX_PAD(0x408, 0xDC, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT7__EMI_EMI_DEBUG_36	IOMUX_PAD(0x408, 0xDC, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT7__TPIU_TRACE_4		IOMUX_PAD(0x408, 0xDC, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT8__IPU_CSI0_D_8		IOMUX_PAD(0x40C, 0xE0, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT8__GPIO5_26		IOMUX_PAD(0x40C, 0xE0, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT8__KPP_COL_7		IOMUX_PAD(0x40C, 0xE0, 2, 0x848, 0, 0)
-#define _MX53_PAD_CSI0_DAT8__ECSPI2_SCLK		IOMUX_PAD(0x40C, 0xE0, 3, 0x7B8, 1, 0)
-#define _MX53_PAD_CSI0_DAT8__USBOH3_USBH3_OC	IOMUX_PAD(0x40C, 0xE0, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT8__I2C1_SDA		IOMUX_PAD(0x40C, 0xE0, 5 | IOMUX_CONFIG_SION, 0x818, 0, 0)
-#define _MX53_PAD_CSI0_DAT8__EMI_EMI_DEBUG_37	IOMUX_PAD(0x40C, 0xE0, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT8__TPIU_TRACE_5		IOMUX_PAD(0x40C, 0xE0, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9		IOMUX_PAD(0x410, 0xE4, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT9__GPIO5_27		IOMUX_PAD(0x410, 0xE4, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT9__KPP_ROW_7		IOMUX_PAD(0x410, 0xE4, 2, 0x854, 0, 0)
-#define _MX53_PAD_CSI0_DAT9__ECSPI2_MOSI		IOMUX_PAD(0x410, 0xE4, 3, 0x7C0, 1, 0)
-#define _MX53_PAD_CSI0_DAT9__USBOH3_USBH3_PWR	IOMUX_PAD(0x410, 0xE4, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT9__I2C1_SCL		IOMUX_PAD(0x410, 0xE4, 5 | IOMUX_CONFIG_SION, 0x814, 0, 0)
-#define _MX53_PAD_CSI0_DAT9__EMI_EMI_DEBUG_38	IOMUX_PAD(0x410, 0xE4, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT9__TPIU_TRACE_6		IOMUX_PAD(0x410, 0xE4, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10		IOMUX_PAD(0x414, 0xE8, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT10__GPIO5_28		IOMUX_PAD(0x414, 0xE8, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT10__UART1_TXD_MUX	IOMUX_PAD(0x414, 0xE8, 2, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT10__ECSPI2_MISO		IOMUX_PAD(0x414, 0xE8, 3, 0x7BC, 1, 0)
-#define _MX53_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC	IOMUX_PAD(0x414, 0xE8, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4	IOMUX_PAD(0x414, 0xE8, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT10__EMI_EMI_DEBUG_39	IOMUX_PAD(0x414, 0xE8, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT10__TPIU_TRACE_7		IOMUX_PAD(0x414, 0xE8, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT11__IPU_CSI0_D_11		IOMUX_PAD(0x418, 0xEC, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT11__GPIO5_29		IOMUX_PAD(0x418, 0xEC, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT11__UART1_RXD_MUX	IOMUX_PAD(0x418, 0xEC, 2, 0x878, 1, 0)
-#define _MX53_PAD_CSI0_DAT11__ECSPI2_SS0		IOMUX_PAD(0x418, 0xEC, 3, 0x7C4, 1, 0)
-#define _MX53_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS	IOMUX_PAD(0x418, 0xEC, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5	IOMUX_PAD(0x418, 0xEC, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT11__EMI_EMI_DEBUG_40	IOMUX_PAD(0x418, 0xEC, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT11__TPIU_TRACE_8		IOMUX_PAD(0x418, 0xEC, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12		IOMUX_PAD(0x41C, 0xF0, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT12__GPIO5_30		IOMUX_PAD(0x41C, 0xF0, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT12__UART4_TXD_MUX	IOMUX_PAD(0x41C, 0xF0, 2, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT12__USBOH3_USBH3_DATA_0	IOMUX_PAD(0x41C, 0xF0, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6	IOMUX_PAD(0x41C, 0xF0, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT12__EMI_EMI_DEBUG_41	IOMUX_PAD(0x41C, 0xF0, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT12__TPIU_TRACE_9		IOMUX_PAD(0x41C, 0xF0, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13		IOMUX_PAD(0x420, 0xF4, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT13__GPIO5_31		IOMUX_PAD(0x420, 0xF4, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT13__UART4_RXD_MUX	IOMUX_PAD(0x420, 0xF4, 2, 0x890, 3, 0)
-#define _MX53_PAD_CSI0_DAT13__USBOH3_USBH3_DATA_1	IOMUX_PAD(0x420, 0xF4, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7	IOMUX_PAD(0x420, 0xF4, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT13__EMI_EMI_DEBUG_42	IOMUX_PAD(0x420, 0xF4, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT13__TPIU_TRACE_10		IOMUX_PAD(0x420, 0xF4, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14		IOMUX_PAD(0x424, 0xF8, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT14__GPIO6_0		IOMUX_PAD(0x424, 0xF8, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT14__UART5_TXD_MUX	IOMUX_PAD(0x424, 0xF8, 2, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT14__USBOH3_USBH3_DATA_2	IOMUX_PAD(0x424, 0xF8, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8	IOMUX_PAD(0x424, 0xF8, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT14__EMI_EMI_DEBUG_43	IOMUX_PAD(0x424, 0xF8, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT14__TPIU_TRACE_11		IOMUX_PAD(0x424, 0xF8, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15		IOMUX_PAD(0x428, 0xFC, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT15__GPIO6_1		IOMUX_PAD(0x428, 0xFC, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT15__UART5_RXD_MUX	IOMUX_PAD(0x428, 0xFC, 2, 0x898, 3, 0)
-#define _MX53_PAD_CSI0_DAT15__USBOH3_USBH3_DATA_3	IOMUX_PAD(0x428, 0xFC, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9	IOMUX_PAD(0x428, 0xFC, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT15__EMI_EMI_DEBUG_44	IOMUX_PAD(0x428, 0xFC, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT15__TPIU_TRACE_12		IOMUX_PAD(0x428, 0xFC, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16		IOMUX_PAD(0x42C, 0x100, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT16__GPIO6_2		IOMUX_PAD(0x42C, 0x100, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT16__UART4_RTS		IOMUX_PAD(0x42C, 0x100, 2, 0x88C, 0, 0)
-#define _MX53_PAD_CSI0_DAT16__USBOH3_USBH3_DATA_4	IOMUX_PAD(0x42C, 0x100, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10	IOMUX_PAD(0x42C, 0x100, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT16__EMI_EMI_DEBUG_45	IOMUX_PAD(0x42C, 0x100, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT16__TPIU_TRACE_13		IOMUX_PAD(0x42C, 0x100, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17		IOMUX_PAD(0x430, 0x104, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT17__GPIO6_3		IOMUX_PAD(0x430, 0x104, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT17__UART4_CTS		IOMUX_PAD(0x430, 0x104, 2, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT17__USBOH3_USBH3_DATA_5	IOMUX_PAD(0x430, 0x104, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11	IOMUX_PAD(0x430, 0x104, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT17__EMI_EMI_DEBUG_46	IOMUX_PAD(0x430, 0x104, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT17__TPIU_TRACE_14		IOMUX_PAD(0x430, 0x104, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18		IOMUX_PAD(0x434, 0x108, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT18__GPIO6_4		IOMUX_PAD(0x434, 0x108, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT18__UART5_RTS		IOMUX_PAD(0x434, 0x108, 2, 0x894, 2, 0)
-#define _MX53_PAD_CSI0_DAT18__USBOH3_USBH3_DATA_6	IOMUX_PAD(0x434, 0x108, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12	IOMUX_PAD(0x434, 0x108, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT18__EMI_EMI_DEBUG_47	IOMUX_PAD(0x434, 0x108, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT18__TPIU_TRACE_15		IOMUX_PAD(0x434, 0x108, 7, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19		IOMUX_PAD(0x438, 0x10C, 0, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT19__GPIO6_5		IOMUX_PAD(0x438, 0x10C, 1, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT19__UART5_CTS		IOMUX_PAD(0x438, 0x10C, 2, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT19__USBOH3_USBH3_DATA_7	IOMUX_PAD(0x438, 0x10C, 4, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13	IOMUX_PAD(0x438, 0x10C, 5, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT19__EMI_EMI_DEBUG_48	IOMUX_PAD(0x438, 0x10C, 6, 0x0, 0, 0)
-#define _MX53_PAD_CSI0_DAT19__USBPHY2_BISTOK	IOMUX_PAD(0x438, 0x10C, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A25__EMI_WEIM_A_25		IOMUX_PAD(0x458, 0x110, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A25__GPIO5_2			IOMUX_PAD(0x458, 0x110, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A25__ECSPI2_RDY		IOMUX_PAD(0x458, 0x110, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A25__IPU_DI1_PIN12		IOMUX_PAD(0x458, 0x110, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A25__CSPI_SS1			IOMUX_PAD(0x458, 0x110, 4, 0x790, 1, 0)
-#define _MX53_PAD_EIM_A25__IPU_DI0_D1_CS		IOMUX_PAD(0x458, 0x110, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A25__USBPHY1_BISTOK		IOMUX_PAD(0x458, 0x110, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB2__EMI_WEIM_EB_2		IOMUX_PAD(0x45C, 0x114, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB2__GPIO2_30			IOMUX_PAD(0x45C, 0x114, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB2__CCM_DI1_EXT_CLK		IOMUX_PAD(0x45C, 0x114, 2, 0x76C, 0, 0)
-#define _MX53_PAD_EIM_EB2__IPU_SER_DISP1_CS		IOMUX_PAD(0x45C, 0x114, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB2__ECSPI1_SS0		IOMUX_PAD(0x45C, 0x114, 4, 0x7A8, 3, 0)
-#define _MX53_PAD_EIM_EB2__I2C2_SCL			IOMUX_PAD(0x45C, 0x114, 5 | IOMUX_CONFIG_SION, 0x81C, 1, 0)
-#define _MX53_PAD_EIM_D16__EMI_WEIM_D_16		IOMUX_PAD(0x460, 0x118, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D16__GPIO3_16			IOMUX_PAD(0x460, 0x118, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D16__IPU_DI0_PIN5		IOMUX_PAD(0x460, 0x118, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D16__IPU_DISPB1_SER_CLK	IOMUX_PAD(0x460, 0x118, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D16__ECSPI1_SCLK		IOMUX_PAD(0x460, 0x118, 4, 0x79C, 3, 0)
-#define _MX53_PAD_EIM_D16__I2C2_SDA			IOMUX_PAD(0x460, 0x118, 5 | IOMUX_CONFIG_SION, 0x820, 1, 0)
-#define _MX53_PAD_EIM_D17__EMI_WEIM_D_17		IOMUX_PAD(0x464, 0x11C, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D17__GPIO3_17			IOMUX_PAD(0x464, 0x11C, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D17__IPU_DI0_PIN6		IOMUX_PAD(0x464, 0x11C, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D17__IPU_DISPB1_SER_DIN	IOMUX_PAD(0x464, 0x11C, 3, 0x830, 0, 0)
-#define _MX53_PAD_EIM_D17__ECSPI1_MISO		IOMUX_PAD(0x464, 0x11C, 4, 0x7A0, 3, 0)
-#define _MX53_PAD_EIM_D17__I2C3_SCL			IOMUX_PAD(0x464, 0x11C, 5 | IOMUX_CONFIG_SION, 0x824, 0, 0)
-#define _MX53_PAD_EIM_D18__EMI_WEIM_D_18		IOMUX_PAD(0x468, 0x120, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D18__GPIO3_18			IOMUX_PAD(0x468, 0x120, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D18__IPU_DI0_PIN7		IOMUX_PAD(0x468, 0x120, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D18__IPU_DISPB1_SER_DIO	IOMUX_PAD(0x468, 0x120, 3, 0x830, 1, 0)
-#define _MX53_PAD_EIM_D18__ECSPI1_MOSI		IOMUX_PAD(0x468, 0x120, 4, 0x7A4, 3, 0)
-#define _MX53_PAD_EIM_D18__I2C3_SDA			IOMUX_PAD(0x468, 0x120, 5 | IOMUX_CONFIG_SION, 0x828, 0, 0)
-#define _MX53_PAD_EIM_D18__IPU_DI1_D0_CS		IOMUX_PAD(0x468, 0x120, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D19__EMI_WEIM_D_19		IOMUX_PAD(0x46C, 0x124, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D19__GPIO3_19			IOMUX_PAD(0x46C, 0x124, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D19__IPU_DI0_PIN8		IOMUX_PAD(0x46C, 0x124, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D19__IPU_DISPB1_SER_RS	IOMUX_PAD(0x46C, 0x124, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D19__ECSPI1_SS1		IOMUX_PAD(0x46C, 0x124, 4, 0x7AC, 2, 0)
-#define _MX53_PAD_EIM_D19__EPIT1_EPITO		IOMUX_PAD(0x46C, 0x124, 5, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D19__UART1_CTS			IOMUX_PAD(0x46C, 0x124, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D19__USBOH3_USBH2_OC		IOMUX_PAD(0x46C, 0x124, 7, 0x8A4, 0, 0)
-#define _MX53_PAD_EIM_D20__EMI_WEIM_D_20		IOMUX_PAD(0x470, 0x128, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D20__GPIO3_20			IOMUX_PAD(0x470, 0x128, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D20__IPU_DI0_PIN16		IOMUX_PAD(0x470, 0x128, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D20__IPU_SER_DISP0_CS		IOMUX_PAD(0x470, 0x128, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D20__CSPI_SS0			IOMUX_PAD(0x470, 0x128, 4, 0x78C, 1, 0)
-#define _MX53_PAD_EIM_D20__EPIT2_EPITO		IOMUX_PAD(0x470, 0x128, 5, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D20__UART1_RTS			IOMUX_PAD(0x470, 0x128, 6, 0x874, 1, 0)
-#define _MX53_PAD_EIM_D20__USBOH3_USBH2_PWR	IOMUX_PAD(0x470, 0x128, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D21__EMI_WEIM_D_21		IOMUX_PAD(0x474, 0x12C, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D21__GPIO3_21			IOMUX_PAD(0x474, 0x12C, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D21__IPU_DI0_PIN17		IOMUX_PAD(0x474, 0x12C, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK	IOMUX_PAD(0x474, 0x12C, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D21__CSPI_SCLK			IOMUX_PAD(0x474, 0x12C, 4, 0x780, 1, 0)
-#define _MX53_PAD_EIM_D21__I2C1_SCL			IOMUX_PAD(0x474, 0x12C, 5 | IOMUX_CONFIG_SION, 0x814, 1, 0)
-#define _MX53_PAD_EIM_D21__USBOH3_USBOTG_OC	IOMUX_PAD(0x474, 0x12C, 6, 0x89C, 1, 0)
-#define _MX53_PAD_EIM_D22__EMI_WEIM_D_22		IOMUX_PAD(0x478, 0x130, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D22__GPIO3_22			IOMUX_PAD(0x478, 0x130, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D22__IPU_DI0_PIN1		IOMUX_PAD(0x478, 0x130, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN	IOMUX_PAD(0x478, 0x130, 3, 0x82C, 0, 0)
-#define _MX53_PAD_EIM_D22__CSPI_MISO			IOMUX_PAD(0x478, 0x130, 4, 0x784, 1, 0)
-#define _MX53_PAD_EIM_D22__USBOH3_USBOTG_PWR	IOMUX_PAD(0x478, 0x130, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D23__EMI_WEIM_D_23		IOMUX_PAD(0x47C, 0x134, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D23__GPIO3_23			IOMUX_PAD(0x47C, 0x134, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D23__UART3_CTS			IOMUX_PAD(0x47C, 0x134, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D23__UART1_DCD		IOMUX_PAD(0x47C, 0x134, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D23__IPU_DI0_D0_CS		IOMUX_PAD(0x47C, 0x134, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D23__IPU_DI1_PIN2		IOMUX_PAD(0x47C, 0x134, 5, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D23__IPU_CSI1_DATA_EN		IOMUX_PAD(0x47C, 0x134, 6, 0x834, 0, 0)
-#define _MX53_PAD_EIM_D23__IPU_DI1_PIN14		IOMUX_PAD(0x47C, 0x134, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB3__EMI_WEIM_EB_3		IOMUX_PAD(0x480, 0x138, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB3__GPIO2_31			IOMUX_PAD(0x480, 0x138, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB3__UART3_RTS			IOMUX_PAD(0x480, 0x138, 2, 0x884, 1, 0)
-#define _MX53_PAD_EIM_EB3__UART1_RI			IOMUX_PAD(0x480, 0x138, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB3__IPU_DI1_PIN3		IOMUX_PAD(0x480, 0x138, 5, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB3__IPU_CSI1_HSYNC		IOMUX_PAD(0x480, 0x138, 6, 0x838, 0, 0)
-#define _MX53_PAD_EIM_EB3__IPU_DI1_PIN16		IOMUX_PAD(0x480, 0x138, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D24__EMI_WEIM_D_24		IOMUX_PAD(0x484, 0x13C, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D24__GPIO3_24			IOMUX_PAD(0x484, 0x13C, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D24__UART3_TXD_MUX		IOMUX_PAD(0x484, 0x13C, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D24__ECSPI1_SS2		IOMUX_PAD(0x484, 0x13C, 3, 0x7B0, 1, 0)
-#define _MX53_PAD_EIM_D24__CSPI_SS2			IOMUX_PAD(0x484, 0x13C, 4, 0x794, 1, 0)
-#define _MX53_PAD_EIM_D24__AUDMUX_AUD5_RXFS	IOMUX_PAD(0x484, 0x13C, 5, 0x754, 1, 0)
-#define _MX53_PAD_EIM_D24__ECSPI2_SS2		IOMUX_PAD(0x484, 0x13C, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D24__UART1_DTR		IOMUX_PAD(0x484, 0x13C, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D25__EMI_WEIM_D_25		IOMUX_PAD(0x488, 0x140, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D25__GPIO3_25			IOMUX_PAD(0x488, 0x140, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D25__UART3_RXD_MUX		IOMUX_PAD(0x488, 0x140, 2, 0x888, 1, 0)
-#define _MX53_PAD_EIM_D25__ECSPI1_SS3		IOMUX_PAD(0x488, 0x140, 3, 0x7B4, 1, 0)
-#define _MX53_PAD_EIM_D25__CSPI_SS3			IOMUX_PAD(0x488, 0x140, 4, 0x798, 1, 0)
-#define _MX53_PAD_EIM_D25__AUDMUX_AUD5_RXC		IOMUX_PAD(0x488, 0x140, 5, 0x750, 1, 0)
-#define _MX53_PAD_EIM_D25__ECSPI2_SS3		IOMUX_PAD(0x488, 0x140, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D25__UART1_DSR		IOMUX_PAD(0x488, 0x140, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D26__EMI_WEIM_D_26		IOMUX_PAD(0x48C, 0x144, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D26__GPIO3_26			IOMUX_PAD(0x48C, 0x144, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D26__UART2_TXD_MUX		IOMUX_PAD(0x48C, 0x144, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D26__FIRI_RXD			IOMUX_PAD(0x48C, 0x144, 3, 0x80C, 0, 0)
-#define _MX53_PAD_EIM_D26__IPU_CSI0_D_1		IOMUX_PAD(0x48C, 0x144, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D26__IPU_DI1_PIN11		IOMUX_PAD(0x48C, 0x144, 5, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D26__IPU_SISG_2		IOMUX_PAD(0x48C, 0x144, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D26__IPU_DISP1_DAT_22		IOMUX_PAD(0x48C, 0x144, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D27__EMI_WEIM_D_27		IOMUX_PAD(0x490, 0x148, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D27__GPIO3_27			IOMUX_PAD(0x490, 0x148, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D27__UART2_RXD_MUX		IOMUX_PAD(0x490, 0x148, 2, 0x880, 1, 0)
-#define _MX53_PAD_EIM_D27__FIRI_TXD			IOMUX_PAD(0x490, 0x148, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D27__IPU_CSI0_D_0		IOMUX_PAD(0x490, 0x148, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D27__IPU_DI1_PIN13		IOMUX_PAD(0x490, 0x148, 5, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D27__IPU_SISG_3		IOMUX_PAD(0x490, 0x148, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D27__IPU_DISP1_DAT_23		IOMUX_PAD(0x490, 0x148, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D28__EMI_WEIM_D_28		IOMUX_PAD(0x494, 0x14C, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D28__GPIO3_28			IOMUX_PAD(0x494, 0x14C, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D28__UART2_CTS			IOMUX_PAD(0x494, 0x14C, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO	IOMUX_PAD(0x494, 0x14C, 3, 0x82C, 1, 0)
-#define _MX53_PAD_EIM_D28__CSPI_MOSI			IOMUX_PAD(0x494, 0x14C, 4, 0x788, 1, 0)
-#define _MX53_PAD_EIM_D28__I2C1_SDA			IOMUX_PAD(0x494, 0x14C, 5 | IOMUX_CONFIG_SION, 0x818, 1, 0)
-#define _MX53_PAD_EIM_D28__IPU_EXT_TRIG		IOMUX_PAD(0x494, 0x14C, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D28__IPU_DI0_PIN13		IOMUX_PAD(0x494, 0x14C, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D29__EMI_WEIM_D_29		IOMUX_PAD(0x498, 0x150, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D29__GPIO3_29			IOMUX_PAD(0x498, 0x150, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D29__UART2_RTS			IOMUX_PAD(0x498, 0x150, 2, 0x87C, 1, 0)
-#define _MX53_PAD_EIM_D29__IPU_DISPB0_SER_RS	IOMUX_PAD(0x498, 0x150, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D29__CSPI_SS0			IOMUX_PAD(0x498, 0x150, 4, 0x78C, 2, 0)
-#define _MX53_PAD_EIM_D29__IPU_DI1_PIN15		IOMUX_PAD(0x498, 0x150, 5, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D29__IPU_CSI1_VSYNC		IOMUX_PAD(0x498, 0x150, 6, 0x83C, 0, 0)
-#define _MX53_PAD_EIM_D29__IPU_DI0_PIN14		IOMUX_PAD(0x498, 0x150, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D30__EMI_WEIM_D_30		IOMUX_PAD(0x49C, 0x154, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D30__GPIO3_30			IOMUX_PAD(0x49C, 0x154, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D30__UART3_CTS			IOMUX_PAD(0x49C, 0x154, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D30__IPU_CSI0_D_3		IOMUX_PAD(0x49C, 0x154, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D30__IPU_DI0_PIN11		IOMUX_PAD(0x49C, 0x154, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D30__IPU_DISP1_DAT_21		IOMUX_PAD(0x49C, 0x154, 5, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D30__USBOH3_USBH1_OC		IOMUX_PAD(0x49C, 0x154, 6, 0x8A0, 0, 0)
-#define _MX53_PAD_EIM_D30__USBOH3_USBH2_OC		IOMUX_PAD(0x49C, 0x154, 7, 0x8A4, 1, 0)
-#define _MX53_PAD_EIM_D31__EMI_WEIM_D_31		IOMUX_PAD(0x4A0, 0x158, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D31__GPIO3_31			IOMUX_PAD(0x4A0, 0x158, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D31__UART3_RTS			IOMUX_PAD(0x4A0, 0x158, 2, 0x884, 3, 0)
-#define _MX53_PAD_EIM_D31__IPU_CSI0_D_2		IOMUX_PAD(0x4A0, 0x158, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D31__IPU_DI0_PIN12		IOMUX_PAD(0x4A0, 0x158, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D31__IPU_DISP1_DAT_20		IOMUX_PAD(0x4A0, 0x158, 5, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D31__USBOH3_USBH1_PWR	IOMUX_PAD(0x4A0, 0x158, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_D31__USBOH3_USBH2_PWR	IOMUX_PAD(0x4A0, 0x158, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A24__EMI_WEIM_A_24		IOMUX_PAD(0x4A8, 0x15C, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A24__GPIO5_4			IOMUX_PAD(0x4A8, 0x15C, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A24__IPU_DISP1_DAT_19		IOMUX_PAD(0x4A8, 0x15C, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A24__IPU_CSI1_D_19		IOMUX_PAD(0x4A8, 0x15C, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A24__IPU_SISG_2		IOMUX_PAD(0x4A8, 0x15C, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A24__USBPHY2_BVALID		IOMUX_PAD(0x4A8, 0x15C, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A23__EMI_WEIM_A_23		IOMUX_PAD(0x4AC, 0x160, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A23__GPIO6_6			IOMUX_PAD(0x4AC, 0x160, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A23__IPU_DISP1_DAT_18		IOMUX_PAD(0x4AC, 0x160, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A23__IPU_CSI1_D_18		IOMUX_PAD(0x4AC, 0x160, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A23__IPU_SISG_3		IOMUX_PAD(0x4AC, 0x160, 6, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A23__USBPHY2_ENDSESSION	IOMUX_PAD(0x4AC, 0x160, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A22__EMI_WEIM_A_22		IOMUX_PAD(0x4B0, 0x164, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A22__GPIO2_16			IOMUX_PAD(0x4B0, 0x164, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A22__IPU_DISP1_DAT_17		IOMUX_PAD(0x4B0, 0x164, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A22__IPU_CSI1_D_17		IOMUX_PAD(0x4B0, 0x164, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A22__SRC_BT_CFG1_7		IOMUX_PAD(0x4B0, 0x164, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A21__EMI_WEIM_A_21		IOMUX_PAD(0x4B4, 0x168, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A21__GPIO2_17			IOMUX_PAD(0x4B4, 0x168, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A21__IPU_DISP1_DAT_16		IOMUX_PAD(0x4B4, 0x168, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A21__IPU_CSI1_D_16		IOMUX_PAD(0x4B4, 0x168, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A21__SRC_BT_CFG1_6		IOMUX_PAD(0x4B4, 0x168, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A20__EMI_WEIM_A_20		IOMUX_PAD(0x4B8, 0x16C, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A20__GPIO2_18			IOMUX_PAD(0x4B8, 0x16C, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A20__IPU_DISP1_DAT_15		IOMUX_PAD(0x4B8, 0x16C, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A20__IPU_CSI1_D_15		IOMUX_PAD(0x4B8, 0x16C, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A20__SRC_BT_CFG1_5		IOMUX_PAD(0x4B8, 0x16C, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A19__EMI_WEIM_A_19		IOMUX_PAD(0x4BC, 0x170, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A19__GPIO2_19			IOMUX_PAD(0x4BC, 0x170, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A19__IPU_DISP1_DAT_14		IOMUX_PAD(0x4BC, 0x170, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A19__IPU_CSI1_D_14		IOMUX_PAD(0x4BC, 0x170, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A19__SRC_BT_CFG1_4		IOMUX_PAD(0x4BC, 0x170, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A18__EMI_WEIM_A_18		IOMUX_PAD(0x4C0, 0x174, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A18__GPIO2_20			IOMUX_PAD(0x4C0, 0x174, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A18__IPU_DISP1_DAT_13		IOMUX_PAD(0x4C0, 0x174, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A18__IPU_CSI1_D_13		IOMUX_PAD(0x4C0, 0x174, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A18__SRC_BT_CFG1_3		IOMUX_PAD(0x4C0, 0x174, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A17__EMI_WEIM_A_17		IOMUX_PAD(0x4C4, 0x178, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A17__GPIO2_21			IOMUX_PAD(0x4C4, 0x178, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A17__IPU_DISP1_DAT_12		IOMUX_PAD(0x4C4, 0x178, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A17__IPU_CSI1_D_12		IOMUX_PAD(0x4C4, 0x178, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A17__SRC_BT_CFG1_2		IOMUX_PAD(0x4C4, 0x178, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A16__EMI_WEIM_A_16		IOMUX_PAD(0x4C8, 0x17C, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A16__GPIO2_22			IOMUX_PAD(0x4C8, 0x17C, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK		IOMUX_PAD(0x4C8, 0x17C, 2, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A16__IPU_CSI1_PIXCLK		IOMUX_PAD(0x4C8, 0x17C, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_A16__SRC_BT_CFG1_1		IOMUX_PAD(0x4C8, 0x17C, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_CS0__EMI_WEIM_CS_0		IOMUX_PAD(0x4CC, 0x180, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_CS0__GPIO2_23			IOMUX_PAD(0x4CC, 0x180, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_CS0__ECSPI2_SCLK		IOMUX_PAD(0x4CC, 0x180, 2, 0x7B8, 2, 0)
-#define _MX53_PAD_EIM_CS0__IPU_DI1_PIN5		IOMUX_PAD(0x4CC, 0x180, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_CS1__EMI_WEIM_CS_1		IOMUX_PAD(0x4D0, 0x184, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_CS1__GPIO2_24			IOMUX_PAD(0x4D0, 0x184, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_CS1__ECSPI2_MOSI		IOMUX_PAD(0x4D0, 0x184, 2, 0x7C0, 2, 0)
-#define _MX53_PAD_EIM_CS1__IPU_DI1_PIN6		IOMUX_PAD(0x4D0, 0x184, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_OE__EMI_WEIM_OE		IOMUX_PAD(0x4D4, 0x188, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_OE__GPIO2_25			IOMUX_PAD(0x4D4, 0x188, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_OE__ECSPI2_MISO		IOMUX_PAD(0x4D4, 0x188, 2, 0x7BC, 2, 0)
-#define _MX53_PAD_EIM_OE__IPU_DI1_PIN7		IOMUX_PAD(0x4D4, 0x188, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_OE__USBPHY2_IDDIG		IOMUX_PAD(0x4D4, 0x188, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_RW__EMI_WEIM_RW		IOMUX_PAD(0x4D8, 0x18C, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_RW__GPIO2_26			IOMUX_PAD(0x4D8, 0x18C, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_RW__ECSPI2_SS0			IOMUX_PAD(0x4D8, 0x18C, 2, 0x7C4, 2, 0)
-#define _MX53_PAD_EIM_RW__IPU_DI1_PIN8		IOMUX_PAD(0x4D8, 0x18C, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_RW__USBPHY2_HOSTDISCONNECT	IOMUX_PAD(0x4D8, 0x18C, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_LBA__EMI_WEIM_LBA		IOMUX_PAD(0x4DC, 0x190, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_LBA__GPIO2_27			IOMUX_PAD(0x4DC, 0x190, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_LBA__ECSPI2_SS1		IOMUX_PAD(0x4DC, 0x190, 2, 0x7C8, 1, 0)
-#define _MX53_PAD_EIM_LBA__IPU_DI1_PIN17		IOMUX_PAD(0x4DC, 0x190, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_LBA__SRC_BT_CFG1_0		IOMUX_PAD(0x4DC, 0x190, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB0__EMI_WEIM_EB_0		IOMUX_PAD(0x4E4, 0x194, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB0__GPIO2_28			IOMUX_PAD(0x4E4, 0x194, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11		IOMUX_PAD(0x4E4, 0x194, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB0__IPU_CSI1_D_11		IOMUX_PAD(0x4E4, 0x194, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB0__GPC_PMIC_RDY		IOMUX_PAD(0x4E4, 0x194, 5, 0x810, 0, 0)
-#define _MX53_PAD_EIM_EB0__SRC_BT_CFG2_7		IOMUX_PAD(0x4E4, 0x194, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB1__EMI_WEIM_EB_1		IOMUX_PAD(0x4E8, 0x198, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB1__GPIO2_29			IOMUX_PAD(0x4E8, 0x198, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10		IOMUX_PAD(0x4E8, 0x198, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB1__IPU_CSI1_D_10		IOMUX_PAD(0x4E8, 0x198, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_EB1__SRC_BT_CFG2_6		IOMUX_PAD(0x4E8, 0x198, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0	IOMUX_PAD(0x4EC, 0x19C, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA0__GPIO3_0			IOMUX_PAD(0x4EC, 0x19C, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9		IOMUX_PAD(0x4EC, 0x19C, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA0__IPU_CSI1_D_9		IOMUX_PAD(0x4EC, 0x19C, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA0__SRC_BT_CFG2_5		IOMUX_PAD(0x4EC, 0x19C, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1	IOMUX_PAD(0x4F0, 0x1A0, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA1__GPIO3_1			IOMUX_PAD(0x4F0, 0x1A0, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8		IOMUX_PAD(0x4F0, 0x1A0, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA1__IPU_CSI1_D_8		IOMUX_PAD(0x4F0, 0x1A0, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA1__SRC_BT_CFG2_4		IOMUX_PAD(0x4F0, 0x1A0, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2	IOMUX_PAD(0x4F4, 0x1A4, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA2__GPIO3_2			IOMUX_PAD(0x4F4, 0x1A4, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7		IOMUX_PAD(0x4F4, 0x1A4, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA2__IPU_CSI1_D_7		IOMUX_PAD(0x4F4, 0x1A4, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA2__SRC_BT_CFG2_3		IOMUX_PAD(0x4F4, 0x1A4, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3	IOMUX_PAD(0x4F8, 0x1A8, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA3__GPIO3_3			IOMUX_PAD(0x4F8, 0x1A8, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6		IOMUX_PAD(0x4F8, 0x1A8, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA3__IPU_CSI1_D_6		IOMUX_PAD(0x4F8, 0x1A8, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA3__SRC_BT_CFG2_2		IOMUX_PAD(0x4F8, 0x1A8, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4	IOMUX_PAD(0x4FC, 0x1AC, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA4__GPIO3_4			IOMUX_PAD(0x4FC, 0x1AC, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5		IOMUX_PAD(0x4FC, 0x1AC, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA4__IPU_CSI1_D_5		IOMUX_PAD(0x4FC, 0x1AC, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA4__SRC_BT_CFG3_7		IOMUX_PAD(0x4FC, 0x1AC, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5	IOMUX_PAD(0x500, 0x1B0, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA5__GPIO3_5			IOMUX_PAD(0x500, 0x1B0, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4		IOMUX_PAD(0x500, 0x1B0, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA5__IPU_CSI1_D_4		IOMUX_PAD(0x500, 0x1B0, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA5__SRC_BT_CFG3_6		IOMUX_PAD(0x500, 0x1B0, 7 | IOMUX_CONFIG_SION, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6	IOMUX_PAD(0x504, 0x1B4, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA6__GPIO3_6			IOMUX_PAD(0x504, 0x1B4, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3		IOMUX_PAD(0x504, 0x1B4, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA6__IPU_CSI1_D_3		IOMUX_PAD(0x504, 0x1B4, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA6__SRC_BT_CFG3_5		IOMUX_PAD(0x504, 0x1B4, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA7__EMI_NAND_WEIM_DA_7	IOMUX_PAD(0x508, 0x1B8, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA7__GPIO3_7			IOMUX_PAD(0x508, 0x1B8, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2		IOMUX_PAD(0x508, 0x1B8, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA7__IPU_CSI1_D_2		IOMUX_PAD(0x508, 0x1B8, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA7__SRC_BT_CFG3_4		IOMUX_PAD(0x508, 0x1B8, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA8__EMI_NAND_WEIM_DA_8	IOMUX_PAD(0x50C, 0x1BC, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA8__GPIO3_8			IOMUX_PAD(0x50C, 0x1BC, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1		IOMUX_PAD(0x50C, 0x1BC, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA8__IPU_CSI1_D_1		IOMUX_PAD(0x50C, 0x1BC, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA8__SRC_BT_CFG3_3		IOMUX_PAD(0x50C, 0x1BC, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA9__EMI_NAND_WEIM_DA_9	IOMUX_PAD(0x510, 0x1C0, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA9__GPIO3_9			IOMUX_PAD(0x510, 0x1C0, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0		IOMUX_PAD(0x510, 0x1C0, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA9__IPU_CSI1_D_0		IOMUX_PAD(0x510, 0x1C0, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA9__SRC_BT_CFG3_2		IOMUX_PAD(0x510, 0x1C0, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA10__EMI_NAND_WEIM_DA_10	IOMUX_PAD(0x514, 0x1C4, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA10__GPIO3_10			IOMUX_PAD(0x514, 0x1C4, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA10__IPU_DI1_PIN15		IOMUX_PAD(0x514, 0x1C4, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA10__IPU_CSI1_DATA_EN	IOMUX_PAD(0x514, 0x1C4, 4, 0x834, 1, 0)
-#define _MX53_PAD_EIM_DA10__SRC_BT_CFG3_1		IOMUX_PAD(0x514, 0x1C4, 7, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA11__EMI_NAND_WEIM_DA_11	IOMUX_PAD(0x518, 0x1C8, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA11__GPIO3_11			IOMUX_PAD(0x518, 0x1C8, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA11__IPU_DI1_PIN2		IOMUX_PAD(0x518, 0x1C8, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA11__IPU_CSI1_HSYNC		IOMUX_PAD(0x518, 0x1C8, 4, 0x838, 1, 0)
-#define _MX53_PAD_EIM_DA12__EMI_NAND_WEIM_DA_12	IOMUX_PAD(0x51C, 0x1CC, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA12__GPIO3_12			IOMUX_PAD(0x51C, 0x1CC, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA12__IPU_DI1_PIN3		IOMUX_PAD(0x51C, 0x1CC, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA12__IPU_CSI1_VSYNC		IOMUX_PAD(0x51C, 0x1CC, 4, 0x83C, 1, 0)
-#define _MX53_PAD_EIM_DA13__EMI_NAND_WEIM_DA_13	IOMUX_PAD(0x520, 0x1D0, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA13__GPIO3_13			IOMUX_PAD(0x520, 0x1D0, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA13__IPU_DI1_D0_CS		IOMUX_PAD(0x520, 0x1D0, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA13__CCM_DI1_EXT_CLK		IOMUX_PAD(0x520, 0x1D0, 4, 0x76C, 1, 0)
-#define _MX53_PAD_EIM_DA14__EMI_NAND_WEIM_DA_14	IOMUX_PAD(0x524, 0x1D4, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA14__GPIO3_14			IOMUX_PAD(0x524, 0x1D4, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA14__IPU_DI1_D1_CS		IOMUX_PAD(0x524, 0x1D4, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA14__CCM_DI0_EXT_CLK		IOMUX_PAD(0x524, 0x1D4, 4, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA15__EMI_NAND_WEIM_DA_15	IOMUX_PAD(0x528, 0x1D8, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA15__GPIO3_15			IOMUX_PAD(0x528, 0x1D8, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA15__IPU_DI1_PIN1		IOMUX_PAD(0x528, 0x1D8, 3, 0x0, 0, 0)
-#define _MX53_PAD_EIM_DA15__IPU_DI1_PIN4		IOMUX_PAD(0x528, 0x1D8, 4, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B	IOMUX_PAD(0x52C, 0x1DC, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_WE_B__GPIO6_12		IOMUX_PAD(0x52C, 0x1DC, 1, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B	IOMUX_PAD(0x530, 0x1E0, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_RE_B__GPIO6_13		IOMUX_PAD(0x530, 0x1E0, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_WAIT__EMI_WEIM_WAIT		IOMUX_PAD(0x534, 0x1E4, 0, 0x0, 0, 0)
-#define _MX53_PAD_EIM_WAIT__GPIO5_0			IOMUX_PAD(0x534, 0x1E4, 1, 0x0, 0, 0)
-#define _MX53_PAD_EIM_WAIT__EMI_WEIM_DTACK_B	IOMUX_PAD(0x534, 0x1E4, 2, 0x0, 0, 0)
-#define _MX53_PAD_LVDS1_TX3_P__GPIO6_22		IOMUX_PAD(NON_PAD_I, 0x1EC, 0, 0x0, 0, 0)
-#define _MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3	IOMUX_PAD(NON_PAD_I, 0x1EC, 1, 0x0, 0, 0)
-#define _MX53_PAD_LVDS1_TX2_P__GPIO6_24		IOMUX_PAD(NON_PAD_I, 0x1F0, 0, 0x0, 0, 0)
-#define _MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2	IOMUX_PAD(NON_PAD_I, 0x1F0, 1, 0x0, 0, 0)
-#define _MX53_PAD_LVDS1_CLK_P__GPIO6_26		IOMUX_PAD(NON_PAD_I, 0x1F4, 0, 0x0, 0, 0)
-#define _MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK	IOMUX_PAD(NON_PAD_I, 0x1F4, 1, 0x0, 0, 0)
-#define _MX53_PAD_LVDS1_TX1_P__GPIO6_28		IOMUX_PAD(NON_PAD_I, 0x1F8, 0, 0x0, 0, 0)
-#define _MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1	IOMUX_PAD(NON_PAD_I, 0x1F8, 1, 0x0, 0, 0)
-#define _MX53_PAD_LVDS1_TX0_P__GPIO6_30		IOMUX_PAD(NON_PAD_I, 0x1FC, 0, 0x0, 0, 0)
-#define _MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0	IOMUX_PAD(NON_PAD_I, 0x1FC, 1, 0x0, 0, 0)
-#define _MX53_PAD_LVDS0_TX3_P__GPIO7_22		IOMUX_PAD(NON_PAD_I, 0x200, 0, 0x0, 0, 0)
-#define _MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3	IOMUX_PAD(NON_PAD_I, 0x200, 1, 0x0, 0, 0)
-#define _MX53_PAD_LVDS0_CLK_P__GPIO7_24		IOMUX_PAD(NON_PAD_I, 0x204, 0, 0x0, 0, 0)
-#define _MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK	IOMUX_PAD(NON_PAD_I, 0x204, 1, 0x0, 0, 0)
-#define _MX53_PAD_LVDS0_TX2_P__GPIO7_26		IOMUX_PAD(NON_PAD_I, 0x208, 0, 0x0, 0, 0)
-#define _MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2	IOMUX_PAD(NON_PAD_I, 0x208, 1, 0x0, 0, 0)
-#define _MX53_PAD_LVDS0_TX1_P__GPIO7_28		IOMUX_PAD(NON_PAD_I, 0x20C, 0, 0x0, 0, 0)
-#define _MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1	IOMUX_PAD(NON_PAD_I, 0x20C, 1, 0x0, 0, 0)
-#define _MX53_PAD_LVDS0_TX0_P__GPIO7_30		IOMUX_PAD(NON_PAD_I, 0x210, 0, 0x0, 0, 0)
-#define _MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0	IOMUX_PAD(NON_PAD_I, 0x210, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_10__GPIO4_0			IOMUX_PAD(0x540, 0x214, 0, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_10__OSC32k_32K_OUT		IOMUX_PAD(0x540, 0x214, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_11__GPIO4_1			IOMUX_PAD(0x544, 0x218, 0, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_12__GPIO4_2			IOMUX_PAD(0x548, 0x21C, 0, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_13__GPIO4_3			IOMUX_PAD(0x54C, 0x220, 0, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_14__GPIO4_4			IOMUX_PAD(0x550, 0x224, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CLE__EMI_NANDF_CLE		IOMUX_PAD(0x5A0, 0x228, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CLE__GPIO6_7			IOMUX_PAD(0x5A0, 0x228, 1, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CLE__USBPHY1_VSTATUS_0	IOMUX_PAD(0x5A0, 0x228, 7, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_ALE__EMI_NANDF_ALE		IOMUX_PAD(0x5A4, 0x22C, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_ALE__GPIO6_8		IOMUX_PAD(0x5A4, 0x22C, 1, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_ALE__USBPHY1_VSTATUS_1	IOMUX_PAD(0x5A4, 0x22C, 7, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B	IOMUX_PAD(0x5A8, 0x230, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_WP_B__GPIO6_9		IOMUX_PAD(0x5A8, 0x230, 1, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_WP_B__USBPHY1_VSTATUS_2	IOMUX_PAD(0x5A8, 0x230, 7, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0	IOMUX_PAD(0x5AC, 0x234, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_RB0__GPIO6_10		IOMUX_PAD(0x5AC, 0x234, 1, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_RB0__USBPHY1_VSTATUS_3	IOMUX_PAD(0x5AC, 0x234, 7, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0	IOMUX_PAD(0x5B0, 0x238, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS0__GPIO6_11		IOMUX_PAD(0x5B0, 0x238, 1, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS0__USBPHY1_VSTATUS_4	IOMUX_PAD(0x5B0, 0x238, 7, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS1__EMI_NANDF_CS_1	IOMUX_PAD(0x5B4, 0x23C, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS1__GPIO6_14		IOMUX_PAD(0x5B4, 0x23C, 1, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS1__MLB_MLBCLK		IOMUX_PAD(0x5B4, 0x23C, 6, 0x858, 0, 0)
-#define _MX53_PAD_NANDF_CS1__USBPHY1_VSTATUS_5	IOMUX_PAD(0x5B4, 0x23C, 7, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS2__EMI_NANDF_CS_2	IOMUX_PAD(0x5B8, 0x240, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS2__GPIO6_15		IOMUX_PAD(0x5B8, 0x240, 1, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS2__IPU_SISG_0		IOMUX_PAD(0x5B8, 0x240, 2, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS2__ESAI1_TX0		IOMUX_PAD(0x5B8, 0x240, 3, 0x7E4, 0, 0)
-#define _MX53_PAD_NANDF_CS2__EMI_WEIM_CRE		IOMUX_PAD(0x5B8, 0x240, 4, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS2__CCM_CSI0_MCLK		IOMUX_PAD(0x5B8, 0x240, 5, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS2__MLB_MLBSIG		IOMUX_PAD(0x5B8, 0x240, 6, 0x860, 0, 0)
-#define _MX53_PAD_NANDF_CS2__USBPHY1_VSTATUS_6	IOMUX_PAD(0x5B8, 0x240, 7, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS3__EMI_NANDF_CS_3	IOMUX_PAD(0x5BC, 0x244, 0, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS3__GPIO6_16		IOMUX_PAD(0x5BC, 0x244, 1, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS3__IPU_SISG_1		IOMUX_PAD(0x5BC, 0x244, 2, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS3__ESAI1_TX1		IOMUX_PAD(0x5BC, 0x244, 3, 0x7E8, 0, 0)
-#define _MX53_PAD_NANDF_CS3__EMI_WEIM_A_26		IOMUX_PAD(0x5BC, 0x244, 4, 0x0, 0, 0)
-#define _MX53_PAD_NANDF_CS3__MLB_MLBDAT		IOMUX_PAD(0x5BC, 0x244, 6, 0x85C, 0, 0)
-#define _MX53_PAD_NANDF_CS3__USBPHY1_VSTATUS_7	IOMUX_PAD(0x5BC, 0x244, 7, 0x0, 0, 0)
-#define _MX53_PAD_FEC_MDIO__FEC_MDIO		IOMUX_PAD(0x5C4, 0x248, 0, 0x804, 1, 0)
-#define _MX53_PAD_FEC_MDIO__GPIO1_22			IOMUX_PAD(0x5C4, 0x248, 1, 0x0, 0, 0)
-#define _MX53_PAD_FEC_MDIO__ESAI1_SCKR		IOMUX_PAD(0x5C4, 0x248, 2, 0x7DC, 0, 0)
-#define _MX53_PAD_FEC_MDIO__FEC_COL			IOMUX_PAD(0x5C4, 0x248, 3, 0x800, 1, 0)
-#define _MX53_PAD_FEC_MDIO__RTC_CE_RTC_PS2		IOMUX_PAD(0x5C4, 0x248, 4, 0x0, 0, 0)
-#define _MX53_PAD_FEC_MDIO__SDMA_DEBUG_BUS_DEVICE_3	IOMUX_PAD(0x5C4, 0x248, 5, 0x0, 0, 0)
-#define _MX53_PAD_FEC_MDIO__EMI_EMI_DEBUG_49	IOMUX_PAD(0x5C4, 0x248, 6, 0x0, 0, 0)
-#define _MX53_PAD_FEC_REF_CLK__FEC_TX_CLK		IOMUX_PAD(0x5C8, 0x24C, 0, 0x0, 0, 0)
-#define _MX53_PAD_FEC_REF_CLK__GPIO1_23		IOMUX_PAD(0x5C8, 0x24C, 1, 0x0, 0, 0)
-#define _MX53_PAD_FEC_REF_CLK__ESAI1_FSR		IOMUX_PAD(0x5C8, 0x24C, 2, 0x7CC, 0, 0)
-#define _MX53_PAD_FEC_REF_CLK__SDMA_DEBUG_BUS_DEVICE_4	IOMUX_PAD(0x5C8, 0x24C, 5, 0x0, 0, 0)
-#define _MX53_PAD_FEC_REF_CLK__EMI_EMI_DEBUG_50	IOMUX_PAD(0x5C8, 0x24C, 6, 0x0, 0, 0)
-#define _MX53_PAD_FEC_RX_ER__FEC_RX_ER		IOMUX_PAD(0x5CC, 0x250, 0, 0x0, 0, 0)
-#define _MX53_PAD_FEC_RX_ER__GPIO1_24		IOMUX_PAD(0x5CC, 0x250, 1, 0x0, 0, 0)
-#define _MX53_PAD_FEC_RX_ER__ESAI1_HCKR		IOMUX_PAD(0x5CC, 0x250, 2, 0x7D4, 0, 0)
-#define _MX53_PAD_FEC_RX_ER__FEC_RX_CLK		IOMUX_PAD(0x5CC, 0x250, 3, 0x808, 1, 0)
-#define _MX53_PAD_FEC_RX_ER__RTC_CE_RTC_PS3		IOMUX_PAD(0x5CC, 0x250, 4, 0x0, 0, 0)
-#define _MX53_PAD_FEC_CRS_DV__FEC_RX_DV		IOMUX_PAD(0x5D0, 0x254, 0, 0x0, 0, 0)
-#define _MX53_PAD_FEC_CRS_DV__GPIO1_25		IOMUX_PAD(0x5D0, 0x254, 1, 0x0, 0, 0)
-#define _MX53_PAD_FEC_CRS_DV__ESAI1_SCKT		IOMUX_PAD(0x5D0, 0x254, 2, 0x7E0, 0, 0)
-#define _MX53_PAD_FEC_RXD1__FEC_RDATA_1		IOMUX_PAD(0x5D4, 0x258, 0, 0x0, 0, 0)
-#define _MX53_PAD_FEC_RXD1__GPIO1_26			IOMUX_PAD(0x5D4, 0x258, 1, 0x0, 0, 0)
-#define _MX53_PAD_FEC_RXD1__ESAI1_FST		IOMUX_PAD(0x5D4, 0x258, 2, 0x7D0, 0, 0)
-#define _MX53_PAD_FEC_RXD1__MLB_MLBSIG		IOMUX_PAD(0x5D4, 0x258, 3, 0x860, 1, 0)
-#define _MX53_PAD_FEC_RXD1__RTC_CE_RTC_PS1		IOMUX_PAD(0x5D4, 0x258, 4, 0x0, 0, 0)
-#define _MX53_PAD_FEC_RXD0__FEC_RDATA_0		IOMUX_PAD(0x5D8, 0x25C, 0, 0x0, 0, 0)
-#define _MX53_PAD_FEC_RXD0__GPIO1_27			IOMUX_PAD(0x5D8, 0x25C, 1, 0x0, 0, 0)
-#define _MX53_PAD_FEC_RXD0__ESAI1_HCKT		IOMUX_PAD(0x5D8, 0x25C, 2, 0x7D8, 0, 0)
-#define _MX53_PAD_FEC_RXD0__OSC32k_32K_OUT		IOMUX_PAD(0x5D8, 0x25C, 3, 0x0, 0, 0)
-#define _MX53_PAD_FEC_TX_EN__FEC_TX_EN		IOMUX_PAD(0x5DC, 0x260, 0, 0x0, 0, 0)
-#define _MX53_PAD_FEC_TX_EN__GPIO1_28		IOMUX_PAD(0x5DC, 0x260, 1, 0x0, 0, 0)
-#define _MX53_PAD_FEC_TX_EN__ESAI1_TX3_RX2		IOMUX_PAD(0x5DC, 0x260, 2, 0x7F0, 0, 0)
-#define _MX53_PAD_FEC_TXD1__FEC_TDATA_1		IOMUX_PAD(0x5E0, 0x264, 0, 0x0, 0, 0)
-#define _MX53_PAD_FEC_TXD1__GPIO1_29			IOMUX_PAD(0x5E0, 0x264, 1, 0x0, 0, 0)
-#define _MX53_PAD_FEC_TXD1__ESAI1_TX2_RX3		IOMUX_PAD(0x5E0, 0x264, 2, 0x7EC, 0, 0)
-#define _MX53_PAD_FEC_TXD1__MLB_MLBCLK		IOMUX_PAD(0x5E0, 0x264, 3, 0x858, 1, 0)
-#define _MX53_PAD_FEC_TXD1__RTC_CE_RTC_PRSC_CLK	IOMUX_PAD(0x5E0, 0x264, 4, 0x0, 0, 0)
-#define _MX53_PAD_FEC_TXD0__FEC_TDATA_0		IOMUX_PAD(0x5E4, 0x268, 0, 0x0, 0, 0)
-#define _MX53_PAD_FEC_TXD0__GPIO1_30			IOMUX_PAD(0x5E4, 0x268, 1, 0x0, 0, 0)
-#define _MX53_PAD_FEC_TXD0__ESAI1_TX4_RX1		IOMUX_PAD(0x5E4, 0x268, 2, 0x7F4, 0, 0)
-#define _MX53_PAD_FEC_TXD0__USBPHY2_DATAOUT_0	IOMUX_PAD(0x5E4, 0x268, 7, 0x0, 0, 0)
-#define _MX53_PAD_FEC_MDC__FEC_MDC			IOMUX_PAD(0x5E8, 0x26C, 0, 0x0, 0, 0)
-#define _MX53_PAD_FEC_MDC__GPIO1_31			IOMUX_PAD(0x5E8, 0x26C, 1, 0x0, 0, 0)
-#define _MX53_PAD_FEC_MDC__ESAI1_TX5_RX0		IOMUX_PAD(0x5E8, 0x26C, 2, 0x7F8, 0, 0)
-#define _MX53_PAD_FEC_MDC__MLB_MLBDAT		IOMUX_PAD(0x5E8, 0x26C, 3, 0x85C, 1, 0)
-#define _MX53_PAD_FEC_MDC__RTC_CE_RTC_ALARM1_TRIG	IOMUX_PAD(0x5E8, 0x26C, 4, 0x0, 0, 0)
-#define _MX53_PAD_FEC_MDC__USBPHY2_DATAOUT_1	IOMUX_PAD(0x5E8, 0x26C, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DIOW__PATA_DIOW		IOMUX_PAD(0x5F0, 0x270, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DIOW__GPIO6_17		IOMUX_PAD(0x5F0, 0x270, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DIOW__UART1_TXD_MUX	IOMUX_PAD(0x5F0, 0x270, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DIOW__USBPHY2_DATAOUT_2	IOMUX_PAD(0x5F0, 0x270, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DMACK__PATA_DMACK		IOMUX_PAD(0x5F4, 0x274, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DMACK__GPIO6_18		IOMUX_PAD(0x5F4, 0x274, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DMACK__UART1_RXD_MUX	IOMUX_PAD(0x5F4, 0x274, 3, 0x878, 3, 0)
-#define _MX53_PAD_PATA_DMACK__USBPHY2_DATAOUT_3	IOMUX_PAD(0x5F4, 0x274, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DMARQ__PATA_DMARQ		IOMUX_PAD(0x5F8, 0x278, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DMARQ__GPIO7_0		IOMUX_PAD(0x5F8, 0x278, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DMARQ__UART2_TXD_MUX	IOMUX_PAD(0x5F8, 0x278, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DMARQ__CCM_CCM_OUT_0	IOMUX_PAD(0x5F8, 0x278, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DMARQ__USBPHY2_DATAOUT_4	IOMUX_PAD(0x5F8, 0x278, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_BUFFER_EN__PATA_BUFFER_EN	IOMUX_PAD(0x5FC, 0x27C, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_BUFFER_EN__GPIO7_1		IOMUX_PAD(0x5FC, 0x27C, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX	IOMUX_PAD(0x5FC, 0x27C, 3, 0x880, 3, 0)
-#define _MX53_PAD_PATA_BUFFER_EN__CCM_CCM_OUT_1	IOMUX_PAD(0x5FC, 0x27C, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_BUFFER_EN__USBPHY2_DATAOUT_5	IOMUX_PAD(0x5FC, 0x27C, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_INTRQ__PATA_INTRQ		IOMUX_PAD(0x600, 0x280, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_INTRQ__GPIO7_2		IOMUX_PAD(0x600, 0x280, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_INTRQ__UART2_CTS		IOMUX_PAD(0x600, 0x280, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_INTRQ__CAN1_TXCAN		IOMUX_PAD(0x600, 0x280, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_INTRQ__CCM_CCM_OUT_2	IOMUX_PAD(0x600, 0x280, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_INTRQ__USBPHY2_DATAOUT_6	IOMUX_PAD(0x600, 0x280, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DIOR__PATA_DIOR		IOMUX_PAD(0x604, 0x284, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DIOR__GPIO7_3			IOMUX_PAD(0x604, 0x284, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DIOR__UART2_RTS		IOMUX_PAD(0x604, 0x284, 3, 0x87C, 3, 0)
-#define _MX53_PAD_PATA_DIOR__CAN1_RXCAN		IOMUX_PAD(0x604, 0x284, 4, 0x760, 1, 0)
-#define _MX53_PAD_PATA_DIOR__USBPHY2_DATAOUT_7	IOMUX_PAD(0x604, 0x284, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_RESET_B__PATA_PATA_RESET_B	IOMUX_PAD(0x608, 0x288, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_RESET_B__GPIO7_4		IOMUX_PAD(0x608, 0x288, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_RESET_B__ESDHC3_CMD		IOMUX_PAD(0x608, 0x288, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_RESET_B__UART1_CTS		IOMUX_PAD(0x608, 0x288, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_RESET_B__CAN2_TXCAN		IOMUX_PAD(0x608, 0x288, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_RESET_B__USBPHY1_DATAOUT_0	IOMUX_PAD(0x608, 0x288, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_IORDY__PATA_IORDY		IOMUX_PAD(0x60C, 0x28C, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_IORDY__GPIO7_5		IOMUX_PAD(0x60C, 0x28C, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_IORDY__ESDHC3_CLK		IOMUX_PAD(0x60C, 0x28C, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_IORDY__UART1_RTS		IOMUX_PAD(0x60C, 0x28C, 3, 0x874, 3, 0)
-#define _MX53_PAD_PATA_IORDY__CAN2_RXCAN		IOMUX_PAD(0x60C, 0x28C, 4, 0x764, 1, 0)
-#define _MX53_PAD_PATA_IORDY__USBPHY1_DATAOUT_1	IOMUX_PAD(0x60C, 0x28C, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_0__PATA_DA_0		IOMUX_PAD(0x610, 0x290, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_0__GPIO7_6		IOMUX_PAD(0x610, 0x290, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_0__ESDHC3_RST		IOMUX_PAD(0x610, 0x290, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_0__OWIRE_LINE		IOMUX_PAD(0x610, 0x290, 4, 0x864, 0, 0)
-#define _MX53_PAD_PATA_DA_0__USBPHY1_DATAOUT_2	IOMUX_PAD(0x610, 0x290, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_1__PATA_DA_1		IOMUX_PAD(0x614, 0x294, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_1__GPIO7_7		IOMUX_PAD(0x614, 0x294, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_1__ESDHC4_CMD		IOMUX_PAD(0x614, 0x294, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_1__UART3_CTS		IOMUX_PAD(0x614, 0x294, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_1__USBPHY1_DATAOUT_3	IOMUX_PAD(0x614, 0x294, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_2__PATA_DA_2		IOMUX_PAD(0x618, 0x298, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_2__GPIO7_8		IOMUX_PAD(0x618, 0x298, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_2__ESDHC4_CLK		IOMUX_PAD(0x618, 0x298, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DA_2__UART3_RTS		IOMUX_PAD(0x618, 0x298, 4, 0x884, 5, 0)
-#define _MX53_PAD_PATA_DA_2__USBPHY1_DATAOUT_4	IOMUX_PAD(0x618, 0x298, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_CS_0__PATA_CS_0		IOMUX_PAD(0x61C, 0x29C, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_CS_0__GPIO7_9			IOMUX_PAD(0x61C, 0x29C, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_CS_0__UART3_TXD_MUX		IOMUX_PAD(0x61C, 0x29C, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_CS_0__USBPHY1_DATAOUT_5	IOMUX_PAD(0x61C, 0x29C, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_CS_1__PATA_CS_1		IOMUX_PAD(0x620, 0x2A0, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_CS_1__GPIO7_10		IOMUX_PAD(0x620, 0x2A0, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_CS_1__UART3_RXD_MUX		IOMUX_PAD(0x620, 0x2A0, 4, 0x888, 3, 0)
-#define _MX53_PAD_PATA_CS_1__USBPHY1_DATAOUT_6	IOMUX_PAD(0x620, 0x2A0, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA0__PATA_DATA_0		IOMUX_PAD(0x628, 0x2A4, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA0__GPIO2_0		IOMUX_PAD(0x628, 0x2A4, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA0__EMI_NANDF_D_0	IOMUX_PAD(0x628, 0x2A4, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA0__ESDHC3_DAT4		IOMUX_PAD(0x628, 0x2A4, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA0__GPU3d_GPU_DEBUG_OUT_0	IOMUX_PAD(0x628, 0x2A4, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA0__IPU_DIAG_BUS_0	IOMUX_PAD(0x628, 0x2A4, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA0__USBPHY1_DATAOUT_7	IOMUX_PAD(0x628, 0x2A4, 7, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA1__PATA_DATA_1		IOMUX_PAD(0x62C, 0x2A8, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA1__GPIO2_1		IOMUX_PAD(0x62C, 0x2A8, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA1__EMI_NANDF_D_1	IOMUX_PAD(0x62C, 0x2A8, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA1__ESDHC3_DAT5		IOMUX_PAD(0x62C, 0x2A8, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA1__GPU3d_GPU_DEBUG_OUT_1	IOMUX_PAD(0x62C, 0x2A8, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA1__IPU_DIAG_BUS_1	IOMUX_PAD(0x62C, 0x2A8, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA2__PATA_DATA_2		IOMUX_PAD(0x630, 0x2AC, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA2__GPIO2_2		IOMUX_PAD(0x630, 0x2AC, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA2__EMI_NANDF_D_2	IOMUX_PAD(0x630, 0x2AC, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA2__ESDHC3_DAT6		IOMUX_PAD(0x630, 0x2AC, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA2__GPU3d_GPU_DEBUG_OUT_2	IOMUX_PAD(0x630, 0x2AC, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA2__IPU_DIAG_BUS_2	IOMUX_PAD(0x630, 0x2AC, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA3__PATA_DATA_3		IOMUX_PAD(0x634, 0x2B0, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA3__GPIO2_3		IOMUX_PAD(0x634, 0x2B0, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA3__EMI_NANDF_D_3	IOMUX_PAD(0x634, 0x2B0, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA3__ESDHC3_DAT7		IOMUX_PAD(0x634, 0x2B0, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA3__GPU3d_GPU_DEBUG_OUT_3	IOMUX_PAD(0x634, 0x2B0, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA3__IPU_DIAG_BUS_3	IOMUX_PAD(0x634, 0x2B0, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA4__PATA_DATA_4		IOMUX_PAD(0x638, 0x2B4, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA4__GPIO2_4		IOMUX_PAD(0x638, 0x2B4, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA4__EMI_NANDF_D_4	IOMUX_PAD(0x638, 0x2B4, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA4__ESDHC4_DAT4		IOMUX_PAD(0x638, 0x2B4, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA4__GPU3d_GPU_DEBUG_OUT_4	IOMUX_PAD(0x638, 0x2B4, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA4__IPU_DIAG_BUS_4	IOMUX_PAD(0x638, 0x2B4, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA5__PATA_DATA_5	IOMUX_PAD(0x63C, 0x2B8, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA5__GPIO2_5		IOMUX_PAD(0x63C, 0x2B8, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA5__EMI_NANDF_D_5	IOMUX_PAD(0x63C, 0x2B8, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA5__ESDHC4_DAT5		IOMUX_PAD(0x63C, 0x2B8, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA5__GPU3d_GPU_DEBUG_OUT_5	IOMUX_PAD(0x63C, 0x2B8, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA5__IPU_DIAG_BUS_5	IOMUX_PAD(0x63C, 0x2B8, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA6__PATA_DATA_6	IOMUX_PAD(0x640, 0x2BC, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA6__GPIO2_6		IOMUX_PAD(0x640, 0x2BC, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA6__EMI_NANDF_D_6	IOMUX_PAD(0x640, 0x2BC, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA6__ESDHC4_DAT6		IOMUX_PAD(0x640, 0x2BC, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA6__GPU3d_GPU_DEBUG_OUT_6	IOMUX_PAD(0x640, 0x2BC, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA6__IPU_DIAG_BUS_6	IOMUX_PAD(0x640, 0x2BC, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA7__PATA_DATA_7		IOMUX_PAD(0x644, 0x2C0, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA7__GPIO2_7		IOMUX_PAD(0x644, 0x2C0, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA7__EMI_NANDF_D_7	IOMUX_PAD(0x644, 0x2C0, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA7__ESDHC4_DAT7		IOMUX_PAD(0x644, 0x2C0, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA7__GPU3d_GPU_DEBUG_OUT_7	IOMUX_PAD(0x644, 0x2C0, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA7__IPU_DIAG_BUS_7	IOMUX_PAD(0x644, 0x2C0, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA8__PATA_DATA_8		IOMUX_PAD(0x648, 0x2C4, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA8__GPIO2_8		IOMUX_PAD(0x648, 0x2C4, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA8__ESDHC1_DAT4		IOMUX_PAD(0x648, 0x2C4, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA8__EMI_NANDF_D_8	IOMUX_PAD(0x648, 0x2C4, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA8__ESDHC3_DAT0		IOMUX_PAD(0x648, 0x2C4, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA8__GPU3d_GPU_DEBUG_OUT_8	IOMUX_PAD(0x648, 0x2C4, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA8__IPU_DIAG_BUS_8	IOMUX_PAD(0x648, 0x2C4, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA9__PATA_DATA_9		IOMUX_PAD(0x64C, 0x2C8, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA9__GPIO2_9		IOMUX_PAD(0x64C, 0x2C8, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA9__ESDHC1_DAT5		IOMUX_PAD(0x64C, 0x2C8, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA9__EMI_NANDF_D_9	IOMUX_PAD(0x64C, 0x2C8, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA9__ESDHC3_DAT1		IOMUX_PAD(0x64C, 0x2C8, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA9__GPU3d_GPU_DEBUG_OUT_9	IOMUX_PAD(0x64C, 0x2C8, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA9__IPU_DIAG_BUS_9	IOMUX_PAD(0x64C, 0x2C8, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA10__PATA_DATA_10	IOMUX_PAD(0x650, 0x2CC, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA10__GPIO2_10		IOMUX_PAD(0x650, 0x2CC, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA10__ESDHC1_DAT6		IOMUX_PAD(0x650, 0x2CC, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA10__EMI_NANDF_D_10	IOMUX_PAD(0x650, 0x2CC, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA10__ESDHC3_DAT2		IOMUX_PAD(0x650, 0x2CC, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA10__GPU3d_GPU_DEBUG_OUT_10	IOMUX_PAD(0x650, 0x2CC, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA10__IPU_DIAG_BUS_10	IOMUX_PAD(0x650, 0x2CC, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA11__PATA_DATA_11	IOMUX_PAD(0x654, 0x2D0, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA11__GPIO2_11		IOMUX_PAD(0x654, 0x2D0, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA11__ESDHC1_DAT7		IOMUX_PAD(0x654, 0x2D0, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA11__EMI_NANDF_D_11	IOMUX_PAD(0x654, 0x2D0, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA11__ESDHC3_DAT3		IOMUX_PAD(0x654, 0x2D0, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA11__GPU3d_GPU_DEBUG_OUT_11	IOMUX_PAD(0x654, 0x2D0, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA11__IPU_DIAG_BUS_11	IOMUX_PAD(0x654, 0x2D0, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA12__PATA_DATA_12	IOMUX_PAD(0x658, 0x2D4, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA12__GPIO2_12		IOMUX_PAD(0x658, 0x2D4, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA12__ESDHC2_DAT4		IOMUX_PAD(0x658, 0x2D4, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA12__EMI_NANDF_D_12	IOMUX_PAD(0x658, 0x2D4, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA12__ESDHC4_DAT0		IOMUX_PAD(0x658, 0x2D4, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA12__GPU3d_GPU_DEBUG_OUT_12	IOMUX_PAD(0x658, 0x2D4, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA12__IPU_DIAG_BUS_12	IOMUX_PAD(0x658, 0x2D4, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA13__PATA_DATA_13	IOMUX_PAD(0x65C, 0x2D8, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA13__GPIO2_13		IOMUX_PAD(0x65C, 0x2D8, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA13__ESDHC2_DAT5		IOMUX_PAD(0x65C, 0x2D8, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA13__EMI_NANDF_D_13	IOMUX_PAD(0x65C, 0x2D8, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA13__ESDHC4_DAT1		IOMUX_PAD(0x65C, 0x2D8, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA13__GPU3d_GPU_DEBUG_OUT_13	IOMUX_PAD(0x65C, 0x2D8, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA13__IPU_DIAG_BUS_13	IOMUX_PAD(0x65C, 0x2D8, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA14__PATA_DATA_14	IOMUX_PAD(0x660, 0x2DC, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA14__GPIO2_14		IOMUX_PAD(0x660, 0x2DC, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA14__ESDHC2_DAT6		IOMUX_PAD(0x660, 0x2DC, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA14__EMI_NANDF_D_14	IOMUX_PAD(0x660, 0x2DC, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA14__ESDHC4_DAT2		IOMUX_PAD(0x660, 0x2DC, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA14__GPU3d_GPU_DEBUG_OUT_14	IOMUX_PAD(0x660, 0x2DC, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA14__IPU_DIAG_BUS_14	IOMUX_PAD(0x660, 0x2DC, 6, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA15__PATA_DATA_15	IOMUX_PAD(0x664, 0x2E0, 0, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA15__GPIO2_15		IOMUX_PAD(0x664, 0x2E0, 1, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA15__ESDHC2_DAT7		IOMUX_PAD(0x664, 0x2E0, 2, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA15__EMI_NANDF_D_15	IOMUX_PAD(0x664, 0x2E0, 3, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA15__ESDHC4_DAT3		IOMUX_PAD(0x664, 0x2E0, 4, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA15__GPU3d_GPU_DEBUG_OUT_15	IOMUX_PAD(0x664, 0x2E0, 5, 0x0, 0, 0)
-#define _MX53_PAD_PATA_DATA15__IPU_DIAG_BUS_15	IOMUX_PAD(0x664, 0x2E0, 6, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA0__ESDHC1_DAT0	IOMUX_PAD(0x66C, 0x2E4, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA0__GPIO1_16	IOMUX_PAD(0x66C, 0x2E4, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA0__GPT_CAPIN1	IOMUX_PAD(0x66C, 0x2E4, 3, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA0__CSPI_MISO	IOMUX_PAD(0x66C, 0x2E4, 5, 0x784, 2, 0)
-#define _MX53_PAD_SD1_DATA0__CCM_PLL3_BYP	IOMUX_PAD(0x66C, 0x2E4, 7, 0x778, 0, 0)
-#define _MX53_PAD_SD1_DATA1__ESDHC1_DAT1	IOMUX_PAD(0x670, 0x2E8, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA1__GPIO1_17	IOMUX_PAD(0x670, 0x2E8, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA1__GPT_CAPIN2	IOMUX_PAD(0x670, 0x2E8, 3, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA1__CSPI_SS0	IOMUX_PAD(0x670, 0x2E8, 5, 0x78C, 3, 0)
-#define _MX53_PAD_SD1_DATA1__CCM_PLL4_BYP	IOMUX_PAD(0x670, 0x2E8, 7, 0x77C, 1, 0)
-#define _MX53_PAD_SD1_CMD__ESDHC1_CMD	IOMUX_PAD(0x674, 0x2EC, IOMUX_CONFIG_SION, 0x0, 0, 0)
-#define _MX53_PAD_SD1_CMD__GPIO1_18		IOMUX_PAD(0x674, 0x2EC, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD1_CMD__GPT_CMPOUT1	IOMUX_PAD(0x674, 0x2EC, 3, 0x0, 0, 0)
-#define _MX53_PAD_SD1_CMD__CSPI_MOSI		IOMUX_PAD(0x674, 0x2EC, 5, 0x788, 2, 0)
-#define _MX53_PAD_SD1_CMD__CCM_PLL1_BYP	IOMUX_PAD(0x674, 0x2EC, 7, 0x770, 0, 0)
-#define _MX53_PAD_SD1_DATA2__ESDHC1_DAT2		IOMUX_PAD(0x678, 0x2F0, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA2__GPIO1_19		IOMUX_PAD(0x678, 0x2F0, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA2__GPT_CMPOUT2		IOMUX_PAD(0x678, 0x2F0, 2, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA2__PWM2_PWMO		IOMUX_PAD(0x678, 0x2F0, 3, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA2__WDOG1_WDOG_B		IOMUX_PAD(0x678, 0x2F0, 4, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA2__CSPI_SS1		IOMUX_PAD(0x678, 0x2F0, 5, 0x790, 2, 0)
-#define _MX53_PAD_SD1_DATA2__WDOG1_WDOG_RST_B_DEB	IOMUX_PAD(0x678, 0x2F0, 6, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA2__CCM_PLL2_BYP		IOMUX_PAD(0x678, 0x2F0, 7, 0x774, 0, 0)
-#define _MX53_PAD_SD1_CLK__ESDHC1_CLK	IOMUX_PAD(0x67C, 0x2F4, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD1_CLK__GPIO1_20		IOMUX_PAD(0x67C, 0x2F4, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD1_CLK__OSC32k_32K_OUT	IOMUX_PAD(0x67C, 0x2F4, 2, 0x0, 0, 0)
-#define _MX53_PAD_SD1_CLK__GPT_CLKIN		IOMUX_PAD(0x67C, 0x2F4, 3, 0x0, 0, 0)
-#define _MX53_PAD_SD1_CLK__CSPI_SCLK		IOMUX_PAD(0x67C, 0x2F4, 5, 0x780, 2, 0)
-#define _MX53_PAD_SD1_CLK__SATA_PHY_DTB_0	IOMUX_PAD(0x67C, 0x2F4, 7, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA3__ESDHC1_DAT3	IOMUX_PAD(0x680, 0x2F8, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA3__GPIO1_21	IOMUX_PAD(0x680, 0x2F8, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA3__GPT_CMPOUT3	IOMUX_PAD(0x680, 0x2F8, 2, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA3__PWM1_PWMO	IOMUX_PAD(0x680, 0x2F8, 3, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA3__WDOG2_WDOG_B	IOMUX_PAD(0x680, 0x2F8, 4, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA3__CSPI_SS2	IOMUX_PAD(0x680, 0x2F8, 5, 0x794, 2, 0)
-#define _MX53_PAD_SD1_DATA3__WDOG2_WDOG_RST_B_DEB	IOMUX_PAD(0x680, 0x2F8, 6, 0x0, 0, 0)
-#define _MX53_PAD_SD1_DATA3__SATA_PHY_DTB_1	IOMUX_PAD(0x680, 0x2F8, 7, 0x0, 0, 0)
-#define _MX53_PAD_SD2_CLK__ESDHC2_CLK	IOMUX_PAD(0x688, 0x2FC, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD2_CLK__GPIO1_10		IOMUX_PAD(0x688, 0x2FC, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD2_CLK__KPP_COL_5		IOMUX_PAD(0x688, 0x2FC, 2, 0x840, 2, 0)
-#define _MX53_PAD_SD2_CLK__AUDMUX_AUD4_RXFS	IOMUX_PAD(0x688, 0x2FC, 3, 0x73C, 1, 0)
-#define _MX53_PAD_SD2_CLK__CSPI_SCLK		IOMUX_PAD(0x688, 0x2FC, 5, 0x780, 3, 0)
-#define _MX53_PAD_SD2_CLK__SCC_RANDOM_V	IOMUX_PAD(0x688, 0x2FC, 7, 0x0, 0, 0)
-#define _MX53_PAD_SD2_CMD__ESDHC2_CMD	IOMUX_PAD(0x68C, 0x300, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD2_CMD__GPIO1_11		IOMUX_PAD(0x68C, 0x300, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD2_CMD__KPP_ROW_5	IOMUX_PAD(0x68C, 0x300, 2, 0x84C, 1, 0)
-#define _MX53_PAD_SD2_CMD__AUDMUX_AUD4_RXC	IOMUX_PAD(0x68C, 0x300, 3, 0x738, 1, 0)
-#define _MX53_PAD_SD2_CMD__CSPI_MOSI		IOMUX_PAD(0x68C, 0x300, 5, 0x788, 3, 0)
-#define _MX53_PAD_SD2_CMD__SCC_RANDOM	IOMUX_PAD(0x68C, 0x300, 7, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA3__ESDHC2_DAT3	IOMUX_PAD(0x690, 0x304, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA3__GPIO1_12	IOMUX_PAD(0x690, 0x304, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA3__KPP_COL_6	IOMUX_PAD(0x690, 0x304, 2, 0x844, 1, 0)
-#define _MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC	IOMUX_PAD(0x690, 0x304, 3, 0x740, 1, 0)
-#define _MX53_PAD_SD2_DATA3__CSPI_SS2	IOMUX_PAD(0x690, 0x304, 5, 0x794, 3, 0)
-#define _MX53_PAD_SD2_DATA3__SJC_DONE	IOMUX_PAD(0x690, 0x304, 7, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA2__ESDHC2_DAT2	IOMUX_PAD(0x694, 0x308, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA2__GPIO1_13	IOMUX_PAD(0x694, 0x308, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA2__KPP_ROW_6	IOMUX_PAD(0x694, 0x308, 2, 0x850, 1, 0)
-#define _MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD	IOMUX_PAD(0x694, 0x308, 3, 0x734, 1, 0)
-#define _MX53_PAD_SD2_DATA2__CSPI_SS1	IOMUX_PAD(0x694, 0x308, 5, 0x790, 3, 0)
-#define _MX53_PAD_SD2_DATA2__SJC_FAIL	IOMUX_PAD(0x694, 0x308, 7, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA1__ESDHC2_DAT1	IOMUX_PAD(0x698, 0x30C, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA1__GPIO1_14	IOMUX_PAD(0x698, 0x30C, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA1__KPP_COL_7	IOMUX_PAD(0x698, 0x30C, 2, 0x848, 1, 0)
-#define _MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS	IOMUX_PAD(0x698, 0x30C, 3, 0x744, 0, 0)
-#define _MX53_PAD_SD2_DATA1__CSPI_SS0	IOMUX_PAD(0x698, 0x30C, 5, 0x78C, 4, 0)
-#define _MX53_PAD_SD2_DATA1__RTIC_SEC_VIO	IOMUX_PAD(0x698, 0x30C, 7, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA0__ESDHC2_DAT0	IOMUX_PAD(0x69C, 0x310, 0, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA0__GPIO1_15	IOMUX_PAD(0x69C, 0x310, 1, 0x0, 0, 0)
-#define _MX53_PAD_SD2_DATA0__KPP_ROW_7	IOMUX_PAD(0x69C, 0x310, 2, 0x854, 1, 0)
-#define _MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD	IOMUX_PAD(0x69C, 0x310, 3, 0x730, 1, 0)
-#define _MX53_PAD_SD2_DATA0__CSPI_MISO	IOMUX_PAD(0x69C, 0x310, 5, 0x784, 3, 0)
-#define _MX53_PAD_SD2_DATA0__RTIC_DONE_INT	IOMUX_PAD(0x69C, 0x310, 7, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_0__CCM_CLKO		IOMUX_PAD(0x6A4, 0x314, 0, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_0__GPIO1_0		IOMUX_PAD(0x6A4, 0x314, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_0__KPP_COL_5		IOMUX_PAD(0x6A4, 0x314, 2, 0x840, 3, 0)
-#define _MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK	IOMUX_PAD(0x6A4, 0x314, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_0__EPIT1_EPITO	IOMUX_PAD(0x6A4, 0x314, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_0__SRTC_ALARM_DEB	IOMUX_PAD(0x6A4, 0x314, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_0__USBOH3_USBH1_PWR	IOMUX_PAD(0x6A4, 0x314, 6, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_0__CSU_TD		IOMUX_PAD(0x6A4, 0x314, 7, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_1__ESAI1_SCKR		IOMUX_PAD(0x6A8, 0x318, 0, 0x7DC, 1, 0)
-#define _MX53_PAD_GPIO_1__GPIO1_1		IOMUX_PAD(0x6A8, 0x318, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_1__KPP_ROW_5		IOMUX_PAD(0x6A8, 0x318, 2, 0x84C, 2, 0)
-#define _MX53_PAD_GPIO_1__CCM_SSI_EXT2_CLK	IOMUX_PAD(0x6A8, 0x318, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_1__PWM2_PWMO	IOMUX_PAD(0x6A8, 0x318, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_1__WDOG2_WDOG_B	IOMUX_PAD(0x6A8, 0x318, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_1__ESDHC1_CD		IOMUX_PAD(0x6A8, 0x318, 6, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_1__SRC_TESTER_ACK	IOMUX_PAD(0x6A8, 0x318, 7, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_9__ESAI1_FSR		IOMUX_PAD(0x6AC, 0x31C, 0, 0x7CC, 1, 0)
-#define _MX53_PAD_GPIO_9__GPIO1_9		IOMUX_PAD(0x6AC, 0x31C, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_9__KPP_COL_6		IOMUX_PAD(0x6AC, 0x31C, 2, 0x844, 2, 0)
-#define _MX53_PAD_GPIO_9__CCM_REF_EN_B	IOMUX_PAD(0x6AC, 0x31C, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_9__PWM1_PWMO	IOMUX_PAD(0x6AC, 0x31C, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_9__WDOG1_WDOG_B	IOMUX_PAD(0x6AC, 0x31C, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_9__ESDHC1_WP		IOMUX_PAD(0x6AC, 0x31C, 6, 0x7FC, 1, 0)
-#define _MX53_PAD_GPIO_9__SCC_FAIL_STATE	IOMUX_PAD(0x6AC, 0x31C, 7, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_3__ESAI1_HCKR		IOMUX_PAD(0x6B0, 0x320, 0, 0x7D4, 1, 0)
-#define _MX53_PAD_GPIO_3__GPIO1_3		IOMUX_PAD(0x6B0, 0x320, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_3__I2C3_SCL		IOMUX_PAD(0x6B0, 0x320, 2 | IOMUX_CONFIG_SION, 0x824, 1, 0)
-#define _MX53_PAD_GPIO_3__DPLLIP1_TOG_EN	IOMUX_PAD(0x6B0, 0x320, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_3__CCM_CLKO2		IOMUX_PAD(0x6B0, 0x320, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_3__OBSERVE_MUX_OBSRV_INT_OUT0	IOMUX_PAD(0x6B0, 0x320, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_3__USBOH3_USBH1_OC	IOMUX_PAD(0x6B0, 0x320, 6, 0x8A0, 1, 0)
-#define _MX53_PAD_GPIO_3__MLB_MLBCLK		IOMUX_PAD(0x6B0, 0x320, 7, 0x858, 2, 0)
-#define _MX53_PAD_GPIO_6__ESAI1_SCKT		IOMUX_PAD(0x6B4, 0x324, 0, 0x7E0, 1, 0)
-#define _MX53_PAD_GPIO_6__GPIO1_6		IOMUX_PAD(0x6B4, 0x324, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_6__I2C3_SDA		IOMUX_PAD(0x6B4, 0x324, 2 | IOMUX_CONFIG_SION, 0x828, 1, 0)
-#define _MX53_PAD_GPIO_6__CCM_CCM_OUT_0	IOMUX_PAD(0x6B4, 0x324, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_6__CSU_CSU_INT_DEB	IOMUX_PAD(0x6B4, 0x324, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1	IOMUX_PAD(0x6B4, 0x324, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_6__ESDHC2_LCTL	IOMUX_PAD(0x6B4, 0x324, 6, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_6__MLB_MLBSIG		IOMUX_PAD(0x6B4, 0x324, 7, 0x860, 2, 0)
-#define _MX53_PAD_GPIO_2__ESAI1_FST		IOMUX_PAD(0x6B8, 0x328, 0, 0x7D0, 1, 0)
-#define _MX53_PAD_GPIO_2__GPIO1_2		IOMUX_PAD(0x6B8, 0x328, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_2__KPP_ROW_6		IOMUX_PAD(0x6B8, 0x328, 2, 0x850, 2, 0)
-#define _MX53_PAD_GPIO_2__CCM_CCM_OUT_1	IOMUX_PAD(0x6B8, 0x328, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0	IOMUX_PAD(0x6B8, 0x328, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_2__OBSERVE_MUX_OBSRV_INT_OUT2	IOMUX_PAD(0x6B8, 0x328, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_2__ESDHC2_WP		IOMUX_PAD(0x6B8, 0x328, 6, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_2__MLB_MLBDAT	IOMUX_PAD(0x6B8, 0x328, 7, 0x85C, 2, 0)
-#define _MX53_PAD_GPIO_4__ESAI1_HCKT		IOMUX_PAD(0x6BC, 0x32C, 0, 0x7D8, 1, 0)
-#define _MX53_PAD_GPIO_4__GPIO1_4		IOMUX_PAD(0x6BC, 0x32C, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_4__KPP_COL_7		IOMUX_PAD(0x6BC, 0x32C, 2, 0x848, 2, 0)
-#define _MX53_PAD_GPIO_4__CCM_CCM_OUT_2	IOMUX_PAD(0x6BC, 0x32C, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1	IOMUX_PAD(0x6BC, 0x32C, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_4__OBSERVE_MUX_OBSRV_INT_OUT3	IOMUX_PAD(0x6BC, 0x32C, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_4__ESDHC2_CD		IOMUX_PAD(0x6BC, 0x32C, 6, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_4__SCC_SEC_STATE	IOMUX_PAD(0x6BC, 0x32C, 7, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_5__ESAI1_TX2_RX3	IOMUX_PAD(0x6C0, 0x330, 0, 0x7EC, 1, 0)
-#define _MX53_PAD_GPIO_5__GPIO1_5		IOMUX_PAD(0x6C0, 0x330, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_5__KPP_ROW_7		IOMUX_PAD(0x6C0, 0x330, 2, 0x854, 2, 0)
-#define _MX53_PAD_GPIO_5__CCM_CLKO		IOMUX_PAD(0x6C0, 0x330, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2	IOMUX_PAD(0x6C0, 0x330, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_5__OBSERVE_MUX_OBSRV_INT_OUT4	IOMUX_PAD(0x6C0, 0x330, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_5__I2C3_SCL		IOMUX_PAD(0x6C0, 0x330, 6 | IOMUX_CONFIG_SION, 0x824, 2, 0)
-#define _MX53_PAD_GPIO_5__CCM_PLL1_BYP	IOMUX_PAD(0x6C0, 0x330, 7, 0x770, 1, 0)
-#define _MX53_PAD_GPIO_7__ESAI1_TX4_RX1	IOMUX_PAD(0x6C4, 0x334, 0, 0x7F4, 1, 0)
-#define _MX53_PAD_GPIO_7__GPIO1_7		IOMUX_PAD(0x6C4, 0x334, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_7__EPIT1_EPITO	IOMUX_PAD(0x6C4, 0x334, 2, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_7__CAN1_TXCAN	IOMUX_PAD(0x6C4, 0x334, 3, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_7__UART2_TXD_MUX	IOMUX_PAD(0x6C4, 0x334, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_7__FIRI_RXD		IOMUX_PAD(0x6C4, 0x334, 5, 0x80C, 1, 0)
-#define _MX53_PAD_GPIO_7__SPDIF_PLOCK	IOMUX_PAD(0x6C4, 0x334, 6, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_7__CCM_PLL2_BYP	IOMUX_PAD(0x6C4, 0x334, 7, 0x774, 1, 0)
-#define _MX53_PAD_GPIO_8__ESAI1_TX5_RX0	IOMUX_PAD(0x6C8, 0x338, 0, 0x7F8, 1, 0)
-#define _MX53_PAD_GPIO_8__GPIO1_8		IOMUX_PAD(0x6C8, 0x338, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_8__EPIT2_EPITO	IOMUX_PAD(0x6C8, 0x338, 2, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_8__CAN1_RXCAN	IOMUX_PAD(0x6C8, 0x338, 3, 0x760, 3, 0)
-#define _MX53_PAD_GPIO_8__UART2_RXD_MUX	IOMUX_PAD(0x6C8, 0x338, 4, 0x880, 5, 0)
-#define _MX53_PAD_GPIO_8__FIRI_TXD		IOMUX_PAD(0x6C8, 0x338, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_8__SPDIF_SRCLK	IOMUX_PAD(0x6C8, 0x338, 6, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_8__CCM_PLL3_BYP	IOMUX_PAD(0x6C8, 0x338, 7, 0x778, 1, 0)
-#define _MX53_PAD_GPIO_16__ESAI1_TX3_RX2	IOMUX_PAD(0x6CC, 0x33C, 0, 0x7F0, 1, 0)
-#define _MX53_PAD_GPIO_16__GPIO7_11		IOMUX_PAD(0x6CC, 0x33C, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_16__TZIC_PWRFAIL_INT	IOMUX_PAD(0x6CC, 0x33C, 2, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_16__RTC_CE_RTC_EXT_TRIG1	IOMUX_PAD(0x6CC, 0x33C, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_16__SPDIF_IN1		IOMUX_PAD(0x6CC, 0x33C, 5, 0x870, 1, 0)
-#define _MX53_PAD_GPIO_16__I2C3_SDA		IOMUX_PAD(0x6CC, 0x33C, 6 | IOMUX_CONFIG_SION, 0x828, 2, 0)
-#define _MX53_PAD_GPIO_16__SJC_DE_B		IOMUX_PAD(0x6CC, 0x33C, 7, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_17__ESAI1_TX0		IOMUX_PAD(0x6D0, 0x340, 0, 0x7E4, 1, 0)
-#define _MX53_PAD_GPIO_17__GPIO7_12		IOMUX_PAD(0x6D0, 0x340, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_17__SDMA_EXT_EVENT_0	IOMUX_PAD(0x6D0, 0x340, 2, 0x868, 1, 0)
-#define _MX53_PAD_GPIO_17__GPC_PMIC_RDY	IOMUX_PAD(0x6D0, 0x340, 3, 0x810, 1, 0)
-#define _MX53_PAD_GPIO_17__RTC_CE_RTC_FSV_TRIG	IOMUX_PAD(0x6D0, 0x340, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_17__SPDIF_OUT1	IOMUX_PAD(0x6D0, 0x340, 5, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_17__IPU_SNOOP2	IOMUX_PAD(0x6D0, 0x340, 6, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_17__SJC_JTAG_ACT	IOMUX_PAD(0x6D0, 0x340, 7, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_18__ESAI1_TX1		IOMUX_PAD(0x6D4, 0x344, 0, 0x7E8, 1, 0)
-#define _MX53_PAD_GPIO_18__GPIO7_13		IOMUX_PAD(0x6D4, 0x344, 1, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_18__SDMA_EXT_EVENT_1	IOMUX_PAD(0x6D4, 0x344, 2, 0x86C, 1, 0)
-#define _MX53_PAD_GPIO_18__OWIRE_LINE	IOMUX_PAD(0x6D4, 0x344, 3, 0x864, 1, 0)
-#define _MX53_PAD_GPIO_18__RTC_CE_RTC_ALARM2_TRIG	IOMUX_PAD(0x6D4, 0x344, 4, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_18__CCM_ASRC_EXT_CLK	IOMUX_PAD(0x6D4, 0x344, 5, 0x768, 1, 0)
-#define _MX53_PAD_GPIO_18__ESDHC1_LCTL	IOMUX_PAD(0x6D4, 0x344, 6, 0x0, 0, 0)
-#define _MX53_PAD_GPIO_18__SRC_SYSTEM_RST	IOMUX_PAD(0x6D4, 0x344, 7, 0x0, 0, 0)
 
-#define MX53_PAD_GPIO_19__KPP_COL_5		(_MX53_PAD_GPIO_19__KPP_COL_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_19__GPIO4_5		(_MX53_PAD_GPIO_19__GPIO4_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_19__CCM_CLKO		(_MX53_PAD_GPIO_19__CCM_CLKO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_19__SPDIF_OUT1		(_MX53_PAD_GPIO_19__SPDIF_OUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_19__RTC_CE_RTC_EXT_TRIG2		(_MX53_PAD_GPIO_19__RTC_CE_RTC_EXT_TRIG2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_19__ECSPI1_RDY		(_MX53_PAD_GPIO_19__ECSPI1_RDY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_19__FEC_TDATA_3		(_MX53_PAD_GPIO_19__FEC_TDATA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_19__SRC_INT_BOOT		(_MX53_PAD_GPIO_19__SRC_INT_BOOT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL0__KPP_COL_0		(_MX53_PAD_KEY_COL0__KPP_COL_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL0__GPIO4_6		(_MX53_PAD_KEY_COL0__GPIO4_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC		(_MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL0__UART4_TXD_MUX		(_MX53_PAD_KEY_COL0__UART4_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_KEY_COL0__ECSPI1_SCLK		(_MX53_PAD_KEY_COL0__ECSPI1_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL0__FEC_RDATA_3		(_MX53_PAD_KEY_COL0__FEC_RDATA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL0__SRC_ANY_PU_RST		(_MX53_PAD_KEY_COL0__SRC_ANY_PU_RST | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW0__KPP_ROW_0		(_MX53_PAD_KEY_ROW0__KPP_ROW_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW0__GPIO4_7		(_MX53_PAD_KEY_ROW0__GPIO4_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD		(_MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW0__UART4_RXD_MUX		(_MX53_PAD_KEY_ROW0__UART4_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_KEY_ROW0__ECSPI1_MOSI		(_MX53_PAD_KEY_ROW0__ECSPI1_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW0__FEC_TX_ER		(_MX53_PAD_KEY_ROW0__FEC_TX_ER | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL1__KPP_COL_1		(_MX53_PAD_KEY_COL1__KPP_COL_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL1__GPIO4_8		(_MX53_PAD_KEY_COL1__GPIO4_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS		(_MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL1__UART5_TXD_MUX		(_MX53_PAD_KEY_COL1__UART5_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_KEY_COL1__ECSPI1_MISO		(_MX53_PAD_KEY_COL1__ECSPI1_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL1__FEC_RX_CLK		(_MX53_PAD_KEY_COL1__FEC_RX_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL1__USBPHY1_TXREADY		(_MX53_PAD_KEY_COL1__USBPHY1_TXREADY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW1__KPP_ROW_1		(_MX53_PAD_KEY_ROW1__KPP_ROW_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW1__GPIO4_9		(_MX53_PAD_KEY_ROW1__GPIO4_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD		(_MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW1__UART5_RXD_MUX		(_MX53_PAD_KEY_ROW1__UART5_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_KEY_ROW1__ECSPI1_SS0		(_MX53_PAD_KEY_ROW1__ECSPI1_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW1__FEC_COL		(_MX53_PAD_KEY_ROW1__FEC_COL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW1__USBPHY1_RXVALID		(_MX53_PAD_KEY_ROW1__USBPHY1_RXVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL2__KPP_COL_2		(_MX53_PAD_KEY_COL2__KPP_COL_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL2__GPIO4_10		(_MX53_PAD_KEY_COL2__GPIO4_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL2__CAN1_TXCAN		(_MX53_PAD_KEY_COL2__CAN1_TXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL2__FEC_MDIO		(_MX53_PAD_KEY_COL2__FEC_MDIO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL2__ECSPI1_SS1		(_MX53_PAD_KEY_COL2__ECSPI1_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL2__FEC_RDATA_2		(_MX53_PAD_KEY_COL2__FEC_RDATA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL2__USBPHY1_RXACTIVE		(_MX53_PAD_KEY_COL2__USBPHY1_RXACTIVE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW2__KPP_ROW_2		(_MX53_PAD_KEY_ROW2__KPP_ROW_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW2__GPIO4_11		(_MX53_PAD_KEY_ROW2__GPIO4_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW2__CAN1_RXCAN		(_MX53_PAD_KEY_ROW2__CAN1_RXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW2__FEC_MDC		(_MX53_PAD_KEY_ROW2__FEC_MDC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW2__ECSPI1_SS2		(_MX53_PAD_KEY_ROW2__ECSPI1_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW2__FEC_TDATA_2		(_MX53_PAD_KEY_ROW2__FEC_TDATA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW2__USBPHY1_RXERROR		(_MX53_PAD_KEY_ROW2__USBPHY1_RXERROR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL3__KPP_COL_3		(_MX53_PAD_KEY_COL3__KPP_COL_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL3__GPIO4_12		(_MX53_PAD_KEY_COL3__GPIO4_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL3__USBOH3_H2_DP		(_MX53_PAD_KEY_COL3__USBOH3_H2_DP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL3__SPDIF_IN1		(_MX53_PAD_KEY_COL3__SPDIF_IN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL3__I2C2_SCL		(_MX53_PAD_KEY_COL3__I2C2_SCL | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_KEY_COL3__ECSPI1_SS3		(_MX53_PAD_KEY_COL3__ECSPI1_SS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL3__FEC_CRS		(_MX53_PAD_KEY_COL3__FEC_CRS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL3__USBPHY1_SIECLOCK		(_MX53_PAD_KEY_COL3__USBPHY1_SIECLOCK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW3__KPP_ROW_3		(_MX53_PAD_KEY_ROW3__KPP_ROW_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW3__GPIO4_13		(_MX53_PAD_KEY_ROW3__GPIO4_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW3__USBOH3_H2_DM		(_MX53_PAD_KEY_ROW3__USBOH3_H2_DM | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW3__CCM_ASRC_EXT_CLK		(_MX53_PAD_KEY_ROW3__CCM_ASRC_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW3__I2C2_SDA		(_MX53_PAD_KEY_ROW3__I2C2_SDA | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_KEY_ROW3__OSC32K_32K_OUT		(_MX53_PAD_KEY_ROW3__OSC32K_32K_OUT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW3__CCM_PLL4_BYP		(_MX53_PAD_KEY_ROW3__CCM_PLL4_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW3__USBPHY1_LINESTATE_0		(_MX53_PAD_KEY_ROW3__USBPHY1_LINESTATE_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL4__KPP_COL_4		(_MX53_PAD_KEY_COL4__KPP_COL_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL4__GPIO4_14		(_MX53_PAD_KEY_COL4__GPIO4_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL4__CAN2_TXCAN		(_MX53_PAD_KEY_COL4__CAN2_TXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL4__IPU_SISG_4		(_MX53_PAD_KEY_COL4__IPU_SISG_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL4__UART5_RTS		(_MX53_PAD_KEY_COL4__UART5_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_KEY_COL4__USBOH3_USBOTG_OC		(_MX53_PAD_KEY_COL4__USBOH3_USBOTG_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_COL4__USBPHY1_LINESTATE_1		(_MX53_PAD_KEY_COL4__USBPHY1_LINESTATE_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW4__KPP_ROW_4		(_MX53_PAD_KEY_ROW4__KPP_ROW_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW4__GPIO4_15		(_MX53_PAD_KEY_ROW4__GPIO4_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW4__CAN2_RXCAN		(_MX53_PAD_KEY_ROW4__CAN2_RXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW4__IPU_SISG_5		(_MX53_PAD_KEY_ROW4__IPU_SISG_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW4__UART5_CTS		(_MX53_PAD_KEY_ROW4__UART5_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_KEY_ROW4__USBOH3_USBOTG_PWR		(_MX53_PAD_KEY_ROW4__USBOH3_USBOTG_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_KEY_ROW4__USBPHY1_VBUSVALID		(_MX53_PAD_KEY_ROW4__USBPHY1_VBUSVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK		(_MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_DISP_CLK__GPIO4_16		(_MX53_PAD_DI0_DISP_CLK__GPIO4_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_DISP_CLK__USBOH3_USBH2_DIR		(_MX53_PAD_DI0_DISP_CLK__USBOH3_USBH2_DIR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_DISP_CLK__SDMA_DEBUG_CORE_STATE_0		(_MX53_PAD_DI0_DISP_CLK__SDMA_DEBUG_CORE_STATE_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_DISP_CLK__EMI_EMI_DEBUG_0		(_MX53_PAD_DI0_DISP_CLK__EMI_EMI_DEBUG_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_DISP_CLK__USBPHY1_AVALID		(_MX53_PAD_DI0_DISP_CLK__USBPHY1_AVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN15__IPU_DI0_PIN15		(_MX53_PAD_DI0_PIN15__IPU_DI0_PIN15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN15__GPIO4_17		(_MX53_PAD_DI0_PIN15__GPIO4_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN15__AUDMUX_AUD6_TXC		(_MX53_PAD_DI0_PIN15__AUDMUX_AUD6_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN15__SDMA_DEBUG_CORE_STATE_1		(_MX53_PAD_DI0_PIN15__SDMA_DEBUG_CORE_STATE_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN15__EMI_EMI_DEBUG_1		(_MX53_PAD_DI0_PIN15__EMI_EMI_DEBUG_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN15__USBPHY1_BVALID		(_MX53_PAD_DI0_PIN15__USBPHY1_BVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN2__IPU_DI0_PIN2		(_MX53_PAD_DI0_PIN2__IPU_DI0_PIN2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN2__GPIO4_18		(_MX53_PAD_DI0_PIN2__GPIO4_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN2__AUDMUX_AUD6_TXD		(_MX53_PAD_DI0_PIN2__AUDMUX_AUD6_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN2__SDMA_DEBUG_CORE_STATE_2		(_MX53_PAD_DI0_PIN2__SDMA_DEBUG_CORE_STATE_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN2__EMI_EMI_DEBUG_2		(_MX53_PAD_DI0_PIN2__EMI_EMI_DEBUG_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN2__USBPHY1_ENDSESSION		(_MX53_PAD_DI0_PIN2__USBPHY1_ENDSESSION | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN3__IPU_DI0_PIN3		(_MX53_PAD_DI0_PIN3__IPU_DI0_PIN3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN3__GPIO4_19		(_MX53_PAD_DI0_PIN3__GPIO4_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS		(_MX53_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN3__SDMA_DEBUG_CORE_STATE_3		(_MX53_PAD_DI0_PIN3__SDMA_DEBUG_CORE_STATE_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN3__EMI_EMI_DEBUG_3		(_MX53_PAD_DI0_PIN3__EMI_EMI_DEBUG_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN3__USBPHY1_IDDIG		(_MX53_PAD_DI0_PIN3__USBPHY1_IDDIG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN4__IPU_DI0_PIN4		(_MX53_PAD_DI0_PIN4__IPU_DI0_PIN4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN4__GPIO4_20		(_MX53_PAD_DI0_PIN4__GPIO4_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN4__AUDMUX_AUD6_RXD		(_MX53_PAD_DI0_PIN4__AUDMUX_AUD6_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN4__ESDHC1_WP		(_MX53_PAD_DI0_PIN4__ESDHC1_WP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN4__SDMA_DEBUG_YIELD		(_MX53_PAD_DI0_PIN4__SDMA_DEBUG_YIELD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN4__EMI_EMI_DEBUG_4		(_MX53_PAD_DI0_PIN4__EMI_EMI_DEBUG_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DI0_PIN4__USBPHY1_HOSTDISCONNECT		(_MX53_PAD_DI0_PIN4__USBPHY1_HOSTDISCONNECT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0		(_MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT0__GPIO4_21		(_MX53_PAD_DISP0_DAT0__GPIO4_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT0__CSPI_SCLK		(_MX53_PAD_DISP0_DAT0__CSPI_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT0__USBOH3_USBH2_DATA_0		(_MX53_PAD_DISP0_DAT0__USBOH3_USBH2_DATA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT0__SDMA_DEBUG_CORE_RUN		(_MX53_PAD_DISP0_DAT0__SDMA_DEBUG_CORE_RUN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT0__EMI_EMI_DEBUG_5		(_MX53_PAD_DISP0_DAT0__EMI_EMI_DEBUG_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT0__USBPHY2_TXREADY		(_MX53_PAD_DISP0_DAT0__USBPHY2_TXREADY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1		(_MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT1__GPIO4_22		(_MX53_PAD_DISP0_DAT1__GPIO4_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT1__CSPI_MOSI		(_MX53_PAD_DISP0_DAT1__CSPI_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT1__USBOH3_USBH2_DATA_1		(_MX53_PAD_DISP0_DAT1__USBOH3_USBH2_DATA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT1__SDMA_DEBUG_EVENT_CHANNEL_SEL		(_MX53_PAD_DISP0_DAT1__SDMA_DEBUG_EVENT_CHANNEL_SEL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT1__EMI_EMI_DEBUG_6		(_MX53_PAD_DISP0_DAT1__EMI_EMI_DEBUG_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT1__USBPHY2_RXVALID		(_MX53_PAD_DISP0_DAT1__USBPHY2_RXVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2		(_MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT2__GPIO4_23		(_MX53_PAD_DISP0_DAT2__GPIO4_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT2__CSPI_MISO		(_MX53_PAD_DISP0_DAT2__CSPI_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT2__USBOH3_USBH2_DATA_2		(_MX53_PAD_DISP0_DAT2__USBOH3_USBH2_DATA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT2__SDMA_DEBUG_MODE		(_MX53_PAD_DISP0_DAT2__SDMA_DEBUG_MODE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT2__EMI_EMI_DEBUG_7		(_MX53_PAD_DISP0_DAT2__EMI_EMI_DEBUG_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT2__USBPHY2_RXACTIVE		(_MX53_PAD_DISP0_DAT2__USBPHY2_RXACTIVE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3		(_MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT3__GPIO4_24		(_MX53_PAD_DISP0_DAT3__GPIO4_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT3__CSPI_SS0		(_MX53_PAD_DISP0_DAT3__CSPI_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT3__USBOH3_USBH2_DATA_3		(_MX53_PAD_DISP0_DAT3__USBOH3_USBH2_DATA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT3__SDMA_DEBUG_BUS_ERROR		(_MX53_PAD_DISP0_DAT3__SDMA_DEBUG_BUS_ERROR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT3__EMI_EMI_DEBUG_8		(_MX53_PAD_DISP0_DAT3__EMI_EMI_DEBUG_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT3__USBPHY2_RXERROR		(_MX53_PAD_DISP0_DAT3__USBPHY2_RXERROR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4		(_MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT4__GPIO4_25		(_MX53_PAD_DISP0_DAT4__GPIO4_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT4__CSPI_SS1		(_MX53_PAD_DISP0_DAT4__CSPI_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT4__USBOH3_USBH2_DATA_4		(_MX53_PAD_DISP0_DAT4__USBOH3_USBH2_DATA_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB		(_MX53_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT4__EMI_EMI_DEBUG_9		(_MX53_PAD_DISP0_DAT4__EMI_EMI_DEBUG_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT4__USBPHY2_SIECLOCK		(_MX53_PAD_DISP0_DAT4__USBPHY2_SIECLOCK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5		(_MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT5__GPIO4_26		(_MX53_PAD_DISP0_DAT5__GPIO4_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT5__CSPI_SS2		(_MX53_PAD_DISP0_DAT5__CSPI_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT5__USBOH3_USBH2_DATA_5		(_MX53_PAD_DISP0_DAT5__USBOH3_USBH2_DATA_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT5__SDMA_DEBUG_MATCHED_DMBUS		(_MX53_PAD_DISP0_DAT5__SDMA_DEBUG_MATCHED_DMBUS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT5__EMI_EMI_DEBUG_10		(_MX53_PAD_DISP0_DAT5__EMI_EMI_DEBUG_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT5__USBPHY2_LINESTATE_0		(_MX53_PAD_DISP0_DAT5__USBPHY2_LINESTATE_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6		(_MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT6__GPIO4_27		(_MX53_PAD_DISP0_DAT6__GPIO4_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT6__CSPI_SS3		(_MX53_PAD_DISP0_DAT6__CSPI_SS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT6__USBOH3_USBH2_DATA_6		(_MX53_PAD_DISP0_DAT6__USBOH3_USBH2_DATA_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT6__SDMA_DEBUG_RTBUFFER_WRITE		(_MX53_PAD_DISP0_DAT6__SDMA_DEBUG_RTBUFFER_WRITE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT6__EMI_EMI_DEBUG_11		(_MX53_PAD_DISP0_DAT6__EMI_EMI_DEBUG_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT6__USBPHY2_LINESTATE_1		(_MX53_PAD_DISP0_DAT6__USBPHY2_LINESTATE_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7		(_MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT7__GPIO4_28		(_MX53_PAD_DISP0_DAT7__GPIO4_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT7__CSPI_RDY		(_MX53_PAD_DISP0_DAT7__CSPI_RDY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT7__USBOH3_USBH2_DATA_7		(_MX53_PAD_DISP0_DAT7__USBOH3_USBH2_DATA_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT7__SDMA_DEBUG_EVENT_CHANNEL_0		(_MX53_PAD_DISP0_DAT7__SDMA_DEBUG_EVENT_CHANNEL_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT7__EMI_EMI_DEBUG_12		(_MX53_PAD_DISP0_DAT7__EMI_EMI_DEBUG_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT7__USBPHY2_VBUSVALID		(_MX53_PAD_DISP0_DAT7__USBPHY2_VBUSVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8		(_MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT8__GPIO4_29		(_MX53_PAD_DISP0_DAT8__GPIO4_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT8__PWM1_PWMO		(_MX53_PAD_DISP0_DAT8__PWM1_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT8__WDOG1_WDOG_B		(_MX53_PAD_DISP0_DAT8__WDOG1_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT8__SDMA_DEBUG_EVENT_CHANNEL_1		(_MX53_PAD_DISP0_DAT8__SDMA_DEBUG_EVENT_CHANNEL_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT8__EMI_EMI_DEBUG_13		(_MX53_PAD_DISP0_DAT8__EMI_EMI_DEBUG_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT8__USBPHY2_AVALID		(_MX53_PAD_DISP0_DAT8__USBPHY2_AVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9		(_MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT9__GPIO4_30		(_MX53_PAD_DISP0_DAT9__GPIO4_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT9__PWM2_PWMO		(_MX53_PAD_DISP0_DAT9__PWM2_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT9__WDOG2_WDOG_B		(_MX53_PAD_DISP0_DAT9__WDOG2_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT9__SDMA_DEBUG_EVENT_CHANNEL_2		(_MX53_PAD_DISP0_DAT9__SDMA_DEBUG_EVENT_CHANNEL_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT9__EMI_EMI_DEBUG_14		(_MX53_PAD_DISP0_DAT9__EMI_EMI_DEBUG_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT9__USBPHY2_VSTATUS_0		(_MX53_PAD_DISP0_DAT9__USBPHY2_VSTATUS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10		(_MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT10__GPIO4_31		(_MX53_PAD_DISP0_DAT10__GPIO4_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT10__USBOH3_USBH2_STP		(_MX53_PAD_DISP0_DAT10__USBOH3_USBH2_STP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT10__SDMA_DEBUG_EVENT_CHANNEL_3		(_MX53_PAD_DISP0_DAT10__SDMA_DEBUG_EVENT_CHANNEL_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT10__EMI_EMI_DEBUG_15		(_MX53_PAD_DISP0_DAT10__EMI_EMI_DEBUG_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT10__USBPHY2_VSTATUS_1		(_MX53_PAD_DISP0_DAT10__USBPHY2_VSTATUS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11		(_MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT11__GPIO5_5		(_MX53_PAD_DISP0_DAT11__GPIO5_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT11__USBOH3_USBH2_NXT		(_MX53_PAD_DISP0_DAT11__USBOH3_USBH2_NXT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT11__SDMA_DEBUG_EVENT_CHANNEL_4		(_MX53_PAD_DISP0_DAT11__SDMA_DEBUG_EVENT_CHANNEL_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT11__EMI_EMI_DEBUG_16		(_MX53_PAD_DISP0_DAT11__EMI_EMI_DEBUG_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT11__USBPHY2_VSTATUS_2		(_MX53_PAD_DISP0_DAT11__USBPHY2_VSTATUS_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12		(_MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT12__GPIO5_6		(_MX53_PAD_DISP0_DAT12__GPIO5_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT12__USBOH3_USBH2_CLK		(_MX53_PAD_DISP0_DAT12__USBOH3_USBH2_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT12__SDMA_DEBUG_EVENT_CHANNEL_5		(_MX53_PAD_DISP0_DAT12__SDMA_DEBUG_EVENT_CHANNEL_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT12__EMI_EMI_DEBUG_17		(_MX53_PAD_DISP0_DAT12__EMI_EMI_DEBUG_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT12__USBPHY2_VSTATUS_3		(_MX53_PAD_DISP0_DAT12__USBPHY2_VSTATUS_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13		(_MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT13__GPIO5_7		(_MX53_PAD_DISP0_DAT13__GPIO5_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS		(_MX53_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT13__SDMA_DEBUG_EVT_CHN_LINES_0		(_MX53_PAD_DISP0_DAT13__SDMA_DEBUG_EVT_CHN_LINES_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT13__EMI_EMI_DEBUG_18		(_MX53_PAD_DISP0_DAT13__EMI_EMI_DEBUG_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT13__USBPHY2_VSTATUS_4		(_MX53_PAD_DISP0_DAT13__USBPHY2_VSTATUS_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14		(_MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT14__GPIO5_8		(_MX53_PAD_DISP0_DAT14__GPIO5_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC		(_MX53_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT14__SDMA_DEBUG_EVT_CHN_LINES_1		(_MX53_PAD_DISP0_DAT14__SDMA_DEBUG_EVT_CHN_LINES_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT14__EMI_EMI_DEBUG_19		(_MX53_PAD_DISP0_DAT14__EMI_EMI_DEBUG_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT14__USBPHY2_VSTATUS_5		(_MX53_PAD_DISP0_DAT14__USBPHY2_VSTATUS_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15		(_MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT15__GPIO5_9		(_MX53_PAD_DISP0_DAT15__GPIO5_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT15__ECSPI1_SS1		(_MX53_PAD_DISP0_DAT15__ECSPI1_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT15__ECSPI2_SS1		(_MX53_PAD_DISP0_DAT15__ECSPI2_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT15__SDMA_DEBUG_EVT_CHN_LINES_2		(_MX53_PAD_DISP0_DAT15__SDMA_DEBUG_EVT_CHN_LINES_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT15__EMI_EMI_DEBUG_20		(_MX53_PAD_DISP0_DAT15__EMI_EMI_DEBUG_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT15__USBPHY2_VSTATUS_6		(_MX53_PAD_DISP0_DAT15__USBPHY2_VSTATUS_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16		(_MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT16__GPIO5_10		(_MX53_PAD_DISP0_DAT16__GPIO5_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT16__ECSPI2_MOSI		(_MX53_PAD_DISP0_DAT16__ECSPI2_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC		(_MX53_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT16__SDMA_EXT_EVENT_0		(_MX53_PAD_DISP0_DAT16__SDMA_EXT_EVENT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT16__SDMA_DEBUG_EVT_CHN_LINES_3		(_MX53_PAD_DISP0_DAT16__SDMA_DEBUG_EVT_CHN_LINES_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT16__EMI_EMI_DEBUG_21		(_MX53_PAD_DISP0_DAT16__EMI_EMI_DEBUG_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT16__USBPHY2_VSTATUS_7		(_MX53_PAD_DISP0_DAT16__USBPHY2_VSTATUS_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17		(_MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT17__GPIO5_11		(_MX53_PAD_DISP0_DAT17__GPIO5_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT17__ECSPI2_MISO		(_MX53_PAD_DISP0_DAT17__ECSPI2_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD		(_MX53_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT17__SDMA_EXT_EVENT_1		(_MX53_PAD_DISP0_DAT17__SDMA_EXT_EVENT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT17__SDMA_DEBUG_EVT_CHN_LINES_4		(_MX53_PAD_DISP0_DAT17__SDMA_DEBUG_EVT_CHN_LINES_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT17__EMI_EMI_DEBUG_22		(_MX53_PAD_DISP0_DAT17__EMI_EMI_DEBUG_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18		(_MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT18__GPIO5_12		(_MX53_PAD_DISP0_DAT18__GPIO5_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT18__ECSPI2_SS0		(_MX53_PAD_DISP0_DAT18__ECSPI2_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS		(_MX53_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS		(_MX53_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT18__SDMA_DEBUG_EVT_CHN_LINES_5		(_MX53_PAD_DISP0_DAT18__SDMA_DEBUG_EVT_CHN_LINES_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT18__EMI_EMI_DEBUG_23		(_MX53_PAD_DISP0_DAT18__EMI_EMI_DEBUG_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT18__EMI_WEIM_CS_2		(_MX53_PAD_DISP0_DAT18__EMI_WEIM_CS_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19		(_MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT19__GPIO5_13		(_MX53_PAD_DISP0_DAT19__GPIO5_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT19__ECSPI2_SCLK		(_MX53_PAD_DISP0_DAT19__ECSPI2_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD		(_MX53_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC		(_MX53_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT19__SDMA_DEBUG_EVT_CHN_LINES_6		(_MX53_PAD_DISP0_DAT19__SDMA_DEBUG_EVT_CHN_LINES_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT19__EMI_EMI_DEBUG_24		(_MX53_PAD_DISP0_DAT19__EMI_EMI_DEBUG_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT19__EMI_WEIM_CS_3		(_MX53_PAD_DISP0_DAT19__EMI_WEIM_CS_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20		(_MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT20__GPIO5_14		(_MX53_PAD_DISP0_DAT20__GPIO5_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT20__ECSPI1_SCLK		(_MX53_PAD_DISP0_DAT20__ECSPI1_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC		(_MX53_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT20__SDMA_DEBUG_EVT_CHN_LINES_7		(_MX53_PAD_DISP0_DAT20__SDMA_DEBUG_EVT_CHN_LINES_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT20__EMI_EMI_DEBUG_25		(_MX53_PAD_DISP0_DAT20__EMI_EMI_DEBUG_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT20__SATA_PHY_TDI		(_MX53_PAD_DISP0_DAT20__SATA_PHY_TDI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21		(_MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT21__GPIO5_15		(_MX53_PAD_DISP0_DAT21__GPIO5_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT21__ECSPI1_MOSI		(_MX53_PAD_DISP0_DAT21__ECSPI1_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD		(_MX53_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT21__SDMA_DEBUG_BUS_DEVICE_0		(_MX53_PAD_DISP0_DAT21__SDMA_DEBUG_BUS_DEVICE_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT21__EMI_EMI_DEBUG_26		(_MX53_PAD_DISP0_DAT21__EMI_EMI_DEBUG_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT21__SATA_PHY_TDO		(_MX53_PAD_DISP0_DAT21__SATA_PHY_TDO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22		(_MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT22__GPIO5_16		(_MX53_PAD_DISP0_DAT22__GPIO5_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT22__ECSPI1_MISO		(_MX53_PAD_DISP0_DAT22__ECSPI1_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS		(_MX53_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT22__SDMA_DEBUG_BUS_DEVICE_1		(_MX53_PAD_DISP0_DAT22__SDMA_DEBUG_BUS_DEVICE_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT22__EMI_EMI_DEBUG_27		(_MX53_PAD_DISP0_DAT22__EMI_EMI_DEBUG_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT22__SATA_PHY_TCK		(_MX53_PAD_DISP0_DAT22__SATA_PHY_TCK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23		(_MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT23__GPIO5_17		(_MX53_PAD_DISP0_DAT23__GPIO5_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT23__ECSPI1_SS0		(_MX53_PAD_DISP0_DAT23__ECSPI1_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD		(_MX53_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT23__SDMA_DEBUG_BUS_DEVICE_2		(_MX53_PAD_DISP0_DAT23__SDMA_DEBUG_BUS_DEVICE_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT23__EMI_EMI_DEBUG_28		(_MX53_PAD_DISP0_DAT23__EMI_EMI_DEBUG_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_DISP0_DAT23__SATA_PHY_TMS		(_MX53_PAD_DISP0_DAT23__SATA_PHY_TMS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK		(_MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_PIXCLK__GPIO5_18		(_MX53_PAD_CSI0_PIXCLK__GPIO5_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0		(_MX53_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_PIXCLK__EMI_EMI_DEBUG_29		(_MX53_PAD_CSI0_PIXCLK__EMI_EMI_DEBUG_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC		(_MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_MCLK__GPIO5_19		(_MX53_PAD_CSI0_MCLK__GPIO5_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_MCLK__CCM_CSI0_MCLK		(_MX53_PAD_CSI0_MCLK__CCM_CSI0_MCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1		(_MX53_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_MCLK__EMI_EMI_DEBUG_30		(_MX53_PAD_CSI0_MCLK__EMI_EMI_DEBUG_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_MCLK__TPIU_TRCTL		(_MX53_PAD_CSI0_MCLK__TPIU_TRCTL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN		(_MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DATA_EN__GPIO5_20		(_MX53_PAD_CSI0_DATA_EN__GPIO5_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2		(_MX53_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DATA_EN__EMI_EMI_DEBUG_31		(_MX53_PAD_CSI0_DATA_EN__EMI_EMI_DEBUG_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DATA_EN__TPIU_TRCLK		(_MX53_PAD_CSI0_DATA_EN__TPIU_TRCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC		(_MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_VSYNC__GPIO5_21		(_MX53_PAD_CSI0_VSYNC__GPIO5_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3		(_MX53_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_VSYNC__EMI_EMI_DEBUG_32		(_MX53_PAD_CSI0_VSYNC__EMI_EMI_DEBUG_32 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_VSYNC__TPIU_TRACE_0		(_MX53_PAD_CSI0_VSYNC__TPIU_TRACE_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT4__IPU_CSI0_D_4		(_MX53_PAD_CSI0_DAT4__IPU_CSI0_D_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT4__GPIO5_22		(_MX53_PAD_CSI0_DAT4__GPIO5_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT4__KPP_COL_5		(_MX53_PAD_CSI0_DAT4__KPP_COL_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT4__ECSPI1_SCLK		(_MX53_PAD_CSI0_DAT4__ECSPI1_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT4__USBOH3_USBH3_STP		(_MX53_PAD_CSI0_DAT4__USBOH3_USBH3_STP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC		(_MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT4__EMI_EMI_DEBUG_33		(_MX53_PAD_CSI0_DAT4__EMI_EMI_DEBUG_33 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT4__TPIU_TRACE_1		(_MX53_PAD_CSI0_DAT4__TPIU_TRACE_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT5__IPU_CSI0_D_5		(_MX53_PAD_CSI0_DAT5__IPU_CSI0_D_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT5__GPIO5_23		(_MX53_PAD_CSI0_DAT5__GPIO5_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT5__KPP_ROW_5		(_MX53_PAD_CSI0_DAT5__KPP_ROW_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT5__ECSPI1_MOSI		(_MX53_PAD_CSI0_DAT5__ECSPI1_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT5__USBOH3_USBH3_NXT		(_MX53_PAD_CSI0_DAT5__USBOH3_USBH3_NXT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD		(_MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT5__EMI_EMI_DEBUG_34		(_MX53_PAD_CSI0_DAT5__EMI_EMI_DEBUG_34 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT5__TPIU_TRACE_2		(_MX53_PAD_CSI0_DAT5__TPIU_TRACE_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT6__IPU_CSI0_D_6		(_MX53_PAD_CSI0_DAT6__IPU_CSI0_D_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT6__GPIO5_24		(_MX53_PAD_CSI0_DAT6__GPIO5_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT6__KPP_COL_6		(_MX53_PAD_CSI0_DAT6__KPP_COL_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT6__ECSPI1_MISO		(_MX53_PAD_CSI0_DAT6__ECSPI1_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT6__USBOH3_USBH3_CLK		(_MX53_PAD_CSI0_DAT6__USBOH3_USBH3_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS		(_MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT6__EMI_EMI_DEBUG_35		(_MX53_PAD_CSI0_DAT6__EMI_EMI_DEBUG_35 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT6__TPIU_TRACE_3		(_MX53_PAD_CSI0_DAT6__TPIU_TRACE_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT7__IPU_CSI0_D_7		(_MX53_PAD_CSI0_DAT7__IPU_CSI0_D_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT7__GPIO5_25		(_MX53_PAD_CSI0_DAT7__GPIO5_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT7__KPP_ROW_6		(_MX53_PAD_CSI0_DAT7__KPP_ROW_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT7__ECSPI1_SS0		(_MX53_PAD_CSI0_DAT7__ECSPI1_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT7__USBOH3_USBH3_DIR		(_MX53_PAD_CSI0_DAT7__USBOH3_USBH3_DIR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD		(_MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT7__EMI_EMI_DEBUG_36		(_MX53_PAD_CSI0_DAT7__EMI_EMI_DEBUG_36 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT7__TPIU_TRACE_4		(_MX53_PAD_CSI0_DAT7__TPIU_TRACE_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT8__IPU_CSI0_D_8		(_MX53_PAD_CSI0_DAT8__IPU_CSI0_D_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT8__GPIO5_26		(_MX53_PAD_CSI0_DAT8__GPIO5_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT8__KPP_COL_7		(_MX53_PAD_CSI0_DAT8__KPP_COL_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT8__ECSPI2_SCLK		(_MX53_PAD_CSI0_DAT8__ECSPI2_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT8__USBOH3_USBH3_OC		(_MX53_PAD_CSI0_DAT8__USBOH3_USBH3_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT8__I2C1_SDA		(_MX53_PAD_CSI0_DAT8__I2C1_SDA | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_CSI0_DAT8__EMI_EMI_DEBUG_37		(_MX53_PAD_CSI0_DAT8__EMI_EMI_DEBUG_37 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT8__TPIU_TRACE_5		(_MX53_PAD_CSI0_DAT8__TPIU_TRACE_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9		(_MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT9__GPIO5_27		(_MX53_PAD_CSI0_DAT9__GPIO5_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT9__KPP_ROW_7		(_MX53_PAD_CSI0_DAT9__KPP_ROW_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT9__ECSPI2_MOSI		(_MX53_PAD_CSI0_DAT9__ECSPI2_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT9__USBOH3_USBH3_PWR		(_MX53_PAD_CSI0_DAT9__USBOH3_USBH3_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT9__I2C1_SCL		(_MX53_PAD_CSI0_DAT9__I2C1_SCL | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_CSI0_DAT9__EMI_EMI_DEBUG_38		(_MX53_PAD_CSI0_DAT9__EMI_EMI_DEBUG_38 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT9__TPIU_TRACE_6		(_MX53_PAD_CSI0_DAT9__TPIU_TRACE_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10		(_MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT10__GPIO5_28		(_MX53_PAD_CSI0_DAT10__GPIO5_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT10__UART1_TXD_MUX		(_MX53_PAD_CSI0_DAT10__UART1_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT10__ECSPI2_MISO		(_MX53_PAD_CSI0_DAT10__ECSPI2_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC		(_MX53_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4		(_MX53_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT10__EMI_EMI_DEBUG_39		(_MX53_PAD_CSI0_DAT10__EMI_EMI_DEBUG_39 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT10__TPIU_TRACE_7		(_MX53_PAD_CSI0_DAT10__TPIU_TRACE_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT11__IPU_CSI0_D_11		(_MX53_PAD_CSI0_DAT11__IPU_CSI0_D_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT11__GPIO5_29		(_MX53_PAD_CSI0_DAT11__GPIO5_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT11__UART1_RXD_MUX		(_MX53_PAD_CSI0_DAT11__UART1_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT11__ECSPI2_SS0		(_MX53_PAD_CSI0_DAT11__ECSPI2_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS		(_MX53_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5		(_MX53_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT11__EMI_EMI_DEBUG_40		(_MX53_PAD_CSI0_DAT11__EMI_EMI_DEBUG_40 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT11__TPIU_TRACE_8		(_MX53_PAD_CSI0_DAT11__TPIU_TRACE_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12		(_MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT12__GPIO5_30		(_MX53_PAD_CSI0_DAT12__GPIO5_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT12__UART4_TXD_MUX		(_MX53_PAD_CSI0_DAT12__UART4_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT12__USBOH3_USBH3_DATA_0		(_MX53_PAD_CSI0_DAT12__USBOH3_USBH3_DATA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6		(_MX53_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT12__EMI_EMI_DEBUG_41		(_MX53_PAD_CSI0_DAT12__EMI_EMI_DEBUG_41 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT12__TPIU_TRACE_9		(_MX53_PAD_CSI0_DAT12__TPIU_TRACE_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13		(_MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT13__GPIO5_31		(_MX53_PAD_CSI0_DAT13__GPIO5_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT13__UART4_RXD_MUX		(_MX53_PAD_CSI0_DAT13__UART4_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT13__USBOH3_USBH3_DATA_1		(_MX53_PAD_CSI0_DAT13__USBOH3_USBH3_DATA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7		(_MX53_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT13__EMI_EMI_DEBUG_42		(_MX53_PAD_CSI0_DAT13__EMI_EMI_DEBUG_42 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT13__TPIU_TRACE_10		(_MX53_PAD_CSI0_DAT13__TPIU_TRACE_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14		(_MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT14__GPIO6_0		(_MX53_PAD_CSI0_DAT14__GPIO6_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT14__UART5_TXD_MUX		(_MX53_PAD_CSI0_DAT14__UART5_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT14__USBOH3_USBH3_DATA_2		(_MX53_PAD_CSI0_DAT14__USBOH3_USBH3_DATA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8		(_MX53_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT14__EMI_EMI_DEBUG_43		(_MX53_PAD_CSI0_DAT14__EMI_EMI_DEBUG_43 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT14__TPIU_TRACE_11		(_MX53_PAD_CSI0_DAT14__TPIU_TRACE_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15		(_MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT15__GPIO6_1		(_MX53_PAD_CSI0_DAT15__GPIO6_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT15__UART5_RXD_MUX		(_MX53_PAD_CSI0_DAT15__UART5_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT15__USBOH3_USBH3_DATA_3		(_MX53_PAD_CSI0_DAT15__USBOH3_USBH3_DATA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9		(_MX53_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT15__EMI_EMI_DEBUG_44		(_MX53_PAD_CSI0_DAT15__EMI_EMI_DEBUG_44 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT15__TPIU_TRACE_12		(_MX53_PAD_CSI0_DAT15__TPIU_TRACE_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16		(_MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT16__GPIO6_2		(_MX53_PAD_CSI0_DAT16__GPIO6_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT16__UART4_RTS		(_MX53_PAD_CSI0_DAT16__UART4_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT16__USBOH3_USBH3_DATA_4		(_MX53_PAD_CSI0_DAT16__USBOH3_USBH3_DATA_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10		(_MX53_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT16__EMI_EMI_DEBUG_45		(_MX53_PAD_CSI0_DAT16__EMI_EMI_DEBUG_45 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT16__TPIU_TRACE_13		(_MX53_PAD_CSI0_DAT16__TPIU_TRACE_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17		(_MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT17__GPIO6_3		(_MX53_PAD_CSI0_DAT17__GPIO6_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT17__UART4_CTS		(_MX53_PAD_CSI0_DAT17__UART4_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT17__USBOH3_USBH3_DATA_5		(_MX53_PAD_CSI0_DAT17__USBOH3_USBH3_DATA_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11		(_MX53_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT17__EMI_EMI_DEBUG_46		(_MX53_PAD_CSI0_DAT17__EMI_EMI_DEBUG_46 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT17__TPIU_TRACE_14		(_MX53_PAD_CSI0_DAT17__TPIU_TRACE_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18		(_MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT18__GPIO6_4		(_MX53_PAD_CSI0_DAT18__GPIO6_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT18__UART5_RTS		(_MX53_PAD_CSI0_DAT18__UART5_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT18__USBOH3_USBH3_DATA_6		(_MX53_PAD_CSI0_DAT18__USBOH3_USBH3_DATA_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12		(_MX53_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT18__EMI_EMI_DEBUG_47		(_MX53_PAD_CSI0_DAT18__EMI_EMI_DEBUG_47 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT18__TPIU_TRACE_15		(_MX53_PAD_CSI0_DAT18__TPIU_TRACE_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19		(_MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT19__GPIO6_5		(_MX53_PAD_CSI0_DAT19__GPIO6_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT19__UART5_CTS		(_MX53_PAD_CSI0_DAT19__UART5_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT19__USBOH3_USBH3_DATA_7		(_MX53_PAD_CSI0_DAT19__USBOH3_USBH3_DATA_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13		(_MX53_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT19__EMI_EMI_DEBUG_48		(_MX53_PAD_CSI0_DAT19__EMI_EMI_DEBUG_48 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_CSI0_DAT19__USBPHY2_BISTOK		(_MX53_PAD_CSI0_DAT19__USBPHY2_BISTOK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A25__EMI_WEIM_A_25		(_MX53_PAD_EIM_A25__EMI_WEIM_A_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A25__GPIO5_2		(_MX53_PAD_EIM_A25__GPIO5_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A25__ECSPI2_RDY		(_MX53_PAD_EIM_A25__ECSPI2_RDY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A25__IPU_DI1_PIN12		(_MX53_PAD_EIM_A25__IPU_DI1_PIN12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A25__CSPI_SS1		(_MX53_PAD_EIM_A25__CSPI_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A25__IPU_DI0_D1_CS		(_MX53_PAD_EIM_A25__IPU_DI0_D1_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A25__USBPHY1_BISTOK		(_MX53_PAD_EIM_A25__USBPHY1_BISTOK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB2__EMI_WEIM_EB_2		(_MX53_PAD_EIM_EB2__EMI_WEIM_EB_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB2__GPIO2_30		(_MX53_PAD_EIM_EB2__GPIO2_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB2__CCM_DI1_EXT_CLK		(_MX53_PAD_EIM_EB2__CCM_DI1_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB2__IPU_SER_DISP1_CS		(_MX53_PAD_EIM_EB2__IPU_SER_DISP1_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB2__ECSPI1_SS0		(_MX53_PAD_EIM_EB2__ECSPI1_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB2__I2C2_SCL		(_MX53_PAD_EIM_EB2__I2C2_SCL | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_EIM_D16__EMI_WEIM_D_16		(_MX53_PAD_EIM_D16__EMI_WEIM_D_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D16__GPIO3_16		(_MX53_PAD_EIM_D16__GPIO3_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D16__IPU_DI0_PIN5		(_MX53_PAD_EIM_D16__IPU_DI0_PIN5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D16__IPU_DISPB1_SER_CLK		(_MX53_PAD_EIM_D16__IPU_DISPB1_SER_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D16__ECSPI1_SCLK		(_MX53_PAD_EIM_D16__ECSPI1_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D16__I2C2_SDA		(_MX53_PAD_EIM_D16__I2C2_SDA | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_EIM_D17__EMI_WEIM_D_17		(_MX53_PAD_EIM_D17__EMI_WEIM_D_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D17__GPIO3_17		(_MX53_PAD_EIM_D17__GPIO3_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D17__IPU_DI0_PIN6		(_MX53_PAD_EIM_D17__IPU_DI0_PIN6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D17__IPU_DISPB1_SER_DIN		(_MX53_PAD_EIM_D17__IPU_DISPB1_SER_DIN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D17__ECSPI1_MISO		(_MX53_PAD_EIM_D17__ECSPI1_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D17__I2C3_SCL		(_MX53_PAD_EIM_D17__I2C3_SCL | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_EIM_D18__EMI_WEIM_D_18		(_MX53_PAD_EIM_D18__EMI_WEIM_D_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D18__GPIO3_18		(_MX53_PAD_EIM_D18__GPIO3_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D18__IPU_DI0_PIN7		(_MX53_PAD_EIM_D18__IPU_DI0_PIN7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D18__IPU_DISPB1_SER_DIO		(_MX53_PAD_EIM_D18__IPU_DISPB1_SER_DIO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D18__ECSPI1_MOSI		(_MX53_PAD_EIM_D18__ECSPI1_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D18__I2C3_SDA		(_MX53_PAD_EIM_D18__I2C3_SDA | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_EIM_D18__IPU_DI1_D0_CS		(_MX53_PAD_EIM_D18__IPU_DI1_D0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D19__EMI_WEIM_D_19		(_MX53_PAD_EIM_D19__EMI_WEIM_D_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D19__GPIO3_19		(_MX53_PAD_EIM_D19__GPIO3_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D19__IPU_DI0_PIN8		(_MX53_PAD_EIM_D19__IPU_DI0_PIN8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D19__IPU_DISPB1_SER_RS		(_MX53_PAD_EIM_D19__IPU_DISPB1_SER_RS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D19__ECSPI1_SS1		(_MX53_PAD_EIM_D19__ECSPI1_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D19__EPIT1_EPITO		(_MX53_PAD_EIM_D19__EPIT1_EPITO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D19__UART1_CTS		(_MX53_PAD_EIM_D19__UART1_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D19__USBOH3_USBH2_OC		(_MX53_PAD_EIM_D19__USBOH3_USBH2_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D20__EMI_WEIM_D_20		(_MX53_PAD_EIM_D20__EMI_WEIM_D_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D20__GPIO3_20		(_MX53_PAD_EIM_D20__GPIO3_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D20__IPU_DI0_PIN16		(_MX53_PAD_EIM_D20__IPU_DI0_PIN16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D20__IPU_SER_DISP0_CS		(_MX53_PAD_EIM_D20__IPU_SER_DISP0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D20__CSPI_SS0		(_MX53_PAD_EIM_D20__CSPI_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D20__EPIT2_EPITO		(_MX53_PAD_EIM_D20__EPIT2_EPITO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D20__UART1_RTS		(_MX53_PAD_EIM_D20__UART1_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D20__USBOH3_USBH2_PWR		(_MX53_PAD_EIM_D20__USBOH3_USBH2_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D21__EMI_WEIM_D_21		(_MX53_PAD_EIM_D21__EMI_WEIM_D_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D21__GPIO3_21		(_MX53_PAD_EIM_D21__GPIO3_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D21__IPU_DI0_PIN17		(_MX53_PAD_EIM_D21__IPU_DI0_PIN17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK		(_MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D21__CSPI_SCLK		(_MX53_PAD_EIM_D21__CSPI_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D21__I2C1_SCL		(_MX53_PAD_EIM_D21__I2C1_SCL | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_EIM_D21__USBOH3_USBOTG_OC		(_MX53_PAD_EIM_D21__USBOH3_USBOTG_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D22__EMI_WEIM_D_22		(_MX53_PAD_EIM_D22__EMI_WEIM_D_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D22__GPIO3_22		(_MX53_PAD_EIM_D22__GPIO3_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D22__IPU_DI0_PIN1		(_MX53_PAD_EIM_D22__IPU_DI0_PIN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN		(_MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D22__CSPI_MISO		(_MX53_PAD_EIM_D22__CSPI_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D22__USBOH3_USBOTG_PWR		(_MX53_PAD_EIM_D22__USBOH3_USBOTG_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D23__EMI_WEIM_D_23		(_MX53_PAD_EIM_D23__EMI_WEIM_D_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D23__GPIO3_23		(_MX53_PAD_EIM_D23__GPIO3_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D23__UART3_CTS		(_MX53_PAD_EIM_D23__UART3_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D23__UART1_DCD		(_MX53_PAD_EIM_D23__UART1_DCD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D23__IPU_DI0_D0_CS		(_MX53_PAD_EIM_D23__IPU_DI0_D0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D23__IPU_DI1_PIN2		(_MX53_PAD_EIM_D23__IPU_DI1_PIN2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D23__IPU_CSI1_DATA_EN		(_MX53_PAD_EIM_D23__IPU_CSI1_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D23__IPU_DI1_PIN14		(_MX53_PAD_EIM_D23__IPU_DI1_PIN14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB3__EMI_WEIM_EB_3		(_MX53_PAD_EIM_EB3__EMI_WEIM_EB_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB3__GPIO2_31		(_MX53_PAD_EIM_EB3__GPIO2_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB3__UART3_RTS		(_MX53_PAD_EIM_EB3__UART3_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_EB3__UART1_RI		(_MX53_PAD_EIM_EB3__UART1_RI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB3__IPU_DI1_PIN3		(_MX53_PAD_EIM_EB3__IPU_DI1_PIN3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB3__IPU_CSI1_HSYNC		(_MX53_PAD_EIM_EB3__IPU_CSI1_HSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB3__IPU_DI1_PIN16		(_MX53_PAD_EIM_EB3__IPU_DI1_PIN16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D24__EMI_WEIM_D_24		(_MX53_PAD_EIM_D24__EMI_WEIM_D_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D24__GPIO3_24		(_MX53_PAD_EIM_D24__GPIO3_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D24__UART3_TXD_MUX		(_MX53_PAD_EIM_D24__UART3_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D24__ECSPI1_SS2		(_MX53_PAD_EIM_D24__ECSPI1_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D24__CSPI_SS2		(_MX53_PAD_EIM_D24__CSPI_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D24__AUDMUX_AUD5_RXFS		(_MX53_PAD_EIM_D24__AUDMUX_AUD5_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D24__ECSPI2_SS2		(_MX53_PAD_EIM_D24__ECSPI2_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D24__UART1_DTR		(_MX53_PAD_EIM_D24__UART1_DTR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D25__EMI_WEIM_D_25		(_MX53_PAD_EIM_D25__EMI_WEIM_D_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D25__GPIO3_25		(_MX53_PAD_EIM_D25__GPIO3_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D25__UART3_RXD_MUX		(_MX53_PAD_EIM_D25__UART3_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D25__ECSPI1_SS3		(_MX53_PAD_EIM_D25__ECSPI1_SS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D25__CSPI_SS3		(_MX53_PAD_EIM_D25__CSPI_SS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D25__AUDMUX_AUD5_RXC		(_MX53_PAD_EIM_D25__AUDMUX_AUD5_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D25__ECSPI2_SS3		(_MX53_PAD_EIM_D25__ECSPI2_SS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D25__UART1_DSR		(_MX53_PAD_EIM_D25__UART1_DSR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D26__EMI_WEIM_D_26		(_MX53_PAD_EIM_D26__EMI_WEIM_D_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D26__GPIO3_26		(_MX53_PAD_EIM_D26__GPIO3_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D26__UART2_TXD_MUX		(_MX53_PAD_EIM_D26__UART2_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D26__FIRI_RXD		(_MX53_PAD_EIM_D26__FIRI_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D26__IPU_CSI0_D_1		(_MX53_PAD_EIM_D26__IPU_CSI0_D_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D26__IPU_DI1_PIN11		(_MX53_PAD_EIM_D26__IPU_DI1_PIN11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D26__IPU_SISG_2		(_MX53_PAD_EIM_D26__IPU_SISG_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D26__IPU_DISP1_DAT_22		(_MX53_PAD_EIM_D26__IPU_DISP1_DAT_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D27__EMI_WEIM_D_27		(_MX53_PAD_EIM_D27__EMI_WEIM_D_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D27__GPIO3_27		(_MX53_PAD_EIM_D27__GPIO3_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D27__UART2_RXD_MUX		(_MX53_PAD_EIM_D27__UART2_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D27__FIRI_TXD		(_MX53_PAD_EIM_D27__FIRI_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D27__IPU_CSI0_D_0		(_MX53_PAD_EIM_D27__IPU_CSI0_D_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D27__IPU_DI1_PIN13		(_MX53_PAD_EIM_D27__IPU_DI1_PIN13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D27__IPU_SISG_3		(_MX53_PAD_EIM_D27__IPU_SISG_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D27__IPU_DISP1_DAT_23		(_MX53_PAD_EIM_D27__IPU_DISP1_DAT_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D28__EMI_WEIM_D_28		(_MX53_PAD_EIM_D28__EMI_WEIM_D_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D28__GPIO3_28		(_MX53_PAD_EIM_D28__GPIO3_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D28__UART2_CTS		(_MX53_PAD_EIM_D28__UART2_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO		(_MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D28__CSPI_MOSI		(_MX53_PAD_EIM_D28__CSPI_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D28__I2C1_SDA		(_MX53_PAD_EIM_D28__I2C1_SDA | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_EIM_D28__IPU_EXT_TRIG		(_MX53_PAD_EIM_D28__IPU_EXT_TRIG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D28__IPU_DI0_PIN13		(_MX53_PAD_EIM_D28__IPU_DI0_PIN13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D29__EMI_WEIM_D_29		(_MX53_PAD_EIM_D29__EMI_WEIM_D_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D29__GPIO3_29		(_MX53_PAD_EIM_D29__GPIO3_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D29__UART2_RTS		(_MX53_PAD_EIM_D29__UART2_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D29__IPU_DISPB0_SER_RS		(_MX53_PAD_EIM_D29__IPU_DISPB0_SER_RS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D29__CSPI_SS0		(_MX53_PAD_EIM_D29__CSPI_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D29__IPU_DI1_PIN15		(_MX53_PAD_EIM_D29__IPU_DI1_PIN15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D29__IPU_CSI1_VSYNC		(_MX53_PAD_EIM_D29__IPU_CSI1_VSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D29__IPU_DI0_PIN14		(_MX53_PAD_EIM_D29__IPU_DI0_PIN14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D30__EMI_WEIM_D_30		(_MX53_PAD_EIM_D30__EMI_WEIM_D_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D30__GPIO3_30		(_MX53_PAD_EIM_D30__GPIO3_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D30__UART3_CTS		(_MX53_PAD_EIM_D30__UART3_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D30__IPU_CSI0_D_3		(_MX53_PAD_EIM_D30__IPU_CSI0_D_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D30__IPU_DI0_PIN11		(_MX53_PAD_EIM_D30__IPU_DI0_PIN11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D30__IPU_DISP1_DAT_21		(_MX53_PAD_EIM_D30__IPU_DISP1_DAT_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D30__USBOH3_USBH1_OC		(_MX53_PAD_EIM_D30__USBOH3_USBH1_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D30__USBOH3_USBH2_OC		(_MX53_PAD_EIM_D30__USBOH3_USBH2_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D31__EMI_WEIM_D_31		(_MX53_PAD_EIM_D31__EMI_WEIM_D_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D31__GPIO3_31		(_MX53_PAD_EIM_D31__GPIO3_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D31__UART3_RTS		(_MX53_PAD_EIM_D31__UART3_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_EIM_D31__IPU_CSI0_D_2		(_MX53_PAD_EIM_D31__IPU_CSI0_D_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D31__IPU_DI0_PIN12		(_MX53_PAD_EIM_D31__IPU_DI0_PIN12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D31__IPU_DISP1_DAT_20		(_MX53_PAD_EIM_D31__IPU_DISP1_DAT_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D31__USBOH3_USBH1_PWR		(_MX53_PAD_EIM_D31__USBOH3_USBH1_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_D31__USBOH3_USBH2_PWR		(_MX53_PAD_EIM_D31__USBOH3_USBH2_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A24__EMI_WEIM_A_24		(_MX53_PAD_EIM_A24__EMI_WEIM_A_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A24__GPIO5_4		(_MX53_PAD_EIM_A24__GPIO5_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A24__IPU_DISP1_DAT_19		(_MX53_PAD_EIM_A24__IPU_DISP1_DAT_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A24__IPU_CSI1_D_19		(_MX53_PAD_EIM_A24__IPU_CSI1_D_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A24__IPU_SISG_2		(_MX53_PAD_EIM_A24__IPU_SISG_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A24__USBPHY2_BVALID		(_MX53_PAD_EIM_A24__USBPHY2_BVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A23__EMI_WEIM_A_23		(_MX53_PAD_EIM_A23__EMI_WEIM_A_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A23__GPIO6_6		(_MX53_PAD_EIM_A23__GPIO6_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A23__IPU_DISP1_DAT_18		(_MX53_PAD_EIM_A23__IPU_DISP1_DAT_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A23__IPU_CSI1_D_18		(_MX53_PAD_EIM_A23__IPU_CSI1_D_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A23__IPU_SISG_3		(_MX53_PAD_EIM_A23__IPU_SISG_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A23__USBPHY2_ENDSESSION		(_MX53_PAD_EIM_A23__USBPHY2_ENDSESSION | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A22__EMI_WEIM_A_22		(_MX53_PAD_EIM_A22__EMI_WEIM_A_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A22__GPIO2_16		(_MX53_PAD_EIM_A22__GPIO2_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A22__IPU_DISP1_DAT_17		(_MX53_PAD_EIM_A22__IPU_DISP1_DAT_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A22__IPU_CSI1_D_17		(_MX53_PAD_EIM_A22__IPU_CSI1_D_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A22__SRC_BT_CFG1_7		(_MX53_PAD_EIM_A22__SRC_BT_CFG1_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A21__EMI_WEIM_A_21		(_MX53_PAD_EIM_A21__EMI_WEIM_A_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A21__GPIO2_17		(_MX53_PAD_EIM_A21__GPIO2_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A21__IPU_DISP1_DAT_16		(_MX53_PAD_EIM_A21__IPU_DISP1_DAT_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A21__IPU_CSI1_D_16		(_MX53_PAD_EIM_A21__IPU_CSI1_D_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A21__SRC_BT_CFG1_6		(_MX53_PAD_EIM_A21__SRC_BT_CFG1_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A20__EMI_WEIM_A_20		(_MX53_PAD_EIM_A20__EMI_WEIM_A_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A20__GPIO2_18		(_MX53_PAD_EIM_A20__GPIO2_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A20__IPU_DISP1_DAT_15		(_MX53_PAD_EIM_A20__IPU_DISP1_DAT_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A20__IPU_CSI1_D_15		(_MX53_PAD_EIM_A20__IPU_CSI1_D_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A20__SRC_BT_CFG1_5		(_MX53_PAD_EIM_A20__SRC_BT_CFG1_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A19__EMI_WEIM_A_19		(_MX53_PAD_EIM_A19__EMI_WEIM_A_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A19__GPIO2_19		(_MX53_PAD_EIM_A19__GPIO2_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A19__IPU_DISP1_DAT_14		(_MX53_PAD_EIM_A19__IPU_DISP1_DAT_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A19__IPU_CSI1_D_14		(_MX53_PAD_EIM_A19__IPU_CSI1_D_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A19__SRC_BT_CFG1_4		(_MX53_PAD_EIM_A19__SRC_BT_CFG1_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A18__EMI_WEIM_A_18		(_MX53_PAD_EIM_A18__EMI_WEIM_A_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A18__GPIO2_20		(_MX53_PAD_EIM_A18__GPIO2_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A18__IPU_DISP1_DAT_13		(_MX53_PAD_EIM_A18__IPU_DISP1_DAT_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A18__IPU_CSI1_D_13		(_MX53_PAD_EIM_A18__IPU_CSI1_D_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A18__SRC_BT_CFG1_3		(_MX53_PAD_EIM_A18__SRC_BT_CFG1_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A17__EMI_WEIM_A_17		(_MX53_PAD_EIM_A17__EMI_WEIM_A_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A17__GPIO2_21		(_MX53_PAD_EIM_A17__GPIO2_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A17__IPU_DISP1_DAT_12		(_MX53_PAD_EIM_A17__IPU_DISP1_DAT_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A17__IPU_CSI1_D_12		(_MX53_PAD_EIM_A17__IPU_CSI1_D_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A17__SRC_BT_CFG1_2		(_MX53_PAD_EIM_A17__SRC_BT_CFG1_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A16__EMI_WEIM_A_16		(_MX53_PAD_EIM_A16__EMI_WEIM_A_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A16__GPIO2_22		(_MX53_PAD_EIM_A16__GPIO2_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK		(_MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A16__IPU_CSI1_PIXCLK		(_MX53_PAD_EIM_A16__IPU_CSI1_PIXCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_A16__SRC_BT_CFG1_1		(_MX53_PAD_EIM_A16__SRC_BT_CFG1_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_CS0__EMI_WEIM_CS_0		(_MX53_PAD_EIM_CS0__EMI_WEIM_CS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_CS0__GPIO2_23		(_MX53_PAD_EIM_CS0__GPIO2_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_CS0__ECSPI2_SCLK		(_MX53_PAD_EIM_CS0__ECSPI2_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_CS0__IPU_DI1_PIN5		(_MX53_PAD_EIM_CS0__IPU_DI1_PIN5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_CS1__EMI_WEIM_CS_1		(_MX53_PAD_EIM_CS1__EMI_WEIM_CS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_CS1__GPIO2_24		(_MX53_PAD_EIM_CS1__GPIO2_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_CS1__ECSPI2_MOSI		(_MX53_PAD_EIM_CS1__ECSPI2_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_CS1__IPU_DI1_PIN6		(_MX53_PAD_EIM_CS1__IPU_DI1_PIN6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_OE__EMI_WEIM_OE		(_MX53_PAD_EIM_OE__EMI_WEIM_OE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_OE__GPIO2_25		(_MX53_PAD_EIM_OE__GPIO2_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_OE__ECSPI2_MISO		(_MX53_PAD_EIM_OE__ECSPI2_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_OE__IPU_DI1_PIN7		(_MX53_PAD_EIM_OE__IPU_DI1_PIN7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_OE__USBPHY2_IDDIG		(_MX53_PAD_EIM_OE__USBPHY2_IDDIG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_RW__EMI_WEIM_RW		(_MX53_PAD_EIM_RW__EMI_WEIM_RW | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_RW__GPIO2_26		(_MX53_PAD_EIM_RW__GPIO2_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_RW__ECSPI2_SS0		(_MX53_PAD_EIM_RW__ECSPI2_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_RW__IPU_DI1_PIN8		(_MX53_PAD_EIM_RW__IPU_DI1_PIN8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_RW__USBPHY2_HOSTDISCONNECT		(_MX53_PAD_EIM_RW__USBPHY2_HOSTDISCONNECT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_LBA__EMI_WEIM_LBA		(_MX53_PAD_EIM_LBA__EMI_WEIM_LBA | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_LBA__GPIO2_27		(_MX53_PAD_EIM_LBA__GPIO2_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_LBA__ECSPI2_SS1		(_MX53_PAD_EIM_LBA__ECSPI2_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_LBA__IPU_DI1_PIN17		(_MX53_PAD_EIM_LBA__IPU_DI1_PIN17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_LBA__SRC_BT_CFG1_0		(_MX53_PAD_EIM_LBA__SRC_BT_CFG1_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB0__EMI_WEIM_EB_0		(_MX53_PAD_EIM_EB0__EMI_WEIM_EB_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB0__GPIO2_28		(_MX53_PAD_EIM_EB0__GPIO2_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11		(_MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB0__IPU_CSI1_D_11		(_MX53_PAD_EIM_EB0__IPU_CSI1_D_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB0__GPC_PMIC_RDY		(_MX53_PAD_EIM_EB0__GPC_PMIC_RDY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB0__SRC_BT_CFG2_7		(_MX53_PAD_EIM_EB0__SRC_BT_CFG2_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB1__EMI_WEIM_EB_1		(_MX53_PAD_EIM_EB1__EMI_WEIM_EB_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB1__GPIO2_29		(_MX53_PAD_EIM_EB1__GPIO2_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10		(_MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB1__IPU_CSI1_D_10		(_MX53_PAD_EIM_EB1__IPU_CSI1_D_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_EB1__SRC_BT_CFG2_6		(_MX53_PAD_EIM_EB1__SRC_BT_CFG2_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0		(_MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA0__GPIO3_0		(_MX53_PAD_EIM_DA0__GPIO3_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9		(_MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA0__IPU_CSI1_D_9		(_MX53_PAD_EIM_DA0__IPU_CSI1_D_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA0__SRC_BT_CFG2_5		(_MX53_PAD_EIM_DA0__SRC_BT_CFG2_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1		(_MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA1__GPIO3_1		(_MX53_PAD_EIM_DA1__GPIO3_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8		(_MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA1__IPU_CSI1_D_8		(_MX53_PAD_EIM_DA1__IPU_CSI1_D_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA1__SRC_BT_CFG2_4		(_MX53_PAD_EIM_DA1__SRC_BT_CFG2_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2		(_MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA2__GPIO3_2		(_MX53_PAD_EIM_DA2__GPIO3_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7		(_MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA2__IPU_CSI1_D_7		(_MX53_PAD_EIM_DA2__IPU_CSI1_D_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA2__SRC_BT_CFG2_3		(_MX53_PAD_EIM_DA2__SRC_BT_CFG2_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3		(_MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA3__GPIO3_3		(_MX53_PAD_EIM_DA3__GPIO3_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6		(_MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA3__IPU_CSI1_D_6		(_MX53_PAD_EIM_DA3__IPU_CSI1_D_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA3__SRC_BT_CFG2_2		(_MX53_PAD_EIM_DA3__SRC_BT_CFG2_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4		(_MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA4__GPIO3_4		(_MX53_PAD_EIM_DA4__GPIO3_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5		(_MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA4__IPU_CSI1_D_5		(_MX53_PAD_EIM_DA4__IPU_CSI1_D_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA4__SRC_BT_CFG3_7		(_MX53_PAD_EIM_DA4__SRC_BT_CFG3_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5		(_MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA5__GPIO3_5		(_MX53_PAD_EIM_DA5__GPIO3_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4		(_MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA5__IPU_CSI1_D_4		(_MX53_PAD_EIM_DA5__IPU_CSI1_D_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA5__SRC_BT_CFG3_6		(_MX53_PAD_EIM_DA5__SRC_BT_CFG3_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6		(_MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA6__GPIO3_6		(_MX53_PAD_EIM_DA6__GPIO3_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3		(_MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA6__IPU_CSI1_D_3		(_MX53_PAD_EIM_DA6__IPU_CSI1_D_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA6__SRC_BT_CFG3_5		(_MX53_PAD_EIM_DA6__SRC_BT_CFG3_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA7__EMI_NAND_WEIM_DA_7		(_MX53_PAD_EIM_DA7__EMI_NAND_WEIM_DA_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA7__GPIO3_7		(_MX53_PAD_EIM_DA7__GPIO3_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2		(_MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA7__IPU_CSI1_D_2		(_MX53_PAD_EIM_DA7__IPU_CSI1_D_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA7__SRC_BT_CFG3_4		(_MX53_PAD_EIM_DA7__SRC_BT_CFG3_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA8__EMI_NAND_WEIM_DA_8		(_MX53_PAD_EIM_DA8__EMI_NAND_WEIM_DA_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA8__GPIO3_8		(_MX53_PAD_EIM_DA8__GPIO3_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1		(_MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA8__IPU_CSI1_D_1		(_MX53_PAD_EIM_DA8__IPU_CSI1_D_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA8__SRC_BT_CFG3_3		(_MX53_PAD_EIM_DA8__SRC_BT_CFG3_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA9__EMI_NAND_WEIM_DA_9		(_MX53_PAD_EIM_DA9__EMI_NAND_WEIM_DA_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA9__GPIO3_9		(_MX53_PAD_EIM_DA9__GPIO3_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0		(_MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA9__IPU_CSI1_D_0		(_MX53_PAD_EIM_DA9__IPU_CSI1_D_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA9__SRC_BT_CFG3_2		(_MX53_PAD_EIM_DA9__SRC_BT_CFG3_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA10__EMI_NAND_WEIM_DA_10		(_MX53_PAD_EIM_DA10__EMI_NAND_WEIM_DA_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA10__GPIO3_10		(_MX53_PAD_EIM_DA10__GPIO3_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA10__IPU_DI1_PIN15		(_MX53_PAD_EIM_DA10__IPU_DI1_PIN15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA10__IPU_CSI1_DATA_EN		(_MX53_PAD_EIM_DA10__IPU_CSI1_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA10__SRC_BT_CFG3_1		(_MX53_PAD_EIM_DA10__SRC_BT_CFG3_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA11__EMI_NAND_WEIM_DA_11		(_MX53_PAD_EIM_DA11__EMI_NAND_WEIM_DA_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA11__GPIO3_11		(_MX53_PAD_EIM_DA11__GPIO3_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA11__IPU_DI1_PIN2		(_MX53_PAD_EIM_DA11__IPU_DI1_PIN2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA11__IPU_CSI1_HSYNC		(_MX53_PAD_EIM_DA11__IPU_CSI1_HSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA12__EMI_NAND_WEIM_DA_12		(_MX53_PAD_EIM_DA12__EMI_NAND_WEIM_DA_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA12__GPIO3_12		(_MX53_PAD_EIM_DA12__GPIO3_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA12__IPU_DI1_PIN3		(_MX53_PAD_EIM_DA12__IPU_DI1_PIN3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA12__IPU_CSI1_VSYNC		(_MX53_PAD_EIM_DA12__IPU_CSI1_VSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA13__EMI_NAND_WEIM_DA_13		(_MX53_PAD_EIM_DA13__EMI_NAND_WEIM_DA_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA13__GPIO3_13		(_MX53_PAD_EIM_DA13__GPIO3_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA13__IPU_DI1_D0_CS		(_MX53_PAD_EIM_DA13__IPU_DI1_D0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA13__CCM_DI1_EXT_CLK		(_MX53_PAD_EIM_DA13__CCM_DI1_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA14__EMI_NAND_WEIM_DA_14		(_MX53_PAD_EIM_DA14__EMI_NAND_WEIM_DA_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA14__GPIO3_14		(_MX53_PAD_EIM_DA14__GPIO3_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA14__IPU_DI1_D1_CS		(_MX53_PAD_EIM_DA14__IPU_DI1_D1_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA14__CCM_DI0_EXT_CLK		(_MX53_PAD_EIM_DA14__CCM_DI0_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA15__EMI_NAND_WEIM_DA_15		(_MX53_PAD_EIM_DA15__EMI_NAND_WEIM_DA_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA15__GPIO3_15		(_MX53_PAD_EIM_DA15__GPIO3_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA15__IPU_DI1_PIN1		(_MX53_PAD_EIM_DA15__IPU_DI1_PIN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_DA15__IPU_DI1_PIN4		(_MX53_PAD_EIM_DA15__IPU_DI1_PIN4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B		(_MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_WE_B__GPIO6_12		(_MX53_PAD_NANDF_WE_B__GPIO6_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B		(_MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_RE_B__GPIO6_13		(_MX53_PAD_NANDF_RE_B__GPIO6_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_WAIT__EMI_WEIM_WAIT		(_MX53_PAD_EIM_WAIT__EMI_WEIM_WAIT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_WAIT__GPIO5_0		(_MX53_PAD_EIM_WAIT__GPIO5_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_EIM_WAIT__EMI_WEIM_DTACK_B		(_MX53_PAD_EIM_WAIT__EMI_WEIM_DTACK_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS1_TX3_P__GPIO6_22		(_MX53_PAD_LVDS1_TX3_P__GPIO6_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3		(_MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS1_TX2_P__GPIO6_24		(_MX53_PAD_LVDS1_TX2_P__GPIO6_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2		(_MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS1_CLK_P__GPIO6_26		(_MX53_PAD_LVDS1_CLK_P__GPIO6_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK		(_MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS1_TX1_P__GPIO6_28		(_MX53_PAD_LVDS1_TX1_P__GPIO6_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1		(_MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS1_TX0_P__GPIO6_30		(_MX53_PAD_LVDS1_TX0_P__GPIO6_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0		(_MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS0_TX3_P__GPIO7_22		(_MX53_PAD_LVDS0_TX3_P__GPIO7_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3		(_MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS0_CLK_P__GPIO7_24		(_MX53_PAD_LVDS0_CLK_P__GPIO7_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK		(_MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS0_TX2_P__GPIO7_26		(_MX53_PAD_LVDS0_TX2_P__GPIO7_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2		(_MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS0_TX1_P__GPIO7_28		(_MX53_PAD_LVDS0_TX1_P__GPIO7_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1		(_MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS0_TX0_P__GPIO7_30		(_MX53_PAD_LVDS0_TX0_P__GPIO7_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0		(_MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_10__GPIO4_0		(_MX53_PAD_GPIO_10__GPIO4_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_10__OSC32k_32K_OUT		(_MX53_PAD_GPIO_10__OSC32k_32K_OUT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_11__GPIO4_1		(_MX53_PAD_GPIO_11__GPIO4_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_12__GPIO4_2		(_MX53_PAD_GPIO_12__GPIO4_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_13__GPIO4_3		(_MX53_PAD_GPIO_13__GPIO4_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_14__GPIO4_4		(_MX53_PAD_GPIO_14__GPIO4_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CLE__EMI_NANDF_CLE		(_MX53_PAD_NANDF_CLE__EMI_NANDF_CLE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CLE__GPIO6_7		(_MX53_PAD_NANDF_CLE__GPIO6_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CLE__USBPHY1_VSTATUS_0		(_MX53_PAD_NANDF_CLE__USBPHY1_VSTATUS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_ALE__EMI_NANDF_ALE		(_MX53_PAD_NANDF_ALE__EMI_NANDF_ALE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_ALE__GPIO6_8		(_MX53_PAD_NANDF_ALE__GPIO6_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_ALE__USBPHY1_VSTATUS_1		(_MX53_PAD_NANDF_ALE__USBPHY1_VSTATUS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B		(_MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_WP_B__GPIO6_9		(_MX53_PAD_NANDF_WP_B__GPIO6_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_WP_B__USBPHY1_VSTATUS_2		(_MX53_PAD_NANDF_WP_B__USBPHY1_VSTATUS_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0		(_MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_RB0__GPIO6_10		(_MX53_PAD_NANDF_RB0__GPIO6_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_RB0__USBPHY1_VSTATUS_3		(_MX53_PAD_NANDF_RB0__USBPHY1_VSTATUS_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0		(_MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS0__GPIO6_11		(_MX53_PAD_NANDF_CS0__GPIO6_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS0__USBPHY1_VSTATUS_4		(_MX53_PAD_NANDF_CS0__USBPHY1_VSTATUS_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS1__EMI_NANDF_CS_1		(_MX53_PAD_NANDF_CS1__EMI_NANDF_CS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS1__GPIO6_14		(_MX53_PAD_NANDF_CS1__GPIO6_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS1__MLB_MLBCLK		(_MX53_PAD_NANDF_CS1__MLB_MLBCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS1__USBPHY1_VSTATUS_5		(_MX53_PAD_NANDF_CS1__USBPHY1_VSTATUS_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS2__EMI_NANDF_CS_2		(_MX53_PAD_NANDF_CS2__EMI_NANDF_CS_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS2__GPIO6_15		(_MX53_PAD_NANDF_CS2__GPIO6_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS2__IPU_SISG_0		(_MX53_PAD_NANDF_CS2__IPU_SISG_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS2__ESAI1_TX0		(_MX53_PAD_NANDF_CS2__ESAI1_TX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS2__EMI_WEIM_CRE		(_MX53_PAD_NANDF_CS2__EMI_WEIM_CRE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS2__CCM_CSI0_MCLK		(_MX53_PAD_NANDF_CS2__CCM_CSI0_MCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS2__MLB_MLBSIG		(_MX53_PAD_NANDF_CS2__MLB_MLBSIG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS2__USBPHY1_VSTATUS_6		(_MX53_PAD_NANDF_CS2__USBPHY1_VSTATUS_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS3__EMI_NANDF_CS_3		(_MX53_PAD_NANDF_CS3__EMI_NANDF_CS_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS3__GPIO6_16		(_MX53_PAD_NANDF_CS3__GPIO6_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS3__IPU_SISG_1		(_MX53_PAD_NANDF_CS3__IPU_SISG_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS3__ESAI1_TX1		(_MX53_PAD_NANDF_CS3__ESAI1_TX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS3__EMI_WEIM_A_26		(_MX53_PAD_NANDF_CS3__EMI_WEIM_A_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS3__MLB_MLBDAT		(_MX53_PAD_NANDF_CS3__MLB_MLBDAT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_NANDF_CS3__USBPHY1_VSTATUS_7		(_MX53_PAD_NANDF_CS3__USBPHY1_VSTATUS_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDIO__FEC_MDIO		(_MX53_PAD_FEC_MDIO__FEC_MDIO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDIO__GPIO1_22		(_MX53_PAD_FEC_MDIO__GPIO1_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDIO__ESAI1_SCKR		(_MX53_PAD_FEC_MDIO__ESAI1_SCKR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDIO__FEC_COL		(_MX53_PAD_FEC_MDIO__FEC_COL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDIO__RTC_CE_RTC_PS2		(_MX53_PAD_FEC_MDIO__RTC_CE_RTC_PS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDIO__SDMA_DEBUG_BUS_DEVICE_3		(_MX53_PAD_FEC_MDIO__SDMA_DEBUG_BUS_DEVICE_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDIO__EMI_EMI_DEBUG_49		(_MX53_PAD_FEC_MDIO__EMI_EMI_DEBUG_49 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_REF_CLK__FEC_TX_CLK		(_MX53_PAD_FEC_REF_CLK__FEC_TX_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_REF_CLK__GPIO1_23		(_MX53_PAD_FEC_REF_CLK__GPIO1_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_REF_CLK__ESAI1_FSR		(_MX53_PAD_FEC_REF_CLK__ESAI1_FSR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_REF_CLK__SDMA_DEBUG_BUS_DEVICE_4		(_MX53_PAD_FEC_REF_CLK__SDMA_DEBUG_BUS_DEVICE_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_REF_CLK__EMI_EMI_DEBUG_50		(_MX53_PAD_FEC_REF_CLK__EMI_EMI_DEBUG_50 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RX_ER__FEC_RX_ER		(_MX53_PAD_FEC_RX_ER__FEC_RX_ER | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RX_ER__GPIO1_24		(_MX53_PAD_FEC_RX_ER__GPIO1_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RX_ER__ESAI1_HCKR		(_MX53_PAD_FEC_RX_ER__ESAI1_HCKR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RX_ER__FEC_RX_CLK		(_MX53_PAD_FEC_RX_ER__FEC_RX_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RX_ER__RTC_CE_RTC_PS3		(_MX53_PAD_FEC_RX_ER__RTC_CE_RTC_PS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_CRS_DV__FEC_RX_DV		(_MX53_PAD_FEC_CRS_DV__FEC_RX_DV | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_CRS_DV__GPIO1_25		(_MX53_PAD_FEC_CRS_DV__GPIO1_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_CRS_DV__ESAI1_SCKT		(_MX53_PAD_FEC_CRS_DV__ESAI1_SCKT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RXD1__FEC_RDATA_1		(_MX53_PAD_FEC_RXD1__FEC_RDATA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RXD1__GPIO1_26		(_MX53_PAD_FEC_RXD1__GPIO1_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RXD1__ESAI1_FST		(_MX53_PAD_FEC_RXD1__ESAI1_FST | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RXD1__MLB_MLBSIG		(_MX53_PAD_FEC_RXD1__MLB_MLBSIG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RXD1__RTC_CE_RTC_PS1		(_MX53_PAD_FEC_RXD1__RTC_CE_RTC_PS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RXD0__FEC_RDATA_0		(_MX53_PAD_FEC_RXD0__FEC_RDATA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RXD0__GPIO1_27		(_MX53_PAD_FEC_RXD0__GPIO1_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RXD0__ESAI1_HCKT		(_MX53_PAD_FEC_RXD0__ESAI1_HCKT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_RXD0__OSC32k_32K_OUT		(_MX53_PAD_FEC_RXD0__OSC32k_32K_OUT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TX_EN__FEC_TX_EN		(_MX53_PAD_FEC_TX_EN__FEC_TX_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TX_EN__GPIO1_28		(_MX53_PAD_FEC_TX_EN__GPIO1_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TX_EN__ESAI1_TX3_RX2		(_MX53_PAD_FEC_TX_EN__ESAI1_TX3_RX2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TXD1__FEC_TDATA_1		(_MX53_PAD_FEC_TXD1__FEC_TDATA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TXD1__GPIO1_29		(_MX53_PAD_FEC_TXD1__GPIO1_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TXD1__ESAI1_TX2_RX3		(_MX53_PAD_FEC_TXD1__ESAI1_TX2_RX3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TXD1__MLB_MLBCLK		(_MX53_PAD_FEC_TXD1__MLB_MLBCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TXD1__RTC_CE_RTC_PRSC_CLK		(_MX53_PAD_FEC_TXD1__RTC_CE_RTC_PRSC_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TXD0__FEC_TDATA_0		(_MX53_PAD_FEC_TXD0__FEC_TDATA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TXD0__GPIO1_30		(_MX53_PAD_FEC_TXD0__GPIO1_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TXD0__ESAI1_TX4_RX1		(_MX53_PAD_FEC_TXD0__ESAI1_TX4_RX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_TXD0__USBPHY2_DATAOUT_0		(_MX53_PAD_FEC_TXD0__USBPHY2_DATAOUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDC__FEC_MDC		(_MX53_PAD_FEC_MDC__FEC_MDC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDC__GPIO1_31		(_MX53_PAD_FEC_MDC__GPIO1_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDC__ESAI1_TX5_RX0		(_MX53_PAD_FEC_MDC__ESAI1_TX5_RX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDC__MLB_MLBDAT		(_MX53_PAD_FEC_MDC__MLB_MLBDAT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDC__RTC_CE_RTC_ALARM1_TRIG		(_MX53_PAD_FEC_MDC__RTC_CE_RTC_ALARM1_TRIG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_FEC_MDC__USBPHY2_DATAOUT_1		(_MX53_PAD_FEC_MDC__USBPHY2_DATAOUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DIOW__PATA_DIOW		(_MX53_PAD_PATA_DIOW__PATA_DIOW | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DIOW__GPIO6_17		(_MX53_PAD_PATA_DIOW__GPIO6_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DIOW__UART1_TXD_MUX		(_MX53_PAD_PATA_DIOW__UART1_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_DIOW__USBPHY2_DATAOUT_2		(_MX53_PAD_PATA_DIOW__USBPHY2_DATAOUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DMACK__PATA_DMACK		(_MX53_PAD_PATA_DMACK__PATA_DMACK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DMACK__GPIO6_18		(_MX53_PAD_PATA_DMACK__GPIO6_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DMACK__UART1_RXD_MUX		(_MX53_PAD_PATA_DMACK__UART1_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_DMACK__USBPHY2_DATAOUT_3		(_MX53_PAD_PATA_DMACK__USBPHY2_DATAOUT_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DMARQ__PATA_DMARQ		(_MX53_PAD_PATA_DMARQ__PATA_DMARQ | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DMARQ__GPIO7_0		(_MX53_PAD_PATA_DMARQ__GPIO7_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DMARQ__UART2_TXD_MUX		(_MX53_PAD_PATA_DMARQ__UART2_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_DMARQ__CCM_CCM_OUT_0		(_MX53_PAD_PATA_DMARQ__CCM_CCM_OUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DMARQ__USBPHY2_DATAOUT_4		(_MX53_PAD_PATA_DMARQ__USBPHY2_DATAOUT_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_BUFFER_EN__PATA_BUFFER_EN		(_MX53_PAD_PATA_BUFFER_EN__PATA_BUFFER_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_BUFFER_EN__GPIO7_1		(_MX53_PAD_PATA_BUFFER_EN__GPIO7_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX		(_MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_BUFFER_EN__CCM_CCM_OUT_1		(_MX53_PAD_PATA_BUFFER_EN__CCM_CCM_OUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_BUFFER_EN__USBPHY2_DATAOUT_5		(_MX53_PAD_PATA_BUFFER_EN__USBPHY2_DATAOUT_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_INTRQ__PATA_INTRQ		(_MX53_PAD_PATA_INTRQ__PATA_INTRQ | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_INTRQ__GPIO7_2		(_MX53_PAD_PATA_INTRQ__GPIO7_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_INTRQ__UART2_CTS		(_MX53_PAD_PATA_INTRQ__UART2_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_INTRQ__CAN1_TXCAN		(_MX53_PAD_PATA_INTRQ__CAN1_TXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_INTRQ__CCM_CCM_OUT_2		(_MX53_PAD_PATA_INTRQ__CCM_CCM_OUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_INTRQ__USBPHY2_DATAOUT_6		(_MX53_PAD_PATA_INTRQ__USBPHY2_DATAOUT_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DIOR__PATA_DIOR		(_MX53_PAD_PATA_DIOR__PATA_DIOR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DIOR__GPIO7_3		(_MX53_PAD_PATA_DIOR__GPIO7_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DIOR__UART2_RTS		(_MX53_PAD_PATA_DIOR__UART2_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_DIOR__CAN1_RXCAN		(_MX53_PAD_PATA_DIOR__CAN1_RXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DIOR__USBPHY2_DATAOUT_7		(_MX53_PAD_PATA_DIOR__USBPHY2_DATAOUT_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_RESET_B__PATA_PATA_RESET_B		(_MX53_PAD_PATA_RESET_B__PATA_PATA_RESET_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_RESET_B__GPIO7_4		(_MX53_PAD_PATA_RESET_B__GPIO7_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_RESET_B__ESDHC3_CMD		(_MX53_PAD_PATA_RESET_B__ESDHC3_CMD | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_RESET_B__UART1_CTS		(_MX53_PAD_PATA_RESET_B__UART1_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_RESET_B__CAN2_TXCAN		(_MX53_PAD_PATA_RESET_B__CAN2_TXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_RESET_B__USBPHY1_DATAOUT_0		(_MX53_PAD_PATA_RESET_B__USBPHY1_DATAOUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_IORDY__PATA_IORDY		(_MX53_PAD_PATA_IORDY__PATA_IORDY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_IORDY__GPIO7_5		(_MX53_PAD_PATA_IORDY__GPIO7_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_IORDY__ESDHC3_CLK		(_MX53_PAD_PATA_IORDY__ESDHC3_CLK | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_IORDY__UART1_RTS		(_MX53_PAD_PATA_IORDY__UART1_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_IORDY__CAN2_RXCAN		(_MX53_PAD_PATA_IORDY__CAN2_RXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_IORDY__USBPHY1_DATAOUT_1		(_MX53_PAD_PATA_IORDY__USBPHY1_DATAOUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_0__PATA_DA_0		(_MX53_PAD_PATA_DA_0__PATA_DA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_0__GPIO7_6		(_MX53_PAD_PATA_DA_0__GPIO7_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_0__ESDHC3_RST		(_MX53_PAD_PATA_DA_0__ESDHC3_RST | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_0__OWIRE_LINE		(_MX53_PAD_PATA_DA_0__OWIRE_LINE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_0__USBPHY1_DATAOUT_2		(_MX53_PAD_PATA_DA_0__USBPHY1_DATAOUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_1__PATA_DA_1		(_MX53_PAD_PATA_DA_1__PATA_DA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_1__GPIO7_7		(_MX53_PAD_PATA_DA_1__GPIO7_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_1__ESDHC4_CMD		(_MX53_PAD_PATA_DA_1__ESDHC4_CMD | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DA_1__UART3_CTS		(_MX53_PAD_PATA_DA_1__UART3_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_DA_1__USBPHY1_DATAOUT_3		(_MX53_PAD_PATA_DA_1__USBPHY1_DATAOUT_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_2__PATA_DA_2		(_MX53_PAD_PATA_DA_2__PATA_DA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_2__GPIO7_8		(_MX53_PAD_PATA_DA_2__GPIO7_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DA_2__ESDHC4_CLK		(_MX53_PAD_PATA_DA_2__ESDHC4_CLK | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DA_2__UART3_RTS		(_MX53_PAD_PATA_DA_2__UART3_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_DA_2__USBPHY1_DATAOUT_4		(_MX53_PAD_PATA_DA_2__USBPHY1_DATAOUT_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_CS_0__PATA_CS_0		(_MX53_PAD_PATA_CS_0__PATA_CS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_CS_0__GPIO7_9		(_MX53_PAD_PATA_CS_0__GPIO7_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_CS_0__UART3_TXD_MUX		(_MX53_PAD_PATA_CS_0__UART3_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_CS_0__USBPHY1_DATAOUT_5		(_MX53_PAD_PATA_CS_0__USBPHY1_DATAOUT_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_CS_1__PATA_CS_1		(_MX53_PAD_PATA_CS_1__PATA_CS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_CS_1__GPIO7_10		(_MX53_PAD_PATA_CS_1__GPIO7_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_CS_1__UART3_RXD_MUX		(_MX53_PAD_PATA_CS_1__UART3_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_PATA_CS_1__USBPHY1_DATAOUT_6		(_MX53_PAD_PATA_CS_1__USBPHY1_DATAOUT_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA0__PATA_DATA_0		(_MX53_PAD_PATA_DATA0__PATA_DATA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA0__GPIO2_0		(_MX53_PAD_PATA_DATA0__GPIO2_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA0__EMI_NANDF_D_0		(_MX53_PAD_PATA_DATA0__EMI_NANDF_D_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA0__ESDHC3_DAT4		(_MX53_PAD_PATA_DATA0__ESDHC3_DAT4 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA0__GPU3d_GPU_DEBUG_OUT_0		(_MX53_PAD_PATA_DATA0__GPU3d_GPU_DEBUG_OUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA0__IPU_DIAG_BUS_0		(_MX53_PAD_PATA_DATA0__IPU_DIAG_BUS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA0__USBPHY1_DATAOUT_7		(_MX53_PAD_PATA_DATA0__USBPHY1_DATAOUT_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA1__PATA_DATA_1		(_MX53_PAD_PATA_DATA1__PATA_DATA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA1__GPIO2_1		(_MX53_PAD_PATA_DATA1__GPIO2_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA1__EMI_NANDF_D_1		(_MX53_PAD_PATA_DATA1__EMI_NANDF_D_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA1__ESDHC3_DAT5		(_MX53_PAD_PATA_DATA1__ESDHC3_DAT5 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA1__GPU3d_GPU_DEBUG_OUT_1		(_MX53_PAD_PATA_DATA1__GPU3d_GPU_DEBUG_OUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA1__IPU_DIAG_BUS_1		(_MX53_PAD_PATA_DATA1__IPU_DIAG_BUS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA2__PATA_DATA_2		(_MX53_PAD_PATA_DATA2__PATA_DATA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA2__GPIO2_2		(_MX53_PAD_PATA_DATA2__GPIO2_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA2__EMI_NANDF_D_2		(_MX53_PAD_PATA_DATA2__EMI_NANDF_D_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA2__ESDHC3_DAT6		(_MX53_PAD_PATA_DATA2__ESDHC3_DAT6 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA2__GPU3d_GPU_DEBUG_OUT_2		(_MX53_PAD_PATA_DATA2__GPU3d_GPU_DEBUG_OUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA2__IPU_DIAG_BUS_2		(_MX53_PAD_PATA_DATA2__IPU_DIAG_BUS_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA3__PATA_DATA_3		(_MX53_PAD_PATA_DATA3__PATA_DATA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA3__GPIO2_3		(_MX53_PAD_PATA_DATA3__GPIO2_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA3__EMI_NANDF_D_3		(_MX53_PAD_PATA_DATA3__EMI_NANDF_D_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA3__ESDHC3_DAT7		(_MX53_PAD_PATA_DATA3__ESDHC3_DAT7 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA3__GPU3d_GPU_DEBUG_OUT_3		(_MX53_PAD_PATA_DATA3__GPU3d_GPU_DEBUG_OUT_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA3__IPU_DIAG_BUS_3		(_MX53_PAD_PATA_DATA3__IPU_DIAG_BUS_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA4__PATA_DATA_4		(_MX53_PAD_PATA_DATA4__PATA_DATA_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA4__GPIO2_4		(_MX53_PAD_PATA_DATA4__GPIO2_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA4__EMI_NANDF_D_4		(_MX53_PAD_PATA_DATA4__EMI_NANDF_D_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA4__ESDHC4_DAT4		(_MX53_PAD_PATA_DATA4__ESDHC4_DAT4 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA4__GPU3d_GPU_DEBUG_OUT_4		(_MX53_PAD_PATA_DATA4__GPU3d_GPU_DEBUG_OUT_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA4__IPU_DIAG_BUS_4		(_MX53_PAD_PATA_DATA4__IPU_DIAG_BUS_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA5__PATA_DATA_5		(_MX53_PAD_PATA_DATA5__PATA_DATA_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA5__GPIO2_5		(_MX53_PAD_PATA_DATA5__GPIO2_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA5__EMI_NANDF_D_5		(_MX53_PAD_PATA_DATA5__EMI_NANDF_D_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA5__ESDHC4_DAT5		(_MX53_PAD_PATA_DATA5__ESDHC4_DAT5 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA5__GPU3d_GPU_DEBUG_OUT_5		(_MX53_PAD_PATA_DATA5__GPU3d_GPU_DEBUG_OUT_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA5__IPU_DIAG_BUS_5		(_MX53_PAD_PATA_DATA5__IPU_DIAG_BUS_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA6__PATA_DATA_6		(_MX53_PAD_PATA_DATA6__PATA_DATA_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA6__GPIO2_6		(_MX53_PAD_PATA_DATA6__GPIO2_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA6__EMI_NANDF_D_6		(_MX53_PAD_PATA_DATA6__EMI_NANDF_D_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA6__ESDHC4_DAT6		(_MX53_PAD_PATA_DATA6__ESDHC4_DAT6 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA6__GPU3d_GPU_DEBUG_OUT_6		(_MX53_PAD_PATA_DATA6__GPU3d_GPU_DEBUG_OUT_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA6__IPU_DIAG_BUS_6		(_MX53_PAD_PATA_DATA6__IPU_DIAG_BUS_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA7__PATA_DATA_7		(_MX53_PAD_PATA_DATA7__PATA_DATA_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA7__GPIO2_7		(_MX53_PAD_PATA_DATA7__GPIO2_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA7__EMI_NANDF_D_7		(_MX53_PAD_PATA_DATA7__EMI_NANDF_D_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA7__ESDHC4_DAT7		(_MX53_PAD_PATA_DATA7__ESDHC4_DAT7 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA7__GPU3d_GPU_DEBUG_OUT_7		(_MX53_PAD_PATA_DATA7__GPU3d_GPU_DEBUG_OUT_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA7__IPU_DIAG_BUS_7		(_MX53_PAD_PATA_DATA7__IPU_DIAG_BUS_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA8__PATA_DATA_8		(_MX53_PAD_PATA_DATA8__PATA_DATA_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA8__GPIO2_8		(_MX53_PAD_PATA_DATA8__GPIO2_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA8__ESDHC1_DAT4		(_MX53_PAD_PATA_DATA8__ESDHC1_DAT4 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA8__EMI_NANDF_D_8		(_MX53_PAD_PATA_DATA8__EMI_NANDF_D_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA8__ESDHC3_DAT0		(_MX53_PAD_PATA_DATA8__ESDHC3_DAT0 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA8__GPU3d_GPU_DEBUG_OUT_8		(_MX53_PAD_PATA_DATA8__GPU3d_GPU_DEBUG_OUT_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA8__IPU_DIAG_BUS_8		(_MX53_PAD_PATA_DATA8__IPU_DIAG_BUS_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA9__PATA_DATA_9		(_MX53_PAD_PATA_DATA9__PATA_DATA_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA9__GPIO2_9		(_MX53_PAD_PATA_DATA9__GPIO2_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA9__ESDHC1_DAT5		(_MX53_PAD_PATA_DATA9__ESDHC1_DAT5 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA9__EMI_NANDF_D_9		(_MX53_PAD_PATA_DATA9__EMI_NANDF_D_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA9__ESDHC3_DAT1		(_MX53_PAD_PATA_DATA9__ESDHC3_DAT1 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA9__GPU3d_GPU_DEBUG_OUT_9		(_MX53_PAD_PATA_DATA9__GPU3d_GPU_DEBUG_OUT_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA9__IPU_DIAG_BUS_9		(_MX53_PAD_PATA_DATA9__IPU_DIAG_BUS_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA10__PATA_DATA_10		(_MX53_PAD_PATA_DATA10__PATA_DATA_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA10__GPIO2_10		(_MX53_PAD_PATA_DATA10__GPIO2_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA10__ESDHC1_DAT6		(_MX53_PAD_PATA_DATA10__ESDHC1_DAT6 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA10__EMI_NANDF_D_10		(_MX53_PAD_PATA_DATA10__EMI_NANDF_D_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA10__ESDHC3_DAT2		(_MX53_PAD_PATA_DATA10__ESDHC3_DAT2 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA10__GPU3d_GPU_DEBUG_OUT_10		(_MX53_PAD_PATA_DATA10__GPU3d_GPU_DEBUG_OUT_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA10__IPU_DIAG_BUS_10		(_MX53_PAD_PATA_DATA10__IPU_DIAG_BUS_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA11__PATA_DATA_11		(_MX53_PAD_PATA_DATA11__PATA_DATA_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA11__GPIO2_11		(_MX53_PAD_PATA_DATA11__GPIO2_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA11__ESDHC1_DAT7		(_MX53_PAD_PATA_DATA11__ESDHC1_DAT7 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA11__EMI_NANDF_D_11		(_MX53_PAD_PATA_DATA11__EMI_NANDF_D_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA11__ESDHC3_DAT3		(_MX53_PAD_PATA_DATA11__ESDHC3_DAT3 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA11__GPU3d_GPU_DEBUG_OUT_11		(_MX53_PAD_PATA_DATA11__GPU3d_GPU_DEBUG_OUT_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA11__IPU_DIAG_BUS_11		(_MX53_PAD_PATA_DATA11__IPU_DIAG_BUS_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA12__PATA_DATA_12		(_MX53_PAD_PATA_DATA12__PATA_DATA_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA12__GPIO2_12		(_MX53_PAD_PATA_DATA12__GPIO2_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA12__ESDHC2_DAT4		(_MX53_PAD_PATA_DATA12__ESDHC2_DAT4 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA12__EMI_NANDF_D_12		(_MX53_PAD_PATA_DATA12__EMI_NANDF_D_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA12__ESDHC4_DAT0		(_MX53_PAD_PATA_DATA12__ESDHC4_DAT0 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA12__GPU3d_GPU_DEBUG_OUT_12		(_MX53_PAD_PATA_DATA12__GPU3d_GPU_DEBUG_OUT_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA12__IPU_DIAG_BUS_12		(_MX53_PAD_PATA_DATA12__IPU_DIAG_BUS_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA13__PATA_DATA_13		(_MX53_PAD_PATA_DATA13__PATA_DATA_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA13__GPIO2_13		(_MX53_PAD_PATA_DATA13__GPIO2_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA13__ESDHC2_DAT5		(_MX53_PAD_PATA_DATA13__ESDHC2_DAT5 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA13__EMI_NANDF_D_13		(_MX53_PAD_PATA_DATA13__EMI_NANDF_D_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA13__ESDHC4_DAT1		(_MX53_PAD_PATA_DATA13__ESDHC4_DAT1 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA13__GPU3d_GPU_DEBUG_OUT_13		(_MX53_PAD_PATA_DATA13__GPU3d_GPU_DEBUG_OUT_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA13__IPU_DIAG_BUS_13		(_MX53_PAD_PATA_DATA13__IPU_DIAG_BUS_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA14__PATA_DATA_14		(_MX53_PAD_PATA_DATA14__PATA_DATA_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA14__GPIO2_14		(_MX53_PAD_PATA_DATA14__GPIO2_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA14__ESDHC2_DAT6		(_MX53_PAD_PATA_DATA14__ESDHC2_DAT6 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA14__EMI_NANDF_D_14		(_MX53_PAD_PATA_DATA14__EMI_NANDF_D_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA14__ESDHC4_DAT2		(_MX53_PAD_PATA_DATA14__ESDHC4_DAT2 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA14__GPU3d_GPU_DEBUG_OUT_14		(_MX53_PAD_PATA_DATA14__GPU3d_GPU_DEBUG_OUT_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA14__IPU_DIAG_BUS_14		(_MX53_PAD_PATA_DATA14__IPU_DIAG_BUS_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA15__PATA_DATA_15		(_MX53_PAD_PATA_DATA15__PATA_DATA_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA15__GPIO2_15		(_MX53_PAD_PATA_DATA15__GPIO2_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA15__ESDHC2_DAT7		(_MX53_PAD_PATA_DATA15__ESDHC2_DAT7 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA15__EMI_NANDF_D_15		(_MX53_PAD_PATA_DATA15__EMI_NANDF_D_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA15__ESDHC4_DAT3		(_MX53_PAD_PATA_DATA15__ESDHC4_DAT3 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_PATA_DATA15__GPU3d_GPU_DEBUG_OUT_15		(_MX53_PAD_PATA_DATA15__GPU3d_GPU_DEBUG_OUT_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_PATA_DATA15__IPU_DIAG_BUS_15		(_MX53_PAD_PATA_DATA15__IPU_DIAG_BUS_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA0__ESDHC1_DAT0		(_MX53_PAD_SD1_DATA0__ESDHC1_DAT0 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD1_DATA0__GPIO1_16		(_MX53_PAD_SD1_DATA0__GPIO1_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA0__GPT_CAPIN1		(_MX53_PAD_SD1_DATA0__GPT_CAPIN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA0__CSPI_MISO		(_MX53_PAD_SD1_DATA0__CSPI_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA0__CCM_PLL3_BYP		(_MX53_PAD_SD1_DATA0__CCM_PLL3_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA1__ESDHC1_DAT1		(_MX53_PAD_SD1_DATA1__ESDHC1_DAT1 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD1_DATA1__GPIO1_17		(_MX53_PAD_SD1_DATA1__GPIO1_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA1__GPT_CAPIN2		(_MX53_PAD_SD1_DATA1__GPT_CAPIN2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA1__CSPI_SS0		(_MX53_PAD_SD1_DATA1__CSPI_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA1__CCM_PLL4_BYP		(_MX53_PAD_SD1_DATA1__CCM_PLL4_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_CMD__ESDHC1_CMD		(_MX53_PAD_SD1_CMD__ESDHC1_CMD | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD1_CMD__GPIO1_18		(_MX53_PAD_SD1_CMD__GPIO1_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_CMD__GPT_CMPOUT1		(_MX53_PAD_SD1_CMD__GPT_CMPOUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_CMD__CSPI_MOSI		(_MX53_PAD_SD1_CMD__CSPI_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_CMD__CCM_PLL1_BYP		(_MX53_PAD_SD1_CMD__CCM_PLL1_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA2__ESDHC1_DAT2		(_MX53_PAD_SD1_DATA2__ESDHC1_DAT2 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD1_DATA2__GPIO1_19		(_MX53_PAD_SD1_DATA2__GPIO1_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA2__GPT_CMPOUT2		(_MX53_PAD_SD1_DATA2__GPT_CMPOUT2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA2__PWM2_PWMO		(_MX53_PAD_SD1_DATA2__PWM2_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA2__WDOG1_WDOG_B		(_MX53_PAD_SD1_DATA2__WDOG1_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA2__CSPI_SS1		(_MX53_PAD_SD1_DATA2__CSPI_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA2__WDOG1_WDOG_RST_B_DEB		(_MX53_PAD_SD1_DATA2__WDOG1_WDOG_RST_B_DEB | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA2__CCM_PLL2_BYP		(_MX53_PAD_SD1_DATA2__CCM_PLL2_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_CLK__ESDHC1_CLK		(_MX53_PAD_SD1_CLK__ESDHC1_CLK | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD1_CLK__GPIO1_20		(_MX53_PAD_SD1_CLK__GPIO1_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_CLK__OSC32k_32K_OUT		(_MX53_PAD_SD1_CLK__OSC32k_32K_OUT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_CLK__GPT_CLKIN		(_MX53_PAD_SD1_CLK__GPT_CLKIN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_CLK__CSPI_SCLK		(_MX53_PAD_SD1_CLK__CSPI_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_CLK__SATA_PHY_DTB_0		(_MX53_PAD_SD1_CLK__SATA_PHY_DTB_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA3__ESDHC1_DAT3		(_MX53_PAD_SD1_DATA3__ESDHC1_DAT3 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD1_DATA3__GPIO1_21		(_MX53_PAD_SD1_DATA3__GPIO1_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA3__GPT_CMPOUT3		(_MX53_PAD_SD1_DATA3__GPT_CMPOUT3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA3__PWM1_PWMO		(_MX53_PAD_SD1_DATA3__PWM1_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA3__WDOG2_WDOG_B		(_MX53_PAD_SD1_DATA3__WDOG2_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA3__CSPI_SS2		(_MX53_PAD_SD1_DATA3__CSPI_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA3__WDOG2_WDOG_RST_B_DEB		(_MX53_PAD_SD1_DATA3__WDOG2_WDOG_RST_B_DEB | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD1_DATA3__SATA_PHY_DTB_1		(_MX53_PAD_SD1_DATA3__SATA_PHY_DTB_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_CLK__ESDHC2_CLK		(_MX53_PAD_SD2_CLK__ESDHC2_CLK | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD2_CLK__GPIO1_10		(_MX53_PAD_SD2_CLK__GPIO1_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_CLK__KPP_COL_5		(_MX53_PAD_SD2_CLK__KPP_COL_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_CLK__AUDMUX_AUD4_RXFS		(_MX53_PAD_SD2_CLK__AUDMUX_AUD4_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_CLK__CSPI_SCLK		(_MX53_PAD_SD2_CLK__CSPI_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_CLK__SCC_RANDOM_V		(_MX53_PAD_SD2_CLK__SCC_RANDOM_V | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_CMD__ESDHC2_CMD		(_MX53_PAD_SD2_CMD__ESDHC2_CMD | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD2_CMD__GPIO1_11		(_MX53_PAD_SD2_CMD__GPIO1_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_CMD__KPP_ROW_5		(_MX53_PAD_SD2_CMD__KPP_ROW_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_CMD__AUDMUX_AUD4_RXC		(_MX53_PAD_SD2_CMD__AUDMUX_AUD4_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_CMD__CSPI_MOSI		(_MX53_PAD_SD2_CMD__CSPI_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_CMD__SCC_RANDOM		(_MX53_PAD_SD2_CMD__SCC_RANDOM | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA3__ESDHC2_DAT3		(_MX53_PAD_SD2_DATA3__ESDHC2_DAT3 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD2_DATA3__GPIO1_12		(_MX53_PAD_SD2_DATA3__GPIO1_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA3__KPP_COL_6		(_MX53_PAD_SD2_DATA3__KPP_COL_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC		(_MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA3__CSPI_SS2		(_MX53_PAD_SD2_DATA3__CSPI_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA3__SJC_DONE		(_MX53_PAD_SD2_DATA3__SJC_DONE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA2__ESDHC2_DAT2		(_MX53_PAD_SD2_DATA2__ESDHC2_DAT2 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD2_DATA2__GPIO1_13		(_MX53_PAD_SD2_DATA2__GPIO1_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA2__KPP_ROW_6		(_MX53_PAD_SD2_DATA2__KPP_ROW_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD		(_MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA2__CSPI_SS1		(_MX53_PAD_SD2_DATA2__CSPI_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA2__SJC_FAIL		(_MX53_PAD_SD2_DATA2__SJC_FAIL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA1__ESDHC2_DAT1		(_MX53_PAD_SD2_DATA1__ESDHC2_DAT1 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD2_DATA1__GPIO1_14		(_MX53_PAD_SD2_DATA1__GPIO1_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA1__KPP_COL_7		(_MX53_PAD_SD2_DATA1__KPP_COL_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS		(_MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA1__CSPI_SS0		(_MX53_PAD_SD2_DATA1__CSPI_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA1__RTIC_SEC_VIO		(_MX53_PAD_SD2_DATA1__RTIC_SEC_VIO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA0__ESDHC2_DAT0		(_MX53_PAD_SD2_DATA0__ESDHC2_DAT0 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
-#define MX53_PAD_SD2_DATA0__GPIO1_15		(_MX53_PAD_SD2_DATA0__GPIO1_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA0__KPP_ROW_7		(_MX53_PAD_SD2_DATA0__KPP_ROW_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD		(_MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA0__CSPI_MISO		(_MX53_PAD_SD2_DATA0__CSPI_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_SD2_DATA0__RTIC_DONE_INT		(_MX53_PAD_SD2_DATA0__RTIC_DONE_INT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_0__CCM_CLKO		(_MX53_PAD_GPIO_0__CCM_CLKO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_0__GPIO1_0		(_MX53_PAD_GPIO_0__GPIO1_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_0__KPP_COL_5		(_MX53_PAD_GPIO_0__KPP_COL_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK		(_MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_0__EPIT1_EPITO		(_MX53_PAD_GPIO_0__EPIT1_EPITO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_0__SRTC_ALARM_DEB		(_MX53_PAD_GPIO_0__SRTC_ALARM_DEB | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_0__USBOH3_USBH1_PWR		(_MX53_PAD_GPIO_0__USBOH3_USBH1_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_0__CSU_TD		(_MX53_PAD_GPIO_0__CSU_TD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_1__ESAI1_SCKR		(_MX53_PAD_GPIO_1__ESAI1_SCKR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_1__GPIO1_1		(_MX53_PAD_GPIO_1__GPIO1_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_1__KPP_ROW_5		(_MX53_PAD_GPIO_1__KPP_ROW_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_1__CCM_SSI_EXT2_CLK		(_MX53_PAD_GPIO_1__CCM_SSI_EXT2_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_1__PWM2_PWMO		(_MX53_PAD_GPIO_1__PWM2_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_1__WDOG2_WDOG_B		(_MX53_PAD_GPIO_1__WDOG2_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_1__ESDHC1_CD		(_MX53_PAD_GPIO_1__ESDHC1_CD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_1__SRC_TESTER_ACK		(_MX53_PAD_GPIO_1__SRC_TESTER_ACK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_9__ESAI1_FSR		(_MX53_PAD_GPIO_9__ESAI1_FSR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_9__GPIO1_9		(_MX53_PAD_GPIO_9__GPIO1_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_9__KPP_COL_6		(_MX53_PAD_GPIO_9__KPP_COL_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_9__CCM_REF_EN_B		(_MX53_PAD_GPIO_9__CCM_REF_EN_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_9__PWM1_PWMO		(_MX53_PAD_GPIO_9__PWM1_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_9__WDOG1_WDOG_B		(_MX53_PAD_GPIO_9__WDOG1_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_9__ESDHC1_WP		(_MX53_PAD_GPIO_9__ESDHC1_WP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_9__SCC_FAIL_STATE		(_MX53_PAD_GPIO_9__SCC_FAIL_STATE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_3__ESAI1_HCKR		(_MX53_PAD_GPIO_3__ESAI1_HCKR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_3__GPIO1_3		(_MX53_PAD_GPIO_3__GPIO1_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_3__I2C3_SCL		(_MX53_PAD_GPIO_3__I2C3_SCL | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_GPIO_3__DPLLIP1_TOG_EN		(_MX53_PAD_GPIO_3__DPLLIP1_TOG_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_3__CCM_CLKO2		(_MX53_PAD_GPIO_3__CCM_CLKO2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_3__OBSERVE_MUX_OBSRV_INT_OUT0		(_MX53_PAD_GPIO_3__OBSERVE_MUX_OBSRV_INT_OUT0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_3__USBOH3_USBH1_OC		(_MX53_PAD_GPIO_3__USBOH3_USBH1_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_3__MLB_MLBCLK		(_MX53_PAD_GPIO_3__MLB_MLBCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_6__ESAI1_SCKT		(_MX53_PAD_GPIO_6__ESAI1_SCKT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_6__GPIO1_6		(_MX53_PAD_GPIO_6__GPIO1_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_6__I2C3_SDA		(_MX53_PAD_GPIO_6__I2C3_SDA | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_GPIO_6__CCM_CCM_OUT_0		(_MX53_PAD_GPIO_6__CCM_CCM_OUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_6__CSU_CSU_INT_DEB		(_MX53_PAD_GPIO_6__CSU_CSU_INT_DEB | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1		(_MX53_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_6__ESDHC2_LCTL		(_MX53_PAD_GPIO_6__ESDHC2_LCTL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_6__MLB_MLBSIG		(_MX53_PAD_GPIO_6__MLB_MLBSIG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_2__ESAI1_FST		(_MX53_PAD_GPIO_2__ESAI1_FST | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_2__GPIO1_2		(_MX53_PAD_GPIO_2__GPIO1_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_2__KPP_ROW_6		(_MX53_PAD_GPIO_2__KPP_ROW_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_2__CCM_CCM_OUT_1		(_MX53_PAD_GPIO_2__CCM_CCM_OUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0		(_MX53_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_2__OBSERVE_MUX_OBSRV_INT_OUT2		(_MX53_PAD_GPIO_2__OBSERVE_MUX_OBSRV_INT_OUT2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_2__ESDHC2_WP		(_MX53_PAD_GPIO_2__ESDHC2_WP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_2__MLB_MLBDAT		(_MX53_PAD_GPIO_2__MLB_MLBDAT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_4__ESAI1_HCKT		(_MX53_PAD_GPIO_4__ESAI1_HCKT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_4__GPIO1_4		(_MX53_PAD_GPIO_4__GPIO1_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_4__KPP_COL_7		(_MX53_PAD_GPIO_4__KPP_COL_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_4__CCM_CCM_OUT_2		(_MX53_PAD_GPIO_4__CCM_CCM_OUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1		(_MX53_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_4__OBSERVE_MUX_OBSRV_INT_OUT3		(_MX53_PAD_GPIO_4__OBSERVE_MUX_OBSRV_INT_OUT3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_4__ESDHC2_CD		(_MX53_PAD_GPIO_4__ESDHC2_CD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_4__SCC_SEC_STATE		(_MX53_PAD_GPIO_4__SCC_SEC_STATE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_5__ESAI1_TX2_RX3		(_MX53_PAD_GPIO_5__ESAI1_TX2_RX3 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_5__GPIO1_5		(_MX53_PAD_GPIO_5__GPIO1_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_5__KPP_ROW_7		(_MX53_PAD_GPIO_5__KPP_ROW_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_5__CCM_CLKO		(_MX53_PAD_GPIO_5__CCM_CLKO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2		(_MX53_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_5__OBSERVE_MUX_OBSRV_INT_OUT4		(_MX53_PAD_GPIO_5__OBSERVE_MUX_OBSRV_INT_OUT4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_5__I2C3_SCL		(_MX53_PAD_GPIO_5__I2C3_SCL | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_GPIO_5__CCM_PLL1_BYP		(_MX53_PAD_GPIO_5__CCM_PLL1_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_7__ESAI1_TX4_RX1		(_MX53_PAD_GPIO_7__ESAI1_TX4_RX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_7__GPIO1_7		(_MX53_PAD_GPIO_7__GPIO1_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_7__EPIT1_EPITO		(_MX53_PAD_GPIO_7__EPIT1_EPITO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_7__CAN1_TXCAN		(_MX53_PAD_GPIO_7__CAN1_TXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_7__UART2_TXD_MUX		(_MX53_PAD_GPIO_7__UART2_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_GPIO_7__FIRI_RXD		(_MX53_PAD_GPIO_7__FIRI_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_7__SPDIF_PLOCK		(_MX53_PAD_GPIO_7__SPDIF_PLOCK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_7__CCM_PLL2_BYP		(_MX53_PAD_GPIO_7__CCM_PLL2_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_8__ESAI1_TX5_RX0		(_MX53_PAD_GPIO_8__ESAI1_TX5_RX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_8__GPIO1_8		(_MX53_PAD_GPIO_8__GPIO1_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_8__EPIT2_EPITO		(_MX53_PAD_GPIO_8__EPIT2_EPITO | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_8__CAN1_RXCAN		(_MX53_PAD_GPIO_8__CAN1_RXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_8__UART2_RXD_MUX		(_MX53_PAD_GPIO_8__UART2_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
-#define MX53_PAD_GPIO_8__FIRI_TXD		(_MX53_PAD_GPIO_8__FIRI_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_8__SPDIF_SRCLK		(_MX53_PAD_GPIO_8__SPDIF_SRCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_8__CCM_PLL3_BYP		(_MX53_PAD_GPIO_8__CCM_PLL3_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_16__ESAI1_TX3_RX2		(_MX53_PAD_GPIO_16__ESAI1_TX3_RX2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_16__GPIO7_11		(_MX53_PAD_GPIO_16__GPIO7_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_16__TZIC_PWRFAIL_INT		(_MX53_PAD_GPIO_16__TZIC_PWRFAIL_INT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_16__RTC_CE_RTC_EXT_TRIG1		(_MX53_PAD_GPIO_16__RTC_CE_RTC_EXT_TRIG1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_16__SPDIF_IN1		(_MX53_PAD_GPIO_16__SPDIF_IN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_16__I2C3_SDA		(_MX53_PAD_GPIO_16__I2C3_SDA | MUX_PAD_CTRL(PAD_CTRL_I2C))
-#define MX53_PAD_GPIO_16__SJC_DE_B		(_MX53_PAD_GPIO_16__SJC_DE_B | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_17__ESAI1_TX0		(_MX53_PAD_GPIO_17__ESAI1_TX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_17__GPIO7_12		(_MX53_PAD_GPIO_17__GPIO7_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_17__SDMA_EXT_EVENT_0		(_MX53_PAD_GPIO_17__SDMA_EXT_EVENT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_17__GPC_PMIC_RDY		(_MX53_PAD_GPIO_17__GPC_PMIC_RDY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_17__RTC_CE_RTC_FSV_TRIG		(_MX53_PAD_GPIO_17__RTC_CE_RTC_FSV_TRIG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_17__SPDIF_OUT1		(_MX53_PAD_GPIO_17__SPDIF_OUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_17__IPU_SNOOP2		(_MX53_PAD_GPIO_17__IPU_SNOOP2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_17__SJC_JTAG_ACT		(_MX53_PAD_GPIO_17__SJC_JTAG_ACT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_18__ESAI1_TX1		(_MX53_PAD_GPIO_18__ESAI1_TX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_18__GPIO7_13		(_MX53_PAD_GPIO_18__GPIO7_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_18__SDMA_EXT_EVENT_1		(_MX53_PAD_GPIO_18__SDMA_EXT_EVENT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_18__OWIRE_LINE		(_MX53_PAD_GPIO_18__OWIRE_LINE | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_18__RTC_CE_RTC_ALARM2_TRIG		(_MX53_PAD_GPIO_18__RTC_CE_RTC_ALARM2_TRIG | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_18__CCM_ASRC_EXT_CLK		(_MX53_PAD_GPIO_18__CCM_ASRC_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_18__ESDHC1_LCTL		(_MX53_PAD_GPIO_18__ESDHC1_LCTL | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX53_PAD_GPIO_18__SRC_SYSTEM_RST		(_MX53_PAD_GPIO_18__SRC_SYSTEM_RST | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_19__KPP_COL_5			IOMUX_PAD(0x348, 0x020, 0, 0x840, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_19__GPIO4_5			IOMUX_PAD(0x348, 0x020, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_19__CCM_CLKO			IOMUX_PAD(0x348, 0x020, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_19__SPDIF_OUT1			IOMUX_PAD(0x348, 0x020, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_19__RTC_CE_RTC_EXT_TRIG2		IOMUX_PAD(0x348, 0x020, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_19__ECSPI1_RDY			IOMUX_PAD(0x348, 0x020, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_19__FEC_TDATA_3			IOMUX_PAD(0x348, 0x020, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_19__SRC_INT_BOOT			IOMUX_PAD(0x348, 0x020, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL0__KPP_COL_0			IOMUX_PAD(0x34C, 0x024, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL0__GPIO4_6			IOMUX_PAD(0x34C, 0x024, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC		IOMUX_PAD(0x34C, 0x024, 2, 0x758, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL0__UART4_TXD_MUX		IOMUX_PAD(0x34C, 0x024, 4, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_KEY_COL0__ECSPI1_SCLK			IOMUX_PAD(0x34C, 0x024, 5, 0x79C, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL0__FEC_RDATA_3			IOMUX_PAD(0x34C, 0x024, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL0__SRC_ANY_PU_RST		IOMUX_PAD(0x34C, 0x024, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW0__KPP_ROW_0			IOMUX_PAD(0x350, 0x028, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW0__GPIO4_7			IOMUX_PAD(0x350, 0x028, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD		IOMUX_PAD(0x350, 0x028, 2, 0x74C, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW0__UART4_RXD_MUX		IOMUX_PAD(0x350, 0x028, 4, 0x890, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_KEY_ROW0__ECSPI1_MOSI			IOMUX_PAD(0x350, 0x028, 5, 0x7A4, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW0__FEC_TX_ER			IOMUX_PAD(0x350, 0x028, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL1__KPP_COL_1			IOMUX_PAD(0x354, 0x02C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL1__GPIO4_8			IOMUX_PAD(0x354, 0x02C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS		IOMUX_PAD(0x354, 0x02C, 2, 0x75C, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL1__UART5_TXD_MUX		IOMUX_PAD(0x354, 0x02C, 4, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_KEY_COL1__ECSPI1_MISO			IOMUX_PAD(0x354, 0x02C, 5, 0x7A0, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL1__FEC_RX_CLK			IOMUX_PAD(0x354, 0x02C, 6, 0x808, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL1__USBPHY1_TXREADY		IOMUX_PAD(0x354, 0x02C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW1__KPP_ROW_1			IOMUX_PAD(0x358, 0x030, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW1__GPIO4_9			IOMUX_PAD(0x358, 0x030, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD		IOMUX_PAD(0x358, 0x030, 2, 0x748, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW1__UART5_RXD_MUX		IOMUX_PAD(0x358, 0x030, 4, 0x898, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_KEY_ROW1__ECSPI1_SS0			IOMUX_PAD(0x358, 0x030, 5, 0x7A8, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW1__FEC_COL			IOMUX_PAD(0x358, 0x030, 6, 0x800, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW1__USBPHY1_RXVALID		IOMUX_PAD(0x358, 0x030, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL2__KPP_COL_2			IOMUX_PAD(0x35C, 0x034, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL2__GPIO4_10			IOMUX_PAD(0x35C, 0x034, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL2__CAN1_TXCAN			IOMUX_PAD(0x35C, 0x034, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL2__FEC_MDIO			IOMUX_PAD(0x35C, 0x034, 4, 0x804, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL2__ECSPI1_SS1			IOMUX_PAD(0x35C, 0x034, 5, 0x7AC, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL2__FEC_RDATA_2			IOMUX_PAD(0x35C, 0x034, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL2__USBPHY1_RXACTIVE		IOMUX_PAD(0x35C, 0x034, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW2__KPP_ROW_2			IOMUX_PAD(0x360, 0x038, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW2__GPIO4_11			IOMUX_PAD(0x360, 0x038, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW2__CAN1_RXCAN			IOMUX_PAD(0x360, 0x038, 2, 0x760, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW2__FEC_MDC			IOMUX_PAD(0x360, 0x038, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW2__ECSPI1_SS2			IOMUX_PAD(0x360, 0x038, 5, 0x7B0, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW2__FEC_TDATA_2			IOMUX_PAD(0x360, 0x038, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW2__USBPHY1_RXERROR		IOMUX_PAD(0x360, 0x038, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__KPP_COL_3			IOMUX_PAD(0x364, 0x03C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__GPIO4_12			IOMUX_PAD(0x364, 0x03C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__USBOH3_H2_DP			IOMUX_PAD(0x364, 0x03C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__SPDIF_IN1			IOMUX_PAD(0x364, 0x03C, 3, 0x870, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__I2C2_SCL			IOMUX_PAD(0x364, 0x03C, 4 | IOMUX_CONFIG_SION, 0x81C, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__ECSPI1_SS3			IOMUX_PAD(0x364, 0x03C, 5, 0x7B4, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__FEC_CRS			IOMUX_PAD(0x364, 0x03C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL3__USBPHY1_SIECLOCK		IOMUX_PAD(0x364, 0x03C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__KPP_ROW_3			IOMUX_PAD(0x368, 0x040, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__GPIO4_13			IOMUX_PAD(0x368, 0x040, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__USBOH3_H2_DM			IOMUX_PAD(0x368, 0x040, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__CCM_ASRC_EXT_CLK		IOMUX_PAD(0x368, 0x040, 3, 0x768, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__I2C2_SDA			IOMUX_PAD(0x368, 0x040, 4 | IOMUX_CONFIG_SION, 0x820, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__OSC32K_32K_OUT		IOMUX_PAD(0x368, 0x040, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__CCM_PLL4_BYP			IOMUX_PAD(0x368, 0x040, 6, 0x77C, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW3__USBPHY1_LINESTATE_0		IOMUX_PAD(0x368, 0x040, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL4__KPP_COL_4			IOMUX_PAD(0x36C, 0x044, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL4__GPIO4_14			IOMUX_PAD(0x36C, 0x044, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL4__CAN2_TXCAN			IOMUX_PAD(0x36C, 0x044, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL4__IPU_SISG_4			IOMUX_PAD(0x36C, 0x044, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL4__UART5_RTS			IOMUX_PAD(0x36C, 0x044, 4, 0x894, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_KEY_COL4__USBOH3_USBOTG_OC		IOMUX_PAD(0x36C, 0x044, 5, 0x89C, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_COL4__USBPHY1_LINESTATE_1		IOMUX_PAD(0x36C, 0x044, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW4__KPP_ROW_4			IOMUX_PAD(0x370, 0x048, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW4__GPIO4_15			IOMUX_PAD(0x370, 0x048, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW4__CAN2_RXCAN			IOMUX_PAD(0x370, 0x048, 2, 0x764, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW4__IPU_SISG_5			IOMUX_PAD(0x370, 0x048, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW4__UART5_CTS			IOMUX_PAD(0x370, 0x048, 4, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_KEY_ROW4__USBOH3_USBOTG_PWR		IOMUX_PAD(0x370, 0x048, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_KEY_ROW4__USBPHY1_VBUSVALID		IOMUX_PAD(0x370, 0x048, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK		IOMUX_PAD(0x378, 0x04C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_DISP_CLK__GPIO4_16			IOMUX_PAD(0x378, 0x04C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_DISP_CLK__USBOH3_USBH2_DIR		IOMUX_PAD(0x378, 0x04C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_DISP_CLK__SDMA_DEBUG_CORE_STATE_0	IOMUX_PAD(0x378, 0x04C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_DISP_CLK__EMI_EMI_DEBUG_0		IOMUX_PAD(0x378, 0x04C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_DISP_CLK__USBPHY1_AVALID		IOMUX_PAD(0x378, 0x04C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN15__IPU_DI0_PIN15		IOMUX_PAD(0x37C, 0x050, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN15__GPIO4_17			IOMUX_PAD(0x37C, 0x050, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN15__AUDMUX_AUD6_TXC		IOMUX_PAD(0x37C, 0x050, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN15__SDMA_DEBUG_CORE_STATE_1	IOMUX_PAD(0x37C, 0x050, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN15__EMI_EMI_DEBUG_1		IOMUX_PAD(0x37C, 0x050, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN15__USBPHY1_BVALID		IOMUX_PAD(0x37C, 0x050, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN2__IPU_DI0_PIN2			IOMUX_PAD(0x380, 0x054, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN2__GPIO4_18			IOMUX_PAD(0x380, 0x054, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN2__AUDMUX_AUD6_TXD		IOMUX_PAD(0x380, 0x054, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN2__SDMA_DEBUG_CORE_STATE_2	IOMUX_PAD(0x380, 0x054, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN2__EMI_EMI_DEBUG_2		IOMUX_PAD(0x380, 0x054, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN2__USBPHY1_ENDSESSION		IOMUX_PAD(0x380, 0x054, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN3__IPU_DI0_PIN3			IOMUX_PAD(0x384, 0x058, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN3__GPIO4_19			IOMUX_PAD(0x384, 0x058, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS		IOMUX_PAD(0x384, 0x058, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN3__SDMA_DEBUG_CORE_STATE_3	IOMUX_PAD(0x384, 0x058, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN3__EMI_EMI_DEBUG_3		IOMUX_PAD(0x384, 0x058, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN3__USBPHY1_IDDIG		IOMUX_PAD(0x384, 0x058, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN4__IPU_DI0_PIN4			IOMUX_PAD(0x388, 0x05C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN4__GPIO4_20			IOMUX_PAD(0x388, 0x05C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN4__AUDMUX_AUD6_RXD		IOMUX_PAD(0x388, 0x05C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN4__ESDHC1_WP			IOMUX_PAD(0x388, 0x05C, 3, 0x7FC, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN4__SDMA_DEBUG_YIELD		IOMUX_PAD(0x388, 0x05C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN4__EMI_EMI_DEBUG_4		IOMUX_PAD(0x388, 0x05C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DI0_PIN4__USBPHY1_HOSTDISCONNECT	IOMUX_PAD(0x388, 0x05C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0		IOMUX_PAD(0x38C, 0x060, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT0__GPIO4_21			IOMUX_PAD(0x38C, 0x060, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT0__CSPI_SCLK			IOMUX_PAD(0x38C, 0x060, 2, 0x780, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT0__USBOH3_USBH2_DATA_0	IOMUX_PAD(0x38C, 0x060, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT0__SDMA_DEBUG_CORE_RUN	IOMUX_PAD(0x38C, 0x060, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT0__EMI_EMI_DEBUG_5		IOMUX_PAD(0x38C, 0x060, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT0__USBPHY2_TXREADY		IOMUX_PAD(0x38C, 0x060, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1		IOMUX_PAD(0x390, 0x064, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT1__GPIO4_22			IOMUX_PAD(0x390, 0x064, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT1__CSPI_MOSI			IOMUX_PAD(0x390, 0x064, 2, 0x788, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT1__USBOH3_USBH2_DATA_1	IOMUX_PAD(0x390, 0x064, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT1__SDMA_DEBUG_EVENT_CHANNEL_SEL	\
+							IOMUX_PAD(0x390, 0x064, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT1__EMI_EMI_DEBUG_6		IOMUX_PAD(0x390, 0x064, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT1__USBPHY2_RXVALID		IOMUX_PAD(0x390, 0x064, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2		IOMUX_PAD(0x394, 0x068, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT2__GPIO4_23			IOMUX_PAD(0x394, 0x068, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT2__CSPI_MISO			IOMUX_PAD(0x394, 0x068, 2, 0x784, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT2__USBOH3_USBH2_DATA_2	IOMUX_PAD(0x394, 0x068, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT2__SDMA_DEBUG_MODE		IOMUX_PAD(0x394, 0x068, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT2__EMI_EMI_DEBUG_7		IOMUX_PAD(0x394, 0x068, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT2__USBPHY2_RXACTIVE		IOMUX_PAD(0x394, 0x068, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3		IOMUX_PAD(0x398, 0x06C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT3__GPIO4_24			IOMUX_PAD(0x398, 0x06C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT3__CSPI_SS0			IOMUX_PAD(0x398, 0x06C, 2, 0x78C, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT3__USBOH3_USBH2_DATA_3	IOMUX_PAD(0x398, 0x06C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT3__SDMA_DEBUG_BUS_ERROR	IOMUX_PAD(0x398, 0x06C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT3__EMI_EMI_DEBUG_8		IOMUX_PAD(0x398, 0x06C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT3__USBPHY2_RXERROR		IOMUX_PAD(0x398, 0x06C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4		IOMUX_PAD(0x39C, 0x070, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT4__GPIO4_25			IOMUX_PAD(0x39C, 0x070, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT4__CSPI_SS1			IOMUX_PAD(0x39C, 0x070, 2, 0x790, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT4__USBOH3_USBH2_DATA_4	IOMUX_PAD(0x39C, 0x070, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB		IOMUX_PAD(0x39C, 0x070, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT4__EMI_EMI_DEBUG_9		IOMUX_PAD(0x39C, 0x070, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT4__USBPHY2_SIECLOCK		IOMUX_PAD(0x39C, 0x070, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5		IOMUX_PAD(0x3A0, 0x074, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT5__GPIO4_26			IOMUX_PAD(0x3A0, 0x074, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT5__CSPI_SS2			IOMUX_PAD(0x3A0, 0x074, 2, 0x794, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT5__USBOH3_USBH2_DATA_5	IOMUX_PAD(0x3A0, 0x074, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT5__SDMA_DEBUG_MATCHED_DMBUS	IOMUX_PAD(0x3A0, 0x074, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT5__EMI_EMI_DEBUG_10		IOMUX_PAD(0x3A0, 0x074, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT5__USBPHY2_LINESTATE_0	IOMUX_PAD(0x3A0, 0x074, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6		IOMUX_PAD(0x3A4, 0x078, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT6__GPIO4_27			IOMUX_PAD(0x3A4, 0x078, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT6__CSPI_SS3			IOMUX_PAD(0x3A4, 0x078, 2, 0x798, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT6__USBOH3_USBH2_DATA_6	IOMUX_PAD(0x3A4, 0x078, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT6__SDMA_DEBUG_RTBUFFER_WRITE	IOMUX_PAD(0x3A4, 0x078, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT6__EMI_EMI_DEBUG_11		IOMUX_PAD(0x3A4, 0x078, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT6__USBPHY2_LINESTATE_1	IOMUX_PAD(0x3A4, 0x078, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7		IOMUX_PAD(0x3A8, 0x07C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT7__GPIO4_28			IOMUX_PAD(0x3A8, 0x07C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT7__CSPI_RDY			IOMUX_PAD(0x3A8, 0x07C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT7__USBOH3_USBH2_DATA_7	IOMUX_PAD(0x3A8, 0x07C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT7__SDMA_DEBUG_EVENT_CHANNEL_0	IOMUX_PAD(0x3A8, 0x07C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT7__EMI_EMI_DEBUG_12		IOMUX_PAD(0x3A8, 0x07C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT7__USBPHY2_VBUSVALID		IOMUX_PAD(0x3A8, 0x07C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8		IOMUX_PAD(0x3AC, 0x080, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT8__GPIO4_29			IOMUX_PAD(0x3AC, 0x080, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT8__PWM1_PWMO			IOMUX_PAD(0x3AC, 0x080, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT8__WDOG1_WDOG_B		IOMUX_PAD(0x3AC, 0x080, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT8__SDMA_DEBUG_EVENT_CHANNEL_1	IOMUX_PAD(0x3AC, 0x080, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT8__EMI_EMI_DEBUG_13		IOMUX_PAD(0x3AC, 0x080, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT8__USBPHY2_AVALID		IOMUX_PAD(0x3AC, 0x080, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9		IOMUX_PAD(0x3B0, 0x084, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT9__GPIO4_30			IOMUX_PAD(0x3B0, 0x084, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT9__PWM2_PWMO			IOMUX_PAD(0x3B0, 0x084, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT9__WDOG2_WDOG_B		IOMUX_PAD(0x3B0, 0x084, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT9__SDMA_DEBUG_EVENT_CHANNEL_2	IOMUX_PAD(0x3B0, 0x084, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT9__EMI_EMI_DEBUG_14		IOMUX_PAD(0x3B0, 0x084, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT9__USBPHY2_VSTATUS_0		IOMUX_PAD(0x3B0, 0x084, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10		IOMUX_PAD(0x3B4, 0x088, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT10__GPIO4_31			IOMUX_PAD(0x3B4, 0x088, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT10__USBOH3_USBH2_STP		IOMUX_PAD(0x3B4, 0x088, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT10__SDMA_DEBUG_EVENT_CHANNEL_3	\
+							IOMUX_PAD(0x3B4, 0x088, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT10__EMI_EMI_DEBUG_15		IOMUX_PAD(0x3B4, 0x088, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT10__USBPHY2_VSTATUS_1		IOMUX_PAD(0x3B4, 0x088, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11		IOMUX_PAD(0x3B8, 0x08C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT11__GPIO5_5			IOMUX_PAD(0x3B8, 0x08C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT11__USBOH3_USBH2_NXT		IOMUX_PAD(0x3B8, 0x08C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT11__SDMA_DEBUG_EVENT_CHANNEL_4	\
+							IOMUX_PAD(0x3B8, 0x08C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT11__EMI_EMI_DEBUG_16		IOMUX_PAD(0x3B8, 0x08C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT11__USBPHY2_VSTATUS_2		IOMUX_PAD(0x3B8, 0x08C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12		IOMUX_PAD(0x3BC, 0x090, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT12__GPIO5_6			IOMUX_PAD(0x3BC, 0x090, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT12__USBOH3_USBH2_CLK		IOMUX_PAD(0x3BC, 0x090, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT12__SDMA_DEBUG_EVENT_CHANNEL_5	\
+							IOMUX_PAD(0x3BC, 0x090, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT12__EMI_EMI_DEBUG_17		IOMUX_PAD(0x3BC, 0x090, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT12__USBPHY2_VSTATUS_3		IOMUX_PAD(0x3BC, 0x090, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13		IOMUX_PAD(0x3C0, 0x094, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT13__GPIO5_7			IOMUX_PAD(0x3C0, 0x094, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS		IOMUX_PAD(0x3C0, 0x094, 3, 0x754, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT13__SDMA_DEBUG_EVT_CHN_LINES_0	\
+							IOMUX_PAD(0x3C0, 0x094, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT13__EMI_EMI_DEBUG_18		IOMUX_PAD(0x3C0, 0x094, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT13__USBPHY2_VSTATUS_4		IOMUX_PAD(0x3C0, 0x094, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14		IOMUX_PAD(0x3C4, 0x098, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT14__GPIO5_8			IOMUX_PAD(0x3C4, 0x098, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC		IOMUX_PAD(0x3C4, 0x098, 3, 0x750, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT14__SDMA_DEBUG_EVT_CHN_LINES_1	\
+							IOMUX_PAD(0x3C4, 0x098, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT14__EMI_EMI_DEBUG_19		IOMUX_PAD(0x3C4, 0x098, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT14__USBPHY2_VSTATUS_5		IOMUX_PAD(0x3C4, 0x098, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15		IOMUX_PAD(0x3C8, 0x09C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT15__GPIO5_9			IOMUX_PAD(0x3C8, 0x09C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT15__ECSPI1_SS1		IOMUX_PAD(0x3C8, 0x09C, 2, 0x7AC, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT15__ECSPI2_SS1		IOMUX_PAD(0x3C8, 0x09C, 3, 0x7C8, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT15__SDMA_DEBUG_EVT_CHN_LINES_2	\
+							IOMUX_PAD(0x3C8, 0x09C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT15__EMI_EMI_DEBUG_20		IOMUX_PAD(0x3C8, 0x09C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT15__USBPHY2_VSTATUS_6		IOMUX_PAD(0x3C8, 0x09C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16		IOMUX_PAD(0x3CC, 0x0A0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__GPIO5_10			IOMUX_PAD(0x3CC, 0x0A0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__ECSPI2_MOSI		IOMUX_PAD(0x3CC, 0x0A0, 2, 0x7C0, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC		IOMUX_PAD(0x3CC, 0x0A0, 3, 0x758, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__SDMA_EXT_EVENT_0		IOMUX_PAD(0x3CC, 0x0A0, 4, 0x868, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__SDMA_DEBUG_EVT_CHN_LINES_3	\
+							IOMUX_PAD(0x3CC, 0x0A0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__EMI_EMI_DEBUG_21		IOMUX_PAD(0x3CC, 0x0A0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT16__USBPHY2_VSTATUS_7		IOMUX_PAD(0x3CC, 0x0A0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17		IOMUX_PAD(0x3D0, 0x0A4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT17__GPIO5_11			IOMUX_PAD(0x3D0, 0x0A4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT17__ECSPI2_MISO		IOMUX_PAD(0x3D0, 0x0A4, 2, 0x7BC, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD		IOMUX_PAD(0x3D0, 0x0A4, 3, 0x74C, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT17__SDMA_EXT_EVENT_1		IOMUX_PAD(0x3D0, 0x0A4, 4, 0x86C, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT17__SDMA_DEBUG_EVT_CHN_LINES_4	\
+							IOMUX_PAD(0x3D0, 0x0A4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT17__EMI_EMI_DEBUG_22		IOMUX_PAD(0x3D0, 0x0A4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18		IOMUX_PAD(0x3D4, 0x0A8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__GPIO5_12			IOMUX_PAD(0x3D4, 0x0A8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__ECSPI2_SS0		IOMUX_PAD(0x3D4, 0x0A8, 2, 0x7C4, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS		IOMUX_PAD(0x3D4, 0x0A8, 3, 0x75C, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS		IOMUX_PAD(0x3D4, 0x0A8, 4, 0x73C, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__SDMA_DEBUG_EVT_CHN_LINES_5	\
+							IOMUX_PAD(0x3D4, 0x0A8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__EMI_EMI_DEBUG_23		IOMUX_PAD(0x3D4, 0x0A8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT18__EMI_WEIM_CS_2		IOMUX_PAD(0x3D4, 0x0A8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19		IOMUX_PAD(0x3D8, 0x0AC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__GPIO5_13			IOMUX_PAD(0x3D8, 0x0AC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__ECSPI2_SCLK		IOMUX_PAD(0x3D8, 0x0AC, 2, 0x7B8, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD		IOMUX_PAD(0x3D8, 0x0AC, 3, 0x748, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC		IOMUX_PAD(0x3D8, 0x0AC, 4, 0x738, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__SDMA_DEBUG_EVT_CHN_LINES_6	\
+							IOMUX_PAD(0x3D8, 0x0AC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__EMI_EMI_DEBUG_24		IOMUX_PAD(0x3D8, 0x0AC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT19__EMI_WEIM_CS_3		IOMUX_PAD(0x3D8, 0x0AC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20		IOMUX_PAD(0x3DC, 0x0B0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT20__GPIO5_14			IOMUX_PAD(0x3DC, 0x0B0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT20__ECSPI1_SCLK		IOMUX_PAD(0x3DC, 0x0B0, 2, 0x79C, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC		IOMUX_PAD(0x3DC, 0x0B0, 3, 0x740, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT20__SDMA_DEBUG_EVT_CHN_LINES_7	\
+							IOMUX_PAD(0x3DC, 0x0B0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT20__EMI_EMI_DEBUG_25		IOMUX_PAD(0x3DC, 0x0B0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT20__SATA_PHY_TDI		IOMUX_PAD(0x3DC, 0x0B0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21		IOMUX_PAD(0x3E0, 0x0B4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT21__GPIO5_15			IOMUX_PAD(0x3E0, 0x0B4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT21__ECSPI1_MOSI		IOMUX_PAD(0x3E0, 0x0B4, 2, 0x7A4, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD		IOMUX_PAD(0x3E0, 0x0B4, 3, 0x734, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT21__SDMA_DEBUG_BUS_DEVICE_0	IOMUX_PAD(0x3E0, 0x0B4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT21__EMI_EMI_DEBUG_26		IOMUX_PAD(0x3E0, 0x0B4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT21__SATA_PHY_TDO		IOMUX_PAD(0x3E0, 0x0B4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22		IOMUX_PAD(0x3E4, 0x0B8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT22__GPIO5_16			IOMUX_PAD(0x3E4, 0x0B8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT22__ECSPI1_MISO		IOMUX_PAD(0x3E4, 0x0B8, 2, 0x7A0, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS		IOMUX_PAD(0x3E4, 0x0B8, 3, 0x744, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT22__SDMA_DEBUG_BUS_DEVICE_1	IOMUX_PAD(0x3E4, 0x0B8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT22__EMI_EMI_DEBUG_27		IOMUX_PAD(0x3E4, 0x0B8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT22__SATA_PHY_TCK		IOMUX_PAD(0x3E4, 0x0B8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23		IOMUX_PAD(0x3E8, 0x0BC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT23__GPIO5_17			IOMUX_PAD(0x3E8, 0x0BC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT23__ECSPI1_SS0		IOMUX_PAD(0x3E8, 0x0BC, 2, 0x7A8, 1, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD		IOMUX_PAD(0x3E8, 0x0BC, 3, 0x730, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT23__SDMA_DEBUG_BUS_DEVICE_2	IOMUX_PAD(0x3E8, 0x0BC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT23__EMI_EMI_DEBUG_28		IOMUX_PAD(0x3E8, 0x0BC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_DISP0_DAT23__SATA_PHY_TMS		IOMUX_PAD(0x3E8, 0x0BC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK		IOMUX_PAD(0x3EC, 0x0C0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_PIXCLK__GPIO5_18			IOMUX_PAD(0x3EC, 0x0C0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0		IOMUX_PAD(0x3EC, 0x0C0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_PIXCLK__EMI_EMI_DEBUG_29		IOMUX_PAD(0x3EC, 0x0C0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC		IOMUX_PAD(0x3F0, 0x0C4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_MCLK__GPIO5_19			IOMUX_PAD(0x3F0, 0x0C4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_MCLK__CCM_CSI0_MCLK		IOMUX_PAD(0x3F0, 0x0C4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1		IOMUX_PAD(0x3F0, 0x0C4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_MCLK__EMI_EMI_DEBUG_30		IOMUX_PAD(0x3F0, 0x0C4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_MCLK__TPIU_TRCTL			IOMUX_PAD(0x3F0, 0x0C4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN		IOMUX_PAD(0x3F4, 0x0C8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DATA_EN__GPIO5_20			IOMUX_PAD(0x3F4, 0x0C8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2		IOMUX_PAD(0x3F4, 0x0C8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DATA_EN__EMI_EMI_DEBUG_31		IOMUX_PAD(0x3F4, 0x0C8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DATA_EN__TPIU_TRCLK		IOMUX_PAD(0x3F4, 0x0C8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC		IOMUX_PAD(0x3F8, 0x0CC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_VSYNC__GPIO5_21			IOMUX_PAD(0x3F8, 0x0CC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3		IOMUX_PAD(0x3F8, 0x0CC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_VSYNC__EMI_EMI_DEBUG_32		IOMUX_PAD(0x3F8, 0x0CC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_VSYNC__TPIU_TRACE_0		IOMUX_PAD(0x3F8, 0x0CC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__IPU_CSI0_D_4		IOMUX_PAD(0x3FC, 0x0D0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__GPIO5_22			IOMUX_PAD(0x3FC, 0x0D0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__KPP_COL_5			IOMUX_PAD(0x3FC, 0x0D0, 2, 0x840, 1, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__ECSPI1_SCLK			IOMUX_PAD(0x3FC, 0x0D0, 3, 0x79C, 2, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__USBOH3_USBH3_STP		IOMUX_PAD(0x3FC, 0x0D0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC		IOMUX_PAD(0x3FC, 0x0D0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__EMI_EMI_DEBUG_33		IOMUX_PAD(0x3FC, 0x0D0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT4__TPIU_TRACE_1		IOMUX_PAD(0x3FC, 0x0D0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__IPU_CSI0_D_5		IOMUX_PAD(0x400, 0x0D4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__GPIO5_23			IOMUX_PAD(0x400, 0x0D4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__KPP_ROW_5			IOMUX_PAD(0x400, 0x0D4, 2, 0x84C, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__ECSPI1_MOSI			IOMUX_PAD(0x400, 0x0D4, 3, 0x7A4, 2, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__USBOH3_USBH3_NXT		IOMUX_PAD(0x400, 0x0D4, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD		IOMUX_PAD(0x400, 0x0D4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__EMI_EMI_DEBUG_34		IOMUX_PAD(0x400, 0x0D4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT5__TPIU_TRACE_2		IOMUX_PAD(0x400, 0x0D4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__IPU_CSI0_D_6		IOMUX_PAD(0x404, 0x0D8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__GPIO5_24			IOMUX_PAD(0x404, 0x0D8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__KPP_COL_6			IOMUX_PAD(0x404, 0x0D8, 2, 0x844, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__ECSPI1_MISO			IOMUX_PAD(0x404, 0x0D8, 3, 0x7A0, 2, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__USBOH3_USBH3_CLK		IOMUX_PAD(0x404, 0x0D8, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS		IOMUX_PAD(0x404, 0x0D8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__EMI_EMI_DEBUG_35		IOMUX_PAD(0x404, 0x0D8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT6__TPIU_TRACE_3		IOMUX_PAD(0x404, 0x0D8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__IPU_CSI0_D_7		IOMUX_PAD(0x408, 0x0DC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__GPIO5_25			IOMUX_PAD(0x408, 0x0DC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__KPP_ROW_6			IOMUX_PAD(0x408, 0x0DC, 2, 0x850, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__ECSPI1_SS0			IOMUX_PAD(0x408, 0x0DC, 3, 0x7A8, 2, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__USBOH3_USBH3_DIR		IOMUX_PAD(0x408, 0x0DC, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD		IOMUX_PAD(0x408, 0x0DC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__EMI_EMI_DEBUG_36		IOMUX_PAD(0x408, 0x0DC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT7__TPIU_TRACE_4		IOMUX_PAD(0x408, 0x0DC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__IPU_CSI0_D_8		IOMUX_PAD(0x40C, 0x0E0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__GPIO5_26			IOMUX_PAD(0x40C, 0x0E0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__KPP_COL_7			IOMUX_PAD(0x40C, 0x0E0, 2, 0x848, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__ECSPI2_SCLK			IOMUX_PAD(0x40C, 0x0E0, 3, 0x7B8, 1, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__USBOH3_USBH3_OC		IOMUX_PAD(0x40C, 0x0E0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__I2C1_SDA			IOMUX_PAD(0x40C, 0x0E0, 5 | IOMUX_CONFIG_SION, 0x818, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__EMI_EMI_DEBUG_37		IOMUX_PAD(0x40C, 0x0E0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT8__TPIU_TRACE_5		IOMUX_PAD(0x40C, 0x0E0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9		IOMUX_PAD(0x410, 0x0E4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__GPIO5_27			IOMUX_PAD(0x410, 0x0E4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__KPP_ROW_7			IOMUX_PAD(0x410, 0x0E4, 2, 0x854, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__ECSPI2_MOSI			IOMUX_PAD(0x410, 0x0E4, 3, 0x7C0, 1, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__USBOH3_USBH3_PWR		IOMUX_PAD(0x410, 0x0E4, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__I2C1_SCL			IOMUX_PAD(0x410, 0x0E4, 5 | IOMUX_CONFIG_SION, 0x814, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__EMI_EMI_DEBUG_38		IOMUX_PAD(0x410, 0x0E4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT9__TPIU_TRACE_6		IOMUX_PAD(0x410, 0x0E4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10		IOMUX_PAD(0x414, 0x0E8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__GPIO5_28			IOMUX_PAD(0x414, 0x0E8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__UART1_TXD_MUX		IOMUX_PAD(0x414, 0x0E8, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__ECSPI2_MISO		IOMUX_PAD(0x414, 0x0E8, 3, 0x7BC, 1, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC		IOMUX_PAD(0x414, 0x0E8, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4		IOMUX_PAD(0x414, 0x0E8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__EMI_EMI_DEBUG_39		IOMUX_PAD(0x414, 0x0E8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT10__TPIU_TRACE_7		IOMUX_PAD(0x414, 0x0E8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__IPU_CSI0_D_11		IOMUX_PAD(0x418, 0x0EC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__GPIO5_29			IOMUX_PAD(0x418, 0x0EC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__UART1_RXD_MUX		IOMUX_PAD(0x418, 0x0EC, 2, 0x878, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__ECSPI2_SS0			IOMUX_PAD(0x418, 0x0EC, 3, 0x7C4, 1, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS		IOMUX_PAD(0x418, 0x0EC, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5		IOMUX_PAD(0x418, 0x0EC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__EMI_EMI_DEBUG_40		IOMUX_PAD(0x418, 0x0EC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT11__TPIU_TRACE_8		IOMUX_PAD(0x418, 0x0EC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12		IOMUX_PAD(0x41C, 0x0F0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT12__GPIO5_30			IOMUX_PAD(0x41C, 0x0F0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT12__UART4_TXD_MUX		IOMUX_PAD(0x41C, 0x0F0, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT12__USBOH3_USBH3_DATA_0	IOMUX_PAD(0x41C, 0x0F0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6		IOMUX_PAD(0x41C, 0x0F0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT12__EMI_EMI_DEBUG_41		IOMUX_PAD(0x41C, 0x0F0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT12__TPIU_TRACE_9		IOMUX_PAD(0x41C, 0x0F0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13		IOMUX_PAD(0x420, 0x0F4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT13__GPIO5_31			IOMUX_PAD(0x420, 0x0F4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT13__UART4_RXD_MUX		IOMUX_PAD(0x420, 0x0F4, 2, 0x890, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT13__USBOH3_USBH3_DATA_1	IOMUX_PAD(0x420, 0x0F4, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7		IOMUX_PAD(0x420, 0x0F4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT13__EMI_EMI_DEBUG_42		IOMUX_PAD(0x420, 0x0F4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT13__TPIU_TRACE_10		IOMUX_PAD(0x420, 0x0F4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14		IOMUX_PAD(0x424, 0x0F8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT14__GPIO6_0			IOMUX_PAD(0x424, 0x0F8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT14__UART5_TXD_MUX		IOMUX_PAD(0x424, 0x0F8, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT14__USBOH3_USBH3_DATA_2	IOMUX_PAD(0x424, 0x0F8, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8		IOMUX_PAD(0x424, 0x0F8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT14__EMI_EMI_DEBUG_43		IOMUX_PAD(0x424, 0x0F8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT14__TPIU_TRACE_11		IOMUX_PAD(0x424, 0x0F8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15		IOMUX_PAD(0x428, 0x0FC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT15__GPIO6_1			IOMUX_PAD(0x428, 0x0FC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT15__UART5_RXD_MUX		IOMUX_PAD(0x428, 0x0FC, 2, 0x898, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT15__USBOH3_USBH3_DATA_3	IOMUX_PAD(0x428, 0x0FC, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9		IOMUX_PAD(0x428, 0x0FC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT15__EMI_EMI_DEBUG_44		IOMUX_PAD(0x428, 0x0FC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT15__TPIU_TRACE_12		IOMUX_PAD(0x428, 0x0FC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16		IOMUX_PAD(0x42C, 0x100, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT16__GPIO6_2			IOMUX_PAD(0x42C, 0x100, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT16__UART4_RTS			IOMUX_PAD(0x42C, 0x100, 2, 0x88C, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT16__USBOH3_USBH3_DATA_4	IOMUX_PAD(0x42C, 0x100, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10		IOMUX_PAD(0x42C, 0x100, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT16__EMI_EMI_DEBUG_45		IOMUX_PAD(0x42C, 0x100, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT16__TPIU_TRACE_13		IOMUX_PAD(0x42C, 0x100, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17		IOMUX_PAD(0x430, 0x104, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT17__GPIO6_3			IOMUX_PAD(0x430, 0x104, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT17__UART4_CTS			IOMUX_PAD(0x430, 0x104, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT17__USBOH3_USBH3_DATA_5	IOMUX_PAD(0x430, 0x104, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11		IOMUX_PAD(0x430, 0x104, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT17__EMI_EMI_DEBUG_46		IOMUX_PAD(0x430, 0x104, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT17__TPIU_TRACE_14		IOMUX_PAD(0x430, 0x104, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18		IOMUX_PAD(0x434, 0x108, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT18__GPIO6_4			IOMUX_PAD(0x434, 0x108, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT18__UART5_RTS			IOMUX_PAD(0x434, 0x108, 2, 0x894, 2, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT18__USBOH3_USBH3_DATA_6	IOMUX_PAD(0x434, 0x108, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12		IOMUX_PAD(0x434, 0x108, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT18__EMI_EMI_DEBUG_47		IOMUX_PAD(0x434, 0x108, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT18__TPIU_TRACE_15		IOMUX_PAD(0x434, 0x108, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19		IOMUX_PAD(0x438, 0x10C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT19__GPIO6_5			IOMUX_PAD(0x438, 0x10C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT19__UART5_CTS			IOMUX_PAD(0x438, 0x10C, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT19__USBOH3_USBH3_DATA_7	IOMUX_PAD(0x438, 0x10C, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13		IOMUX_PAD(0x438, 0x10C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT19__EMI_EMI_DEBUG_48		IOMUX_PAD(0x438, 0x10C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_CSI0_DAT19__USBPHY2_BISTOK		IOMUX_PAD(0x438, 0x10C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A25__EMI_WEIM_A_25			IOMUX_PAD(0x458, 0x110, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A25__GPIO5_2			IOMUX_PAD(0x458, 0x110, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A25__ECSPI2_RDY			IOMUX_PAD(0x458, 0x110, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A25__IPU_DI1_PIN12			IOMUX_PAD(0x458, 0x110, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A25__CSPI_SS1			IOMUX_PAD(0x458, 0x110, 4, 0x790, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A25__IPU_DI0_D1_CS			IOMUX_PAD(0x458, 0x110, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A25__USBPHY1_BISTOK		IOMUX_PAD(0x458, 0x110, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB2__EMI_WEIM_EB_2			IOMUX_PAD(0x45C, 0x114, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB2__GPIO2_30			IOMUX_PAD(0x45C, 0x114, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB2__CCM_DI1_EXT_CLK		IOMUX_PAD(0x45C, 0x114, 2, 0x76C, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB2__IPU_SER_DISP1_CS		IOMUX_PAD(0x45C, 0x114, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB2__ECSPI1_SS0			IOMUX_PAD(0x45C, 0x114, 4, 0x7A8, 3, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB2__I2C2_SCL			IOMUX_PAD(0x45C, 0x114, 5 | IOMUX_CONFIG_SION, 0x81C, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D16__EMI_WEIM_D_16			IOMUX_PAD(0x460, 0x118, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D16__GPIO3_16			IOMUX_PAD(0x460, 0x118, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D16__IPU_DI0_PIN5			IOMUX_PAD(0x460, 0x118, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D16__IPU_DISPB1_SER_CLK		IOMUX_PAD(0x460, 0x118, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D16__ECSPI1_SCLK			IOMUX_PAD(0x460, 0x118, 4, 0x79C, 3, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D16__I2C2_SDA			IOMUX_PAD(0x460, 0x118, 5 | IOMUX_CONFIG_SION, 0x820, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D17__EMI_WEIM_D_17			IOMUX_PAD(0x464, 0x11C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D17__GPIO3_17			IOMUX_PAD(0x464, 0x11C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D17__IPU_DI0_PIN6			IOMUX_PAD(0x464, 0x11C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D17__IPU_DISPB1_SER_DIN		IOMUX_PAD(0x464, 0x11C, 3, 0x830, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D17__ECSPI1_MISO			IOMUX_PAD(0x464, 0x11C, 4, 0x7A0, 3, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D17__I2C3_SCL			IOMUX_PAD(0x464, 0x11C, 5 | IOMUX_CONFIG_SION, 0x824, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D18__EMI_WEIM_D_18			IOMUX_PAD(0x468, 0x120, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D18__GPIO3_18			IOMUX_PAD(0x468, 0x120, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D18__IPU_DI0_PIN7			IOMUX_PAD(0x468, 0x120, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D18__IPU_DISPB1_SER_DIO		IOMUX_PAD(0x468, 0x120, 3, 0x830, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D18__ECSPI1_MOSI			IOMUX_PAD(0x468, 0x120, 4, 0x7A4, 3, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D18__I2C3_SDA			IOMUX_PAD(0x468, 0x120, 5 | IOMUX_CONFIG_SION, 0x828, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D18__IPU_DI1_D0_CS			IOMUX_PAD(0x468, 0x120, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D19__EMI_WEIM_D_19			IOMUX_PAD(0x46C, 0x124, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D19__GPIO3_19			IOMUX_PAD(0x46C, 0x124, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D19__IPU_DI0_PIN8			IOMUX_PAD(0x46C, 0x124, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D19__IPU_DISPB1_SER_RS		IOMUX_PAD(0x46C, 0x124, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D19__ECSPI1_SS1			IOMUX_PAD(0x46C, 0x124, 4, 0x7AC, 2, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D19__EPIT1_EPITO			IOMUX_PAD(0x46C, 0x124, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D19__UART1_CTS			IOMUX_PAD(0x46C, 0x124, 6, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D19__USBOH3_USBH2_OC		IOMUX_PAD(0x46C, 0x124, 7, 0x8A4, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D20__EMI_WEIM_D_20			IOMUX_PAD(0x470, 0x128, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D20__GPIO3_20			IOMUX_PAD(0x470, 0x128, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D20__IPU_DI0_PIN16			IOMUX_PAD(0x470, 0x128, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D20__IPU_SER_DISP0_CS		IOMUX_PAD(0x470, 0x128, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D20__CSPI_SS0			IOMUX_PAD(0x470, 0x128, 4, 0x78C, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D20__EPIT2_EPITO			IOMUX_PAD(0x470, 0x128, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D20__UART1_RTS			IOMUX_PAD(0x470, 0x128, 6, 0x874, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D20__USBOH3_USBH2_PWR		IOMUX_PAD(0x470, 0x128, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D21__EMI_WEIM_D_21			IOMUX_PAD(0x474, 0x12C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D21__GPIO3_21			IOMUX_PAD(0x474, 0x12C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D21__IPU_DI0_PIN17			IOMUX_PAD(0x474, 0x12C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK		IOMUX_PAD(0x474, 0x12C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D21__CSPI_SCLK			IOMUX_PAD(0x474, 0x12C, 4, 0x780, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D21__I2C1_SCL			IOMUX_PAD(0x474, 0x12C, 5 | IOMUX_CONFIG_SION, 0x814, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D21__USBOH3_USBOTG_OC		IOMUX_PAD(0x474, 0x12C, 6, 0x89C, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D22__EMI_WEIM_D_22			IOMUX_PAD(0x478, 0x130, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D22__GPIO3_22			IOMUX_PAD(0x478, 0x130, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D22__IPU_DI0_PIN1			IOMUX_PAD(0x478, 0x130, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN		IOMUX_PAD(0x478, 0x130, 3, 0x82C, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D22__CSPI_MISO			IOMUX_PAD(0x478, 0x130, 4, 0x784, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D22__USBOH3_USBOTG_PWR		IOMUX_PAD(0x478, 0x130, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D23__EMI_WEIM_D_23			IOMUX_PAD(0x47C, 0x134, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D23__GPIO3_23			IOMUX_PAD(0x47C, 0x134, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D23__UART3_CTS			IOMUX_PAD(0x47C, 0x134, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D23__UART1_DCD			IOMUX_PAD(0x47C, 0x134, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D23__IPU_DI0_D0_CS			IOMUX_PAD(0x47C, 0x134, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D23__IPU_DI1_PIN2			IOMUX_PAD(0x47C, 0x134, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D23__IPU_CSI1_DATA_EN		IOMUX_PAD(0x47C, 0x134, 6, 0x834, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D23__IPU_DI1_PIN14			IOMUX_PAD(0x47C, 0x134, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB3__EMI_WEIM_EB_3			IOMUX_PAD(0x480, 0x138, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB3__GPIO2_31			IOMUX_PAD(0x480, 0x138, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB3__UART3_RTS			IOMUX_PAD(0x480, 0x138, 2, 0x884, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_EB3__UART1_RI			IOMUX_PAD(0x480, 0x138, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB3__IPU_DI1_PIN3			IOMUX_PAD(0x480, 0x138, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB3__IPU_CSI1_HSYNC		IOMUX_PAD(0x480, 0x138, 6, 0x838, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB3__IPU_DI1_PIN16			IOMUX_PAD(0x480, 0x138, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D24__EMI_WEIM_D_24			IOMUX_PAD(0x484, 0x13C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D24__GPIO3_24			IOMUX_PAD(0x484, 0x13C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D24__UART3_TXD_MUX			IOMUX_PAD(0x484, 0x13C, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D24__ECSPI1_SS2			IOMUX_PAD(0x484, 0x13C, 3, 0x7B0, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D24__CSPI_SS2			IOMUX_PAD(0x484, 0x13C, 4, 0x794, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D24__AUDMUX_AUD5_RXFS		IOMUX_PAD(0x484, 0x13C, 5, 0x754, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D24__ECSPI2_SS2			IOMUX_PAD(0x484, 0x13C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D24__UART1_DTR			IOMUX_PAD(0x484, 0x13C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D25__EMI_WEIM_D_25			IOMUX_PAD(0x488, 0x140, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D25__GPIO3_25			IOMUX_PAD(0x488, 0x140, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D25__UART3_RXD_MUX			IOMUX_PAD(0x488, 0x140, 2, 0x888, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D25__ECSPI1_SS3			IOMUX_PAD(0x488, 0x140, 3, 0x7B4, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D25__CSPI_SS3			IOMUX_PAD(0x488, 0x140, 4, 0x798, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D25__AUDMUX_AUD5_RXC		IOMUX_PAD(0x488, 0x140, 5, 0x750, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D25__ECSPI2_SS3			IOMUX_PAD(0x488, 0x140, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D25__UART1_DSR			IOMUX_PAD(0x488, 0x140, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D26__EMI_WEIM_D_26			IOMUX_PAD(0x48C, 0x144, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D26__GPIO3_26			IOMUX_PAD(0x48C, 0x144, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D26__UART2_TXD_MUX			IOMUX_PAD(0x48C, 0x144, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D26__FIRI_RXD			IOMUX_PAD(0x48C, 0x144, 3, 0x80C, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D26__IPU_CSI0_D_1			IOMUX_PAD(0x48C, 0x144, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D26__IPU_DI1_PIN11			IOMUX_PAD(0x48C, 0x144, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D26__IPU_SISG_2			IOMUX_PAD(0x48C, 0x144, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D26__IPU_DISP1_DAT_22		IOMUX_PAD(0x48C, 0x144, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D27__EMI_WEIM_D_27			IOMUX_PAD(0x490, 0x148, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D27__GPIO3_27			IOMUX_PAD(0x490, 0x148, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D27__UART2_RXD_MUX			IOMUX_PAD(0x490, 0x148, 2, 0x880, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D27__FIRI_TXD			IOMUX_PAD(0x490, 0x148, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D27__IPU_CSI0_D_0			IOMUX_PAD(0x490, 0x148, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D27__IPU_DI1_PIN13			IOMUX_PAD(0x490, 0x148, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D27__IPU_SISG_3			IOMUX_PAD(0x490, 0x148, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D27__IPU_DISP1_DAT_23		IOMUX_PAD(0x490, 0x148, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D28__EMI_WEIM_D_28			IOMUX_PAD(0x494, 0x14C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D28__GPIO3_28			IOMUX_PAD(0x494, 0x14C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D28__UART2_CTS			IOMUX_PAD(0x494, 0x14C, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO		IOMUX_PAD(0x494, 0x14C, 3, 0x82C, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D28__CSPI_MOSI			IOMUX_PAD(0x494, 0x14C, 4, 0x788, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D28__I2C1_SDA			IOMUX_PAD(0x494, 0x14C, 5 | IOMUX_CONFIG_SION, 0x818, 1, PAD_CTRL_I2C)
+#define MX53_PAD_EIM_D28__IPU_EXT_TRIG			IOMUX_PAD(0x494, 0x14C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D28__IPU_DI0_PIN13			IOMUX_PAD(0x494, 0x14C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D29__EMI_WEIM_D_29			IOMUX_PAD(0x498, 0x150, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D29__GPIO3_29			IOMUX_PAD(0x498, 0x150, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D29__UART2_RTS			IOMUX_PAD(0x498, 0x150, 2, 0x87C, 1, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D29__IPU_DISPB0_SER_RS		IOMUX_PAD(0x498, 0x150, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D29__CSPI_SS0			IOMUX_PAD(0x498, 0x150, 4, 0x78C, 2, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D29__IPU_DI1_PIN15			IOMUX_PAD(0x498, 0x150, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D29__IPU_CSI1_VSYNC		IOMUX_PAD(0x498, 0x150, 6, 0x83C, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D29__IPU_DI0_PIN14			IOMUX_PAD(0x498, 0x150, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D30__EMI_WEIM_D_30			IOMUX_PAD(0x49C, 0x154, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D30__GPIO3_30			IOMUX_PAD(0x49C, 0x154, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D30__UART3_CTS			IOMUX_PAD(0x49C, 0x154, 2, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D30__IPU_CSI0_D_3			IOMUX_PAD(0x49C, 0x154, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D30__IPU_DI0_PIN11			IOMUX_PAD(0x49C, 0x154, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D30__IPU_DISP1_DAT_21		IOMUX_PAD(0x49C, 0x154, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D30__USBOH3_USBH1_OC		IOMUX_PAD(0x49C, 0x154, 6, 0x8A0, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D30__USBOH3_USBH2_OC		IOMUX_PAD(0x49C, 0x154, 7, 0x8A4, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D31__EMI_WEIM_D_31			IOMUX_PAD(0x4A0, 0x158, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D31__GPIO3_31			IOMUX_PAD(0x4A0, 0x158, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D31__UART3_RTS			IOMUX_PAD(0x4A0, 0x158, 2, 0x884, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_EIM_D31__IPU_CSI0_D_2			IOMUX_PAD(0x4A0, 0x158, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D31__IPU_DI0_PIN12			IOMUX_PAD(0x4A0, 0x158, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D31__IPU_DISP1_DAT_20		IOMUX_PAD(0x4A0, 0x158, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D31__USBOH3_USBH1_PWR		IOMUX_PAD(0x4A0, 0x158, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_D31__USBOH3_USBH2_PWR		IOMUX_PAD(0x4A0, 0x158, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A24__EMI_WEIM_A_24			IOMUX_PAD(0x4A8, 0x15C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A24__GPIO5_4			IOMUX_PAD(0x4A8, 0x15C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A24__IPU_DISP1_DAT_19		IOMUX_PAD(0x4A8, 0x15C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A24__IPU_CSI1_D_19			IOMUX_PAD(0x4A8, 0x15C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A24__IPU_SISG_2			IOMUX_PAD(0x4A8, 0x15C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A24__USBPHY2_BVALID		IOMUX_PAD(0x4A8, 0x15C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A23__EMI_WEIM_A_23			IOMUX_PAD(0x4AC, 0x160, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A23__GPIO6_6			IOMUX_PAD(0x4AC, 0x160, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A23__IPU_DISP1_DAT_18		IOMUX_PAD(0x4AC, 0x160, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A23__IPU_CSI1_D_18			IOMUX_PAD(0x4AC, 0x160, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A23__IPU_SISG_3			IOMUX_PAD(0x4AC, 0x160, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A23__USBPHY2_ENDSESSION		IOMUX_PAD(0x4AC, 0x160, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A22__EMI_WEIM_A_22			IOMUX_PAD(0x4B0, 0x164, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A22__GPIO2_16			IOMUX_PAD(0x4B0, 0x164, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A22__IPU_DISP1_DAT_17		IOMUX_PAD(0x4B0, 0x164, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A22__IPU_CSI1_D_17			IOMUX_PAD(0x4B0, 0x164, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A22__SRC_BT_CFG1_7			IOMUX_PAD(0x4B0, 0x164, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A21__EMI_WEIM_A_21			IOMUX_PAD(0x4B4, 0x168, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A21__GPIO2_17			IOMUX_PAD(0x4B4, 0x168, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A21__IPU_DISP1_DAT_16		IOMUX_PAD(0x4B4, 0x168, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A21__IPU_CSI1_D_16			IOMUX_PAD(0x4B4, 0x168, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A21__SRC_BT_CFG1_6			IOMUX_PAD(0x4B4, 0x168, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A20__EMI_WEIM_A_20			IOMUX_PAD(0x4B8, 0x16C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A20__GPIO2_18			IOMUX_PAD(0x4B8, 0x16C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A20__IPU_DISP1_DAT_15		IOMUX_PAD(0x4B8, 0x16C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A20__IPU_CSI1_D_15			IOMUX_PAD(0x4B8, 0x16C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A20__SRC_BT_CFG1_5			IOMUX_PAD(0x4B8, 0x16C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A19__EMI_WEIM_A_19			IOMUX_PAD(0x4BC, 0x170, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A19__GPIO2_19			IOMUX_PAD(0x4BC, 0x170, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A19__IPU_DISP1_DAT_14		IOMUX_PAD(0x4BC, 0x170, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A19__IPU_CSI1_D_14			IOMUX_PAD(0x4BC, 0x170, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A19__SRC_BT_CFG1_4			IOMUX_PAD(0x4BC, 0x170, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A18__EMI_WEIM_A_18			IOMUX_PAD(0x4C0, 0x174, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A18__GPIO2_20			IOMUX_PAD(0x4C0, 0x174, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A18__IPU_DISP1_DAT_13		IOMUX_PAD(0x4C0, 0x174, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A18__IPU_CSI1_D_13			IOMUX_PAD(0x4C0, 0x174, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A18__SRC_BT_CFG1_3			IOMUX_PAD(0x4C0, 0x174, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A17__EMI_WEIM_A_17			IOMUX_PAD(0x4C4, 0x178, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A17__GPIO2_21			IOMUX_PAD(0x4C4, 0x178, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A17__IPU_DISP1_DAT_12		IOMUX_PAD(0x4C4, 0x178, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A17__IPU_CSI1_D_12			IOMUX_PAD(0x4C4, 0x178, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A17__SRC_BT_CFG1_2			IOMUX_PAD(0x4C4, 0x178, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A16__EMI_WEIM_A_16			IOMUX_PAD(0x4C8, 0x17C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A16__GPIO2_22			IOMUX_PAD(0x4C8, 0x17C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK		IOMUX_PAD(0x4C8, 0x17C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A16__IPU_CSI1_PIXCLK		IOMUX_PAD(0x4C8, 0x17C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_A16__SRC_BT_CFG1_1			IOMUX_PAD(0x4C8, 0x17C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS0__EMI_WEIM_CS_0			IOMUX_PAD(0x4CC, 0x180, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS0__GPIO2_23			IOMUX_PAD(0x4CC, 0x180, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS0__ECSPI2_SCLK			IOMUX_PAD(0x4CC, 0x180, 2, 0x7B8, 2, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS0__IPU_DI1_PIN5			IOMUX_PAD(0x4CC, 0x180, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS1__EMI_WEIM_CS_1			IOMUX_PAD(0x4D0, 0x184, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS1__GPIO2_24			IOMUX_PAD(0x4D0, 0x184, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS1__ECSPI2_MOSI			IOMUX_PAD(0x4D0, 0x184, 2, 0x7C0, 2, NO_PAD_CTRL)
+#define MX53_PAD_EIM_CS1__IPU_DI1_PIN6			IOMUX_PAD(0x4D0, 0x184, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_OE__EMI_WEIM_OE			IOMUX_PAD(0x4D4, 0x188, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_OE__GPIO2_25			IOMUX_PAD(0x4D4, 0x188, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_OE__ECSPI2_MISO			IOMUX_PAD(0x4D4, 0x188, 2, 0x7BC, 2, NO_PAD_CTRL)
+#define MX53_PAD_EIM_OE__IPU_DI1_PIN7			IOMUX_PAD(0x4D4, 0x188, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_OE__USBPHY2_IDDIG			IOMUX_PAD(0x4D4, 0x188, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_RW__EMI_WEIM_RW			IOMUX_PAD(0x4D8, 0x18C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_RW__GPIO2_26			IOMUX_PAD(0x4D8, 0x18C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_RW__ECSPI2_SS0			IOMUX_PAD(0x4D8, 0x18C, 2, 0x7C4, 2, NO_PAD_CTRL)
+#define MX53_PAD_EIM_RW__IPU_DI1_PIN8			IOMUX_PAD(0x4D8, 0x18C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_RW__USBPHY2_HOSTDISCONNECT		IOMUX_PAD(0x4D8, 0x18C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_LBA__EMI_WEIM_LBA			IOMUX_PAD(0x4DC, 0x190, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_LBA__GPIO2_27			IOMUX_PAD(0x4DC, 0x190, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_LBA__ECSPI2_SS1			IOMUX_PAD(0x4DC, 0x190, 2, 0x7C8, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_LBA__IPU_DI1_PIN17			IOMUX_PAD(0x4DC, 0x190, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_LBA__SRC_BT_CFG1_0			IOMUX_PAD(0x4DC, 0x190, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB0__EMI_WEIM_EB_0			IOMUX_PAD(0x4E4, 0x194, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB0__GPIO2_28			IOMUX_PAD(0x4E4, 0x194, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11		IOMUX_PAD(0x4E4, 0x194, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB0__IPU_CSI1_D_11			IOMUX_PAD(0x4E4, 0x194, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB0__GPC_PMIC_RDY			IOMUX_PAD(0x4E4, 0x194, 5, 0x810, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB0__SRC_BT_CFG2_7			IOMUX_PAD(0x4E4, 0x194, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB1__EMI_WEIM_EB_1			IOMUX_PAD(0x4E8, 0x198, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB1__GPIO2_29			IOMUX_PAD(0x4E8, 0x198, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10		IOMUX_PAD(0x4E8, 0x198, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB1__IPU_CSI1_D_10			IOMUX_PAD(0x4E8, 0x198, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_EB1__SRC_BT_CFG2_6			IOMUX_PAD(0x4E8, 0x198, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0		IOMUX_PAD(0x4EC, 0x19C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA0__GPIO3_0			IOMUX_PAD(0x4EC, 0x19C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9		IOMUX_PAD(0x4EC, 0x19C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA0__IPU_CSI1_D_9			IOMUX_PAD(0x4EC, 0x19C, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA0__SRC_BT_CFG2_5			IOMUX_PAD(0x4EC, 0x19C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1		IOMUX_PAD(0x4F0, 0x1A0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA1__GPIO3_1			IOMUX_PAD(0x4F0, 0x1A0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8		IOMUX_PAD(0x4F0, 0x1A0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA1__IPU_CSI1_D_8			IOMUX_PAD(0x4F0, 0x1A0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA1__SRC_BT_CFG2_4			IOMUX_PAD(0x4F0, 0x1A0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2		IOMUX_PAD(0x4F4, 0x1A4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA2__GPIO3_2			IOMUX_PAD(0x4F4, 0x1A4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7		IOMUX_PAD(0x4F4, 0x1A4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA2__IPU_CSI1_D_7			IOMUX_PAD(0x4F4, 0x1A4, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA2__SRC_BT_CFG2_3			IOMUX_PAD(0x4F4, 0x1A4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3		IOMUX_PAD(0x4F8, 0x1A8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA3__GPIO3_3			IOMUX_PAD(0x4F8, 0x1A8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6		IOMUX_PAD(0x4F8, 0x1A8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA3__IPU_CSI1_D_6			IOMUX_PAD(0x4F8, 0x1A8, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA3__SRC_BT_CFG2_2			IOMUX_PAD(0x4F8, 0x1A8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4		IOMUX_PAD(0x4FC, 0x1AC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA4__GPIO3_4			IOMUX_PAD(0x4FC, 0x1AC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5		IOMUX_PAD(0x4FC, 0x1AC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA4__IPU_CSI1_D_5			IOMUX_PAD(0x4FC, 0x1AC, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA4__SRC_BT_CFG3_7			IOMUX_PAD(0x4FC, 0x1AC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5		IOMUX_PAD(0x500, 0x1B0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA5__GPIO3_5			IOMUX_PAD(0x500, 0x1B0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4		IOMUX_PAD(0x500, 0x1B0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA5__IPU_CSI1_D_4			IOMUX_PAD(0x500, 0x1B0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA5__SRC_BT_CFG3_6			IOMUX_PAD(0x500, 0x1B0, 7 | IOMUX_CONFIG_SION, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6		IOMUX_PAD(0x504, 0x1B4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA6__GPIO3_6			IOMUX_PAD(0x504, 0x1B4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3		IOMUX_PAD(0x504, 0x1B4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA6__IPU_CSI1_D_3			IOMUX_PAD(0x504, 0x1B4, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA6__SRC_BT_CFG3_5			IOMUX_PAD(0x504, 0x1B4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA7__EMI_NAND_WEIM_DA_7		IOMUX_PAD(0x508, 0x1B8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA7__GPIO3_7			IOMUX_PAD(0x508, 0x1B8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2		IOMUX_PAD(0x508, 0x1B8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA7__IPU_CSI1_D_2			IOMUX_PAD(0x508, 0x1B8, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA7__SRC_BT_CFG3_4			IOMUX_PAD(0x508, 0x1B8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA8__EMI_NAND_WEIM_DA_8		IOMUX_PAD(0x50C, 0x1BC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA8__GPIO3_8			IOMUX_PAD(0x50C, 0x1BC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1		IOMUX_PAD(0x50C, 0x1BC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA8__IPU_CSI1_D_1			IOMUX_PAD(0x50C, 0x1BC, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA8__SRC_BT_CFG3_3			IOMUX_PAD(0x50C, 0x1BC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA9__EMI_NAND_WEIM_DA_9		IOMUX_PAD(0x510, 0x1C0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA9__GPIO3_9			IOMUX_PAD(0x510, 0x1C0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0		IOMUX_PAD(0x510, 0x1C0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA9__IPU_CSI1_D_0			IOMUX_PAD(0x510, 0x1C0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA9__SRC_BT_CFG3_2			IOMUX_PAD(0x510, 0x1C0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA10__EMI_NAND_WEIM_DA_10		IOMUX_PAD(0x514, 0x1C4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA10__GPIO3_10			IOMUX_PAD(0x514, 0x1C4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA10__IPU_DI1_PIN15		IOMUX_PAD(0x514, 0x1C4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA10__IPU_CSI1_DATA_EN		IOMUX_PAD(0x514, 0x1C4, 4, 0x834, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA10__SRC_BT_CFG3_1		IOMUX_PAD(0x514, 0x1C4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA11__EMI_NAND_WEIM_DA_11		IOMUX_PAD(0x518, 0x1C8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA11__GPIO3_11			IOMUX_PAD(0x518, 0x1C8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA11__IPU_DI1_PIN2			IOMUX_PAD(0x518, 0x1C8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA11__IPU_CSI1_HSYNC		IOMUX_PAD(0x518, 0x1C8, 4, 0x838, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA12__EMI_NAND_WEIM_DA_12		IOMUX_PAD(0x51C, 0x1CC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA12__GPIO3_12			IOMUX_PAD(0x51C, 0x1CC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA12__IPU_DI1_PIN3			IOMUX_PAD(0x51C, 0x1CC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA12__IPU_CSI1_VSYNC		IOMUX_PAD(0x51C, 0x1CC, 4, 0x83C, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA13__EMI_NAND_WEIM_DA_13		IOMUX_PAD(0x520, 0x1D0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA13__GPIO3_13			IOMUX_PAD(0x520, 0x1D0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA13__IPU_DI1_D0_CS		IOMUX_PAD(0x520, 0x1D0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA13__CCM_DI1_EXT_CLK		IOMUX_PAD(0x520, 0x1D0, 4, 0x76C, 1, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA14__EMI_NAND_WEIM_DA_14		IOMUX_PAD(0x524, 0x1D4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA14__GPIO3_14			IOMUX_PAD(0x524, 0x1D4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA14__IPU_DI1_D1_CS		IOMUX_PAD(0x524, 0x1D4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA14__CCM_DI0_EXT_CLK		IOMUX_PAD(0x524, 0x1D4, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA15__EMI_NAND_WEIM_DA_15		IOMUX_PAD(0x528, 0x1D8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA15__GPIO3_15			IOMUX_PAD(0x528, 0x1D8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA15__IPU_DI1_PIN1			IOMUX_PAD(0x528, 0x1D8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_DA15__IPU_DI1_PIN4			IOMUX_PAD(0x528, 0x1D8, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B		IOMUX_PAD(0x52C, 0x1DC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_WE_B__GPIO6_12			IOMUX_PAD(0x52C, 0x1DC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B		IOMUX_PAD(0x530, 0x1E0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_RE_B__GPIO6_13			IOMUX_PAD(0x530, 0x1E0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_WAIT__EMI_WEIM_WAIT		IOMUX_PAD(0x534, 0x1E4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_WAIT__GPIO5_0			IOMUX_PAD(0x534, 0x1E4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_EIM_WAIT__EMI_WEIM_DTACK_B		IOMUX_PAD(0x534, 0x1E4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX3_P__GPIO6_22			IOMUX_PAD(__NA_, 0x1EC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3		IOMUX_PAD(__NA_, 0x1EC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX2_P__GPIO6_24			IOMUX_PAD(__NA_, 0x1F0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2		IOMUX_PAD(__NA_, 0x1F0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_CLK_P__GPIO6_26			IOMUX_PAD(__NA_, 0x1F4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK		IOMUX_PAD(__NA_, 0x1F4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX1_P__GPIO6_28			IOMUX_PAD(__NA_, 0x1F8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1		IOMUX_PAD(__NA_, 0x1F8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX0_P__GPIO6_30			IOMUX_PAD(__NA_, 0x1FC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0		IOMUX_PAD(__NA_, 0x1FC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX3_P__GPIO7_22			IOMUX_PAD(__NA_, 0x200, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3		IOMUX_PAD(__NA_, 0x200, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_CLK_P__GPIO7_24			IOMUX_PAD(__NA_, 0x204, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK		IOMUX_PAD(__NA_, 0x204, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX2_P__GPIO7_26			IOMUX_PAD(__NA_, 0x208, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2		IOMUX_PAD(__NA_, 0x208, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX1_P__GPIO7_28			IOMUX_PAD(__NA_, 0x20C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1		IOMUX_PAD(__NA_, 0x20C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX0_P__GPIO7_30			IOMUX_PAD(__NA_, 0x210, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0		IOMUX_PAD(__NA_, 0x210, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_10__GPIO4_0			IOMUX_PAD(0x540, 0x214, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_10__OSC32k_32K_OUT		IOMUX_PAD(0x540, 0x214, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_11__GPIO4_1			IOMUX_PAD(0x544, 0x218, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_12__GPIO4_2			IOMUX_PAD(0x548, 0x21C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_13__GPIO4_3			IOMUX_PAD(0x54C, 0x220, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_14__GPIO4_4			IOMUX_PAD(0x550, 0x224, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CLE__EMI_NANDF_CLE		IOMUX_PAD(0x5A0, 0x228, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CLE__GPIO6_7			IOMUX_PAD(0x5A0, 0x228, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CLE__USBPHY1_VSTATUS_0		IOMUX_PAD(0x5A0, 0x228, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_ALE__EMI_NANDF_ALE		IOMUX_PAD(0x5A4, 0x22C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_ALE__GPIO6_8			IOMUX_PAD(0x5A4, 0x22C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_ALE__USBPHY1_VSTATUS_1		IOMUX_PAD(0x5A4, 0x22C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B		IOMUX_PAD(0x5A8, 0x230, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_WP_B__GPIO6_9			IOMUX_PAD(0x5A8, 0x230, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_WP_B__USBPHY1_VSTATUS_2		IOMUX_PAD(0x5A8, 0x230, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0		IOMUX_PAD(0x5AC, 0x234, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_RB0__GPIO6_10			IOMUX_PAD(0x5AC, 0x234, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_RB0__USBPHY1_VSTATUS_3		IOMUX_PAD(0x5AC, 0x234, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0		IOMUX_PAD(0x5B0, 0x238, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS0__GPIO6_11			IOMUX_PAD(0x5B0, 0x238, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS0__USBPHY1_VSTATUS_4		IOMUX_PAD(0x5B0, 0x238, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS1__EMI_NANDF_CS_1		IOMUX_PAD(0x5B4, 0x23C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS1__GPIO6_14			IOMUX_PAD(0x5B4, 0x23C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS1__MLB_MLBCLK			IOMUX_PAD(0x5B4, 0x23C, 6, 0x858, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS1__USBPHY1_VSTATUS_5		IOMUX_PAD(0x5B4, 0x23C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__EMI_NANDF_CS_2		IOMUX_PAD(0x5B8, 0x240, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__GPIO6_15			IOMUX_PAD(0x5B8, 0x240, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__IPU_SISG_0			IOMUX_PAD(0x5B8, 0x240, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__ESAI1_TX0			IOMUX_PAD(0x5B8, 0x240, 3, 0x7E4, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__EMI_WEIM_CRE		IOMUX_PAD(0x5B8, 0x240, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__CCM_CSI0_MCLK		IOMUX_PAD(0x5B8, 0x240, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__MLB_MLBSIG			IOMUX_PAD(0x5B8, 0x240, 6, 0x860, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS2__USBPHY1_VSTATUS_6		IOMUX_PAD(0x5B8, 0x240, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS3__EMI_NANDF_CS_3		IOMUX_PAD(0x5BC, 0x244, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS3__GPIO6_16			IOMUX_PAD(0x5BC, 0x244, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS3__IPU_SISG_1			IOMUX_PAD(0x5BC, 0x244, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS3__ESAI1_TX1			IOMUX_PAD(0x5BC, 0x244, 3, 0x7E8, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS3__EMI_WEIM_A_26		IOMUX_PAD(0x5BC, 0x244, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS3__MLB_MLBDAT			IOMUX_PAD(0x5BC, 0x244, 6, 0x85C, 0, NO_PAD_CTRL)
+#define MX53_PAD_NANDF_CS3__USBPHY1_VSTATUS_7		IOMUX_PAD(0x5BC, 0x244, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDIO__FEC_MDIO			IOMUX_PAD(0x5C4, 0x248, 0, 0x804, 1, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDIO__GPIO1_22			IOMUX_PAD(0x5C4, 0x248, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDIO__ESAI1_SCKR			IOMUX_PAD(0x5C4, 0x248, 2, 0x7DC, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDIO__FEC_COL			IOMUX_PAD(0x5C4, 0x248, 3, 0x800, 1, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDIO__RTC_CE_RTC_PS2		IOMUX_PAD(0x5C4, 0x248, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDIO__SDMA_DEBUG_BUS_DEVICE_3	IOMUX_PAD(0x5C4, 0x248, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDIO__EMI_EMI_DEBUG_49		IOMUX_PAD(0x5C4, 0x248, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_REF_CLK__FEC_TX_CLK		IOMUX_PAD(0x5C8, 0x24C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_REF_CLK__GPIO1_23			IOMUX_PAD(0x5C8, 0x24C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_REF_CLK__ESAI1_FSR			IOMUX_PAD(0x5C8, 0x24C, 2, 0x7CC, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_REF_CLK__SDMA_DEBUG_BUS_DEVICE_4	IOMUX_PAD(0x5C8, 0x24C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_REF_CLK__EMI_EMI_DEBUG_50		IOMUX_PAD(0x5C8, 0x24C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RX_ER__FEC_RX_ER			IOMUX_PAD(0x5CC, 0x250, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RX_ER__GPIO1_24			IOMUX_PAD(0x5CC, 0x250, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RX_ER__ESAI1_HCKR			IOMUX_PAD(0x5CC, 0x250, 2, 0x7D4, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RX_ER__FEC_RX_CLK			IOMUX_PAD(0x5CC, 0x250, 3, 0x808, 1, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RX_ER__RTC_CE_RTC_PS3		IOMUX_PAD(0x5CC, 0x250, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_CRS_DV__FEC_RX_DV			IOMUX_PAD(0x5D0, 0x254, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_CRS_DV__GPIO1_25			IOMUX_PAD(0x5D0, 0x254, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_CRS_DV__ESAI1_SCKT			IOMUX_PAD(0x5D0, 0x254, 2, 0x7E0, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD1__FEC_RDATA_1			IOMUX_PAD(0x5D4, 0x258, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD1__GPIO1_26			IOMUX_PAD(0x5D4, 0x258, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD1__ESAI1_FST			IOMUX_PAD(0x5D4, 0x258, 2, 0x7D0, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD1__MLB_MLBSIG			IOMUX_PAD(0x5D4, 0x258, 3, 0x860, 1, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD1__RTC_CE_RTC_PS1		IOMUX_PAD(0x5D4, 0x258, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD0__FEC_RDATA_0			IOMUX_PAD(0x5D8, 0x25C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD0__GPIO1_27			IOMUX_PAD(0x5D8, 0x25C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD0__ESAI1_HCKT			IOMUX_PAD(0x5D8, 0x25C, 2, 0x7D8, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_RXD0__OSC32k_32K_OUT		IOMUX_PAD(0x5D8, 0x25C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TX_EN__FEC_TX_EN			IOMUX_PAD(0x5DC, 0x260, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TX_EN__GPIO1_28			IOMUX_PAD(0x5DC, 0x260, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TX_EN__ESAI1_TX3_RX2		IOMUX_PAD(0x5DC, 0x260, 2, 0x7F0, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD1__FEC_TDATA_1			IOMUX_PAD(0x5E0, 0x264, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD1__GPIO1_29			IOMUX_PAD(0x5E0, 0x264, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD1__ESAI1_TX2_RX3		IOMUX_PAD(0x5E0, 0x264, 2, 0x7EC, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD1__MLB_MLBCLK			IOMUX_PAD(0x5E0, 0x264, 3, 0x858, 1, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD1__RTC_CE_RTC_PRSC_CLK		IOMUX_PAD(0x5E0, 0x264, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD0__FEC_TDATA_0			IOMUX_PAD(0x5E4, 0x268, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD0__GPIO1_30			IOMUX_PAD(0x5E4, 0x268, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD0__ESAI1_TX4_RX1		IOMUX_PAD(0x5E4, 0x268, 2, 0x7F4, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_TXD0__USBPHY2_DATAOUT_0		IOMUX_PAD(0x5E4, 0x268, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDC__FEC_MDC			IOMUX_PAD(0x5E8, 0x26C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDC__GPIO1_31			IOMUX_PAD(0x5E8, 0x26C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDC__ESAI1_TX5_RX0			IOMUX_PAD(0x5E8, 0x26C, 2, 0x7F8, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDC__MLB_MLBDAT			IOMUX_PAD(0x5E8, 0x26C, 3, 0x85C, 1, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDC__RTC_CE_RTC_ALARM1_TRIG	IOMUX_PAD(0x5E8, 0x26C, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_FEC_MDC__USBPHY2_DATAOUT_1		IOMUX_PAD(0x5E8, 0x26C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DIOW__PATA_DIOW			IOMUX_PAD(0x5F0, 0x270, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DIOW__GPIO6_17			IOMUX_PAD(0x5F0, 0x270, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DIOW__UART1_TXD_MUX		IOMUX_PAD(0x5F0, 0x270, 3, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_DIOW__USBPHY2_DATAOUT_2		IOMUX_PAD(0x5F0, 0x270, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DMACK__PATA_DMACK			IOMUX_PAD(0x5F4, 0x274, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DMACK__GPIO6_18			IOMUX_PAD(0x5F4, 0x274, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DMACK__UART1_RXD_MUX		IOMUX_PAD(0x5F4, 0x274, 3, 0x878, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_DMACK__USBPHY2_DATAOUT_3		IOMUX_PAD(0x5F4, 0x274, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DMARQ__PATA_DMARQ			IOMUX_PAD(0x5F8, 0x278, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DMARQ__GPIO7_0			IOMUX_PAD(0x5F8, 0x278, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DMARQ__UART2_TXD_MUX		IOMUX_PAD(0x5F8, 0x278, 3, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_DMARQ__CCM_CCM_OUT_0		IOMUX_PAD(0x5F8, 0x278, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DMARQ__USBPHY2_DATAOUT_4		IOMUX_PAD(0x5F8, 0x278, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_BUFFER_EN__PATA_BUFFER_EN		IOMUX_PAD(0x5FC, 0x27C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_BUFFER_EN__GPIO7_1		IOMUX_PAD(0x5FC, 0x27C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX		IOMUX_PAD(0x5FC, 0x27C, 3, 0x880, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_BUFFER_EN__CCM_CCM_OUT_1		IOMUX_PAD(0x5FC, 0x27C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_BUFFER_EN__USBPHY2_DATAOUT_5	IOMUX_PAD(0x5FC, 0x27C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_INTRQ__PATA_INTRQ			IOMUX_PAD(0x600, 0x280, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_INTRQ__GPIO7_2			IOMUX_PAD(0x600, 0x280, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_INTRQ__UART2_CTS			IOMUX_PAD(0x600, 0x280, 3, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_INTRQ__CAN1_TXCAN			IOMUX_PAD(0x600, 0x280, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_INTRQ__CCM_CCM_OUT_2		IOMUX_PAD(0x600, 0x280, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_INTRQ__USBPHY2_DATAOUT_6		IOMUX_PAD(0x600, 0x280, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DIOR__PATA_DIOR			IOMUX_PAD(0x604, 0x284, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DIOR__GPIO7_3			IOMUX_PAD(0x604, 0x284, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DIOR__UART2_RTS			IOMUX_PAD(0x604, 0x284, 3, 0x87C, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_DIOR__CAN1_RXCAN			IOMUX_PAD(0x604, 0x284, 4, 0x760, 1, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DIOR__USBPHY2_DATAOUT_7		IOMUX_PAD(0x604, 0x284, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_RESET_B__PATA_PATA_RESET_B	IOMUX_PAD(0x608, 0x288, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_RESET_B__GPIO7_4			IOMUX_PAD(0x608, 0x288, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_RESET_B__ESDHC3_CMD		IOMUX_PAD(0x608, 0x288, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_RESET_B__UART1_CTS		IOMUX_PAD(0x608, 0x288, 3, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_RESET_B__CAN2_TXCAN		IOMUX_PAD(0x608, 0x288, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_RESET_B__USBPHY1_DATAOUT_0	IOMUX_PAD(0x608, 0x288, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_IORDY__PATA_IORDY			IOMUX_PAD(0x60C, 0x28C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_IORDY__GPIO7_5			IOMUX_PAD(0x60C, 0x28C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_IORDY__ESDHC3_CLK			IOMUX_PAD(0x60C, 0x28C, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_IORDY__UART1_RTS			IOMUX_PAD(0x60C, 0x28C, 3, 0x874, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_IORDY__CAN2_RXCAN			IOMUX_PAD(0x60C, 0x28C, 4, 0x764, 1, NO_PAD_CTRL)
+#define MX53_PAD_PATA_IORDY__USBPHY1_DATAOUT_1		IOMUX_PAD(0x60C, 0x28C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_0__PATA_DA_0			IOMUX_PAD(0x610, 0x290, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_0__GPIO7_6			IOMUX_PAD(0x610, 0x290, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_0__ESDHC3_RST			IOMUX_PAD(0x610, 0x290, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_0__OWIRE_LINE			IOMUX_PAD(0x610, 0x290, 4, 0x864, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_0__USBPHY1_DATAOUT_2		IOMUX_PAD(0x610, 0x290, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_1__PATA_DA_1			IOMUX_PAD(0x614, 0x294, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_1__GPIO7_7			IOMUX_PAD(0x614, 0x294, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_1__ESDHC4_CMD			IOMUX_PAD(0x614, 0x294, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DA_1__UART3_CTS			IOMUX_PAD(0x614, 0x294, 4, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_DA_1__USBPHY1_DATAOUT_3		IOMUX_PAD(0x614, 0x294, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_2__PATA_DA_2			IOMUX_PAD(0x618, 0x298, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_2__GPIO7_8			IOMUX_PAD(0x618, 0x298, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DA_2__ESDHC4_CLK			IOMUX_PAD(0x618, 0x298, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DA_2__UART3_RTS			IOMUX_PAD(0x618, 0x298, 4, 0x884, 5, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_DA_2__USBPHY1_DATAOUT_4		IOMUX_PAD(0x618, 0x298, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_CS_0__PATA_CS_0			IOMUX_PAD(0x61C, 0x29C, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_CS_0__GPIO7_9			IOMUX_PAD(0x61C, 0x29C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_CS_0__UART3_TXD_MUX		IOMUX_PAD(0x61C, 0x29C, 4, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_CS_0__USBPHY1_DATAOUT_5		IOMUX_PAD(0x61C, 0x29C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_CS_1__PATA_CS_1			IOMUX_PAD(0x620, 0x2A0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_CS_1__GPIO7_10			IOMUX_PAD(0x620, 0x2A0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_CS_1__UART3_RXD_MUX		IOMUX_PAD(0x620, 0x2A0, 4, 0x888, 3, MX53_UART_PAD_CTRL)
+#define MX53_PAD_PATA_CS_1__USBPHY1_DATAOUT_6		IOMUX_PAD(0x620, 0x2A0, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA0__PATA_DATA_0		IOMUX_PAD(0x628, 0x2A4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA0__GPIO2_0			IOMUX_PAD(0x628, 0x2A4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA0__EMI_NANDF_D_0		IOMUX_PAD(0x628, 0x2A4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA0__ESDHC3_DAT4		IOMUX_PAD(0x628, 0x2A4, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA0__GPU3d_GPU_DEBUG_OUT_0	IOMUX_PAD(0x628, 0x2A4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA0__IPU_DIAG_BUS_0		IOMUX_PAD(0x628, 0x2A4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA0__USBPHY1_DATAOUT_7		IOMUX_PAD(0x628, 0x2A4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA1__PATA_DATA_1		IOMUX_PAD(0x62C, 0x2A8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA1__GPIO2_1			IOMUX_PAD(0x62C, 0x2A8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA1__EMI_NANDF_D_1		IOMUX_PAD(0x62C, 0x2A8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA1__ESDHC3_DAT5		IOMUX_PAD(0x62C, 0x2A8, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA1__GPU3d_GPU_DEBUG_OUT_1	IOMUX_PAD(0x62C, 0x2A8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA1__IPU_DIAG_BUS_1		IOMUX_PAD(0x62C, 0x2A8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA2__PATA_DATA_2		IOMUX_PAD(0x630, 0x2AC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA2__GPIO2_2			IOMUX_PAD(0x630, 0x2AC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA2__EMI_NANDF_D_2		IOMUX_PAD(0x630, 0x2AC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA2__ESDHC3_DAT6		IOMUX_PAD(0x630, 0x2AC, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA2__GPU3d_GPU_DEBUG_OUT_2	IOMUX_PAD(0x630, 0x2AC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA2__IPU_DIAG_BUS_2		IOMUX_PAD(0x630, 0x2AC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA3__PATA_DATA_3		IOMUX_PAD(0x634, 0x2B0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA3__GPIO2_3			IOMUX_PAD(0x634, 0x2B0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA3__EMI_NANDF_D_3		IOMUX_PAD(0x634, 0x2B0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA3__ESDHC3_DAT7		IOMUX_PAD(0x634, 0x2B0, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA3__GPU3d_GPU_DEBUG_OUT_3	IOMUX_PAD(0x634, 0x2B0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA3__IPU_DIAG_BUS_3		IOMUX_PAD(0x634, 0x2B0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA4__PATA_DATA_4		IOMUX_PAD(0x638, 0x2B4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA4__GPIO2_4			IOMUX_PAD(0x638, 0x2B4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA4__EMI_NANDF_D_4		IOMUX_PAD(0x638, 0x2B4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA4__ESDHC4_DAT4		IOMUX_PAD(0x638, 0x2B4, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA4__GPU3d_GPU_DEBUG_OUT_4	IOMUX_PAD(0x638, 0x2B4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA4__IPU_DIAG_BUS_4		IOMUX_PAD(0x638, 0x2B4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA5__PATA_DATA_5		IOMUX_PAD(0x63C, 0x2B8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA5__GPIO2_5			IOMUX_PAD(0x63C, 0x2B8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA5__EMI_NANDF_D_5		IOMUX_PAD(0x63C, 0x2B8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA5__ESDHC4_DAT5		IOMUX_PAD(0x63C, 0x2B8, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA5__GPU3d_GPU_DEBUG_OUT_5	IOMUX_PAD(0x63C, 0x2B8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA5__IPU_DIAG_BUS_5		IOMUX_PAD(0x63C, 0x2B8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA6__PATA_DATA_6		IOMUX_PAD(0x640, 0x2BC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA6__GPIO2_6			IOMUX_PAD(0x640, 0x2BC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA6__EMI_NANDF_D_6		IOMUX_PAD(0x640, 0x2BC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA6__ESDHC4_DAT6		IOMUX_PAD(0x640, 0x2BC, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA6__GPU3d_GPU_DEBUG_OUT_6	IOMUX_PAD(0x640, 0x2BC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA6__IPU_DIAG_BUS_6		IOMUX_PAD(0x640, 0x2BC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA7__PATA_DATA_7		IOMUX_PAD(0x644, 0x2C0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA7__GPIO2_7			IOMUX_PAD(0x644, 0x2C0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA7__EMI_NANDF_D_7		IOMUX_PAD(0x644, 0x2C0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA7__ESDHC4_DAT7		IOMUX_PAD(0x644, 0x2C0, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA7__GPU3d_GPU_DEBUG_OUT_7	IOMUX_PAD(0x644, 0x2C0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA7__IPU_DIAG_BUS_7		IOMUX_PAD(0x644, 0x2C0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA8__PATA_DATA_8		IOMUX_PAD(0x648, 0x2C4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA8__GPIO2_8			IOMUX_PAD(0x648, 0x2C4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA8__ESDHC1_DAT4		IOMUX_PAD(0x648, 0x2C4, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA8__EMI_NANDF_D_8		IOMUX_PAD(0x648, 0x2C4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA8__ESDHC3_DAT0		IOMUX_PAD(0x648, 0x2C4, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA8__GPU3d_GPU_DEBUG_OUT_8	IOMUX_PAD(0x648, 0x2C4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA8__IPU_DIAG_BUS_8		IOMUX_PAD(0x648, 0x2C4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA9__PATA_DATA_9		IOMUX_PAD(0x64C, 0x2C8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA9__GPIO2_9			IOMUX_PAD(0x64C, 0x2C8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA9__ESDHC1_DAT5		IOMUX_PAD(0x64C, 0x2C8, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA9__EMI_NANDF_D_9		IOMUX_PAD(0x64C, 0x2C8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA9__ESDHC3_DAT1		IOMUX_PAD(0x64C, 0x2C8, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA9__GPU3d_GPU_DEBUG_OUT_9	IOMUX_PAD(0x64C, 0x2C8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA9__IPU_DIAG_BUS_9		IOMUX_PAD(0x64C, 0x2C8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA10__PATA_DATA_10		IOMUX_PAD(0x650, 0x2CC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA10__GPIO2_10			IOMUX_PAD(0x650, 0x2CC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA10__ESDHC1_DAT6		IOMUX_PAD(0x650, 0x2CC, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA10__EMI_NANDF_D_10		IOMUX_PAD(0x650, 0x2CC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA10__ESDHC3_DAT2		IOMUX_PAD(0x650, 0x2CC, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA10__GPU3d_GPU_DEBUG_OUT_10	IOMUX_PAD(0x650, 0x2CC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA10__IPU_DIAG_BUS_10		IOMUX_PAD(0x650, 0x2CC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA11__PATA_DATA_11		IOMUX_PAD(0x654, 0x2D0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA11__GPIO2_11			IOMUX_PAD(0x654, 0x2D0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA11__ESDHC1_DAT7		IOMUX_PAD(0x654, 0x2D0, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA11__EMI_NANDF_D_11		IOMUX_PAD(0x654, 0x2D0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA11__ESDHC3_DAT3		IOMUX_PAD(0x654, 0x2D0, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA11__GPU3d_GPU_DEBUG_OUT_11	IOMUX_PAD(0x654, 0x2D0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA11__IPU_DIAG_BUS_11		IOMUX_PAD(0x654, 0x2D0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA12__PATA_DATA_12		IOMUX_PAD(0x658, 0x2D4, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA12__GPIO2_12			IOMUX_PAD(0x658, 0x2D4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA12__ESDHC2_DAT4		IOMUX_PAD(0x658, 0x2D4, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA12__EMI_NANDF_D_12		IOMUX_PAD(0x658, 0x2D4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA12__ESDHC4_DAT0		IOMUX_PAD(0x658, 0x2D4, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA12__GPU3d_GPU_DEBUG_OUT_12	IOMUX_PAD(0x658, 0x2D4, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA12__IPU_DIAG_BUS_12		IOMUX_PAD(0x658, 0x2D4, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA13__PATA_DATA_13		IOMUX_PAD(0x65C, 0x2D8, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA13__GPIO2_13			IOMUX_PAD(0x65C, 0x2D8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA13__ESDHC2_DAT5		IOMUX_PAD(0x65C, 0x2D8, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA13__EMI_NANDF_D_13		IOMUX_PAD(0x65C, 0x2D8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA13__ESDHC4_DAT1		IOMUX_PAD(0x65C, 0x2D8, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA13__GPU3d_GPU_DEBUG_OUT_13	IOMUX_PAD(0x65C, 0x2D8, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA13__IPU_DIAG_BUS_13		IOMUX_PAD(0x65C, 0x2D8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA14__PATA_DATA_14		IOMUX_PAD(0x660, 0x2DC, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA14__GPIO2_14			IOMUX_PAD(0x660, 0x2DC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA14__ESDHC2_DAT6		IOMUX_PAD(0x660, 0x2DC, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA14__EMI_NANDF_D_14		IOMUX_PAD(0x660, 0x2DC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA14__ESDHC4_DAT2		IOMUX_PAD(0x660, 0x2DC, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA14__GPU3d_GPU_DEBUG_OUT_14	IOMUX_PAD(0x660, 0x2DC, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA14__IPU_DIAG_BUS_14		IOMUX_PAD(0x660, 0x2DC, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA15__PATA_DATA_15		IOMUX_PAD(0x664, 0x2E0, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA15__GPIO2_15			IOMUX_PAD(0x664, 0x2E0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA15__ESDHC2_DAT7		IOMUX_PAD(0x664, 0x2E0, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA15__EMI_NANDF_D_15		IOMUX_PAD(0x664, 0x2E0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA15__ESDHC4_DAT3		IOMUX_PAD(0x664, 0x2E0, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_PATA_DATA15__GPU3d_GPU_DEBUG_OUT_15	IOMUX_PAD(0x664, 0x2E0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_PATA_DATA15__IPU_DIAG_BUS_15		IOMUX_PAD(0x664, 0x2E0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA0__ESDHC1_DAT0			IOMUX_PAD(0x66C, 0x2E4, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD1_DATA0__GPIO1_16			IOMUX_PAD(0x66C, 0x2E4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA0__GPT_CAPIN1			IOMUX_PAD(0x66C, 0x2E4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA0__CSPI_MISO			IOMUX_PAD(0x66C, 0x2E4, 5, 0x784, 2, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA0__CCM_PLL3_BYP		IOMUX_PAD(0x66C, 0x2E4, 7, 0x778, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA1__ESDHC1_DAT1			IOMUX_PAD(0x670, 0x2E8, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD1_DATA1__GPIO1_17			IOMUX_PAD(0x670, 0x2E8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA1__GPT_CAPIN2			IOMUX_PAD(0x670, 0x2E8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA1__CSPI_SS0			IOMUX_PAD(0x670, 0x2E8, 5, 0x78C, 3, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA1__CCM_PLL4_BYP		IOMUX_PAD(0x670, 0x2E8, 7, 0x77C, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CMD__ESDHC1_CMD			IOMUX_PAD(0x674, 0x2EC, 0 | IOMUX_CONFIG_SION, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD1_CMD__GPIO1_18			IOMUX_PAD(0x674, 0x2EC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CMD__GPT_CMPOUT1			IOMUX_PAD(0x674, 0x2EC, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CMD__CSPI_MOSI			IOMUX_PAD(0x674, 0x2EC, 5, 0x788, 2, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CMD__CCM_PLL1_BYP			IOMUX_PAD(0x674, 0x2EC, 7, 0x770, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__ESDHC1_DAT2			IOMUX_PAD(0x678, 0x2F0, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__GPIO1_19			IOMUX_PAD(0x678, 0x2F0, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__GPT_CMPOUT2			IOMUX_PAD(0x678, 0x2F0, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__PWM2_PWMO			IOMUX_PAD(0x678, 0x2F0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__WDOG1_WDOG_B		IOMUX_PAD(0x678, 0x2F0, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__CSPI_SS1			IOMUX_PAD(0x678, 0x2F0, 5, 0x790, 2, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__WDOG1_WDOG_RST_B_DEB	IOMUX_PAD(0x678, 0x2F0, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA2__CCM_PLL2_BYP		IOMUX_PAD(0x678, 0x2F0, 7, 0x774, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CLK__ESDHC1_CLK			IOMUX_PAD(0x67C, 0x2F4, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD1_CLK__GPIO1_20			IOMUX_PAD(0x67C, 0x2F4, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CLK__OSC32k_32K_OUT		IOMUX_PAD(0x67C, 0x2F4, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CLK__GPT_CLKIN			IOMUX_PAD(0x67C, 0x2F4, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CLK__CSPI_SCLK			IOMUX_PAD(0x67C, 0x2F4, 5, 0x780, 2, NO_PAD_CTRL)
+#define MX53_PAD_SD1_CLK__SATA_PHY_DTB_0		IOMUX_PAD(0x67C, 0x2F4, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__ESDHC1_DAT3			IOMUX_PAD(0x680, 0x2F8, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__GPIO1_21			IOMUX_PAD(0x680, 0x2F8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__GPT_CMPOUT3			IOMUX_PAD(0x680, 0x2F8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__PWM1_PWMO			IOMUX_PAD(0x680, 0x2F8, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__WDOG2_WDOG_B		IOMUX_PAD(0x680, 0x2F8, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__CSPI_SS2			IOMUX_PAD(0x680, 0x2F8, 5, 0x794, 2, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__WDOG2_WDOG_RST_B_DEB	IOMUX_PAD(0x680, 0x2F8, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD1_DATA3__SATA_PHY_DTB_1		IOMUX_PAD(0x680, 0x2F8, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CLK__ESDHC2_CLK			IOMUX_PAD(0x688, 0x2FC, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD2_CLK__GPIO1_10			IOMUX_PAD(0x688, 0x2FC, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CLK__KPP_COL_5			IOMUX_PAD(0x688, 0x2FC, 2, 0x840, 2, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CLK__AUDMUX_AUD4_RXFS		IOMUX_PAD(0x688, 0x2FC, 3, 0x73C, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CLK__CSPI_SCLK			IOMUX_PAD(0x688, 0x2FC, 5, 0x780, 3, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CLK__SCC_RANDOM_V			IOMUX_PAD(0x688, 0x2FC, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CMD__ESDHC2_CMD			IOMUX_PAD(0x68C, 0x300, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD2_CMD__GPIO1_11			IOMUX_PAD(0x68C, 0x300, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CMD__KPP_ROW_5			IOMUX_PAD(0x68C, 0x300, 2, 0x84C, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CMD__AUDMUX_AUD4_RXC		IOMUX_PAD(0x68C, 0x300, 3, 0x738, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CMD__CSPI_MOSI			IOMUX_PAD(0x68C, 0x300, 5, 0x788, 3, NO_PAD_CTRL)
+#define MX53_PAD_SD2_CMD__SCC_RANDOM			IOMUX_PAD(0x68C, 0x300, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA3__ESDHC2_DAT3			IOMUX_PAD(0x690, 0x304, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD2_DATA3__GPIO1_12			IOMUX_PAD(0x690, 0x304, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA3__KPP_COL_6			IOMUX_PAD(0x690, 0x304, 2, 0x844, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC		IOMUX_PAD(0x690, 0x304, 3, 0x740, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA3__CSPI_SS2			IOMUX_PAD(0x690, 0x304, 5, 0x794, 3, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA3__SJC_DONE			IOMUX_PAD(0x690, 0x304, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA2__ESDHC2_DAT2			IOMUX_PAD(0x694, 0x308, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD2_DATA2__GPIO1_13			IOMUX_PAD(0x694, 0x308, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA2__KPP_ROW_6			IOMUX_PAD(0x694, 0x308, 2, 0x850, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD		IOMUX_PAD(0x694, 0x308, 3, 0x734, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA2__CSPI_SS1			IOMUX_PAD(0x694, 0x308, 5, 0x790, 3, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA2__SJC_FAIL			IOMUX_PAD(0x694, 0x308, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA1__ESDHC2_DAT1			IOMUX_PAD(0x698, 0x30C, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD2_DATA1__GPIO1_14			IOMUX_PAD(0x698, 0x30C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA1__KPP_COL_7			IOMUX_PAD(0x698, 0x30C, 2, 0x848, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS		IOMUX_PAD(0x698, 0x30C, 3, 0x744, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA1__CSPI_SS0			IOMUX_PAD(0x698, 0x30C, 5, 0x78C, 4, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA1__RTIC_SEC_VIO		IOMUX_PAD(0x698, 0x30C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA0__ESDHC2_DAT0			IOMUX_PAD(0x69C, 0x310, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
+#define MX53_PAD_SD2_DATA0__GPIO1_15			IOMUX_PAD(0x69C, 0x310, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA0__KPP_ROW_7			IOMUX_PAD(0x69C, 0x310, 2, 0x854, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD		IOMUX_PAD(0x69C, 0x310, 3, 0x730, 1, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA0__CSPI_MISO			IOMUX_PAD(0x69C, 0x310, 5, 0x784, 3, NO_PAD_CTRL)
+#define MX53_PAD_SD2_DATA0__RTIC_DONE_INT		IOMUX_PAD(0x69C, 0x310, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__CCM_CLKO			IOMUX_PAD(0x6A4, 0x314, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__GPIO1_0			IOMUX_PAD(0x6A4, 0x314, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__KPP_COL_5			IOMUX_PAD(0x6A4, 0x314, 2, 0x840, 3, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK		IOMUX_PAD(0x6A4, 0x314, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__EPIT1_EPITO			IOMUX_PAD(0x6A4, 0x314, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__SRTC_ALARM_DEB			IOMUX_PAD(0x6A4, 0x314, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__USBOH3_USBH1_PWR		IOMUX_PAD(0x6A4, 0x314, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_0__CSU_TD				IOMUX_PAD(0x6A4, 0x314, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__ESAI1_SCKR			IOMUX_PAD(0x6A8, 0x318, 0, 0x7DC, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__GPIO1_1			IOMUX_PAD(0x6A8, 0x318, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__KPP_ROW_5			IOMUX_PAD(0x6A8, 0x318, 2, 0x84C, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__CCM_SSI_EXT2_CLK		IOMUX_PAD(0x6A8, 0x318, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__PWM2_PWMO			IOMUX_PAD(0x6A8, 0x318, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__WDOG2_WDOG_B			IOMUX_PAD(0x6A8, 0x318, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__ESDHC1_CD			IOMUX_PAD(0x6A8, 0x318, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_1__SRC_TESTER_ACK			IOMUX_PAD(0x6A8, 0x318, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__ESAI1_FSR			IOMUX_PAD(0x6AC, 0x31C, 0, 0x7CC, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__GPIO1_9			IOMUX_PAD(0x6AC, 0x31C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__KPP_COL_6			IOMUX_PAD(0x6AC, 0x31C, 2, 0x844, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__CCM_REF_EN_B			IOMUX_PAD(0x6AC, 0x31C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__PWM1_PWMO			IOMUX_PAD(0x6AC, 0x31C, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__WDOG1_WDOG_B			IOMUX_PAD(0x6AC, 0x31C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__ESDHC1_WP			IOMUX_PAD(0x6AC, 0x31C, 6, 0x7FC, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_9__SCC_FAIL_STATE			IOMUX_PAD(0x6AC, 0x31C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__ESAI1_HCKR			IOMUX_PAD(0x6B0, 0x320, 0, 0x7D4, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__GPIO1_3			IOMUX_PAD(0x6B0, 0x320, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__I2C3_SCL			IOMUX_PAD(0x6B0, 0x320, 2 | IOMUX_CONFIG_SION, 0x824, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__DPLLIP1_TOG_EN			IOMUX_PAD(0x6B0, 0x320, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__CCM_CLKO2			IOMUX_PAD(0x6B0, 0x320, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__OBSERVE_MUX_OBSRV_INT_OUT0	IOMUX_PAD(0x6B0, 0x320, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__USBOH3_USBH1_OC		IOMUX_PAD(0x6B0, 0x320, 6, 0x8A0, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_3__MLB_MLBCLK			IOMUX_PAD(0x6B0, 0x320, 7, 0x858, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__ESAI1_SCKT			IOMUX_PAD(0x6B4, 0x324, 0, 0x7E0, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__GPIO1_6			IOMUX_PAD(0x6B4, 0x324, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__I2C3_SDA			IOMUX_PAD(0x6B4, 0x324, 2 | IOMUX_CONFIG_SION, 0x828, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__CCM_CCM_OUT_0			IOMUX_PAD(0x6B4, 0x324, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__CSU_CSU_INT_DEB		IOMUX_PAD(0x6B4, 0x324, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1	IOMUX_PAD(0x6B4, 0x324, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__ESDHC2_LCTL			IOMUX_PAD(0x6B4, 0x324, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_6__MLB_MLBSIG			IOMUX_PAD(0x6B4, 0x324, 7, 0x860, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__ESAI1_FST			IOMUX_PAD(0x6B8, 0x328, 0, 0x7D0, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__GPIO1_2			IOMUX_PAD(0x6B8, 0x328, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__KPP_ROW_6			IOMUX_PAD(0x6B8, 0x328, 2, 0x850, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__CCM_CCM_OUT_1			IOMUX_PAD(0x6B8, 0x328, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0		IOMUX_PAD(0x6B8, 0x328, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__OBSERVE_MUX_OBSRV_INT_OUT2	IOMUX_PAD(0x6B8, 0x328, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__ESDHC2_WP			IOMUX_PAD(0x6B8, 0x328, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_2__MLB_MLBDAT			IOMUX_PAD(0x6B8, 0x328, 7, 0x85C, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__ESAI1_HCKT			IOMUX_PAD(0x6BC, 0x32C, 0, 0x7D8, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__GPIO1_4			IOMUX_PAD(0x6BC, 0x32C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__KPP_COL_7			IOMUX_PAD(0x6BC, 0x32C, 2, 0x848, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__CCM_CCM_OUT_2			IOMUX_PAD(0x6BC, 0x32C, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1		IOMUX_PAD(0x6BC, 0x32C, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__OBSERVE_MUX_OBSRV_INT_OUT3	IOMUX_PAD(0x6BC, 0x32C, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__ESDHC2_CD			IOMUX_PAD(0x6BC, 0x32C, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_4__SCC_SEC_STATE			IOMUX_PAD(0x6BC, 0x32C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__ESAI1_TX2_RX3			IOMUX_PAD(0x6C0, 0x330, 0, 0x7EC, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__GPIO1_5			IOMUX_PAD(0x6C0, 0x330, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__KPP_ROW_7			IOMUX_PAD(0x6C0, 0x330, 2, 0x854, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__CCM_CLKO			IOMUX_PAD(0x6C0, 0x330, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2		IOMUX_PAD(0x6C0, 0x330, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__OBSERVE_MUX_OBSRV_INT_OUT4	IOMUX_PAD(0x6C0, 0x330, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__I2C3_SCL			IOMUX_PAD(0x6C0, 0x330, 6 | IOMUX_CONFIG_SION, 0x824, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_5__CCM_PLL1_BYP			IOMUX_PAD(0x6C0, 0x330, 7, 0x770, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_7__ESAI1_TX4_RX1			IOMUX_PAD(0x6C4, 0x334, 0, 0x7F4, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_7__GPIO1_7			IOMUX_PAD(0x6C4, 0x334, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_7__EPIT1_EPITO			IOMUX_PAD(0x6C4, 0x334, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_7__CAN1_TXCAN			IOMUX_PAD(0x6C4, 0x334, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_7__UART2_TXD_MUX			IOMUX_PAD(0x6C4, 0x334, 4, __NA_, 0, MX53_UART_PAD_CTRL)
+#define MX53_PAD_GPIO_7__FIRI_RXD			IOMUX_PAD(0x6C4, 0x334, 5, 0x80C, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_7__SPDIF_PLOCK			IOMUX_PAD(0x6C4, 0x334, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_7__CCM_PLL2_BYP			IOMUX_PAD(0x6C4, 0x334, 7, 0x774, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_8__ESAI1_TX5_RX0			IOMUX_PAD(0x6C8, 0x338, 0, 0x7F8, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_8__GPIO1_8			IOMUX_PAD(0x6C8, 0x338, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_8__EPIT2_EPITO			IOMUX_PAD(0x6C8, 0x338, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_8__CAN1_RXCAN			IOMUX_PAD(0x6C8, 0x338, 3, 0x760, 3, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_8__UART2_RXD_MUX			IOMUX_PAD(0x6C8, 0x338, 4, 0x880, 5, MX53_UART_PAD_CTRL)
+#define MX53_PAD_GPIO_8__FIRI_TXD			IOMUX_PAD(0x6C8, 0x338, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_8__SPDIF_SRCLK			IOMUX_PAD(0x6C8, 0x338, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_8__CCM_PLL3_BYP			IOMUX_PAD(0x6C8, 0x338, 7, 0x778, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_16__ESAI1_TX3_RX2			IOMUX_PAD(0x6CC, 0x33C, 0, 0x7F0, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_16__GPIO7_11			IOMUX_PAD(0x6CC, 0x33C, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_16__TZIC_PWRFAIL_INT		IOMUX_PAD(0x6CC, 0x33C, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_16__RTC_CE_RTC_EXT_TRIG1		IOMUX_PAD(0x6CC, 0x33C, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_16__SPDIF_IN1			IOMUX_PAD(0x6CC, 0x33C, 5, 0x870, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_16__I2C3_SDA			IOMUX_PAD(0x6CC, 0x33C, 6 | IOMUX_CONFIG_SION, 0x828, 2, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_16__SJC_DE_B			IOMUX_PAD(0x6CC, 0x33C, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__ESAI1_TX0			IOMUX_PAD(0x6D0, 0x340, 0, 0x7E4, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__GPIO7_12			IOMUX_PAD(0x6D0, 0x340, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__SDMA_EXT_EVENT_0		IOMUX_PAD(0x6D0, 0x340, 2, 0x868, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__GPC_PMIC_RDY			IOMUX_PAD(0x6D0, 0x340, 3, 0x810, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__RTC_CE_RTC_FSV_TRIG		IOMUX_PAD(0x6D0, 0x340, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__SPDIF_OUT1			IOMUX_PAD(0x6D0, 0x340, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__IPU_SNOOP2			IOMUX_PAD(0x6D0, 0x340, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_17__SJC_JTAG_ACT			IOMUX_PAD(0x6D0, 0x340, 7, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__ESAI1_TX1			IOMUX_PAD(0x6D4, 0x344, 0, 0x7E8, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__GPIO7_13			IOMUX_PAD(0x6D4, 0x344, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__SDMA_EXT_EVENT_1		IOMUX_PAD(0x6D4, 0x344, 2, 0x86C, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__OWIRE_LINE			IOMUX_PAD(0x6D4, 0x344, 3, 0x864, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__RTC_CE_RTC_ALARM2_TRIG	IOMUX_PAD(0x6D4, 0x344, 4, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__CCM_ASRC_EXT_CLK		IOMUX_PAD(0x6D4, 0x344, 5, 0x768, 1, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__ESDHC1_LCTL			IOMUX_PAD(0x6D4, 0x344, 6, __NA_, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_18__SRC_SYSTEM_RST		IOMUX_PAD(0x6D4, 0x344, 7, __NA_, 0, NO_PAD_CTRL)
 
 #endif	/* __MACH_IOMUX_MX53_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/iomux-v3.h b/arch/arm/plat-mxc/include/mach/iomux-v3.h
index ebbce33..2fa3b54 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-v3.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-v3.h
@@ -80,6 +80,7 @@ typedef u64 iomux_v3_cfg_t;
 		((iomux_v3_cfg_t)(_sel_input_ofs) << MUX_SEL_INPUT_OFS_SHIFT) | \
 		((iomux_v3_cfg_t)(_sel_input) << MUX_SEL_INPUT_SHIFT))
 
+#define NEW_PAD_CTRL(cfg, pad)	(((cfg) & ~MUX_PAD_CTRL_MASK) | MUX_PAD_CTRL(pad))
 /*
  * Use to set PAD control
  */
@@ -89,11 +90,11 @@ typedef u64 iomux_v3_cfg_t;
 #define PAD_CTL_HYS			(1 << 8)
 
 #define PAD_CTL_PKE			(1 << 7)
-#define PAD_CTL_PUE			(1 << 6)
-#define PAD_CTL_PUS_100K_DOWN		(0 << 4)
-#define PAD_CTL_PUS_47K_UP		(1 << 4)
-#define PAD_CTL_PUS_100K_UP		(2 << 4)
-#define PAD_CTL_PUS_22K_UP		(3 << 4)
+#define PAD_CTL_PUE			(1 << 6 | PAD_CTL_PKE)
+#define PAD_CTL_PUS_100K_DOWN		(0 << 4 | PAD_CTL_PUE)
+#define PAD_CTL_PUS_47K_UP		(1 << 4 | PAD_CTL_PUE)
+#define PAD_CTL_PUS_100K_UP		(2 << 4 | PAD_CTL_PUE)
+#define PAD_CTL_PUS_22K_UP		(3 << 4 | PAD_CTL_PUE)
 
 #define PAD_CTL_ODE			(1 << 3)
 
diff --git a/arch/arm/plat-mxc/include/mach/irqs.h b/arch/arm/plat-mxc/include/mach/irqs.h
index 00e812b..fd9efb0 100644
--- a/arch/arm/plat-mxc/include/mach/irqs.h
+++ b/arch/arm/plat-mxc/include/mach/irqs.h
@@ -14,9 +14,15 @@
 #include <asm-generic/gpio.h>
 
 /*
- * SoCs with TZIC interrupt controller have 128 IRQs, those with AVIC have 64
+ * SoCs with GIC interrupt controller have 160 IRQs, those with TZIC
+ * have 128 IRQs, and those with AVIC have 64.
+ *
+ * To support single image, the biggest number should be defined on
+ * top of the list.
  */
-#ifdef CONFIG_MXC_TZIC
+#if defined CONFIG_ARM_GIC
+#define MXC_INTERNAL_IRQS	160
+#elif defined CONFIG_MXC_TZIC
 #define MXC_INTERNAL_IRQS	128
 #else
 #define MXC_INTERNAL_IRQS	64
diff --git a/arch/arm/plat-mxc/include/mach/mx25.h b/arch/arm/plat-mxc/include/mach/mx25.h
index 087cd7a..ccebf5b 100644
--- a/arch/arm/plat-mxc/include/mach/mx25.h
+++ b/arch/arm/plat-mxc/include/mach/mx25.h
@@ -41,6 +41,7 @@
 #define MX25_SSI2_BASE_ADDR		0x50014000
 #define MX25_SSI1_BASE_ADDR		0x50034000
 #define MX25_NFC_BASE_ADDR		0xbb000000
+#define MX25_IIM_BASE_ADDR		0x53ff0000
 #define MX25_DRYICE_BASE_ADDR		0x53ffc000
 #define MX25_ESDHC1_BASE_ADDR		0x53fb4000
 #define MX25_ESDHC2_BASE_ADDR		0x53fb8000
@@ -104,4 +105,8 @@
 #define MX25_DMA_REQ_SSI1_RX0	28
 #define MX25_DMA_REQ_SSI1_TX0	29
 
+#ifndef __ASSEMBLY__
+extern int mx25_revision(void);
+#endif
+
 #endif /* ifndef __MACH_MX25_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx27.h b/arch/arm/plat-mxc/include/mach/mx27.h
index 1dc1c52..6265357 100644
--- a/arch/arm/plat-mxc/include/mach/mx27.h
+++ b/arch/arm/plat-mxc/include/mach/mx27.h
@@ -24,10 +24,6 @@
 #ifndef __MACH_MX27_H__
 #define __MACH_MX27_H__
 
-#ifndef __ASSEMBLER__
-#include <linux/io.h>
-#endif
-
 #define MX27_AIPI_BASE_ADDR		0x10000000
 #define MX27_AIPI_SIZE			SZ_1M
 #define MX27_DMA_BASE_ADDR			(MX27_AIPI_BASE_ADDR + 0x01000)
@@ -131,16 +127,6 @@
 #define MX27_IO_P2V(x)			IMX_IO_P2V(x)
 #define MX27_IO_ADDRESS(x)		IOMEM(MX27_IO_P2V(x))
 
-#ifndef __ASSEMBLER__
-static inline void mx27_setup_weimcs(size_t cs,
-		unsigned upper, unsigned lower, unsigned addional)
-{
-	__raw_writel(upper, MX27_IO_ADDRESS(MX27_WEIM_CSCRxU(cs)));
-	__raw_writel(lower, MX27_IO_ADDRESS(MX27_WEIM_CSCRxL(cs)));
-	__raw_writel(addional, MX27_IO_ADDRESS(MX27_WEIM_CSCRxA(cs)));
-}
-#endif
-
 /* fixed interrupt numbers */
 #define MX27_INT_I2C2		1
 #define MX27_INT_GPT6		2
diff --git a/arch/arm/plat-mxc/include/mach/mx31.h b/arch/arm/plat-mxc/include/mach/mx31.h
index 79e7fc0..e27619e 100644
--- a/arch/arm/plat-mxc/include/mach/mx31.h
+++ b/arch/arm/plat-mxc/include/mach/mx31.h
@@ -1,10 +1,6 @@
 #ifndef __MACH_MX31_H__
 #define __MACH_MX31_H__
 
-#ifndef __ASSEMBLER__
-#include <linux/io.h>
-#endif
-
 /*
  * IRAM
  */
@@ -122,16 +118,6 @@
 #define MX31_IO_P2V(x)			IMX_IO_P2V(x)
 #define MX31_IO_ADDRESS(x)		IOMEM(MX31_IO_P2V(x))
 
-#ifndef __ASSEMBLER__
-static inline void mx31_setup_weimcs(size_t cs,
-		unsigned upper, unsigned lower, unsigned addional)
-{
-	__raw_writel(upper, MX31_IO_ADDRESS(MX31_WEIM_CSCRxU(cs)));
-	__raw_writel(lower, MX31_IO_ADDRESS(MX31_WEIM_CSCRxL(cs)));
-	__raw_writel(addional, MX31_IO_ADDRESS(MX31_WEIM_CSCRxA(cs)));
-}
-#endif
-
 #define MX31_INT_I2C3		3
 #define MX31_INT_I2C2		4
 #define MX31_INT_MPEG4_ENCODER	5
diff --git a/arch/arm/plat-mxc/include/mach/mx35.h b/arch/arm/plat-mxc/include/mach/mx35.h
index d13dbfe..80965a9 100644
--- a/arch/arm/plat-mxc/include/mach/mx35.h
+++ b/arch/arm/plat-mxc/include/mach/mx35.h
@@ -36,7 +36,7 @@
 #define MX35_UART3_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x0c000)
 #define MX35_CSPI2_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x10000)
 #define MX35_SSI2_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x14000)
-#define MX35_ATA_DMA_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x20000)
+#define MX35_ATA_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x20000)
 #define MX35_MSHC1_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x24000)
 #define MX35_FEC_BASE_ADDR		0x50038000
 #define MX35_SPBA_CTRL_BASE_ADDR		(MX35_SPBA0_BASE_ADDR + 0x3c000)
diff --git a/arch/arm/plat-mxc/include/mach/mx3x.h b/arch/arm/plat-mxc/include/mach/mx3x.h
index 388a407..30dbf42 100644
--- a/arch/arm/plat-mxc/include/mach/mx3x.h
+++ b/arch/arm/plat-mxc/include/mach/mx3x.h
@@ -187,22 +187,8 @@
 /* Mandatory defines used globally */
 
 #if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
-
-extern unsigned int mx31_cpu_rev;
-extern void mx31_read_cpu_rev(void);
-
-static inline int mx31_revision(void)
-{
-	return mx31_cpu_rev;
-}
-
-extern unsigned int mx35_cpu_rev;
-extern void mx35_read_cpu_rev(void);
-
-static inline int mx35_revision(void)
-{
-	return mx35_cpu_rev;
-}
+extern int mx35_revision(void);
+extern int mx31_revision(void);
 #endif
 
 #endif /* ifndef __MACH_MX3x_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx51.h b/arch/arm/plat-mxc/include/mach/mx51.h
index dede19a..cdf07c6 100644
--- a/arch/arm/plat-mxc/include/mach/mx51.h
+++ b/arch/arm/plat-mxc/include/mach/mx51.h
@@ -18,18 +18,6 @@
 #define MX51_GPU_CTRL_BASE_ADDR		0x30000000
 #define MX51_IPU_CTRL_BASE_ADDR		0x40000000
 
-#define MX51_DEBUG_BASE_ADDR		0x60000000
-#define MX51_DEBUG_SIZE			SZ_1M
-
-#define MX51_ETB_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x01000)
-#define MX51_ETM_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x02000)
-#define MX51_TPIU_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x03000)
-#define MX51_CTI0_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x04000)
-#define MX51_CTI1_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x05000)
-#define MX51_CTI2_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x06000)
-#define MX51_CTI3_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x07000)
-#define MX51_CORTEX_DBG_BASE_ADDR	(MX51_DEBUG_BASE_ADDR + 0x08000)
-
 /*
  * SPBA global module enabled #0
  */
@@ -55,7 +43,10 @@
 #define MX51_AIPS1_BASE_ADDR		0x73f00000
 #define MX51_AIPS1_SIZE			SZ_1M
 
-#define MX51_OTG_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x80000)
+#define MX51_USB_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x80000)
+#define MX51_USB_OTG_BASE_ADDR		(MX51_USB_BASE_ADDR + 0x0000)
+#define MX51_USB_HS1_BASE_ADDR		(MX51_USB_BASE_ADDR + 0x0200)
+#define MX51_USB_HS2_BASE_ADDR		(MX51_USB_BASE_ADDR + 0x0400)
 #define MX51_GPIO1_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x84000)
 #define MX51_GPIO2_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x88000)
 #define MX51_GPIO3_BASE_ADDR		(MX51_AIPS1_BASE_ADDR + 0x8c000)
@@ -132,6 +123,7 @@
 
 #define MX51_GPU2D_BASE_ADDR		0xd0000000
 #define MX51_TZIC_BASE_ADDR		0xe0000000
+#define MX51_TZIC_SIZE			SZ_16K
 
 #define MX51_IO_P2V(x)			IMX_IO_P2V(x)
 #define MX51_IO_ADDRESS(x)		IOMEM(MX51_IO_P2V(x))
@@ -240,117 +232,114 @@
 /*
  * Interrupt numbers
  */
-#define MX51_MXC_INT_BASE		0
-#define MX51_MXC_INT_RESV0		0
+#define MX51_INT_BASE			0
+#define MX51_INT_RESV0			0
 #define MX51_INT_ESDHC1			1
 #define MX51_INT_ESDHC2			2
 #define MX51_INT_ESDHC3			3
 #define MX51_INT_ESDHC4			4
-#define MX51_MXC_INT_RESV5		5
+#define MX51_INT_RESV5			5
 #define MX51_INT_SDMA			6
-#define MX51_MXC_INT_IOMUX		7
+#define MX51_INT_IOMUX			7
 #define MX51_INT_NFC			8
-#define MX51_MXC_INT_VPU		9
+#define MX51_INT_VPU			9
 #define MX51_INT_IPU_ERR		10
 #define MX51_INT_IPU_SYN		11
-#define MX51_MXC_INT_GPU		12
-#define MX51_MXC_INT_RESV13		13
-#define MX51_MXC_INT_USB_H1		14
-#define MX51_MXC_INT_EMI		15
-#define MX51_MXC_INT_USB_H2		16
-#define MX51_MXC_INT_USB_H3		17
-#define MX51_MXC_INT_USB_OTG		18
-#define MX51_MXC_INT_SAHARA_H0		19
-#define MX51_MXC_INT_SAHARA_H1		20
-#define MX51_MXC_INT_SCC_SMN		21
-#define MX51_MXC_INT_SCC_STZ		22
-#define MX51_MXC_INT_SCC_SCM		23
-#define MX51_MXC_INT_SRTC_NTZ		24
-#define MX51_MXC_INT_SRTC_TZ		25
-#define MX51_MXC_INT_RTIC		26
-#define MX51_MXC_INT_CSU		27
-#define MX51_MXC_INT_SLIM_B		28
+#define MX51_INT_GPU			12
+#define MX51_INT_RESV13			13
+#define MX51_INT_USB_HS1		14
+#define MX51_INT_EMI			15
+#define MX51_INT_USB_HS2		16
+#define MX51_INT_USB_HS3		17
+#define MX51_INT_USB_OTG		18
+#define MX51_INT_SAHARA_H0		19
+#define MX51_INT_SAHARA_H1		20
+#define MX51_INT_SCC_SMN		21
+#define MX51_INT_SCC_STZ		22
+#define MX51_INT_SCC_SCM		23
+#define MX51_INT_SRTC_NTZ		24
+#define MX51_INT_SRTC_TZ		25
+#define MX51_INT_RTIC			26
+#define MX51_INT_CSU			27
+#define MX51_INT_SLIM_B			28
 #define MX51_INT_SSI1			29
 #define MX51_INT_SSI2			30
 #define MX51_INT_UART1			31
 #define MX51_INT_UART2			32
 #define MX51_INT_UART3			33
-#define MX51_MXC_INT_RESV34		34
-#define MX51_MXC_INT_RESV35		35
+#define MX51_INT_RESV34			34
+#define MX51_INT_RESV35			35
 #define MX51_INT_ECSPI1			36
 #define MX51_INT_ECSPI2			37
 #define MX51_INT_CSPI			38
-#define MX51_MXC_INT_GPT		39
-#define MX51_MXC_INT_EPIT1		40
-#define MX51_MXC_INT_EPIT2		41
-#define MX51_MXC_INT_GPIO1_INT7		42
-#define MX51_MXC_INT_GPIO1_INT6		43
-#define MX51_MXC_INT_GPIO1_INT5		44
-#define MX51_MXC_INT_GPIO1_INT4		45
-#define MX51_MXC_INT_GPIO1_INT3		46
-#define MX51_MXC_INT_GPIO1_INT2		47
-#define MX51_MXC_INT_GPIO1_INT1		48
-#define MX51_MXC_INT_GPIO1_INT0		49
-#define MX51_MXC_INT_GPIO1_LOW		50
-#define MX51_MXC_INT_GPIO1_HIGH		51
-#define MX51_MXC_INT_GPIO2_LOW		52
-#define MX51_MXC_INT_GPIO2_HIGH		53
-#define MX51_MXC_INT_GPIO3_LOW		54
-#define MX51_MXC_INT_GPIO3_HIGH		55
-#define MX51_MXC_INT_GPIO4_LOW		56
-#define MX51_MXC_INT_GPIO4_HIGH		57
-#define MX51_MXC_INT_WDOG1		58
-#define MX51_MXC_INT_WDOG2		59
+#define MX51_INT_GPT			39
+#define MX51_INT_EPIT1			40
+#define MX51_INT_EPIT2			41
+#define MX51_INT_GPIO1_INT7		42
+#define MX51_INT_GPIO1_INT6		43
+#define MX51_INT_GPIO1_INT5		44
+#define MX51_INT_GPIO1_INT4		45
+#define MX51_INT_GPIO1_INT3		46
+#define MX51_INT_GPIO1_INT2		47
+#define MX51_INT_GPIO1_INT1		48
+#define MX51_INT_GPIO1_INT0		49
+#define MX51_INT_GPIO1_LOW		50
+#define MX51_INT_GPIO1_HIGH		51
+#define MX51_INT_GPIO2_LOW		52
+#define MX51_INT_GPIO2_HIGH		53
+#define MX51_INT_GPIO3_LOW		54
+#define MX51_INT_GPIO3_HIGH		55
+#define MX51_INT_GPIO4_LOW		56
+#define MX51_INT_GPIO4_HIGH		57
+#define MX51_INT_WDOG1			58
+#define MX51_INT_WDOG2			59
 #define MX51_INT_KPP			60
 #define MX51_INT_PWM1			61
 #define MX51_INT_I2C1			62
 #define MX51_INT_I2C2			63
-#define MX51_MXC_INT_HS_I2C		64
-#define MX51_MXC_INT_RESV65		65
-#define MX51_MXC_INT_RESV66		66
-#define MX51_MXC_INT_SIM_IPB		67
-#define MX51_MXC_INT_SIM_DAT		68
-#define MX51_MXC_INT_IIM		69
-#define MX51_MXC_INT_ATA		70
-#define MX51_MXC_INT_CCM1		71
-#define MX51_MXC_INT_CCM2		72
-#define MX51_MXC_INT_GPC1		73
-#define MX51_MXC_INT_GPC2		74
-#define MX51_MXC_INT_SRC		75
-#define MX51_MXC_INT_NM			76
-#define MX51_MXC_INT_PMU		77
-#define MX51_MXC_INT_CTI_IRQ		78
-#define MX51_MXC_INT_CTI1_TG0		79
-#define MX51_MXC_INT_CTI1_TG1		80
-#define MX51_MXC_INT_MCG_ERR		81
-#define MX51_MXC_INT_MCG_TMR		82
-#define MX51_MXC_INT_MCG_FUNC		83
-#define MX51_MXC_INT_GPU2_IRQ		84
-#define MX51_MXC_INT_GPU2_BUSY		85
-#define MX51_MXC_INT_RESV86		86
+#define MX51_INT_HS_I2C			64
+#define MX51_INT_RESV65			65
+#define MX51_INT_RESV66			66
+#define MX51_INT_SIM_IPB		67
+#define MX51_INT_SIM_DAT		68
+#define MX51_INT_IIM			69
+#define MX51_INT_ATA			70
+#define MX51_INT_CCM1			71
+#define MX51_INT_CCM2			72
+#define MX51_INT_GPC1				73
+#define MX51_INT_GPC2			74
+#define MX51_INT_SRC			75
+#define MX51_INT_NM			76
+#define MX51_INT_PMU			77
+#define MX51_INT_CTI_IRQ		78
+#define MX51_INT_CTI1_TG0		79
+#define MX51_INT_CTI1_TG1		80
+#define MX51_INT_MCG_ERR		81
+#define MX51_INT_MCG_TMR		82
+#define MX51_INT_MCG_FUNC		83
+#define MX51_INT_GPU2_IRQ		84
+#define MX51_INT_GPU2_BUSY		85
+#define MX51_INT_RESV86			86
 #define MX51_INT_FEC			87
-#define MX51_MXC_INT_OWIRE		88
-#define MX51_MXC_INT_CTI1_TG2		89
-#define MX51_MXC_INT_SJC		90
-#define MX51_MXC_INT_SPDIF		91
-#define MX51_MXC_INT_TVE		92
-#define MX51_MXC_INT_FIRI		93
+#define MX51_INT_OWIRE			88
+#define MX51_INT_CTI1_TG2		89
+#define MX51_INT_SJC			90
+#define MX51_INT_SPDIF			91
+#define MX51_INT_TVE			92
+#define MX51_INT_FIRI			93
 #define MX51_INT_PWM2			94
-#define MX51_MXC_INT_SLIM_EXP		95
+#define MX51_INT_SLIM_EXP		95
 #define MX51_INT_SSI3			96
-#define MX51_MXC_INT_EMI_BOOT		97
-#define MX51_MXC_INT_CTI1_TG3		98
-#define MX51_MXC_INT_SMC_RX		99
-#define MX51_MXC_INT_VPU_IDLE		100
-#define MX51_MXC_INT_EMI_NFC		101
-#define MX51_MXC_INT_GPU_IDLE		102
+#define MX51_INT_EMI_BOOT		97
+#define MX51_INT_CTI1_TG3		98
+#define MX51_INT_SMC_RX			99
+#define MX51_INT_VPU_IDLE		100
+#define MX51_INT_EMI_NFC		101
+#define MX51_INT_GPU_IDLE		102
 
 #if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
 extern int mx51_revision(void);
 extern void mx51_display_revision(void);
 #endif
 
-/* tape-out 1 defines */
-#define MX51_TZIC_BASE_ADDR_TO1		0x8fffc000
-
 #endif	/* ifndef __MACH_MX51_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx53.h b/arch/arm/plat-mxc/include/mach/mx53.h
index 5e3c323..a37e8c3 100644
--- a/arch/arm/plat-mxc/include/mach/mx53.h
+++ b/arch/arm/plat-mxc/include/mach/mx53.h
@@ -9,6 +9,7 @@
 
 /* TZIC */
 #define MX53_TZIC_BASE_ADDR		0x0FFFC000
+#define MX53_TZIC_SIZE			SZ_16K
 
 /*
  * AHCI SATA
diff --git a/arch/arm/plat-mxc/include/mach/mx6q.h b/arch/arm/plat-mxc/include/mach/mx6q.h
new file mode 100644
index 0000000..254a561
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/mx6q.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef __MACH_MX6Q_H__
+#define __MACH_MX6Q_H__
+
+#define MX6Q_IO_P2V(x)			IMX_IO_P2V(x)
+#define MX6Q_IO_ADDRESS(x)		IOMEM(MX6Q_IO_P2V(x))
+
+/*
+ * The following are the blocks that need to be statically mapped.
+ * For other blocks, the base address really should be retrieved from
+ * device tree.
+ */
+#define MX6Q_SCU_BASE_ADDR		0x00a00000
+#define MX6Q_SCU_SIZE			0x1000
+#define MX6Q_CCM_BASE_ADDR		0x020c4000
+#define MX6Q_CCM_SIZE			0x4000
+#define MX6Q_ANATOP_BASE_ADDR		0x020c8000
+#define MX6Q_ANATOP_SIZE		0x1000
+#define MX6Q_UART4_BASE_ADDR		0x021f0000
+#define MX6Q_UART4_SIZE			0x4000
+
+#endif	/* __MACH_MX6Q_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mxc.h b/arch/arm/plat-mxc/include/mach/mxc.h
index 0987923..00a7819 100644
--- a/arch/arm/plat-mxc/include/mach/mxc.h
+++ b/arch/arm/plat-mxc/include/mach/mxc.h
@@ -183,13 +183,6 @@ struct cpu_op {
 };
 
 int tzic_enable_wake(int is_idle);
-enum mxc_cpu_pwr_mode {
-	WAIT_CLOCKED,		/* wfi only */
-	WAIT_UNCLOCKED,		/* WAIT */
-	WAIT_UNCLOCKED_POWER_OFF,	/* WAIT + SRPG */
-	STOP_POWER_ON,		/* just STOP */
-	STOP_POWER_OFF,		/* STOP + SRPG */
-};
 
 extern struct cpu_op *(*get_cpu_op)(int *op);
 #endif
diff --git a/arch/arm/plat-mxc/include/mach/system.h b/arch/arm/plat-mxc/include/mach/system.h
index 51f02a9..cf88b35 100644
--- a/arch/arm/plat-mxc/include/mach/system.h
+++ b/arch/arm/plat-mxc/include/mach/system.h
@@ -17,41 +17,12 @@
 #ifndef __ASM_ARCH_MXC_SYSTEM_H__
 #define __ASM_ARCH_MXC_SYSTEM_H__
 
-#include <mach/hardware.h>
-#include <mach/common.h>
-
-extern void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode);
+extern void (*imx_idle)(void);
 
 static inline void arch_idle(void)
 {
-	/* fix i.MX31 errata TLSbo65953 and i.MX35 errata ENGcm09472 */
-	if (cpu_is_mx31() || cpu_is_mx35()) {
-		unsigned long reg = 0;
-		__asm__ __volatile__(
-			/* disable I and D cache */
-			"mrc p15, 0, %0, c1, c0, 0\n"
-			"bic %0, %0, #0x00001000\n"
-			"bic %0, %0, #0x00000004\n"
-			"mcr p15, 0, %0, c1, c0, 0\n"
-			/* invalidate I cache */
-			"mov %0, #0\n"
-			"mcr p15, 0, %0, c7, c5, 0\n"
-			/* clear and invalidate D cache */
-			"mov %0, #0\n"
-			"mcr p15, 0, %0, c7, c14, 0\n"
-			/* WFI */
-			"mov %0, #0\n"
-			"mcr p15, 0, %0, c7, c0, 4\n"
-			"nop\n" "nop\n" "nop\n" "nop\n"
-			"nop\n" "nop\n" "nop\n"
-			/* enable I and D cache */
-			"mrc p15, 0, %0, c1, c0, 0\n"
-			"orr %0, %0, #0x00001000\n"
-			"orr %0, %0, #0x00000004\n"
-			"mcr p15, 0, %0, c1, c0, 0\n"
-			: "=r" (reg));
-	} else if (cpu_is_mx51())
-		mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
+	if (imx_idle != NULL)
+		(imx_idle)();
 	else
 		cpu_do_idle();
 }
diff --git a/arch/arm/plat-mxc/irq-common.c b/arch/arm/plat-mxc/irq-common.c
index 96953e2..b6e1145 100644
--- a/arch/arm/plat-mxc/irq-common.c
+++ b/arch/arm/plat-mxc/irq-common.c
@@ -23,17 +23,17 @@
 
 int imx_irq_set_priority(unsigned char irq, unsigned char prio)
 {
-	struct mxc_irq_chip *chip;
-	struct irq_chip *base;
+	struct irq_chip_generic *gc;
+	struct mxc_extra_irq *exirq;
 	int ret;
 
 	ret = -ENOSYS;
 
-	base = irq_get_chip(irq);
-	if (base) {
-		chip = container_of(base, struct mxc_irq_chip, base);
-		if (chip->set_priority)
-			ret = chip->set_priority(irq, prio);
+	gc = irq_get_chip_data(irq);
+	if (gc && gc->private) {
+		exirq = gc->private;
+		if (exirq->set_priority)
+			ret = exirq->set_priority(irq, prio);
 	}
 
 	return ret;
@@ -43,15 +43,16 @@ EXPORT_SYMBOL(imx_irq_set_priority);
 int mxc_set_irq_fiq(unsigned int irq, unsigned int type)
 {
 	struct irq_chip_generic *gc;
-	int (*set_irq_fiq)(unsigned int, unsigned int);
+	struct mxc_extra_irq *exirq;
 	int ret;
 
 	ret = -ENOSYS;
 
 	gc = irq_get_chip_data(irq);
 	if (gc && gc->private) {
-		set_irq_fiq = gc->private;
-		ret = set_irq_fiq(irq, type);
+		exirq = gc->private;
+		if (exirq->set_irq_fiq)
+			ret = exirq->set_irq_fiq(irq, type);
 	}
 
 	return ret;
diff --git a/arch/arm/plat-mxc/irq-common.h b/arch/arm/plat-mxc/irq-common.h
index 7203543..6ccb3a1 100644
--- a/arch/arm/plat-mxc/irq-common.h
+++ b/arch/arm/plat-mxc/irq-common.h
@@ -19,9 +19,8 @@
 #ifndef __PLAT_MXC_IRQ_COMMON_H__
 #define __PLAT_MXC_IRQ_COMMON_H__
 
-struct mxc_irq_chip
+struct mxc_extra_irq
 {
-	struct irq_chip	base;
 	int (*set_priority)(unsigned char irq, unsigned char prio);
 	int (*set_irq_fiq)(unsigned int irq, unsigned int type);
 };
diff --git a/arch/arm/plat-mxc/pwm.c b/arch/arm/plat-mxc/pwm.c
index 761c3c9..42d74ea 100644
--- a/arch/arm/plat-mxc/pwm.c
+++ b/arch/arm/plat-mxc/pwm.c
@@ -57,7 +57,7 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
 	if (pwm == NULL || period_ns == 0 || duty_ns > period_ns)
 		return -EINVAL;
 
-	if (cpu_is_mx27() || cpu_is_mx3() || cpu_is_mx25() || cpu_is_mx51()) {
+	if (!(cpu_is_mx1() || cpu_is_mx21())) {
 		unsigned long long c;
 		unsigned long period_cycles, duty_cycles, prescale;
 		u32 cr;
diff --git a/arch/arm/plat-mxc/system.c b/arch/arm/plat-mxc/system.c
index 8024f2a..9dad8dc 100644
--- a/arch/arm/plat-mxc/system.c
+++ b/arch/arm/plat-mxc/system.c
@@ -28,6 +28,9 @@
 #include <asm/system.h>
 #include <asm/mach-types.h>
 
+void (*imx_idle)(void) = NULL;
+void __iomem *(*imx_ioremap)(unsigned long, size_t, unsigned int) = NULL;
+
 static void __iomem *wdog_base;
 
 /*
diff --git a/arch/arm/plat-mxc/tzic.c b/arch/arm/plat-mxc/tzic.c
index f257fcc..e993a18 100644
--- a/arch/arm/plat-mxc/tzic.c
+++ b/arch/arm/plat-mxc/tzic.c
@@ -42,7 +42,7 @@
 #define TZIC_SRCCLAR0	0x0280	/* Source Clear Register 0 */
 #define TZIC_PRIORITY0	0x0400	/* Priority Register 0 */
 #define TZIC_PND0	0x0D00	/* Pending Register 0 */
-#define TZIC_HIPND0	0x0D80	/* High Priority Pending Register */
+#define TZIC_HIPND(i)	(0x0D80+ ((i) << 2))	/* High Priority Pending Register */
 #define TZIC_WAKEUP0(i)	(0x0E00 + ((i) << 2))	/* Wakeup Config Register */
 #define TZIC_SWINT	0x0F00	/* Software Interrupt Rigger Register */
 #define TZIC_ID0	0x0FD0	/* Indentification Register 0 */
@@ -74,6 +74,12 @@ static int tzic_set_irq_fiq(unsigned int irq, unsigned int type)
 
 static unsigned int *wakeup_intr[4];
 
+static struct mxc_extra_irq tzic_extra_irq = {
+#ifdef CONFIG_FIQ
+	.set_irq_fiq = tzic_set_irq_fiq,
+#endif
+};
+
 static __init void tzic_init_gc(unsigned int irq_start)
 {
 	struct irq_chip_generic *gc;
@@ -82,7 +88,7 @@ static __init void tzic_init_gc(unsigned int irq_start)
 
 	gc = irq_alloc_generic_chip("tzic", 1, irq_start, tzic_base,
 				    handle_level_irq);
-	gc->private = tzic_set_irq_fiq;
+	gc->private = &tzic_extra_irq;
 	gc->wake_enabled = IRQ_MSK(32);
 	wakeup_intr[idx] = &gc->wake_active;
 
@@ -96,6 +102,28 @@ static __init void tzic_init_gc(unsigned int irq_start)
 	irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0);
 }
 
+asmlinkage void __exception_irq_entry tzic_handle_irq(struct pt_regs *regs)
+{
+	u32 stat;
+	int i, irqofs, handled;
+
+	do {
+		handled = 0;
+
+		for (i = 0; i < 4; i++) {
+			stat = __raw_readl(tzic_base + TZIC_HIPND(i)) &
+				__raw_readl(tzic_base + TZIC_INTSEC0(i));
+
+			while (stat) {
+				handled = 1;
+				irqofs = fls(stat) - 1;
+				handle_IRQ(irqofs + i * 32, regs);
+				stat &= ~(1 << irqofs);
+			}
+		}
+	} while (handled);
+}
+
 /*
  * This function initializes the TZIC hardware and disables all the
  * interrupts. It registers the interrupt enable and disable functions
diff --git a/arch/arm/plat-nomadik/Kconfig b/arch/arm/plat-nomadik/Kconfig
index ce65901..bca4914 100644
--- a/arch/arm/plat-nomadik/Kconfig
+++ b/arch/arm/plat-nomadik/Kconfig
@@ -15,10 +15,16 @@ if PLAT_NOMADIK
 
 config HAS_MTU
 	bool
-	select HAVE_SCHED_CLOCK
 	help
 	  Support for Multi Timer Unit. MTU provides access
 	  to multiple interrupt generating programmable
 	  32-bit free running decrementing counters.
 
+config NOMADIK_MTU_SCHED_CLOCK
+	bool
+	depends on HAS_MTU
+	select HAVE_SCHED_CLOCK
+	help
+	  Use the Multi Timer Unit as the sched_clock.
+
 endif
diff --git a/arch/arm/plat-nomadik/include/plat/mtu.h b/arch/arm/plat-nomadik/include/plat/mtu.h
index 65704a3..6508e76 100644
--- a/arch/arm/plat-nomadik/include/plat/mtu.h
+++ b/arch/arm/plat-nomadik/include/plat/mtu.h
@@ -1,54 +1,11 @@
 #ifndef __PLAT_MTU_H
 #define __PLAT_MTU_H
 
-/*
- * Guaranteed runtime conversion range in seconds for
- * the clocksource and clockevent.
- */
-#define MTU_MIN_RANGE 4
-
 /* should be set by the platform code */
 extern void __iomem *mtu_base;
 
-/*
- * The MTU device hosts four different counters, with 4 set of
- * registers. These are register names.
- */
-
-#define MTU_IMSC	0x00	/* Interrupt mask set/clear */
-#define MTU_RIS		0x04	/* Raw interrupt status */
-#define MTU_MIS		0x08	/* Masked interrupt status */
-#define MTU_ICR		0x0C	/* Interrupt clear register */
-
-/* per-timer registers take 0..3 as argument */
-#define MTU_LR(x)	(0x10 + 0x10 * (x) + 0x00)	/* Load value */
-#define MTU_VAL(x)	(0x10 + 0x10 * (x) + 0x04)	/* Current value */
-#define MTU_CR(x)	(0x10 + 0x10 * (x) + 0x08)	/* Control reg */
-#define MTU_BGLR(x)	(0x10 + 0x10 * (x) + 0x0c)	/* At next overflow */
-
-/* bits for the control register */
-#define MTU_CRn_ENA		0x80
-#define MTU_CRn_PERIODIC	0x40	/* if 0 = free-running */
-#define MTU_CRn_PRESCALE_MASK	0x0c
-#define MTU_CRn_PRESCALE_1		0x00
-#define MTU_CRn_PRESCALE_16		0x04
-#define MTU_CRn_PRESCALE_256		0x08
-#define MTU_CRn_32BITS		0x02
-#define MTU_CRn_ONESHOT		0x01	/* if 0 = wraps reloading from BGLR*/
-
-/* Other registers are usual amba/primecell registers, currently not used */
-#define MTU_ITCR	0xff0
-#define MTU_ITOP	0xff4
-
-#define MTU_PERIPH_ID0	0xfe0
-#define MTU_PERIPH_ID1	0xfe4
-#define MTU_PERIPH_ID2	0xfe8
-#define MTU_PERIPH_ID3	0xfeC
-
-#define MTU_PCELL0	0xff0
-#define MTU_PCELL1	0xff4
-#define MTU_PCELL2	0xff8
-#define MTU_PCELL3	0xffC
+void nmdk_clkevt_reset(void);
+void nmdk_clksrc_reset(void);
 
 #endif /* __PLAT_MTU_H */
 
diff --git a/arch/arm/plat-nomadik/include/plat/pincfg.h b/arch/arm/plat-nomadik/include/plat/pincfg.h
index 05a3936..22cb97d 100644
--- a/arch/arm/plat-nomadik/include/plat/pincfg.h
+++ b/arch/arm/plat-nomadik/include/plat/pincfg.h
@@ -37,7 +37,6 @@
  *		     SLPM value = same as normal
  *
  * PIN_CFG	   - default config with alternate function
- * PIN_CFG_PULL	   - default config with alternate function and pull up/down
  */
 
 typedef unsigned long pin_cfg_t;
@@ -133,10 +132,6 @@ typedef unsigned long pin_cfg_t;
 	(PIN_CFG_DEFAULT |\
 	 (PIN_NUM(num) | PIN_##alt | PIN_OUTPUT_##val))
 
-#define PIN_CFG_PULL(num, alt, pull)	\
-	((PIN_CFG_DEFAULT & ~PIN_PULL_MASK) |\
-	 (PIN_NUM(num) | PIN_##alt | PIN_PULL_##pull))
-
 extern int nmk_config_pin(pin_cfg_t cfg, bool sleep);
 extern int nmk_config_pins(pin_cfg_t *cfgs, int num);
 extern int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num);
diff --git a/arch/arm/plat-nomadik/timer.c b/arch/arm/plat-nomadik/timer.c
index ef74e15..30b6433 100644
--- a/arch/arm/plat-nomadik/timer.c
+++ b/arch/arm/plat-nomadik/timer.c
@@ -21,10 +21,59 @@
 #include <asm/mach/time.h>
 #include <asm/sched_clock.h>
 
-#include <plat/mtu.h>
+/*
+ * Guaranteed runtime conversion range in seconds for
+ * the clocksource and clockevent.
+ */
+#define MTU_MIN_RANGE 4
+
+/*
+ * The MTU device hosts four different counters, with 4 set of
+ * registers. These are register names.
+ */
+
+#define MTU_IMSC	0x00	/* Interrupt mask set/clear */
+#define MTU_RIS		0x04	/* Raw interrupt status */
+#define MTU_MIS		0x08	/* Masked interrupt status */
+#define MTU_ICR		0x0C	/* Interrupt clear register */
+
+/* per-timer registers take 0..3 as argument */
+#define MTU_LR(x)	(0x10 + 0x10 * (x) + 0x00)	/* Load value */
+#define MTU_VAL(x)	(0x10 + 0x10 * (x) + 0x04)	/* Current value */
+#define MTU_CR(x)	(0x10 + 0x10 * (x) + 0x08)	/* Control reg */
+#define MTU_BGLR(x)	(0x10 + 0x10 * (x) + 0x0c)	/* At next overflow */
+
+/* bits for the control register */
+#define MTU_CRn_ENA		0x80
+#define MTU_CRn_PERIODIC	0x40	/* if 0 = free-running */
+#define MTU_CRn_PRESCALE_MASK	0x0c
+#define MTU_CRn_PRESCALE_1		0x00
+#define MTU_CRn_PRESCALE_16		0x04
+#define MTU_CRn_PRESCALE_256		0x08
+#define MTU_CRn_32BITS		0x02
+#define MTU_CRn_ONESHOT		0x01	/* if 0 = wraps reloading from BGLR*/
+
+/* Other registers are usual amba/primecell registers, currently not used */
+#define MTU_ITCR	0xff0
+#define MTU_ITOP	0xff4
+
+#define MTU_PERIPH_ID0	0xfe0
+#define MTU_PERIPH_ID1	0xfe4
+#define MTU_PERIPH_ID2	0xfe8
+#define MTU_PERIPH_ID3	0xfeC
+
+#define MTU_PCELL0	0xff0
+#define MTU_PCELL1	0xff4
+#define MTU_PCELL2	0xff8
+#define MTU_PCELL3	0xffC
+
+static bool clkevt_periodic;
+static u32 clk_prescale;
+static u32 nmdk_cycle;		/* write-once */
 
 void __iomem *mtu_base; /* Assigned by machine code */
 
+#ifdef CONFIG_NOMADIK_MTU_SCHED_CLOCK
 /*
  * Override the global weak sched_clock symbol with this
  * local implementation which uses the clocksource to get some
@@ -48,32 +97,56 @@ static void notrace nomadik_update_sched_clock(void)
 	u32 cyc = -readl(mtu_base + MTU_VAL(0));
 	update_sched_clock(&cd, cyc, (u32)~0);
 }
+#endif
 
 /* Clockevent device: use one-shot mode */
+static int nmdk_clkevt_next(unsigned long evt, struct clock_event_device *ev)
+{
+	writel(1 << 1, mtu_base + MTU_IMSC);
+	writel(evt, mtu_base + MTU_LR(1));
+	/* Load highest value, enable device, enable interrupts */
+	writel(MTU_CRn_ONESHOT | clk_prescale |
+	       MTU_CRn_32BITS | MTU_CRn_ENA,
+	       mtu_base + MTU_CR(1));
+
+	return 0;
+}
+
+void nmdk_clkevt_reset(void)
+{
+	if (clkevt_periodic) {
+
+		/* Timer: configure load and background-load, and fire it up */
+		writel(nmdk_cycle, mtu_base + MTU_LR(1));
+		writel(nmdk_cycle, mtu_base + MTU_BGLR(1));
+
+		writel(MTU_CRn_PERIODIC | clk_prescale |
+		       MTU_CRn_32BITS | MTU_CRn_ENA,
+		       mtu_base + MTU_CR(1));
+		writel(1 << 1, mtu_base + MTU_IMSC);
+	} else {
+		/* Generate an interrupt to start the clockevent again */
+		(void) nmdk_clkevt_next(nmdk_cycle, NULL);
+	}
+}
+
 static void nmdk_clkevt_mode(enum clock_event_mode mode,
 			     struct clock_event_device *dev)
 {
-	u32 cr;
 
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
-		pr_err("%s: periodic mode not supported\n", __func__);
+		clkevt_periodic = true;
+		nmdk_clkevt_reset();
 		break;
 	case CLOCK_EVT_MODE_ONESHOT:
-		/* Load highest value, enable device, enable interrupts */
-		cr = readl(mtu_base + MTU_CR(1));
-		writel(0, mtu_base + MTU_LR(1));
-		writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(1));
-		writel(1 << 1, mtu_base + MTU_IMSC);
+		clkevt_periodic = false;
 		break;
 	case CLOCK_EVT_MODE_SHUTDOWN:
 	case CLOCK_EVT_MODE_UNUSED:
-		/* disable irq */
 		writel(0, mtu_base + MTU_IMSC);
 		/* disable timer */
-		cr = readl(mtu_base + MTU_CR(1));
-		cr &= ~MTU_CRn_ENA;
-		writel(cr, mtu_base + MTU_CR(1));
+		writel(0, mtu_base + MTU_CR(1));
 		/* load some high default value */
 		writel(0xffffffff, mtu_base + MTU_LR(1));
 		break;
@@ -82,16 +155,9 @@ static void nmdk_clkevt_mode(enum clock_event_mode mode,
 	}
 }
 
-static int nmdk_clkevt_next(unsigned long evt, struct clock_event_device *ev)
-{
-	/* writing the value has immediate effect */
-	writel(evt, mtu_base + MTU_LR(1));
-	return 0;
-}
-
 static struct clock_event_device nmdk_clkevt = {
 	.name		= "mtu_1",
-	.features	= CLOCK_EVT_FEAT_ONESHOT,
+	.features	= CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
 	.rating		= 200,
 	.set_mode	= nmdk_clkevt_mode,
 	.set_next_event	= nmdk_clkevt_next,
@@ -116,11 +182,23 @@ static struct irqaction nmdk_timer_irq = {
 	.dev_id		= &nmdk_clkevt,
 };
 
+void nmdk_clksrc_reset(void)
+{
+	/* Disable */
+	writel(0, mtu_base + MTU_CR(0));
+
+	/* ClockSource: configure load and background-load, and fire it up */
+	writel(nmdk_cycle, mtu_base + MTU_LR(0));
+	writel(nmdk_cycle, mtu_base + MTU_BGLR(0));
+
+	writel(clk_prescale | MTU_CRn_32BITS | MTU_CRn_ENA,
+	       mtu_base + MTU_CR(0));
+}
+
 void __init nmdk_timer_init(void)
 {
 	unsigned long rate;
 	struct clk *clk0;
-	u32 cr = MTU_CRn_32BITS;
 
 	clk0 = clk_get_sys("mtu0", NULL);
 	BUG_ON(IS_ERR(clk0));
@@ -138,30 +216,28 @@ void __init nmdk_timer_init(void)
 	rate = clk_get_rate(clk0);
 	if (rate > 32000000) {
 		rate /= 16;
-		cr |= MTU_CRn_PRESCALE_16;
+		clk_prescale = MTU_CRn_PRESCALE_16;
 	} else {
-		cr |= MTU_CRn_PRESCALE_1;
+		clk_prescale = MTU_CRn_PRESCALE_1;
 	}
 
+	nmdk_cycle = (rate + HZ/2) / HZ;
+
+
 	/* Timer 0 is the free running clocksource */
-	writel(cr, mtu_base + MTU_CR(0));
-	writel(0, mtu_base + MTU_LR(0));
-	writel(0, mtu_base + MTU_BGLR(0));
-	writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0));
+	nmdk_clksrc_reset();
 
 	if (clocksource_mmio_init(mtu_base + MTU_VAL(0), "mtu_0",
 			rate, 200, 32, clocksource_mmio_readl_down))
 		pr_err("timer: failed to initialize clock source %s\n",
 		       "mtu_0");
-
+#ifdef CONFIG_NOMADIK_MTU_SCHED_CLOCK
 	init_sched_clock(&cd, nomadik_update_sched_clock, 32, rate);
-
+#endif
 	/* Timer 1 is used for events */
 
 	clockevents_calc_mult_shift(&nmdk_clkevt, rate, MTU_MIN_RANGE);
 
-	writel(cr | MTU_CRn_ONESHOT, mtu_base + MTU_CR(1)); /* off, currently */
-
 	nmdk_clkevt.max_delta_ns =
 		clockevent_delta2ns(0xffffffff, &nmdk_clkevt);
 	nmdk_clkevt.min_delta_ns =
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c
index c46c47a..1971932 100644
--- a/arch/arm/plat-omap/devices.c
+++ b/arch/arm/plat-omap/devices.c
@@ -25,54 +25,8 @@
 #include <plat/board.h>
 #include <plat/mmc.h>
 #include <plat/menelaus.h>
-#include <plat/mcbsp.h>
 #include <plat/omap44xx.h>
 
-/*-------------------------------------------------------------------------*/
-
-#if defined(CONFIG_OMAP_MCBSP) || defined(CONFIG_OMAP_MCBSP_MODULE)
-
-static struct platform_device **omap_mcbsp_devices;
-
-void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
-			struct omap_mcbsp_platform_data *config, int size)
-{
-	int i;
-
-	omap_mcbsp_devices = kzalloc(size * sizeof(struct platform_device *),
-				     GFP_KERNEL);
-	if (!omap_mcbsp_devices) {
-		printk(KERN_ERR "Could not register McBSP devices\n");
-		return;
-	}
-
-	for (i = 0; i < size; i++) {
-		struct platform_device *new_mcbsp;
-		int ret;
-
-		new_mcbsp = platform_device_alloc("omap-mcbsp", i + 1);
-		if (!new_mcbsp)
-			continue;
-		platform_device_add_resources(new_mcbsp, &res[i * res_count],
-					res_count);
-		new_mcbsp->dev.platform_data = &config[i];
-		ret = platform_device_add(new_mcbsp);
-		if (ret) {
-			platform_device_put(new_mcbsp);
-			continue;
-		}
-		omap_mcbsp_devices[i] = new_mcbsp;
-	}
-}
-
-#else
-void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
-			struct omap_mcbsp_platform_data *config, int size)
-{  }
-#endif
-
-/*-------------------------------------------------------------------------*/
-
 #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \
 	defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
 
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 75a847d..2def4e1 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -3,6 +3,12 @@
  *
  * OMAP Dual-Mode Timers
  *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ * Tarun Kanti DebBarma <tarun.kanti@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * dmtimer adaptation to platform_driver.
+ *
  * Copyright (C) 2005 Nokia Corporation
  * OMAP2 support by Juha Yrjola
  * API improvements and OMAP2 clock framework support by Timo Teras
@@ -29,168 +35,80 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/errno.h>
-#include <linux/list.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
 #include <linux/io.h>
-#include <linux/module.h>
-#include <mach/hardware.h>
-#include <plat/dmtimer.h>
-#include <mach/irqs.h>
-
-static int dm_timer_count;
-
-#ifdef CONFIG_ARCH_OMAP1
-static struct omap_dm_timer omap1_dm_timers[] = {
-	{ .phys_base = 0xfffb1400, .irq = INT_1610_GPTIMER1 },
-	{ .phys_base = 0xfffb1c00, .irq = INT_1610_GPTIMER2 },
-	{ .phys_base = 0xfffb2400, .irq = INT_1610_GPTIMER3 },
-	{ .phys_base = 0xfffb2c00, .irq = INT_1610_GPTIMER4 },
-	{ .phys_base = 0xfffb3400, .irq = INT_1610_GPTIMER5 },
-	{ .phys_base = 0xfffb3c00, .irq = INT_1610_GPTIMER6 },
-	{ .phys_base = 0xfffb7400, .irq = INT_1610_GPTIMER7 },
-	{ .phys_base = 0xfffbd400, .irq = INT_1610_GPTIMER8 },
-};
-
-static const int omap1_dm_timer_count = ARRAY_SIZE(omap1_dm_timers);
-
-#else
-#define omap1_dm_timers			NULL
-#define omap1_dm_timer_count		0
-#endif	/* CONFIG_ARCH_OMAP1 */
-
-#ifdef CONFIG_ARCH_OMAP2
-static struct omap_dm_timer omap2_dm_timers[] = {
-	{ .phys_base = 0x48028000, .irq = INT_24XX_GPTIMER1 },
-	{ .phys_base = 0x4802a000, .irq = INT_24XX_GPTIMER2 },
-	{ .phys_base = 0x48078000, .irq = INT_24XX_GPTIMER3 },
-	{ .phys_base = 0x4807a000, .irq = INT_24XX_GPTIMER4 },
-	{ .phys_base = 0x4807c000, .irq = INT_24XX_GPTIMER5 },
-	{ .phys_base = 0x4807e000, .irq = INT_24XX_GPTIMER6 },
-	{ .phys_base = 0x48080000, .irq = INT_24XX_GPTIMER7 },
-	{ .phys_base = 0x48082000, .irq = INT_24XX_GPTIMER8 },
-	{ .phys_base = 0x48084000, .irq = INT_24XX_GPTIMER9 },
-	{ .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 },
-	{ .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 },
-	{ .phys_base = 0x4808a000, .irq = INT_24XX_GPTIMER12 },
-};
-
-static const char *omap2_dm_source_names[] __initdata = {
-	"sys_ck",
-	"func_32k_ck",
-	"alt_ck",
-	NULL
-};
-
-static struct clk *omap2_dm_source_clocks[3];
-static const int omap2_dm_timer_count = ARRAY_SIZE(omap2_dm_timers);
-
-#else
-#define omap2_dm_timers			NULL
-#define omap2_dm_timer_count		0
-#define omap2_dm_source_names		NULL
-#define omap2_dm_source_clocks		NULL
-#endif	/* CONFIG_ARCH_OMAP2 */
-
-#ifdef CONFIG_ARCH_OMAP3
-static struct omap_dm_timer omap3_dm_timers[] = {
-	{ .phys_base = 0x48318000, .irq = INT_24XX_GPTIMER1 },
-	{ .phys_base = 0x49032000, .irq = INT_24XX_GPTIMER2 },
-	{ .phys_base = 0x49034000, .irq = INT_24XX_GPTIMER3 },
-	{ .phys_base = 0x49036000, .irq = INT_24XX_GPTIMER4 },
-	{ .phys_base = 0x49038000, .irq = INT_24XX_GPTIMER5 },
-	{ .phys_base = 0x4903A000, .irq = INT_24XX_GPTIMER6 },
-	{ .phys_base = 0x4903C000, .irq = INT_24XX_GPTIMER7 },
-	{ .phys_base = 0x4903E000, .irq = INT_24XX_GPTIMER8 },
-	{ .phys_base = 0x49040000, .irq = INT_24XX_GPTIMER9 },
-	{ .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 },
-	{ .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 },
-	{ .phys_base = 0x48304000, .irq = INT_34XX_GPT12_IRQ },
-};
-
-static const char *omap3_dm_source_names[] __initdata = {
-	"sys_ck",
-	"omap_32k_fck",
-	NULL
-};
-
-static struct clk *omap3_dm_source_clocks[2];
-static const int omap3_dm_timer_count = ARRAY_SIZE(omap3_dm_timers);
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/pm_runtime.h>
 
-#else
-#define omap3_dm_timers			NULL
-#define omap3_dm_timer_count		0
-#define omap3_dm_source_names		NULL
-#define omap3_dm_source_clocks		NULL
-#endif	/* CONFIG_ARCH_OMAP3 */
-
-#ifdef CONFIG_ARCH_OMAP4
-static struct omap_dm_timer omap4_dm_timers[] = {
-	{ .phys_base = 0x4a318000, .irq = OMAP44XX_IRQ_GPT1 },
-	{ .phys_base = 0x48032000, .irq = OMAP44XX_IRQ_GPT2 },
-	{ .phys_base = 0x48034000, .irq = OMAP44XX_IRQ_GPT3 },
-	{ .phys_base = 0x48036000, .irq = OMAP44XX_IRQ_GPT4 },
-	{ .phys_base = 0x40138000, .irq = OMAP44XX_IRQ_GPT5 },
-	{ .phys_base = 0x4013a000, .irq = OMAP44XX_IRQ_GPT6 },
-	{ .phys_base = 0x4013a000, .irq = OMAP44XX_IRQ_GPT7 },
-	{ .phys_base = 0x4013e000, .irq = OMAP44XX_IRQ_GPT8 },
-	{ .phys_base = 0x4803e000, .irq = OMAP44XX_IRQ_GPT9 },
-	{ .phys_base = 0x48086000, .irq = OMAP44XX_IRQ_GPT10 },
-	{ .phys_base = 0x48088000, .irq = OMAP44XX_IRQ_GPT11 },
-	{ .phys_base = 0x4a320000, .irq = OMAP44XX_IRQ_GPT12 },
-};
-static const char *omap4_dm_source_names[] __initdata = {
-	"sys_clkin_ck",
-	"sys_32k_ck",
-	NULL
-};
-static struct clk *omap4_dm_source_clocks[2];
-static const int omap4_dm_timer_count = ARRAY_SIZE(omap4_dm_timers);
-
-#else
-#define omap4_dm_timers			NULL
-#define omap4_dm_timer_count		0
-#define omap4_dm_source_names		NULL
-#define omap4_dm_source_clocks		NULL
-#endif	/* CONFIG_ARCH_OMAP4 */
-
-static struct omap_dm_timer *dm_timers;
-static const char **dm_source_names;
-static struct clk **dm_source_clocks;
+#include <plat/dmtimer.h>
 
-static spinlock_t dm_timer_lock;
+static LIST_HEAD(omap_timer_list);
+static DEFINE_SPINLOCK(dm_timer_lock);
 
-/*
- * Reads timer registers in posted and non-posted mode. The posted mode bit
- * is encoded in reg. Note that in posted mode write pending bit must be
- * checked. Otherwise a read of a non completed write will produce an error.
+/**
+ * omap_dm_timer_read_reg - read timer registers in posted and non-posted mode
+ * @timer:      timer pointer over which read operation to perform
+ * @reg:        lowest byte holds the register offset
+ *
+ * The posted mode bit is encoded in reg. Note that in posted mode write
+ * pending bit must be checked. Otherwise a read of a non completed write
+ * will produce an error.
  */
 static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
 {
-	return __omap_dm_timer_read(timer->io_base, reg, timer->posted);
+	WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
+	return __omap_dm_timer_read(timer, reg, timer->posted);
 }
 
-/*
- * Writes timer registers in posted and non-posted mode. The posted mode bit
- * is encoded in reg. Note that in posted mode the write pending bit must be
- * checked. Otherwise a write on a register which has a pending write will be
- * lost.
+/**
+ * omap_dm_timer_write_reg - write timer registers in posted and non-posted mode
+ * @timer:      timer pointer over which write operation is to perform
+ * @reg:        lowest byte holds the register offset
+ * @value:      data to write into the register
+ *
+ * The posted mode bit is encoded in reg. Note that in posted mode the write
+ * pending bit must be checked. Otherwise a write on a register which has a
+ * pending write will be lost.
  */
 static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
 						u32 value)
 {
-	__omap_dm_timer_write(timer->io_base, reg, value, timer->posted);
+	WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
+	__omap_dm_timer_write(timer, reg, value, timer->posted);
+}
+
+static void omap_timer_restore_context(struct omap_dm_timer *timer)
+{
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_OFFSET,
+				timer->context.tiocp_cfg);
+	if (timer->revision > 1)
+		__raw_writel(timer->context.tistat, timer->sys_stat);
+
+	__raw_writel(timer->context.tisr, timer->irq_stat);
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG,
+				timer->context.twer);
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG,
+				timer->context.tcrr);
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG,
+				timer->context.tldr);
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG,
+				timer->context.tmar);
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG,
+				timer->context.tsicr);
+	__raw_writel(timer->context.tier, timer->irq_ena);
+	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG,
+				timer->context.tclr);
 }
 
 static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
 {
 	int c;
 
+	if (!timer->sys_stat)
+		return;
+
 	c = 0;
-	while (!(omap_dm_timer_read_reg(timer, OMAP_TIMER_SYS_STAT_REG) & 1)) {
+	while (!(__raw_readl(timer->sys_stat) & 1)) {
 		c++;
 		if (c > 100000) {
 			printk(KERN_ERR "Timer failed to reset\n");
@@ -201,53 +119,65 @@ static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
 
 static void omap_dm_timer_reset(struct omap_dm_timer *timer)
 {
-	int autoidle = 0, wakeup = 0;
-
-	if (!cpu_class_is_omap2() || timer != &dm_timers[0]) {
+	omap_dm_timer_enable(timer);
+	if (timer->pdev->id != 1) {
 		omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
 		omap_dm_timer_wait_for_reset(timer);
 	}
-	omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
-
-	/* Enable autoidle on OMAP2+ */
-	if (cpu_class_is_omap2())
-		autoidle = 1;
-
-	/*
-	 * Enable wake-up on OMAP2 CPUs.
-	 */
-	if (cpu_class_is_omap2())
-		wakeup = 1;
 
-	__omap_dm_timer_reset(timer->io_base, autoidle, wakeup);
+	__omap_dm_timer_reset(timer, 0, 0);
+	omap_dm_timer_disable(timer);
 	timer->posted = 1;
 }
 
-void omap_dm_timer_prepare(struct omap_dm_timer *timer)
+int omap_dm_timer_prepare(struct omap_dm_timer *timer)
 {
-	omap_dm_timer_enable(timer);
-	omap_dm_timer_reset(timer);
+	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
+	int ret;
+
+	timer->fclk = clk_get(&timer->pdev->dev, "fck");
+	if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) {
+		timer->fclk = NULL;
+		dev_err(&timer->pdev->dev, ": No fclk handle.\n");
+		return -EINVAL;
+	}
+
+	if (pdata->needs_manual_reset)
+		omap_dm_timer_reset(timer);
+
+	ret = omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
+
+	timer->posted = 1;
+	return ret;
 }
 
 struct omap_dm_timer *omap_dm_timer_request(void)
 {
-	struct omap_dm_timer *timer = NULL;
+	struct omap_dm_timer *timer = NULL, *t;
 	unsigned long flags;
-	int i;
+	int ret = 0;
 
 	spin_lock_irqsave(&dm_timer_lock, flags);
-	for (i = 0; i < dm_timer_count; i++) {
-		if (dm_timers[i].reserved)
+	list_for_each_entry(t, &omap_timer_list, node) {
+		if (t->reserved)
 			continue;
 
-		timer = &dm_timers[i];
+		timer = t;
 		timer->reserved = 1;
 		break;
 	}
+
+	if (timer) {
+		ret = omap_dm_timer_prepare(timer);
+		if (ret) {
+			timer->reserved = 0;
+			timer = NULL;
+		}
+	}
 	spin_unlock_irqrestore(&dm_timer_lock, flags);
 
-	if (timer != NULL)
-		omap_dm_timer_prepare(timer);
+	if (!timer)
+		pr_debug("%s: timer request failed!\n", __func__);
 
 	return timer;
 }
@@ -255,74 +185,65 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_request);
 
 struct omap_dm_timer *omap_dm_timer_request_specific(int id)
 {
-	struct omap_dm_timer *timer;
+	struct omap_dm_timer *timer = NULL, *t;
 	unsigned long flags;
+	int ret = 0;
 
 	spin_lock_irqsave(&dm_timer_lock, flags);
-	if (id <= 0 || id > dm_timer_count || dm_timers[id-1].reserved) {
-		spin_unlock_irqrestore(&dm_timer_lock, flags);
-		printk("BUG: warning at %s:%d/%s(): unable to get timer %d\n",
-		       __FILE__, __LINE__, __func__, id);
-		dump_stack();
-		return NULL;
+	list_for_each_entry(t, &omap_timer_list, node) {
+		if (t->pdev->id == id && !t->reserved) {
+			timer = t;
+			timer->reserved = 1;
+			break;
+		}
 	}
 
-	timer = &dm_timers[id-1];
-	timer->reserved = 1;
+	if (timer) {
+		ret = omap_dm_timer_prepare(timer);
+		if (ret) {
+			timer->reserved = 0;
+			timer = NULL;
+		}
+	}
 	spin_unlock_irqrestore(&dm_timer_lock, flags);
 
-	omap_dm_timer_prepare(timer);
+	if (!timer)
+		pr_debug("%s: timer%d request failed!\n", __func__, id);
 
 	return timer;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
 
-void omap_dm_timer_free(struct omap_dm_timer *timer)
+int omap_dm_timer_free(struct omap_dm_timer *timer)
 {
-	omap_dm_timer_enable(timer);
-	omap_dm_timer_reset(timer);
-	omap_dm_timer_disable(timer);
+	if (unlikely(!timer))
+		return -EINVAL;
+
+	clk_put(timer->fclk);
 
 	WARN_ON(!timer->reserved);
 	timer->reserved = 0;
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_free);
 
 void omap_dm_timer_enable(struct omap_dm_timer *timer)
 {
-	if (timer->enabled)
-		return;
-
-#ifdef CONFIG_ARCH_OMAP2PLUS
-	if (cpu_class_is_omap2()) {
-		clk_enable(timer->fclk);
-		clk_enable(timer->iclk);
-	}
-#endif
-
-	timer->enabled = 1;
+	pm_runtime_get_sync(&timer->pdev->dev);
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
 
 void omap_dm_timer_disable(struct omap_dm_timer *timer)
 {
-	if (!timer->enabled)
-		return;
-
-#ifdef CONFIG_ARCH_OMAP2PLUS
-	if (cpu_class_is_omap2()) {
-		clk_disable(timer->iclk);
-		clk_disable(timer->fclk);
-	}
-#endif
-
-	timer->enabled = 0;
+	pm_runtime_put(&timer->pdev->dev);
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_disable);
 
 int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
 {
-	return timer->irq;
+	if (timer)
+		return timer->irq;
+	return -EINVAL;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
 
@@ -334,24 +255,29 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
  */
 __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
 {
-	int i;
+	int i = 0;
+	struct omap_dm_timer *timer = NULL;
+	unsigned long flags;
 
 	/* If ARMXOR cannot be idled this function call is unnecessary */
 	if (!(inputmask & (1 << 1)))
 		return inputmask;
 
 	/* If any active timer is using ARMXOR return modified mask */
-	for (i = 0; i < dm_timer_count; i++) {
+	spin_lock_irqsave(&dm_timer_lock, flags);
+	list_for_each_entry(timer, &omap_timer_list, node) {
 		u32 l;
 
-		l = omap_dm_timer_read_reg(&dm_timers[i], OMAP_TIMER_CTRL_REG);
+		l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 		if (l & OMAP_TIMER_CTRL_ST) {
 			if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)
 				inputmask &= ~(1 << 1);
 			else
 				inputmask &= ~(1 << 2);
 		}
+		i++;
 	}
+	spin_unlock_irqrestore(&dm_timer_lock, flags);
 
 	return inputmask;
 }
@@ -361,7 +287,9 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
 
 struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
 {
-	return timer->fclk;
+	if (timer)
+		return timer->fclk;
+	return NULL;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk);
 
@@ -375,70 +303,91 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
 
 #endif
 
-void omap_dm_timer_trigger(struct omap_dm_timer *timer)
+int omap_dm_timer_trigger(struct omap_dm_timer *timer)
 {
+	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
+		pr_err("%s: timer not available or enabled.\n", __func__);
+		return -EINVAL;
+	}
+
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_trigger);
 
-void omap_dm_timer_start(struct omap_dm_timer *timer)
+int omap_dm_timer_start(struct omap_dm_timer *timer)
 {
 	u32 l;
 
+	if (unlikely(!timer))
+		return -EINVAL;
+
+	omap_dm_timer_enable(timer);
+
+	if (timer->loses_context) {
+		u32 ctx_loss_cnt_after =
+			timer->get_context_loss_count(&timer->pdev->dev);
+		if (ctx_loss_cnt_after != timer->ctx_loss_count)
+			omap_timer_restore_context(timer);
+	}
+
 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 	if (!(l & OMAP_TIMER_CTRL_ST)) {
 		l |= OMAP_TIMER_CTRL_ST;
 		omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 	}
+
+	/* Save the context */
+	timer->context.tclr = l;
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_start);
 
-void omap_dm_timer_stop(struct omap_dm_timer *timer)
+int omap_dm_timer_stop(struct omap_dm_timer *timer)
 {
 	unsigned long rate = 0;
+	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
 
-#ifdef CONFIG_ARCH_OMAP2PLUS
-	rate = clk_get_rate(timer->fclk);
-#endif
+	if (unlikely(!timer))
+		return -EINVAL;
 
-	__omap_dm_timer_stop(timer->io_base, timer->posted, rate);
+	if (!pdata->needs_manual_reset)
+		rate = clk_get_rate(timer->fclk);
+
+	__omap_dm_timer_stop(timer, timer->posted, rate);
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
 
-#ifdef CONFIG_ARCH_OMAP1
-
 int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
 {
-	int n = (timer - dm_timers) << 1;
-	u32 l;
-
-	l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
-	l |= source << n;
-	omap_writel(l, MOD_CONF_CTRL_1);
+	int ret;
+	struct dmtimer_platform_data *pdata;
 
-	return 0;
-}
-EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
+	if (unlikely(!timer))
+		return -EINVAL;
 
-#else
+	pdata = timer->pdev->dev.platform_data;
 
-int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
-{
 	if (source < 0 || source >= 3)
 		return -EINVAL;
 
-	return __omap_dm_timer_set_source(timer->fclk,
-						dm_source_clocks[source]);
+	ret = pdata->set_timer_src(timer->pdev, source);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
 
-#endif
-
-void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
+int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
 			    unsigned int load)
 {
 	u32 l;
 
+	if (unlikely(!timer))
+		return -EINVAL;
+
+	omap_dm_timer_enable(timer);
 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 	if (autoreload)
 		l |= OMAP_TIMER_CTRL_AR;
@@ -448,15 +397,32 @@ void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
 
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
+	/* Save the context */
+	timer->context.tclr = l;
+	timer->context.tldr = load;
+	omap_dm_timer_disable(timer);
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_load);
 
 /* Optimized set_load which removes costly spin wait in timer_start */
-void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
+int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
                             unsigned int load)
 {
 	u32 l;
 
+	if (unlikely(!timer))
+		return -EINVAL;
+
+	omap_dm_timer_enable(timer);
+
+	if (timer->loses_context) {
+		u32 ctx_loss_cnt_after =
+			timer->get_context_loss_count(&timer->pdev->dev);
+		if (ctx_loss_cnt_after != timer->ctx_loss_count)
+			omap_timer_restore_context(timer);
+	}
+
 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 	if (autoreload) {
 		l |= OMAP_TIMER_CTRL_AR;
@@ -466,15 +432,25 @@ void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
 	}
 	l |= OMAP_TIMER_CTRL_ST;
 
-	__omap_dm_timer_load_start(timer->io_base, l, load, timer->posted);
+	__omap_dm_timer_load_start(timer, l, load, timer->posted);
+
+	/* Save the context */
+	timer->context.tclr = l;
+	timer->context.tldr = load;
+	timer->context.tcrr = load;
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
 
-void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
+int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
 			     unsigned int match)
 {
 	u32 l;
 
+	if (unlikely(!timer))
+		return -EINVAL;
+
+	omap_dm_timer_enable(timer);
 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 	if (enable)
 		l |= OMAP_TIMER_CTRL_CE;
@@ -482,14 +458,24 @@ void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
 		l &= ~OMAP_TIMER_CTRL_CE;
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
+
+	/* Save the context */
+	timer->context.tclr = l;
+	timer->context.tmar = match;
+	omap_dm_timer_disable(timer);
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_match);
 
-void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
+int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
 			   int toggle, int trigger)
 {
 	u32 l;
 
+	if (unlikely(!timer))
+		return -EINVAL;
+
+	omap_dm_timer_enable(timer);
 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 	l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
 	       OMAP_TIMER_CTRL_PT | (0x03 << 10));
@@ -499,13 +485,22 @@ void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
 		l |= OMAP_TIMER_CTRL_PT;
 	l |= trigger << 10;
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+
+	/* Save the context */
+	timer->context.tclr = l;
+	omap_dm_timer_disable(timer);
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm);
 
-void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
+int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
 {
 	u32 l;
 
+	if (unlikely(!timer))
+		return -EINVAL;
+
+	omap_dm_timer_enable(timer);
 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 	l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));
 	if (prescaler >= 0x00 && prescaler <= 0x07) {
@@ -513,13 +508,28 @@ void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
 		l |= prescaler << 2;
 	}
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+
+	/* Save the context */
+	timer->context.tclr = l;
+	omap_dm_timer_disable(timer);
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
 
-void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
+int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
 				  unsigned int value)
 {
-	__omap_dm_timer_int_enable(timer->io_base, value);
+	if (unlikely(!timer))
+		return -EINVAL;
+
+	omap_dm_timer_enable(timer);
+	__omap_dm_timer_int_enable(timer, value);
+
+	/* Save the context */
+	timer->context.tier = value;
+	timer->context.twer = value;
+	omap_dm_timer_disable(timer);
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
 
@@ -527,40 +537,61 @@ unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
 {
 	unsigned int l;
 
-	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
+	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
+		pr_err("%s: timer not available or enabled.\n", __func__);
+		return 0;
+	}
+
+	l = __raw_readl(timer->irq_stat);
 
 	return l;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
 
-void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
+int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
 {
-	__omap_dm_timer_write_status(timer->io_base, value);
+	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev)))
+		return -EINVAL;
+
+	__omap_dm_timer_write_status(timer, value);
+	/* Save the context */
+	timer->context.tisr = value;
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
 
 unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
 {
-	return __omap_dm_timer_read_counter(timer->io_base, timer->posted);
+	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
+		pr_err("%s: timer not iavailable or enabled.\n", __func__);
+		return 0;
+	}
+
+	return __omap_dm_timer_read_counter(timer, timer->posted);
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
 
-void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
+int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
 {
+	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
+		pr_err("%s: timer not available or enabled.\n", __func__);
+		return -EINVAL;
+	}
+
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
+
+	/* Save the context */
+	timer->context.tcrr = value;
+	return 0;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter);
 
 int omap_dm_timers_active(void)
 {
-	int i;
-
-	for (i = 0; i < dm_timer_count; i++) {
-		struct omap_dm_timer *timer;
-
-		timer = &dm_timers[i];
+	struct omap_dm_timer *timer;
 
-		if (!timer->enabled)
+	list_for_each_entry(timer, &omap_timer_list, node) {
+		if (!timer->reserved)
 			continue;
 
 		if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
@@ -572,69 +603,147 @@ int omap_dm_timers_active(void)
 }
 EXPORT_SYMBOL_GPL(omap_dm_timers_active);
 
-static int __init omap_dm_timer_init(void)
+/**
+ * omap_dm_timer_probe - probe function called for every registered device
+ * @pdev:	pointer to current timer platform device
+ *
+ * Called by driver framework at the end of device registration for all
+ * timer devices.
+ */
+static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
 {
+	int ret;
+	unsigned long flags;
 	struct omap_dm_timer *timer;
-	int i, map_size = SZ_8K;	/* Module 4KB + L4 4KB except on omap1 */
+	struct resource *mem, *irq, *ioarea;
+	struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
 
-	if (!(cpu_is_omap16xx() || cpu_class_is_omap2()))
+	if (!pdata) {
+		dev_err(&pdev->dev, "%s: no platform data.\n", __func__);
 		return -ENODEV;
+	}
 
-	spin_lock_init(&dm_timer_lock);
-
-	if (cpu_class_is_omap1()) {
-		dm_timers = omap1_dm_timers;
-		dm_timer_count = omap1_dm_timer_count;
-		map_size = SZ_2K;
-	} else if (cpu_is_omap24xx()) {
-		dm_timers = omap2_dm_timers;
-		dm_timer_count = omap2_dm_timer_count;
-		dm_source_names = omap2_dm_source_names;
-		dm_source_clocks = omap2_dm_source_clocks;
-	} else if (cpu_is_omap34xx()) {
-		dm_timers = omap3_dm_timers;
-		dm_timer_count = omap3_dm_timer_count;
-		dm_source_names = omap3_dm_source_names;
-		dm_source_clocks = omap3_dm_source_clocks;
-	} else if (cpu_is_omap44xx()) {
-		dm_timers = omap4_dm_timers;
-		dm_timer_count = omap4_dm_timer_count;
-		dm_source_names = omap4_dm_source_names;
-		dm_source_clocks = omap4_dm_source_clocks;
+	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (unlikely(!irq)) {
+		dev_err(&pdev->dev, "%s: no IRQ resource.\n", __func__);
+		return -ENODEV;
 	}
 
-	if (cpu_class_is_omap2())
-		for (i = 0; dm_source_names[i] != NULL; i++)
-			dm_source_clocks[i] = clk_get(NULL, dm_source_names[i]);
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (unlikely(!mem)) {
+		dev_err(&pdev->dev, "%s: no memory resource.\n", __func__);
+		return -ENODEV;
+	}
 
-	if (cpu_is_omap243x())
-		dm_timers[0].phys_base = 0x49018000;
+	ioarea = request_mem_region(mem->start, resource_size(mem),
+			pdev->name);
+	if (!ioarea) {
+		dev_err(&pdev->dev, "%s: region already claimed.\n", __func__);
+		return -EBUSY;
+	}
 
-	for (i = 0; i < dm_timer_count; i++) {
-		timer = &dm_timers[i];
+	timer = kzalloc(sizeof(struct omap_dm_timer), GFP_KERNEL);
+	if (!timer) {
+		dev_err(&pdev->dev, "%s: no memory for omap_dm_timer.\n",
+			__func__);
+		ret = -ENOMEM;
+		goto err_free_ioregion;
+	}
 
-		/* Static mapping, never released */
-		timer->io_base = ioremap(timer->phys_base, map_size);
-		BUG_ON(!timer->io_base);
+	timer->io_base = ioremap(mem->start, resource_size(mem));
+	if (!timer->io_base) {
+		dev_err(&pdev->dev, "%s: ioremap failed.\n", __func__);
+		ret = -ENOMEM;
+		goto err_free_mem;
+	}
 
-#ifdef CONFIG_ARCH_OMAP2PLUS
-		if (cpu_class_is_omap2()) {
-			char clk_name[16];
-			sprintf(clk_name, "gpt%d_ick", i + 1);
-			timer->iclk = clk_get(NULL, clk_name);
-			sprintf(clk_name, "gpt%d_fck", i + 1);
-			timer->fclk = clk_get(NULL, clk_name);
-		}
+	timer->id = pdev->id;
+	timer->irq = irq->start;
+	timer->reserved = pdata->reserved;
+	timer->pdev = pdev;
+	timer->loses_context = pdata->loses_context;
+	timer->get_context_loss_count = pdata->get_context_loss_count;
+
+	/* Skip pm_runtime_enable for OMAP1 */
+	if (!pdata->needs_manual_reset) {
+		pm_runtime_enable(&pdev->dev);
+		pm_runtime_irq_safe(&pdev->dev);
+	}
 
-		/* One or two timers may be set up early for sys_timer */
-		if (sys_timer_reserved & (1  << i)) {
-			timer->reserved = 1;
-			timer->posted = 1;
-		}
-#endif
+	if (!timer->reserved) {
+		pm_runtime_get_sync(&pdev->dev);
+		__omap_dm_timer_init_regs(timer);
+		pm_runtime_put(&pdev->dev);
 	}
 
+	/* add the timer element to the list */
+	spin_lock_irqsave(&dm_timer_lock, flags);
+	list_add_tail(&timer->node, &omap_timer_list);
+	spin_unlock_irqrestore(&dm_timer_lock, flags);
+
+	dev_dbg(&pdev->dev, "Device Probed.\n");
+
 	return 0;
+
+err_free_mem:
+	kfree(timer);
+
+err_free_ioregion:
+	release_mem_region(mem->start, resource_size(mem));
+
+	return ret;
 }
 
-arch_initcall(omap_dm_timer_init);
+/**
+ * omap_dm_timer_remove - cleanup a registered timer device
+ * @pdev:	pointer to current timer platform device
+ *
+ * Called by driver framework whenever a timer device is unregistered.
+ * In addition to freeing platform resources it also deletes the timer
+ * entry from the local list.
+ */
+static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
+{
+	struct omap_dm_timer *timer;
+	unsigned long flags;
+	int ret = -EINVAL;
+
+	spin_lock_irqsave(&dm_timer_lock, flags);
+	list_for_each_entry(timer, &omap_timer_list, node)
+		if (timer->pdev->id == pdev->id) {
+			list_del(&timer->node);
+			kfree(timer);
+			ret = 0;
+			break;
+		}
+	spin_unlock_irqrestore(&dm_timer_lock, flags);
+
+	return ret;
+}
+
+static struct platform_driver omap_dm_timer_driver = {
+	.probe  = omap_dm_timer_probe,
+	.remove = __devexit_p(omap_dm_timer_remove),
+	.driver = {
+		.name   = "omap_timer",
+	},
+};
+
+static int __init omap_dm_timer_driver_init(void)
+{
+	return platform_driver_register(&omap_dm_timer_driver);
+}
+
+static void __exit omap_dm_timer_driver_exit(void)
+{
+	platform_driver_unregister(&omap_dm_timer_driver);
+}
+
+early_platform_init("earlytimer", &omap_dm_timer_driver);
+module_init(omap_dm_timer_driver_init);
+module_exit(omap_dm_timer_driver_exit);
+
+MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("Texas Instruments Inc");
diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c
index 3341ca4..679cbd4 100644
--- a/arch/arm/plat-omap/i2c.c
+++ b/arch/arm/plat-omap/i2c.c
@@ -108,6 +108,22 @@ static inline int omap1_i2c_add_bus(int bus_id)
 	res[1].start = INT_I2C;
 	pdata = &i2c_pdata[bus_id - 1];
 
+	/* all OMAP1 have IP version 1 register set */
+	pdata->rev = OMAP_I2C_IP_VERSION_1;
+
+	/* all OMAP1 I2C are implemented like this */
+	pdata->flags = OMAP_I2C_FLAG_NO_FIFO |
+		       OMAP_I2C_FLAG_SIMPLE_CLOCK |
+		       OMAP_I2C_FLAG_16BIT_DATA_REG |
+		       OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK;
+
+	/* how the cpu bus is wired up differs for 7xx only */
+
+	if (cpu_is_omap7xx())
+		pdata->flags |= OMAP_I2C_FLAG_BUS_SHIFT_1;
+	else
+		pdata->flags |= OMAP_I2C_FLAG_BUS_SHIFT_2;
+
 	return platform_device_register(pdev);
 }
 
@@ -123,21 +139,14 @@ static void omap_pm_set_max_mpu_wakeup_lat_compat(struct device *dev, long t)
 	omap_pm_set_max_mpu_wakeup_lat(dev, t);
 }
 
-static struct omap_device_pm_latency omap_i2c_latency[] = {
-	[0] = {
-		.deactivate_func	= omap_device_idle_hwmods,
-		.activate_func		= omap_device_enable_hwmods,
-		.flags			= OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	},
-};
-
 static inline int omap2_i2c_add_bus(int bus_id)
 {
 	int l;
 	struct omap_hwmod *oh;
-	struct omap_device *od;
+	struct platform_device *pdev;
 	char oh_name[MAX_OMAP_I2C_HWMOD_NAME_LEN];
 	struct omap_i2c_bus_platform_data *pdata;
+	struct omap_i2c_dev_attr *dev_attr;
 
 	omap2_i2c_mux_pins(bus_id);
 
@@ -152,6 +161,16 @@ static inline int omap2_i2c_add_bus(int bus_id)
 
 	pdata = &i2c_pdata[bus_id - 1];
 	/*
+	 * pass the hwmod class's CPU-specific knowledge of I2C IP revision in
+	 * use, and functionality implementation flags, up to the OMAP I2C
+	 * driver via platform data
+	 */
+	pdata->rev = oh->class->rev;
+
+	dev_attr = (struct omap_i2c_dev_attr *)oh->dev_attr;
+	pdata->flags = dev_attr->flags;
+
+	/*
 	 * When waiting for completion of a i2c transfer, we need to
 	 * set a wake up latency constraint for the MPU. This is to
 	 * ensure quick enough wakeup from idle, when transfer
@@ -160,12 +179,12 @@ static inline int omap2_i2c_add_bus(int bus_id)
 	 */
 	if (cpu_is_omap34xx())
 		pdata->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat;
-	od = omap_device_build(name, bus_id, oh, pdata,
+	pdev = omap_device_build(name, bus_id, oh, pdata,
 			sizeof(struct omap_i2c_bus_platform_data),
-			omap_i2c_latency, ARRAY_SIZE(omap_i2c_latency), 0);
-	WARN(IS_ERR(od), "Could not build omap_device for %s\n", name);
+			NULL, 0, 0);
+	WARN(IS_ERR(pdev), "Could not build omap_device for %s\n", name);
 
-	return PTR_ERR(od);
+	return PTR_ERR(pdev);
 }
 #else
 static inline int omap2_i2c_add_bus(int bus_id)
diff --git a/arch/arm/plat-omap/include/plat/clock.h b/arch/arm/plat-omap/include/plat/clock.h
index df4b968..197ca03 100644
--- a/arch/arm/plat-omap/include/plat/clock.h
+++ b/arch/arm/plat-omap/include/plat/clock.h
@@ -80,8 +80,6 @@ struct clkops {
  *
  * @div is the divisor that should be applied to the parent clock's rate
  * to produce the current clock's rate.
- *
- * XXX @flags probably should be replaced with an struct omap_chip.
  */
 struct clksel_rate {
 	u32			val;
diff --git a/arch/arm/plat-omap/include/plat/common.h b/arch/arm/plat-omap/include/plat/common.h
index 4564cc6..c50df48 100644
--- a/arch/arm/plat-omap/include/plat/common.h
+++ b/arch/arm/plat-omap/include/plat/common.h
@@ -45,6 +45,18 @@ extern unsigned long long notrace omap_32k_sched_clock(void);
 
 extern void omap_reserve(void);
 
+void omap2420_init_early(void);
+void omap2430_init_early(void);
+void omap3430_init_early(void);
+void omap35xx_init_early(void);
+void omap3630_init_early(void);
+void omap3_init_early(void);	/* Do not use this one */
+void am35xx_init_early(void);
+void ti816x_init_early(void);
+void omap4430_init_early(void);
+
+void omap_sram_init(void);
+
 /*
  * IO bases for various OMAP processors
  * Except the tap base, rest all the io bases
@@ -53,13 +65,13 @@ extern void omap_reserve(void);
 struct omap_globals {
 	u32		class;		/* OMAP class to detect */
 	void __iomem	*tap;		/* Control module ID code */
-	unsigned long   sdrc;           /* SDRAM Controller */
-	unsigned long   sms;            /* SDRAM Memory Scheduler */
-	unsigned long   ctrl;           /* System Control Module */
-	unsigned long   ctrl_pad;	/* PAD Control Module */
-	unsigned long   prm;            /* Power and Reset Management */
-	unsigned long   cm;             /* Clock Management */
-	unsigned long   cm2;
+	void __iomem	*sdrc;           /* SDRAM Controller */
+	void __iomem	*sms;            /* SDRAM Memory Scheduler */
+	void __iomem	*ctrl;           /* System Control Module */
+	void __iomem	*ctrl_pad;	/* PAD Control Module */
+	void __iomem	*prm;            /* Power and Reset Management */
+	void __iomem	*cm;             /* Clock Management */
+	void __iomem	*cm2;
 };
 
 void omap2_set_globals_242x(void);
@@ -74,7 +86,11 @@ void omap2_set_globals_sdrc(struct omap_globals *);
 void omap2_set_globals_control(struct omap_globals *);
 void omap2_set_globals_prcm(struct omap_globals *);
 
+void omap242x_map_io(void);
+void omap243x_map_io(void);
 void omap3_map_io(void);
+void omap4_map_io(void);
+
 
 /**
  * omap_test_timeout - busy-loop, testing a condition
diff --git a/arch/arm/plat-omap/include/plat/cpu.h b/arch/arm/plat-omap/include/plat/cpu.h
index 67b3d75..2f90269 100644
--- a/arch/arm/plat-omap/include/plat/cpu.h
+++ b/arch/arm/plat-omap/include/plat/cpu.h
@@ -44,13 +44,6 @@
 
 int omap_type(void);
 
-struct omap_chip_id {
-	u16 oc;
-	u8 type;
-};
-
-#define OMAP_CHIP_INIT(x)	{ .oc = x }
-
 /*
  * omap_rev bits:
  * CPU id bits	(0730, 1510, 1710, 2422...)	[31:16]
@@ -60,19 +53,6 @@ struct omap_chip_id {
 unsigned int omap_rev(void);
 
 /*
- * Define CPU revision bits
- *
- * Verbose meaning of the revision bits may be different for a silicon
- * family. This difference can be handled separately.
- */
-#define OMAP_REVBITS_00		0x00
-#define OMAP_REVBITS_01		0x01
-#define OMAP_REVBITS_02		0x02
-#define OMAP_REVBITS_03		0x03
-#define OMAP_REVBITS_04		0x04
-#define OMAP_REVBITS_05		0x05
-
-/*
  * Get the CPU revision for OMAP devices
  */
 #define GET_OMAP_REVISION()	((omap_rev() >> 8) & 0xff)
@@ -262,7 +242,7 @@ IS_OMAP_TYPE(2422, 0x2422)
 IS_OMAP_TYPE(2423, 0x2423)
 IS_OMAP_TYPE(2430, 0x2430)
 IS_OMAP_TYPE(3430, 0x3430)
-IS_OMAP_TYPE(3505, 0x3505)
+IS_OMAP_TYPE(3505, 0x3517)
 IS_OMAP_TYPE(3517, 0x3517)
 
 #define cpu_is_omap310()		0
@@ -354,8 +334,9 @@ IS_OMAP_TYPE(3517, 0x3517)
 						(!omap3_has_sgx()) &&	\
 						(omap3_has_iva()))
 # define cpu_is_omap3530()		(cpu_is_omap3430())
-# define cpu_is_omap3505()		is_omap3505()
 # define cpu_is_omap3517()		is_omap3517()
+# define cpu_is_omap3505()		(cpu_is_omap3517() &&		\
+						!omap3_has_sgx())
 # undef cpu_is_omap3630
 # define cpu_is_omap3630()		is_omap363x()
 # define cpu_is_ti816x()		is_ti816x()
@@ -379,35 +360,31 @@ IS_OMAP_TYPE(3517, 0x3517)
 /* Various silicon revisions for omap2 */
 #define OMAP242X_CLASS		0x24200024
 #define OMAP2420_REV_ES1_0	OMAP242X_CLASS
-#define OMAP2420_REV_ES2_0	(OMAP242X_CLASS | (OMAP_REVBITS_01 << 8))
+#define OMAP2420_REV_ES2_0	(OMAP242X_CLASS | (0x1 << 8))
 
 #define OMAP243X_CLASS		0x24300024
 #define OMAP2430_REV_ES1_0	OMAP243X_CLASS
 
 #define OMAP343X_CLASS		0x34300034
 #define OMAP3430_REV_ES1_0	OMAP343X_CLASS
-#define OMAP3430_REV_ES2_0	(OMAP343X_CLASS | (OMAP_REVBITS_01 << 8))
-#define OMAP3430_REV_ES2_1	(OMAP343X_CLASS | (OMAP_REVBITS_02 << 8))
-#define OMAP3430_REV_ES3_0	(OMAP343X_CLASS | (OMAP_REVBITS_03 << 8))
-#define OMAP3430_REV_ES3_1	(OMAP343X_CLASS | (OMAP_REVBITS_04 << 8))
-#define OMAP3430_REV_ES3_1_2	(OMAP343X_CLASS | (OMAP_REVBITS_05 << 8))
+#define OMAP3430_REV_ES2_0	(OMAP343X_CLASS | (0x1 << 8))
+#define OMAP3430_REV_ES2_1	(OMAP343X_CLASS | (0x2 << 8))
+#define OMAP3430_REV_ES3_0	(OMAP343X_CLASS | (0x3 << 8))
+#define OMAP3430_REV_ES3_1	(OMAP343X_CLASS | (0x4 << 8))
+#define OMAP3430_REV_ES3_1_2	(OMAP343X_CLASS | (0x5 << 8))
 
 #define OMAP363X_CLASS		0x36300034
 #define OMAP3630_REV_ES1_0	OMAP363X_CLASS
-#define OMAP3630_REV_ES1_1	(OMAP363X_CLASS | (OMAP_REVBITS_01 << 8))
-#define OMAP3630_REV_ES1_2	(OMAP363X_CLASS | (OMAP_REVBITS_02 << 8))
+#define OMAP3630_REV_ES1_1	(OMAP363X_CLASS | (0x1 << 8))
+#define OMAP3630_REV_ES1_2	(OMAP363X_CLASS | (0x2 << 8))
 
-#define OMAP35XX_CLASS		0x35000034
-#define OMAP3503_REV(v)		(OMAP35XX_CLASS | (0x3503 << 16) | (v << 8))
-#define OMAP3515_REV(v)		(OMAP35XX_CLASS | (0x3515 << 16) | (v << 8))
-#define OMAP3525_REV(v)		(OMAP35XX_CLASS | (0x3525 << 16) | (v << 8))
-#define OMAP3530_REV(v)		(OMAP35XX_CLASS | (0x3530 << 16) | (v << 8))
-#define OMAP3505_REV(v)		(OMAP35XX_CLASS | (0x3505 << 16) | (v << 8))
-#define OMAP3517_REV(v)		(OMAP35XX_CLASS | (0x3517 << 16) | (v << 8))
+#define OMAP3517_CLASS		0x35170034
+#define OMAP3517_REV_ES1_0	OMAP3517_CLASS
+#define OMAP3517_REV_ES1_1	(OMAP3517_CLASS | (0x1 << 8))
 
 #define TI816X_CLASS		0x81600034
 #define TI8168_REV_ES1_0	TI816X_CLASS
-#define TI8168_REV_ES1_1	(TI816X_CLASS | (OMAP_REVBITS_01 << 8))
+#define TI8168_REV_ES1_1	(TI816X_CLASS | (0x1 << 8))
 
 #define OMAP443X_CLASS		0x44300044
 #define OMAP4430_REV_ES1_0	(OMAP443X_CLASS | (0x10 << 8))
@@ -418,61 +395,6 @@ IS_OMAP_TYPE(3517, 0x3517)
 #define OMAP446X_CLASS		0x44600044
 #define OMAP4460_REV_ES1_0	(OMAP446X_CLASS | (0x10 << 8))
 
-/*
- * omap_chip bits
- *
- * CHIP_IS_OMAP{2420,2430,3430} indicate that a particular structure is
- * valid on all chips of that type.  CHIP_IS_OMAP3430ES{1,2} indicates
- * something that is only valid on that particular ES revision.
- *
- * These bits may be ORed together to indicate structures that are
- * available on multiple chip types.
- *
- * To test whether a particular structure matches the current OMAP chip type,
- * use omap_chip_is().
- *
- */
-#define CHIP_IS_OMAP2420		(1 << 0)
-#define CHIP_IS_OMAP2430		(1 << 1)
-#define CHIP_IS_OMAP3430		(1 << 2)
-#define CHIP_IS_OMAP3430ES1		(1 << 3)
-#define CHIP_IS_OMAP3430ES2		(1 << 4)
-#define CHIP_IS_OMAP3430ES3_0		(1 << 5)
-#define CHIP_IS_OMAP3430ES3_1		(1 << 6)
-#define CHIP_IS_OMAP3630ES1		(1 << 7)
-#define CHIP_IS_OMAP4430ES1		(1 << 8)
-#define CHIP_IS_OMAP3630ES1_1           (1 << 9)
-#define CHIP_IS_OMAP3630ES1_2           (1 << 10)
-#define CHIP_IS_OMAP4430ES2		(1 << 11)
-#define CHIP_IS_OMAP4430ES2_1		(1 << 12)
-#define CHIP_IS_OMAP4430ES2_2		(1 << 13)
-#define CHIP_IS_TI816X			(1 << 14)
-#define CHIP_IS_OMAP4460ES1_0		(1 << 15)
-
-#define CHIP_IS_OMAP24XX		(CHIP_IS_OMAP2420 | CHIP_IS_OMAP2430)
-
-#define CHIP_IS_OMAP4430		(CHIP_IS_OMAP4430ES1 |		\
-					 CHIP_IS_OMAP4430ES2 |		\
-					 CHIP_IS_OMAP4430ES2_1 |	\
-					 CHIP_IS_OMAP4430ES2_2 |	\
-					 CHIP_IS_OMAP4460ES1_0)
-
-/*
- * "GE" here represents "greater than or equal to" in terms of ES
- * levels.  So CHIP_GE_OMAP3430ES2 is intended to match all OMAP3430
- * chips at ES2 and beyond, but not, for example, any OMAP lines after
- * OMAP3.
- */
-#define CHIP_GE_OMAP3430ES2		(CHIP_IS_OMAP3430ES2 | \
-					 CHIP_IS_OMAP3430ES3_0 | \
-					 CHIP_GE_OMAP3430ES3_1)
-#define CHIP_GE_OMAP3430ES3_1		(CHIP_IS_OMAP3430ES3_1 | \
-					 CHIP_IS_OMAP3630ES1 | \
-					 CHIP_GE_OMAP3630ES1_1)
-#define CHIP_GE_OMAP3630ES1_1		(CHIP_IS_OMAP3630ES1_1 | \
-					 CHIP_IS_OMAP3630ES1_2)
-
-int omap_chip_is(struct omap_chip_id oci);
 void omap2_check_revision(void);
 
 /*
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
index eb5d16c..d11025e 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -1,5 +1,5 @@
 /*
- * arch/arm/plat-omap/include/mach/dmtimer.h
+ * arch/arm/plat-omap/include/plat/dmtimer.h
  *
  * OMAP Dual-Mode Timers
  *
@@ -35,6 +35,7 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/platform_device.h>
 
 #ifndef __ASM_ARCH_DMTIMER_H
 #define __ASM_ARCH_DMTIMER_H
@@ -59,12 +60,56 @@
  * in OMAP4 can be distinguished.
  */
 #define OMAP_TIMER_IP_VERSION_1                        0x1
+
+/* timer capabilities used in hwmod database */
+#define OMAP_TIMER_SECURE				0x80000000
+#define OMAP_TIMER_ALWON				0x40000000
+#define OMAP_TIMER_HAS_PWM				0x20000000
+
+struct omap_timer_capability_dev_attr {
+	u32 timer_capability;
+};
+
 struct omap_dm_timer;
 struct clk;
 
+struct timer_regs {
+	u32 tidr;
+	u32 tiocp_cfg;
+	u32 tistat;
+	u32 tisr;
+	u32 tier;
+	u32 twer;
+	u32 tclr;
+	u32 tcrr;
+	u32 tldr;
+	u32 ttrg;
+	u32 twps;
+	u32 tmar;
+	u32 tcar1;
+	u32 tsicr;
+	u32 tcar2;
+	u32 tpir;
+	u32 tnir;
+	u32 tcvr;
+	u32 tocr;
+	u32 towr;
+};
+
+struct dmtimer_platform_data {
+	int (*set_timer_src)(struct platform_device *pdev, int source);
+	int timer_ip_version;
+	u32 needs_manual_reset:1;
+	bool reserved;
+
+	bool loses_context;
+
+	u32 (*get_context_loss_count)(struct device *dev);
+};
+
 struct omap_dm_timer *omap_dm_timer_request(void);
 struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id);
-void omap_dm_timer_free(struct omap_dm_timer *timer);
+int omap_dm_timer_free(struct omap_dm_timer *timer);
 void omap_dm_timer_enable(struct omap_dm_timer *timer);
 void omap_dm_timer_disable(struct omap_dm_timer *timer);
 
@@ -73,23 +118,23 @@ int omap_dm_timer_get_irq(struct omap_dm_timer *timer);
 u32 omap_dm_timer_modify_idlect_mask(u32 inputmask);
 struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer);
 
-void omap_dm_timer_trigger(struct omap_dm_timer *timer);
-void omap_dm_timer_start(struct omap_dm_timer *timer);
-void omap_dm_timer_stop(struct omap_dm_timer *timer);
+int omap_dm_timer_trigger(struct omap_dm_timer *timer);
+int omap_dm_timer_start(struct omap_dm_timer *timer);
+int omap_dm_timer_stop(struct omap_dm_timer *timer);
 
 int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source);
-void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, unsigned int value);
-void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, unsigned int value);
-void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, unsigned int match);
-void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int toggle, int trigger);
-void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler);
+int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, unsigned int value);
+int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, unsigned int value);
+int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, unsigned int match);
+int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int toggle, int trigger);
+int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler);
 
-void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value);
+int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value);
 
 unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer);
-void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value);
+int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value);
 unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer);
-void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value);
+int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value);
 
 int omap_dm_timers_active(void);
 
@@ -98,12 +143,30 @@ int omap_dm_timers_active(void);
  * used by dmtimer.c and sys_timer related code.
  */
 
-/* register offsets */
-#define _OMAP_TIMER_ID_OFFSET		0x00
-#define _OMAP_TIMER_OCP_CFG_OFFSET	0x10
-#define _OMAP_TIMER_SYS_STAT_OFFSET	0x14
-#define _OMAP_TIMER_STAT_OFFSET		0x18
-#define _OMAP_TIMER_INT_EN_OFFSET	0x1c
+/*
+ * The interrupt registers are different between v1 and v2 ip.
+ * These registers are offsets from timer->iobase.
+ */
+#define OMAP_TIMER_ID_OFFSET		0x00
+#define OMAP_TIMER_OCP_CFG_OFFSET	0x10
+
+#define OMAP_TIMER_V1_SYS_STAT_OFFSET	0x14
+#define OMAP_TIMER_V1_STAT_OFFSET	0x18
+#define OMAP_TIMER_V1_INT_EN_OFFSET	0x1c
+
+#define OMAP_TIMER_V2_IRQSTATUS_RAW	0x24
+#define OMAP_TIMER_V2_IRQSTATUS		0x28
+#define OMAP_TIMER_V2_IRQENABLE_SET	0x2c
+#define OMAP_TIMER_V2_IRQENABLE_CLR	0x30
+
+/*
+ * The functional registers have a different base on v1 and v2 ip.
+ * These registers are offsets from timer->func_base. The func_base
+ * is samae as io_base for v1 and io_base + 0x14 for v2 ip.
+ *
+ */
+#define OMAP_TIMER_V2_FUNC_OFFSET		0x14
+
 #define _OMAP_TIMER_WAKEUP_EN_OFFSET	0x20
 #define _OMAP_TIMER_CTRL_OFFSET		0x24
 #define		OMAP_TIMER_CTRL_GPOCFG		(1 << 14)
@@ -147,21 +210,6 @@ int omap_dm_timers_active(void);
 /* register offsets with the write pending bit encoded */
 #define	WPSHIFT					16
 
-#define OMAP_TIMER_ID_REG			(_OMAP_TIMER_ID_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_OCP_CFG_REG			(_OMAP_TIMER_OCP_CFG_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_SYS_STAT_REG			(_OMAP_TIMER_SYS_STAT_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_STAT_REG			(_OMAP_TIMER_STAT_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_INT_EN_REG			(_OMAP_TIMER_INT_EN_OFFSET \
-							| (WP_NONE << WPSHIFT))
-
 #define OMAP_TIMER_WAKEUP_EN_REG		(_OMAP_TIMER_WAKEUP_EN_OFFSET \
 							| (WP_NONE << WPSHIFT))
 
@@ -209,49 +257,88 @@ int omap_dm_timers_active(void);
 
 struct omap_dm_timer {
 	unsigned long phys_base;
+	int id;
 	int irq;
-#ifdef CONFIG_ARCH_OMAP2PLUS
 	struct clk *iclk, *fclk;
-#endif
-	void __iomem *io_base;
+
+	void __iomem	*io_base;
+	void __iomem	*sys_stat;	/* TISTAT timer status */
+	void __iomem	*irq_stat;	/* TISR/IRQSTATUS interrupt status */
+	void __iomem	*irq_ena;	/* irq enable */
+	void __iomem	*irq_dis;	/* irq disable, only on v2 ip */
+	void __iomem	*pend;		/* write pending */
+	void __iomem	*func_base;	/* function register base */
+
 	unsigned long rate;
 	unsigned reserved:1;
-	unsigned enabled:1;
 	unsigned posted:1;
+	struct timer_regs context;
+	bool loses_context;
+	int ctx_loss_count;
+	int revision;
+	struct platform_device *pdev;
+	struct list_head node;
+
+	u32 (*get_context_loss_count)(struct device *dev);
 };
 
-extern u32 sys_timer_reserved;
-void omap_dm_timer_prepare(struct omap_dm_timer *timer);
+int omap_dm_timer_prepare(struct omap_dm_timer *timer);
 
-static inline u32 __omap_dm_timer_read(void __iomem *base, u32 reg,
+static inline u32 __omap_dm_timer_read(struct omap_dm_timer *timer, u32 reg,
 						int posted)
 {
 	if (posted)
-		while (__raw_readl(base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
-				& (reg >> WPSHIFT))
+		while (__raw_readl(timer->pend) & (reg >> WPSHIFT))
 			cpu_relax();
 
-	return __raw_readl(base + (reg & 0xff));
+	return __raw_readl(timer->func_base + (reg & 0xff));
 }
 
-static inline void __omap_dm_timer_write(void __iomem *base, u32 reg, u32 val,
-						int posted)
+static inline void __omap_dm_timer_write(struct omap_dm_timer *timer,
+					u32 reg, u32 val, int posted)
 {
 	if (posted)
-		while (__raw_readl(base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
-				& (reg >> WPSHIFT))
+		while (__raw_readl(timer->pend) & (reg >> WPSHIFT))
 			cpu_relax();
 
-	__raw_writel(val, base + (reg & 0xff));
+	__raw_writel(val, timer->func_base + (reg & 0xff));
+}
+
+static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer)
+{
+	u32 tidr;
+
+	/* Assume v1 ip if bits [31:16] are zero */
+	tidr = __raw_readl(timer->io_base);
+	if (!(tidr >> 16)) {
+		timer->revision = 1;
+		timer->sys_stat = timer->io_base +
+				OMAP_TIMER_V1_SYS_STAT_OFFSET;
+		timer->irq_stat = timer->io_base + OMAP_TIMER_V1_STAT_OFFSET;
+		timer->irq_ena = timer->io_base + OMAP_TIMER_V1_INT_EN_OFFSET;
+		timer->irq_dis = 0;
+		timer->pend = timer->io_base + _OMAP_TIMER_WRITE_PEND_OFFSET;
+		timer->func_base = timer->io_base;
+	} else {
+		timer->revision = 2;
+		timer->sys_stat = 0;
+		timer->irq_stat = timer->io_base + OMAP_TIMER_V2_IRQSTATUS;
+		timer->irq_ena = timer->io_base + OMAP_TIMER_V2_IRQENABLE_SET;
+		timer->irq_dis = timer->io_base + OMAP_TIMER_V2_IRQENABLE_CLR;
+		timer->pend = timer->io_base +
+			_OMAP_TIMER_WRITE_PEND_OFFSET +
+				OMAP_TIMER_V2_FUNC_OFFSET;
+		timer->func_base = timer->io_base + OMAP_TIMER_V2_FUNC_OFFSET;
+	}
 }
 
 /* Assumes the source clock has been set by caller */
-static inline void __omap_dm_timer_reset(void __iomem *base, int autoidle,
-						int wakeup)
+static inline void __omap_dm_timer_reset(struct omap_dm_timer *timer,
+					int autoidle, int wakeup)
 {
 	u32 l;
 
-	l = __omap_dm_timer_read(base, OMAP_TIMER_OCP_CFG_REG, 0);
+	l = __raw_readl(timer->io_base + OMAP_TIMER_OCP_CFG_OFFSET);
 	l |= 0x02 << 3;  /* Set to smart-idle mode */
 	l |= 0x2 << 8;   /* Set clock activity to perserve f-clock on idle */
 
@@ -261,10 +348,10 @@ static inline void __omap_dm_timer_reset(void __iomem *base, int autoidle,
 	if (wakeup)
 		l |= 1 << 2;
 
-	__omap_dm_timer_write(base, OMAP_TIMER_OCP_CFG_REG, l, 0);
+	__raw_writel(l, timer->io_base + OMAP_TIMER_OCP_CFG_OFFSET);
 
 	/* Match hardware reset default of posted mode */
-	__omap_dm_timer_write(base, OMAP_TIMER_IF_CTRL_REG,
+	__omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG,
 					OMAP_TIMER_CTRL_POSTED, 0);
 }
 
@@ -286,18 +373,18 @@ static inline int __omap_dm_timer_set_source(struct clk *timer_fck,
 	return ret;
 }
 
-static inline void __omap_dm_timer_stop(void __iomem *base, int posted,
-						unsigned long rate)
+static inline void __omap_dm_timer_stop(struct omap_dm_timer *timer,
+					int posted, unsigned long rate)
 {
 	u32 l;
 
-	l = __omap_dm_timer_read(base, OMAP_TIMER_CTRL_REG, posted);
+	l = __omap_dm_timer_read(timer, OMAP_TIMER_CTRL_REG, posted);
 	if (l & OMAP_TIMER_CTRL_ST) {
 		l &= ~0x1;
-		__omap_dm_timer_write(base, OMAP_TIMER_CTRL_REG, l, posted);
+		__omap_dm_timer_write(timer, OMAP_TIMER_CTRL_REG, l, posted);
 #ifdef CONFIG_ARCH_OMAP2PLUS
 		/* Readback to make sure write has completed */
-		__omap_dm_timer_read(base, OMAP_TIMER_CTRL_REG, posted);
+		__omap_dm_timer_read(timer, OMAP_TIMER_CTRL_REG, posted);
 		/*
 		 * Wait for functional clock period x 3.5 to make sure that
 		 * timer is stopped
@@ -307,34 +394,34 @@ static inline void __omap_dm_timer_stop(void __iomem *base, int posted,
 	}
 
 	/* Ack possibly pending interrupt */
-	__omap_dm_timer_write(base, OMAP_TIMER_STAT_REG,
-					OMAP_TIMER_INT_OVERFLOW, 0);
+	__raw_writel(OMAP_TIMER_INT_OVERFLOW, timer->irq_stat);
 }
 
-static inline void __omap_dm_timer_load_start(void __iomem *base, u32 ctrl,
-						unsigned int load, int posted)
+static inline void __omap_dm_timer_load_start(struct omap_dm_timer *timer,
+						u32 ctrl, unsigned int load,
+						int posted)
 {
-	__omap_dm_timer_write(base, OMAP_TIMER_COUNTER_REG, load, posted);
-	__omap_dm_timer_write(base, OMAP_TIMER_CTRL_REG, ctrl, posted);
+	__omap_dm_timer_write(timer, OMAP_TIMER_COUNTER_REG, load, posted);
+	__omap_dm_timer_write(timer, OMAP_TIMER_CTRL_REG, ctrl, posted);
 }
 
-static inline void __omap_dm_timer_int_enable(void __iomem *base,
+static inline void __omap_dm_timer_int_enable(struct omap_dm_timer *timer,
 						unsigned int value)
 {
-	__omap_dm_timer_write(base, OMAP_TIMER_INT_EN_REG, value, 0);
-	__omap_dm_timer_write(base, OMAP_TIMER_WAKEUP_EN_REG, value, 0);
+	__raw_writel(value, timer->irq_ena);
+	__omap_dm_timer_write(timer, OMAP_TIMER_WAKEUP_EN_REG, value, 0);
 }
 
-static inline unsigned int __omap_dm_timer_read_counter(void __iomem *base,
-							int posted)
+static inline unsigned int
+__omap_dm_timer_read_counter(struct omap_dm_timer *timer, int posted)
 {
-	return __omap_dm_timer_read(base, OMAP_TIMER_COUNTER_REG, posted);
+	return __omap_dm_timer_read(timer, OMAP_TIMER_COUNTER_REG, posted);
 }
 
-static inline void __omap_dm_timer_write_status(void __iomem *base,
+static inline void __omap_dm_timer_write_status(struct omap_dm_timer *timer,
 						unsigned int value)
 {
-	__omap_dm_timer_write(base, OMAP_TIMER_STAT_REG, value, 0);
+	__raw_writel(value, timer->irq_stat);
 }
 
 #endif /* __ASM_ARCH_DMTIMER_H */
diff --git a/arch/arm/plat-omap/include/plat/io.h b/arch/arm/plat-omap/include/plat/io.h
index ebe67ea..7f2969e 100644
--- a/arch/arm/plat-omap/include/plat/io.h
+++ b/arch/arm/plat-omap/include/plat/io.h
@@ -228,13 +228,13 @@
 
 #define OMAP44XX_EMIF2_PHYS	OMAP44XX_EMIF2_BASE
 						/* 0x4d000000 --> 0xfd200000 */
-#define OMAP44XX_EMIF2_VIRT	(OMAP44XX_EMIF2_PHYS + OMAP4_L3_PER_IO_OFFSET)
 #define OMAP44XX_EMIF2_SIZE	SZ_1M
+#define OMAP44XX_EMIF2_VIRT	(OMAP44XX_EMIF1_VIRT + OMAP44XX_EMIF1_SIZE)
 
 #define OMAP44XX_DMM_PHYS	OMAP44XX_DMM_BASE
 						/* 0x4e000000 --> 0xfd300000 */
-#define OMAP44XX_DMM_VIRT	(OMAP44XX_DMM_PHYS + OMAP4_L3_PER_IO_OFFSET)
 #define OMAP44XX_DMM_SIZE	SZ_1M
+#define OMAP44XX_DMM_VIRT	(OMAP44XX_EMIF2_VIRT + OMAP44XX_EMIF2_SIZE)
 /*
  * ----------------------------------------------------------------------------
  * Omap specific register access
@@ -247,6 +247,8 @@
  * NOTE: Please use ioremap + __raw_read/write where possible instead of these
  */
 
+void omap_ioremap_init(void);
+
 extern u8 omap_readb(u32 pa);
 extern u16 omap_readw(u32 pa);
 extern u32 omap_readl(u32 pa);
@@ -256,8 +258,31 @@ extern void omap_writel(u32 v, u32 pa);
 
 struct omap_sdrc_params;
 
-extern void omap1_map_common_io(void);
-extern void omap1_init_common_hw(void);
+#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+void omap7xx_map_io(void);
+#else
+static inline void omap_map_io(void)
+{
+}
+#endif
+
+#ifdef CONFIG_ARCH_OMAP15XX
+void omap15xx_map_io(void);
+#else
+static inline void omap15xx_map_io(void)
+{
+}
+#endif
+
+#ifdef CONFIG_ARCH_OMAP16XX
+void omap16xx_map_io(void);
+#else
+static inline void omap16xx_map_io(void)
+{
+}
+#endif
+
+void omap1_init_early(void);
 
 #ifdef CONFIG_SOC_OMAP2420
 extern void omap242x_map_common_io(void);
@@ -300,7 +325,7 @@ static inline void omap44xx_map_common_io(void)
 #endif
 
 extern void omap2_init_common_infrastructure(void);
-extern void omap2_init_common_devices(struct omap_sdrc_params *sdrc_cs0,
+extern void omap_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
 				      struct omap_sdrc_params *sdrc_cs1);
 
 #define __arch_ioremap	omap_ioremap
diff --git a/arch/arm/plat-omap/include/plat/mcbsp.h b/arch/arm/plat-omap/include/plat/mcbsp.h
index 9882c65..8fa74e2 100644
--- a/arch/arm/plat-omap/include/plat/mcbsp.h
+++ b/arch/arm/plat-omap/include/plat/mcbsp.h
@@ -25,9 +25,7 @@
 #define __ASM_ARCH_OMAP_MCBSP_H
 
 #include <linux/spinlock.h>
-
-#include <mach/hardware.h>
-#include <plat/clock.h>
+#include <linux/clk.h>
 
 /* macro for building platform_device for McBSP ports */
 #define OMAP_MCBSP_PLATFORM_DEVICE(port_nr)		\
@@ -40,104 +38,60 @@ static struct platform_device omap_mcbsp##port_nr = {	\
 #define MCBSP_CONFIG_TYPE3	0x3
 #define MCBSP_CONFIG_TYPE4	0x4
 
-#define OMAP7XX_MCBSP1_BASE	0xfffb1000
-#define OMAP7XX_MCBSP2_BASE	0xfffb1800
-
-#define OMAP1510_MCBSP1_BASE	0xe1011800
-#define OMAP1510_MCBSP2_BASE	0xfffb1000
-#define OMAP1510_MCBSP3_BASE	0xe1017000
-
-#define OMAP1610_MCBSP1_BASE	0xe1011800
-#define OMAP1610_MCBSP2_BASE	0xfffb1000
-#define OMAP1610_MCBSP3_BASE	0xe1017000
-
-#ifdef CONFIG_ARCH_OMAP1
-
-#define OMAP_MCBSP_REG_DRR2	0x00
-#define OMAP_MCBSP_REG_DRR1	0x02
-#define OMAP_MCBSP_REG_DXR2	0x04
-#define OMAP_MCBSP_REG_DXR1	0x06
-#define OMAP_MCBSP_REG_DRR	0x02
-#define OMAP_MCBSP_REG_DXR	0x06
-#define OMAP_MCBSP_REG_SPCR2	0x08
-#define OMAP_MCBSP_REG_SPCR1	0x0a
-#define OMAP_MCBSP_REG_RCR2	0x0c
-#define OMAP_MCBSP_REG_RCR1	0x0e
-#define OMAP_MCBSP_REG_XCR2	0x10
-#define OMAP_MCBSP_REG_XCR1	0x12
-#define OMAP_MCBSP_REG_SRGR2	0x14
-#define OMAP_MCBSP_REG_SRGR1	0x16
-#define OMAP_MCBSP_REG_MCR2	0x18
-#define OMAP_MCBSP_REG_MCR1	0x1a
-#define OMAP_MCBSP_REG_RCERA	0x1c
-#define OMAP_MCBSP_REG_RCERB	0x1e
-#define OMAP_MCBSP_REG_XCERA	0x20
-#define OMAP_MCBSP_REG_XCERB	0x22
-#define OMAP_MCBSP_REG_PCR0	0x24
-#define OMAP_MCBSP_REG_RCERC	0x26
-#define OMAP_MCBSP_REG_RCERD	0x28
-#define OMAP_MCBSP_REG_XCERC	0x2A
-#define OMAP_MCBSP_REG_XCERD	0x2C
-#define OMAP_MCBSP_REG_RCERE	0x2E
-#define OMAP_MCBSP_REG_RCERF	0x30
-#define OMAP_MCBSP_REG_XCERE	0x32
-#define OMAP_MCBSP_REG_XCERF	0x34
-#define OMAP_MCBSP_REG_RCERG	0x36
-#define OMAP_MCBSP_REG_RCERH	0x38
-#define OMAP_MCBSP_REG_XCERG	0x3A
-#define OMAP_MCBSP_REG_XCERH	0x3C
-
-/* Dummy defines, these are not available on omap1 */
-#define OMAP_MCBSP_REG_XCCR	0x00
-#define OMAP_MCBSP_REG_RCCR	0x00
-
-#else
-
-#define OMAP_MCBSP_REG_DRR2	0x00
-#define OMAP_MCBSP_REG_DRR1	0x04
-#define OMAP_MCBSP_REG_DXR2	0x08
-#define OMAP_MCBSP_REG_DXR1	0x0C
-#define OMAP_MCBSP_REG_DRR	0x00
-#define OMAP_MCBSP_REG_DXR	0x08
-#define OMAP_MCBSP_REG_SPCR2	0x10
-#define OMAP_MCBSP_REG_SPCR1	0x14
-#define OMAP_MCBSP_REG_RCR2	0x18
-#define OMAP_MCBSP_REG_RCR1	0x1C
-#define OMAP_MCBSP_REG_XCR2	0x20
-#define OMAP_MCBSP_REG_XCR1	0x24
-#define OMAP_MCBSP_REG_SRGR2	0x28
-#define OMAP_MCBSP_REG_SRGR1	0x2C
-#define OMAP_MCBSP_REG_MCR2	0x30
-#define OMAP_MCBSP_REG_MCR1	0x34
-#define OMAP_MCBSP_REG_RCERA	0x38
-#define OMAP_MCBSP_REG_RCERB	0x3C
-#define OMAP_MCBSP_REG_XCERA	0x40
-#define OMAP_MCBSP_REG_XCERB	0x44
-#define OMAP_MCBSP_REG_PCR0	0x48
-#define OMAP_MCBSP_REG_RCERC	0x4C
-#define OMAP_MCBSP_REG_RCERD	0x50
-#define OMAP_MCBSP_REG_XCERC	0x54
-#define OMAP_MCBSP_REG_XCERD	0x58
-#define OMAP_MCBSP_REG_RCERE	0x5C
-#define OMAP_MCBSP_REG_RCERF	0x60
-#define OMAP_MCBSP_REG_XCERE	0x64
-#define OMAP_MCBSP_REG_XCERF	0x68
-#define OMAP_MCBSP_REG_RCERG	0x6C
-#define OMAP_MCBSP_REG_RCERH	0x70
-#define OMAP_MCBSP_REG_XCERG	0x74
-#define OMAP_MCBSP_REG_XCERH	0x78
-#define OMAP_MCBSP_REG_SYSCON	0x8C
-#define OMAP_MCBSP_REG_THRSH2	0x90
-#define OMAP_MCBSP_REG_THRSH1	0x94
-#define OMAP_MCBSP_REG_IRQST	0xA0
-#define OMAP_MCBSP_REG_IRQEN	0xA4
-#define OMAP_MCBSP_REG_WAKEUPEN	0xA8
-#define OMAP_MCBSP_REG_XCCR	0xAC
-#define OMAP_MCBSP_REG_RCCR	0xB0
-#define OMAP_MCBSP_REG_XBUFFSTAT	0xB4
-#define OMAP_MCBSP_REG_RBUFFSTAT	0xB8
-#define OMAP_MCBSP_REG_SSELCR	0xBC
+/* McBSP register numbers. Register address offset = num * reg_step */
+enum {
+	/* Common registers */
+	OMAP_MCBSP_REG_SPCR2 = 4,
+	OMAP_MCBSP_REG_SPCR1,
+	OMAP_MCBSP_REG_RCR2,
+	OMAP_MCBSP_REG_RCR1,
+	OMAP_MCBSP_REG_XCR2,
+	OMAP_MCBSP_REG_XCR1,
+	OMAP_MCBSP_REG_SRGR2,
+	OMAP_MCBSP_REG_SRGR1,
+	OMAP_MCBSP_REG_MCR2,
+	OMAP_MCBSP_REG_MCR1,
+	OMAP_MCBSP_REG_RCERA,
+	OMAP_MCBSP_REG_RCERB,
+	OMAP_MCBSP_REG_XCERA,
+	OMAP_MCBSP_REG_XCERB,
+	OMAP_MCBSP_REG_PCR0,
+	OMAP_MCBSP_REG_RCERC,
+	OMAP_MCBSP_REG_RCERD,
+	OMAP_MCBSP_REG_XCERC,
+	OMAP_MCBSP_REG_XCERD,
+	OMAP_MCBSP_REG_RCERE,
+	OMAP_MCBSP_REG_RCERF,
+	OMAP_MCBSP_REG_XCERE,
+	OMAP_MCBSP_REG_XCERF,
+	OMAP_MCBSP_REG_RCERG,
+	OMAP_MCBSP_REG_RCERH,
+	OMAP_MCBSP_REG_XCERG,
+	OMAP_MCBSP_REG_XCERH,
+
+	/* OMAP1-OMAP2420 registers */
+	OMAP_MCBSP_REG_DRR2 = 0,
+	OMAP_MCBSP_REG_DRR1,
+	OMAP_MCBSP_REG_DXR2,
+	OMAP_MCBSP_REG_DXR1,
+
+	/* OMAP2430 and onwards */
+	OMAP_MCBSP_REG_DRR = 0,
+	OMAP_MCBSP_REG_DXR = 2,
+	OMAP_MCBSP_REG_SYSCON =	35,
+	OMAP_MCBSP_REG_THRSH2,
+	OMAP_MCBSP_REG_THRSH1,
+	OMAP_MCBSP_REG_IRQST = 40,
+	OMAP_MCBSP_REG_IRQEN,
+	OMAP_MCBSP_REG_WAKEUPEN,
+	OMAP_MCBSP_REG_XCCR,
+	OMAP_MCBSP_REG_RCCR,
+	OMAP_MCBSP_REG_XBUFFSTAT,
+	OMAP_MCBSP_REG_RBUFFSTAT,
+	OMAP_MCBSP_REG_SSELCR,
+};
 
+/* OMAP3 sidetone control registers */
 #define OMAP_ST_REG_REV		0x00
 #define OMAP_ST_REG_SYSCONFIG	0x10
 #define OMAP_ST_REG_IRQSTATUS	0x18
@@ -146,8 +100,6 @@ static struct platform_device omap_mcbsp##port_nr = {	\
 #define OMAP_ST_REG_SFIRCR	0x28
 #define OMAP_ST_REG_SSELCR	0x2C
 
-#endif
-
 /************************** McBSP SPCR1 bit definitions ***********************/
 #define RRST			0x0001
 #define RRDY			0x0002
@@ -344,20 +296,20 @@ typedef enum {
 struct omap_mcbsp_ops {
 	void (*request)(unsigned int);
 	void (*free)(unsigned int);
-	int (*set_clks_src)(u8, u8);
 };
 
 struct omap_mcbsp_platform_data {
-	unsigned long phys_base;
-	u8 dma_rx_sync, dma_tx_sync;
-	u16 rx_irq, tx_irq;
 	struct omap_mcbsp_ops *ops;
-#ifdef CONFIG_ARCH_OMAP3
-	/* Sidetone block for McBSP 2 and 3 */
-	unsigned long phys_base_st;
-#endif
 	u16 buffer_size;
-	unsigned int mcbsp_config_type;
+	u8 reg_size;
+	u8 reg_step;
+
+	/* McBSP platform and instance specific features */
+	bool has_wakeup; /* Wakeup capability */
+	bool has_ccr; /* Transceiver has configuration control registers */
+	int (*enable_st_clock)(unsigned int, bool);
+	int (*set_clk_src)(struct device *dev, struct clk *clk, const char *src);
+	int (*mux_signal)(struct device *dev, const char *signal, const char *src);
 };
 
 struct omap_mcbsp_st_data {
@@ -389,14 +341,12 @@ struct omap_mcbsp {
 	spinlock_t lock;
 	struct omap_mcbsp_platform_data *pdata;
 	struct clk *fclk;
-#ifdef CONFIG_ARCH_OMAP3
 	struct omap_mcbsp_st_data *st_data;
 	int dma_op_mode;
 	u16 max_tx_thres;
 	u16 max_rx_thres;
-#endif
 	void *reg_cache;
-	unsigned int mcbsp_config_type;
+	int reg_cache_size;
 };
 
 /**
@@ -408,16 +358,10 @@ struct omap_mcbsp_dev_attr {
 };
 
 extern struct omap_mcbsp **mcbsp_ptr;
-extern int omap_mcbsp_count, omap_mcbsp_cache_size;
-
-#define omap_mcbsp_check_valid_id(id)	(id < omap_mcbsp_count)
-#define id_to_mcbsp_ptr(id)		mcbsp_ptr[id];
+extern int omap_mcbsp_count;
 
 int omap_mcbsp_init(void);
-void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
-			struct omap_mcbsp_platform_data *config, int size);
 void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config);
-#ifdef CONFIG_ARCH_OMAP3
 void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold);
 void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold);
 u16 omap_mcbsp_get_max_tx_threshold(unsigned int id);
@@ -426,18 +370,6 @@ u16 omap_mcbsp_get_fifo_size(unsigned int id);
 u16 omap_mcbsp_get_tx_delay(unsigned int id);
 u16 omap_mcbsp_get_rx_delay(unsigned int id);
 int omap_mcbsp_get_dma_op_mode(unsigned int id);
-#else
-static inline void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold)
-{ }
-static inline void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold)
-{ }
-static inline u16 omap_mcbsp_get_max_tx_threshold(unsigned int id) { return 0; }
-static inline u16 omap_mcbsp_get_max_rx_threshold(unsigned int id) { return 0; }
-static inline u16 omap_mcbsp_get_fifo_size(unsigned int id) { return 0; }
-static inline u16 omap_mcbsp_get_tx_delay(unsigned int id) { return 0; }
-static inline u16 omap_mcbsp_get_rx_delay(unsigned int id) { return 0; }
-static inline int omap_mcbsp_get_dma_op_mode(unsigned int id) { return 0; }
-#endif
 int omap_mcbsp_request(unsigned int id);
 void omap_mcbsp_free(unsigned int id);
 void omap_mcbsp_start(unsigned int id, int tx, int rx);
@@ -453,21 +385,11 @@ void omap2_mcbsp1_mux_fsr_src(u8 mux);
 int omap_mcbsp_dma_ch_params(unsigned int id, unsigned int stream);
 int omap_mcbsp_dma_reg_params(unsigned int id, unsigned int stream);
 
-#ifdef CONFIG_ARCH_OMAP3
 /* Sidetone specific API */
 int omap_st_set_chgain(unsigned int id, int channel, s16 chgain);
 int omap_st_get_chgain(unsigned int id, int channel, s16 *chgain);
 int omap_st_enable(unsigned int id);
 int omap_st_disable(unsigned int id);
 int omap_st_is_enabled(unsigned int id);
-#else
-static inline int omap_st_set_chgain(unsigned int id, int channel,
-				     s16 chgain) { return 0; }
-static inline int omap_st_get_chgain(unsigned int id, int channel,
-				     s16 *chgain) { return 0; }
-static inline int omap_st_enable(unsigned int id) { return 0; }
-static inline int omap_st_disable(unsigned int id) { return 0; }
-static inline int omap_st_is_enabled(unsigned int id) {  return 0; }
-#endif
 
 #endif
diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h
index ee405b36..12c5b0c 100644
--- a/arch/arm/plat-omap/include/plat/omap_device.h
+++ b/arch/arm/plat-omap/include/plat/omap_device.h
@@ -68,7 +68,7 @@ extern struct device omap_device_parent;
  *
  */
 struct omap_device {
-	struct platform_device		pdev;
+	struct platform_device		*pdev;
 	struct omap_hwmod		**hwmods;
 	struct omap_device_pm_latency	*pm_lats;
 	u32				dev_wakeup_lat;
@@ -88,25 +88,20 @@ int omap_device_shutdown(struct platform_device *pdev);
 
 /* Core code interface */
 
-int omap_device_count_resources(struct omap_device *od);
-int omap_device_fill_resources(struct omap_device *od, struct resource *res);
-
-struct omap_device *omap_device_build(const char *pdev_name, int pdev_id,
+struct platform_device *omap_device_build(const char *pdev_name, int pdev_id,
 				      struct omap_hwmod *oh, void *pdata,
 				      int pdata_len,
 				      struct omap_device_pm_latency *pm_lats,
 				      int pm_lats_cnt, int is_early_device);
 
-struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
+struct platform_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
 					 struct omap_hwmod **oh, int oh_cnt,
 					 void *pdata, int pdata_len,
 					 struct omap_device_pm_latency *pm_lats,
 					 int pm_lats_cnt, int is_early_device);
 
-int omap_device_register(struct omap_device *od);
-int omap_early_device_register(struct omap_device *od);
-
 void __iomem *omap_device_get_rt_va(struct omap_device *od);
+struct device *omap_device_get_by_hwmod_name(const char *oh_name);
 
 /* OMAP PM interface */
 int omap_device_align_pm_lat(struct platform_device *pdev,
@@ -122,11 +117,6 @@ int omap_device_enable_hwmods(struct omap_device *od);
 int omap_device_disable_clocks(struct omap_device *od);
 int omap_device_enable_clocks(struct omap_device *od);
 
-static inline void omap_device_disable_idle_on_suspend(struct omap_device *od)
-{
-	od->flags |= OMAP_DEVICE_NO_IDLE_ON_SUSPEND;
-}
-
 /*
  * Entries should be kept in latency order ascending
  *
@@ -157,6 +147,17 @@ struct omap_device_pm_latency {
 #define OMAP_DEVICE_LATENCY_AUTO_ADJUST BIT(1)
 
 /* Get omap_device pointer from platform_device pointer */
-#define to_omap_device(x) container_of((x), struct omap_device, pdev)
+static inline struct omap_device *to_omap_device(struct platform_device *pdev)
+{
+	return pdev ? pdev->archdata.od : NULL;
+}
+
+static inline
+void omap_device_disable_idle_on_suspend(struct platform_device *pdev)
+{
+	struct omap_device *od = to_omap_device(pdev);
+
+	od->flags |= OMAP_DEVICE_NO_IDLE_ON_SUSPEND;
+}
 
 #endif
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index 0e329ca..5419f1a 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -496,7 +496,6 @@ struct omap_hwmod_class {
  * @_state: internal-use hwmod state
  * @_postsetup_state: internal-use state to leave the hwmod in after _setup()
  * @flags: hwmod flags (documented below)
- * @omap_chip: OMAP chips this hwmod is present on
  * @_lock: spinlock serializing operations on this hwmod
  * @node: list node for hwmod list (internal use)
  *
@@ -526,7 +525,6 @@ struct omap_hwmod {
 	char				*clkdm_name;
 	struct clockdomain		*clkdm;
 	char				*vdd_name;
-	struct voltagedomain		*voltdm;
 	struct omap_hwmod_ocp_if	**masters; /* connect to *_IA */
 	struct omap_hwmod_ocp_if	**slaves;  /* connect to *_TA */
 	void				*dev_attr;
@@ -545,7 +543,6 @@ struct omap_hwmod {
 	u8				_int_flags;
 	u8				_state;
 	u8				_postsetup_state;
-	const struct omap_chip_id	omap_chip;
 };
 
 int omap_hwmod_register(struct omap_hwmod **ohs);
diff --git a/arch/arm/plat-omap/include/plat/voltage.h b/arch/arm/plat-omap/include/plat/voltage.h
new file mode 100644
index 0000000..0a6a482
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/voltage.h
@@ -0,0 +1,20 @@
+/*
+ * OMAP Voltage Management Routines
+ *
+ * Copyright (C) 2011, Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ARCH_ARM_OMAP_VOLTAGE_H
+#define __ARCH_ARM_OMAP_VOLTAGE_H
+
+struct voltagedomain;
+
+struct voltagedomain *voltdm_lookup(const char *name);
+int voltdm_scale(struct voltagedomain *voltdm, unsigned long target_volt);
+unsigned long voltdm_get_voltage(struct voltagedomain *voltdm);
+
+#endif
diff --git a/arch/arm/plat-omap/io.c b/arch/arm/plat-omap/io.c
index e9b0e23..333871f 100644
--- a/arch/arm/plat-omap/io.c
+++ b/arch/arm/plat-omap/io.c
@@ -24,11 +24,16 @@
 #define BETWEEN(p,st,sz)	((p) >= (st) && (p) < ((st) + (sz)))
 #define XLATE(p,pst,vst)	((void __iomem *)((p) - (pst) + (vst)))
 
+static int initialized;
+
 /*
  * Intercept ioremap() requests for addresses in our fixed mapping regions.
  */
 void __iomem *omap_ioremap(unsigned long p, size_t size, unsigned int type)
 {
+
+	WARN(!initialized, "Do not use ioremap before init_early\n");
+
 #ifdef CONFIG_ARCH_OMAP1
 	if (cpu_class_is_omap1()) {
 		if (BETWEEN(p, OMAP1_IO_PHYS, OMAP1_IO_SIZE))
@@ -147,3 +152,8 @@ void __init omap_init_consistent_dma_size(void)
 	init_consistent_dma_size(CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE << 20);
 #endif
 }
+
+void __init omap_ioremap_init(void)
+{
+	initialized++;
+}
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index 6c62af1..4b15cd7 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -24,45 +24,40 @@
 #include <linux/slab.h>
 
 #include <plat/mcbsp.h>
-#include <plat/omap_device.h>
 #include <linux/pm_runtime.h>
 
-/* XXX These "sideways" includes are a sign that something is wrong */
-#include "../mach-omap2/cm2xxx_3xxx.h"
-#include "../mach-omap2/cm-regbits-34xx.h"
-
 struct omap_mcbsp **mcbsp_ptr;
-int omap_mcbsp_count, omap_mcbsp_cache_size;
+int omap_mcbsp_count;
+
+#define omap_mcbsp_check_valid_id(id)	(id < omap_mcbsp_count)
+#define id_to_mcbsp_ptr(id)		mcbsp_ptr[id];
 
 static void omap_mcbsp_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
 {
-	if (cpu_class_is_omap1()) {
-		((u16 *)mcbsp->reg_cache)[reg / sizeof(u16)] = (u16)val;
-		__raw_writew((u16)val, mcbsp->io_base + reg);
-	} else if (cpu_is_omap2420()) {
-		((u16 *)mcbsp->reg_cache)[reg / sizeof(u32)] = (u16)val;
-		__raw_writew((u16)val, mcbsp->io_base + reg);
+	void __iomem *addr = mcbsp->io_base + reg * mcbsp->pdata->reg_step;
+
+	if (mcbsp->pdata->reg_size == 2) {
+		((u16 *)mcbsp->reg_cache)[reg] = (u16)val;
+		__raw_writew((u16)val, addr);
 	} else {
-		((u32 *)mcbsp->reg_cache)[reg / sizeof(u32)] = val;
-		__raw_writel(val, mcbsp->io_base + reg);
+		((u32 *)mcbsp->reg_cache)[reg] = val;
+		__raw_writel(val, addr);
 	}
 }
 
 static int omap_mcbsp_read(struct omap_mcbsp *mcbsp, u16 reg, bool from_cache)
 {
-	if (cpu_class_is_omap1()) {
-		return !from_cache ? __raw_readw(mcbsp->io_base + reg) :
-				((u16 *)mcbsp->reg_cache)[reg / sizeof(u16)];
-	} else if (cpu_is_omap2420()) {
-		return !from_cache ? __raw_readw(mcbsp->io_base + reg) :
-				((u16 *)mcbsp->reg_cache)[reg / sizeof(u32)];
+	void __iomem *addr = mcbsp->io_base + reg * mcbsp->pdata->reg_step;
+
+	if (mcbsp->pdata->reg_size == 2) {
+		return !from_cache ? __raw_readw(addr) :
+				     ((u16 *)mcbsp->reg_cache)[reg];
 	} else {
-		return !from_cache ? __raw_readl(mcbsp->io_base + reg) :
-				((u32 *)mcbsp->reg_cache)[reg / sizeof(u32)];
+		return !from_cache ? __raw_readl(addr) :
+				     ((u32 *)mcbsp->reg_cache)[reg];
 	}
 }
 
-#ifdef CONFIG_ARCH_OMAP3
 static void omap_mcbsp_st_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
 {
 	__raw_writel(val, mcbsp->st_data->io_base_st + reg);
@@ -72,7 +67,6 @@ static int omap_mcbsp_st_read(struct omap_mcbsp *mcbsp, u16 reg)
 {
 	return __raw_readl(mcbsp->st_data->io_base_st + reg);
 }
-#endif
 
 #define MCBSP_READ(mcbsp, reg) \
 		omap_mcbsp_read(mcbsp, OMAP_MCBSP_REG_##reg, 0)
@@ -187,7 +181,7 @@ void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config)
 	MCBSP_WRITE(mcbsp, MCR2, config->mcr2);
 	MCBSP_WRITE(mcbsp, MCR1, config->mcr1);
 	MCBSP_WRITE(mcbsp, PCR0, config->pcr0);
-	if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
+	if (mcbsp->pdata->has_ccr) {
 		MCBSP_WRITE(mcbsp, XCCR, config->xccr);
 		MCBSP_WRITE(mcbsp, RCCR, config->rccr);
 	}
@@ -239,46 +233,28 @@ int omap_mcbsp_dma_reg_params(unsigned int id, unsigned int stream)
 	}
 	mcbsp = id_to_mcbsp_ptr(id);
 
-	data_reg = mcbsp->phys_dma_base;
-
-	if (mcbsp->mcbsp_config_type < MCBSP_CONFIG_TYPE2) {
+	if (mcbsp->pdata->reg_size == 2) {
 		if (stream)
-			data_reg += OMAP_MCBSP_REG_DRR1;
+			data_reg = OMAP_MCBSP_REG_DRR1;
 		else
-			data_reg += OMAP_MCBSP_REG_DXR1;
+			data_reg = OMAP_MCBSP_REG_DXR1;
 	} else {
 		if (stream)
-			data_reg += OMAP_MCBSP_REG_DRR;
+			data_reg = OMAP_MCBSP_REG_DRR;
 		else
-			data_reg += OMAP_MCBSP_REG_DXR;
+			data_reg = OMAP_MCBSP_REG_DXR;
 	}
 
-	return data_reg;
+	return mcbsp->phys_dma_base + data_reg * mcbsp->pdata->reg_step;
 }
 EXPORT_SYMBOL(omap_mcbsp_dma_reg_params);
 
-#ifdef CONFIG_ARCH_OMAP3
-static struct omap_device *find_omap_device_by_dev(struct device *dev)
-{
-	struct platform_device *pdev = container_of(dev,
-					struct platform_device, dev);
-	return container_of(pdev, struct omap_device, pdev);
-}
-
 static void omap_st_on(struct omap_mcbsp *mcbsp)
 {
 	unsigned int w;
-	struct omap_device *od;
 
-	od = find_omap_device_by_dev(mcbsp->dev);
-
-	/*
-	 * Sidetone uses McBSP ICLK - which must not idle when sidetones
-	 * are enabled or sidetones start sounding ugly.
-	 */
-	w = omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
-	w &= ~(1 << (mcbsp->id - 2));
-	omap2_cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE);
+	if (mcbsp->pdata->enable_st_clock)
+		mcbsp->pdata->enable_st_clock(mcbsp->id, 1);
 
 	/* Enable McBSP Sidetone */
 	w = MCBSP_READ(mcbsp, SSELCR);
@@ -292,9 +268,6 @@ static void omap_st_on(struct omap_mcbsp *mcbsp)
 static void omap_st_off(struct omap_mcbsp *mcbsp)
 {
 	unsigned int w;
-	struct omap_device *od;
-
-	od = find_omap_device_by_dev(mcbsp->dev);
 
 	w = MCBSP_ST_READ(mcbsp, SSELCR);
 	MCBSP_ST_WRITE(mcbsp, SSELCR, w & ~(ST_SIDETONEEN));
@@ -302,17 +275,13 @@ static void omap_st_off(struct omap_mcbsp *mcbsp)
 	w = MCBSP_READ(mcbsp, SSELCR);
 	MCBSP_WRITE(mcbsp, SSELCR, w & ~(SIDETONEEN));
 
-	w = omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
-	w |= 1 << (mcbsp->id - 2);
-	omap2_cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE);
+	if (mcbsp->pdata->enable_st_clock)
+		mcbsp->pdata->enable_st_clock(mcbsp->id, 0);
 }
 
 static void omap_st_fir_write(struct omap_mcbsp *mcbsp, s16 *fir)
 {
 	u16 val, i;
-	struct omap_device *od;
-
-	od = find_omap_device_by_dev(mcbsp->dev);
 
 	val = MCBSP_ST_READ(mcbsp, SSELCR);
 
@@ -340,9 +309,6 @@ static void omap_st_chgain(struct omap_mcbsp *mcbsp)
 {
 	u16 w;
 	struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
-	struct omap_device *od;
-
-	od = find_omap_device_by_dev(mcbsp->dev);
 
 	w = MCBSP_ST_READ(mcbsp, SSELCR);
 
@@ -525,14 +491,13 @@ void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold)
 {
 	struct omap_mcbsp *mcbsp;
 
-	if (!cpu_is_omap34xx() && !cpu_is_omap44xx())
-		return;
-
 	if (!omap_mcbsp_check_valid_id(id)) {
 		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
 		return;
 	}
 	mcbsp = id_to_mcbsp_ptr(id);
+	if (mcbsp->pdata->buffer_size == 0)
+		return;
 
 	if (threshold && threshold <= mcbsp->max_tx_thres)
 		MCBSP_WRITE(mcbsp, THRSH2, threshold - 1);
@@ -548,14 +513,13 @@ void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold)
 {
 	struct omap_mcbsp *mcbsp;
 
-	if (!cpu_is_omap34xx() && !cpu_is_omap44xx())
-		return;
-
 	if (!omap_mcbsp_check_valid_id(id)) {
 		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
 		return;
 	}
 	mcbsp = id_to_mcbsp_ptr(id);
+	if (mcbsp->pdata->buffer_size == 0)
+		return;
 
 	if (threshold && threshold <= mcbsp->max_rx_thres)
 		MCBSP_WRITE(mcbsp, THRSH1, threshold - 1);
@@ -625,6 +589,8 @@ u16 omap_mcbsp_get_tx_delay(unsigned int id)
 		return -ENODEV;
 	}
 	mcbsp = id_to_mcbsp_ptr(id);
+	if (mcbsp->pdata->buffer_size == 0)
+		return 0;
 
 	/* Returns the number of free locations in the buffer */
 	buffstat = MCBSP_READ(mcbsp, XBUFFSTAT);
@@ -648,6 +614,8 @@ u16 omap_mcbsp_get_rx_delay(unsigned int id)
 		return -ENODEV;
 	}
 	mcbsp = id_to_mcbsp_ptr(id);
+	if (mcbsp->pdata->buffer_size == 0)
+		return 0;
 
 	/* Returns the number of used locations in the buffer */
 	buffstat = MCBSP_READ(mcbsp, RBUFFSTAT);
@@ -683,46 +651,6 @@ int omap_mcbsp_get_dma_op_mode(unsigned int id)
 }
 EXPORT_SYMBOL(omap_mcbsp_get_dma_op_mode);
 
-static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp)
-{
-	struct omap_device *od;
-
-	od = find_omap_device_by_dev(mcbsp->dev);
-	/*
-	 * Enable wakup behavior, smart idle and all wakeups
-	 * REVISIT: some wakeups may be unnecessary
-	 */
-	if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
-		MCBSP_WRITE(mcbsp, WAKEUPEN, XRDYEN | RRDYEN);
-	}
-}
-
-static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp)
-{
-	struct omap_device *od;
-
-	od = find_omap_device_by_dev(mcbsp->dev);
-
-	/*
-	 * Disable wakup behavior, smart idle and all wakeups
-	 */
-	if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
-		/*
-		 * HW bug workaround - If no_idle mode is taken, we need to
-		 * go to smart_idle before going to always_idle, or the
-		 * device will not hit retention anymore.
-		 */
-
-		MCBSP_WRITE(mcbsp, WAKEUPEN, 0);
-	}
-}
-#else
-static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp) {}
-static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp) {}
-static inline void omap_st_start(struct omap_mcbsp *mcbsp) {}
-static inline void omap_st_stop(struct omap_mcbsp *mcbsp) {}
-#endif
-
 int omap_mcbsp_request(unsigned int id)
 {
 	struct omap_mcbsp *mcbsp;
@@ -735,7 +663,7 @@ int omap_mcbsp_request(unsigned int id)
 	}
 	mcbsp = id_to_mcbsp_ptr(id);
 
-	reg_cache = kzalloc(omap_mcbsp_cache_size, GFP_KERNEL);
+	reg_cache = kzalloc(mcbsp->reg_cache_size, GFP_KERNEL);
 	if (!reg_cache) {
 		return -ENOMEM;
 	}
@@ -757,8 +685,9 @@ int omap_mcbsp_request(unsigned int id)
 
 	pm_runtime_get_sync(mcbsp->dev);
 
-	/* Do procedure specific to omap34xx arch, if applicable */
-	omap34xx_mcbsp_request(mcbsp);
+	/* Enable wakeup behavior */
+	if (mcbsp->pdata->has_wakeup)
+		MCBSP_WRITE(mcbsp, WAKEUPEN, XRDYEN | RRDYEN);
 
 	/*
 	 * Make sure that transmitter, receiver and sample-rate generator are
@@ -795,8 +724,9 @@ err_clk_disable:
 	if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free)
 		mcbsp->pdata->ops->free(id);
 
-	/* Do procedure specific to omap34xx arch, if applicable */
-	omap34xx_mcbsp_free(mcbsp);
+	/* Disable wakeup behavior */
+	if (mcbsp->pdata->has_wakeup)
+		MCBSP_WRITE(mcbsp, WAKEUPEN, 0);
 
 	pm_runtime_put_sync(mcbsp->dev);
 
@@ -825,8 +755,9 @@ void omap_mcbsp_free(unsigned int id)
 	if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free)
 		mcbsp->pdata->ops->free(id);
 
-	/* Do procedure specific to omap34xx arch, if applicable */
-	omap34xx_mcbsp_free(mcbsp);
+	/* Disable wakeup behavior */
+	if (mcbsp->pdata->has_wakeup)
+		MCBSP_WRITE(mcbsp, WAKEUPEN, 0);
 
 	pm_runtime_put_sync(mcbsp->dev);
 
@@ -866,7 +797,7 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx)
 	}
 	mcbsp = id_to_mcbsp_ptr(id);
 
-	if (cpu_is_omap34xx())
+	if (mcbsp->st_data)
 		omap_st_start(mcbsp);
 
 	/* Only enable SRG, if McBSP is master */
@@ -904,7 +835,7 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx)
 		MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 7));
 	}
 
-	if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
+	if (mcbsp->pdata->has_ccr) {
 		/* Release the transmitter and receiver */
 		w = MCBSP_READ_CACHE(mcbsp, XCCR);
 		w &= ~(tx ? XDISABLE : 0);
@@ -934,7 +865,7 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx)
 
 	/* Reset transmitter */
 	tx &= 1;
-	if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
+	if (mcbsp->pdata->has_ccr) {
 		w = MCBSP_READ_CACHE(mcbsp, XCCR);
 		w |= (tx ? XDISABLE : 0);
 		MCBSP_WRITE(mcbsp, XCCR, w);
@@ -944,7 +875,7 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx)
 
 	/* Reset receiver */
 	rx &= 1;
-	if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
+	if (mcbsp->pdata->has_ccr) {
 		w = MCBSP_READ_CACHE(mcbsp, RCCR);
 		w |= (rx ? RDISABLE : 0);
 		MCBSP_WRITE(mcbsp, RCCR, w);
@@ -961,39 +892,72 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx)
 		MCBSP_WRITE(mcbsp, SPCR2, w & ~(1 << 6));
 	}
 
-	if (cpu_is_omap34xx())
+	if (mcbsp->st_data)
 		omap_st_stop(mcbsp);
 }
 EXPORT_SYMBOL(omap_mcbsp_stop);
 
-/*
- * The following functions are only required on an OMAP1-only build.
- * mach-omap2/mcbsp.c contains the real functions
- */
-#ifndef CONFIG_ARCH_OMAP2PLUS
 int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id)
 {
-	WARN(1, "%s: should never be called on an OMAP1-only kernel\n",
-	     __func__);
-	return -EINVAL;
+	struct omap_mcbsp *mcbsp;
+	const char *src;
+
+	if (!omap_mcbsp_check_valid_id(id)) {
+		pr_err("%s: Invalid id (%d)\n", __func__, id + 1);
+		return -EINVAL;
+	}
+	mcbsp = id_to_mcbsp_ptr(id);
+
+	if (fck_src_id == MCBSP_CLKS_PAD_SRC)
+		src = "clks_ext";
+	else if (fck_src_id == MCBSP_CLKS_PRCM_SRC)
+		src = "clks_fclk";
+	else
+		return -EINVAL;
+
+	if (mcbsp->pdata->set_clk_src)
+		return mcbsp->pdata->set_clk_src(mcbsp->dev, mcbsp->fclk, src);
+	else
+		return -EINVAL;
 }
+EXPORT_SYMBOL(omap2_mcbsp_set_clks_src);
 
 void omap2_mcbsp1_mux_clkr_src(u8 mux)
 {
-	WARN(1, "%s: should never be called on an OMAP1-only kernel\n",
-	     __func__);
-	return;
+	struct omap_mcbsp *mcbsp;
+	const char *src;
+
+	if (mux == CLKR_SRC_CLKR)
+		src = "clkr";
+	else if (mux == CLKR_SRC_CLKX)
+		src = "clkx";
+	else
+		return;
+
+	mcbsp = id_to_mcbsp_ptr(0);
+	if (mcbsp->pdata->mux_signal)
+		mcbsp->pdata->mux_signal(mcbsp->dev, "clkr", src);
 }
+EXPORT_SYMBOL(omap2_mcbsp1_mux_clkr_src);
 
 void omap2_mcbsp1_mux_fsr_src(u8 mux)
 {
-	WARN(1, "%s: should never be called on an OMAP1-only kernel\n",
-	     __func__);
-	return;
+	struct omap_mcbsp *mcbsp;
+	const char *src;
+
+	if (mux == FSR_SRC_FSR)
+		src = "fsr";
+	else if (mux == FSR_SRC_FSX)
+		src = "fsx";
+	else
+		return;
+
+	mcbsp = id_to_mcbsp_ptr(0);
+	if (mcbsp->pdata->mux_signal)
+		mcbsp->pdata->mux_signal(mcbsp->dev, "fsr", src);
 }
-#endif
+EXPORT_SYMBOL(omap2_mcbsp1_mux_fsr_src);
 
-#ifdef CONFIG_ARCH_OMAP3
 #define max_thres(m)			(mcbsp->pdata->buffer_size)
 #define valid_threshold(m, val)		((val) <= max_thres(m))
 #define THRESHOLD_PROP_BUILDER(prop)					\
@@ -1084,6 +1048,17 @@ unlock:
 
 static DEVICE_ATTR(dma_op_mode, 0644, dma_op_mode_show, dma_op_mode_store);
 
+static const struct attribute *additional_attrs[] = {
+	&dev_attr_max_tx_thres.attr,
+	&dev_attr_max_rx_thres.attr,
+	&dev_attr_dma_op_mode.attr,
+	NULL,
+};
+
+static const struct attribute_group additional_attr_group = {
+	.attrs = (struct attribute **)additional_attrs,
+};
+
 static ssize_t st_taps_show(struct device *dev,
 			    struct device_attribute *attr, char *buf)
 {
@@ -1142,27 +1117,6 @@ out:
 
 static DEVICE_ATTR(st_taps, 0644, st_taps_show, st_taps_store);
 
-static const struct attribute *additional_attrs[] = {
-	&dev_attr_max_tx_thres.attr,
-	&dev_attr_max_rx_thres.attr,
-	&dev_attr_dma_op_mode.attr,
-	NULL,
-};
-
-static const struct attribute_group additional_attr_group = {
-	.attrs = (struct attribute **)additional_attrs,
-};
-
-static inline int __devinit omap_additional_add(struct device *dev)
-{
-	return sysfs_create_group(&dev->kobj, &additional_attr_group);
-}
-
-static inline void __devexit omap_additional_remove(struct device *dev)
-{
-	sysfs_remove_group(&dev->kobj, &additional_attr_group);
-}
-
 static const struct attribute *sidetone_attrs[] = {
 	&dev_attr_st_taps.attr,
 	NULL,
@@ -1172,10 +1126,9 @@ static const struct attribute_group sidetone_attr_group = {
 	.attrs = (struct attribute **)sidetone_attrs,
 };
 
-static int __devinit omap_st_add(struct omap_mcbsp *mcbsp)
+static int __devinit omap_st_add(struct omap_mcbsp *mcbsp,
+				 struct resource *res)
 {
-	struct platform_device *pdev;
-	struct resource *res;
 	struct omap_mcbsp_st_data *st_data;
 	int err;
 
@@ -1185,9 +1138,6 @@ static int __devinit omap_st_add(struct omap_mcbsp *mcbsp)
 		goto err1;
 	}
 
-	pdev = container_of(mcbsp->dev, struct platform_device, dev);
-
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sidetone");
 	st_data->io_base_st = ioremap(res->start, resource_size(res));
 	if (!st_data->io_base_st) {
 		err = -ENOMEM;
@@ -1214,59 +1164,10 @@ static void __devexit omap_st_remove(struct omap_mcbsp *mcbsp)
 {
 	struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
 
-	if (st_data) {
-		sysfs_remove_group(&mcbsp->dev->kobj, &sidetone_attr_group);
-		iounmap(st_data->io_base_st);
-		kfree(st_data);
-	}
-}
-
-static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp)
-{
-	mcbsp->dma_op_mode = MCBSP_DMA_MODE_ELEMENT;
-	if (cpu_is_omap34xx()) {
-		/*
-		 * Initially configure the maximum thresholds to a safe value.
-		 * The McBSP FIFO usage with these values should not go under
-		 * 16 locations.
-		 * If the whole FIFO without safety buffer is used, than there
-		 * is a possibility that the DMA will be not able to push the
-		 * new data on time, causing channel shifts in runtime.
-		 */
-		mcbsp->max_tx_thres = max_thres(mcbsp) - 0x10;
-		mcbsp->max_rx_thres = max_thres(mcbsp) - 0x10;
-		/*
-		 * REVISIT: Set dmap_op_mode to THRESHOLD as default
-		 * for mcbsp2 instances.
-		 */
-		if (omap_additional_add(mcbsp->dev))
-			dev_warn(mcbsp->dev,
-				"Unable to create additional controls\n");
-
-		if (mcbsp->id == 2 || mcbsp->id == 3)
-			if (omap_st_add(mcbsp))
-				dev_warn(mcbsp->dev,
-				 "Unable to create sidetone controls\n");
-
-	} else {
-		mcbsp->max_tx_thres = -EINVAL;
-		mcbsp->max_rx_thres = -EINVAL;
-	}
-}
-
-static inline void __devexit omap34xx_device_exit(struct omap_mcbsp *mcbsp)
-{
-	if (cpu_is_omap34xx()) {
-		omap_additional_remove(mcbsp->dev);
-
-		if (mcbsp->id == 2 || mcbsp->id == 3)
-			omap_st_remove(mcbsp);
-	}
+	sysfs_remove_group(&mcbsp->dev->kobj, &sidetone_attr_group);
+	iounmap(st_data->io_base_st);
+	kfree(st_data);
 }
-#else
-static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp) {}
-static inline void __devexit omap34xx_device_exit(struct omap_mcbsp *mcbsp) {}
-#endif /* CONFIG_ARCH_OMAP3 */
 
 /*
  * McBSP1 and McBSP3 are directly mapped on 1610 and 1510.
@@ -1316,7 +1217,7 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
 		}
 	}
 	mcbsp->phys_base = res->start;
-	omap_mcbsp_cache_size = resource_size(res);
+	mcbsp->reg_cache_size = resource_size(res);
 	mcbsp->io_base = ioremap(res->start, resource_size(res));
 	if (!mcbsp->io_base) {
 		ret = -ENOMEM;
@@ -1364,15 +1265,52 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
 	mcbsp->pdata = pdata;
 	mcbsp->dev = &pdev->dev;
 	mcbsp_ptr[id] = mcbsp;
-	mcbsp->mcbsp_config_type = pdata->mcbsp_config_type;
 	platform_set_drvdata(pdev, mcbsp);
 	pm_runtime_enable(mcbsp->dev);
 
-	/* Initialize mcbsp properties for OMAP34XX if needed / applicable */
-	omap34xx_device_init(mcbsp);
+	mcbsp->dma_op_mode = MCBSP_DMA_MODE_ELEMENT;
+	if (mcbsp->pdata->buffer_size) {
+		/*
+		 * Initially configure the maximum thresholds to a safe value.
+		 * The McBSP FIFO usage with these values should not go under
+		 * 16 locations.
+		 * If the whole FIFO without safety buffer is used, than there
+		 * is a possibility that the DMA will be not able to push the
+		 * new data on time, causing channel shifts in runtime.
+		 */
+		mcbsp->max_tx_thres = max_thres(mcbsp) - 0x10;
+		mcbsp->max_rx_thres = max_thres(mcbsp) - 0x10;
+
+		ret = sysfs_create_group(&mcbsp->dev->kobj,
+					 &additional_attr_group);
+		if (ret) {
+			dev_err(mcbsp->dev,
+				"Unable to create additional controls\n");
+			goto err_thres;
+		}
+	} else {
+		mcbsp->max_tx_thres = -EINVAL;
+		mcbsp->max_rx_thres = -EINVAL;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sidetone");
+	if (res) {
+		ret = omap_st_add(mcbsp, res);
+		if (ret) {
+			dev_err(mcbsp->dev,
+				"Unable to create sidetone controls\n");
+			goto err_st;
+		}
+	}
 
 	return 0;
 
+err_st:
+	if (mcbsp->pdata->buffer_size)
+		sysfs_remove_group(&mcbsp->dev->kobj,
+				   &additional_attr_group);
+err_thres:
+	clk_put(mcbsp->fclk);
 err_res:
 	iounmap(mcbsp->io_base);
 err_ioremap:
@@ -1392,7 +1330,12 @@ static int __devexit omap_mcbsp_remove(struct platform_device *pdev)
 				mcbsp->pdata->ops->free)
 			mcbsp->pdata->ops->free(mcbsp->id);
 
-		omap34xx_device_exit(mcbsp);
+		if (mcbsp->pdata->buffer_size)
+			sysfs_remove_group(&mcbsp->dev->kobj,
+					   &additional_attr_group);
+
+		if (mcbsp->st_data)
+			omap_st_remove(mcbsp);
 
 		clk_put(mcbsp->fclk);
 
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index 02609ee..cd90bed 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -85,6 +85,8 @@
 #include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/notifier.h>
 
 #include <plat/omap_device.h>
 #include <plat/omap_hwmod.h>
@@ -94,6 +96,23 @@
 #define USE_WAKEUP_LAT			0
 #define IGNORE_WAKEUP_LAT		1
 
+static int omap_device_register(struct platform_device *pdev);
+static int omap_early_device_register(struct platform_device *pdev);
+static struct omap_device *omap_device_alloc(struct platform_device *pdev,
+				      struct omap_hwmod **ohs, int oh_cnt,
+				      struct omap_device_pm_latency *pm_lats,
+				      int pm_lats_cnt);
+static void omap_device_delete(struct omap_device *od);
+
+
+static struct omap_device_pm_latency omap_default_latency[] = {
+	{
+		.deactivate_func = omap_device_idle_hwmods,
+		.activate_func   = omap_device_enable_hwmods,
+		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+	}
+};
+
 /* Private functions */
 
 /**
@@ -114,7 +133,7 @@ static int _omap_device_activate(struct omap_device *od, u8 ignore_lat)
 {
 	struct timespec a, b, c;
 
-	pr_debug("omap_device: %s: activating\n", od->pdev.name);
+	dev_dbg(&od->pdev->dev, "omap_device: activating\n");
 
 	while (od->pm_lat_level > 0) {
 		struct omap_device_pm_latency *odpl;
@@ -138,25 +157,24 @@ static int _omap_device_activate(struct omap_device *od, u8 ignore_lat)
 		c = timespec_sub(b, a);
 		act_lat = timespec_to_ns(&c);
 
-		pr_debug("omap_device: %s: pm_lat %d: activate: elapsed time "
-			 "%llu nsec\n", od->pdev.name, od->pm_lat_level,
-			 act_lat);
+		dev_dbg(&od->pdev->dev,
+			"omap_device: pm_lat %d: activate: elapsed time "
+			"%llu nsec\n", od->pm_lat_level, act_lat);
 
 		if (act_lat > odpl->activate_lat) {
 			odpl->activate_lat_worst = act_lat;
 			if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) {
 				odpl->activate_lat = act_lat;
-				pr_warning("omap_device: %s.%d: new worst case "
-					   "activate latency %d: %llu\n",
-					   od->pdev.name, od->pdev.id,
-					   od->pm_lat_level, act_lat);
+				dev_dbg(&od->pdev->dev,
+					"new worst case activate latency "
+					"%d: %llu\n",
+					od->pm_lat_level, act_lat);
 			} else
-				pr_warning("omap_device: %s.%d: activate "
-					   "latency %d higher than exptected. "
-					   "(%llu > %d)\n",
-					   od->pdev.name, od->pdev.id,
-					   od->pm_lat_level, act_lat,
-					   odpl->activate_lat);
+				dev_warn(&od->pdev->dev,
+					 "activate latency %d "
+					 "higher than exptected. (%llu > %d)\n",
+					 od->pm_lat_level, act_lat,
+					 odpl->activate_lat);
 		}
 
 		od->dev_wakeup_lat -= odpl->activate_lat;
@@ -183,7 +201,7 @@ static int _omap_device_deactivate(struct omap_device *od, u8 ignore_lat)
 {
 	struct timespec a, b, c;
 
-	pr_debug("omap_device: %s: deactivating\n", od->pdev.name);
+	dev_dbg(&od->pdev->dev, "omap_device: deactivating\n");
 
 	while (od->pm_lat_level < od->pm_lats_cnt) {
 		struct omap_device_pm_latency *odpl;
@@ -206,28 +224,26 @@ static int _omap_device_deactivate(struct omap_device *od, u8 ignore_lat)
 		c = timespec_sub(b, a);
 		deact_lat = timespec_to_ns(&c);
 
-		pr_debug("omap_device: %s: pm_lat %d: deactivate: elapsed time "
-			 "%llu nsec\n", od->pdev.name, od->pm_lat_level,
-			 deact_lat);
+		dev_dbg(&od->pdev->dev,
+			"omap_device: pm_lat %d: deactivate: elapsed time "
+			"%llu nsec\n", od->pm_lat_level, deact_lat);
 
 		if (deact_lat > odpl->deactivate_lat) {
 			odpl->deactivate_lat_worst = deact_lat;
 			if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) {
 				odpl->deactivate_lat = deact_lat;
-				pr_warning("omap_device: %s.%d: new worst case "
-					   "deactivate latency %d: %llu\n",
-					   od->pdev.name, od->pdev.id,
-					   od->pm_lat_level, deact_lat);
+				dev_dbg(&od->pdev->dev,
+					"new worst case deactivate latency "
+					"%d: %llu\n",
+					od->pm_lat_level, deact_lat);
 			} else
-				pr_warning("omap_device: %s.%d: deactivate "
-					   "latency %d higher than exptected. "
-					   "(%llu > %d)\n",
-					   od->pdev.name, od->pdev.id,
-					   od->pm_lat_level, deact_lat,
-					   odpl->deactivate_lat);
+				dev_warn(&od->pdev->dev,
+					 "deactivate latency %d "
+					 "higher than exptected. (%llu > %d)\n",
+					 od->pm_lat_level, deact_lat,
+					 odpl->deactivate_lat);
 		}
 
-
 		od->dev_wakeup_lat += odpl->activate_lat;
 
 		od->pm_lat_level++;
@@ -245,28 +261,27 @@ static void _add_clkdev(struct omap_device *od, const char *clk_alias,
 	if (!clk_alias || !clk_name)
 		return;
 
-	pr_debug("omap_device: %s: Creating %s -> %s\n",
-		 dev_name(&od->pdev.dev), clk_alias, clk_name);
+	dev_dbg(&od->pdev->dev, "Creating %s -> %s\n", clk_alias, clk_name);
 
-	r = clk_get_sys(dev_name(&od->pdev.dev), clk_alias);
+	r = clk_get_sys(dev_name(&od->pdev->dev), clk_alias);
 	if (!IS_ERR(r)) {
-		pr_warning("omap_device: %s: alias %s already exists\n",
-			   dev_name(&od->pdev.dev), clk_alias);
+		dev_warn(&od->pdev->dev,
+			 "alias %s already exists\n", clk_alias);
 		clk_put(r);
 		return;
 	}
 
 	r = omap_clk_get_by_name(clk_name);
 	if (IS_ERR(r)) {
-		pr_err("omap_device: %s: omap_clk_get_by_name for %s failed\n",
-		       dev_name(&od->pdev.dev), clk_name);
+		dev_err(&od->pdev->dev,
+			"omap_clk_get_by_name for %s failed\n", clk_name);
 		return;
 	}
 
-	l = clkdev_alloc(r, clk_alias, dev_name(&od->pdev.dev));
+	l = clkdev_alloc(r, clk_alias, dev_name(&od->pdev->dev));
 	if (!l) {
-		pr_err("omap_device: %s: clkdev_alloc for %s failed\n",
-		       dev_name(&od->pdev.dev), clk_alias);
+		dev_err(&od->pdev->dev,
+			"clkdev_alloc for %s failed\n", clk_alias);
 		return;
 	}
 
@@ -304,6 +319,96 @@ static void _add_hwmod_clocks_clkdev(struct omap_device *od,
 }
 
 
+static struct dev_pm_domain omap_device_pm_domain;
+
+/**
+ * omap_device_build_from_dt - build an omap_device with multiple hwmods
+ * @pdev_name: name of the platform_device driver to use
+ * @pdev_id: this platform_device's connection ID
+ * @oh: ptr to the single omap_hwmod that backs this omap_device
+ * @pdata: platform_data ptr to associate with the platform_device
+ * @pdata_len: amount of memory pointed to by @pdata
+ * @pm_lats: pointer to a omap_device_pm_latency array for this device
+ * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
+ * @is_early_device: should the device be registered as an early device or not
+ *
+ * Function for building an omap_device already registered from device-tree
+ *
+ * Returns 0 or PTR_ERR() on error.
+ */
+static int omap_device_build_from_dt(struct platform_device *pdev)
+{
+	struct omap_hwmod **hwmods;
+	struct omap_device *od;
+	struct omap_hwmod *oh;
+	struct device_node *node = pdev->dev.of_node;
+	const char *oh_name;
+	int oh_cnt, i, ret = 0;
+
+	oh_cnt = of_property_count_strings(node, "ti,hwmods");
+	if (!oh_cnt || IS_ERR_VALUE(oh_cnt)) {
+		dev_warn(&pdev->dev, "No 'hwmods' to build omap_device\n");
+		return -ENODEV;
+	}
+
+	hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
+	if (!hwmods) {
+		ret = -ENOMEM;
+		goto odbfd_exit;
+	}
+
+	for (i = 0; i < oh_cnt; i++) {
+		of_property_read_string_index(node, "ti,hwmods", i, &oh_name);
+		oh = omap_hwmod_lookup(oh_name);
+		if (!oh) {
+			dev_err(&pdev->dev, "Cannot lookup hwmod '%s'\n",
+				oh_name);
+			ret = -EINVAL;
+			goto odbfd_exit1;
+		}
+		hwmods[i] = oh;
+	}
+
+	od = omap_device_alloc(pdev, hwmods, oh_cnt, NULL, 0);
+	if (!od) {
+		dev_err(&pdev->dev, "Cannot allocate omap_device for :%s\n",
+			oh_name);
+		ret = PTR_ERR(od);
+		goto odbfd_exit1;
+	}
+
+	if (of_get_property(node, "ti,no_idle_on_suspend", NULL))
+		omap_device_disable_idle_on_suspend(pdev);
+
+	pdev->dev.pm_domain = &omap_device_pm_domain;
+
+odbfd_exit1:
+	kfree(hwmods);
+odbfd_exit:
+	return ret;
+}
+
+static int _omap_device_notifier_call(struct notifier_block *nb,
+				      unsigned long event, void *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+
+	switch (event) {
+	case BUS_NOTIFY_ADD_DEVICE:
+		if (pdev->dev.of_node)
+			omap_device_build_from_dt(pdev);
+		break;
+
+	case BUS_NOTIFY_DEL_DEVICE:
+		if (pdev->archdata.od)
+			omap_device_delete(pdev->archdata.od);
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
+
 /* Public functions for use by core code */
 
 /**
@@ -343,7 +448,7 @@ u32 omap_device_get_context_loss_count(struct platform_device *pdev)
  * much memory to allocate before calling
  * omap_device_fill_resources().  Returns the count.
  */
-int omap_device_count_resources(struct omap_device *od)
+static int omap_device_count_resources(struct omap_device *od)
 {
 	int c = 0;
 	int i;
@@ -352,7 +457,7 @@ int omap_device_count_resources(struct omap_device *od)
 		c += omap_hwmod_count_resources(od->hwmods[i]);
 
 	pr_debug("omap_device: %s: counted %d total resources across %d "
-		 "hwmods\n", od->pdev.name, c, od->hwmods_cnt);
+		 "hwmods\n", od->pdev->name, c, od->hwmods_cnt);
 
 	return c;
 }
@@ -374,7 +479,8 @@ int omap_device_count_resources(struct omap_device *od)
  * functions to get device resources.  Hacking around the existing
  * platform_device code wastes memory.  Returns 0.
  */
-int omap_device_fill_resources(struct omap_device *od, struct resource *res)
+static int omap_device_fill_resources(struct omap_device *od,
+				      struct resource *res)
 {
 	int c = 0;
 	int i, r;
@@ -389,6 +495,113 @@ int omap_device_fill_resources(struct omap_device *od, struct resource *res)
 }
 
 /**
+ * omap_device_alloc - allocate an omap_device
+ * @pdev: platform_device that will be included in this omap_device
+ * @oh: ptr to the single omap_hwmod that backs this omap_device
+ * @pdata: platform_data ptr to associate with the platform_device
+ * @pdata_len: amount of memory pointed to by @pdata
+ * @pm_lats: pointer to a omap_device_pm_latency array for this device
+ * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
+ *
+ * Convenience function for allocating an omap_device structure and filling
+ * hwmods, resources and pm_latency attributes.
+ *
+ * Returns an struct omap_device pointer or ERR_PTR() on error;
+ */
+static struct omap_device *omap_device_alloc(struct platform_device *pdev,
+					struct omap_hwmod **ohs, int oh_cnt,
+					struct omap_device_pm_latency *pm_lats,
+					int pm_lats_cnt)
+{
+	int ret = -ENOMEM;
+	struct omap_device *od;
+	struct resource *res = NULL;
+	int i, res_count;
+	struct omap_hwmod **hwmods;
+
+	od = kzalloc(sizeof(struct omap_device), GFP_KERNEL);
+	if (!od) {
+		ret = -ENOMEM;
+		goto oda_exit1;
+	}
+	od->hwmods_cnt = oh_cnt;
+
+	hwmods = kmemdup(ohs, sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
+	if (!hwmods)
+		goto oda_exit2;
+
+	od->hwmods = hwmods;
+	od->pdev = pdev;
+
+	/*
+	 * HACK: Ideally the resources from DT should match, and hwmod
+	 * should just add the missing ones. Since the name is not
+	 * properly populated by DT, stick to hwmod resources only.
+	 */
+	if (pdev->num_resources && pdev->resource)
+		dev_warn(&pdev->dev, "%s(): resources already allocated %d\n",
+			__func__, pdev->num_resources);
+
+	res_count = omap_device_count_resources(od);
+	if (res_count > 0) {
+		dev_dbg(&pdev->dev, "%s(): resources allocated from hwmod %d\n",
+			__func__, res_count);
+		res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL);
+		if (!res)
+			goto oda_exit3;
+
+		omap_device_fill_resources(od, res);
+
+		ret = platform_device_add_resources(pdev, res, res_count);
+		kfree(res);
+
+		if (ret)
+			goto oda_exit3;
+	}
+
+	if (!pm_lats) {
+		pm_lats = omap_default_latency;
+		pm_lats_cnt = ARRAY_SIZE(omap_default_latency);
+	}
+
+	od->pm_lats_cnt = pm_lats_cnt;
+	od->pm_lats = kmemdup(pm_lats,
+			sizeof(struct omap_device_pm_latency) * pm_lats_cnt,
+			GFP_KERNEL);
+	if (!od->pm_lats)
+		goto oda_exit3;
+
+	pdev->archdata.od = od;
+
+	for (i = 0; i < oh_cnt; i++) {
+		hwmods[i]->od = od;
+		_add_hwmod_clocks_clkdev(od, hwmods[i]);
+	}
+
+	return od;
+
+oda_exit3:
+	kfree(hwmods);
+oda_exit2:
+	kfree(od);
+oda_exit1:
+	dev_err(&pdev->dev, "omap_device: build failed (%d)\n", ret);
+
+	return ERR_PTR(ret);
+}
+
+static void omap_device_delete(struct omap_device *od)
+{
+	if (!od)
+		return;
+
+	od->pdev->archdata.od = NULL;
+	kfree(od->pm_lats);
+	kfree(od->hwmods);
+	kfree(od);
+}
+
+/**
  * omap_device_build - build and register an omap_device with one omap_hwmod
  * @pdev_name: name of the platform_device driver to use
  * @pdev_id: this platform_device's connection ID
@@ -405,7 +618,7 @@ int omap_device_fill_resources(struct omap_device *od, struct resource *res)
  * information.  Returns ERR_PTR(-EINVAL) if @oh is NULL; otherwise,
  * passes along the return value of omap_device_build_ss().
  */
-struct omap_device *omap_device_build(const char *pdev_name, int pdev_id,
+struct platform_device *omap_device_build(const char *pdev_name, int pdev_id,
 				      struct omap_hwmod *oh, void *pdata,
 				      int pdata_len,
 				      struct omap_device_pm_latency *pm_lats,
@@ -438,18 +651,15 @@ struct omap_device *omap_device_build(const char *pdev_name, int pdev_id,
  * platform_device record.  Returns an ERR_PTR() on error, or passes
  * along the return value of omap_device_register().
  */
-struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
+struct platform_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
 					 struct omap_hwmod **ohs, int oh_cnt,
 					 void *pdata, int pdata_len,
 					 struct omap_device_pm_latency *pm_lats,
 					 int pm_lats_cnt, int is_early_device)
 {
 	int ret = -ENOMEM;
+	struct platform_device *pdev;
 	struct omap_device *od;
-	char *pdev_name2;
-	struct resource *res = NULL;
-	int i, res_count;
-	struct omap_hwmod **hwmods;
 
 	if (!ohs || oh_cnt == 0 || !pdev_name)
 		return ERR_PTR(-EINVAL);
@@ -457,72 +667,40 @@ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
 	if (!pdata && pdata_len > 0)
 		return ERR_PTR(-EINVAL);
 
-	pr_debug("omap_device: %s: building with %d hwmods\n", pdev_name,
-		 oh_cnt);
-
-	od = kzalloc(sizeof(struct omap_device), GFP_KERNEL);
-	if (!od)
-		return ERR_PTR(-ENOMEM);
+	pdev = platform_device_alloc(pdev_name, pdev_id);
+	if (!pdev) {
+		ret = -ENOMEM;
+		goto odbs_exit;
+	}
 
-	od->hwmods_cnt = oh_cnt;
+	/* Set the dev_name early to allow dev_xxx in omap_device_alloc */
+	if (pdev->id != -1)
+		dev_set_name(&pdev->dev, "%s.%d", pdev->name,  pdev->id);
+	else
+		dev_set_name(&pdev->dev, "%s", pdev->name);
 
-	hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt,
-			 GFP_KERNEL);
-	if (!hwmods)
+	od = omap_device_alloc(pdev, ohs, oh_cnt, pm_lats, pm_lats_cnt);
+	if (!od)
 		goto odbs_exit1;
 
-	memcpy(hwmods, ohs, sizeof(struct omap_hwmod *) * oh_cnt);
-	od->hwmods = hwmods;
-
-	pdev_name2 = kzalloc(strlen(pdev_name) + 1, GFP_KERNEL);
-	if (!pdev_name2)
-		goto odbs_exit2;
-	strcpy(pdev_name2, pdev_name);
-
-	od->pdev.name = pdev_name2;
-	od->pdev.id = pdev_id;
-
-	res_count = omap_device_count_resources(od);
-	if (res_count > 0) {
-		res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL);
-		if (!res)
-			goto odbs_exit3;
-	}
-	omap_device_fill_resources(od, res);
-
-	od->pdev.num_resources = res_count;
-	od->pdev.resource = res;
-
-	ret = platform_device_add_data(&od->pdev, pdata, pdata_len);
+	ret = platform_device_add_data(pdev, pdata, pdata_len);
 	if (ret)
-		goto odbs_exit4;
-
-	od->pm_lats = pm_lats;
-	od->pm_lats_cnt = pm_lats_cnt;
+		goto odbs_exit2;
 
 	if (is_early_device)
-		ret = omap_early_device_register(od);
+		ret = omap_early_device_register(pdev);
 	else
-		ret = omap_device_register(od);
-
-	for (i = 0; i < oh_cnt; i++) {
-		hwmods[i]->od = od;
-		_add_hwmod_clocks_clkdev(od, hwmods[i]);
-	}
-
+		ret = omap_device_register(pdev);
 	if (ret)
-		goto odbs_exit4;
+		goto odbs_exit2;
 
-	return od;
+	return pdev;
 
-odbs_exit4:
-	kfree(res);
-odbs_exit3:
-	kfree(pdev_name2);
 odbs_exit2:
-	kfree(hwmods);
+	omap_device_delete(od);
 odbs_exit1:
-	kfree(od);
+	platform_device_put(pdev);
+odbs_exit:
 
 	pr_err("omap_device: %s: build failed (%d)\n", pdev_name, ret);
 
@@ -538,11 +716,11 @@ odbs_exit1:
  * platform_early_add_device() on the underlying platform_device.
  * Returns 0 by default.
  */
-int omap_early_device_register(struct omap_device *od)
+static int omap_early_device_register(struct platform_device *pdev)
 {
 	struct platform_device *devices[1];
 
-	devices[0] = &(od->pdev);
+	devices[0] = pdev;
 	early_platform_add_devices(devices, 1);
 	return 0;
 }
@@ -638,13 +816,13 @@ static struct dev_pm_domain omap_device_pm_domain = {
  * platform_device_register() on the underlying platform_device.
  * Returns the return value of platform_device_register().
  */
-int omap_device_register(struct omap_device *od)
+static int omap_device_register(struct platform_device *pdev)
 {
-	pr_debug("omap_device: %s: registering\n", od->pdev.name);
+	pr_debug("omap_device: %s: registering\n", pdev->name);
 
-	od->pdev.dev.parent = &omap_device_parent;
-	od->pdev.dev.pm_domain = &omap_device_pm_domain;
-	return platform_device_register(&od->pdev);
+	pdev->dev.parent = &omap_device_parent;
+	pdev->dev.pm_domain = &omap_device_pm_domain;
+	return platform_device_add(pdev);
 }
 
 
@@ -671,8 +849,9 @@ int omap_device_enable(struct platform_device *pdev)
 	od = to_omap_device(pdev);
 
 	if (od->_state == OMAP_DEVICE_STATE_ENABLED) {
-		WARN(1, "omap_device: %s.%d: %s() called from invalid state %d\n",
-		     od->pdev.name, od->pdev.id, __func__, od->_state);
+		dev_warn(&pdev->dev,
+			 "omap_device: %s() called from invalid state %d\n",
+			 __func__, od->_state);
 		return -EINVAL;
 	}
 
@@ -710,8 +889,9 @@ int omap_device_idle(struct platform_device *pdev)
 	od = to_omap_device(pdev);
 
 	if (od->_state != OMAP_DEVICE_STATE_ENABLED) {
-		WARN(1, "omap_device: %s.%d: %s() called from invalid state %d\n",
-		     od->pdev.name, od->pdev.id, __func__, od->_state);
+		dev_warn(&pdev->dev,
+			 "omap_device: %s() called from invalid state %d\n",
+			 __func__, od->_state);
 		return -EINVAL;
 	}
 
@@ -742,8 +922,9 @@ int omap_device_shutdown(struct platform_device *pdev)
 
 	if (od->_state != OMAP_DEVICE_STATE_ENABLED &&
 	    od->_state != OMAP_DEVICE_STATE_IDLE) {
-		WARN(1, "omap_device: %s.%d: %s() called from invalid state %d\n",
-		     od->pdev.name, od->pdev.id, __func__, od->_state);
+		dev_warn(&pdev->dev,
+			 "omap_device: %s() called from invalid state %d\n",
+			 __func__, od->_state);
 		return -EINVAL;
 	}
 
@@ -837,6 +1018,42 @@ void __iomem *omap_device_get_rt_va(struct omap_device *od)
 	return omap_hwmod_get_mpu_rt_va(od->hwmods[0]);
 }
 
+/**
+ * omap_device_get_by_hwmod_name() - convert a hwmod name to
+ * device pointer.
+ * @oh_name: name of the hwmod device
+ *
+ * Returns back a struct device * pointer associated with a hwmod
+ * device represented by a hwmod_name
+ */
+struct device *omap_device_get_by_hwmod_name(const char *oh_name)
+{
+	struct omap_hwmod *oh;
+
+	if (!oh_name) {
+		WARN(1, "%s: no hwmod name!\n", __func__);
+		return ERR_PTR(-EINVAL);
+	}
+
+	oh = omap_hwmod_lookup(oh_name);
+	if (IS_ERR_OR_NULL(oh)) {
+		WARN(1, "%s: no hwmod for %s\n", __func__,
+			oh_name);
+		return ERR_PTR(oh ? PTR_ERR(oh) : -ENODEV);
+	}
+	if (IS_ERR_OR_NULL(oh->od)) {
+		WARN(1, "%s: no omap_device for %s\n", __func__,
+			oh_name);
+		return ERR_PTR(oh->od ? PTR_ERR(oh->od) : -ENODEV);
+	}
+
+	if (IS_ERR_OR_NULL(oh->od->pdev))
+		return ERR_PTR(oh->od->pdev ? PTR_ERR(oh->od->pdev) : -ENODEV);
+
+	return &oh->od->pdev->dev;
+}
+EXPORT_SYMBOL(omap_device_get_by_hwmod_name);
+
 /*
  * Public functions intended for use in omap_device_pm_latency
  * .activate_func and .deactivate_func function pointers
@@ -917,8 +1134,13 @@ struct device omap_device_parent = {
 	.parent         = &platform_bus,
 };
 
+static struct notifier_block platform_nb = {
+	.notifier_call = _omap_device_notifier_call,
+};
+
 static int __init omap_device_init(void)
 {
+	bus_register_notifier(&platform_bus_type, &platform_nb);
 	return device_register(&omap_device_parent);
 }
 core_initcall(omap_device_init);
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index 363c91e..8b28664 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -19,7 +19,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
-#include <linux/omapfb.h>
 
 #include <asm/tlb.h>
 #include <asm/cacheflush.h>
@@ -29,10 +28,8 @@
 #include <plat/sram.h>
 #include <plat/board.h>
 #include <plat/cpu.h>
-#include <plat/vram.h>
 
 #include "sram.h"
-#include "fb.h"
 
 /* XXX These "sideways" includes are a sign that something is wrong */
 #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
@@ -41,16 +38,9 @@
 #endif
 
 #define OMAP1_SRAM_PA		0x20000000
-#define OMAP1_SRAM_VA		VMALLOC_END
 #define OMAP2_SRAM_PUB_PA	(OMAP2_SRAM_PA + 0xf800)
-#define OMAP2_SRAM_VA		0xfe400000
-#define OMAP2_SRAM_PUB_VA	(OMAP2_SRAM_VA + 0x800)
-#define OMAP3_SRAM_VA           0xfe400000
 #define OMAP3_SRAM_PUB_PA       (OMAP3_SRAM_PA + 0x8000)
-#define OMAP3_SRAM_PUB_VA       (OMAP3_SRAM_VA + 0x8000)
-#define OMAP4_SRAM_VA		0xfe400000
 #define OMAP4_SRAM_PUB_PA	(OMAP4_SRAM_PA + 0x4000)
-#define OMAP4_SRAM_PUB_VA	(OMAP4_SRAM_VA + 0x4000)
 
 #if defined(CONFIG_ARCH_OMAP2PLUS)
 #define SRAM_BOOTLOADER_SZ	0x00
@@ -73,9 +63,9 @@
 #define ROUND_DOWN(value,boundary)	((value) & (~((boundary)-1)))
 
 static unsigned long omap_sram_start;
-static unsigned long omap_sram_base;
+static void __iomem *omap_sram_base;
 static unsigned long omap_sram_size;
-static unsigned long omap_sram_ceil;
+static void __iomem *omap_sram_ceil;
 
 /*
  * Depending on the target RAMFS firewall setup, the public usable amount of
@@ -112,12 +102,9 @@ static int is_sram_locked(void)
  */
 static void __init omap_detect_sram(void)
 {
-	unsigned long reserved;
-
 	if (cpu_class_is_omap2()) {
 		if (is_sram_locked()) {
 			if (cpu_is_omap34xx()) {
-				omap_sram_base = OMAP3_SRAM_PUB_VA;
 				omap_sram_start = OMAP3_SRAM_PUB_PA;
 				if ((omap_type() == OMAP2_DEVICE_TYPE_EMU) ||
 				    (omap_type() == OMAP2_DEVICE_TYPE_SEC)) {
@@ -126,25 +113,20 @@ static void __init omap_detect_sram(void)
 					omap_sram_size = 0x8000; /* 32K */
 				}
 			} else if (cpu_is_omap44xx()) {
-				omap_sram_base = OMAP4_SRAM_PUB_VA;
 				omap_sram_start = OMAP4_SRAM_PUB_PA;
 				omap_sram_size = 0xa000; /* 40K */
 			} else {
-				omap_sram_base = OMAP2_SRAM_PUB_VA;
 				omap_sram_start = OMAP2_SRAM_PUB_PA;
 				omap_sram_size = 0x800; /* 2K */
 			}
 		} else {
 			if (cpu_is_omap34xx()) {
-				omap_sram_base = OMAP3_SRAM_VA;
 				omap_sram_start = OMAP3_SRAM_PA;
 				omap_sram_size = 0x10000; /* 64K */
 			} else if (cpu_is_omap44xx()) {
-				omap_sram_base = OMAP4_SRAM_VA;
 				omap_sram_start = OMAP4_SRAM_PA;
 				omap_sram_size = 0xe000; /* 56K */
 			} else {
-				omap_sram_base = OMAP2_SRAM_VA;
 				omap_sram_start = OMAP2_SRAM_PA;
 				if (cpu_is_omap242x())
 					omap_sram_size = 0xa0000; /* 640K */
@@ -153,7 +135,6 @@ static void __init omap_detect_sram(void)
 			}
 		}
 	} else {
-		omap_sram_base = OMAP1_SRAM_VA;
 		omap_sram_start = OMAP1_SRAM_PA;
 
 		if (cpu_is_omap7xx())
@@ -170,35 +151,14 @@ static void __init omap_detect_sram(void)
 			omap_sram_size = 0x4000;
 		}
 	}
-	reserved = omapfb_reserve_sram(omap_sram_start, omap_sram_base,
-				       omap_sram_size,
-				       omap_sram_start + SRAM_BOOTLOADER_SZ,
-				       omap_sram_size - SRAM_BOOTLOADER_SZ);
-	omap_sram_size -= reserved;
-
-	reserved = omap_vram_reserve_sram(omap_sram_start, omap_sram_base,
-			omap_sram_size,
-			omap_sram_start + SRAM_BOOTLOADER_SZ,
-			omap_sram_size - SRAM_BOOTLOADER_SZ);
-	omap_sram_size -= reserved;
-
-	omap_sram_ceil = omap_sram_base + omap_sram_size;
 }
 
-static struct map_desc omap_sram_io_desc[] __initdata = {
-	{	/* .length gets filled in at runtime */
-		.virtual	= OMAP1_SRAM_VA,
-		.pfn		= __phys_to_pfn(OMAP1_SRAM_PA),
-		.type		= MT_MEMORY
-	}
-};
-
 /*
  * Note that we cannot use ioremap for SRAM, as clock init needs SRAM early.
  */
 static void __init omap_map_sram(void)
 {
-	unsigned long base;
+	int cached = 1;
 
 	if (omap_sram_size == 0)
 		return;
@@ -211,28 +171,18 @@ static void __init omap_map_sram(void)
 		 * the ARM may attempt to write cache lines back to SDRAM
 		 * which will cause the system to hang.
 		 */
-		omap_sram_io_desc[0].type = MT_MEMORY_NONCACHED;
+		cached = 0;
 	}
 
-	omap_sram_io_desc[0].virtual = omap_sram_base;
-	base = omap_sram_start;
-	base = ROUND_DOWN(base, PAGE_SIZE);
-	omap_sram_io_desc[0].pfn = __phys_to_pfn(base);
-	omap_sram_io_desc[0].length = ROUND_DOWN(omap_sram_size, PAGE_SIZE);
-	iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc));
-
-	pr_info("SRAM: Mapped pa 0x%08llx to va 0x%08lx size: 0x%lx\n",
-		(long long) __pfn_to_phys(omap_sram_io_desc[0].pfn),
-		omap_sram_io_desc[0].virtual,
-		omap_sram_io_desc[0].length);
+	omap_sram_start = ROUND_DOWN(omap_sram_start, PAGE_SIZE);
+	omap_sram_base = __arm_ioremap_exec(omap_sram_start, omap_sram_size,
+						cached);
+	if (!omap_sram_base) {
+		pr_err("SRAM: Could not map\n");
+		return;
+	}
 
-	/*
-	 * Normally devicemaps_init() would flush caches and tlb after
-	 * mdesc->map_io(), but since we're called from map_io(), we
-	 * must do it here.
-	 */
-	local_flush_tlb_all();
-	flush_cache_all();
+	omap_sram_ceil = omap_sram_base + omap_sram_size;
 
 	/*
 	 * Looks like we need to preserve some bootloader code at the
@@ -251,13 +201,18 @@ static void __init omap_map_sram(void)
  */
 void *omap_sram_push_address(unsigned long size)
 {
-	if (size > (omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ))) {
+	unsigned long available, new_ceil = (unsigned long)omap_sram_ceil;
+
+	available = omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ);
+
+	if (size > available) {
 		pr_err("Not enough space in SRAM\n");
 		return NULL;
 	}
 
-	omap_sram_ceil -= size;
-	omap_sram_ceil = ROUND_DOWN(omap_sram_ceil, FNCPY_ALIGN);
+	new_ceil -= size;
+	new_ceil = ROUND_DOWN(new_ceil, FNCPY_ALIGN);
+	omap_sram_ceil = IOMEM(new_ceil);
 
 	return (void *)omap_sram_ceil;
 }
diff --git a/arch/arm/plat-pxa/include/plat/mfp.h b/arch/arm/plat-pxa/include/plat/mfp.h
index 89e68e0..5c79c29 100644
--- a/arch/arm/plat-pxa/include/plat/mfp.h
+++ b/arch/arm/plat-pxa/include/plat/mfp.h
@@ -456,7 +456,7 @@ struct mfp_addr_map {
 
 #define MFP_ADDR_END	{ MFP_PIN_INVALID, 0 }
 
-void __init mfp_init_base(unsigned long mfpr_base);
+void __init mfp_init_base(void __iomem *mfpr_base);
 void __init mfp_init_addr(struct mfp_addr_map *map);
 
 /*
diff --git a/arch/arm/plat-pxa/mfp.c b/arch/arm/plat-pxa/mfp.c
index be12ead..2c4dbb1 100644
--- a/arch/arm/plat-pxa/mfp.c
+++ b/arch/arm/plat-pxa/mfp.c
@@ -229,7 +229,7 @@ void mfp_write(int mfp, unsigned long val)
 	spin_unlock_irqrestore(&mfp_spin_lock, flags);
 }
 
-void __init mfp_init_base(unsigned long mfpr_base)
+void __init mfp_init_base(void __iomem *mfpr_base)
 {
 	int i;
 
@@ -237,7 +237,7 @@ void __init mfp_init_base(unsigned long mfpr_base)
 	for (i = 0; i < ARRAY_SIZE(mfp_table); i++)
 		mfp_table[i].config = -1;
 
-	mfpr_mmio_base = (void __iomem *)mfpr_base;
+	mfpr_mmio_base = mfpr_base;
 }
 
 void __init mfp_init_addr(struct mfp_addr_map *map)
diff --git a/arch/arm/plat-s3c24xx/cpu.c b/arch/arm/plat-s3c24xx/cpu.c
index c1fc6c6..3c63353 100644
--- a/arch/arm/plat-s3c24xx/cpu.c
+++ b/arch/arm/plat-s3c24xx/cpu.c
@@ -215,19 +215,18 @@ static void s3c24xx_pm_restart(char mode, const char *cmd)
 
 void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
 {
-	unsigned long idcode = 0x0;
-
 	/* initialise the io descriptors we need for initialisation */
 	iotable_init(mach_desc, size);
 	iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));
 
 	if (cpu_architecture() >= CPU_ARCH_ARMv5) {
-		idcode = s3c24xx_read_idcode_v5();
+		samsung_cpu_id = s3c24xx_read_idcode_v5();
 	} else {
-		idcode = s3c24xx_read_idcode_v4();
+		samsung_cpu_id = s3c24xx_read_idcode_v4();
 	}
+	s3c24xx_init_cpu();
 
 	arm_pm_restart = s3c24xx_pm_restart;
 
-	s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids));
+	s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
 }
diff --git a/arch/arm/plat-s3c24xx/include/plat/map.h b/arch/arm/plat-s3c24xx/include/plat/map.h
deleted file mode 100644
index bd534d3..0000000
--- a/arch/arm/plat-s3c24xx/include/plat/map.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/map.h
- *
- * Copyright (c) 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C24XX - Memory map definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_PLAT_S3C24XX_MAP_H
-#define __ASM_PLAT_S3C24XX_MAP_H
-
-/* interrupt controller is the first thing we put in, to make
- * the assembly code for the irq detection easier
- */
-#define S3C24XX_VA_IRQ	   S3C_VA_IRQ
-#define S3C2410_PA_IRQ	   (0x4A000000)
-#define S3C24XX_SZ_IRQ	   SZ_1M
-
-/* memory controller registers */
-#define S3C24XX_VA_MEMCTRL S3C_VA_MEM
-#define S3C2410_PA_MEMCTRL (0x48000000)
-#define S3C24XX_SZ_MEMCTRL SZ_1M
-
-/* UARTs */
-#define S3C24XX_VA_UART	   S3C_VA_UART
-#define S3C2410_PA_UART	   (0x50000000)
-#define S3C24XX_SZ_UART	   SZ_1M
-#define S3C_UART_OFFSET	   (0x4000)
-
-#define S3C_VA_UARTx(uart) (S3C_VA_UART + ((uart * S3C_UART_OFFSET)))
-
-/* Timers */
-#define S3C24XX_VA_TIMER   S3C_VA_TIMER
-#define S3C2410_PA_TIMER   (0x51000000)
-#define S3C24XX_SZ_TIMER   SZ_1M
-
-/* Clock and Power management */
-#define S3C24XX_VA_CLKPWR  S3C_VA_SYS
-#define S3C24XX_SZ_CLKPWR  SZ_1M
-
-/* USB Device port */
-#define S3C2410_PA_USBDEV  (0x52000000)
-#define S3C24XX_SZ_USBDEV  SZ_1M
-
-/* Watchdog */
-#define S3C24XX_VA_WATCHDOG S3C_VA_WATCHDOG
-#define S3C2410_PA_WATCHDOG (0x53000000)
-#define S3C24XX_SZ_WATCHDOG SZ_1M
-
-/* Standard size definitions for peripheral blocks. */
-
-#define S3C24XX_SZ_IIS		SZ_1M
-#define S3C24XX_SZ_ADC		SZ_1M
-#define S3C24XX_SZ_SPI		SZ_1M
-#define S3C24XX_SZ_SDI		SZ_1M
-#define S3C24XX_SZ_NAND		SZ_1M
-
-/* GPIO ports */
-
-/* the calculation for the VA of this must ensure that
- * it is the same distance apart from the UART in the
- * phsyical address space, as the initial mapping for the IO
- * is done as a 1:1 mapping. This puts it (currently) at
- * 0xFA800000, which is not in the way of any current mapping
- * by the base system.
-*/
-
-#define S3C2410_PA_GPIO	   (0x56000000)
-#define S3C24XX_VA_GPIO	   ((S3C24XX_PA_GPIO - S3C24XX_PA_UART) + S3C24XX_VA_UART)
-#define S3C24XX_SZ_GPIO	   SZ_1M
-
-
-/* ISA style IO, for each machine to sort out mappings for, if it
- * implements it. We reserve two 16M regions for ISA.
- */
-
-#define S3C24XX_VA_ISA_WORD  S3C2410_ADDR(0x02000000)
-#define S3C24XX_VA_ISA_BYTE  S3C2410_ADDR(0x03000000)
-
-/* deal with the registers that move under the 2412/2413 */
-
-#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
-#ifndef __ASSEMBLY__
-extern void __iomem *s3c24xx_va_gpio2;
-#endif
-#ifdef CONFIG_CPU_S3C2412_ONLY
-#define S3C24XX_VA_GPIO2 (S3C24XX_VA_GPIO + 0x10)
-#else
-#define S3C24XX_VA_GPIO2 s3c24xx_va_gpio2
-#endif
-#else
-#define s3c24xx_va_gpio2 S3C24XX_VA_GPIO
-#define S3C24XX_VA_GPIO2 S3C24XX_VA_GPIO
-#endif
-
-#endif /* __ASM_PLAT_S3C24XX_MAP_H */
diff --git a/arch/arm/plat-s5p/cpu.c b/arch/arm/plat-s5p/cpu.c
index bbc2aa7..7b0a28f 100644
--- a/arch/arm/plat-s5p/cpu.c
+++ b/arch/arm/plat-s5p/cpu.c
@@ -33,48 +33,66 @@ static const char name_s5p6450[] = "S5P6450";
 static const char name_s5pc100[] = "S5PC100";
 static const char name_s5pv210[] = "S5PV210/S5PC110";
 static const char name_exynos4210[] = "EXYNOS4210";
+static const char name_exynos4212[] = "EXYNOS4212";
+static const char name_exynos4412[] = "EXYNOS4412";
 
 static struct cpu_table cpu_ids[] __initdata = {
 	{
-		.idcode		= 0x56440100,
-		.idmask		= 0xfffff000,
+		.idcode		= S5P6440_CPU_ID,
+		.idmask		= S5P64XX_CPU_MASK,
 		.map_io		= s5p6440_map_io,
 		.init_clocks	= s5p6440_init_clocks,
 		.init_uarts	= s5p6440_init_uarts,
 		.init		= s5p64x0_init,
 		.name		= name_s5p6440,
 	}, {
-		.idcode		= 0x36450000,
-		.idmask		= 0xfffff000,
+		.idcode		= S5P6450_CPU_ID,
+		.idmask		= S5P64XX_CPU_MASK,
 		.map_io		= s5p6450_map_io,
 		.init_clocks	= s5p6450_init_clocks,
 		.init_uarts	= s5p6450_init_uarts,
 		.init		= s5p64x0_init,
 		.name		= name_s5p6450,
 	}, {
-		.idcode		= 0x43100000,
-		.idmask		= 0xfffff000,
+		.idcode		= S5PC100_CPU_ID,
+		.idmask		= S5PC100_CPU_MASK,
 		.map_io		= s5pc100_map_io,
 		.init_clocks	= s5pc100_init_clocks,
 		.init_uarts	= s5pc100_init_uarts,
 		.init		= s5pc100_init,
 		.name		= name_s5pc100,
 	}, {
-		.idcode		= 0x43110000,
-		.idmask		= 0xfffff000,
+		.idcode		= S5PV210_CPU_ID,
+		.idmask		= S5PV210_CPU_MASK,
 		.map_io		= s5pv210_map_io,
 		.init_clocks	= s5pv210_init_clocks,
 		.init_uarts	= s5pv210_init_uarts,
 		.init		= s5pv210_init,
 		.name		= name_s5pv210,
 	}, {
-		.idcode		= 0x43210000,
-		.idmask		= 0xfffe0000,
+		.idcode		= EXYNOS4210_CPU_ID,
+		.idmask		= EXYNOS4_CPU_MASK,
 		.map_io		= exynos4_map_io,
 		.init_clocks	= exynos4_init_clocks,
 		.init_uarts	= exynos4_init_uarts,
 		.init		= exynos4_init,
 		.name		= name_exynos4210,
+	}, {
+		.idcode		= EXYNOS4212_CPU_ID,
+		.idmask		= EXYNOS4_CPU_MASK,
+		.map_io		= exynos4_map_io,
+		.init_clocks	= exynos4_init_clocks,
+		.init_uarts	= exynos4_init_uarts,
+		.init		= exynos4_init,
+		.name		= name_exynos4212,
+	}, {
+		.idcode		= EXYNOS4412_CPU_ID,
+		.idmask		= EXYNOS4_CPU_MASK,
+		.map_io		= exynos4_map_io,
+		.init_clocks	= exynos4_init_clocks,
+		.init_uarts	= exynos4_init_uarts,
+		.init		= exynos4_init,
+		.name		= name_exynos4412,
 	},
 };
 
@@ -114,13 +132,13 @@ static struct map_desc s5p_iodesc[] __initdata = {
 void __init s5p_init_io(struct map_desc *mach_desc,
 			int size, void __iomem *cpuid_addr)
 {
-	unsigned long idcode;
-
 	/* initialize the io descriptors we need for initialization */
 	iotable_init(s5p_iodesc, ARRAY_SIZE(s5p_iodesc));
 	if (mach_desc)
 		iotable_init(mach_desc, size);
 
-	idcode = __raw_readl(cpuid_addr);
-	s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids));
+	/* detect cpu id and rev. */
+	s5p_init_cpu(cpuid_addr);
+
+	s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
 }
diff --git a/arch/arm/plat-s5p/include/plat/exynos4.h b/arch/arm/plat-s5p/include/plat/exynos4.h
index 907caab..f680a14 100644
--- a/arch/arm/plat-s5p/include/plat/exynos4.h
+++ b/arch/arm/plat-s5p/include/plat/exynos4.h
@@ -14,10 +14,11 @@
 
 extern void exynos4_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
 extern void exynos4_register_clocks(void);
+extern void exynos4210_register_clocks(void);
+extern void exynos4212_register_clocks(void);
 extern void exynos4_setup_clocks(void);
 
-#ifdef CONFIG_CPU_EXYNOS4210
-
+#ifdef CONFIG_ARCH_EXYNOS4
 extern  int exynos4_init(void);
 extern void exynos4_init_irq(void);
 extern void exynos4_map_io(void);
diff --git a/arch/arm/plat-s5p/include/plat/map-s5p.h b/arch/arm/plat-s5p/include/plat/map-s5p.h
deleted file mode 100644
index 36d3551..0000000
--- a/arch/arm/plat-s5p/include/plat/map-s5p.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* linux/arch/arm/plat-s5p/include/plat/map-s5p.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5P - Memory map definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_PLAT_MAP_S5P_H
-#define __ASM_PLAT_MAP_S5P_H __FILE__
-
-#define S5P_VA_CHIPID		S3C_ADDR(0x02000000)
-#define S5P_VA_CMU		S3C_ADDR(0x02100000)
-#define S5P_VA_PMU		S3C_ADDR(0x02180000)
-#define S5P_VA_GPIO		S3C_ADDR(0x02200000)
-#define S5P_VA_GPIO1		S5P_VA_GPIO
-#define S5P_VA_GPIO2		S3C_ADDR(0x02240000)
-#define S5P_VA_GPIO3		S3C_ADDR(0x02280000)
-
-#define S5P_VA_SYSRAM		S3C_ADDR(0x02400000)
-#define S5P_VA_DMC0		S3C_ADDR(0x02440000)
-#define S5P_VA_DMC1		S3C_ADDR(0x02480000)
-#define S5P_VA_SROMC		S3C_ADDR(0x024C0000)
-
-#define S5P_VA_SYSTIMER		S3C_ADDR(0x02500000)
-#define S5P_VA_L2CC		S3C_ADDR(0x02600000)
-
-#define S5P_VA_COMBINER_BASE	S3C_ADDR(0x02700000)
-#define S5P_VA_COMBINER(x)	(S5P_VA_COMBINER_BASE + ((x) >> 2) * 0x10)
-
-#define S5P_VA_COREPERI_BASE	S3C_ADDR(0x02800000)
-#define S5P_VA_COREPERI(x)	(S5P_VA_COREPERI_BASE + (x))
-#define S5P_VA_SCU		S5P_VA_COREPERI(0x0)
-#define S5P_VA_TWD		S5P_VA_COREPERI(0x600)
-
-#define S5P_VA_GIC_CPU		S3C_ADDR(0x02810000)
-#define S5P_VA_GIC_DIST		S3C_ADDR(0x02820000)
-
-#define S3C_VA_USB_HSPHY	S3C_ADDR(0x02900000)
-
-#define VA_VIC(x)		(S3C_VA_IRQ + ((x) * 0x10000))
-#define VA_VIC0			VA_VIC(0)
-#define VA_VIC1			VA_VIC(1)
-#define VA_VIC2			VA_VIC(2)
-#define VA_VIC3			VA_VIC(3)
-
-#define S5P_VA_UART(x)		(S3C_VA_UART + ((x) * S3C_UART_OFFSET))
-#define S5P_VA_UART0		S5P_VA_UART(0)
-#define S5P_VA_UART1		S5P_VA_UART(1)
-#define S5P_VA_UART2		S5P_VA_UART(2)
-#define S5P_VA_UART3		S5P_VA_UART(3)
-
-#ifndef S3C_UART_OFFSET
-#define S3C_UART_OFFSET		(0x400)
-#endif
-
-#endif /* __ASM_PLAT_MAP_S5P_H */
diff --git a/arch/arm/plat-s5p/include/plat/pll.h b/arch/arm/plat-s5p/include/plat/pll.h
index bf28fad..3e21b94 100644
--- a/arch/arm/plat-s5p/include/plat/pll.h
+++ b/arch/arm/plat-s5p/include/plat/pll.h
@@ -12,6 +12,59 @@
  * published by the Free Software Foundation.
 */
 
+#include <asm/div64.h>
+
+#define PLL35XX_MDIV_MASK	(0x3FF)
+#define PLL35XX_PDIV_MASK	(0x3F)
+#define PLL35XX_SDIV_MASK	(0x7)
+#define PLL35XX_MDIV_SHIFT	(16)
+#define PLL35XX_PDIV_SHIFT	(8)
+#define PLL35XX_SDIV_SHIFT	(0)
+
+static inline unsigned long s5p_get_pll35xx(unsigned long baseclk, u32 pll_con)
+{
+	u32 mdiv, pdiv, sdiv;
+	u64 fvco = baseclk;
+
+	mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
+	pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
+	sdiv = (pll_con >> PLL35XX_SDIV_SHIFT) & PLL35XX_SDIV_MASK;
+
+	fvco *= mdiv;
+	do_div(fvco, (pdiv << sdiv));
+
+	return (unsigned long)fvco;
+}
+
+#define PLL36XX_KDIV_MASK	(0xFFFF)
+#define PLL36XX_MDIV_MASK	(0x1FF)
+#define PLL36XX_PDIV_MASK	(0x3F)
+#define PLL36XX_SDIV_MASK	(0x7)
+#define PLL36XX_MDIV_SHIFT	(16)
+#define PLL36XX_PDIV_SHIFT	(8)
+#define PLL36XX_SDIV_SHIFT	(0)
+
+static inline unsigned long s5p_get_pll36xx(unsigned long baseclk,
+					    u32 pll_con0, u32 pll_con1)
+{
+	unsigned long result;
+	u32 mdiv, pdiv, sdiv, kdiv;
+	u64 tmp;
+
+	mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
+	pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
+	sdiv = (pll_con0 >> PLL36XX_SDIV_SHIFT) & PLL36XX_SDIV_MASK;
+	kdiv = pll_con1 & PLL36XX_KDIV_MASK;
+
+	tmp = baseclk;
+
+	tmp *= (mdiv << 16) + kdiv;
+	do_div(tmp, (pdiv << sdiv));
+	result = tmp >> 16;
+
+	return result;
+}
+
 #define PLL45XX_MDIV_MASK	(0x3FF)
 #define PLL45XX_PDIV_MASK	(0x3F)
 #define PLL45XX_SDIV_MASK	(0x7)
@@ -19,8 +72,6 @@
 #define PLL45XX_PDIV_SHIFT	(8)
 #define PLL45XX_SDIV_SHIFT	(0)
 
-#include <asm/div64.h>
-
 enum pll45xx_type_t {
 	pll_4500,
 	pll_4502,
@@ -72,7 +123,6 @@ static inline unsigned long s5p_get_pll46xx(unsigned long baseclk,
 	mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK;
 	pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
 	sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK;
-	kdiv = pll_con1 & PLL46XX_KDIV_MASK;
 
 	if (pll_type == pll_4650c)
 		kdiv = pll_con1 & PLL4650C_KDIV_MASK;
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index dffa37b..3895f9a 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -362,4 +362,11 @@ config SAMSUNG_PD
 	help
 	  Say Y here if you want to control Power Domain by Runtime PM.
 
+config DEBUG_S3C_UART
+	depends on PLAT_SAMSUNG
+	int
+	default "0" if DEBUG_S3C_UART0
+	default "1" if DEBUG_S3C_UART1
+	default "2" if DEBUG_S3C_UART2
+
 endif
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index 1105922..09adb84 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -11,7 +11,7 @@ obj-				:=
 
 # Objects we always build independent of SoC choice
 
-obj-y				+= init.o
+obj-y				+= init.o cpu.o
 obj-$(CONFIG_ARCH_USES_GETTIMEOFFSET)   += time.o
 obj-y				+= clock.o
 obj-y				+= pwm-clock.o
diff --git a/arch/arm/plat-samsung/cpu.c b/arch/arm/plat-samsung/cpu.c
new file mode 100644
index 0000000..81c06d4
--- /dev/null
+++ b/arch/arm/plat-samsung/cpu.c
@@ -0,0 +1,58 @@
+/* linux/arch/arm/plat-samsung/cpu.c
+ *
+ * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Samsung CPU Support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+
+#include <mach/map.h>
+#include <plat/cpu.h>
+
+unsigned long samsung_cpu_id;
+static unsigned int samsung_cpu_rev;
+
+unsigned int samsung_rev(void)
+{
+	return samsung_cpu_rev;
+}
+EXPORT_SYMBOL(samsung_rev);
+
+void __init s3c24xx_init_cpu(void)
+{
+	/* nothing here yet */
+
+	samsung_cpu_rev = 0;
+}
+
+void __init s3c64xx_init_cpu(void)
+{
+	samsung_cpu_id = __raw_readl(S3C_VA_SYS + 0x118);
+	if (!samsung_cpu_id) {
+		/*
+		 * S3C6400 has the ID register in a different place,
+		 * and needs a write before it can be read.
+		 */
+		__raw_writel(0x0, S3C_VA_SYS + 0xA1C);
+		samsung_cpu_id = __raw_readl(S3C_VA_SYS + 0xA1C);
+	}
+
+	samsung_cpu_rev = 0;
+}
+
+void __init s5p_init_cpu(void __iomem *cpuid_addr)
+{
+	samsung_cpu_id = __raw_readl(cpuid_addr);
+	samsung_cpu_rev = samsung_cpu_id & 0xFF;
+}
diff --git a/arch/arm/plat-samsung/dev-hsmmc.c b/arch/arm/plat-samsung/dev-hsmmc.c
index db7a65c..06825c4 100644
--- a/arch/arm/plat-samsung/dev-hsmmc.c
+++ b/arch/arm/plat-samsung/dev-hsmmc.c
@@ -58,22 +58,5 @@ struct platform_device s3c_device_hsmmc0 = {
 
 void s3c_sdhci0_set_platdata(struct s3c_sdhci_platdata *pd)
 {
-	struct s3c_sdhci_platdata *set = &s3c_hsmmc0_def_platdata;
-
-	set->cd_type = pd->cd_type;
-	set->ext_cd_init = pd->ext_cd_init;
-	set->ext_cd_cleanup = pd->ext_cd_cleanup;
-	set->ext_cd_gpio = pd->ext_cd_gpio;
-	set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
-
-	if (pd->max_width)
-		set->max_width = pd->max_width;
-	if (pd->cfg_gpio)
-		set->cfg_gpio = pd->cfg_gpio;
-	if (pd->cfg_card)
-		set->cfg_card = pd->cfg_card;
-	if (pd->host_caps)
-		set->host_caps |= pd->host_caps;
-	if (pd->clk_type)
-		set->clk_type = pd->clk_type;
+	s3c_sdhci_set_platdata(pd, &s3c_hsmmc0_def_platdata);
 }
diff --git a/arch/arm/plat-samsung/dev-hsmmc1.c b/arch/arm/plat-samsung/dev-hsmmc1.c
index 2497321..4524ef4 100644
--- a/arch/arm/plat-samsung/dev-hsmmc1.c
+++ b/arch/arm/plat-samsung/dev-hsmmc1.c
@@ -58,22 +58,5 @@ struct platform_device s3c_device_hsmmc1 = {
 
 void s3c_sdhci1_set_platdata(struct s3c_sdhci_platdata *pd)
 {
-	struct s3c_sdhci_platdata *set = &s3c_hsmmc1_def_platdata;
-
-	set->cd_type = pd->cd_type;
-	set->ext_cd_init = pd->ext_cd_init;
-	set->ext_cd_cleanup = pd->ext_cd_cleanup;
-	set->ext_cd_gpio = pd->ext_cd_gpio;
-	set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
-
-	if (pd->max_width)
-		set->max_width = pd->max_width;
-	if (pd->cfg_gpio)
-		set->cfg_gpio = pd->cfg_gpio;
-	if (pd->cfg_card)
-		set->cfg_card = pd->cfg_card;
-	if (pd->host_caps)
-		set->host_caps |= pd->host_caps;
-	if (pd->clk_type)
-		set->clk_type = pd->clk_type;
+	s3c_sdhci_set_platdata(pd, &s3c_hsmmc1_def_platdata);
 }
diff --git a/arch/arm/plat-samsung/dev-hsmmc2.c b/arch/arm/plat-samsung/dev-hsmmc2.c
index f60aedb..9cede96 100644
--- a/arch/arm/plat-samsung/dev-hsmmc2.c
+++ b/arch/arm/plat-samsung/dev-hsmmc2.c
@@ -59,22 +59,5 @@ struct platform_device s3c_device_hsmmc2 = {
 
 void s3c_sdhci2_set_platdata(struct s3c_sdhci_platdata *pd)
 {
-	struct s3c_sdhci_platdata *set = &s3c_hsmmc2_def_platdata;
-
-	set->cd_type = pd->cd_type;
-	set->ext_cd_init = pd->ext_cd_init;
-	set->ext_cd_cleanup = pd->ext_cd_cleanup;
-	set->ext_cd_gpio = pd->ext_cd_gpio;
-	set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
-
-	if (pd->max_width)
-		set->max_width = pd->max_width;
-	if (pd->cfg_gpio)
-		set->cfg_gpio = pd->cfg_gpio;
-	if (pd->cfg_card)
-		set->cfg_card = pd->cfg_card;
-	if (pd->host_caps)
-		set->host_caps |= pd->host_caps;
-	if (pd->clk_type)
-		set->clk_type = pd->clk_type;
+	s3c_sdhci_set_platdata(pd, &s3c_hsmmc2_def_platdata);
 }
diff --git a/arch/arm/plat-samsung/dev-hsmmc3.c b/arch/arm/plat-samsung/dev-hsmmc3.c
index ede776f..0358ef4 100644
--- a/arch/arm/plat-samsung/dev-hsmmc3.c
+++ b/arch/arm/plat-samsung/dev-hsmmc3.c
@@ -62,22 +62,5 @@ struct platform_device s3c_device_hsmmc3 = {
 
 void s3c_sdhci3_set_platdata(struct s3c_sdhci_platdata *pd)
 {
-	struct s3c_sdhci_platdata *set = &s3c_hsmmc3_def_platdata;
-
-	set->cd_type = pd->cd_type;
-	set->ext_cd_init = pd->ext_cd_init;
-	set->ext_cd_cleanup = pd->ext_cd_cleanup;
-	set->ext_cd_gpio = pd->ext_cd_gpio;
-	set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
-
-	if (pd->max_width)
-		set->max_width = pd->max_width;
-	if (pd->cfg_gpio)
-		set->cfg_gpio = pd->cfg_gpio;
-	if (pd->cfg_card)
-		set->cfg_card = pd->cfg_card;
-	if (pd->host_caps)
-		set->host_caps |= pd->host_caps;
-	if (pd->clk_type)
-		set->clk_type = pd->clk_type;
+	s3c_sdhci_set_platdata(pd, &s3c_hsmmc3_def_platdata);
 }
diff --git a/arch/arm/plat-samsung/dev-ts.c b/arch/arm/plat-samsung/dev-ts.c
index 82543f0..5f3d46a 100644
--- a/arch/arm/plat-samsung/dev-ts.c
+++ b/arch/arm/plat-samsung/dev-ts.c
@@ -43,8 +43,17 @@ struct platform_device s3c_device_ts = {
 	.resource	= s3c_ts_resource,
 };
 
+static struct s3c2410_ts_mach_info default_ts_data __initdata = {
+	.delay			= 10000,
+	.presc			= 49,
+	.oversampling_shift	= 2,
+};
+
 void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *pd)
 {
+	if (!pd)
+		pd = &default_ts_data;
+
 	s3c_set_platdata(pd, sizeof(struct s3c2410_ts_mach_info),
 			 &s3c_device_ts);
 }
diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h
index c0a5741..54f370f 100644
--- a/arch/arm/plat-samsung/include/plat/cpu.h
+++ b/arch/arm/plat-samsung/include/plat/cpu.h
@@ -1,9 +1,12 @@
 /* linux/arch/arm/plat-samsung/include/plat/cpu.h
  *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
  * Copyright (c) 2004-2005 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
  *
- * Header file for S3C24XX CPU support
+ * Header file for Samsung CPU support
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -15,6 +18,108 @@
 #ifndef __SAMSUNG_PLAT_CPU_H
 #define __SAMSUNG_PLAT_CPU_H
 
+extern unsigned long samsung_cpu_id;
+
+#define S3C24XX_CPU_ID		0x32400000
+#define S3C24XX_CPU_MASK	0xFFF00000
+
+#define S3C6400_CPU_ID		0x36400000
+#define S3C6410_CPU_ID		0x36410000
+#define S3C64XX_CPU_ID		(S3C6400_CPU_ID & S3C6410_CPU_ID)
+#define S3C64XX_CPU_MASK	0xFFFFF000
+
+#define S5P6440_CPU_ID		0x56440000
+#define S5P6450_CPU_ID		0x36450000
+#define S5P64XX_CPU_MASK	0xFFFFF000
+
+#define S5PC100_CPU_ID		0x43100000
+#define S5PC100_CPU_MASK	0xFFFFF000
+
+#define S5PV210_CPU_ID		0x43110000
+#define S5PV210_CPU_MASK	0xFFFFF000
+
+#define EXYNOS4210_CPU_ID	0x43210000
+#define EXYNOS4212_CPU_ID	0x43220000
+#define EXYNOS4412_CPU_ID	0xE4412200
+#define EXYNOS4_CPU_MASK	0xFFFE0000
+
+#define IS_SAMSUNG_CPU(name, id, mask)		\
+static inline int is_samsung_##name(void)	\
+{						\
+	return ((samsung_cpu_id & mask) == (id & mask));	\
+}
+
+IS_SAMSUNG_CPU(s3c24xx, S3C24XX_CPU_ID, S3C24XX_CPU_MASK)
+IS_SAMSUNG_CPU(s3c64xx, S3C64XX_CPU_ID, S3C64XX_CPU_MASK)
+IS_SAMSUNG_CPU(s5p6440, S5P6440_CPU_ID, S5P64XX_CPU_MASK)
+IS_SAMSUNG_CPU(s5p6450, S5P6450_CPU_ID, S5P64XX_CPU_MASK)
+IS_SAMSUNG_CPU(s5pc100, S5PC100_CPU_ID, S5PC100_CPU_MASK)
+IS_SAMSUNG_CPU(s5pv210, S5PV210_CPU_ID, S5PV210_CPU_MASK)
+IS_SAMSUNG_CPU(exynos4210, EXYNOS4210_CPU_ID, EXYNOS4_CPU_MASK)
+IS_SAMSUNG_CPU(exynos4212, EXYNOS4212_CPU_ID, EXYNOS4_CPU_MASK)
+IS_SAMSUNG_CPU(exynos4412, EXYNOS4412_CPU_ID, EXYNOS4_CPU_MASK)
+
+#if defined(CONFIG_CPU_S3C2410) || defined(CONFIG_CPU_S3C2412) || \
+    defined(CONFIG_CPU_S3C2416) || defined(CONFIG_CPU_S3C2440) || \
+    defined(CONFIG_CPU_S3C2442) || defined(CONFIG_CPU_S3C244X) || \
+    defined(CONFIG_CPU_S3C2443)
+# define soc_is_s3c24xx()	is_samsung_s3c24xx()
+#else
+# define soc_is_s3c24xx()	0
+#endif
+
+#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
+# define soc_is_s3c64xx()	is_samsung_s3c64xx()
+#else
+# define soc_is_s3c64xx()	0
+#endif
+
+#if defined(CONFIG_CPU_S5P6440)
+# define soc_is_s5p6440()	is_samsung_s5p6440()
+#else
+# define soc_is_s5p6440()	0
+#endif
+
+#if defined(CONFIG_CPU_S5P6450)
+# define soc_is_s5p6450()	is_samsung_s5p6450()
+#else
+# define soc_is_s5p6450()	0
+#endif
+
+#if defined(CONFIG_CPU_S5PC100)
+# define soc_is_s5pc100()	is_samsung_s5pc100()
+#else
+# define soc_is_s5pc100()	0
+#endif
+
+#if defined(CONFIG_CPU_S5PV210)
+# define soc_is_s5pv210()	is_samsung_s5pv210()
+#else
+# define soc_is_s5pv210()	0
+#endif
+
+#if defined(CONFIG_CPU_EXYNOS4210)
+# define soc_is_exynos4210()	is_samsung_exynos4210()
+#else
+# define soc_is_exynos4210()	0
+#endif
+
+#if defined(CONFIG_SOC_EXYNOS4212)
+# define soc_is_exynos4212()	is_samsung_exynos4212()
+#else
+# define soc_is_exynos4212()	0
+#endif
+
+#if defined(CONFIG_SOC_EXYNOS4412)
+# define soc_is_exynos4412()	is_samsung_exynos4412()
+#else
+# define soc_is_exynos4412()	0
+#endif
+
+#define EXYNOS4210_REV_0	(0x0)
+#define EXYNOS4210_REV_1_0	(0x10)
+#define EXYNOS4210_REV_1_1	(0x11)
+
 #define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE }
 
 #ifndef MHZ
@@ -55,6 +160,12 @@ extern void s3c64xx_init_io(struct map_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_cpu(void);
+extern void s3c64xx_init_cpu(void);
+extern void s5p_init_cpu(void __iomem *cpuid_addr);
+
+extern unsigned int samsung_rev(void);
+
 extern void s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no);
 
 extern void s3c24xx_init_clocks(int xtal);
diff --git a/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h b/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h
index 336d5ac..ab9bce6 100644
--- a/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h
+++ b/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h
@@ -18,11 +18,6 @@ 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
@@ -31,7 +26,6 @@ struct s3c24xx_dma_addr {
 
 struct s3c24xx_dma_map {
 	const char		*name;
-	struct s3c24xx_dma_addr  hw_addr;
 
 	unsigned long		 channels[S3C_DMA_CHANNELS];
 	unsigned long		 channels_rx[S3C_DMA_CHANNELS];
diff --git a/arch/arm/plat-samsung/include/plat/map-s3c.h b/arch/arm/plat-samsung/include/plat/map-s3c.h
new file mode 100644
index 0000000..7d04875
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/map-s3c.h
@@ -0,0 +1,84 @@
+/* linux/arch/arm/plat-samsung/include/plat/map-s3c.h
+ *
+ * Copyright (c) 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX - Memory map definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_PLAT_MAP_S3C_H
+#define __ASM_PLAT_MAP_S3C_H __FILE__
+
+#define S3C24XX_VA_IRQ		S3C_VA_IRQ
+#define S3C24XX_VA_MEMCTRL	S3C_VA_MEM
+#define S3C24XX_VA_UART		S3C_VA_UART
+
+#define S3C24XX_VA_TIMER	S3C_VA_TIMER
+#define S3C24XX_VA_CLKPWR	S3C_VA_SYS
+#define S3C24XX_VA_WATCHDOG	S3C_VA_WATCHDOG
+
+#define S3C2412_VA_SSMC		S3C_ADDR_CPU(0x00000000)
+#define S3C2412_VA_EBI		S3C_ADDR_CPU(0x00010000)
+
+#define S3C2410_PA_UART		(0x50000000)
+#define S3C24XX_PA_UART		S3C2410_PA_UART
+
+#ifndef S3C_UART_OFFSET
+#define S3C_UART_OFFSET		(0x400)
+#endif
+
+/*
+ * GPIO ports
+ *
+ * the calculation for the VA of this must ensure that
+ * it is the same distance apart from the UART in the
+ * phsyical address space, as the initial mapping for the IO
+ * is done as a 1:1 mapping. This puts it (currently) at
+ * 0xFA800000, which is not in the way of any current mapping
+ * by the base system.
+*/
+
+#define S3C2410_PA_GPIO		(0x56000000)
+#define S3C24XX_PA_GPIO		S3C2410_PA_GPIO
+
+#define S3C24XX_VA_GPIO		((S3C24XX_PA_GPIO - S3C24XX_PA_UART) + S3C24XX_VA_UART)
+#define S3C64XX_VA_GPIO		S3C_ADDR_CPU(0x00000000)
+
+#define S3C64XX_VA_MODEM	S3C_ADDR_CPU(0x00100000)
+#define S3C64XX_VA_USB_HSPHY	S3C_ADDR_CPU(0x00200000)
+
+#define S3C_VA_USB_HSPHY	S3C64XX_VA_USB_HSPHY
+
+/*
+ * ISA style IO, for each machine to sort out mappings for,
+ * if it implements it. We reserve two 16M regions for ISA.
+ */
+
+#define S3C2410_ADDR(x)		S3C_ADDR(x)
+
+#define S3C24XX_VA_ISA_WORD	S3C2410_ADDR(0x02000000)
+#define S3C24XX_VA_ISA_BYTE	S3C2410_ADDR(0x03000000)
+
+/* deal with the registers that move under the 2412/2413 */
+
+#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
+#ifndef __ASSEMBLY__
+extern void __iomem *s3c24xx_va_gpio2;
+#endif
+#ifdef CONFIG_CPU_S3C2412_ONLY
+#define S3C24XX_VA_GPIO2	(S3C24XX_VA_GPIO + 0x10)
+#else
+#define S3C24XX_VA_GPIO2 s3c24xx_va_gpio2
+#endif
+#else
+#define s3c24xx_va_gpio2 S3C24XX_VA_GPIO
+#define S3C24XX_VA_GPIO2 S3C24XX_VA_GPIO
+#endif
+
+#include <plat/map-s5p.h>
+
+#endif /* __ASM_PLAT_MAP_S3C_H */
diff --git a/arch/arm/plat-samsung/include/plat/map-s5p.h b/arch/arm/plat-samsung/include/plat/map-s5p.h
new file mode 100644
index 0000000..c2d7bda
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/map-s5p.h
@@ -0,0 +1,61 @@
+/* linux/arch/arm/plat-samsung/include/plat/map-s5p.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P - Memory map definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_PLAT_MAP_S5P_H
+#define __ASM_PLAT_MAP_S5P_H __FILE__
+
+#define S5P_VA_CHIPID		S3C_ADDR(0x02000000)
+#define S5P_VA_CMU		S3C_ADDR(0x02100000)
+#define S5P_VA_PMU		S3C_ADDR(0x02180000)
+#define S5P_VA_GPIO		S3C_ADDR(0x02200000)
+#define S5P_VA_GPIO1		S5P_VA_GPIO
+#define S5P_VA_GPIO2		S3C_ADDR(0x02240000)
+#define S5P_VA_GPIO3		S3C_ADDR(0x02280000)
+
+#define S5P_VA_SYSRAM		S3C_ADDR(0x02400000)
+#define S5P_VA_DMC0		S3C_ADDR(0x02440000)
+#define S5P_VA_DMC1		S3C_ADDR(0x02480000)
+#define S5P_VA_SROMC		S3C_ADDR(0x024C0000)
+
+#define S5P_VA_SYSTIMER		S3C_ADDR(0x02500000)
+#define S5P_VA_L2CC		S3C_ADDR(0x02600000)
+
+#define S5P_VA_COMBINER_BASE	S3C_ADDR(0x02700000)
+#define S5P_VA_COMBINER(x)	(S5P_VA_COMBINER_BASE + ((x) >> 2) * 0x10)
+
+#define S5P_VA_COREPERI_BASE	S3C_ADDR(0x02800000)
+#define S5P_VA_COREPERI(x)	(S5P_VA_COREPERI_BASE + (x))
+#define S5P_VA_SCU		S5P_VA_COREPERI(0x0)
+#define S5P_VA_TWD		S5P_VA_COREPERI(0x600)
+
+#define S5P_VA_GIC_CPU		S3C_ADDR(0x02810000)
+#define S5P_VA_GIC_DIST		S3C_ADDR(0x02820000)
+
+#define VA_VIC(x)		(S3C_VA_IRQ + ((x) * 0x10000))
+#define VA_VIC0			VA_VIC(0)
+#define VA_VIC1			VA_VIC(1)
+#define VA_VIC2			VA_VIC(2)
+#define VA_VIC3			VA_VIC(3)
+
+#define S5P_VA_UART(x)		(S3C_VA_UART + ((x) * S3C_UART_OFFSET))
+#define S5P_VA_UART0		S5P_VA_UART(0)
+#define S5P_VA_UART1		S5P_VA_UART(1)
+#define S5P_VA_UART2		S5P_VA_UART(2)
+#define S5P_VA_UART3		S5P_VA_UART(3)
+
+#ifndef S3C_UART_OFFSET
+#define S3C_UART_OFFSET		(0x400)
+#endif
+
+#include <plat/map-s3c.h>
+
+#endif /* __ASM_PLAT_MAP_S5P_H */
diff --git a/arch/arm/plat-samsung/include/plat/sdhci.h b/arch/arm/plat-samsung/include/plat/sdhci.h
index 058e096..4a65520 100644
--- a/arch/arm/plat-samsung/include/plat/sdhci.h
+++ b/arch/arm/plat-samsung/include/plat/sdhci.h
@@ -86,6 +86,13 @@ struct s3c_sdhci_platdata {
 			    struct mmc_card *card);
 };
 
+/* s3c_sdhci_set_platdata() - common helper for setting SDHCI platform data
+ * @pd: The default platform data for this device.
+ * @set: Pointer to the platform data to fill in.
+ */
+extern void s3c_sdhci_set_platdata(struct s3c_sdhci_platdata *pd,
+				    struct s3c_sdhci_platdata *set);
+
 /**
  * s3c_sdhci0_set_platdata - Set platform data for S3C SDHCI device.
  * @pd: Platform data to register to device.
diff --git a/arch/arm/plat-samsung/platformdata.c b/arch/arm/plat-samsung/platformdata.c
index 7cf2e1e..6de1a38 100644
--- a/arch/arm/plat-samsung/platformdata.c
+++ b/arch/arm/plat-samsung/platformdata.c
@@ -14,6 +14,7 @@
 #include <linux/platform_device.h>
 
 #include <plat/devs.h>
+#include <plat/sdhci.h>
 
 void __init *s3c_set_platdata(void *pd, size_t pdsize,
 			      struct platform_device *pdev)
@@ -35,3 +36,24 @@ void __init *s3c_set_platdata(void *pd, size_t pdsize,
 	pdev->dev.platform_data = npd;
 	return npd;
 }
+
+void s3c_sdhci_set_platdata(struct s3c_sdhci_platdata *pd,
+			     struct s3c_sdhci_platdata *set)
+{
+	set->cd_type = pd->cd_type;
+	set->ext_cd_init = pd->ext_cd_init;
+	set->ext_cd_cleanup = pd->ext_cd_cleanup;
+	set->ext_cd_gpio = pd->ext_cd_gpio;
+	set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert;
+
+	if (pd->max_width)
+		set->max_width = pd->max_width;
+	if (pd->cfg_gpio)
+		set->cfg_gpio = pd->cfg_gpio;
+	if (pd->cfg_card)
+		set->cfg_card = pd->cfg_card;
+	if (pd->host_caps)
+		set->host_caps |= pd->host_caps;
+	if (pd->clk_type)
+		set->clk_type = pd->clk_type;
+}
diff --git a/arch/arm/plat-versatile/platsmp.c b/arch/arm/plat-versatile/platsmp.c
index 51ecfea..92f18d3 100644
--- a/arch/arm/plat-versatile/platsmp.c
+++ b/arch/arm/plat-versatile/platsmp.c
@@ -77,7 +77,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 	 * since we haven't sent them a soft interrupt, they shouldn't
 	 * be there.
 	 */
-	write_pen_release(cpu);
+	write_pen_release(cpu_logical_map(cpu));
 
 	/*
 	 * Send the secondary CPU a soft interrupt, thereby causing
diff --git a/arch/hexagon/Kconfig b/arch/hexagon/Kconfig
new file mode 100644
index 0000000..02513c2
--- /dev/null
+++ b/arch/hexagon/Kconfig
@@ -0,0 +1,220 @@
+# Hexagon configuration
+comment "Linux Kernel Configuration for Hexagon"
+
+config HEXAGON
+	def_bool y
+	select HAVE_OPROFILE
+	select USE_GENERIC_SMP_HELPERS if SMP
+	# Other pending projects/to-do items.
+	# select HAVE_REGS_AND_STACK_ACCESS_API
+	# select HAVE_HW_BREAKPOINT if PERF_EVENTS
+	# select ARCH_HAS_CPU_IDLE_WAIT
+	# select ARCH_WANT_OPTIONAL_GPIOLIB
+	# select ARCH_REQUIRE_GPIOLIB
+	# select HAVE_CLK
+	# select IRQ_PER_CPU
+	select HAVE_IRQ_WORK
+	# select GENERIC_PENDING_IRQ if SMP
+	select GENERIC_ATOMIC64
+	select HAVE_PERF_EVENTS
+	select HAVE_GENERIC_HARDIRQS
+	select GENERIC_HARDIRQS_NO__DO_IRQ
+	select GENERIC_HARDIRQS_NO_DEPRECATED
+	# GENERIC_ALLOCATOR is used by dma_alloc_coherent()
+	select GENERIC_ALLOCATOR
+	select GENERIC_IRQ_SHOW
+	select HAVE_ARCH_KGDB
+	select HAVE_ARCH_TRACEHOOK
+	select NO_IOPORT
+	# mostly generic routines, with some accelerated ones
+	---help---
+	  Qualcomm Hexagon is a processor architecture designed for high
+	  performance and low power across a wide variety of applications.
+
+config HEXAGON_ARCH_V1
+	bool
+
+config HEXAGON_ARCH_V2
+	bool
+
+config HEXAGON_ARCH_V3
+	bool
+
+config HEXAGON_ARCH_V4
+	bool
+
+config FRAME_POINTER
+	def_bool y
+
+config LOCKDEP_SUPPORT
+	def_bool y
+
+config PCI
+	def_bool n
+
+config EARLY_PRINTK
+	def_bool y
+
+config KTIME_SCALAR
+	def_bool y
+
+config MMU
+	def_bool y
+
+config TRACE_IRQFLAGS_SUPPORT
+	def_bool y
+
+config GENERIC_CSUM
+	def_bool y
+
+#
+# Use the generic interrupt handling code in kernel/irq/:
+#
+config GENERIC_IRQ_PROBE
+	def_bool y
+
+config GENERIC_IOMAP
+	def_bool y
+
+#config ZONE_DMA
+#	bool
+#	default y
+
+config HAS_DMA
+	bool
+	select HAVE_DMA_ATTRS
+	default y
+
+config NEED_SG_DMA_LENGTH
+	def_bool y
+
+config RWSEM_GENERIC_SPINLOCK
+	def_bool n
+
+config RWSEM_XCHGADD_ALGORITHM
+	def_bool y
+
+config GENERIC_FIND_NEXT_BIT
+	def_bool y
+
+config GENERIC_HWEIGHT
+	def_bool y
+
+config GENERIC_TIME
+	def_bool y
+
+config GENERIC_CLOCKEVENTS
+	def_bool y
+
+config GENERIC_CLOCKEVENTS_BROADCAST
+	def_bool y
+
+config STACKTRACE_SUPPORT
+	def_bool y
+	select STACKTRACE
+
+config GENERIC_BUG
+	def_bool y
+	depends on BUG
+
+config BUG
+	def_bool y
+
+menu "Machine selection"
+
+choice
+	prompt "System type"
+	default HEXAGON_ARCH_V2
+
+config HEXAGON_COMET
+	bool "Comet Board"
+	select HEXAGON_ARCH_V2
+	---help---
+	  Support for the Comet platform.
+
+endchoice
+
+config HEXAGON_VM
+	def_bool y
+
+config CMDLINE
+	string "Default kernel command string"
+	default ""
+	help
+	  On some platforms, there is currently no way for the boot loader
+	  to pass arguments to the kernel. For these, you should supply some
+	  command-line options at build time by entering them here.  At a
+	  minimum, you should specify the memory size and the root device
+	  (e.g., mem=64M root=/dev/nfs).
+
+config HEXAGON_ANGEL_TRAPS
+	bool "Use Angel Traps"
+	default n
+	---help---
+	  Enable angel debug traps (for printk's).
+
+config SMP
+	bool "Multi-Processing support"
+	---help---
+	  Enables SMP support in the kernel.  If unsure, say "Y"
+
+config NR_CPUS
+	int "Maximum number of CPUs" if SMP
+	range 2 6 if SMP
+	default "1" if !SMP
+	default "6" if SMP
+	---help---
+	  This allows you to specify the maximum number of CPUs which this
+	  kernel will support.  The maximum supported value is 6 and the
+	  minimum value which makes sense is 2.
+
+	  This is purely to save memory - each supported CPU adds
+	  approximately eight kilobytes to the kernel image.
+
+choice
+	prompt "Kernel page size"
+	default PAGE_SIZE_4KB
+	---help---
+	  Changes the default page size; use with caution.
+
+config PAGE_SIZE_4KB
+	bool "4KB"
+
+config PAGE_SIZE_16KB
+	bool "16KB"
+
+config PAGE_SIZE_64KB
+	bool "64KB"
+
+config PAGE_SIZE_256KB
+	bool "256KB"
+
+endchoice
+
+source "mm/Kconfig"
+
+source "kernel/Kconfig.hz"
+source "kernel/time/Kconfig"
+
+config GENERIC_GPIO
+	bool "Generic GPIO support"
+	default n
+
+endmenu
+
+source "init/Kconfig"
+source "drivers/Kconfig"
+source "fs/Kconfig"
+
+menu "Executable File Formats"
+source "fs/Kconfig.binfmt"
+endmenu
+
+source "net/Kconfig"
+source "security/Kconfig"
+source "crypto/Kconfig"
+source "lib/Kconfig"
+
+menu "Kernel hacking"
+source "lib/Kconfig.debug"
+endmenu
diff --git a/arch/hexagon/Makefile b/arch/hexagon/Makefile
new file mode 100644
index 0000000..0c4de87
--- /dev/null
+++ b/arch/hexagon/Makefile
@@ -0,0 +1,58 @@
+#  Makefile for the Hexagon arch
+
+KBUILD_DEFCONFIG = comet_defconfig
+
+# Do not use GP-relative jumps
+KBUILD_CFLAGS += -G0
+LDFLAGS_vmlinux += -G0
+
+# Do not use single-byte enums; these will overflow.
+KBUILD_CFLAGS += -fno-short-enums
+
+# Modules must use either long-calls, or use pic/plt.
+# Use long-calls for now, it's easier.  And faster.
+# CFLAGS_MODULE += -fPIC
+# LDFLAGS_MODULE += -shared
+CFLAGS_MODULE += -mlong-calls
+
+cflags-$(CONFIG_HEXAGON_ARCH_V1) += $(call cc-option,-mv1)
+cflags-$(CONFIG_HEXAGON_ARCH_V2) += $(call cc-option,-mv2)
+cflags-$(CONFIG_HEXAGON_ARCH_V3) += $(call cc-option,-mv3)
+cflags-$(CONFIG_HEXAGON_ARCH_V4) += $(call cc-option,-mv4)
+
+aflags-$(CONFIG_HEXAGON_ARCH_V1) += $(call cc-option,-mv1)
+aflags-$(CONFIG_HEXAGON_ARCH_V2) += $(call cc-option,-mv2)
+aflags-$(CONFIG_HEXAGON_ARCH_V3) += $(call cc-option,-mv3)
+aflags-$(CONFIG_HEXAGON_ARCH_V4) += $(call cc-option,-mv4)
+
+ldflags-$(CONFIG_HEXAGON_ARCH_V1) += $(call cc-option,-mv1)
+ldflags-$(CONFIG_HEXAGON_ARCH_V2) += $(call cc-option,-mv2)
+ldflags-$(CONFIG_HEXAGON_ARCH_V3) += $(call cc-option,-mv3)
+ldflags-$(CONFIG_HEXAGON_ARCH_V4) += $(call cc-option,-mv4)
+
+KBUILD_CFLAGS += $(cflags-y)
+KBUILD_AFLAGS += $(aflags-y)
+
+#  no KBUILD_LDFLAGS?
+LDFLAGS += $(ldflags-y)
+
+# Thread-info register will be r19.  This value is not configureable;
+# it is hard-coded in several files.
+TIR_NAME := r19
+KBUILD_CFLAGS += -ffixed-$(TIR_NAME) -DTHREADINFO_REG=$(TIR_NAME) -D__linux__
+KBUILD_AFLAGS += -DTHREADINFO_REG=$(TIR_NAME)
+
+LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
+libs-y += $(LIBGCC)
+
+head-y := arch/hexagon/kernel/head.o \
+	arch/hexagon/kernel/init_task.o
+
+core-y += arch/hexagon/kernel/ \
+	arch/hexagon/mm/ \
+	arch/hexagon/lib/
+
+#	arch/hexagon/platform/common/
+#
+#core-$(CONFIG_HEXAGON_COMET)		+= arch/hexagon/platform/comet/
+#machine-$(CONFIG_HEXAGON_COMET)		:= comet
diff --git a/arch/hexagon/configs/comet_defconfig b/arch/hexagon/configs/comet_defconfig
new file mode 100644
index 0000000..e324f65
--- /dev/null
+++ b/arch/hexagon/configs/comet_defconfig
@@ -0,0 +1,85 @@
+CONFIG_SMP=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=0
+CONFIG_HZ_100=y
+CONFIG_EXPERIMENTAL=y
+CONFIG_CROSS_COMPILE="hexagon-"
+CONFIG_LOCALVERSION="-smp"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EMBEDDED=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_STANDALONE is not set
+CONFIG_CONNECTOR=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_NBD=y
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_PHYLIB=y
+CONFIG_NET_ETHERNET=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_CONSOLE_TRANSLATIONS is not set
+CONFIG_LEGACY_PTY_COUNT=64
+# CONFIG_DEVKMEM is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_SPI=y
+CONFIG_SPI_DEBUG=y
+CONFIG_SPI_BITBANG=y
+# CONFIG_HWMON is not set
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_LIBCRC32C=y
+CONFIG_FRAME_WARN=0
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_DEBUG_INFO=y
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
new file mode 100644
index 0000000..9aa17f1
--- /dev/null
+++ b/arch/hexagon/include/asm/Kbuild
@@ -0,0 +1,58 @@
+include include/asm-generic/Kbuild.asm
+
+header-y += registers.h
+header-y += ucontext.h
+header-y += user.h
+
+generic-y += auxvec.h
+generic-y += bug.h
+generic-y += bugs.h
+generic-y += cpumask.h
+generic-y += cputime.h
+generic-y += current.h
+generic-y += device.h
+generic-y += div64.h
+generic-y += emergency-restart.h
+generic-y += errno.h
+generic-y += fb.h
+generic-y += fcntl.h
+generic-y += ftrace.h
+generic-y += hardirq.h
+generic-y += hw_irq.h
+generic-y += ioctl.h
+generic-y += ioctls.h
+generic-y += iomap.h
+generic-y += ipcbuf.h
+generic-y += ipc.h
+generic-y += irq_regs.h
+generic-y += kdebug.h
+generic-y += kmap_types.h
+generic-y += local64.h
+generic-y += local.h
+generic-y += local.h
+generic-y += mman.h
+generic-y += msgbuf.h
+generic-y += pci.h
+generic-y += percpu.h
+generic-y += poll.h
+generic-y += posix_types.h
+generic-y += resource.h
+generic-y += rwsem.h
+generic-y += scatterlist.h
+generic-y += sections.h
+generic-y += segment.h
+generic-y += sembuf.h
+generic-y += shmbuf.h
+generic-y += shmparam.h
+generic-y += siginfo.h
+generic-y += socket.h
+generic-y += sockios.h
+generic-y += statfs.h
+generic-y += stat.h
+generic-y += termbits.h
+generic-y += termios.h
+generic-y += topology.h
+generic-y += types.h
+generic-y += ucontext.h
+generic-y += unaligned.h
+generic-y += xor.h
diff --git a/arch/hexagon/include/asm/asm-offsets.h b/arch/hexagon/include/asm/asm-offsets.h
new file mode 100644
index 0000000..d370ee3
--- /dev/null
+++ b/arch/hexagon/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/hexagon/include/asm/atomic.h b/arch/hexagon/include/asm/atomic.h
new file mode 100644
index 0000000..e220f90
--- /dev/null
+++ b/arch/hexagon/include/asm/atomic.h
@@ -0,0 +1,164 @@
+/*
+ * Atomic operations for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_ATOMIC_H
+#define _ASM_ATOMIC_H
+
+#include <linux/types.h>
+
+#define ATOMIC_INIT(i)		{ (i) }
+#define atomic_set(v, i)	((v)->counter = (i))
+
+/**
+ * atomic_read - reads a word, atomically
+ * @v: pointer to atomic value
+ *
+ * Assumes all word reads on our architecture are atomic.
+ */
+#define atomic_read(v)		((v)->counter)
+
+/**
+ * atomic_xchg - atomic
+ * @v: pointer to memory to change
+ * @new: new value (technically passed in a register -- see xchg)
+ */
+#define atomic_xchg(v, new)	(xchg(&((v)->counter), (new)))
+
+
+/**
+ * atomic_cmpxchg - atomic compare-and-exchange values
+ * @v: pointer to value to change
+ * @old:  desired old value to match
+ * @new:  new value to put in
+ *
+ * Parameters are then pointer, value-in-register, value-in-register,
+ * and the output is the old value.
+ *
+ * Apparently this is complicated for archs that don't support
+ * the memw_locked like we do (or it's broken or whatever).
+ *
+ * Kind of the lynchpin of the rest of the generically defined routines.
+ * Remember V2 had that bug with dotnew predicate set by memw_locked.
+ *
+ * "old" is "expected" old val, __oldval is actual old value
+ */
+static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
+{
+	int __oldval;
+
+	asm volatile(
+		"1:	%0 = memw_locked(%1);\n"
+		"	{ P0 = cmp.eq(%0,%2);\n"
+		"	  if (!P0.new) jump:nt 2f; }\n"
+		"	memw_locked(%1,P0) = %3;\n"
+		"	if (!P0) jump 1b;\n"
+		"2:\n"
+		: "=&r" (__oldval)
+		: "r" (&v->counter), "r" (old), "r" (new)
+		: "memory", "p0"
+	);
+
+	return __oldval;
+}
+
+static inline int atomic_add_return(int i, atomic_t *v)
+{
+	int output;
+
+	__asm__ __volatile__ (
+		"1:	%0 = memw_locked(%1);\n"
+		"	%0 = add(%0,%2);\n"
+		"	memw_locked(%1,P3)=%0;\n"
+		"	if !P3 jump 1b;\n"
+		: "=&r" (output)
+		: "r" (&v->counter), "r" (i)
+		: "memory", "p3"
+	);
+	return output;
+
+}
+
+#define atomic_add(i, v) atomic_add_return(i, (v))
+
+static inline int atomic_sub_return(int i, atomic_t *v)
+{
+	int output;
+	__asm__ __volatile__ (
+		"1:	%0 = memw_locked(%1);\n"
+		"	%0 = sub(%0,%2);\n"
+		"	memw_locked(%1,P3)=%0\n"
+		"	if !P3 jump 1b;\n"
+		: "=&r" (output)
+		: "r" (&v->counter), "r" (i)
+		: "memory", "p3"
+	);
+	return output;
+}
+
+#define atomic_sub(i, v) atomic_sub_return(i, (v))
+
+/**
+ * atomic_add_unless - add unless the number is a given value
+ * @v: pointer to value
+ * @a: amount to add
+ * @u: unless value is equal to u
+ *
+ * Returns 1 if the add happened, 0 if it didn't.
+ */
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
+{
+	int output, __oldval;
+	asm volatile(
+		"1:	%0 = memw_locked(%2);"
+		"	{"
+		"		p3 = cmp.eq(%0, %4);"
+		"		if (p3.new) jump:nt 2f;"
+		"		%0 = add(%0, %3);"
+		"		%1 = #0;"
+		"	}"
+		"	memw_locked(%2, p3) = %0;"
+		"	{"
+		"		if !p3 jump 1b;"
+		"		%1 = #1;"
+		"	}"
+		"2:"
+		: "=&r" (__oldval), "=&r" (output)
+		: "r" (v), "r" (a), "r" (u)
+		: "memory", "p3"
+	);
+	return output;
+}
+
+#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
+
+#define atomic_inc(v) atomic_add(1, (v))
+#define atomic_dec(v) atomic_sub(1, (v))
+
+#define atomic_inc_and_test(v) (atomic_add_return(1, (v)) == 0)
+#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
+#define atomic_sub_and_test(i, v) (atomic_sub_return(i, (v)) == 0)
+#define atomic_add_negative(i, v) (atomic_add_return(i, (v)) < 0)
+
+
+#define atomic_inc_return(v) (atomic_add_return(1, v))
+#define atomic_dec_return(v) (atomic_sub_return(1, v))
+
+#endif
diff --git a/arch/hexagon/include/asm/bitops.h b/arch/hexagon/include/asm/bitops.h
new file mode 100644
index 0000000..d23461e
--- /dev/null
+++ b/arch/hexagon/include/asm/bitops.h
@@ -0,0 +1,301 @@
+/*
+ * Bit operations for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_BITOPS_H
+#define _ASM_BITOPS_H
+
+#include <linux/compiler.h>
+#include <asm/byteorder.h>
+#include <asm/system.h>
+#include <asm/atomic.h>
+
+#ifdef __KERNEL__
+
+#define smp_mb__before_clear_bit()	barrier()
+#define smp_mb__after_clear_bit()	barrier()
+
+/*
+ * The offset calculations for these are based on BITS_PER_LONG == 32
+ * (i.e. I get to shift by #5-2 (32 bits per long, 4 bytes per access),
+ * mask by 0x0000001F)
+ *
+ * Typically, R10 is clobbered for address, R11 bit nr, and R12 is temp
+ */
+
+/**
+ * test_and_clear_bit - clear a bit and return its old value
+ * @nr:  bit number to clear
+ * @addr:  pointer to memory
+ */
+static inline int test_and_clear_bit(int nr, volatile void *addr)
+{
+	int oldval;
+
+	__asm__ __volatile__ (
+	"	{R10 = %1; R11 = asr(%2,#5); }\n"
+	"	{R10 += asl(R11,#2); R11 = and(%2,#0x1f)}\n"
+	"1:	R12 = memw_locked(R10);\n"
+	"	{ P0 = tstbit(R12,R11); R12 = clrbit(R12,R11); }\n"
+	"	memw_locked(R10,P1) = R12;\n"
+	"	{if !P1 jump 1b; %0 = mux(P0,#1,#0);}\n"
+	: "=&r" (oldval)
+	: "r" (addr), "r" (nr)
+	: "r10", "r11", "r12", "p0", "p1", "memory"
+	);
+
+	return oldval;
+}
+
+/**
+ * test_and_set_bit - set a bit and return its old value
+ * @nr:  bit number to set
+ * @addr:  pointer to memory
+ */
+static inline int test_and_set_bit(int nr, volatile void *addr)
+{
+	int oldval;
+
+	__asm__ __volatile__ (
+	"	{R10 = %1; R11 = asr(%2,#5); }\n"
+	"	{R10 += asl(R11,#2); R11 = and(%2,#0x1f)}\n"
+	"1:	R12 = memw_locked(R10);\n"
+	"	{ P0 = tstbit(R12,R11); R12 = setbit(R12,R11); }\n"
+	"	memw_locked(R10,P1) = R12;\n"
+	"	{if !P1 jump 1b; %0 = mux(P0,#1,#0);}\n"
+	: "=&r" (oldval)
+	: "r" (addr), "r" (nr)
+	: "r10", "r11", "r12", "p0", "p1", "memory"
+	);
+
+
+	return oldval;
+
+}
+
+/**
+ * test_and_change_bit - toggle a bit and return its old value
+ * @nr:  bit number to set
+ * @addr:  pointer to memory
+ */
+static inline int test_and_change_bit(int nr, volatile void *addr)
+{
+	int oldval;
+
+	__asm__ __volatile__ (
+	"	{R10 = %1; R11 = asr(%2,#5); }\n"
+	"	{R10 += asl(R11,#2); R11 = and(%2,#0x1f)}\n"
+	"1:	R12 = memw_locked(R10);\n"
+	"	{ P0 = tstbit(R12,R11); R12 = togglebit(R12,R11); }\n"
+	"	memw_locked(R10,P1) = R12;\n"
+	"	{if !P1 jump 1b; %0 = mux(P0,#1,#0);}\n"
+	: "=&r" (oldval)
+	: "r" (addr), "r" (nr)
+	: "r10", "r11", "r12", "p0", "p1", "memory"
+	);
+
+	return oldval;
+
+}
+
+/*
+ * Atomic, but doesn't care about the return value.
+ * Rewrite later to save a cycle or two.
+ */
+
+static inline void clear_bit(int nr, volatile void *addr)
+{
+	test_and_clear_bit(nr, addr);
+}
+
+static inline void set_bit(int nr, volatile void *addr)
+{
+	test_and_set_bit(nr, addr);
+}
+
+static inline void change_bit(int nr, volatile void *addr)
+{
+	test_and_change_bit(nr, addr);
+}
+
+
+/*
+ * These are allowed to be non-atomic.  In fact the generic flavors are
+ * in non-atomic.h.  Would it be better to use intrinsics for this?
+ *
+ * OK, writes in our architecture do not invalidate LL/SC, so this has to
+ * be atomic, particularly for things like slab_lock and slab_unlock.
+ *
+ */
+static inline void __clear_bit(int nr, volatile unsigned long *addr)
+{
+	test_and_clear_bit(nr, addr);
+}
+
+static inline void __set_bit(int nr, volatile unsigned long *addr)
+{
+	test_and_set_bit(nr, addr);
+}
+
+static inline void __change_bit(int nr, volatile unsigned long *addr)
+{
+	test_and_change_bit(nr, addr);
+}
+
+/*  Apparently, at least some of these are allowed to be non-atomic  */
+static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
+{
+	return test_and_clear_bit(nr, addr);
+}
+
+static inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
+{
+	return test_and_set_bit(nr, addr);
+}
+
+static inline int __test_and_change_bit(int nr, volatile unsigned long *addr)
+{
+	return test_and_change_bit(nr, addr);
+}
+
+static inline int __test_bit(int nr, const volatile unsigned long *addr)
+{
+	int retval;
+
+	asm volatile(
+	"{P0 = tstbit(%1,%2); if (P0.new) %0 = #1; if (!P0.new) %0 = #0;}\n"
+	: "=&r" (retval)
+	: "r" (addr[BIT_WORD(nr)]), "r" (nr % BITS_PER_LONG)
+	: "p0"
+	);
+
+	return retval;
+}
+
+#define test_bit(nr, addr) __test_bit(nr, addr)
+
+/*
+ * ffz - find first zero in word.
+ * @word: The word to search
+ *
+ * Undefined if no zero exists, so code should check against ~0UL first.
+ */
+static inline long ffz(int x)
+{
+	int r;
+
+	asm("%0 = ct1(%1);\n"
+		: "=&r" (r)
+		: "r" (x));
+	return r;
+}
+
+/*
+ * fls - find last (most-significant) bit set
+ * @x: the word to search
+ *
+ * This is defined the same way as ffs.
+ * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
+ */
+static inline long fls(int x)
+{
+	int r;
+
+	asm("{ %0 = cl0(%1);}\n"
+		"%0 = sub(#32,%0);\n"
+		: "=&r" (r)
+		: "r" (x)
+		: "p0");
+
+	return r;
+}
+
+/*
+ * ffs - find first bit set
+ * @x: the word to search
+ *
+ * This is defined the same way as
+ * the libc and compiler builtin ffs routines, therefore
+ * differs in spirit from the above ffz (man ffs).
+ */
+static inline long ffs(int x)
+{
+	int r;
+
+	asm("{ P0 = cmp.eq(%1,#0); %0 = ct0(%1);}\n"
+		"{ if P0 %0 = #0; if !P0 %0 = add(%0,#1);}\n"
+		: "=&r" (r)
+		: "r" (x)
+		: "p0");
+
+	return r;
+}
+
+/*
+ * __ffs - find first bit in word.
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ *
+ * bits_per_long assumed to be 32
+ * numbering starts at 0 I think (instead of 1 like ffs)
+ */
+static inline unsigned long __ffs(unsigned long word)
+{
+	int num;
+
+	asm("%0 = ct0(%1);\n"
+		: "=&r" (num)
+		: "r" (word));
+
+	return num;
+}
+
+/*
+ * __fls - find last (most-significant) set bit in a long word
+ * @word: the word to search
+ *
+ * Undefined if no set bit exists, so code should check against 0 first.
+ * bits_per_long assumed to be 32
+ */
+static inline unsigned long __fls(unsigned long word)
+{
+	int num;
+
+	asm("%0 = cl0(%1);\n"
+		"%0 = sub(#31,%0);\n"
+		: "=&r" (num)
+		: "r" (word));
+
+	return num;
+}
+
+#include <asm-generic/bitops/lock.h>
+#include <asm-generic/bitops/find.h>
+
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/sched.h>
+#include <asm-generic/bitops/hweight.h>
+
+#include <asm-generic/bitops/le.h>
+#include <asm-generic/bitops/ext2-atomic.h>
+
+#endif /* __KERNEL__ */
+#endif
diff --git a/arch/hexagon/include/asm/bitsperlong.h b/arch/hexagon/include/asm/bitsperlong.h
new file mode 100644
index 0000000..2701cae
--- /dev/null
+++ b/arch/hexagon/include/asm/bitsperlong.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __ASM_HEXAGON_BITSPERLONG_H
+#define __ASM_HEXAGON_BITSPERLONG_H
+
+#define __BITS_PER_LONG 32
+
+#include <asm-generic/bitsperlong.h>
+
+#endif
diff --git a/arch/hexagon/include/asm/byteorder.h b/arch/hexagon/include/asm/byteorder.h
new file mode 100644
index 0000000..0e19b9f
--- /dev/null
+++ b/arch/hexagon/include/asm/byteorder.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_BYTEORDER_H
+#define _ASM_BYTEORDER_H
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+#  define __BYTEORDER_HAS_U64__
+#endif
+
+#include <linux/byteorder/little_endian.h>
+
+#endif /* _ASM_BYTEORDER_H */
diff --git a/arch/hexagon/include/asm/cache.h b/arch/hexagon/include/asm/cache.h
new file mode 100644
index 0000000..0f01de2
--- /dev/null
+++ b/arch/hexagon/include/asm/cache.h
@@ -0,0 +1,34 @@
+/*
+ * Cache definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __ASM_CACHE_H
+#define __ASM_CACHE_H
+
+/* Bytes per L1 cache line */
+#define L1_CACHE_SHIFT		(5)
+#define L1_CACHE_BYTES		(1 << L1_CACHE_SHIFT)
+
+#define __cacheline_aligned	__aligned(L1_CACHE_BYTES)
+#define ____cacheline_aligned	__aligned(L1_CACHE_BYTES)
+
+/* See http://kerneltrap.org/node/15100  */
+#define __read_mostly
+
+#endif
diff --git a/arch/hexagon/include/asm/cacheflush.h b/arch/hexagon/include/asm/cacheflush.h
new file mode 100644
index 0000000..6865c1b
--- /dev/null
+++ b/arch/hexagon/include/asm/cacheflush.h
@@ -0,0 +1,99 @@
+/*
+ * Cache flush operations for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_CACHEFLUSH_H
+#define _ASM_CACHEFLUSH_H
+
+#include <linux/cache.h>
+#include <linux/mm.h>
+#include <asm/string.h>
+#include <asm-generic/cacheflush.h>
+
+/* Cache flushing:
+ *
+ *  - flush_cache_all() flushes entire cache
+ *  - flush_cache_mm(mm) flushes the specified mm context's cache lines
+ *  - flush_cache_page(mm, vmaddr, pfn) flushes a single page
+ *  - flush_cache_range(vma, start, end) flushes a range of pages
+ *  - flush_icache_range(start, end) flush a range of instructions
+ *  - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache
+ *  - flush_icache_page(vma, pg) flushes(invalidates) a page for icache
+ *
+ *  Need to doublecheck which one is really needed for ptrace stuff to work.
+ */
+#define LINESIZE	32
+#define LINEBITS	5
+
+/*
+ * Flush Dcache range through current map.
+ */
+extern void flush_dcache_range(unsigned long start, unsigned long end);
+
+/*
+ * Flush Icache range through current map.
+ */
+#undef flush_icache_range
+extern void flush_icache_range(unsigned long start, unsigned long end);
+
+/*
+ * Memory-management related flushes are there to ensure in non-physically
+ * indexed cache schemes that stale lines belonging to a given ASID aren't
+ * in the cache to confuse things.  The prototype Hexagon Virtual Machine
+ * only uses a single ASID for all user-mode maps, which should
+ * mean that they aren't necessary.  A brute-force, flush-everything
+ * implementation, with the name xxxxx_hexagon() is present in
+ * arch/hexagon/mm/cache.c, but let's not wire it up until we know
+ * it is needed.
+ */
+extern void flush_cache_all_hexagon(void);
+
+/*
+ * This may or may not ever have to be non-null, depending on the
+ * virtual machine MMU.  For a native kernel, it's definitiely  a no-op
+ *
+ * This is also the place where deferred cache coherency stuff seems
+ * to happen, classically...  but instead we do it like ia64 and
+ * clean the cache when the PTE is set.
+ *
+ */
+static inline void update_mmu_cache(struct vm_area_struct *vma,
+					unsigned long address, pte_t *ptep)
+{
+	/*  generic_ptrace_pokedata doesn't wind up here, does it?  */
+}
+
+#undef copy_to_user_page
+static inline void copy_to_user_page(struct vm_area_struct *vma,
+					     struct page *page,
+					     unsigned long vaddr,
+					     void *dst, void *src, int len)
+{
+	memcpy(dst, src, len);
+	if (vma->vm_flags & VM_EXEC) {
+		flush_icache_range((unsigned long) dst,
+		(unsigned long) dst + len);
+	}
+}
+
+
+extern void hexagon_inv_dcache_range(unsigned long start, unsigned long end);
+extern void hexagon_clean_dcache_range(unsigned long start, unsigned long end);
+
+#endif
diff --git a/arch/hexagon/include/asm/checksum.h b/arch/hexagon/include/asm/checksum.h
new file mode 100644
index 0000000..3ce4ecd
--- /dev/null
+++ b/arch/hexagon/include/asm/checksum.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_CHECKSUM_H
+#define _ASM_CHECKSUM_H
+
+#define do_csum	do_csum
+unsigned int do_csum(const void *voidptr, int len);
+
+/*
+ * the same as csum_partial, but copies from src while it
+ * checksums
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+#define csum_partial_copy_nocheck csum_partial_copy_nocheck
+__wsum csum_partial_copy_nocheck(const void *src, void *dst,
+					int len, __wsum sum);
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+#define csum_tcpudp_nofold csum_tcpudp_nofold
+__wsum csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr,
+	unsigned short len, unsigned short proto, __wsum sum);
+
+#define csum_tcpudp_magic csum_tcpudp_magic
+__sum16 csum_tcpudp_magic(unsigned long saddr, unsigned long daddr,
+	unsigned short len, unsigned short proto, __wsum sum);
+
+#include <asm-generic/checksum.h>
+
+#endif
diff --git a/arch/hexagon/include/asm/delay.h b/arch/hexagon/include/asm/delay.h
new file mode 100644
index 0000000..9ab12e9
--- /dev/null
+++ b/arch/hexagon/include/asm/delay.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_DELAY_H
+#define _ASM_DELAY_H
+
+#include <asm/param.h>
+
+extern void __udelay(unsigned long usecs);
+
+#define udelay(usecs) __udelay((usecs))
+
+#endif /* _ASM_DELAY_H */
diff --git a/arch/hexagon/include/asm/dma-mapping.h b/arch/hexagon/include/asm/dma-mapping.h
new file mode 100644
index 0000000..448b224
--- /dev/null
+++ b/arch/hexagon/include/asm/dma-mapping.h
@@ -0,0 +1,101 @@
+/*
+ * DMA operations for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_DMA_MAPPING_H
+#define _ASM_DMA_MAPPING_H
+
+#include <linux/types.h>
+#include <linux/cache.h>
+#include <linux/mm.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma-debug.h>
+#include <linux/dma-attrs.h>
+#include <asm/io.h>
+
+struct device;
+extern int bad_dma_address;
+
+extern struct dma_map_ops *dma_ops;
+
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+
+static inline struct dma_map_ops *get_dma_ops(struct device *dev)
+{
+	if (unlikely(dev == NULL))
+		return NULL;
+
+	return dma_ops;
+}
+
+extern int dma_supported(struct device *dev, u64 mask);
+extern int dma_set_mask(struct device *dev, u64 mask);
+extern int dma_is_consistent(struct device *dev, dma_addr_t dma_handle);
+extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+			   enum dma_data_direction direction);
+
+#include <asm-generic/dma-mapping-common.h>
+
+static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+{
+	if (!dev->dma_mask)
+		return 0;
+	return addr + size - 1 <= *dev->dma_mask;
+}
+
+static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+	struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+	if (dma_ops->mapping_error)
+		return dma_ops->mapping_error(dev, dma_addr);
+
+	return (dma_addr == bad_dma_address);
+}
+
+static inline void *dma_alloc_coherent(struct device *dev, size_t size,
+				       dma_addr_t *dma_handle, gfp_t flag)
+{
+	void *ret;
+	struct dma_map_ops *ops = get_dma_ops(dev);
+
+	BUG_ON(!dma_ops);
+
+	ret = ops->alloc_coherent(dev, size, dma_handle, flag);
+
+	debug_dma_alloc_coherent(dev, size, *dma_handle, ret);
+
+	return ret;
+}
+
+static inline void dma_free_coherent(struct device *dev, size_t size,
+				     void *cpu_addr, dma_addr_t dma_handle)
+{
+	struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+	BUG_ON(!dma_ops);
+
+	dma_ops->free_coherent(dev, size, cpu_addr, dma_handle);
+
+	debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
+}
+
+#endif
diff --git a/arch/hexagon/include/asm/dma.h b/arch/hexagon/include/asm/dma.h
new file mode 100644
index 0000000..da6d2f6
--- /dev/null
+++ b/arch/hexagon/include/asm/dma.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_DMA_H
+#define _ASM_DMA_H
+
+#include <asm/io.h>
+
+#define MAX_DMA_CHANNELS 1
+#define MAX_DMA_ADDRESS  (PAGE_OFFSET)
+
+extern size_t hexagon_coherent_pool_size;
+
+#endif
diff --git a/arch/hexagon/include/asm/elf.h b/arch/hexagon/include/asm/elf.h
new file mode 100644
index 0000000..37976a0
--- /dev/null
+++ b/arch/hexagon/include/asm/elf.h
@@ -0,0 +1,229 @@
+/*
+ * ELF definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __ASM_ELF_H
+#define __ASM_ELF_H
+
+#include <asm/ptrace.h>
+#include <asm/user.h>
+
+/*
+ * This should really be in linux/elf-em.h.
+ */
+#define EM_HEXAGON	164   /* QUALCOMM Hexagon */
+
+struct elf32_hdr;
+
+/*
+ * ELF header e_flags defines.
+ */
+
+/*  should have stuff like "CPU type" and maybe "ABI version", etc  */
+
+/* Hexagon relocations */
+  /* V2 */
+#define R_HEXAGON_NONE           0
+#define R_HEXAGON_B22_PCREL      1
+#define R_HEXAGON_B15_PCREL      2
+#define R_HEXAGON_B7_PCREL       3
+#define R_HEXAGON_LO16           4
+#define R_HEXAGON_HI16           5
+#define R_HEXAGON_32             6
+#define R_HEXAGON_16             7
+#define R_HEXAGON_8              8
+#define R_HEXAGON_GPREL16_0      9
+#define R_HEXAGON_GPREL16_1     10
+#define R_HEXAGON_GPREL16_2     11
+#define R_HEXAGON_GPREL16_3     12
+#define R_HEXAGON_HL16          13
+  /* V3 */
+#define R_HEXAGON_B13_PCREL     14
+  /* V4 */
+#define R_HEXAGON_B9_PCREL      15
+  /* V4 (extenders) */
+#define R_HEXAGON_B32_PCREL_X   16
+#define R_HEXAGON_32_6_X        17
+  /* V4 (extended) */
+#define R_HEXAGON_B22_PCREL_X   18
+#define R_HEXAGON_B15_PCREL_X   19
+#define R_HEXAGON_B13_PCREL_X   20
+#define R_HEXAGON_B9_PCREL_X    21
+#define R_HEXAGON_B7_PCREL_X    22
+#define R_HEXAGON_16_X          23
+#define R_HEXAGON_12_X          24
+#define R_HEXAGON_11_X          25
+#define R_HEXAGON_10_X          26
+#define R_HEXAGON_9_X           27
+#define R_HEXAGON_8_X           28
+#define R_HEXAGON_7_X           29
+#define R_HEXAGON_6_X           30
+  /* V2 PIC */
+#define R_HEXAGON_32_PCREL      31
+#define R_HEXAGON_COPY          32
+#define R_HEXAGON_GLOB_DAT      33
+#define R_HEXAGON_JMP_SLOT      34
+#define R_HEXAGON_RELATIVE      35
+#define R_HEXAGON_PLT_B22_PCREL 36
+#define R_HEXAGON_GOTOFF_LO16   37
+#define R_HEXAGON_GOTOFF_HI16   38
+#define R_HEXAGON_GOTOFF_32     39
+#define R_HEXAGON_GOT_LO16      40
+#define R_HEXAGON_GOT_HI16      41
+#define R_HEXAGON_GOT_32        42
+#define R_HEXAGON_GOT_16        43
+
+/*
+ * ELF register definitions..
+ */
+typedef unsigned long elf_greg_t;
+
+typedef struct user_regs_struct elf_gregset_t;
+#define ELF_NGREG (sizeof(elf_gregset_t)/sizeof(unsigned long))
+
+/*  Placeholder  */
+typedef unsigned long elf_fpregset_t;
+
+/*
+ * Bypass the whole "regsets" thing for now and use the define.
+ */
+
+#define ELF_CORE_COPY_REGS(DEST, REGS)	\
+do {					\
+	DEST.r0 = REGS->r00;		\
+	DEST.r1 = REGS->r01;		\
+	DEST.r2 = REGS->r02;		\
+	DEST.r3 = REGS->r03;		\
+	DEST.r4 = REGS->r04;		\
+	DEST.r5 = REGS->r05;		\
+	DEST.r6 = REGS->r06;		\
+	DEST.r7 = REGS->r07;		\
+	DEST.r8 = REGS->r08;		\
+	DEST.r9 = REGS->r09;		\
+	DEST.r10 = REGS->r10;		\
+	DEST.r11 = REGS->r11;		\
+	DEST.r12 = REGS->r12;		\
+	DEST.r13 = REGS->r13;		\
+	DEST.r14 = REGS->r14;		\
+	DEST.r15 = REGS->r15;		\
+	DEST.r16 = REGS->r16;		\
+	DEST.r17 = REGS->r17;		\
+	DEST.r18 = REGS->r18;		\
+	DEST.r19 = REGS->r19;		\
+	DEST.r20 = REGS->r20;		\
+	DEST.r21 = REGS->r21;		\
+	DEST.r22 = REGS->r22;		\
+	DEST.r23 = REGS->r23;		\
+	DEST.r24 = REGS->r24;		\
+	DEST.r25 = REGS->r25;		\
+	DEST.r26 = REGS->r26;		\
+	DEST.r27 = REGS->r27;		\
+	DEST.r28 = REGS->r28;		\
+	DEST.r29 = pt_psp(REGS);	\
+	DEST.r30 = REGS->r30;		\
+	DEST.r31 = REGS->r31;		\
+	DEST.sa0 = REGS->sa0;		\
+	DEST.lc0 = REGS->lc0;		\
+	DEST.sa1 = REGS->sa1;		\
+	DEST.lc1 = REGS->lc1;		\
+	DEST.m0 = REGS->m0;		\
+	DEST.m1 = REGS->m1;		\
+	DEST.usr = REGS->usr;		\
+	DEST.p3_0 = REGS->preds;	\
+	DEST.gp = REGS->gp;		\
+	DEST.ugp = REGS->ugp;		\
+	DEST.pc = pt_elr(REGS);	\
+	DEST.cause = pt_cause(REGS);	\
+	DEST.badva = pt_badva(REGS);	\
+} while (0);
+
+
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ * Checks the machine and ABI type.
+ */
+#define elf_check_arch(hdr)	((hdr)->e_machine == EM_HEXAGON)
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS	ELFCLASS32
+#define ELF_DATA	ELFDATA2LSB
+#define ELF_ARCH	EM_HEXAGON
+
+#ifdef CONFIG_HEXAGON_ARCH_V2
+#define ELF_CORE_EFLAGS 0x1
+#endif
+
+#ifdef CONFIG_HEXAGON_ARCH_V3
+#define ELF_CORE_EFLAGS 0x2
+#endif
+
+#ifdef CONFIG_HEXAGON_ARCH_V4
+#define ELF_CORE_EFLAGS 0x3
+#endif
+
+/*
+ * Some architectures have ld.so set up a pointer to a function
+ * to be registered using atexit, to facilitate cleanup.  So that
+ * static executables will be well-behaved, we would null the register
+ * in question here, in the pt_regs structure passed.  For now,
+ * leave it a null macro.
+ */
+#define ELF_PLAT_INIT(regs, load_addr) do { } while (0)
+
+#define USE_ELF_CORE_DUMP
+#define CORE_DUMP_USE_REGSET
+
+/* Hrm is this going to cause problems for changing PAGE_SIZE?  */
+#define ELF_EXEC_PAGESIZE	4096
+
+/*
+ * This is the location that an ET_DYN program is loaded if exec'ed.  Typical
+ * use of this is to invoke "./ld.so someprog" to test out a new version of
+ * the loader.  We need to make sure that it is out of the way of the program
+ * that it will "exec", and that there is sufficient room for the brk.
+ */
+#define ELF_ET_DYN_BASE         0x08000000UL
+
+/*
+ * This yields a mask that user programs can use to figure out what
+ * instruction set this cpu supports.
+ */
+#define ELF_HWCAP	(0)
+
+/*
+ * This yields a string that ld.so will use to load implementation
+ * specific libraries for optimization.  This is more specific in
+ * intent than poking at uname or /proc/cpuinfo.
+ */
+#define ELF_PLATFORM  (NULL)
+
+#ifdef __KERNEL__
+#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+#endif
+
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
+struct linux_binprm;
+extern int arch_setup_additional_pages(struct linux_binprm *bprm,
+				       int uses_interp);
+
+
+#endif
diff --git a/arch/hexagon/include/asm/fixmap.h b/arch/hexagon/include/asm/fixmap.h
new file mode 100644
index 0000000..b27f494
--- /dev/null
+++ b/arch/hexagon/include/asm/fixmap.h
@@ -0,0 +1,73 @@
+/*
+ * Fixmap support for Hexagon - enough to support highmem features
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_FIXMAP_H
+#define _ASM_FIXMAP_H
+
+/*
+ * A lot of the fixmap info is already in mem-layout.h
+ */
+#include <asm/mem-layout.h>
+
+/*
+ * Full fixmap support involves set_fixmap() functions, but
+ * these may not be needed if all we're after is an area for
+ * highmem kernel mappings.
+ */
+#define	__fix_to_virt(x)	(FIXADDR_TOP - ((x) << PAGE_SHIFT))
+#define	__virt_to_fix(x)	((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
+
+extern void __this_fixmap_does_not_exist(void);
+
+/**
+ * fix_to_virt -- "index to address" translation.
+ *
+ * If anyone tries to use the idx directly without translation,
+ * we catch the bug with a NULL-deference kernel oops. Illegal
+ * ranges of incoming indices are caught too.
+ */
+static inline unsigned long fix_to_virt(const unsigned int idx)
+{
+	/*
+	 * This branch gets completely eliminated after inlining,
+	 * except when someone tries to use fixaddr indices in an
+	 * illegal way. (such as mixing up address types or using
+	 * out-of-range indices).
+	 *
+	 * If it doesn't get removed, the linker will complain
+	 * loudly with a reasonably clear error message..
+	 */
+	if (idx >= __end_of_fixed_addresses)
+		__this_fixmap_does_not_exist();
+
+	return __fix_to_virt(idx);
+}
+
+static inline unsigned long virt_to_fix(const unsigned long vaddr)
+{
+	BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
+	return __virt_to_fix(vaddr);
+}
+
+#define kmap_get_fixmap_pte(vaddr) \
+	pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), \
+				(vaddr)), (vaddr)), (vaddr))
+
+#endif
diff --git a/arch/hexagon/include/asm/fpu.h b/arch/hexagon/include/asm/fpu.h
new file mode 100644
index 0000000..0e135ea
--- /dev/null
+++ b/arch/hexagon/include/asm/fpu.h
@@ -0,0 +1,4 @@
+/*
+ * If the FPU is used inside the kernel,
+ * kernel_fpu_end() will be defined here.
+ */
diff --git a/arch/hexagon/include/asm/futex.h b/arch/hexagon/include/asm/futex.h
new file mode 100644
index 0000000..7e597f8
--- /dev/null
+++ b/arch/hexagon/include/asm/futex.h
@@ -0,0 +1,137 @@
+#ifndef _ASM_HEXAGON_FUTEX_H
+#define _ASM_HEXAGON_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <linux/uaccess.h>
+#include <asm/errno.h>
+
+/* XXX TODO-- need to add sync barriers! */
+
+#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
+	__asm__ __volatile( \
+	"1: %0 = memw_locked(%3);\n" \
+	    /* For example: %1 = %4 */ \
+	    insn \
+	"2: memw_locked(%3,p2) = %1;\n" \
+	"   if !p2 jump 1b;\n" \
+	"   %1 = #0;\n" \
+	"3:\n" \
+	".section .fixup,\"ax\"\n" \
+	"4: %1 = #%5;\n" \
+	"   jump 3b\n" \
+	".previous\n" \
+	".section __ex_table,\"a\"\n" \
+	".long 1b,4b,2b,4b\n" \
+	".previous\n" \
+	: "=&r" (oldval), "=&r" (ret), "+m" (*uaddr) \
+	: "r" (uaddr), "r" (oparg), "i" (-EFAULT) \
+	: "p2", "memory")
+
+
+static inline int
+futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+{
+	int op = (encoded_op >> 28) & 7;
+	int cmp = (encoded_op >> 24) & 15;
+	int oparg = (encoded_op << 8) >> 20;
+	int cmparg = (encoded_op << 20) >> 20;
+	int oldval = 0, ret;
+	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+		oparg = 1 << oparg;
+
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+		return -EFAULT;
+
+	pagefault_disable();
+
+	switch (op) {
+	case FUTEX_OP_SET:
+		__futex_atomic_op("%1 = %4\n", ret, oldval, uaddr, oparg);
+		break;
+	case FUTEX_OP_ADD:
+		__futex_atomic_op("%1 = add(%0,%4)\n", ret, oldval, uaddr,
+				  oparg);
+		break;
+	case FUTEX_OP_OR:
+		__futex_atomic_op("%1 = or(%0,%4)\n", ret, oldval, uaddr,
+				  oparg);
+		break;
+	case FUTEX_OP_ANDN:
+		__futex_atomic_op("%1 = not(%4); %1 = and(%0,%1)\n", ret,
+				  oldval, uaddr, oparg);
+		break;
+	case FUTEX_OP_XOR:
+		__futex_atomic_op("%1 = xor(%0,%4)\n", ret, oldval, uaddr,
+				  oparg);
+		break;
+	default:
+		ret = -ENOSYS;
+	}
+
+	pagefault_enable();
+
+	if (!ret) {
+		switch (cmp) {
+		case FUTEX_OP_CMP_EQ:
+			ret = (oldval == cmparg);
+			break;
+		case FUTEX_OP_CMP_NE:
+			ret = (oldval != cmparg);
+			break;
+		case FUTEX_OP_CMP_LT:
+			ret = (oldval < cmparg);
+			break;
+		case FUTEX_OP_CMP_GE:
+			ret = (oldval >= cmparg);
+			break;
+		case FUTEX_OP_CMP_LE:
+			ret = (oldval <= cmparg);
+			break;
+		case FUTEX_OP_CMP_GT:
+			ret = (oldval > cmparg);
+			break;
+		default:
+			ret = -ENOSYS;
+		}
+	}
+	return ret;
+}
+
+static inline int
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, u32 oldval,
+			      u32 newval)
+{
+	int prev;
+	int ret;
+
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
+		return -EFAULT;
+
+	__asm__ __volatile__ (
+	"1: %1 = memw_locked(%3)\n"
+	"   {\n"
+	"      p2 = cmp.eq(%1,%4)\n"
+	"      if !p2.new jump:NT 3f\n"
+	"   }\n"
+	"2: memw_locked(%3,p2) = %5\n"
+	"   if !p2 jump 1b\n"
+	"3:\n"
+	".section .fixup,\"ax\"\n"
+	"4: %0 = #%6\n"
+	"   jump 3b\n"
+	".previous\n"
+	".section __ex_table,\"a\"\n"
+	".long 1b,4b,2b,4b\n"
+	".previous\n"
+	: "+r" (ret), "=&r" (prev), "+m" (*uaddr)
+	: "r" (uaddr), "r" (oldval), "r" (newval), "i"(-EFAULT)
+	: "p2", "memory");
+
+	*uval = prev;
+	return ret;
+}
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_HEXAGON_FUTEX_H */
diff --git a/arch/hexagon/include/asm/hexagon_vm.h b/arch/hexagon/include/asm/hexagon_vm.h
new file mode 100644
index 0000000..182cb9d
--- /dev/null
+++ b/arch/hexagon/include/asm/hexagon_vm.h
@@ -0,0 +1,281 @@
+/*
+ * Declarations for to Hexagon Virtal Machine.
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef ASM_HEXAGON_VM_H
+#define ASM_HEXAGON_VM_H
+
+/*
+ * In principle, a Linux kernel for the VM could
+ * selectively define the virtual instructions
+ * as inline assembler macros, but for a first pass,
+ * we'll use subroutines for both the VM and the native
+ * kernels.  It's costing a subroutine call/return,
+ * but it makes for a single set of entry points
+ * for tracing/debugging.
+ */
+
+/*
+ * Lets make this stuff visible only if configured,
+ * so we can unconditionally include the file.
+ */
+
+#ifndef __ASSEMBLY__
+
+enum VM_CACHE_OPS {
+	ickill,
+	dckill,
+	l2kill,
+	dccleaninva,
+	icinva,
+	idsync,
+	fetch_cfg
+};
+
+enum VM_INT_OPS {
+	nop,
+	globen,
+	globdis,
+	locen,
+	locdis,
+	affinity,
+	get,
+	peek,
+	status,
+	post,
+	clear
+};
+
+extern void _K_VM_event_vector(void);
+
+void __vmrte(void);
+long __vmsetvec(void *);
+long __vmsetie(long);
+long __vmgetie(void);
+long __vmintop(enum VM_INT_OPS, long, long, long, long);
+long __vmclrmap(void *, unsigned long);
+long __vmnewmap(void *);
+long __vmcache(enum VM_CACHE_OPS op, unsigned long addr, unsigned long len);
+unsigned long long __vmgettime(void);
+long __vmsettime(unsigned long long);
+long __vmstart(void *, void *);
+void __vmstop(void);
+long __vmwait(void);
+void __vmyield(void);
+long __vmvpid(void);
+
+static inline long __vmcache_ickill(void)
+{
+	return __vmcache(ickill, 0, 0);
+}
+
+static inline long __vmcache_dckill(void)
+{
+	return __vmcache(dckill, 0, 0);
+}
+
+static inline long __vmcache_l2kill(void)
+{
+	return __vmcache(l2kill, 0, 0);
+}
+
+static inline long __vmcache_dccleaninva(unsigned long addr, unsigned long len)
+{
+	return __vmcache(dccleaninva, addr, len);
+}
+
+static inline long __vmcache_icinva(unsigned long addr, unsigned long len)
+{
+	return __vmcache(icinva, addr, len);
+}
+
+static inline long __vmcache_idsync(unsigned long addr,
+					   unsigned long len)
+{
+	return __vmcache(idsync, addr, len);
+}
+
+static inline long __vmcache_fetch_cfg(unsigned long val)
+{
+	return __vmcache(fetch_cfg, val, 0);
+}
+
+/* interrupt operations  */
+
+static inline long __vmintop_nop(void)
+{
+	return __vmintop(nop, 0, 0, 0, 0);
+}
+
+static inline long __vmintop_globen(long i)
+{
+	return __vmintop(globen, i, 0, 0, 0);
+}
+
+static inline long __vmintop_globdis(long i)
+{
+	return __vmintop(globdis, i, 0, 0, 0);
+}
+
+static inline long __vmintop_locen(long i)
+{
+	return __vmintop(locen, i, 0, 0, 0);
+}
+
+static inline long __vmintop_locdis(long i)
+{
+	return __vmintop(locdis, i, 0, 0, 0);
+}
+
+static inline long __vmintop_affinity(long i, long cpu)
+{
+	return __vmintop(locdis, i, cpu, 0, 0);
+}
+
+static inline long __vmintop_get(void)
+{
+	return __vmintop(get, 0, 0, 0, 0);
+}
+
+static inline long __vmintop_peek(void)
+{
+	return __vmintop(peek, 0, 0, 0, 0);
+}
+
+static inline long __vmintop_status(long i)
+{
+	return __vmintop(status, i, 0, 0, 0);
+}
+
+static inline long __vmintop_post(long i)
+{
+	return __vmintop(post, i, 0, 0, 0);
+}
+
+static inline long __vmintop_clear(long i)
+{
+	return __vmintop(clear, i, 0, 0, 0);
+}
+
+#else /* Only assembly code should reference these */
+
+#define HVM_TRAP1_VMRTE			1
+#define HVM_TRAP1_VMSETVEC		2
+#define HVM_TRAP1_VMSETIE		3
+#define HVM_TRAP1_VMGETIE		4
+#define HVM_TRAP1_VMINTOP		5
+#define HVM_TRAP1_VMCLRMAP		10
+#define HVM_TRAP1_VMNEWMAP		11
+#define HVM_TRAP1_FORMERLY_VMWIRE	12
+#define HVM_TRAP1_VMCACHE		13
+#define HVM_TRAP1_VMGETTIME		14
+#define HVM_TRAP1_VMSETTIME		15
+#define HVM_TRAP1_VMWAIT		16
+#define HVM_TRAP1_VMYIELD		17
+#define HVM_TRAP1_VMSTART		18
+#define HVM_TRAP1_VMSTOP		19
+#define HVM_TRAP1_VMVPID		20
+#define HVM_TRAP1_VMSETREGS		21
+#define HVM_TRAP1_VMGETREGS		22
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * Constants for virtual instruction parameters and return values
+ */
+
+/* vmsetie arguments */
+
+#define VM_INT_DISABLE	0
+#define VM_INT_ENABLE	1
+
+/* vmsetimask arguments */
+
+#define VM_INT_UNMASK	0
+#define VM_INT_MASK	1
+
+#define VM_NEWMAP_TYPE_LINEAR	0
+#define VM_NEWMAP_TYPE_PGTABLES	1
+
+
+/*
+ * Event Record definitions useful to both C and Assembler
+ */
+
+/* VMEST Layout */
+
+#define HVM_VMEST_UM_SFT	31
+#define HVM_VMEST_UM_MSK	1
+#define HVM_VMEST_IE_SFT	30
+#define HVM_VMEST_IE_MSK	1
+#define HVM_VMEST_EVENTNUM_SFT	16
+#define HVM_VMEST_EVENTNUM_MSK	0xff
+#define HVM_VMEST_CAUSE_SFT	0
+#define HVM_VMEST_CAUSE_MSK	0xffff
+
+/*
+ * The initial program gets to find a system environment descriptor
+ * on its stack when it begins exection. The first word is a version
+ * code to indicate what is there.  Zero means nothing more.
+ */
+
+#define HEXAGON_VM_SED_NULL	0
+
+/*
+ * Event numbers for vector binding
+ */
+
+#define HVM_EV_RESET		0
+#define HVM_EV_MACHCHECK	1
+#define HVM_EV_GENEX		2
+#define HVM_EV_TRAP		8
+#define HVM_EV_INTR		15
+/* These shoud be nuked as soon as we know the VM is up to spec v0.1.1 */
+#define HVM_EV_INTR_0		16
+#define HVM_MAX_INTR		240
+
+/*
+ * Cause values for General Exception
+ */
+
+#define HVM_GE_C_BUS	0x01
+#define HVM_GE_C_XPROT	0x11
+#define HVM_GE_C_XUSER	0x14
+#define HVM_GE_C_INVI	0x15
+#define HVM_GE_C_PRIVI	0x1B
+#define HVM_GE_C_XMAL	0x1C
+#define HVM_GE_C_RMAL	0x20
+#define HVM_GE_C_WMAL	0x21
+#define HVM_GE_C_RPROT	0x22
+#define HVM_GE_C_WPROT	0x23
+#define HVM_GE_C_RUSER	0x24
+#define HVM_GE_C_WUSER	0x25
+#define HVM_GE_C_CACHE	0x28
+
+/*
+ * Cause codes for Machine Check
+ */
+
+#define	HVM_MCHK_C_DOWN		0x00
+#define	HVM_MCHK_C_BADSP	0x01
+#define	HVM_MCHK_C_BADEX	0x02
+#define	HVM_MCHK_C_BADPT	0x03
+#define	HVM_MCHK_C_REGWR	0x29
+
+#endif
diff --git a/arch/hexagon/include/asm/intrinsics.h b/arch/hexagon/include/asm/intrinsics.h
new file mode 100644
index 0000000..1c02186
--- /dev/null
+++ b/arch/hexagon/include/asm/intrinsics.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_HEXAGON_INTRINSICS_H
+#define _ASM_HEXAGON_INTRINSICS_H
+
+#define HEXAGON_P_vrmpyhacc_PP	__builtin_HEXAGON_M2_vrmac_s0
+#define HEXAGON_P_vrmpyh_PP	__builtin_HEXAGON_M2_vrmpy_s0
+#define HEXAGON_R_cl0_R		__builtin_HEXAGON_S2_cl0
+
+#endif
diff --git a/arch/hexagon/include/asm/io.h b/arch/hexagon/include/asm/io.h
new file mode 100644
index 0000000..b3acc2c
--- /dev/null
+++ b/arch/hexagon/include/asm/io.h
@@ -0,0 +1,326 @@
+/*
+ * IO definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_IO_H
+#define _ASM_IO_H
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/vmalloc.h>
+#include <asm/string.h>
+#include <asm/mem-layout.h>
+#include <asm/iomap.h>
+#include <asm/page.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+
+/*
+ * We don't have PCI yet.
+ * _IO_BASE is pointing at what should be unused virtual space.
+ */
+#define IO_SPACE_LIMIT 0xffff
+#define _IO_BASE ((void __iomem *)0xfe000000)
+
+extern int remap_area_pages(unsigned long start, unsigned long phys_addr,
+				unsigned long end, unsigned long flags);
+
+extern void __iounmap(const volatile void __iomem *addr);
+
+/* Defined in lib/io.c, needed for smc91x driver. */
+extern void __raw_readsw(const void __iomem *addr, void *data, int wordlen);
+extern void __raw_writesw(void __iomem *addr, const void *data, int wordlen);
+
+extern void __raw_readsl(const void __iomem *addr, void *data, int wordlen);
+extern void __raw_writesl(void __iomem *addr, const void *data, int wordlen);
+
+#define readsw(p, d, l)	__raw_readsw(p, d, l)
+#define writesw(p, d, l) __raw_writesw(p, d, l)
+
+#define readsl(p, d, l)   __raw_readsl(p, d, l)
+#define writesl(p, d, l)  __raw_writesl(p, d, l)
+
+/*
+ * virt_to_phys - map virtual address to physical
+ * @address:  address to map
+ */
+static inline unsigned long virt_to_phys(volatile void *address)
+{
+	return __pa(address);
+}
+
+/*
+ * phys_to_virt - map physical address to virtual
+ * @address: address to map
+ */
+static inline void *phys_to_virt(unsigned long address)
+{
+	return __va(address);
+}
+
+/*
+ * convert a physical pointer to a virtual kernel pointer for
+ * /dev/mem access.
+ */
+#define xlate_dev_kmem_ptr(p)    __va(p)
+#define xlate_dev_mem_ptr(p)    __va(p)
+
+/*
+ * IO port access primitives.  Hexagon doesn't have special IO access
+ * instructions; all I/O is memory mapped.
+ *
+ * in/out are used for "ports", but we don't have "port instructions",
+ * so these are really just memory mapped too.
+ */
+
+/*
+ * readb - read byte from memory mapped device
+ * @addr:  pointer to memory
+ *
+ * Operates on "I/O bus memory space"
+ */
+static inline u8 readb(const volatile void __iomem *addr)
+{
+	u8 val;
+	asm volatile(
+		"%0 = memb(%1);"
+		: "=&r" (val)
+		: "r" (addr)
+	);
+	return val;
+}
+
+static inline u16 readw(const volatile void __iomem *addr)
+{
+	u16 val;
+	asm volatile(
+		"%0 = memh(%1);"
+		: "=&r" (val)
+		: "r" (addr)
+	);
+	return val;
+}
+
+static inline u32 readl(const volatile void __iomem *addr)
+{
+	u32 val;
+	asm volatile(
+		"%0 = memw(%1);"
+		: "=&r" (val)
+		: "r" (addr)
+	);
+	return val;
+}
+
+/*
+ * writeb - write a byte to a memory location
+ * @data: data to write to
+ * @addr:  pointer to memory
+ *
+ */
+static inline void writeb(u8 data, volatile void __iomem *addr)
+{
+	asm volatile(
+		"memb(%0) = %1;"
+		:
+		: "r" (addr), "r" (data)
+		: "memory"
+	);
+}
+
+static inline void writew(u16 data, volatile void __iomem *addr)
+{
+	asm volatile(
+		"memh(%0) = %1;"
+		:
+		: "r" (addr), "r" (data)
+		: "memory"
+	);
+
+}
+
+static inline void writel(u32 data, volatile void __iomem *addr)
+{
+	asm volatile(
+		"memw(%0) = %1;"
+		:
+		: "r" (addr), "r" (data)
+		: "memory"
+	);
+}
+
+#define __raw_writeb writeb
+#define __raw_writew writew
+#define __raw_writel writel
+
+#define __raw_readb readb
+#define __raw_readw readw
+#define __raw_readl readl
+
+/*
+ * Need an mtype somewhere in here, for cache type deals?
+ * This is probably too long for an inline.
+ */
+void __iomem *ioremap_nocache(unsigned long phys_addr, unsigned long size);
+
+static inline void __iomem *ioremap(unsigned long phys_addr, unsigned long size)
+{
+	return ioremap_nocache(phys_addr, size);
+}
+
+static inline void iounmap(volatile void __iomem *addr)
+{
+	__iounmap(addr);
+}
+
+#define __raw_writel writel
+
+static inline void memcpy_fromio(void *dst, const volatile void __iomem *src,
+	int count)
+{
+	memcpy(dst, (void *) src, count);
+}
+
+static inline void memcpy_toio(volatile void __iomem *dst, const void *src,
+	int count)
+{
+	memcpy((void *) dst, src, count);
+}
+
+#define PCI_IO_ADDR	(volatile void __iomem *)
+
+/*
+ * inb - read byte from I/O port or something
+ * @port:  address in I/O space
+ *
+ * Operates on "I/O bus I/O space"
+ */
+static inline u8 inb(unsigned long port)
+{
+	return readb(_IO_BASE + (port & IO_SPACE_LIMIT));
+}
+
+static inline u16 inw(unsigned long port)
+{
+	return readw(_IO_BASE + (port & IO_SPACE_LIMIT));
+}
+
+static inline u32 inl(unsigned long port)
+{
+	return readl(_IO_BASE + (port & IO_SPACE_LIMIT));
+}
+
+/*
+ * outb - write a byte to a memory location
+ * @data: data to write to
+ * @addr:  address in I/O space
+ */
+static inline void outb(u8 data, unsigned long port)
+{
+	writeb(data, _IO_BASE + (port & IO_SPACE_LIMIT));
+}
+
+static inline void outw(u16 data, unsigned long port)
+{
+	writew(data, _IO_BASE + (port & IO_SPACE_LIMIT));
+}
+
+static inline void outl(u32 data, unsigned long port)
+{
+	writel(data, _IO_BASE + (port & IO_SPACE_LIMIT));
+}
+
+#define outb_p outb
+#define outw_p outw
+#define outl_p outl
+
+#define inb_p inb
+#define inw_p inw
+#define inl_p inl
+
+static inline void insb(unsigned long port, void *buffer, int count)
+{
+	if (count) {
+		u8 *buf = buffer;
+		do {
+			u8 x = inb(port);
+			*buf++ = x;
+		} while (--count);
+	}
+}
+
+static inline void insw(unsigned long port, void *buffer, int count)
+{
+	if (count) {
+		u16 *buf = buffer;
+		do {
+			u16 x = inw(port);
+			*buf++ = x;
+		} while (--count);
+	}
+}
+
+static inline void insl(unsigned long port, void *buffer, int count)
+{
+	if (count) {
+		u32 *buf = buffer;
+		do {
+			u32 x = inw(port);
+			*buf++ = x;
+		} while (--count);
+	}
+}
+
+static inline void outsb(unsigned long port, const void *buffer, int count)
+{
+	if (count) {
+		const u8 *buf = buffer;
+		do {
+			outb(*buf++, port);
+		} while (--count);
+	}
+}
+
+static inline void outsw(unsigned long port, const void *buffer, int count)
+{
+	if (count) {
+		const u16 *buf = buffer;
+		do {
+			outw(*buf++, port);
+		} while (--count);
+	}
+}
+
+static inline void outsl(unsigned long port, const void *buffer, int count)
+{
+	if (count) {
+		const u32 *buf = buffer;
+		do {
+			outl(*buf++, port);
+		} while (--count);
+	}
+}
+
+#define flush_write_buffers() do { } while (0)
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/arch/hexagon/include/asm/irq.h b/arch/hexagon/include/asm/irq.h
new file mode 100644
index 0000000..ded8c15
--- /dev/null
+++ b/arch/hexagon/include/asm/irq.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_IRQ_H_
+#define _ASM_IRQ_H_
+
+/* Number of first-level interrupts associated with the CPU core. */
+#define HEXAGON_CPUINTS 32
+
+/*
+ * Must define NR_IRQS before including <asm-generic/irq.h>
+ * 64 == the two SIRC's, 176 == the two gpio's
+ *
+ * IRQ configuration is still in flux; defining this to a comfortably
+ * large number.
+ */
+#define NR_IRQS 512
+
+#include <asm-generic/irq.h>
+
+#endif
diff --git a/arch/hexagon/include/asm/irqflags.h b/arch/hexagon/include/asm/irqflags.h
new file mode 100644
index 0000000..ec15236
--- /dev/null
+++ b/arch/hexagon/include/asm/irqflags.h
@@ -0,0 +1,62 @@
+/*
+ * IRQ support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_IRQFLAGS_H
+#define _ASM_IRQFLAGS_H
+
+#include <asm/hexagon_vm.h>
+#include <linux/types.h>
+
+static inline unsigned long arch_local_save_flags(void)
+{
+	return __vmgetie();
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+	return __vmsetie(VM_INT_DISABLE);
+}
+
+static inline bool arch_irqs_disabled_flags(unsigned long flags)
+{
+	return !flags;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+	return !__vmgetie();
+}
+
+static inline void arch_local_irq_enable(void)
+{
+	__vmsetie(VM_INT_ENABLE);
+}
+
+static inline void arch_local_irq_disable(void)
+{
+	__vmsetie(VM_INT_DISABLE);
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+	__vmsetie(flags);
+}
+
+#endif
diff --git a/arch/hexagon/include/asm/kgdb.h b/arch/hexagon/include/asm/kgdb.h
new file mode 100644
index 0000000..9e87797
--- /dev/null
+++ b/arch/hexagon/include/asm/kgdb.h
@@ -0,0 +1,43 @@
+/*
+ * arch/hexagon/include/asm/kgdb.h - Hexagon KGDB Support
+ *
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __HEXAGON_KGDB_H__
+#define __HEXAGON_KGDB_H__
+
+#define BREAK_INSTR_SIZE 4
+#define CACHE_FLUSH_IS_SAFE   1
+#define BUFMAX       ((NUMREGBYTES * 2) + 512)
+
+static inline void arch_kgdb_breakpoint(void)
+{
+	asm("trap0(#0xDB)");
+}
+
+/* Registers:
+ * 32 gpr + sa0/1 + lc0/1 + m0/1 + gp + ugp + pred + pc = 42 total.
+ * vm regs = psp+elr+est+badva = 4
+ * syscall+restart = 2 more
+ * so 48 = 42 +4 + 2
+ */
+#define DBG_USER_REGS 42
+#define DBG_MAX_REG_NUM (DBG_USER_REGS + 6)
+#define NUMREGBYTES  (DBG_MAX_REG_NUM*4)
+
+#endif /* __HEXAGON_KGDB_H__ */
diff --git a/arch/hexagon/include/asm/linkage.h b/arch/hexagon/include/asm/linkage.h
new file mode 100644
index 0000000..a00b85f
--- /dev/null
+++ b/arch/hexagon/include/asm/linkage.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __ASM_LINKAGE_H
+#define __ASM_LINKAGE_H
+
+#define __ALIGN		.align 4
+#define __ALIGN_STR	".align 4"
+
+#endif
diff --git a/arch/hexagon/include/asm/mem-layout.h b/arch/hexagon/include/asm/mem-layout.h
new file mode 100644
index 0000000..72e5dcd
--- /dev/null
+++ b/arch/hexagon/include/asm/mem-layout.h
@@ -0,0 +1,112 @@
+/*
+ * Memory layout definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_HEXAGON_MEM_LAYOUT_H
+#define _ASM_HEXAGON_MEM_LAYOUT_H
+
+#include <linux/const.h>
+
+/*
+ * Have to do this for ginormous numbers, else they get printed as
+ * negative numbers, which the linker no likey when you try to
+ * assign it to the location counter.
+ */
+
+#define PAGE_OFFSET			_AC(0xc0000000, UL)
+
+/*
+ * LOAD_ADDRESS is the physical/linear address of where in memory
+ * the kernel gets loaded. The 12 least significant bits must be zero (0)
+ * due to limitations on setting the EVB
+ *
+ */
+
+#ifndef LOAD_ADDRESS
+#define LOAD_ADDRESS			0x00000000
+#endif
+
+#define TASK_SIZE			(PAGE_OFFSET)
+
+/*  not sure how these are used yet  */
+#define STACK_TOP			TASK_SIZE
+#define STACK_TOP_MAX			TASK_SIZE
+
+#ifndef __ASSEMBLY__
+enum fixed_addresses {
+	FIX_KMAP_BEGIN,
+	FIX_KMAP_END,  /*  check for per-cpuism  */
+	__end_of_fixed_addresses
+};
+
+#define MIN_KERNEL_SEG 0x300   /* From 0xc0000000 */
+extern int max_kernel_seg;
+
+/*
+ * Start of vmalloc virtual address space for kernel;
+ * supposed to be based on the amount of physical memory available
+ */
+
+#define VMALLOC_START (PAGE_OFFSET + VMALLOC_OFFSET + \
+	(unsigned long)high_memory)
+
+/* Gap between physical ram and vmalloc space for guard purposes. */
+#define VMALLOC_OFFSET PAGE_SIZE
+
+/*
+ * Create the space between VMALLOC_START and FIXADDR_TOP backwards
+ * from the ... "top".
+ *
+ * Permanent IO mappings will live at 0xfexx_xxxx
+ * Hypervisor occupies the last 16MB page at 0xffxxxxxx
+ */
+
+#define FIXADDR_TOP     0xfe000000
+#define FIXADDR_SIZE    (__end_of_fixed_addresses << PAGE_SHIFT)
+#define FIXADDR_START   (FIXADDR_TOP - FIXADDR_SIZE)
+
+/*
+ * "permanent kernel mappings", defined as long-lasting mappings of
+ * high-memory page frames into the kernel address space.
+ */
+
+#define LAST_PKMAP	PTRS_PER_PTE
+#define LAST_PKMAP_MASK	(LAST_PKMAP - 1)
+#define PKMAP_NR(virt)	((virt - PKMAP_BASE) >> PAGE_SHIFT)
+#define PKMAP_ADDR(nr)	(PKMAP_BASE + ((nr) << PAGE_SHIFT))
+
+/*
+ * To the "left" of the fixed map space is the kmap space
+ *
+ * "Permanent Kernel Mappings"; fancy (or less fancy) PTE table
+ * that looks like it's actually walked.
+ * Need to check the alignment/shift usage; some archs use
+ * PMD_MASK on this value
+ */
+#define PKMAP_BASE (FIXADDR_START-PAGE_SIZE*LAST_PKMAP)
+
+/*
+ * 2 pages of guard gap between where vmalloc area ends
+ * and pkmap_base begins.
+ */
+#define VMALLOC_END (PKMAP_BASE-PAGE_SIZE*2)
+#endif /*  !__ASSEMBLY__  */
+
+
+#endif /* _ASM_HEXAGON_MEM_LAYOUT_H */
diff --git a/arch/hexagon/include/asm/mmu.h b/arch/hexagon/include/asm/mmu.h
new file mode 100644
index 0000000..30a5d8d
--- /dev/null
+++ b/arch/hexagon/include/asm/mmu.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_MMU_H
+#define _ASM_MMU_H
+
+#include <asm/vdso.h>
+
+/*
+ * Architecture-specific state for a mm_struct.
+ * For the Hexagon Virtual Machine, it can be a copy
+ * of the pointer to the page table base.
+ */
+struct mm_context {
+	unsigned long long generation;
+	unsigned long ptbase;
+	struct hexagon_vdso *vdso;
+};
+
+typedef struct mm_context mm_context_t;
+
+#endif
diff --git a/arch/hexagon/include/asm/mmu_context.h b/arch/hexagon/include/asm/mmu_context.h
new file mode 100644
index 0000000..b4fe5a5
--- /dev/null
+++ b/arch/hexagon/include/asm/mmu_context.h
@@ -0,0 +1,100 @@
+/*
+ * MM context support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_MMU_CONTEXT_H
+#define _ASM_MMU_CONTEXT_H
+
+#include <asm/setup.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+#include <asm/mem-layout.h>
+
+static inline void destroy_context(struct mm_struct *mm)
+{
+}
+
+/*
+ * VM port hides all TLB management, so "lazy TLB" isn't very
+ * meaningful.  Even for ports to architectures with visble TLBs,
+ * this is almost invariably a null function.
+ */
+static inline void enter_lazy_tlb(struct mm_struct *mm,
+	struct task_struct *tsk)
+{
+}
+
+/*
+ * Architecture-specific actions, if any, for memory map deactivation.
+ */
+static inline void deactivate_mm(struct task_struct *tsk,
+	struct mm_struct *mm)
+{
+}
+
+/**
+ * init_new_context - initialize context related info for new mm_struct instance
+ * @tsk: pointer to a task struct
+ * @mm: pointer to a new mm struct
+ */
+static inline int init_new_context(struct task_struct *tsk,
+					struct mm_struct *mm)
+{
+	/* mm->context is set up by pgd_alloc */
+	return 0;
+}
+
+/*
+ *  Switch active mm context
+ */
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+				struct task_struct *tsk)
+{
+	int l1;
+
+	/*
+	 * For virtual machine, we have to update system map if it's been
+	 * touched.
+	 */
+	if (next->context.generation < prev->context.generation) {
+		for (l1 = MIN_KERNEL_SEG; l1 <= max_kernel_seg; l1++)
+			next->pgd[l1] = init_mm.pgd[l1];
+
+		next->context.generation = prev->context.generation;
+	}
+
+	__vmnewmap((void *)next->context.ptbase);
+}
+
+/*
+ *  Activate new memory map for task
+ */
+static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	switch_mm(prev, next, current_thread_info()->task);
+	local_irq_restore(flags);
+}
+
+/*  Generic hooks for arch_dup_mmap and arch_exit_mmap  */
+#include <asm-generic/mm_hooks.h>
+
+#endif
diff --git a/arch/hexagon/include/asm/module.h b/arch/hexagon/include/asm/module.h
new file mode 100644
index 0000000..72ba494
--- /dev/null
+++ b/arch/hexagon/include/asm/module.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_MODULE_H
+#define _ASM_MODULE_H
+
+#include <asm-generic/module.h>
+
+#define MODULE_ARCH_VERMAGIC __stringify(PROCESSOR_MODEL_NAME) " "
+
+#endif
diff --git a/arch/hexagon/include/asm/mutex.h b/arch/hexagon/include/asm/mutex.h
new file mode 100644
index 0000000..58b52de
--- /dev/null
+++ b/arch/hexagon/include/asm/mutex.h
@@ -0,0 +1,8 @@
+/*
+ * Pull in the generic implementation for the mutex fastpath.
+ *
+ * TODO: implement optimized primitives instead, or leave the generic
+ * implementation in place, or pick the atomic_xchg() based generic
+ * implementation. (see asm-generic/mutex-xchg.h for details)
+ */
+#include <asm-generic/mutex-xchg.h>
diff --git a/arch/hexagon/include/asm/page.h b/arch/hexagon/include/asm/page.h
new file mode 100644
index 0000000..edd9762
--- /dev/null
+++ b/arch/hexagon/include/asm/page.h
@@ -0,0 +1,157 @@
+/*
+ * Page management definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_PAGE_H
+#define _ASM_PAGE_H
+
+#include <linux/const.h>
+
+/*  This is probably not the most graceful way to handle this.  */
+
+#ifdef CONFIG_PAGE_SIZE_4KB
+#define PAGE_SHIFT 12
+#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_4KB
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_16KB
+#define PAGE_SHIFT 14
+#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_16KB
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_64KB
+#define PAGE_SHIFT 16
+#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_64KB
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_256KB
+#define PAGE_SHIFT 18
+#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_256KB
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_1MB
+#define PAGE_SHIFT 20
+#define HEXAGON_L1_PTE_SIZE __HVM_PDE_S_1MB
+#endif
+
+/*
+ *  These should be defined in hugetlb.h, but apparently not.
+ *  "Huge" for us should be 4MB or 16MB, which are both represented
+ *  in L1 PTE's.  Right now, it's set up for 4MB.
+ */
+#ifdef CONFIG_HUGETLB_PAGE
+#define HPAGE_SHIFT 22
+#define HPAGE_SIZE (1UL << HPAGE_SHIFT)
+#define HPAGE_MASK (~(HPAGE_SIZE-1))
+#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT-PAGE_SHIFT)
+#define HVM_HUGEPAGE_SIZE 0x5
+#endif
+
+#define PAGE_SIZE  (1UL << PAGE_SHIFT)
+#define PAGE_MASK  (~((1 << PAGE_SHIFT) - 1))
+
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+
+/*
+ * This is for PFN_DOWN, which mm.h needs.  Seems the right place to pull it in.
+ */
+#include <linux/pfn.h>
+
+/*
+ * We implement a two-level architecture-specific page table structure.
+ * Null intermediate page table level (pmd, pud) definitions will come from
+ * asm-generic/pagetable-nopmd.h and asm-generic/pagetable-nopud.h
+ */
+typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long pgd; } pgd_t;
+typedef struct { unsigned long pgprot; } pgprot_t;
+typedef struct page *pgtable_t;
+
+#define pte_val(x)     ((x).pte)
+#define pgd_val(x)     ((x).pgd)
+#define pgprot_val(x)  ((x).pgprot)
+#define __pte(x)       ((pte_t) { (x) })
+#define __pgd(x)       ((pgd_t) { (x) })
+#define __pgprot(x)    ((pgprot_t) { (x) })
+
+/*
+ * We need a __pa and a __va routine for kernel space.
+ * MIPS says they're only used during mem_init.
+ * also, check if we need a PHYS_OFFSET.
+ */
+#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET)
+#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET))
+
+/* The "page frame" descriptor is defined in linux/mm.h */
+struct page;
+
+/* Returns page frame descriptor for virtual address. */
+#define virt_to_page(kaddr) pfn_to_page(PFN_DOWN(__pa(kaddr)))
+
+/* Default vm area behavior is non-executable.  */
+#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | \
+				VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#define pfn_valid(pfn) ((pfn) < max_mapnr)
+#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
+
+/*  Need to not use a define for linesize; may move this to another file.  */
+static inline void clear_page(void *page)
+{
+	/*  This can only be done on pages with L1 WB cache */
+	asm volatile(
+		"	loop0(1f,%1);\n"
+		"1:	{ dczeroa(%0);\n"
+		"	  %0 = add(%0,#32); }:endloop0\n"
+		: "+r" (page)
+		: "r" (PAGE_SIZE/32)
+		: "lc0", "sa0", "memory"
+	);
+}
+
+#define copy_page(to, from)	memcpy((to), (from), PAGE_SIZE)
+
+/*
+ * Under assumption that kernel always "sees" user map...
+ */
+#define clear_user_page(page, vaddr, pg)	clear_page(page)
+#define copy_user_page(to, from, vaddr, pg)	copy_page(to, from)
+
+/*
+ * page_to_phys - convert page to physical address
+ * @page - pointer to page entry in mem_map
+ */
+#define page_to_phys(page)      (page_to_pfn(page) << PAGE_SHIFT)
+
+/*
+ * For port to Hexagon Virtual Machine, MAYBE we check for attempts
+ * to reference reserved HVM space, but in any case, the VM will be
+ * protected.
+ */
+#define kern_addr_valid(addr)   (1)
+
+#include <asm-generic/memory_model.h>
+/* XXX Todo: implement assembly-optimized version of getorder. */
+#include <asm-generic/getorder.h>
+
+#endif /* ifdef __ASSEMBLY__ */
+#endif /* ifdef __KERNEL__ */
+
+#endif
diff --git a/arch/hexagon/include/asm/param.h b/arch/hexagon/include/asm/param.h
new file mode 100644
index 0000000..285344b
--- /dev/null
+++ b/arch/hexagon/include/asm/param.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_PARAM_H
+#define _ASM_PARAM_H
+
+#define EXEC_PAGESIZE	16384
+
+#include <asm-generic/param.h>
+
+#endif
diff --git a/arch/hexagon/include/asm/perf_event.h b/arch/hexagon/include/asm/perf_event.h
new file mode 100644
index 0000000..6c2910f
--- /dev/null
+++ b/arch/hexagon/include/asm/perf_event.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_PERF_EVENT_H
+#define _ASM_PERF_EVENT_H
+
+#define PERF_EVENT_INDEX_OFFSET	0
+
+#endif /* _ASM_PERF_EVENT_H */
diff --git a/arch/hexagon/include/asm/pgalloc.h b/arch/hexagon/include/asm/pgalloc.h
new file mode 100644
index 0000000..13443c7
--- /dev/null
+++ b/arch/hexagon/include/asm/pgalloc.h
@@ -0,0 +1,146 @@
+/*
+ * Page table support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_PGALLOC_H
+#define _ASM_PGALLOC_H
+
+#include <asm/mem-layout.h>
+#include <asm/atomic.h>
+
+#define check_pgt_cache() do {} while (0)
+
+extern unsigned long long kmap_generation;
+
+/*
+ * Page table creation interface
+ */
+static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+	pgd_t *pgd;
+
+	pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
+
+	/*
+	 * There may be better ways to do this, but to ensure
+	 * that new address spaces always contain the kernel
+	 * base mapping, and to ensure that the user area is
+	 * initially marked invalid, initialize the new map
+	 * map with a copy of the kernel's persistent map.
+	 */
+
+	memcpy(pgd, swapper_pg_dir, PTRS_PER_PGD*sizeof(pgd_t *));
+	mm->context.generation = kmap_generation;
+
+	/* Physical version is what is passed to virtual machine on switch */
+	mm->context.ptbase = __pa(pgd);
+
+	return pgd;
+}
+
+static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+{
+	free_page((unsigned long) pgd);
+}
+
+static inline struct page *pte_alloc_one(struct mm_struct *mm,
+					 unsigned long address)
+{
+	struct page *pte;
+
+	pte = alloc_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
+
+	if (pte)
+		pgtable_page_ctor(pte);
+
+	return pte;
+}
+
+/* _kernel variant gets to use a different allocator */
+static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
+					  unsigned long address)
+{
+	gfp_t flags =  GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO;
+	return (pte_t *) __get_free_page(flags);
+}
+
+static inline void pte_free(struct mm_struct *mm, struct page *pte)
+{
+	pgtable_page_dtor(pte);
+	__free_page(pte);
+}
+
+static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+{
+	free_page((unsigned long)pte);
+}
+
+static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
+				pgtable_t pte)
+{
+	/*
+	 * Conveniently, zero in 3 LSB means indirect 4K page table.
+	 * Not so convenient when you're trying to vary the page size.
+	 */
+	set_pmd(pmd, __pmd(((unsigned long)page_to_pfn(pte) << PAGE_SHIFT) |
+		HEXAGON_L1_PTE_SIZE));
+}
+
+/*
+ * Other architectures seem to have ways of making all processes
+ * share the same pmd's for their kernel mappings, but the v0.3
+ * Hexagon VM spec has a "monolithic" L1 table for user and kernel
+ * segments.  We track "generations" of the kernel map to minimize
+ * overhead, and update the "slave" copies of the kernel mappings
+ * as part of switch_mm.  However, we still need to update the
+ * kernel map of the active thread who's calling pmd_populate_kernel...
+ */
+static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
+				       pte_t *pte)
+{
+	extern spinlock_t kmap_gen_lock;
+	pmd_t *ppmd;
+	int pmdindex;
+
+	spin_lock(&kmap_gen_lock);
+	kmap_generation++;
+	mm->context.generation = kmap_generation;
+	current->active_mm->context.generation = kmap_generation;
+	spin_unlock(&kmap_gen_lock);
+
+	set_pmd(pmd, __pmd(((unsigned long)__pa(pte)) | HEXAGON_L1_PTE_SIZE));
+
+	/*
+	 * Now the "slave" copy of the current thread.
+	 * This is pointer arithmetic, not byte addresses!
+	 */
+	pmdindex = (pgd_t *)pmd - mm->pgd;
+	ppmd = (pmd_t *)current->active_mm->pgd + pmdindex;
+	set_pmd(ppmd, __pmd(((unsigned long)__pa(pte)) | HEXAGON_L1_PTE_SIZE));
+	if (pmdindex > max_kernel_seg)
+		max_kernel_seg = pmdindex;
+}
+
+#define __pte_free_tlb(tlb, pte, addr)		\
+do {						\
+	pgtable_page_dtor((pte));		\
+	tlb_remove_page((tlb), (pte));		\
+} while (0)
+
+#endif
diff --git a/arch/hexagon/include/asm/pgtable.h b/arch/hexagon/include/asm/pgtable.h
new file mode 100644
index 0000000..ca619bf
--- /dev/null
+++ b/arch/hexagon/include/asm/pgtable.h
@@ -0,0 +1,518 @@
+/*
+ * Page table support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_PGTABLE_H
+#define _ASM_PGTABLE_H
+
+/*
+ * Page table definitions for Qualcomm Hexagon processor.
+ */
+#include <linux/swap.h>
+#include <asm/page.h>
+#include <asm-generic/pgtable-nopmd.h>
+
+/* A handy thing to have if one has the RAM. Declared in head.S */
+extern unsigned long empty_zero_page;
+extern unsigned long zero_page_mask;
+
+/*
+ * The PTE model described here is that of the Hexagon Virtual Machine,
+ * which autonomously walks 2-level page tables.  At a lower level, we
+ * also describe the RISCish software-loaded TLB entry structure of
+ * the underlying Hexagon processor. A kernel built to run on the
+ * virtual machine has no need to know about the underlying hardware.
+ */
+#include <asm/vm_mmu.h>
+
+/*
+ * To maximize the comfort level for the PTE manipulation macros,
+ * define the "well known" architecture-specific bits.
+ */
+#define _PAGE_READ	__HVM_PTE_R
+#define _PAGE_WRITE	__HVM_PTE_W
+#define _PAGE_EXECUTE	__HVM_PTE_X
+#define _PAGE_USER	__HVM_PTE_U
+
+/*
+ * We have a total of 4 "soft" bits available in the abstract PTE.
+ * The two mandatory software bits are Dirty and Accessed.
+ * To make nonlinear swap work according to the more recent
+ * model, we want a low order "Present" bit to indicate whether
+ * the PTE describes MMU programming or swap space.
+ */
+#define _PAGE_PRESENT	(1<<0)
+#define _PAGE_DIRTY	(1<<1)
+#define _PAGE_ACCESSED	(1<<2)
+
+/*
+ * _PAGE_FILE is only meaningful if _PAGE_PRESENT is false, while
+ * _PAGE_DIRTY is only meaningful if _PAGE_PRESENT is true.
+ * So we can overload the bit...
+ */
+#define _PAGE_FILE	_PAGE_DIRTY /* set:  pagecache, unset = swap */
+
+/*
+ * For now, let's say that Valid and Present are the same thing.
+ * Alternatively, we could say that it's the "or" of R, W, and X
+ * permissions.
+ */
+#define _PAGE_VALID	_PAGE_PRESENT
+
+/*
+ * We're not defining _PAGE_GLOBAL here, since there's no concept
+ * of global pages or ASIDs exposed to the Hexagon Virtual Machine,
+ * and we want to use the same page table structures and macros in
+ * the native kernel as we do in the virtual machine kernel.
+ * So we'll put up with a bit of inefficiency for now...
+ */
+
+/*
+ * Top "FOURTH" level (pgd), which for the Hexagon VM is really
+ * only the second from the bottom, pgd and pud both being collapsed.
+ * Each entry represents 4MB of virtual address space, 4K of table
+ * thus maps the full 4GB.
+ */
+#define PGDIR_SHIFT 22
+#define PTRS_PER_PGD 1024
+
+#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
+#define PGDIR_MASK (~(PGDIR_SIZE-1))
+
+#ifdef CONFIG_PAGE_SIZE_4KB
+#define PTRS_PER_PTE 1024
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_16KB
+#define PTRS_PER_PTE 256
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_64KB
+#define PTRS_PER_PTE 64
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_256KB
+#define PTRS_PER_PTE 16
+#endif
+
+#ifdef CONFIG_PAGE_SIZE_1MB
+#define PTRS_PER_PTE 4
+#endif
+
+/*  Any bigger and the PTE disappears.  */
+#define pgd_ERROR(e) \
+	printk(KERN_ERR "%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__,\
+		pgd_val(e))
+
+/*
+ * Page Protection Constants. Includes (in this variant) cache attributes.
+ */
+extern unsigned long _dflt_cache_att;
+
+#define PAGE_NONE	__pgprot(_PAGE_PRESENT | _PAGE_USER | \
+				_dflt_cache_att)
+#define PAGE_READONLY	__pgprot(_PAGE_PRESENT | _PAGE_USER | \
+				_PAGE_READ | _PAGE_EXECUTE | _dflt_cache_att)
+#define PAGE_COPY	PAGE_READONLY
+#define PAGE_EXEC	__pgprot(_PAGE_PRESENT | _PAGE_USER | \
+				_PAGE_READ | _PAGE_EXECUTE | _dflt_cache_att)
+#define PAGE_COPY_EXEC	PAGE_EXEC
+#define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | \
+				_PAGE_EXECUTE | _PAGE_WRITE | _dflt_cache_att)
+#define PAGE_KERNEL	__pgprot(_PAGE_PRESENT | _PAGE_READ | \
+				_PAGE_WRITE | _PAGE_EXECUTE | _dflt_cache_att)
+
+
+/*
+ * Aliases for mapping mmap() protection bits to page protections.
+ * These get used for static initialization, so using the _dflt_cache_att
+ * variable for the default cache attribute isn't workable. If the
+ * default gets changed at boot time, the boot option code has to
+ * update data structures like the protaction_map[] array.
+ */
+#define CACHEDEF	(CACHE_DEFAULT << 6)
+
+/* Private (copy-on-write) page protections. */
+#define __P000 __pgprot(_PAGE_PRESENT | _PAGE_USER | CACHEDEF)
+#define __P001 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | CACHEDEF)
+#define __P010 __P000	/* Write-only copy-on-write */
+#define __P011 __P001	/* Read/Write copy-on-write */
+#define __P100 __pgprot(_PAGE_PRESENT | _PAGE_USER | \
+			_PAGE_EXECUTE | CACHEDEF)
+#define __P101 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_EXECUTE | \
+			_PAGE_READ | CACHEDEF)
+#define __P110 __P100	/* Write/execute copy-on-write */
+#define __P111 __P101	/* Read/Write/Execute, copy-on-write */
+
+/* Shared page protections. */
+#define __S000 __P000
+#define __S001 __P001
+#define __S010 __pgprot(_PAGE_PRESENT | _PAGE_USER | \
+			_PAGE_WRITE | CACHEDEF)
+#define __S011 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | \
+			_PAGE_WRITE | CACHEDEF)
+#define __S100 __pgprot(_PAGE_PRESENT | _PAGE_USER | \
+			_PAGE_EXECUTE | CACHEDEF)
+#define __S101 __P101
+#define __S110 __pgprot(_PAGE_PRESENT | _PAGE_USER | \
+			_PAGE_EXECUTE | _PAGE_WRITE | CACHEDEF)
+#define __S111 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | \
+			_PAGE_EXECUTE | _PAGE_WRITE | CACHEDEF)
+
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];  /* located in head.S */
+
+/* Seems to be zero even in architectures where the zero page is firewalled? */
+#define FIRST_USER_ADDRESS 0
+#define pte_special(pte)	0
+#define pte_mkspecial(pte)	(pte)
+
+/*  HUGETLB not working currently  */
+#ifdef CONFIG_HUGETLB_PAGE
+#define pte_mkhuge(pte) __pte((pte_val(pte) & ~0x3) | HVM_HUGEPAGE_SIZE)
+#endif
+
+/*
+ * For now, assume that higher-level code will do TLB/MMU invalidations
+ * and don't insert that overhead into this low-level function.
+ */
+extern void sync_icache_dcache(pte_t pte);
+
+#define pte_present_exec_user(pte) \
+	((pte_val(pte) & (_PAGE_EXECUTE | _PAGE_USER)) == \
+	(_PAGE_EXECUTE | _PAGE_USER))
+
+static inline void set_pte(pte_t *ptep, pte_t pteval)
+{
+	/*  should really be using pte_exec, if it weren't declared later. */
+	if (pte_present_exec_user(pteval))
+		sync_icache_dcache(pteval);
+
+	*ptep = pteval;
+}
+
+/*
+ * For the Hexagon Virtual Machine MMU (or its emulation), a null/invalid
+ * L1 PTE (PMD/PGD) has 7 in the least significant bits. For the L2 PTE
+ * (Linux PTE), the key is to have bits 11..9 all zero.  We'd use 0x7
+ * as a universal null entry, but some of those least significant bits
+ * are interpreted by software.
+ */
+#define _NULL_PMD	0x7
+#define _NULL_PTE	0x0
+
+static inline void pmd_clear(pmd_t *pmd_entry_ptr)
+{
+	 pmd_val(*pmd_entry_ptr) = _NULL_PMD;
+}
+
+/*
+ * Conveniently, a null PTE value is invalid.
+ */
+static inline void pte_clear(struct mm_struct *mm, unsigned long addr,
+				pte_t *ptep)
+{
+	pte_val(*ptep) = _NULL_PTE;
+}
+
+#ifdef NEED_PMD_INDEX_DESPITE_BEING_2_LEVEL
+/**
+ * pmd_index - returns the index of the entry in the PMD page
+ * which would control the given virtual address
+ */
+#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
+
+#endif
+
+/**
+ * pgd_index - returns the index of the entry in the PGD page
+ * which would control the given virtual address
+ *
+ * This returns the *index* for the address in the pgd_t
+ */
+#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
+
+/*
+ * pgd_offset - find an offset in a page-table-directory
+ */
+#define pgd_offset(mm, addr) ((mm)->pgd + pgd_index(addr))
+
+/*
+ * pgd_offset_k - get kernel (init_mm) pgd entry pointer for addr
+ */
+#define pgd_offset_k(address) pgd_offset(&init_mm, address)
+
+/**
+ * pmd_none - check if pmd_entry is mapped
+ * @pmd_entry:  pmd entry
+ *
+ * MIPS checks it against that "invalid pte table" thing.
+ */
+static inline int pmd_none(pmd_t pmd)
+{
+	return pmd_val(pmd) == _NULL_PMD;
+}
+
+/**
+ * pmd_present - is there a page table behind this?
+ * Essentially the inverse of pmd_none.  We maybe
+ * save an inline instruction by defining it this
+ * way, instead of simply "!pmd_none".
+ */
+static inline int pmd_present(pmd_t pmd)
+{
+	return pmd_val(pmd) != (unsigned long)_NULL_PMD;
+}
+
+/**
+ * pmd_bad - check if a PMD entry is "bad". That might mean swapped out.
+ * As we have no known cause of badness, it's null, as it is for many
+ * architectures.
+ */
+static inline int pmd_bad(pmd_t pmd)
+{
+	return 0;
+}
+
+/*
+ * pmd_page - converts a PMD entry to a page pointer
+ */
+#define pmd_page(pmd)  (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
+#define pmd_pgtable(pmd) pmd_page(pmd)
+
+/**
+ * pte_none - check if pte is mapped
+ * @pte: pte_t entry
+ */
+static inline int pte_none(pte_t pte)
+{
+	return pte_val(pte) == _NULL_PTE;
+};
+
+/*
+ * pte_present - check if page is present
+ */
+static inline int pte_present(pte_t pte)
+{
+	return pte_val(pte) & _PAGE_PRESENT;
+}
+
+/* mk_pte - make a PTE out of a page pointer and protection bits */
+#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot))
+
+/* pte_page - returns a page (frame pointer/descriptor?) based on a PTE */
+#define pte_page(x) pfn_to_page(pte_pfn(x))
+
+/* pte_mkold - mark PTE as not recently accessed */
+static inline pte_t pte_mkold(pte_t pte)
+{
+	pte_val(pte) &= ~_PAGE_ACCESSED;
+	return pte;
+}
+
+/* pte_mkyoung - mark PTE as recently accessed */
+static inline pte_t pte_mkyoung(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_ACCESSED;
+	return pte;
+}
+
+/* pte_mkclean - mark page as in sync with backing store */
+static inline pte_t pte_mkclean(pte_t pte)
+{
+	pte_val(pte) &= ~_PAGE_DIRTY;
+	return pte;
+}
+
+/* pte_mkdirty - mark page as modified */
+static inline pte_t pte_mkdirty(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_DIRTY;
+	return pte;
+}
+
+/* pte_young - "is PTE marked as accessed"? */
+static inline int pte_young(pte_t pte)
+{
+	return pte_val(pte) & _PAGE_ACCESSED;
+}
+
+/* pte_dirty - "is PTE dirty?" */
+static inline int pte_dirty(pte_t pte)
+{
+	return pte_val(pte) & _PAGE_DIRTY;
+}
+
+/* pte_modify - set protection bits on PTE */
+static inline pte_t pte_modify(pte_t pte, pgprot_t prot)
+{
+	pte_val(pte) &= PAGE_MASK;
+	pte_val(pte) |= pgprot_val(prot);
+	return pte;
+}
+
+/* pte_wrprotect - mark page as not writable */
+static inline pte_t pte_wrprotect(pte_t pte)
+{
+	pte_val(pte) &= ~_PAGE_WRITE;
+	return pte;
+}
+
+/* pte_mkwrite - mark page as writable */
+static inline pte_t pte_mkwrite(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_WRITE;
+	return pte;
+}
+
+/* pte_mkexec - mark PTE as executable */
+static inline pte_t pte_mkexec(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_EXECUTE;
+	return pte;
+}
+
+/* pte_read - "is PTE marked as readable?" */
+static inline int pte_read(pte_t pte)
+{
+	return pte_val(pte) & _PAGE_READ;
+}
+
+/* pte_write - "is PTE marked as writable?" */
+static inline int pte_write(pte_t pte)
+{
+	return pte_val(pte) & _PAGE_WRITE;
+}
+
+
+/* pte_exec - "is PTE marked as executable?" */
+static inline int pte_exec(pte_t pte)
+{
+	return pte_val(pte) & _PAGE_EXECUTE;
+}
+
+/* __pte_to_swp_entry - extract swap entry from PTE */
+#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
+
+/* __swp_entry_to_pte - extract PTE from swap entry */
+#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
+
+/* pfn_pte - convert page number and protection value to page table entry */
+#define pfn_pte(pfn, pgprot) __pte((pfn << PAGE_SHIFT) | pgprot_val(pgprot))
+
+/* pte_pfn - convert pte to page frame number */
+#define pte_pfn(pte) (pte_val(pte) >> PAGE_SHIFT)
+#define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval))
+
+/*
+ * set_pte_at - update page table and do whatever magic may be
+ * necessary to make the underlying hardware/firmware take note.
+ *
+ * VM may require a virtual instruction to alert the MMU.
+ */
+#define set_pte_at(mm, addr, ptep, pte) set_pte(ptep, pte)
+
+/*
+ * May need to invoke the virtual machine as well...
+ */
+#define pte_unmap(pte)		do { } while (0)
+#define pte_unmap_nested(pte)	do { } while (0)
+
+/*
+ * pte_offset_map - returns the linear address of the page table entry
+ * corresponding to an address
+ */
+#define pte_offset_map(dir, address)                                    \
+	((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
+
+#define pte_offset_map_nested(pmd, addr) pte_offset_map(pmd, addr)
+
+/* pte_offset_kernel - kernel version of pte_offset */
+#define pte_offset_kernel(dir, address) \
+	((pte_t *) (unsigned long) __va(pmd_val(*dir) & PAGE_MASK) \
+				+  __pte_offset(address))
+
+/* ZERO_PAGE - returns the globally shared zero page */
+#define ZERO_PAGE(vaddr) (virt_to_page(&empty_zero_page))
+
+#define __pte_offset(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+
+/* Nothing special about IO remapping at this point */
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
+	remap_pfn_range(vma, vaddr, pfn, size, prot)
+
+/*  I think this is in case we have page table caches; needed by init/main.c  */
+#define pgtable_cache_init()    do { } while (0)
+
+/*
+ * Swap/file PTE definitions.  If _PAGE_PRESENT is zero, the rest of the
+ * PTE is interpreted as swap information.  Depending on the _PAGE_FILE
+ * bit, the remaining free bits are eitehr interpreted as a file offset
+ * or a swap type/offset tuple.  Rather than have the TLB fill handler
+ * test _PAGE_PRESENT, we're going to reserve the permissions bits
+ * and set them to all zeros for swap entries, which speeds up the
+ * miss handler at the cost of 3 bits of offset.  That trade-off can
+ * be revisited if necessary, but Hexagon processor architecture and
+ * target applications suggest a lot of TLB misses and not much swap space.
+ *
+ * Format of swap PTE:
+ *	bit	0:	Present (zero)
+ *	bit	1:	_PAGE_FILE (zero)
+ *	bits	2-6:	swap type (arch independent layer uses 5 bits max)
+ *	bits	7-9:	bits 2:0 of offset
+ *	bits 10-12:	effectively _PAGE_PROTNONE (all zero)
+ *	bits 13-31:  bits 21:3 of swap offset
+ *
+ * Format of file PTE:
+ *	bit	0:	Present (zero)
+ *	bit	1:	_PAGE_FILE (zero)
+ *	bits	2-9:	bits 7:0 of offset
+ *	bits 10-12:	effectively _PAGE_PROTNONE (all zero)
+ *	bits 13-31:  bits 26:8 of swap offset
+ *
+ * The split offset makes some of the following macros a little gnarly,
+ * but there's plenty of precedent for this sort of thing.
+ */
+#define PTE_FILE_MAX_BITS     27
+
+/* Used for swap PTEs */
+#define __swp_type(swp_pte)		(((swp_pte).val >> 2) & 0x1f)
+
+#define __swp_offset(swp_pte) \
+	((((swp_pte).val >> 7) & 0x7) | (((swp_pte).val >> 10) & 0x003ffff8))
+
+#define __swp_entry(type, offset) \
+	((swp_entry_t)	{ \
+		((type << 2) | \
+		 ((offset & 0x3ffff8) << 10) | ((offset & 0x7) << 7)) })
+
+/* Used for file PTEs */
+#define pte_file(pte) \
+	((pte_val(pte) & (_PAGE_FILE | _PAGE_PRESENT)) == _PAGE_FILE)
+
+#define pte_to_pgoff(pte) \
+	(((pte_val(pte) >> 2) & 0xff) | ((pte_val(pte) >> 5) & 0x07ffff00))
+
+#define pgoff_to_pte(off) \
+	((pte_t) { ((((off) & 0x7ffff00) << 5) | (((off) & 0xff) << 2)\
+	| _PAGE_FILE) })
+
+/*  Oh boy.  There are a lot of possible arch overrides found in this file.  */
+#include <asm-generic/pgtable.h>
+
+#endif
diff --git a/arch/hexagon/include/asm/processor.h b/arch/hexagon/include/asm/processor.h
new file mode 100644
index 0000000..20c5dda
--- /dev/null
+++ b/arch/hexagon/include/asm/processor.h
@@ -0,0 +1,123 @@
+/*
+ * Process/processor support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_PROCESSOR_H
+#define _ASM_PROCESSOR_H
+
+#ifndef __ASSEMBLY__
+
+#include <asm/mem-layout.h>
+#include <asm/registers.h>
+#include <asm/hexagon_vm.h>
+
+/*  must be a macro  */
+#define current_text_addr() ({ __label__ _l; _l: &&_l; })
+
+/*  task_struct, defined elsewhere, is the "process descriptor" */
+struct task_struct;
+
+/*  this is defined in arch/process.c  */
+extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
+extern unsigned long thread_saved_pc(struct task_struct *tsk);
+
+extern void start_thread(struct pt_regs *, unsigned long, unsigned long);
+
+/*
+ * thread_struct is supposed to be for context switch data.
+ * Specifically, to hold the state necessary to perform switch_to...
+ */
+struct thread_struct {
+	void *switch_sp;
+};
+
+/*
+ * initializes thread_struct
+ * The only thing we have in there is switch_sp
+ * which doesn't really need to be initialized.
+ */
+
+#define INIT_THREAD { \
+}
+
+#define cpu_relax() __vmyield()
+
+/*
+ * "Unlazying all lazy status" occurs here.
+ */
+static inline void prepare_to_copy(struct task_struct *tsk)
+{
+}
+
+/*
+ * Decides where the kernel will search for a free chunk of vm space during
+ * mmaps.
+ * See also arch_get_unmapped_area.
+ * Doesn't affect if you have MAX_FIXED in the page flags set though...
+ *
+ * Apparently the convention is that ld.so will ask for "unmapped" private
+ * memory to be allocated SOMEWHERE, but it also asks for memory explicitly
+ * via MAP_FIXED at the lower * addresses starting at VA=0x0.
+ *
+ * If the two requests collide, you get authentic segfaulting action, so
+ * you have to kick the "unmapped" base requests higher up.
+ */
+#define TASK_UNMAPPED_BASE	(PAGE_ALIGN(TASK_SIZE/3))
+
+
+#define task_pt_regs(task) \
+	((struct pt_regs *)(task_stack_page(task) + THREAD_SIZE) - 1)
+
+#define KSTK_EIP(tsk) (pt_elr(task_pt_regs(tsk)))
+#define KSTK_ESP(tsk) (pt_psp(task_pt_regs(tsk)))
+
+/*  Free all resources held by a thread; defined in process.c  */
+extern void release_thread(struct task_struct *dead_task);
+
+/* Get wait channel for task P.  */
+extern unsigned long get_wchan(struct task_struct *p);
+
+/*  The following stuff is pretty HEXAGON specific.  */
+
+/*  This is really just here for __switch_to.
+    Offsets are pulled via asm-offsets.c  */
+
+/*
+ * No real reason why VM and native switch stacks should be different.
+ * Ultimately this should merge.  Note that Rev C. ABI called out only
+ * R24-27 as callee saved GPRs needing explicit attention (R29-31 being
+ * dealt with automagically by allocframe), but the current ABI has
+ * more, R16-R27.  By saving more, the worst case is that we waste some
+ * cycles if building with the old compilers.
+ */
+
+struct hexagon_switch_stack {
+	unsigned long long	r1716;
+	unsigned long long	r1918;
+	unsigned long long	r2120;
+	unsigned long long	r2322;
+	unsigned long long	r2524;
+	unsigned long long	r2726;
+	unsigned long		fp;
+	unsigned long		lr;
+};
+
+#endif /* !__ASSEMBLY__ */
+
+#endif
diff --git a/arch/hexagon/include/asm/ptrace.h b/arch/hexagon/include/asm/ptrace.h
new file mode 100644
index 0000000..3d2f607
--- /dev/null
+++ b/arch/hexagon/include/asm/ptrace.h
@@ -0,0 +1,35 @@
+/*
+ * Ptrace definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_PTRACE_H
+#define _ASM_PTRACE_H
+
+#include <asm/registers.h>
+
+#define instruction_pointer(regs) pt_elr(regs)
+#define user_stack_pointer(regs) ((regs)->r29)
+
+#define profile_pc(regs) instruction_pointer(regs)
+
+/* kprobe-based event tracer support */
+extern int regs_query_register_offset(const char *name);
+extern const char *regs_query_register_name(unsigned int offset);
+
+#endif
diff --git a/arch/hexagon/include/asm/registers.h b/arch/hexagon/include/asm/registers.h
new file mode 100644
index 0000000..4dd741b
--- /dev/null
+++ b/arch/hexagon/include/asm/registers.h
@@ -0,0 +1,236 @@
+/*
+ * Register definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_REGISTERS_H
+#define _ASM_REGISTERS_H
+
+#define SP r29
+
+#ifndef __ASSEMBLY__
+
+/*  See kernel/entry.S for further documentation.  */
+
+/*
+ * Entry code copies the event record out of guest registers into
+ * this structure (which is on the stack).
+ */
+
+struct hvm_event_record {
+	unsigned long vmel;     /* Event Linkage (return address) */
+	unsigned long vmest;    /* Event context - pre-event SSR values */
+	unsigned long vmpsp;    /* Previous stack pointer */
+	unsigned long vmbadva;  /* Bad virtual address for addressing events */
+};
+
+struct pt_regs {
+	long restart_r0;        /* R0 checkpoint for syscall restart */
+	long syscall_nr;        /* Only used in system calls */
+	union {
+		struct {
+			unsigned long usr;
+			unsigned long preds;
+		};
+		long long int predsusr;
+	};
+	union {
+		struct {
+			unsigned long m0;
+			unsigned long m1;
+		};
+		long long int m1m0;
+	};
+	union {
+		struct {
+			unsigned long sa1;
+			unsigned long lc1;
+		};
+		long long int lc1sa1;
+	};
+	union {
+		struct {
+			unsigned long sa0;
+			unsigned long lc0;
+		};
+		long long int lc0sa0;
+	};
+	union {
+		struct {
+			unsigned long gp;
+			unsigned long ugp;
+		};
+		long long int ugpgp;
+	};
+	/*
+	* Be extremely careful with rearranging these, if at all.  Some code
+	* assumes the 32 registers exist exactly like this in memory;
+	* e.g. kernel/ptrace.c
+	* e.g. kernel/signal.c (restore_sigcontext)
+	*/
+	union {
+		struct {
+			unsigned long r00;
+			unsigned long r01;
+		};
+		long long int r0100;
+	};
+	union {
+		struct {
+			unsigned long r02;
+			unsigned long r03;
+		};
+		long long int r0302;
+	};
+	union {
+		struct {
+			unsigned long r04;
+			unsigned long r05;
+		};
+		long long int r0504;
+	};
+	union {
+		struct {
+			unsigned long r06;
+			unsigned long r07;
+		};
+		long long int r0706;
+	};
+	union {
+		struct {
+			unsigned long r08;
+			unsigned long r09;
+		};
+		long long int r0908;
+	};
+	union {
+	       struct {
+			unsigned long r10;
+			unsigned long r11;
+	       };
+	       long long int r1110;
+	};
+	union {
+	       struct {
+			unsigned long r12;
+			unsigned long r13;
+	       };
+	       long long int r1312;
+	};
+	union {
+	       struct {
+			unsigned long r14;
+			unsigned long r15;
+	       };
+	       long long int r1514;
+	};
+	union {
+		struct {
+			unsigned long r16;
+			unsigned long r17;
+		};
+		long long int r1716;
+	};
+	union {
+		struct {
+			unsigned long r18;
+			unsigned long r19;
+		};
+		long long int r1918;
+	};
+	union {
+		struct {
+			unsigned long r20;
+			unsigned long r21;
+		};
+		long long int r2120;
+	};
+	union {
+		struct {
+			unsigned long r22;
+			unsigned long r23;
+		};
+		long long int r2322;
+	};
+	union {
+		struct {
+			unsigned long r24;
+			unsigned long r25;
+		};
+		long long int r2524;
+	};
+	union {
+		struct {
+			unsigned long r26;
+			unsigned long r27;
+		};
+		long long int r2726;
+	};
+	union {
+		struct {
+			unsigned long r28;
+			unsigned long r29;
+	       };
+	       long long int r2928;
+	};
+	union {
+		struct {
+			unsigned long r30;
+			unsigned long r31;
+		};
+		long long int r3130;
+	};
+	/* VM dispatch pushes event record onto stack - we can build on it */
+	struct hvm_event_record hvmer;
+};
+
+/* Defines to conveniently access the values  */
+
+/*
+ * As of the VM spec 0.5, these registers are now set/retrieved via a
+ * VM call.  On the in-bound side, we just fetch the values
+ * at the entry points and stuff them into the old record in pt_regs.
+ * However, on the outbound side, probably at VM rte, we set the
+ * registers back.
+ */
+
+#define pt_elr(regs) ((regs)->hvmer.vmel)
+#define pt_set_elr(regs, val) ((regs)->hvmer.vmel = (val))
+#define pt_cause(regs) ((regs)->hvmer.vmest & (HVM_VMEST_CAUSE_MSK))
+#define user_mode(regs) \
+	(((regs)->hvmer.vmest & (HVM_VMEST_UM_MSK << HVM_VMEST_UM_SFT)) != 0)
+#define ints_enabled(regs) \
+	(((regs)->hvmer.vmest & (HVM_VMEST_IE_MSK << HVM_VMEST_IE_SFT)) != 0)
+#define pt_psp(regs) ((regs)->hvmer.vmpsp)
+#define pt_badva(regs) ((regs)->hvmer.vmbadva)
+
+#define pt_set_rte_sp(regs, sp) do {\
+	pt_psp(regs) = (sp);\
+	(regs)->SP = (unsigned long) &((regs)->hvmer);\
+	} while (0)
+
+#define pt_set_kmode(regs) \
+	(regs)->hvmer.vmest = (HVM_VMEST_IE_MSK << HVM_VMEST_IE_SFT)
+
+#define pt_set_usermode(regs) \
+	(regs)->hvmer.vmest = (HVM_VMEST_UM_MSK << HVM_VMEST_UM_SFT) \
+			    | (HVM_VMEST_IE_MSK << HVM_VMEST_IE_SFT)
+
+#endif  /*  ifndef __ASSEMBLY  */
+
+#endif
diff --git a/arch/hexagon/include/asm/setup.h b/arch/hexagon/include/asm/setup.h
new file mode 100644
index 0000000..3b754c5
--- /dev/null
+++ b/arch/hexagon/include/asm/setup.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SETUP_H
+#define _ASM_SETUP_H
+
+#include <linux/init.h>
+#include <asm-generic/setup.h>
+
+extern char external_cmdline_buffer;
+
+void __init setup_arch_memory(void);
+
+#endif
diff --git a/arch/hexagon/include/asm/sigcontext.h b/arch/hexagon/include/asm/sigcontext.h
new file mode 100644
index 0000000..ce6dcd9
--- /dev/null
+++ b/arch/hexagon/include/asm/sigcontext.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SIGCONTEXT_H
+#define _ASM_SIGCONTEXT_H
+
+#include <asm/user.h>
+
+/*
+ * Signal context structure - contains all info to do with the state
+ * before the signal handler was invoked.  Note: only add new entries
+ * to the end of the structure.
+ */
+struct sigcontext {
+	struct user_regs_struct sc_regs;
+} __aligned(8);
+
+#endif
diff --git a/arch/hexagon/include/asm/signal.h b/arch/hexagon/include/asm/signal.h
new file mode 100644
index 0000000..471c056
--- /dev/null
+++ b/arch/hexagon/include/asm/signal.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SIGNAL_H
+#define _ASM_SIGNAL_H
+
+extern unsigned long __rt_sigtramp_template[2];
+
+#include <asm-generic/signal.h>
+
+#endif
diff --git a/arch/hexagon/include/asm/smp.h b/arch/hexagon/include/asm/smp.h
new file mode 100644
index 0000000..87c869a
--- /dev/null
+++ b/arch/hexagon/include/asm/smp.h
@@ -0,0 +1,44 @@
+/*
+ * SMP definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __ASM_SMP_H
+#define __ASM_SMP_H
+
+#include <linux/cpumask.h>
+
+#define raw_smp_processor_id() (current_thread_info()->cpu)
+
+enum ipi_message_type {
+	IPI_NOP = 0,
+	IPI_RESCHEDULE = 1,
+	IPI_CALL_FUNC,
+	IPI_CALL_FUNC_SINGLE,
+	IPI_CPU_STOP,
+	IPI_TIMER,
+};
+
+extern void send_ipi(const struct cpumask *cpumask, enum ipi_message_type msg);
+extern void smp_start_cpus(void);
+extern void arch_send_call_function_single_ipi(int cpu);
+extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
+
+extern void smp_vm_unmask_irq(void *info);
+
+#endif
diff --git a/arch/hexagon/include/asm/spinlock.h b/arch/hexagon/include/asm/spinlock.h
new file mode 100644
index 0000000..168a920
--- /dev/null
+++ b/arch/hexagon/include/asm/spinlock.h
@@ -0,0 +1,186 @@
+/*
+ * Spinlock support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SPINLOCK_H
+#define _ASM_SPINLOCK_H
+
+#include <asm/irqflags.h>
+
+/*
+ * This file is pulled in for SMP builds.
+ * Really need to check all the barrier stuff for "true" SMP
+ */
+
+/*
+ * Read locks:
+ * - load the lock value
+ * - increment it
+ * - if the lock value is still negative, go back and try again.
+ * - unsuccessful store is unsuccessful.  Go back and try again.  Loser.
+ * - successful store new lock value if positive -> lock acquired
+ */
+static inline void arch_read_lock(arch_rwlock_t *lock)
+{
+	__asm__ __volatile__(
+		"1:	R6 = memw_locked(%0);\n"
+		"	{ P3 = cmp.ge(R6,#0); R6 = add(R6,#1);}\n"
+		"	{ if !P3 jump 1b; }\n"
+		"	memw_locked(%0,P3) = R6;\n"
+		"	{ if !P3 jump 1b; }\n"
+		:
+		: "r" (&lock->lock)
+		: "memory", "r6", "p3"
+	);
+
+}
+
+static inline void arch_read_unlock(arch_rwlock_t *lock)
+{
+	__asm__ __volatile__(
+		"1:	R6 = memw_locked(%0);\n"
+		"	R6 = add(R6,#-1);\n"
+		"	memw_locked(%0,P3) = R6\n"
+		"	if !P3 jump 1b;\n"
+		:
+		: "r" (&lock->lock)
+		: "memory", "r6", "p3"
+	);
+
+}
+
+/*  I think this returns 0 on fail, 1 on success.  */
+static inline int arch_read_trylock(arch_rwlock_t *lock)
+{
+	int temp;
+	__asm__ __volatile__(
+		"	R6 = memw_locked(%1);\n"
+		"	{ %0 = #0; P3 = cmp.ge(R6,#0); R6 = add(R6,#1);}\n"
+		"	{ if !P3 jump 1f; }\n"
+		"	memw_locked(%1,P3) = R6;\n"
+		"	{ %0 = P3 }\n"
+		"1:\n"
+		: "=&r" (temp)
+		: "r" (&lock->lock)
+		: "memory", "r6", "p3"
+	);
+	return temp;
+}
+
+static inline int arch_read_can_lock(arch_rwlock_t *rwlock)
+{
+	return rwlock->lock == 0;
+}
+
+static inline int arch_write_can_lock(arch_rwlock_t *rwlock)
+{
+	return rwlock->lock == 0;
+}
+
+/*  Stuffs a -1 in the lock value?  */
+static inline void arch_write_lock(arch_rwlock_t *lock)
+{
+	__asm__ __volatile__(
+		"1:	R6 = memw_locked(%0)\n"
+		"	{ P3 = cmp.eq(R6,#0);  R6 = #-1;}\n"
+		"	{ if !P3 jump 1b; }\n"
+		"	memw_locked(%0,P3) = R6;\n"
+		"	{ if !P3 jump 1b; }\n"
+		:
+		: "r" (&lock->lock)
+		: "memory", "r6", "p3"
+	);
+}
+
+
+static inline int arch_write_trylock(arch_rwlock_t *lock)
+{
+	int temp;
+	__asm__ __volatile__(
+		"	R6 = memw_locked(%1)\n"
+		"	{ %0 = #0; P3 = cmp.eq(R6,#0);  R6 = #-1;}\n"
+		"	{ if !P3 jump 1f; }\n"
+		"	memw_locked(%1,P3) = R6;\n"
+		"	%0 = P3;\n"
+		"1:\n"
+		: "=&r" (temp)
+		: "r" (&lock->lock)
+		: "memory", "r6", "p3"
+	);
+	return temp;
+
+}
+
+static inline void arch_write_unlock(arch_rwlock_t *lock)
+{
+	smp_mb();
+	lock->lock = 0;
+}
+
+static inline void arch_spin_lock(arch_spinlock_t *lock)
+{
+	__asm__ __volatile__(
+		"1:	R6 = memw_locked(%0);\n"
+		"	P3 = cmp.eq(R6,#0);\n"
+		"	{ if !P3 jump 1b; R6 = #1; }\n"
+		"	memw_locked(%0,P3) = R6;\n"
+		"	{ if !P3 jump 1b; }\n"
+		:
+		: "r" (&lock->lock)
+		: "memory", "r6", "p3"
+	);
+
+}
+
+static inline void arch_spin_unlock(arch_spinlock_t *lock)
+{
+	smp_mb();
+	lock->lock = 0;
+}
+
+static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock)
+{
+	int temp;
+	__asm__ __volatile__(
+		"	R6 = memw_locked(%1);\n"
+		"	P3 = cmp.eq(R6,#0);\n"
+		"	{ if !P3 jump 1f; R6 = #1; %0 = #0; }\n"
+		"	memw_locked(%1,P3) = R6;\n"
+		"	%0 = P3;\n"
+		"1:\n"
+		: "=&r" (temp)
+		: "r" (&lock->lock)
+		: "memory", "r6", "p3"
+	);
+	return temp;
+}
+
+/*
+ * SMP spinlocks are intended to allow only a single CPU at the lock
+ */
+#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
+#define arch_spin_unlock_wait(lock) \
+	do {while (arch_spin_is_locked(lock)) cpu_relax(); } while (0)
+#define arch_spin_is_locked(x) ((x)->lock != 0)
+
+#define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
+#define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
+
+#endif
diff --git a/arch/hexagon/include/asm/spinlock_types.h b/arch/hexagon/include/asm/spinlock_types.h
new file mode 100644
index 0000000..5e937af
--- /dev/null
+++ b/arch/hexagon/include/asm/spinlock_types.h
@@ -0,0 +1,42 @@
+/*
+ * Spinlock support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SPINLOCK_TYPES_H
+#define _ASM_SPINLOCK_TYPES_H
+
+#include <linux/version.h>
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+	volatile unsigned int lock;
+} arch_spinlock_t;
+
+#define __ARCH_SPIN_LOCK_UNLOCKED	{ 0 }
+
+typedef struct {
+	volatile unsigned int lock;
+} arch_rwlock_t;
+
+#define __ARCH_RW_LOCK_UNLOCKED		{ 0 }
+
+#endif
diff --git a/arch/hexagon/include/asm/string.h b/arch/hexagon/include/asm/string.h
new file mode 100644
index 0000000..f4489c1
--- /dev/null
+++ b/arch/hexagon/include/asm/string.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_STRING_H_
+#define _ASM_STRING_H_
+
+#ifdef __KERNEL__
+#define __HAVE_ARCH_MEMCPY
+extern void *memcpy(void *__to, __const__ void *__from, size_t __n);
+
+/*  ToDo:  use dczeroa, accelerate the compiler-constant zero case  */
+#define __HAVE_ARCH_MEMSET
+extern void *memset(void *__to, int c, size_t __n);
+#endif
+
+
+#endif /* _ASM_STRING_H_ */
diff --git a/arch/hexagon/include/asm/suspend.h b/arch/hexagon/include/asm/suspend.h
new file mode 100644
index 0000000..089dd82
--- /dev/null
+++ b/arch/hexagon/include/asm/suspend.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SUSPEND_H
+#define _ASM_SUSPEND_H
+
+static inline int arch_prepare_suspend(void)
+{
+	return 0;
+}
+
+#endif
diff --git a/arch/hexagon/include/asm/swab.h b/arch/hexagon/include/asm/swab.h
new file mode 100644
index 0000000..99cf0be
--- /dev/null
+++ b/arch/hexagon/include/asm/swab.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SWAB_H
+#define _ASM_SWAB_H
+
+#define __SWAB_64_THRU_32__
+
+#endif
diff --git a/arch/hexagon/include/asm/syscall.h b/arch/hexagon/include/asm/syscall.h
new file mode 100644
index 0000000..3e7d61d
--- /dev/null
+++ b/arch/hexagon/include/asm/syscall.h
@@ -0,0 +1,54 @@
+/*
+ * Syscall support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_HEXAGON_SYSCALL_H
+#define _ASM_HEXAGON_SYSCALL_H
+
+typedef long (*syscall_fn)(unsigned long, unsigned long,
+	unsigned long, unsigned long,
+	unsigned long, unsigned long);
+
+asmlinkage int sys_execve(char __user *ufilename, char __user * __user *argv,
+			  char __user * __user *envp);
+asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
+			 unsigned long parent_tidp, unsigned long child_tidp);
+
+#define sys_execve	sys_execve
+#define sys_clone	sys_clone
+
+#include <asm-generic/syscalls.h>
+
+extern void *sys_call_table[];
+
+static inline long syscall_get_nr(struct task_struct *task,
+				  struct pt_regs *regs)
+{
+	return regs->r06;
+}
+
+static inline void syscall_get_arguments(struct task_struct *task,
+					 struct pt_regs *regs,
+					 unsigned int i, unsigned int n,
+					 unsigned long *args)
+{
+	BUG_ON(i + n > 6);
+	memcpy(args, &(&regs->r00)[i], n * sizeof(args[0]));
+}
+#endif
diff --git a/arch/hexagon/include/asm/system.h b/arch/hexagon/include/asm/system.h
new file mode 100644
index 0000000..323ed1d
--- /dev/null
+++ b/arch/hexagon/include/asm/system.h
@@ -0,0 +1,126 @@
+/*
+ * System level definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SYSTEM_H
+#define _ASM_SYSTEM_H
+
+#include <linux/linkage.h>
+#include <linux/irqflags.h>
+#include <asm/atomic.h>
+#include <asm/hexagon_vm.h>
+
+struct thread_struct;
+
+extern struct task_struct *__switch_to(struct task_struct *,
+	struct task_struct *,
+	struct task_struct *);
+
+#define switch_to(p, n, r) do {\
+	r = __switch_to((p), (n), (r));\
+} while (0)
+
+
+#define rmb()				barrier()
+#define read_barrier_depends()		barrier()
+#define wmb()				barrier()
+#define mb()				barrier()
+#define smp_rmb()			barrier()
+#define smp_read_barrier_depends()	barrier()
+#define smp_wmb()			barrier()
+#define smp_mb()			barrier()
+#define smp_mb__before_atomic_dec()	barrier()
+#define smp_mb__after_atomic_dec()	barrier()
+#define smp_mb__before_atomic_inc()	barrier()
+#define smp_mb__after_atomic_inc()	barrier()
+
+/*
+ * __xchg - atomically exchange a register and a memory location
+ * @x: value to swap
+ * @ptr: pointer to memory
+ * @size:  size of the value
+ *
+ * Only 4 bytes supported currently.
+ *
+ * Note:  there was an errata for V2 about .new's and memw_locked.
+ *
+ */
+static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
+				   int size)
+{
+	unsigned long retval;
+
+	/*  Can't seem to use printk or panic here, so just stop  */
+	if (size != 4) do { asm volatile("brkpt;\n"); } while (1);
+
+	__asm__ __volatile__ (
+	"1:	%0 = memw_locked(%1);\n"    /*  load into retval */
+	"	memw_locked(%1,P0) = %2;\n" /*  store into memory */
+	"	if !P0 jump 1b;\n"
+	: "=&r" (retval)
+	: "r" (ptr), "r" (x)
+	: "memory", "p0"
+	);
+	return retval;
+}
+
+/*
+ * Atomically swap the contents of a register with memory.  Should be atomic
+ * between multiple CPU's and within interrupts on the same CPU.
+ */
+#define xchg(ptr, v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), \
+	sizeof(*(ptr))))
+
+/*  Set a value and use a memory barrier.  Used by the scheduler somewhere.  */
+#define set_mb(var, value) \
+	do { var = value; mb(); } while (0)
+
+/*
+ *  see rt-mutex-design.txt; cmpxchg supposedly checks if *ptr == A and swaps.
+ *  looks just like atomic_cmpxchg on our arch currently with a bunch of
+ *  variable casting.
+ */
+#define __HAVE_ARCH_CMPXCHG 1
+
+#define cmpxchg(ptr, old, new)					\
+({								\
+	__typeof__(ptr) __ptr = (ptr);				\
+	__typeof__(*(ptr)) __old = (old);			\
+	__typeof__(*(ptr)) __new = (new);			\
+	__typeof__(*(ptr)) __oldval = 0;			\
+								\
+	asm volatile(						\
+		"1:	%0 = memw_locked(%1);\n"		\
+		"	{ P0 = cmp.eq(%0,%2);\n"		\
+		"	  if (!P0.new) jump:nt 2f; }\n"		\
+		"	memw_locked(%1,p0) = %3;\n"		\
+		"	if (!P0) jump 1b;\n"			\
+		"2:\n"						\
+		: "=&r" (__oldval)				\
+		: "r" (__ptr), "r" (__old), "r" (__new)		\
+		: "memory", "p0"				\
+	);							\
+	__oldval;						\
+})
+
+/*  Should probably shoot for an 8-byte aligned stack pointer  */
+#define STACK_MASK (~7)
+#define arch_align_stack(x) (x & STACK_MASK)
+
+#endif
diff --git a/arch/hexagon/include/asm/thread_info.h b/arch/hexagon/include/asm/thread_info.h
new file mode 100644
index 0000000..9c2934f
--- /dev/null
+++ b/arch/hexagon/include/asm/thread_info.h
@@ -0,0 +1,154 @@
+/*
+ * Thread support for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_THREAD_INFO_H
+#define _ASM_THREAD_INFO_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+#include <asm/processor.h>
+#include <asm/registers.h>
+#include <asm/page.h>
+#endif
+
+#define THREAD_SHIFT		12
+#define THREAD_SIZE		(1<<THREAD_SHIFT)
+
+#if THREAD_SHIFT >= PAGE_SHIFT
+#define THREAD_SIZE_ORDER	(THREAD_SHIFT - PAGE_SHIFT)
+#else  /*  don't use standard allocator  */
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
+extern struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node);
+extern void free_thread_info(struct thread_info *ti);
+#endif
+
+
+#ifndef __ASSEMBLY__
+
+typedef struct {
+	unsigned long seg;
+} mm_segment_t;
+
+/*
+ * This is union'd with the "bottom" of the kernel stack.
+ * It keeps track of thread info which is handy for routines
+ * to access quickly.
+ */
+
+struct thread_info {
+	struct task_struct	*task;		/* main task structure */
+	struct exec_domain      *exec_domain;   /* execution domain */
+	unsigned long		flags;          /* low level flags */
+	__u32                   cpu;            /* current cpu */
+	int                     preempt_count;  /* 0=>preemptible,<0=>BUG */
+	mm_segment_t            addr_limit;     /* segmentation sux */
+	/*
+	 * used for syscalls somehow;
+	 * seems to have a function pointer and four arguments
+	 */
+	struct restart_block    restart_block;
+	/* Points to the current pt_regs frame  */
+	struct pt_regs		*regs;
+	/*
+	 * saved kernel sp at switch_to time;
+	 * not sure if this is used (it's not in the VM model it seems;
+	 * see thread_struct)
+	 */
+	unsigned long		sp;
+};
+
+#else /* !__ASSEMBLY__ */
+
+#include <asm/asm-offsets.h>
+
+#endif  /* __ASSEMBLY__  */
+
+/*  looks like "linux/hardirq.h" uses this.  */
+
+#define PREEMPT_ACTIVE		0x10000000
+
+#ifndef __ASSEMBLY__
+
+#define INIT_THREAD_INFO(tsk)                   \
+{                                               \
+	.task           = &tsk,                 \
+	.exec_domain    = &default_exec_domain, \
+	.flags          = 0,                    \
+	.cpu            = 0,                    \
+	.preempt_count  = 1,                    \
+	.addr_limit     = KERNEL_DS,            \
+	.restart_block = {                      \
+		.fn = do_no_restart_syscall,    \
+	},                                      \
+	.sp = 0,				\
+	.regs = NULL,			\
+}
+
+#define init_thread_info        (init_thread_union.thread_info)
+#define init_stack              (init_thread_union.stack)
+
+/* Tacky preprocessor trickery */
+#define	qqstr(s) qstr(s)
+#define qstr(s) #s
+#define QUOTED_THREADINFO_REG qqstr(THREADINFO_REG)
+
+register struct thread_info *__current_thread_info asm(QUOTED_THREADINFO_REG);
+#define current_thread_info()  __current_thread_info
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * thread information flags
+ * - these are process state flags that various assembly files
+ *   may need to access
+ * - pending work-to-be-done flags are in LSW
+ * - other flags in MSW
+ */
+
+#define TIF_SYSCALL_TRACE       0       /* syscall trace active */
+#define TIF_NOTIFY_RESUME       1       /* resumption notification requested */
+#define TIF_SIGPENDING          2       /* signal pending */
+#define TIF_NEED_RESCHED        3       /* rescheduling necessary */
+#define TIF_SINGLESTEP          4       /* restore ss @ return to usr mode */
+#define TIF_IRET                5       /* return with iret */
+#define TIF_RESTORE_SIGMASK     6       /* restore sig mask in do_signal() */
+/* true if poll_idle() is polling TIF_NEED_RESCHED */
+#define TIF_POLLING_NRFLAG      16
+#define TIF_MEMDIE              17      /* OOM killer killed process */
+
+#define _TIF_SYSCALL_TRACE      (1 << TIF_SYSCALL_TRACE)
+#define _TIF_NOTIFY_RESUME      (1 << TIF_NOTIFY_RESUME)
+#define _TIF_SIGPENDING         (1 << TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED       (1 << TIF_NEED_RESCHED)
+#define _TIF_SINGLESTEP         (1 << TIF_SINGLESTEP)
+#define _TIF_IRET               (1 << TIF_IRET)
+#define _TIF_RESTORE_SIGMASK    (1 << TIF_RESTORE_SIGMASK)
+#define _TIF_POLLING_NRFLAG     (1 << TIF_POLLING_NRFLAG)
+
+/* work to do on interrupt/exception return - All but TIF_SYSCALL_TRACE */
+#define _TIF_WORK_MASK          (0x0000FFFF & ~_TIF_SYSCALL_TRACE)
+
+/* work to do on any return to u-space */
+#define _TIF_ALLWORK_MASK       0x0000FFFF
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/arch/hexagon/include/asm/time.h b/arch/hexagon/include/asm/time.h
new file mode 100644
index 0000000..081b82c
--- /dev/null
+++ b/arch/hexagon/include/asm/time.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef ASM_TIME_H
+#define ASM_TIME_H
+
+extern cycles_t        pcycle_freq_mhz;
+extern cycles_t        thread_freq_mhz;
+extern cycles_t        sleep_clk_freq;
+
+void setup_percpu_clockdev(void);
+void ipi_timer(void);
+
+#endif
diff --git a/arch/hexagon/include/asm/timer-regs.h b/arch/hexagon/include/asm/timer-regs.h
new file mode 100644
index 0000000..d80db23
--- /dev/null
+++ b/arch/hexagon/include/asm/timer-regs.h
@@ -0,0 +1,39 @@
+/*
+ * Timer support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_TIMER_REGS_H
+#define _ASM_TIMER_REGS_H
+
+/*  This stuff should go into a platform specific file  */
+#define TCX0_CLK_RATE		19200
+#define TIMER_ENABLE		0
+#define TIMER_CLR_ON_MATCH	1
+
+/*
+ * 8x50 HDD Specs 5-8.  Simulator co-sim not fixed until
+ * release 1.1, and then it's "adjustable" and probably not defaulted.
+ */
+#define RTOS_TIMER_INT		3
+#ifdef CONFIG_HEXAGON_COMET
+#define RTOS_TIMER_REGS_ADDR	0xAB000000UL
+#endif
+#define SLEEP_CLK_RATE		32000
+
+#endif
diff --git a/arch/hexagon/include/asm/timex.h b/arch/hexagon/include/asm/timex.h
new file mode 100644
index 0000000..b11c62b
--- /dev/null
+++ b/arch/hexagon/include/asm/timex.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_TIMEX_H
+#define _ASM_TIMEX_H
+
+#include <asm-generic/timex.h>
+#include <asm/timer-regs.h>
+
+/* Using TCX0 as our clock.  CLOCK_TICK_RATE scheduled to be removed. */
+#define CLOCK_TICK_RATE              TCX0_CLK_RATE
+
+#define ARCH_HAS_READ_CURRENT_TIMER
+
+static inline int read_current_timer(unsigned long *timer_val)
+{
+	*timer_val = (unsigned long) __vmgettime();
+	return 0;
+}
+
+#endif
diff --git a/arch/hexagon/include/asm/tlb.h b/arch/hexagon/include/asm/tlb.h
new file mode 100644
index 0000000..473abde
--- /dev/null
+++ b/arch/hexagon/include/asm/tlb.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_TLB_H
+#define _ASM_TLB_H
+
+#include <linux/pagemap.h>
+#include <asm/tlbflush.h>
+
+/*
+ * We don't need any special per-pte or per-vma handling...
+ */
+#define tlb_start_vma(tlb, vma)				do { } while (0)
+#define tlb_end_vma(tlb, vma)				do { } while (0)
+#define __tlb_remove_tlb_entry(tlb, ptep, address)	do { } while (0)
+
+/*
+ * .. because we flush the whole mm when it fills up
+ */
+#define tlb_flush(tlb)		flush_tlb_mm((tlb)->mm)
+
+#include <asm-generic/tlb.h>
+
+#endif
diff --git a/arch/hexagon/include/asm/tlbflush.h b/arch/hexagon/include/asm/tlbflush.h
new file mode 100644
index 0000000..b89a902
--- /dev/null
+++ b/arch/hexagon/include/asm/tlbflush.h
@@ -0,0 +1,58 @@
+/*
+ * TLB flush support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_TLBFLUSH_H
+#define _ASM_TLBFLUSH_H
+
+#include <linux/mm.h>
+#include <asm/processor.h>
+
+/*
+ * TLB flushing -- in "SMP", these routines get defined to be the
+ * ones from smp.c, else they are some local flavors.
+ */
+
+/*
+ * These functions are commonly macros, but in the interests of
+ * VM vs. native implementation and code size, we simply declare
+ * the function prototypes here.
+ */
+extern void tlb_flush_all(void);
+extern void flush_tlb_mm(struct mm_struct *mm);
+extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr);
+extern void flush_tlb_range(struct vm_area_struct *vma,
+				unsigned long start, unsigned long end);
+extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
+extern void flush_tlb_one(unsigned long);
+
+/*
+ * "This is called in munmap when we have freed up some page-table pages.
+ * We don't need to do anything here..."
+ *
+ * The VM kernel doesn't walk page tables, and they are passed to the VMM
+ * by logical address. There doesn't seem to be any possibility that they
+ * could be referenced by the VM kernel based on a stale mapping, since
+ * they would only be located by consulting the mm structure, and they
+ * will have been purged from that structure by the munmap.  Seems like
+ * a noop on HVM as well.
+ */
+#define flush_tlb_pgtables(mm, start, end)
+
+#endif
diff --git a/arch/hexagon/include/asm/traps.h b/arch/hexagon/include/asm/traps.h
new file mode 100644
index 0000000..6a407f6
--- /dev/null
+++ b/arch/hexagon/include/asm/traps.h
@@ -0,0 +1,29 @@
+/*
+ * Trap support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_HEXAGON_TRAPS_H
+#define _ASM_HEXAGON_TRAPS_H
+
+#include <asm/registers.h>
+
+extern int die(const char *str, struct pt_regs *regs, long err);
+extern int die_if_kernel(char *str, struct pt_regs *regs, long err);
+
+#endif /* _ASM_HEXAGON_TRAPS_H */
diff --git a/arch/hexagon/include/asm/uaccess.h b/arch/hexagon/include/asm/uaccess.h
new file mode 100644
index 0000000..7e706ea
--- /dev/null
+++ b/arch/hexagon/include/asm/uaccess.h
@@ -0,0 +1,116 @@
+/*
+ * User memory access support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_UACCESS_H
+#define _ASM_UACCESS_H
+/*
+ * User space memory access functions
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/segment.h>
+#include <asm/sections.h>
+
+/*
+ * access_ok: - Checks if a user space pointer is valid
+ * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE.  Note that
+ *        %VERIFY_WRITE is a superset of %VERIFY_READ - if it is safe
+ *        to write to a block, it is always safe to read from it.
+ * @addr: User space pointer to start of block to check
+ * @size: Size of block to check
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * Checks if a pointer to a block of memory in user space is valid.
+ *
+ * Returns true (nonzero) if the memory block *may* be valid, false (zero)
+ * if it is definitely invalid.
+ *
+ * User address space in Hexagon, like x86, goes to 0xbfffffff, so the
+ * simple MSB-based tests used by MIPS won't work.  Some further
+ * optimization is probably possible here, but for now, keep it
+ * reasonably simple and not *too* slow.  After all, we've got the
+ * MMU for backup.
+ */
+#define VERIFY_READ     0
+#define VERIFY_WRITE    1
+
+#define __access_ok(addr, size) \
+	((get_fs().seg == KERNEL_DS.seg) || \
+	(((unsigned long)addr < get_fs().seg) && \
+	  (unsigned long)size < (get_fs().seg - (unsigned long)addr)))
+
+/*
+ * When a kernel-mode page fault is taken, the faulting instruction
+ * address is checked against a table of exception_table_entries.
+ * Each entry is a tuple of the address of an instruction that may
+ * be authorized to fault, and the address at which execution should
+ * be resumed instead of the faulting instruction, so as to effect
+ * a workaround.
+ */
+
+/*  Assembly somewhat optimized copy routines  */
+unsigned long __copy_from_user_hexagon(void *to, const void __user *from,
+				     unsigned long n);
+unsigned long __copy_to_user_hexagon(void __user *to, const void *from,
+				   unsigned long n);
+
+#define __copy_from_user(to, from, n) __copy_from_user_hexagon(to, from, n)
+#define __copy_to_user(to, from, n) __copy_to_user_hexagon(to, from, n)
+
+/*
+ * XXX todo: some additonal performance gain is possible by
+ * implementing __copy_to/from_user_inatomic, which is much
+ * like __copy_to/from_user, but performs slightly less checking.
+ */
+
+__kernel_size_t __clear_user_hexagon(void __user *dest, unsigned long count);
+#define __clear_user(a, s) __clear_user_hexagon((a), (s))
+
+#define __strncpy_from_user(dst, src, n) hexagon_strncpy_from_user(dst, src, n)
+
+/*  get around the ifndef in asm-generic/uaccess.h  */
+#define __strnlen_user __strnlen_user
+
+extern long __strnlen_user(const char __user *src, long n);
+
+static inline long hexagon_strncpy_from_user(char *dst, const char __user *src,
+					     long n);
+
+#include <asm-generic/uaccess.h>
+
+/*  Todo:  an actual accelerated version of this.  */
+static inline long hexagon_strncpy_from_user(char *dst, const char __user *src,
+					     long n)
+{
+	long res = __strnlen_user(src, n);
+
+	/* return from strnlen can't be zero -- that would be rubbish. */
+
+	if (res > n) {
+		copy_from_user(dst, src, n);
+		return n;
+	} else {
+		copy_from_user(dst, src, res);
+		return res-1;
+	}
+}
+
+#endif
diff --git a/arch/hexagon/include/asm/unistd.h b/arch/hexagon/include/asm/unistd.h
new file mode 100644
index 0000000..4d0ecde
--- /dev/null
+++ b/arch/hexagon/include/asm/unistd.h
@@ -0,0 +1,36 @@
+/*
+ * Syscall support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#if !defined(_ASM_HEXAGON_UNISTD_H) || defined(__SYSCALL)
+#define _ASM_HEXAGON_UNISTD_H
+
+/*
+ *  The kernel pulls this unistd.h in three different ways:
+ *  1.  the "normal" way which gets all the __NR defines
+ *  2.  with __SYSCALL defined to produce function declarations
+ *  3.  with __SYSCALL defined to produce syscall table initialization
+ *  See also:  syscalltab.c
+ */
+
+#define sys_mmap2 sys_mmap_pgoff
+
+#include <asm-generic/unistd.h>
+
+#endif
diff --git a/arch/hexagon/include/asm/user.h b/arch/hexagon/include/asm/user.h
new file mode 100644
index 0000000..3a55078
--- /dev/null
+++ b/arch/hexagon/include/asm/user.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef HEXAGON_ASM_USER_H
+#define HEXAGON_ASM_USER_H
+
+/*
+ * Layout for registers passed in elf core dumps to userspace.
+ *
+ * Basically a rearranged subset of "pt_regs".
+ *
+ * Interested parties:  libc, gdb...
+ */
+
+struct user_regs_struct {
+	unsigned long r0;
+	unsigned long r1;
+	unsigned long r2;
+	unsigned long r3;
+	unsigned long r4;
+	unsigned long r5;
+	unsigned long r6;
+	unsigned long r7;
+	unsigned long r8;
+	unsigned long r9;
+	unsigned long r10;
+	unsigned long r11;
+	unsigned long r12;
+	unsigned long r13;
+	unsigned long r14;
+	unsigned long r15;
+	unsigned long r16;
+	unsigned long r17;
+	unsigned long r18;
+	unsigned long r19;
+	unsigned long r20;
+	unsigned long r21;
+	unsigned long r22;
+	unsigned long r23;
+	unsigned long r24;
+	unsigned long r25;
+	unsigned long r26;
+	unsigned long r27;
+	unsigned long r28;
+	unsigned long r29;
+	unsigned long r30;
+	unsigned long r31;
+	unsigned long sa0;
+	unsigned long lc0;
+	unsigned long sa1;
+	unsigned long lc1;
+	unsigned long m0;
+	unsigned long m1;
+	unsigned long usr;
+	unsigned long p3_0;
+	unsigned long gp;
+	unsigned long ugp;
+	unsigned long pc;
+	unsigned long cause;
+	unsigned long badva;
+	unsigned long pad1;  /* pad out to 48 words total */
+	unsigned long pad2;  /* pad out to 48 words total */
+	unsigned long pad3;  /* pad out to 48 words total */
+};
+
+#endif
diff --git a/arch/hexagon/include/asm/vdso.h b/arch/hexagon/include/asm/vdso.h
new file mode 100644
index 0000000..2d95cbb
--- /dev/null
+++ b/arch/hexagon/include/asm/vdso.h
@@ -0,0 +1,30 @@
+/*
+ * vDSO implementation for Hexagon
+ *
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __ASM_VDSO_H
+#define __ASM_VDSO_H
+
+#include <linux/types.h>
+
+struct hexagon_vdso {
+	u32 rt_signal_trampoline[2];
+};
+
+#endif /* __ASM_VDSO_H */
diff --git a/arch/hexagon/include/asm/vm_fault.h b/arch/hexagon/include/asm/vm_fault.h
new file mode 100644
index 0000000..cacda36
--- /dev/null
+++ b/arch/hexagon/include/asm/vm_fault.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_HEXAGON_VM_FAULT_H
+#define _ASM_HEXAGON_VM_FAULT_H
+
+extern void execute_protection_fault(struct pt_regs *);
+extern void write_protection_fault(struct pt_regs *);
+extern void read_protection_fault(struct pt_regs *);
+
+#endif
diff --git a/arch/hexagon/include/asm/vm_mmu.h b/arch/hexagon/include/asm/vm_mmu.h
new file mode 100644
index 0000000..580462d
--- /dev/null
+++ b/arch/hexagon/include/asm/vm_mmu.h
@@ -0,0 +1,111 @@
+/*
+ * Hexagon VM page table entry definitions
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_VM_MMU_H
+#define _ASM_VM_MMU_H
+
+/*
+ * Shift, mask, and other constants for the Hexagon Virtual Machine
+ * page tables.
+ *
+ * Virtual machine MMU allows first-level entries to either be
+ * single-level lookup PTEs for very large pages, or PDEs pointing
+ * to second-level PTEs for smaller pages. If PTE is single-level,
+ * the least significant bits cannot be used as software bits to encode
+ * virtual memory subsystem information about the page, and that state
+ * must be maintained in some parallel data structure.
+ */
+
+/* S or Page Size field in PDE */
+#define	__HVM_PDE_S		(0x7 << 0)
+#define __HVM_PDE_S_4KB		0
+#define __HVM_PDE_S_16KB	1
+#define __HVM_PDE_S_64KB	2
+#define __HVM_PDE_S_256KB	3
+#define __HVM_PDE_S_1MB		4
+#define __HVM_PDE_S_4MB		5
+#define __HVM_PDE_S_16MB	6
+#define __HVM_PDE_S_INVALID	7
+
+/* Masks for L2 page table pointer, as function of page size */
+#define __HVM_PDE_PTMASK_4KB	0xfffff000
+#define __HVM_PDE_PTMASK_16KB	0xfffffc00
+#define __HVM_PDE_PTMASK_64KB	0xffffff00
+#define __HVM_PDE_PTMASK_256KB	0xffffffc0
+#define __HVM_PDE_PTMASK_1MB	0xfffffff0
+
+/*
+ * Virtual Machine PTE Bits/Fields
+ */
+#define __HVM_PTE_T		(1<<4)
+#define __HVM_PTE_U		(1<<5)
+#define	__HVM_PTE_C		(0x7<<6)
+#define __HVM_PTE_CVAL(pte)	(((pte) & __HVM_PTE_C) >> 6)
+#define __HVM_PTE_R		(1<<9)
+#define __HVM_PTE_W		(1<<10)
+#define __HVM_PTE_X		(1<<11)
+
+/*
+ * Cache Attributes, to be shifted as necessary for virtual/physical PTEs
+ */
+
+#define __HEXAGON_C_WB		0x0	/* Write-back, no L2 */
+#define	__HEXAGON_C_WT		0x1	/* Write-through, no L2 */
+#define	__HEXAGON_C_DEV		0x4	/* Device register space */
+#define	__HEXAGON_C_WT_L2	0x5	/* Write-through, with L2 */
+/* this really should be #if CONFIG_HEXAGON_ARCH = 2 but that's not defined */
+#if defined(CONFIG_HEXAGON_COMET) || defined(CONFIG_QDSP6_ST1)
+#define __HEXAGON_C_UNC		__HEXAGON_C_DEV
+#else
+#define	__HEXAGON_C_UNC		0x6	/* Uncached memory */
+#endif
+#define	__HEXAGON_C_WB_L2	0x7	/* Write-back, with L2 */
+
+/*
+ * This can be overriden, but we're defaulting to the most aggressive
+ * cache policy, the better to find bugs sooner.
+ */
+
+#define	CACHE_DEFAULT	__HEXAGON_C_WB_L2
+
+/* Masks for physical page address, as a function of page size */
+
+#define __HVM_PTE_PGMASK_4KB	0xfffff000
+#define __HVM_PTE_PGMASK_16KB	0xffffc000
+#define __HVM_PTE_PGMASK_64KB	0xffff0000
+#define __HVM_PTE_PGMASK_256KB	0xfffc0000
+#define __HVM_PTE_PGMASK_1MB	0xfff00000
+
+/* Masks for single-level large page lookups */
+
+#define __HVM_PTE_PGMASK_4MB	0xffc00000
+#define __HVM_PTE_PGMASK_16MB	0xff000000
+
+/*
+ * "Big kernel page mappings" (see vm_init_segtable.S)
+ * are currently 16MB
+ */
+
+#define BIG_KERNEL_PAGE_SHIFT 24
+#define BIG_KERNEL_PAGE_SIZE (1 << BIG_KERNEL_PAGE_SHIFT)
+
+
+
+#endif /* _ASM_VM_MMU_H */
diff --git a/arch/hexagon/kernel/Makefile b/arch/hexagon/kernel/Makefile
new file mode 100644
index 0000000..3689f37
--- /dev/null
+++ b/arch/hexagon/kernel/Makefile
@@ -0,0 +1,18 @@
+extra-y := head.o vmlinux.lds init_task.o
+
+obj-$(CONFIG_SMP) += smp.o topology.o
+
+obj-y += setup.o irq_cpu.o traps.o syscalltab.o signal.o time.o
+obj-y += process.o syscall.o trampoline.o reset.o ptrace.o
+obj-y += vdso.o
+
+obj-$(CONFIG_KGDB)    += kgdb.o
+obj-$(CONFIG_MODULES) += module.o hexagon_ksyms.o
+
+# Modules required to work with the Hexagon Virtual Machine
+obj-y += vm_entry.o vm_events.o vm_switch.o vm_ops.o vm_init_segtable.o
+obj-y += vm_vectors.o
+
+obj-$(CONFIG_HAS_DMA) += dma.o
+
+obj-$(CONFIG_STACKTRACE) += stacktrace.o
diff --git a/arch/hexagon/kernel/asm-offsets.c b/arch/hexagon/kernel/asm-offsets.c
new file mode 100644
index 0000000..89ffa51
--- /dev/null
+++ b/arch/hexagon/kernel/asm-offsets.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 1996 David S. Miller
+ * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/compat.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/kbuild.h>
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+
+/*  This file is used to produce asm/linkerscript constants from header
+    files typically used in c.  Specifically, it generates asm-offsets.h  */
+
+int main(void)
+{
+	COMMENT("This is a comment.");
+	/*  might get these from somewhere else.  */
+	DEFINE(_PAGE_SIZE, PAGE_SIZE);
+	DEFINE(_PAGE_SHIFT, PAGE_SHIFT);
+	BLANK();
+
+	COMMENT("Hexagon pt_regs definitions");
+	OFFSET(_PT_SYSCALL_NR, pt_regs, syscall_nr);
+	OFFSET(_PT_UGPGP, pt_regs, ugpgp);
+	OFFSET(_PT_R3130, pt_regs, r3130);
+	OFFSET(_PT_R2928, pt_regs, r2928);
+	OFFSET(_PT_R2726, pt_regs, r2726);
+	OFFSET(_PT_R2524, pt_regs, r2524);
+	OFFSET(_PT_R2322, pt_regs, r2322);
+	OFFSET(_PT_R2120, pt_regs, r2120);
+	OFFSET(_PT_R1918, pt_regs, r1918);
+	OFFSET(_PT_R1716, pt_regs, r1716);
+	OFFSET(_PT_R1514, pt_regs, r1514);
+	OFFSET(_PT_R1312, pt_regs, r1312);
+	OFFSET(_PT_R1110, pt_regs, r1110);
+	OFFSET(_PT_R0908, pt_regs, r0908);
+	OFFSET(_PT_R0706, pt_regs, r0706);
+	OFFSET(_PT_R0504, pt_regs, r0504);
+	OFFSET(_PT_R0302, pt_regs, r0302);
+	OFFSET(_PT_R0100, pt_regs, r0100);
+	OFFSET(_PT_LC0SA0, pt_regs, lc0sa0);
+	OFFSET(_PT_LC1SA1, pt_regs, lc1sa1);
+	OFFSET(_PT_M1M0, pt_regs, m1m0);
+	OFFSET(_PT_PREDSUSR, pt_regs, predsusr);
+	OFFSET(_PT_EVREC, pt_regs, hvmer);
+	OFFSET(_PT_ER_VMEL, pt_regs, hvmer.vmel);
+	OFFSET(_PT_ER_VMEST, pt_regs, hvmer.vmest);
+	OFFSET(_PT_ER_VMPSP, pt_regs, hvmer.vmpsp);
+	OFFSET(_PT_ER_VMBADVA, pt_regs, hvmer.vmbadva);
+	DEFINE(_PT_REGS_SIZE, sizeof(struct pt_regs));
+	BLANK();
+
+	COMMENT("Hexagon thread_info definitions");
+	OFFSET(_THREAD_INFO_FLAGS, thread_info, flags);
+	OFFSET(_THREAD_INFO_PT_REGS, thread_info, regs);
+	OFFSET(_THREAD_INFO_SP, thread_info, sp);
+	DEFINE(_THREAD_SIZE, THREAD_SIZE);
+	BLANK();
+
+	COMMENT("Hexagon hexagon_switch_stack definitions");
+	OFFSET(_SWITCH_R1716, hexagon_switch_stack, r1716);
+	OFFSET(_SWITCH_R1918, hexagon_switch_stack, r1918);
+	OFFSET(_SWITCH_R2120, hexagon_switch_stack, r2120);
+	OFFSET(_SWITCH_R2322, hexagon_switch_stack, r2322);
+
+	OFFSET(_SWITCH_R2524, hexagon_switch_stack, r2524);
+	OFFSET(_SWITCH_R2726, hexagon_switch_stack, r2726);
+	OFFSET(_SWITCH_FP, hexagon_switch_stack, fp);
+	OFFSET(_SWITCH_LR, hexagon_switch_stack, lr);
+	DEFINE(_SWITCH_STACK_SIZE, sizeof(struct hexagon_switch_stack));
+	BLANK();
+
+	COMMENT("Hexagon task_struct definitions");
+	OFFSET(_TASK_THREAD_INFO, task_struct, stack);
+	OFFSET(_TASK_STRUCT_THREAD, task_struct, thread);
+
+	COMMENT("Hexagon thread_struct definitions");
+	OFFSET(_THREAD_STRUCT_SWITCH_SP, thread_struct, switch_sp);
+
+	return 0;
+}
diff --git a/arch/hexagon/kernel/dma.c b/arch/hexagon/kernel/dma.c
new file mode 100644
index 0000000..e711ace
--- /dev/null
+++ b/arch/hexagon/kernel/dma.c
@@ -0,0 +1,220 @@
+/*
+ * DMA implementation for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/bootmem.h>
+#include <linux/genalloc.h>
+#include <asm/dma-mapping.h>
+
+struct dma_map_ops *dma_ops;
+EXPORT_SYMBOL(dma_ops);
+
+int bad_dma_address;  /*  globals are automatically initialized to zero  */
+
+int dma_supported(struct device *dev, u64 mask)
+{
+	if (mask == DMA_BIT_MASK(32))
+		return 1;
+	else
+		return 0;
+}
+EXPORT_SYMBOL(dma_supported);
+
+int dma_set_mask(struct device *dev, u64 mask)
+{
+	if (!dev->dma_mask || !dma_supported(dev, mask))
+		return -EIO;
+
+	*dev->dma_mask = mask;
+
+	return 0;
+}
+EXPORT_SYMBOL(dma_set_mask);
+
+static struct gen_pool *coherent_pool;
+
+
+/* Allocates from a pool of uncached memory that was reserved at boot time */
+
+void *hexagon_dma_alloc_coherent(struct device *dev, size_t size,
+				 dma_addr_t *dma_addr, gfp_t flag)
+{
+	void *ret;
+
+	if (coherent_pool == NULL) {
+		coherent_pool = gen_pool_create(PAGE_SHIFT, -1);
+
+		if (coherent_pool == NULL)
+			panic("Can't create %s() memory pool!", __func__);
+		else
+			gen_pool_add(coherent_pool,
+				(PAGE_OFFSET + (max_low_pfn << PAGE_SHIFT)),
+				hexagon_coherent_pool_size, -1);
+	}
+
+	ret = (void *) gen_pool_alloc(coherent_pool, size);
+
+	if (ret) {
+		memset(ret, 0, size);
+		*dma_addr = (dma_addr_t) (ret - PAGE_OFFSET);
+	} else
+		*dma_addr = ~0;
+
+	return ret;
+}
+
+static void hexagon_free_coherent(struct device *dev, size_t size, void *vaddr,
+				  dma_addr_t dma_addr)
+{
+	gen_pool_free(coherent_pool, (unsigned long) vaddr, size);
+}
+
+static int check_addr(const char *name, struct device *hwdev,
+		      dma_addr_t bus, size_t size)
+{
+	if (hwdev && hwdev->dma_mask && !dma_capable(hwdev, bus, size)) {
+		if (*hwdev->dma_mask >= DMA_BIT_MASK(32))
+			printk(KERN_ERR
+				"%s: overflow %Lx+%zu of device mask %Lx\n",
+				name, (long long)bus, size,
+				(long long)*hwdev->dma_mask);
+		return 0;
+	}
+	return 1;
+}
+
+static int hexagon_map_sg(struct device *hwdev, struct scatterlist *sg,
+			  int nents, enum dma_data_direction dir,
+			  struct dma_attrs *attrs)
+{
+	struct scatterlist *s;
+	int i;
+
+	WARN_ON(nents == 0 || sg[0].length == 0);
+
+	for_each_sg(sg, s, nents, i) {
+		s->dma_address = sg_phys(s);
+		if (!check_addr("map_sg", hwdev, s->dma_address, s->length))
+			return 0;
+
+		s->dma_length = s->length;
+
+		flush_dcache_range(PAGE_OFFSET + s->dma_address,
+				   PAGE_OFFSET + s->dma_address + s->length);
+	}
+
+	return nents;
+}
+
+/*
+ * address is virtual
+ */
+static inline void dma_sync(void *addr, size_t size,
+			    enum dma_data_direction dir)
+{
+	switch (dir) {
+	case DMA_TO_DEVICE:
+		hexagon_clean_dcache_range((unsigned long) addr,
+		(unsigned long) addr + size);
+		break;
+	case DMA_FROM_DEVICE:
+		hexagon_inv_dcache_range((unsigned long) addr,
+		(unsigned long) addr + size);
+		break;
+	case DMA_BIDIRECTIONAL:
+		flush_dcache_range((unsigned long) addr,
+		(unsigned long) addr + size);
+		break;
+	default:
+		BUG();
+	}
+}
+
+static inline void *dma_addr_to_virt(dma_addr_t dma_addr)
+{
+	return phys_to_virt((unsigned long) dma_addr);
+}
+
+/**
+ * hexagon_map_page() - maps an address for device DMA
+ * @dev:	pointer to DMA device
+ * @page:	pointer to page struct of DMA memory
+ * @offset:	offset within page
+ * @size:	size of memory to map
+ * @dir:	transfer direction
+ * @attrs:	pointer to DMA attrs (not used)
+ *
+ * Called to map a memory address to a DMA address prior
+ * to accesses to/from device.
+ *
+ * We don't particularly have many hoops to jump through
+ * so far.  Straight translation between phys and virtual.
+ *
+ * DMA is not cache coherent so sync is necessary; this
+ * seems to be a convenient place to do it.
+ *
+ */
+static dma_addr_t hexagon_map_page(struct device *dev, struct page *page,
+				   unsigned long offset, size_t size,
+				   enum dma_data_direction dir,
+				   struct dma_attrs *attrs)
+{
+	dma_addr_t bus = page_to_phys(page) + offset;
+	WARN_ON(size == 0);
+
+	if (!check_addr("map_single", dev, bus, size))
+		return bad_dma_address;
+
+	dma_sync(dma_addr_to_virt(bus), size, dir);
+
+	return bus;
+}
+
+static void hexagon_sync_single_for_cpu(struct device *dev,
+					dma_addr_t dma_handle, size_t size,
+					enum dma_data_direction dir)
+{
+	dma_sync(dma_addr_to_virt(dma_handle), size, dir);
+}
+
+static void hexagon_sync_single_for_device(struct device *dev,
+					dma_addr_t dma_handle, size_t size,
+					enum dma_data_direction dir)
+{
+	dma_sync(dma_addr_to_virt(dma_handle), size, dir);
+}
+
+struct dma_map_ops hexagon_dma_ops = {
+	.alloc_coherent	= hexagon_dma_alloc_coherent,
+	.free_coherent	= hexagon_free_coherent,
+	.map_sg		= hexagon_map_sg,
+	.map_page	= hexagon_map_page,
+	.sync_single_for_cpu = hexagon_sync_single_for_cpu,
+	.sync_single_for_device = hexagon_sync_single_for_device,
+	.is_phys	= 1,
+};
+
+void __init hexagon_dma_init(void)
+{
+	if (dma_ops)
+		return;
+
+	dma_ops = &hexagon_dma_ops;
+}
diff --git a/arch/hexagon/kernel/head.S b/arch/hexagon/kernel/head.S
new file mode 100644
index 0000000..8e6b819
--- /dev/null
+++ b/arch/hexagon/kernel/head.S
@@ -0,0 +1,162 @@
+/*
+ * Early kernel startup code for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/asm-offsets.h>
+#include <asm/mem-layout.h>
+#include <asm/vm_mmu.h>
+#include <asm/page.h>
+
+	__INIT
+ENTRY(stext)
+	/*
+	 * VMM will already have set up true vector page, MMU, etc.
+	 * To set up initial kernel identity map, we have to pass
+	 * the VMM a pointer to some canonical page tables. In
+	 * this implementation, we're assuming that we've got
+	 * them precompiled. Generate value in R24, as we'll need
+	 * it again shortly.
+	 */
+	r24.L = #LO(swapper_pg_dir)
+	r24.H = #HI(swapper_pg_dir)
+
+	/*
+	 * Symbol is kernel segment address, but we need
+	 * the logical/physical address.
+	 */
+	r24 = asl(r24, #2)
+	r24 = lsr(r24, #2)
+
+	r0 = r24
+
+	/*
+	 * Initialize a 16MB PTE to make the virtual and physical
+	 * addresses where the kernel was loaded be identical.
+	 */
+#define PTE_BITS ( __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X	\
+		  | __HEXAGON_C_WB_L2 << 6			\
+		  | __HVM_PDE_S_4MB)
+
+	r1 = pc
+	r2.H = #0xffc0
+	r2.L = #0x0000
+	r1 = and(r1,r2)		/* round PC to 4MB boundary	*/
+	r2 = lsr(r1, #22)	/* 4MB page number		*/
+	r2 = asl(r2, #2)	/* times sizeof(PTE) (4bytes)	*/
+	r0 = add(r0,r2)		/* r0 = address of correct PTE	*/
+	r2 = #PTE_BITS
+	r1 = add(r1,r2)		/* r1 = 4MB PTE for the first entry	*/
+	r2.h = #0x0040
+	r2.l = #0x0000		/* 4MB	*/
+	memw(r0 ++ #4) = r1
+	r1 = add(r1, r2)
+	memw(r0 ++ #4) = r1
+
+	r0 = r24
+
+	/*
+	 * The subroutine wrapper around the virtual instruction touches
+	 * no memory, so we should be able to use it even here.
+	 */
+	call	__vmnewmap;
+
+	/*  Jump into virtual address range.  */
+
+	r31.h = #hi(__head_s_vaddr_target)
+	r31.l = #lo(__head_s_vaddr_target)
+	jumpr r31
+
+	/*  Insert trippy space effects.  */
+
+__head_s_vaddr_target:
+	/*
+	 * Tear down VA=PA translation now that we are running
+	 * in the desgnated kernel segments.
+	 */
+	r0 = #__HVM_PDE_S_INVALID
+	r1 = r24
+	loop0(1f,#0x100)
+1:
+	{
+		memw(R1 ++ #4) = R0
+	}:endloop0
+
+	r0 = r24
+	call __vmnewmap
+
+	/*  Go ahead and install the trap0 return so angel calls work  */
+	r0.h = #hi(_K_provisional_vec)
+	r0.l = #lo(_K_provisional_vec)
+	call __vmsetvec
+
+	/*
+	 * OK, at this point we should start to be much more careful,
+	 * we're going to enter C code and start touching memory
+	 * in all sorts of places.
+	 * This means:
+	 *      SGP needs to be OK
+	 *	Need to lock shared resources
+	 *	A bunch of other things that will cause
+	 * 	all kinds of painful bugs
+	 */
+
+	/*
+	 * Stack pointer should be pointed at the init task's
+	 * thread stack, which should have been declared in arch/init_task.c.
+	 * So uhhhhh...
+	 * It's accessible via the init_thread_union, which is a union
+	 * of a thread_info struct and a stack; of course, the top
+	 * of the stack is not for you.  The end of the stack
+	 * is simply init_thread_union + THREAD_SIZE.
+	 */
+
+	{r29.H = #HI(init_thread_union); r0.H = #HI(_THREAD_SIZE); }
+	{r29.L = #LO(init_thread_union); r0.L = #LO(_THREAD_SIZE); }
+
+	/*  initialize the register used to point to current_thread_info */
+	/*  Fixme:  THREADINFO_REG can't be R2 because of that memset thing. */
+	{r29 = add(r29,r0); THREADINFO_REG = r29; }
+
+	/*  Hack:  zero bss; */
+	{ r0.L = #LO(__bss_start);  r1 = #0; r2.l = #LO(__bss_stop); }
+	{ r0.H = #HI(__bss_start);           r2.h = #HI(__bss_stop); }
+
+	r2 = sub(r2,r0);
+	call memset;
+
+	/* Time to make the doughnuts.   */
+	call start_kernel
+
+	/*
+	 * Should not reach here.
+	 */
+1:
+	jump 1b
+
+.p2align PAGE_SHIFT
+ENTRY(external_cmdline_buffer)
+        .fill _PAGE_SIZE,1,0
+
+.data
+.p2align PAGE_SHIFT
+ENTRY(empty_zero_page)
+        .fill _PAGE_SIZE,1,0
diff --git a/arch/hexagon/kernel/hexagon_ksyms.c b/arch/hexagon/kernel/hexagon_ksyms.c
new file mode 100644
index 0000000..7f18924
--- /dev/null
+++ b/arch/hexagon/kernel/hexagon_ksyms.c
@@ -0,0 +1,40 @@
+/*
+ * Export of symbols defined in assembly files and/or libgcc.
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <asm/hexagon_vm.h>
+#include <asm/uaccess.h>
+
+EXPORT_SYMBOL(__copy_from_user_hexagon);
+EXPORT_SYMBOL(__copy_to_user_hexagon);
+EXPORT_SYMBOL(__vmgetie);
+EXPORT_SYMBOL(__vmsetie);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+
+#define DECLARE_EXPORT(name)     \
+	extern void name(void); EXPORT_SYMBOL(name)
+
+/* Symbols found in libgcc that assorted kernel modules need */
+DECLARE_EXPORT(__hexagon_memcpy_likely_aligned_min32bytes_mult8bytes);
+
+DECLARE_EXPORT(__hexagon_divsi3);
+DECLARE_EXPORT(__hexagon_modsi3);
+DECLARE_EXPORT(__hexagon_udivsi3);
+DECLARE_EXPORT(__hexagon_umodsi3);
diff --git a/arch/hexagon/kernel/init_task.c b/arch/hexagon/kernel/init_task.c
new file mode 100644
index 0000000..73283d3
--- /dev/null
+++ b/arch/hexagon/kernel/init_task.c
@@ -0,0 +1,54 @@
+/*
+ * Init task definition
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init_task.h>
+#include <linux/fs.h>
+#include <linux/mqueue.h>
+#include <asm/thread_info.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+
+static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
+
+/*
+ * Initial thread structure.
+ *
+ * We need to make sure that this is 8192-byte aligned due to the
+ * way process stacks are handled. This is done by making sure
+ * the linker maps this in the .text segment right after head.S,
+ * and making head.S ensure the proper alignment.
+ */
+union thread_union init_thread_union
+	__attribute__((__section__(".data.init_task"),
+		__aligned__(THREAD_SIZE))) = {
+			INIT_THREAD_INFO(init_task)
+		};
+
+/*
+ * Initial task structure.
+ *
+ * All other task structs will be allocated on slabs in fork.c
+ */
+struct task_struct init_task = INIT_TASK(init_task);
+EXPORT_SYMBOL(init_task);
diff --git a/arch/hexagon/kernel/irq_cpu.c b/arch/hexagon/kernel/irq_cpu.c
new file mode 100644
index 0000000..d4416a1
--- /dev/null
+++ b/arch/hexagon/kernel/irq_cpu.c
@@ -0,0 +1,90 @@
+/*
+ * First-level interrupt controller model for Hexagon.
+ *
+ * Copyright (c) 2010-2011 Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+#include <asm/hexagon_vm.h>
+
+static void mask_irq(struct irq_data *data)
+{
+	__vmintop_locdis((long) data->irq);
+}
+
+static void mask_irq_num(unsigned int irq)
+{
+	__vmintop_locdis((long) irq);
+}
+
+static void unmask_irq(struct irq_data *data)
+{
+	__vmintop_locen((long) data->irq);
+}
+
+/*  This is actually all we need for handle_fasteoi_irq  */
+static void eoi_irq(struct irq_data *data)
+{
+	__vmintop_globen((long) data->irq);
+}
+
+/* Power mamangement wake call. We don't need this, however,
+ * if this is absent, then an -ENXIO error is returned to the
+ * msm_serial driver, and it fails to correctly initialize.
+ * This is a bug in the msm_serial driver, but, for now, we
+ * work around it here, by providing this bogus handler.
+ * XXX FIXME!!! remove this when msm_serial is fixed.
+ */
+static int set_wake(struct irq_data *data, unsigned int on)
+{
+	return 0;
+}
+
+static struct irq_chip hexagon_irq_chip = {
+	.name		= "HEXAGON",
+	.irq_mask	= mask_irq,
+	.irq_unmask	= unmask_irq,
+	.irq_set_wake	= set_wake,
+	.irq_eoi	= eoi_irq
+};
+
+/**
+ * The hexagon core comes with a first-level interrupt controller
+ * with 32 total possible interrupts.  When the core is embedded
+ * into different systems/platforms, it is typically wrapped by
+ * macro cells that provide one or more second-level interrupt
+ * controllers that are cascaded into one or more of the first-level
+ * interrupts handled here. The precise wiring of these other
+ * irqs varies from platform to platform, and are set up & configured
+ * in the platform-specific files.
+ *
+ * The first-level interrupt controller is wrapped by the VM, which
+ * virtualizes the interrupt controller for us.  It provides a very
+ * simple, fast & efficient API, and so the fasteoi handler is
+ * appropriate for this case.
+ */
+void __init init_IRQ(void)
+{
+	int irq;
+
+	for (irq = 0; irq < HEXAGON_CPUINTS; irq++) {
+		mask_irq_num(irq);
+		irq_set_chip_and_handler(irq, &hexagon_irq_chip,
+						 handle_fasteoi_irq);
+	}
+}
diff --git a/arch/hexagon/kernel/kgdb.c b/arch/hexagon/kernel/kgdb.c
new file mode 100644
index 0000000..fe4aa1b
--- /dev/null
+++ b/arch/hexagon/kernel/kgdb.c
@@ -0,0 +1,254 @@
+/*
+ * arch/hexagon/kernel/kgdb.c - Hexagon KGDB Support
+ *
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/kdebug.h>
+#include <linux/kgdb.h>
+
+/* All registers are 4 bytes, for now */
+#define GDB_SIZEOF_REG 4
+
+/* The register names are used during printing of the regs;
+ * Keep these at three letters to pretty-print. */
+struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = {
+	{ " r0", GDB_SIZEOF_REG, offsetof(struct pt_regs, r00)},
+	{ " r1", GDB_SIZEOF_REG, offsetof(struct pt_regs, r01)},
+	{ " r2", GDB_SIZEOF_REG, offsetof(struct pt_regs, r02)},
+	{ " r3", GDB_SIZEOF_REG, offsetof(struct pt_regs, r03)},
+	{ " r4", GDB_SIZEOF_REG, offsetof(struct pt_regs, r04)},
+	{ " r5", GDB_SIZEOF_REG, offsetof(struct pt_regs, r05)},
+	{ " r6", GDB_SIZEOF_REG, offsetof(struct pt_regs, r06)},
+	{ " r7", GDB_SIZEOF_REG, offsetof(struct pt_regs, r07)},
+	{ " r8", GDB_SIZEOF_REG, offsetof(struct pt_regs, r08)},
+	{ " r9", GDB_SIZEOF_REG, offsetof(struct pt_regs, r09)},
+	{ "r10", GDB_SIZEOF_REG, offsetof(struct pt_regs, r10)},
+	{ "r11", GDB_SIZEOF_REG, offsetof(struct pt_regs, r11)},
+	{ "r12", GDB_SIZEOF_REG, offsetof(struct pt_regs, r12)},
+	{ "r13", GDB_SIZEOF_REG, offsetof(struct pt_regs, r13)},
+	{ "r14", GDB_SIZEOF_REG, offsetof(struct pt_regs, r14)},
+	{ "r15", GDB_SIZEOF_REG, offsetof(struct pt_regs, r15)},
+	{ "r16", GDB_SIZEOF_REG, offsetof(struct pt_regs, r16)},
+	{ "r17", GDB_SIZEOF_REG, offsetof(struct pt_regs, r17)},
+	{ "r18", GDB_SIZEOF_REG, offsetof(struct pt_regs, r18)},
+	{ "r19", GDB_SIZEOF_REG, offsetof(struct pt_regs, r19)},
+	{ "r20", GDB_SIZEOF_REG, offsetof(struct pt_regs, r20)},
+	{ "r21", GDB_SIZEOF_REG, offsetof(struct pt_regs, r21)},
+	{ "r22", GDB_SIZEOF_REG, offsetof(struct pt_regs, r22)},
+	{ "r23", GDB_SIZEOF_REG, offsetof(struct pt_regs, r23)},
+	{ "r24", GDB_SIZEOF_REG, offsetof(struct pt_regs, r24)},
+	{ "r25", GDB_SIZEOF_REG, offsetof(struct pt_regs, r25)},
+	{ "r26", GDB_SIZEOF_REG, offsetof(struct pt_regs, r26)},
+	{ "r27", GDB_SIZEOF_REG, offsetof(struct pt_regs, r27)},
+	{ "r28", GDB_SIZEOF_REG, offsetof(struct pt_regs, r28)},
+	{ "r29", GDB_SIZEOF_REG, offsetof(struct pt_regs, r29)},
+	{ "r30", GDB_SIZEOF_REG, offsetof(struct pt_regs, r30)},
+	{ "r31", GDB_SIZEOF_REG, offsetof(struct pt_regs, r31)},
+
+	{ "usr", GDB_SIZEOF_REG, offsetof(struct pt_regs, usr)},
+	{ "preds", GDB_SIZEOF_REG, offsetof(struct pt_regs, preds)},
+	{ " m0", GDB_SIZEOF_REG, offsetof(struct pt_regs, m0)},
+	{ " m1", GDB_SIZEOF_REG, offsetof(struct pt_regs, m1)},
+	{ "sa0", GDB_SIZEOF_REG, offsetof(struct pt_regs, sa0)},
+	{ "sa1", GDB_SIZEOF_REG, offsetof(struct pt_regs, sa1)},
+	{ "lc0", GDB_SIZEOF_REG, offsetof(struct pt_regs, lc0)},
+	{ "lc1", GDB_SIZEOF_REG, offsetof(struct pt_regs, lc1)},
+	{ " gp", GDB_SIZEOF_REG, offsetof(struct pt_regs, gp)},
+	{ "ugp", GDB_SIZEOF_REG, offsetof(struct pt_regs, ugp)},
+	{ "psp", GDB_SIZEOF_REG, offsetof(struct pt_regs, hvmer.vmpsp)},
+	{ "elr", GDB_SIZEOF_REG, offsetof(struct pt_regs, hvmer.vmel)},
+	{ "est", GDB_SIZEOF_REG, offsetof(struct pt_regs, hvmer.vmest)},
+	{ "badva", GDB_SIZEOF_REG, offsetof(struct pt_regs, hvmer.vmbadva)},
+	{ "restart_r0", GDB_SIZEOF_REG, offsetof(struct pt_regs, restart_r0)},
+	{ "syscall_nr", GDB_SIZEOF_REG, offsetof(struct pt_regs, syscall_nr)},
+};
+
+struct kgdb_arch arch_kgdb_ops = {
+	/* trap0(#0xDB) 0x0cdb0054 */
+	.gdb_bpt_instr = {0x54, 0x00, 0xdb, 0x0c},
+};
+
+char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
+{
+	if (regno >= DBG_MAX_REG_NUM || regno < 0)
+		return NULL;
+
+	*((unsigned long *) mem) = *((unsigned long *) ((void *)regs +
+		dbg_reg_def[regno].offset));
+
+	return dbg_reg_def[regno].name;
+}
+
+int dbg_set_reg(int regno, void *mem, struct pt_regs *regs)
+{
+	if (regno >= DBG_MAX_REG_NUM || regno < 0)
+		return -EINVAL;
+
+	*((unsigned long *) ((void *)regs + dbg_reg_def[regno].offset)) =
+		*((unsigned long *) mem);
+
+	return 0;
+}
+
+void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
+{
+	instruction_pointer(regs) = pc;
+}
+
+#ifdef CONFIG_SMP
+
+/**
+ * kgdb_roundup_cpus - Get other CPUs into a holding pattern
+ * @flags: Current IRQ state
+ *
+ * On SMP systems, we need to get the attention of the other CPUs
+ * and get them be in a known state.  This should do what is needed
+ * to get the other CPUs to call kgdb_wait(). Note that on some arches,
+ * the NMI approach is not used for rounding up all the CPUs. For example,
+ * in case of MIPS, smp_call_function() is used to roundup CPUs. In
+ * this case, we have to make sure that interrupts are enabled before
+ * calling smp_call_function(). The argument to this function is
+ * the flags that will be used when restoring the interrupts. There is
+ * local_irq_save() call before kgdb_roundup_cpus().
+ *
+ * On non-SMP systems, this is not called.
+ */
+
+static void hexagon_kgdb_nmi_hook(void *ignored)
+{
+	kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs());
+}
+
+void kgdb_roundup_cpus(unsigned long flags)
+{
+	local_irq_enable();
+	smp_call_function(hexagon_kgdb_nmi_hook, NULL, 0);
+	local_irq_disable();
+}
+#endif
+
+
+/*  Not yet working  */
+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs,
+				 struct task_struct *task)
+{
+	struct pt_regs *thread_regs;
+
+	if (task == NULL)
+		return;
+
+	/* Initialize to zero */
+	memset(gdb_regs, 0, NUMREGBYTES);
+
+	/* Otherwise, we have only some registers from switch_to() */
+	thread_regs = task_pt_regs(task);
+	gdb_regs[0] = thread_regs->r00;
+}
+
+/**
+ * kgdb_arch_handle_exception - Handle architecture specific GDB packets.
+ * @vector: The error vector of the exception that happened.
+ * @signo: The signal number of the exception that happened.
+ * @err_code: The error code of the exception that happened.
+ * @remcom_in_buffer: The buffer of the packet we have read.
+ * @remcom_out_buffer: The buffer of %BUFMAX bytes to write a packet into.
+ * @regs: The &struct pt_regs of the current process.
+ *
+ * This function MUST handle the 'c' and 's' command packets,
+ * as well packets to set / remove a hardware breakpoint, if used.
+ * If there are additional packets which the hardware needs to handle,
+ * they are handled here.  The code should return -1 if it wants to
+ * process more packets, and a %0 or %1 if it wants to exit from the
+ * kgdb callback.
+ *
+ * Not yet working.
+ */
+int kgdb_arch_handle_exception(int vector, int signo, int err_code,
+			       char *remcom_in_buffer, char *remcom_out_buffer,
+			       struct pt_regs *linux_regs)
+{
+	switch (remcom_in_buffer[0]) {
+	case 's':
+	case 'c':
+		return 0;
+	}
+	/* Stay in the debugger. */
+	return -1;
+}
+
+static int __kgdb_notify(struct die_args *args, unsigned long cmd)
+{
+	/* cpu roundup */
+	if (atomic_read(&kgdb_active) != -1) {
+		kgdb_nmicallback(smp_processor_id(), args->regs);
+		return NOTIFY_STOP;
+	}
+
+	if (user_mode(args->regs))
+		return NOTIFY_DONE;
+
+	if (kgdb_handle_exception(args->trapnr & 0xff, args->signr, args->err,
+				    args->regs))
+		return NOTIFY_DONE;
+
+	return NOTIFY_STOP;
+}
+
+static int
+kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr)
+{
+	unsigned long flags;
+	int ret;
+
+	local_irq_save(flags);
+	ret = __kgdb_notify(ptr, cmd);
+	local_irq_restore(flags);
+
+	return ret;
+}
+
+static struct notifier_block kgdb_notifier = {
+	.notifier_call = kgdb_notify,
+
+	/*
+	 * Lowest-prio notifier priority, we want to be notified last:
+	 */
+	.priority = -INT_MAX,
+};
+
+/**
+ * kgdb_arch_init - Perform any architecture specific initalization.
+ *
+ * This function will handle the initalization of any architecture
+ * specific callbacks.
+ */
+int kgdb_arch_init(void)
+{
+	return register_die_notifier(&kgdb_notifier);
+}
+
+/**
+ * kgdb_arch_exit - Perform any architecture specific uninitalization.
+ *
+ * This function will handle the uninitalization of any architecture
+ * specific callbacks, for dynamic registration and unregistration.
+ */
+void kgdb_arch_exit(void)
+{
+	unregister_die_notifier(&kgdb_notifier);
+}
diff --git a/arch/hexagon/kernel/module.c b/arch/hexagon/kernel/module.c
new file mode 100644
index 0000000..61a76ba
--- /dev/null
+++ b/arch/hexagon/kernel/module.c
@@ -0,0 +1,162 @@
+/*
+ * Kernel module loader for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <asm/module.h>
+#include <linux/elf.h>
+#include <linux/module.h>
+#include <linux/moduleloader.h>
+#include <linux/vmalloc.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(fmt , ...)
+#endif
+
+/*
+ * module_frob_arch_sections - tweak got/plt sections.
+ * @hdr - pointer to elf header
+ * @sechdrs - pointer to elf load section headers
+ * @secstrings - symbol names
+ * @mod - pointer to module
+ */
+int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
+				char *secstrings,
+				struct module *mod)
+{
+	unsigned int i;
+	int found = 0;
+
+	/* Look for .plt and/or .got.plt and/or .init.plt sections */
+	for (i = 0; i < hdr->e_shnum; i++) {
+		DEBUGP("Section %d is %s\n", i,
+		       secstrings + sechdrs[i].sh_name);
+		if (strcmp(secstrings + sechdrs[i].sh_name, ".plt") == 0)
+			found = i+1;
+		if (strcmp(secstrings + sechdrs[i].sh_name, ".got.plt") == 0)
+			found = i+1;
+		if (strcmp(secstrings + sechdrs[i].sh_name, ".rela.plt") == 0)
+			found = i+1;
+	}
+
+	/* At this time, we don't support modules comiled with -shared */
+	if (found) {
+		printk(KERN_WARNING
+			"Module '%s' contains unexpected .plt/.got sections.\n",
+			mod->name);
+		/*  return -ENOEXEC;  */
+	}
+
+	return 0;
+}
+
+/*
+ * apply_relocate_add - perform rela relocations.
+ * @sechdrs - pointer to section headers
+ * @strtab - some sort of start address?
+ * @symindex - symbol index offset or something?
+ * @relsec - address to relocate to?
+ * @module - pointer to module
+ *
+ * Perform rela relocations.
+ */
+int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
+			unsigned int symindex, unsigned int relsec,
+			struct module *module)
+{
+	unsigned int i;
+	Elf32_Sym *sym;
+	uint32_t *location;
+	uint32_t value;
+	unsigned int nrelocs = sechdrs[relsec].sh_size / sizeof(Elf32_Rela);
+	Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
+	Elf32_Word sym_info = sechdrs[relsec].sh_info;
+	Elf32_Sym *sym_base = (Elf32_Sym *) sechdrs[symindex].sh_addr;
+	void *loc_base = (void *) sechdrs[sym_info].sh_addr;
+
+	DEBUGP("Applying relocations in section %u to section %u base=%p\n",
+	       relsec, sym_info, loc_base);
+
+	for (i = 0; i < nrelocs; i++) {
+
+		/* Symbol to relocate */
+		sym = sym_base + ELF32_R_SYM(rela[i].r_info);
+
+		/* Where to make the change */
+		location = loc_base + rela[i].r_offset;
+
+		/* `Everything is relative'. */
+		value = sym->st_value + rela[i].r_addend;
+
+		DEBUGP("%d: value=%08x loc=%p reloc=%d symbol=%s\n",
+		       i, value, location, ELF32_R_TYPE(rela[i].r_info),
+		       sym->st_name ?
+		       &strtab[sym->st_name] : "(anonymous)");
+
+		switch (ELF32_R_TYPE(rela[i].r_info)) {
+		case R_HEXAGON_B22_PCREL: {
+			int dist = (int)(value - (uint32_t)location);
+			if ((dist < -0x00800000) ||
+			    (dist >= 0x00800000)) {
+				printk(KERN_ERR
+				       "%s: %s: %08x=%08x-%08x %s\n",
+				       module->name,
+				       "R_HEXAGON_B22_PCREL reloc out of range",
+				       dist, value, (uint32_t)location,
+				       sym->st_name ?
+				       &strtab[sym->st_name] : "(anonymous)");
+				return -ENOEXEC;
+			}
+			DEBUGP("B22_PCREL contents: %08X.\n", *location);
+			*location &= ~0x01ff3fff;
+			*location |= 0x00003fff & dist;
+			*location |= 0x01ff0000 & (dist<<2);
+			DEBUGP("Contents after reloc: %08x\n", *location);
+			break;
+		}
+		case R_HEXAGON_HI16:
+			value = (value>>16) & 0xffff;
+			/* fallthrough */
+		case R_HEXAGON_LO16:
+			*location &= ~0x00c03fff;
+			*location |= value & 0x3fff;
+			*location |= (value & 0xc000) << 8;
+			break;
+		case R_HEXAGON_32:
+			*location = value;
+			break;
+		case R_HEXAGON_32_PCREL:
+			*location = value - (uint32_t)location;
+			break;
+		case R_HEXAGON_PLT_B22_PCREL:
+		case R_HEXAGON_GOTOFF_LO16:
+		case R_HEXAGON_GOTOFF_HI16:
+			printk(KERN_ERR "%s: GOT/PLT relocations unsupported\n",
+			       module->name);
+			return -ENOEXEC;
+		default:
+			printk(KERN_ERR "%s: unknown relocation: %u\n",
+			       module->name,
+			       ELF32_R_TYPE(rela[i].r_info));
+			return -ENOEXEC;
+		}
+	}
+	return 0;
+}
diff --git a/arch/hexagon/kernel/process.c b/arch/hexagon/kernel/process.c
new file mode 100644
index 0000000..18c4f0b
--- /dev/null
+++ b/arch/hexagon/kernel/process.c
@@ -0,0 +1,279 @@
+/*
+ * Process creation support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/tick.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+
+/*
+ * Kernel thread creation.  The desired kernel function is "wrapped"
+ * in the kernel_thread_helper function, which does cleanup
+ * afterwards.
+ */
+static void __noreturn kernel_thread_helper(void *arg, int (*fn)(void *))
+{
+	do_exit(fn(arg));
+}
+
+int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
+{
+	struct pt_regs regs;
+
+	memset(&regs, 0, sizeof(regs));
+	/*
+	 * Yes, we're exploting illicit knowledge of the ABI here.
+	 */
+	regs.r00 = (unsigned long) arg;
+	regs.r01 = (unsigned long) fn;
+	pt_set_elr(&regs, (unsigned long)kernel_thread_helper);
+	pt_set_kmode(&regs);
+
+	return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
+}
+EXPORT_SYMBOL(kernel_thread);
+
+/*
+ * Program thread launch.  Often defined as a macro in processor.h,
+ * but we're shooting for a small footprint and it's not an inner-loop
+ * performance-critical operation.
+ *
+ * The Hexagon ABI specifies that R28 is zero'ed before program launch,
+ * so that gets automatically done here.  If we ever stop doing that here,
+ * we'll probably want to define the ELF_PLAT_INIT macro.
+ */
+void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp)
+{
+	/* Set to run with user-mode data segmentation */
+	set_fs(USER_DS);
+	/* We want to zero all data-containing registers. Is this overkill? */
+	memset(regs, 0, sizeof(*regs));
+	/* We might want to also zero all Processor registers here */
+	pt_set_usermode(regs);
+	pt_set_elr(regs, pc);
+	pt_set_rte_sp(regs, sp);
+}
+
+/*
+ *  Spin, or better still, do a hardware or VM wait instruction
+ *  If hardware or VM offer wait termination even though interrupts
+ *  are disabled.
+ */
+static void default_idle(void)
+{
+	__vmwait();
+}
+
+void (*idle_sleep)(void) = default_idle;
+
+void cpu_idle(void)
+{
+	while (1) {
+		tick_nohz_stop_sched_tick(1);
+		local_irq_disable();
+		while (!need_resched()) {
+			idle_sleep();
+			/*  interrupts wake us up, but aren't serviced  */
+			local_irq_enable();	/* service interrupt   */
+			local_irq_disable();
+		}
+		local_irq_enable();
+		tick_nohz_restart_sched_tick();
+		schedule();
+	}
+}
+
+/*
+ *  Return saved PC of a blocked thread
+ */
+unsigned long thread_saved_pc(struct task_struct *tsk)
+{
+	return 0;
+}
+
+/*
+ * Copy architecture-specific thread state
+ */
+int copy_thread(unsigned long clone_flags, unsigned long usp,
+		unsigned long unused, struct task_struct *p,
+		struct pt_regs *regs)
+{
+	struct thread_info *ti = task_thread_info(p);
+	struct hexagon_switch_stack *ss;
+	struct pt_regs *childregs;
+	asmlinkage void ret_from_fork(void);
+
+	childregs = (struct pt_regs *) (((unsigned long) ti + THREAD_SIZE) -
+					sizeof(*childregs));
+
+	memcpy(childregs, regs, sizeof(*childregs));
+	ti->regs = childregs;
+
+	/*
+	 * Establish kernel stack pointer and initial PC for new thread
+	 */
+	ss = (struct hexagon_switch_stack *) ((unsigned long) childregs -
+						    sizeof(*ss));
+	ss->lr = (unsigned long)ret_from_fork;
+	p->thread.switch_sp = ss;
+
+	/* If User mode thread, set pt_reg stack pointer as per parameter */
+	if (user_mode(childregs)) {
+		pt_set_rte_sp(childregs, usp);
+
+		/* Child sees zero return value */
+		childregs->r00 = 0;
+
+		/*
+		 * The clone syscall has the C signature:
+		 * int [r0] clone(int flags [r0],
+		 *           void *child_frame [r1],
+		 *           void *parent_tid [r2],
+		 *           void *child_tid [r3],
+		 *           void *thread_control_block [r4]);
+		 * ugp is used to provide TLS support.
+		 */
+		if (clone_flags & CLONE_SETTLS)
+			childregs->ugp = childregs->r04;
+
+		/*
+		 * Parent sees new pid -- not necessary, not even possible at
+		 * this point in the fork process
+		 * Might also want to set things like ti->addr_limit
+		 */
+	} else {
+		/*
+		 * If kernel thread, resume stack is kernel stack base.
+		 * Note that this is pointer arithmetic on pt_regs *
+		 */
+		pt_set_rte_sp(childregs, (unsigned long)(childregs + 1));
+		/*
+		 * We need the current thread_info fast path pointer
+		 * set up in pt_regs.  The register to be used is
+		 * parametric for assembler code, but the mechanism
+		 * doesn't drop neatly into C.  Needs to be fixed.
+		 */
+		childregs->THREADINFO_REG = (unsigned long) ti;
+	}
+
+	/*
+	 * thread_info pointer is pulled out of task_struct "stack"
+	 * field on switch_to.
+	 */
+	p->stack = (void *)ti;
+
+	return 0;
+}
+
+/*
+ * Release any architecture-specific resources locked by thread
+ */
+void release_thread(struct task_struct *dead_task)
+{
+}
+
+/*
+ * Free any architecture-specific thread data structures, etc.
+ */
+void exit_thread(void)
+{
+}
+
+/*
+ * Some archs flush debug and FPU info here
+ */
+void flush_thread(void)
+{
+}
+
+/*
+ * The "wait channel" terminology is archaic, but what we want
+ * is an identification of the point at which the scheduler
+ * was invoked by a blocked thread.
+ */
+unsigned long get_wchan(struct task_struct *p)
+{
+	unsigned long fp, pc;
+	unsigned long stack_page;
+	int count = 0;
+	if (!p || p == current || p->state == TASK_RUNNING)
+		return 0;
+
+	stack_page = (unsigned long)task_stack_page(p);
+	fp = ((struct hexagon_switch_stack *)p->thread.switch_sp)->fp;
+	do {
+		if (fp < (stack_page + sizeof(struct thread_info)) ||
+			fp >= (THREAD_SIZE - 8 + stack_page))
+			return 0;
+		pc = ((unsigned long *)fp)[1];
+		if (!in_sched_functions(pc))
+			return pc;
+		fp = *(unsigned long *) fp;
+	} while (count++ < 16);
+
+	return 0;
+}
+
+/*
+ * Borrowed from PowerPC -- basically allow smaller kernel stacks if we
+ * go crazy with the page sizes.
+ */
+#if THREAD_SHIFT < PAGE_SHIFT
+
+static struct kmem_cache *thread_info_cache;
+
+struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node)
+{
+	struct thread_info *ti;
+
+	ti = kmem_cache_alloc_node(thread_info_cache, GFP_KERNEL, node);
+	if (unlikely(ti == NULL))
+		return NULL;
+#ifdef CONFIG_DEBUG_STACK_USAGE
+	memset(ti, 0, THREAD_SIZE);
+#endif
+	return ti;
+}
+
+void free_thread_info(struct thread_info *ti)
+{
+	kmem_cache_free(thread_info_cache, ti);
+}
+
+/*  Weak symbol; called by init/main.c  */
+
+void thread_info_cache_init(void)
+{
+	thread_info_cache = kmem_cache_create("thread_info", THREAD_SIZE,
+					      THREAD_SIZE, 0, NULL);
+	BUG_ON(thread_info_cache == NULL);
+}
+
+#endif /* THREAD_SHIFT < PAGE_SHIFT */
+
+/*
+ * Required placeholder.
+ */
+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
+{
+	return 0;
+}
diff --git a/arch/hexagon/kernel/ptrace.c b/arch/hexagon/kernel/ptrace.c
new file mode 100644
index 0000000..bea3f08
--- /dev/null
+++ b/arch/hexagon/kernel/ptrace.c
@@ -0,0 +1,180 @@
+/*
+ * Ptrace support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <generated/compile.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/regset.h>
+#include <linux/user.h>
+
+#include <asm/system.h>
+#include <asm/user.h>
+
+static int genregs_get(struct task_struct *target,
+		   const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   void *kbuf, void __user *ubuf)
+{
+	int ret;
+	unsigned int dummy;
+	struct pt_regs *regs = task_pt_regs(target);
+
+
+	if (!regs)
+		return -EIO;
+
+	/* The general idea here is that the copyout must happen in
+	 * exactly the same order in which the userspace expects these
+	 * regs. Now, the sequence in userspace does not match the
+	 * sequence in the kernel, so everything past the 32 gprs
+	 * happens one at a time.
+	 */
+	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				  &regs->r00, 0, 32*sizeof(unsigned long));
+
+#define ONEXT(KPT_REG, USR_REG) \
+	if (!ret) \
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, \
+			KPT_REG, offsetof(struct user_regs_struct, USR_REG), \
+			offsetof(struct user_regs_struct, USR_REG) + \
+				 sizeof(unsigned long));
+
+	/* Must be exactly same sequence as struct user_regs_struct */
+	ONEXT(&regs->sa0, sa0);
+	ONEXT(&regs->lc0, lc0);
+	ONEXT(&regs->sa1, sa1);
+	ONEXT(&regs->lc1, lc1);
+	ONEXT(&regs->m0, m0);
+	ONEXT(&regs->m1, m1);
+	ONEXT(&regs->usr, usr);
+	ONEXT(&regs->preds, p3_0);
+	ONEXT(&regs->gp, gp);
+	ONEXT(&regs->ugp, ugp);
+	ONEXT(&pt_elr(regs), pc);
+	dummy = pt_cause(regs);
+	ONEXT(&dummy, cause);
+	ONEXT(&pt_badva(regs), badva);
+
+	/* Pad the rest with zeros, if needed */
+	if (!ret)
+		ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+					offsetof(struct user_regs_struct, pad1), -1);
+	return ret;
+}
+
+static int genregs_set(struct task_struct *target,
+		   const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   const void *kbuf, const void __user *ubuf)
+{
+	int ret;
+	unsigned long bucket;
+	struct pt_regs *regs = task_pt_regs(target);
+
+	if (!regs)
+		return -EIO;
+
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				 &regs->r00, 0, 32*sizeof(unsigned long));
+
+#define INEXT(KPT_REG, USR_REG) \
+	if (!ret) \
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, \
+			KPT_REG, offsetof(struct user_regs_struct, USR_REG), \
+			offsetof(struct user_regs_struct, USR_REG) + \
+				sizeof(unsigned long));
+
+	/* Must be exactly same sequence as struct user_regs_struct */
+	INEXT(&regs->sa0, sa0);
+	INEXT(&regs->lc0, lc0);
+	INEXT(&regs->sa1, sa1);
+	INEXT(&regs->lc1, lc1);
+	INEXT(&regs->m0, m0);
+	INEXT(&regs->m1, m1);
+	INEXT(&regs->usr, usr);
+	INEXT(&regs->preds, p3_0);
+	INEXT(&regs->gp, gp);
+	INEXT(&regs->ugp, ugp);
+	INEXT(&pt_elr(regs), pc);
+
+	/* CAUSE and BADVA aren't writeable. */
+	INEXT(&bucket, cause);
+	INEXT(&bucket, badva);
+
+	/* Ignore the rest, if needed */
+	if (!ret)
+		ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+					offsetof(struct user_regs_struct, pad1), -1);
+
+	if (ret)
+		return ret;
+
+	/*
+	 * This is special; SP is actually restored by the VM via the
+	 * special event record which is set by the special trap.
+	 */
+	regs->hvmer.vmpsp = regs->r29;
+	return 0;
+}
+
+enum hexagon_regset {
+	REGSET_GENERAL,
+};
+
+static const struct user_regset hexagon_regsets[] = {
+	[REGSET_GENERAL] = {
+		.core_note_type = NT_PRSTATUS,
+		.n = ELF_NGREG,
+		.size = sizeof(unsigned long),
+		.align = sizeof(unsigned long),
+		.get = genregs_get,
+		.set = genregs_set,
+	},
+};
+
+static const struct user_regset_view hexagon_user_view = {
+	.name = UTS_MACHINE,
+	.e_machine = ELF_ARCH,
+	.ei_osabi = ELF_OSABI,
+	.regsets = hexagon_regsets,
+	.n = ARRAY_SIZE(hexagon_regsets)
+};
+
+const struct user_regset_view *task_user_regset_view(struct task_struct *task)
+{
+	return &hexagon_user_view;
+}
+
+void ptrace_disable(struct task_struct *child)
+{
+	/* Boilerplate - resolves to null inline if no HW single-step */
+	user_disable_single_step(child);
+}
+
+long arch_ptrace(struct task_struct *child, long request,
+		 unsigned long addr, unsigned long data)
+{
+	return ptrace_request(child, request, addr, data);
+}
diff --git a/arch/hexagon/kernel/reset.c b/arch/hexagon/kernel/reset.c
new file mode 100644
index 0000000..4d72fc5
--- /dev/null
+++ b/arch/hexagon/kernel/reset.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/smp.h>
+#include <asm/hexagon_vm.h>
+
+void machine_power_off(void)
+{
+	smp_send_stop();
+	__vmstop();
+}
+
+void machine_halt(void)
+{
+}
+
+void machine_restart(char *cmd)
+{
+}
+
+void pm_power_off(void)
+{
+}
diff --git a/arch/hexagon/kernel/setup.c b/arch/hexagon/kernel/setup.c
new file mode 100644
index 0000000..1202f78
--- /dev/null
+++ b/arch/hexagon/kernel/setup.c
@@ -0,0 +1,145 @@
+/*
+ * Arch related setup for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/mmzone.h>
+#include <linux/mm.h>
+#include <linux/seq_file.h>
+#include <linux/console.h>
+#include <linux/of_fdt.h>
+#include <asm/io.h>
+#include <asm/sections.h>
+#include <asm/setup.h>
+#include <asm/processor.h>
+#include <asm/hexagon_vm.h>
+#include <asm/vm_mmu.h>
+#include <asm/time.h>
+#ifdef CONFIG_OF
+#include <asm/prom.h>
+#endif
+
+char cmd_line[COMMAND_LINE_SIZE];
+static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
+
+int on_simulator;
+
+void __cpuinit calibrate_delay(void)
+{
+	loops_per_jiffy = thread_freq_mhz * 1000000 / HZ;
+}
+
+/*
+ * setup_arch -  high level architectural setup routine
+ * @cmdline_p: pointer to pointer to command-line arguments
+ */
+
+void __init setup_arch(char **cmdline_p)
+{
+	char *p = &external_cmdline_buffer;
+
+	/*
+	 * These will eventually be pulled in via either some hypervisor
+	 * or devicetree description.  Hardwiring for now.
+	 */
+	pcycle_freq_mhz = 600;
+	thread_freq_mhz = 100;
+	sleep_clk_freq = 32000;
+
+	/*
+	 * Set up event bindings to handle exceptions and interrupts.
+	 */
+	__vmsetvec(_K_VM_event_vector);
+
+	/*
+	 * Simulator has a few differences from the hardware.
+	 * For now, check uninitialized-but-mapped memory
+	 * prior to invoking setup_arch_memory().
+	 */
+	if (*(int *)((unsigned long)_end + 8) == 0x1f1f1f1f)
+		on_simulator = 1;
+	else
+		on_simulator = 0;
+
+	if (p[0] != '\0')
+		strlcpy(boot_command_line, p, COMMAND_LINE_SIZE);
+	else
+		strlcpy(boot_command_line, default_command_line,
+			COMMAND_LINE_SIZE);
+
+	/*
+	 * boot_command_line and the value set up by setup_arch
+	 * are both picked up by the init code. If no reason to
+	 * make them different, pass the same pointer back.
+	 */
+	strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
+	*cmdline_p = cmd_line;
+
+	parse_early_param();
+
+	setup_arch_memory();
+
+#ifdef CONFIG_SMP
+	smp_start_cpus();
+#endif
+}
+
+/*
+ * Functions for dumping CPU info via /proc
+ * Probably should move to kernel/proc.c or something.
+ */
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+	return *pos < nr_cpu_ids ? (void *)((unsigned long) *pos + 1) : NULL;
+}
+
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	++*pos;
+	return c_start(m, pos);
+}
+
+static void c_stop(struct seq_file *m, void *v)
+{
+}
+
+/*
+ * Eventually this will dump information about
+ * CPU properties like ISA level, TLB size, etc.
+ */
+static int show_cpuinfo(struct seq_file *m, void *v)
+{
+	int cpu = (unsigned long) v - 1;
+
+	seq_printf(m, "processor\t: %d\n", cpu);
+	seq_printf(m, "model name\t: Hexagon Virtual Machine\n");
+	seq_printf(m, "BogoMips\t: %lu.%02lu\n",
+		(loops_per_jiffy * HZ) / 500000,
+		((loops_per_jiffy * HZ) / 5000) % 100);
+	seq_printf(m, "\n");
+	return 0;
+}
+
+const struct seq_operations cpuinfo_op = {
+	.start  = &c_start,
+	.next   = &c_next,
+	.stop   = &c_stop,
+	.show   = &show_cpuinfo,
+};
diff --git a/arch/hexagon/kernel/signal.c b/arch/hexagon/kernel/signal.c
new file mode 100644
index 0000000..b45be31
--- /dev/null
+++ b/arch/hexagon/kernel/signal.c
@@ -0,0 +1,345 @@
+/*
+ * Signal support for Hexagon processor
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/linkage.h>
+#include <linux/syscalls.h>
+#include <linux/freezer.h>
+#include <linux/tracehook.h>
+#include <asm/registers.h>
+#include <asm/thread_info.h>
+#include <asm/unistd.h>
+#include <asm/uaccess.h>
+#include <asm/ucontext.h>
+#include <asm/cacheflush.h>
+#include <asm/signal.h>
+#include <asm/vdso.h>
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+struct rt_sigframe {
+	unsigned long tramp[2];
+	struct siginfo info;
+	struct ucontext uc;
+};
+
+static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+			  size_t frame_size)
+{
+	unsigned long sp = regs->r29;
+
+	/* Switch to signal stack if appropriate */
+	if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
+		sp = current->sas_ss_sp + current->sas_ss_size;
+
+	return (void __user *)((sp - frame_size) & ~(sizeof(long long) - 1));
+}
+
+static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
+{
+	unsigned long tmp;
+	int err = 0;
+
+	err |= copy_to_user(&sc->sc_regs.r0, &regs->r00,
+			    32*sizeof(unsigned long));
+
+	err |= __put_user(regs->sa0, &sc->sc_regs.sa0);
+	err |= __put_user(regs->lc0, &sc->sc_regs.lc0);
+	err |= __put_user(regs->sa1, &sc->sc_regs.sa1);
+	err |= __put_user(regs->lc1, &sc->sc_regs.lc1);
+	err |= __put_user(regs->m0, &sc->sc_regs.m0);
+	err |= __put_user(regs->m1, &sc->sc_regs.m1);
+	err |= __put_user(regs->usr, &sc->sc_regs.usr);
+	err |= __put_user(regs->preds, &sc->sc_regs.p3_0);
+	err |= __put_user(regs->gp, &sc->sc_regs.gp);
+	err |= __put_user(regs->ugp, &sc->sc_regs.ugp);
+
+	tmp = pt_elr(regs); err |= __put_user(tmp, &sc->sc_regs.pc);
+	tmp = pt_cause(regs); err |= __put_user(tmp, &sc->sc_regs.cause);
+	tmp = pt_badva(regs); err |= __put_user(tmp, &sc->sc_regs.badva);
+
+	return err;
+}
+
+static int restore_sigcontext(struct pt_regs *regs,
+			      struct sigcontext __user *sc)
+{
+	unsigned long tmp;
+	int err = 0;
+
+	err |= copy_from_user(&regs->r00, &sc->sc_regs.r0,
+			      32 * sizeof(unsigned long));
+
+	err |= __get_user(regs->sa0, &sc->sc_regs.sa0);
+	err |= __get_user(regs->lc0, &sc->sc_regs.lc0);
+	err |= __get_user(regs->sa1, &sc->sc_regs.sa1);
+	err |= __get_user(regs->lc1, &sc->sc_regs.lc1);
+	err |= __get_user(regs->m0, &sc->sc_regs.m0);
+	err |= __get_user(regs->m1, &sc->sc_regs.m1);
+	err |= __get_user(regs->usr, &sc->sc_regs.usr);
+	err |= __get_user(regs->preds, &sc->sc_regs.p3_0);
+	err |= __get_user(regs->gp, &sc->sc_regs.gp);
+	err |= __get_user(regs->ugp, &sc->sc_regs.ugp);
+
+	err |= __get_user(tmp, &sc->sc_regs.pc); pt_set_elr(regs, tmp);
+
+	return err;
+}
+
+/*
+ * Setup signal stack frame with siginfo structure
+ */
+static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
+			  sigset_t *set,  struct pt_regs *regs)
+{
+	int err = 0;
+	struct rt_sigframe __user *frame;
+	struct hexagon_vdso *vdso = current->mm->context.vdso;
+
+	frame = get_sigframe(ka, regs, sizeof(struct rt_sigframe));
+
+	if (!access_ok(VERIFY_WRITE, frame, sizeof(struct rt_sigframe)))
+		goto	sigsegv;
+
+	if (copy_siginfo_to_user(&frame->info, info))
+		goto	sigsegv;
+
+	/* The on-stack signal trampoline is no longer executed;
+	 * however, the libgcc signal frame unwinding code checks for
+	 * the presence of these two numeric magic values.
+	 */
+	err |= __put_user(0x7800d166, &frame->tramp[0]);
+	err |= __put_user(0x5400c004, &frame->tramp[1]);
+	err |= setup_sigcontext(regs, &frame->uc.uc_mcontext);
+	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+	if (err)
+		goto sigsegv;
+
+	/* Load r0/r1 pair with signumber/siginfo pointer... */
+	regs->r0100 = ((unsigned long long)((unsigned long)&frame->info) << 32)
+		| (unsigned long long)signr;
+	regs->r02 = (unsigned long) &frame->uc;
+	regs->r31 = (unsigned long) vdso->rt_signal_trampoline;
+	pt_psp(regs) = (unsigned long) frame;
+	pt_set_elr(regs, (unsigned long)ka->sa.sa_handler);
+
+	return 0;
+
+sigsegv:
+	force_sigsegv(signr, current);
+	return -EFAULT;
+}
+
+/*
+ * Setup invocation of signal handler
+ */
+static int handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
+			 sigset_t *oldset, struct pt_regs *regs)
+{
+	int rc;
+
+	/*
+	 * If we're handling a signal that aborted a system call,
+	 * set up the error return value before adding the signal
+	 * frame to the stack.
+	 */
+
+	if (regs->syscall_nr >= 0) {
+		switch (regs->r00) {
+		case -ERESTART_RESTARTBLOCK:
+		case -ERESTARTNOHAND:
+			regs->r00 = -EINTR;
+			break;
+		case -ERESTARTSYS:
+			if (!(ka->sa.sa_flags & SA_RESTART)) {
+				regs->r00 = -EINTR;
+				break;
+			}
+			/* Fall through */
+		case -ERESTARTNOINTR:
+			regs->r06 = regs->syscall_nr;
+			pt_set_elr(regs, pt_elr(regs) - 4);
+			regs->r00 = regs->restart_r0;
+			break;
+		default:
+			break;
+		}
+	}
+
+	/*
+	 * Set up the stack frame; not doing the SA_SIGINFO thing.  We
+	 * only set up the rt_frame flavor.
+	 */
+	rc = setup_rt_frame(sig, ka, info, oldset, regs);
+
+	/* If there was an error on setup, no signal was delivered. */
+	if (rc)
+		return rc;
+
+	spin_lock_irq(&current->sighand->siglock);
+	sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
+	if (!(ka->sa.sa_flags & SA_NODEFER))
+		sigaddset(&current->blocked, sig);
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+
+	return 0;
+}
+
+/*
+ * Called from return-from-event code.
+ */
+static void do_signal(struct pt_regs *regs)
+{
+	struct k_sigaction sigact;
+	siginfo_t info;
+	int signo;
+
+	if (!user_mode(regs))
+		return;
+
+	if (try_to_freeze())
+		goto no_signal;
+
+	signo = get_signal_to_deliver(&info, &sigact, regs, NULL);
+
+	if (signo > 0) {
+		sigset_t *oldset;
+
+		if (test_thread_flag(TIF_RESTORE_SIGMASK))
+			oldset = &current->saved_sigmask;
+		else
+			oldset = &current->blocked;
+
+		if (handle_signal(signo, &info, &sigact, oldset, regs) == 0) {
+			/*
+			 * Successful delivery case.  The saved sigmask is
+			 * stored in the signal frame, and will be restored
+			 * by sigreturn.  We can clear the TIF flag.
+			 */
+			clear_thread_flag(TIF_RESTORE_SIGMASK);
+
+			tracehook_signal_handler(signo, &info, &sigact, regs,
+				test_thread_flag(TIF_SINGLESTEP));
+		}
+		return;
+	}
+
+no_signal:
+	/*
+	 * If we came from a system call, handle the restart.
+	 */
+	if (regs->syscall_nr >= 0) {
+		switch (regs->r00) {
+		case -ERESTARTNOHAND:
+		case -ERESTARTSYS:
+		case -ERESTARTNOINTR:
+			regs->r06 = regs->syscall_nr;
+			break;
+		case -ERESTART_RESTARTBLOCK:
+			regs->r06 = __NR_restart_syscall;
+			break;
+		default:
+			goto no_restart;
+		}
+		pt_set_elr(regs, pt_elr(regs) - 4);
+		regs->r00 = regs->restart_r0;
+	}
+
+no_restart:
+	/* If there's no signal to deliver, put the saved sigmask back */
+	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+		clear_thread_flag(TIF_RESTORE_SIGMASK);
+		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+	}
+}
+
+void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
+{
+	if (thread_info_flags & _TIF_SIGPENDING)
+		do_signal(regs);
+
+	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
+		clear_thread_flag(TIF_NOTIFY_RESUME);
+		if (current->replacement_session_keyring)
+			key_replace_session_keyring();
+	}
+}
+
+/*
+ * Architecture-specific wrappers for signal-related system calls
+ */
+asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
+{
+	struct pt_regs *regs = current_thread_info()->regs;
+
+	return do_sigaltstack(uss, uoss, regs->r29);
+}
+
+asmlinkage int sys_rt_sigreturn(void)
+{
+	struct pt_regs *regs = current_thread_info()->regs;
+	struct rt_sigframe __user *frame;
+	sigset_t blocked;
+
+	frame = (struct rt_sigframe __user *)pt_psp(regs);
+	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+		goto badframe;
+	if (__copy_from_user(&blocked, &frame->uc.uc_sigmask, sizeof(blocked)))
+		goto badframe;
+
+	sigdelsetmask(&blocked, ~_BLOCKABLE);
+	spin_lock_irq(&current->sighand->siglock);
+	current->blocked = blocked;
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+
+	if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
+		goto badframe;
+
+	/* Restore the user's stack as well */
+	pt_psp(regs) = regs->r29;
+
+	/*
+	 * Leave a trace in the stack frame that this was a sigreturn.
+	 * If the system call is to replay, we've already restored the
+	 * number in the GPR slot and it will be regenerated on the
+	 * new system call trap entry. Note that if restore_sigcontext()
+	 * did something other than a bulk copy of the pt_regs struct,
+	 * we could avoid this assignment by simply not overwriting
+	 * regs->syscall_nr.
+	 */
+	regs->syscall_nr = __NR_rt_sigreturn;
+
+	/*
+	 * If we were meticulous, we'd only call this if we knew that
+	 * we were actually going to use an alternate stack, and we'd
+	 * consider any error to be fatal.  What we do here, in common
+	 * with many other architectures, is call it blindly and only
+	 * consider the -EFAULT return case to be proof of a problem.
+	 */
+	if (do_sigaltstack(&frame->uc.uc_stack, NULL, pt_psp(regs)) == -EFAULT)
+		goto badframe;
+
+	return 0;
+
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}
diff --git a/arch/hexagon/kernel/smp.c b/arch/hexagon/kernel/smp.c
new file mode 100644
index 0000000..c871a2c
--- /dev/null
+++ b/arch/hexagon/kernel/smp.c
@@ -0,0 +1,276 @@
+/*
+ * SMP support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/percpu.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+
+#include <asm/system.h>  /*  xchg  */
+#include <asm/time.h>    /*  timer_interrupt  */
+#include <asm/hexagon_vm.h>
+
+#define BASE_IPI_IRQ 26
+
+/*
+ * cpu_possible_map needs to be filled out prior to setup_per_cpu_areas
+ * (which is prior to any of our smp_prepare_cpu crap), in order to set
+ * up the...  per_cpu areas.
+ */
+
+struct ipi_data {
+	unsigned long bits;
+};
+
+static DEFINE_PER_CPU(struct ipi_data, ipi_data);
+
+static inline void __handle_ipi(unsigned long *ops, struct ipi_data *ipi,
+				int cpu)
+{
+	unsigned long msg = 0;
+	do {
+		msg = find_next_bit(ops, BITS_PER_LONG, msg+1);
+
+		switch (msg) {
+
+		case IPI_TIMER:
+			ipi_timer();
+			break;
+
+		case IPI_CALL_FUNC:
+			generic_smp_call_function_interrupt();
+			break;
+
+		case IPI_CALL_FUNC_SINGLE:
+			generic_smp_call_function_single_interrupt();
+			break;
+
+		case IPI_CPU_STOP:
+			/*
+			 * call vmstop()
+			 */
+			__vmstop();
+			break;
+
+		case IPI_RESCHEDULE:
+			scheduler_ipi();
+			break;
+		}
+	} while (msg < BITS_PER_LONG);
+}
+
+/*  Used for IPI call from other CPU's to unmask int  */
+void smp_vm_unmask_irq(void *info)
+{
+	__vmintop_locen((long) info);
+}
+
+
+/*
+ * This is based on Alpha's IPI stuff.
+ * Supposed to take (int, void*) as args now.
+ * Specifically, first arg is irq, second is the irq_desc.
+ */
+
+irqreturn_t handle_ipi(int irq, void *desc)
+{
+	int cpu = smp_processor_id();
+	struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
+	unsigned long ops;
+
+	while ((ops = xchg(&ipi->bits, 0)) != 0)
+		__handle_ipi(&ops, ipi, cpu);
+	return IRQ_HANDLED;
+}
+
+void send_ipi(const struct cpumask *cpumask, enum ipi_message_type msg)
+{
+	unsigned long flags;
+	unsigned long cpu;
+	unsigned long retval;
+
+	local_irq_save(flags);
+
+	for_each_cpu(cpu, cpumask) {
+		struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
+
+		set_bit(msg, &ipi->bits);
+		/*  Possible barrier here  */
+		retval = __vmintop_post(BASE_IPI_IRQ+cpu);
+
+		if (retval != 0) {
+			printk(KERN_ERR "interrupt %ld not configured?\n",
+				BASE_IPI_IRQ+cpu);
+		}
+	}
+
+	local_irq_restore(flags);
+}
+
+static struct irqaction ipi_intdesc = {
+	.handler = handle_ipi,
+	.flags = IRQF_TRIGGER_RISING,
+	.name = "ipi_handler"
+};
+
+void __init smp_prepare_boot_cpu(void)
+{
+}
+
+/*
+ * interrupts should already be disabled from the VM
+ * SP should already be correct; need to set THREADINFO_REG
+ * to point to current thread info
+ */
+
+void __cpuinit start_secondary(void)
+{
+	unsigned int cpu;
+	unsigned long thread_ptr;
+
+	/*  Calculate thread_info pointer from stack pointer  */
+	__asm__ __volatile__(
+		"%0 = SP;\n"
+		: "=r" (thread_ptr)
+	);
+
+	thread_ptr = thread_ptr & ~(THREAD_SIZE-1);
+
+	__asm__ __volatile__(
+		QUOTED_THREADINFO_REG " = %0;\n"
+		:
+		: "r" (thread_ptr)
+	);
+
+	/*  Set the memory struct  */
+	atomic_inc(&init_mm.mm_count);
+	current->active_mm = &init_mm;
+
+	cpu = smp_processor_id();
+
+	setup_irq(BASE_IPI_IRQ + cpu, &ipi_intdesc);
+
+	/*  Register the clock_event dummy  */
+	setup_percpu_clockdev();
+
+	printk(KERN_INFO "%s cpu %d\n", __func__, current_thread_info()->cpu);
+
+	set_cpu_online(cpu, true);
+	while (!cpumask_test_cpu(cpu, cpu_active_mask))
+		cpu_relax();
+	local_irq_enable();
+
+	cpu_idle();
+}
+
+
+/*
+ * called once for each present cpu
+ * apparently starts up the CPU and then
+ * maintains control until "cpu_online(cpu)" is set.
+ */
+
+int __cpuinit __cpu_up(unsigned int cpu)
+{
+	struct task_struct *idle;
+	struct thread_info *thread;
+	void *stack_start;
+
+	/*  Create new init task for the CPU  */
+	idle = fork_idle(cpu);
+	if (IS_ERR(idle))
+		panic(KERN_ERR "fork_idle failed\n");
+
+	thread = (struct thread_info *)idle->stack;
+	thread->cpu = cpu;
+
+	/*  Boot to the head.  */
+	stack_start =  ((void *) thread) + THREAD_SIZE;
+	__vmstart(start_secondary, stack_start);
+
+	while (!cpu_isset(cpu, cpu_online_map))
+		barrier();
+
+	return 0;
+}
+
+void __init smp_cpus_done(unsigned int max_cpus)
+{
+}
+
+void __init smp_prepare_cpus(unsigned int max_cpus)
+{
+	int i;
+
+	/*
+	 * should eventually have some sort of machine
+	 * descriptor that has this stuff
+	 */
+
+	/*  Right now, let's just fake it. */
+	for (i = 0; i < max_cpus; i++)
+		cpu_set(i, cpu_present_map);
+
+	/*  Also need to register the interrupts for IPI  */
+	if (max_cpus > 1)
+		setup_irq(BASE_IPI_IRQ, &ipi_intdesc);
+}
+
+void smp_send_reschedule(int cpu)
+{
+	send_ipi(cpumask_of(cpu), IPI_RESCHEDULE);
+}
+
+void smp_send_stop(void)
+{
+	struct cpumask targets;
+	cpumask_copy(&targets, cpu_online_mask);
+	cpumask_clear_cpu(smp_processor_id(), &targets);
+	send_ipi(&targets, IPI_CPU_STOP);
+}
+
+void arch_send_call_function_single_ipi(int cpu)
+{
+	send_ipi(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
+}
+
+void arch_send_call_function_ipi_mask(const struct cpumask *mask)
+{
+	send_ipi(mask, IPI_CALL_FUNC);
+}
+
+int setup_profiling_timer(unsigned int multiplier)
+{
+	return -EINVAL;
+}
+
+void smp_start_cpus(void)
+{
+	int i;
+
+	for (i = 0; i < NR_CPUS; i++)
+		cpu_set(i, cpu_possible_map);
+}
diff --git a/arch/hexagon/kernel/stacktrace.c b/arch/hexagon/kernel/stacktrace.c
new file mode 100644
index 0000000..11c597b
--- /dev/null
+++ b/arch/hexagon/kernel/stacktrace.c
@@ -0,0 +1,66 @@
+/*
+ * Stacktrace support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/sched.h>
+#include <linux/stacktrace.h>
+#include <linux/thread_info.h>
+#include <linux/module.h>
+
+register unsigned long current_frame_pointer asm("r30");
+
+struct stackframe {
+	unsigned long fp;
+	unsigned long rets;
+};
+
+/*
+ * Save stack-backtrace addresses into a stack_trace buffer.
+ */
+void save_stack_trace(struct stack_trace *trace)
+{
+	unsigned long low, high;
+	unsigned long fp;
+	struct stackframe *frame;
+	int skip = trace->skip;
+
+	low = (unsigned long)task_stack_page(current);
+	high = low + THREAD_SIZE;
+	fp = current_frame_pointer;
+
+	while (fp >= low && fp <= (high - sizeof(*frame))) {
+		frame = (struct stackframe *)fp;
+
+		if (skip) {
+			skip--;
+		} else {
+			trace->entries[trace->nr_entries++] = frame->rets;
+			if (trace->nr_entries >= trace->max_entries)
+				break;
+		}
+
+		/*
+		 * The next frame must be at a higher address than the
+		 * current frame.
+		 */
+		low = fp + sizeof(*frame);
+		fp = frame->fp;
+	}
+}
+EXPORT_SYMBOL_GPL(save_stack_trace);
diff --git a/arch/hexagon/kernel/syscall.c b/arch/hexagon/kernel/syscall.c
new file mode 100644
index 0000000..620dd18
--- /dev/null
+++ b/arch/hexagon/kernel/syscall.c
@@ -0,0 +1,90 @@
+/*
+ * Hexagon system calls
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/linkage.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/syscalls.h>
+#include <linux/unistd.h>
+#include <asm/mman.h>
+#include <asm/registers.h>
+
+/*
+ * System calls with architecture-specific wrappers.
+ * See signal.c for signal-related system call wrappers.
+ */
+
+asmlinkage int sys_execve(char __user *ufilename,
+			  const char __user *const __user *argv,
+			  const char __user *const __user *envp)
+{
+	struct pt_regs *pregs = current_thread_info()->regs;
+	char *filename;
+	int retval;
+
+	filename = getname(ufilename);
+	retval = PTR_ERR(filename);
+	if (IS_ERR(filename))
+		return retval;
+
+	retval = do_execve(filename, argv, envp, pregs);
+	putname(filename);
+
+	return retval;
+}
+
+asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
+			 unsigned long parent_tidp, unsigned long child_tidp)
+{
+	struct pt_regs *pregs = current_thread_info()->regs;
+
+	if (!newsp)
+		newsp = pregs->SP;
+	return do_fork(clone_flags, newsp, pregs, 0, (int __user *)parent_tidp,
+		       (int __user *)child_tidp);
+}
+
+/*
+ * Do a system call from the kernel, so as to have a proper pt_regs
+ * and recycle the sys_execvpe infrustructure.
+ */
+int kernel_execve(const char *filename,
+		  const char *const argv[], const char *const envp[])
+{
+	register unsigned long __a0 asm("r0") = (unsigned long) filename;
+	register unsigned long __a1 asm("r1") = (unsigned long) argv;
+	register unsigned long __a2 asm("r2") = (unsigned long) envp;
+	int retval;
+
+	__asm__ volatile(
+		"	R6 = #%4;\n"
+		"	trap0(#1);\n"
+		"	%0 = R0;\n"
+		: "=r" (retval)
+		: "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_execve)
+	);
+
+	return retval;
+}
+EXPORT_SYMBOL(kernel_execve);
diff --git a/arch/hexagon/kernel/syscalltab.c b/arch/hexagon/kernel/syscalltab.c
new file mode 100644
index 0000000..c550f41
--- /dev/null
+++ b/arch/hexagon/kernel/syscalltab.c
@@ -0,0 +1,32 @@
+/*
+ * System call table for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/syscalls.h>
+#include <linux/signal.h>
+#include <linux/unistd.h>
+
+#include <asm/syscall.h>
+
+#undef __SYSCALL
+#define __SYSCALL(nr, call) [nr] = (call),
+
+void *sys_call_table[__NR_syscalls] = {
+#include <asm/unistd.h>
+};
diff --git a/arch/hexagon/kernel/time.c b/arch/hexagon/kernel/time.c
new file mode 100644
index 0000000..6bee15c
--- /dev/null
+++ b/arch/hexagon/kernel/time.c
@@ -0,0 +1,250 @@
+/*
+ * Time related functions for Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/ioport.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#include <asm/timer-regs.h>
+#include <asm/hexagon_vm.h>
+
+/*
+ * For the clocksource we need:
+ *	pcycle frequency (600MHz)
+ * For the loops_per_jiffy we need:
+ *	thread/cpu frequency (100MHz)
+ * And for the timer, we need:
+ *	sleep clock rate
+ */
+
+cycles_t	pcycle_freq_mhz;
+cycles_t	thread_freq_mhz;
+cycles_t	sleep_clk_freq;
+
+static struct resource rtos_timer_resources[] = {
+	{
+		.start	= RTOS_TIMER_REGS_ADDR,
+		.end	= RTOS_TIMER_REGS_ADDR+PAGE_SIZE-1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device rtos_timer_device = {
+	.name		= "rtos_timer",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(rtos_timer_resources),
+	.resource	= rtos_timer_resources,
+};
+
+/*  A lot of this stuff should move into a platform specific section.  */
+struct adsp_hw_timer_struct {
+	u32 match;   /*  Match value  */
+	u32 count;
+	u32 enable;  /*  [1] - CLR_ON_MATCH_EN, [0] - EN  */
+	u32 clear;   /*  one-shot register that clears the count  */
+};
+
+/*  Look for "TCX0" for related constants.  */
+static __iomem struct adsp_hw_timer_struct *rtos_timer;
+
+static cycle_t timer_get_cycles(struct clocksource *cs)
+{
+	return (cycle_t) __vmgettime();
+}
+
+static struct clocksource hexagon_clocksource = {
+	.name		= "pcycles",
+	.rating		= 250,
+	.read		= timer_get_cycles,
+	.mask		= CLOCKSOURCE_MASK(64),
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int set_next_event(unsigned long delta, struct clock_event_device *evt)
+{
+	/*  Assuming the timer will be disabled when we enter here.  */
+
+	iowrite32(1, &rtos_timer->clear);
+	iowrite32(0, &rtos_timer->clear);
+
+	iowrite32(delta, &rtos_timer->match);
+	iowrite32(1 << TIMER_ENABLE, &rtos_timer->enable);
+	return 0;
+}
+
+/*
+ * Sets the mode (periodic, shutdown, oneshot, etc) of a timer.
+ */
+static void set_mode(enum clock_event_mode mode,
+	struct clock_event_device *evt)
+{
+	switch (mode) {
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		/* XXX implement me */
+	default:
+		break;
+	}
+}
+
+#ifdef CONFIG_SMP
+/*  Broadcast mechanism  */
+static void broadcast(const struct cpumask *mask)
+{
+	send_ipi(mask, IPI_TIMER);
+}
+#endif
+
+static struct clock_event_device hexagon_clockevent_dev = {
+	.name		= "clockevent",
+	.features	= CLOCK_EVT_FEAT_ONESHOT,
+	.rating		= 400,
+	.irq		= RTOS_TIMER_INT,
+	.set_next_event = set_next_event,
+	.set_mode	= set_mode,
+#ifdef CONFIG_SMP
+	.broadcast	= broadcast,
+#endif
+};
+
+#ifdef CONFIG_SMP
+static DEFINE_PER_CPU(struct clock_event_device, clock_events);
+
+void setup_percpu_clockdev(void)
+{
+	int cpu = smp_processor_id();
+	struct clock_event_device *ce_dev = &hexagon_clockevent_dev;
+	struct clock_event_device *dummy_clock_dev =
+		&per_cpu(clock_events, cpu);
+
+	memcpy(dummy_clock_dev, ce_dev, sizeof(*dummy_clock_dev));
+	INIT_LIST_HEAD(&dummy_clock_dev->list);
+
+	dummy_clock_dev->features = CLOCK_EVT_FEAT_DUMMY;
+	dummy_clock_dev->cpumask = cpumask_of(cpu);
+	dummy_clock_dev->mode = CLOCK_EVT_MODE_UNUSED;
+
+	clockevents_register_device(dummy_clock_dev);
+}
+
+/*  Called from smp.c for each CPU's timer ipi call  */
+void ipi_timer(void)
+{
+	int cpu = smp_processor_id();
+	struct clock_event_device *ce_dev = &per_cpu(clock_events, cpu);
+
+	ce_dev->event_handler(ce_dev);
+}
+#endif /* CONFIG_SMP */
+
+static irqreturn_t timer_interrupt(int irq, void *devid)
+{
+	struct clock_event_device *ce_dev = &hexagon_clockevent_dev;
+
+	iowrite32(0, &rtos_timer->enable);
+	ce_dev->event_handler(ce_dev);
+
+	return IRQ_HANDLED;
+}
+
+/*  This should also be pulled from devtree  */
+static struct irqaction rtos_timer_intdesc = {
+	.handler = timer_interrupt,
+	.flags = IRQF_TIMER | IRQF_TRIGGER_RISING,
+	.name = "rtos_timer"
+};
+
+/*
+ * time_init_deferred - called by start_kernel to set up timer/clock source
+ *
+ * Install the IRQ handler for the clock, setup timers.
+ * This is done late, as that way, we can use ioremap().
+ *
+ * This runs just before the delay loop is calibrated, and
+ * is used for delay calibration.
+ */
+void __init time_init_deferred(void)
+{
+	struct resource *resource = NULL;
+	struct clock_event_device *ce_dev = &hexagon_clockevent_dev;
+	struct device_node *dn;
+	struct resource r;
+	int err;
+
+	ce_dev->cpumask = cpu_all_mask;
+
+	if (!resource)
+		resource = rtos_timer_device.resource;
+
+	/*  ioremap here means this has to run later, after paging init  */
+	rtos_timer = ioremap(resource->start, resource->end
+		- resource->start + 1);
+
+	if (!rtos_timer) {
+		release_mem_region(resource->start, resource->end
+			- resource->start + 1);
+	}
+	clocksource_register_khz(&hexagon_clocksource, pcycle_freq_mhz * 1000);
+
+	/*  Note: the sim generic RTOS clock is apparently really 18750Hz  */
+
+	/*
+	 * Last arg is some guaranteed seconds for which the conversion will
+	 * work without overflow.
+	 */
+	clockevents_calc_mult_shift(ce_dev, sleep_clk_freq, 4);
+
+	ce_dev->max_delta_ns = clockevent_delta2ns(0x7fffffff, ce_dev);
+	ce_dev->min_delta_ns = clockevent_delta2ns(0xf, ce_dev);
+
+#ifdef CONFIG_SMP
+	setup_percpu_clockdev();
+#endif
+
+	clockevents_register_device(ce_dev);
+	setup_irq(ce_dev->irq, &rtos_timer_intdesc);
+}
+
+void __init time_init(void)
+{
+	late_time_init = time_init_deferred;
+}
+
+/*
+ * This could become parametric or perhaps even computed at run-time,
+ * but for now we take the observed simulator jitter.
+ */
+static long long fudgefactor = 350;  /* Maybe lower if kernel optimized. */
+
+void __udelay(unsigned long usecs)
+{
+	unsigned long long start = __vmgettime();
+	unsigned long long finish = (pcycle_freq_mhz * usecs) - fudgefactor;
+
+	while ((__vmgettime() - start) < finish)
+		cpu_relax(); /*  not sure how this improves readability  */
+}
+EXPORT_SYMBOL(__udelay);
diff --git a/arch/hexagon/kernel/topology.c b/arch/hexagon/kernel/topology.c
new file mode 100644
index 0000000..ba44751
--- /dev/null
+++ b/arch/hexagon/kernel/topology.c
@@ -0,0 +1,52 @@
+/*
+ * CPU topology for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/init.h>
+#include <linux/node.h>
+#include <linux/nodemask.h>
+#include <linux/percpu.h>
+
+/*  Swiped from MIPS.  */
+
+static DEFINE_PER_CPU(struct cpu, cpu_devices);
+
+static int __init topology_init(void)
+{
+	int i, ret;
+
+	for_each_present_cpu(i) {
+
+		/*
+		 * register_cpu takes a per_cpu pointer and
+		 * just points it at another per_cpu struct...
+		 */
+
+		ret = register_cpu(&per_cpu(cpu_devices, i), i);
+		if (ret)
+			printk(KERN_WARNING "topology_init: register_cpu %d "
+			       "failed (%d)\n", i, ret);
+	}
+
+	return 0;
+}
+
+subsys_initcall(topology_init);
diff --git a/arch/hexagon/kernel/trampoline.S b/arch/hexagon/kernel/trampoline.S
new file mode 100644
index 0000000..06c36c0
--- /dev/null
+++ b/arch/hexagon/kernel/trampoline.S
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * Trampoline sequences to be copied onto user stack.
+ * This consumes a little more space than hand-assembling
+ * immediate constants for use in C, but is more portable
+ * to future tweaks to the Hexagon instruction set.
+ */
+
+#include <asm/unistd.h>
+
+/*  Sig trampolines - call sys_sigreturn or sys_rt_sigreturn as appropriate */
+
+/*  plain sigreturn is gone.  */
+
+	.globl __rt_sigtramp_template
+__rt_sigtramp_template:
+	r6 = #__NR_rt_sigreturn;
+	trap0(#1);
diff --git a/arch/hexagon/kernel/traps.c b/arch/hexagon/kernel/traps.c
new file mode 100644
index 0000000..f08857d
--- /dev/null
+++ b/arch/hexagon/kernel/traps.c
@@ -0,0 +1,454 @@
+/*
+ * Kernel traps/events for Hexagon processor
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/kallsyms.h>
+#include <linux/kdebug.h>
+#include <linux/syscalls.h>
+#include <linux/signal.h>
+#include <linux/tracehook.h>
+#include <asm/traps.h>
+#include <asm/vm_fault.h>
+#include <asm/syscall.h>
+#include <asm/registers.h>
+#include <asm/unistd.h>
+#include <asm/sections.h>
+#ifdef CONFIG_KGDB
+# include <linux/kgdb.h>
+#endif
+
+#define TRAP_SYSCALL	1
+#define TRAP_DEBUG	0xdb
+
+void __init trap_init(void)
+{
+}
+
+#ifdef CONFIG_GENERIC_BUG
+/* Maybe should resemble arch/sh/kernel/traps.c ?? */
+int is_valid_bugaddr(unsigned long addr)
+{
+	return 1;
+}
+#endif /* CONFIG_GENERIC_BUG */
+
+static const char *ex_name(int ex)
+{
+	switch (ex) {
+	case HVM_GE_C_XPROT:
+	case HVM_GE_C_XUSER:
+		return "Execute protection fault";
+	case HVM_GE_C_RPROT:
+	case HVM_GE_C_RUSER:
+		return "Read protection fault";
+	case HVM_GE_C_WPROT:
+	case HVM_GE_C_WUSER:
+		return "Write protection fault";
+	case HVM_GE_C_XMAL:
+		return "Misaligned instruction";
+	case HVM_GE_C_RMAL:
+		return "Misaligned data load";
+	case HVM_GE_C_WMAL:
+		return "Misaligned data store";
+	case HVM_GE_C_INVI:
+	case HVM_GE_C_PRIVI:
+		return "Illegal instruction";
+	case HVM_GE_C_BUS:
+		return "Precise bus error";
+	case HVM_GE_C_CACHE:
+		return "Cache error";
+
+	case 0xdb:
+		return "Debugger trap";
+
+	default:
+		return "Unrecognized exception";
+	}
+}
+
+static void do_show_stack(struct task_struct *task, unsigned long *fp,
+			  unsigned long ip)
+{
+	int kstack_depth_to_print = 24;
+	unsigned long offset, size;
+	const char *name = NULL;
+	unsigned long *newfp;
+	unsigned long low, high;
+	char tmpstr[128];
+	char *modname;
+	int i;
+
+	if (task == NULL)
+		task = current;
+
+	printk(KERN_INFO "CPU#%d, %s/%d, Call Trace:\n",
+	       raw_smp_processor_id(), task->comm,
+	       task_pid_nr(task));
+
+	if (fp == NULL) {
+		if (task == current) {
+			asm("%0 = r30" : "=r" (fp));
+		} else {
+			fp = (unsigned long *)
+			     ((struct hexagon_switch_stack *)
+			     task->thread.switch_sp)->fp;
+		}
+	}
+
+	if ((((unsigned long) fp) & 0x3) || ((unsigned long) fp < 0x1000)) {
+		printk(KERN_INFO "-- Corrupt frame pointer %p\n", fp);
+		return;
+	}
+
+	/* Saved link reg is one word above FP */
+	if (!ip)
+		ip = *(fp+1);
+
+	/* Expect kernel stack to be in-bounds */
+	low = (unsigned long)task_stack_page(task);
+	high = low + THREAD_SIZE - 8;
+	low += sizeof(struct thread_info);
+
+	for (i = 0; i < kstack_depth_to_print; i++) {
+
+		name = kallsyms_lookup(ip, &size, &offset, &modname, tmpstr);
+
+		printk(KERN_INFO "[%p] 0x%lx: %s + 0x%lx", fp, ip, name,
+			offset);
+		if (((unsigned long) fp < low) || (high < (unsigned long) fp))
+			printk(KERN_CONT " (FP out of bounds!)");
+		if (modname)
+			printk(KERN_CONT " [%s] ", modname);
+		printk(KERN_CONT "\n");
+
+		newfp = (unsigned long *) *fp;
+
+		if (((unsigned long) newfp) & 0x3) {
+			printk(KERN_INFO "-- Corrupt frame pointer %p\n",
+				newfp);
+			break;
+		}
+
+		/* Attempt to continue past exception. */
+		if (0 == newfp) {
+			struct pt_regs *regs = (struct pt_regs *) (((void *)fp)
+						+ 8);
+
+			if (regs->syscall_nr != -1) {
+				printk(KERN_INFO "-- trap0 -- syscall_nr: %ld",
+					regs->syscall_nr);
+				printk(KERN_CONT "  psp: %lx  elr: %lx\n",
+					 pt_psp(regs), pt_elr(regs));
+				break;
+			} else {
+				/* really want to see more ... */
+				kstack_depth_to_print += 6;
+				printk(KERN_INFO "-- %s (0x%lx)  badva: %lx\n",
+					ex_name(pt_cause(regs)), pt_cause(regs),
+					pt_badva(regs));
+			}
+
+			newfp = (unsigned long *) regs->r30;
+			ip = pt_elr(regs);
+		} else {
+			ip = *(newfp + 1);
+		}
+
+		/* If link reg is null, we are done. */
+		if (ip == 0x0)
+			break;
+
+		/* If newfp isn't larger, we're tracing garbage. */
+		if (newfp > fp)
+			fp = newfp;
+		else
+			break;
+	}
+}
+
+void show_stack(struct task_struct *task, unsigned long *fp)
+{
+	/* Saved link reg is one word above FP */
+	do_show_stack(task, fp, 0);
+}
+
+void dump_stack(void)
+{
+	unsigned long *fp;
+	asm("%0 = r30" : "=r" (fp));
+	show_stack(current, fp);
+}
+EXPORT_SYMBOL(dump_stack);
+
+int die(const char *str, struct pt_regs *regs, long err)
+{
+	static struct {
+		spinlock_t lock;
+		int counter;
+	} die = {
+		.lock = __SPIN_LOCK_UNLOCKED(die.lock),
+		.counter = 0
+	};
+
+	console_verbose();
+	oops_enter();
+
+	spin_lock_irq(&die.lock);
+	bust_spinlocks(1);
+	printk(KERN_EMERG "Oops: %s[#%d]:\n", str, ++die.counter);
+
+	if (notify_die(DIE_OOPS, str, regs, err, pt_cause(regs), SIGSEGV) ==
+	    NOTIFY_STOP)
+		return 1;
+
+	print_modules();
+	show_regs(regs);
+	do_show_stack(current, &regs->r30, pt_elr(regs));
+
+	bust_spinlocks(0);
+	add_taint(TAINT_DIE);
+
+	spin_unlock_irq(&die.lock);
+
+	if (in_interrupt())
+		panic("Fatal exception in interrupt");
+
+	if (panic_on_oops)
+		panic("Fatal exception");
+
+	oops_exit();
+	do_exit(err);
+	return 0;
+}
+
+int die_if_kernel(char *str, struct pt_regs *regs, long err)
+{
+	if (!user_mode(regs))
+		return die(str, regs, err);
+	else
+		return 0;
+}
+
+/*
+ * It's not clear that misaligned fetches are ever recoverable.
+ */
+static void misaligned_instruction(struct pt_regs *regs)
+{
+	die_if_kernel("Misaligned Instruction", regs, 0);
+	force_sig(SIGBUS, current);
+}
+
+/*
+ * Misaligned loads and stores, on the other hand, can be
+ * emulated, and probably should be, some day.  But for now
+ * they will be considered fatal.
+ */
+static void misaligned_data_load(struct pt_regs *regs)
+{
+	die_if_kernel("Misaligned Data Load", regs, 0);
+	force_sig(SIGBUS, current);
+}
+
+static void misaligned_data_store(struct pt_regs *regs)
+{
+	die_if_kernel("Misaligned Data Store", regs, 0);
+	force_sig(SIGBUS, current);
+}
+
+static void illegal_instruction(struct pt_regs *regs)
+{
+	die_if_kernel("Illegal Instruction", regs, 0);
+	force_sig(SIGILL, current);
+}
+
+/*
+ * Precise bus errors may be recoverable with a a retry,
+ * but for now, treat them as irrecoverable.
+ */
+static void precise_bus_error(struct pt_regs *regs)
+{
+	die_if_kernel("Precise Bus Error", regs, 0);
+	force_sig(SIGBUS, current);
+}
+
+/*
+ * If anything is to be done here other than panic,
+ * it will probably be complex and migrate to another
+ * source module.  For now, just die.
+ */
+static void cache_error(struct pt_regs *regs)
+{
+	die("Cache Error", regs, 0);
+}
+
+/*
+ * General exception handler
+ */
+void do_genex(struct pt_regs *regs)
+{
+	/*
+	 * Decode Cause and Dispatch
+	 */
+	switch (pt_cause(regs)) {
+	case HVM_GE_C_XPROT:
+	case HVM_GE_C_XUSER:
+		execute_protection_fault(regs);
+		break;
+	case HVM_GE_C_RPROT:
+	case HVM_GE_C_RUSER:
+		read_protection_fault(regs);
+		break;
+	case HVM_GE_C_WPROT:
+	case HVM_GE_C_WUSER:
+		write_protection_fault(regs);
+		break;
+	case HVM_GE_C_XMAL:
+		misaligned_instruction(regs);
+		break;
+	case HVM_GE_C_RMAL:
+		misaligned_data_load(regs);
+		break;
+	case HVM_GE_C_WMAL:
+		misaligned_data_store(regs);
+		break;
+	case HVM_GE_C_INVI:
+	case HVM_GE_C_PRIVI:
+		illegal_instruction(regs);
+		break;
+	case HVM_GE_C_BUS:
+		precise_bus_error(regs);
+		break;
+	case HVM_GE_C_CACHE:
+		cache_error(regs);
+		break;
+	default:
+		/* Halt and catch fire */
+		panic("Unrecognized exception 0x%lx\n", pt_cause(regs));
+		break;
+	}
+}
+
+/* Indirect system call dispatch */
+long sys_syscall(void)
+{
+	printk(KERN_ERR "sys_syscall invoked!\n");
+	return -ENOSYS;
+}
+
+void do_trap0(struct pt_regs *regs)
+{
+	unsigned long syscallret = 0;
+	syscall_fn syscall;
+
+	switch (pt_cause(regs)) {
+	case TRAP_SYSCALL:
+		/* System call is trap0 #1 */
+
+		/* allow strace to catch syscall args  */
+		if (unlikely(test_thread_flag(TIF_SYSCALL_TRACE) &&
+			tracehook_report_syscall_entry(regs)))
+			return;  /*  return -ENOSYS somewhere?  */
+
+		/* Interrupts should be re-enabled for syscall processing */
+		__vmsetie(VM_INT_ENABLE);
+
+		/*
+		 * System call number is in r6, arguments in r0..r5.
+		 * Fortunately, no Linux syscall has more than 6 arguments,
+		 * and Hexagon ABI passes first 6 arguments in registers.
+		 * 64-bit arguments are passed in odd/even register pairs.
+		 * Fortunately, we have no system calls that take more
+		 * than three arguments with more than one 64-bit value.
+		 * Should that change, we'd need to redesign to copy
+		 * between user and kernel stacks.
+		 */
+		regs->syscall_nr = regs->r06;
+
+		/*
+		 * GPR R0 carries the first parameter, and is also used
+		 * to report the return value.  We need a backup of
+		 * the user's value in case we need to do a late restart
+		 * of the system call.
+		 */
+		regs->restart_r0 = regs->r00;
+
+		if ((unsigned long) regs->syscall_nr >= __NR_syscalls) {
+			regs->r00 = -1;
+		} else {
+			syscall = (syscall_fn)
+				  (sys_call_table[regs->syscall_nr]);
+			syscallret = syscall(regs->r00, regs->r01,
+				   regs->r02, regs->r03,
+				   regs->r04, regs->r05);
+		}
+
+		/*
+		 * If it was a sigreturn system call, don't overwrite
+		 * r0 value in stack frame with return value.
+		 *
+		 * __NR_sigreturn doesn't seem to exist in new unistd.h
+		 */
+
+		if (regs->syscall_nr != __NR_rt_sigreturn)
+			regs->r00 = syscallret;
+
+		/* allow strace to get the syscall return state  */
+		if (unlikely(test_thread_flag(TIF_SYSCALL_TRACE)))
+			tracehook_report_syscall_exit(regs, 0);
+
+		break;
+	case TRAP_DEBUG:
+		/* Trap0 0xdb is debug breakpoint */
+		if (user_mode(regs)) {
+			struct siginfo info;
+
+			info.si_signo = SIGTRAP;
+			info.si_errno = 0;
+			/*
+			 * Some architecures add some per-thread state
+			 * to distinguish between breakpoint traps and
+			 * trace traps.  We may want to do that, and
+			 * set the si_code value appropriately, or we
+			 * may want to use a different trap0 flavor.
+			 */
+			info.si_code = TRAP_BRKPT;
+			info.si_addr = (void __user *) pt_elr(regs);
+			send_sig_info(SIGTRAP, &info, current);
+		} else {
+#ifdef CONFIG_KGDB
+			kgdb_handle_exception(pt_cause(regs), SIGTRAP,
+					      TRAP_BRKPT, regs);
+#endif
+		}
+		break;
+	}
+	/* Ignore other trap0 codes for now, especially 0 (Angel calls) */
+}
+
+/*
+ * Machine check exception handler
+ */
+void do_machcheck(struct pt_regs *regs)
+{
+	/* Halt and catch fire */
+	__vmstop();
+}
diff --git a/arch/hexagon/kernel/vdso.c b/arch/hexagon/kernel/vdso.c
new file mode 100644
index 0000000..16277c3
--- /dev/null
+++ b/arch/hexagon/kernel/vdso.c
@@ -0,0 +1,100 @@
+/*
+ * vDSO implementation for Hexagon
+ *
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/err.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+
+#include <asm/vdso.h>
+
+static struct page *vdso_page;
+
+/* Create a vDSO page holding the signal trampoline.
+ * We want this for a non-executable stack.
+ */
+static int __init vdso_init(void)
+{
+	struct hexagon_vdso *vdso;
+
+	vdso_page = alloc_page(GFP_KERNEL);
+	if (!vdso_page)
+		panic("Cannot allocate vdso");
+
+	vdso = vmap(&vdso_page, 1, 0, PAGE_KERNEL);
+	if (!vdso)
+		panic("Cannot map vdso");
+	clear_page(vdso);
+
+	/* Install the signal trampoline; currently looks like this:
+	 *	r6 = #__NR_rt_sigreturn;
+	 *	trap0(#1);
+	 */
+	vdso->rt_signal_trampoline[0] = __rt_sigtramp_template[0];
+	vdso->rt_signal_trampoline[1] = __rt_sigtramp_template[1];
+
+	vunmap(vdso);
+
+	return 0;
+}
+arch_initcall(vdso_init);
+
+/*
+ * Called from binfmt_elf.  Create a VMA for the vDSO page.
+ */
+int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
+{
+	int ret;
+	unsigned long vdso_base;
+	struct mm_struct *mm = current->mm;
+
+	down_write(&mm->mmap_sem);
+
+	/* Try to get it loaded right near ld.so/glibc. */
+	vdso_base = STACK_TOP;
+
+	vdso_base = get_unmapped_area(NULL, vdso_base, PAGE_SIZE, 0, 0);
+	if (IS_ERR_VALUE(vdso_base)) {
+		ret = vdso_base;
+		goto up_fail;
+	}
+
+	/* MAYWRITE to allow gdb to COW and set breakpoints. */
+	ret = install_special_mapping(mm, vdso_base, PAGE_SIZE,
+				      VM_READ|VM_EXEC|
+				      VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
+				      VM_ALWAYSDUMP,
+				      &vdso_page);
+
+	if (ret)
+		goto up_fail;
+
+	mm->context.vdso = (void *)vdso_base;
+
+up_fail:
+	up_write(&mm->mmap_sem);
+	return ret;
+}
+
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+	if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso)
+		return "[vdso]";
+	return NULL;
+}
diff --git a/arch/hexagon/kernel/vm_entry.S b/arch/hexagon/kernel/vm_entry.S
new file mode 100644
index 0000000..5b99066
--- /dev/null
+++ b/arch/hexagon/kernel/vm_entry.S
@@ -0,0 +1,269 @@
+/*
+ * Event entry/exit for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <asm/asm-offsets.h>  /*  assembly-safer versions of C defines */
+#include <asm/mem-layout.h>   /*  sigh, except for page_offset  */
+#include <asm/hexagon_vm.h>
+#include <asm/thread_info.h>
+
+/*
+ * Entry into guest-mode Linux under Hexagon Virtual Machine.
+ * Stack pointer points to event record - build pt_regs on top of it,
+ * set up a plausible C stack frame, and dispatch to the C handler.
+ * On return, do vmrte virtual instruction with SP where we started.
+ *
+ * VM Spec 0.5 uses a trap to fetch HVM record now.
+ */
+
+/*
+ * Save full register state, while setting up thread_info struct
+ * pointer derived from kernel stack pointer in THREADINFO_REG
+ * register, putting prior thread_info.regs pointer in a callee-save
+ * register (R24, which had better not ever be assigned to THREADINFO_REG),
+ * and updating thread_info.regs to point to current stack frame,
+ * so as to support nested events in kernel mode.
+ *
+ * As this is common code, we set the pt_regs system call number
+ * to -1 for all events.  It will be replaced with the system call
+ * number in the case where we decode a system call (trap0(#1)).
+ */
+
+#define save_pt_regs()\
+	memd(R0 + #_PT_R3130) = R31:30; \
+	{ memw(R0 + #_PT_R2928) = R28; \
+	  R31 = memw(R0 + #_PT_ER_VMPSP); }\
+	{ memw(R0 + #(_PT_R2928 + 4)) = R31; \
+	  R31 = ugp; } \
+	{ memd(R0 + #_PT_R2726) = R27:26; \
+	  R30 = gp ; } \
+	memd(R0 + #_PT_R2524) = R25:24; \
+	memd(R0 + #_PT_R2322) = R23:22; \
+	memd(R0 + #_PT_R2120) = R21:20; \
+	memd(R0 + #_PT_R1918) = R19:18; \
+	memd(R0 + #_PT_R1716) = R17:16; \
+	memd(R0 + #_PT_R1514) = R15:14; \
+	memd(R0 + #_PT_R1312) = R13:12; \
+	{ memd(R0 + #_PT_R1110) = R11:10; \
+	  R15 = lc0; } \
+	{ memd(R0 + #_PT_R0908) = R9:8; \
+	  R14 = sa0; } \
+	{ memd(R0 + #_PT_R0706) = R7:6; \
+	  R13 = lc1; } \
+	{ memd(R0 + #_PT_R0504) = R5:4; \
+	  R12 = sa1; } \
+	{ memd(R0 + #_PT_UGPGP) = R31:30; \
+	  R11 = m1; \
+	  R2.H = #HI(_THREAD_SIZE); } \
+	{ memd(R0 + #_PT_LC0SA0) = R15:14; \
+	  R10 = m0; \
+	  R2.L = #LO(_THREAD_SIZE); } \
+	{ memd(R0 + #_PT_LC1SA1) = R13:12; \
+	  R15 = p3:0; \
+	  R2 = neg(R2); } \
+	{ memd(R0 + #_PT_M1M0) = R11:10; \
+	  R14  = usr; \
+	  R2 = and(R0,R2); } \
+	{ memd(R0 + #_PT_PREDSUSR) =  R15:14; \
+	  THREADINFO_REG = R2; } \
+	{ r24 = memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS); \
+	  memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS) = R0; \
+	  R2 = #-1; } \
+	{ memw(R0 + #_PT_SYSCALL_NR) = R2; \
+	  R30 = #0; }
+
+/*
+ * Restore registers and thread_info.regs state. THREADINFO_REG
+ * is assumed to still be sane, and R24 to have been correctly
+ * preserved. Don't restore R29 (SP) until later.
+ */
+
+#define restore_pt_regs() \
+	{ memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS) = R24; \
+	  R15:14 = memd(R0 + #_PT_PREDSUSR); } \
+	{ R11:10 = memd(R0 + #_PT_M1M0); \
+	  p3:0 = R15; } \
+	{ R13:12 = memd(R0 + #_PT_LC1SA1); \
+	  usr = R14; } \
+	{ R15:14 = memd(R0 + #_PT_LC0SA0); \
+	  m1 = R11; } \
+	{ R3:2 = memd(R0 + #_PT_R0302); \
+	  m0 = R10; } \
+	{ R5:4 = memd(R0 + #_PT_R0504); \
+	  lc1 = R13; } \
+	{ R7:6 = memd(R0 + #_PT_R0706); \
+	  sa1 = R12; } \
+	{ R9:8 = memd(R0 + #_PT_R0908); \
+	  lc0 = R15; } \
+	{ R11:10 = memd(R0 + #_PT_R1110); \
+	  sa0 = R14; } \
+	{ R13:12 = memd(R0 + #_PT_R1312); \
+	  R15:14 = memd(R0 + #_PT_R1514); } \
+	{ R17:16 = memd(R0 + #_PT_R1716); \
+	  R19:18 = memd(R0 + #_PT_R1918); } \
+	{ R21:20 = memd(R0 + #_PT_R2120); \
+	  R23:22 = memd(R0 + #_PT_R2322); } \
+	{ R25:24 = memd(R0 + #_PT_R2524); \
+	  R27:26 = memd(R0 + #_PT_R2726); } \
+	R31:30 = memd(R0 + #_PT_UGPGP); \
+	{ R28 = memw(R0 + #_PT_R2928); \
+	  ugp = R31; } \
+	{ R31:30 = memd(R0 + #_PT_R3130); \
+	  gp = R30; }
+
+	/*
+	 * Clears off enough space for the rest of pt_regs; evrec is a part
+	 * of pt_regs in HVM mode.  Save R0/R1, set handler's address in R1.
+	 * R0 is the address of pt_regs and is the parameter to save_pt_regs.
+	 */
+
+/*
+ * Since the HVM isn't automagically pushing the EVREC onto the stack anymore,
+ * we'll subract the entire size out and then fill it in ourselves.
+ * Need to save off R0, R1, R2, R3 immediately.
+ */
+
+#define	vm_event_entry(CHandler) \
+	{ \
+		R29 = add(R29, #-(_PT_REGS_SIZE)); \
+		memd(R29 + #(_PT_R0100 + -_PT_REGS_SIZE)) = R1:0; \
+	} \
+	{ \
+		memd(R29 +#_PT_R0302) = R3:2; \
+	} \
+	trap1(#HVM_TRAP1_VMGETREGS); \
+	{ \
+		memd(R29 + #_PT_ER_VMEL) = R1:0; \
+		R0 = R29; \
+		R1.L = #LO(CHandler); \
+	} \
+	{ \
+		memd(R29 + #_PT_ER_VMPSP) = R3:2; \
+		R1.H = #HI(CHandler); \
+		jump event_dispatch; \
+	}
+
+.text
+	/*
+	 * Do bulk save/restore in one place.
+	 * Adds a jump to dispatch latency, but
+	 * saves hundreds of bytes.
+	 */
+
+event_dispatch:
+	save_pt_regs()
+	callr	r1
+
+	/*
+	 * If we were in kernel mode, we don't need to check scheduler
+	 * or signals if CONFIG_PREEMPT is not set.  If set, then it has
+	 * to jump to a need_resched kind of block.
+	 * BTW, CONFIG_PREEMPT is not supported yet.
+	 */
+
+#ifdef CONFIG_PREEMPT
+	R0 = #VM_INT_DISABLE
+	trap1(#HVM_TRAP1_VMSETIE)
+#endif
+
+	/*  "Nested control path" -- if the previous mode was kernel  */
+	R0 = memw(R29 + #_PT_ER_VMEST);
+	P0 = tstbit(R0, #HVM_VMEST_UM_SFT);
+	if !P0 jump restore_all;
+	/*
+	 * Returning from system call, normally coming back from user mode
+	 */
+return_from_syscall:
+	/*  Disable interrupts while checking TIF  */
+	R0 = #VM_INT_DISABLE
+	trap1(#HVM_TRAP1_VMSETIE)
+
+	/*
+	 * Coming back from the C-world, our thread info pointer
+	 * should be in the designated register (usually R19)
+	 */
+	R1.L = #LO(_TIF_ALLWORK_MASK)
+	{
+		R1.H = #HI(_TIF_ALLWORK_MASK);
+		R0 = memw(THREADINFO_REG + #_THREAD_INFO_FLAGS);
+	}
+
+	/*
+	 * Compare against the "return to userspace" _TIF_WORK_MASK
+	 */
+	R1 = and(R1,R0);
+	{ P0 = cmp.eq(R1,#0); if (!P0.new) jump:t work_pending;}
+	jump restore_all;  /*  we're outta here!  */
+
+work_pending:
+	{
+		P0 = tstbit(R1, #TIF_NEED_RESCHED);
+		if (!P0.new) jump:nt work_notifysig;
+	}
+	call schedule
+	jump return_from_syscall;  /*  check for more work  */
+
+work_notifysig:
+	/*  this is the part that's kind of fuzzy.  */
+	R1 = and(R0, #(_TIF_SIGPENDING | _TIF_NOTIFY_RESUME));
+	P0 = cmp.eq(R1, #0);
+	if P0 jump restore_all
+	R1 = R0; 	/* unsigned long thread_info_flags */
+	R0 = R29;	/* regs should still be at top of stack  */
+	call do_notify_resume
+
+restore_all:
+	/* Disable interrupts, if they weren't already, before reg restore.  */
+	R0 = #VM_INT_DISABLE
+	trap1(#HVM_TRAP1_VMSETIE)
+
+	/*  do the setregs here for VM 0.5  */
+	/*  R29 here should already be pointing at pt_regs  */
+	R1:0 = memd(R29 + #_PT_ER_VMEL);
+	R3:2 = memd(R29 + #_PT_ER_VMPSP);
+	trap1(#HVM_TRAP1_VMSETREGS);
+
+	R0 = R29
+	restore_pt_regs()
+	R1:0 = memd(R29 + #_PT_R0100);
+	R29 = add(R29, #_PT_REGS_SIZE);
+	trap1(#HVM_TRAP1_VMRTE)
+	/* Notreached */
+
+	.globl _K_enter_genex
+_K_enter_genex:
+	vm_event_entry(do_genex)
+
+	.globl _K_enter_interrupt
+_K_enter_interrupt:
+	vm_event_entry(arch_do_IRQ)
+
+	.globl _K_enter_trap0
+_K_enter_trap0:
+	vm_event_entry(do_trap0)
+
+	.globl _K_enter_machcheck
+_K_enter_machcheck:
+	vm_event_entry(do_machcheck)
+
+
+	.globl ret_from_fork
+ret_from_fork:
+	call schedule_tail
+	jump return_from_syscall
diff --git a/arch/hexagon/kernel/vm_events.c b/arch/hexagon/kernel/vm_events.c
new file mode 100644
index 0000000..986a081
--- /dev/null
+++ b/arch/hexagon/kernel/vm_events.c
@@ -0,0 +1,101 @@
+/*
+ * Mostly IRQ support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/kernel.h>
+#include <asm/registers.h>
+#include <linux/irq.h>
+#include <linux/hardirq.h>
+#include <asm/system.h>
+
+/*
+ * show_regs - print pt_regs structure
+ * @regs: pointer to pt_regs
+ *
+ * To-do:  add all the accessor definitions to registers.h
+ *
+ * Will make this routine a lot easier to write.
+ */
+void show_regs(struct pt_regs *regs)
+{
+	printk(KERN_EMERG "restart_r0: \t0x%08lx   syscall_nr: %ld\n",
+	       regs->restart_r0, regs->syscall_nr);
+	printk(KERN_EMERG "preds: \t\t0x%08lx\n", regs->preds);
+	printk(KERN_EMERG "lc0: \t0x%08lx   sa0: 0x%08lx   m0:  0x%08lx\n",
+	       regs->lc0, regs->sa0, regs->m0);
+	printk(KERN_EMERG "lc1: \t0x%08lx   sa1: 0x%08lx   m1:  0x%08lx\n",
+	       regs->lc1, regs->sa1, regs->m1);
+	printk(KERN_EMERG "gp: \t0x%08lx   ugp: 0x%08lx   usr: 0x%08lx\n",
+	       regs->gp, regs->ugp, regs->usr);
+	printk(KERN_EMERG "r0: \t0x%08lx %08lx %08lx %08lx\n", regs->r00,
+		regs->r01,
+		regs->r02,
+		regs->r03);
+	printk(KERN_EMERG "r4:  \t0x%08lx %08lx %08lx %08lx\n", regs->r04,
+		regs->r05,
+		regs->r06,
+		regs->r07);
+	printk(KERN_EMERG "r8:  \t0x%08lx %08lx %08lx %08lx\n", regs->r08,
+		regs->r09,
+		regs->r10,
+		regs->r11);
+	printk(KERN_EMERG "r12: \t0x%08lx %08lx %08lx %08lx\n", regs->r12,
+		regs->r13,
+		regs->r14,
+		regs->r15);
+	printk(KERN_EMERG "r16: \t0x%08lx %08lx %08lx %08lx\n", regs->r16,
+		regs->r17,
+		regs->r18,
+		regs->r19);
+	printk(KERN_EMERG "r20: \t0x%08lx %08lx %08lx %08lx\n", regs->r20,
+		regs->r21,
+		regs->r22,
+		regs->r23);
+	printk(KERN_EMERG "r24: \t0x%08lx %08lx %08lx %08lx\n", regs->r24,
+		regs->r25,
+		regs->r26,
+		regs->r27);
+	printk(KERN_EMERG "r28: \t0x%08lx %08lx %08lx %08lx\n", regs->r28,
+		regs->r29,
+		regs->r30,
+		regs->r31);
+
+	printk(KERN_EMERG "elr: \t0x%08lx   cause: 0x%08lx   user_mode: %d\n",
+		pt_elr(regs), pt_cause(regs), user_mode(regs));
+	printk(KERN_EMERG "psp: \t0x%08lx   badva: 0x%08lx   int_enabled: %d\n",
+		pt_psp(regs), pt_badva(regs), ints_enabled(regs));
+}
+
+void dummy_handler(struct pt_regs *regs)
+{
+	unsigned int elr = pt_elr(regs);
+	printk(KERN_ERR "Unimplemented handler; ELR=0x%08x\n", elr);
+}
+
+
+void arch_do_IRQ(struct pt_regs *regs)
+{
+	int irq = pt_cause(regs);
+	struct pt_regs *old_regs = set_irq_regs(regs);
+
+	irq_enter();
+	generic_handle_irq(irq);
+	irq_exit();
+	set_irq_regs(old_regs);
+}
diff --git a/arch/hexagon/kernel/vm_init_segtable.S b/arch/hexagon/kernel/vm_init_segtable.S
new file mode 100644
index 0000000..aebb35b
--- /dev/null
+++ b/arch/hexagon/kernel/vm_init_segtable.S
@@ -0,0 +1,442 @@
+/*
+ * Initial page table for Linux kernel under Hexagon VM,
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * These tables are pre-computed and linked into kernel.
+ */
+
+#include <asm/vm_mmu.h>
+/*  #include <asm/iomap.h>  */
+
+/*
+ * Start with mapping PA=0 to both VA=0x0 and VA=0xc000000 as 16MB large pages.
+ * No user mode access, RWX, write-back cache.  The entry needs
+ * to be replicated for all 4 virtual segments mapping to the page.
+ */
+
+/* "Big Kernel Page"  */
+#define BKP(pa) (((pa) & __HVM_PTE_PGMASK_4MB)		\
+		| __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X	\
+		| __HEXAGON_C_WB_L2 << 6			\
+		| __HVM_PDE_S_16MB)
+
+/*  No cache version  */
+
+#define BKPG_IO(pa) (((pa) & __HVM_PTE_PGMASK_16MB) \
+			| __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X \
+			| __HVM_PDE_S_16MB | __HEXAGON_C_DEV << 6 )
+
+#define FOURK_IO(pa) (((pa) & __HVM_PTE_PGMASK_4KB) \
+			| __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X \
+			| __HEXAGON_C_DEV << 6 )
+
+#define L2_PTR(pa) (((pa) & __HVM_PTE_PGMASK_4KB) \
+			| __HVM_PDE_S_4KB  )
+
+#define X __HVM_PDE_S_INVALID
+
+	.p2align 12
+	.globl swapper_pg_dir
+	.globl _K_init_segtable
+swapper_pg_dir:
+/* VA 0x00000000 */
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+/* VA 0x40000000 */
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+/* VA 0x80000000 */
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+/*0xa8*/.word X,X,X,X
+#ifdef CONFIG_COMET_EARLY_UART_DEBUG
+UART_PTE_ENTRY:
+/*0xa9*/.word BKPG_IO(0xa9000000),BKPG_IO(0xa9000000),BKPG_IO(0xa9000000),BKPG_IO(0xa9000000)
+#else
+/*0xa9*/.word X,X,X,X
+#endif
+/*0xaa*/.word X,X,X,X
+/*0xab*/.word X,X,X,X
+/*0xac*/.word X,X,X,X
+/*0xad*/.word X,X,X,X
+/*0xae*/.word X,X,X,X
+/*0xaf*/.word X,X,X,X
+/*0xb0*/.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+	.word X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X
+_K_init_segtable:
+/* VA 0xC0000000 */
+	.word BKP(0x00000000), BKP(0x00400000), BKP(0x00800000), BKP(0x00c00000)
+	.word BKP(0x01000000), BKP(0x01400000), BKP(0x01800000), BKP(0x01c00000)
+	.word BKP(0x02000000), BKP(0x02400000), BKP(0x02800000), BKP(0x02c00000)
+	.word BKP(0x03000000), BKP(0x03400000), BKP(0x03800000), BKP(0x03c00000)
+	.word BKP(0x04000000), BKP(0x04400000), BKP(0x04800000), BKP(0x04c00000)
+	.word BKP(0x05000000), BKP(0x05400000), BKP(0x05800000), BKP(0x05c00000)
+	.word BKP(0x06000000), BKP(0x06400000), BKP(0x06800000), BKP(0x06c00000)
+	.word BKP(0x07000000), BKP(0x07400000), BKP(0x07800000), BKP(0x07c00000)
+
+	.word BKP(0x08000000), BKP(0x08400000), BKP(0x08800000), BKP(0x08c00000)
+	.word BKP(0x09000000), BKP(0x09400000), BKP(0x09800000), BKP(0x09c00000)
+	.word BKP(0x0a000000), BKP(0x0a400000), BKP(0x0a800000), BKP(0x0ac00000)
+	.word BKP(0x0b000000), BKP(0x0b400000), BKP(0x0b800000), BKP(0x0bc00000)
+	.word BKP(0x0c000000), BKP(0x0c400000), BKP(0x0c800000), BKP(0x0cc00000)
+	.word BKP(0x0d000000), BKP(0x0d400000), BKP(0x0d800000), BKP(0x0dc00000)
+	.word BKP(0x0e000000), BKP(0x0e400000), BKP(0x0e800000), BKP(0x0ec00000)
+	.word BKP(0x0f000000), BKP(0x0f400000), BKP(0x0f800000), BKP(0x0fc00000)
+
+	.word BKP(0x10000000), BKP(0x10400000), BKP(0x10800000), BKP(0x10c00000)
+	.word BKP(0x11000000), BKP(0x11400000), BKP(0x11800000), BKP(0x11c00000)
+	.word BKP(0x12000000), BKP(0x12400000), BKP(0x12800000), BKP(0x12c00000)
+	.word BKP(0x13000000), BKP(0x13400000), BKP(0x13800000), BKP(0x13c00000)
+	.word BKP(0x14000000), BKP(0x14400000), BKP(0x14800000), BKP(0x14c00000)
+	.word BKP(0x15000000), BKP(0x15400000), BKP(0x15800000), BKP(0x15c00000)
+	.word BKP(0x16000000), BKP(0x16400000), BKP(0x16800000), BKP(0x16c00000)
+	.word BKP(0x17000000), BKP(0x17400000), BKP(0x17800000), BKP(0x17c00000)
+
+	.word BKP(0x18000000), BKP(0x18400000), BKP(0x18800000), BKP(0x18c00000)
+	.word BKP(0x19000000), BKP(0x19400000), BKP(0x19800000), BKP(0x19c00000)
+	.word BKP(0x1a000000), BKP(0x1a400000), BKP(0x1a800000), BKP(0x1ac00000)
+	.word BKP(0x1b000000), BKP(0x1b400000), BKP(0x1b800000), BKP(0x1bc00000)
+	.word BKP(0x1c000000), BKP(0x1c400000), BKP(0x1c800000), BKP(0x1cc00000)
+	.word BKP(0x1d000000), BKP(0x1d400000), BKP(0x1d800000), BKP(0x1dc00000)
+	.word BKP(0x1e000000), BKP(0x1e400000), BKP(0x1e800000), BKP(0x1ec00000)
+	.word BKP(0x1f000000), BKP(0x1f400000), BKP(0x1f800000), BKP(0x1fc00000)
+
+	.word BKP(0x20000000), BKP(0x20400000), BKP(0x20800000), BKP(0x20c00000)
+	.word BKP(0x21000000), BKP(0x21400000), BKP(0x21800000), BKP(0x21c00000)
+	.word BKP(0x22000000), BKP(0x22400000), BKP(0x22800000), BKP(0x22c00000)
+	.word BKP(0x23000000), BKP(0x23400000), BKP(0x23800000), BKP(0x23c00000)
+	.word BKP(0x24000000), BKP(0x24400000), BKP(0x24800000), BKP(0x24c00000)
+	.word BKP(0x25000000), BKP(0x25400000), BKP(0x25800000), BKP(0x25c00000)
+	.word BKP(0x26000000), BKP(0x26400000), BKP(0x26800000), BKP(0x26c00000)
+	.word BKP(0x27000000), BKP(0x27400000), BKP(0x27800000), BKP(0x27c00000)
+
+	.word BKP(0x28000000), BKP(0x28400000), BKP(0x28800000), BKP(0x28c00000)
+	.word BKP(0x29000000), BKP(0x29400000), BKP(0x29800000), BKP(0x29c00000)
+	.word BKP(0x2a000000), BKP(0x2a400000), BKP(0x2a800000), BKP(0x2ac00000)
+	.word BKP(0x2b000000), BKP(0x2b400000), BKP(0x2b800000), BKP(0x2bc00000)
+	.word BKP(0x2c000000), BKP(0x2c400000), BKP(0x2c800000), BKP(0x2cc00000)
+	.word BKP(0x2d000000), BKP(0x2d400000), BKP(0x2d800000), BKP(0x2dc00000)
+	.word BKP(0x2e000000), BKP(0x2e400000), BKP(0x2e800000), BKP(0x2ec00000)
+	.word BKP(0x2f000000), BKP(0x2f400000), BKP(0x2f800000), BKP(0x2fc00000)
+
+	.word BKP(0x30000000), BKP(0x30400000), BKP(0x30800000), BKP(0x30c00000)
+	.word BKP(0x31000000), BKP(0x31400000), BKP(0x31800000), BKP(0x31c00000)
+	.word BKP(0x32000000), BKP(0x32400000), BKP(0x32800000), BKP(0x32c00000)
+	.word BKP(0x33000000), BKP(0x33400000), BKP(0x33800000), BKP(0x33c00000)
+	.word BKP(0x34000000), BKP(0x34400000), BKP(0x34800000), BKP(0x34c00000)
+	.word BKP(0x35000000), BKP(0x35400000), BKP(0x35800000), BKP(0x35c00000)
+	.word BKP(0x36000000), BKP(0x36400000), BKP(0x36800000), BKP(0x36c00000)
+	.word BKP(0x37000000), BKP(0x37400000), BKP(0x37800000), BKP(0x37c00000)
+
+	.word BKP(0x38000000), BKP(0x38400000), BKP(0x38800000), BKP(0x38c00000)
+	.word BKP(0x39000000), BKP(0x39400000), BKP(0x39800000), BKP(0x39c00000)
+	.word BKP(0x3a000000), BKP(0x3a400000), BKP(0x3a800000), BKP(0x3ac00000)
+	.word BKP(0x3b000000), BKP(0x3b400000), BKP(0x3b800000), BKP(0x3bc00000)
+	.word BKP(0x3c000000), BKP(0x3c400000), BKP(0x3c800000), BKP(0x3cc00000)
+	.word BKP(0x3d000000), BKP(0x3d400000), BKP(0x3d800000), BKP(0x3dc00000)
+_K_io_map:
+	.word X,X,X,X /* 0x3e000000 - device IO early remap */
+	.word X,X,X,X /* 0x3f000000 - hypervisor space*/
+
+#if 0
+/*
+ * This is in here as an example for devices which need to be mapped really
+ * early.
+ */
+	.p2align 12
+	.globl _K_io_kmap
+	.globl _K_init_devicetable
+_K_init_devicetable:  /*  Should be 4MB worth of entries  */
+	.word FOURK_IO(MSM_GPIO1_PHYS),FOURK_IO(MSM_GPIO2_PHYS),FOURK_IO(MSM_SIRC_PHYS),X
+	.word FOURK_IO(TLMM_GPIO1_PHYS),X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+	.word X,X,X,X
+#endif
diff --git a/arch/hexagon/kernel/vm_ops.S b/arch/hexagon/kernel/vm_ops.S
new file mode 100644
index 0000000..24d7fca
--- /dev/null
+++ b/arch/hexagon/kernel/vm_ops.S
@@ -0,0 +1,102 @@
+/*
+ * Hexagon VM instruction support
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/linkage.h>
+#include <asm/hexagon_vm.h>
+
+/*
+ * C wrappers for virtual machine "instructions".  These
+ * could be, and perhaps some day will be, handled as in-line
+ * macros, but for tracing/debugging it's handy to have
+ * a single point of invocation for each of them.
+ * Conveniently, they take paramters and return values
+ * consistent with the ABI calling convention.
+ */
+
+ENTRY(__vmrte)
+	trap1(#HVM_TRAP1_VMRTE);
+	jumpr	R31;
+
+ENTRY(__vmsetvec)
+	trap1(#HVM_TRAP1_VMSETVEC);
+	jumpr	R31;
+
+ENTRY(__vmsetie)
+	trap1(#HVM_TRAP1_VMSETIE);
+	jumpr	R31;
+
+ENTRY(__vmgetie)
+	trap1(#HVM_TRAP1_VMGETIE);
+	jumpr	R31;
+
+ENTRY(__vmintop)
+	trap1(#HVM_TRAP1_VMINTOP);
+	jumpr	R31;
+
+ENTRY(__vmclrmap)
+	trap1(#HVM_TRAP1_VMCLRMAP);
+	jumpr	R31;
+
+ENTRY(__vmnewmap)
+	r1 = #VM_NEWMAP_TYPE_PGTABLES;
+	trap1(#HVM_TRAP1_VMNEWMAP);
+	jumpr	R31;
+
+ENTRY(__vmcache)
+	trap1(#HVM_TRAP1_VMCACHE);
+	jumpr	R31;
+
+ENTRY(__vmgettime)
+	trap1(#HVM_TRAP1_VMGETTIME);
+	jumpr	R31;
+
+ENTRY(__vmsettime)
+	trap1(#HVM_TRAP1_VMSETTIME);
+	jumpr	R31;
+
+ENTRY(__vmwait)
+	trap1(#HVM_TRAP1_VMWAIT);
+	jumpr	R31;
+
+ENTRY(__vmyield)
+	trap1(#HVM_TRAP1_VMYIELD);
+	jumpr	R31;
+
+ENTRY(__vmstart)
+	trap1(#HVM_TRAP1_VMSTART);
+	jumpr	R31;
+
+ENTRY(__vmstop)
+	trap1(#HVM_TRAP1_VMSTOP);
+	jumpr	R31;
+
+ENTRY(__vmvpid)
+	trap1(#HVM_TRAP1_VMVPID);
+	jumpr	R31;
+
+/*  Probably not actually going to use these; see vm_entry.S  */
+
+ENTRY(__vmsetregs)
+	trap1(#HVM_TRAP1_VMSETREGS);
+	jumpr	R31;
+
+ENTRY(__vmgetregs)
+	trap1(#HVM_TRAP1_VMGETREGS);
+	jumpr	R31;
diff --git a/arch/hexagon/kernel/vm_switch.S b/arch/hexagon/kernel/vm_switch.S
new file mode 100644
index 0000000..0decf2f
--- /dev/null
+++ b/arch/hexagon/kernel/vm_switch.S
@@ -0,0 +1,95 @@
+/*
+ * Context switch support for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <asm/asm-offsets.h>
+
+.text
+
+/*
+ * The register used as a fast-path thread information pointer
+ * is determined as a kernel configuration option.  If it happens
+ * to be a callee-save register, we're going to be saving and
+ * restoring it twice here.
+ *
+ * This code anticipates a revised ABI where R20-23 are added
+ * to the set of callee-save registers, but this should be
+ * backward compatible to legacy tools.
+ */
+
+
+/*
+ *	void switch_to(struct task_struct *prev,
+ *		struct task_struct *next, struct task_struct *last);
+ */
+	.p2align 2
+	.globl __switch_to
+	.type	__switch_to, @function
+
+/*
+ * When we exit the wormhole, we need to store the previous task
+ * in the new R0's pointer.  Technically it should be R2, but they should
+ * be the same; seems like a legacy thing.  In short, don't butcher
+ * R0, let it go back out unmolested.
+ */
+
+__switch_to:
+	/*
+	 * Push callee-saves onto "prev" stack.
+	 * Here, we're sneaky because the LR and FP
+	 * storage of the thread_stack structure
+	 * is automagically allocated by allocframe,
+	 * so we pass struct size less 8.
+	 */
+	allocframe(#(_SWITCH_STACK_SIZE - 8));
+	memd(R29+#(_SWITCH_R2726))=R27:26;
+	memd(R29+#(_SWITCH_R2524))=R25:24;
+	memd(R29+#(_SWITCH_R2322))=R23:22;
+	memd(R29+#(_SWITCH_R2120))=R21:20;
+	memd(R29+#(_SWITCH_R1918))=R19:18;
+	memd(R29+#(_SWITCH_R1716))=R17:16;
+	/* Stash thread_info pointer in task_struct */
+	memw(R0+#_TASK_THREAD_INFO) = THREADINFO_REG;
+	memw(R0 +#(_TASK_STRUCT_THREAD + _THREAD_STRUCT_SWITCH_SP)) = R29;
+	/* Switch to "next" stack and restore callee saves from there */
+	R29 = memw(R1 + #(_TASK_STRUCT_THREAD + _THREAD_STRUCT_SWITCH_SP));
+	{
+	    R27:26 = memd(R29+#(_SWITCH_R2726));
+	    R25:24 = memd(R29+#(_SWITCH_R2524));
+	}
+	{
+	    R23:22 = memd(R29+#(_SWITCH_R2322));
+	    R21:20 = memd(R29+#(_SWITCH_R2120));
+	}
+	{
+	    R19:18 = memd(R29+#(_SWITCH_R1918));
+	    R17:16 = memd(R29+#(_SWITCH_R1716));
+	}
+	{
+	    /* THREADINFO_REG is currently one of the callee-saved regs
+	     * above, and so be sure to re-load it last.
+	     */
+	    THREADINFO_REG = memw(R1 + #_TASK_THREAD_INFO);
+	    R31:30 = memd(R29+#_SWITCH_FP);
+	}
+	{
+	    R29 = add(R29,#_SWITCH_STACK_SIZE);
+	    jumpr R31;
+	}
+	.size	__switch_to, .-__switch_to
diff --git a/arch/hexagon/kernel/vm_vectors.S b/arch/hexagon/kernel/vm_vectors.S
new file mode 100644
index 0000000..97a4b50
--- /dev/null
+++ b/arch/hexagon/kernel/vm_vectors.S
@@ -0,0 +1,48 @@
+/*
+ * Event jump tables
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <asm/hexagon_vm.h>
+
+.text
+
+/*  This is registered early on to allow angel  */
+.global _K_provisional_vec
+_K_provisional_vec:
+	jump 1f;
+	jump 1f;
+	jump 1f;
+	jump 1f;
+	jump 1f;
+	trap1(#HVM_TRAP1_VMRTE)
+	jump 1f;
+	jump 1f;
+
+
+.global _K_VM_event_vector
+_K_VM_event_vector:
+1:
+	jump 1b;  /*  Reset  */
+	jump _K_enter_machcheck;
+	jump _K_enter_genex;
+	jump 1b;  /*  3 Rsvd  */
+	jump 1b;  /*  4 Rsvd  */
+	jump _K_enter_trap0;
+	jump 1b;  /*  6 Rsvd  */
+	jump _K_enter_interrupt;
diff --git a/arch/hexagon/kernel/vmlinux.lds.S b/arch/hexagon/kernel/vmlinux.lds.S
new file mode 100644
index 0000000..071d3c3
--- /dev/null
+++ b/arch/hexagon/kernel/vmlinux.lds.S
@@ -0,0 +1,88 @@
+/*
+ * Linker script for Hexagon kernel
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#define LOAD_OFFSET PAGE_OFFSET
+
+#include <asm-generic/vmlinux.lds.h>
+#include <asm/asm-offsets.h>	/*  Most of the kernel defines are here  */
+#include <asm/mem-layout.h>	/*  except for page_offset  */
+#include <asm/cache.h>		/*  and now we're pulling cache line size  */
+OUTPUT_ARCH(hexagon)
+ENTRY(stext)
+
+jiffies = jiffies_64;
+
+/*
+See asm-generic/vmlinux.lds.h for expansion of some of these macros.
+See asm-generic/sections.h for seemingly required labels.
+*/
+
+#define PAGE_SIZE _PAGE_SIZE
+
+/*  This LOAD_OFFSET is temporary for debugging on the simulator; it may change
+    for hypervisor pseudo-physical memory.  */
+
+
+SECTIONS
+{
+	. = PAGE_OFFSET + LOAD_ADDRESS;
+
+	__init_begin = .;
+	HEAD_TEXT_SECTION
+	INIT_TEXT_SECTION(PAGE_SIZE)
+	PERCPU_SECTION(L1_CACHE_BYTES)
+	__init_end = .;
+
+        . = ALIGN(_PAGE_SIZE);
+	_stext = .;
+	.text : AT(ADDR(.text) - LOAD_OFFSET) {
+		_text = .;
+		TEXT_TEXT
+		SCHED_TEXT
+		LOCK_TEXT
+		KPROBES_TEXT
+		*(.fixup)
+	}
+	_etext = .;
+
+	INIT_DATA_SECTION(PAGE_SIZE)
+
+	_sdata = .;
+		RW_DATA_SECTION(32,PAGE_SIZE,PAGE_SIZE)
+		RO_DATA_SECTION(PAGE_SIZE)
+	_edata = .;
+
+	EXCEPTION_TABLE(16)
+	NOTES
+
+	BSS_SECTION(_PAGE_SIZE, _PAGE_SIZE, _PAGE_SIZE)
+
+	_end = .;
+
+	/DISCARD/ : {
+		EXIT_TEXT
+		EXIT_DATA
+		EXIT_CALL
+	}
+
+	STABS_DEBUG
+	DWARF_DEBUG
+
+}
diff --git a/arch/hexagon/lib/Makefile b/arch/hexagon/lib/Makefile
new file mode 100644
index 0000000..874655e
--- /dev/null
+++ b/arch/hexagon/lib/Makefile
@@ -0,0 +1,4 @@
+#
+# Makefile for hexagon-specific library files.
+#
+obj-y = checksum.o io.o memcpy.o memset.o
diff --git a/arch/hexagon/lib/checksum.c b/arch/hexagon/lib/checksum.c
new file mode 100644
index 0000000..9300552
--- /dev/null
+++ b/arch/hexagon/lib/checksum.c
@@ -0,0 +1,203 @@
+/*
+ * Checksum functions for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*  This was derived from arch/alpha/lib/checksum.c  */
+
+
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include <asm/byteorder.h>
+#include <net/checksum.h>
+#include <linux/uaccess.h>
+#include <asm/intrinsics.h>
+
+
+/*  Vector value operations  */
+#define SIGN(x, y)	((0x8000ULL*x)<<y)
+#define CARRY(x, y)	((0x0002ULL*x)<<y)
+#define SELECT(x, y)	((0x0001ULL*x)<<y)
+
+#define VR_NEGATE(a, b, c, d)	(SIGN(a, 48) + SIGN(b, 32) + SIGN(c, 16) \
+	+ SIGN(d, 0))
+#define VR_CARRY(a, b, c, d)	(CARRY(a, 48) + CARRY(b, 32) + CARRY(c, 16) \
+	+ CARRY(d, 0))
+#define VR_SELECT(a, b, c, d)	(SELECT(a, 48) + SELECT(b, 32) + SELECT(c, 16) \
+	+ SELECT(d, 0))
+
+
+/* optimized HEXAGON V3 intrinsic version */
+static inline unsigned short from64to16(u64 x)
+{
+	u64 sum;
+
+	sum = HEXAGON_P_vrmpyh_PP(x^VR_NEGATE(1, 1, 1, 1),
+			     VR_SELECT(1, 1, 1, 1));
+	sum += VR_CARRY(0, 0, 1, 0);
+	sum = HEXAGON_P_vrmpyh_PP(sum, VR_SELECT(0, 0, 1, 1));
+
+	return 0xFFFF & sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented.
+ */
+__sum16 csum_tcpudp_magic(unsigned long saddr, unsigned long daddr,
+			  unsigned short len, unsigned short proto,
+			  __wsum sum)
+{
+	return (__force __sum16)~from64to16(
+		(__force u64)saddr + (__force u64)daddr +
+		(__force u64)sum + ((len + proto) << 8));
+}
+
+__wsum csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr,
+			  unsigned short len, unsigned short proto,
+			  __wsum sum)
+{
+	u64 result;
+
+	result = (__force u64)saddr + (__force u64)daddr +
+		 (__force u64)sum + ((len + proto) << 8);
+
+	/* Fold down to 32-bits so we don't lose in the typedef-less
+	   network stack.  */
+	/* 64 to 33 */
+	result = (result & 0xffffffffUL) + (result >> 32);
+	/* 33 to 32 */
+	result = (result & 0xffffffffUL) + (result >> 32);
+	return (__force __wsum)result;
+}
+EXPORT_SYMBOL(csum_tcpudp_nofold);
+
+/*
+ * Do a 64-bit checksum on an arbitrary memory area..
+ *
+ * This isn't a great routine, but it's not _horrible_ either. The
+ * inner loop could be unrolled a bit further, and there are better
+ * ways to do the carry, but this is reasonable.
+ */
+
+/* optimized HEXAGON intrinsic version, with over read fixed */
+unsigned int do_csum(const void *voidptr, int len)
+{
+	u64 sum0, sum1, x0, x1, *ptr8_o, *ptr8_e, *ptr8;
+	int i, start, mid, end, mask;
+	const char *ptr = voidptr;
+	unsigned short *ptr2;
+	unsigned int *ptr4;
+
+	if (len <= 0)
+		return 0;
+
+	start = 0xF & (16-(((int) ptr) & 0xF)) ;
+	mask  = 0x7fffffffUL >> HEXAGON_R_cl0_R(len);
+	start = start & mask ;
+
+	mid = len - start;
+	end = mid & 0xF;
+	mid = mid>>4;
+	sum0 = mid << 18;
+	sum1 = 0;
+
+	if (start & 1)
+		sum0 += (u64) (ptr[0] << 8);
+	ptr2 = (unsigned short *) &ptr[start & 1];
+	if (start & 2)
+		sum1 += (u64) ptr2[0];
+	ptr4 = (unsigned int *) &ptr[start & 3];
+	if (start & 4) {
+		sum0 = HEXAGON_P_vrmpyhacc_PP(sum0,
+			VR_NEGATE(0, 0, 1, 1)^((u64)ptr4[0]),
+			VR_SELECT(0, 0, 1, 1));
+		sum0 += VR_SELECT(0, 0, 1, 0);
+	}
+	ptr8 = (u64 *) &ptr[start & 7];
+	if (start & 8) {
+		sum1 = HEXAGON_P_vrmpyhacc_PP(sum1,
+			VR_NEGATE(1, 1, 1, 1)^(ptr8[0]),
+			VR_SELECT(1, 1, 1, 1));
+		sum1 += VR_CARRY(0, 0, 1, 0);
+	}
+	ptr8_o = (u64 *) (ptr + start);
+	ptr8_e = (u64 *) (ptr + start + 8);
+
+	if (mid) {
+		x0 = *ptr8_e; ptr8_e += 2;
+		x1 = *ptr8_o; ptr8_o += 2;
+		if (mid > 1)
+			for (i = 0; i < mid-1; i++) {
+				sum0 = HEXAGON_P_vrmpyhacc_PP(sum0,
+					x0^VR_NEGATE(1, 1, 1, 1),
+					VR_SELECT(1, 1, 1, 1));
+				sum1 = HEXAGON_P_vrmpyhacc_PP(sum1,
+					x1^VR_NEGATE(1, 1, 1, 1),
+					VR_SELECT(1, 1, 1, 1));
+				x0 = *ptr8_e; ptr8_e += 2;
+				x1 = *ptr8_o; ptr8_o += 2;
+			}
+		sum0 = HEXAGON_P_vrmpyhacc_PP(sum0, x0^VR_NEGATE(1, 1, 1, 1),
+			VR_SELECT(1, 1, 1, 1));
+		sum1 = HEXAGON_P_vrmpyhacc_PP(sum1, x1^VR_NEGATE(1, 1, 1, 1),
+			VR_SELECT(1, 1, 1, 1));
+	}
+
+	ptr4 = (unsigned int *) &ptr[start + (mid * 16) + (end & 8)];
+	if (end & 4) {
+		sum1 = HEXAGON_P_vrmpyhacc_PP(sum1,
+			VR_NEGATE(0, 0, 1, 1)^((u64)ptr4[0]),
+			VR_SELECT(0, 0, 1, 1));
+		sum1 += VR_SELECT(0, 0, 1, 0);
+	}
+	ptr2 = (unsigned short *) &ptr[start + (mid * 16) + (end & 12)];
+	if (end & 2)
+		sum0 += (u64) ptr2[0];
+
+	if (end & 1)
+		sum1 += (u64) ptr[start + (mid * 16) + (end & 14)];
+
+	ptr8 = (u64 *) &ptr[start + (mid * 16)];
+	if (end & 8) {
+		sum0 = HEXAGON_P_vrmpyhacc_PP(sum0,
+			VR_NEGATE(1, 1, 1, 1)^(ptr8[0]),
+			VR_SELECT(1, 1, 1, 1));
+		sum0 += VR_CARRY(0, 0, 1, 0);
+	}
+	sum0 = HEXAGON_P_vrmpyh_PP((sum0+sum1)^VR_NEGATE(0, 0, 0, 1),
+		VR_SELECT(0, 0, 1, 1));
+	sum0 += VR_NEGATE(0, 0, 0, 1);
+	sum0 = HEXAGON_P_vrmpyh_PP(sum0, VR_SELECT(0, 0, 1, 1));
+
+	if (start & 1)
+		sum0 = (sum0 << 8) | (0xFF & (sum0 >> 8));
+
+	return 0xFFFF & sum0;
+}
+
+/*
+ * copy from ds while checksumming, otherwise like csum_partial
+ */
+__wsum
+csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
+{
+	memcpy(dst, src, len);
+	return csum_partial(dst, len, sum);
+}
diff --git a/arch/hexagon/lib/io.c b/arch/hexagon/lib/io.c
new file mode 100644
index 0000000..8ae47ba
--- /dev/null
+++ b/arch/hexagon/lib/io.c
@@ -0,0 +1,91 @@
+/*
+ * I/O access functions for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <asm/io.h>
+
+/*  These are all FIFO routines!  */
+
+/*
+ * __raw_readsw - read words a short at a time
+ * @addr:  source address
+ * @data:  data address
+ * @len: number of shorts to read
+ */
+void __raw_readsw(const void __iomem *addr, void *data, int len)
+{
+	const volatile short int *src = (short int *) addr;
+	short int *dst = (short int *) data;
+
+	if ((u32)data & 0x1)
+		panic("unaligned pointer to readsw");
+
+	while (len-- > 0)
+		*dst++ = *src;
+
+}
+
+/*
+ * __raw_writesw - read words a short at a time
+ * @addr:  source address
+ * @data:  data address
+ * @len: number of shorts to read
+ */
+void __raw_writesw(void __iomem *addr, const void *data, int len)
+{
+	const short int *src = (short int *)data;
+	volatile short int *dst = (short int *)addr;
+
+	if ((u32)data & 0x1)
+		panic("unaligned pointer to writesw");
+
+	while (len-- > 0)
+		*dst = *src++;
+
+
+}
+
+/*  Pretty sure len is pre-adjusted for the length of the access already */
+void __raw_readsl(const void __iomem *addr, void *data, int len)
+{
+	const volatile long *src = (long *) addr;
+	long *dst = (long *) data;
+
+	if ((u32)data & 0x3)
+		panic("unaligned pointer to readsl");
+
+	while (len-- > 0)
+		*dst++ = *src;
+
+
+}
+
+void __raw_writesl(void __iomem *addr, const void *data, int len)
+{
+	const long *src = (long *)data;
+	volatile long *dst = (long *)addr;
+
+	if ((u32)data & 0x3)
+		panic("unaligned pointer to writesl");
+
+	while (len-- > 0)
+		*dst = *src++;
+
+
+}
diff --git a/arch/hexagon/lib/memcpy.S b/arch/hexagon/lib/memcpy.S
new file mode 100644
index 0000000..2101c33
--- /dev/null
+++ b/arch/hexagon/lib/memcpy.S
@@ -0,0 +1,543 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * Description
+ *
+ *   library function for memcpy where length bytes are copied from
+ *   ptr_in to ptr_out. ptr_out is returned unchanged.
+ *   Allows any combination of alignment on input and output pointers
+ *   and length from 0 to 2^32-1
+ *
+ * Restrictions
+ *   The arrays should not overlap, the program will produce undefined output
+ *   if they do.
+ *   For blocks less than 16 bytes a byte by byte copy is performed. For
+ *   8byte alignments, and length multiples, a dword copy is performed up to
+ *   96bytes
+ * History
+ *
+ *   DJH  5/15/09 Initial version 1.0
+ *   DJH  6/ 1/09 Version 1.1 modified ABI to inlcude R16-R19
+ *   DJH  7/12/09 Version 1.2 optimized codesize down to 760 was 840
+ *   DJH 10/14/09 Version 1.3 added special loop for aligned case, was
+ *                            overreading bloated codesize back up to 892
+ *   DJH  4/20/10 Version 1.4 fixed Ldword_loop_epilog loop to prevent loads
+ *                            occuring if only 1 left outstanding, fixes bug
+ *                            # 3888, corrected for all alignments. Peeled off
+ *                            1 32byte chunk from kernel loop and extended 8byte
+ *                            loop at end to solve all combinations and prevent
+ *                            over read.  Fixed Ldword_loop_prolog to prevent
+ *                            overread for blocks less than 48bytes. Reduced
+ *                            codesize to 752 bytes
+ *   DJH  4/21/10 version 1.5 1.4 fix broke code for input block ends not
+ *                            aligned to dword boundaries,underwriting by 1
+ *                            byte, added detection for this and fixed. A
+ *                            little bloat.
+ *   DJH  4/23/10 version 1.6 corrected stack error, R20 was not being restored
+ *                            always, fixed the error of R20 being modified
+ *                            before it was being saved
+ * Natural c model
+ * ===============
+ * void * memcpy(char * ptr_out, char * ptr_in, int length) {
+ *   int i;
+ *   if(length) for(i=0; i < length; i++) { ptr_out[i] = ptr_in[i]; }
+ *   return(ptr_out);
+ * }
+ *
+ * Optimized memcpy function
+ * =========================
+ * void * memcpy(char * ptr_out, char * ptr_in, int len) {
+ *   int i, prolog, kernel, epilog, mask;
+ *   u8 offset;
+ *   s64 data0, dataF8, data70;
+ *
+ *   s64 * ptr8_in;
+ *   s64 * ptr8_out;
+ *   s32 * ptr4;
+ *   s16 * ptr2;
+ *
+ *   offset = ((int) ptr_in) & 7;
+ *   ptr8_in = (s64 *) &ptr_in[-offset];   //read in the aligned pointers
+ *
+ *   data70 = *ptr8_in++;
+ *   dataF8 = *ptr8_in++;
+ *
+ *   data0 = HEXAGON_P_valignb_PPp(dataF8, data70, offset);
+ *
+ *   prolog = 32 - ((int) ptr_out);
+ *   mask  = 0x7fffffff >> HEXAGON_R_cl0_R(len);
+ *   prolog = prolog & mask;
+ *   kernel = len - prolog;
+ *   epilog = kernel & 0x1F;
+ *   kernel = kernel>>5;
+ *
+ *   if (prolog & 1) { ptr_out[0] = (u8) data0; data0 >>= 8; ptr_out += 1;}
+ *   ptr2 = (s16 *) &ptr_out[0];
+ *   if (prolog & 2) { ptr2[0] = (u16) data0;  data0 >>= 16; ptr_out += 2;}
+ *   ptr4 = (s32 *) &ptr_out[0];
+ *   if (prolog & 4) { ptr4[0] = (u32) data0;  data0 >>= 32; ptr_out += 4;}
+ *
+ *   offset = offset + (prolog & 7);
+ *   if (offset >= 8) {
+ *     data70 = dataF8;
+ *     dataF8 = *ptr8_in++;
+ *   }
+ *   offset = offset & 0x7;
+ *
+ *   prolog = prolog >> 3;
+ *   if (prolog) for (i=0; i < prolog; i++) {
+ *       data0 = HEXAGON_P_valignb_PPp(dataF8, data70, offset);
+ *       ptr8_out = (s64 *) &ptr_out[0]; *ptr8_out = data0; ptr_out += 8;
+ *       data70 = dataF8;
+ *       dataF8 = *ptr8_in++;
+ *   }
+ *   if(kernel) { kernel -= 1; epilog += 32; }
+ *   if(kernel) for(i=0; i < kernel; i++) {
+ *       data0 = HEXAGON_P_valignb_PPp(dataF8, data70, offset);
+ *       ptr8_out = (s64 *) &ptr_out[0]; *ptr8_out = data0; ptr_out += 8;
+ *       data70 = *ptr8_in++;
+ *
+ *       data0 = HEXAGON_P_valignb_PPp(data70, dataF8, offset);
+ *       ptr8_out = (s64 *) &ptr_out[0]; *ptr8_out = data0; ptr_out += 8;
+ *       dataF8 = *ptr8_in++;
+ *
+ *       data0 = HEXAGON_P_valignb_PPp(dataF8, data70, offset);
+ *       ptr8_out = (s64 *) &ptr_out[0]; *ptr8_out = data0; ptr_out += 8;
+ *       data70 = *ptr8_in++;
+ *
+ *       data0 = HEXAGON_P_valignb_PPp(data70, dataF8, offset);
+ *       ptr8_out = (s64 *) &ptr_out[0]; *ptr8_out = data0; ptr_out += 8;
+ *       dataF8 = *ptr8_in++;
+ *   }
+ *   epilogdws = epilog >> 3;
+ *   if (epilogdws) for (i=0; i < epilogdws; i++) {
+ *       data0 = HEXAGON_P_valignb_PPp(dataF8, data70, offset);
+ *       ptr8_out = (s64 *) &ptr_out[0]; *ptr8_out = data0; ptr_out += 8;
+ *       data70 = dataF8;
+ *       dataF8 = *ptr8_in++;
+ *   }
+ *   data0 = HEXAGON_P_valignb_PPp(dataF8, data70, offset);
+ *
+ *   ptr4 = (s32 *) &ptr_out[0];
+ *   if (epilog & 4) { ptr4[0] = (u32) data0; data0 >>= 32; ptr_out += 4;}
+ *   ptr2 = (s16 *) &ptr_out[0];
+ *   if (epilog & 2) { ptr2[0] = (u16) data0; data0 >>= 16; ptr_out += 2;}
+ *   if (epilog & 1) { *ptr_out++ = (u8) data0; }
+ *
+ *   return(ptr_out - length);
+ * }
+ *
+ * Codesize : 784 bytes
+ */
+
+
+#define ptr_out		R0	/*  destination  pounter  */
+#define ptr_in		R1	/*  source pointer  */
+#define len		R2	/*  length of copy in bytes  */
+
+#define data70		R13:12	/*  lo 8 bytes of non-aligned transfer  */
+#define dataF8		R11:10	/*  hi 8 bytes of non-aligned transfer  */
+#define ldata0		R7:6	/*  even 8 bytes chunks  */
+#define ldata1		R25:24	/*  odd 8 bytes chunks  */
+#define data1		R7	/*  lower 8 bytes of ldata1  */
+#define data0		R6	/*  lower 8 bytes of ldata0  */
+
+#define ifbyte		p0	/*  if transfer has bytes in epilog/prolog  */
+#define ifhword		p0	/*  if transfer has shorts in epilog/prolog  */
+#define ifword		p0	/*  if transfer has words in epilog/prolog  */
+#define noprolog	p0	/*  no prolog, xfer starts at 32byte  */
+#define nokernel	p1	/*  no 32byte multiple block in the transfer  */
+#define noepilog	p0	/*  no epilog, xfer ends on 32byte boundary  */
+#define align		p2	/*  alignment of input rel to 8byte boundary  */
+#define kernel1		p0	/*  kernel count == 1  */
+
+#define dalign		R25	/*  rel alignment of input to output data  */
+#define star3		R16	/*  number bytes in prolog - dwords  */
+#define rest		R8	/*  length - prolog bytes  */
+#define back		R7	/*  nr bytes > dword boundary in src block  */
+#define epilog		R3	/*  bytes in epilog  */
+#define inc		R15:14	/*  inc kernel by -1 and defetch ptr by 32  */
+#define kernel		R4	/*  number of 32byte chunks in kernel  */
+#define ptr_in_p_128	R5	/*  pointer for prefetch of input data  */
+#define mask		R8	/*  mask used to determine prolog size  */
+#define shift		R8	/*  used to work a shifter to extract bytes  */
+#define shift2		R5	/*  in epilog to workshifter to extract bytes */
+#define prolog		R15	/*  bytes in  prolog  */
+#define epilogdws	R15	/*  number dwords in epilog  */
+#define shiftb		R14	/*  used to extract bytes  */
+#define offset		R9	/*  same as align in reg  */
+#define ptr_out_p_32	R17	/*  pointer to output dczero  */
+#define align888	R14	/*  if simple dword loop can be used  */
+#define len8		R9	/*  number of dwords in length  */
+#define over		R20	/*  nr of bytes > last inp buf dword boundary */
+
+#define ptr_in_p_128kernel	R5:4	/*  packed fetch pointer & kernel cnt */
+
+	.section .text
+	.p2align 4
+        .global memcpy
+        .type memcpy, @function
+memcpy:
+{
+	p2 = cmp.eq(len, #0);		/*  =0 */
+	align888 = or(ptr_in, ptr_out);	/*  %8 < 97 */
+	p0 = cmp.gtu(len, #23);		/*  %1, <24 */
+	p1 = cmp.eq(ptr_in, ptr_out);	/*  attempt to overwrite self */
+}
+{
+	p1 = or(p2, p1);
+	p3 = cmp.gtu(len, #95);		/*  %8 < 97 */
+	align888 = or(align888, len);	/*  %8 < 97 */
+	len8 = lsr(len, #3);		/*  %8 < 97 */
+}
+{
+	dcfetch(ptr_in);		/*  zero/ptrin=ptrout causes fetch */
+	p2 = bitsclr(align888, #7);	/*  %8 < 97  */
+	if(p1) jumpr r31;		/*  =0  */
+}
+{
+	p2 = and(p2,!p3);			/*  %8 < 97  */
+	if (p2.new) len = add(len, #-8);	/*  %8 < 97  */
+	if (p2.new) jump:NT .Ldwordaligned; 	/*  %8 < 97  */
+}
+{
+	if(!p0) jump .Lbytes23orless;	/*  %1, <24  */
+	mask.l = #LO(0x7fffffff);
+	/*  all bytes before line multiples of data  */
+	prolog = sub(#0, ptr_out);
+}
+{
+	/*  save r31 on stack, decrement sp by 16  */
+	allocframe(#24);
+	mask.h = #HI(0x7fffffff);
+	ptr_in_p_128 = add(ptr_in, #32);
+	back = cl0(len);
+}
+{
+	memd(sp+#0) = R17:16;		/*  save r16,r17 on stack6  */
+	r31.l = #LO(.Lmemcpy_return);	/*  set up final return pointer  */
+	prolog &= lsr(mask, back);
+	offset = and(ptr_in, #7);
+}
+{
+	memd(sp+#8) = R25:24;		/*  save r25,r24 on stack  */
+	dalign = sub(ptr_out, ptr_in);
+	r31.h = #HI(.Lmemcpy_return);	/*  set up final return pointer  */
+}
+{
+	/*  see if there if input buffer end if aligned  */
+	over = add(len, ptr_in);
+	back = add(len, offset);
+	memd(sp+#16) = R21:20;		/*  save r20,r21 on stack  */
+}
+{
+	noprolog = bitsclr(prolog, #7);
+	prolog = and(prolog, #31);
+	dcfetch(ptr_in_p_128);
+	ptr_in_p_128 = add(ptr_in_p_128, #32);
+}
+{
+	kernel = sub(len, prolog);
+	shift = asl(prolog, #3);
+	star3 = and(prolog, #7);
+	ptr_in = and(ptr_in, #-8);
+}
+{
+	prolog = lsr(prolog, #3);
+	epilog = and(kernel, #31);
+	ptr_out_p_32 = add(ptr_out, prolog);
+	over = and(over, #7);
+}
+{
+	p3 = cmp.gtu(back, #8);
+	kernel = lsr(kernel, #5);
+	dcfetch(ptr_in_p_128);
+	ptr_in_p_128 = add(ptr_in_p_128, #32);
+}
+{
+	p1 = cmp.eq(prolog, #0);
+	if(!p1.new) prolog = add(prolog, #1);
+	dcfetch(ptr_in_p_128);	/*  reserve the line 64bytes on  */
+	ptr_in_p_128 = add(ptr_in_p_128, #32);
+}
+{
+	nokernel = cmp.eq(kernel,#0);
+	dcfetch(ptr_in_p_128);	/* reserve the line 64bytes on  */
+	ptr_in_p_128 = add(ptr_in_p_128, #32);
+	shiftb = and(shift, #8);
+}
+{
+	dcfetch(ptr_in_p_128);		/*  reserve the line 64bytes on  */
+	ptr_in_p_128 = add(ptr_in_p_128, #32);
+	if(nokernel) jump .Lskip64;
+	p2 = cmp.eq(kernel, #1);	/*  skip ovr if kernel == 0  */
+}
+{
+	dczeroa(ptr_out_p_32);
+	/*  don't advance pointer  */
+	if(!p2) ptr_out_p_32 = add(ptr_out_p_32, #32);
+}
+{
+	dalign = and(dalign, #31);
+	dczeroa(ptr_out_p_32);
+}
+.Lskip64:
+{
+	data70 = memd(ptr_in++#16);
+	if(p3) dataF8 = memd(ptr_in+#8);
+	if(noprolog) jump .Lnoprolog32;
+	align = offset;
+}
+/*  upto initial 7 bytes  */
+{
+	ldata0 = valignb(dataF8, data70, align);
+	ifbyte = tstbit(shift,#3);
+	offset = add(offset, star3);
+}
+{
+	if(ifbyte) memb(ptr_out++#1) = data0;
+	ldata0 = lsr(ldata0, shiftb);
+	shiftb = and(shift, #16);
+	ifhword = tstbit(shift,#4);
+}
+{
+	if(ifhword) memh(ptr_out++#2) = data0;
+	ldata0 = lsr(ldata0, shiftb);
+	ifword = tstbit(shift,#5);
+	p2 = cmp.gtu(offset, #7);
+}
+{
+	if(ifword) memw(ptr_out++#4) = data0;
+	if(p2) data70 = dataF8;
+	if(p2) dataF8 = memd(ptr_in++#8);	/*  another 8 bytes  */
+	align = offset;
+}
+.Lnoprolog32:
+{
+	p3 = sp1loop0(.Ldword_loop_prolog, prolog)
+	rest = sub(len, star3);	/*  whats left after the loop  */
+	p0 = cmp.gt(over, #0);
+}
+	if(p0) rest = add(rest, #16);
+.Ldword_loop_prolog:
+{
+	if(p3) memd(ptr_out++#8) = ldata0;
+	ldata0 = valignb(dataF8, data70, align);
+	p0 = cmp.gt(rest, #16);
+}
+{
+	data70 = dataF8;
+	if(p0) dataF8 = memd(ptr_in++#8);
+	rest = add(rest, #-8);
+}:endloop0
+.Lkernel:
+{
+	/*  kernel is at least 32bytes  */
+	p3 = cmp.gtu(kernel, #0);
+	/*  last itn. remove edge effects  */
+	if(p3.new) kernel = add(kernel, #-1);
+	/*  dealt with in last dword loop  */
+	if(p3.new) epilog = add(epilog, #32);
+}
+{
+	nokernel = cmp.eq(kernel, #0);		/*  after adjustment, recheck */
+	if(nokernel.new) jump:NT .Lepilog;	/*  likely not taken  */
+	inc = combine(#32, #-1);
+	p3 = cmp.gtu(dalign, #24);
+}
+{
+	if(p3) jump .Lodd_alignment;
+}
+{
+	loop0(.Loword_loop_25to31, kernel);
+	kernel1 = cmp.gtu(kernel, #1);
+	rest = kernel;
+}
+	.falign
+.Loword_loop_25to31:
+{
+	dcfetch(ptr_in_p_128);	/*  prefetch 4 lines ahead  */
+	if(kernel1) ptr_out_p_32 = add(ptr_out_p_32, #32);
+}
+{
+	dczeroa(ptr_out_p_32);	/*  reserve the next 32bytes in cache  */
+	p3 = cmp.eq(kernel, rest);
+}
+{
+	/*  kernel -= 1  */
+	ptr_in_p_128kernel = vaddw(ptr_in_p_128kernel, inc);
+	/*  kill write on first iteration  */
+	if(!p3) memd(ptr_out++#8) = ldata1;
+	ldata1 = valignb(dataF8, data70, align);
+	data70 = memd(ptr_in++#8);
+}
+{
+	memd(ptr_out++#8) = ldata0;
+	ldata0 = valignb(data70, dataF8, align);
+	dataF8 = memd(ptr_in++#8);
+}
+{
+	memd(ptr_out++#8) = ldata1;
+	ldata1 = valignb(dataF8, data70, align);
+	data70 = memd(ptr_in++#8);
+}
+{
+	memd(ptr_out++#8) = ldata0;
+	ldata0 = valignb(data70, dataF8, align);
+	dataF8 = memd(ptr_in++#8);
+	kernel1 = cmp.gtu(kernel, #1);
+}:endloop0
+{
+	memd(ptr_out++#8) = ldata1;
+	jump .Lepilog;
+}
+.Lodd_alignment:
+{
+	loop0(.Loword_loop_00to24, kernel);
+	kernel1 = cmp.gtu(kernel, #1);
+	rest = add(kernel, #-1);
+}
+	.falign
+.Loword_loop_00to24:
+{
+	dcfetch(ptr_in_p_128);	/*  prefetch 4 lines ahead  */
+	ptr_in_p_128kernel = vaddw(ptr_in_p_128kernel, inc);
+	if(kernel1) ptr_out_p_32 = add(ptr_out_p_32, #32);
+}
+{
+	dczeroa(ptr_out_p_32);	/*  reserve the next 32bytes in cache  */
+}
+{
+	memd(ptr_out++#8) = ldata0;
+	ldata0 = valignb(dataF8, data70, align);
+	data70 = memd(ptr_in++#8);
+}
+{
+	memd(ptr_out++#8) = ldata0;
+	ldata0 = valignb(data70, dataF8, align);
+	dataF8 = memd(ptr_in++#8);
+}
+{
+	memd(ptr_out++#8) = ldata0;
+	ldata0 = valignb(dataF8, data70, align);
+	data70 = memd(ptr_in++#8);
+}
+{
+	memd(ptr_out++#8) = ldata0;
+	ldata0 = valignb(data70, dataF8, align);
+	dataF8 = memd(ptr_in++#8);
+	kernel1 = cmp.gtu(kernel, #1);
+}:endloop0
+.Lepilog:
+{
+	noepilog = cmp.eq(epilog,#0);
+	epilogdws = lsr(epilog, #3);
+	kernel = and(epilog, #7);
+}
+{
+	if(noepilog) jumpr r31;
+	if(noepilog) ptr_out = sub(ptr_out, len);
+	p3 = cmp.eq(epilogdws, #0);
+	shift2 = asl(epilog, #3);
+}
+{
+	shiftb = and(shift2, #32);
+	ifword = tstbit(epilog,#2);
+	if(p3) jump .Lepilog60;
+	if(!p3) epilog = add(epilog, #-16);
+}
+{
+	loop0(.Ldword_loop_epilog, epilogdws);
+	/*  stop criteria is lsbs unless = 0 then its 8  */
+	p3 = cmp.eq(kernel, #0);
+	if(p3.new) kernel= #8;
+	p1 = cmp.gt(over, #0);
+}
+	/*  if not aligned to end of buffer execute 1 more iteration  */
+	if(p1) kernel= #0;
+.Ldword_loop_epilog:
+{
+	memd(ptr_out++#8) = ldata0;
+	ldata0 = valignb(dataF8, data70, align);
+	p3 = cmp.gt(epilog, kernel);
+}
+{
+	data70 = dataF8;
+	if(p3) dataF8 = memd(ptr_in++#8);
+	epilog = add(epilog, #-8);
+}:endloop0
+/* copy last 7 bytes */
+.Lepilog60:
+{
+	if(ifword) memw(ptr_out++#4) = data0;
+	ldata0 = lsr(ldata0, shiftb);
+	ifhword = tstbit(epilog,#1);
+	shiftb = and(shift2, #16);
+}
+{
+	if(ifhword) memh(ptr_out++#2) = data0;
+	ldata0 = lsr(ldata0, shiftb);
+	ifbyte = tstbit(epilog,#0);
+	if(ifbyte.new) len = add(len, #-1);
+}
+{
+	if(ifbyte) memb(ptr_out) = data0;
+	ptr_out = sub(ptr_out, len);	/*  return dest pointer  */
+        jumpr r31;
+}
+/*  do byte copy for small n  */
+.Lbytes23orless:
+{
+	p3 = sp1loop0(.Lbyte_copy, len);
+	len = add(len, #-1);
+}
+.Lbyte_copy:
+{
+	data0 = memb(ptr_in++#1);
+	if(p3) memb(ptr_out++#1) = data0;
+}:endloop0
+{
+	memb(ptr_out) = data0;
+	ptr_out = sub(ptr_out, len);
+	jumpr r31;
+}
+/*  do dword copies for aligned in, out and length  */
+.Ldwordaligned:
+{
+	p3 = sp1loop0(.Ldword_copy, len8);
+}
+.Ldword_copy:
+{
+	if(p3) memd(ptr_out++#8) = ldata0;
+	ldata0 = memd(ptr_in++#8);
+}:endloop0
+{
+	memd(ptr_out) = ldata0;
+	ptr_out = sub(ptr_out, len);
+	jumpr r31;	/*  return to function caller  */
+}
+.Lmemcpy_return:
+	r21:20 = memd(sp+#16);	/*  restore r20+r21  */
+{
+	r25:24 = memd(sp+#8);	/*  restore r24+r25  */
+	r17:16 = memd(sp+#0);	/*  restore r16+r17  */
+}
+	deallocframe;	/*  restore r31 and incrment stack by 16  */
+	jumpr r31
diff --git a/arch/hexagon/lib/memset.S b/arch/hexagon/lib/memset.S
new file mode 100644
index 0000000..26d9614
--- /dev/null
+++ b/arch/hexagon/lib/memset.S
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2011 Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+
+/* HEXAGON assembly optimized memset */
+/* Replaces the standard library function memset */
+
+
+        .macro HEXAGON_OPT_FUNC_BEGIN name
+	.text
+	.p2align 4
+	.globl \name
+	.type  \name, @function
+\name:
+	.endm
+
+	.macro HEXAGON_OPT_FUNC_FINISH name
+	.size  \name, . - \name
+	.endm
+
+/* FUNCTION: memset (v2 version) */
+#if __HEXAGON_ARCH__ < 3
+HEXAGON_OPT_FUNC_BEGIN memset
+	{
+		r6 = #8
+		r7 = extractu(r0, #3 , #0)
+		p0 = cmp.eq(r2, #0)
+		p1 = cmp.gtu(r2, #7)
+	}
+	{
+		r4 = vsplatb(r1)
+		r8 = r0           /* leave r0 intact for return val  */
+		r9 = sub(r6, r7)  /* bytes until double alignment  */
+		if p0 jumpr r31   /* count == 0, so return  */
+	}
+	{
+		r3 = #0
+		r7 = #0
+		p0 = tstbit(r9, #0)
+		if p1 jump 2f /* skip byte loop */
+	}
+
+/* less than 8 bytes to set, so just set a byte at a time and return  */
+
+		loop0(1f, r2) /* byte loop */
+	.falign
+1: /* byte loop */
+	{
+		memb(r8++#1) = r4
+	}:endloop0
+		jumpr r31
+	.falign
+2: /* skip byte loop */
+	{
+		r6 = #1
+		p0 = tstbit(r9, #1)
+		p1 = cmp.eq(r2, #1)
+		if !p0 jump 3f /* skip initial byte store */
+	}
+	{
+		memb(r8++#1) = r4
+		r3:2 = sub(r3:2, r7:6)
+		if p1 jumpr r31
+	}
+	.falign
+3: /* skip initial byte store */
+	{
+		r6 = #2
+		p0 = tstbit(r9, #2)
+		p1 = cmp.eq(r2, #2)
+		if !p0 jump 4f /* skip initial half store */
+	}
+	{
+		memh(r8++#2) = r4
+		r3:2 = sub(r3:2, r7:6)
+		if p1 jumpr r31
+	}
+	.falign
+4: /* skip initial half store */
+	{
+		r6 = #4
+		p0 = cmp.gtu(r2, #7)
+		p1 = cmp.eq(r2, #4)
+		if !p0 jump 5f /* skip initial word store */
+	}
+	{
+		memw(r8++#4) = r4
+		r3:2 = sub(r3:2, r7:6)
+		p0 = cmp.gtu(r2, #11)
+		if p1 jumpr r31
+	}
+	.falign
+5: /* skip initial word store */
+	{
+		r10 = lsr(r2, #3)
+		p1 = cmp.eq(r3, #1)
+		if !p0 jump 7f /* skip double loop */
+	}
+	{
+		r5 = r4
+		r6 = #8
+		loop0(6f, r10) /* double loop */
+	}
+
+/* set bytes a double word at a time  */
+
+	.falign
+6: /* double loop */
+	{
+		memd(r8++#8) = r5:4
+		r3:2 = sub(r3:2, r7:6)
+		p1 = cmp.eq(r2, #8)
+	}:endloop0
+	.falign
+7: /* skip double loop */
+	{
+		p0 = tstbit(r2, #2)
+		if p1 jumpr r31
+	}
+	{
+		r6 = #4
+		p0 = tstbit(r2, #1)
+		p1 = cmp.eq(r2, #4)
+		if !p0 jump 8f /* skip final word store */
+	}
+	{
+		memw(r8++#4) = r4
+		r3:2 = sub(r3:2, r7:6)
+		if p1 jumpr r31
+	}
+	.falign
+8: /* skip final word store */
+	{
+		p1 = cmp.eq(r2, #2)
+		if !p0 jump 9f /* skip final half store */
+	}
+	{
+		memh(r8++#2) = r4
+		if p1 jumpr r31
+	}
+	.falign
+9: /* skip final half store */
+	{
+		memb(r8++#1) = r4
+		jumpr r31
+	}
+HEXAGON_OPT_FUNC_FINISH memset
+#endif
+
+
+/*  FUNCTION: memset (v3 and higher version)  */
+#if __HEXAGON_ARCH__ >= 3
+HEXAGON_OPT_FUNC_BEGIN memset
+	{
+		r7=vsplatb(r1)
+		r6 = r0
+		if (r2==#0) jump:nt .L1
+	}
+	{
+		r5:4=combine(r7,r7)
+		p0 = cmp.gtu(r2,#8)
+		if (p0.new) jump:nt .L3
+	}
+	{
+		r3 = r0
+		loop0(.L47,r2)
+	}
+	.falign
+.L47:
+	{
+		memb(r3++#1) = r1
+	}:endloop0 /* start=.L47 */
+		jumpr r31
+.L3:
+	{
+		p0 = tstbit(r0,#0)
+		if (!p0.new) jump:nt .L8
+		p1 = cmp.eq(r2, #1)
+	}
+	{
+		r6 = add(r0, #1)
+		r2 = add(r2,#-1)
+		memb(r0) = r1
+		if (p1) jump .L1
+	}
+.L8:
+	{
+		p0 = tstbit(r6,#1)
+		if (!p0.new) jump:nt .L10
+	}
+	{
+		r2 = add(r2,#-2)
+		memh(r6++#2) = r7
+		p0 = cmp.eq(r2, #2)
+		if (p0.new) jump:nt .L1
+	}
+.L10:
+	{
+		p0 = tstbit(r6,#2)
+		if (!p0.new) jump:nt .L12
+	}
+	{
+		r2 = add(r2,#-4)
+		memw(r6++#4) = r7
+		p0 = cmp.eq(r2, #4)
+		if (p0.new) jump:nt .L1
+	}
+.L12:
+	{
+		p0 = cmp.gtu(r2,#127)
+		if (!p0.new) jump:nt .L14
+	}
+		r3 = and(r6,#31)
+		if (r3==#0) jump:nt .L17
+	{
+		memd(r6++#8) = r5:4
+		r2 = add(r2,#-8)
+	}
+		r3 = and(r6,#31)
+		if (r3==#0) jump:nt .L17
+	{
+		memd(r6++#8) = r5:4
+		r2 = add(r2,#-8)
+	}
+		r3 = and(r6,#31)
+		if (r3==#0) jump:nt .L17
+	{
+		memd(r6++#8) = r5:4
+		r2 = add(r2,#-8)
+	}
+.L17:
+	{
+		r3 = lsr(r2,#5)
+		if (r1!=#0) jump:nt .L18
+	}
+	{
+		r8 = r3
+		r3 = r6
+		loop0(.L46,r3)
+	}
+	.falign
+.L46:
+	{
+		dczeroa(r6)
+		r6 = add(r6,#32)
+		r2 = add(r2,#-32)
+	}:endloop0 /* start=.L46 */
+.L14:
+	{
+		p0 = cmp.gtu(r2,#7)
+		if (!p0.new) jump:nt .L28
+		r8 = lsr(r2,#3)
+	}
+		loop0(.L44,r8)
+	.falign
+.L44:
+	{
+		memd(r6++#8) = r5:4
+		r2 = add(r2,#-8)
+	}:endloop0 /* start=.L44 */
+.L28:
+	{
+		p0 = tstbit(r2,#2)
+		if (!p0.new) jump:nt .L33
+	}
+	{
+		r2 = add(r2,#-4)
+		memw(r6++#4) = r7
+	}
+.L33:
+	{
+		p0 = tstbit(r2,#1)
+		if (!p0.new) jump:nt .L35
+	}
+	{
+		r2 = add(r2,#-2)
+		memh(r6++#2) = r7
+	}
+.L35:
+		p0 = cmp.eq(r2,#1)
+		if (p0) memb(r6) = r1
+.L1:
+		jumpr r31
+.L18:
+		loop0(.L45,r3)
+	.falign
+.L45:
+		dczeroa(r6)
+	{
+		memd(r6++#8) = r5:4
+		r2 = add(r2,#-32)
+	}
+		memd(r6++#8) = r5:4
+		memd(r6++#8) = r5:4
+	{
+		memd(r6++#8) = r5:4
+	}:endloop0 /* start=.L45  */
+		jump .L14
+HEXAGON_OPT_FUNC_FINISH memset
+#endif
diff --git a/arch/hexagon/mm/Makefile b/arch/hexagon/mm/Makefile
new file mode 100644
index 0000000..1a0be4d
--- /dev/null
+++ b/arch/hexagon/mm/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for Hexagon memory management subsystem
+#
+
+obj-y := init.o pgalloc.o ioremap.o uaccess.o vm_fault.o cache.o
+obj-y += copy_to_user.o copy_from_user.o strnlen_user.o vm_tlb.o
diff --git a/arch/hexagon/mm/cache.c b/arch/hexagon/mm/cache.c
new file mode 100644
index 0000000..c5cf6ee
--- /dev/null
+++ b/arch/hexagon/mm/cache.c
@@ -0,0 +1,128 @@
+/*
+ * Cache management functions for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/mm.h>
+#include <asm/cacheflush.h>
+#include <asm/hexagon_vm.h>
+
+#define spanlines(start, end) \
+	(((end - (start & ~(LINESIZE - 1))) >> LINEBITS) + 1)
+
+void flush_dcache_range(unsigned long start, unsigned long end)
+{
+	unsigned long lines = spanlines(start, end-1);
+	unsigned long i, flags;
+
+	start &= ~(LINESIZE - 1);
+
+	local_irq_save(flags);
+
+	for (i = 0; i < lines; i++) {
+		__asm__ __volatile__ (
+		"	dccleaninva(%0);	"
+		:
+		: "r" (start)
+		);
+		start += LINESIZE;
+	}
+	local_irq_restore(flags);
+}
+
+void flush_icache_range(unsigned long start, unsigned long end)
+{
+	unsigned long lines = spanlines(start, end-1);
+	unsigned long i, flags;
+
+	start &= ~(LINESIZE - 1);
+
+	local_irq_save(flags);
+
+	for (i = 0; i < lines; i++) {
+		__asm__ __volatile__ (
+			"	dccleana(%0); "
+			"	icinva(%0);	"
+			:
+			: "r" (start)
+		);
+		start += LINESIZE;
+	}
+	__asm__ __volatile__ (
+		"isync"
+	);
+	local_irq_restore(flags);
+}
+
+void hexagon_clean_dcache_range(unsigned long start, unsigned long end)
+{
+	unsigned long lines = spanlines(start, end-1);
+	unsigned long i, flags;
+
+	start &= ~(LINESIZE - 1);
+
+	local_irq_save(flags);
+
+	for (i = 0; i < lines; i++) {
+		__asm__ __volatile__ (
+		"	dccleana(%0);	"
+		:
+		: "r" (start)
+		);
+		start += LINESIZE;
+	}
+	local_irq_restore(flags);
+}
+
+void hexagon_inv_dcache_range(unsigned long start, unsigned long end)
+{
+	unsigned long lines = spanlines(start, end-1);
+	unsigned long i, flags;
+
+	start &= ~(LINESIZE - 1);
+
+	local_irq_save(flags);
+
+	for (i = 0; i < lines; i++) {
+		__asm__ __volatile__ (
+		"	dcinva(%0);	"
+		:
+		: "r" (start)
+		);
+		start += LINESIZE;
+	}
+	local_irq_restore(flags);
+}
+
+
+
+
+/*
+ * This is just really brutal and shouldn't be used anyways,
+ * especially on V2.  Left here just in case.
+ */
+void flush_cache_all_hexagon(void)
+{
+	unsigned long flags;
+	local_irq_save(flags);
+	__vmcache_ickill();
+	__vmcache_dckill();
+	__vmcache_l2kill();
+	local_irq_restore(flags);
+	mb();
+}
diff --git a/arch/hexagon/mm/copy_from_user.S b/arch/hexagon/mm/copy_from_user.S
new file mode 100644
index 0000000..8eb1d4d
--- /dev/null
+++ b/arch/hexagon/mm/copy_from_user.S
@@ -0,0 +1,114 @@
+/*
+ * User memory copy functions for kernel
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * The right way to do this involves valignb
+ * The easy way to do this is only speed up src/dest similar alignment.
+ */
+
+/*
+ * Copy to/from user are the same, except that for packets with a load and
+ * a store, I don't know how to tell which kind of exception we got.
+ * Therefore, we duplicate the function, and handle faulting addresses
+ * differently for each function
+ */
+
+/*
+ * copy from user: loads can fault
+ */
+#define src_sav r13
+#define dst_sav r12
+#define src_dst_sav r13:12
+#define d_dbuf r15:14
+#define w_dbuf r15
+
+#define dst r0
+#define src r1
+#define bytes r2
+#define loopcount r5
+
+#define FUNCNAME __copy_from_user_hexagon
+#include "copy_user_template.S"
+
+	/* LOAD FAULTS from COPY_FROM_USER */
+
+	/* Alignment loop.  r2 has been updated. Return it. */
+	.falign
+1009:
+2009:
+4009:
+	{
+		r0 = r2
+		jumpr r31
+	}
+	/* Normal copy loops. Do epilog. Use src-src_sav to compute distance */
+	/* X - (A - B) == X + B - A */
+	.falign
+8089:
+	{
+		memd(dst) = d_dbuf
+		r2 += sub(src_sav,src)
+	}
+	{
+		r0 = r2
+		jumpr r31
+	}
+	.falign
+4089:
+	{
+		memw(dst) = w_dbuf
+		r2 += sub(src_sav,src)
+	}
+	{
+		r0 = r2
+		jumpr r31
+	}
+	.falign
+2089:
+	{
+		memh(dst) = w_dbuf
+		r2 += sub(src_sav,src)
+	}
+	{
+		r0 = r2
+		jumpr r31
+	}
+	.falign
+1089:
+	{
+		memb(dst) = w_dbuf
+		r2 += sub(src_sav,src)
+	}
+	{
+		r0 = r2
+		jumpr r31
+	}
+
+	/* COPY FROM USER: only loads can fail */
+
+	.section __ex_table,"a"
+	.long 1000b,1009b
+	.long 2000b,2009b
+	.long 4000b,4009b
+	.long 8080b,8089b
+	.long 4080b,4089b
+	.long 2080b,2089b
+	.long 1080b,1089b
+	.previous
diff --git a/arch/hexagon/mm/copy_to_user.S b/arch/hexagon/mm/copy_to_user.S
new file mode 100644
index 0000000..cb9740e
--- /dev/null
+++ b/arch/hexagon/mm/copy_to_user.S
@@ -0,0 +1,92 @@
+/*
+ * User memory copying routines for the Hexagon Kernel
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/* The right way to do this involves valignb
+ * The easy way to do this is only speed up src/dest similar alignment.
+ */
+
+/*
+ * Copy to/from user are the same, except that for packets with a load and
+ * a store, I don't know how to tell which kind of exception we got.
+ * Therefore, we duplicate the function, and handle faulting addresses
+ * differently for each function
+ */
+
+/*
+ * copy to user: stores can fault
+ */
+#define src_sav r13
+#define dst_sav r12
+#define src_dst_sav r13:12
+#define d_dbuf r15:14
+#define w_dbuf r15
+
+#define dst r0
+#define src r1
+#define bytes r2
+#define loopcount r5
+
+#define FUNCNAME __copy_to_user_hexagon
+#include "copy_user_template.S"
+
+	/* STORE FAULTS from COPY_TO_USER */
+	.falign
+1109:
+2109:
+4109:
+	/* Alignment loop.  r2 has been updated.  Return it. */
+	{
+		r0 = r2
+		jumpr r31
+	}
+	/* Normal copy loops.  Use dst-dst_sav to compute distance */
+	/* dst holds best write, no need to unwind any loops */
+	/* X - (A - B) == X + B - A */
+	.falign
+8189:
+8199:
+4189:
+4199:
+2189:
+2199:
+1189:
+1199:
+	{
+		r2 += sub(dst_sav,dst)
+	}
+	{
+		r0 = r2
+		jumpr r31
+	}
+
+	/* COPY TO USER: only stores can fail */
+	.section __ex_table,"a"
+	.long 1100b,1109b
+	.long 2100b,2109b
+	.long 4100b,4109b
+	.long 8180b,8189b
+	.long 8190b,8199b
+	.long 4180b,4189b
+	.long 4190b,4199b
+	.long 2180b,2189b
+	.long 2190b,2199b
+	.long 1180b,1189b
+	.long 1190b,1199b
+	.previous
diff --git a/arch/hexagon/mm/copy_user_template.S b/arch/hexagon/mm/copy_user_template.S
new file mode 100644
index 0000000..08d7d7b
--- /dev/null
+++ b/arch/hexagon/mm/copy_user_template.S
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/* Numerology:
+ * WXYZ
+ * W: width in bytes
+ * X: Load=0, Store=1
+ * Y: Location 0=preamble,8=loop,9=epilog
+ * Z: Location=0,handler=9
+ */
+	.text
+	.global FUNCNAME
+	.type FUNCNAME, @function
+	.p2align 5
+FUNCNAME:
+	{
+		p0 = cmp.gtu(bytes,#0)
+		if (!p0.new) jump:nt .Ldone
+		r3 = or(dst,src)
+		r4 = xor(dst,src)
+	}
+	{
+		p1 = cmp.gtu(bytes,#15)
+		p0 = bitsclr(r3,#7)
+		if (!p0.new) jump:nt .Loop_not_aligned_8
+		src_dst_sav = combine(src,dst)
+	}
+
+	{
+		loopcount = lsr(bytes,#3)
+		if (!p1) jump .Lsmall
+	}
+	p3=sp1loop0(.Loop8,loopcount)
+.Loop8:
+8080:
+8180:
+	{
+		if (p3) memd(dst++#8) = d_dbuf
+		d_dbuf = memd(src++#8)
+	}:endloop0
+8190:
+	{
+		memd(dst++#8) = d_dbuf
+		bytes -= asl(loopcount,#3)
+		jump .Lsmall
+	}
+
+.Loop_not_aligned_8:
+	{
+		p0 = bitsclr(r4,#7)
+		if (p0.new) jump:nt .Lalign
+	}
+	{
+		p0 = bitsclr(r3,#3)
+		if (!p0.new) jump:nt .Loop_not_aligned_4
+		p1 = cmp.gtu(bytes,#7)
+	}
+
+	{
+		if (!p1) jump .Lsmall
+		loopcount = lsr(bytes,#2)
+	}
+	p3=sp1loop0(.Loop4,loopcount)
+.Loop4:
+4080:
+4180:
+	{
+		if (p3) memw(dst++#4) = w_dbuf
+		w_dbuf = memw(src++#4)
+	}:endloop0
+4190:
+	{
+		memw(dst++#4) = w_dbuf
+		bytes -= asl(loopcount,#2)
+		jump .Lsmall
+	}
+
+.Loop_not_aligned_4:
+	{
+		p0 = bitsclr(r3,#1)
+		if (!p0.new) jump:nt .Loop_not_aligned
+		p1 = cmp.gtu(bytes,#3)
+	}
+
+	{
+		if (!p1) jump .Lsmall
+		loopcount = lsr(bytes,#1)
+	}
+	p3=sp1loop0(.Loop2,loopcount)
+.Loop2:
+2080:
+2180:
+	{
+		if (p3) memh(dst++#2) = w_dbuf
+		w_dbuf = memuh(src++#2)
+	}:endloop0
+2190:
+	{
+		memh(dst++#2) = w_dbuf
+		bytes -= asl(loopcount,#1)
+		jump .Lsmall
+	}
+
+.Loop_not_aligned: /* Works for as small as one byte */
+	p3=sp1loop0(.Loop1,bytes)
+.Loop1:
+1080:
+1180:
+	{
+		if (p3) memb(dst++#1) = w_dbuf
+		w_dbuf = memub(src++#1)
+	}:endloop0
+	/* Done */
+1190:
+	{
+		memb(dst) = w_dbuf
+		jumpr r31
+		r0 = #0
+	}
+
+.Lsmall:
+	{
+		p0 = cmp.gtu(bytes,#0)
+		if (p0.new) jump:nt .Loop_not_aligned
+	}
+.Ldone:
+	{
+		r0 = #0
+		jumpr r31
+	}
+	.falign
+.Lalign:
+1000:
+	{
+		if (p0.new) w_dbuf = memub(src)
+		p0 = tstbit(src,#0)
+		if (!p1) jump .Lsmall
+	}
+1100:
+	{
+		if (p0) memb(dst++#1) = w_dbuf
+		if (p0) bytes = add(bytes,#-1)
+		if (p0) src = add(src,#1)
+	}
+2000:
+	{
+		if (p0.new) w_dbuf = memuh(src)
+		p0 = tstbit(src,#1)
+		if (!p1) jump .Lsmall
+	}
+2100:
+	{
+		if (p0) memh(dst++#2) = w_dbuf
+		if (p0) bytes = add(bytes,#-2)
+		if (p0) src = add(src,#2)
+	}
+4000:
+	{
+		if (p0.new) w_dbuf = memw(src)
+		p0 = tstbit(src,#2)
+		if (!p1) jump .Lsmall
+	}
+4100:
+	{
+		if (p0) memw(dst++#4) = w_dbuf
+		if (p0) bytes = add(bytes,#-4)
+		if (p0) src = add(src,#4)
+		jump FUNCNAME
+	}
+	.size FUNCNAME,.-FUNCNAME
diff --git a/arch/hexagon/mm/init.c b/arch/hexagon/mm/init.c
new file mode 100644
index 0000000..b57d741
--- /dev/null
+++ b/arch/hexagon/mm/init.c
@@ -0,0 +1,276 @@
+/*
+ * Memory subsystem initialization for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <asm/atomic.h>
+#include <linux/highmem.h>
+#include <asm/tlb.h>
+#include <asm/sections.h>
+#include <asm/vm_mmu.h>
+
+/*
+ * Define a startpg just past the end of the kernel image and a lastpg
+ * that corresponds to the end of real or simulated platform memory.
+ */
+#define bootmem_startpg (PFN_UP(((unsigned long) _end) - PAGE_OFFSET))
+
+unsigned long bootmem_lastpg;  /*  Should be set by platform code  */
+
+/*  Set as variable to limit PMD copies  */
+int max_kernel_seg = 0x303;
+
+/*  think this should be (page_size-1) the way it's used...*/
+unsigned long zero_page_mask;
+
+/*  indicate pfn's of high memory  */
+unsigned long highstart_pfn, highend_pfn;
+
+/* struct mmu_gather defined in asm-generic.h;  */
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+
+/* Default cache attribute for newly created page tables */
+unsigned long _dflt_cache_att = CACHEDEF;
+
+/*
+ * The current "generation" of kernel map, which should not roll
+ * over until Hell freezes over.  Actual bound in years needs to be
+ * calculated to confirm.
+ */
+DEFINE_SPINLOCK(kmap_gen_lock);
+
+/*  checkpatch says don't init this to 0.  */
+unsigned long long kmap_generation;
+
+/*
+ * mem_init - initializes memory
+ *
+ * Frees up bootmem
+ * Fixes up more stuff for HIGHMEM
+ * Calculates and displays memory available/used
+ */
+void __init mem_init(void)
+{
+	/*  No idea where this is actually declared.  Seems to evade LXR.  */
+	totalram_pages += free_all_bootmem();
+	num_physpages = bootmem_lastpg;	/*  seriously, what?  */
+
+	printk(KERN_INFO "totalram_pages = %ld\n", totalram_pages);
+
+	/*
+	 *  To-Do:  someone somewhere should wipe out the bootmem map
+	 *  after we're done?
+	 */
+
+	/*
+	 * This can be moved to some more virtual-memory-specific
+	 * initialization hook at some point.  Set the init_mm
+	 * descriptors "context" value to point to the initial
+	 * kernel segment table's physical address.
+	 */
+	init_mm.context.ptbase = __pa(init_mm.pgd);
+}
+
+/*
+ * free_initmem - frees memory used by stuff declared with __init
+ *
+ * Todo:  free pages between __init_begin and __init_end; possibly
+ * some devtree related stuff as well.
+ */
+void __init_refok free_initmem(void)
+{
+}
+
+/*
+ * free_initrd_mem - frees...  initrd memory.
+ * @start - start of init memory
+ * @end - end of init memory
+ *
+ * Apparently has to be passed the address of the initrd memory.
+ *
+ * Wrapped by #ifdef CONFIG_BLKDEV_INITRD
+ */
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+}
+
+void sync_icache_dcache(pte_t pte)
+{
+	unsigned long addr;
+	struct page *page;
+
+	page = pte_page(pte);
+	addr = (unsigned long) page_address(page);
+
+	__vmcache_idsync(addr, PAGE_SIZE);
+}
+
+/*
+ * In order to set up page allocator "nodes",
+ * somebody has to call free_area_init() for UMA.
+ *
+ * In this mode, we only have one pg_data_t
+ * structure: contig_mem_data.
+ */
+void __init paging_init(void)
+{
+	unsigned long zones_sizes[MAX_NR_ZONES] = {0, };
+
+	/*
+	 *  This is not particularly well documented anywhere, but
+	 *  give ZONE_NORMAL all the memory, including the big holes
+	 *  left by the kernel+bootmem_map which are already left as reserved
+	 *  in the bootmem_map; free_area_init should see those bits and
+	 *  adjust accordingly.
+	 */
+
+	zones_sizes[ZONE_NORMAL] = max_low_pfn;
+
+	free_area_init(zones_sizes);  /*  sets up the zonelists and mem_map  */
+
+	/*
+	 * Start of high memory area.  Will probably need something more
+	 * fancy if we...  get more fancy.
+	 */
+	high_memory = (void *)((bootmem_lastpg + 1) << PAGE_SHIFT);
+}
+
+#ifndef DMA_RESERVE
+#define DMA_RESERVE		(4)
+#endif
+
+#define DMA_CHUNKSIZE		(1<<22)
+#define DMA_RESERVED_BYTES	(DMA_RESERVE * DMA_CHUNKSIZE)
+
+/*
+ * Pick out the memory size.  We look for mem=size,
+ * where size is "size[KkMm]"
+ */
+static int __init early_mem(char *p)
+{
+	unsigned long size;
+	char *endp;
+
+	size = memparse(p, &endp);
+
+	bootmem_lastpg = PFN_DOWN(size);
+
+	return 0;
+}
+early_param("mem", early_mem);
+
+size_t hexagon_coherent_pool_size = (size_t) (DMA_RESERVE << 22);
+
+void __init setup_arch_memory(void)
+{
+	int bootmap_size;
+	/*  XXX Todo: this probably should be cleaned up  */
+	u32 *segtable = (u32 *) &swapper_pg_dir[0];
+	u32 *segtable_end;
+
+	/*
+	 * Set up boot memory allocator
+	 *
+	 * The Gorman book also talks about these functions.
+	 * This needs to change for highmem setups.
+	 */
+
+	/* Memory size needs to be a multiple of 16M */
+	bootmem_lastpg = PFN_DOWN((bootmem_lastpg << PAGE_SHIFT) &
+		~((BIG_KERNEL_PAGE_SIZE) - 1));
+
+	/*
+	 * Reserve the top DMA_RESERVE bytes of RAM for DMA (uncached)
+	 * memory allocation
+	 */
+	bootmap_size = init_bootmem(bootmem_startpg, bootmem_lastpg -
+				    PFN_DOWN(DMA_RESERVED_BYTES));
+
+	printk(KERN_INFO "bootmem_startpg:  0x%08lx\n", bootmem_startpg);
+	printk(KERN_INFO "bootmem_lastpg:  0x%08lx\n", bootmem_lastpg);
+	printk(KERN_INFO "bootmap_size:  %d\n", bootmap_size);
+	printk(KERN_INFO "max_low_pfn:  0x%08lx\n", max_low_pfn);
+
+	/*
+	 * The default VM page tables (will be) populated with
+	 * VA=PA+PAGE_OFFSET mapping.  We go in and invalidate entries
+	 * higher than what we have memory for.
+	 */
+
+	/*  this is pointer arithmetic; each entry covers 4MB  */
+	segtable = segtable + (PAGE_OFFSET >> 22);
+
+	/*  this actually only goes to the end of the first gig  */
+	segtable_end = segtable + (1<<(30-22));
+
+	/*  Move forward to the start of empty pages  */
+	segtable += bootmem_lastpg >> (22-PAGE_SHIFT);
+
+	{
+	    int i;
+
+	    for (i = 1 ; i <= DMA_RESERVE ; i++)
+		segtable[-i] = ((segtable[-i] & __HVM_PTE_PGMASK_4MB)
+				| __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X
+				| __HEXAGON_C_UNC << 6
+				| __HVM_PDE_S_4MB);
+	}
+
+	printk(KERN_INFO "clearing segtable from %p to %p\n", segtable,
+		segtable_end);
+	while (segtable < (segtable_end-8))
+		*(segtable++) = __HVM_PDE_S_INVALID;
+	/* stop the pointer at the device I/O 4MB page  */
+
+	printk(KERN_INFO "segtable = %p (should be equal to _K_io_map)\n",
+		segtable);
+
+#if 0
+	/*  Other half of the early device table from vm_init_segtable. */
+	printk(KERN_INFO "&_K_init_devicetable = 0x%08x\n",
+		(unsigned long) _K_init_devicetable-PAGE_OFFSET);
+	*segtable = ((u32) (unsigned long) _K_init_devicetable-PAGE_OFFSET) |
+		__HVM_PDE_S_4KB;
+	printk(KERN_INFO "*segtable = 0x%08x\n", *segtable);
+#endif
+
+	/*
+	 * Free all the memory that wasn't taken up by the bootmap, the DMA
+	 * reserve, or kernel itself.
+	 */
+	free_bootmem(PFN_PHYS(bootmem_startpg)+bootmap_size,
+		     PFN_PHYS(bootmem_lastpg - bootmem_startpg) - bootmap_size -
+		     DMA_RESERVED_BYTES);
+
+	/*
+	 *  The bootmem allocator seemingly just lives to feed memory
+	 *  to the paging system
+	 */
+	printk(KERN_INFO "PAGE_SIZE=%lu\n", PAGE_SIZE);
+	paging_init();  /*  See Gorman Book, 2.3  */
+
+	/*
+	 *  At this point, the page allocator is kind of initialized, but
+	 *  apparently no pages are available (just like with the bootmem
+	 *  allocator), and need to be freed themselves via mem_init(),
+	 *  which is called by start_kernel() later on in the process
+	 */
+}
diff --git a/arch/hexagon/mm/ioremap.c b/arch/hexagon/mm/ioremap.c
new file mode 100644
index 0000000..3a37bc3
--- /dev/null
+++ b/arch/hexagon/mm/ioremap.c
@@ -0,0 +1,56 @@
+/*
+ * I/O remap functions for Hexagon
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/io.h>
+#include <linux/vmalloc.h>
+
+void __iomem *ioremap_nocache(unsigned long phys_addr, unsigned long size)
+{
+	unsigned long last_addr, addr;
+	unsigned long offset = phys_addr & ~PAGE_MASK;
+	struct vm_struct *area;
+
+	pgprot_t prot = __pgprot(_PAGE_PRESENT|_PAGE_READ|_PAGE_WRITE
+					|(__HEXAGON_C_DEV << 6));
+
+	last_addr = phys_addr + size - 1;
+
+	/*  Wrapping not allowed  */
+	if (!size || (last_addr < phys_addr))
+		return NULL;
+
+	/*  Rounds up to next page size, including whole-page offset */
+	size = PAGE_ALIGN(offset + size);
+
+	area = get_vm_area(size, VM_IOREMAP);
+	addr = (unsigned long)area->addr;
+
+	if (ioremap_page_range(addr, addr+size, phys_addr, prot)) {
+		vunmap((void *)addr);
+		return NULL;
+	}
+
+	return (void __iomem *) (offset + addr);
+}
+
+void __iounmap(const volatile void __iomem *addr)
+{
+	vunmap((void *) ((unsigned long) addr & PAGE_MASK));
+}
diff --git a/arch/hexagon/mm/pgalloc.c b/arch/hexagon/mm/pgalloc.c
new file mode 100644
index 0000000..b175e2d
--- /dev/null
+++ b/arch/hexagon/mm/pgalloc.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/init.h>
+
+void __init pgtable_cache_init(void)
+{
+}
diff --git a/arch/hexagon/mm/strnlen_user.S b/arch/hexagon/mm/strnlen_user.S
new file mode 100644
index 0000000..5c6a16c
--- /dev/null
+++ b/arch/hexagon/mm/strnlen_user.S
@@ -0,0 +1,139 @@
+/*
+ * User string length functions for kernel
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#define isrc	r0
+#define max	r1	/*  Do not change!  */
+
+#define end	r2
+#define tmp1	r3
+
+#define obo	r6	/*  off-by-one  */
+#define start	r7
+#define mod8	r8
+#define dbuf    r15:14
+#define dcmp	r13:12
+
+/*
+ * The vector mask version of this turned out *really* badly.
+ * The hardware loop version also turned out *really* badly.
+ * Seems straight pointer arithmetic basically wins here.
+ */
+
+#define fname __strnlen_user
+
+	.text
+	.global fname
+	.type fname, @function
+	.p2align 5  /*  why?  */
+fname:
+	{
+		mod8 = and(isrc,#7);
+		end = add(isrc,max);
+		start = isrc;
+	}
+	{
+		P0 = cmp.eq(mod8,#0);
+		mod8 = and(end,#7);
+		dcmp = #0;
+		if (P0.new) jump:t dw_loop;	/*  fire up the oven  */
+	}
+
+alignment_loop:
+fail_1:	{
+		tmp1 = memb(start++#1);
+	}
+	{
+		P0 = cmp.eq(tmp1,#0);
+		if (P0.new) jump:nt exit_found;
+		P1 = cmp.gtu(end,start);
+		mod8 = and(start,#7);
+	}
+	{
+		if (!P1) jump exit_error;  /*  hit the end  */
+		P0 = cmp.eq(mod8,#0);
+	}
+	{
+		if (!P0) jump alignment_loop;
+	}
+
+
+
+dw_loop:
+fail_2:	{
+		dbuf = memd(start);
+		obo = add(start,#1);
+	}
+	{
+		P0 = vcmpb.eq(dbuf,dcmp);
+	}
+	{
+		tmp1 = P0;
+		P0 = cmp.gtu(end,start);
+	}
+	{
+		tmp1 = ct0(tmp1);
+		mod8 = and(end,#7);
+		if (!P0) jump end_check;
+	}
+	{
+		P0 = cmp.eq(tmp1,#32);
+		if (!P0.new) jump:nt exit_found;
+		if (!P0.new) start = add(obo,tmp1);
+	}
+	{
+		start = add(start,#8);
+		jump dw_loop;
+	}	/*  might be nice to combine these jumps...   */
+
+
+end_check:
+	{
+		P0 = cmp.gt(tmp1,mod8);
+		if (P0.new) jump:nt exit_error;	/*  neverfound!  */
+		start = add(obo,tmp1);
+	}
+
+exit_found:
+	{
+		R0 = sub(start,isrc);
+		jumpr R31;
+	}
+
+exit_error:
+	{
+		R0 = add(max,#1);
+		jumpr R31;
+	}
+
+	/*  Uh, what does the "fixup" return here?  */
+	.falign
+fix_1:
+	{
+		R0 = #0;
+		jumpr R31;
+	}
+
+	.size fname,.-fname
+
+
+.section __ex_table,"a"
+.long fail_1,fix_1
+.long fail_2,fix_1
+.previous
diff --git a/arch/hexagon/mm/uaccess.c b/arch/hexagon/mm/uaccess.c
new file mode 100644
index 0000000..e748108
--- /dev/null
+++ b/arch/hexagon/mm/uaccess.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * Support for user memory access from kernel.  This will
+ * probably be inlined for performance at some point, but
+ * for ease of debug, and to a lesser degree for code size,
+ * we implement here as subroutines.
+ */
+#include <linux/types.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+
+/*
+ * For clear_user(), exploit previously defined copy_to_user function
+ * and the fact that we've got a handy zero page defined in kernel/head.S
+ *
+ * dczero here would be even faster.
+ */
+__kernel_size_t __clear_user_hexagon(void __user *dest, unsigned long count)
+{
+	long uncleared;
+
+	while (count > PAGE_SIZE) {
+		uncleared = __copy_to_user_hexagon(dest, &empty_zero_page,
+						PAGE_SIZE);
+		if (uncleared)
+			return count - (PAGE_SIZE - uncleared);
+		count -= PAGE_SIZE;
+		dest += PAGE_SIZE;
+	}
+	if (count)
+		count = __copy_to_user_hexagon(dest, &empty_zero_page, count);
+
+	return count;
+}
+
+unsigned long clear_user_hexagon(void __user *dest, unsigned long count)
+{
+	if (!access_ok(VERIFY_WRITE, dest, count))
+		return count;
+	else
+		return __clear_user_hexagon(dest, count);
+}
diff --git a/arch/hexagon/mm/vm_fault.c b/arch/hexagon/mm/vm_fault.c
new file mode 100644
index 0000000..c10b76f
--- /dev/null
+++ b/arch/hexagon/mm/vm_fault.c
@@ -0,0 +1,187 @@
+/*
+ * Memory fault handling for Hexagon
+ *
+ * Copyright (c) 2010-2011 Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * Page fault handling for the Hexagon Virtual Machine.
+ * Can also be called by a native port emulating the HVM
+ * execptions.
+ */
+
+#include <asm/pgtable.h>
+#include <asm/traps.h>
+#include <asm/uaccess.h>
+#include <linux/mm.h>
+#include <linux/signal.h>
+#include <linux/module.h>
+#include <linux/hardirq.h>
+
+/*
+ * Decode of hardware exception sends us to one of several
+ * entry points.  At each, we generate canonical arguments
+ * for handling by the abstract memory management code.
+ */
+#define FLT_IFETCH     -1
+#define FLT_LOAD        0
+#define FLT_STORE       1
+
+
+/*
+ * Canonical page fault handler
+ */
+void do_page_fault(unsigned long address, long cause, struct pt_regs *regs)
+{
+	struct vm_area_struct *vma;
+	struct mm_struct *mm = current->mm;
+	siginfo_t info;
+	int si_code = SEGV_MAPERR;
+	int fault;
+	const struct exception_table_entry *fixup;
+
+	/*
+	 * If we're in an interrupt or have no user context,
+	 * then must not take the fault.
+	 */
+	if (unlikely(in_interrupt() || !mm))
+		goto no_context;
+
+	local_irq_enable();
+
+	down_read(&mm->mmap_sem);
+	vma = find_vma(mm, address);
+	if (!vma)
+		goto bad_area;
+
+	if (vma->vm_start <= address)
+		goto good_area;
+
+	if (!(vma->vm_flags & VM_GROWSDOWN))
+		goto bad_area;
+
+	if (expand_stack(vma, address))
+		goto bad_area;
+
+good_area:
+	/* Address space is OK.  Now check access rights. */
+	si_code = SEGV_ACCERR;
+
+	switch (cause) {
+	case FLT_IFETCH:
+		if (!(vma->vm_flags & VM_EXEC))
+			goto bad_area;
+		break;
+	case FLT_LOAD:
+		if (!(vma->vm_flags & VM_READ))
+			goto bad_area;
+		break;
+	case FLT_STORE:
+		if (!(vma->vm_flags & VM_WRITE))
+			goto bad_area;
+		break;
+	}
+
+	fault = handle_mm_fault(mm, vma, address, (cause > 0));
+
+	/* The most common case -- we are done. */
+	if (likely(!(fault & VM_FAULT_ERROR))) {
+		if (fault & VM_FAULT_MAJOR)
+			current->maj_flt++;
+		else
+			current->min_flt++;
+
+		up_read(&mm->mmap_sem);
+		return;
+	}
+
+	up_read(&mm->mmap_sem);
+
+	/* Handle copyin/out exception cases */
+	if (!user_mode(regs))
+		goto no_context;
+
+	if (fault & VM_FAULT_OOM) {
+		pagefault_out_of_memory();
+		return;
+	}
+
+	/* User-mode address is in the memory map, but we are
+	 * unable to fix up the page fault.
+	 */
+	if (fault & VM_FAULT_SIGBUS) {
+		info.si_signo = SIGBUS;
+		info.si_code = BUS_ADRERR;
+	}
+	/* Address is not in the memory map */
+	else {
+		info.si_signo = SIGSEGV;
+		info.si_code = SEGV_ACCERR;
+	}
+	info.si_errno = 0;
+	info.si_addr = (void __user *)address;
+	force_sig_info(info.si_code, &info, current);
+	return;
+
+bad_area:
+	up_read(&mm->mmap_sem);
+
+	if (user_mode(regs)) {
+		info.si_signo = SIGSEGV;
+		info.si_errno = 0;
+		info.si_code = si_code;
+		info.si_addr = (void *)address;
+		force_sig_info(SIGSEGV, &info, current);
+		return;
+	}
+	/* Kernel-mode fault falls through */
+
+no_context:
+	fixup = search_exception_tables(pt_elr(regs));
+	if (fixup) {
+		pt_set_elr(regs, fixup->fixup);
+		return;
+	}
+
+	/* Things are looking very, very bad now */
+	bust_spinlocks(1);
+	printk(KERN_EMERG "Unable to handle kernel paging request at "
+		"virtual address 0x%08lx, regs %p\n", address, regs);
+	die("Bad Kernel VA", regs, SIGKILL);
+}
+
+
+void read_protection_fault(struct pt_regs *regs)
+{
+	unsigned long badvadr = pt_badva(regs);
+
+	do_page_fault(badvadr, FLT_LOAD, regs);
+}
+
+void write_protection_fault(struct pt_regs *regs)
+{
+	unsigned long badvadr = pt_badva(regs);
+
+	do_page_fault(badvadr, FLT_STORE, regs);
+}
+
+void execute_protection_fault(struct pt_regs *regs)
+{
+	unsigned long badvadr = pt_badva(regs);
+
+	do_page_fault(badvadr, FLT_IFETCH, regs);
+}
diff --git a/arch/hexagon/mm/vm_tlb.c b/arch/hexagon/mm/vm_tlb.c
new file mode 100644
index 0000000..c6ff415
--- /dev/null
+++ b/arch/hexagon/mm/vm_tlb.c
@@ -0,0 +1,93 @@
+/*
+ * Hexagon Virtual Machine TLB functions
+ *
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ * The Hexagon Virtual Machine conceals the real workings of
+ * the TLB, but there are one or two functions that need to
+ * be instantiated for it, differently from a native build.
+ */
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <asm/hexagon_vm.h>
+
+/*
+ * Initial VM implementation has only one map active at a time, with
+ * TLB purgings on changes.  So either we're nuking the current map,
+ * or it's a no-op.  This operation is messy on true SMPs where other
+ * processors must be induced to flush the copies in their local TLBs,
+ * but Hexagon thread-based virtual processors share the same MMU.
+ */
+void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+			unsigned long end)
+{
+	struct mm_struct *mm = vma->vm_mm;
+
+	if (mm->context.ptbase == current->active_mm->context.ptbase)
+		__vmclrmap((void *)start, end - start);
+}
+
+/*
+ * Flush a page from the kernel virtual map - used by highmem
+ */
+void flush_tlb_one(unsigned long vaddr)
+{
+	__vmclrmap((void *)vaddr, PAGE_SIZE);
+}
+
+/*
+ * Flush all TLBs across all CPUs, virtual or real.
+ * A single Hexagon core has 6 thread contexts but
+ * only one TLB.
+ */
+void tlb_flush_all(void)
+{
+	/*  should probably use that fixaddr end or whateve label  */
+	__vmclrmap(0, 0xffff0000);
+}
+
+/*
+ * Flush TLB entries associated with a given mm_struct mapping.
+ */
+void flush_tlb_mm(struct mm_struct *mm)
+{
+	/* Current Virtual Machine has only one map active at a time */
+	if (current->active_mm->context.ptbase == mm->context.ptbase)
+		tlb_flush_all();
+}
+
+/*
+ * Flush TLB state associated with a page of a vma.
+ */
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long vaddr)
+{
+	struct mm_struct *mm = vma->vm_mm;
+
+	if (mm->context.ptbase  == current->active_mm->context.ptbase)
+		__vmclrmap((void *)vaddr, PAGE_SIZE);
+}
+
+/*
+ * Flush TLB entries associated with a kernel address range.
+ * Like flush range, but without the check on the vma->vm_mm.
+ */
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+		__vmclrmap((void *)start, end - start);
+}
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 3ff7785..27489b6 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -92,7 +92,7 @@ config HAVE_SETUP_PER_CPU_AREA
 	def_bool y
 
 config GENERIC_GPIO
-	def_bool y
+	bool
 
 config DMI
 	bool
diff --git a/arch/ia64/configs/generic_defconfig b/arch/ia64/configs/generic_defconfig
index 43ab1cd..954d81e 100644
--- a/arch/ia64/configs/generic_defconfig
+++ b/arch/ia64/configs/generic_defconfig
@@ -87,6 +87,7 @@ CONFIG_NET_ETHERNET=y
 CONFIG_NET_TULIP=y
 CONFIG_TULIP=m
 CONFIG_NET_PCI=y
+CONFIG_NET_VENDOR_INTEL=y
 CONFIG_E100=m
 CONFIG_E1000=y
 CONFIG_IGB=y
diff --git a/arch/ia64/configs/gensparse_defconfig b/arch/ia64/configs/gensparse_defconfig
index b11fa88..91c41ec 100644
--- a/arch/ia64/configs/gensparse_defconfig
+++ b/arch/ia64/configs/gensparse_defconfig
@@ -75,6 +75,7 @@ CONFIG_NET_ETHERNET=y
 CONFIG_NET_TULIP=y
 CONFIG_TULIP=m
 CONFIG_NET_PCI=y
+CONFIG_NET_VENDOR_INTEL=y
 CONFIG_E100=m
 CONFIG_E1000=y
 CONFIG_TIGON3=y
diff --git a/arch/ia64/configs/tiger_defconfig b/arch/ia64/configs/tiger_defconfig
index 137a453..a5a9e02 100644
--- a/arch/ia64/configs/tiger_defconfig
+++ b/arch/ia64/configs/tiger_defconfig
@@ -77,6 +77,7 @@ CONFIG_NET_ETHERNET=y
 CONFIG_NET_TULIP=y
 CONFIG_TULIP=m
 CONFIG_NET_PCI=y
+CONFIG_NET_VENDOR_INTEL=y
 CONFIG_E100=m
 CONFIG_E1000=y
 CONFIG_TIGON3=y
diff --git a/arch/ia64/configs/xen_domu_defconfig b/arch/ia64/configs/xen_domu_defconfig
index 2bf76e4..37b9b42 100644
--- a/arch/ia64/configs/xen_domu_defconfig
+++ b/arch/ia64/configs/xen_domu_defconfig
@@ -80,6 +80,7 @@ CONFIG_NET_ETHERNET=y
 CONFIG_NET_TULIP=y
 CONFIG_TULIP=m
 CONFIG_NET_PCI=y
+CONFIG_NET_VENDOR_INTEL=y
 CONFIG_E100=m
 CONFIG_E1000=y
 CONFIG_TIGON3=y
diff --git a/arch/ia64/configs/zx1_defconfig b/arch/ia64/configs/zx1_defconfig
index 1d42827..fc7aba0 100644
--- a/arch/ia64/configs/zx1_defconfig
+++ b/arch/ia64/configs/zx1_defconfig
@@ -57,6 +57,7 @@ CONFIG_TULIP_MMIO=y
 CONFIG_TULIP_NAPI=y
 CONFIG_TULIP_NAPI_HW_MITIGATION=y
 CONFIG_NET_PCI=y
+CONFIG_NET_VENDOR_INTEL=y
 CONFIG_E100=y
 CONFIG_E1000=y
 CONFIG_TIGON3=y
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index 30862c0..2de41d4 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -615,11 +615,15 @@ static int sn_hwperf_op_cpu(struct sn_hwperf_op_info *op_info)
 		}
 	}
 
-	if (cpu == SN_HWPERF_ARG_ANY_CPU || cpu == get_cpu()) {
-		/* don't care, or already on correct cpu */
+	if (cpu == SN_HWPERF_ARG_ANY_CPU) {
+		/* don't care which cpu */
 		sn_hwperf_call_sal(op_info);
-	}
-	else {
+	} else if (cpu == get_cpu()) {
+		/* already on correct cpu */
+		sn_hwperf_call_sal(op_info);
+		put_cpu();
+	} else {
+		put_cpu();
 		if (use_ipi) {
 			/* use an interprocessor interrupt to call SAL */
 			smp_call_function_single(cpu, sn_hwperf_call_sal,
diff --git a/arch/mips/include/asm/mach-au1x00/au1xxx_psc.h b/arch/mips/include/asm/mach-au1x00/au1xxx_psc.h
index 892b7f1..5a5cb73 100644
--- a/arch/mips/include/asm/mach-au1x00/au1xxx_psc.h
+++ b/arch/mips/include/asm/mach-au1x00/au1xxx_psc.h
@@ -394,19 +394,6 @@ typedef struct	psc_spi {
 #define PSC_SPITXRX_LC		(1 << 29)
 #define PSC_SPITXRX_SR		(1 << 28)
 
-/* PSC in SMBus (I2C) Mode. */
-typedef struct	psc_smb {
-	u32	psc_sel;
-	u32	psc_ctrl;
-	u32	psc_smbcfg;
-	u32	psc_smbmsk;
-	u32	psc_smbpcr;
-	u32	psc_smbstat;
-	u32	psc_smbevnt;
-	u32	psc_smbtxrx;
-	u32	psc_smbtmr;
-} psc_smb_t;
-
 /* SMBus Config Register. */
 #define PSC_SMBCFG_RT_MASK	(3 << 30)
 #define PSC_SMBCFG_RT_FIFO1	(0 << 30)
diff --git a/arch/powerpc/mm/gup.c b/arch/powerpc/mm/gup.c
index fec1320..d7efdbf 100644
--- a/arch/powerpc/mm/gup.c
+++ b/arch/powerpc/mm/gup.c
@@ -16,16 +16,6 @@
 
 #ifdef __HAVE_ARCH_PTE_SPECIAL
 
-static inline void get_huge_page_tail(struct page *page)
-{
-	/*
-	 * __split_huge_page_refcount() cannot run
-	 * from under us.
-	 */
-	VM_BUG_ON(atomic_read(&page->_count) < 0);
-	atomic_inc(&page->_count);
-}
-
 /*
  * The performance critical leaf functions are made noinline otherwise gcc
  * inlines everything into a single function which results in too much
@@ -57,8 +47,6 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
 			put_page(page);
 			return 0;
 		}
-		if (PageTail(page))
-			get_huge_page_tail(page);
 		pages[*nr] = page;
 		(*nr)++;
 
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index 0b9a5c1..da5eb38 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -390,7 +390,7 @@ static noinline int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long add
 {
 	unsigned long mask;
 	unsigned long pte_end;
-	struct page *head, *page;
+	struct page *head, *page, *tail;
 	pte_t pte;
 	int refs;
 
@@ -413,6 +413,7 @@ static noinline int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long add
 	head = pte_page(pte);
 
 	page = head + ((addr & (sz-1)) >> PAGE_SHIFT);
+	tail = page;
 	do {
 		VM_BUG_ON(compound_head(page) != head);
 		pages[*nr] = page;
@@ -428,10 +429,20 @@ static noinline int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long add
 
 	if (unlikely(pte_val(pte) != pte_val(*ptep))) {
 		/* Could be optimized better */
-		while (*nr) {
-			put_page(page);
-			(*nr)--;
-		}
+		*nr -= refs;
+		while (refs--)
+			put_page(head);
+		return 0;
+	}
+
+	/*
+	 * Any tail page need their mapcount reference taken before we
+	 * return.
+	 */
+	while (refs--) {
+		if (PageTail(tail))
+			get_huge_page_tail(tail);
+		tail++;
 	}
 
 	return 1;
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index c65f75a..22ffccd 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -1608,6 +1608,7 @@ int fsl_rio_setup(struct platform_device *dev)
 	return 0;
 err:
 	iounmap(priv->regs_win);
+	release_resource(&port->iores);
 err_res:
 	kfree(priv);
 err_priv:
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
index 6fe874f..481f4f7 100644
--- a/arch/s390/hypfs/inode.c
+++ b/arch/s390/hypfs/inode.c
@@ -108,9 +108,7 @@ static struct inode *hypfs_make_inode(struct super_block *sb, int mode)
 		ret->i_gid = hypfs_info->gid;
 		ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
 		if (mode & S_IFDIR)
-			ret->i_nlink = 2;
-		else
-			ret->i_nlink = 1;
+			set_nlink(ret, 2);
 	}
 	return ret;
 }
@@ -361,7 +359,7 @@ static struct dentry *hypfs_create_file(struct super_block *sb,
 	} else if (mode & S_IFDIR) {
 		inode->i_op = &simple_dir_inode_operations;
 		inode->i_fop = &simple_dir_operations;
-		parent->d_inode->i_nlink++;
+		inc_nlink(parent->d_inode);
 	} else
 		BUG();
 	inode->i_private = data;
diff --git a/arch/s390/mm/gup.c b/arch/s390/mm/gup.c
index 45b405c..65cb06e 100644
--- a/arch/s390/mm/gup.c
+++ b/arch/s390/mm/gup.c
@@ -52,7 +52,7 @@ static inline int gup_huge_pmd(pmd_t *pmdp, pmd_t pmd, unsigned long addr,
 		unsigned long end, int write, struct page **pages, int *nr)
 {
 	unsigned long mask, result;
-	struct page *head, *page;
+	struct page *head, *page, *tail;
 	int refs;
 
 	result = write ? 0 : _SEGMENT_ENTRY_RO;
@@ -64,6 +64,7 @@ static inline int gup_huge_pmd(pmd_t *pmdp, pmd_t pmd, unsigned long addr,
 	refs = 0;
 	head = pmd_page(pmd);
 	page = head + ((addr & ~PMD_MASK) >> PAGE_SHIFT);
+	tail = page;
 	do {
 		VM_BUG_ON(compound_head(page) != head);
 		pages[*nr] = page;
@@ -81,6 +82,17 @@ static inline int gup_huge_pmd(pmd_t *pmdp, pmd_t pmd, unsigned long addr,
 		*nr -= refs;
 		while (refs--)
 			put_page(head);
+		return 0;
+	}
+
+	/*
+	 * Any tail page need their mapcount reference taken before we
+	 * return.
+	 */
+	while (refs--) {
+		if (PageTail(tail))
+			get_huge_page_tail(tail);
+		tail++;
 	}
 
 	return 1;
diff --git a/arch/sparc/mm/gup.c b/arch/sparc/mm/gup.c
index a986b5d..42c55df 100644
--- a/arch/sparc/mm/gup.c
+++ b/arch/sparc/mm/gup.c
@@ -56,6 +56,8 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
 			put_page(head);
 			return 0;
 		}
+		if (head != page)
+			get_huge_page_tail(page);
 
 		pages[*nr] = page;
 		(*nr)++;
diff --git a/arch/um/Kconfig.char b/arch/um/Kconfig.char
index 70dabd1..b9d7c42 100644
--- a/arch/um/Kconfig.char
+++ b/arch/um/Kconfig.char
@@ -1,5 +1,4 @@
-
-menu "Character Devices"
+menu "UML Character Devices"
 
 config STDERR_CONSOLE
 	bool "stderr console"
@@ -105,92 +104,6 @@ config SSL_CHAN
           this if you expect the UML that you build to be run in environments
           which don't have a set of /dev/pty* devices.
 
-config UNIX98_PTYS
-	bool "Unix98 PTY support"
-	help
-	  A pseudo terminal (PTY) is a software device consisting of two
-	  halves: a master and a slave. The slave device behaves identical to
-	  a physical terminal; the master device is used by a process to
-	  read data from and write data to the slave, thereby emulating a
-	  terminal. Typical programs for the master side are telnet servers
-	  and xterms.
-
-	  Linux has traditionally used the BSD-like names /dev/ptyxx for
-	  masters and /dev/ttyxx for slaves of pseudo terminals. This scheme
-	  has a number of problems. The GNU C library glibc 2.1 and later,
-	  however, supports the Unix98 naming standard: in order to acquire a
-	  pseudo terminal, a process opens /dev/ptmx; the number of the pseudo
-	  terminal is then made available to the process and the pseudo
-	  terminal slave can be accessed as /dev/pts/<number>. What was
-	  traditionally /dev/ttyp2 will then be /dev/pts/2, for example.
-
-	  All modern Linux systems use the Unix98 ptys.  Say Y unless
-	  you're on an embedded system and want to conserve memory.
-
-config LEGACY_PTYS
-	bool "Legacy (BSD) PTY support"
-	default y
-	help
-	  A pseudo terminal (PTY) is a software device consisting of two
-	  halves: a master and a slave. The slave device behaves identical to
-	  a physical terminal; the master device is used by a process to
-	  read data from and write data to the slave, thereby emulating a
-	  terminal. Typical programs for the master side are telnet servers
-	  and xterms.
-
-	  Linux has traditionally used the BSD-like names /dev/ptyxx
-	  for masters and /dev/ttyxx for slaves of pseudo
-	  terminals. This scheme has a number of problems, including
-	  security.  This option enables these legacy devices; on most
-	  systems, it is safe to say N.
-
-config RAW_DRIVER
-        tristate "RAW driver (/dev/raw/rawN)"
-	depends on BLOCK
-        help
-          The raw driver permits block devices to be bound to /dev/raw/rawN.
-          Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O.
-          See the raw(8) manpage for more details.
-
-          Applications should preferably open the device (eg /dev/hda1)
-          with the O_DIRECT flag.
-
-config MAX_RAW_DEVS
-        int "Maximum number of RAW devices to support (1-8192)"
-        depends on RAW_DRIVER
-        default "256"
-        help
-          The maximum number of RAW devices that are supported.
-          Default is 256. Increase this number in case you need lots of
-          raw devices.
-
-config LEGACY_PTY_COUNT
-	int "Maximum number of legacy PTY in use"
-	depends on LEGACY_PTYS
-	default "256"
-	help
-	  The maximum number of legacy PTYs that can be used at any one time.
-	  The default is 256, and should be more than enough.  Embedded
-	  systems may want to reduce this to save memory.
-
-	  When not in use, each legacy PTY occupies 12 bytes on 32-bit
-	  architectures and 24 bytes on 64-bit architectures.
-
-config WATCHDOG
-	bool "Watchdog Timer Support"
-
-config WATCHDOG_NOWAYOUT
-	bool "Disable watchdog shutdown on close"
-	depends on WATCHDOG
-
-config SOFT_WATCHDOG
-	tristate "Software Watchdog"
-	depends on WATCHDOG
-
-config UML_WATCHDOG
-	tristate "UML watchdog"
-	depends on WATCHDOG
-
 config UML_SOUND
 	tristate "Sound support"
 	help
@@ -211,29 +124,4 @@ config HOSTAUDIO
 	tristate
 	default UML_SOUND
 
-#It is selected elsewhere, so kconfig would warn without this.
-config HW_RANDOM
-	tristate
-	default n
-
-config UML_RANDOM
-	tristate "Hardware random number generator"
-	help
-	  This option enables UML's "hardware" random number generator.  It
-	  attaches itself to the host's /dev/random, supplying as much entropy
-	  as the host has, rather than the small amount the UML gets from its
-	  own drivers.  It registers itself as a standard hardware random number
-	  generator, major 10, minor 183, and the canonical device name is
-	  /dev/hwrng.
-	  The way to make use of this is to install the rng-tools package
-	  (check your distro, or download from
-	  http://sourceforge.net/projects/gkernel/).  rngd periodically reads
-	  /dev/hwrng and injects the entropy into /dev/random.
-
-config MMAPPER
-	tristate "iomem emulation driver"
-	help
-	  This driver allows a host file to be used as emulated IO memory inside
-	  UML.
-
 endmenu
diff --git a/arch/um/Kconfig.rest b/arch/um/Kconfig.rest
index 0ccad0f..567eb5f 100644
--- a/arch/um/Kconfig.rest
+++ b/arch/um/Kconfig.rest
@@ -2,20 +2,14 @@ source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
 
-source "drivers/block/Kconfig"
-
 source "arch/um/Kconfig.char"
 
-source "drivers/base/Kconfig"
+source "drivers/Kconfig"
 
 source "net/Kconfig"
 
 source "arch/um/Kconfig.net"
 
-source "drivers/net/Kconfig"
-
-source "drivers/connector/Kconfig"
-
 source "fs/Kconfig"
 
 source "security/Kconfig"
@@ -24,19 +18,4 @@ source "crypto/Kconfig"
 
 source "lib/Kconfig"
 
-source "drivers/scsi/Kconfig"
-
-source "drivers/md/Kconfig"
-
-if BROKEN
-	source "drivers/mtd/Kconfig"
-endif
-
-source "drivers/leds/Kconfig"
-
-#This is just to shut up some Kconfig warnings, so no prompt.
-config INPUT
-	tristate
-	default n
-
 source "arch/um/Kconfig.debug"
diff --git a/arch/um/Kconfig.um b/arch/um/Kconfig.um
index b5e675e..70fd690 100644
--- a/arch/um/Kconfig.um
+++ b/arch/um/Kconfig.um
@@ -148,5 +148,11 @@ config KERNEL_STACK_ORDER
 	  be 1 << order pages.  The default is OK unless you're running Valgrind
 	  on UML, in which case, set this to 3.
 
+config MMAPPER
+	tristate "iomem emulation driver"
+	help
+	  This driver allows a host file to be used as emulated IO memory inside
+	  UML.
+
 config NO_DMA
 	def_bool y
diff --git a/arch/um/Kconfig.x86 b/arch/um/Kconfig.x86
deleted file mode 100644
index 21bebe6..0000000
--- a/arch/um/Kconfig.x86
+++ /dev/null
@@ -1,70 +0,0 @@
-mainmenu "User Mode Linux/$SUBARCH $KERNELVERSION Kernel Configuration"
-
-source "arch/um/Kconfig.common"
-
-menu "UML-specific options"
-
-menu "Host processor type and features"
-
-config CMPXCHG_LOCAL
-	bool
-	default n
-
-config CMPXCHG_DOUBLE
-	bool
-	default n
-
-source "arch/x86/Kconfig.cpu"
-
-endmenu
-
-config UML_X86
-	def_bool y
-	select GENERIC_FIND_FIRST_BIT
-
-config 64BIT
-	bool
-	default SUBARCH = "x86_64"
-
-config X86_32
-	def_bool !64BIT
-	select HAVE_AOUT
-
-config X86_64
-	def_bool 64BIT
-
-config RWSEM_XCHGADD_ALGORITHM
-	def_bool X86_XADD && 64BIT
-
-config RWSEM_GENERIC_SPINLOCK
-	def_bool !RWSEM_XCHGADD_ALGORITHM
-
-config 3_LEVEL_PGTABLES
-	bool "Three-level pagetables (EXPERIMENTAL)" if !64BIT
-	default 64BIT
-	depends on EXPERIMENTAL
-	help
-	Three-level pagetables will let UML have more than 4G of physical
-	memory.  All the memory that can't be mapped directly will be treated
-	as high memory.
-
-	However, this it experimental on 32-bit architectures, so if unsure say
-	N (on x86-64 it's automatically enabled, instead, as it's safe there).
-
-config ARCH_HAS_SC_SIGNALS
-	def_bool !64BIT
-
-config ARCH_REUSE_HOST_VSYSCALL_AREA
-	def_bool !64BIT
-
-config SMP_BROKEN
-	def_bool 64BIT
-
-config GENERIC_HWEIGHT
-	def_bool y
-
-source "arch/um/Kconfig.um"
-
-endmenu
-
-source "arch/um/Kconfig.rest"
diff --git a/arch/um/Makefile b/arch/um/Makefile
index c0f712c..7730af6 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -20,15 +20,27 @@ core-y			+= $(ARCH_DIR)/kernel/		\
 
 MODE_INCLUDE	+= -I$(srctree)/$(ARCH_DIR)/include/shared/skas
 
+HEADER_ARCH 	:= $(SUBARCH)
+
+# Additional ARCH settings for x86
+ifeq ($(SUBARCH),i386)
+        HEADER_ARCH := x86
+endif
+ifeq ($(SUBARCH),x86_64)
+        HEADER_ARCH := x86
+endif
+
+HOST_DIR := arch/$(HEADER_ARCH)
+
 include $(srctree)/$(ARCH_DIR)/Makefile-skas
+include $(srctree)/$(HOST_DIR)/Makefile.um
+
+core-y += $(HOST_DIR)/um/
 
 SHARED_HEADERS	:= $(ARCH_DIR)/include/shared
 ARCH_INCLUDE	:= -I$(srctree)/$(SHARED_HEADERS)
-ARCH_INCLUDE	+= -I$(srctree)/$(ARCH_DIR)/sys-$(SUBARCH)/shared
-ifneq ($(KBUILD_SRC),)
-ARCH_INCLUDE	+= -I$(SHARED_HEADERS)
-endif
-KBUILD_CPPFLAGS += -I$(srctree)/$(ARCH_DIR)/sys-$(SUBARCH)
+ARCH_INCLUDE	+= -I$(srctree)/$(HOST_DIR)/um/shared
+KBUILD_CPPFLAGS += -I$(srctree)/$(HOST_DIR)/um
 
 # -Dvmap=kernel_vmap prevents anything from referencing the libpcap.o symbol so
 # named - it's a common symbol in libpcap, so we get a binary which crashes.
@@ -47,14 +59,12 @@ KBUILD_AFLAGS += $(ARCH_INCLUDE)
 
 USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -D__KERNEL__,,\
 	$(patsubst -I%,,$(KBUILD_CFLAGS)))) $(ARCH_INCLUDE) $(MODE_INCLUDE) \
-	$(filter -I%,$(CFLAGS)) -D_FILE_OFFSET_BITS=64
-
-include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH)
+	$(filter -I%,$(CFLAGS)) -D_FILE_OFFSET_BITS=64 -idirafter include
 
 #This will adjust *FLAGS accordingly to the platform.
 include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS)
 
-KBUILD_CPPFLAGS += -I$(srctree)/arch/$(HEADER_ARCH)/include
+KBUILD_CPPFLAGS += -I$(srctree)/$(HOST_DIR)/include
 
 # -Derrno=kernel_errno - This turns all kernel references to errno into
 # kernel_errno to separate them from the libc errno.  This allows -fno-common
@@ -84,10 +94,9 @@ define archhelp
   echo '		   find in the kernel root.'
 endef
 
-KBUILD_KCONFIG := arch/um/Kconfig.$(HEADER_ARCH)
+KBUILD_KCONFIG := $(HOST_DIR)/um/Kconfig
 
-archprepare: $(SHARED_HEADERS)/user_constants.h
-archprepare: $(SHARED_HEADERS)/kern_constants.h
+archprepare: include/generated/user_constants.h
 
 LINK-$(CONFIG_LD_SCRIPT_STATIC) += -static
 LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib
@@ -118,9 +127,7 @@ endef
 
 # When cleaning we don't include .config, so we don't include
 # TT or skas makefiles and don't clean skas_ptregs.h.
-CLEAN_FILES += linux x.i gmon.out \
-	$(SHARED_HEADERS)/user_constants.h \
-	$(SHARED_HEADERS)/kern_constants.h
+CLEAN_FILES += linux x.i gmon.out
 
 archclean:
 	@find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
@@ -128,8 +135,8 @@ archclean:
 
 # Generated files
 
-$(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.s: FORCE
-	$(Q)$(MAKE) $(build)=$(ARCH_DIR)/sys-$(SUBARCH) $@
+$(HOST_DIR)/um/user-offsets.s: FORCE
+	$(Q)$(MAKE) $(build)=$(HOST_DIR)/um $@
 
 define filechk_gen-asm-offsets
         (set -e; \
@@ -144,11 +151,7 @@ define filechk_gen-asm-offsets
          echo ""; )
 endef
 
-$(SHARED_HEADERS)/user_constants.h: $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.s
+include/generated/user_constants.h: $(HOST_DIR)/um/user-offsets.s
 	$(call filechk,gen-asm-offsets)
 
-$(SHARED_HEADERS)/kern_constants.h:
-	$(Q)mkdir -p $(dir $@)
-	$(Q)echo '#include "../../../../include/generated/asm-offsets.h"' >$@
-
-export SUBARCH USER_CFLAGS CFLAGS_NO_HARDENING OS HEADER_ARCH DEV_NULL_PATH
+export SUBARCH USER_CFLAGS CFLAGS_NO_HARDENING OS DEV_NULL_PATH
diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386
deleted file mode 100644
index 302cbe5..0000000
--- a/arch/um/Makefile-i386
+++ /dev/null
@@ -1,42 +0,0 @@
-core-y += arch/um/sys-i386/ arch/x86/crypto/
-
-TOP_ADDR := $(CONFIG_TOP_ADDR)
-
-START := 0x8048000
-
-LDFLAGS			+= -m elf_i386
-ELF_ARCH		:= $(SUBARCH)
-ELF_FORMAT 		:= elf32-$(SUBARCH)
-OBJCOPYFLAGS  		:= -O binary -R .note -R .comment -S
-HEADER_ARCH		:= x86
-CHECKFLAGS	+= -D__i386__
-
-ifeq ("$(origin SUBARCH)", "command line")
-ifneq ("$(shell uname -m | sed -e s/i.86/i386/)", "$(SUBARCH)")
-KBUILD_CFLAGS		+= $(call cc-option,-m32)
-KBUILD_AFLAGS		+= $(call cc-option,-m32)
-LINK-y			+= $(call cc-option,-m32)
-UML_OBJCOPYFLAGS	+= -F $(ELF_FORMAT)
-
-export LDFLAGS HOSTCFLAGS HOSTLDFLAGS UML_OBJCOPYFLAGS
-endif
-endif
-
-# First of all, tune CFLAGS for the specific CPU. This actually sets cflags-y.
-include $(srctree)/arch/x86/Makefile_32.cpu
-
-# prevent gcc from keeping the stack 16 byte aligned. Taken from i386.
-cflags-y += $(call cc-option,-mpreferred-stack-boundary=2)
-
-# Prevent sprintf in nfsd from being converted to strcpy and resulting in
-# an unresolved reference.
-cflags-y += -ffreestanding
-
-# Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use
-# a lot more stack due to the lack of sharing of stacklots.  Also, gcc
-# 4.3.0 needs -funit-at-a-time for extern inline functions.
-KBUILD_CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then \
-			echo $(call cc-option,-fno-unit-at-a-time); \
-			else echo $(call cc-option,-funit-at-a-time); fi ;)
-
-KBUILD_CFLAGS += $(cflags-y)
diff --git a/arch/um/Makefile-x86_64 b/arch/um/Makefile-x86_64
deleted file mode 100644
index a9cd7e7..0000000
--- a/arch/um/Makefile-x86_64
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2003 - 2004 Pathscale, Inc
-# Released under the GPL
-
-core-y += arch/um/sys-x86_64/ arch/x86/crypto/
-START := 0x60000000
-
-_extra_flags_ = -fno-builtin -m64
-
-KBUILD_CFLAGS += $(_extra_flags_)
-
-CHECKFLAGS  += -m64 -D__x86_64__
-KBUILD_AFLAGS += -m64
-LDFLAGS += -m elf_x86_64
-KBUILD_CPPFLAGS += -m64
-
-ELF_ARCH := i386:x86-64
-ELF_FORMAT := elf64-x86-64
-HEADER_ARCH := x86
-
-# Not on all 64-bit distros /lib is a symlink to /lib64. PLD is an example.
-
-LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib64
-LINK-y += -m64
-
-# Do unit-at-a-time unconditionally on x86_64, following the host
-KBUILD_CFLAGS += $(call cc-option,-funit-at-a-time)
diff --git a/arch/um/drivers/chan.h b/arch/um/drivers/chan.h
new file mode 100644
index 0000000..8df0fd9
--- /dev/null
+++ b/arch/um/drivers/chan.h
@@ -0,0 +1,50 @@
+/* 
+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __CHAN_KERN_H__
+#define __CHAN_KERN_H__
+
+#include <linux/tty.h>
+#include <linux/list.h>
+#include <linux/console.h>
+#include "chan_user.h"
+#include "line.h"
+
+struct chan {
+	struct list_head list;
+	struct list_head free_list;
+	struct line *line;
+	char *dev;
+	unsigned int primary:1;
+	unsigned int input:1;
+	unsigned int output:1;
+	unsigned int opened:1;
+	unsigned int enabled:1;
+	int fd;
+	const struct chan_ops *ops;
+	void *data;
+};
+
+extern void chan_interrupt(struct list_head *chans, struct delayed_work *task,
+			   struct tty_struct *tty, int irq);
+extern int parse_chan_pair(char *str, struct line *line, int device,
+			   const struct chan_opts *opts, char **error_out);
+extern int write_chan(struct list_head *chans, const char *buf, int len,
+			     int write_irq);
+extern int console_write_chan(struct list_head *chans, const char *buf, 
+			      int len);
+extern int console_open_chan(struct line *line, struct console *co);
+extern void deactivate_chan(struct list_head *chans, int irq);
+extern void reactivate_chan(struct list_head *chans, int irq);
+extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty);
+extern int enable_chan(struct line *line);
+extern void close_chan(struct list_head *chans, int delay_free_irq);
+extern int chan_window_size(struct list_head *chans, 
+			     unsigned short *rows_out, 
+			     unsigned short *cols_out);
+extern int chan_config_string(struct list_head *chans, char *str, int size,
+			      char **error_out);
+
+#endif
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index d4191fe..420e2c8 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -6,7 +6,7 @@
 #include <linux/slab.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
-#include "chan_kern.h"
+#include "chan.h"
 #include "os.h"
 
 #ifdef CONFIG_NOCONFIG_CHAN
@@ -358,11 +358,11 @@ int chan_window_size(struct list_head *chans, unsigned short *rows_out,
 	return 0;
 }
 
-static void free_one_chan(struct chan *chan, int delay_free_irq)
+static void free_one_chan(struct chan *chan)
 {
 	list_del(&chan->list);
 
-	close_one_chan(chan, delay_free_irq);
+	close_one_chan(chan, 0);
 
 	if (chan->ops->free != NULL)
 		(*chan->ops->free)(chan->data);
@@ -372,14 +372,14 @@ static void free_one_chan(struct chan *chan, int delay_free_irq)
 	kfree(chan);
 }
 
-static void free_chan(struct list_head *chans, int delay_free_irq)
+static void free_chan(struct list_head *chans)
 {
 	struct list_head *ele, *next;
 	struct chan *chan;
 
 	list_for_each_safe(ele, next, chans) {
 		chan = list_entry(ele, struct chan, list);
-		free_one_chan(chan, delay_free_irq);
+		free_one_chan(chan);
 	}
 }
 
@@ -547,7 +547,7 @@ int parse_chan_pair(char *str, struct line *line, int device,
 	char *in, *out;
 
 	if (!list_empty(chans)) {
-		free_chan(chans, 0);
+		free_chan(chans);
 		INIT_LIST_HEAD(chans);
 	}
 
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c
index cfeb3f4..f180813 100644
--- a/arch/um/drivers/chan_user.c
+++ b/arch/um/drivers/chan_user.c
@@ -11,10 +11,8 @@
 #include <termios.h>
 #include <sys/ioctl.h>
 #include "chan_user.h"
-#include "kern_constants.h"
 #include "os.h"
 #include "um_malloc.h"
-#include "user.h"
 
 void generic_close(int fd, void *unused)
 {
@@ -283,7 +281,12 @@ void register_winch(int fd, struct tty_struct *tty)
 		return;
 
 	pid = tcgetpgrp(fd);
-	if (!is_skas_winch(pid, fd, tty) && (pid == -1)) {
+	if (is_skas_winch(pid, fd, tty)) {
+		register_winch_irq(-1, fd, -1, tty, 0);
+		return;
+	}
+
+	if (pid == -1) {
 		thread = winch_tramp(fd, tty, &thread_fd, &stack);
 		if (thread < 0)
 			return;
diff --git a/arch/um/drivers/chan_user.h b/arch/um/drivers/chan_user.h
new file mode 100644
index 0000000..9b9ced8
--- /dev/null
+++ b/arch/um/drivers/chan_user.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __CHAN_USER_H__
+#define __CHAN_USER_H__
+
+#include "init.h"
+
+struct chan_opts {
+	void (*const announce)(char *dev_name, int dev);
+	char *xterm_title;
+	const int raw;
+};
+
+enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE };
+
+struct chan_ops {
+	char *type;
+	void *(*init)(char *, int, const struct chan_opts *);
+	int (*open)(int, int, int, void *, char **);
+	void (*close)(int, void *);
+	int (*read)(int, char *, void *);
+	int (*write)(int, const char *, int, void *);
+	int (*console_write)(int, const char *, int);
+	int (*window_size)(int, void *, unsigned short *, unsigned short *);
+	void (*free)(void *);
+	int winch;
+};
+
+extern const struct chan_ops fd_ops, null_ops, port_ops, pts_ops, pty_ops,
+	tty_ops, xterm_ops;
+
+extern void generic_close(int fd, void *unused);
+extern int generic_read(int fd, char *c_out, void *unused);
+extern int generic_write(int fd, const char *buf, int n, void *unused);
+extern int generic_console_write(int fd, const char *buf, int n);
+extern int generic_window_size(int fd, void *unused, unsigned short *rows_out,
+			       unsigned short *cols_out);
+extern void generic_free(void *data);
+
+struct tty_struct;
+extern void register_winch(int fd,  struct tty_struct *tty);
+extern void register_winch_irq(int fd, int tty_fd, int pid,
+			       struct tty_struct *tty, unsigned long stack);
+
+#define __channel_help(fn, prefix) \
+__uml_help(fn, prefix "[0-9]*=<channel description>\n" \
+"    Attach a console or serial line to a host channel.  See\n" \
+"    http://user-mode-linux.sourceforge.net/old/input.html for a complete\n" \
+"    description of this switch.\n\n" \
+);
+
+#endif
diff --git a/arch/um/drivers/cow_sys.h b/arch/um/drivers/cow_sys.h
index f5701fd..7f2ed0b 100644
--- a/arch/um/drivers/cow_sys.h
+++ b/arch/um/drivers/cow_sys.h
@@ -3,7 +3,6 @@
 
 #include "kern_util.h"
 #include "os.h"
-#include "user.h"
 #include "um_malloc.h"
 
 static inline void *cow_malloc(int size)
diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c
index f8e85e0..a4fd7bc 100644
--- a/arch/um/drivers/daemon_user.c
+++ b/arch/um/drivers/daemon_user.c
@@ -17,7 +17,6 @@
 #include "net_user.h"
 #include "os.h"
 #include "um_malloc.h"
-#include "user.h"
 
 enum request_type { REQ_NEW_CONTROL };
 
diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c
index f5a981a..5b81d25 100644
--- a/arch/um/drivers/fd.c
+++ b/arch/um/drivers/fd.c
@@ -9,10 +9,8 @@
 #include <errno.h>
 #include <termios.h>
 #include "chan_user.h"
-#include "kern_constants.h"
 #include "os.h"
 #include "um_malloc.h"
-#include "user.h"
 
 struct fd_chan {
 	int fd;
diff --git a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c
index 84dce3f..0345d62 100644
--- a/arch/um/drivers/harddog_user.c
+++ b/arch/um/drivers/harddog_user.c
@@ -7,7 +7,6 @@
 #include <unistd.h>
 #include <errno.h>
 #include "os.h"
-#include "user.h"
 
 struct dog_data {
 	int stdin;
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 364c8a1..c1cf220 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -7,7 +7,7 @@
 #include "linux/kd.h"
 #include "linux/sched.h"
 #include "linux/slab.h"
-#include "chan_kern.h"
+#include "chan.h"
 #include "irq_kern.h"
 #include "irq_user.h"
 #include "kern_util.h"
diff --git a/arch/um/drivers/line.h b/arch/um/drivers/line.h
new file mode 100644
index 0000000..63df3ca
--- /dev/null
+++ b/arch/um/drivers/line.h
@@ -0,0 +1,106 @@
+/* 
+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __LINE_H__
+#define __LINE_H__
+
+#include "linux/list.h"
+#include "linux/workqueue.h"
+#include "linux/tty.h"
+#include "linux/interrupt.h"
+#include "linux/spinlock.h"
+#include "linux/mutex.h"
+#include "chan_user.h"
+#include "mconsole_kern.h"
+
+/* There's only one modifiable field in this - .mc.list */
+struct line_driver {
+	const char *name;
+	const char *device_name;
+	const short major;
+	const short minor_start;
+	const short type;
+	const short subtype;
+	const int read_irq;
+	const char *read_irq_name;
+	const int write_irq;
+	const char *write_irq_name;
+	struct mc_device mc;
+};
+
+struct line {
+	struct tty_struct *tty;
+	spinlock_t count_lock;
+	unsigned long count;
+	int valid;
+
+	char *init_str;
+	int init_pri;
+	struct list_head chan_list;
+
+	/*This lock is actually, mostly, local to*/
+	spinlock_t lock;
+	int throttled;
+	/* Yes, this is a real circular buffer.
+	 * XXX: And this should become a struct kfifo!
+	 *
+	 * buffer points to a buffer allocated on demand, of length
+	 * LINE_BUFSIZE, head to the start of the ring, tail to the end.*/
+	char *buffer;
+	char *head;
+	char *tail;
+
+	int sigio;
+	struct delayed_work task;
+	const struct line_driver *driver;
+	int have_irq;
+};
+
+#define LINE_INIT(str, d) \
+	{ .count_lock =	__SPIN_LOCK_UNLOCKED((str).count_lock), \
+	  .init_str =	str,	\
+	  .init_pri =	INIT_STATIC, \
+	  .valid =	1, \
+	  .lock =	__SPIN_LOCK_UNLOCKED((str).lock), \
+	  .driver =	d }
+
+extern void line_close(struct tty_struct *tty, struct file * filp);
+extern int line_open(struct line *lines, struct tty_struct *tty);
+extern int line_setup(struct line *lines, unsigned int sizeof_lines,
+		      char *init, char **error_out);
+extern int line_write(struct tty_struct *tty, const unsigned char *buf,
+		      int len);
+extern int line_put_char(struct tty_struct *tty, unsigned char ch);
+extern void line_set_termios(struct tty_struct *tty, struct ktermios * old);
+extern int line_chars_in_buffer(struct tty_struct *tty);
+extern void line_flush_buffer(struct tty_struct *tty);
+extern void line_flush_chars(struct tty_struct *tty);
+extern int line_write_room(struct tty_struct *tty);
+extern int line_ioctl(struct tty_struct *tty, unsigned int cmd,
+				unsigned long arg);
+extern void line_throttle(struct tty_struct *tty);
+extern void line_unthrottle(struct tty_struct *tty);
+
+extern char *add_xterm_umid(char *base);
+extern int line_setup_irq(int fd, int input, int output, struct line *line,
+			  void *data);
+extern void line_close_chan(struct line *line);
+extern struct tty_driver *register_lines(struct line_driver *line_driver,
+					 const struct tty_operations *driver,
+					 struct line *lines, int nlines);
+extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts);
+extern void close_lines(struct line *lines, int nlines);
+
+extern int line_config(struct line *lines, unsigned int sizeof_lines,
+		       char *str, const struct chan_opts *opts,
+		       char **error_out);
+extern int line_id(char **str, int *start_out, int *end_out);
+extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n,
+		       char **error_out);
+extern int line_get_config(char *dev, struct line *lines,
+			   unsigned int sizeof_lines, char *str,
+			   int size, char **error_out);
+
+#endif
diff --git a/arch/um/drivers/mconsole.h b/arch/um/drivers/mconsole.h
new file mode 100644
index 0000000..c139ae1
--- /dev/null
+++ b/arch/um/drivers/mconsole.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __MCONSOLE_H__
+#define __MCONSOLE_H__
+
+#ifndef __KERNEL__
+#include <stdint.h>
+#define u32 uint32_t
+#endif
+
+#include "sysdep/ptrace.h"
+
+#define MCONSOLE_MAGIC (0xcafebabe)
+#define MCONSOLE_MAX_DATA (512)
+#define MCONSOLE_VERSION 2
+
+struct mconsole_request {
+	u32 magic;
+	u32 version;
+	u32 len;
+	char data[MCONSOLE_MAX_DATA];
+};
+
+struct mconsole_reply {
+	u32 err;
+	u32 more;
+	u32 len;
+	char data[MCONSOLE_MAX_DATA];
+};
+
+struct mconsole_notify {
+	u32 magic;
+	u32 version;
+	enum { MCONSOLE_SOCKET, MCONSOLE_PANIC, MCONSOLE_HANG,
+	       MCONSOLE_USER_NOTIFY } type;
+	u32 len;
+	char data[MCONSOLE_MAX_DATA];
+};
+
+struct mc_request;
+
+enum mc_context { MCONSOLE_INTR, MCONSOLE_PROC };
+
+struct mconsole_command
+{
+	char *command;
+	void (*handler)(struct mc_request *req);
+	enum mc_context context;
+};
+
+struct mc_request
+{
+	int len;
+	int as_interrupt;
+
+	int originating_fd;
+	unsigned int originlen;
+	unsigned char origin[128];			/* sockaddr_un */
+
+	struct mconsole_request request;
+	struct mconsole_command *cmd;
+	struct uml_pt_regs regs;
+};
+
+extern char mconsole_socket_name[];
+
+extern int mconsole_unlink_socket(void);
+extern int mconsole_reply_len(struct mc_request *req, const char *reply,
+			      int len, int err, int more);
+extern int mconsole_reply(struct mc_request *req, const char *str, int err,
+			  int more);
+
+extern void mconsole_version(struct mc_request *req);
+extern void mconsole_help(struct mc_request *req);
+extern void mconsole_halt(struct mc_request *req);
+extern void mconsole_reboot(struct mc_request *req);
+extern void mconsole_config(struct mc_request *req);
+extern void mconsole_remove(struct mc_request *req);
+extern void mconsole_sysrq(struct mc_request *req);
+extern void mconsole_cad(struct mc_request *req);
+extern void mconsole_stop(struct mc_request *req);
+extern void mconsole_go(struct mc_request *req);
+extern void mconsole_log(struct mc_request *req);
+extern void mconsole_proc(struct mc_request *req);
+extern void mconsole_stack(struct mc_request *req);
+
+extern int mconsole_get_request(int fd, struct mc_request *req);
+extern int mconsole_notify(char *sock_name, int type, const void *data,
+			   int len);
+extern char *mconsole_notify_socket(void);
+extern void lock_notify(void);
+extern void unlock_notify(void);
+
+#endif
diff --git a/arch/um/drivers/mconsole_kern.h b/arch/um/drivers/mconsole_kern.h
new file mode 100644
index 0000000..d2fe07e
--- /dev/null
+++ b/arch/um/drivers/mconsole_kern.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __MCONSOLE_KERN_H__
+#define __MCONSOLE_KERN_H__
+
+#include "linux/list.h"
+#include "mconsole.h"
+
+struct mconsole_entry {
+	struct list_head list;
+	struct mc_request request;
+};
+
+/* All these methods are called in process context. */
+struct mc_device {
+	struct list_head list;
+	char *name;
+	int (*config)(char *, char **);
+	int (*get_config)(char *, char *, int, char **);
+	int (*id)(char **, int *, int *);
+	int (*remove)(int, char **);
+};
+
+#define CONFIG_CHUNK(str, size, current, chunk, end) \
+do { \
+	current += strlen(chunk); \
+	if(current >= size) \
+		str = NULL; \
+	if(str != NULL){ \
+		strcpy(str, chunk); \
+		str += strlen(chunk); \
+	} \
+	if(end) \
+		current++; \
+} while(0)
+
+#ifdef CONFIG_MCONSOLE
+
+extern void mconsole_register_dev(struct mc_device *new);
+
+#else
+
+static inline void mconsole_register_dev(struct mc_device *new)
+{
+}
+
+#endif
+
+#endif
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
index f8cf4c8..9920982 100644
--- a/arch/um/drivers/mconsole_user.c
+++ b/arch/um/drivers/mconsole_user.c
@@ -10,9 +10,7 @@
 #include <sys/socket.h>
 #include <sys/uio.h>
 #include <sys/un.h>
-#include "kern_constants.h"
 #include "mconsole.h"
-#include "user.h"
 
 static struct mconsole_command commands[] = {
 	/*
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index 5201188..05090c3 100644
--- a/arch/um/drivers/net_user.c
+++ b/arch/um/drivers/net_user.c
@@ -12,10 +12,8 @@
 #include <sys/socket.h>
 #include <sys/wait.h>
 #include "net_user.h"
-#include "kern_constants.h"
 #include "os.h"
 #include "um_malloc.h"
-#include "user.h"
 
 int tap_open_common(void *dev, char *gate_addr)
 {
diff --git a/arch/um/drivers/pcap_user.c b/arch/um/drivers/pcap_user.c
index 5f90358..702a75b 100644
--- a/arch/um/drivers/pcap_user.c
+++ b/arch/um/drivers/pcap_user.c
@@ -9,9 +9,7 @@
 #include <asm/types.h>
 #include "net_user.h"
 #include "pcap_user.h"
-#include "kern_constants.h"
 #include "um_malloc.h"
-#include "user.h"
 
 #define PCAP_FD(p) (*(int *)(p))
 
diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c
index b49bf56..7b010b7 100644
--- a/arch/um/drivers/port_user.c
+++ b/arch/um/drivers/port_user.c
@@ -10,11 +10,9 @@
 #include <unistd.h>
 #include <netinet/in.h>
 #include "chan_user.h"
-#include "kern_constants.h"
 #include "os.h"
 #include "port.h"
 #include "um_malloc.h"
-#include "user.h"
 
 struct port_chan {
 	int raw;
diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c
index 1113911..cff2b75 100644
--- a/arch/um/drivers/pty.c
+++ b/arch/um/drivers/pty.c
@@ -12,10 +12,8 @@
 #include <termios.h>
 #include <sys/stat.h>
 #include "chan_user.h"
-#include "kern_constants.h"
 #include "os.h"
 #include "um_malloc.h"
-#include "user.h"
 
 struct pty_chan {
 	void (*announce)(char *dev_name, int dev);
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
index cbacfc4..932b4d6 100644
--- a/arch/um/drivers/slip_user.c
+++ b/arch/um/drivers/slip_user.c
@@ -11,12 +11,10 @@
 #include <string.h>
 #include <sys/termios.h>
 #include <sys/wait.h>
-#include "kern_constants.h"
 #include "net_user.h"
 #include "os.h"
 #include "slip.h"
 #include "um_malloc.h"
-#include "user.h"
 
 static int slip_user_init(void *data, void *dev)
 {
diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c
index a0ada8f..db4adb6 100644
--- a/arch/um/drivers/slirp_user.c
+++ b/arch/um/drivers/slirp_user.c
@@ -7,11 +7,9 @@
 #include <errno.h>
 #include <string.h>
 #include <sys/wait.h>
-#include "kern_constants.h"
 #include "net_user.h"
 #include "os.h"
 #include "slirp.h"
-#include "user.h"
 
 static int slirp_user_init(void *data, void *dev)
 {
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index f1786e6..9d8c20a 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -12,10 +12,8 @@
 #include "linux/console.h"
 #include "asm/termbits.h"
 #include "asm/irq.h"
-#include "line.h"
 #include "ssl.h"
-#include "chan_kern.h"
-#include "kern.h"
+#include "chan.h"
 #include "init.h"
 #include "irq_user.h"
 #include "mconsole_kern.h"
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 49266f6..088776f 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -20,8 +20,7 @@
 #include "asm/current.h"
 #include "asm/irq.h"
 #include "stdio_console.h"
-#include "line.h"
-#include "chan_kern.h"
+#include "chan.h"
 #include "irq_user.h"
 #include "mconsole_kern.h"
 #include "init.h"
diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c
index 495858a..a97391f 100644
--- a/arch/um/drivers/tty.c
+++ b/arch/um/drivers/tty.c
@@ -7,10 +7,8 @@
 #include <fcntl.h>
 #include <termios.h>
 #include "chan_user.h"
-#include "kern_constants.h"
 #include "os.h"
 #include "um_malloc.h"
-#include "user.h"
 
 struct tty_chan {
 	char *dev;
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 620f5b7..944453a 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -46,7 +46,6 @@
 #include "asm/tlbflush.h"
 #include "mem_user.h"
 #include "kern_util.h"
-#include "kern.h"
 #include "mconsole_kern.h"
 #include "init.h"
 #include "irq_user.h"
@@ -54,7 +53,6 @@
 #include "ubd_user.h"
 #include "os.h"
 #include "mem.h"
-#include "mem_kern.h"
 #include "cow.h"
 
 enum ubd_req { UBD_READ, UBD_WRITE };
@@ -513,8 +511,37 @@ __uml_exitcall(kill_io_thread);
 static inline int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out)
 {
 	char *file;
+	int fd;
+	int err;
+
+	__u32 version;
+	__u32 align;
+	char *backing_file;
+	time_t mtime;
+	unsigned long long size;
+	int sector_size;
+	int bitmap_offset;
+
+	if (ubd_dev->file && ubd_dev->cow.file) {
+		file = ubd_dev->cow.file;
+
+		goto out;
+	}
 
-	file = ubd_dev->cow.file ? ubd_dev->cow.file : ubd_dev->file;
+	fd = os_open_file(ubd_dev->file, global_openflags, 0);
+	if (fd < 0)
+		return fd;
+
+	err = read_cow_header(file_reader, &fd, &version, &backing_file, \
+		&mtime, &size, &sector_size, &align, &bitmap_offset);
+	os_close_file(fd);
+
+	if(err == -EINVAL)
+		file = ubd_dev->file;
+	else
+		file = backing_file;
+
+out:
 	return os_file_size(file, size_out);
 }
 
diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c
index b591bb9..007b94d 100644
--- a/arch/um/drivers/ubd_user.c
+++ b/arch/um/drivers/ubd_user.c
@@ -16,7 +16,6 @@
 #include <sys/mman.h>
 #include <sys/param.h>
 #include "asm/types.h"
-#include "user.h"
 #include "ubd_user.h"
 #include "os.h"
 #include "cow.h"
diff --git a/arch/um/drivers/ubd_user.h b/arch/um/drivers/ubd_user.h
new file mode 100644
index 0000000..3845051
--- /dev/null
+++ b/arch/um/drivers/ubd_user.h
@@ -0,0 +1,16 @@
+/* 
+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 RidgeRun, Inc (glonnon@ridgerun.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_UBD_USER_H
+#define __UM_UBD_USER_H
+
+extern void ignore_sigwinch_sig(void);
+extern int start_io_thread(unsigned long sp, int *fds_out);
+extern int io_thread(void *arg);
+extern int kernel_fd;
+
+#endif
+
diff --git a/arch/um/drivers/umcast_user.c b/arch/um/drivers/umcast_user.c
index 59c56fd..010fa2d 100644
--- a/arch/um/drivers/umcast_user.c
+++ b/arch/um/drivers/umcast_user.c
@@ -15,11 +15,9 @@
 #include <unistd.h>
 #include <errno.h>
 #include <netinet/in.h>
-#include "kern_constants.h"
 #include "umcast.h"
 #include "net_user.h"
 #include "um_malloc.h"
-#include "user.h"
 
 static struct sockaddr_in *new_addr(char *addr, unsigned short port)
 {
diff --git a/arch/um/drivers/vde_user.c b/arch/um/drivers/vde_user.c
index c5c4325..b8c2867 100644
--- a/arch/um/drivers/vde_user.c
+++ b/arch/um/drivers/vde_user.c
@@ -6,10 +6,8 @@
 #include <stddef.h>
 #include <errno.h>
 #include <libvdeplug.h>
-#include "kern_constants.h"
 #include "net_user.h"
 #include "um_malloc.h"
-#include "user.h"
 #include "vde.h"
 
 static int vde_user_init(void *data, void *dev)
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c
index 2e1de57..969110e 100644
--- a/arch/um/drivers/xterm.c
+++ b/arch/um/drivers/xterm.c
@@ -11,10 +11,8 @@
 #include <string.h>
 #include <termios.h>
 #include "chan_user.h"
-#include "kern_constants.h"
 #include "os.h"
 #include "um_malloc.h"
-#include "user.h"
 #include "xterm.h"
 
 struct xterm_chan {
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
new file mode 100644
index 0000000..451f451
--- /dev/null
+++ b/arch/um/include/asm/Kbuild
@@ -0,0 +1,3 @@
+generic-y += bug.h cputime.h device.h emergency-restart.h futex.h hardirq.h
+generic-y += hw_irq.h irq_regs.h kdebug.h percpu.h sections.h topology.h xor.h
+generic-y += ftrace.h
diff --git a/arch/um/include/asm/apic.h b/arch/um/include/asm/apic.h
deleted file mode 100644
index 876dee8..0000000
--- a/arch/um/include/asm/apic.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef __UM_APIC_H
-#define __UM_APIC_H
-
-#endif
diff --git a/arch/um/include/asm/arch_hweight.h b/arch/um/include/asm/arch_hweight.h
deleted file mode 100644
index c656cf4..0000000
--- a/arch/um/include/asm/arch_hweight.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_UM_HWEIGHT_H
-#define _ASM_UM_HWEIGHT_H
-
-#include <asm-generic/bitops/arch_hweight.h>
-
-#endif
diff --git a/arch/um/include/asm/bug.h b/arch/um/include/asm/bug.h
deleted file mode 100644
index 9e33b86..0000000
--- a/arch/um/include/asm/bug.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __UM_BUG_H
-#define __UM_BUG_H
-
-#include <asm-generic/bug.h>
-
-#endif
diff --git a/arch/um/include/asm/checksum.h b/arch/um/include/asm/checksum.h
deleted file mode 100644
index 5b50136..0000000
--- a/arch/um/include/asm/checksum.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __UM_CHECKSUM_H
-#define __UM_CHECKSUM_H
-
-#include "sysdep/checksum.h"
-
-#endif
diff --git a/arch/um/include/asm/cputime.h b/arch/um/include/asm/cputime.h
deleted file mode 100644
index c84acba..0000000
--- a/arch/um/include/asm/cputime.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __UM_CPUTIME_H
-#define __UM_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* __UM_CPUTIME_H */
diff --git a/arch/um/include/asm/desc.h b/arch/um/include/asm/desc.h
deleted file mode 100644
index 4ec34a5..0000000
--- a/arch/um/include/asm/desc.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef __UM_DESC_H
-#define __UM_DESC_H
-
-/* Taken from asm-i386/desc.h, it's the only thing we need. The rest wouldn't
- * compile, and has never been used. */
-#define LDT_empty(info) (\
-	(info)->base_addr	== 0	&& \
-	(info)->limit		== 0	&& \
-	(info)->contents	== 0	&& \
-	(info)->read_exec_only	== 1	&& \
-	(info)->seg_32bit	== 0	&& \
-	(info)->limit_in_pages	== 0	&& \
-	(info)->seg_not_present	== 1	&& \
-	(info)->useable		== 0	)
-
-#endif
diff --git a/arch/um/include/asm/device.h b/arch/um/include/asm/device.h
deleted file mode 100644
index d8f9872..0000000
--- a/arch/um/include/asm/device.h
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * Arch specific extensions to struct device
- *
- * This file is released under the GPLv2
- */
-#include <asm-generic/device.h>
-
diff --git a/arch/um/include/asm/emergency-restart.h b/arch/um/include/asm/emergency-restart.h
deleted file mode 100644
index 108d8c4..0000000
--- a/arch/um/include/asm/emergency-restart.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_EMERGENCY_RESTART_H
-#define _ASM_EMERGENCY_RESTART_H
-
-#include <asm-generic/emergency-restart.h>
-
-#endif /* _ASM_EMERGENCY_RESTART_H */
diff --git a/arch/um/include/asm/ftrace.h b/arch/um/include/asm/ftrace.h
deleted file mode 100644
index 40a8c17..0000000
--- a/arch/um/include/asm/ftrace.h
+++ /dev/null
@@ -1 +0,0 @@
-/* empty */
diff --git a/arch/um/include/asm/futex.h b/arch/um/include/asm/futex.h
deleted file mode 100644
index 6a332a9..0000000
--- a/arch/um/include/asm/futex.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_FUTEX_H
-#define _ASM_FUTEX_H
-
-#include <asm-generic/futex.h>
-
-#endif
diff --git a/arch/um/include/asm/hardirq.h b/arch/um/include/asm/hardirq.h
deleted file mode 100644
index fb3c05a..0000000
--- a/arch/um/include/asm/hardirq.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/hardirq.h>
diff --git a/arch/um/include/asm/hw_irq.h b/arch/um/include/asm/hw_irq.h
deleted file mode 100644
index 1cf84cf..0000000
--- a/arch/um/include/asm/hw_irq.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _ASM_UM_HW_IRQ_H
-#define _ASM_UM_HW_IRQ_H
-
-#include "asm/irq.h"
-#include "asm/archparam.h"
-
-#endif
diff --git a/arch/um/include/asm/irq_regs.h b/arch/um/include/asm/irq_regs.h
deleted file mode 100644
index 3dd9c0b..0000000
--- a/arch/um/include/asm/irq_regs.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/irq_regs.h>
diff --git a/arch/um/include/asm/irq_vectors.h b/arch/um/include/asm/irq_vectors.h
deleted file mode 100644
index 272a81e..0000000
--- a/arch/um/include/asm/irq_vectors.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __UM_IRQ_VECTORS_H
-#define __UM_IRQ_VECTORS_H
-
-#endif
-
diff --git a/arch/um/include/asm/irqflags.h b/arch/um/include/asm/irqflags.h
index 659b9ab..c780d8a 100644
--- a/arch/um/include/asm/irqflags.h
+++ b/arch/um/include/asm/irqflags.h
@@ -1,6 +1,42 @@
 #ifndef __UM_IRQFLAGS_H
 #define __UM_IRQFLAGS_H
 
-/* Empty for now */
+extern int get_signals(void);
+extern int set_signals(int enable);
+extern void block_signals(void);
+extern void unblock_signals(void);
+
+static inline unsigned long arch_local_save_flags(void)
+{
+	return get_signals();
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+	set_signals(flags);
+}
+
+static inline void arch_local_irq_enable(void)
+{
+	unblock_signals();
+}
+
+static inline void arch_local_irq_disable(void)
+{
+	block_signals();
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+	unsigned long flags;
+	flags = arch_local_save_flags();
+	arch_local_irq_disable();
+	return flags;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+	return arch_local_save_flags() == 0;
+}
 
 #endif
diff --git a/arch/um/include/asm/kdebug.h b/arch/um/include/asm/kdebug.h
deleted file mode 100644
index 6ece1b0..0000000
--- a/arch/um/include/asm/kdebug.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kdebug.h>
diff --git a/arch/um/include/asm/mmu.h b/arch/um/include/asm/mmu.h
index cf259de..30509b9 100644
--- a/arch/um/include/asm/mmu.h
+++ b/arch/um/include/asm/mmu.h
@@ -1,12 +1,24 @@
 /* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  * Licensed under the GPL
  */
 
-#ifndef __MMU_H
-#define __MMU_H
+#ifndef __ARCH_UM_MMU_H
+#define __ARCH_UM_MMU_H
 
-#include "um_mmu.h"
+#include "mm_id.h"
+#include <asm/mm_context.h>
 
-#endif
+typedef struct mm_context {
+	struct mm_id id;
+	struct uml_arch_mm_context arch;
+	struct page **stub_pages;
+} mm_context_t;
+
+extern void __switch_mm(struct mm_id * mm_idp);
 
+/* Avoid tangled inclusion with asm/ldt.h */
+extern long init_new_ldt(struct mm_context *to_mm, struct mm_context *from_mm);
+extern void free_ldt(struct mm_context *mm);
+
+#endif
diff --git a/arch/um/include/asm/mmu_context.h b/arch/um/include/asm/mmu_context.h
index 34d8130..591b3d8 100644
--- a/arch/um/include/asm/mmu_context.h
+++ b/arch/um/include/asm/mmu_context.h
@@ -6,15 +6,12 @@
 #ifndef __UM_MMU_CONTEXT_H
 #define __UM_MMU_CONTEXT_H
 
-#include "linux/sched.h"
-#include "um_mmu.h"
+#include <linux/sched.h>
+#include <asm/mmu.h>
 
 extern void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm);
 extern void arch_exit_mmap(struct mm_struct *mm);
 
-#define get_mmu_context(task) do ; while(0)
-#define activate_context(tsk) do ; while(0)
-
 #define deactivate_mm(tsk,mm)	do { } while (0)
 
 extern void force_flush_all(void);
diff --git a/arch/um/include/asm/page.h b/arch/um/include/asm/page.h
index 4cc9b6c..7cfc3ce 100644
--- a/arch/um/include/asm/page.h
+++ b/arch/um/include/asm/page.h
@@ -19,7 +19,7 @@
 struct page;
 
 #include <linux/types.h>
-#include <sysdep/vm-flags.h>
+#include <asm/vm-flags.h>
 
 /*
  * These are used to make use of C type-checking..
diff --git a/arch/um/include/asm/page_offset.h b/arch/um/include/asm/page_offset.h
deleted file mode 100644
index 1c168df..0000000
--- a/arch/um/include/asm/page_offset.h
+++ /dev/null
@@ -1 +0,0 @@
-#define PAGE_OFFSET_RAW (uml_physmem)
diff --git a/arch/um/include/asm/pda.h b/arch/um/include/asm/pda.h
deleted file mode 100644
index ddcd774..0000000
--- a/arch/um/include/asm/pda.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#ifndef __UM_PDA_X86_64_H
-#define __UM_PDA_X86_64_H
-
-/* XXX */
-struct foo {
-	unsigned int __softirq_pending;
-	unsigned int __nmi_count;
-};
-
-extern struct foo me;
-
-#define read_pda(me) (&me)
-
-#endif
-
diff --git a/arch/um/include/asm/percpu.h b/arch/um/include/asm/percpu.h
deleted file mode 100644
index efe7508..0000000
--- a/arch/um/include/asm/percpu.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __UM_PERCPU_H
-#define __UM_PERCPU_H
-
-#include <asm-generic/percpu.h>
-
-#endif /* __UM_PERCPU_H */
diff --git a/arch/um/include/asm/ptrace-generic.h b/arch/um/include/asm/ptrace-generic.h
index 1a7d275..f605d3c 100644
--- a/arch/um/include/asm/ptrace-generic.h
+++ b/arch/um/include/asm/ptrace-generic.h
@@ -23,17 +23,10 @@ struct pt_regs {
 #define PT_REGS_IP(r) UPT_IP(&(r)->regs)
 #define PT_REGS_SP(r) UPT_SP(&(r)->regs)
 
-#define PT_REG(r, reg) UPT_REG(&(r)->regs, reg)
-#define PT_REGS_SET(r, reg, val) UPT_SET(&(r)->regs, reg, val)
-
-#define PT_REGS_SET_SYSCALL_RETURN(r, res) \
-	UPT_SET_SYSCALL_RETURN(&(r)->regs, res)
 #define PT_REGS_RESTART_SYSCALL(r) UPT_RESTART_SYSCALL(&(r)->regs)
 
 #define PT_REGS_SYSCALL_NR(r) UPT_SYSCALL_NR(&(r)->regs)
 
-#define PT_REGS_SC(r) UPT_SC(&(r)->regs)
-
 #define instruction_pointer(regs) PT_REGS_IP(regs)
 
 struct task_struct;
diff --git a/arch/um/include/asm/required-features.h b/arch/um/include/asm/required-features.h
deleted file mode 100644
index dfb967b..0000000
--- a/arch/um/include/asm/required-features.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __UM_REQUIRED_FEATURES_H
-#define __UM_REQUIRED_FEATURES_H
-
-/*
- * Nothing to see, just need something for the i386 and x86_64 asm
- * headers to include.
- */
-
-#endif
diff --git a/arch/um/include/asm/sections.h b/arch/um/include/asm/sections.h
deleted file mode 100644
index 6b0231e..0000000
--- a/arch/um/include/asm/sections.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _UM_SECTIONS_H
-#define _UM_SECTIONS_H
-
-/* nothing to see, move along */
-#include <asm-generic/sections.h>
-
-#endif
diff --git a/arch/um/include/asm/segment.h b/arch/um/include/asm/segment.h
deleted file mode 100644
index 45183fc..0000000
--- a/arch/um/include/asm/segment.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __UM_SEGMENT_H
-#define __UM_SEGMENT_H
-
-extern int host_gdt_entry_tls_min;
-
-#define GDT_ENTRY_TLS_ENTRIES 3
-#define GDT_ENTRY_TLS_MIN host_gdt_entry_tls_min
-#define GDT_ENTRY_TLS_MAX (GDT_ENTRY_TLS_MIN + GDT_ENTRY_TLS_ENTRIES - 1)
-
-#endif
diff --git a/arch/um/include/asm/system.h b/arch/um/include/asm/system.h
deleted file mode 100644
index 68a90ec..0000000
--- a/arch/um/include/asm/system.h
+++ /dev/null
@@ -1,47 +0,0 @@
-#ifndef __UM_SYSTEM_GENERIC_H
-#define __UM_SYSTEM_GENERIC_H
-
-#include "sysdep/system.h"
-
-extern int get_signals(void);
-extern int set_signals(int enable);
-extern void block_signals(void);
-extern void unblock_signals(void);
-
-static inline unsigned long arch_local_save_flags(void)
-{
-	return get_signals();
-}
-
-static inline void arch_local_irq_restore(unsigned long flags)
-{
-	set_signals(flags);
-}
-
-static inline void arch_local_irq_enable(void)
-{
-	unblock_signals();
-}
-
-static inline void arch_local_irq_disable(void)
-{
-	block_signals();
-}
-
-static inline unsigned long arch_local_irq_save(void)
-{
-	unsigned long flags;
-	flags = arch_local_save_flags();
-	arch_local_irq_disable();
-	return flags;
-}
-
-static inline bool arch_irqs_disabled(void)
-{
-	return arch_local_save_flags() == 0;
-}
-
-extern void *_switch_to(void *prev, void *next, void *last);
-#define switch_to(prev, next, last) prev = _switch_to(prev, next, last)
-
-#endif
diff --git a/arch/um/include/asm/topology.h b/arch/um/include/asm/topology.h
deleted file mode 100644
index 0905e4f..0000000
--- a/arch/um/include/asm/topology.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_UM_TOPOLOGY_H
-#define _ASM_UM_TOPOLOGY_H
-
-#include <asm-generic/topology.h>
-
-#endif
diff --git a/arch/um/include/asm/uaccess.h b/arch/um/include/asm/uaccess.h
index b9a895d..3f22fbf 100644
--- a/arch/um/include/asm/uaccess.h
+++ b/arch/um/include/asm/uaccess.h
@@ -6,15 +6,15 @@
 #ifndef __UM_UACCESS_H
 #define __UM_UACCESS_H
 
-#include <asm/errno.h>
-#include <asm/processor.h>
-
 /* thread_info has a mm_segment_t in it, so put the definition up here */
 typedef struct {
 	unsigned long seg;
 } mm_segment_t;
 
-#include "linux/thread_info.h"
+#include <linux/thread_info.h>
+#include <linux/errno.h>
+#include <asm/processor.h>
+#include <asm/elf.h>
 
 #define VERIFY_READ 0
 #define VERIFY_WRITE 1
@@ -38,7 +38,86 @@ typedef struct {
 
 #define segment_eq(a, b) ((a).seg == (b).seg)
 
-#include "um_uaccess.h"
+#define __under_task_size(addr, size) \
+	(((unsigned long) (addr) < TASK_SIZE) && \
+	 (((unsigned long) (addr) + (size)) < TASK_SIZE))
+
+#define __access_ok_vsyscall(type, addr, size) \
+	 ((type == VERIFY_READ) && \
+	  ((unsigned long) (addr) >= FIXADDR_USER_START) && \
+	  ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \
+	  ((unsigned long) (addr) + (size) >= (unsigned long)(addr)))
+
+#define __addr_range_nowrap(addr, size) \
+	((unsigned long) (addr) <= ((unsigned long) (addr) + (size)))
+
+#define access_ok(type, addr, size) \
+	(__addr_range_nowrap(addr, size) && \
+	 (__under_task_size(addr, size) || \
+	  __access_ok_vsyscall(type, addr, size) || \
+	  segment_eq(get_fs(), KERNEL_DS)))
+
+extern int copy_from_user(void *to, const void __user *from, int n);
+extern int copy_to_user(void __user *to, const void *from, int n);
+
+/*
+ * strncpy_from_user: - Copy a NUL terminated string from userspace.
+ * @dst:   Destination address, in kernel space.  This buffer must be at
+ *         least @count bytes long.
+ * @src:   Source address, in user space.
+ * @count: Maximum number of bytes to copy, including the trailing NUL.
+ *
+ * Copies a NUL-terminated string from userspace to kernel space.
+ *
+ * On success, returns the length of the string (not including the trailing
+ * NUL).
+ *
+ * If access to userspace fails, returns -EFAULT (some data may have been
+ * copied).
+ *
+ * If @count is smaller than the length of the string, copies @count bytes
+ * and returns @count.
+ */
+
+extern int strncpy_from_user(char *dst, const char __user *src, int count);
+
+/*
+ * __clear_user: - Zero a block of memory in user space, with less checking.
+ * @to:   Destination address, in user space.
+ * @n:    Number of bytes to zero.
+ *
+ * Zero a block of memory in user space.  Caller must check
+ * the specified block with access_ok() before calling this function.
+ *
+ * Returns number of bytes that could not be cleared.
+ * On success, this will be zero.
+ */
+extern int __clear_user(void __user *mem, int len);
+
+/*
+ * clear_user: - Zero a block of memory in user space.
+ * @to:   Destination address, in user space.
+ * @n:    Number of bytes to zero.
+ *
+ * Zero a block of memory in user space.
+ *
+ * Returns number of bytes that could not be cleared.
+ * On success, this will be zero.
+ */
+extern int clear_user(void __user *mem, int len);
+
+/*
+ * strlen_user: - Get the size of a string in user space.
+ * @str: The string to measure.
+ * @n:   The maximum valid length
+ *
+ * Get the size of a NUL-terminated string in user space.
+ *
+ * Returns the size of the string INCLUDING the terminating NUL.
+ * On exception, returns 0.
+ * If the string is too long, returns a value greater than @n.
+ */
+extern int strnlen_user(const void __user *str, int len);
 
 #define __copy_from_user(to, from, n) copy_from_user(to, from, n)
 
diff --git a/arch/um/include/asm/xor.h b/arch/um/include/asm/xor.h
deleted file mode 100644
index a19db3e..0000000
--- a/arch/um/include/asm/xor.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __UM_XOR_H
-#define __UM_XOR_H
-
-#include "asm-generic/xor.h"
-
-#endif
diff --git a/arch/um/include/shared/as-layout.h b/arch/um/include/shared/as-layout.h
index a92b678..896e166 100644
--- a/arch/um/include/shared/as-layout.h
+++ b/arch/um/include/shared/as-layout.h
@@ -6,7 +6,7 @@
 #ifndef __START_H__
 #define __START_H__
 
-#include "kern_constants.h"
+#include <generated/asm-offsets.h>
 
 /*
  * Stolen from linux/const.h, which can't be directly included since
diff --git a/arch/um/include/shared/chan_kern.h b/arch/um/include/shared/chan_kern.h
deleted file mode 100644
index 1e65145..0000000
--- a/arch/um/include/shared/chan_kern.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* 
- * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __CHAN_KERN_H__
-#define __CHAN_KERN_H__
-
-#include "linux/tty.h"
-#include "linux/list.h"
-#include "linux/console.h"
-#include "chan_user.h"
-#include "line.h"
-
-struct chan {
-	struct list_head list;
-	struct list_head free_list;
-	struct line *line;
-	char *dev;
-	unsigned int primary:1;
-	unsigned int input:1;
-	unsigned int output:1;
-	unsigned int opened:1;
-	unsigned int enabled:1;
-	int fd;
-	const struct chan_ops *ops;
-	void *data;
-};
-
-extern void chan_interrupt(struct list_head *chans, struct delayed_work *task,
-			   struct tty_struct *tty, int irq);
-extern int parse_chan_pair(char *str, struct line *line, int device,
-			   const struct chan_opts *opts, char **error_out);
-extern int write_chan(struct list_head *chans, const char *buf, int len,
-			     int write_irq);
-extern int console_write_chan(struct list_head *chans, const char *buf, 
-			      int len);
-extern int console_open_chan(struct line *line, struct console *co);
-extern void deactivate_chan(struct list_head *chans, int irq);
-extern void reactivate_chan(struct list_head *chans, int irq);
-extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty);
-extern int enable_chan(struct line *line);
-extern void close_chan(struct list_head *chans, int delay_free_irq);
-extern int chan_window_size(struct list_head *chans, 
-			     unsigned short *rows_out, 
-			     unsigned short *cols_out);
-extern int chan_config_string(struct list_head *chans, char *str, int size,
-			      char **error_out);
-
-#endif
diff --git a/arch/um/include/shared/chan_user.h b/arch/um/include/shared/chan_user.h
deleted file mode 100644
index 9b9ced8..0000000
--- a/arch/um/include/shared/chan_user.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __CHAN_USER_H__
-#define __CHAN_USER_H__
-
-#include "init.h"
-
-struct chan_opts {
-	void (*const announce)(char *dev_name, int dev);
-	char *xterm_title;
-	const int raw;
-};
-
-enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE };
-
-struct chan_ops {
-	char *type;
-	void *(*init)(char *, int, const struct chan_opts *);
-	int (*open)(int, int, int, void *, char **);
-	void (*close)(int, void *);
-	int (*read)(int, char *, void *);
-	int (*write)(int, const char *, int, void *);
-	int (*console_write)(int, const char *, int);
-	int (*window_size)(int, void *, unsigned short *, unsigned short *);
-	void (*free)(void *);
-	int winch;
-};
-
-extern const struct chan_ops fd_ops, null_ops, port_ops, pts_ops, pty_ops,
-	tty_ops, xterm_ops;
-
-extern void generic_close(int fd, void *unused);
-extern int generic_read(int fd, char *c_out, void *unused);
-extern int generic_write(int fd, const char *buf, int n, void *unused);
-extern int generic_console_write(int fd, const char *buf, int n);
-extern int generic_window_size(int fd, void *unused, unsigned short *rows_out,
-			       unsigned short *cols_out);
-extern void generic_free(void *data);
-
-struct tty_struct;
-extern void register_winch(int fd,  struct tty_struct *tty);
-extern void register_winch_irq(int fd, int tty_fd, int pid,
-			       struct tty_struct *tty, unsigned long stack);
-
-#define __channel_help(fn, prefix) \
-__uml_help(fn, prefix "[0-9]*=<channel description>\n" \
-"    Attach a console or serial line to a host channel.  See\n" \
-"    http://user-mode-linux.sourceforge.net/old/input.html for a complete\n" \
-"    description of this switch.\n\n" \
-);
-
-#endif
diff --git a/arch/um/include/shared/common-offsets.h b/arch/um/include/shared/common-offsets.h
index 72009c7..d7fe563 100644
--- a/arch/um/include/shared/common-offsets.h
+++ b/arch/um/include/shared/common-offsets.h
@@ -2,7 +2,6 @@
 
 DEFINE(KERNEL_MADV_REMOVE, MADV_REMOVE);
 
-OFFSET(HOST_TASK_REGS, task_struct, thread.regs);
 OFFSET(HOST_TASK_PID, task_struct, pid);
 
 DEFINE(UM_KERN_PAGE_SIZE, PAGE_SIZE);
diff --git a/arch/um/include/shared/initrd.h b/arch/um/include/shared/initrd.h
deleted file mode 100644
index 22673bc..0000000
--- a/arch/um/include/shared/initrd.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __INITRD_USER_H__
-#define __INITRD_USER_H__
-
-extern int load_initrd(char *filename, void *buf, int size);
-
-#endif
-
diff --git a/arch/um/include/shared/kern.h b/arch/um/include/shared/kern.h
index 4ce3fc6..6cd0124 100644
--- a/arch/um/include/shared/kern.h
+++ b/arch/um/include/shared/kern.h
@@ -13,28 +13,10 @@
  * includes.
  */
 
-extern int errno;
-
-extern int clone(int (*proc)(void *), void *sp, int flags, void *data);
-extern int sleep(int);
 extern int printf(const char *fmt, ...);
-extern char *strerror(int errnum);
-extern char *ptsname(int __fd);
-extern int munmap(void *, int);
 extern void *sbrk(int increment);
-extern void *malloc(int size);
-extern void perror(char *err);
-extern int kill(int pid, int sig);
-extern int getuid(void);
-extern int getgid(void);
 extern int pause(void);
-extern int write(int, const void *, int);
 extern void exit(int);
-extern int close(int);
-extern int read(unsigned int, char *, int);
-extern int pipe(int *);
-extern int sched_yield(void);
-extern int ptrace(int op, int pid, long addr, long data);
 
 #endif
 
diff --git a/arch/um/include/shared/kern_util.h b/arch/um/include/shared/kern_util.h
index 3c34122..0f14838 100644
--- a/arch/um/include/shared/kern_util.h
+++ b/arch/um/include/shared/kern_util.h
@@ -21,7 +21,6 @@ extern unsigned long alloc_stack(int order, int atomic);
 extern void free_stack(unsigned long stack, int order);
 
 extern int do_signal(void);
-extern void copy_sc(struct uml_pt_regs *regs, void *from);
 extern void interrupt_end(void);
 extern void relay_signal(int sig, struct uml_pt_regs *regs);
 
diff --git a/arch/um/include/shared/ldt.h b/arch/um/include/shared/ldt.h
deleted file mode 100644
index a7f999a..0000000
--- a/arch/um/include/shared/ldt.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
- * Licensed under the GPL
- *
- * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
- */
-
-#ifndef __ASM_LDT_H
-#define __ASM_LDT_H
-
-#include <linux/mutex.h>
-#include <sysdep/host_ldt.h>
-
-extern void ldt_host_info(void);
-
-#define LDT_PAGES_MAX \
-	((LDT_ENTRIES * LDT_ENTRY_SIZE)/PAGE_SIZE)
-#define LDT_ENTRIES_PER_PAGE \
-	(PAGE_SIZE/LDT_ENTRY_SIZE)
-#define LDT_DIRECT_ENTRIES \
-	((LDT_PAGES_MAX*sizeof(void *))/LDT_ENTRY_SIZE)
-
-struct ldt_entry {
-	__u32 a;
-	__u32 b;
-};
-
-typedef struct uml_ldt {
-	int entry_count;
-	struct mutex lock;
-	union {
-		struct ldt_entry * pages[LDT_PAGES_MAX];
-		struct ldt_entry entries[LDT_DIRECT_ENTRIES];
-	} u;
-} uml_ldt_t;
-
-#endif
diff --git a/arch/um/include/shared/line.h b/arch/um/include/shared/line.h
deleted file mode 100644
index 63df3ca..0000000
--- a/arch/um/include/shared/line.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/* 
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __LINE_H__
-#define __LINE_H__
-
-#include "linux/list.h"
-#include "linux/workqueue.h"
-#include "linux/tty.h"
-#include "linux/interrupt.h"
-#include "linux/spinlock.h"
-#include "linux/mutex.h"
-#include "chan_user.h"
-#include "mconsole_kern.h"
-
-/* There's only one modifiable field in this - .mc.list */
-struct line_driver {
-	const char *name;
-	const char *device_name;
-	const short major;
-	const short minor_start;
-	const short type;
-	const short subtype;
-	const int read_irq;
-	const char *read_irq_name;
-	const int write_irq;
-	const char *write_irq_name;
-	struct mc_device mc;
-};
-
-struct line {
-	struct tty_struct *tty;
-	spinlock_t count_lock;
-	unsigned long count;
-	int valid;
-
-	char *init_str;
-	int init_pri;
-	struct list_head chan_list;
-
-	/*This lock is actually, mostly, local to*/
-	spinlock_t lock;
-	int throttled;
-	/* Yes, this is a real circular buffer.
-	 * XXX: And this should become a struct kfifo!
-	 *
-	 * buffer points to a buffer allocated on demand, of length
-	 * LINE_BUFSIZE, head to the start of the ring, tail to the end.*/
-	char *buffer;
-	char *head;
-	char *tail;
-
-	int sigio;
-	struct delayed_work task;
-	const struct line_driver *driver;
-	int have_irq;
-};
-
-#define LINE_INIT(str, d) \
-	{ .count_lock =	__SPIN_LOCK_UNLOCKED((str).count_lock), \
-	  .init_str =	str,	\
-	  .init_pri =	INIT_STATIC, \
-	  .valid =	1, \
-	  .lock =	__SPIN_LOCK_UNLOCKED((str).lock), \
-	  .driver =	d }
-
-extern void line_close(struct tty_struct *tty, struct file * filp);
-extern int line_open(struct line *lines, struct tty_struct *tty);
-extern int line_setup(struct line *lines, unsigned int sizeof_lines,
-		      char *init, char **error_out);
-extern int line_write(struct tty_struct *tty, const unsigned char *buf,
-		      int len);
-extern int line_put_char(struct tty_struct *tty, unsigned char ch);
-extern void line_set_termios(struct tty_struct *tty, struct ktermios * old);
-extern int line_chars_in_buffer(struct tty_struct *tty);
-extern void line_flush_buffer(struct tty_struct *tty);
-extern void line_flush_chars(struct tty_struct *tty);
-extern int line_write_room(struct tty_struct *tty);
-extern int line_ioctl(struct tty_struct *tty, unsigned int cmd,
-				unsigned long arg);
-extern void line_throttle(struct tty_struct *tty);
-extern void line_unthrottle(struct tty_struct *tty);
-
-extern char *add_xterm_umid(char *base);
-extern int line_setup_irq(int fd, int input, int output, struct line *line,
-			  void *data);
-extern void line_close_chan(struct line *line);
-extern struct tty_driver *register_lines(struct line_driver *line_driver,
-					 const struct tty_operations *driver,
-					 struct line *lines, int nlines);
-extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts);
-extern void close_lines(struct line *lines, int nlines);
-
-extern int line_config(struct line *lines, unsigned int sizeof_lines,
-		       char *str, const struct chan_opts *opts,
-		       char **error_out);
-extern int line_id(char **str, int *start_out, int *end_out);
-extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n,
-		       char **error_out);
-extern int line_get_config(char *dev, struct line *lines,
-			   unsigned int sizeof_lines, char *str,
-			   int size, char **error_out);
-
-#endif
diff --git a/arch/um/include/shared/mconsole.h b/arch/um/include/shared/mconsole.h
deleted file mode 100644
index c139ae1..0000000
--- a/arch/um/include/shared/mconsole.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
- * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#ifndef __MCONSOLE_H__
-#define __MCONSOLE_H__
-
-#ifndef __KERNEL__
-#include <stdint.h>
-#define u32 uint32_t
-#endif
-
-#include "sysdep/ptrace.h"
-
-#define MCONSOLE_MAGIC (0xcafebabe)
-#define MCONSOLE_MAX_DATA (512)
-#define MCONSOLE_VERSION 2
-
-struct mconsole_request {
-	u32 magic;
-	u32 version;
-	u32 len;
-	char data[MCONSOLE_MAX_DATA];
-};
-
-struct mconsole_reply {
-	u32 err;
-	u32 more;
-	u32 len;
-	char data[MCONSOLE_MAX_DATA];
-};
-
-struct mconsole_notify {
-	u32 magic;
-	u32 version;
-	enum { MCONSOLE_SOCKET, MCONSOLE_PANIC, MCONSOLE_HANG,
-	       MCONSOLE_USER_NOTIFY } type;
-	u32 len;
-	char data[MCONSOLE_MAX_DATA];
-};
-
-struct mc_request;
-
-enum mc_context { MCONSOLE_INTR, MCONSOLE_PROC };
-
-struct mconsole_command
-{
-	char *command;
-	void (*handler)(struct mc_request *req);
-	enum mc_context context;
-};
-
-struct mc_request
-{
-	int len;
-	int as_interrupt;
-
-	int originating_fd;
-	unsigned int originlen;
-	unsigned char origin[128];			/* sockaddr_un */
-
-	struct mconsole_request request;
-	struct mconsole_command *cmd;
-	struct uml_pt_regs regs;
-};
-
-extern char mconsole_socket_name[];
-
-extern int mconsole_unlink_socket(void);
-extern int mconsole_reply_len(struct mc_request *req, const char *reply,
-			      int len, int err, int more);
-extern int mconsole_reply(struct mc_request *req, const char *str, int err,
-			  int more);
-
-extern void mconsole_version(struct mc_request *req);
-extern void mconsole_help(struct mc_request *req);
-extern void mconsole_halt(struct mc_request *req);
-extern void mconsole_reboot(struct mc_request *req);
-extern void mconsole_config(struct mc_request *req);
-extern void mconsole_remove(struct mc_request *req);
-extern void mconsole_sysrq(struct mc_request *req);
-extern void mconsole_cad(struct mc_request *req);
-extern void mconsole_stop(struct mc_request *req);
-extern void mconsole_go(struct mc_request *req);
-extern void mconsole_log(struct mc_request *req);
-extern void mconsole_proc(struct mc_request *req);
-extern void mconsole_stack(struct mc_request *req);
-
-extern int mconsole_get_request(int fd, struct mc_request *req);
-extern int mconsole_notify(char *sock_name, int type, const void *data,
-			   int len);
-extern char *mconsole_notify_socket(void);
-extern void lock_notify(void);
-extern void unlock_notify(void);
-
-#endif
diff --git a/arch/um/include/shared/mconsole_kern.h b/arch/um/include/shared/mconsole_kern.h
deleted file mode 100644
index d2fe07e..0000000
--- a/arch/um/include/shared/mconsole_kern.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __MCONSOLE_KERN_H__
-#define __MCONSOLE_KERN_H__
-
-#include "linux/list.h"
-#include "mconsole.h"
-
-struct mconsole_entry {
-	struct list_head list;
-	struct mc_request request;
-};
-
-/* All these methods are called in process context. */
-struct mc_device {
-	struct list_head list;
-	char *name;
-	int (*config)(char *, char **);
-	int (*get_config)(char *, char *, int, char **);
-	int (*id)(char **, int *, int *);
-	int (*remove)(int, char **);
-};
-
-#define CONFIG_CHUNK(str, size, current, chunk, end) \
-do { \
-	current += strlen(chunk); \
-	if(current >= size) \
-		str = NULL; \
-	if(str != NULL){ \
-		strcpy(str, chunk); \
-		str += strlen(chunk); \
-	} \
-	if(end) \
-		current++; \
-} while(0)
-
-#ifdef CONFIG_MCONSOLE
-
-extern void mconsole_register_dev(struct mc_device *new);
-
-#else
-
-static inline void mconsole_register_dev(struct mc_device *new)
-{
-}
-
-#endif
-
-#endif
diff --git a/arch/um/include/shared/mem_kern.h b/arch/um/include/shared/mem_kern.h
deleted file mode 100644
index 69be0fd..0000000
--- a/arch/um/include/shared/mem_kern.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2003 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#ifndef __MEM_KERN_H__
-#define __MEM_KERN_H__
-
-#include "linux/list.h"
-#include "linux/types.h"
-
-struct remapper {
-	struct list_head list;
-	int (*proc)(int, unsigned long, int, __u64);
-};
-
-extern void register_remapper(struct remapper *info);
-
-#endif
-
diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h
index 83c7c2e..89b686c1 100644
--- a/arch/um/include/shared/os.h
+++ b/arch/um/include/shared/os.h
@@ -10,7 +10,6 @@
 #include "irq_user.h"
 #include "longjmp.h"
 #include "mm_id.h"
-#include "sysdep/tls.h"
 
 #define CATCH_EINTR(expr) while ((errno = 0, ((expr) < 0)) && (errno == EINTR))
 
@@ -203,12 +202,6 @@ extern int os_drop_memory(void *addr, int length);
 extern int can_drop_memory(void);
 extern void os_flush_stdout(void);
 
-/* uaccess.c */
-extern unsigned long __do_user_copy(void *to, const void *from, int n,
-				    void **fault_addr, jmp_buf **fault_catcher,
-				    void (*op)(void *to, const void *from,
-					       int n), int *faulted_out);
-
 /* execvp.c */
 extern int execvp_noalloc(char *buf, const char *file, char *const argv[]);
 /* helper.c */
@@ -218,10 +211,6 @@ extern int run_helper_thread(int (*proc)(void *), void *arg,
 extern int helper_wait(int pid);
 
 
-/* tls.c */
-extern int os_set_thread_area(user_desc_t *info, int pid);
-extern int os_get_thread_area(user_desc_t *info, int pid);
-
 /* umid.c */
 extern int umid_file_name(char *name, char *buf, int len);
 extern int set_umid(char *name);
@@ -231,7 +220,7 @@ extern char *get_umid(void);
 extern void timer_init(void);
 extern void set_sigstack(void *sig_stack, int size);
 extern void remove_sigstack(void);
-extern void set_handler(int sig, void (*handler)(int), int flags, ...);
+extern void set_handler(int sig);
 extern int change_sig(int signal, int on);
 extern void block_signals(void);
 extern void unblock_signals(void);
diff --git a/arch/um/include/shared/process.h b/arch/um/include/shared/process.h
deleted file mode 100644
index bb873a5..0000000
--- a/arch/um/include/shared/process.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* 
- * Copyright (C) 2000 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#ifndef __PROCESS_H__
-#define __PROCESS_H__
-
-#include <signal.h>
-
-/* Copied from linux/compiler-gcc.h since we can't include it directly */
-#define barrier() __asm__ __volatile__("": : :"memory")
-
-extern void sig_handler(int sig, struct sigcontext *sc);
-extern void alarm_handler(int sig, struct sigcontext *sc);
-
-#endif
diff --git a/arch/um/include/shared/ptrace_user.h b/arch/um/include/shared/ptrace_user.h
index 7fd8539..56b2f28 100644
--- a/arch/um/include/shared/ptrace_user.h
+++ b/arch/um/include/shared/ptrace_user.h
@@ -6,7 +6,8 @@
 #ifndef __PTRACE_USER_H__
 #define __PTRACE_USER_H__
 
-#include "sysdep/ptrace_user.h"
+#include <sys/ptrace.h>
+#include <sysdep/ptrace_user.h>
 
 extern int ptrace_getregs(long pid, unsigned long *regs_out);
 extern int ptrace_setregs(long pid, unsigned long *regs_in);
diff --git a/arch/um/include/shared/skas_ptregs.h b/arch/um/include/shared/skas_ptregs.h
deleted file mode 100644
index 73db19e..0000000
--- a/arch/um/include/shared/skas_ptregs.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __SKAS_PT_REGS_
-#define __SKAS_PT_REGS_
-
-#include <user_constants.h>
-
-#endif
diff --git a/arch/um/include/shared/syscall.h b/arch/um/include/shared/syscall.h
deleted file mode 100644
index dda1df9..0000000
--- a/arch/um/include/shared/syscall.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYSCALL_USER_H
-#define __SYSCALL_USER_H
-
-extern int record_syscall_start(int syscall);
-extern void record_syscall_end(int index, long result);
-
-#endif
diff --git a/arch/um/include/shared/task.h b/arch/um/include/shared/task.h
deleted file mode 100644
index 3fe726b..0000000
--- a/arch/um/include/shared/task.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __TASK_H
-#define __TASK_H
-
-#include <kern_constants.h>
-
-#define TASK_REGS(task) ((struct uml_pt_regs *) &(((char *) (task))[HOST_TASK_REGS]))
-#define TASK_PID(task) *((int *) &(((char *) (task))[HOST_TASK_PID]))
-
-#endif
diff --git a/arch/um/include/shared/tlb.h b/arch/um/include/shared/tlb.h
deleted file mode 100644
index ecd2265..0000000
--- a/arch/um/include/shared/tlb.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __TLB_H__
-#define __TLB_H__
-
-#include "um_mmu.h"
-
-extern void force_flush_all(void);
-extern int flush_tlb_kernel_range_common(unsigned long start,
-					 unsigned long end);
-
-#endif
diff --git a/arch/um/include/shared/ubd_user.h b/arch/um/include/shared/ubd_user.h
deleted file mode 100644
index 3845051..0000000
--- a/arch/um/include/shared/ubd_user.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* 
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
- * Copyright (C) 2001 RidgeRun, Inc (glonnon@ridgerun.com)
- * Licensed under the GPL
- */
-
-#ifndef __UM_UBD_USER_H
-#define __UM_UBD_USER_H
-
-extern void ignore_sigwinch_sig(void);
-extern int start_io_thread(unsigned long sp, int *fds_out);
-extern int io_thread(void *arg);
-extern int kernel_fd;
-
-#endif
-
diff --git a/arch/um/include/shared/um_malloc.h b/arch/um/include/shared/um_malloc.h
index c554d70..6395fef 100644
--- a/arch/um/include/shared/um_malloc.h
+++ b/arch/um/include/shared/um_malloc.h
@@ -6,7 +6,7 @@
 #ifndef __UM_MALLOC_H__
 #define __UM_MALLOC_H__
 
-#include "kern_constants.h"
+#include <generated/asm-offsets.h>
 
 extern void *uml_kmalloc(int size, int flags);
 extern void kfree(const void *ptr);
diff --git a/arch/um/include/shared/um_mmu.h b/arch/um/include/shared/um_mmu.h
deleted file mode 100644
index b1a7e47..0000000
--- a/arch/um/include/shared/um_mmu.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* 
- * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#ifndef __ARCH_UM_MMU_H
-#define __ARCH_UM_MMU_H
-
-#include "mm_id.h"
-#include "ldt.h"
-
-typedef struct mm_context {
-	struct mm_id id;
-	struct uml_ldt ldt;
-	struct page **stub_pages;
-} mm_context_t;
-
-extern void __switch_mm(struct mm_id * mm_idp);
-
-/* Avoid tangled inclusion with asm/ldt.h */
-extern long init_new_ldt(struct mm_context *to_mm, struct mm_context *from_mm);
-extern void free_ldt(struct mm_context *mm);
-
-#endif
diff --git a/arch/um/include/shared/um_uaccess.h b/arch/um/include/shared/um_uaccess.h
deleted file mode 100644
index 45c0499..0000000
--- a/arch/um/include/shared/um_uaccess.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/* 
- * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#ifndef __ARCH_UM_UACCESS_H
-#define __ARCH_UM_UACCESS_H
-
-#include <asm/elf.h>
-#include <asm/fixmap.h>
-#include "sysdep/archsetjmp.h"
-
-#define __under_task_size(addr, size) \
-	(((unsigned long) (addr) < TASK_SIZE) && \
-	 (((unsigned long) (addr) + (size)) < TASK_SIZE))
-
-#define __access_ok_vsyscall(type, addr, size) \
-	 ((type == VERIFY_READ) && \
-	  ((unsigned long) (addr) >= FIXADDR_USER_START) && \
-	  ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \
-	  ((unsigned long) (addr) + (size) >= (unsigned long)(addr)))
-
-#define __addr_range_nowrap(addr, size) \
-	((unsigned long) (addr) <= ((unsigned long) (addr) + (size)))
-
-#define access_ok(type, addr, size) \
-	(__addr_range_nowrap(addr, size) && \
-	 (__under_task_size(addr, size) || \
-	  __access_ok_vsyscall(type, addr, size) || \
-	  segment_eq(get_fs(), KERNEL_DS)))
-
-extern int copy_from_user(void *to, const void __user *from, int n);
-extern int copy_to_user(void __user *to, const void *from, int n);
-
-extern int __do_copy_to_user(void *to, const void *from, int n,
-			     void **fault_addr, jmp_buf **fault_catcher);
-
-/*
- * strncpy_from_user: - Copy a NUL terminated string from userspace.
- * @dst:   Destination address, in kernel space.  This buffer must be at
- *         least @count bytes long.
- * @src:   Source address, in user space.
- * @count: Maximum number of bytes to copy, including the trailing NUL.
- *
- * Copies a NUL-terminated string from userspace to kernel space.
- *
- * On success, returns the length of the string (not including the trailing
- * NUL).
- *
- * If access to userspace fails, returns -EFAULT (some data may have been
- * copied).
- *
- * If @count is smaller than the length of the string, copies @count bytes
- * and returns @count.
- */
-
-extern int strncpy_from_user(char *dst, const char __user *src, int count);
-
-/*
- * __clear_user: - Zero a block of memory in user space, with less checking.
- * @to:   Destination address, in user space.
- * @n:    Number of bytes to zero.
- *
- * Zero a block of memory in user space.  Caller must check
- * the specified block with access_ok() before calling this function.
- *
- * Returns number of bytes that could not be cleared.
- * On success, this will be zero.
- */
-extern int __clear_user(void __user *mem, int len);
-
-/*
- * clear_user: - Zero a block of memory in user space.
- * @to:   Destination address, in user space.
- * @n:    Number of bytes to zero.
- *
- * Zero a block of memory in user space.
- *
- * Returns number of bytes that could not be cleared.
- * On success, this will be zero.
- */
-extern int clear_user(void __user *mem, int len);
-
-/*
- * strlen_user: - Get the size of a string in user space.
- * @str: The string to measure.
- * @n:   The maximum valid length
- *
- * Get the size of a NUL-terminated string in user space.
- *
- * Returns the size of the string INCLUDING the terminating NUL.
- * On exception, returns 0.
- * If the string is too long, returns a value greater than @n.
- */
-extern int strnlen_user(const void __user *str, int len);
-
-#endif
diff --git a/arch/um/include/shared/user.h b/arch/um/include/shared/user.h
index 293f7c7..4fa82c0 100644
--- a/arch/um/include/shared/user.h
+++ b/arch/um/include/shared/user.h
@@ -6,7 +6,7 @@
 #ifndef __USER_H__
 #define __USER_H__
 
-#include "kern_constants.h"
+#include <generated/asm-offsets.h>
 
 /*
  * The usual definition - copied here because the kernel provides its own,
@@ -36,10 +36,11 @@ static inline int printk(const char *fmt, ...)
 }
 #endif
 
-extern void schedule(void);
 extern int in_aton(char *str);
-extern int open_gdb_chan(void);
 extern size_t strlcpy(char *, const char *, size_t);
 extern size_t strlcat(char *, const char *, size_t);
 
+/* Copied from linux/compiler-gcc.h since we can't include it directly */
+#define barrier() __asm__ __volatile__("": : :"memory")
+
 #endif
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index c4491c1..bc49474 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -11,7 +11,7 @@ clean-files :=
 
 obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \
 	physmem.o process.o ptrace.o reboot.o sigio.o \
-	signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o uaccess.o \
+	signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o \
 	um_arch.o umid.o skas/
 
 obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c
index 939a4a6..6cade93 100644
--- a/arch/um/kernel/exec.c
+++ b/arch/um/kernel/exec.c
@@ -3,14 +3,15 @@
  * Licensed under the GPL
  */
 
-#include "linux/stddef.h"
-#include "linux/fs.h"
-#include "linux/ptrace.h"
-#include "linux/sched.h"
-#include "linux/slab.h"
-#include "asm/current.h"
-#include "asm/processor.h"
-#include "asm/uaccess.h"
+#include <linux/stddef.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/ptrace.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <asm/current.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
 #include "as-layout.h"
 #include "mem_user.h"
 #include "skas.h"
@@ -41,6 +42,7 @@ void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
 	PT_REGS_IP(regs) = eip;
 	PT_REGS_SP(regs) = esp;
 }
+EXPORT_SYMBOL(start_thread);
 
 static long execve1(const char *file,
 		    const char __user *const __user *argv,
diff --git a/arch/um/kernel/gmon_syms.c b/arch/um/kernel/gmon_syms.c
index 72eccd2..e9bcf247 100644
--- a/arch/um/kernel/gmon_syms.c
+++ b/arch/um/kernel/gmon_syms.c
@@ -7,18 +7,3 @@
 
 extern void __bb_init_func(void *)  __attribute__((weak));
 EXPORT_SYMBOL(__bb_init_func);
-
-/*
- * This is defined (and referred to in profiling stub code) only by some GCC
- * versions in libgcov.
- *
- * Since SuSE backported the fix, we cannot handle it depending on GCC version.
- * So, unconditionally export it. But also give it a weak declaration, which
- * will be overridden by any other one.
- */
-
-extern void __gcov_init(void *) __attribute__((weak));
-EXPORT_SYMBOL(__gcov_init);
-
-extern void __gcov_merge_add(void *) __attribute__((weak));
-EXPORT_SYMBOL(__gcov_merge_add);
diff --git a/arch/um/kernel/initrd.c b/arch/um/kernel/initrd.c
index d386c75..10cc18f 100644
--- a/arch/um/kernel/initrd.c
+++ b/arch/um/kernel/initrd.c
@@ -7,12 +7,12 @@
 #include "linux/bootmem.h"
 #include "linux/initrd.h"
 #include "asm/types.h"
-#include "initrd.h"
 #include "init.h"
 #include "os.h"
 
 /* Changed by uml_initrd_setup, which is a setup */
 static char *initrd __initdata = NULL;
+static int load_initrd(char *filename, void *buf, int size);
 
 static int __init read_initrd(void)
 {
@@ -62,7 +62,7 @@ __uml_setup("initrd=", uml_initrd_setup,
 "    name of the file containing the image.\n\n"
 );
 
-int load_initrd(char *filename, void *buf, int size)
+static int load_initrd(char *filename, void *buf, int size)
 {
 	int fd, n;
 
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index 9e485c7..71b8c94 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -258,6 +258,7 @@ void deactivate_fd(int fd, int irqnum)
 
 	ignore_sigio_fd(fd);
 }
+EXPORT_SYMBOL(deactivate_fd);
 
 /*
  * Called just before shutdown in order to provide a clean exec
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
index 0ae0dfc..e17bea0 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -3,33 +3,11 @@
  * Licensed under the GPL
  */
 
-#include "linux/module.h"
-#include "linux/syscalls.h"
-#include "asm/tlbflush.h"
-#include "asm/uaccess.h"
-#include "as-layout.h"
-#include "kern_util.h"
-#include "mem_user.h"
+#include <linux/module.h>
 #include "os.h"
 
-EXPORT_SYMBOL(uml_physmem);
 EXPORT_SYMBOL(set_signals);
 EXPORT_SYMBOL(get_signals);
-EXPORT_SYMBOL(kernel_thread);
-EXPORT_SYMBOL(sys_waitpid);
-EXPORT_SYMBOL(flush_tlb_range);
-
-EXPORT_SYMBOL(high_physmem);
-EXPORT_SYMBOL(empty_zero_page);
-EXPORT_SYMBOL(handle_page_fault);
-EXPORT_SYMBOL(find_iomem);
-
-EXPORT_SYMBOL(strnlen_user);
-EXPORT_SYMBOL(strncpy_from_user);
-EXPORT_SYMBOL(copy_to_user);
-EXPORT_SYMBOL(copy_from_user);
-EXPORT_SYMBOL(clear_user);
-EXPORT_SYMBOL(uml_strdup);
 
 EXPORT_SYMBOL(os_stat_fd);
 EXPORT_SYMBOL(os_stat_file);
@@ -57,24 +35,10 @@ EXPORT_SYMBOL(os_connect_socket);
 EXPORT_SYMBOL(os_accept_connection);
 EXPORT_SYMBOL(os_rcv_fd);
 EXPORT_SYMBOL(run_helper);
-EXPORT_SYMBOL(start_thread);
 EXPORT_SYMBOL(os_major);
 EXPORT_SYMBOL(os_minor);
 EXPORT_SYMBOL(os_makedev);
 
 EXPORT_SYMBOL(add_sigio_fd);
 EXPORT_SYMBOL(ignore_sigio_fd);
-EXPORT_SYMBOL(deactivate_fd);
 EXPORT_SYMBOL(sigio_broken);
-
-#ifdef CONFIG_SMP
-
-/* required for SMP */
-
-extern void __write_lock_failed(rwlock_t *rw);
-EXPORT_SYMBOL(__write_lock_failed);
-
-extern void __read_lock_failed(rwlock_t *rw);
-EXPORT_SYMBOL(__read_lock_failed);
-
-#endif
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index 8137ccc..ebb86b2 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -4,6 +4,7 @@
  */
 
 #include <linux/stddef.h>
+#include <linux/module.h>
 #include <linux/bootmem.h>
 #include <linux/highmem.h>
 #include <linux/mm.h>
@@ -20,6 +21,7 @@
 
 /* allocated in paging_init, zeroed in mem_init, and unchanged thereafter */
 unsigned long *empty_zero_page = NULL;
+EXPORT_SYMBOL(empty_zero_page);
 /* allocated in paging_init and unchanged thereafter */
 static unsigned long *empty_bad_page = NULL;
 
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index a1a9090..f116db1 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -3,20 +3,22 @@
  * Licensed under the GPL
  */
 
-#include "linux/bootmem.h"
-#include "linux/mm.h"
-#include "linux/pfn.h"
-#include "asm/page.h"
-#include "as-layout.h"
-#include "init.h"
-#include "kern.h"
-#include "mem_user.h"
-#include "os.h"
+#include <linux/module.h>
+#include <linux/bootmem.h>
+#include <linux/mm.h>
+#include <linux/pfn.h>
+#include <asm/page.h>
+#include <as-layout.h>
+#include <init.h>
+#include <kern.h>
+#include <mem_user.h>
+#include <os.h>
 
 static int physmem_fd = -1;
 
 /* Changed during early boot */
 unsigned long high_physmem;
+EXPORT_SYMBOL(high_physmem);
 
 extern unsigned long long physmem_size;
 
@@ -184,6 +186,7 @@ unsigned long find_iomem(char *driver, unsigned long *len_out)
 
 	return 0;
 }
+EXPORT_SYMBOL(find_iomem);
 
 static int setup_iomem(void)
 {
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 21c1ae7..c533835 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -20,12 +20,12 @@
 #include <linux/threads.h>
 #include <asm/current.h>
 #include <asm/pgtable.h>
+#include <asm/mmu_context.h>
 #include <asm/uaccess.h>
 #include "as-layout.h"
 #include "kern_util.h"
 #include "os.h"
 #include "skas.h"
-#include "tlb.h"
 
 /*
  * This is a per-cpu array.  A processor only modifies its entry and it only
@@ -78,6 +78,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 		      &current->thread.regs, 0, NULL, NULL);
 	return pid;
 }
+EXPORT_SYMBOL(kernel_thread);
 
 static inline void set_current(struct task_struct *task)
 {
@@ -286,6 +287,7 @@ char *uml_strdup(const char *string)
 {
 	return kstrdup(string, GFP_KERNEL);
 }
+EXPORT_SYMBOL(uml_strdup);
 
 int copy_to_user_proc(void __user *to, void *from, int size)
 {
diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c
index b5c094c..e8b889d 100644
--- a/arch/um/kernel/signal.c
+++ b/arch/um/kernel/signal.c
@@ -11,7 +11,6 @@
 #include <asm/unistd.h>
 #include "frame_kern.h"
 #include "kern_util.h"
-#include <sysdep/sigcontext.h>
 
 EXPORT_SYMBOL(block_signals);
 EXPORT_SYMBOL(unblock_signals);
diff --git a/arch/um/kernel/skas/clone.c b/arch/um/kernel/skas/clone.c
index 2c8583c..e1fd066 100644
--- a/arch/um/kernel/skas/clone.c
+++ b/arch/um/kernel/skas/clone.c
@@ -8,7 +8,6 @@
 #include <asm/unistd.h>
 #include <sys/time.h>
 #include "as-layout.h"
-#include "kern_constants.h"
 #include "ptrace_user.h"
 #include "stub-data.h"
 #include "sysdep/stub.h"
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c
index 6966342..9fefd92 100644
--- a/arch/um/kernel/skas/uaccess.c
+++ b/arch/um/kernel/skas/uaccess.c
@@ -6,6 +6,7 @@
 #include <linux/err.h>
 #include <linux/highmem.h>
 #include <linux/mm.h>
+#include <linux/module.h>
 #include <linux/sched.h>
 #include <asm/current.h>
 #include <asm/page.h>
@@ -149,6 +150,7 @@ int copy_from_user(void *to, const void __user *from, int n)
 	       buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to):
 	       n;
 }
+EXPORT_SYMBOL(copy_from_user);
 
 static int copy_chunk_to_user(unsigned long to, int len, void *arg)
 {
@@ -170,6 +172,7 @@ int copy_to_user(void __user *to, const void *from, int n)
 	       buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) :
 	       n;
 }
+EXPORT_SYMBOL(copy_to_user);
 
 static int strncpy_chunk_from_user(unsigned long from, int len, void *arg)
 {
@@ -204,6 +207,7 @@ int strncpy_from_user(char *dst, const char __user *src, int count)
 		return -EFAULT;
 	return strnlen(dst, count);
 }
+EXPORT_SYMBOL(strncpy_from_user);
 
 static int clear_chunk(unsigned long addr, int len, void *unused)
 {
@@ -226,6 +230,7 @@ int clear_user(void __user *mem, int len)
 	return access_ok(VERIFY_WRITE, mem, len) ?
 	       buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len;
 }
+EXPORT_SYMBOL(clear_user);
 
 static int strnlen_chunk(unsigned long str, int len, void *arg)
 {
@@ -251,3 +256,4 @@ int strnlen_user(const void __user *str, int len)
 		return count + 1;
 	return -EFAULT;
 }
+EXPORT_SYMBOL(strnlen_user);
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
index d175d05..7f3d4d8 100644
--- a/arch/um/kernel/tlb.c
+++ b/arch/um/kernel/tlb.c
@@ -4,6 +4,7 @@
  */
 
 #include <linux/mm.h>
+#include <linux/module.h>
 #include <linux/sched.h>
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
@@ -11,7 +12,6 @@
 #include "mem_user.h"
 #include "os.h"
 #include "skas.h"
-#include "tlb.h"
 
 struct host_vm_change {
 	struct host_vm_op {
@@ -287,7 +287,7 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
 	}
 }
 
-int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
+static int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
 {
 	struct mm_struct *mm;
 	pgd_t *pgd;
@@ -499,6 +499,7 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
 		flush_tlb_kernel_range_common(start, end);
 	else fix_range(vma->vm_mm, start, end, 0);
 }
+EXPORT_SYMBOL(flush_tlb_range);
 
 void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
 			unsigned long end)
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index 8c7b882..dafc947 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -6,6 +6,7 @@
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/hardirq.h>
+#include <linux/module.h>
 #include <asm/current.h>
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
@@ -14,7 +15,6 @@
 #include "kern_util.h"
 #include "os.h"
 #include "skas.h"
-#include "sysdep/sigcontext.h"
 
 /*
  * Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by
@@ -112,6 +112,7 @@ out_of_memory:
 	pagefault_out_of_memory();
 	return 0;
 }
+EXPORT_SYMBOL(handle_page_fault);
 
 static void show_segv_info(struct uml_pt_regs *regs)
 {
diff --git a/arch/um/kernel/uaccess.c b/arch/um/kernel/uaccess.c
deleted file mode 100644
index dd33f04..0000000
--- a/arch/um/kernel/uaccess.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk)
- * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-/*
- * These are here rather than tt/uaccess.c because skas mode needs them in
- * order to do SIGBUS recovery when a tmpfs mount runs out of room.
- */
-
-#include <linux/string.h>
-#include "os.h"
-
-static void __do_copy(void *to, const void *from, int n)
-{
-	memcpy(to, from, n);
-}
-
-
-int __do_copy_to_user(void *to, const void *from, int n,
-		      void **fault_addr, jmp_buf **fault_catcher)
-{
-	unsigned long fault;
-	int faulted;
-
-	fault = __do_user_copy(to, from, n, fault_addr, fault_catcher,
-			       __do_copy, &faulted);
-	if (!faulted)
-		return 0;
-	else
-		return n - (fault - (unsigned long) to);
-}
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 8d84250..ba00eae 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -102,6 +102,8 @@ const struct seq_operations cpuinfo_op = {
 
 /* Set in linux_main */
 unsigned long uml_physmem;
+EXPORT_SYMBOL(uml_physmem);
+
 unsigned long uml_reserved; /* Also modified in mem_init */
 unsigned long start_vm;
 unsigned long end_vm;
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index b33f4df..dd76410 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -4,14 +4,14 @@
 #
 
 obj-y = aio.o execvp.o file.o helper.o irq.o main.o mem.o process.o \
-	registers.o sigio.o signal.o start_up.o time.o tty.o uaccess.o \
-	umid.o tls.o user_syms.o util.o drivers/ sys-$(SUBARCH)/ skas/
+	registers.o sigio.o signal.o start_up.o time.o tty.o \
+	umid.o user_syms.o util.o drivers/ skas/
 
 obj-$(CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA) += elf_aux.o
 
 USER_OBJS := $(user-objs-y) aio.o elf_aux.o execvp.o file.o helper.o irq.o \
 	main.o mem.o process.o registers.o sigio.o signal.o start_up.o time.o \
-	tty.o tls.o uaccess.o umid.o util.o
+	tty.o umid.o util.o
 
 CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH)
 
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c
index 57e3d46..c5d039e 100644
--- a/arch/um/os-Linux/aio.c
+++ b/arch/um/os-Linux/aio.c
@@ -11,10 +11,8 @@
 #include <asm/unistd.h>
 #include "aio.h"
 #include "init.h"
-#include "kern_constants.h"
 #include "kern_util.h"
 #include "os.h"
-#include "user.h"
 
 struct aio_thread_req {
 	enum aio_type type;
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
index cc72cb2..db3d648 100644
--- a/arch/um/os-Linux/drivers/ethertap_user.c
+++ b/arch/um/os-Linux/drivers/ethertap_user.c
@@ -13,11 +13,9 @@
 #include <sys/socket.h>
 #include <sys/wait.h>
 #include "etap.h"
-#include "kern_constants.h"
 #include "os.h"
 #include "net_user.h"
 #include "um_malloc.h"
-#include "user.h"
 
 #define MAX_PACKET ETH_MAX_PACKET
 
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c
index 2448be0..a2aacff 100644
--- a/arch/um/os-Linux/drivers/tuntap_user.c
+++ b/arch/um/os-Linux/drivers/tuntap_user.c
@@ -13,11 +13,9 @@
 #include <sys/socket.h>
 #include <sys/wait.h>
 #include <sys/uio.h>
-#include "kern_constants.h"
 #include "kern_util.h"
 #include "os.h"
 #include "tuntap.h"
-#include "user.h"
 
 static int tuntap_user_init(void *data, void *dev)
 {
diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c
index 9533237..d895271 100644
--- a/arch/um/os-Linux/elf_aux.c
+++ b/arch/um/os-Linux/elf_aux.c
@@ -12,7 +12,6 @@
 #include "init.h"
 #include "elf_user.h"
 #include "mem_user.h"
-#include <kern_constants.h>
 
 typedef Elf32_auxv_t elf_auxv_t;
 
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
index 140e587..b049a63 100644
--- a/arch/um/os-Linux/file.c
+++ b/arch/um/os-Linux/file.c
@@ -13,9 +13,7 @@
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/un.h>
-#include "kern_constants.h"
 #include "os.h"
-#include "user.h"
 
 static void copy_stat(struct uml_stat *dst, const struct stat64 *src)
 {
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index feff22d..cf26c4a 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -10,11 +10,9 @@
 #include <linux/limits.h>
 #include <sys/socket.h>
 #include <sys/wait.h>
-#include "kern_constants.h"
 #include "kern_util.h"
 #include "os.h"
 #include "um_malloc.h"
-#include "user.h"
 
 struct helper_data {
 	void (*pre_exec)(void*);
diff --git a/arch/um/os-Linux/internal.h b/arch/um/os-Linux/internal.h
new file mode 100644
index 0000000..2c3c3ec
--- /dev/null
+++ b/arch/um/os-Linux/internal.h
@@ -0,0 +1 @@
+void alarm_handler(int, mcontext_t *);
diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c
index 0348b97..9a49908 100644
--- a/arch/um/os-Linux/irq.c
+++ b/arch/um/os-Linux/irq.c
@@ -9,11 +9,8 @@
 #include <signal.h>
 #include <string.h>
 #include "irq_user.h"
-#include "kern_constants.h"
 #include "os.h"
-#include "process.h"
 #include "um_malloc.h"
-#include "user.h"
 
 /*
  * Locked by irq_lock in arch/um/kernel/irq.c.  Changed by os_create_pollfd
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index 8471b81..7a86dd5 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -12,7 +12,6 @@
 #include <sys/resource.h>
 #include "as-layout.h"
 #include "init.h"
-#include "kern_constants.h"
 #include "kern_util.h"
 #include "os.h"
 #include "um_malloc.h"
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index 62878cf..8e421e1 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -14,9 +14,7 @@
 #include <sys/mman.h>
 #include <sys/param.h>
 #include "init.h"
-#include "kern_constants.h"
 #include "os.h"
-#include "user.h"
 
 /* Modified by which_tmpdir, which is called during early boot */
 static char *default_tmpdir = "/tmp";
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index 0c45dc8..307f173 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -13,12 +13,9 @@
 #include <sys/wait.h>
 #include <asm/unistd.h>
 #include "init.h"
-#include "kern_constants.h"
 #include "longjmp.h"
 #include "os.h"
-#include "process.h"
 #include "skas_ptrace.h"
-#include "user.h"
 
 #define ARBITRARY_ADDR -1
 #define FAILURE_PID    -1
@@ -237,21 +234,13 @@ out:
 
 void init_new_thread_signals(void)
 {
-	set_handler(SIGSEGV, (__sighandler_t) sig_handler, SA_ONSTACK,
-		    SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
-	set_handler(SIGTRAP, (__sighandler_t) sig_handler, SA_ONSTACK,
-		    SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
-	set_handler(SIGFPE, (__sighandler_t) sig_handler, SA_ONSTACK,
-		    SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
-	set_handler(SIGILL, (__sighandler_t) sig_handler, SA_ONSTACK,
-		    SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
-	set_handler(SIGBUS, (__sighandler_t) sig_handler, SA_ONSTACK,
-		    SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
+	set_handler(SIGSEGV);
+	set_handler(SIGTRAP);
+	set_handler(SIGFPE);
+	set_handler(SIGILL);
+	set_handler(SIGBUS);
 	signal(SIGHUP, SIG_IGN);
-
-	set_handler(SIGIO, (__sighandler_t) sig_handler,
-		    SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM,
-		    SIGVTALRM, -1);
+	set_handler(SIGIO);
 	signal(SIGWINCH, SIG_IGN);
 	signal(SIGTERM, SIG_DFL);
 }
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c
index 63d299d..3c16121 100644
--- a/arch/um/os-Linux/sigio.c
+++ b/arch/um/os-Linux/sigio.c
@@ -11,14 +11,11 @@
 #include <sched.h>
 #include <signal.h>
 #include <string.h>
-#include "kern_constants.h"
 #include "kern_util.h"
 #include "init.h"
 #include "os.h"
-#include "process.h"
 #include "sigio.h"
 #include "um_malloc.h"
-#include "user.h"
 
 /*
  * Protected by sigio_lock(), also used by sigio_cleanup, which is an
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index 6ae1807..2d22f1f 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -12,13 +12,7 @@
 #include "as-layout.h"
 #include "kern_util.h"
 #include "os.h"
-#include "process.h"
-#include "sysdep/barrier.h"
-#include "sysdep/sigcontext.h"
-#include "user.h"
-
-/* Copied from linux/compiler-gcc.h since we can't include it directly */
-#define barrier() __asm__ __volatile__("": : :"memory")
+#include "sysdep/mcontext.h"
 
 void (*sig_info[NSIG])(int, struct uml_pt_regs *) = {
 	[SIGTRAP]	= relay_signal,
@@ -30,7 +24,7 @@ void (*sig_info[NSIG])(int, struct uml_pt_regs *) = {
 	[SIGIO]		= sigio_handler,
 	[SIGVTALRM]	= timer_handler };
 
-static void sig_handler_common(int sig, struct sigcontext *sc)
+static void sig_handler_common(int sig, mcontext_t *mc)
 {
 	struct uml_pt_regs r;
 	int save_errno = errno;
@@ -38,8 +32,8 @@ static void sig_handler_common(int sig, struct sigcontext *sc)
 	r.is_user = 0;
 	if (sig == SIGSEGV) {
 		/* For segfaults, we want the data from the sigcontext. */
-		copy_sc(&r, sc);
-		GET_FAULTINFO_FROM_SC(r.faultinfo, sc);
+		get_regs_from_mc(&r, mc);
+		GET_FAULTINFO_FROM_MC(r.faultinfo, mc);
 	}
 
 	/* enable signals if sig isn't IRQ signal */
@@ -66,7 +60,7 @@ static void sig_handler_common(int sig, struct sigcontext *sc)
 static int signals_enabled;
 static unsigned int signals_pending;
 
-void sig_handler(int sig, struct sigcontext *sc)
+void sig_handler(int sig, mcontext_t *mc)
 {
 	int enabled;
 
@@ -78,23 +72,23 @@ void sig_handler(int sig, struct sigcontext *sc)
 
 	block_signals();
 
-	sig_handler_common(sig, sc);
+	sig_handler_common(sig, mc);
 
 	set_signals(enabled);
 }
 
-static void real_alarm_handler(struct sigcontext *sc)
+static void real_alarm_handler(mcontext_t *mc)
 {
 	struct uml_pt_regs regs;
 
-	if (sc != NULL)
-		copy_sc(&regs, sc);
+	if (mc != NULL)
+		get_regs_from_mc(&regs, mc);
 	regs.is_user = 0;
 	unblock_signals();
 	timer_handler(SIGVTALRM, &regs);
 }
 
-void alarm_handler(int sig, struct sigcontext *sc)
+void alarm_handler(int sig, mcontext_t *mc)
 {
 	int enabled;
 
@@ -106,14 +100,13 @@ void alarm_handler(int sig, struct sigcontext *sc)
 
 	block_signals();
 
-	real_alarm_handler(sc);
+	real_alarm_handler(mc);
 	set_signals(enabled);
 }
 
 void timer_init(void)
 {
-	set_handler(SIGVTALRM, (__sighandler_t) alarm_handler,
-		    SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, -1);
+	set_handler(SIGVTALRM);
 }
 
 void set_sigstack(void *sig_stack, int size)
@@ -126,10 +119,23 @@ void set_sigstack(void *sig_stack, int size)
 		panic("enabling signal stack failed, errno = %d\n", errno);
 }
 
-static void (*handlers[_NSIG])(int sig, struct sigcontext *sc);
+static void (*handlers[_NSIG])(int sig, mcontext_t *mc) = {
+	[SIGSEGV] = sig_handler,
+	[SIGBUS] = sig_handler,
+	[SIGILL] = sig_handler,
+	[SIGFPE] = sig_handler,
+	[SIGTRAP] = sig_handler,
+
+	[SIGIO] = sig_handler,
+	[SIGWINCH] = sig_handler,
+	[SIGVTALRM] = alarm_handler
+};
+
 
-void handle_signal(int sig, struct sigcontext *sc)
+static void hard_handler(int sig, siginfo_t *info, void *p)
 {
+	struct ucontext *uc = p;
+	mcontext_t *mc = &uc->uc_mcontext;
 	unsigned long pending = 1UL << sig;
 
 	do {
@@ -155,7 +161,7 @@ void handle_signal(int sig, struct sigcontext *sc)
 		while ((sig = ffs(pending)) != 0){
 			sig--;
 			pending &= ~(1 << sig);
-			(*handlers[sig])(sig, sc);
+			(*handlers[sig])(sig, mc);
 		}
 
 		/*
@@ -169,28 +175,26 @@ void handle_signal(int sig, struct sigcontext *sc)
 	} while (pending);
 }
 
-extern void hard_handler(int sig);
-
-void set_handler(int sig, void (*handler)(int), int flags, ...)
+void set_handler(int sig)
 {
 	struct sigaction action;
-	va_list ap;
+	int flags = SA_SIGINFO | SA_ONSTACK;
 	sigset_t sig_mask;
-	int mask;
 
-	handlers[sig] = (void (*)(int, struct sigcontext *)) handler;
-	action.sa_handler = hard_handler;
+	action.sa_sigaction = hard_handler;
 
+	/* block irq ones */
 	sigemptyset(&action.sa_mask);
-
-	va_start(ap, flags);
-	while ((mask = va_arg(ap, int)) != -1)
-		sigaddset(&action.sa_mask, mask);
-	va_end(ap);
+	sigaddset(&action.sa_mask, SIGVTALRM);
+	sigaddset(&action.sa_mask, SIGIO);
+	sigaddset(&action.sa_mask, SIGWINCH);
 
 	if (sig == SIGSEGV)
 		flags |= SA_NODEFER;
 
+	if (sigismember(&action.sa_mask, sig))
+		flags |= SA_RESTART; /* if it's an irq signal */
+
 	action.sa_flags = flags;
 	action.sa_restorer = NULL;
 	if (sigaction(sig, &action, NULL) < 0)
diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c
index e771398..c0afff7 100644
--- a/arch/um/os-Linux/skas/mem.c
+++ b/arch/um/os-Linux/skas/mem.c
@@ -9,7 +9,6 @@
 #include <string.h>
 #include <sys/mman.h>
 #include "init.h"
-#include "kern_constants.h"
 #include "as-layout.h"
 #include "mm_id.h"
 #include "os.h"
@@ -17,7 +16,6 @@
 #include "ptrace_user.h"
 #include "registers.h"
 #include "skas.h"
-#include "user.h"
 #include "sysdep/ptrace.h"
 #include "sysdep/stub.h"
 
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index dee0e8c..cd65727 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -9,31 +9,23 @@
 #include <errno.h>
 #include <string.h>
 #include <sys/mman.h>
-#include <sys/ptrace.h>
 #include <sys/wait.h>
 #include <asm/unistd.h>
 #include "as-layout.h"
-#include "chan_user.h"
-#include "kern_constants.h"
+#include "init.h"
 #include "kern_util.h"
 #include "mem.h"
 #include "os.h"
-#include "process.h"
 #include "proc_mm.h"
 #include "ptrace_user.h"
 #include "registers.h"
 #include "skas.h"
 #include "skas_ptrace.h"
-#include "user.h"
 #include "sysdep/stub.h"
 
 int is_skas_winch(int pid, int fd, void *data)
 {
-	if (pid != getpgrp())
-		return 0;
-
-	register_winch_irq(-1, fd, -1, data, 0);
-	return 1;
+	return pid == getpgrp();
 }
 
 static int ptrace_dump_regs(int pid)
@@ -169,7 +161,7 @@ static void handle_trap(int pid, struct uml_pt_regs *regs,
 
 	if (!local_using_sysemu)
 	{
-		err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
+		err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET,
 			     __NR_getpid);
 		if (err < 0) {
 			printk(UM_KERN_ERR "handle_trap - nullifying syscall "
@@ -257,8 +249,8 @@ static int userspace_tramp(void *stack)
 
 		set_sigstack((void *) STUB_DATA, UM_KERN_PAGE_SIZE);
 		sigemptyset(&sa.sa_mask);
-		sa.sa_flags = SA_ONSTACK | SA_NODEFER;
-		sa.sa_handler = (void *) v;
+		sa.sa_flags = SA_ONSTACK | SA_NODEFER | SA_SIGINFO;
+		sa.sa_sigaction = (void *) v;
 		sa.sa_restorer = NULL;
 		if (sigaction(SIGSEGV, &sa, NULL) < 0) {
 			printk(UM_KERN_ERR "userspace_tramp - setting SIGSEGV "
@@ -661,8 +653,7 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf)
 {
 	int n;
 
-	set_handler(SIGWINCH, (__sighandler_t) sig_handler,
-		    SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGVTALRM, -1);
+	set_handler(SIGWINCH);
 
 	/*
 	 * Can't use UML_SETJMP or UML_LONGJMP here because they save
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 02ee9ad..425162e 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -13,12 +13,10 @@
 #include <signal.h>
 #include <string.h>
 #include <sys/mman.h>
-#include <sys/ptrace.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
 #include <asm/unistd.h>
 #include "init.h"
-#include "kern_constants.h"
 #include "os.h"
 #include "mem_user.h"
 #include "ptrace_user.h"
@@ -225,7 +223,7 @@ static void __init check_sysemu(void)
 		goto fail;
 	}
 
-	n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, os_getpid());
+	n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET, os_getpid());
 	if (n < 0) {
 		non_fatal("check_sysemu : failed to modify system call "
 			  "return");
@@ -261,7 +259,7 @@ static void __init check_sysemu(void)
 					  "doesn't singlestep");
 				goto fail;
 			}
-			n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET,
+			n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET,
 				   os_getpid());
 			if (n < 0)
 				fatal_perror("check_sysemu : failed to modify "
@@ -317,10 +315,10 @@ static void __init check_ptrace(void)
 			fatal("check_ptrace : expected (SIGTRAP|0x80), "
 			       "got status = %d", status);
 
-		syscall = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET,
+		syscall = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_NR_OFFSET,
 				 0);
 		if (syscall == __NR_getpid) {
-			n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
+			n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET,
 				   __NR_getppid);
 			if (n < 0)
 				fatal_perror("check_ptrace : failed to modify "
diff --git a/arch/um/os-Linux/sys-i386/Makefile b/arch/um/os-Linux/sys-i386/Makefile
deleted file mode 100644
index b4bc6ac..0000000
--- a/arch/um/os-Linux/sys-i386/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-#
-# Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
-# Licensed under the GPL
-#
-
-obj-y = registers.o signal.o task_size.o tls.o
-
-USER_OBJS := $(obj-y)
-
-include arch/um/scripts/Makefile.rules
diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c
deleted file mode 100644
index 229f7a5..0000000
--- a/arch/um/os-Linux/sys-i386/registers.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2004 PathScale, Inc
- * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <errno.h>
-#include <sys/ptrace.h>
-#include <sys/user.h>
-#include "kern_constants.h"
-#include "longjmp.h"
-#include "user.h"
-#include "sysdep/ptrace_user.h"
-
-int save_fp_registers(int pid, unsigned long *fp_regs)
-{
-	if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
-		return -errno;
-	return 0;
-}
-
-int restore_fp_registers(int pid, unsigned long *fp_regs)
-{
-	if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
-		return -errno;
-	return 0;
-}
-
-int save_fpx_registers(int pid, unsigned long *fp_regs)
-{
-	if (ptrace(PTRACE_GETFPXREGS, pid, 0, fp_regs) < 0)
-		return -errno;
-	return 0;
-}
-
-int restore_fpx_registers(int pid, unsigned long *fp_regs)
-{
-	if (ptrace(PTRACE_SETFPXREGS, pid, 0, fp_regs) < 0)
-		return -errno;
-	return 0;
-}
-
-unsigned long get_thread_reg(int reg, jmp_buf *buf)
-{
-	switch (reg) {
-	case EIP:
-		return buf[0]->__eip;
-	case UESP:
-		return buf[0]->__esp;
-	case EBP:
-		return buf[0]->__ebp;
-	default:
-		printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n",
-		       reg);
-		return 0;
-	}
-}
-
-int have_fpx_regs = 1;
-
-int get_fp_registers(int pid, unsigned long *regs)
-{
-	if (have_fpx_regs)
-		return save_fpx_registers(pid, regs);
-	else
-		return save_fp_registers(pid, regs);
-}
-
-int put_fp_registers(int pid, unsigned long *regs)
-{
-	if (have_fpx_regs)
-		return restore_fpx_registers(pid, regs);
-	else
-		return restore_fp_registers(pid, regs);
-}
-
-void arch_init_registers(int pid)
-{
-	struct user_fpxregs_struct fpx_regs;
-	int err;
-
-	err = ptrace(PTRACE_GETFPXREGS, pid, 0, &fpx_regs);
-	if (!err)
-		return;
-
-	if (errno != EIO)
-		panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d",
-		      errno);
-
-	have_fpx_regs = 0;
-}
diff --git a/arch/um/os-Linux/sys-i386/signal.c b/arch/um/os-Linux/sys-i386/signal.c
deleted file mode 100644
index f311609..0000000
--- a/arch/um/os-Linux/sys-i386/signal.c
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Copyright (C) 2006 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <signal.h>
-
-extern void handle_signal(int sig, struct sigcontext *sc);
-
-void hard_handler(int sig)
-{
-	handle_signal(sig, (struct sigcontext *) (&sig + 1));
-}
diff --git a/arch/um/os-Linux/sys-i386/task_size.c b/arch/um/os-Linux/sys-i386/task_size.c
deleted file mode 100644
index be04c1e..0000000
--- a/arch/um/os-Linux/sys-i386/task_size.c
+++ /dev/null
@@ -1,139 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <sys/mman.h>
-#include "longjmp.h"
-#include "kern_constants.h"
-
-static jmp_buf buf;
-
-static void segfault(int sig)
-{
-	longjmp(buf, 1);
-}
-
-static int page_ok(unsigned long page)
-{
-	unsigned long *address = (unsigned long *) (page << UM_KERN_PAGE_SHIFT);
-	unsigned long n = ~0UL;
-	void *mapped = NULL;
-	int ok = 0;
-
-	/*
-	 * First see if the page is readable.  If it is, it may still
-	 * be a VDSO, so we go on to see if it's writable.  If not
-	 * then try mapping memory there.  If that fails, then we're
-	 * still in the kernel area.  As a sanity check, we'll fail if
-	 * the mmap succeeds, but gives us an address different from
-	 * what we wanted.
-	 */
-	if (setjmp(buf) == 0)
-		n = *address;
-	else {
-		mapped = mmap(address, UM_KERN_PAGE_SIZE,
-			      PROT_READ | PROT_WRITE,
-			      MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-		if (mapped == MAP_FAILED)
-			return 0;
-		if (mapped != address)
-			goto out;
-	}
-
-	/*
-	 * Now, is it writeable?  If so, then we're in user address
-	 * space.  If not, then try mprotecting it and try the write
-	 * again.
-	 */
-	if (setjmp(buf) == 0) {
-		*address = n;
-		ok = 1;
-		goto out;
-	} else if (mprotect(address, UM_KERN_PAGE_SIZE,
-			    PROT_READ | PROT_WRITE) != 0)
-		goto out;
-
-	if (setjmp(buf) == 0) {
-		*address = n;
-		ok = 1;
-	}
-
- out:
-	if (mapped != NULL)
-		munmap(mapped, UM_KERN_PAGE_SIZE);
-	return ok;
-}
-
-unsigned long os_get_top_address(void)
-{
-	struct sigaction sa, old;
-	unsigned long bottom = 0;
-	/*
-	 * A 32-bit UML on a 64-bit host gets confused about the VDSO at
-	 * 0xffffe000.  It is mapped, is readable, can be reprotected writeable
-	 * and written.  However, exec discovers later that it can't be
-	 * unmapped.  So, just set the highest address to be checked to just
-	 * below it.  This might waste some address space on 4G/4G 32-bit
-	 * hosts, but shouldn't hurt otherwise.
-	 */
-	unsigned long top = 0xffffd000 >> UM_KERN_PAGE_SHIFT;
-	unsigned long test, original;
-
-	printf("Locating the bottom of the address space ... ");
-	fflush(stdout);
-
-	/*
-	 * We're going to be longjmping out of the signal handler, so
-	 * SA_DEFER needs to be set.
-	 */
-	sa.sa_handler = segfault;
-	sigemptyset(&sa.sa_mask);
-	sa.sa_flags = SA_NODEFER;
-	if (sigaction(SIGSEGV, &sa, &old)) {
-		perror("os_get_top_address");
-		exit(1);
-	}
-
-	/* Manually scan the address space, bottom-up, until we find
-	 * the first valid page (or run out of them).
-	 */
-	for (bottom = 0; bottom < top; bottom++) {
-		if (page_ok(bottom))
-			break;
-	}
-
-	/* If we've got this far, we ran out of pages. */
-	if (bottom == top) {
-		fprintf(stderr, "Unable to determine bottom of address "
-			"space.\n");
-		exit(1);
-	}
-
-	printf("0x%x\n", bottom << UM_KERN_PAGE_SHIFT);
-	printf("Locating the top of the address space ... ");
-	fflush(stdout);
-
-	original = bottom;
-
-	/* This could happen with a 4G/4G split */
-	if (page_ok(top))
-		goto out;
-
-	do {
-		test = bottom + (top - bottom) / 2;
-		if (page_ok(test))
-			bottom = test;
-		else
-			top = test;
-	} while (top - bottom > 1);
-
-out:
-	/* Restore the old SIGSEGV handling */
-	if (sigaction(SIGSEGV, &old, NULL)) {
-		perror("os_get_top_address");
-		exit(1);
-	}
-	top <<= UM_KERN_PAGE_SHIFT;
-	printf("0x%x\n", top);
-
-	return top;
-}
diff --git a/arch/um/os-Linux/sys-i386/tls.c b/arch/um/os-Linux/sys-i386/tls.c
deleted file mode 100644
index 32ed41e..0000000
--- a/arch/um/os-Linux/sys-i386/tls.c
+++ /dev/null
@@ -1,36 +0,0 @@
-#include <errno.h>
-#include <linux/unistd.h>
-
-#include <sys/syscall.h>
-#include <unistd.h>
-
-#include "sysdep/tls.h"
-#include "user.h"
-
-/* Checks whether host supports TLS, and sets *tls_min according to the value
- * valid on the host.
- * i386 host have it == 6; x86_64 host have it == 12, for i386 emulation. */
-void check_host_supports_tls(int *supports_tls, int *tls_min) {
-	/* Values for x86 and x86_64.*/
-	int val[] = {GDT_ENTRY_TLS_MIN_I386, GDT_ENTRY_TLS_MIN_X86_64};
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(val); i++) {
-		user_desc_t info;
-		info.entry_number = val[i];
-
-		if (syscall(__NR_get_thread_area, &info) == 0) {
-			*tls_min = val[i];
-			*supports_tls = 1;
-			return;
-		} else {
-			if (errno == EINVAL)
-				continue;
-			else if (errno == ENOSYS)
-				*supports_tls = 0;
-				return;
-		}
-	}
-
-	*supports_tls = 0;
-}
diff --git a/arch/um/os-Linux/sys-x86_64/Makefile b/arch/um/os-Linux/sys-x86_64/Makefile
deleted file mode 100644
index a44a47f..0000000
--- a/arch/um/os-Linux/sys-x86_64/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-#
-# Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
-# Licensed under the GPL
-#
-
-obj-y = registers.o prctl.o signal.o task_size.o
-
-USER_OBJS := $(obj-y)
-
-include arch/um/scripts/Makefile.rules
diff --git a/arch/um/os-Linux/sys-x86_64/prctl.c b/arch/um/os-Linux/sys-x86_64/prctl.c
deleted file mode 100644
index 9d34edd..0000000
--- a/arch/um/os-Linux/sys-x86_64/prctl.c
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright (C) 2007 Jeff Dike (jdike@{addtoit.com,linux.intel.com})
- * Licensed under the GPL
- */
-
-#include <sys/ptrace.h>
-#include <linux/ptrace.h>
-
-int os_arch_prctl(int pid, int code, unsigned long *addr)
-{
-        return ptrace(PTRACE_ARCH_PRCTL, pid, (unsigned long) addr, code);
-}
diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c
deleted file mode 100644
index 594d97a..0000000
--- a/arch/um/os-Linux/sys-x86_64/registers.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2006 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <errno.h>
-#include <sys/ptrace.h>
-#define __FRAME_OFFSETS
-#include <asm/ptrace.h>
-#include "kern_constants.h"
-#include "longjmp.h"
-#include "user.h"
-
-int save_fp_registers(int pid, unsigned long *fp_regs)
-{
-	if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
-		return -errno;
-	return 0;
-}
-
-int restore_fp_registers(int pid, unsigned long *fp_regs)
-{
-	if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
-		return -errno;
-	return 0;
-}
-
-unsigned long get_thread_reg(int reg, jmp_buf *buf)
-{
-	switch (reg) {
-	case RIP:
-		return buf[0]->__rip;
-	case RSP:
-		return buf[0]->__rsp;
-	case RBP:
-		return buf[0]->__rbp;
-	default:
-		printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n",
-		       reg);
-		return 0;
-	}
-}
-
-int get_fp_registers(int pid, unsigned long *regs)
-{
-	return save_fp_registers(pid, regs);
-}
-
-int put_fp_registers(int pid, unsigned long *regs)
-{
-	return restore_fp_registers(pid, regs);
-}
diff --git a/arch/um/os-Linux/sys-x86_64/signal.c b/arch/um/os-Linux/sys-x86_64/signal.c
deleted file mode 100644
index 82a3888..0000000
--- a/arch/um/os-Linux/sys-x86_64/signal.c
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (C) 2006 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <signal.h>
-
-extern void handle_signal(int sig, struct sigcontext *sc);
-
-void hard_handler(int sig)
-{
-	struct ucontext *uc;
-	asm("movq %%rdx, %0" : "=r" (uc));
-
-	handle_signal(sig, (struct sigcontext *) &uc->uc_mcontext);
-}
diff --git a/arch/um/os-Linux/sys-x86_64/task_size.c b/arch/um/os-Linux/sys-x86_64/task_size.c
deleted file mode 100644
index 26a0dd1..0000000
--- a/arch/um/os-Linux/sys-x86_64/task_size.c
+++ /dev/null
@@ -1,5 +0,0 @@
-unsigned long os_get_top_address(unsigned long shift)
-{
-	/* The old value of CONFIG_TOP_ADDR */
-	return 0x7fc0000000;
-}
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c
index 6e3359d..910499d 100644
--- a/arch/um/os-Linux/time.c
+++ b/arch/um/os-Linux/time.c
@@ -8,11 +8,9 @@
 #include <signal.h>
 #include <time.h>
 #include <sys/time.h>
-#include "kern_constants.h"
 #include "kern_util.h"
 #include "os.h"
-#include "process.h"
-#include "user.h"
+#include "internal.h"
 
 int set_interval(void)
 {
diff --git a/arch/um/os-Linux/tls.c b/arch/um/os-Linux/tls.c
deleted file mode 100644
index 7327780..0000000
--- a/arch/um/os-Linux/tls.c
+++ /dev/null
@@ -1,35 +0,0 @@
-#include <errno.h>
-#include <sys/ptrace.h>
-#include "sysdep/tls.h"
-
-/* TLS support - we basically rely on the host's one.*/
-
-#ifndef PTRACE_GET_THREAD_AREA
-#define PTRACE_GET_THREAD_AREA 25
-#endif
-
-#ifndef PTRACE_SET_THREAD_AREA
-#define PTRACE_SET_THREAD_AREA 26
-#endif
-
-int os_set_thread_area(user_desc_t *info, int pid)
-{
-	int ret;
-
-	ret = ptrace(PTRACE_SET_THREAD_AREA, pid, info->entry_number,
-		     (unsigned long) info);
-	if (ret < 0)
-		ret = -errno;
-	return ret;
-}
-
-int os_get_thread_area(user_desc_t *info, int pid)
-{
-	int ret;
-
-	ret = ptrace(PTRACE_GET_THREAD_AREA, pid, info->entry_number,
-		     (unsigned long) info);
-	if (ret < 0)
-		ret = -errno;
-	return ret;
-}
diff --git a/arch/um/os-Linux/tty.c b/arch/um/os-Linux/tty.c
index b09ff66..dd12b99 100644
--- a/arch/um/os-Linux/tty.c
+++ b/arch/um/os-Linux/tty.c
@@ -7,10 +7,8 @@
 #include <unistd.h>
 #include <errno.h>
 #include <fcntl.h>
-#include "kern_constants.h"
 #include "kern_util.h"
 #include "os.h"
-#include "user.h"
 
 struct grantpt_info {
 	int fd;
diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c
deleted file mode 100644
index 087ed74..0000000
--- a/arch/um/os-Linux/uaccess.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk)
- * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <stddef.h>
-#include "longjmp.h"
-
-unsigned long __do_user_copy(void *to, const void *from, int n,
-			     void **fault_addr, jmp_buf **fault_catcher,
-			     void (*op)(void *to, const void *from,
-					int n), int *faulted_out)
-{
-	unsigned long *faddrp = (unsigned long *) fault_addr, ret;
-
-	jmp_buf jbuf;
-	*fault_catcher = &jbuf;
-	if (UML_SETJMP(&jbuf) == 0) {
-		(*op)(to, from, n);
-		ret = 0;
-		*faulted_out = 0;
-	}
-	else {
-		ret = *faddrp;
-		*faulted_out = 1;
-	}
-	*fault_addr = NULL;
-	*fault_catcher = NULL;
-	return ret;
-}
-
diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c
index a27defb..4832eb5 100644
--- a/arch/um/os-Linux/umid.c
+++ b/arch/um/os-Linux/umid.c
@@ -13,9 +13,7 @@
 #include <unistd.h>
 #include <sys/stat.h>
 #include "init.h"
-#include "kern_constants.h"
 #include "os.h"
-#include "user.h"
 
 #define UML_DIR "~/.uml/"
 
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index 5803b18..9e3b43b 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -13,9 +13,7 @@
 #include <wait.h>
 #include <sys/mman.h>
 #include <sys/utsname.h>
-#include "kern_constants.h"
 #include "os.h"
-#include "user.h"
 
 void stack_protections(unsigned long address)
 {
diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules
index 61107b6..2eb2843 100644
--- a/arch/um/scripts/Makefile.rules
+++ b/arch/um/scripts/Makefile.rules
@@ -8,7 +8,7 @@ USER_OBJS += $(filter %_user.o,$(obj-y) $(obj-m)  $(USER_SINGLE_OBJS))
 USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
 
 $(USER_OBJS:.o=.%): \
-	c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) $(CFLAGS_$(basetarget).o)
+	c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) -include user.h $(CFLAGS_$(basetarget).o)
 $(USER_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \
 	-Dunix -D__unix__ -D__$(SUBARCH)__ $(CF)
 
@@ -25,8 +25,3 @@ $(UNPROFILE_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \
 define unprofile
 	$(patsubst -pg,,$(patsubst -fprofile-arcs -ftest-coverage,,$(1)))
 endef
-
-ifdef subarch-obj-y
-obj-y += subarch.o
-subarch-y = $(addprefix ../../$(HEADER_ARCH)/,$(subarch-obj-y))
-endif
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
deleted file mode 100644
index 3923cfb..0000000
--- a/arch/um/sys-i386/Makefile
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
-#
-
-obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
-	ptrace_user.o setjmp.o signal.o stub.o stub_segv.o syscalls.o sysrq.o \
-	sys_call_table.o tls.o atomic64_cx8_32.o mem.o
-
-obj-$(CONFIG_BINFMT_ELF) += elfcore.o
-
-subarch-obj-y = lib/string_32.o
-subarch-obj-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += lib/rwsem.o
-subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o
-subarch-obj-$(CONFIG_MODULES) += kernel/module.o
-
-USER_OBJS := bugs.o ptrace_user.o fault.o
-
-USER_OBJS += user-offsets.s
-extra-y += user-offsets.s
-
-UNPROFILE_OBJS := stub_segv.o
-CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING)
-
-include arch/um/scripts/Makefile.rules
diff --git a/arch/um/sys-i386/asm/archparam.h b/arch/um/sys-i386/asm/archparam.h
deleted file mode 100644
index 2a18a88..0000000
--- a/arch/um/sys-i386/asm/archparam.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* 
- * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#ifndef __UM_ARCHPARAM_I386_H
-#define __UM_ARCHPARAM_I386_H
-
-#ifdef CONFIG_X86_PAE
-#define LAST_PKMAP 512
-#else
-#define LAST_PKMAP 1024
-#endif
-
-#endif
-
diff --git a/arch/um/sys-i386/asm/elf.h b/arch/um/sys-i386/asm/elf.h
deleted file mode 100644
index 4230555..0000000
--- a/arch/um/sys-i386/asm/elf.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-#ifndef __UM_ELF_I386_H
-#define __UM_ELF_I386_H
-
-#include <asm/user.h>
-#include "skas.h"
-
-#define R_386_NONE	0
-#define R_386_32	1
-#define R_386_PC32	2
-#define R_386_GOT32	3
-#define R_386_PLT32	4
-#define R_386_COPY	5
-#define R_386_GLOB_DAT	6
-#define R_386_JMP_SLOT	7
-#define R_386_RELATIVE	8
-#define R_386_GOTOFF	9
-#define R_386_GOTPC	10
-#define R_386_NUM	11
-
-typedef unsigned long elf_greg_t;
-
-#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-
-typedef struct user_i387_struct elf_fpregset_t;
-
-/*
- * This is used to ensure we don't load something for the wrong architecture.
- */
-#define elf_check_arch(x) \
-	(((x)->e_machine == EM_386) || ((x)->e_machine == EM_486))
-
-#define ELF_CLASS	ELFCLASS32
-#define ELF_DATA        ELFDATA2LSB
-#define ELF_ARCH        EM_386
-
-#define ELF_PLAT_INIT(regs, load_addr) do { \
-	PT_REGS_EBX(regs) = 0; \
-	PT_REGS_ECX(regs) = 0; \
-	PT_REGS_EDX(regs) = 0; \
-	PT_REGS_ESI(regs) = 0; \
-	PT_REGS_EDI(regs) = 0; \
-	PT_REGS_EBP(regs) = 0; \
-	PT_REGS_EAX(regs) = 0; \
-} while (0)
-
-#define ELF_EXEC_PAGESIZE 4096
-
-#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
-
-/* Shamelessly stolen from include/asm-i386/elf.h */
-
-#define ELF_CORE_COPY_REGS(pr_reg, regs) do {	\
-	pr_reg[0] = PT_REGS_EBX(regs);		\
-	pr_reg[1] = PT_REGS_ECX(regs);		\
-	pr_reg[2] = PT_REGS_EDX(regs);		\
-	pr_reg[3] = PT_REGS_ESI(regs);		\
-	pr_reg[4] = PT_REGS_EDI(regs);		\
-	pr_reg[5] = PT_REGS_EBP(regs);		\
-	pr_reg[6] = PT_REGS_EAX(regs);		\
-	pr_reg[7] = PT_REGS_DS(regs);		\
-	pr_reg[8] = PT_REGS_ES(regs);		\
-	/* fake once used fs and gs selectors? */	\
-	pr_reg[9] = PT_REGS_DS(regs);		\
-	pr_reg[10] = PT_REGS_DS(regs);		\
-	pr_reg[11] = PT_REGS_SYSCALL_NR(regs);	\
-	pr_reg[12] = PT_REGS_IP(regs);		\
-	pr_reg[13] = PT_REGS_CS(regs);		\
-	pr_reg[14] = PT_REGS_EFLAGS(regs);	\
-	pr_reg[15] = PT_REGS_SP(regs);		\
-	pr_reg[16] = PT_REGS_SS(regs);		\
-} while (0);
-
-#define task_pt_regs(t) (&(t)->thread.regs)
-
-struct task_struct;
-
-extern int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu);
-
-#define ELF_CORE_COPY_FPREGS(t, fpu) elf_core_copy_fpregs(t, fpu)
-
-extern long elf_aux_hwcap;
-#define ELF_HWCAP (elf_aux_hwcap)
-
-extern char * elf_aux_platform;
-#define ELF_PLATFORM (elf_aux_platform)
-
-#define SET_PERSONALITY(ex) do { } while (0)
-
-extern unsigned long vsyscall_ehdr;
-extern unsigned long vsyscall_end;
-extern unsigned long __kernel_vsyscall;
-
-#define VSYSCALL_BASE vsyscall_ehdr
-#define VSYSCALL_END vsyscall_end
-
-/*
- * This is the range that is readable by user mode, and things
- * acting like user mode such as get_user_pages.
- */
-#define FIXADDR_USER_START      VSYSCALL_BASE
-#define FIXADDR_USER_END        VSYSCALL_END
-
-#define __HAVE_ARCH_GATE_AREA 1
-
-/*
- * Architecture-neutral AT_ values in 0-17, leave some room
- * for more of them, start the x86-specific ones at 32.
- */
-#define AT_SYSINFO		32
-#define AT_SYSINFO_EHDR		33
-
-#define ARCH_DLINFO						\
-do {								\
-	if ( vsyscall_ehdr ) {					\
-		NEW_AUX_ENT(AT_SYSINFO,	__kernel_vsyscall);	\
-		NEW_AUX_ENT(AT_SYSINFO_EHDR, vsyscall_ehdr);	\
-	}							\
-} while (0)
-
-#endif
diff --git a/arch/um/sys-i386/asm/module.h b/arch/um/sys-i386/asm/module.h
deleted file mode 100644
index 5ead4a0..0000000
--- a/arch/um/sys-i386/asm/module.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __UM_MODULE_I386_H
-#define __UM_MODULE_I386_H
-
-/* UML is simple */
-struct mod_arch_specific
-{
-};
-
-#define Elf_Shdr Elf32_Shdr
-#define Elf_Sym Elf32_Sym
-#define Elf_Ehdr Elf32_Ehdr
-
-#endif
diff --git a/arch/um/sys-i386/asm/processor.h b/arch/um/sys-i386/asm/processor.h
deleted file mode 100644
index 82a9061..0000000
--- a/arch/um/sys-i386/asm/processor.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __UM_PROCESSOR_I386_H
-#define __UM_PROCESSOR_I386_H
-
-#include "linux/string.h"
-#include <sysdep/host_ldt.h>
-#include "asm/segment.h"
-
-extern int host_has_cmov;
-
-/* include faultinfo structure */
-#include "sysdep/faultinfo.h"
-
-struct uml_tls_struct {
-	struct user_desc tls;
-	unsigned flushed:1;
-	unsigned present:1;
-};
-
-struct arch_thread {
-	struct uml_tls_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
-	unsigned long debugregs[8];
-	int debugregs_seq;
-	struct faultinfo faultinfo;
-};
-
-#define INIT_ARCH_THREAD { \
-	.tls_array  		= { [ 0 ... GDT_ENTRY_TLS_ENTRIES - 1 ] = \
-				    { .present = 0, .flushed = 0 } }, \
-	.debugregs  		= { [ 0 ... 7 ] = 0 }, \
-	.debugregs_seq		= 0, \
-	.faultinfo		= { 0, 0, 0 } \
-}
-
-static inline void arch_flush_thread(struct arch_thread *thread)
-{
-	/* Clear any TLS still hanging */
-	memset(&thread->tls_array, 0, sizeof(thread->tls_array));
-}
-
-static inline void arch_copy_thread(struct arch_thread *from,
-                                    struct arch_thread *to)
-{
-        memcpy(&to->tls_array, &from->tls_array, sizeof(from->tls_array));
-}
-
-#include <asm/user.h>
-
-/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
-static inline void rep_nop(void)
-{
-	__asm__ __volatile__("rep;nop": : :"memory");
-}
-
-#define cpu_relax()	rep_nop()
-
-/*
- * Default implementation of macro that returns current
- * instruction pointer ("program counter"). Stolen
- * from asm-i386/processor.h
- */
-#define current_text_addr() \
-	({ void *pc; __asm__("movl $1f,%0\n1:":"=g" (pc)); pc; })
-
-#define ARCH_IS_STACKGROW(address) \
-       (address + 32 >= UPT_SP(&current->thread.regs.regs))
-
-#define KSTK_EIP(tsk) KSTK_REG(tsk, EIP)
-#define KSTK_ESP(tsk) KSTK_REG(tsk, UESP)
-#define KSTK_EBP(tsk) KSTK_REG(tsk, EBP)
-
-#include "asm/processor-generic.h"
-
-#endif
diff --git a/arch/um/sys-i386/asm/ptrace.h b/arch/um/sys-i386/asm/ptrace.h
deleted file mode 100644
index 5d2a591..0000000
--- a/arch/um/sys-i386/asm/ptrace.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* 
- * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#ifndef __UM_PTRACE_I386_H
-#define __UM_PTRACE_I386_H
-
-#define HOST_AUDIT_ARCH AUDIT_ARCH_I386
-
-#include "linux/compiler.h"
-#include "asm/ptrace-generic.h"
-
-#define PT_REGS_EAX(r) UPT_EAX(&(r)->regs)
-#define PT_REGS_EBX(r) UPT_EBX(&(r)->regs)
-#define PT_REGS_ECX(r) UPT_ECX(&(r)->regs)
-#define PT_REGS_EDX(r) UPT_EDX(&(r)->regs)
-#define PT_REGS_ESI(r) UPT_ESI(&(r)->regs)
-#define PT_REGS_EDI(r) UPT_EDI(&(r)->regs)
-#define PT_REGS_EBP(r) UPT_EBP(&(r)->regs)
-
-#define PT_REGS_CS(r) UPT_CS(&(r)->regs)
-#define PT_REGS_SS(r) UPT_SS(&(r)->regs)
-#define PT_REGS_DS(r) UPT_DS(&(r)->regs)
-#define PT_REGS_ES(r) UPT_ES(&(r)->regs)
-#define PT_REGS_FS(r) UPT_FS(&(r)->regs)
-#define PT_REGS_GS(r) UPT_GS(&(r)->regs)
-
-#define PT_REGS_EFLAGS(r) UPT_EFLAGS(&(r)->regs)
-
-#define PT_REGS_ORIG_SYSCALL(r) PT_REGS_EAX(r)
-#define PT_REGS_SYSCALL_RET(r) PT_REGS_EAX(r)
-#define PT_FIX_EXEC_STACK(sp) do ; while(0)
-
-#define profile_pc(regs) PT_REGS_IP(regs)
-
-#define user_mode(r) UPT_IS_USER(&(r)->regs)
-
-/*
- * Forward declaration to avoid including sysdep/tls.h, which causes a
- * circular include, and compilation failures.
- */
-struct user_desc;
-
-extern int ptrace_get_thread_area(struct task_struct *child, int idx,
-                                  struct user_desc __user *user_desc);
-
-extern int ptrace_set_thread_area(struct task_struct *child, int idx,
-                                  struct user_desc __user *user_desc);
-
-#endif
diff --git a/arch/um/sys-i386/atomic64_cx8_32.S b/arch/um/sys-i386/atomic64_cx8_32.S
deleted file mode 100644
index 1e901d3..0000000
--- a/arch/um/sys-i386/atomic64_cx8_32.S
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * atomic64_t for 586+
- *
- * Copied from arch/x86/lib/atomic64_cx8_32.S
- *
- * Copyright © 2010  Luca Barbieri
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#include <linux/linkage.h>
-#include <asm/alternative-asm.h>
-#include <asm/dwarf2.h>
-
-.macro SAVE reg
-	pushl_cfi %\reg
-	CFI_REL_OFFSET \reg, 0
-.endm
-
-.macro RESTORE reg
-	popl_cfi %\reg
-	CFI_RESTORE \reg
-.endm
-
-.macro read64 reg
-	movl %ebx, %eax
-	movl %ecx, %edx
-/* we need LOCK_PREFIX since otherwise cmpxchg8b always does the write */
-	LOCK_PREFIX
-	cmpxchg8b (\reg)
-.endm
-
-ENTRY(atomic64_read_cx8)
-	CFI_STARTPROC
-
-	read64 %ecx
-	ret
-	CFI_ENDPROC
-ENDPROC(atomic64_read_cx8)
-
-ENTRY(atomic64_set_cx8)
-	CFI_STARTPROC
-
-1:
-/* we don't need LOCK_PREFIX since aligned 64-bit writes
- * are atomic on 586 and newer */
-	cmpxchg8b (%esi)
-	jne 1b
-
-	ret
-	CFI_ENDPROC
-ENDPROC(atomic64_set_cx8)
-
-ENTRY(atomic64_xchg_cx8)
-	CFI_STARTPROC
-
-	movl %ebx, %eax
-	movl %ecx, %edx
-1:
-	LOCK_PREFIX
-	cmpxchg8b (%esi)
-	jne 1b
-
-	ret
-	CFI_ENDPROC
-ENDPROC(atomic64_xchg_cx8)
-
-.macro addsub_return func ins insc
-ENTRY(atomic64_\func\()_return_cx8)
-	CFI_STARTPROC
-	SAVE ebp
-	SAVE ebx
-	SAVE esi
-	SAVE edi
-
-	movl %eax, %esi
-	movl %edx, %edi
-	movl %ecx, %ebp
-
-	read64 %ebp
-1:
-	movl %eax, %ebx
-	movl %edx, %ecx
-	\ins\()l %esi, %ebx
-	\insc\()l %edi, %ecx
-	LOCK_PREFIX
-	cmpxchg8b (%ebp)
-	jne 1b
-
-10:
-	movl %ebx, %eax
-	movl %ecx, %edx
-	RESTORE edi
-	RESTORE esi
-	RESTORE ebx
-	RESTORE ebp
-	ret
-	CFI_ENDPROC
-ENDPROC(atomic64_\func\()_return_cx8)
-.endm
-
-addsub_return add add adc
-addsub_return sub sub sbb
-
-.macro incdec_return func ins insc
-ENTRY(atomic64_\func\()_return_cx8)
-	CFI_STARTPROC
-	SAVE ebx
-
-	read64 %esi
-1:
-	movl %eax, %ebx
-	movl %edx, %ecx
-	\ins\()l $1, %ebx
-	\insc\()l $0, %ecx
-	LOCK_PREFIX
-	cmpxchg8b (%esi)
-	jne 1b
-
-10:
-	movl %ebx, %eax
-	movl %ecx, %edx
-	RESTORE ebx
-	ret
-	CFI_ENDPROC
-ENDPROC(atomic64_\func\()_return_cx8)
-.endm
-
-incdec_return inc add adc
-incdec_return dec sub sbb
-
-ENTRY(atomic64_dec_if_positive_cx8)
-	CFI_STARTPROC
-	SAVE ebx
-
-	read64 %esi
-1:
-	movl %eax, %ebx
-	movl %edx, %ecx
-	subl $1, %ebx
-	sbb $0, %ecx
-	js 2f
-	LOCK_PREFIX
-	cmpxchg8b (%esi)
-	jne 1b
-
-2:
-	movl %ebx, %eax
-	movl %ecx, %edx
-	RESTORE ebx
-	ret
-	CFI_ENDPROC
-ENDPROC(atomic64_dec_if_positive_cx8)
-
-ENTRY(atomic64_add_unless_cx8)
-	CFI_STARTPROC
-	SAVE ebp
-	SAVE ebx
-/* these just push these two parameters on the stack */
-	SAVE edi
-	SAVE esi
-
-	movl %ecx, %ebp
-	movl %eax, %esi
-	movl %edx, %edi
-
-	read64 %ebp
-1:
-	cmpl %eax, 0(%esp)
-	je 4f
-2:
-	movl %eax, %ebx
-	movl %edx, %ecx
-	addl %esi, %ebx
-	adcl %edi, %ecx
-	LOCK_PREFIX
-	cmpxchg8b (%ebp)
-	jne 1b
-
-	movl $1, %eax
-3:
-	addl $8, %esp
-	CFI_ADJUST_CFA_OFFSET -8
-	RESTORE ebx
-	RESTORE ebp
-	ret
-4:
-	cmpl %edx, 4(%esp)
-	jne 2b
-	xorl %eax, %eax
-	jmp 3b
-	CFI_ENDPROC
-ENDPROC(atomic64_add_unless_cx8)
-
-ENTRY(atomic64_inc_not_zero_cx8)
-	CFI_STARTPROC
-	SAVE ebx
-
-	read64 %esi
-1:
-	testl %eax, %eax
-	je 4f
-2:
-	movl %eax, %ebx
-	movl %edx, %ecx
-	addl $1, %ebx
-	adcl $0, %ecx
-	LOCK_PREFIX
-	cmpxchg8b (%esi)
-	jne 1b
-
-	movl $1, %eax
-3:
-	RESTORE ebx
-	ret
-4:
-	testl %edx, %edx
-	jne 2b
-	jmp 3b
-	CFI_ENDPROC
-ENDPROC(atomic64_inc_not_zero_cx8)
diff --git a/arch/um/sys-i386/bug.c b/arch/um/sys-i386/bug.c
deleted file mode 100644
index 8d4f273..0000000
--- a/arch/um/sys-i386/bug.c
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL V2
- */
-
-#include <linux/uaccess.h>
-#include <asm/errno.h>
-
-/* Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because
- * that's not relevant in skas mode.
- */
-
-int is_valid_bugaddr(unsigned long eip)
-{
-	unsigned short ud2;
-
-	if (probe_kernel_address((unsigned short __user *)eip, ud2))
-		return 0;
-
-	return ud2 == 0x0b0f;
-}
diff --git a/arch/um/sys-i386/bugs.c b/arch/um/sys-i386/bugs.c
deleted file mode 100644
index 2c6d0d7..0000000
--- a/arch/um/sys-i386/bugs.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <signal.h>
-#include "kern_constants.h"
-#include "kern_util.h"
-#include "longjmp.h"
-#include "task.h"
-#include "user.h"
-#include "sysdep/ptrace.h"
-
-/* Set during early boot */
-static int host_has_cmov = 1;
-static jmp_buf cmov_test_return;
-
-static void cmov_sigill_test_handler(int sig)
-{
-	host_has_cmov = 0;
-	longjmp(cmov_test_return, 1);
-}
-
-void arch_check_bugs(void)
-{
-	struct sigaction old, new;
-
-	printk(UM_KERN_INFO "Checking for host processor cmov support...");
-	new.sa_handler = cmov_sigill_test_handler;
-
-	/* Make sure that SIGILL is enabled after the handler longjmps back */
-	new.sa_flags = SA_NODEFER;
-	sigemptyset(&new.sa_mask);
-	sigaction(SIGILL, &new, &old);
-
-	if (setjmp(cmov_test_return) == 0) {
-		unsigned long foo = 0;
-		__asm__ __volatile__("cmovz %0, %1" : "=r" (foo) : "0" (foo));
-		printk(UM_KERN_CONT "Yes\n");
-	} else
-		printk(UM_KERN_CONT "No\n");
-
-	sigaction(SIGILL, &old, &new);
-}
-
-void arch_examine_signal(int sig, struct uml_pt_regs *regs)
-{
-	unsigned char tmp[2];
-
-	/*
-	 * This is testing for a cmov (0x0f 0x4x) instruction causing a
-	 * SIGILL in init.
-	 */
-	if ((sig != SIGILL) || (TASK_PID(get_current()) != 1))
-		return;
-
-	if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2)) {
-		printk(UM_KERN_ERR "SIGILL in init, could not read "
-		       "instructions!\n");
-		return;
-	}
-
-	if ((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40))
-		return;
-
-	if (host_has_cmov == 0)
-		printk(UM_KERN_ERR "SIGILL caused by cmov, which this "
-		       "processor doesn't implement.  Boot a filesystem "
-		       "compiled for older processors");
-	else if (host_has_cmov == 1)
-		printk(UM_KERN_ERR "SIGILL caused by cmov, which this "
-		       "processor claims to implement");
-	else
-		printk(UM_KERN_ERR "Bad value for host_has_cmov (%d)",
-			host_has_cmov);
-}
diff --git a/arch/um/sys-i386/checksum.S b/arch/um/sys-i386/checksum.S
deleted file mode 100644
index f058d2f..0000000
--- a/arch/um/sys-i386/checksum.S
+++ /dev/null
@@ -1,458 +0,0 @@
-/*
- * INET		An implementation of the TCP/IP protocol suite for the LINUX
- *		operating system.  INET is implemented using the  BSD Socket
- *		interface as the means of communication with the user level.
- *
- *		IP/TCP/UDP checksumming routines
- *
- * Authors:	Jorge Cwik, <jorge@laser.satlink.net>
- *		Arnt Gulbrandsen, <agulbra@nvg.unit.no>
- *		Tom May, <ftom@netcom.com>
- *              Pentium Pro/II routines:
- *              Alexander Kjeldaas <astor@guardian.no>
- *              Finn Arne Gangstad <finnag@guardian.no>
- *		Lots of code moved from tcp.c and ip.c; see those files
- *		for more names.
- *
- * Changes:     Ingo Molnar, converted csum_partial_copy() to 2.1 exception
- *			     handling.
- *		Andi Kleen,  add zeroing on error
- *                   converted to pure assembler
- *
- *		This program is free software; you can redistribute it and/or
- *		modify it under the terms of the GNU General Public License
- *		as published by the Free Software Foundation; either version
- *		2 of the License, or (at your option) any later version.
- */
-
-#include <asm/errno.h>
-				
-/*
- * computes a partial checksum, e.g. for TCP/UDP fragments
- */
-
-/*	
-unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
- */
-		
-.text
-.align 4
-.globl csum_partial
-		
-#ifndef CONFIG_X86_USE_PPRO_CHECKSUM
-
-	  /*		
-	   * Experiments with Ethernet and SLIP connections show that buff
-	   * is aligned on either a 2-byte or 4-byte boundary.  We get at
-	   * least a twofold speedup on 486 and Pentium if it is 4-byte aligned.
-	   * Fortunately, it is easy to convert 2-byte alignment to 4-byte
-	   * alignment for the unrolled loop.
-	   */		
-csum_partial:
-	pushl %esi
-	pushl %ebx
-	movl 20(%esp),%eax	# Function arg: unsigned int sum
-	movl 16(%esp),%ecx	# Function arg: int len
-	movl 12(%esp),%esi	# Function arg: unsigned char *buff
-	testl $2, %esi		# Check alignment.
-	jz 2f			# Jump if alignment is ok.
-	subl $2, %ecx		# Alignment uses up two bytes.
-	jae 1f			# Jump if we had at least two bytes.
-	addl $2, %ecx		# ecx was < 2.  Deal with it.
-	jmp 4f
-1:	movw (%esi), %bx
-	addl $2, %esi
-	addw %bx, %ax
-	adcl $0, %eax
-2:
-	movl %ecx, %edx
-	shrl $5, %ecx
-	jz 2f
-	testl %esi, %esi
-1:	movl (%esi), %ebx
-	adcl %ebx, %eax
-	movl 4(%esi), %ebx
-	adcl %ebx, %eax
-	movl 8(%esi), %ebx
-	adcl %ebx, %eax
-	movl 12(%esi), %ebx
-	adcl %ebx, %eax
-	movl 16(%esi), %ebx
-	adcl %ebx, %eax
-	movl 20(%esi), %ebx
-	adcl %ebx, %eax
-	movl 24(%esi), %ebx
-	adcl %ebx, %eax
-	movl 28(%esi), %ebx
-	adcl %ebx, %eax
-	lea 32(%esi), %esi
-	dec %ecx
-	jne 1b
-	adcl $0, %eax
-2:	movl %edx, %ecx
-	andl $0x1c, %edx
-	je 4f
-	shrl $2, %edx		# This clears CF
-3:	adcl (%esi), %eax
-	lea 4(%esi), %esi
-	dec %edx
-	jne 3b
-	adcl $0, %eax
-4:	andl $3, %ecx
-	jz 7f
-	cmpl $2, %ecx
-	jb 5f
-	movw (%esi),%cx
-	leal 2(%esi),%esi
-	je 6f
-	shll $16,%ecx
-5:	movb (%esi),%cl
-6:	addl %ecx,%eax
-	adcl $0, %eax 
-7:	
-	popl %ebx
-	popl %esi
-	ret
-
-#else
-
-/* Version for PentiumII/PPro */
-
-csum_partial:
-	pushl %esi
-	pushl %ebx
-	movl 20(%esp),%eax	# Function arg: unsigned int sum
-	movl 16(%esp),%ecx	# Function arg: int len
-	movl 12(%esp),%esi	# Function arg:	const unsigned char *buf
-
-	testl $2, %esi         
-	jnz 30f                 
-10:
-	movl %ecx, %edx
-	movl %ecx, %ebx
-	andl $0x7c, %ebx
-	shrl $7, %ecx
-	addl %ebx,%esi
-	shrl $2, %ebx  
-	negl %ebx
-	lea 45f(%ebx,%ebx,2), %ebx
-	testl %esi, %esi
-	jmp *%ebx
-
-	# Handle 2-byte-aligned regions
-20:	addw (%esi), %ax
-	lea 2(%esi), %esi
-	adcl $0, %eax
-	jmp 10b
-
-30:	subl $2, %ecx          
-	ja 20b                 
-	je 32f
-	movzbl (%esi),%ebx	# csumming 1 byte, 2-aligned
-	addl %ebx, %eax
-	adcl $0, %eax
-	jmp 80f
-32:
-	addw (%esi), %ax	# csumming 2 bytes, 2-aligned
-	adcl $0, %eax
-	jmp 80f
-
-40: 
-	addl -128(%esi), %eax
-	adcl -124(%esi), %eax
-	adcl -120(%esi), %eax
-	adcl -116(%esi), %eax   
-	adcl -112(%esi), %eax   
-	adcl -108(%esi), %eax
-	adcl -104(%esi), %eax
-	adcl -100(%esi), %eax
-	adcl -96(%esi), %eax
-	adcl -92(%esi), %eax
-	adcl -88(%esi), %eax
-	adcl -84(%esi), %eax
-	adcl -80(%esi), %eax
-	adcl -76(%esi), %eax
-	adcl -72(%esi), %eax
-	adcl -68(%esi), %eax
-	adcl -64(%esi), %eax     
-	adcl -60(%esi), %eax     
-	adcl -56(%esi), %eax     
-	adcl -52(%esi), %eax   
-	adcl -48(%esi), %eax   
-	adcl -44(%esi), %eax
-	adcl -40(%esi), %eax
-	adcl -36(%esi), %eax
-	adcl -32(%esi), %eax
-	adcl -28(%esi), %eax
-	adcl -24(%esi), %eax
-	adcl -20(%esi), %eax
-	adcl -16(%esi), %eax
-	adcl -12(%esi), %eax
-	adcl -8(%esi), %eax
-	adcl -4(%esi), %eax
-45:
-	lea 128(%esi), %esi
-	adcl $0, %eax
-	dec %ecx
-	jge 40b
-	movl %edx, %ecx
-50:	andl $3, %ecx
-	jz 80f
-
-	# Handle the last 1-3 bytes without jumping
-	notl %ecx		# 1->2, 2->1, 3->0, higher bits are masked
-	movl $0xffffff,%ebx	# by the shll and shrl instructions
-	shll $3,%ecx
-	shrl %cl,%ebx
-	andl -128(%esi),%ebx	# esi is 4-aligned so should be ok
-	addl %ebx,%eax
-	adcl $0,%eax
-80: 
-	popl %ebx
-	popl %esi
-	ret
-				
-#endif
-
-/*
-unsigned int csum_partial_copy_generic (const char *src, char *dst,
-				  int len, int sum, int *src_err_ptr, int *dst_err_ptr)
- */ 
-
-/*
- * Copy from ds while checksumming, otherwise like csum_partial
- *
- * The macros SRC and DST specify the type of access for the instruction.
- * thus we can call a custom exception handler for all access types.
- *
- * FIXME: could someone double-check whether I haven't mixed up some SRC and
- *	  DST definitions? It's damn hard to trigger all cases.  I hope I got
- *	  them all but there's no guarantee.
- */
-
-#define SRC(y...)			\
-	9999: y;			\
-	.section __ex_table, "a";	\
-	.long 9999b, 6001f	;	\
-	.previous
-
-#define DST(y...)			\
-	9999: y;			\
-	.section __ex_table, "a";	\
-	.long 9999b, 6002f	;	\
-	.previous
-
-.align 4
-
-#ifndef CONFIG_X86_USE_PPRO_CHECKSUM
-
-#define ARGBASE 16		
-#define FP		12
-
-csum_partial_copy_generic_i386:
-	subl  $4,%esp	
-	pushl %edi
-	pushl %esi
-	pushl %ebx
-	movl ARGBASE+16(%esp),%eax	# sum
-	movl ARGBASE+12(%esp),%ecx	# len
-	movl ARGBASE+4(%esp),%esi	# src
-	movl ARGBASE+8(%esp),%edi	# dst
-
-	testl $2, %edi			# Check alignment. 
-	jz 2f				# Jump if alignment is ok.
-	subl $2, %ecx			# Alignment uses up two bytes.
-	jae 1f				# Jump if we had at least two bytes.
-	addl $2, %ecx			# ecx was < 2.  Deal with it.
-	jmp 4f
-SRC(1:	movw (%esi), %bx	)
-	addl $2, %esi
-DST(	movw %bx, (%edi)	)
-	addl $2, %edi
-	addw %bx, %ax	
-	adcl $0, %eax
-2:
-	movl %ecx, FP(%esp)
-	shrl $5, %ecx
-	jz 2f
-	testl %esi, %esi
-SRC(1:	movl (%esi), %ebx	)
-SRC(	movl 4(%esi), %edx	)
-	adcl %ebx, %eax
-DST(	movl %ebx, (%edi)	)
-	adcl %edx, %eax
-DST(	movl %edx, 4(%edi)	)
-
-SRC(	movl 8(%esi), %ebx	)
-SRC(	movl 12(%esi), %edx	)
-	adcl %ebx, %eax
-DST(	movl %ebx, 8(%edi)	)
-	adcl %edx, %eax
-DST(	movl %edx, 12(%edi)	)
-
-SRC(	movl 16(%esi), %ebx 	)
-SRC(	movl 20(%esi), %edx	)
-	adcl %ebx, %eax
-DST(	movl %ebx, 16(%edi)	)
-	adcl %edx, %eax
-DST(	movl %edx, 20(%edi)	)
-
-SRC(	movl 24(%esi), %ebx	)
-SRC(	movl 28(%esi), %edx	)
-	adcl %ebx, %eax
-DST(	movl %ebx, 24(%edi)	)
-	adcl %edx, %eax
-DST(	movl %edx, 28(%edi)	)
-
-	lea 32(%esi), %esi
-	lea 32(%edi), %edi
-	dec %ecx
-	jne 1b
-	adcl $0, %eax
-2:	movl FP(%esp), %edx
-	movl %edx, %ecx
-	andl $0x1c, %edx
-	je 4f
-	shrl $2, %edx			# This clears CF
-SRC(3:	movl (%esi), %ebx	)
-	adcl %ebx, %eax
-DST(	movl %ebx, (%edi)	)
-	lea 4(%esi), %esi
-	lea 4(%edi), %edi
-	dec %edx
-	jne 3b
-	adcl $0, %eax
-4:	andl $3, %ecx
-	jz 7f
-	cmpl $2, %ecx
-	jb 5f
-SRC(	movw (%esi), %cx	)
-	leal 2(%esi), %esi
-DST(	movw %cx, (%edi)	)
-	leal 2(%edi), %edi
-	je 6f
-	shll $16,%ecx
-SRC(5:	movb (%esi), %cl	)
-DST(	movb %cl, (%edi)	)
-6:	addl %ecx, %eax
-	adcl $0, %eax
-7:
-5000:
-
-# Exception handler:
-.section .fixup, "ax"							
-
-6001:
-	movl ARGBASE+20(%esp), %ebx	# src_err_ptr
-	movl $-EFAULT, (%ebx)
-
-	# zero the complete destination - computing the rest
-	# is too much work 
-	movl ARGBASE+8(%esp), %edi	# dst
-	movl ARGBASE+12(%esp), %ecx	# len
-	xorl %eax,%eax
-	rep ; stosb
-
-	jmp 5000b
-
-6002:
-	movl ARGBASE+24(%esp), %ebx	# dst_err_ptr
-	movl $-EFAULT,(%ebx)
-	jmp 5000b
-
-.previous
-
-	popl %ebx
-	popl %esi
-	popl %edi
-	popl %ecx			# equivalent to addl $4,%esp
-	ret	
-
-#else
-
-/* Version for PentiumII/PPro */
-
-#define ROUND1(x) \
-	SRC(movl x(%esi), %ebx	)	;	\
-	addl %ebx, %eax			;	\
-	DST(movl %ebx, x(%edi)	)	; 
-
-#define ROUND(x) \
-	SRC(movl x(%esi), %ebx	)	;	\
-	adcl %ebx, %eax			;	\
-	DST(movl %ebx, x(%edi)	)	;
-
-#define ARGBASE 12
-		
-csum_partial_copy_generic_i386:
-	pushl %ebx
-	pushl %edi
-	pushl %esi
-	movl ARGBASE+4(%esp),%esi	#src
-	movl ARGBASE+8(%esp),%edi	#dst	
-	movl ARGBASE+12(%esp),%ecx	#len
-	movl ARGBASE+16(%esp),%eax	#sum
-#	movl %ecx, %edx  
-	movl %ecx, %ebx  
-	movl %esi, %edx
-	shrl $6, %ecx     
-	andl $0x3c, %ebx  
-	negl %ebx
-	subl %ebx, %esi  
-	subl %ebx, %edi  
-	lea  -1(%esi),%edx
-	andl $-32,%edx
-	lea 3f(%ebx,%ebx), %ebx
-	testl %esi, %esi 
-	jmp *%ebx
-1:	addl $64,%esi
-	addl $64,%edi 
-	SRC(movb -32(%edx),%bl)	; SRC(movb (%edx),%bl)
-	ROUND1(-64) ROUND(-60) ROUND(-56) ROUND(-52)	
-	ROUND (-48) ROUND(-44) ROUND(-40) ROUND(-36)	
-	ROUND (-32) ROUND(-28) ROUND(-24) ROUND(-20)	
-	ROUND (-16) ROUND(-12) ROUND(-8)  ROUND(-4)	
-3:	adcl $0,%eax
-	addl $64, %edx
-	dec %ecx
-	jge 1b
-4:	movl ARGBASE+12(%esp),%edx	#len
-	andl $3, %edx
-	jz 7f
-	cmpl $2, %edx
-	jb 5f
-SRC(	movw (%esi), %dx         )
-	leal 2(%esi), %esi
-DST(	movw %dx, (%edi)         )
-	leal 2(%edi), %edi
-	je 6f
-	shll $16,%edx
-5:
-SRC(	movb (%esi), %dl         )
-DST(	movb %dl, (%edi)         )
-6:	addl %edx, %eax
-	adcl $0, %eax
-7:
-.section .fixup, "ax"
-6001:	movl	ARGBASE+20(%esp), %ebx	# src_err_ptr	
-	movl $-EFAULT, (%ebx)
-	# zero the complete destination (computing the rest is too much work)
-	movl ARGBASE+8(%esp),%edi	# dst
-	movl ARGBASE+12(%esp),%ecx	# len
-	xorl %eax,%eax
-	rep; stosb
-	jmp 7b
-6002:	movl ARGBASE+24(%esp), %ebx	# dst_err_ptr
-	movl $-EFAULT, (%ebx)
-	jmp  7b			
-.previous				
-
-	popl %esi
-	popl %edi
-	popl %ebx
-	ret
-				
-#undef ROUND
-#undef ROUND1		
-		
-#endif
diff --git a/arch/um/sys-i386/delay.c b/arch/um/sys-i386/delay.c
deleted file mode 100644
index f3fe1a6..0000000
--- a/arch/um/sys-i386/delay.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
- * Mostly copied from arch/x86/lib/delay.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <asm/param.h>
-
-void __delay(unsigned long loops)
-{
-	asm volatile(
-		"test %0,%0\n"
-		"jz 3f\n"
-		"jmp 1f\n"
-
-		".align 16\n"
-		"1: jmp 2f\n"
-
-		".align 16\n"
-		"2: dec %0\n"
-		" jnz 2b\n"
-		"3: dec %0\n"
-
-		: /* we don't need output */
-		: "a" (loops)
-	);
-}
-EXPORT_SYMBOL(__delay);
-
-inline void __const_udelay(unsigned long xloops)
-{
-	int d0;
-
-	xloops *= 4;
-	asm("mull %%edx"
-		: "=d" (xloops), "=&a" (d0)
-		: "1" (xloops), "0"
-		(loops_per_jiffy * (HZ/4)));
-
-	__delay(++xloops);
-}
-EXPORT_SYMBOL(__const_udelay);
-
-void __udelay(unsigned long usecs)
-{
-	__const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */
-}
-EXPORT_SYMBOL(__udelay);
-
-void __ndelay(unsigned long nsecs)
-{
-	__const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */
-}
-EXPORT_SYMBOL(__ndelay);
diff --git a/arch/um/sys-i386/elfcore.c b/arch/um/sys-i386/elfcore.c
deleted file mode 100644
index 6bb49b6..0000000
--- a/arch/um/sys-i386/elfcore.c
+++ /dev/null
@@ -1,83 +0,0 @@
-#include <linux/elf.h>
-#include <linux/coredump.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-
-#include <asm/elf.h>
-
-
-Elf32_Half elf_core_extra_phdrs(void)
-{
-	return vsyscall_ehdr ? (((struct elfhdr *)vsyscall_ehdr)->e_phnum) : 0;
-}
-
-int elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size,
-			       unsigned long limit)
-{
-	if ( vsyscall_ehdr ) {
-		const struct elfhdr *const ehdrp =
-			(struct elfhdr *) vsyscall_ehdr;
-		const struct elf_phdr *const phdrp =
-			(const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);
-		int i;
-		Elf32_Off ofs = 0;
-
-		for (i = 0; i < ehdrp->e_phnum; ++i) {
-			struct elf_phdr phdr = phdrp[i];
-
-			if (phdr.p_type == PT_LOAD) {
-				ofs = phdr.p_offset = offset;
-				offset += phdr.p_filesz;
-			} else {
-				phdr.p_offset += ofs;
-			}
-			phdr.p_paddr = 0; /* match other core phdrs */
-			*size += sizeof(phdr);
-			if (*size > limit
-			    || !dump_write(file, &phdr, sizeof(phdr)))
-				return 0;
-		}
-	}
-	return 1;
-}
-
-int elf_core_write_extra_data(struct file *file, size_t *size,
-			      unsigned long limit)
-{
-	if ( vsyscall_ehdr ) {
-		const struct elfhdr *const ehdrp =
-			(struct elfhdr *) vsyscall_ehdr;
-		const struct elf_phdr *const phdrp =
-			(const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);
-		int i;
-
-		for (i = 0; i < ehdrp->e_phnum; ++i) {
-			if (phdrp[i].p_type == PT_LOAD) {
-				void *addr = (void *) phdrp[i].p_vaddr;
-				size_t filesz = phdrp[i].p_filesz;
-
-				*size += filesz;
-				if (*size > limit
-				    || !dump_write(file, addr, filesz))
-					return 0;
-			}
-		}
-	}
-	return 1;
-}
-
-size_t elf_core_extra_data_size(void)
-{
-	if ( vsyscall_ehdr ) {
-		const struct elfhdr *const ehdrp =
-			(struct elfhdr *)vsyscall_ehdr;
-		const struct elf_phdr *const phdrp =
-			(const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);
-		int i;
-
-		for (i = 0; i < ehdrp->e_phnum; ++i)
-			if (phdrp[i].p_type == PT_LOAD)
-				return (size_t) phdrp[i].p_filesz;
-	}
-	return 0;
-}
diff --git a/arch/um/sys-i386/fault.c b/arch/um/sys-i386/fault.c
deleted file mode 100644
index d670f68..0000000
--- a/arch/um/sys-i386/fault.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/* 
- * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include "sysdep/ptrace.h"
-
-/* These two are from asm-um/uaccess.h and linux/module.h, check them. */
-struct exception_table_entry
-{
-	unsigned long insn;
-	unsigned long fixup;
-};
-
-const struct exception_table_entry *search_exception_tables(unsigned long add);
-
-/* Compare this to arch/i386/mm/extable.c:fixup_exception() */
-int arch_fixup(unsigned long address, struct uml_pt_regs *regs)
-{
-	const struct exception_table_entry *fixup;
-
-	fixup = search_exception_tables(address);
-	if (fixup != 0) {
-		UPT_IP(regs) = fixup->fixup;
-		return 1;
-	}
-	return 0;
-}
diff --git a/arch/um/sys-i386/ksyms.c b/arch/um/sys-i386/ksyms.c
deleted file mode 100644
index bfbefd3..0000000
--- a/arch/um/sys-i386/ksyms.c
+++ /dev/null
@@ -1,5 +0,0 @@
-#include "linux/module.h"
-#include "asm/checksum.h"
-
-/* Networking helper routines. */
-EXPORT_SYMBOL(csum_partial);
diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c
deleted file mode 100644
index 3f2bf20..0000000
--- a/arch/um/sys-i386/ldt.c
+++ /dev/null
@@ -1,502 +0,0 @@
-/*
- * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <asm/unistd.h>
-#include "os.h"
-#include "proc_mm.h"
-#include "skas.h"
-#include "skas_ptrace.h"
-#include "sysdep/tls.h"
-
-extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
-
-static long write_ldt_entry(struct mm_id *mm_idp, int func,
-		     struct user_desc *desc, void **addr, int done)
-{
-	long res;
-
-	if (proc_mm) {
-		/*
-		 * This is a special handling for the case, that the mm to
-		 * modify isn't current->active_mm.
-		 * If this is called directly by modify_ldt,
-		 *     (current->active_mm->context.skas.u == mm_idp)
-		 * will be true. So no call to __switch_mm(mm_idp) is done.
-		 * If this is called in case of init_new_ldt or PTRACE_LDT,
-		 * mm_idp won't belong to current->active_mm, but child->mm.
-		 * So we need to switch child's mm into our userspace, then
-		 * later switch back.
-		 *
-		 * Note: I'm unsure: should interrupts be disabled here?
-		 */
-		if (!current->active_mm || current->active_mm == &init_mm ||
-		    mm_idp != &current->active_mm->context.id)
-			__switch_mm(mm_idp);
-	}
-
-	if (ptrace_ldt) {
-		struct ptrace_ldt ldt_op = (struct ptrace_ldt) {
-			.func = func,
-			.ptr = desc,
-			.bytecount = sizeof(*desc)};
-		u32 cpu;
-		int pid;
-
-		if (!proc_mm)
-			pid = mm_idp->u.pid;
-		else {
-			cpu = get_cpu();
-			pid = userspace_pid[cpu];
-		}
-
-		res = os_ptrace_ldt(pid, 0, (unsigned long) &ldt_op);
-
-		if (proc_mm)
-			put_cpu();
-	}
-	else {
-		void *stub_addr;
-		res = syscall_stub_data(mm_idp, (unsigned long *)desc,
-					(sizeof(*desc) + sizeof(long) - 1) &
-					    ~(sizeof(long) - 1),
-					addr, &stub_addr);
-		if (!res) {
-			unsigned long args[] = { func,
-						 (unsigned long)stub_addr,
-						 sizeof(*desc),
-						 0, 0, 0 };
-			res = run_syscall_stub(mm_idp, __NR_modify_ldt, args,
-					       0, addr, done);
-		}
-	}
-
-	if (proc_mm) {
-		/*
-		 * This is the second part of special handling, that makes
-		 * PTRACE_LDT possible to implement.
-		 */
-		if (current->active_mm && current->active_mm != &init_mm &&
-		    mm_idp != &current->active_mm->context.id)
-			__switch_mm(&current->active_mm->context.id);
-	}
-
-	return res;
-}
-
-static long read_ldt_from_host(void __user * ptr, unsigned long bytecount)
-{
-	int res, n;
-	struct ptrace_ldt ptrace_ldt = (struct ptrace_ldt) {
-			.func = 0,
-			.bytecount = bytecount,
-			.ptr = kmalloc(bytecount, GFP_KERNEL)};
-	u32 cpu;
-
-	if (ptrace_ldt.ptr == NULL)
-		return -ENOMEM;
-
-	/*
-	 * This is called from sys_modify_ldt only, so userspace_pid gives
-	 * us the right number
-	 */
-
-	cpu = get_cpu();
-	res = os_ptrace_ldt(userspace_pid[cpu], 0, (unsigned long) &ptrace_ldt);
-	put_cpu();
-	if (res < 0)
-		goto out;
-
-	n = copy_to_user(ptr, ptrace_ldt.ptr, res);
-	if (n != 0)
-		res = -EFAULT;
-
-  out:
-	kfree(ptrace_ldt.ptr);
-
-	return res;
-}
-
-/*
- * In skas mode, we hold our own ldt data in UML.
- * Thus, the code implementing sys_modify_ldt_skas
- * is very similar to (and mostly stolen from) sys_modify_ldt
- * for arch/i386/kernel/ldt.c
- * The routines copied and modified in part are:
- * - read_ldt
- * - read_default_ldt
- * - write_ldt
- * - sys_modify_ldt_skas
- */
-
-static int read_ldt(void __user * ptr, unsigned long bytecount)
-{
-	int i, err = 0;
-	unsigned long size;
-	uml_ldt_t * ldt = &current->mm->context.ldt;
-
-	if (!ldt->entry_count)
-		goto out;
-	if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES)
-		bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES;
-	err = bytecount;
-
-	if (ptrace_ldt)
-		return read_ldt_from_host(ptr, bytecount);
-
-	mutex_lock(&ldt->lock);
-	if (ldt->entry_count <= LDT_DIRECT_ENTRIES) {
-		size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES;
-		if (size > bytecount)
-			size = bytecount;
-		if (copy_to_user(ptr, ldt->u.entries, size))
-			err = -EFAULT;
-		bytecount -= size;
-		ptr += size;
-	}
-	else {
-		for (i=0; i<ldt->entry_count/LDT_ENTRIES_PER_PAGE && bytecount;
-		     i++) {
-			size = PAGE_SIZE;
-			if (size > bytecount)
-				size = bytecount;
-			if (copy_to_user(ptr, ldt->u.pages[i], size)) {
-				err = -EFAULT;
-				break;
-			}
-			bytecount -= size;
-			ptr += size;
-		}
-	}
-	mutex_unlock(&ldt->lock);
-
-	if (bytecount == 0 || err == -EFAULT)
-		goto out;
-
-	if (clear_user(ptr, bytecount))
-		err = -EFAULT;
-
-out:
-	return err;
-}
-
-static int read_default_ldt(void __user * ptr, unsigned long bytecount)
-{
-	int err;
-
-	if (bytecount > 5*LDT_ENTRY_SIZE)
-		bytecount = 5*LDT_ENTRY_SIZE;
-
-	err = bytecount;
-	/*
-	 * UML doesn't support lcall7 and lcall27.
-	 * So, we don't really have a default ldt, but emulate
-	 * an empty ldt of common host default ldt size.
-	 */
-	if (clear_user(ptr, bytecount))
-		err = -EFAULT;
-
-	return err;
-}
-
-static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
-{
-	uml_ldt_t * ldt = &current->mm->context.ldt;
-	struct mm_id * mm_idp = &current->mm->context.id;
-	int i, err;
-	struct user_desc ldt_info;
-	struct ldt_entry entry0, *ldt_p;
-	void *addr = NULL;
-
-	err = -EINVAL;
-	if (bytecount != sizeof(ldt_info))
-		goto out;
-	err = -EFAULT;
-	if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info)))
-		goto out;
-
-	err = -EINVAL;
-	if (ldt_info.entry_number >= LDT_ENTRIES)
-		goto out;
-	if (ldt_info.contents == 3) {
-		if (func == 1)
-			goto out;
-		if (ldt_info.seg_not_present == 0)
-			goto out;
-	}
-
-	if (!ptrace_ldt)
-		mutex_lock(&ldt->lock);
-
-	err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1);
-	if (err)
-		goto out_unlock;
-	else if (ptrace_ldt) {
-		/* With PTRACE_LDT available, this is used as a flag only */
-		ldt->entry_count = 1;
-		goto out;
-	}
-
-	if (ldt_info.entry_number >= ldt->entry_count &&
-	    ldt_info.entry_number >= LDT_DIRECT_ENTRIES) {
-		for (i=ldt->entry_count/LDT_ENTRIES_PER_PAGE;
-		     i*LDT_ENTRIES_PER_PAGE <= ldt_info.entry_number;
-		     i++) {
-			if (i == 0)
-				memcpy(&entry0, ldt->u.entries,
-				       sizeof(entry0));
-			ldt->u.pages[i] = (struct ldt_entry *)
-				__get_free_page(GFP_KERNEL|__GFP_ZERO);
-			if (!ldt->u.pages[i]) {
-				err = -ENOMEM;
-				/* Undo the change in host */
-				memset(&ldt_info, 0, sizeof(ldt_info));
-				write_ldt_entry(mm_idp, 1, &ldt_info, &addr, 1);
-				goto out_unlock;
-			}
-			if (i == 0) {
-				memcpy(ldt->u.pages[0], &entry0,
-				       sizeof(entry0));
-				memcpy(ldt->u.pages[0]+1, ldt->u.entries+1,
-				       sizeof(entry0)*(LDT_DIRECT_ENTRIES-1));
-			}
-			ldt->entry_count = (i + 1) * LDT_ENTRIES_PER_PAGE;
-		}
-	}
-	if (ldt->entry_count <= ldt_info.entry_number)
-		ldt->entry_count = ldt_info.entry_number + 1;
-
-	if (ldt->entry_count <= LDT_DIRECT_ENTRIES)
-		ldt_p = ldt->u.entries + ldt_info.entry_number;
-	else
-		ldt_p = ldt->u.pages[ldt_info.entry_number/LDT_ENTRIES_PER_PAGE] +
-			ldt_info.entry_number%LDT_ENTRIES_PER_PAGE;
-
-	if (ldt_info.base_addr == 0 && ldt_info.limit == 0 &&
-	   (func == 1 || LDT_empty(&ldt_info))) {
-		ldt_p->a = 0;
-		ldt_p->b = 0;
-	}
-	else{
-		if (func == 1)
-			ldt_info.useable = 0;
-		ldt_p->a = LDT_entry_a(&ldt_info);
-		ldt_p->b = LDT_entry_b(&ldt_info);
-	}
-	err = 0;
-
-out_unlock:
-	mutex_unlock(&ldt->lock);
-out:
-	return err;
-}
-
-static long do_modify_ldt_skas(int func, void __user *ptr,
-			       unsigned long bytecount)
-{
-	int ret = -ENOSYS;
-
-	switch (func) {
-		case 0:
-			ret = read_ldt(ptr, bytecount);
-			break;
-		case 1:
-		case 0x11:
-			ret = write_ldt(ptr, bytecount, func);
-			break;
-		case 2:
-			ret = read_default_ldt(ptr, bytecount);
-			break;
-	}
-	return ret;
-}
-
-static DEFINE_SPINLOCK(host_ldt_lock);
-static short dummy_list[9] = {0, -1};
-static short * host_ldt_entries = NULL;
-
-static void ldt_get_host_info(void)
-{
-	long ret;
-	struct ldt_entry * ldt;
-	short *tmp;
-	int i, size, k, order;
-
-	spin_lock(&host_ldt_lock);
-
-	if (host_ldt_entries != NULL) {
-		spin_unlock(&host_ldt_lock);
-		return;
-	}
-	host_ldt_entries = dummy_list+1;
-
-	spin_unlock(&host_ldt_lock);
-
-	for (i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++)
-		;
-
-	ldt = (struct ldt_entry *)
-	      __get_free_pages(GFP_KERNEL|__GFP_ZERO, order);
-	if (ldt == NULL) {
-		printk(KERN_ERR "ldt_get_host_info: couldn't allocate buffer "
-		       "for host ldt\n");
-		return;
-	}
-
-	ret = modify_ldt(0, ldt, (1<<order)*PAGE_SIZE);
-	if (ret < 0) {
-		printk(KERN_ERR "ldt_get_host_info: couldn't read host ldt\n");
-		goto out_free;
-	}
-	if (ret == 0) {
-		/* default_ldt is active, simply write an empty entry 0 */
-		host_ldt_entries = dummy_list;
-		goto out_free;
-	}
-
-	for (i=0, size=0; i<ret/LDT_ENTRY_SIZE; i++) {
-		if (ldt[i].a != 0 || ldt[i].b != 0)
-			size++;
-	}
-
-	if (size < ARRAY_SIZE(dummy_list))
-		host_ldt_entries = dummy_list;
-	else {
-		size = (size + 1) * sizeof(dummy_list[0]);
-		tmp = kmalloc(size, GFP_KERNEL);
-		if (tmp == NULL) {
-			printk(KERN_ERR "ldt_get_host_info: couldn't allocate "
-			       "host ldt list\n");
-			goto out_free;
-		}
-		host_ldt_entries = tmp;
-	}
-
-	for (i=0, k=0; i<ret/LDT_ENTRY_SIZE; i++) {
-		if (ldt[i].a != 0 || ldt[i].b != 0)
-			host_ldt_entries[k++] = i;
-	}
-	host_ldt_entries[k] = -1;
-
-out_free:
-	free_pages((unsigned long)ldt, order);
-}
-
-long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
-{
-	struct user_desc desc;
-	short * num_p;
-	int i;
-	long page, err=0;
-	void *addr = NULL;
-	struct proc_mm_op copy;
-
-
-	if (!ptrace_ldt)
-		mutex_init(&new_mm->ldt.lock);
-
-	if (!from_mm) {
-		memset(&desc, 0, sizeof(desc));
-		/*
-		 * We have to initialize a clean ldt.
-		 */
-		if (proc_mm) {
-			/*
-			 * If the new mm was created using proc_mm, host's
-			 * default-ldt currently is assigned, which normally
-			 * contains the call-gates for lcall7 and lcall27.
-			 * To remove these gates, we simply write an empty
-			 * entry as number 0 to the host.
-			 */
-			err = write_ldt_entry(&new_mm->id, 1, &desc, &addr, 1);
-		}
-		else{
-			/*
-			 * Now we try to retrieve info about the ldt, we
-			 * inherited from the host. All ldt-entries found
-			 * will be reset in the following loop
-			 */
-			ldt_get_host_info();
-			for (num_p=host_ldt_entries; *num_p != -1; num_p++) {
-				desc.entry_number = *num_p;
-				err = write_ldt_entry(&new_mm->id, 1, &desc,
-						      &addr, *(num_p + 1) == -1);
-				if (err)
-					break;
-			}
-		}
-		new_mm->ldt.entry_count = 0;
-
-		goto out;
-	}
-
-	if (proc_mm) {
-		/*
-		 * We have a valid from_mm, so we now have to copy the LDT of
-		 * from_mm to new_mm, because using proc_mm an new mm with
-		 * an empty/default LDT was created in new_mm()
-		 */
-		copy = ((struct proc_mm_op) { .op 	= MM_COPY_SEGMENTS,
-					      .u 	=
-					      { .copy_segments =
-							from_mm->id.u.mm_fd } } );
-		i = os_write_file(new_mm->id.u.mm_fd, &copy, sizeof(copy));
-		if (i != sizeof(copy))
-			printk(KERN_ERR "new_mm : /proc/mm copy_segments "
-			       "failed, err = %d\n", -i);
-	}
-
-	if (!ptrace_ldt) {
-		/*
-		 * Our local LDT is used to supply the data for
-		 * modify_ldt(READLDT), if PTRACE_LDT isn't available,
-		 * i.e., we have to use the stub for modify_ldt, which
-		 * can't handle the big read buffer of up to 64kB.
-		 */
-		mutex_lock(&from_mm->ldt.lock);
-		if (from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES)
-			memcpy(new_mm->ldt.u.entries, from_mm->ldt.u.entries,
-			       sizeof(new_mm->ldt.u.entries));
-		else {
-			i = from_mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE;
-			while (i-->0) {
-				page = __get_free_page(GFP_KERNEL|__GFP_ZERO);
-				if (!page) {
-					err = -ENOMEM;
-					break;
-				}
-				new_mm->ldt.u.pages[i] =
-					(struct ldt_entry *) page;
-				memcpy(new_mm->ldt.u.pages[i],
-				       from_mm->ldt.u.pages[i], PAGE_SIZE);
-			}
-		}
-		new_mm->ldt.entry_count = from_mm->ldt.entry_count;
-		mutex_unlock(&from_mm->ldt.lock);
-	}
-
-    out:
-	return err;
-}
-
-
-void free_ldt(struct mm_context *mm)
-{
-	int i;
-
-	if (!ptrace_ldt && mm->ldt.entry_count > LDT_DIRECT_ENTRIES) {
-		i = mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE;
-		while (i-- > 0)
-			free_page((long) mm->ldt.u.pages[i]);
-	}
-	mm->ldt.entry_count = 0;
-}
-
-int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
-{
-	return do_modify_ldt_skas(func, ptr, bytecount);
-}
diff --git a/arch/um/sys-i386/mem.c b/arch/um/sys-i386/mem.c
deleted file mode 100644
index 639900a..0000000
--- a/arch/um/sys-i386/mem.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/mm.h>
-#include <asm/page.h>
-#include <asm/mman.h>
-
-static struct vm_area_struct gate_vma;
-
-static int __init gate_vma_init(void)
-{
-	if (!FIXADDR_USER_START)
-		return 0;
-
-	gate_vma.vm_mm = NULL;
-	gate_vma.vm_start = FIXADDR_USER_START;
-	gate_vma.vm_end = FIXADDR_USER_END;
-	gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC;
-	gate_vma.vm_page_prot = __P101;
-
-	/*
-	 * Make sure the vDSO gets into every core dump.
-	 * Dumping its contents makes post-mortem fully interpretable later
-	 * without matching up the same kernel and hardware config to see
-	 * what PC values meant.
-	 */
-	gate_vma.vm_flags |= VM_ALWAYSDUMP;
-
-	return 0;
-}
-__initcall(gate_vma_init);
-
-struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
-{
-	return FIXADDR_USER_START ? &gate_vma : NULL;
-}
-
-int in_gate_area_no_mm(unsigned long addr)
-{
-	if (!FIXADDR_USER_START)
-		return 0;
-
-	if ((addr >= FIXADDR_USER_START) && (addr < FIXADDR_USER_END))
-		return 1;
-
-	return 0;
-}
-
-int in_gate_area(struct mm_struct *mm, unsigned long addr)
-{
-	struct vm_area_struct *vma = get_gate_vma(mm);
-
-	if (!vma)
-		return 0;
-
-	return (addr >= vma->vm_start) && (addr < vma->vm_end);
-}
diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c
deleted file mode 100644
index 3375c27..0000000
--- a/arch/um/sys-i386/ptrace.c
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include "linux/mm.h"
-#include "linux/sched.h"
-#include "asm/uaccess.h"
-#include "skas.h"
-
-extern int arch_switch_tls(struct task_struct *to);
-
-void arch_switch_to(struct task_struct *to)
-{
-	int err = arch_switch_tls(to);
-	if (!err)
-		return;
-
-	if (err != -EINVAL)
-		printk(KERN_WARNING "arch_switch_tls failed, errno %d, "
-		       "not EINVAL\n", -err);
-	else
-		printk(KERN_WARNING "arch_switch_tls failed, errno = EINVAL\n");
-}
-
-int is_syscall(unsigned long addr)
-{
-	unsigned short instr;
-	int n;
-
-	n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
-	if (n) {
-		/* access_process_vm() grants access to vsyscall and stub,
-		 * while copy_from_user doesn't. Maybe access_process_vm is
-		 * slow, but that doesn't matter, since it will be called only
-		 * in case of singlestepping, if copy_from_user failed.
-		 */
-		n = access_process_vm(current, addr, &instr, sizeof(instr), 0);
-		if (n != sizeof(instr)) {
-			printk(KERN_ERR "is_syscall : failed to read "
-			       "instruction from 0x%lx\n", addr);
-			return 1;
-		}
-	}
-	/* int 0x80 or sysenter */
-	return (instr == 0x80cd) || (instr == 0x340f);
-}
-
-/* determines which flags the user has access to. */
-/* 1 = access 0 = no access */
-#define FLAG_MASK 0x00044dd5
-
-int putreg(struct task_struct *child, int regno, unsigned long value)
-{
-	regno >>= 2;
-	switch (regno) {
-	case FS:
-		if (value && (value & 3) != 3)
-			return -EIO;
-		PT_REGS_FS(&child->thread.regs) = value;
-		return 0;
-	case GS:
-		if (value && (value & 3) != 3)
-			return -EIO;
-		PT_REGS_GS(&child->thread.regs) = value;
-		return 0;
-	case DS:
-	case ES:
-		if (value && (value & 3) != 3)
-			return -EIO;
-		value &= 0xffff;
-		break;
-	case SS:
-	case CS:
-		if ((value & 3) != 3)
-			return -EIO;
-		value &= 0xffff;
-		break;
-	case EFL:
-		value &= FLAG_MASK;
-		value |= PT_REGS_EFLAGS(&child->thread.regs);
-		break;
-	}
-	PT_REGS_SET(&child->thread.regs, regno, value);
-	return 0;
-}
-
-int poke_user(struct task_struct *child, long addr, long data)
-{
-	if ((addr & 3) || addr < 0)
-		return -EIO;
-
-	if (addr < MAX_REG_OFFSET)
-		return putreg(child, addr, data);
-	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
-		 (addr <= offsetof(struct user, u_debugreg[7]))) {
-		addr -= offsetof(struct user, u_debugreg[0]);
-		addr = addr >> 2;
-		if ((addr == 4) || (addr == 5))
-			return -EIO;
-		child->thread.arch.debugregs[addr] = data;
-		return 0;
-	}
-	return -EIO;
-}
-
-unsigned long getreg(struct task_struct *child, int regno)
-{
-	unsigned long retval = ~0UL;
-
-	regno >>= 2;
-	switch (regno) {
-	case FS:
-	case GS:
-	case DS:
-	case ES:
-	case SS:
-	case CS:
-		retval = 0xffff;
-		/* fall through */
-	default:
-		retval &= PT_REG(&child->thread.regs, regno);
-	}
-	return retval;
-}
-
-/* read the word at location addr in the USER area. */
-int peek_user(struct task_struct *child, long addr, long data)
-{
-	unsigned long tmp;
-
-	if ((addr & 3) || addr < 0)
-		return -EIO;
-
-	tmp = 0;  /* Default return condition */
-	if (addr < MAX_REG_OFFSET) {
-		tmp = getreg(child, addr);
-	}
-	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
-		 (addr <= offsetof(struct user, u_debugreg[7]))) {
-		addr -= offsetof(struct user, u_debugreg[0]);
-		addr = addr >> 2;
-		tmp = child->thread.arch.debugregs[addr];
-	}
-	return put_user(tmp, (unsigned long __user *) data);
-}
-
-static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
-{
-	int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
-	struct user_i387_struct fpregs;
-
-	err = save_fp_registers(userspace_pid[cpu], (unsigned long *) &fpregs);
-	if (err)
-		return err;
-
-	n = copy_to_user(buf, &fpregs, sizeof(fpregs));
-	if(n > 0)
-		return -EFAULT;
-
-	return n;
-}
-
-static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
-{
-	int n, cpu = ((struct thread_info *) child->stack)->cpu;
-	struct user_i387_struct fpregs;
-
-	n = copy_from_user(&fpregs, buf, sizeof(fpregs));
-	if (n > 0)
-		return -EFAULT;
-
-	return restore_fp_registers(userspace_pid[cpu],
-				    (unsigned long *) &fpregs);
-}
-
-static int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child)
-{
-	int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
-	struct user_fxsr_struct fpregs;
-
-	err = save_fpx_registers(userspace_pid[cpu], (unsigned long *) &fpregs);
-	if (err)
-		return err;
-
-	n = copy_to_user(buf, &fpregs, sizeof(fpregs));
-	if(n > 0)
-		return -EFAULT;
-
-	return n;
-}
-
-static int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child)
-{
-	int n, cpu = ((struct thread_info *) child->stack)->cpu;
-	struct user_fxsr_struct fpregs;
-
-	n = copy_from_user(&fpregs, buf, sizeof(fpregs));
-	if (n > 0)
-		return -EFAULT;
-
-	return restore_fpx_registers(userspace_pid[cpu],
-				     (unsigned long *) &fpregs);
-}
-
-long subarch_ptrace(struct task_struct *child, long request,
-		    unsigned long addr, unsigned long data)
-{
-	int ret = -EIO;
-	void __user *datap = (void __user *) data;
-	switch (request) {
-	case PTRACE_GETFPREGS: /* Get the child FPU state. */
-		ret = get_fpregs(datap, child);
-		break;
-	case PTRACE_SETFPREGS: /* Set the child FPU state. */
-		ret = set_fpregs(datap, child);
-		break;
-	case PTRACE_GETFPXREGS: /* Get the child FPU state. */
-		ret = get_fpxregs(datap, child);
-		break;
-	case PTRACE_SETFPXREGS: /* Set the child FPU state. */
-		ret = set_fpxregs(datap, child);
-		break;
-	default:
-		ret = -EIO;
-	}
-	return ret;
-}
diff --git a/arch/um/sys-i386/ptrace_user.c b/arch/um/sys-i386/ptrace_user.c
deleted file mode 100644
index 0b10c3e..0000000
--- a/arch/um/sys-i386/ptrace_user.c
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <errno.h>
-#include <sys/ptrace.h>
-
-int ptrace_getregs(long pid, unsigned long *regs_out)
-{
-	if (ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0)
-		return -errno;
-	return 0;
-}
-
-int ptrace_setregs(long pid, unsigned long *regs)
-{
-	if (ptrace(PTRACE_SETREGS, pid, 0, regs) < 0)
-		return -errno;
-	return 0;
-}
diff --git a/arch/um/sys-i386/setjmp.S b/arch/um/sys-i386/setjmp.S
deleted file mode 100644
index b766792..0000000
--- a/arch/um/sys-i386/setjmp.S
+++ /dev/null
@@ -1,58 +0,0 @@
-#
-# arch/i386/setjmp.S
-#
-# setjmp/longjmp for the i386 architecture
-#
-
-#
-# The jmp_buf is assumed to contain the following, in order:
-#	%ebx
-#	%esp
-#	%ebp
-#	%esi
-#	%edi
-#	<return address>
-#
-
-	.text
-	.align 4
-	.globl setjmp
-	.type setjmp, @function
-setjmp:
-#ifdef _REGPARM
-	movl %eax,%edx
-#else
-	movl 4(%esp),%edx
-#endif
-	popl %ecx			# Return address, and adjust the stack
-	xorl %eax,%eax			# Return value
-	movl %ebx,(%edx)
-	movl %esp,4(%edx)		# Post-return %esp!
-	pushl %ecx			# Make the call/return stack happy
-	movl %ebp,8(%edx)
-	movl %esi,12(%edx)
-	movl %edi,16(%edx)
-	movl %ecx,20(%edx)		# Return address
-	ret
-
-	.size setjmp,.-setjmp
-
-	.text
-	.align 4
-	.globl longjmp
-	.type longjmp, @function
-longjmp:
-#ifdef _REGPARM
-	xchgl %eax,%edx
-#else
-	movl 4(%esp),%edx		# jmp_ptr address
-	movl 8(%esp),%eax		# Return value
-#endif
-	movl (%edx),%ebx
-	movl 4(%edx),%esp
-	movl 8(%edx),%ebp
-	movl 12(%edx),%esi
-	movl 16(%edx),%edi
-	jmp *20(%edx)
-
-	.size longjmp,.-longjmp
diff --git a/arch/um/sys-i386/shared/sysdep/archsetjmp.h b/arch/um/sys-i386/shared/sysdep/archsetjmp.h
deleted file mode 100644
index 0f31208..0000000
--- a/arch/um/sys-i386/shared/sysdep/archsetjmp.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * arch/um/include/sysdep-i386/archsetjmp.h
- */
-
-#ifndef _KLIBC_ARCHSETJMP_H
-#define _KLIBC_ARCHSETJMP_H
-
-struct __jmp_buf {
-	unsigned int __ebx;
-	unsigned int __esp;
-	unsigned int __ebp;
-	unsigned int __esi;
-	unsigned int __edi;
-	unsigned int __eip;
-};
-
-typedef struct __jmp_buf jmp_buf[1];
-
-#define JB_IP __eip
-#define JB_SP __esp
-
-#endif				/* _SETJMP_H */
diff --git a/arch/um/sys-i386/shared/sysdep/barrier.h b/arch/um/sys-i386/shared/sysdep/barrier.h
deleted file mode 100644
index b58d52c..0000000
--- a/arch/um/sys-i386/shared/sysdep/barrier.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __SYSDEP_I386_BARRIER_H
-#define __SYSDEP_I386_BARRIER_H
-
-/* Copied from include/asm-i386 for use by userspace.  i386 has the option
- * of using mfence, but I'm just using this, which works everywhere, for now.
- */
-#define mb() asm volatile("lock; addl $0,0(%esp)")
-
-#endif
diff --git a/arch/um/sys-i386/shared/sysdep/checksum.h b/arch/um/sys-i386/shared/sysdep/checksum.h
deleted file mode 100644
index ed47445..0000000
--- a/arch/um/sys-i386/shared/sysdep/checksum.h
+++ /dev/null
@@ -1,201 +0,0 @@
-/* 
- * Licensed under the GPL
- */
-
-#ifndef __UM_SYSDEP_CHECKSUM_H
-#define __UM_SYSDEP_CHECKSUM_H
-
-#include "linux/in6.h"
-#include "linux/string.h"
-
-/*
- * computes the checksum of a memory block at buff, length len,
- * and adds in "sum" (32-bit)
- *
- * returns a 32-bit number suitable for feeding into itself
- * or csum_tcpudp_magic
- *
- * this function must be called with even lengths, except
- * for the last fragment, which may be odd
- *
- * it's best to have buff aligned on a 32-bit boundary
- */
-__wsum csum_partial(const void *buff, int len, __wsum sum);
-
-/*
- *	Note: when you get a NULL pointer exception here this means someone
- *	passed in an incorrect kernel address to one of these functions.
- *
- *	If you use these functions directly please don't forget the
- *	access_ok().
- */
-
-static __inline__
-__wsum csum_partial_copy_nocheck(const void *src, void *dst,
-				       int len, __wsum sum)
-{
-	memcpy(dst, src, len);
-	return csum_partial(dst, len, sum);
-}
-
-/*
- * the same as csum_partial, but copies from src while it
- * checksums, and handles user-space pointer exceptions correctly, when needed.
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-
-static __inline__
-__wsum csum_partial_copy_from_user(const void __user *src, void *dst,
-					 int len, __wsum sum, int *err_ptr)
-{
-	if (copy_from_user(dst, src, len)) {
-		*err_ptr = -EFAULT;
-		return (__force __wsum)-1;
-	}
-
-	return csum_partial(dst, len, sum);
-}
-
-/*
- *	This is a version of ip_compute_csum() optimized for IP headers,
- *	which always checksum on 4 octet boundaries.
- *
- *	By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
- *	Arnt Gulbrandsen.
- */
-static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
-{
-	unsigned int sum;
-
-	__asm__ __volatile__(
-	    "movl (%1), %0	;\n"
-	    "subl $4, %2	;\n"
-	    "jbe 2f		;\n"
-	    "addl 4(%1), %0	;\n"
-	    "adcl 8(%1), %0	;\n"
-	    "adcl 12(%1), %0	;\n"
-"1:	    adcl 16(%1), %0	;\n"
-	    "lea 4(%1), %1	;\n"
-	    "decl %2		;\n"
-	    "jne 1b		;\n"
-	    "adcl $0, %0	;\n"
-	    "movl %0, %2	;\n"
-	    "shrl $16, %0	;\n"
-	    "addw %w2, %w0	;\n"
-	    "adcl $0, %0	;\n"
-	    "notl %0		;\n"
-"2:				;\n"
-	/* Since the input registers which are loaded with iph and ipl
-	   are modified, we must also specify them as outputs, or gcc
-	   will assume they contain their original values. */
-	: "=r" (sum), "=r" (iph), "=r" (ihl)
-	: "1" (iph), "2" (ihl)
-	: "memory");
-	return (__force __sum16)sum;
-}
-
-/*
- *	Fold a partial checksum
- */
-
-static inline __sum16 csum_fold(__wsum sum)
-{
-	__asm__(
-		"addl %1, %0		;\n"
-		"adcl $0xffff, %0	;\n"
-		: "=r" (sum)
-		: "r" ((__force u32)sum << 16),
-		  "0" ((__force u32)sum & 0xffff0000)
-	);
-	return (__force __sum16)(~(__force u32)sum >> 16);
-}
-
-static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
-						   unsigned short len,
-						   unsigned short proto,
-						   __wsum sum)
-{
-    __asm__(
-	"addl %1, %0	;\n"
-	"adcl %2, %0	;\n"
-	"adcl %3, %0	;\n"
-	"adcl $0, %0	;\n"
-	: "=r" (sum)
-	: "g" (daddr), "g"(saddr), "g"((len + proto) << 8), "0"(sum));
-    return sum;
-}
-
-/*
- * computes the checksum of the TCP/UDP pseudo-header
- * returns a 16-bit checksum, already complemented
- */
-static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
-						   unsigned short len,
-						   unsigned short proto,
-						   __wsum sum)
-{
-	return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
-}
-
-/*
- * this routine is used for miscellaneous IP-like checksums, mainly
- * in icmp.c
- */
-
-static inline __sum16 ip_compute_csum(const void *buff, int len)
-{
-    return csum_fold (csum_partial(buff, len, 0));
-}
-
-#define _HAVE_ARCH_IPV6_CSUM
-static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
-					  const struct in6_addr *daddr,
-					  __u32 len, unsigned short proto,
-					  __wsum sum)
-{
-	__asm__(
-		"addl 0(%1), %0		;\n"
-		"adcl 4(%1), %0		;\n"
-		"adcl 8(%1), %0		;\n"
-		"adcl 12(%1), %0	;\n"
-		"adcl 0(%2), %0		;\n"
-		"adcl 4(%2), %0		;\n"
-		"adcl 8(%2), %0		;\n"
-		"adcl 12(%2), %0	;\n"
-		"adcl %3, %0		;\n"
-		"adcl %4, %0		;\n"
-		"adcl $0, %0		;\n"
-		: "=&r" (sum)
-		: "r" (saddr), "r" (daddr),
-		  "r"(htonl(len)), "r"(htonl(proto)), "0"(sum));
-
-	return csum_fold(sum);
-}
-
-/*
- *	Copy and checksum to user
- */
-#define HAVE_CSUM_COPY_USER
-static __inline__ __wsum csum_and_copy_to_user(const void *src,
-						     void __user *dst,
-						     int len, __wsum sum, int *err_ptr)
-{
-	if (access_ok(VERIFY_WRITE, dst, len)) {
-		if (copy_to_user(dst, src, len)) {
-			*err_ptr = -EFAULT;
-			return (__force __wsum)-1;
-		}
-
-		return csum_partial(src, len, sum);
-	}
-
-	if (len)
-		*err_ptr = -EFAULT;
-
-	return (__force __wsum)-1; /* invalid checksum */
-}
-
-#endif
-
diff --git a/arch/um/sys-i386/shared/sysdep/faultinfo.h b/arch/um/sys-i386/shared/sysdep/faultinfo.h
deleted file mode 100644
index db437cc..0000000
--- a/arch/um/sys-i386/shared/sysdep/faultinfo.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
- * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
- * Licensed under the GPL
- */
-
-#ifndef __FAULTINFO_I386_H
-#define __FAULTINFO_I386_H
-
-/* this structure contains the full arch-specific faultinfo
- * from the traps.
- * On i386, ptrace_faultinfo unfortunately doesn't provide
- * all the info, since trap_no is missing.
- * All common elements are defined at the same position in
- * both structures, thus making it easy to copy the
- * contents without knowledge about the structure elements.
- */
-struct faultinfo {
-        int error_code; /* in ptrace_faultinfo misleadingly called is_write */
-        unsigned long cr2; /* in ptrace_faultinfo called addr */
-        int trap_no; /* missing in ptrace_faultinfo */
-};
-
-#define FAULT_WRITE(fi) ((fi).error_code & 2)
-#define FAULT_ADDRESS(fi) ((fi).cr2)
-
-#define PTRACE_FULL_FAULTINFO 0
-
-#endif
diff --git a/arch/um/sys-i386/shared/sysdep/host_ldt.h b/arch/um/sys-i386/shared/sysdep/host_ldt.h
deleted file mode 100644
index 0953cc4..0000000
--- a/arch/um/sys-i386/shared/sysdep/host_ldt.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef __ASM_HOST_LDT_I386_H
-#define __ASM_HOST_LDT_I386_H
-
-#include <asm/ldt.h>
-
-/*
- * macros stolen from include/asm-i386/desc.h
- */
-#define LDT_entry_a(info) \
-	((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
-
-#define LDT_entry_b(info) \
-	(((info)->base_addr & 0xff000000) | \
-	(((info)->base_addr & 0x00ff0000) >> 16) | \
-	((info)->limit & 0xf0000) | \
-	(((info)->read_exec_only ^ 1) << 9) | \
-	((info)->contents << 10) | \
-	(((info)->seg_not_present ^ 1) << 15) | \
-	((info)->seg_32bit << 22) | \
-	((info)->limit_in_pages << 23) | \
-	((info)->useable << 20) | \
-	0x7000)
-
-#define LDT_empty(info) (\
-	(info)->base_addr	== 0	&& \
-	(info)->limit		== 0	&& \
-	(info)->contents	== 0	&& \
-	(info)->read_exec_only	== 1	&& \
-	(info)->seg_32bit	== 0	&& \
-	(info)->limit_in_pages	== 0	&& \
-	(info)->seg_not_present	== 1	&& \
-	(info)->useable		== 0	)
-
-#endif
diff --git a/arch/um/sys-i386/shared/sysdep/kernel-offsets.h b/arch/um/sys-i386/shared/sysdep/kernel-offsets.h
deleted file mode 100644
index 5868526..0000000
--- a/arch/um/sys-i386/shared/sysdep/kernel-offsets.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#include <linux/stddef.h>
-#include <linux/sched.h>
-#include <linux/elf.h>
-#include <linux/crypto.h>
-#include <asm/mman.h>
-
-#define DEFINE(sym, val) \
-	asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define STR(x) #x
-#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " STR(val) " " #val: : )
-
-#define BLANK() asm volatile("\n->" : : )
-
-#define OFFSET(sym, str, mem) \
-	DEFINE(sym, offsetof(struct str, mem));
-
-void foo(void)
-{
-#include <common-offsets.h>
-}
diff --git a/arch/um/sys-i386/shared/sysdep/ptrace.h b/arch/um/sys-i386/shared/sysdep/ptrace.h
deleted file mode 100644
index c398a50..0000000
--- a/arch/um/sys-i386/shared/sysdep/ptrace.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_I386_PTRACE_H
-#define __SYSDEP_I386_PTRACE_H
-
-#include "user_constants.h"
-#include "sysdep/faultinfo.h"
-
-#define MAX_REG_NR (UM_FRAME_SIZE / sizeof(unsigned long))
-#define MAX_REG_OFFSET (UM_FRAME_SIZE)
-
-static inline void update_debugregs(int seq) {}
-
-/* syscall emulation path in ptrace */
-
-#ifndef PTRACE_SYSEMU
-#define PTRACE_SYSEMU 31
-#endif
-
-void set_using_sysemu(int value);
-int get_using_sysemu(void);
-extern int sysemu_supported;
-
-#include "skas_ptregs.h"
-
-#define REGS_IP(r) ((r)[HOST_IP])
-#define REGS_SP(r) ((r)[HOST_SP])
-#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS])
-#define REGS_EAX(r) ((r)[HOST_EAX])
-#define REGS_EBX(r) ((r)[HOST_EBX])
-#define REGS_ECX(r) ((r)[HOST_ECX])
-#define REGS_EDX(r) ((r)[HOST_EDX])
-#define REGS_ESI(r) ((r)[HOST_ESI])
-#define REGS_EDI(r) ((r)[HOST_EDI])
-#define REGS_EBP(r) ((r)[HOST_EBP])
-#define REGS_CS(r) ((r)[HOST_CS])
-#define REGS_SS(r) ((r)[HOST_SS])
-#define REGS_DS(r) ((r)[HOST_DS])
-#define REGS_ES(r) ((r)[HOST_ES])
-#define REGS_FS(r) ((r)[HOST_FS])
-#define REGS_GS(r) ((r)[HOST_GS])
-
-#define REGS_SET_SYSCALL_RETURN(r, res) REGS_EAX(r) = (res)
-
-#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r))
-
-#ifndef PTRACE_SYSEMU_SINGLESTEP
-#define PTRACE_SYSEMU_SINGLESTEP 32
-#endif
-
-struct uml_pt_regs {
-	unsigned long gp[MAX_REG_NR];
-	unsigned long fp[HOST_FPX_SIZE];
-	struct faultinfo faultinfo;
-	long syscall;
-	int is_user;
-};
-
-#define EMPTY_UML_PT_REGS { }
-
-#define UPT_IP(r) REGS_IP((r)->gp)
-#define UPT_SP(r) REGS_SP((r)->gp)
-#define UPT_EFLAGS(r) REGS_EFLAGS((r)->gp)
-#define UPT_EAX(r) REGS_EAX((r)->gp)
-#define UPT_EBX(r) REGS_EBX((r)->gp)
-#define UPT_ECX(r) REGS_ECX((r)->gp)
-#define UPT_EDX(r) REGS_EDX((r)->gp)
-#define UPT_ESI(r) REGS_ESI((r)->gp)
-#define UPT_EDI(r) REGS_EDI((r)->gp)
-#define UPT_EBP(r) REGS_EBP((r)->gp)
-#define UPT_ORIG_EAX(r) ((r)->syscall)
-#define UPT_CS(r) REGS_CS((r)->gp)
-#define UPT_SS(r) REGS_SS((r)->gp)
-#define UPT_DS(r) REGS_DS((r)->gp)
-#define UPT_ES(r) REGS_ES((r)->gp)
-#define UPT_FS(r) REGS_FS((r)->gp)
-#define UPT_GS(r) REGS_GS((r)->gp)
-
-#define UPT_SYSCALL_ARG1(r) UPT_EBX(r)
-#define UPT_SYSCALL_ARG2(r) UPT_ECX(r)
-#define UPT_SYSCALL_ARG3(r) UPT_EDX(r)
-#define UPT_SYSCALL_ARG4(r) UPT_ESI(r)
-#define UPT_SYSCALL_ARG5(r) UPT_EDI(r)
-#define UPT_SYSCALL_ARG6(r) UPT_EBP(r)
-
-extern int user_context(unsigned long sp);
-
-#define UPT_IS_USER(r) ((r)->is_user)
-
-struct syscall_args {
-	unsigned long args[6];
-};
-
-#define SYSCALL_ARGS(r) ((struct syscall_args) \
-			 { .args = { UPT_SYSCALL_ARG1(r),	\
-				     UPT_SYSCALL_ARG2(r),	\
-				     UPT_SYSCALL_ARG3(r),	\
-				     UPT_SYSCALL_ARG4(r),	\
-				     UPT_SYSCALL_ARG5(r),	\
-				     UPT_SYSCALL_ARG6(r) } } )
-
-#define UPT_REG(regs, reg) \
-	({	unsigned long val; \
-		switch(reg){ \
-		case EIP: val = UPT_IP(regs); break; \
-		case UESP: val = UPT_SP(regs); break; \
-		case EAX: val = UPT_EAX(regs); break; \
-		case EBX: val = UPT_EBX(regs); break; \
-		case ECX: val = UPT_ECX(regs); break; \
-		case EDX: val = UPT_EDX(regs); break; \
-		case ESI: val = UPT_ESI(regs); break; \
-		case EDI: val = UPT_EDI(regs); break; \
-		case EBP: val = UPT_EBP(regs); break; \
-		case ORIG_EAX: val = UPT_ORIG_EAX(regs); break; \
-		case CS: val = UPT_CS(regs); break; \
-		case SS: val = UPT_SS(regs); break; \
-		case DS: val = UPT_DS(regs); break; \
-		case ES: val = UPT_ES(regs); break; \
-		case FS: val = UPT_FS(regs); break; \
-		case GS: val = UPT_GS(regs); break; \
-		case EFL: val = UPT_EFLAGS(regs); break; \
-		default :  \
-			panic("Bad register in UPT_REG : %d\n", reg);  \
-			val = -1; \
-		} \
-	        val; \
-	})
-
-#define UPT_SET(regs, reg, val) \
-	do { \
-		switch(reg){ \
-		case EIP: UPT_IP(regs) = val; break; \
-		case UESP: UPT_SP(regs) = val; break; \
-		case EAX: UPT_EAX(regs) = val; break; \
-		case EBX: UPT_EBX(regs) = val; break; \
-		case ECX: UPT_ECX(regs) = val; break; \
-		case EDX: UPT_EDX(regs) = val; break; \
-		case ESI: UPT_ESI(regs) = val; break; \
-		case EDI: UPT_EDI(regs) = val; break; \
-		case EBP: UPT_EBP(regs) = val; break; \
-		case ORIG_EAX: UPT_ORIG_EAX(regs) = val; break; \
-		case CS: UPT_CS(regs) = val; break; \
-		case SS: UPT_SS(regs) = val; break; \
-		case DS: UPT_DS(regs) = val; break; \
-		case ES: UPT_ES(regs) = val; break; \
-		case FS: UPT_FS(regs) = val; break; \
-		case GS: UPT_GS(regs) = val; break; \
-		case EFL: UPT_EFLAGS(regs) = val; break; \
-		default :  \
-			panic("Bad register in UPT_SET : %d\n", reg);  \
-			break; \
-		} \
-	} while (0)
-
-#define UPT_SET_SYSCALL_RETURN(r, res) \
-	REGS_SET_SYSCALL_RETURN((r)->regs, (res))
-
-#define UPT_RESTART_SYSCALL(r) REGS_RESTART_SYSCALL((r)->gp)
-
-#define UPT_ORIG_SYSCALL(r) UPT_EAX(r)
-#define UPT_SYSCALL_NR(r) UPT_ORIG_EAX(r)
-#define UPT_SYSCALL_RET(r) UPT_EAX(r)
-
-#define UPT_FAULTINFO(r) (&(r)->faultinfo)
-
-extern void arch_init_registers(int pid);
-
-#endif
diff --git a/arch/um/sys-i386/shared/sysdep/ptrace_user.h b/arch/um/sys-i386/shared/sysdep/ptrace_user.h
deleted file mode 100644
index ef56247..0000000
--- a/arch/um/sys-i386/shared/sysdep/ptrace_user.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_I386_PTRACE_USER_H__
-#define __SYSDEP_I386_PTRACE_USER_H__
-
-#include <sys/ptrace.h>
-#include <linux/ptrace.h>
-#include <asm/ptrace.h>
-#include "user_constants.h"
-
-#define PT_OFFSET(r) ((r) * sizeof(long))
-
-#define PT_SYSCALL_NR(regs) ((regs)[ORIG_EAX])
-#define PT_SYSCALL_NR_OFFSET PT_OFFSET(ORIG_EAX)
-
-#define PT_SYSCALL_ARG1_OFFSET PT_OFFSET(EBX)
-#define PT_SYSCALL_ARG2_OFFSET PT_OFFSET(ECX)
-#define PT_SYSCALL_ARG3_OFFSET PT_OFFSET(EDX)
-#define PT_SYSCALL_ARG4_OFFSET PT_OFFSET(ESI)
-#define PT_SYSCALL_ARG5_OFFSET PT_OFFSET(EDI)
-#define PT_SYSCALL_ARG6_OFFSET PT_OFFSET(EBP)
-
-#define PT_SYSCALL_RET_OFFSET PT_OFFSET(EAX)
-
-#define REGS_SYSCALL_NR EAX /* This is used before a system call */
-#define REGS_SYSCALL_ARG1 EBX
-#define REGS_SYSCALL_ARG2 ECX
-#define REGS_SYSCALL_ARG3 EDX
-#define REGS_SYSCALL_ARG4 ESI
-#define REGS_SYSCALL_ARG5 EDI
-#define REGS_SYSCALL_ARG6 EBP
-
-#define REGS_IP_INDEX EIP
-#define REGS_SP_INDEX UESP
-
-#define PT_IP_OFFSET PT_OFFSET(EIP)
-#define PT_IP(regs) ((regs)[EIP])
-#define PT_SP_OFFSET PT_OFFSET(UESP)
-#define PT_SP(regs) ((regs)[UESP])
-
-#define FP_SIZE ((HOST_FPX_SIZE > HOST_FP_SIZE) ? HOST_FPX_SIZE : HOST_FP_SIZE)
-
-#ifndef FRAME_SIZE
-#define FRAME_SIZE (17)
-#endif
-
-#endif
diff --git a/arch/um/sys-i386/shared/sysdep/sc.h b/arch/um/sys-i386/shared/sysdep/sc.h
deleted file mode 100644
index c57d178..0000000
--- a/arch/um/sys-i386/shared/sysdep/sc.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef __SYSDEP_I386_SC_H
-#define __SYSDEP_I386_SC_H
-
-#include <user_constants.h>
-
-#define SC_OFFSET(sc, field) \
-	*((unsigned long *) &(((char *) (sc))[HOST_##field]))
-#define SC_FP_OFFSET(sc, field) \
-	*((unsigned long *) &(((char *) (SC_FPSTATE(sc)))[HOST_##field]))
-#define SC_FP_OFFSET_PTR(sc, field, type) \
-	((type *) &(((char *) (SC_FPSTATE(sc)))[HOST_##field]))
-
-#define SC_IP(sc) SC_OFFSET(sc, SC_IP)
-#define SC_SP(sc) SC_OFFSET(sc, SC_SP)
-#define SC_FS(sc) SC_OFFSET(sc, SC_FS)
-#define SC_GS(sc) SC_OFFSET(sc, SC_GS)
-#define SC_DS(sc) SC_OFFSET(sc, SC_DS)
-#define SC_ES(sc) SC_OFFSET(sc, SC_ES)
-#define SC_SS(sc) SC_OFFSET(sc, SC_SS)
-#define SC_CS(sc) SC_OFFSET(sc, SC_CS)
-#define SC_EFLAGS(sc) SC_OFFSET(sc, SC_EFLAGS)
-#define SC_EAX(sc) SC_OFFSET(sc, SC_EAX)
-#define SC_EBX(sc) SC_OFFSET(sc, SC_EBX)
-#define SC_ECX(sc) SC_OFFSET(sc, SC_ECX)
-#define SC_EDX(sc) SC_OFFSET(sc, SC_EDX)
-#define SC_EDI(sc) SC_OFFSET(sc, SC_EDI)
-#define SC_ESI(sc) SC_OFFSET(sc, SC_ESI)
-#define SC_EBP(sc) SC_OFFSET(sc, SC_EBP)
-#define SC_TRAPNO(sc) SC_OFFSET(sc, SC_TRAPNO)
-#define SC_ERR(sc) SC_OFFSET(sc, SC_ERR)
-#define SC_CR2(sc) SC_OFFSET(sc, SC_CR2)
-#define SC_FPSTATE(sc) SC_OFFSET(sc, SC_FPSTATE)
-#define SC_SIGMASK(sc) SC_OFFSET(sc, SC_SIGMASK)
-#define SC_FP_CW(sc) SC_FP_OFFSET(sc, SC_FP_CW)
-#define SC_FP_SW(sc) SC_FP_OFFSET(sc, SC_FP_SW)
-#define SC_FP_TAG(sc) SC_FP_OFFSET(sc, SC_FP_TAG)
-#define SC_FP_IPOFF(sc) SC_FP_OFFSET(sc, SC_FP_IPOFF)
-#define SC_FP_CSSEL(sc) SC_FP_OFFSET(sc, SC_FP_CSSEL)
-#define SC_FP_DATAOFF(sc) SC_FP_OFFSET(sc, SC_FP_DATAOFF)
-#define SC_FP_DATASEL(sc) SC_FP_OFFSET(sc, SC_FP_DATASEL)
-#define SC_FP_ST(sc) SC_FP_OFFSET_PTR(sc, SC_FP_ST, struct _fpstate)
-#define SC_FXSR_ENV(sc) SC_FP_OFFSET_PTR(sc, SC_FXSR_ENV, void)
-
-#endif
diff --git a/arch/um/sys-i386/shared/sysdep/sigcontext.h b/arch/um/sys-i386/shared/sysdep/sigcontext.h
deleted file mode 100644
index f583c87..0000000
--- a/arch/um/sys-i386/shared/sysdep/sigcontext.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* 
- * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYS_SIGCONTEXT_I386_H
-#define __SYS_SIGCONTEXT_I386_H
-
-#include "sysdep/sc.h"
-
-#define IP_RESTART_SYSCALL(ip) ((ip) -= 2)
-
-#define GET_FAULTINFO_FROM_SC(fi, sc) \
-	{ \
-		(fi).cr2 = SC_CR2(sc); \
-		(fi).error_code = SC_ERR(sc); \
-		(fi).trap_no = SC_TRAPNO(sc); \
-	}
-
-/* This is Page Fault */
-#define SEGV_IS_FIXABLE(fi)	((fi)->trap_no == 14)
-
-/* SKAS3 has no trap_no on i386, but get_skas_faultinfo() sets it to 0. */
-#define SEGV_MAYBE_FIXABLE(fi)	((fi)->trap_no == 0 && ptrace_faultinfo)
-
-#endif
diff --git a/arch/um/sys-i386/shared/sysdep/skas_ptrace.h b/arch/um/sys-i386/shared/sysdep/skas_ptrace.h
deleted file mode 100644
index e27b8a7..0000000
--- a/arch/um/sys-i386/shared/sysdep/skas_ptrace.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_I386_SKAS_PTRACE_H
-#define __SYSDEP_I386_SKAS_PTRACE_H
-
-struct ptrace_faultinfo {
-        int is_write;
-        unsigned long addr;
-};
-
-struct ptrace_ldt {
-        int func;
-        void *ptr;
-        unsigned long bytecount;
-};
-
-#define PTRACE_LDT 54
-
-#endif
diff --git a/arch/um/sys-i386/shared/sysdep/stub.h b/arch/um/sys-i386/shared/sysdep/stub.h
deleted file mode 100644
index 977dedd..0000000
--- a/arch/um/sys-i386/shared/sysdep/stub.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_STUB_H
-#define __SYSDEP_STUB_H
-
-#include <sys/mman.h>
-#include <asm/ptrace.h>
-#include <asm/unistd.h>
-#include "as-layout.h"
-#include "stub-data.h"
-#include "kern_constants.h"
-
-extern void stub_segv_handler(int sig);
-extern void stub_clone_handler(void);
-
-#define STUB_SYSCALL_RET EAX
-#define STUB_MMAP_NR __NR_mmap2
-#define MMAP_OFFSET(o) ((o) >> UM_KERN_PAGE_SHIFT)
-
-static inline long stub_syscall0(long syscall)
-{
-	long ret;
-
-	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall));
-
-	return ret;
-}
-
-static inline long stub_syscall1(long syscall, long arg1)
-{
-	long ret;
-
-	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1));
-
-	return ret;
-}
-
-static inline long stub_syscall2(long syscall, long arg1, long arg2)
-{
-	long ret;
-
-	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
-			"c" (arg2));
-
-	return ret;
-}
-
-static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3)
-{
-	long ret;
-
-	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
-			"c" (arg2), "d" (arg3));
-
-	return ret;
-}
-
-static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3,
-				 long arg4)
-{
-	long ret;
-
-	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
-			"c" (arg2), "d" (arg3), "S" (arg4));
-
-	return ret;
-}
-
-static inline long stub_syscall5(long syscall, long arg1, long arg2, long arg3,
-				 long arg4, long arg5)
-{
-	long ret;
-
-	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
-			"c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5));
-
-	return ret;
-}
-
-static inline void trap_myself(void)
-{
-	__asm("int3");
-}
-
-static inline void remap_stack(int fd, unsigned long offset)
-{
-	__asm__ volatile ("movl %%eax,%%ebp ; movl %0,%%eax ; int $0x80 ;"
-			  "movl %7, %%ebx ; movl %%eax, (%%ebx)"
-			  : : "g" (STUB_MMAP_NR), "b" (STUB_DATA),
-			    "c" (UM_KERN_PAGE_SIZE),
-			    "d" (PROT_READ | PROT_WRITE),
-			    "S" (MAP_FIXED | MAP_SHARED), "D" (fd),
-			    "a" (offset),
-			    "i" (&((struct stub_data *) STUB_DATA)->err)
-			  : "memory");
-}
-
-#endif
diff --git a/arch/um/sys-i386/shared/sysdep/syscalls.h b/arch/um/sys-i386/shared/sysdep/syscalls.h
deleted file mode 100644
index 05cb796..0000000
--- a/arch/um/sys-i386/shared/sysdep/syscalls.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* 
- * Copyright (C) 2000 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include "asm/unistd.h"
-#include "sysdep/ptrace.h"
-
-typedef long syscall_handler_t(struct pt_regs);
-
-/* Not declared on x86, incompatible declarations on x86_64, so these have
- * to go here rather than in sys_call_table.c
- */
-extern syscall_handler_t sys_rt_sigaction;
-
-extern syscall_handler_t *sys_call_table[];
-
-#define EXECUTE_SYSCALL(syscall, regs) \
-	((long (*)(struct syscall_args)) \
-	 (*sys_call_table[syscall]))(SYSCALL_ARGS(&regs->regs))
diff --git a/arch/um/sys-i386/shared/sysdep/system.h b/arch/um/sys-i386/shared/sysdep/system.h
deleted file mode 100644
index d1b93c4..0000000
--- a/arch/um/sys-i386/shared/sysdep/system.h
+++ /dev/null
@@ -1,132 +0,0 @@
-#ifndef _ASM_X86_SYSTEM_H_
-#define _ASM_X86_SYSTEM_H_
-
-#include <asm/asm.h>
-#include <asm/segment.h>
-#include <asm/cpufeature.h>
-#include <asm/cmpxchg.h>
-#include <asm/nops.h>
-
-#include <linux/kernel.h>
-#include <linux/irqflags.h>
-
-/* entries in ARCH_DLINFO: */
-#ifdef CONFIG_IA32_EMULATION
-# define AT_VECTOR_SIZE_ARCH 2
-#else
-# define AT_VECTOR_SIZE_ARCH 1
-#endif
-
-extern unsigned long arch_align_stack(unsigned long sp);
-
-void default_idle(void);
-
-/*
- * Force strict CPU ordering.
- * And yes, this is required on UP too when we're talking
- * to devices.
- */
-#ifdef CONFIG_X86_32
-/*
- * Some non-Intel clones support out of order store. wmb() ceases to be a
- * nop for these.
- */
-#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
-#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
-#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
-#else
-#define mb() 	asm volatile("mfence":::"memory")
-#define rmb()	asm volatile("lfence":::"memory")
-#define wmb()	asm volatile("sfence" ::: "memory")
-#endif
-
-/**
- * read_barrier_depends - Flush all pending reads that subsequents reads
- * depend on.
- *
- * No data-dependent reads from memory-like regions are ever reordered
- * over this barrier.  All reads preceding this primitive are guaranteed
- * to access memory (but not necessarily other CPUs' caches) before any
- * reads following this primitive that depend on the data return by
- * any of the preceding reads.  This primitive is much lighter weight than
- * rmb() on most CPUs, and is never heavier weight than is
- * rmb().
- *
- * These ordering constraints are respected by both the local CPU
- * and the compiler.
- *
- * Ordering is not guaranteed by anything other than these primitives,
- * not even by data dependencies.  See the documentation for
- * memory_barrier() for examples and URLs to more information.
- *
- * For example, the following code would force ordering (the initial
- * value of "a" is zero, "b" is one, and "p" is "&a"):
- *
- * <programlisting>
- *	CPU 0				CPU 1
- *
- *	b = 2;
- *	memory_barrier();
- *	p = &b;				q = p;
- *					read_barrier_depends();
- *					d = *q;
- * </programlisting>
- *
- * because the read of "*q" depends on the read of "p" and these
- * two reads are separated by a read_barrier_depends().  However,
- * the following code, with the same initial values for "a" and "b":
- *
- * <programlisting>
- *	CPU 0				CPU 1
- *
- *	a = 2;
- *	memory_barrier();
- *	b = 3;				y = b;
- *					read_barrier_depends();
- *					x = a;
- * </programlisting>
- *
- * does not enforce ordering, since there is no data dependency between
- * the read of "a" and the read of "b".  Therefore, on some CPUs, such
- * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
- * in cases like this where there are no data dependencies.
- **/
-
-#define read_barrier_depends()	do { } while (0)
-
-#ifdef CONFIG_SMP
-#define smp_mb()	mb()
-#ifdef CONFIG_X86_PPRO_FENCE
-# define smp_rmb()	rmb()
-#else
-# define smp_rmb()	barrier()
-#endif
-#ifdef CONFIG_X86_OOSTORE
-# define smp_wmb() 	wmb()
-#else
-# define smp_wmb()	barrier()
-#endif
-#define smp_read_barrier_depends()	read_barrier_depends()
-#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
-#else
-#define smp_mb()	barrier()
-#define smp_rmb()	barrier()
-#define smp_wmb()	barrier()
-#define smp_read_barrier_depends()	do { } while (0)
-#define set_mb(var, value) do { var = value; barrier(); } while (0)
-#endif
-
-/*
- * Stop RDTSC speculation. This is needed when you need to use RDTSC
- * (or get_cycles or vread that possibly accesses the TSC) in a defined
- * code region.
- *
- * (Could use an alternative three way for this if there was one.)
- */
-static inline void rdtsc_barrier(void)
-{
-	alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC);
-	alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
-}
-
-#endif
diff --git a/arch/um/sys-i386/shared/sysdep/tls.h b/arch/um/sys-i386/shared/sysdep/tls.h
deleted file mode 100644
index 3455075..0000000
--- a/arch/um/sys-i386/shared/sysdep/tls.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef _SYSDEP_TLS_H
-#define _SYSDEP_TLS_H
-
-# ifndef __KERNEL__
-
-/* Change name to avoid conflicts with the original one from <asm/ldt.h>, which
- * may be named user_desc (but in 2.4 and in header matching its API was named
- * modify_ldt_ldt_s). */
-
-typedef struct um_dup_user_desc {
-	unsigned int  entry_number;
-	unsigned int  base_addr;
-	unsigned int  limit;
-	unsigned int  seg_32bit:1;
-	unsigned int  contents:2;
-	unsigned int  read_exec_only:1;
-	unsigned int  limit_in_pages:1;
-	unsigned int  seg_not_present:1;
-	unsigned int  useable:1;
-} user_desc_t;
-
-# else /* __KERNEL__ */
-
-#  include <ldt.h>
-typedef struct user_desc user_desc_t;
-
-# endif /* __KERNEL__ */
-
-#define GDT_ENTRY_TLS_MIN_I386 6
-#define GDT_ENTRY_TLS_MIN_X86_64 12
-
-#endif /* _SYSDEP_TLS_H */
diff --git a/arch/um/sys-i386/shared/sysdep/vm-flags.h b/arch/um/sys-i386/shared/sysdep/vm-flags.h
deleted file mode 100644
index e0d24c5..0000000
--- a/arch/um/sys-i386/shared/sysdep/vm-flags.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#ifndef __VM_FLAGS_I386_H
-#define __VM_FLAGS_I386_H
-
-#define VM_DATA_DEFAULT_FLAGS \
-	(VM_READ | VM_WRITE | \
-	((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
-		 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
-
-#endif
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
deleted file mode 100644
index 89a4662..0000000
--- a/arch/um/sys-i386/signal.c
+++ /dev/null
@@ -1,508 +0,0 @@
-/*
- * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <linux/ptrace.h>
-#include <asm/unistd.h>
-#include <asm/uaccess.h>
-#include <asm/ucontext.h>
-#include "frame_kern.h"
-#include "skas.h"
-
-void copy_sc(struct uml_pt_regs *regs, void *from)
-{
-	struct sigcontext *sc = from;
-
-	REGS_GS(regs->gp) = sc->gs;
-	REGS_FS(regs->gp) = sc->fs;
-	REGS_ES(regs->gp) = sc->es;
-	REGS_DS(regs->gp) = sc->ds;
-	REGS_EDI(regs->gp) = sc->di;
-	REGS_ESI(regs->gp) = sc->si;
-	REGS_EBP(regs->gp) = sc->bp;
-	REGS_SP(regs->gp) = sc->sp;
-	REGS_EBX(regs->gp) = sc->bx;
-	REGS_EDX(regs->gp) = sc->dx;
-	REGS_ECX(regs->gp) = sc->cx;
-	REGS_EAX(regs->gp) = sc->ax;
-	REGS_IP(regs->gp) = sc->ip;
-	REGS_CS(regs->gp) = sc->cs;
-	REGS_EFLAGS(regs->gp) = sc->flags;
-	REGS_SS(regs->gp) = sc->ss;
-}
-
-/*
- * FPU tag word conversions.
- */
-
-static inline unsigned short twd_i387_to_fxsr(unsigned short twd)
-{
-	unsigned int tmp; /* to avoid 16 bit prefixes in the code */
-
-	/* Transform each pair of bits into 01 (valid) or 00 (empty) */
-	tmp = ~twd;
-	tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */
-	/* and move the valid bits to the lower byte. */
-	tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */
-	tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */
-	tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */
-	return tmp;
-}
-
-static inline unsigned long twd_fxsr_to_i387(struct user_fxsr_struct *fxsave)
-{
-	struct _fpxreg *st = NULL;
-	unsigned long twd = (unsigned long) fxsave->twd;
-	unsigned long tag;
-	unsigned long ret = 0xffff0000;
-	int i;
-
-#define FPREG_ADDR(f, n)	((char *)&(f)->st_space + (n) * 16)
-
-	for (i = 0; i < 8; i++) {
-		if (twd & 0x1) {
-			st = (struct _fpxreg *) FPREG_ADDR(fxsave, i);
-
-			switch (st->exponent & 0x7fff) {
-			case 0x7fff:
-				tag = 2;		/* Special */
-				break;
-			case 0x0000:
-				if ( !st->significand[0] &&
-				     !st->significand[1] &&
-				     !st->significand[2] &&
-				     !st->significand[3] ) {
-					tag = 1;	/* Zero */
-				} else {
-					tag = 2;	/* Special */
-				}
-				break;
-			default:
-				if (st->significand[3] & 0x8000) {
-					tag = 0;	/* Valid */
-				} else {
-					tag = 2;	/* Special */
-				}
-				break;
-			}
-		} else {
-			tag = 3;			/* Empty */
-		}
-		ret |= (tag << (2 * i));
-		twd = twd >> 1;
-	}
-	return ret;
-}
-
-static int convert_fxsr_to_user(struct _fpstate __user *buf,
-				struct user_fxsr_struct *fxsave)
-{
-	unsigned long env[7];
-	struct _fpreg __user *to;
-	struct _fpxreg *from;
-	int i;
-
-	env[0] = (unsigned long)fxsave->cwd | 0xffff0000ul;
-	env[1] = (unsigned long)fxsave->swd | 0xffff0000ul;
-	env[2] = twd_fxsr_to_i387(fxsave);
-	env[3] = fxsave->fip;
-	env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16);
-	env[5] = fxsave->foo;
-	env[6] = fxsave->fos;
-
-	if (__copy_to_user(buf, env, 7 * sizeof(unsigned long)))
-		return 1;
-
-	to = &buf->_st[0];
-	from = (struct _fpxreg *) &fxsave->st_space[0];
-	for (i = 0; i < 8; i++, to++, from++) {
-		unsigned long __user *t = (unsigned long __user *)to;
-		unsigned long *f = (unsigned long *)from;
-
-		if (__put_user(*f, t) ||
-				__put_user(*(f + 1), t + 1) ||
-				__put_user(from->exponent, &to->exponent))
-			return 1;
-	}
-	return 0;
-}
-
-static int convert_fxsr_from_user(struct user_fxsr_struct *fxsave,
-				  struct _fpstate __user *buf)
-{
-	unsigned long env[7];
-	struct _fpxreg *to;
-	struct _fpreg __user *from;
-	int i;
-
-	if (copy_from_user( env, buf, 7 * sizeof(long)))
-		return 1;
-
-	fxsave->cwd = (unsigned short)(env[0] & 0xffff);
-	fxsave->swd = (unsigned short)(env[1] & 0xffff);
-	fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff));
-	fxsave->fip = env[3];
-	fxsave->fop = (unsigned short)((env[4] & 0xffff0000ul) >> 16);
-	fxsave->fcs = (env[4] & 0xffff);
-	fxsave->foo = env[5];
-	fxsave->fos = env[6];
-
-	to = (struct _fpxreg *) &fxsave->st_space[0];
-	from = &buf->_st[0];
-	for (i = 0; i < 8; i++, to++, from++) {
-		unsigned long *t = (unsigned long *)to;
-		unsigned long __user *f = (unsigned long __user *)from;
-
-		if (__get_user(*t, f) ||
-		    __get_user(*(t + 1), f + 1) ||
-		    __get_user(to->exponent, &from->exponent))
-			return 1;
-	}
-	return 0;
-}
-
-extern int have_fpx_regs;
-
-static int copy_sc_from_user(struct pt_regs *regs,
-			     struct sigcontext __user *from)
-{
-	struct sigcontext sc;
-	int err, pid;
-
-	err = copy_from_user(&sc, from, sizeof(sc));
-	if (err)
-		return err;
-
-	pid = userspace_pid[current_thread_info()->cpu];
-	copy_sc(&regs->regs, &sc);
-	if (have_fpx_regs) {
-		struct user_fxsr_struct fpx;
-
-		err = copy_from_user(&fpx,
-			&((struct _fpstate __user *)sc.fpstate)->_fxsr_env[0],
-				     sizeof(struct user_fxsr_struct));
-		if (err)
-			return 1;
-
-		err = convert_fxsr_from_user(&fpx, sc.fpstate);
-		if (err)
-			return 1;
-
-		err = restore_fpx_registers(pid, (unsigned long *) &fpx);
-		if (err < 0) {
-			printk(KERN_ERR "copy_sc_from_user - "
-			       "restore_fpx_registers failed, errno = %d\n",
-			       -err);
-			return 1;
-		}
-	}
-	else {
-		struct user_i387_struct fp;
-
-		err = copy_from_user(&fp, sc.fpstate,
-				     sizeof(struct user_i387_struct));
-		if (err)
-			return 1;
-
-		err = restore_fp_registers(pid, (unsigned long *) &fp);
-		if (err < 0) {
-			printk(KERN_ERR "copy_sc_from_user - "
-			       "restore_fp_registers failed, errno = %d\n",
-			       -err);
-			return 1;
-		}
-	}
-
-	return 0;
-}
-
-static int copy_sc_to_user(struct sigcontext __user *to,
-			   struct _fpstate __user *to_fp, struct pt_regs *regs,
-			   unsigned long sp)
-{
-	struct sigcontext sc;
-	struct faultinfo * fi = &current->thread.arch.faultinfo;
-	int err, pid;
-
-	sc.gs = REGS_GS(regs->regs.gp);
-	sc.fs = REGS_FS(regs->regs.gp);
-	sc.es = REGS_ES(regs->regs.gp);
-	sc.ds = REGS_DS(regs->regs.gp);
-	sc.di = REGS_EDI(regs->regs.gp);
-	sc.si = REGS_ESI(regs->regs.gp);
-	sc.bp = REGS_EBP(regs->regs.gp);
-	sc.sp = sp;
-	sc.bx = REGS_EBX(regs->regs.gp);
-	sc.dx = REGS_EDX(regs->regs.gp);
-	sc.cx = REGS_ECX(regs->regs.gp);
-	sc.ax = REGS_EAX(regs->regs.gp);
-	sc.ip = REGS_IP(regs->regs.gp);
-	sc.cs = REGS_CS(regs->regs.gp);
-	sc.flags = REGS_EFLAGS(regs->regs.gp);
-	sc.sp_at_signal = regs->regs.gp[UESP];
-	sc.ss = regs->regs.gp[SS];
-	sc.cr2 = fi->cr2;
-	sc.err = fi->error_code;
-	sc.trapno = fi->trap_no;
-
-	to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1));
-	sc.fpstate = to_fp;
-
-	pid = userspace_pid[current_thread_info()->cpu];
-	if (have_fpx_regs) {
-		struct user_fxsr_struct fpx;
-
-		err = save_fpx_registers(pid, (unsigned long *) &fpx);
-		if (err < 0){
-			printk(KERN_ERR "copy_sc_to_user - save_fpx_registers "
-			       "failed, errno = %d\n", err);
-			return 1;
-		}
-
-		err = convert_fxsr_to_user(to_fp, &fpx);
-		if (err)
-			return 1;
-
-		err |= __put_user(fpx.swd, &to_fp->status);
-		err |= __put_user(X86_FXSR_MAGIC, &to_fp->magic);
-		if (err)
-			return 1;
-
-		if (copy_to_user(&to_fp->_fxsr_env[0], &fpx,
-				 sizeof(struct user_fxsr_struct)))
-			return 1;
-	}
-	else {
-		struct user_i387_struct fp;
-
-		err = save_fp_registers(pid, (unsigned long *) &fp);
-		if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct)))
-			return 1;
-	}
-
-	return copy_to_user(to, &sc, sizeof(sc));
-}
-
-static int copy_ucontext_to_user(struct ucontext __user *uc,
-				 struct _fpstate __user *fp, sigset_t *set,
-				 unsigned long sp)
-{
-	int err = 0;
-
-	err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp);
-	err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags);
-	err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size);
-	err |= copy_sc_to_user(&uc->uc_mcontext, fp, &current->thread.regs, sp);
-	err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set));
-	return err;
-}
-
-struct sigframe
-{
-	char __user *pretcode;
-	int sig;
-	struct sigcontext sc;
-	struct _fpstate fpstate;
-	unsigned long extramask[_NSIG_WORDS-1];
-	char retcode[8];
-};
-
-struct rt_sigframe
-{
-	char __user *pretcode;
-	int sig;
-	struct siginfo __user *pinfo;
-	void __user *puc;
-	struct siginfo info;
-	struct ucontext uc;
-	struct _fpstate fpstate;
-	char retcode[8];
-};
-
-int setup_signal_stack_sc(unsigned long stack_top, int sig,
-			  struct k_sigaction *ka, struct pt_regs *regs,
-			  sigset_t *mask)
-{
-	struct sigframe __user *frame;
-	void __user *restorer;
-	unsigned long save_sp = PT_REGS_SP(regs);
-	int err = 0;
-
-	/* This is the same calculation as i386 - ((sp + 4) & 15) == 0 */
-	stack_top = ((stack_top + 4) & -16UL) - 4;
-	frame = (struct sigframe __user *) stack_top - 1;
-	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		return 1;
-
-	restorer = frame->retcode;
-	if (ka->sa.sa_flags & SA_RESTORER)
-		restorer = ka->sa.sa_restorer;
-
-	/* Update SP now because the page fault handler refuses to extend
-	 * the stack if the faulting address is too far below the current
-	 * SP, which frame now certainly is.  If there's an error, the original
-	 * value is restored on the way out.
-	 * When writing the sigcontext to the stack, we have to write the
-	 * original value, so that's passed to copy_sc_to_user, which does
-	 * the right thing with it.
-	 */
-	PT_REGS_SP(regs) = (unsigned long) frame;
-
-	err |= __put_user(restorer, &frame->pretcode);
-	err |= __put_user(sig, &frame->sig);
-	err |= copy_sc_to_user(&frame->sc, NULL, regs, save_sp);
-	err |= __put_user(mask->sig[0], &frame->sc.oldmask);
-	if (_NSIG_WORDS > 1)
-		err |= __copy_to_user(&frame->extramask, &mask->sig[1],
-				      sizeof(frame->extramask));
-
-	/*
-	 * This is popl %eax ; movl $,%eax ; int $0x80
-	 *
-	 * WE DO NOT USE IT ANY MORE! It's only left here for historical
-	 * reasons and because gdb uses it as a signature to notice
-	 * signal handler stack frames.
-	 */
-	err |= __put_user(0xb858, (short __user *)(frame->retcode+0));
-	err |= __put_user(__NR_sigreturn, (int __user *)(frame->retcode+2));
-	err |= __put_user(0x80cd, (short __user *)(frame->retcode+6));
-
-	if (err)
-		goto err;
-
-	PT_REGS_SP(regs) = (unsigned long) frame;
-	PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
-	PT_REGS_EAX(regs) = (unsigned long) sig;
-	PT_REGS_EDX(regs) = (unsigned long) 0;
-	PT_REGS_ECX(regs) = (unsigned long) 0;
-
-	if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
-		ptrace_notify(SIGTRAP);
-	return 0;
-
-err:
-	PT_REGS_SP(regs) = save_sp;
-	return err;
-}
-
-int setup_signal_stack_si(unsigned long stack_top, int sig,
-			  struct k_sigaction *ka, struct pt_regs *regs,
-			  siginfo_t *info, sigset_t *mask)
-{
-	struct rt_sigframe __user *frame;
-	void __user *restorer;
-	unsigned long save_sp = PT_REGS_SP(regs);
-	int err = 0;
-
-	stack_top &= -8UL;
-	frame = (struct rt_sigframe __user *) stack_top - 1;
-	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		return 1;
-
-	restorer = frame->retcode;
-	if (ka->sa.sa_flags & SA_RESTORER)
-		restorer = ka->sa.sa_restorer;
-
-	/* See comment above about why this is here */
-	PT_REGS_SP(regs) = (unsigned long) frame;
-
-	err |= __put_user(restorer, &frame->pretcode);
-	err |= __put_user(sig, &frame->sig);
-	err |= __put_user(&frame->info, &frame->pinfo);
-	err |= __put_user(&frame->uc, &frame->puc);
-	err |= copy_siginfo_to_user(&frame->info, info);
-	err |= copy_ucontext_to_user(&frame->uc, &frame->fpstate, mask,
-				     save_sp);
-
-	/*
-	 * This is movl $,%eax ; int $0x80
-	 *
-	 * WE DO NOT USE IT ANY MORE! It's only left here for historical
-	 * reasons and because gdb uses it as a signature to notice
-	 * signal handler stack frames.
-	 */
-	err |= __put_user(0xb8, (char __user *)(frame->retcode+0));
-	err |= __put_user(__NR_rt_sigreturn, (int __user *)(frame->retcode+1));
-	err |= __put_user(0x80cd, (short __user *)(frame->retcode+5));
-
-	if (err)
-		goto err;
-
-	PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
-	PT_REGS_EAX(regs) = (unsigned long) sig;
-	PT_REGS_EDX(regs) = (unsigned long) &frame->info;
-	PT_REGS_ECX(regs) = (unsigned long) &frame->uc;
-
-	if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
-		ptrace_notify(SIGTRAP);
-	return 0;
-
-err:
-	PT_REGS_SP(regs) = save_sp;
-	return err;
-}
-
-long sys_sigreturn(struct pt_regs regs)
-{
-	unsigned long sp = PT_REGS_SP(&current->thread.regs);
-	struct sigframe __user *frame = (struct sigframe __user *)(sp - 8);
-	sigset_t set;
-	struct sigcontext __user *sc = &frame->sc;
-	unsigned long __user *oldmask = &sc->oldmask;
-	unsigned long __user *extramask = frame->extramask;
-	int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
-
-	if (copy_from_user(&set.sig[0], oldmask, sizeof(set.sig[0])) ||
-	    copy_from_user(&set.sig[1], extramask, sig_size))
-		goto segfault;
-
-	sigdelsetmask(&set, ~_BLOCKABLE);
-
-	spin_lock_irq(&current->sighand->siglock);
-	current->blocked = set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	if (copy_sc_from_user(&current->thread.regs, sc))
-		goto segfault;
-
-	/* Avoid ERESTART handling */
-	PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
-	return PT_REGS_SYSCALL_RET(&current->thread.regs);
-
- segfault:
-	force_sig(SIGSEGV, current);
-	return 0;
-}
-
-long sys_rt_sigreturn(struct pt_regs regs)
-{
-	unsigned long sp = PT_REGS_SP(&current->thread.regs);
-	struct rt_sigframe __user *frame =
-		(struct rt_sigframe __user *) (sp - 4);
-	sigset_t set;
-	struct ucontext __user *uc = &frame->uc;
-	int sig_size = _NSIG_WORDS * sizeof(unsigned long);
-
-	if (copy_from_user(&set, &uc->uc_sigmask, sig_size))
-		goto segfault;
-
-	sigdelsetmask(&set, ~_BLOCKABLE);
-
-	spin_lock_irq(&current->sighand->siglock);
-	current->blocked = set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	if (copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext))
-		goto segfault;
-
-	/* Avoid ERESTART handling */
-	PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
-	return PT_REGS_SYSCALL_RET(&current->thread.regs);
-
- segfault:
-	force_sig(SIGSEGV, current);
-	return 0;
-}
diff --git a/arch/um/sys-i386/stub.S b/arch/um/sys-i386/stub.S
deleted file mode 100644
index 54a36ec..0000000
--- a/arch/um/sys-i386/stub.S
+++ /dev/null
@@ -1,51 +0,0 @@
-#include "as-layout.h"
-
-	.globl syscall_stub
-.section .__syscall_stub, "ax"
-
-	.globl batch_syscall_stub
-batch_syscall_stub:
-	/* load pointer to first operation */
-	mov	$(STUB_DATA+8), %esp
-
-again:
-	/* load length of additional data */
-	mov	0x0(%esp), %eax
-
-	/* if(length == 0) : end of list */
-	/* write possible 0 to header */
-	mov	%eax, STUB_DATA+4
-	cmpl	$0, %eax
-	jz	done
-
-	/* save current pointer */
-	mov	%esp, STUB_DATA+4
-
-	/* skip additional data */
-	add	%eax, %esp
-
-	/* load syscall-# */
-	pop	%eax
-
-	/* load syscall params */
-	pop	%ebx
-	pop	%ecx
-	pop	%edx
-	pop	%esi
- 	pop	%edi
-	pop	%ebp
-
-	/* execute syscall */
-	int	$0x80
-
-	/* check return value */
-	pop	%ebx
-	cmp	%ebx, %eax
-	je	again
-
-done:
-	/* save return value */
-	mov	%eax, STUB_DATA
-
-	/* stop */
-	int3
diff --git a/arch/um/sys-i386/stub_segv.c b/arch/um/sys-i386/stub_segv.c
deleted file mode 100644
index 28ccf73..0000000
--- a/arch/um/sys-i386/stub_segv.c
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include "sysdep/stub.h"
-#include "sysdep/sigcontext.h"
-
-void __attribute__ ((__section__ (".__syscall_stub")))
-stub_segv_handler(int sig)
-{
-	struct sigcontext *sc = (struct sigcontext *) (&sig + 1);
-
-	GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA), sc);
-
-	trap_myself();
-}
diff --git a/arch/um/sys-i386/sys_call_table.S b/arch/um/sys-i386/sys_call_table.S
deleted file mode 100644
index de27407..0000000
--- a/arch/um/sys-i386/sys_call_table.S
+++ /dev/null
@@ -1,28 +0,0 @@
-#include <linux/linkage.h>
-/* Steal i386 syscall table for our purposes, but with some slight changes.*/
-
-#define sys_iopl sys_ni_syscall
-#define sys_ioperm sys_ni_syscall
-
-#define sys_vm86old sys_ni_syscall
-#define sys_vm86 sys_ni_syscall
-
-#define old_mmap sys_old_mmap
-
-#define ptregs_fork sys_fork
-#define ptregs_execve sys_execve
-#define ptregs_iopl sys_iopl
-#define ptregs_vm86old sys_vm86old
-#define ptregs_sigreturn sys_sigreturn
-#define ptregs_clone sys_clone
-#define ptregs_vm86 sys_vm86
-#define ptregs_rt_sigreturn sys_rt_sigreturn
-#define ptregs_sigaltstack sys_sigaltstack
-#define ptregs_vfork sys_vfork
-
-.section .rodata,"a"
-
-#include "../../x86/kernel/syscall_table_32.S"
-
-ENTRY(syscall_table_size)
-.long .-sys_call_table
diff --git a/arch/um/sys-i386/syscalls.c b/arch/um/sys-i386/syscalls.c
deleted file mode 100644
index 70ca357..0000000
--- a/arch/um/sys-i386/syscalls.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/* 
- * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#include "linux/sched.h"
-#include "linux/shm.h"
-#include "linux/ipc.h"
-#include "linux/syscalls.h"
-#include "asm/mman.h"
-#include "asm/uaccess.h"
-#include "asm/unistd.h"
-
-/*
- * The prototype on i386 is:
- *
- *     int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls, int * child_tidptr)
- *
- * and the "newtls" arg. on i386 is read by copy_thread directly from the
- * register saved on the stack.
- */
-long sys_clone(unsigned long clone_flags, unsigned long newsp,
-	       int __user *parent_tid, void *newtls, int __user *child_tid)
-{
-	long ret;
-
-	if (!newsp)
-		newsp = UPT_SP(&current->thread.regs.regs);
-
-	current->thread.forking = 1;
-	ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
-		      child_tid);
-	current->thread.forking = 0;
-	return ret;
-}
-
-long sys_sigaction(int sig, const struct old_sigaction __user *act,
-			 struct old_sigaction __user *oact)
-{
-	struct k_sigaction new_ka, old_ka;
-	int ret;
-
-	if (act) {
-		old_sigset_t mask;
-		if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
-		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
-		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
-			return -EFAULT;
-		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
-		__get_user(mask, &act->sa_mask);
-		siginitset(&new_ka.sa.sa_mask, mask);
-	}
-
-	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
-
-	if (!ret && oact) {
-		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
-		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
-		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
-			return -EFAULT;
-		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
-		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
-	}
-
-	return ret;
-}
diff --git a/arch/um/sys-i386/sysrq.c b/arch/um/sys-i386/sysrq.c
deleted file mode 100644
index 171b3e9..0000000
--- a/arch/um/sys-i386/sysrq.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#include "linux/kernel.h"
-#include "linux/smp.h"
-#include "linux/sched.h"
-#include "linux/kallsyms.h"
-#include "asm/ptrace.h"
-#include "sysrq.h"
-
-/* This is declared by <linux/sched.h> */
-void show_regs(struct pt_regs *regs)
-{
-        printk("\n");
-        printk("EIP: %04lx:[<%08lx>] CPU: %d %s", 
-	       0xffff & PT_REGS_CS(regs), PT_REGS_IP(regs),
-	       smp_processor_id(), print_tainted());
-        if (PT_REGS_CS(regs) & 3)
-                printk(" ESP: %04lx:%08lx", 0xffff & PT_REGS_SS(regs),
-		       PT_REGS_SP(regs));
-        printk(" EFLAGS: %08lx\n    %s\n", PT_REGS_EFLAGS(regs),
-	       print_tainted());
-        printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
-                PT_REGS_EAX(regs), PT_REGS_EBX(regs), 
-	       PT_REGS_ECX(regs), 
-	       PT_REGS_EDX(regs));
-        printk("ESI: %08lx EDI: %08lx EBP: %08lx",
-	       PT_REGS_ESI(regs), PT_REGS_EDI(regs), 
-	       PT_REGS_EBP(regs));
-        printk(" DS: %04lx ES: %04lx\n",
-	       0xffff & PT_REGS_DS(regs), 
-	       0xffff & PT_REGS_ES(regs));
-
-        show_trace(NULL, (unsigned long *) &regs);
-}
-
-/* Copied from i386. */
-static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
-{
-	return	p > (void *)tinfo &&
-		p < (void *)tinfo + THREAD_SIZE - 3;
-}
-
-/* Adapted from i386 (we also print the address we read from). */
-static inline unsigned long print_context_stack(struct thread_info *tinfo,
-				unsigned long *stack, unsigned long ebp)
-{
-	unsigned long addr;
-
-#ifdef CONFIG_FRAME_POINTER
-	while (valid_stack_ptr(tinfo, (void *)ebp)) {
-		addr = *(unsigned long *)(ebp + 4);
-		printk("%08lx:  [<%08lx>]", ebp + 4, addr);
-		print_symbol(" %s", addr);
-		printk("\n");
-		ebp = *(unsigned long *)ebp;
-	}
-#else
-	while (valid_stack_ptr(tinfo, stack)) {
-		addr = *stack;
-		if (__kernel_text_address(addr)) {
-			printk("%08lx:  [<%08lx>]", (unsigned long) stack, addr);
-			print_symbol(" %s", addr);
-			printk("\n");
-		}
-		stack++;
-	}
-#endif
-	return ebp;
-}
-
-void show_trace(struct task_struct* task, unsigned long * stack)
-{
-	unsigned long ebp;
-	struct thread_info *context;
-
-	/* Turn this into BUG_ON if possible. */
-	if (!stack) {
-		stack = (unsigned long*) &stack;
-		printk("show_trace: got NULL stack, implicit assumption task == current");
-		WARN_ON(1);
-	}
-
-	if (!task)
-		task = current;
-
-	if (task != current) {
-		ebp = (unsigned long) KSTK_EBP(task);
-	} else {
-		asm ("movl %%ebp, %0" : "=r" (ebp) : );
-	}
-
-	context = (struct thread_info *)
-		((unsigned long)stack & (~(THREAD_SIZE - 1)));
-	print_context_stack(context, stack, ebp);
-
-	printk("\n");
-}
-
diff --git a/arch/um/sys-i386/tls.c b/arch/um/sys-i386/tls.c
deleted file mode 100644
index c6c7131..0000000
--- a/arch/um/sys-i386/tls.c
+++ /dev/null
@@ -1,396 +0,0 @@
-/*
- * Copyright (C) 2005 Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
- * Licensed under the GPL
- */
-
-#include "linux/percpu.h"
-#include "linux/sched.h"
-#include "asm/uaccess.h"
-#include "os.h"
-#include "skas.h"
-#include "sysdep/tls.h"
-
-/*
- * If needed we can detect when it's uninitialized.
- *
- * These are initialized in an initcall and unchanged thereafter.
- */
-static int host_supports_tls = -1;
-int host_gdt_entry_tls_min;
-
-int do_set_thread_area(struct user_desc *info)
-{
-	int ret;
-	u32 cpu;
-
-	cpu = get_cpu();
-	ret = os_set_thread_area(info, userspace_pid[cpu]);
-	put_cpu();
-
-	if (ret)
-		printk(KERN_ERR "PTRACE_SET_THREAD_AREA failed, err = %d, "
-		       "index = %d\n", ret, info->entry_number);
-
-	return ret;
-}
-
-int do_get_thread_area(struct user_desc *info)
-{
-	int ret;
-	u32 cpu;
-
-	cpu = get_cpu();
-	ret = os_get_thread_area(info, userspace_pid[cpu]);
-	put_cpu();
-
-	if (ret)
-		printk(KERN_ERR "PTRACE_GET_THREAD_AREA failed, err = %d, "
-		       "index = %d\n", ret, info->entry_number);
-
-	return ret;
-}
-
-/*
- * sys_get_thread_area: get a yet unused TLS descriptor index.
- * XXX: Consider leaving one free slot for glibc usage at first place. This must
- * be done here (and by changing GDT_ENTRY_TLS_* macros) and nowhere else.
- *
- * Also, this must be tested when compiling in SKAS mode with dynamic linking
- * and running against NPTL.
- */
-static int get_free_idx(struct task_struct* task)
-{
-	struct thread_struct *t = &task->thread;
-	int idx;
-
-	if (!t->arch.tls_array)
-		return GDT_ENTRY_TLS_MIN;
-
-	for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++)
-		if (!t->arch.tls_array[idx].present)
-			return idx + GDT_ENTRY_TLS_MIN;
-	return -ESRCH;
-}
-
-static inline void clear_user_desc(struct user_desc* info)
-{
-	/* Postcondition: LDT_empty(info) returns true. */
-	memset(info, 0, sizeof(*info));
-
-	/*
-	 * Check the LDT_empty or the i386 sys_get_thread_area code - we obtain
-	 * indeed an empty user_desc.
-	 */
-	info->read_exec_only = 1;
-	info->seg_not_present = 1;
-}
-
-#define O_FORCE 1
-
-static int load_TLS(int flags, struct task_struct *to)
-{
-	int ret = 0;
-	int idx;
-
-	for (idx = GDT_ENTRY_TLS_MIN; idx < GDT_ENTRY_TLS_MAX; idx++) {
-		struct uml_tls_struct* curr =
-			&to->thread.arch.tls_array[idx - GDT_ENTRY_TLS_MIN];
-
-		/*
-		 * Actually, now if it wasn't flushed it gets cleared and
-		 * flushed to the host, which will clear it.
-		 */
-		if (!curr->present) {
-			if (!curr->flushed) {
-				clear_user_desc(&curr->tls);
-				curr->tls.entry_number = idx;
-			} else {
-				WARN_ON(!LDT_empty(&curr->tls));
-				continue;
-			}
-		}
-
-		if (!(flags & O_FORCE) && curr->flushed)
-			continue;
-
-		ret = do_set_thread_area(&curr->tls);
-		if (ret)
-			goto out;
-
-		curr->flushed = 1;
-	}
-out:
-	return ret;
-}
-
-/*
- * Verify if we need to do a flush for the new process, i.e. if there are any
- * present desc's, only if they haven't been flushed.
- */
-static inline int needs_TLS_update(struct task_struct *task)
-{
-	int i;
-	int ret = 0;
-
-	for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) {
-		struct uml_tls_struct* curr =
-			&task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN];
-
-		/*
-		 * Can't test curr->present, we may need to clear a descriptor
-		 * which had a value.
-		 */
-		if (curr->flushed)
-			continue;
-		ret = 1;
-		break;
-	}
-	return ret;
-}
-
-/*
- * On a newly forked process, the TLS descriptors haven't yet been flushed. So
- * we mark them as such and the first switch_to will do the job.
- */
-void clear_flushed_tls(struct task_struct *task)
-{
-	int i;
-
-	for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) {
-		struct uml_tls_struct* curr =
-			&task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN];
-
-		/*
-		 * Still correct to do this, if it wasn't present on the host it
-		 * will remain as flushed as it was.
-		 */
-		if (!curr->present)
-			continue;
-
-		curr->flushed = 0;
-	}
-}
-
-/*
- * In SKAS0 mode, currently, multiple guest threads sharing the same ->mm have a
- * common host process. So this is needed in SKAS0 too.
- *
- * However, if each thread had a different host process (and this was discussed
- * for SMP support) this won't be needed.
- *
- * And this will not need be used when (and if) we'll add support to the host
- * SKAS patch.
- */
-
-int arch_switch_tls(struct task_struct *to)
-{
-	if (!host_supports_tls)
-		return 0;
-
-	/*
-	 * We have no need whatsoever to switch TLS for kernel threads; beyond
-	 * that, that would also result in us calling os_set_thread_area with
-	 * userspace_pid[cpu] == 0, which gives an error.
-	 */
-	if (likely(to->mm))
-		return load_TLS(O_FORCE, to);
-
-	return 0;
-}
-
-static int set_tls_entry(struct task_struct* task, struct user_desc *info,
-			 int idx, int flushed)
-{
-	struct thread_struct *t = &task->thread;
-
-	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
-		return -EINVAL;
-
-	t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].tls = *info;
-	t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].present = 1;
-	t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed = flushed;
-
-	return 0;
-}
-
-int arch_copy_tls(struct task_struct *new)
-{
-	struct user_desc info;
-	int idx, ret = -EFAULT;
-
-	if (copy_from_user(&info,
-			   (void __user *) UPT_ESI(&new->thread.regs.regs),
-			   sizeof(info)))
-		goto out;
-
-	ret = -EINVAL;
-	if (LDT_empty(&info))
-		goto out;
-
-	idx = info.entry_number;
-
-	ret = set_tls_entry(new, &info, idx, 0);
-out:
-	return ret;
-}
-
-/* XXX: use do_get_thread_area to read the host value? I'm not at all sure! */
-static int get_tls_entry(struct task_struct *task, struct user_desc *info,
-			 int idx)
-{
-	struct thread_struct *t = &task->thread;
-
-	if (!t->arch.tls_array)
-		goto clear;
-
-	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
-		return -EINVAL;
-
-	if (!t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].present)
-		goto clear;
-
-	*info = t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].tls;
-
-out:
-	/*
-	 * Temporary debugging check, to make sure that things have been
-	 * flushed. This could be triggered if load_TLS() failed.
-	 */
-	if (unlikely(task == current &&
-		     !t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed)) {
-		printk(KERN_ERR "get_tls_entry: task with pid %d got here "
-				"without flushed TLS.", current->pid);
-	}
-
-	return 0;
-clear:
-	/*
-	 * When the TLS entry has not been set, the values read to user in the
-	 * tls_array are 0 (because it's cleared at boot, see
-	 * arch/i386/kernel/head.S:cpu_gdt_table). Emulate that.
-	 */
-	clear_user_desc(info);
-	info->entry_number = idx;
-	goto out;
-}
-
-int sys_set_thread_area(struct user_desc __user *user_desc)
-{
-	struct user_desc info;
-	int idx, ret;
-
-	if (!host_supports_tls)
-		return -ENOSYS;
-
-	if (copy_from_user(&info, user_desc, sizeof(info)))
-		return -EFAULT;
-
-	idx = info.entry_number;
-
-	if (idx == -1) {
-		idx = get_free_idx(current);
-		if (idx < 0)
-			return idx;
-		info.entry_number = idx;
-		/* Tell the user which slot we chose for him.*/
-		if (put_user(idx, &user_desc->entry_number))
-			return -EFAULT;
-	}
-
-	ret = do_set_thread_area(&info);
-	if (ret)
-		return ret;
-	return set_tls_entry(current, &info, idx, 1);
-}
-
-/*
- * Perform set_thread_area on behalf of the traced child.
- * Note: error handling is not done on the deferred load, and this differ from
- * i386. However the only possible error are caused by bugs.
- */
-int ptrace_set_thread_area(struct task_struct *child, int idx,
-			   struct user_desc __user *user_desc)
-{
-	struct user_desc info;
-
-	if (!host_supports_tls)
-		return -EIO;
-
-	if (copy_from_user(&info, user_desc, sizeof(info)))
-		return -EFAULT;
-
-	return set_tls_entry(child, &info, idx, 0);
-}
-
-int sys_get_thread_area(struct user_desc __user *user_desc)
-{
-	struct user_desc info;
-	int idx, ret;
-
-	if (!host_supports_tls)
-		return -ENOSYS;
-
-	if (get_user(idx, &user_desc->entry_number))
-		return -EFAULT;
-
-	ret = get_tls_entry(current, &info, idx);
-	if (ret < 0)
-		goto out;
-
-	if (copy_to_user(user_desc, &info, sizeof(info)))
-		ret = -EFAULT;
-
-out:
-	return ret;
-}
-
-/*
- * Perform get_thread_area on behalf of the traced child.
- */
-int ptrace_get_thread_area(struct task_struct *child, int idx,
-		struct user_desc __user *user_desc)
-{
-	struct user_desc info;
-	int ret;
-
-	if (!host_supports_tls)
-		return -EIO;
-
-	ret = get_tls_entry(child, &info, idx);
-	if (ret < 0)
-		goto out;
-
-	if (copy_to_user(user_desc, &info, sizeof(info)))
-		ret = -EFAULT;
-out:
-	return ret;
-}
-
-/*
- * This code is really i386-only, but it detects and logs x86_64 GDT indexes
- * if a 32-bit UML is running on a 64-bit host.
- */
-static int __init __setup_host_supports_tls(void)
-{
-	check_host_supports_tls(&host_supports_tls, &host_gdt_entry_tls_min);
-	if (host_supports_tls) {
-		printk(KERN_INFO "Host TLS support detected\n");
-		printk(KERN_INFO "Detected host type: ");
-		switch (host_gdt_entry_tls_min) {
-		case GDT_ENTRY_TLS_MIN_I386:
-			printk(KERN_CONT "i386");
-			break;
-		case GDT_ENTRY_TLS_MIN_X86_64:
-			printk(KERN_CONT "x86_64");
-			break;
-		}
-		printk(KERN_CONT " (GDT indexes %d to %d)\n",
-		       host_gdt_entry_tls_min,
-		       host_gdt_entry_tls_min + GDT_ENTRY_TLS_ENTRIES);
-	} else
-		printk(KERN_ERR "  Host TLS support NOT detected! "
-				"TLS support inside UML will not work\n");
-	return 0;
-}
-
-__initcall(__setup_host_supports_tls);
diff --git a/arch/um/sys-i386/user-offsets.c b/arch/um/sys-i386/user-offsets.c
deleted file mode 100644
index 5f883bf..0000000
--- a/arch/um/sys-i386/user-offsets.c
+++ /dev/null
@@ -1,53 +0,0 @@
-#include <stdio.h>
-#include <stddef.h>
-#include <signal.h>
-#include <sys/poll.h>
-#include <sys/user.h>
-#include <sys/mman.h>
-#include <asm/ptrace.h>
-
-#define DEFINE(sym, val) \
-	asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define DEFINE_LONGS(sym, val) \
-	asm volatile("\n->" #sym " %0 " #val : : "i" (val/sizeof(unsigned long)))
-
-#define OFFSET(sym, str, mem) \
-	DEFINE(sym, offsetof(struct str, mem));
-
-void foo(void)
-{
-	OFFSET(HOST_SC_TRAPNO, sigcontext, trapno);
-	OFFSET(HOST_SC_ERR, sigcontext, err);
-	OFFSET(HOST_SC_CR2, sigcontext, cr2);
-
-	DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_fpregs_struct));
-	DEFINE_LONGS(HOST_FPX_SIZE, sizeof(struct user_fpxregs_struct));
-
-	DEFINE(HOST_IP, EIP);
-	DEFINE(HOST_SP, UESP);
-	DEFINE(HOST_EFLAGS, EFL);
-	DEFINE(HOST_EAX, EAX);
-	DEFINE(HOST_EBX, EBX);
-	DEFINE(HOST_ECX, ECX);
-	DEFINE(HOST_EDX, EDX);
-	DEFINE(HOST_ESI, ESI);
-	DEFINE(HOST_EDI, EDI);
-	DEFINE(HOST_EBP, EBP);
-	DEFINE(HOST_CS, CS);
-	DEFINE(HOST_SS, SS);
-	DEFINE(HOST_DS, DS);
-	DEFINE(HOST_FS, FS);
-	DEFINE(HOST_ES, ES);
-	DEFINE(HOST_GS, GS);
-	DEFINE(UM_FRAME_SIZE, sizeof(struct user_regs_struct));
-
-	/* XXX Duplicated between i386 and x86_64 */
-	DEFINE(UM_POLLIN, POLLIN);
-	DEFINE(UM_POLLPRI, POLLPRI);
-	DEFINE(UM_POLLOUT, POLLOUT);
-
-	DEFINE(UM_PROT_READ, PROT_READ);
-	DEFINE(UM_PROT_WRITE, PROT_WRITE);
-	DEFINE(UM_PROT_EXEC, PROT_EXEC);
-}
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile
deleted file mode 100644
index bd4d1d3..0000000
--- a/arch/um/sys-x86_64/Makefile
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# Copyright 2003 PathScale, Inc.
-#
-# Licensed under the GPL
-#
-
-obj-y = bug.o bugs.o delay.o fault.o ldt.o ptrace.o ptrace_user.o mem.o \
-	setjmp.o signal.o stub.o stub_segv.o syscalls.o syscall_table.o \
-	sysrq.o ksyms.o tls.o
-
-obj-y += vdso/
-
-subarch-obj-y = lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o \
-		lib/rwsem.o
-subarch-obj-$(CONFIG_MODULES) += kernel/module.o
-
-ldt-y = ../sys-i386/ldt.o
-
-USER_OBJS := ptrace_user.o
-
-USER_OBJS += user-offsets.s
-extra-y += user-offsets.s
-
-UNPROFILE_OBJS := stub_segv.o
-CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING)
-
-include arch/um/scripts/Makefile.rules
diff --git a/arch/um/sys-x86_64/asm/archparam.h b/arch/um/sys-x86_64/asm/archparam.h
deleted file mode 100644
index 6c08366..0000000
--- a/arch/um/sys-x86_64/asm/archparam.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#ifndef __UM_ARCHPARAM_X86_64_H
-#define __UM_ARCHPARAM_X86_64_H
-
-
-/* No user-accessible fixmap addresses, i.e. vsyscall */
-#define FIXADDR_USER_START	0
-#define FIXADDR_USER_END	0
-
-#endif
-
diff --git a/arch/um/sys-x86_64/asm/elf.h b/arch/um/sys-x86_64/asm/elf.h
deleted file mode 100644
index 11a2bfb..0000000
--- a/arch/um/sys-x86_64/asm/elf.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- *
- * Licensed under the GPL
- */
-#ifndef __UM_ELF_X86_64_H
-#define __UM_ELF_X86_64_H
-
-#include <asm/user.h>
-#include "skas.h"
-
-/* x86-64 relocation types, taken from asm-x86_64/elf.h */
-#define R_X86_64_NONE		0	/* No reloc */
-#define R_X86_64_64		1	/* Direct 64 bit  */
-#define R_X86_64_PC32		2	/* PC relative 32 bit signed */
-#define R_X86_64_GOT32		3	/* 32 bit GOT entry */
-#define R_X86_64_PLT32		4	/* 32 bit PLT address */
-#define R_X86_64_COPY		5	/* Copy symbol at runtime */
-#define R_X86_64_GLOB_DAT	6	/* Create GOT entry */
-#define R_X86_64_JUMP_SLOT	7	/* Create PLT entry */
-#define R_X86_64_RELATIVE	8	/* Adjust by program base */
-#define R_X86_64_GOTPCREL	9	/* 32 bit signed pc relative
-					   offset to GOT */
-#define R_X86_64_32		10	/* Direct 32 bit zero extended */
-#define R_X86_64_32S		11	/* Direct 32 bit sign extended */
-#define R_X86_64_16		12	/* Direct 16 bit zero extended */
-#define R_X86_64_PC16		13	/* 16 bit sign extended pc relative */
-#define R_X86_64_8		14	/* Direct 8 bit sign extended  */
-#define R_X86_64_PC8		15	/* 8 bit sign extended pc relative */
-
-#define R_X86_64_NUM		16
-
-typedef unsigned long elf_greg_t;
-
-#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-
-typedef struct user_i387_struct elf_fpregset_t;
-
-/*
- * This is used to ensure we don't load something for the wrong architecture.
- */
-#define elf_check_arch(x) \
-	((x)->e_machine == EM_X86_64)
-
-#define ELF_CLASS	ELFCLASS64
-#define ELF_DATA        ELFDATA2LSB
-#define ELF_ARCH        EM_X86_64
-
-#define ELF_PLAT_INIT(regs, load_addr)    do { \
-	PT_REGS_RBX(regs) = 0; \
-	PT_REGS_RCX(regs) = 0; \
-	PT_REGS_RDX(regs) = 0; \
-	PT_REGS_RSI(regs) = 0; \
-	PT_REGS_RDI(regs) = 0; \
-	PT_REGS_RBP(regs) = 0; \
-	PT_REGS_RAX(regs) = 0; \
-	PT_REGS_R8(regs) = 0; \
-	PT_REGS_R9(regs) = 0; \
-	PT_REGS_R10(regs) = 0; \
-	PT_REGS_R11(regs) = 0; \
-	PT_REGS_R12(regs) = 0; \
-	PT_REGS_R13(regs) = 0; \
-	PT_REGS_R14(regs) = 0; \
-	PT_REGS_R15(regs) = 0; \
-} while (0)
-
-#define ELF_CORE_COPY_REGS(pr_reg, _regs)		\
-	(pr_reg)[0] = (_regs)->regs.gp[0];			\
-	(pr_reg)[1] = (_regs)->regs.gp[1];			\
-	(pr_reg)[2] = (_regs)->regs.gp[2];			\
-	(pr_reg)[3] = (_regs)->regs.gp[3];			\
-	(pr_reg)[4] = (_regs)->regs.gp[4];			\
-	(pr_reg)[5] = (_regs)->regs.gp[5];			\
-	(pr_reg)[6] = (_regs)->regs.gp[6];			\
-	(pr_reg)[7] = (_regs)->regs.gp[7];			\
-	(pr_reg)[8] = (_regs)->regs.gp[8];			\
-	(pr_reg)[9] = (_regs)->regs.gp[9];			\
-	(pr_reg)[10] = (_regs)->regs.gp[10];			\
-	(pr_reg)[11] = (_regs)->regs.gp[11];			\
-	(pr_reg)[12] = (_regs)->regs.gp[12];			\
-	(pr_reg)[13] = (_regs)->regs.gp[13];			\
-	(pr_reg)[14] = (_regs)->regs.gp[14];			\
-	(pr_reg)[15] = (_regs)->regs.gp[15];			\
-	(pr_reg)[16] = (_regs)->regs.gp[16];			\
-	(pr_reg)[17] = (_regs)->regs.gp[17];			\
-	(pr_reg)[18] = (_regs)->regs.gp[18];			\
-	(pr_reg)[19] = (_regs)->regs.gp[19];			\
-	(pr_reg)[20] = (_regs)->regs.gp[20];			\
-	(pr_reg)[21] = current->thread.arch.fs;			\
-	(pr_reg)[22] = 0;					\
-	(pr_reg)[23] = 0;					\
-	(pr_reg)[24] = 0;					\
-	(pr_reg)[25] = 0;					\
-	(pr_reg)[26] = 0;
-
-#define task_pt_regs(t) (&(t)->thread.regs)
-
-struct task_struct;
-
-extern int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu);
-
-#define ELF_CORE_COPY_FPREGS(t, fpu) elf_core_copy_fpregs(t, fpu)
-
-#ifdef TIF_IA32 /* XXX */
-#error XXX, indeed
-        clear_thread_flag(TIF_IA32);
-#endif
-
-#define ELF_EXEC_PAGESIZE 4096
-
-#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
-
-extern long elf_aux_hwcap;
-#define ELF_HWCAP (elf_aux_hwcap)
-
-#define ELF_PLATFORM "x86_64"
-
-#define SET_PERSONALITY(ex) do ; while(0)
-
-#define __HAVE_ARCH_GATE_AREA 1
-#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
-struct linux_binprm;
-extern int arch_setup_additional_pages(struct linux_binprm *bprm,
-	int uses_interp);
-
-extern unsigned long um_vdso_addr;
-#define AT_SYSINFO_EHDR 33
-#define ARCH_DLINFO	NEW_AUX_ENT(AT_SYSINFO_EHDR, um_vdso_addr)
-
-#endif
diff --git a/arch/um/sys-x86_64/asm/module.h b/arch/um/sys-x86_64/asm/module.h
deleted file mode 100644
index 8eb79c2..0000000
--- a/arch/um/sys-x86_64/asm/module.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#ifndef __UM_MODULE_X86_64_H
-#define __UM_MODULE_X86_64_H
-
-/* UML is simple */
-struct mod_arch_specific
-{
-};
-
-#define Elf_Shdr Elf64_Shdr
-#define Elf_Sym Elf64_Sym
-#define Elf_Ehdr Elf64_Ehdr
-
-#endif
-
diff --git a/arch/um/sys-x86_64/asm/processor.h b/arch/um/sys-x86_64/asm/processor.h
deleted file mode 100644
index 875a26a..0000000
--- a/arch/um/sys-x86_64/asm/processor.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#ifndef __UM_PROCESSOR_X86_64_H
-#define __UM_PROCESSOR_X86_64_H
-
-/* include faultinfo structure */
-#include "sysdep/faultinfo.h"
-
-struct arch_thread {
-        unsigned long debugregs[8];
-        int debugregs_seq;
-        unsigned long fs;
-        struct faultinfo faultinfo;
-};
-
-/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
-static inline void rep_nop(void)
-{
-	__asm__ __volatile__("rep;nop": : :"memory");
-}
-
-#define cpu_relax()   rep_nop()
-
-#define INIT_ARCH_THREAD { .debugregs  		= { [ 0 ... 7 ] = 0 }, \
-			   .debugregs_seq	= 0, \
-			   .fs			= 0, \
-			   .faultinfo		= { 0, 0, 0 } }
-
-static inline void arch_flush_thread(struct arch_thread *thread)
-{
-}
-
-static inline void arch_copy_thread(struct arch_thread *from,
-                                    struct arch_thread *to)
-{
-	to->fs = from->fs;
-}
-
-#include <asm/user.h>
-
-#define current_text_addr() \
-	({ void *pc; __asm__("movq $1f,%0\n1:":"=g" (pc)); pc; })
-
-#define ARCH_IS_STACKGROW(address) \
-        (address + 128 >= UPT_SP(&current->thread.regs.regs))
-
-#define KSTK_EIP(tsk) KSTK_REG(tsk, RIP)
-#define KSTK_ESP(tsk) KSTK_REG(tsk, RSP)
-
-#include "asm/processor-generic.h"
-
-#endif
diff --git a/arch/um/sys-x86_64/asm/ptrace.h b/arch/um/sys-x86_64/asm/ptrace.h
deleted file mode 100644
index 83d8c47..0000000
--- a/arch/um/sys-x86_64/asm/ptrace.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#ifndef __UM_PTRACE_X86_64_H
-#define __UM_PTRACE_X86_64_H
-
-#include "linux/compiler.h"
-#include "asm/errno.h"
-
-#define __FRAME_OFFSETS /* Needed to get the R* macros */
-#include "asm/ptrace-generic.h"
-
-#define HOST_AUDIT_ARCH AUDIT_ARCH_X86_64
-
-#define PT_REGS_RBX(r) UPT_RBX(&(r)->regs)
-#define PT_REGS_RCX(r) UPT_RCX(&(r)->regs)
-#define PT_REGS_RDX(r) UPT_RDX(&(r)->regs)
-#define PT_REGS_RSI(r) UPT_RSI(&(r)->regs)
-#define PT_REGS_RDI(r) UPT_RDI(&(r)->regs)
-#define PT_REGS_RBP(r) UPT_RBP(&(r)->regs)
-#define PT_REGS_RAX(r) UPT_RAX(&(r)->regs)
-#define PT_REGS_R8(r) UPT_R8(&(r)->regs)
-#define PT_REGS_R9(r) UPT_R9(&(r)->regs)
-#define PT_REGS_R10(r) UPT_R10(&(r)->regs)
-#define PT_REGS_R11(r) UPT_R11(&(r)->regs)
-#define PT_REGS_R12(r) UPT_R12(&(r)->regs)
-#define PT_REGS_R13(r) UPT_R13(&(r)->regs)
-#define PT_REGS_R14(r) UPT_R14(&(r)->regs)
-#define PT_REGS_R15(r) UPT_R15(&(r)->regs)
-
-#define PT_REGS_FS(r) UPT_FS(&(r)->regs)
-#define PT_REGS_GS(r) UPT_GS(&(r)->regs)
-#define PT_REGS_DS(r) UPT_DS(&(r)->regs)
-#define PT_REGS_ES(r) UPT_ES(&(r)->regs)
-#define PT_REGS_SS(r) UPT_SS(&(r)->regs)
-#define PT_REGS_CS(r) UPT_CS(&(r)->regs)
-
-#define PT_REGS_ORIG_RAX(r) UPT_ORIG_RAX(&(r)->regs)
-#define PT_REGS_RIP(r) UPT_IP(&(r)->regs)
-#define PT_REGS_RSP(r) UPT_SP(&(r)->regs)
-
-#define PT_REGS_EFLAGS(r) UPT_EFLAGS(&(r)->regs)
-
-/* XXX */
-#define user_mode(r) UPT_IS_USER(&(r)->regs)
-#define PT_REGS_ORIG_SYSCALL(r) PT_REGS_RAX(r)
-#define PT_REGS_SYSCALL_RET(r) PT_REGS_RAX(r)
-
-#define PT_FIX_EXEC_STACK(sp) do ; while(0)
-
-#define profile_pc(regs) PT_REGS_IP(regs)
-
-struct user_desc;
-
-static inline int ptrace_get_thread_area(struct task_struct *child, int idx,
-                                         struct user_desc __user *user_desc)
-{
-        return -ENOSYS;
-}
-
-static inline int ptrace_set_thread_area(struct task_struct *child, int idx,
-                                         struct user_desc __user *user_desc)
-{
-        return -ENOSYS;
-}
-
-extern long arch_prctl(struct task_struct *task, int code,
-		       unsigned long __user *addr);
-#endif
diff --git a/arch/um/sys-x86_64/bug.c b/arch/um/sys-x86_64/bug.c
deleted file mode 100644
index e8034e3..0000000
--- a/arch/um/sys-x86_64/bug.c
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL V2
- */
-
-#include <linux/uaccess.h>
-
-/*
- * Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because
- * that's not relevant in skas mode.
- */
-
-int is_valid_bugaddr(unsigned long eip)
-{
-	unsigned short ud2;
-
-	if (probe_kernel_address((unsigned short __user *)eip, ud2))
-		return 0;
-
-	return ud2 == 0x0b0f;
-}
diff --git a/arch/um/sys-x86_64/bugs.c b/arch/um/sys-x86_64/bugs.c
deleted file mode 100644
index 44e02ba..0000000
--- a/arch/um/sys-x86_64/bugs.c
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#include "sysdep/ptrace.h"
-
-void arch_check_bugs(void)
-{
-}
-
-void arch_examine_signal(int sig, struct uml_pt_regs *regs)
-{
-}
diff --git a/arch/um/sys-x86_64/delay.c b/arch/um/sys-x86_64/delay.c
deleted file mode 100644
index f3fe1a6..0000000
--- a/arch/um/sys-x86_64/delay.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
- * Mostly copied from arch/x86/lib/delay.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <asm/param.h>
-
-void __delay(unsigned long loops)
-{
-	asm volatile(
-		"test %0,%0\n"
-		"jz 3f\n"
-		"jmp 1f\n"
-
-		".align 16\n"
-		"1: jmp 2f\n"
-
-		".align 16\n"
-		"2: dec %0\n"
-		" jnz 2b\n"
-		"3: dec %0\n"
-
-		: /* we don't need output */
-		: "a" (loops)
-	);
-}
-EXPORT_SYMBOL(__delay);
-
-inline void __const_udelay(unsigned long xloops)
-{
-	int d0;
-
-	xloops *= 4;
-	asm("mull %%edx"
-		: "=d" (xloops), "=&a" (d0)
-		: "1" (xloops), "0"
-		(loops_per_jiffy * (HZ/4)));
-
-	__delay(++xloops);
-}
-EXPORT_SYMBOL(__const_udelay);
-
-void __udelay(unsigned long usecs)
-{
-	__const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */
-}
-EXPORT_SYMBOL(__udelay);
-
-void __ndelay(unsigned long nsecs)
-{
-	__const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */
-}
-EXPORT_SYMBOL(__ndelay);
diff --git a/arch/um/sys-x86_64/fault.c b/arch/um/sys-x86_64/fault.c
deleted file mode 100644
index ce85117..0000000
--- a/arch/um/sys-x86_64/fault.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#include "sysdep/ptrace.h"
-
-/* These two are from asm-um/uaccess.h and linux/module.h, check them. */
-struct exception_table_entry
-{
-	unsigned long insn;
-	unsigned long fixup;
-};
-
-const struct exception_table_entry *search_exception_tables(unsigned long add);
-
-int arch_fixup(unsigned long address, struct uml_pt_regs *regs)
-{
-	const struct exception_table_entry *fixup;
-
-	fixup = search_exception_tables(address);
-	if (fixup != 0) {
-		UPT_IP(regs) = fixup->fixup;
-		return 1;
-	}
-	return 0;
-}
diff --git a/arch/um/sys-x86_64/ksyms.c b/arch/um/sys-x86_64/ksyms.c
deleted file mode 100644
index 1db2fce..0000000
--- a/arch/um/sys-x86_64/ksyms.c
+++ /dev/null
@@ -1,11 +0,0 @@
-#include <linux/module.h>
-#include <asm/string.h>
-#include <asm/checksum.h>
-
-/*XXX: we need them because they would be exported by x86_64 */
-#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4
-EXPORT_SYMBOL(memcpy);
-#else
-EXPORT_SYMBOL(__memcpy);
-#endif
-EXPORT_SYMBOL(csum_partial);
diff --git a/arch/um/sys-x86_64/mem.c b/arch/um/sys-x86_64/mem.c
deleted file mode 100644
index 5465187..0000000
--- a/arch/um/sys-x86_64/mem.c
+++ /dev/null
@@ -1,26 +0,0 @@
-#include "linux/mm.h"
-#include "asm/page.h"
-#include "asm/mman.h"
-
-const char *arch_vma_name(struct vm_area_struct *vma)
-{
-	if (vma->vm_mm && vma->vm_start == um_vdso_addr)
-		return "[vdso]";
-
-	return NULL;
-}
-
-struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
-{
-	return NULL;
-}
-
-int in_gate_area(struct mm_struct *mm, unsigned long addr)
-{
-	return 0;
-}
-
-int in_gate_area_no_mm(unsigned long addr)
-{
-	return 0;
-}
diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c
deleted file mode 100644
index 4005506..0000000
--- a/arch/um/sys-x86_64/ptrace.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- *
- * Licensed under the GPL
- */
-
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#define __FRAME_OFFSETS
-#include <asm/ptrace.h>
-#include <asm/uaccess.h>
-
-/*
- * determines which flags the user has access to.
- * 1 = access 0 = no access
- */
-#define FLAG_MASK 0x44dd5UL
-
-int putreg(struct task_struct *child, int regno, unsigned long value)
-{
-	unsigned long tmp;
-
-#ifdef TIF_IA32
-	/*
-	 * Some code in the 64bit emulation may not be 64bit clean.
-	 * Don't take any chances.
-	 */
-	if (test_tsk_thread_flag(child, TIF_IA32))
-		value &= 0xffffffff;
-#endif
-	switch (regno) {
-	case FS:
-	case GS:
-	case DS:
-	case ES:
-	case SS:
-	case CS:
-		if (value && (value & 3) != 3)
-			return -EIO;
-		value &= 0xffff;
-		break;
-
-	case FS_BASE:
-	case GS_BASE:
-		if (!((value >> 48) == 0 || (value >> 48) == 0xffff))
-			return -EIO;
-		break;
-
-	case EFLAGS:
-		value &= FLAG_MASK;
-		tmp = PT_REGS_EFLAGS(&child->thread.regs) & ~FLAG_MASK;
-		value |= tmp;
-		break;
-	}
-
-	PT_REGS_SET(&child->thread.regs, regno, value);
-	return 0;
-}
-
-int poke_user(struct task_struct *child, long addr, long data)
-{
-	if ((addr & 3) || addr < 0)
-		return -EIO;
-
-	if (addr < MAX_REG_OFFSET)
-		return putreg(child, addr, data);
-	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
-		(addr <= offsetof(struct user, u_debugreg[7]))) {
-		addr -= offsetof(struct user, u_debugreg[0]);
-		addr = addr >> 2;
-		if ((addr == 4) || (addr == 5))
-			return -EIO;
-		child->thread.arch.debugregs[addr] = data;
-		return 0;
-	}
-	return -EIO;
-}
-
-unsigned long getreg(struct task_struct *child, int regno)
-{
-	unsigned long retval = ~0UL;
-	switch (regno) {
-	case FS:
-	case GS:
-	case DS:
-	case ES:
-	case SS:
-	case CS:
-		retval = 0xffff;
-		/* fall through */
-	default:
-		retval &= PT_REG(&child->thread.regs, regno);
-#ifdef TIF_IA32
-		if (test_tsk_thread_flag(child, TIF_IA32))
-			retval &= 0xffffffff;
-#endif
-	}
-	return retval;
-}
-
-int peek_user(struct task_struct *child, long addr, long data)
-{
-	/* read the word at location addr in the USER area. */
-	unsigned long tmp;
-
-	if ((addr & 3) || addr < 0)
-		return -EIO;
-
-	tmp = 0;  /* Default return condition */
-	if (addr < MAX_REG_OFFSET)
-		tmp = getreg(child, addr);
-	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
-		(addr <= offsetof(struct user, u_debugreg[7]))) {
-		addr -= offsetof(struct user, u_debugreg[0]);
-		addr = addr >> 2;
-		tmp = child->thread.arch.debugregs[addr];
-	}
-	return put_user(tmp, (unsigned long *) data);
-}
-
-/* XXX Mostly copied from sys-i386 */
-int is_syscall(unsigned long addr)
-{
-	unsigned short instr;
-	int n;
-
-	n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
-	if (n) {
-		/*
-		 * access_process_vm() grants access to vsyscall and stub,
-		 * while copy_from_user doesn't. Maybe access_process_vm is
-		 * slow, but that doesn't matter, since it will be called only
-		 * in case of singlestepping, if copy_from_user failed.
-		 */
-		n = access_process_vm(current, addr, &instr, sizeof(instr), 0);
-		if (n != sizeof(instr)) {
-			printk("is_syscall : failed to read instruction from "
-			       "0x%lx\n", addr);
-			return 1;
-		}
-	}
-	/* sysenter */
-	return instr == 0x050f;
-}
-
-static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
-{
-	int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
-	long fpregs[HOST_FP_SIZE];
-
-	BUG_ON(sizeof(*buf) != sizeof(fpregs));
-	err = save_fp_registers(userspace_pid[cpu], fpregs);
-	if (err)
-		return err;
-
-	n = copy_to_user(buf, fpregs, sizeof(fpregs));
-	if (n > 0)
-		return -EFAULT;
-
-	return n;
-}
-
-static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
-{
-	int n, cpu = ((struct thread_info *) child->stack)->cpu;
-	long fpregs[HOST_FP_SIZE];
-
-	BUG_ON(sizeof(*buf) != sizeof(fpregs));
-	n = copy_from_user(fpregs, buf, sizeof(fpregs));
-	if (n > 0)
-		return -EFAULT;
-
-	return restore_fp_registers(userspace_pid[cpu], fpregs);
-}
-
-long subarch_ptrace(struct task_struct *child, long request,
-		    unsigned long addr, unsigned long data)
-{
-	int ret = -EIO;
-	void __user *datap = (void __user *) data;
-
-	switch (request) {
-	case PTRACE_GETFPREGS: /* Get the child FPU state. */
-		ret = get_fpregs(datap, child);
-		break;
-	case PTRACE_SETFPREGS: /* Set the child FPU state. */
-		ret = set_fpregs(datap, child);
-		break;
-	case PTRACE_ARCH_PRCTL:
-		/* XXX Calls ptrace on the host - needs some SMP thinking */
-		ret = arch_prctl(child, data, (void __user *) addr);
-		break;
-	}
-
-	return ret;
-}
diff --git a/arch/um/sys-x86_64/ptrace_user.c b/arch/um/sys-x86_64/ptrace_user.c
deleted file mode 100644
index c57a496..0000000
--- a/arch/um/sys-x86_64/ptrace_user.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#include <errno.h>
-#include "ptrace_user.h"
-
-int ptrace_getregs(long pid, unsigned long *regs_out)
-{
-	if (ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0)
-		return -errno;
-	return(0);
-}
-
-int ptrace_setregs(long pid, unsigned long *regs_out)
-{
-	if (ptrace(PTRACE_SETREGS, pid, 0, regs_out) < 0)
-		return -errno;
-	return(0);
-}
diff --git a/arch/um/sys-x86_64/setjmp.S b/arch/um/sys-x86_64/setjmp.S
deleted file mode 100644
index 45f547b..0000000
--- a/arch/um/sys-x86_64/setjmp.S
+++ /dev/null
@@ -1,54 +0,0 @@
-#
-# arch/x86_64/setjmp.S
-#
-# setjmp/longjmp for the x86-64 architecture
-#
-
-#
-# The jmp_buf is assumed to contain the following, in order:
-#	%rbx
-#	%rsp (post-return)
-#	%rbp
-#	%r12
-#	%r13
-#	%r14
-#	%r15
-#	<return address>
-#
-
-	.text
-	.align 4
-	.globl setjmp
-	.type setjmp, @function
-setjmp:
-	pop  %rsi			# Return address, and adjust the stack
-	xorl %eax,%eax			# Return value
-	movq %rbx,(%rdi)
-	movq %rsp,8(%rdi)		# Post-return %rsp!
-	push %rsi			# Make the call/return stack happy
-	movq %rbp,16(%rdi)
-	movq %r12,24(%rdi)
-	movq %r13,32(%rdi)
-	movq %r14,40(%rdi)
-	movq %r15,48(%rdi)
-	movq %rsi,56(%rdi)		# Return address
-	ret
-
-	.size setjmp,.-setjmp
-
-	.text
-	.align 4
-	.globl longjmp
-	.type longjmp, @function
-longjmp:
-	movl %esi,%eax			# Return value (int)
-	movq (%rdi),%rbx
-	movq 8(%rdi),%rsp
-	movq 16(%rdi),%rbp
-	movq 24(%rdi),%r12
-	movq 32(%rdi),%r13
-	movq 40(%rdi),%r14
-	movq 48(%rdi),%r15
-	jmp *56(%rdi)
-
-	.size longjmp,.-longjmp
diff --git a/arch/um/sys-x86_64/shared/sysdep/archsetjmp.h b/arch/um/sys-x86_64/shared/sysdep/archsetjmp.h
deleted file mode 100644
index 2af8f12..0000000
--- a/arch/um/sys-x86_64/shared/sysdep/archsetjmp.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * arch/um/include/sysdep-x86_64/archsetjmp.h
- */
-
-#ifndef _KLIBC_ARCHSETJMP_H
-#define _KLIBC_ARCHSETJMP_H
-
-struct __jmp_buf {
-	unsigned long __rbx;
-	unsigned long __rsp;
-	unsigned long __rbp;
-	unsigned long __r12;
-	unsigned long __r13;
-	unsigned long __r14;
-	unsigned long __r15;
-	unsigned long __rip;
-};
-
-typedef struct __jmp_buf jmp_buf[1];
-
-#define JB_IP __rip
-#define JB_SP __rsp
-
-#endif				/* _SETJMP_H */
diff --git a/arch/um/sys-x86_64/shared/sysdep/barrier.h b/arch/um/sys-x86_64/shared/sysdep/barrier.h
deleted file mode 100644
index 7b610be..0000000
--- a/arch/um/sys-x86_64/shared/sysdep/barrier.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __SYSDEP_X86_64_BARRIER_H
-#define __SYSDEP_X86_64_BARRIER_H
-
-/* Copied from include/asm-x86_64 for use by userspace. */
-#define mb() 	asm volatile("mfence":::"memory")
-
-#endif
diff --git a/arch/um/sys-x86_64/shared/sysdep/checksum.h b/arch/um/sys-x86_64/shared/sysdep/checksum.h
deleted file mode 100644
index a5be903..0000000
--- a/arch/um/sys-x86_64/shared/sysdep/checksum.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Licensed under the GPL
- */
-
-#ifndef __UM_SYSDEP_CHECKSUM_H
-#define __UM_SYSDEP_CHECKSUM_H
-
-#include "linux/string.h"
-#include "linux/in6.h"
-#include "asm/uaccess.h"
-
-extern __wsum csum_partial(const void *buff, int len, __wsum sum);
-
-/*
- *	Note: when you get a NULL pointer exception here this means someone
- *	passed in an incorrect kernel address to one of these functions.
- *
- *	If you use these functions directly please don't forget the
- *	access_ok().
- */
-
-static __inline__
-__wsum csum_partial_copy_nocheck(const void *src, void *dst,
-				       int len, __wsum sum)
-{
-	memcpy(dst, src, len);
-	return(csum_partial(dst, len, sum));
-}
-
-static __inline__
-__wsum csum_partial_copy_from_user(const void __user *src,
-                                         void *dst, int len, __wsum sum,
-                                         int *err_ptr)
-{
-        if (copy_from_user(dst, src, len)) {
-                *err_ptr = -EFAULT;
-                return (__force __wsum)-1;
-        }
-        return csum_partial(dst, len, sum);
-}
-
-/**
- * csum_fold - Fold and invert a 32bit checksum.
- * sum: 32bit unfolded sum
- *
- * Fold a 32bit running checksum to 16bit and invert it. This is usually
- * the last step before putting a checksum into a packet.
- * Make sure not to mix with 64bit checksums.
- */
-static inline __sum16 csum_fold(__wsum sum)
-{
-	__asm__(
-		"  addl %1,%0\n"
-		"  adcl $0xffff,%0"
-		: "=r" (sum)
-		: "r" ((__force u32)sum << 16),
-		  "0" ((__force u32)sum & 0xffff0000)
-	);
-	return (__force __sum16)(~(__force u32)sum >> 16);
-}
-
-/**
- * csum_tcpup_nofold - Compute an IPv4 pseudo header checksum.
- * @saddr: source address
- * @daddr: destination address
- * @len: length of packet
- * @proto: ip protocol of packet
- * @sum: initial sum to be added in (32bit unfolded)
- *
- * Returns the pseudo header checksum the input data. Result is
- * 32bit unfolded.
- */
-static inline __wsum
-csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
-		   unsigned short proto, __wsum sum)
-{
-	asm("  addl %1, %0\n"
-	    "  adcl %2, %0\n"
-	    "  adcl %3, %0\n"
-	    "  adcl $0, %0\n"
-		: "=r" (sum)
-	    : "g" (daddr), "g" (saddr), "g" ((len + proto) << 8), "0" (sum));
-	return sum;
-}
-
-/*
- * computes the checksum of the TCP/UDP pseudo-header
- * returns a 16-bit checksum, already complemented
- */
-static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
-					   unsigned short len,
-					   unsigned short proto,
-					   __wsum sum)
-{
-	return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
-}
-
-/**
- * ip_fast_csum - Compute the IPv4 header checksum efficiently.
- * iph: ipv4 header
- * ihl: length of header / 4
- */
-static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
-{
-	unsigned int sum;
-
-	asm(	"  movl (%1), %0\n"
-		"  subl $4, %2\n"
-		"  jbe 2f\n"
-		"  addl 4(%1), %0\n"
-		"  adcl 8(%1), %0\n"
-		"  adcl 12(%1), %0\n"
-		"1: adcl 16(%1), %0\n"
-		"  lea 4(%1), %1\n"
-		"  decl %2\n"
-		"  jne	1b\n"
-		"  adcl $0, %0\n"
-		"  movl %0, %2\n"
-		"  shrl $16, %0\n"
-		"  addw %w2, %w0\n"
-		"  adcl $0, %0\n"
-		"  notl %0\n"
-		"2:"
-	/* Since the input registers which are loaded with iph and ipl
-	   are modified, we must also specify them as outputs, or gcc
-	   will assume they contain their original values. */
-	: "=r" (sum), "=r" (iph), "=r" (ihl)
-	: "1" (iph), "2" (ihl)
-	: "memory");
-	return (__force __sum16)sum;
-}
-
-static inline unsigned add32_with_carry(unsigned a, unsigned b)
-{
-        asm("addl %2,%0\n\t"
-            "adcl $0,%0"
-            : "=r" (a)
-            : "0" (a), "r" (b));
-        return a;
-}
-
-extern __sum16 ip_compute_csum(const void *buff, int len);
-
-#endif
diff --git a/arch/um/sys-x86_64/shared/sysdep/faultinfo.h b/arch/um/sys-x86_64/shared/sysdep/faultinfo.h
deleted file mode 100644
index cb917b0..0000000
--- a/arch/um/sys-x86_64/shared/sysdep/faultinfo.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
- * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
- * Licensed under the GPL
- */
-
-#ifndef __FAULTINFO_X86_64_H
-#define __FAULTINFO_X86_64_H
-
-/* this structure contains the full arch-specific faultinfo
- * from the traps.
- * On i386, ptrace_faultinfo unfortunately doesn't provide
- * all the info, since trap_no is missing.
- * All common elements are defined at the same position in
- * both structures, thus making it easy to copy the
- * contents without knowledge about the structure elements.
- */
-struct faultinfo {
-        int error_code; /* in ptrace_faultinfo misleadingly called is_write */
-        unsigned long cr2; /* in ptrace_faultinfo called addr */
-        int trap_no; /* missing in ptrace_faultinfo */
-};
-
-#define FAULT_WRITE(fi) ((fi).error_code & 2)
-#define FAULT_ADDRESS(fi) ((fi).cr2)
-
-#define PTRACE_FULL_FAULTINFO 1
-
-#endif
diff --git a/arch/um/sys-x86_64/shared/sysdep/host_ldt.h b/arch/um/sys-x86_64/shared/sysdep/host_ldt.h
deleted file mode 100644
index e8b1be1..0000000
--- a/arch/um/sys-x86_64/shared/sysdep/host_ldt.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef __ASM_HOST_LDT_X86_64_H
-#define __ASM_HOST_LDT_X86_64_H
-
-#include <asm/ldt.h>
-
-/*
- * macros stolen from include/asm-x86_64/desc.h
- */
-#define LDT_entry_a(info) \
-	((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
-
-/* Don't allow setting of the lm bit. It is useless anyways because
- * 64bit system calls require __USER_CS. */
-#define LDT_entry_b(info) \
-	(((info)->base_addr & 0xff000000) | \
-	(((info)->base_addr & 0x00ff0000) >> 16) | \
-	((info)->limit & 0xf0000) | \
-	(((info)->read_exec_only ^ 1) << 9) | \
-	((info)->contents << 10) | \
-	(((info)->seg_not_present ^ 1) << 15) | \
-	((info)->seg_32bit << 22) | \
-	((info)->limit_in_pages << 23) | \
-	((info)->useable << 20) | \
-	/* ((info)->lm << 21) | */ \
-	0x7000)
-
-#define LDT_empty(info) (\
-	(info)->base_addr	== 0	&& \
-	(info)->limit		== 0	&& \
-	(info)->contents	== 0	&& \
-	(info)->read_exec_only	== 1	&& \
-	(info)->seg_32bit	== 0	&& \
-	(info)->limit_in_pages	== 0	&& \
-	(info)->seg_not_present	== 1	&& \
-	(info)->useable		== 0	&& \
-	(info)->lm              == 0)
-
-#endif
diff --git a/arch/um/sys-x86_64/shared/sysdep/kernel-offsets.h b/arch/um/sys-x86_64/shared/sysdep/kernel-offsets.h
deleted file mode 100644
index a307237..0000000
--- a/arch/um/sys-x86_64/shared/sysdep/kernel-offsets.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#include <linux/stddef.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/elf.h>
-#include <linux/crypto.h>
-#include <asm/page.h>
-#include <asm/mman.h>
-
-#define DEFINE(sym, val) \
-	asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define DEFINE_STR1(x) #x
-#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " DEFINE_STR1(val) " " #val: : )
-
-#define BLANK() asm volatile("\n->" : : )
-
-#define OFFSET(sym, str, mem) \
-	DEFINE(sym, offsetof(struct str, mem));
-
-void foo(void)
-{
-#include <common-offsets.h>
-}
diff --git a/arch/um/sys-x86_64/shared/sysdep/ptrace.h b/arch/um/sys-x86_64/shared/sysdep/ptrace.h
deleted file mode 100644
index 8ee8f8e..0000000
--- a/arch/um/sys-x86_64/shared/sysdep/ptrace.h
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- *
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_X86_64_PTRACE_H
-#define __SYSDEP_X86_64_PTRACE_H
-
-#include "user_constants.h"
-#include "sysdep/faultinfo.h"
-
-#define MAX_REG_OFFSET (UM_FRAME_SIZE)
-#define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long))
-
-#include "skas_ptregs.h"
-
-#define REGS_IP(r) ((r)[HOST_IP])
-#define REGS_SP(r) ((r)[HOST_SP])
-
-#define REGS_RBX(r) ((r)[HOST_RBX])
-#define REGS_RCX(r) ((r)[HOST_RCX])
-#define REGS_RDX(r) ((r)[HOST_RDX])
-#define REGS_RSI(r) ((r)[HOST_RSI])
-#define REGS_RDI(r) ((r)[HOST_RDI])
-#define REGS_RBP(r) ((r)[HOST_RBP])
-#define REGS_RAX(r) ((r)[HOST_RAX])
-#define REGS_R8(r) ((r)[HOST_R8])
-#define REGS_R9(r) ((r)[HOST_R9])
-#define REGS_R10(r) ((r)[HOST_R10])
-#define REGS_R11(r) ((r)[HOST_R11])
-#define REGS_R12(r) ((r)[HOST_R12])
-#define REGS_R13(r) ((r)[HOST_R13])
-#define REGS_R14(r) ((r)[HOST_R14])
-#define REGS_R15(r) ((r)[HOST_R15])
-#define REGS_CS(r) ((r)[HOST_CS])
-#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS])
-#define REGS_SS(r) ((r)[HOST_SS])
-
-#define HOST_FS_BASE 21
-#define HOST_GS_BASE 22
-#define HOST_DS 23
-#define HOST_ES 24
-#define HOST_FS 25
-#define HOST_GS 26
-
-/* Also defined in asm/ptrace-x86_64.h, but not in libc headers.  So, these
- * are already defined for kernel code, but not for userspace code.
- */
-#ifndef FS_BASE
-/* These aren't defined in ptrace.h, but exist in struct user_regs_struct,
- * which is what x86_64 ptrace actually uses.
- */
-#define FS_BASE (HOST_FS_BASE * sizeof(long))
-#define GS_BASE (HOST_GS_BASE * sizeof(long))
-#define DS (HOST_DS * sizeof(long))
-#define ES (HOST_ES * sizeof(long))
-#define FS (HOST_FS * sizeof(long))
-#define GS (HOST_GS * sizeof(long))
-#endif
-
-#define REGS_FS_BASE(r) ((r)[HOST_FS_BASE])
-#define REGS_GS_BASE(r) ((r)[HOST_GS_BASE])
-#define REGS_DS(r) ((r)[HOST_DS])
-#define REGS_ES(r) ((r)[HOST_ES])
-#define REGS_FS(r) ((r)[HOST_FS])
-#define REGS_GS(r) ((r)[HOST_GS])
-
-#define REGS_ORIG_RAX(r) ((r)[HOST_ORIG_RAX])
-
-#define REGS_SET_SYSCALL_RETURN(r, res) REGS_RAX(r) = (res)
-
-#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r))
-
-#define REGS_SEGV_IS_FIXABLE(r) SEGV_IS_FIXABLE((r)->trap_type)
-
-#define REGS_FAULT_ADDR(r) ((r)->fault_addr)
-
-#define REGS_FAULT_WRITE(r) FAULT_WRITE((r)->fault_type)
-
-#define REGS_TRAP(r) ((r)->trap_type)
-
-#define REGS_ERR(r) ((r)->fault_type)
-
-struct uml_pt_regs {
-	unsigned long gp[MAX_REG_NR];
-	unsigned long fp[HOST_FP_SIZE];
-	struct faultinfo faultinfo;
-	long syscall;
-	int is_user;
-};
-
-#define EMPTY_UML_PT_REGS { }
-
-#define UPT_RBX(r) REGS_RBX((r)->gp)
-#define UPT_RCX(r) REGS_RCX((r)->gp)
-#define UPT_RDX(r) REGS_RDX((r)->gp)
-#define UPT_RSI(r) REGS_RSI((r)->gp)
-#define UPT_RDI(r) REGS_RDI((r)->gp)
-#define UPT_RBP(r) REGS_RBP((r)->gp)
-#define UPT_RAX(r) REGS_RAX((r)->gp)
-#define UPT_R8(r) REGS_R8((r)->gp)
-#define UPT_R9(r) REGS_R9((r)->gp)
-#define UPT_R10(r) REGS_R10((r)->gp)
-#define UPT_R11(r) REGS_R11((r)->gp)
-#define UPT_R12(r) REGS_R12((r)->gp)
-#define UPT_R13(r) REGS_R13((r)->gp)
-#define UPT_R14(r) REGS_R14((r)->gp)
-#define UPT_R15(r) REGS_R15((r)->gp)
-#define UPT_CS(r) REGS_CS((r)->gp)
-#define UPT_FS_BASE(r) REGS_FS_BASE((r)->gp)
-#define UPT_FS(r) REGS_FS((r)->gp)
-#define UPT_GS_BASE(r) REGS_GS_BASE((r)->gp)
-#define UPT_GS(r) REGS_GS((r)->gp)
-#define UPT_DS(r) REGS_DS((r)->gp)
-#define UPT_ES(r) REGS_ES((r)->gp)
-#define UPT_CS(r) REGS_CS((r)->gp)
-#define UPT_SS(r) REGS_SS((r)->gp)
-#define UPT_ORIG_RAX(r) REGS_ORIG_RAX((r)->gp)
-
-#define UPT_IP(r) REGS_IP((r)->gp)
-#define UPT_SP(r) REGS_SP((r)->gp)
-
-#define UPT_EFLAGS(r) REGS_EFLAGS((r)->gp)
-#define UPT_SYSCALL_NR(r) ((r)->syscall)
-#define UPT_SYSCALL_RET(r) UPT_RAX(r)
-
-extern int user_context(unsigned long sp);
-
-#define UPT_IS_USER(r) ((r)->is_user)
-
-#define UPT_SYSCALL_ARG1(r) UPT_RDI(r)
-#define UPT_SYSCALL_ARG2(r) UPT_RSI(r)
-#define UPT_SYSCALL_ARG3(r) UPT_RDX(r)
-#define UPT_SYSCALL_ARG4(r) UPT_R10(r)
-#define UPT_SYSCALL_ARG5(r) UPT_R8(r)
-#define UPT_SYSCALL_ARG6(r) UPT_R9(r)
-
-struct syscall_args {
-	unsigned long args[6];
-};
-
-#define SYSCALL_ARGS(r) ((struct syscall_args) \
-			 { .args = { UPT_SYSCALL_ARG1(r),	 \
-				     UPT_SYSCALL_ARG2(r),	 \
-				     UPT_SYSCALL_ARG3(r),	 \
-				     UPT_SYSCALL_ARG4(r),	 \
-				     UPT_SYSCALL_ARG5(r),	 \
-				     UPT_SYSCALL_ARG6(r) } } )
-
-#define UPT_REG(regs, reg) \
-	({      unsigned long val;		\
-		switch(reg){						\
-		case R8: val = UPT_R8(regs); break;			\
-		case R9: val = UPT_R9(regs); break;			\
-		case R10: val = UPT_R10(regs); break;			\
-		case R11: val = UPT_R11(regs); break;			\
-		case R12: val = UPT_R12(regs); break;			\
-		case R13: val = UPT_R13(regs); break;			\
-		case R14: val = UPT_R14(regs); break;			\
-		case R15: val = UPT_R15(regs); break;			\
-		case RIP: val = UPT_IP(regs); break;			\
-		case RSP: val = UPT_SP(regs); break;			\
-		case RAX: val = UPT_RAX(regs); break;			\
-		case RBX: val = UPT_RBX(regs); break;			\
-		case RCX: val = UPT_RCX(regs); break;			\
-		case RDX: val = UPT_RDX(regs); break;			\
-		case RSI: val = UPT_RSI(regs); break;			\
-		case RDI: val = UPT_RDI(regs); break;			\
-		case RBP: val = UPT_RBP(regs); break;			\
-		case ORIG_RAX: val = UPT_ORIG_RAX(regs); break;		\
-		case CS: val = UPT_CS(regs); break;			\
-		case SS: val = UPT_SS(regs); break;			\
-		case FS_BASE: val = UPT_FS_BASE(regs); break;		\
-		case GS_BASE: val = UPT_GS_BASE(regs); break;		\
-		case DS: val = UPT_DS(regs); break;			\
-		case ES: val = UPT_ES(regs); break;			\
-		case FS : val = UPT_FS (regs); break;			\
-		case GS: val = UPT_GS(regs); break;			\
-		case EFLAGS: val = UPT_EFLAGS(regs); break;		\
-		default :						\
-			panic("Bad register in UPT_REG : %d\n", reg);	\
-			val = -1;					\
-		}							\
-		val;							\
-	})
-
-
-#define UPT_SET(regs, reg, val) \
-	({      unsigned long __upt_val = val;	\
-		switch(reg){						\
-		case R8: UPT_R8(regs) = __upt_val; break;		\
-		case R9: UPT_R9(regs) = __upt_val; break;		\
-		case R10: UPT_R10(regs) = __upt_val; break;		\
-		case R11: UPT_R11(regs) = __upt_val; break;		\
-		case R12: UPT_R12(regs) = __upt_val; break;		\
-		case R13: UPT_R13(regs) = __upt_val; break;		\
-		case R14: UPT_R14(regs) = __upt_val; break;		\
-		case R15: UPT_R15(regs) = __upt_val; break;		\
-		case RIP: UPT_IP(regs) = __upt_val; break;		\
-		case RSP: UPT_SP(regs) = __upt_val; break;		\
-		case RAX: UPT_RAX(regs) = __upt_val; break;		\
-		case RBX: UPT_RBX(regs) = __upt_val; break;		\
-		case RCX: UPT_RCX(regs) = __upt_val; break;		\
-		case RDX: UPT_RDX(regs) = __upt_val; break;		\
-		case RSI: UPT_RSI(regs) = __upt_val; break;		\
-		case RDI: UPT_RDI(regs) = __upt_val; break;		\
-		case RBP: UPT_RBP(regs) = __upt_val; break;		\
-		case ORIG_RAX: UPT_ORIG_RAX(regs) = __upt_val; break;	\
-		case CS: UPT_CS(regs) = __upt_val; break;		\
-		case SS: UPT_SS(regs) = __upt_val; break;		\
-		case FS_BASE: UPT_FS_BASE(regs) = __upt_val; break;	\
-		case GS_BASE: UPT_GS_BASE(regs) = __upt_val; break;	\
-		case DS: UPT_DS(regs) = __upt_val; break;		\
-		case ES: UPT_ES(regs) = __upt_val; break;		\
-		case FS: UPT_FS(regs) = __upt_val; break;		\
-		case GS: UPT_GS(regs) = __upt_val; break;		\
-		case EFLAGS: UPT_EFLAGS(regs) = __upt_val; break;	\
-		default :						\
-			panic("Bad register in UPT_SET : %d\n", reg);	\
-			break;						\
-		}							\
-		__upt_val;						\
-	})
-
-#define UPT_SET_SYSCALL_RETURN(r, res) \
-	REGS_SET_SYSCALL_RETURN((r)->regs, (res))
-
-#define UPT_RESTART_SYSCALL(r) REGS_RESTART_SYSCALL((r)->gp)
-
-#define UPT_SEGV_IS_FIXABLE(r) REGS_SEGV_IS_FIXABLE(&r->skas)
-
-#define UPT_FAULTINFO(r) (&(r)->faultinfo)
-
-static inline void arch_init_registers(int pid)
-{
-}
-
-#endif
diff --git a/arch/um/sys-x86_64/shared/sysdep/ptrace_user.h b/arch/um/sys-x86_64/shared/sysdep/ptrace_user.h
deleted file mode 100644
index 4dbccdb..0000000
--- a/arch/um/sys-x86_64/shared/sysdep/ptrace_user.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_X86_64_PTRACE_USER_H__
-#define __SYSDEP_X86_64_PTRACE_USER_H__
-
-#define __FRAME_OFFSETS
-#include <sys/ptrace.h>
-#include <linux/ptrace.h>
-#include <asm/ptrace.h>
-#undef __FRAME_OFFSETS
-#include "user_constants.h"
-
-#define PT_INDEX(off) ((off) / sizeof(unsigned long))
-
-#define PT_SYSCALL_NR(regs) ((regs)[PT_INDEX(ORIG_RAX)])
-#define PT_SYSCALL_NR_OFFSET (ORIG_RAX)
-
-#define PT_SYSCALL_ARG1(regs) (((unsigned long *) (regs))[PT_INDEX(RDI)])
-#define PT_SYSCALL_ARG1_OFFSET (RDI)
-
-#define PT_SYSCALL_ARG2(regs) (((unsigned long *) (regs))[PT_INDEX(RSI)])
-#define PT_SYSCALL_ARG2_OFFSET (RSI)
-
-#define PT_SYSCALL_ARG3(regs) (((unsigned long *) (regs))[PT_INDEX(RDX)])
-#define PT_SYSCALL_ARG3_OFFSET (RDX)
-
-#define PT_SYSCALL_ARG4(regs) (((unsigned long *) (regs))[PT_INDEX(RCX)])
-#define PT_SYSCALL_ARG4_OFFSET (RCX)
-
-#define PT_SYSCALL_ARG5(regs) (((unsigned long *) (regs))[PT_INDEX(R8)])
-#define PT_SYSCALL_ARG5_OFFSET (R8)
-
-#define PT_SYSCALL_ARG6(regs) (((unsigned long *) (regs))[PT_INDEX(R9)])
-#define PT_SYSCALL_ARG6_OFFSET (R9)
-
-#define PT_SYSCALL_RET_OFFSET (RAX)
-
-#define PT_IP_OFFSET (RIP)
-#define PT_IP(regs) ((regs)[PT_INDEX(RIP)])
-
-#define PT_SP_OFFSET (RSP)
-#define PT_SP(regs) ((regs)[PT_INDEX(RSP)])
-
-#define PT_ORIG_RAX_OFFSET (ORIG_RAX)
-#define PT_ORIG_RAX(regs) ((regs)[PT_INDEX(ORIG_RAX)])
-
-/*
- * x86_64 FC3 doesn't define this in /usr/include/linux/ptrace.h even though
- * it's defined in the kernel's include/linux/ptrace.h. Additionally, use the
- * 2.4 name and value for 2.4 host compatibility.
- */
-#ifndef PTRACE_OLDSETOPTIONS
-#define PTRACE_OLDSETOPTIONS 21
-#endif
-
-/*
- * These are before the system call, so the system call number is RAX
- * rather than ORIG_RAX, and arg4 is R10 rather than RCX
- */
-#define REGS_SYSCALL_NR PT_INDEX(RAX)
-#define REGS_SYSCALL_ARG1 PT_INDEX(RDI)
-#define REGS_SYSCALL_ARG2 PT_INDEX(RSI)
-#define REGS_SYSCALL_ARG3 PT_INDEX(RDX)
-#define REGS_SYSCALL_ARG4 PT_INDEX(R10)
-#define REGS_SYSCALL_ARG5 PT_INDEX(R8)
-#define REGS_SYSCALL_ARG6 PT_INDEX(R9)
-
-#define REGS_IP_INDEX PT_INDEX(RIP)
-#define REGS_SP_INDEX PT_INDEX(RSP)
-
-#define FP_SIZE (HOST_FP_SIZE)
-
-#endif
diff --git a/arch/um/sys-x86_64/shared/sysdep/sc.h b/arch/um/sys-x86_64/shared/sysdep/sc.h
deleted file mode 100644
index 8aee45b..0000000
--- a/arch/um/sys-x86_64/shared/sysdep/sc.h
+++ /dev/null
@@ -1,45 +0,0 @@
-#ifndef __SYSDEP_X86_64_SC_H
-#define __SYSDEP_X86_64_SC_H
-
-/* Copyright (C) 2003 - 2004 PathScale, Inc
- * Released under the GPL
- */
-
-#include <user_constants.h>
-
-#define SC_OFFSET(sc, field) \
-	 *((unsigned long *) &(((char *) (sc))[HOST_##field]))
-
-#define SC_RBX(sc) SC_OFFSET(sc, SC_RBX)
-#define SC_RCX(sc) SC_OFFSET(sc, SC_RCX)
-#define SC_RDX(sc) SC_OFFSET(sc, SC_RDX)
-#define SC_RSI(sc) SC_OFFSET(sc, SC_RSI)
-#define SC_RDI(sc) SC_OFFSET(sc, SC_RDI)
-#define SC_RBP(sc) SC_OFFSET(sc, SC_RBP)
-#define SC_RAX(sc) SC_OFFSET(sc, SC_RAX)
-#define SC_R8(sc) SC_OFFSET(sc, SC_R8)
-#define SC_R9(sc) SC_OFFSET(sc, SC_R9)
-#define SC_R10(sc) SC_OFFSET(sc, SC_R10)
-#define SC_R11(sc) SC_OFFSET(sc, SC_R11)
-#define SC_R12(sc) SC_OFFSET(sc, SC_R12)
-#define SC_R13(sc) SC_OFFSET(sc, SC_R13)
-#define SC_R14(sc) SC_OFFSET(sc, SC_R14)
-#define SC_R15(sc) SC_OFFSET(sc, SC_R15)
-#define SC_IP(sc) SC_OFFSET(sc, SC_IP)
-#define SC_SP(sc) SC_OFFSET(sc, SC_SP)
-#define SC_CR2(sc) SC_OFFSET(sc, SC_CR2)
-#define SC_ERR(sc) SC_OFFSET(sc, SC_ERR)
-#define SC_TRAPNO(sc) SC_OFFSET(sc, SC_TRAPNO)
-#define SC_CS(sc) SC_OFFSET(sc, SC_CS)
-#define SC_FS(sc) SC_OFFSET(sc, SC_FS)
-#define SC_GS(sc) SC_OFFSET(sc, SC_GS)
-#define SC_EFLAGS(sc) SC_OFFSET(sc, SC_EFLAGS)
-#define SC_SIGMASK(sc) SC_OFFSET(sc, SC_SIGMASK)
-#define SC_SS(sc) SC_OFFSET(sc, SC_SS)
-#if 0
-#define SC_ORIG_RAX(sc) SC_OFFSET(sc, SC_ORIG_RAX)
-#define SC_DS(sc) SC_OFFSET(sc, SC_DS)
-#define SC_ES(sc) SC_OFFSET(sc, SC_ES)
-#endif
-
-#endif
diff --git a/arch/um/sys-x86_64/shared/sysdep/sigcontext.h b/arch/um/sys-x86_64/shared/sysdep/sigcontext.h
deleted file mode 100644
index 0155133..0000000
--- a/arch/um/sys-x86_64/shared/sysdep/sigcontext.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_X86_64_SIGCONTEXT_H
-#define __SYSDEP_X86_64_SIGCONTEXT_H
-
-#include <sysdep/sc.h>
-
-#define IP_RESTART_SYSCALL(ip) ((ip) -= 2)
-
-#define GET_FAULTINFO_FROM_SC(fi, sc) \
-	{ \
-		(fi).cr2 = SC_CR2(sc); \
-		(fi).error_code = SC_ERR(sc); \
-		(fi).trap_no = SC_TRAPNO(sc); \
-	}
-
-/* This is Page Fault */
-#define SEGV_IS_FIXABLE(fi)	((fi)->trap_no == 14)
-
-/* No broken SKAS API, which doesn't pass trap_no, here. */
-#define SEGV_MAYBE_FIXABLE(fi)	0
-
-#endif
diff --git a/arch/um/sys-x86_64/shared/sysdep/skas_ptrace.h b/arch/um/sys-x86_64/shared/sysdep/skas_ptrace.h
deleted file mode 100644
index 95db4be7..0000000
--- a/arch/um/sys-x86_64/shared/sysdep/skas_ptrace.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_X86_64_SKAS_PTRACE_H
-#define __SYSDEP_X86_64_SKAS_PTRACE_H
-
-struct ptrace_faultinfo {
-        int is_write;
-        unsigned long addr;
-};
-
-struct ptrace_ldt {
-        int func;
-        void *ptr;
-        unsigned long bytecount;
-};
-
-#define PTRACE_LDT 54
-
-#endif
diff --git a/arch/um/sys-x86_64/shared/sysdep/stub.h b/arch/um/sys-x86_64/shared/sysdep/stub.h
deleted file mode 100644
index 3432aa2..0000000
--- a/arch/um/sys-x86_64/shared/sysdep/stub.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_STUB_H
-#define __SYSDEP_STUB_H
-
-#include <sys/mman.h>
-#include <asm/unistd.h>
-#include <sysdep/ptrace_user.h>
-#include "as-layout.h"
-#include "stub-data.h"
-#include "kern_constants.h"
-
-extern void stub_segv_handler(int sig);
-extern void stub_clone_handler(void);
-
-#define STUB_SYSCALL_RET PT_INDEX(RAX)
-#define STUB_MMAP_NR __NR_mmap
-#define MMAP_OFFSET(o) (o)
-
-#define __syscall_clobber "r11","rcx","memory"
-#define __syscall "syscall"
-
-static inline long stub_syscall0(long syscall)
-{
-	long ret;
-
-	__asm__ volatile (__syscall
-		: "=a" (ret)
-		: "0" (syscall) : __syscall_clobber );
-
-	return ret;
-}
-
-static inline long stub_syscall2(long syscall, long arg1, long arg2)
-{
-	long ret;
-
-	__asm__ volatile (__syscall
-		: "=a" (ret)
-		: "0" (syscall), "D" (arg1), "S" (arg2) : __syscall_clobber );
-
-	return ret;
-}
-
-static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3)
-{
-	long ret;
-
-	__asm__ volatile (__syscall
-		: "=a" (ret)
-		: "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3)
-		: __syscall_clobber );
-
-	return ret;
-}
-
-static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3,
-				 long arg4)
-{
-	long ret;
-
-	__asm__ volatile ("movq %5,%%r10 ; " __syscall
-		: "=a" (ret)
-		: "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3),
-		  "g" (arg4)
-		: __syscall_clobber, "r10" );
-
-	return ret;
-}
-
-static inline long stub_syscall5(long syscall, long arg1, long arg2, long arg3,
-				 long arg4, long arg5)
-{
-	long ret;
-
-	__asm__ volatile ("movq %5,%%r10 ; movq %6,%%r8 ; " __syscall
-		: "=a" (ret)
-		: "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3),
-		  "g" (arg4), "g" (arg5)
-		: __syscall_clobber, "r10", "r8" );
-
-	return ret;
-}
-
-static inline void trap_myself(void)
-{
-	__asm("int3");
-}
-
-static inline void remap_stack(long fd, unsigned long offset)
-{
-	__asm__ volatile ("movq %4,%%r10 ; movq %5,%%r8 ; "
-			  "movq %6, %%r9; " __syscall "; movq %7, %%rbx ; "
-			  "movq %%rax, (%%rbx)":
-			  : "a" (STUB_MMAP_NR), "D" (STUB_DATA),
-			    "S" (UM_KERN_PAGE_SIZE),
-			    "d" (PROT_READ | PROT_WRITE),
-                            "g" (MAP_FIXED | MAP_SHARED), "g" (fd),
-			    "g" (offset),
-			    "i" (&((struct stub_data *) STUB_DATA)->err)
-			  : __syscall_clobber, "r10", "r8", "r9" );
-}
-
-#endif
diff --git a/arch/um/sys-x86_64/shared/sysdep/syscalls.h b/arch/um/sys-x86_64/shared/sysdep/syscalls.h
deleted file mode 100644
index 7cfb0b0..0000000
--- a/arch/um/sys-x86_64/shared/sysdep/syscalls.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#ifndef __SYSDEP_X86_64_SYSCALLS_H__
-#define __SYSDEP_X86_64_SYSCALLS_H__
-
-#include <linux/msg.h>
-#include <linux/shm.h>
-#include <kern_constants.h>
-
-typedef long syscall_handler_t(void);
-
-extern syscall_handler_t *sys_call_table[];
-
-#define EXECUTE_SYSCALL(syscall, regs) \
-	(((long (*)(long, long, long, long, long, long)) \
-	  (*sys_call_table[syscall]))(UPT_SYSCALL_ARG1(&regs->regs), \
-		 		      UPT_SYSCALL_ARG2(&regs->regs), \
-				      UPT_SYSCALL_ARG3(&regs->regs), \
-				      UPT_SYSCALL_ARG4(&regs->regs), \
-				      UPT_SYSCALL_ARG5(&regs->regs), \
-				      UPT_SYSCALL_ARG6(&regs->regs)))
-
-extern long old_mmap(unsigned long addr, unsigned long len,
-		     unsigned long prot, unsigned long flags,
-		     unsigned long fd, unsigned long pgoff);
-extern syscall_handler_t sys_modify_ldt;
-extern syscall_handler_t sys_arch_prctl;
-
-#endif
diff --git a/arch/um/sys-x86_64/shared/sysdep/system.h b/arch/um/sys-x86_64/shared/sysdep/system.h
deleted file mode 100644
index d1b93c4..0000000
--- a/arch/um/sys-x86_64/shared/sysdep/system.h
+++ /dev/null
@@ -1,132 +0,0 @@
-#ifndef _ASM_X86_SYSTEM_H_
-#define _ASM_X86_SYSTEM_H_
-
-#include <asm/asm.h>
-#include <asm/segment.h>
-#include <asm/cpufeature.h>
-#include <asm/cmpxchg.h>
-#include <asm/nops.h>
-
-#include <linux/kernel.h>
-#include <linux/irqflags.h>
-
-/* entries in ARCH_DLINFO: */
-#ifdef CONFIG_IA32_EMULATION
-# define AT_VECTOR_SIZE_ARCH 2
-#else
-# define AT_VECTOR_SIZE_ARCH 1
-#endif
-
-extern unsigned long arch_align_stack(unsigned long sp);
-
-void default_idle(void);
-
-/*
- * Force strict CPU ordering.
- * And yes, this is required on UP too when we're talking
- * to devices.
- */
-#ifdef CONFIG_X86_32
-/*
- * Some non-Intel clones support out of order store. wmb() ceases to be a
- * nop for these.
- */
-#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
-#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
-#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
-#else
-#define mb() 	asm volatile("mfence":::"memory")
-#define rmb()	asm volatile("lfence":::"memory")
-#define wmb()	asm volatile("sfence" ::: "memory")
-#endif
-
-/**
- * read_barrier_depends - Flush all pending reads that subsequents reads
- * depend on.
- *
- * No data-dependent reads from memory-like regions are ever reordered
- * over this barrier.  All reads preceding this primitive are guaranteed
- * to access memory (but not necessarily other CPUs' caches) before any
- * reads following this primitive that depend on the data return by
- * any of the preceding reads.  This primitive is much lighter weight than
- * rmb() on most CPUs, and is never heavier weight than is
- * rmb().
- *
- * These ordering constraints are respected by both the local CPU
- * and the compiler.
- *
- * Ordering is not guaranteed by anything other than these primitives,
- * not even by data dependencies.  See the documentation for
- * memory_barrier() for examples and URLs to more information.
- *
- * For example, the following code would force ordering (the initial
- * value of "a" is zero, "b" is one, and "p" is "&a"):
- *
- * <programlisting>
- *	CPU 0				CPU 1
- *
- *	b = 2;
- *	memory_barrier();
- *	p = &b;				q = p;
- *					read_barrier_depends();
- *					d = *q;
- * </programlisting>
- *
- * because the read of "*q" depends on the read of "p" and these
- * two reads are separated by a read_barrier_depends().  However,
- * the following code, with the same initial values for "a" and "b":
- *
- * <programlisting>
- *	CPU 0				CPU 1
- *
- *	a = 2;
- *	memory_barrier();
- *	b = 3;				y = b;
- *					read_barrier_depends();
- *					x = a;
- * </programlisting>
- *
- * does not enforce ordering, since there is no data dependency between
- * the read of "a" and the read of "b".  Therefore, on some CPUs, such
- * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
- * in cases like this where there are no data dependencies.
- **/
-
-#define read_barrier_depends()	do { } while (0)
-
-#ifdef CONFIG_SMP
-#define smp_mb()	mb()
-#ifdef CONFIG_X86_PPRO_FENCE
-# define smp_rmb()	rmb()
-#else
-# define smp_rmb()	barrier()
-#endif
-#ifdef CONFIG_X86_OOSTORE
-# define smp_wmb() 	wmb()
-#else
-# define smp_wmb()	barrier()
-#endif
-#define smp_read_barrier_depends()	read_barrier_depends()
-#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
-#else
-#define smp_mb()	barrier()
-#define smp_rmb()	barrier()
-#define smp_wmb()	barrier()
-#define smp_read_barrier_depends()	do { } while (0)
-#define set_mb(var, value) do { var = value; barrier(); } while (0)
-#endif
-
-/*
- * Stop RDTSC speculation. This is needed when you need to use RDTSC
- * (or get_cycles or vread that possibly accesses the TSC) in a defined
- * code region.
- *
- * (Could use an alternative three way for this if there was one.)
- */
-static inline void rdtsc_barrier(void)
-{
-	alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC);
-	alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
-}
-
-#endif
diff --git a/arch/um/sys-x86_64/shared/sysdep/tls.h b/arch/um/sys-x86_64/shared/sysdep/tls.h
deleted file mode 100644
index 18c000d..0000000
--- a/arch/um/sys-x86_64/shared/sysdep/tls.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef _SYSDEP_TLS_H
-#define _SYSDEP_TLS_H
-
-# ifndef __KERNEL__
-
-/* Change name to avoid conflicts with the original one from <asm/ldt.h>, which
- * may be named user_desc (but in 2.4 and in header matching its API was named
- * modify_ldt_ldt_s). */
-
-typedef struct um_dup_user_desc {
-	unsigned int  entry_number;
-	unsigned int  base_addr;
-	unsigned int  limit;
-	unsigned int  seg_32bit:1;
-	unsigned int  contents:2;
-	unsigned int  read_exec_only:1;
-	unsigned int  limit_in_pages:1;
-	unsigned int  seg_not_present:1;
-	unsigned int  useable:1;
-	unsigned int  lm:1;
-} user_desc_t;
-
-# else /* __KERNEL__ */
-
-#  include <ldt.h>
-typedef struct user_desc user_desc_t;
-
-# endif /* __KERNEL__ */
-#endif /* _SYSDEP_TLS_H */
diff --git a/arch/um/sys-x86_64/shared/sysdep/vm-flags.h b/arch/um/sys-x86_64/shared/sysdep/vm-flags.h
deleted file mode 100644
index 3978e55..0000000
--- a/arch/um/sys-x86_64/shared/sysdep/vm-flags.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
- * Copyright 2003 PathScale, Inc.
- * Licensed under the GPL
- */
-
-#ifndef __VM_FLAGS_X86_64_H
-#define __VM_FLAGS_X86_64_H
-
-#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
-	VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
-#define VM_STACK_DEFAULT_FLAGS (VM_GROWSDOWN | VM_READ | VM_WRITE | \
-	VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
-
-#endif
diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c
deleted file mode 100644
index b6b65c7..0000000
--- a/arch/um/sys-x86_64/signal.c
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * Copyright (C) 2003 PathScale, Inc.
- * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <linux/personality.h>
-#include <linux/ptrace.h>
-#include <linux/kernel.h>
-#include <asm/unistd.h>
-#include <asm/uaccess.h>
-#include <asm/ucontext.h>
-#include "frame_kern.h"
-#include "skas.h"
-
-void copy_sc(struct uml_pt_regs *regs, void *from)
-{
-	struct sigcontext *sc = from;
-
-#define GETREG(regs, regno, sc, regname)				\
-	(regs)->gp[(regno) / sizeof(unsigned long)] = (sc)->regname
-
-	GETREG(regs, R8, sc, r8);
-	GETREG(regs, R9, sc, r9);
-	GETREG(regs, R10, sc, r10);
-	GETREG(regs, R11, sc, r11);
-	GETREG(regs, R12, sc, r12);
-	GETREG(regs, R13, sc, r13);
-	GETREG(regs, R14, sc, r14);
-	GETREG(regs, R15, sc, r15);
-	GETREG(regs, RDI, sc, di);
-	GETREG(regs, RSI, sc, si);
-	GETREG(regs, RBP, sc, bp);
-	GETREG(regs, RBX, sc, bx);
-	GETREG(regs, RDX, sc, dx);
-	GETREG(regs, RAX, sc, ax);
-	GETREG(regs, RCX, sc, cx);
-	GETREG(regs, RSP, sc, sp);
-	GETREG(regs, RIP, sc, ip);
-	GETREG(regs, EFLAGS, sc, flags);
-	GETREG(regs, CS, sc, cs);
-
-#undef GETREG
-}
-
-static int copy_sc_from_user(struct pt_regs *regs,
-			     struct sigcontext __user *from,
-			     struct _fpstate __user *fpp)
-{
-	struct user_i387_struct fp;
-	int err = 0;
-
-#define GETREG(regs, regno, sc, regname)				\
-	__get_user((regs)->regs.gp[(regno) / sizeof(unsigned long)],	\
-		   &(sc)->regname)
-
-	err |= GETREG(regs, R8, from, r8);
-	err |= GETREG(regs, R9, from, r9);
-	err |= GETREG(regs, R10, from, r10);
-	err |= GETREG(regs, R11, from, r11);
-	err |= GETREG(regs, R12, from, r12);
-	err |= GETREG(regs, R13, from, r13);
-	err |= GETREG(regs, R14, from, r14);
-	err |= GETREG(regs, R15, from, r15);
-	err |= GETREG(regs, RDI, from, di);
-	err |= GETREG(regs, RSI, from, si);
-	err |= GETREG(regs, RBP, from, bp);
-	err |= GETREG(regs, RBX, from, bx);
-	err |= GETREG(regs, RDX, from, dx);
-	err |= GETREG(regs, RAX, from, ax);
-	err |= GETREG(regs, RCX, from, cx);
-	err |= GETREG(regs, RSP, from, sp);
-	err |= GETREG(regs, RIP, from, ip);
-	err |= GETREG(regs, EFLAGS, from, flags);
-	err |= GETREG(regs, CS, from, cs);
-	if (err)
-		return 1;
-
-#undef GETREG
-
-	err = copy_from_user(&fp, fpp, sizeof(struct user_i387_struct));
-	if (err)
-		return 1;
-
-	err = restore_fp_registers(userspace_pid[current_thread_info()->cpu],
-				   (unsigned long *) &fp);
-	if (err < 0) {
-		printk(KERN_ERR "copy_sc_from_user - "
-		       "restore_fp_registers failed, errno = %d\n",
-		       -err);
-		return 1;
-	}
-
-	return 0;
-}
-
-static int copy_sc_to_user(struct sigcontext __user *to,
-			   struct _fpstate __user *to_fp, struct pt_regs *regs,
-			   unsigned long mask, unsigned long sp)
-{
-	struct faultinfo * fi = &current->thread.arch.faultinfo;
-	struct user_i387_struct fp;
-	int err = 0;
-
-	err |= __put_user(0, &to->gs);
-	err |= __put_user(0, &to->fs);
-
-#define PUTREG(regs, regno, sc, regname)				\
-	__put_user((regs)->regs.gp[(regno) / sizeof(unsigned long)],	\
-		   &(sc)->regname)
-
-	err |= PUTREG(regs, RDI, to, di);
-	err |= PUTREG(regs, RSI, to, si);
-	err |= PUTREG(regs, RBP, to, bp);
-	/*
-	 * Must use original RSP, which is passed in, rather than what's in
-	 * the pt_regs, because that's already been updated to point at the
-	 * signal frame.
-	 */
-	err |= __put_user(sp, &to->sp);
-	err |= PUTREG(regs, RBX, to, bx);
-	err |= PUTREG(regs, RDX, to, dx);
-	err |= PUTREG(regs, RCX, to, cx);
-	err |= PUTREG(regs, RAX, to, ax);
-	err |= PUTREG(regs, R8, to, r8);
-	err |= PUTREG(regs, R9, to, r9);
-	err |= PUTREG(regs, R10, to, r10);
-	err |= PUTREG(regs, R11, to, r11);
-	err |= PUTREG(regs, R12, to, r12);
-	err |= PUTREG(regs, R13, to, r13);
-	err |= PUTREG(regs, R14, to, r14);
-	err |= PUTREG(regs, R15, to, r15);
-	err |= PUTREG(regs, CS, to, cs); /* XXX x86_64 doesn't do this */
-
-	err |= __put_user(fi->cr2, &to->cr2);
-	err |= __put_user(fi->error_code, &to->err);
-	err |= __put_user(fi->trap_no, &to->trapno);
-
-	err |= PUTREG(regs, RIP, to, ip);
-	err |= PUTREG(regs, EFLAGS, to, flags);
-#undef PUTREG
-
-	err |= __put_user(mask, &to->oldmask);
-	if (err)
-		return 1;
-
-	err = save_fp_registers(userspace_pid[current_thread_info()->cpu],
-				(unsigned long *) &fp);
-	if (err < 0) {
-		printk(KERN_ERR "copy_sc_from_user - restore_fp_registers "
-		       "failed, errno = %d\n", -err);
-		return 1;
-	}
-
-	if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct)))
-		return 1;
-
-	return err;
-}
-
-struct rt_sigframe
-{
-	char __user *pretcode;
-	struct ucontext uc;
-	struct siginfo info;
-	struct _fpstate fpstate;
-};
-
-int setup_signal_stack_si(unsigned long stack_top, int sig,
-			  struct k_sigaction *ka, struct pt_regs * regs,
-			  siginfo_t *info, sigset_t *set)
-{
-	struct rt_sigframe __user *frame;
-	unsigned long save_sp = PT_REGS_RSP(regs);
-	int err = 0;
-	struct task_struct *me = current;
-
-	frame = (struct rt_sigframe __user *)
-		round_down(stack_top - sizeof(struct rt_sigframe), 16);
-	/* Subtract 128 for a red zone and 8 for proper alignment */
-	frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8);
-
-	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		goto out;
-
-	if (ka->sa.sa_flags & SA_SIGINFO) {
-		err |= copy_siginfo_to_user(&frame->info, info);
-		if (err)
-			goto out;
-	}
-
-	/*
-	 * Update SP now because the page fault handler refuses to extend
-	 * the stack if the faulting address is too far below the current
-	 * SP, which frame now certainly is.  If there's an error, the original
-	 * value is restored on the way out.
-	 * When writing the sigcontext to the stack, we have to write the
-	 * original value, so that's passed to copy_sc_to_user, which does
-	 * the right thing with it.
-	 */
-	PT_REGS_RSP(regs) = (unsigned long) frame;
-
-	/* Create the ucontext.  */
-	err |= __put_user(0, &frame->uc.uc_flags);
-	err |= __put_user(0, &frame->uc.uc_link);
-	err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
-	err |= __put_user(sas_ss_flags(save_sp),
-			  &frame->uc.uc_stack.ss_flags);
-	err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size);
-	err |= copy_sc_to_user(&frame->uc.uc_mcontext, &frame->fpstate, regs,
-			       set->sig[0], save_sp);
-	err |= __put_user(&frame->fpstate, &frame->uc.uc_mcontext.fpstate);
-	if (sizeof(*set) == 16) {
-		__put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]);
-		__put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]);
-	}
-	else
-		err |= __copy_to_user(&frame->uc.uc_sigmask, set,
-				      sizeof(*set));
-
-	/*
-	 * Set up to return from userspace.  If provided, use a stub
-	 * already in userspace.
-	 */
-	/* x86-64 should always use SA_RESTORER. */
-	if (ka->sa.sa_flags & SA_RESTORER)
-		err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
-	else
-		/* could use a vstub here */
-		goto restore_sp;
-
-	if (err)
-		goto restore_sp;
-
-	/* Set up registers for signal handler */
-	{
-		struct exec_domain *ed = current_thread_info()->exec_domain;
-		if (unlikely(ed && ed->signal_invmap && sig < 32))
-			sig = ed->signal_invmap[sig];
-	}
-
-	PT_REGS_RDI(regs) = sig;
-	/* In case the signal handler was declared without prototypes */
-	PT_REGS_RAX(regs) = 0;
-
-	/*
-	 * This also works for non SA_SIGINFO handlers because they expect the
-	 * next argument after the signal number on the stack.
-	 */
-	PT_REGS_RSI(regs) = (unsigned long) &frame->info;
-	PT_REGS_RDX(regs) = (unsigned long) &frame->uc;
-	PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler;
- out:
-	return err;
-
-restore_sp:
-	PT_REGS_RSP(regs) = save_sp;
-	return err;
-}
-
-long sys_rt_sigreturn(struct pt_regs *regs)
-{
-	unsigned long sp = PT_REGS_SP(&current->thread.regs);
-	struct rt_sigframe __user *frame =
-		(struct rt_sigframe __user *)(sp - 8);
-	struct ucontext __user *uc = &frame->uc;
-	sigset_t set;
-
-	if (copy_from_user(&set, &uc->uc_sigmask, sizeof(set)))
-		goto segfault;
-
-	sigdelsetmask(&set, ~_BLOCKABLE);
-
-	spin_lock_irq(&current->sighand->siglock);
-	current->blocked = set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	if (copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext,
-			      &frame->fpstate))
-		goto segfault;
-
-	/* Avoid ERESTART handling */
-	PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
-	return PT_REGS_SYSCALL_RET(&current->thread.regs);
-
- segfault:
-	force_sig(SIGSEGV, current);
-	return 0;
-}
diff --git a/arch/um/sys-x86_64/stub.S b/arch/um/sys-x86_64/stub.S
deleted file mode 100644
index 20e4a96..0000000
--- a/arch/um/sys-x86_64/stub.S
+++ /dev/null
@@ -1,66 +0,0 @@
-#include "as-layout.h"
-
-	.globl syscall_stub
-.section .__syscall_stub, "ax"
-syscall_stub:
-	syscall
-	/* We don't have 64-bit constants, so this constructs the address
-	 * we need.
-	 */
-	movq	$(STUB_DATA >> 32), %rbx
-	salq	$32, %rbx
-	movq	$(STUB_DATA & 0xffffffff), %rcx
-	or	%rcx, %rbx
-	movq	%rax, (%rbx)
-	int3
-
-	.globl batch_syscall_stub
-batch_syscall_stub:
-	mov	$(STUB_DATA >> 32), %rbx
-	sal	$32, %rbx
-	mov	$(STUB_DATA & 0xffffffff), %rax
-	or	%rax, %rbx
-	/* load pointer to first operation */
-	mov	%rbx, %rsp
-	add	$0x10, %rsp
-again:
-	/* load length of additional data */
-	mov	0x0(%rsp), %rax
-
-	/* if(length == 0) : end of list */
-	/* write possible 0 to header */
-	mov	%rax, 8(%rbx)
-	cmp	$0, %rax
-	jz	done
-
-	/* save current pointer */
-	mov	%rsp, 8(%rbx)
-
-	/* skip additional data */
-	add	%rax, %rsp
-
-	/* load syscall-# */
-	pop	%rax
-
-	/* load syscall params */
-	pop	%rdi
-	pop	%rsi
-	pop	%rdx
-	pop	%r10
- 	pop	%r8
-	pop	%r9
-
-	/* execute syscall */
-	syscall
-
-	/* check return value */
-	pop	%rcx
-	cmp	%rcx, %rax
-	je	again
-
-done:
-	/* save return value */
-	mov	%rax, (%rbx)
-
-	/* stop */
-	int3
diff --git a/arch/um/sys-x86_64/stub_segv.c b/arch/um/sys-x86_64/stub_segv.c
deleted file mode 100644
index ced051a..0000000
--- a/arch/um/sys-x86_64/stub_segv.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <signal.h>
-#include "as-layout.h"
-#include "sysdep/stub.h"
-#include "sysdep/faultinfo.h"
-#include "sysdep/sigcontext.h"
-
-void __attribute__ ((__section__ (".__syscall_stub")))
-stub_segv_handler(int sig)
-{
-	struct ucontext *uc;
-
-	__asm__ __volatile__("movq %%rdx, %0" : "=g" (uc) :);
-	GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA),
-			      &uc->uc_mcontext);
-	trap_myself();
-}
-
diff --git a/arch/um/sys-x86_64/syscall_table.c b/arch/um/sys-x86_64/syscall_table.c
deleted file mode 100644
index 47d469e..0000000
--- a/arch/um/sys-x86_64/syscall_table.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * System call table for UML/x86-64, copied from arch/x86_64/kernel/syscall.c
- * with some changes for UML.
- */
-
-#include <linux/linkage.h>
-#include <linux/sys.h>
-#include <linux/cache.h>
-#include <kern_constants.h>
-
-#define __NO_STUBS
-
-/*
- * Below you can see, in terms of #define's, the differences between the x86-64
- * and the UML syscall table.
- */
-
-/* Not going to be implemented by UML, since we have no hardware. */
-#define stub_iopl sys_ni_syscall
-#define sys_ioperm sys_ni_syscall
-
-/*
- * The UML TLS problem. Note that x86_64 does not implement this, so the below
- * is needed only for the ia32 compatibility.
- */
-
-/* On UML we call it this way ("old" means it's not mmap2) */
-#define sys_mmap old_mmap
-
-#define stub_clone sys_clone
-#define stub_fork sys_fork
-#define stub_vfork sys_vfork
-#define stub_execve sys_execve
-#define stub_rt_sigsuspend sys_rt_sigsuspend
-#define stub_sigaltstack sys_sigaltstack
-#define stub_rt_sigreturn sys_rt_sigreturn
-
-#define __SYSCALL(nr, sym) extern asmlinkage void sym(void) ;
-#undef _ASM_X86_UNISTD_64_H
-#include "../../x86/include/asm/unistd_64.h"
-
-#undef __SYSCALL
-#define __SYSCALL(nr, sym) [ nr ] = sym,
-#undef _ASM_X86_UNISTD_64_H
-
-typedef void (*sys_call_ptr_t)(void);
-
-extern void sys_ni_syscall(void);
-
-/*
- * We used to have a trick here which made sure that holes in the
- * x86_64 table were filled in with sys_ni_syscall, but a comment in
- * unistd_64.h says that holes aren't allowed, so the trick was
- * removed.
- * The trick looked like this
- *	[0 ... UM_NR_syscall_max] = &sys_ni_syscall
- * before including unistd_64.h - the later initializations overwrote
- * the sys_ni_syscall filler.
- */
-
-sys_call_ptr_t sys_call_table[] __cacheline_aligned = {
-#include "../../x86/include/asm/unistd_64.h"
-};
-
-int syscall_table_size = sizeof(sys_call_table);
diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c
deleted file mode 100644
index f3d82bb..0000000
--- a/arch/um/sys-x86_64/syscalls.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#include "linux/linkage.h"
-#include "linux/personality.h"
-#include "linux/utsname.h"
-#include "asm/prctl.h" /* XXX This should get the constants from libc */
-#include "asm/uaccess.h"
-#include "os.h"
-
-long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
-{
-	unsigned long *ptr = addr, tmp;
-	long ret;
-	int pid = task->mm->context.id.u.pid;
-
-	/*
-	 * With ARCH_SET_FS (and ARCH_SET_GS is treated similarly to
-	 * be safe), we need to call arch_prctl on the host because
-	 * setting %fs may result in something else happening (like a
-	 * GDT or thread.fs being set instead).  So, we let the host
-	 * fiddle the registers and thread struct and restore the
-	 * registers afterwards.
-	 *
-	 * So, the saved registers are stored to the process (this
-	 * needed because a stub may have been the last thing to run),
-	 * arch_prctl is run on the host, then the registers are read
-	 * back.
-	 */
-	switch (code) {
-	case ARCH_SET_FS:
-	case ARCH_SET_GS:
-		ret = restore_registers(pid, &current->thread.regs.regs);
-		if (ret)
-			return ret;
-		break;
-	case ARCH_GET_FS:
-	case ARCH_GET_GS:
-		/*
-		 * With these two, we read to a local pointer and
-		 * put_user it to the userspace pointer that we were
-		 * given.  If addr isn't valid (because it hasn't been
-		 * faulted in or is just bogus), we want put_user to
-		 * fault it in (or return -EFAULT) instead of having
-		 * the host return -EFAULT.
-		 */
-		ptr = &tmp;
-	}
-
-	ret = os_arch_prctl(pid, code, ptr);
-	if (ret)
-		return ret;
-
-	switch (code) {
-	case ARCH_SET_FS:
-		current->thread.arch.fs = (unsigned long) ptr;
-		ret = save_registers(pid, &current->thread.regs.regs);
-		break;
-	case ARCH_SET_GS:
-		ret = save_registers(pid, &current->thread.regs.regs);
-		break;
-	case ARCH_GET_FS:
-		ret = put_user(tmp, addr);
-		break;
-	case ARCH_GET_GS:
-		ret = put_user(tmp, addr);
-		break;
-	}
-
-	return ret;
-}
-
-long sys_arch_prctl(int code, unsigned long addr)
-{
-	return arch_prctl(current, code, (unsigned long __user *) addr);
-}
-
-long sys_clone(unsigned long clone_flags, unsigned long newsp,
-	       void __user *parent_tid, void __user *child_tid)
-{
-	long ret;
-
-	if (!newsp)
-		newsp = UPT_SP(&current->thread.regs.regs);
-	current->thread.forking = 1;
-	ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
-		      child_tid);
-	current->thread.forking = 0;
-	return ret;
-}
-
-void arch_switch_to(struct task_struct *to)
-{
-	if ((to->thread.arch.fs == 0) || (to->mm == NULL))
-		return;
-
-	arch_prctl(to, ARCH_SET_FS, (void __user *) to->thread.arch.fs);
-}
diff --git a/arch/um/sys-x86_64/sysrq.c b/arch/um/sys-x86_64/sysrq.c
deleted file mode 100644
index f4f82be..0000000
--- a/arch/um/sys-x86_64/sysrq.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/utsname.h>
-#include <asm/current.h>
-#include <asm/ptrace.h>
-#include "sysrq.h"
-
-void __show_regs(struct pt_regs *regs)
-{
-	printk("\n");
-	print_modules();
-	printk(KERN_INFO "Pid: %d, comm: %.20s %s %s\n", task_pid_nr(current),
-		current->comm, print_tainted(), init_utsname()->release);
-	printk(KERN_INFO "RIP: %04lx:[<%016lx>]\n", PT_REGS_CS(regs) & 0xffff,
-	       PT_REGS_RIP(regs));
-	printk(KERN_INFO "RSP: %016lx  EFLAGS: %08lx\n", PT_REGS_RSP(regs),
-	       PT_REGS_EFLAGS(regs));
-	printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n",
-	       PT_REGS_RAX(regs), PT_REGS_RBX(regs), PT_REGS_RCX(regs));
-	printk(KERN_INFO "RDX: %016lx RSI: %016lx RDI: %016lx\n",
-	       PT_REGS_RDX(regs), PT_REGS_RSI(regs), PT_REGS_RDI(regs));
-	printk(KERN_INFO "RBP: %016lx R08: %016lx R09: %016lx\n",
-	       PT_REGS_RBP(regs), PT_REGS_R8(regs), PT_REGS_R9(regs));
-	printk(KERN_INFO "R10: %016lx R11: %016lx R12: %016lx\n",
-	       PT_REGS_R10(regs), PT_REGS_R11(regs), PT_REGS_R12(regs));
-	printk(KERN_INFO "R13: %016lx R14: %016lx R15: %016lx\n",
-	       PT_REGS_R13(regs), PT_REGS_R14(regs), PT_REGS_R15(regs));
-}
-
-void show_regs(struct pt_regs *regs)
-{
-	__show_regs(regs);
-	show_trace(current, (unsigned long *) &regs);
-}
diff --git a/arch/um/sys-x86_64/tls.c b/arch/um/sys-x86_64/tls.c
deleted file mode 100644
index f7ba462..0000000
--- a/arch/um/sys-x86_64/tls.c
+++ /dev/null
@@ -1,17 +0,0 @@
-#include "linux/sched.h"
-
-void clear_flushed_tls(struct task_struct *task)
-{
-}
-
-int arch_copy_tls(struct task_struct *t)
-{
-	/*
-	 * If CLONE_SETTLS is set, we need to save the thread id
-	 * (which is argument 5, child_tid, of clone) so it can be set
-	 * during context switches.
-	 */
-	t->thread.arch.fs = t->thread.regs.regs.gp[R8 / sizeof(long)];
-
-	return 0;
-}
diff --git a/arch/um/sys-x86_64/user-offsets.c b/arch/um/sys-x86_64/user-offsets.c
deleted file mode 100644
index 9735854..0000000
--- a/arch/um/sys-x86_64/user-offsets.c
+++ /dev/null
@@ -1,65 +0,0 @@
-#include <stdio.h>
-#include <stddef.h>
-#include <signal.h>
-#include <sys/poll.h>
-#include <sys/mman.h>
-#include <sys/user.h>
-#define __FRAME_OFFSETS
-#include <asm/ptrace.h>
-#include <asm/types.h>
-
-#define DEFINE(sym, val) \
-        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define DEFINE_LONGS(sym, val) \
-        asm volatile("\n->" #sym " %0 " #val : : "i" (val/sizeof(unsigned long)))
-
-#define OFFSET(sym, str, mem) \
-	DEFINE(sym, offsetof(struct str, mem));
-
-void foo(void)
-{
-	OFFSET(HOST_SC_CR2, sigcontext, cr2);
-	OFFSET(HOST_SC_ERR, sigcontext, err);
-	OFFSET(HOST_SC_TRAPNO, sigcontext, trapno);
-
-	DEFINE(HOST_FP_SIZE, sizeof(struct _fpstate) / sizeof(unsigned long));
-	DEFINE_LONGS(HOST_RBX, RBX);
-	DEFINE_LONGS(HOST_RCX, RCX);
-	DEFINE_LONGS(HOST_RDI, RDI);
-	DEFINE_LONGS(HOST_RSI, RSI);
-	DEFINE_LONGS(HOST_RDX, RDX);
-	DEFINE_LONGS(HOST_RBP, RBP);
-	DEFINE_LONGS(HOST_RAX, RAX);
-	DEFINE_LONGS(HOST_R8, R8);
-	DEFINE_LONGS(HOST_R9, R9);
-	DEFINE_LONGS(HOST_R10, R10);
-	DEFINE_LONGS(HOST_R11, R11);
-	DEFINE_LONGS(HOST_R12, R12);
-	DEFINE_LONGS(HOST_R13, R13);
-	DEFINE_LONGS(HOST_R14, R14);
-	DEFINE_LONGS(HOST_R15, R15);
-	DEFINE_LONGS(HOST_ORIG_RAX, ORIG_RAX);
-	DEFINE_LONGS(HOST_CS, CS);
-	DEFINE_LONGS(HOST_SS, SS);
-	DEFINE_LONGS(HOST_EFLAGS, EFLAGS);
-#if 0
-	DEFINE_LONGS(HOST_FS, FS);
-	DEFINE_LONGS(HOST_GS, GS);
-	DEFINE_LONGS(HOST_DS, DS);
-	DEFINE_LONGS(HOST_ES, ES);
-#endif
-
-	DEFINE_LONGS(HOST_IP, RIP);
-	DEFINE_LONGS(HOST_SP, RSP);
-	DEFINE(UM_FRAME_SIZE, sizeof(struct user_regs_struct));
-
-	/* XXX Duplicated between i386 and x86_64 */
-	DEFINE(UM_POLLIN, POLLIN);
-	DEFINE(UM_POLLPRI, POLLPRI);
-	DEFINE(UM_POLLOUT, POLLOUT);
-
-	DEFINE(UM_PROT_READ, PROT_READ);
-	DEFINE(UM_PROT_WRITE, PROT_WRITE);
-	DEFINE(UM_PROT_EXEC, PROT_EXEC);
-}
diff --git a/arch/um/sys-x86_64/vdso/Makefile b/arch/um/sys-x86_64/vdso/Makefile
deleted file mode 100644
index 5dffe6d..0000000
--- a/arch/um/sys-x86_64/vdso/Makefile
+++ /dev/null
@@ -1,90 +0,0 @@
-#
-# Building vDSO images for x86.
-#
-
-VDSO64-y		:= y
-
-vdso-install-$(VDSO64-y)	+= vdso.so
-
-
-# files to link into the vdso
-vobjs-y := vdso-note.o um_vdso.o
-
-# files to link into kernel
-obj-$(VDSO64-y)			+= vdso.o vma.o
-
-vobjs := $(foreach F,$(vobjs-y),$(obj)/$F)
-
-$(obj)/vdso.o: $(obj)/vdso.so
-
-targets += vdso.so vdso.so.dbg vdso.lds $(vobjs-y)
-
-export CPPFLAGS_vdso.lds += -P -C
-
-VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
-       -Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
-
-$(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so
-
-$(obj)/vdso.so.dbg: $(src)/vdso.lds $(vobjs) FORCE
-	$(call if_changed,vdso)
-
-$(obj)/%.so: OBJCOPYFLAGS := -S
-$(obj)/%.so: $(obj)/%.so.dbg FORCE
-	$(call if_changed,objcopy)
-
-#
-# Don't omit frame pointers for ease of userspace debugging, but do
-# optimize sibling calls.
-#
-CFL := $(PROFILING) -mcmodel=small -fPIC -O2 -fasynchronous-unwind-tables -m64 \
-       $(filter -g%,$(KBUILD_CFLAGS)) $(call cc-option, -fno-stack-protector) \
-       -fno-omit-frame-pointer -foptimize-sibling-calls
-
-$(vobjs): KBUILD_CFLAGS += $(CFL)
-
-#
-# vDSO code runs in userspace and -pg doesn't help with profiling anyway.
-#
-CFLAGS_REMOVE_vdso-note.o = -pg
-CFLAGS_REMOVE_um_vdso.o = -pg
-
-targets += vdso-syms.lds
-obj-$(VDSO64-y)			+= vdso-syms.lds
-
-#
-# Match symbols in the DSO that look like VDSO*; produce a file of constants.
-#
-sed-vdsosym := -e 's/^00*/0/' \
-	-e 's/^\([0-9a-fA-F]*\) . \(VDSO[a-zA-Z0-9_]*\)$$/\2 = 0x\1;/p'
-quiet_cmd_vdsosym = VDSOSYM $@
-define cmd_vdsosym
-	$(NM) $< | LC_ALL=C sed -n $(sed-vdsosym) | LC_ALL=C sort > $@
-endef
-
-$(obj)/%-syms.lds: $(obj)/%.so.dbg FORCE
-	$(call if_changed,vdsosym)
-
-#
-# The DSO images are built using a special linker script.
-#
-quiet_cmd_vdso = VDSO    $@
-      cmd_vdso = $(CC) -nostdlib -o $@ \
-		       $(VDSO_LDFLAGS) $(VDSO_LDFLAGS_$(filter %.lds,$(^F))) \
-		       -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) && \
-		 sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@'
-
-VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
-GCOV_PROFILE := n
-
-#
-# Install the unstripped copy of vdso*.so listed in $(vdso-install-y).
-#
-quiet_cmd_vdso_install = INSTALL $@
-      cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
-$(vdso-install-y): %.so: $(obj)/%.so.dbg FORCE
-	@mkdir -p $(MODLIB)/vdso
-	$(call cmd,vdso_install)
-
-PHONY += vdso_install $(vdso-install-y)
-vdso_install: $(vdso-install-y)
diff --git a/arch/um/sys-x86_64/vdso/checkundef.sh b/arch/um/sys-x86_64/vdso/checkundef.sh
deleted file mode 100644
index 7ee90a9..0000000
--- a/arch/um/sys-x86_64/vdso/checkundef.sh
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh
-nm="$1"
-file="$2"
-$nm "$file" | grep '^ *U' > /dev/null 2>&1
-if [ $? -eq 1 ]; then
-    exit 0
-else
-    echo "$file: undefined symbols found" >&2
-    exit 1
-fi
diff --git a/arch/um/sys-x86_64/vdso/um_vdso.c b/arch/um/sys-x86_64/vdso/um_vdso.c
deleted file mode 100644
index 7c441b5..0000000
--- a/arch/um/sys-x86_64/vdso/um_vdso.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This vDSO turns all calls into a syscall so that UML can trap them.
- */
-
-
-/* Disable profiling for userspace code */
-#define DISABLE_BRANCH_PROFILING
-
-#include <linux/time.h>
-#include <linux/getcpu.h>
-#include <asm/unistd.h>
-
-int __vdso_clock_gettime(clockid_t clock, struct timespec *ts)
-{
-	long ret;
-
-	asm("syscall" : "=a" (ret) :
-		"0" (__NR_clock_gettime), "D" (clock), "S" (ts) : "memory");
-
-	return ret;
-}
-int clock_gettime(clockid_t, struct timespec *)
-	__attribute__((weak, alias("__vdso_clock_gettime")));
-
-int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
-{
-	long ret;
-
-	asm("syscall" : "=a" (ret) :
-		"0" (__NR_gettimeofday), "D" (tv), "S" (tz) : "memory");
-
-	return ret;
-}
-int gettimeofday(struct timeval *, struct timezone *)
-	__attribute__((weak, alias("__vdso_gettimeofday")));
-
-time_t __vdso_time(time_t *t)
-{
-	long secs;
-
-	asm volatile("syscall"
-		: "=a" (secs)
-		: "0" (__NR_time), "D" (t) : "cc", "r11", "cx", "memory");
-
-	return secs;
-}
-int time(time_t *t) __attribute__((weak, alias("__vdso_time")));
-
-long
-__vdso_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *unused)
-{
-	/*
-	 * UML does not support SMP, we can cheat here. :)
-	 */
-
-	if (cpu)
-		*cpu = 0;
-	if (node)
-		*node = 0;
-
-	return 0;
-}
-
-long getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache)
-	__attribute__((weak, alias("__vdso_getcpu")));
diff --git a/arch/um/sys-x86_64/vdso/vdso-layout.lds.S b/arch/um/sys-x86_64/vdso/vdso-layout.lds.S
deleted file mode 100644
index 634a2cf..0000000
--- a/arch/um/sys-x86_64/vdso/vdso-layout.lds.S
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Linker script for vDSO.  This is an ELF shared object prelinked to
- * its virtual address, and with only one read-only segment.
- * This script controls its layout.
- */
-
-SECTIONS
-{
-	. = VDSO_PRELINK + SIZEOF_HEADERS;
-
-	.hash		: { *(.hash) }			:text
-	.gnu.hash	: { *(.gnu.hash) }
-	.dynsym		: { *(.dynsym) }
-	.dynstr		: { *(.dynstr) }
-	.gnu.version	: { *(.gnu.version) }
-	.gnu.version_d	: { *(.gnu.version_d) }
-	.gnu.version_r	: { *(.gnu.version_r) }
-
-	.note		: { *(.note.*) }		:text	:note
-
-	.eh_frame_hdr	: { *(.eh_frame_hdr) }		:text	:eh_frame_hdr
-	.eh_frame	: { KEEP (*(.eh_frame)) }	:text
-
-	.dynamic	: { *(.dynamic) }		:text	:dynamic
-
-	.rodata		: { *(.rodata*) }		:text
-	.data		: {
-	      *(.data*)
-	      *(.sdata*)
-	      *(.got.plt) *(.got)
-	      *(.gnu.linkonce.d.*)
-	      *(.bss*)
-	      *(.dynbss*)
-	      *(.gnu.linkonce.b.*)
-	}
-
-	.altinstructions	: { *(.altinstructions) }
-	.altinstr_replacement	: { *(.altinstr_replacement) }
-
-	/*
-	 * Align the actual code well away from the non-instruction data.
-	 * This is the best thing for the I-cache.
-	 */
-	. = ALIGN(0x100);
-
-	.text		: { *(.text*) }			:text	=0x90909090
-}
-
-/*
- * Very old versions of ld do not recognize this name token; use the constant.
- */
-#define PT_GNU_EH_FRAME	0x6474e550
-
-/*
- * We must supply the ELF program headers explicitly to get just one
- * PT_LOAD segment, and set the flags explicitly to make segments read-only.
- */
-PHDRS
-{
-	text		PT_LOAD		FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */
-	dynamic		PT_DYNAMIC	FLAGS(4);		/* PF_R */
-	note		PT_NOTE		FLAGS(4);		/* PF_R */
-	eh_frame_hdr	PT_GNU_EH_FRAME;
-}
diff --git a/arch/um/sys-x86_64/vdso/vdso-note.S b/arch/um/sys-x86_64/vdso/vdso-note.S
deleted file mode 100644
index 79a071e..0000000
--- a/arch/um/sys-x86_64/vdso/vdso-note.S
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text.
- * Here we can supply some information useful to userland.
- */
-
-#include <linux/uts.h>
-#include <linux/version.h>
-#include <linux/elfnote.h>
-
-ELFNOTE_START(Linux, 0, "a")
-	.long LINUX_VERSION_CODE
-ELFNOTE_END
diff --git a/arch/um/sys-x86_64/vdso/vdso.S b/arch/um/sys-x86_64/vdso/vdso.S
deleted file mode 100644
index ec82c16..0000000
--- a/arch/um/sys-x86_64/vdso/vdso.S
+++ /dev/null
@@ -1,10 +0,0 @@
-#include <linux/init.h>
-
-__INITDATA
-
-	.globl vdso_start, vdso_end
-vdso_start:
-	.incbin "arch/um/sys-x86_64/vdso/vdso.so"
-vdso_end:
-
-__FINIT
diff --git a/arch/um/sys-x86_64/vdso/vdso.lds.S b/arch/um/sys-x86_64/vdso/vdso.lds.S
deleted file mode 100644
index b96b267..0000000
--- a/arch/um/sys-x86_64/vdso/vdso.lds.S
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Linker script for 64-bit vDSO.
- * We #include the file to define the layout details.
- * Here we only choose the prelinked virtual address.
- *
- * This file defines the version script giving the user-exported symbols in
- * the DSO.  We can define local symbols here called VDSO* to make their
- * values visible using the asm-x86/vdso.h macros from the kernel proper.
- */
-
-#define VDSO_PRELINK 0xffffffffff700000
-#include "vdso-layout.lds.S"
-
-/*
- * This controls what userland symbols we export from the vDSO.
- */
-VERSION {
-	LINUX_2.6 {
-	global:
-		clock_gettime;
-		__vdso_clock_gettime;
-		gettimeofday;
-		__vdso_gettimeofday;
-		getcpu;
-		__vdso_getcpu;
-		time;
-		__vdso_time;
-	local: *;
-	};
-}
-
-VDSO64_PRELINK = VDSO_PRELINK;
diff --git a/arch/um/sys-x86_64/vdso/vma.c b/arch/um/sys-x86_64/vdso/vma.c
deleted file mode 100644
index 9495c8d..0000000
--- a/arch/um/sys-x86_64/vdso/vma.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/slab.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <asm/page.h>
-#include <linux/init.h>
-
-unsigned int __read_mostly vdso_enabled = 1;
-unsigned long um_vdso_addr;
-
-extern unsigned long task_size;
-extern char vdso_start[], vdso_end[];
-
-static struct page **vdsop;
-
-static int __init init_vdso(void)
-{
-	struct page *um_vdso;
-
-	BUG_ON(vdso_end - vdso_start > PAGE_SIZE);
-
-	um_vdso_addr = task_size - PAGE_SIZE;
-
-	vdsop = kmalloc(GFP_KERNEL, sizeof(struct page *));
-	if (!vdsop)
-		goto oom;
-
-	um_vdso = alloc_page(GFP_KERNEL);
-	if (!um_vdso) {
-		kfree(vdsop);
-
-		goto oom;
-	}
-
-	copy_page(page_address(um_vdso), vdso_start);
-	*vdsop = um_vdso;
-
-	return 0;
-
-oom:
-	printk(KERN_ERR "Cannot allocate vdso\n");
-	vdso_enabled = 0;
-
-	return -ENOMEM;
-}
-subsys_initcall(init_vdso);
-
-int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
-{
-	int err;
-	struct mm_struct *mm = current->mm;
-
-	if (!vdso_enabled)
-		return 0;
-
-	down_write(&mm->mmap_sem);
-
-	err = install_special_mapping(mm, um_vdso_addr, PAGE_SIZE,
-		VM_READ|VM_EXEC|
-		VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
-		VM_ALWAYSDUMP,
-		vdsop);
-
-	up_write(&mm->mmap_sem);
-
-	return err;
-}
diff --git a/arch/x86/Makefile.um b/arch/x86/Makefile.um
new file mode 100644
index 0000000..36ddec6
--- /dev/null
+++ b/arch/x86/Makefile.um
@@ -0,0 +1,61 @@
+core-y += arch/x86/crypto/
+
+ifeq ($(CONFIG_X86_32),y)
+START := 0x8048000
+
+LDFLAGS			+= -m elf_i386
+ELF_ARCH		:= i386
+ELF_FORMAT 		:= elf32-i386
+CHECKFLAGS	+= -D__i386__
+
+ifeq ("$(origin SUBARCH)", "command line")
+ifneq ("$(shell uname -m | sed -e s/i.86/i386/)", "$(SUBARCH)")
+KBUILD_CFLAGS		+= $(call cc-option,-m32)
+KBUILD_AFLAGS		+= $(call cc-option,-m32)
+LINK-y			+= $(call cc-option,-m32)
+
+export LDFLAGS
+endif
+endif
+
+# First of all, tune CFLAGS for the specific CPU. This actually sets cflags-y.
+include $(srctree)/arch/x86/Makefile_32.cpu
+
+# prevent gcc from keeping the stack 16 byte aligned. Taken from i386.
+cflags-y += $(call cc-option,-mpreferred-stack-boundary=2)
+
+# Prevent sprintf in nfsd from being converted to strcpy and resulting in
+# an unresolved reference.
+cflags-y += -ffreestanding
+
+# Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use
+# a lot more stack due to the lack of sharing of stacklots.  Also, gcc
+# 4.3.0 needs -funit-at-a-time for extern inline functions.
+KBUILD_CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then \
+			echo $(call cc-option,-fno-unit-at-a-time); \
+			else echo $(call cc-option,-funit-at-a-time); fi ;)
+
+KBUILD_CFLAGS += $(cflags-y)
+
+else
+
+START := 0x60000000
+
+KBUILD_CFLAGS += -fno-builtin -m64 
+
+CHECKFLAGS  += -m64 -D__x86_64__
+KBUILD_AFLAGS += -m64
+LDFLAGS += -m elf_x86_64
+KBUILD_CPPFLAGS += -m64
+
+ELF_ARCH := i386:x86-64
+ELF_FORMAT := elf64-x86-64
+
+# Not on all 64-bit distros /lib is a symlink to /lib64. PLD is an example.
+
+LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib64
+LINK-y += -m64
+
+# Do unit-at-a-time unconditionally on x86_64, following the host
+KBUILD_CFLAGS += $(call cc-option,-funit-at-a-time)
+endif
diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile
index c04f1b7..3537d4b 100644
--- a/arch/x86/crypto/Makefile
+++ b/arch/x86/crypto/Makefile
@@ -7,21 +7,33 @@ obj-$(CONFIG_CRYPTO_TWOFISH_586) += twofish-i586.o
 obj-$(CONFIG_CRYPTO_SALSA20_586) += salsa20-i586.o
 
 obj-$(CONFIG_CRYPTO_AES_X86_64) += aes-x86_64.o
+obj-$(CONFIG_CRYPTO_BLOWFISH_X86_64) += blowfish-x86_64.o
 obj-$(CONFIG_CRYPTO_TWOFISH_X86_64) += twofish-x86_64.o
+obj-$(CONFIG_CRYPTO_TWOFISH_X86_64_3WAY) += twofish-x86_64-3way.o
 obj-$(CONFIG_CRYPTO_SALSA20_X86_64) += salsa20-x86_64.o
 obj-$(CONFIG_CRYPTO_AES_NI_INTEL) += aesni-intel.o
 obj-$(CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL) += ghash-clmulni-intel.o
 
 obj-$(CONFIG_CRYPTO_CRC32C_INTEL) += crc32c-intel.o
+obj-$(CONFIG_CRYPTO_SHA1_SSSE3) += sha1-ssse3.o
 
 aes-i586-y := aes-i586-asm_32.o aes_glue.o
 twofish-i586-y := twofish-i586-asm_32.o twofish_glue.o
 salsa20-i586-y := salsa20-i586-asm_32.o salsa20_glue.o
 
 aes-x86_64-y := aes-x86_64-asm_64.o aes_glue.o
+blowfish-x86_64-y := blowfish-x86_64-asm_64.o blowfish_glue.o
 twofish-x86_64-y := twofish-x86_64-asm_64.o twofish_glue.o
+twofish-x86_64-3way-y := twofish-x86_64-asm_64-3way.o twofish_glue_3way.o
 salsa20-x86_64-y := salsa20-x86_64-asm_64.o salsa20_glue.o
 
 aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o fpu.o
 
 ghash-clmulni-intel-y := ghash-clmulni-intel_asm.o ghash-clmulni-intel_glue.o
+
+# enable AVX support only when $(AS) can actually assemble the instructions
+ifeq ($(call as-instr,vpxor %xmm0$(comma)%xmm1$(comma)%xmm2,yes,no),yes)
+AFLAGS_sha1_ssse3_asm.o += -DSHA1_ENABLE_AVX_SUPPORT
+CFLAGS_sha1_ssse3_glue.o += -DSHA1_ENABLE_AVX_SUPPORT
+endif
+sha1-ssse3-y := sha1_ssse3_asm.o sha1_ssse3_glue.o
diff --git a/arch/x86/crypto/aes_glue.c b/arch/x86/crypto/aes_glue.c
index 49ae9fe..b0b6950 100644
--- a/arch/x86/crypto/aes_glue.c
+++ b/arch/x86/crypto/aes_glue.c
@@ -4,6 +4,7 @@
  */
 
 #include <crypto/aes.h>
+#include <asm/aes.h>
 
 asmlinkage void aes_enc_blk(struct crypto_aes_ctx *ctx, u8 *out, const u8 *in);
 asmlinkage void aes_dec_blk(struct crypto_aes_ctx *ctx, u8 *out, const u8 *in);
diff --git a/arch/x86/crypto/blowfish-x86_64-asm_64.S b/arch/x86/crypto/blowfish-x86_64-asm_64.S
new file mode 100644
index 0000000..391d245
--- /dev/null
+++ b/arch/x86/crypto/blowfish-x86_64-asm_64.S
@@ -0,0 +1,390 @@
+/*
+ * Blowfish Cipher Algorithm (x86_64)
+ *
+ * Copyright (C) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ * USA
+ *
+ */
+
+.file "blowfish-x86_64-asm.S"
+.text
+
+/* structure of crypto context */
+#define p	0
+#define s0	((16 + 2) * 4)
+#define s1	((16 + 2 + (1 * 256)) * 4)
+#define s2	((16 + 2 + (2 * 256)) * 4)
+#define s3	((16 + 2 + (3 * 256)) * 4)
+
+/* register macros */
+#define CTX %rdi
+#define RIO %rsi
+
+#define RX0 %rax
+#define RX1 %rbx
+#define RX2 %rcx
+#define RX3 %rdx
+
+#define RX0d %eax
+#define RX1d %ebx
+#define RX2d %ecx
+#define RX3d %edx
+
+#define RX0bl %al
+#define RX1bl %bl
+#define RX2bl %cl
+#define RX3bl %dl
+
+#define RX0bh %ah
+#define RX1bh %bh
+#define RX2bh %ch
+#define RX3bh %dh
+
+#define RT0 %rbp
+#define RT1 %rsi
+#define RT2 %r8
+#define RT3 %r9
+
+#define RT0d %ebp
+#define RT1d %esi
+#define RT2d %r8d
+#define RT3d %r9d
+
+#define RKEY %r10
+
+/***********************************************************************
+ * 1-way blowfish
+ ***********************************************************************/
+#define F() \
+	rorq $16,		RX0; \
+	movzbl RX0bh,		RT0d; \
+	movzbl RX0bl,		RT1d; \
+	rolq $16,		RX0; \
+	movl s0(CTX,RT0,4),	RT0d; \
+	addl s1(CTX,RT1,4),	RT0d; \
+	movzbl RX0bh,		RT1d; \
+	movzbl RX0bl,		RT2d; \
+	rolq $32,		RX0; \
+	xorl s2(CTX,RT1,4),	RT0d; \
+	addl s3(CTX,RT2,4),	RT0d; \
+	xorq RT0,		RX0;
+
+#define add_roundkey_enc(n) \
+	xorq p+4*(n)(CTX), 	RX0;
+
+#define round_enc(n) \
+	add_roundkey_enc(n); \
+	\
+	F(); \
+	F();
+
+#define add_roundkey_dec(n) \
+	movq p+4*(n-1)(CTX),	RT0; \
+	rorq $32,		RT0; \
+	xorq RT0,		RX0;
+
+#define round_dec(n) \
+	add_roundkey_dec(n); \
+	\
+	F(); \
+	F(); \
+
+#define read_block() \
+	movq (RIO), 		RX0; \
+	rorq $32, 		RX0; \
+	bswapq 			RX0;
+
+#define write_block() \
+	bswapq 			RX0; \
+	movq RX0, 		(RIO);
+
+#define xor_block() \
+	bswapq 			RX0; \
+	xorq RX0, 		(RIO);
+
+.align 8
+.global __blowfish_enc_blk
+.type   __blowfish_enc_blk,@function;
+
+__blowfish_enc_blk:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 *	%rcx: bool, if true: xor output
+	 */
+	movq %rbp, %r11;
+
+	movq %rsi, %r10;
+	movq %rdx, RIO;
+
+	read_block();
+
+	round_enc(0);
+	round_enc(2);
+	round_enc(4);
+	round_enc(6);
+	round_enc(8);
+	round_enc(10);
+	round_enc(12);
+	round_enc(14);
+	add_roundkey_enc(16);
+
+	movq %r11, %rbp;
+
+	movq %r10, RIO;
+	test %cl, %cl;
+	jnz __enc_xor;
+
+	write_block();
+	ret;
+__enc_xor:
+	xor_block();
+	ret;
+
+.align 8
+.global blowfish_dec_blk
+.type   blowfish_dec_blk,@function;
+
+blowfish_dec_blk:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 */
+	movq %rbp, %r11;
+
+	movq %rsi, %r10;
+	movq %rdx, RIO;
+
+	read_block();
+
+	round_dec(17);
+	round_dec(15);
+	round_dec(13);
+	round_dec(11);
+	round_dec(9);
+	round_dec(7);
+	round_dec(5);
+	round_dec(3);
+	add_roundkey_dec(1);
+
+	movq %r10, RIO;
+	write_block();
+
+	movq %r11, %rbp;
+
+	ret;
+
+/**********************************************************************
+  4-way blowfish, four blocks parallel
+ **********************************************************************/
+
+/* F() for 4-way. Slower when used alone/1-way, but faster when used
+ * parallel/4-way (tested on AMD Phenom II & Intel Xeon E7330).
+ */
+#define F4(x) \
+	movzbl x ## bh,		RT1d; \
+	movzbl x ## bl,		RT3d; \
+	rorq $16,		x; \
+	movzbl x ## bh,		RT0d; \
+	movzbl x ## bl,		RT2d; \
+	rorq $16,		x; \
+	movl s0(CTX,RT0,4),	RT0d; \
+	addl s1(CTX,RT2,4),	RT0d; \
+	xorl s2(CTX,RT1,4),	RT0d; \
+	addl s3(CTX,RT3,4),	RT0d; \
+	xorq RT0,		x;
+
+#define add_preloaded_roundkey4() \
+	xorq RKEY,		RX0; \
+	xorq RKEY,		RX1; \
+	xorq RKEY,		RX2; \
+	xorq RKEY,		RX3;
+
+#define preload_roundkey_enc(n) \
+	movq p+4*(n)(CTX),	RKEY;
+
+#define add_roundkey_enc4(n) \
+	add_preloaded_roundkey4(); \
+	preload_roundkey_enc(n + 2);
+
+#define round_enc4(n) \
+	add_roundkey_enc4(n); \
+	\
+	F4(RX0); \
+	F4(RX1); \
+	F4(RX2); \
+	F4(RX3); \
+	\
+	F4(RX0); \
+	F4(RX1); \
+	F4(RX2); \
+	F4(RX3);
+
+#define preload_roundkey_dec(n) \
+	movq p+4*((n)-1)(CTX),	RKEY; \
+	rorq $32,		RKEY;
+
+#define add_roundkey_dec4(n) \
+	add_preloaded_roundkey4(); \
+	preload_roundkey_dec(n - 2);
+
+#define round_dec4(n) \
+	add_roundkey_dec4(n); \
+	\
+	F4(RX0); \
+	F4(RX1); \
+	F4(RX2); \
+	F4(RX3); \
+	\
+	F4(RX0); \
+	F4(RX1); \
+	F4(RX2); \
+	F4(RX3);
+
+#define read_block4() \
+	movq (RIO),		RX0; \
+	rorq $32,		RX0; \
+	bswapq 			RX0; \
+	\
+	movq 8(RIO),		RX1; \
+	rorq $32,		RX1; \
+	bswapq 			RX1; \
+	\
+	movq 16(RIO),		RX2; \
+	rorq $32,		RX2; \
+	bswapq 			RX2; \
+	\
+	movq 24(RIO),		RX3; \
+	rorq $32,		RX3; \
+	bswapq 			RX3;
+
+#define write_block4() \
+	bswapq 			RX0; \
+	movq RX0,		(RIO); \
+	\
+	bswapq 			RX1; \
+	movq RX1,		8(RIO); \
+	\
+	bswapq 			RX2; \
+	movq RX2,		16(RIO); \
+	\
+	bswapq 			RX3; \
+	movq RX3,		24(RIO);
+
+#define xor_block4() \
+	bswapq 			RX0; \
+	xorq RX0,		(RIO); \
+	\
+	bswapq 			RX1; \
+	xorq RX1,		8(RIO); \
+	\
+	bswapq 			RX2; \
+	xorq RX2,		16(RIO); \
+	\
+	bswapq 			RX3; \
+	xorq RX3,		24(RIO);
+
+.align 8
+.global __blowfish_enc_blk_4way
+.type   __blowfish_enc_blk_4way,@function;
+
+__blowfish_enc_blk_4way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 *	%rcx: bool, if true: xor output
+	 */
+	pushq %rbp;
+	pushq %rbx;
+	pushq %rcx;
+
+	preload_roundkey_enc(0);
+
+	movq %rsi, %r11;
+	movq %rdx, RIO;
+
+	read_block4();
+
+	round_enc4(0);
+	round_enc4(2);
+	round_enc4(4);
+	round_enc4(6);
+	round_enc4(8);
+	round_enc4(10);
+	round_enc4(12);
+	round_enc4(14);
+	add_preloaded_roundkey4();
+
+	popq %rbp;
+	movq %r11, RIO;
+
+	test %bpl, %bpl;
+	jnz __enc_xor4;
+
+	write_block4();
+
+	popq %rbx;
+	popq %rbp;
+	ret;
+
+__enc_xor4:
+	xor_block4();
+
+	popq %rbx;
+	popq %rbp;
+	ret;
+
+.align 8
+.global blowfish_dec_blk_4way
+.type   blowfish_dec_blk_4way,@function;
+
+blowfish_dec_blk_4way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 */
+	pushq %rbp;
+	pushq %rbx;
+	preload_roundkey_dec(17);
+
+	movq %rsi, %r11;
+	movq %rdx, RIO;
+
+	read_block4();
+
+	round_dec4(17);
+	round_dec4(15);
+	round_dec4(13);
+	round_dec4(11);
+	round_dec4(9);
+	round_dec4(7);
+	round_dec4(5);
+	round_dec4(3);
+	add_preloaded_roundkey4();
+
+	movq %r11, RIO;
+	write_block4();
+
+	popq %rbx;
+	popq %rbp;
+
+	ret;
+
diff --git a/arch/x86/crypto/blowfish_glue.c b/arch/x86/crypto/blowfish_glue.c
new file mode 100644
index 0000000..b05aa16
--- /dev/null
+++ b/arch/x86/crypto/blowfish_glue.c
@@ -0,0 +1,492 @@
+/*
+ * Glue Code for assembler optimized version of Blowfish
+ *
+ * Copyright (c) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ * CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by:
+ *   Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
+ * CTR part based on code (crypto/ctr.c) by:
+ *   (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ * USA
+ *
+ */
+
+#include <crypto/blowfish.h>
+#include <linux/crypto.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <crypto/algapi.h>
+
+/* regular block cipher functions */
+asmlinkage void __blowfish_enc_blk(struct bf_ctx *ctx, u8 *dst, const u8 *src,
+				   bool xor);
+asmlinkage void blowfish_dec_blk(struct bf_ctx *ctx, u8 *dst, const u8 *src);
+
+/* 4-way parallel cipher functions */
+asmlinkage void __blowfish_enc_blk_4way(struct bf_ctx *ctx, u8 *dst,
+					const u8 *src, bool xor);
+asmlinkage void blowfish_dec_blk_4way(struct bf_ctx *ctx, u8 *dst,
+				      const u8 *src);
+
+static inline void blowfish_enc_blk(struct bf_ctx *ctx, u8 *dst, const u8 *src)
+{
+	__blowfish_enc_blk(ctx, dst, src, false);
+}
+
+static inline void blowfish_enc_blk_xor(struct bf_ctx *ctx, u8 *dst,
+					const u8 *src)
+{
+	__blowfish_enc_blk(ctx, dst, src, true);
+}
+
+static inline void blowfish_enc_blk_4way(struct bf_ctx *ctx, u8 *dst,
+					 const u8 *src)
+{
+	__blowfish_enc_blk_4way(ctx, dst, src, false);
+}
+
+static inline void blowfish_enc_blk_xor_4way(struct bf_ctx *ctx, u8 *dst,
+				      const u8 *src)
+{
+	__blowfish_enc_blk_4way(ctx, dst, src, true);
+}
+
+static void blowfish_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	blowfish_enc_blk(crypto_tfm_ctx(tfm), dst, src);
+}
+
+static void blowfish_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	blowfish_dec_blk(crypto_tfm_ctx(tfm), dst, src);
+}
+
+static struct crypto_alg bf_alg = {
+	.cra_name		=	"blowfish",
+	.cra_driver_name	=	"blowfish-asm",
+	.cra_priority		=	200,
+	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize		=	BF_BLOCK_SIZE,
+	.cra_ctxsize		=	sizeof(struct bf_ctx),
+	.cra_alignmask		=	3,
+	.cra_module		=	THIS_MODULE,
+	.cra_list		=	LIST_HEAD_INIT(bf_alg.cra_list),
+	.cra_u			=	{
+		.cipher = {
+			.cia_min_keysize	=	BF_MIN_KEY_SIZE,
+			.cia_max_keysize	=	BF_MAX_KEY_SIZE,
+			.cia_setkey		=	blowfish_setkey,
+			.cia_encrypt		=	blowfish_encrypt,
+			.cia_decrypt		=	blowfish_decrypt,
+		}
+	}
+};
+
+static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk,
+		     void (*fn)(struct bf_ctx *, u8 *, const u8 *),
+		     void (*fn_4way)(struct bf_ctx *, u8 *, const u8 *))
+{
+	struct bf_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	unsigned int bsize = BF_BLOCK_SIZE;
+	unsigned int nbytes;
+	int err;
+
+	err = blkcipher_walk_virt(desc, walk);
+
+	while ((nbytes = walk->nbytes)) {
+		u8 *wsrc = walk->src.virt.addr;
+		u8 *wdst = walk->dst.virt.addr;
+
+		/* Process four block batch */
+		if (nbytes >= bsize * 4) {
+			do {
+				fn_4way(ctx, wdst, wsrc);
+
+				wsrc += bsize * 4;
+				wdst += bsize * 4;
+				nbytes -= bsize * 4;
+			} while (nbytes >= bsize * 4);
+
+			if (nbytes < bsize)
+				goto done;
+		}
+
+		/* Handle leftovers */
+		do {
+			fn(ctx, wdst, wsrc);
+
+			wsrc += bsize;
+			wdst += bsize;
+			nbytes -= bsize;
+		} while (nbytes >= bsize);
+
+done:
+		err = blkcipher_walk_done(desc, walk, nbytes);
+	}
+
+	return err;
+}
+
+static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	return ecb_crypt(desc, &walk, blowfish_enc_blk, blowfish_enc_blk_4way);
+}
+
+static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	return ecb_crypt(desc, &walk, blowfish_dec_blk, blowfish_dec_blk_4way);
+}
+
+static struct crypto_alg blk_ecb_alg = {
+	.cra_name		= "ecb(blowfish)",
+	.cra_driver_name	= "ecb-blowfish-asm",
+	.cra_priority		= 300,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= BF_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct bf_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(blk_ecb_alg.cra_list),
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= BF_MIN_KEY_SIZE,
+			.max_keysize	= BF_MAX_KEY_SIZE,
+			.setkey		= blowfish_setkey,
+			.encrypt	= ecb_encrypt,
+			.decrypt	= ecb_decrypt,
+		},
+	},
+};
+
+static unsigned int __cbc_encrypt(struct blkcipher_desc *desc,
+				  struct blkcipher_walk *walk)
+{
+	struct bf_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	unsigned int bsize = BF_BLOCK_SIZE;
+	unsigned int nbytes = walk->nbytes;
+	u64 *src = (u64 *)walk->src.virt.addr;
+	u64 *dst = (u64 *)walk->dst.virt.addr;
+	u64 *iv = (u64 *)walk->iv;
+
+	do {
+		*dst = *src ^ *iv;
+		blowfish_enc_blk(ctx, (u8 *)dst, (u8 *)dst);
+		iv = dst;
+
+		src += 1;
+		dst += 1;
+		nbytes -= bsize;
+	} while (nbytes >= bsize);
+
+	*(u64 *)walk->iv = *iv;
+	return nbytes;
+}
+
+static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	while ((nbytes = walk.nbytes)) {
+		nbytes = __cbc_encrypt(desc, &walk);
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+
+	return err;
+}
+
+static unsigned int __cbc_decrypt(struct blkcipher_desc *desc,
+				  struct blkcipher_walk *walk)
+{
+	struct bf_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	unsigned int bsize = BF_BLOCK_SIZE;
+	unsigned int nbytes = walk->nbytes;
+	u64 *src = (u64 *)walk->src.virt.addr;
+	u64 *dst = (u64 *)walk->dst.virt.addr;
+	u64 ivs[4 - 1];
+	u64 last_iv;
+
+	/* Start of the last block. */
+	src += nbytes / bsize - 1;
+	dst += nbytes / bsize - 1;
+
+	last_iv = *src;
+
+	/* Process four block batch */
+	if (nbytes >= bsize * 4) {
+		do {
+			nbytes -= bsize * 4 - bsize;
+			src -= 4 - 1;
+			dst -= 4 - 1;
+
+			ivs[0] = src[0];
+			ivs[1] = src[1];
+			ivs[2] = src[2];
+
+			blowfish_dec_blk_4way(ctx, (u8 *)dst, (u8 *)src);
+
+			dst[1] ^= ivs[0];
+			dst[2] ^= ivs[1];
+			dst[3] ^= ivs[2];
+
+			nbytes -= bsize;
+			if (nbytes < bsize)
+				goto done;
+
+			*dst ^= *(src - 1);
+			src -= 1;
+			dst -= 1;
+		} while (nbytes >= bsize * 4);
+
+		if (nbytes < bsize)
+			goto done;
+	}
+
+	/* Handle leftovers */
+	for (;;) {
+		blowfish_dec_blk(ctx, (u8 *)dst, (u8 *)src);
+
+		nbytes -= bsize;
+		if (nbytes < bsize)
+			break;
+
+		*dst ^= *(src - 1);
+		src -= 1;
+		dst -= 1;
+	}
+
+done:
+	*dst ^= *(u64 *)walk->iv;
+	*(u64 *)walk->iv = last_iv;
+
+	return nbytes;
+}
+
+static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	while ((nbytes = walk.nbytes)) {
+		nbytes = __cbc_decrypt(desc, &walk);
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+
+	return err;
+}
+
+static struct crypto_alg blk_cbc_alg = {
+	.cra_name		= "cbc(blowfish)",
+	.cra_driver_name	= "cbc-blowfish-asm",
+	.cra_priority		= 300,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= BF_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct bf_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(blk_cbc_alg.cra_list),
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= BF_MIN_KEY_SIZE,
+			.max_keysize	= BF_MAX_KEY_SIZE,
+			.ivsize		= BF_BLOCK_SIZE,
+			.setkey		= blowfish_setkey,
+			.encrypt	= cbc_encrypt,
+			.decrypt	= cbc_decrypt,
+		},
+	},
+};
+
+static void ctr_crypt_final(struct bf_ctx *ctx, struct blkcipher_walk *walk)
+{
+	u8 *ctrblk = walk->iv;
+	u8 keystream[BF_BLOCK_SIZE];
+	u8 *src = walk->src.virt.addr;
+	u8 *dst = walk->dst.virt.addr;
+	unsigned int nbytes = walk->nbytes;
+
+	blowfish_enc_blk(ctx, keystream, ctrblk);
+	crypto_xor(keystream, src, nbytes);
+	memcpy(dst, keystream, nbytes);
+
+	crypto_inc(ctrblk, BF_BLOCK_SIZE);
+}
+
+static unsigned int __ctr_crypt(struct blkcipher_desc *desc,
+				struct blkcipher_walk *walk)
+{
+	struct bf_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	unsigned int bsize = BF_BLOCK_SIZE;
+	unsigned int nbytes = walk->nbytes;
+	u64 *src = (u64 *)walk->src.virt.addr;
+	u64 *dst = (u64 *)walk->dst.virt.addr;
+	u64 ctrblk = be64_to_cpu(*(__be64 *)walk->iv);
+	__be64 ctrblocks[4];
+
+	/* Process four block batch */
+	if (nbytes >= bsize * 4) {
+		do {
+			if (dst != src) {
+				dst[0] = src[0];
+				dst[1] = src[1];
+				dst[2] = src[2];
+				dst[3] = src[3];
+			}
+
+			/* create ctrblks for parallel encrypt */
+			ctrblocks[0] = cpu_to_be64(ctrblk++);
+			ctrblocks[1] = cpu_to_be64(ctrblk++);
+			ctrblocks[2] = cpu_to_be64(ctrblk++);
+			ctrblocks[3] = cpu_to_be64(ctrblk++);
+
+			blowfish_enc_blk_xor_4way(ctx, (u8 *)dst,
+						  (u8 *)ctrblocks);
+
+			src += 4;
+			dst += 4;
+		} while ((nbytes -= bsize * 4) >= bsize * 4);
+
+		if (nbytes < bsize)
+			goto done;
+	}
+
+	/* Handle leftovers */
+	do {
+		if (dst != src)
+			*dst = *src;
+
+		ctrblocks[0] = cpu_to_be64(ctrblk++);
+
+		blowfish_enc_blk_xor(ctx, (u8 *)dst, (u8 *)ctrblocks);
+
+		src += 1;
+		dst += 1;
+	} while ((nbytes -= bsize) >= bsize);
+
+done:
+	*(__be64 *)walk->iv = cpu_to_be64(ctrblk);
+	return nbytes;
+}
+
+static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		     struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt_block(desc, &walk, BF_BLOCK_SIZE);
+
+	while ((nbytes = walk.nbytes) >= BF_BLOCK_SIZE) {
+		nbytes = __ctr_crypt(desc, &walk);
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+
+	if (walk.nbytes) {
+		ctr_crypt_final(crypto_blkcipher_ctx(desc->tfm), &walk);
+		err = blkcipher_walk_done(desc, &walk, 0);
+	}
+
+	return err;
+}
+
+static struct crypto_alg blk_ctr_alg = {
+	.cra_name		= "ctr(blowfish)",
+	.cra_driver_name	= "ctr-blowfish-asm",
+	.cra_priority		= 300,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= 1,
+	.cra_ctxsize		= sizeof(struct bf_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(blk_ctr_alg.cra_list),
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= BF_MIN_KEY_SIZE,
+			.max_keysize	= BF_MAX_KEY_SIZE,
+			.ivsize		= BF_BLOCK_SIZE,
+			.setkey		= blowfish_setkey,
+			.encrypt	= ctr_crypt,
+			.decrypt	= ctr_crypt,
+		},
+	},
+};
+
+static int __init init(void)
+{
+	int err;
+
+	err = crypto_register_alg(&bf_alg);
+	if (err)
+		goto bf_err;
+	err = crypto_register_alg(&blk_ecb_alg);
+	if (err)
+		goto ecb_err;
+	err = crypto_register_alg(&blk_cbc_alg);
+	if (err)
+		goto cbc_err;
+	err = crypto_register_alg(&blk_ctr_alg);
+	if (err)
+		goto ctr_err;
+
+	return 0;
+
+ctr_err:
+	crypto_unregister_alg(&blk_cbc_alg);
+cbc_err:
+	crypto_unregister_alg(&blk_ecb_alg);
+ecb_err:
+	crypto_unregister_alg(&bf_alg);
+bf_err:
+	return err;
+}
+
+static void __exit fini(void)
+{
+	crypto_unregister_alg(&blk_ctr_alg);
+	crypto_unregister_alg(&blk_cbc_alg);
+	crypto_unregister_alg(&blk_ecb_alg);
+	crypto_unregister_alg(&bf_alg);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Blowfish Cipher Algorithm, asm optimized");
+MODULE_ALIAS("blowfish");
+MODULE_ALIAS("blowfish-asm");
diff --git a/arch/x86/crypto/sha1_ssse3_asm.S b/arch/x86/crypto/sha1_ssse3_asm.S
new file mode 100644
index 0000000..b2c2f57
--- /dev/null
+++ b/arch/x86/crypto/sha1_ssse3_asm.S
@@ -0,0 +1,558 @@
+/*
+ * This is a SIMD SHA-1 implementation. It requires the Intel(R) Supplemental
+ * SSE3 instruction set extensions introduced in Intel Core Microarchitecture
+ * processors. CPUs supporting Intel(R) AVX extensions will get an additional
+ * boost.
+ *
+ * This work was inspired by the vectorized implementation of Dean Gaudet.
+ * Additional information on it can be found at:
+ *    http://www.arctic.org/~dean/crypto/sha1.html
+ *
+ * It was improved upon with more efficient vectorization of the message
+ * scheduling. This implementation has also been optimized for all current and
+ * several future generations of Intel CPUs.
+ *
+ * See this article for more information about the implementation details:
+ *   http://software.intel.com/en-us/articles/improving-the-performance-of-the-secure-hash-algorithm-1/
+ *
+ * Copyright (C) 2010, Intel Corp.
+ *   Authors: Maxim Locktyukhin <maxim.locktyukhin@intel.com>
+ *            Ronen Zohar <ronen.zohar@intel.com>
+ *
+ * Converted to AT&T syntax and adapted for inclusion in the Linux kernel:
+ *   Author: Mathias Krause <minipli@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#define CTX	%rdi	// arg1
+#define BUF	%rsi	// arg2
+#define CNT	%rdx	// arg3
+
+#define REG_A	%ecx
+#define REG_B	%esi
+#define REG_C	%edi
+#define REG_D	%ebp
+#define REG_E	%edx
+
+#define REG_T1	%eax
+#define REG_T2	%ebx
+
+#define K_BASE		%r8
+#define HASH_PTR	%r9
+#define BUFFER_PTR	%r10
+#define BUFFER_END	%r11
+
+#define W_TMP1	%xmm0
+#define W_TMP2	%xmm9
+
+#define W0	%xmm1
+#define W4	%xmm2
+#define W8	%xmm3
+#define W12	%xmm4
+#define W16	%xmm5
+#define W20	%xmm6
+#define W24	%xmm7
+#define W28	%xmm8
+
+#define XMM_SHUFB_BSWAP	%xmm10
+
+/* we keep window of 64 w[i]+K pre-calculated values in a circular buffer */
+#define WK(t)	(((t) & 15) * 4)(%rsp)
+#define W_PRECALC_AHEAD	16
+
+/*
+ * This macro implements the SHA-1 function's body for single 64-byte block
+ * param: function's name
+ */
+.macro SHA1_VECTOR_ASM  name
+	.global	\name
+	.type	\name, @function
+	.align 32
+\name:
+	push	%rbx
+	push	%rbp
+	push	%r12
+
+	mov	%rsp, %r12
+	sub	$64, %rsp		# allocate workspace
+	and	$~15, %rsp		# align stack
+
+	mov	CTX, HASH_PTR
+	mov	BUF, BUFFER_PTR
+
+	shl	$6, CNT			# multiply by 64
+	add	BUF, CNT
+	mov	CNT, BUFFER_END
+
+	lea	K_XMM_AR(%rip), K_BASE
+	xmm_mov	BSWAP_SHUFB_CTL(%rip), XMM_SHUFB_BSWAP
+
+	SHA1_PIPELINED_MAIN_BODY
+
+	# cleanup workspace
+	mov	$8, %ecx
+	mov	%rsp, %rdi
+	xor	%rax, %rax
+	rep stosq
+
+	mov	%r12, %rsp		# deallocate workspace
+
+	pop	%r12
+	pop	%rbp
+	pop	%rbx
+	ret
+
+	.size	\name, .-\name
+.endm
+
+/*
+ * This macro implements 80 rounds of SHA-1 for one 64-byte block
+ */
+.macro SHA1_PIPELINED_MAIN_BODY
+	INIT_REGALLOC
+
+	mov	  (HASH_PTR), A
+	mov	 4(HASH_PTR), B
+	mov	 8(HASH_PTR), C
+	mov	12(HASH_PTR), D
+	mov	16(HASH_PTR), E
+
+  .set i, 0
+  .rept W_PRECALC_AHEAD
+	W_PRECALC i
+    .set i, (i+1)
+  .endr
+
+.align 4
+1:
+	RR F1,A,B,C,D,E,0
+	RR F1,D,E,A,B,C,2
+	RR F1,B,C,D,E,A,4
+	RR F1,E,A,B,C,D,6
+	RR F1,C,D,E,A,B,8
+
+	RR F1,A,B,C,D,E,10
+	RR F1,D,E,A,B,C,12
+	RR F1,B,C,D,E,A,14
+	RR F1,E,A,B,C,D,16
+	RR F1,C,D,E,A,B,18
+
+	RR F2,A,B,C,D,E,20
+	RR F2,D,E,A,B,C,22
+	RR F2,B,C,D,E,A,24
+	RR F2,E,A,B,C,D,26
+	RR F2,C,D,E,A,B,28
+
+	RR F2,A,B,C,D,E,30
+	RR F2,D,E,A,B,C,32
+	RR F2,B,C,D,E,A,34
+	RR F2,E,A,B,C,D,36
+	RR F2,C,D,E,A,B,38
+
+	RR F3,A,B,C,D,E,40
+	RR F3,D,E,A,B,C,42
+	RR F3,B,C,D,E,A,44
+	RR F3,E,A,B,C,D,46
+	RR F3,C,D,E,A,B,48
+
+	RR F3,A,B,C,D,E,50
+	RR F3,D,E,A,B,C,52
+	RR F3,B,C,D,E,A,54
+	RR F3,E,A,B,C,D,56
+	RR F3,C,D,E,A,B,58
+
+	add	$64, BUFFER_PTR		# move to the next 64-byte block
+	cmp	BUFFER_END, BUFFER_PTR	# if the current is the last one use
+	cmovae	K_BASE, BUFFER_PTR	# dummy source to avoid buffer overrun
+
+	RR F4,A,B,C,D,E,60
+	RR F4,D,E,A,B,C,62
+	RR F4,B,C,D,E,A,64
+	RR F4,E,A,B,C,D,66
+	RR F4,C,D,E,A,B,68
+
+	RR F4,A,B,C,D,E,70
+	RR F4,D,E,A,B,C,72
+	RR F4,B,C,D,E,A,74
+	RR F4,E,A,B,C,D,76
+	RR F4,C,D,E,A,B,78
+
+	UPDATE_HASH   (HASH_PTR), A
+	UPDATE_HASH  4(HASH_PTR), B
+	UPDATE_HASH  8(HASH_PTR), C
+	UPDATE_HASH 12(HASH_PTR), D
+	UPDATE_HASH 16(HASH_PTR), E
+
+	RESTORE_RENAMED_REGS
+	cmp	K_BASE, BUFFER_PTR	# K_BASE means, we reached the end
+	jne	1b
+.endm
+
+.macro INIT_REGALLOC
+  .set A, REG_A
+  .set B, REG_B
+  .set C, REG_C
+  .set D, REG_D
+  .set E, REG_E
+  .set T1, REG_T1
+  .set T2, REG_T2
+.endm
+
+.macro RESTORE_RENAMED_REGS
+	# order is important (REG_C is where it should be)
+	mov	B, REG_B
+	mov	D, REG_D
+	mov	A, REG_A
+	mov	E, REG_E
+.endm
+
+.macro SWAP_REG_NAMES  a, b
+  .set _T, \a
+  .set \a, \b
+  .set \b, _T
+.endm
+
+.macro F1  b, c, d
+	mov	\c, T1
+	SWAP_REG_NAMES \c, T1
+	xor	\d, T1
+	and	\b, T1
+	xor	\d, T1
+.endm
+
+.macro F2  b, c, d
+	mov	\d, T1
+	SWAP_REG_NAMES \d, T1
+	xor	\c, T1
+	xor	\b, T1
+.endm
+
+.macro F3  b, c ,d
+	mov	\c, T1
+	SWAP_REG_NAMES \c, T1
+	mov	\b, T2
+	or	\b, T1
+	and	\c, T2
+	and	\d, T1
+	or	T2, T1
+.endm
+
+.macro F4  b, c, d
+	F2 \b, \c, \d
+.endm
+
+.macro UPDATE_HASH  hash, val
+	add	\hash, \val
+	mov	\val, \hash
+.endm
+
+/*
+ * RR does two rounds of SHA-1 back to back with W[] pre-calc
+ *   t1 = F(b, c, d);   e += w(i)
+ *   e += t1;           b <<= 30;   d  += w(i+1);
+ *   t1 = F(a, b, c);
+ *   d += t1;           a <<= 5;
+ *   e += a;
+ *   t1 = e;            a >>= 7;
+ *   t1 <<= 5;
+ *   d += t1;
+ */
+.macro RR  F, a, b, c, d, e, round
+	add	WK(\round), \e
+	\F   \b, \c, \d		# t1 = F(b, c, d);
+	W_PRECALC (\round + W_PRECALC_AHEAD)
+	rol	$30, \b
+	add	T1, \e
+	add	WK(\round + 1), \d
+
+	\F   \a, \b, \c
+	W_PRECALC (\round + W_PRECALC_AHEAD + 1)
+	rol	$5, \a
+	add	\a, \e
+	add	T1, \d
+	ror	$7, \a		# (a <<r 5) >>r 7) => a <<r 30)
+
+	mov	\e, T1
+	SWAP_REG_NAMES \e, T1
+
+	rol	$5, T1
+	add	T1, \d
+
+	# write:  \a, \b
+	# rotate: \a<=\d, \b<=\e, \c<=\a, \d<=\b, \e<=\c
+.endm
+
+.macro W_PRECALC  r
+  .set i, \r
+
+  .if (i < 20)
+    .set K_XMM, 0
+  .elseif (i < 40)
+    .set K_XMM, 16
+  .elseif (i < 60)
+    .set K_XMM, 32
+  .elseif (i < 80)
+    .set K_XMM, 48
+  .endif
+
+  .if ((i < 16) || ((i >= 80) && (i < (80 + W_PRECALC_AHEAD))))
+    .set i, ((\r) % 80)	    # pre-compute for the next iteration
+    .if (i == 0)
+	W_PRECALC_RESET
+    .endif
+	W_PRECALC_00_15
+  .elseif (i<32)
+	W_PRECALC_16_31
+  .elseif (i < 80)   // rounds 32-79
+	W_PRECALC_32_79
+  .endif
+.endm
+
+.macro W_PRECALC_RESET
+  .set W,          W0
+  .set W_minus_04, W4
+  .set W_minus_08, W8
+  .set W_minus_12, W12
+  .set W_minus_16, W16
+  .set W_minus_20, W20
+  .set W_minus_24, W24
+  .set W_minus_28, W28
+  .set W_minus_32, W
+.endm
+
+.macro W_PRECALC_ROTATE
+  .set W_minus_32, W_minus_28
+  .set W_minus_28, W_minus_24
+  .set W_minus_24, W_minus_20
+  .set W_minus_20, W_minus_16
+  .set W_minus_16, W_minus_12
+  .set W_minus_12, W_minus_08
+  .set W_minus_08, W_minus_04
+  .set W_minus_04, W
+  .set W,          W_minus_32
+.endm
+
+.macro W_PRECALC_SSSE3
+
+.macro W_PRECALC_00_15
+	W_PRECALC_00_15_SSSE3
+.endm
+.macro W_PRECALC_16_31
+	W_PRECALC_16_31_SSSE3
+.endm
+.macro W_PRECALC_32_79
+	W_PRECALC_32_79_SSSE3
+.endm
+
+/* message scheduling pre-compute for rounds 0-15 */
+.macro W_PRECALC_00_15_SSSE3
+  .if ((i & 3) == 0)
+	movdqu	(i*4)(BUFFER_PTR), W_TMP1
+  .elseif ((i & 3) == 1)
+	pshufb	XMM_SHUFB_BSWAP, W_TMP1
+	movdqa	W_TMP1, W
+  .elseif ((i & 3) == 2)
+	paddd	(K_BASE), W_TMP1
+  .elseif ((i & 3) == 3)
+	movdqa  W_TMP1, WK(i&~3)
+	W_PRECALC_ROTATE
+  .endif
+.endm
+
+/* message scheduling pre-compute for rounds 16-31
+ *
+ * - calculating last 32 w[i] values in 8 XMM registers
+ * - pre-calculate K+w[i] values and store to mem, for later load by ALU add
+ *   instruction
+ *
+ * some "heavy-lifting" vectorization for rounds 16-31 due to w[i]->w[i-3]
+ * dependency, but improves for 32-79
+ */
+.macro W_PRECALC_16_31_SSSE3
+  # blended scheduling of vector and scalar instruction streams, one 4-wide
+  # vector iteration / 4 scalar rounds
+  .if ((i & 3) == 0)
+	movdqa	W_minus_12, W
+	palignr	$8, W_minus_16, W	# w[i-14]
+	movdqa	W_minus_04, W_TMP1
+	psrldq	$4, W_TMP1		# w[i-3]
+	pxor	W_minus_08, W
+  .elseif ((i & 3) == 1)
+	pxor	W_minus_16, W_TMP1
+	pxor	W_TMP1, W
+	movdqa	W, W_TMP2
+	movdqa	W, W_TMP1
+	pslldq	$12, W_TMP2
+  .elseif ((i & 3) == 2)
+	psrld	$31, W
+	pslld	$1, W_TMP1
+	por	W, W_TMP1
+	movdqa	W_TMP2, W
+	psrld	$30, W_TMP2
+	pslld	$2, W
+  .elseif ((i & 3) == 3)
+	pxor	W, W_TMP1
+	pxor	W_TMP2, W_TMP1
+	movdqa	W_TMP1, W
+	paddd	K_XMM(K_BASE), W_TMP1
+	movdqa	W_TMP1, WK(i&~3)
+	W_PRECALC_ROTATE
+  .endif
+.endm
+
+/* message scheduling pre-compute for rounds 32-79
+ *
+ * in SHA-1 specification: w[i] = (w[i-3] ^ w[i-8]  ^ w[i-14] ^ w[i-16]) rol 1
+ * instead we do equal:    w[i] = (w[i-6] ^ w[i-16] ^ w[i-28] ^ w[i-32]) rol 2
+ * allows more efficient vectorization since w[i]=>w[i-3] dependency is broken
+ */
+.macro W_PRECALC_32_79_SSSE3
+  .if ((i & 3) == 0)
+	movdqa	W_minus_04, W_TMP1
+	pxor	W_minus_28, W		# W is W_minus_32 before xor
+	palignr	$8, W_minus_08, W_TMP1
+  .elseif ((i & 3) == 1)
+	pxor	W_minus_16, W
+	pxor	W_TMP1, W
+	movdqa	W, W_TMP1
+  .elseif ((i & 3) == 2)
+	psrld	$30, W
+	pslld	$2, W_TMP1
+	por	W, W_TMP1
+  .elseif ((i & 3) == 3)
+	movdqa	W_TMP1, W
+	paddd	K_XMM(K_BASE), W_TMP1
+	movdqa	W_TMP1, WK(i&~3)
+	W_PRECALC_ROTATE
+  .endif
+.endm
+
+.endm		// W_PRECALC_SSSE3
+
+
+#define K1	0x5a827999
+#define K2	0x6ed9eba1
+#define K3	0x8f1bbcdc
+#define K4	0xca62c1d6
+
+.section .rodata
+.align 16
+
+K_XMM_AR:
+	.long K1, K1, K1, K1
+	.long K2, K2, K2, K2
+	.long K3, K3, K3, K3
+	.long K4, K4, K4, K4
+
+BSWAP_SHUFB_CTL:
+	.long 0x00010203
+	.long 0x04050607
+	.long 0x08090a0b
+	.long 0x0c0d0e0f
+
+
+.section .text
+
+W_PRECALC_SSSE3
+.macro xmm_mov a, b
+	movdqu	\a,\b
+.endm
+
+/* SSSE3 optimized implementation:
+ *  extern "C" void sha1_transform_ssse3(u32 *digest, const char *data, u32 *ws,
+ *                                       unsigned int rounds);
+ */
+SHA1_VECTOR_ASM     sha1_transform_ssse3
+
+#ifdef SHA1_ENABLE_AVX_SUPPORT
+
+.macro W_PRECALC_AVX
+
+.purgem W_PRECALC_00_15
+.macro  W_PRECALC_00_15
+    W_PRECALC_00_15_AVX
+.endm
+.purgem W_PRECALC_16_31
+.macro  W_PRECALC_16_31
+    W_PRECALC_16_31_AVX
+.endm
+.purgem W_PRECALC_32_79
+.macro  W_PRECALC_32_79
+    W_PRECALC_32_79_AVX
+.endm
+
+.macro W_PRECALC_00_15_AVX
+  .if ((i & 3) == 0)
+	vmovdqu	(i*4)(BUFFER_PTR), W_TMP1
+  .elseif ((i & 3) == 1)
+	vpshufb	XMM_SHUFB_BSWAP, W_TMP1, W
+  .elseif ((i & 3) == 2)
+	vpaddd	(K_BASE), W, W_TMP1
+  .elseif ((i & 3) == 3)
+	vmovdqa	W_TMP1, WK(i&~3)
+	W_PRECALC_ROTATE
+  .endif
+.endm
+
+.macro W_PRECALC_16_31_AVX
+  .if ((i & 3) == 0)
+	vpalignr $8, W_minus_16, W_minus_12, W	# w[i-14]
+	vpsrldq	$4, W_minus_04, W_TMP1		# w[i-3]
+	vpxor	W_minus_08, W, W
+	vpxor	W_minus_16, W_TMP1, W_TMP1
+  .elseif ((i & 3) == 1)
+	vpxor	W_TMP1, W, W
+	vpslldq	$12, W, W_TMP2
+	vpslld	$1, W, W_TMP1
+  .elseif ((i & 3) == 2)
+	vpsrld	$31, W, W
+	vpor	W, W_TMP1, W_TMP1
+	vpslld	$2, W_TMP2, W
+	vpsrld	$30, W_TMP2, W_TMP2
+  .elseif ((i & 3) == 3)
+	vpxor	W, W_TMP1, W_TMP1
+	vpxor	W_TMP2, W_TMP1, W
+	vpaddd	K_XMM(K_BASE), W, W_TMP1
+	vmovdqu	W_TMP1, WK(i&~3)
+	W_PRECALC_ROTATE
+  .endif
+.endm
+
+.macro W_PRECALC_32_79_AVX
+  .if ((i & 3) == 0)
+	vpalignr $8, W_minus_08, W_minus_04, W_TMP1
+	vpxor	W_minus_28, W, W		# W is W_minus_32 before xor
+  .elseif ((i & 3) == 1)
+	vpxor	W_minus_16, W_TMP1, W_TMP1
+	vpxor	W_TMP1, W, W
+  .elseif ((i & 3) == 2)
+	vpslld	$2, W, W_TMP1
+	vpsrld	$30, W, W
+	vpor	W, W_TMP1, W
+  .elseif ((i & 3) == 3)
+	vpaddd	K_XMM(K_BASE), W, W_TMP1
+	vmovdqu	W_TMP1, WK(i&~3)
+	W_PRECALC_ROTATE
+  .endif
+.endm
+
+.endm    // W_PRECALC_AVX
+
+W_PRECALC_AVX
+.purgem xmm_mov
+.macro xmm_mov a, b
+	vmovdqu	\a,\b
+.endm
+
+
+/* AVX optimized implementation:
+ *  extern "C" void sha1_transform_avx(u32 *digest, const char *data, u32 *ws,
+ *                                     unsigned int rounds);
+ */
+SHA1_VECTOR_ASM     sha1_transform_avx
+
+#endif
diff --git a/arch/x86/crypto/sha1_ssse3_glue.c b/arch/x86/crypto/sha1_ssse3_glue.c
new file mode 100644
index 0000000..f916499
--- /dev/null
+++ b/arch/x86/crypto/sha1_ssse3_glue.c
@@ -0,0 +1,240 @@
+/*
+ * Cryptographic API.
+ *
+ * Glue code for the SHA1 Secure Hash Algorithm assembler implementation using
+ * Supplemental SSE3 instructions.
+ *
+ * This file is based on sha1_generic.c
+ *
+ * Copyright (c) Alan Smithee.
+ * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
+ * Copyright (c) Jean-Francois Dive <jef@linuxbe.org>
+ * Copyright (c) Mathias Krause <minipli@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <crypto/internal/hash.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/cryptohash.h>
+#include <linux/types.h>
+#include <crypto/sha.h>
+#include <asm/byteorder.h>
+#include <asm/i387.h>
+#include <asm/xcr.h>
+#include <asm/xsave.h>
+
+
+asmlinkage void sha1_transform_ssse3(u32 *digest, const char *data,
+				     unsigned int rounds);
+#ifdef SHA1_ENABLE_AVX_SUPPORT
+asmlinkage void sha1_transform_avx(u32 *digest, const char *data,
+				   unsigned int rounds);
+#endif
+
+static asmlinkage void (*sha1_transform_asm)(u32 *, const char *, unsigned int);
+
+
+static int sha1_ssse3_init(struct shash_desc *desc)
+{
+	struct sha1_state *sctx = shash_desc_ctx(desc);
+
+	*sctx = (struct sha1_state){
+		.state = { SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4 },
+	};
+
+	return 0;
+}
+
+static int __sha1_ssse3_update(struct shash_desc *desc, const u8 *data,
+			       unsigned int len, unsigned int partial)
+{
+	struct sha1_state *sctx = shash_desc_ctx(desc);
+	unsigned int done = 0;
+
+	sctx->count += len;
+
+	if (partial) {
+		done = SHA1_BLOCK_SIZE - partial;
+		memcpy(sctx->buffer + partial, data, done);
+		sha1_transform_asm(sctx->state, sctx->buffer, 1);
+	}
+
+	if (len - done >= SHA1_BLOCK_SIZE) {
+		const unsigned int rounds = (len - done) / SHA1_BLOCK_SIZE;
+
+		sha1_transform_asm(sctx->state, data + done, rounds);
+		done += rounds * SHA1_BLOCK_SIZE;
+	}
+
+	memcpy(sctx->buffer, data + done, len - done);
+
+	return 0;
+}
+
+static int sha1_ssse3_update(struct shash_desc *desc, const u8 *data,
+			     unsigned int len)
+{
+	struct sha1_state *sctx = shash_desc_ctx(desc);
+	unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
+	int res;
+
+	/* Handle the fast case right here */
+	if (partial + len < SHA1_BLOCK_SIZE) {
+		sctx->count += len;
+		memcpy(sctx->buffer + partial, data, len);
+
+		return 0;
+	}
+
+	if (!irq_fpu_usable()) {
+		res = crypto_sha1_update(desc, data, len);
+	} else {
+		kernel_fpu_begin();
+		res = __sha1_ssse3_update(desc, data, len, partial);
+		kernel_fpu_end();
+	}
+
+	return res;
+}
+
+
+/* Add padding and return the message digest. */
+static int sha1_ssse3_final(struct shash_desc *desc, u8 *out)
+{
+	struct sha1_state *sctx = shash_desc_ctx(desc);
+	unsigned int i, index, padlen;
+	__be32 *dst = (__be32 *)out;
+	__be64 bits;
+	static const u8 padding[SHA1_BLOCK_SIZE] = { 0x80, };
+
+	bits = cpu_to_be64(sctx->count << 3);
+
+	/* Pad out to 56 mod 64 and append length */
+	index = sctx->count % SHA1_BLOCK_SIZE;
+	padlen = (index < 56) ? (56 - index) : ((SHA1_BLOCK_SIZE+56) - index);
+	if (!irq_fpu_usable()) {
+		crypto_sha1_update(desc, padding, padlen);
+		crypto_sha1_update(desc, (const u8 *)&bits, sizeof(bits));
+	} else {
+		kernel_fpu_begin();
+		/* We need to fill a whole block for __sha1_ssse3_update() */
+		if (padlen <= 56) {
+			sctx->count += padlen;
+			memcpy(sctx->buffer + index, padding, padlen);
+		} else {
+			__sha1_ssse3_update(desc, padding, padlen, index);
+		}
+		__sha1_ssse3_update(desc, (const u8 *)&bits, sizeof(bits), 56);
+		kernel_fpu_end();
+	}
+
+	/* Store state in digest */
+	for (i = 0; i < 5; i++)
+		dst[i] = cpu_to_be32(sctx->state[i]);
+
+	/* Wipe context */
+	memset(sctx, 0, sizeof(*sctx));
+
+	return 0;
+}
+
+static int sha1_ssse3_export(struct shash_desc *desc, void *out)
+{
+	struct sha1_state *sctx = shash_desc_ctx(desc);
+
+	memcpy(out, sctx, sizeof(*sctx));
+
+	return 0;
+}
+
+static int sha1_ssse3_import(struct shash_desc *desc, const void *in)
+{
+	struct sha1_state *sctx = shash_desc_ctx(desc);
+
+	memcpy(sctx, in, sizeof(*sctx));
+
+	return 0;
+}
+
+static struct shash_alg alg = {
+	.digestsize	=	SHA1_DIGEST_SIZE,
+	.init		=	sha1_ssse3_init,
+	.update		=	sha1_ssse3_update,
+	.final		=	sha1_ssse3_final,
+	.export		=	sha1_ssse3_export,
+	.import		=	sha1_ssse3_import,
+	.descsize	=	sizeof(struct sha1_state),
+	.statesize	=	sizeof(struct sha1_state),
+	.base		=	{
+		.cra_name	=	"sha1",
+		.cra_driver_name=	"sha1-ssse3",
+		.cra_priority	=	150,
+		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
+		.cra_blocksize	=	SHA1_BLOCK_SIZE,
+		.cra_module	=	THIS_MODULE,
+	}
+};
+
+#ifdef SHA1_ENABLE_AVX_SUPPORT
+static bool __init avx_usable(void)
+{
+	u64 xcr0;
+
+	if (!cpu_has_avx || !cpu_has_osxsave)
+		return false;
+
+	xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK);
+	if ((xcr0 & (XSTATE_SSE | XSTATE_YMM)) != (XSTATE_SSE | XSTATE_YMM)) {
+		pr_info("AVX detected but unusable.\n");
+
+		return false;
+	}
+
+	return true;
+}
+#endif
+
+static int __init sha1_ssse3_mod_init(void)
+{
+	/* test for SSSE3 first */
+	if (cpu_has_ssse3)
+		sha1_transform_asm = sha1_transform_ssse3;
+
+#ifdef SHA1_ENABLE_AVX_SUPPORT
+	/* allow AVX to override SSSE3, it's a little faster */
+	if (avx_usable())
+		sha1_transform_asm = sha1_transform_avx;
+#endif
+
+	if (sha1_transform_asm) {
+		pr_info("Using %s optimized SHA-1 implementation\n",
+		        sha1_transform_asm == sha1_transform_ssse3 ? "SSSE3"
+		                                                   : "AVX");
+		return crypto_register_shash(&alg);
+	}
+	pr_info("Neither AVX nor SSSE3 is available/usable.\n");
+
+	return -ENODEV;
+}
+
+static void __exit sha1_ssse3_mod_fini(void)
+{
+	crypto_unregister_shash(&alg);
+}
+
+module_init(sha1_ssse3_mod_init);
+module_exit(sha1_ssse3_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm, Supplemental SSE3 accelerated");
+
+MODULE_ALIAS("sha1");
diff --git a/arch/x86/crypto/twofish-i586-asm_32.S b/arch/x86/crypto/twofish-i586-asm_32.S
index 575331c..658af4b 100644
--- a/arch/x86/crypto/twofish-i586-asm_32.S
+++ b/arch/x86/crypto/twofish-i586-asm_32.S
@@ -26,7 +26,7 @@
 
 #define in_blk    12  /* input byte array address parameter*/
 #define out_blk   8  /* output byte array address parameter*/
-#define tfm       4  /* Twofish context structure */
+#define ctx       4  /* Twofish context structure */
 
 #define a_offset	0
 #define b_offset	4
@@ -229,8 +229,8 @@ twofish_enc_blk:
 	push    %esi
 	push    %edi
 
-	mov	tfm + 16(%esp),	%ebp	/* abuse the base pointer: set new base bointer to the crypto tfm */
-	add	$crypto_tfm_ctx_offset, %ebp	/* ctx address */
+	mov	ctx + 16(%esp),	%ebp	/* abuse the base pointer: set new base
+					 * pointer to the ctx address */
 	mov     in_blk+16(%esp),%edi	/* input address in edi */
 
 	mov	(%edi),		%eax
@@ -285,8 +285,8 @@ twofish_dec_blk:
 	push    %edi
 
 
-	mov	tfm + 16(%esp),	%ebp	/* abuse the base pointer: set new base bointer to the crypto tfm */
-	add	$crypto_tfm_ctx_offset, %ebp	/* ctx address */
+	mov	ctx + 16(%esp),	%ebp	/* abuse the base pointer: set new base
+					 * pointer to the ctx address */
 	mov     in_blk+16(%esp),%edi	/* input address in edi */
 
 	mov	(%edi),		%eax
diff --git a/arch/x86/crypto/twofish-x86_64-asm_64-3way.S b/arch/x86/crypto/twofish-x86_64-asm_64-3way.S
new file mode 100644
index 0000000..5b012a2
--- /dev/null
+++ b/arch/x86/crypto/twofish-x86_64-asm_64-3way.S
@@ -0,0 +1,316 @@
+/*
+ * Twofish Cipher 3-way parallel algorithm (x86_64)
+ *
+ * Copyright (C) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ * USA
+ *
+ */
+
+.file "twofish-x86_64-asm-3way.S"
+.text
+
+/* structure of crypto context */
+#define s0	0
+#define s1	1024
+#define s2	2048
+#define s3	3072
+#define w	4096
+#define k	4128
+
+/**********************************************************************
+  3-way twofish
+ **********************************************************************/
+#define CTX %rdi
+#define RIO %rdx
+
+#define RAB0 %rax
+#define RAB1 %rbx
+#define RAB2 %rcx
+
+#define RAB0d %eax
+#define RAB1d %ebx
+#define RAB2d %ecx
+
+#define RAB0bh %ah
+#define RAB1bh %bh
+#define RAB2bh %ch
+
+#define RAB0bl %al
+#define RAB1bl %bl
+#define RAB2bl %cl
+
+#define RCD0 %r8
+#define RCD1 %r9
+#define RCD2 %r10
+
+#define RCD0d %r8d
+#define RCD1d %r9d
+#define RCD2d %r10d
+
+#define RX0 %rbp
+#define RX1 %r11
+#define RX2 %r12
+
+#define RX0d %ebp
+#define RX1d %r11d
+#define RX2d %r12d
+
+#define RY0 %r13
+#define RY1 %r14
+#define RY2 %r15
+
+#define RY0d %r13d
+#define RY1d %r14d
+#define RY2d %r15d
+
+#define RT0 %rdx
+#define RT1 %rsi
+
+#define RT0d %edx
+#define RT1d %esi
+
+#define do16bit_ror(rot, op1, op2, T0, T1, tmp1, tmp2, ab, dst) \
+	movzbl ab ## bl,		tmp2 ## d; \
+	movzbl ab ## bh,		tmp1 ## d; \
+	rorq $(rot),			ab; \
+	op1##l T0(CTX, tmp2, 4),	dst ## d; \
+	op2##l T1(CTX, tmp1, 4),	dst ## d;
+
+/*
+ * Combined G1 & G2 function. Reordered with help of rotates to have moves
+ * at begining.
+ */
+#define g1g2_3(ab, cd, Tx0, Tx1, Tx2, Tx3, Ty0, Ty1, Ty2, Ty3, x, y) \
+	/* G1,1 && G2,1 */ \
+	do16bit_ror(32, mov, xor, Tx0, Tx1, RT0, x ## 0, ab ## 0, x ## 0); \
+	do16bit_ror(48, mov, xor, Ty1, Ty2, RT0, y ## 0, ab ## 0, y ## 0); \
+	\
+	do16bit_ror(32, mov, xor, Tx0, Tx1, RT0, x ## 1, ab ## 1, x ## 1); \
+	do16bit_ror(48, mov, xor, Ty1, Ty2, RT0, y ## 1, ab ## 1, y ## 1); \
+	\
+	do16bit_ror(32, mov, xor, Tx0, Tx1, RT0, x ## 2, ab ## 2, x ## 2); \
+	do16bit_ror(48, mov, xor, Ty1, Ty2, RT0, y ## 2, ab ## 2, y ## 2); \
+	\
+	/* G1,2 && G2,2 */ \
+	do16bit_ror(32, xor, xor, Tx2, Tx3, RT0, RT1, ab ## 0, x ## 0); \
+	do16bit_ror(16, xor, xor, Ty3, Ty0, RT0, RT1, ab ## 0, y ## 0); \
+	xchgq cd ## 0, ab ## 0; \
+	\
+	do16bit_ror(32, xor, xor, Tx2, Tx3, RT0, RT1, ab ## 1, x ## 1); \
+	do16bit_ror(16, xor, xor, Ty3, Ty0, RT0, RT1, ab ## 1, y ## 1); \
+	xchgq cd ## 1, ab ## 1; \
+	\
+	do16bit_ror(32, xor, xor, Tx2, Tx3, RT0, RT1, ab ## 2, x ## 2); \
+	do16bit_ror(16, xor, xor, Ty3, Ty0, RT0, RT1, ab ## 2, y ## 2); \
+	xchgq cd ## 2, ab ## 2;
+
+#define enc_round_end(ab, x, y, n) \
+	addl y ## d,			x ## d; \
+	addl x ## d,			y ## d; \
+	addl k+4*(2*(n))(CTX),		x ## d; \
+	xorl ab ## d,			x ## d; \
+	addl k+4*(2*(n)+1)(CTX),	y ## d; \
+	shrq $32,			ab; \
+	roll $1,			ab ## d; \
+	xorl y ## d,			ab ## d; \
+	shlq $32,			ab; \
+	rorl $1,			x ## d; \
+	orq x,				ab;
+
+#define dec_round_end(ba, x, y, n) \
+	addl y ## d,			x ## d; \
+	addl x ## d,			y ## d; \
+	addl k+4*(2*(n))(CTX),		x ## d; \
+	addl k+4*(2*(n)+1)(CTX),	y ## d; \
+	xorl ba ## d,			y ## d; \
+	shrq $32,			ba; \
+	roll $1,			ba ## d; \
+	xorl x ## d,			ba ## d; \
+	shlq $32,			ba; \
+	rorl $1,			y ## d; \
+	orq y,				ba;
+
+#define encrypt_round3(ab, cd, n) \
+	g1g2_3(ab, cd, s0, s1, s2, s3, s0, s1, s2, s3, RX, RY); \
+	\
+	enc_round_end(ab ## 0, RX0, RY0, n); \
+	enc_round_end(ab ## 1, RX1, RY1, n); \
+	enc_round_end(ab ## 2, RX2, RY2, n);
+
+#define decrypt_round3(ba, dc, n) \
+	g1g2_3(ba, dc, s1, s2, s3, s0, s3, s0, s1, s2, RY, RX); \
+	\
+	dec_round_end(ba ## 0, RX0, RY0, n); \
+	dec_round_end(ba ## 1, RX1, RY1, n); \
+	dec_round_end(ba ## 2, RX2, RY2, n);
+
+#define encrypt_cycle3(ab, cd, n) \
+	encrypt_round3(ab, cd, n*2); \
+	encrypt_round3(ab, cd, (n*2)+1);
+
+#define decrypt_cycle3(ba, dc, n) \
+	decrypt_round3(ba, dc, (n*2)+1); \
+	decrypt_round3(ba, dc, (n*2));
+
+#define inpack3(in, n, xy, m) \
+	movq 4*(n)(in),			xy ## 0; \
+	xorq w+4*m(CTX),		xy ## 0; \
+	\
+	movq 4*(4+(n))(in),		xy ## 1; \
+	xorq w+4*m(CTX),		xy ## 1; \
+	\
+	movq 4*(8+(n))(in),		xy ## 2; \
+	xorq w+4*m(CTX),		xy ## 2;
+
+#define outunpack3(op, out, n, xy, m) \
+	xorq w+4*m(CTX),		xy ## 0; \
+	op ## q xy ## 0,		4*(n)(out); \
+	\
+	xorq w+4*m(CTX),		xy ## 1; \
+	op ## q xy ## 1,		4*(4+(n))(out); \
+	\
+	xorq w+4*m(CTX),		xy ## 2; \
+	op ## q xy ## 2,		4*(8+(n))(out);
+
+#define inpack_enc3() \
+	inpack3(RIO, 0, RAB, 0); \
+	inpack3(RIO, 2, RCD, 2);
+
+#define outunpack_enc3(op) \
+	outunpack3(op, RIO, 2, RAB, 6); \
+	outunpack3(op, RIO, 0, RCD, 4);
+
+#define inpack_dec3() \
+	inpack3(RIO, 0, RAB, 4); \
+	rorq $32,			RAB0; \
+	rorq $32,			RAB1; \
+	rorq $32,			RAB2; \
+	inpack3(RIO, 2, RCD, 6); \
+	rorq $32,			RCD0; \
+	rorq $32,			RCD1; \
+	rorq $32,			RCD2;
+
+#define outunpack_dec3() \
+	rorq $32,			RCD0; \
+	rorq $32,			RCD1; \
+	rorq $32,			RCD2; \
+	outunpack3(mov, RIO, 0, RCD, 0); \
+	rorq $32,			RAB0; \
+	rorq $32,			RAB1; \
+	rorq $32,			RAB2; \
+	outunpack3(mov, RIO, 2, RAB, 2);
+
+.align 8
+.global __twofish_enc_blk_3way
+.type   __twofish_enc_blk_3way,@function;
+
+__twofish_enc_blk_3way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src, RIO
+	 *	%rcx: bool, if true: xor output
+	 */
+	pushq %r15;
+	pushq %r14;
+	pushq %r13;
+	pushq %r12;
+	pushq %rbp;
+	pushq %rbx;
+
+	pushq %rcx; /* bool xor */
+	pushq %rsi; /* dst */
+
+	inpack_enc3();
+
+	encrypt_cycle3(RAB, RCD, 0);
+	encrypt_cycle3(RAB, RCD, 1);
+	encrypt_cycle3(RAB, RCD, 2);
+	encrypt_cycle3(RAB, RCD, 3);
+	encrypt_cycle3(RAB, RCD, 4);
+	encrypt_cycle3(RAB, RCD, 5);
+	encrypt_cycle3(RAB, RCD, 6);
+	encrypt_cycle3(RAB, RCD, 7);
+
+	popq RIO; /* dst */
+	popq %rbp; /* bool xor */
+
+	testb %bpl, %bpl;
+	jnz __enc_xor3;
+
+	outunpack_enc3(mov);
+
+	popq %rbx;
+	popq %rbp;
+	popq %r12;
+	popq %r13;
+	popq %r14;
+	popq %r15;
+	ret;
+
+__enc_xor3:
+	outunpack_enc3(xor);
+
+	popq %rbx;
+	popq %rbp;
+	popq %r12;
+	popq %r13;
+	popq %r14;
+	popq %r15;
+	ret;
+
+.global twofish_dec_blk_3way
+.type   twofish_dec_blk_3way,@function;
+
+twofish_dec_blk_3way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src, RIO
+	 */
+	pushq %r15;
+	pushq %r14;
+	pushq %r13;
+	pushq %r12;
+	pushq %rbp;
+	pushq %rbx;
+
+	pushq %rsi; /* dst */
+
+	inpack_dec3();
+
+	decrypt_cycle3(RAB, RCD, 7);
+	decrypt_cycle3(RAB, RCD, 6);
+	decrypt_cycle3(RAB, RCD, 5);
+	decrypt_cycle3(RAB, RCD, 4);
+	decrypt_cycle3(RAB, RCD, 3);
+	decrypt_cycle3(RAB, RCD, 2);
+	decrypt_cycle3(RAB, RCD, 1);
+	decrypt_cycle3(RAB, RCD, 0);
+
+	popq RIO; /* dst */
+
+	outunpack_dec3();
+
+	popq %rbx;
+	popq %rbp;
+	popq %r12;
+	popq %r13;
+	popq %r14;
+	popq %r15;
+	ret;
+
diff --git a/arch/x86/crypto/twofish-x86_64-asm_64.S b/arch/x86/crypto/twofish-x86_64-asm_64.S
index 573aa10..7bcf3fc 100644
--- a/arch/x86/crypto/twofish-x86_64-asm_64.S
+++ b/arch/x86/crypto/twofish-x86_64-asm_64.S
@@ -221,10 +221,9 @@
 twofish_enc_blk:
 	pushq    R1
 
-	/* %rdi contains the crypto tfm address */
+	/* %rdi contains the ctx address */
 	/* %rsi contains the output address */
 	/* %rdx contains the input address */
-	add	$crypto_tfm_ctx_offset, %rdi	/* set ctx address */
 	/* ctx address is moved to free one non-rex register
 	as target for the 8bit high operations */
 	mov	%rdi,		%r11
@@ -274,10 +273,9 @@ twofish_enc_blk:
 twofish_dec_blk:
 	pushq    R1
 
-	/* %rdi contains the crypto tfm address */
+	/* %rdi contains the ctx address */
 	/* %rsi contains the output address */
 	/* %rdx contains the input address */
-	add	$crypto_tfm_ctx_offset, %rdi	/* set ctx address */
 	/* ctx address is moved to free one non-rex register
 	as target for the 8bit high operations */
 	mov	%rdi,		%r11
diff --git a/arch/x86/crypto/twofish_glue.c b/arch/x86/crypto/twofish_glue.c
index cefaf8b..dc6b3fb 100644
--- a/arch/x86/crypto/twofish_glue.c
+++ b/arch/x86/crypto/twofish_glue.c
@@ -44,17 +44,21 @@
 #include <linux/module.h>
 #include <linux/types.h>
 
-asmlinkage void twofish_enc_blk(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
-asmlinkage void twofish_dec_blk(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
+asmlinkage void twofish_enc_blk(struct twofish_ctx *ctx, u8 *dst,
+				const u8 *src);
+EXPORT_SYMBOL_GPL(twofish_enc_blk);
+asmlinkage void twofish_dec_blk(struct twofish_ctx *ctx, u8 *dst,
+				const u8 *src);
+EXPORT_SYMBOL_GPL(twofish_dec_blk);
 
 static void twofish_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
-	twofish_enc_blk(tfm, dst, src);
+	twofish_enc_blk(crypto_tfm_ctx(tfm), dst, src);
 }
 
 static void twofish_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
-	twofish_dec_blk(tfm, dst, src);
+	twofish_dec_blk(crypto_tfm_ctx(tfm), dst, src);
 }
 
 static struct crypto_alg alg = {
diff --git a/arch/x86/crypto/twofish_glue_3way.c b/arch/x86/crypto/twofish_glue_3way.c
new file mode 100644
index 0000000..5ede9c4
--- /dev/null
+++ b/arch/x86/crypto/twofish_glue_3way.c
@@ -0,0 +1,472 @@
+/*
+ * Glue Code for 3-way parallel assembler optimized version of Twofish
+ *
+ * Copyright (c) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ * CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by:
+ *   Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
+ * CTR part based on code (crypto/ctr.c) by:
+ *   (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ * USA
+ *
+ */
+
+#include <linux/crypto.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <crypto/algapi.h>
+#include <crypto/twofish.h>
+#include <crypto/b128ops.h>
+
+/* regular block cipher functions from twofish_x86_64 module */
+asmlinkage void twofish_enc_blk(struct twofish_ctx *ctx, u8 *dst,
+				const u8 *src);
+asmlinkage void twofish_dec_blk(struct twofish_ctx *ctx, u8 *dst,
+				const u8 *src);
+
+/* 3-way parallel cipher functions */
+asmlinkage void __twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst,
+				       const u8 *src, bool xor);
+asmlinkage void twofish_dec_blk_3way(struct twofish_ctx *ctx, u8 *dst,
+				     const u8 *src);
+
+static inline void twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst,
+					const u8 *src)
+{
+	__twofish_enc_blk_3way(ctx, dst, src, false);
+}
+
+static inline void twofish_enc_blk_xor_3way(struct twofish_ctx *ctx, u8 *dst,
+					    const u8 *src)
+{
+	__twofish_enc_blk_3way(ctx, dst, src, true);
+}
+
+static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk,
+		     void (*fn)(struct twofish_ctx *, u8 *, const u8 *),
+		     void (*fn_3way)(struct twofish_ctx *, u8 *, const u8 *))
+{
+	struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	unsigned int bsize = TF_BLOCK_SIZE;
+	unsigned int nbytes;
+	int err;
+
+	err = blkcipher_walk_virt(desc, walk);
+
+	while ((nbytes = walk->nbytes)) {
+		u8 *wsrc = walk->src.virt.addr;
+		u8 *wdst = walk->dst.virt.addr;
+
+		/* Process three block batch */
+		if (nbytes >= bsize * 3) {
+			do {
+				fn_3way(ctx, wdst, wsrc);
+
+				wsrc += bsize * 3;
+				wdst += bsize * 3;
+				nbytes -= bsize * 3;
+			} while (nbytes >= bsize * 3);
+
+			if (nbytes < bsize)
+				goto done;
+		}
+
+		/* Handle leftovers */
+		do {
+			fn(ctx, wdst, wsrc);
+
+			wsrc += bsize;
+			wdst += bsize;
+			nbytes -= bsize;
+		} while (nbytes >= bsize);
+
+done:
+		err = blkcipher_walk_done(desc, walk, nbytes);
+	}
+
+	return err;
+}
+
+static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	return ecb_crypt(desc, &walk, twofish_enc_blk, twofish_enc_blk_3way);
+}
+
+static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	return ecb_crypt(desc, &walk, twofish_dec_blk, twofish_dec_blk_3way);
+}
+
+static struct crypto_alg blk_ecb_alg = {
+	.cra_name		= "ecb(twofish)",
+	.cra_driver_name	= "ecb-twofish-3way",
+	.cra_priority		= 300,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= TF_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct twofish_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(blk_ecb_alg.cra_list),
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= TF_MIN_KEY_SIZE,
+			.max_keysize	= TF_MAX_KEY_SIZE,
+			.setkey		= twofish_setkey,
+			.encrypt	= ecb_encrypt,
+			.decrypt	= ecb_decrypt,
+		},
+	},
+};
+
+static unsigned int __cbc_encrypt(struct blkcipher_desc *desc,
+				  struct blkcipher_walk *walk)
+{
+	struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	unsigned int bsize = TF_BLOCK_SIZE;
+	unsigned int nbytes = walk->nbytes;
+	u128 *src = (u128 *)walk->src.virt.addr;
+	u128 *dst = (u128 *)walk->dst.virt.addr;
+	u128 *iv = (u128 *)walk->iv;
+
+	do {
+		u128_xor(dst, src, iv);
+		twofish_enc_blk(ctx, (u8 *)dst, (u8 *)dst);
+		iv = dst;
+
+		src += 1;
+		dst += 1;
+		nbytes -= bsize;
+	} while (nbytes >= bsize);
+
+	u128_xor((u128 *)walk->iv, (u128 *)walk->iv, iv);
+	return nbytes;
+}
+
+static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	while ((nbytes = walk.nbytes)) {
+		nbytes = __cbc_encrypt(desc, &walk);
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+
+	return err;
+}
+
+static unsigned int __cbc_decrypt(struct blkcipher_desc *desc,
+				  struct blkcipher_walk *walk)
+{
+	struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	unsigned int bsize = TF_BLOCK_SIZE;
+	unsigned int nbytes = walk->nbytes;
+	u128 *src = (u128 *)walk->src.virt.addr;
+	u128 *dst = (u128 *)walk->dst.virt.addr;
+	u128 ivs[3 - 1];
+	u128 last_iv;
+
+	/* Start of the last block. */
+	src += nbytes / bsize - 1;
+	dst += nbytes / bsize - 1;
+
+	last_iv = *src;
+
+	/* Process three block batch */
+	if (nbytes >= bsize * 3) {
+		do {
+			nbytes -= bsize * (3 - 1);
+			src -= 3 - 1;
+			dst -= 3 - 1;
+
+			ivs[0] = src[0];
+			ivs[1] = src[1];
+
+			twofish_dec_blk_3way(ctx, (u8 *)dst, (u8 *)src);
+
+			u128_xor(dst + 1, dst + 1, ivs + 0);
+			u128_xor(dst + 2, dst + 2, ivs + 1);
+
+			nbytes -= bsize;
+			if (nbytes < bsize)
+				goto done;
+
+			u128_xor(dst, dst, src - 1);
+			src -= 1;
+			dst -= 1;
+		} while (nbytes >= bsize * 3);
+
+		if (nbytes < bsize)
+			goto done;
+	}
+
+	/* Handle leftovers */
+	for (;;) {
+		twofish_dec_blk(ctx, (u8 *)dst, (u8 *)src);
+
+		nbytes -= bsize;
+		if (nbytes < bsize)
+			break;
+
+		u128_xor(dst, dst, src - 1);
+		src -= 1;
+		dst -= 1;
+	}
+
+done:
+	u128_xor(dst, dst, (u128 *)walk->iv);
+	*(u128 *)walk->iv = last_iv;
+
+	return nbytes;
+}
+
+static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	while ((nbytes = walk.nbytes)) {
+		nbytes = __cbc_decrypt(desc, &walk);
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+
+	return err;
+}
+
+static struct crypto_alg blk_cbc_alg = {
+	.cra_name		= "cbc(twofish)",
+	.cra_driver_name	= "cbc-twofish-3way",
+	.cra_priority		= 300,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= TF_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct twofish_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(blk_cbc_alg.cra_list),
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= TF_MIN_KEY_SIZE,
+			.max_keysize	= TF_MAX_KEY_SIZE,
+			.ivsize		= TF_BLOCK_SIZE,
+			.setkey		= twofish_setkey,
+			.encrypt	= cbc_encrypt,
+			.decrypt	= cbc_decrypt,
+		},
+	},
+};
+
+static inline void u128_to_be128(be128 *dst, const u128 *src)
+{
+	dst->a = cpu_to_be64(src->a);
+	dst->b = cpu_to_be64(src->b);
+}
+
+static inline void be128_to_u128(u128 *dst, const be128 *src)
+{
+	dst->a = be64_to_cpu(src->a);
+	dst->b = be64_to_cpu(src->b);
+}
+
+static inline void u128_inc(u128 *i)
+{
+	i->b++;
+	if (!i->b)
+		i->a++;
+}
+
+static void ctr_crypt_final(struct blkcipher_desc *desc,
+			    struct blkcipher_walk *walk)
+{
+	struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	u8 *ctrblk = walk->iv;
+	u8 keystream[TF_BLOCK_SIZE];
+	u8 *src = walk->src.virt.addr;
+	u8 *dst = walk->dst.virt.addr;
+	unsigned int nbytes = walk->nbytes;
+
+	twofish_enc_blk(ctx, keystream, ctrblk);
+	crypto_xor(keystream, src, nbytes);
+	memcpy(dst, keystream, nbytes);
+
+	crypto_inc(ctrblk, TF_BLOCK_SIZE);
+}
+
+static unsigned int __ctr_crypt(struct blkcipher_desc *desc,
+				struct blkcipher_walk *walk)
+{
+	struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	unsigned int bsize = TF_BLOCK_SIZE;
+	unsigned int nbytes = walk->nbytes;
+	u128 *src = (u128 *)walk->src.virt.addr;
+	u128 *dst = (u128 *)walk->dst.virt.addr;
+	u128 ctrblk;
+	be128 ctrblocks[3];
+
+	be128_to_u128(&ctrblk, (be128 *)walk->iv);
+
+	/* Process three block batch */
+	if (nbytes >= bsize * 3) {
+		do {
+			if (dst != src) {
+				dst[0] = src[0];
+				dst[1] = src[1];
+				dst[2] = src[2];
+			}
+
+			/* create ctrblks for parallel encrypt */
+			u128_to_be128(&ctrblocks[0], &ctrblk);
+			u128_inc(&ctrblk);
+			u128_to_be128(&ctrblocks[1], &ctrblk);
+			u128_inc(&ctrblk);
+			u128_to_be128(&ctrblocks[2], &ctrblk);
+			u128_inc(&ctrblk);
+
+			twofish_enc_blk_xor_3way(ctx, (u8 *)dst,
+						 (u8 *)ctrblocks);
+
+			src += 3;
+			dst += 3;
+			nbytes -= bsize * 3;
+		} while (nbytes >= bsize * 3);
+
+		if (nbytes < bsize)
+			goto done;
+	}
+
+	/* Handle leftovers */
+	do {
+		if (dst != src)
+			*dst = *src;
+
+		u128_to_be128(&ctrblocks[0], &ctrblk);
+		u128_inc(&ctrblk);
+
+		twofish_enc_blk(ctx, (u8 *)ctrblocks, (u8 *)ctrblocks);
+		u128_xor(dst, dst, (u128 *)ctrblocks);
+
+		src += 1;
+		dst += 1;
+		nbytes -= bsize;
+	} while (nbytes >= bsize);
+
+done:
+	u128_to_be128((be128 *)walk->iv, &ctrblk);
+	return nbytes;
+}
+
+static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		     struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt_block(desc, &walk, TF_BLOCK_SIZE);
+
+	while ((nbytes = walk.nbytes) >= TF_BLOCK_SIZE) {
+		nbytes = __ctr_crypt(desc, &walk);
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+
+	if (walk.nbytes) {
+		ctr_crypt_final(desc, &walk);
+		err = blkcipher_walk_done(desc, &walk, 0);
+	}
+
+	return err;
+}
+
+static struct crypto_alg blk_ctr_alg = {
+	.cra_name		= "ctr(twofish)",
+	.cra_driver_name	= "ctr-twofish-3way",
+	.cra_priority		= 300,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= 1,
+	.cra_ctxsize		= sizeof(struct twofish_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(blk_ctr_alg.cra_list),
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= TF_MIN_KEY_SIZE,
+			.max_keysize	= TF_MAX_KEY_SIZE,
+			.ivsize		= TF_BLOCK_SIZE,
+			.setkey		= twofish_setkey,
+			.encrypt	= ctr_crypt,
+			.decrypt	= ctr_crypt,
+		},
+	},
+};
+
+int __init init(void)
+{
+	int err;
+
+	err = crypto_register_alg(&blk_ecb_alg);
+	if (err)
+		goto ecb_err;
+	err = crypto_register_alg(&blk_cbc_alg);
+	if (err)
+		goto cbc_err;
+	err = crypto_register_alg(&blk_ctr_alg);
+	if (err)
+		goto ctr_err;
+
+	return 0;
+
+ctr_err:
+	crypto_unregister_alg(&blk_cbc_alg);
+cbc_err:
+	crypto_unregister_alg(&blk_ecb_alg);
+ecb_err:
+	return err;
+}
+
+void __exit fini(void)
+{
+	crypto_unregister_alg(&blk_ctr_alg);
+	crypto_unregister_alg(&blk_cbc_alg);
+	crypto_unregister_alg(&blk_ecb_alg);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Twofish Cipher Algorithm, 3-way parallel asm optimized");
+MODULE_ALIAS("twofish");
+MODULE_ALIAS("twofish-asm");
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 2f84a43..f3444f7 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -259,7 +259,9 @@ extern const char * const x86_power_flags[32];
 #define cpu_has_xmm		boot_cpu_has(X86_FEATURE_XMM)
 #define cpu_has_xmm2		boot_cpu_has(X86_FEATURE_XMM2)
 #define cpu_has_xmm3		boot_cpu_has(X86_FEATURE_XMM3)
+#define cpu_has_ssse3		boot_cpu_has(X86_FEATURE_SSSE3)
 #define cpu_has_aes		boot_cpu_has(X86_FEATURE_AES)
+#define cpu_has_avx		boot_cpu_has(X86_FEATURE_AVX)
 #define cpu_has_ht		boot_cpu_has(X86_FEATURE_HT)
 #define cpu_has_mp		boot_cpu_has(X86_FEATURE_MP)
 #define cpu_has_nx		boot_cpu_has(X86_FEATURE_NX)
@@ -287,6 +289,7 @@ extern const char * const x86_power_flags[32];
 #define cpu_has_xmm4_2		boot_cpu_has(X86_FEATURE_XMM4_2)
 #define cpu_has_x2apic		boot_cpu_has(X86_FEATURE_X2APIC)
 #define cpu_has_xsave		boot_cpu_has(X86_FEATURE_XSAVE)
+#define cpu_has_osxsave		boot_cpu_has(X86_FEATURE_OSXSAVE)
 #define cpu_has_hypervisor	boot_cpu_has(X86_FEATURE_HYPERVISOR)
 #define cpu_has_pclmulqdq	boot_cpu_has(X86_FEATURE_PCLMULQDQ)
 #define cpu_has_perfctr_core	boot_cpu_has(X86_FEATURE_PERFCTR_CORE)
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 7b5063a..864830e 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -36,7 +36,6 @@
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/debugfs.h>
-#include <linux/edac_mce.h>
 #include <linux/irq_work.h>
 
 #include <asm/processor.h>
@@ -144,23 +143,20 @@ static struct mce_log mcelog = {
 void mce_log(struct mce *mce)
 {
 	unsigned next, entry;
+	int ret = 0;
 
 	/* Emit the trace record: */
 	trace_mce_record(mce);
 
+	ret = atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, mce);
+	if (ret == NOTIFY_STOP)
+		return;
+
 	mce->finished = 0;
 	wmb();
 	for (;;) {
 		entry = rcu_dereference_check_mce(mcelog.next);
 		for (;;) {
-			/*
-			 * If edac_mce is enabled, it will check the error type
-			 * and will process it, if it is a known error.
-			 * Otherwise, the error will be sent through mcelog
-			 * interface
-			 */
-			if (edac_mce_parse(mce))
-				return;
 
 			/*
 			 * When the buffer fills up discard new entries.
@@ -556,10 +552,8 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
 		 * Don't get the IP here because it's unlikely to
 		 * have anything to do with the actual error location.
 		 */
-		if (!(flags & MCP_DONTLOG) && !mce_dont_log_ce) {
+		if (!(flags & MCP_DONTLOG) && !mce_dont_log_ce)
 			mce_log(&m);
-			atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, &m);
-		}
 
 		/*
 		 * Clear state for this bank.
diff --git a/arch/x86/mm/gup.c b/arch/x86/mm/gup.c
index dbe34b9..ea30585 100644
--- a/arch/x86/mm/gup.c
+++ b/arch/x86/mm/gup.c
@@ -108,16 +108,6 @@ static inline void get_head_page_multiple(struct page *page, int nr)
 	SetPageReferenced(page);
 }
 
-static inline void get_huge_page_tail(struct page *page)
-{
-	/*
-	 * __split_huge_page_refcount() cannot run
-	 * from under us.
-	 */
-	VM_BUG_ON(atomic_read(&page->_count) < 0);
-	atomic_inc(&page->_count);
-}
-
 static noinline int gup_huge_pmd(pmd_t pmd, unsigned long addr,
 		unsigned long end, int write, struct page **pages, int *nr)
 {
diff --git a/arch/x86/um/Kconfig b/arch/x86/um/Kconfig
new file mode 100644
index 0000000..21bebe6
--- /dev/null
+++ b/arch/x86/um/Kconfig
@@ -0,0 +1,70 @@
+mainmenu "User Mode Linux/$SUBARCH $KERNELVERSION Kernel Configuration"
+
+source "arch/um/Kconfig.common"
+
+menu "UML-specific options"
+
+menu "Host processor type and features"
+
+config CMPXCHG_LOCAL
+	bool
+	default n
+
+config CMPXCHG_DOUBLE
+	bool
+	default n
+
+source "arch/x86/Kconfig.cpu"
+
+endmenu
+
+config UML_X86
+	def_bool y
+	select GENERIC_FIND_FIRST_BIT
+
+config 64BIT
+	bool
+	default SUBARCH = "x86_64"
+
+config X86_32
+	def_bool !64BIT
+	select HAVE_AOUT
+
+config X86_64
+	def_bool 64BIT
+
+config RWSEM_XCHGADD_ALGORITHM
+	def_bool X86_XADD && 64BIT
+
+config RWSEM_GENERIC_SPINLOCK
+	def_bool !RWSEM_XCHGADD_ALGORITHM
+
+config 3_LEVEL_PGTABLES
+	bool "Three-level pagetables (EXPERIMENTAL)" if !64BIT
+	default 64BIT
+	depends on EXPERIMENTAL
+	help
+	Three-level pagetables will let UML have more than 4G of physical
+	memory.  All the memory that can't be mapped directly will be treated
+	as high memory.
+
+	However, this it experimental on 32-bit architectures, so if unsure say
+	N (on x86-64 it's automatically enabled, instead, as it's safe there).
+
+config ARCH_HAS_SC_SIGNALS
+	def_bool !64BIT
+
+config ARCH_REUSE_HOST_VSYSCALL_AREA
+	def_bool !64BIT
+
+config SMP_BROKEN
+	def_bool 64BIT
+
+config GENERIC_HWEIGHT
+	def_bool y
+
+source "arch/um/Kconfig.um"
+
+endmenu
+
+source "arch/um/Kconfig.rest"
diff --git a/arch/x86/um/Makefile b/arch/x86/um/Makefile
new file mode 100644
index 0000000..8fb5840
--- /dev/null
+++ b/arch/x86/um/Makefile
@@ -0,0 +1,45 @@
+#
+# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+#
+
+ifeq ($(CONFIG_X86_32),y)
+	BITS := 32
+else
+	BITS := 64
+endif
+
+obj-y = bug.o bugs_$(BITS).o delay.o fault.o ksyms.o ldt.o \
+	ptrace_$(BITS).o ptrace_user.o setjmp_$(BITS).o signal.o \
+	stub_$(BITS).o stub_segv.o syscalls_$(BITS).o \
+	sys_call_table_$(BITS).o sysrq_$(BITS).o tls_$(BITS).o \
+	mem_$(BITS).o subarch.o os-$(OS)/
+
+ifeq ($(CONFIG_X86_32),y)
+
+obj-y += checksum_32.o
+obj-$(CONFIG_BINFMT_ELF) += elfcore.o
+
+subarch-y = ../lib/string_32.o ../lib/atomic64_32.o ../lib/atomic64_cx8_32.o
+subarch-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += ../lib/rwsem.o
+subarch-$(CONFIG_HIGHMEM) += ../mm/highmem_32.o
+
+else
+
+obj-y += vdso/
+
+subarch-y = ../lib/csum-partial_64.o ../lib/memcpy_64.o ../lib/thunk_64.o \
+		../lib/rwsem.o
+
+endif
+
+subarch-$(CONFIG_MODULES) += ../kernel/module.o
+
+USER_OBJS := bugs_$(BITS).o ptrace_user.o fault.o
+
+extra-y += user-offsets.s
+$(obj)/user-offsets.s: c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS)
+
+UNPROFILE_OBJS := stub_segv.o
+CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING)
+
+include arch/um/scripts/Makefile.rules
diff --git a/arch/x86/um/asm/apic.h b/arch/x86/um/asm/apic.h
new file mode 100644
index 0000000..876dee8
--- /dev/null
+++ b/arch/x86/um/asm/apic.h
@@ -0,0 +1,4 @@
+#ifndef __UM_APIC_H
+#define __UM_APIC_H
+
+#endif
diff --git a/arch/x86/um/asm/arch_hweight.h b/arch/x86/um/asm/arch_hweight.h
new file mode 100644
index 0000000..c656cf4
--- /dev/null
+++ b/arch/x86/um/asm/arch_hweight.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_UM_HWEIGHT_H
+#define _ASM_UM_HWEIGHT_H
+
+#include <asm-generic/bitops/arch_hweight.h>
+
+#endif
diff --git a/arch/x86/um/asm/archparam.h b/arch/x86/um/asm/archparam.h
new file mode 100644
index 0000000..c17cf68
--- /dev/null
+++ b/arch/x86/um/asm/archparam.h
@@ -0,0 +1,20 @@
+/* 
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Copyright 2003 PathScale, Inc.
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_ARCHPARAM_H
+#define __UM_ARCHPARAM_H
+
+#ifdef CONFIG_X86_32
+
+#ifdef CONFIG_X86_PAE
+#define LAST_PKMAP 512
+#else
+#define LAST_PKMAP 1024
+#endif
+
+#endif
+
+#endif
diff --git a/arch/x86/um/asm/checksum.h b/arch/x86/um/asm/checksum.h
new file mode 100644
index 0000000..b6efe23
--- /dev/null
+++ b/arch/x86/um/asm/checksum.h
@@ -0,0 +1,10 @@
+#ifndef __UM_CHECKSUM_H
+#define __UM_CHECKSUM_H
+
+#ifdef CONFIG_X86_32
+# include "checksum_32.h"
+#else
+# include "checksum_64.h"
+#endif
+
+#endif
diff --git a/arch/x86/um/asm/checksum_32.h b/arch/x86/um/asm/checksum_32.h
new file mode 100644
index 0000000..caab742
--- /dev/null
+++ b/arch/x86/um/asm/checksum_32.h
@@ -0,0 +1,201 @@
+/*
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_SYSDEP_CHECKSUM_H
+#define __UM_SYSDEP_CHECKSUM_H
+
+#include "linux/in6.h"
+#include "linux/string.h"
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+__wsum csum_partial(const void *buff, int len, __wsum sum);
+
+/*
+ *	Note: when you get a NULL pointer exception here this means someone
+ *	passed in an incorrect kernel address to one of these functions.
+ *
+ *	If you use these functions directly please don't forget the
+ *	access_ok().
+ */
+
+static __inline__
+__wsum csum_partial_copy_nocheck(const void *src, void *dst,
+				       int len, __wsum sum)
+{
+	memcpy(dst, src, len);
+	return csum_partial(dst, len, sum);
+}
+
+/*
+ * the same as csum_partial, but copies from src while it
+ * checksums, and handles user-space pointer exceptions correctly, when needed.
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+
+static __inline__
+__wsum csum_partial_copy_from_user(const void __user *src, void *dst,
+					 int len, __wsum sum, int *err_ptr)
+{
+	if (copy_from_user(dst, src, len)) {
+		*err_ptr = -EFAULT;
+		return (__force __wsum)-1;
+	}
+
+	return csum_partial(dst, len, sum);
+}
+
+/*
+ *	This is a version of ip_compute_csum() optimized for IP headers,
+ *	which always checksum on 4 octet boundaries.
+ *
+ *	By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
+ *	Arnt Gulbrandsen.
+ */
+static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+{
+	unsigned int sum;
+
+	__asm__ __volatile__(
+	    "movl (%1), %0	;\n"
+	    "subl $4, %2	;\n"
+	    "jbe 2f		;\n"
+	    "addl 4(%1), %0	;\n"
+	    "adcl 8(%1), %0	;\n"
+	    "adcl 12(%1), %0	;\n"
+"1:	    adcl 16(%1), %0	;\n"
+	    "lea 4(%1), %1	;\n"
+	    "decl %2		;\n"
+	    "jne 1b		;\n"
+	    "adcl $0, %0	;\n"
+	    "movl %0, %2	;\n"
+	    "shrl $16, %0	;\n"
+	    "addw %w2, %w0	;\n"
+	    "adcl $0, %0	;\n"
+	    "notl %0		;\n"
+"2:				;\n"
+	/* Since the input registers which are loaded with iph and ipl
+	   are modified, we must also specify them as outputs, or gcc
+	   will assume they contain their original values. */
+	: "=r" (sum), "=r" (iph), "=r" (ihl)
+	: "1" (iph), "2" (ihl)
+	: "memory");
+	return (__force __sum16)sum;
+}
+
+/*
+ *	Fold a partial checksum
+ */
+
+static inline __sum16 csum_fold(__wsum sum)
+{
+	__asm__(
+		"addl %1, %0		;\n"
+		"adcl $0xffff, %0	;\n"
+		: "=r" (sum)
+		: "r" ((__force u32)sum << 16),
+		  "0" ((__force u32)sum & 0xffff0000)
+	);
+	return (__force __sum16)(~(__force u32)sum >> 16);
+}
+
+static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
+						   unsigned short len,
+						   unsigned short proto,
+						   __wsum sum)
+{
+    __asm__(
+	"addl %1, %0	;\n"
+	"adcl %2, %0	;\n"
+	"adcl %3, %0	;\n"
+	"adcl $0, %0	;\n"
+	: "=r" (sum)
+	: "g" (daddr), "g"(saddr), "g"((len + proto) << 8), "0"(sum));
+    return sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
+						   unsigned short len,
+						   unsigned short proto,
+						   __wsum sum)
+{
+	return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+}
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+
+static inline __sum16 ip_compute_csum(const void *buff, int len)
+{
+    return csum_fold (csum_partial(buff, len, 0));
+}
+
+#define _HAVE_ARCH_IPV6_CSUM
+static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+					  const struct in6_addr *daddr,
+					  __u32 len, unsigned short proto,
+					  __wsum sum)
+{
+	__asm__(
+		"addl 0(%1), %0		;\n"
+		"adcl 4(%1), %0		;\n"
+		"adcl 8(%1), %0		;\n"
+		"adcl 12(%1), %0	;\n"
+		"adcl 0(%2), %0		;\n"
+		"adcl 4(%2), %0		;\n"
+		"adcl 8(%2), %0		;\n"
+		"adcl 12(%2), %0	;\n"
+		"adcl %3, %0		;\n"
+		"adcl %4, %0		;\n"
+		"adcl $0, %0		;\n"
+		: "=&r" (sum)
+		: "r" (saddr), "r" (daddr),
+		  "r"(htonl(len)), "r"(htonl(proto)), "0"(sum));
+
+	return csum_fold(sum);
+}
+
+/*
+ *	Copy and checksum to user
+ */
+#define HAVE_CSUM_COPY_USER
+static __inline__ __wsum csum_and_copy_to_user(const void *src,
+						     void __user *dst,
+						     int len, __wsum sum, int *err_ptr)
+{
+	if (access_ok(VERIFY_WRITE, dst, len)) {
+		if (copy_to_user(dst, src, len)) {
+			*err_ptr = -EFAULT;
+			return (__force __wsum)-1;
+		}
+
+		return csum_partial(src, len, sum);
+	}
+
+	if (len)
+		*err_ptr = -EFAULT;
+
+	return (__force __wsum)-1; /* invalid checksum */
+}
+
+#endif
+
diff --git a/arch/x86/um/asm/checksum_64.h b/arch/x86/um/asm/checksum_64.h
new file mode 100644
index 0000000..a5be903
--- /dev/null
+++ b/arch/x86/um/asm/checksum_64.h
@@ -0,0 +1,144 @@
+/*
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_SYSDEP_CHECKSUM_H
+#define __UM_SYSDEP_CHECKSUM_H
+
+#include "linux/string.h"
+#include "linux/in6.h"
+#include "asm/uaccess.h"
+
+extern __wsum csum_partial(const void *buff, int len, __wsum sum);
+
+/*
+ *	Note: when you get a NULL pointer exception here this means someone
+ *	passed in an incorrect kernel address to one of these functions.
+ *
+ *	If you use these functions directly please don't forget the
+ *	access_ok().
+ */
+
+static __inline__
+__wsum csum_partial_copy_nocheck(const void *src, void *dst,
+				       int len, __wsum sum)
+{
+	memcpy(dst, src, len);
+	return(csum_partial(dst, len, sum));
+}
+
+static __inline__
+__wsum csum_partial_copy_from_user(const void __user *src,
+                                         void *dst, int len, __wsum sum,
+                                         int *err_ptr)
+{
+        if (copy_from_user(dst, src, len)) {
+                *err_ptr = -EFAULT;
+                return (__force __wsum)-1;
+        }
+        return csum_partial(dst, len, sum);
+}
+
+/**
+ * csum_fold - Fold and invert a 32bit checksum.
+ * sum: 32bit unfolded sum
+ *
+ * Fold a 32bit running checksum to 16bit and invert it. This is usually
+ * the last step before putting a checksum into a packet.
+ * Make sure not to mix with 64bit checksums.
+ */
+static inline __sum16 csum_fold(__wsum sum)
+{
+	__asm__(
+		"  addl %1,%0\n"
+		"  adcl $0xffff,%0"
+		: "=r" (sum)
+		: "r" ((__force u32)sum << 16),
+		  "0" ((__force u32)sum & 0xffff0000)
+	);
+	return (__force __sum16)(~(__force u32)sum >> 16);
+}
+
+/**
+ * csum_tcpup_nofold - Compute an IPv4 pseudo header checksum.
+ * @saddr: source address
+ * @daddr: destination address
+ * @len: length of packet
+ * @proto: ip protocol of packet
+ * @sum: initial sum to be added in (32bit unfolded)
+ *
+ * Returns the pseudo header checksum the input data. Result is
+ * 32bit unfolded.
+ */
+static inline __wsum
+csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
+		   unsigned short proto, __wsum sum)
+{
+	asm("  addl %1, %0\n"
+	    "  adcl %2, %0\n"
+	    "  adcl %3, %0\n"
+	    "  adcl $0, %0\n"
+		: "=r" (sum)
+	    : "g" (daddr), "g" (saddr), "g" ((len + proto) << 8), "0" (sum));
+	return sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
+					   unsigned short len,
+					   unsigned short proto,
+					   __wsum sum)
+{
+	return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+}
+
+/**
+ * ip_fast_csum - Compute the IPv4 header checksum efficiently.
+ * iph: ipv4 header
+ * ihl: length of header / 4
+ */
+static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+{
+	unsigned int sum;
+
+	asm(	"  movl (%1), %0\n"
+		"  subl $4, %2\n"
+		"  jbe 2f\n"
+		"  addl 4(%1), %0\n"
+		"  adcl 8(%1), %0\n"
+		"  adcl 12(%1), %0\n"
+		"1: adcl 16(%1), %0\n"
+		"  lea 4(%1), %1\n"
+		"  decl %2\n"
+		"  jne	1b\n"
+		"  adcl $0, %0\n"
+		"  movl %0, %2\n"
+		"  shrl $16, %0\n"
+		"  addw %w2, %w0\n"
+		"  adcl $0, %0\n"
+		"  notl %0\n"
+		"2:"
+	/* Since the input registers which are loaded with iph and ipl
+	   are modified, we must also specify them as outputs, or gcc
+	   will assume they contain their original values. */
+	: "=r" (sum), "=r" (iph), "=r" (ihl)
+	: "1" (iph), "2" (ihl)
+	: "memory");
+	return (__force __sum16)sum;
+}
+
+static inline unsigned add32_with_carry(unsigned a, unsigned b)
+{
+        asm("addl %2,%0\n\t"
+            "adcl $0,%0"
+            : "=r" (a)
+            : "0" (a), "r" (b));
+        return a;
+}
+
+extern __sum16 ip_compute_csum(const void *buff, int len);
+
+#endif
diff --git a/arch/x86/um/asm/desc.h b/arch/x86/um/asm/desc.h
new file mode 100644
index 0000000..4ec34a5
--- /dev/null
+++ b/arch/x86/um/asm/desc.h
@@ -0,0 +1,16 @@
+#ifndef __UM_DESC_H
+#define __UM_DESC_H
+
+/* Taken from asm-i386/desc.h, it's the only thing we need. The rest wouldn't
+ * compile, and has never been used. */
+#define LDT_empty(info) (\
+	(info)->base_addr	== 0	&& \
+	(info)->limit		== 0	&& \
+	(info)->contents	== 0	&& \
+	(info)->read_exec_only	== 1	&& \
+	(info)->seg_32bit	== 0	&& \
+	(info)->limit_in_pages	== 0	&& \
+	(info)->seg_not_present	== 1	&& \
+	(info)->useable		== 0	)
+
+#endif
diff --git a/arch/x86/um/asm/elf.h b/arch/x86/um/asm/elf.h
new file mode 100644
index 0000000..f3b0633
--- /dev/null
+++ b/arch/x86/um/asm/elf.h
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+#ifndef __UM_ELF_X86_H
+#define __UM_ELF_X86_H
+
+#include <asm/user.h>
+#include "skas.h"
+
+#ifdef CONFIG_X86_32
+
+#define R_386_NONE	0
+#define R_386_32	1
+#define R_386_PC32	2
+#define R_386_GOT32	3
+#define R_386_PLT32	4
+#define R_386_COPY	5
+#define R_386_GLOB_DAT	6
+#define R_386_JMP_SLOT	7
+#define R_386_RELATIVE	8
+#define R_386_GOTOFF	9
+#define R_386_GOTPC	10
+#define R_386_NUM	11
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) \
+	(((x)->e_machine == EM_386) || ((x)->e_machine == EM_486))
+
+#define ELF_CLASS	ELFCLASS32
+#define ELF_DATA        ELFDATA2LSB
+#define ELF_ARCH        EM_386
+
+#define ELF_PLAT_INIT(regs, load_addr) do { \
+	PT_REGS_EBX(regs) = 0; \
+	PT_REGS_ECX(regs) = 0; \
+	PT_REGS_EDX(regs) = 0; \
+	PT_REGS_ESI(regs) = 0; \
+	PT_REGS_EDI(regs) = 0; \
+	PT_REGS_EBP(regs) = 0; \
+	PT_REGS_EAX(regs) = 0; \
+} while (0)
+
+/* Shamelessly stolen from include/asm-i386/elf.h */
+
+#define ELF_CORE_COPY_REGS(pr_reg, regs) do {	\
+	pr_reg[0] = PT_REGS_EBX(regs);		\
+	pr_reg[1] = PT_REGS_ECX(regs);		\
+	pr_reg[2] = PT_REGS_EDX(regs);		\
+	pr_reg[3] = PT_REGS_ESI(regs);		\
+	pr_reg[4] = PT_REGS_EDI(regs);		\
+	pr_reg[5] = PT_REGS_EBP(regs);		\
+	pr_reg[6] = PT_REGS_EAX(regs);		\
+	pr_reg[7] = PT_REGS_DS(regs);		\
+	pr_reg[8] = PT_REGS_ES(regs);		\
+	/* fake once used fs and gs selectors? */	\
+	pr_reg[9] = PT_REGS_DS(regs);		\
+	pr_reg[10] = PT_REGS_DS(regs);		\
+	pr_reg[11] = PT_REGS_SYSCALL_NR(regs);	\
+	pr_reg[12] = PT_REGS_IP(regs);		\
+	pr_reg[13] = PT_REGS_CS(regs);		\
+	pr_reg[14] = PT_REGS_EFLAGS(regs);	\
+	pr_reg[15] = PT_REGS_SP(regs);		\
+	pr_reg[16] = PT_REGS_SS(regs);		\
+} while (0);
+
+extern char * elf_aux_platform;
+#define ELF_PLATFORM (elf_aux_platform)
+
+extern unsigned long vsyscall_ehdr;
+extern unsigned long vsyscall_end;
+extern unsigned long __kernel_vsyscall;
+
+/*
+ * This is the range that is readable by user mode, and things
+ * acting like user mode such as get_user_pages.
+ */
+#define FIXADDR_USER_START      vsyscall_ehdr
+#define FIXADDR_USER_END        vsyscall_end
+
+
+/*
+ * Architecture-neutral AT_ values in 0-17, leave some room
+ * for more of them, start the x86-specific ones at 32.
+ */
+#define AT_SYSINFO		32
+#define AT_SYSINFO_EHDR		33
+
+#define ARCH_DLINFO						\
+do {								\
+	if ( vsyscall_ehdr ) {					\
+		NEW_AUX_ENT(AT_SYSINFO,	__kernel_vsyscall);	\
+		NEW_AUX_ENT(AT_SYSINFO_EHDR, vsyscall_ehdr);	\
+	}							\
+} while (0)
+
+#else
+
+/* x86-64 relocation types, taken from asm-x86_64/elf.h */
+#define R_X86_64_NONE		0	/* No reloc */
+#define R_X86_64_64		1	/* Direct 64 bit  */
+#define R_X86_64_PC32		2	/* PC relative 32 bit signed */
+#define R_X86_64_GOT32		3	/* 32 bit GOT entry */
+#define R_X86_64_PLT32		4	/* 32 bit PLT address */
+#define R_X86_64_COPY		5	/* Copy symbol at runtime */
+#define R_X86_64_GLOB_DAT	6	/* Create GOT entry */
+#define R_X86_64_JUMP_SLOT	7	/* Create PLT entry */
+#define R_X86_64_RELATIVE	8	/* Adjust by program base */
+#define R_X86_64_GOTPCREL	9	/* 32 bit signed pc relative
+					   offset to GOT */
+#define R_X86_64_32		10	/* Direct 32 bit zero extended */
+#define R_X86_64_32S		11	/* Direct 32 bit sign extended */
+#define R_X86_64_16		12	/* Direct 16 bit zero extended */
+#define R_X86_64_PC16		13	/* 16 bit sign extended pc relative */
+#define R_X86_64_8		14	/* Direct 8 bit sign extended  */
+#define R_X86_64_PC8		15	/* 8 bit sign extended pc relative */
+
+#define R_X86_64_NUM		16
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) \
+	((x)->e_machine == EM_X86_64)
+
+#define ELF_CLASS	ELFCLASS64
+#define ELF_DATA        ELFDATA2LSB
+#define ELF_ARCH        EM_X86_64
+
+#define ELF_PLAT_INIT(regs, load_addr)    do { \
+	PT_REGS_RBX(regs) = 0; \
+	PT_REGS_RCX(regs) = 0; \
+	PT_REGS_RDX(regs) = 0; \
+	PT_REGS_RSI(regs) = 0; \
+	PT_REGS_RDI(regs) = 0; \
+	PT_REGS_RBP(regs) = 0; \
+	PT_REGS_RAX(regs) = 0; \
+	PT_REGS_R8(regs) = 0; \
+	PT_REGS_R9(regs) = 0; \
+	PT_REGS_R10(regs) = 0; \
+	PT_REGS_R11(regs) = 0; \
+	PT_REGS_R12(regs) = 0; \
+	PT_REGS_R13(regs) = 0; \
+	PT_REGS_R14(regs) = 0; \
+	PT_REGS_R15(regs) = 0; \
+} while (0)
+
+#define ELF_CORE_COPY_REGS(pr_reg, _regs)		\
+	(pr_reg)[0] = (_regs)->regs.gp[0];			\
+	(pr_reg)[1] = (_regs)->regs.gp[1];			\
+	(pr_reg)[2] = (_regs)->regs.gp[2];			\
+	(pr_reg)[3] = (_regs)->regs.gp[3];			\
+	(pr_reg)[4] = (_regs)->regs.gp[4];			\
+	(pr_reg)[5] = (_regs)->regs.gp[5];			\
+	(pr_reg)[6] = (_regs)->regs.gp[6];			\
+	(pr_reg)[7] = (_regs)->regs.gp[7];			\
+	(pr_reg)[8] = (_regs)->regs.gp[8];			\
+	(pr_reg)[9] = (_regs)->regs.gp[9];			\
+	(pr_reg)[10] = (_regs)->regs.gp[10];			\
+	(pr_reg)[11] = (_regs)->regs.gp[11];			\
+	(pr_reg)[12] = (_regs)->regs.gp[12];			\
+	(pr_reg)[13] = (_regs)->regs.gp[13];			\
+	(pr_reg)[14] = (_regs)->regs.gp[14];			\
+	(pr_reg)[15] = (_regs)->regs.gp[15];			\
+	(pr_reg)[16] = (_regs)->regs.gp[16];			\
+	(pr_reg)[17] = (_regs)->regs.gp[17];			\
+	(pr_reg)[18] = (_regs)->regs.gp[18];			\
+	(pr_reg)[19] = (_regs)->regs.gp[19];			\
+	(pr_reg)[20] = (_regs)->regs.gp[20];			\
+	(pr_reg)[21] = current->thread.arch.fs;			\
+	(pr_reg)[22] = 0;					\
+	(pr_reg)[23] = 0;					\
+	(pr_reg)[24] = 0;					\
+	(pr_reg)[25] = 0;					\
+	(pr_reg)[26] = 0;
+
+#define ELF_PLATFORM "x86_64"
+
+/* No user-accessible fixmap addresses, i.e. vsyscall */
+#define FIXADDR_USER_START      0
+#define FIXADDR_USER_END        0
+
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
+struct linux_binprm;
+extern int arch_setup_additional_pages(struct linux_binprm *bprm,
+	int uses_interp);
+
+extern unsigned long um_vdso_addr;
+#define AT_SYSINFO_EHDR 33
+#define ARCH_DLINFO	NEW_AUX_ENT(AT_SYSINFO_EHDR, um_vdso_addr)
+
+#endif
+
+typedef unsigned long elf_greg_t;
+
+#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef struct user_i387_struct elf_fpregset_t;
+
+#define task_pt_regs(t) (&(t)->thread.regs)
+
+struct task_struct;
+
+extern int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu);
+
+#define ELF_CORE_COPY_FPREGS(t, fpu) elf_core_copy_fpregs(t, fpu)
+
+#define ELF_EXEC_PAGESIZE 4096
+
+#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
+
+extern long elf_aux_hwcap;
+#define ELF_HWCAP (elf_aux_hwcap)
+
+#define SET_PERSONALITY(ex) do ; while(0)
+#define __HAVE_ARCH_GATE_AREA 1
+
+#endif
diff --git a/arch/x86/um/asm/irq_vectors.h b/arch/x86/um/asm/irq_vectors.h
new file mode 100644
index 0000000..272a81e
--- /dev/null
+++ b/arch/x86/um/asm/irq_vectors.h
@@ -0,0 +1,10 @@
+/* 
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_IRQ_VECTORS_H
+#define __UM_IRQ_VECTORS_H
+
+#endif
+
diff --git a/arch/x86/um/asm/mm_context.h b/arch/x86/um/asm/mm_context.h
new file mode 100644
index 0000000..4a73d63
--- /dev/null
+++ b/arch/x86/um/asm/mm_context.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
+ * Licensed under the GPL
+ *
+ * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
+ */
+
+#ifndef __ASM_LDT_H
+#define __ASM_LDT_H
+
+#include <linux/mutex.h>
+#include <asm/ldt.h>
+
+extern void ldt_host_info(void);
+
+#define LDT_PAGES_MAX \
+	((LDT_ENTRIES * LDT_ENTRY_SIZE)/PAGE_SIZE)
+#define LDT_ENTRIES_PER_PAGE \
+	(PAGE_SIZE/LDT_ENTRY_SIZE)
+#define LDT_DIRECT_ENTRIES \
+	((LDT_PAGES_MAX*sizeof(void *))/LDT_ENTRY_SIZE)
+
+struct ldt_entry {
+	__u32 a;
+	__u32 b;
+};
+
+typedef struct uml_ldt {
+	int entry_count;
+	struct mutex lock;
+	union {
+		struct ldt_entry * pages[LDT_PAGES_MAX];
+		struct ldt_entry entries[LDT_DIRECT_ENTRIES];
+	} u;
+} uml_ldt_t;
+
+#define LDT_entry_a(info) \
+	((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
+
+#define LDT_entry_b(info) \
+	(((info)->base_addr & 0xff000000) | \
+	(((info)->base_addr & 0x00ff0000) >> 16) | \
+	((info)->limit & 0xf0000) | \
+	(((info)->read_exec_only ^ 1) << 9) | \
+	((info)->contents << 10) | \
+	(((info)->seg_not_present ^ 1) << 15) | \
+	((info)->seg_32bit << 22) | \
+	((info)->limit_in_pages << 23) | \
+	((info)->useable << 20) | \
+	0x7000)
+
+#define _LDT_empty(info) (\
+	(info)->base_addr	== 0	&& \
+	(info)->limit		== 0	&& \
+	(info)->contents	== 0	&& \
+	(info)->read_exec_only	== 1	&& \
+	(info)->seg_32bit	== 0	&& \
+	(info)->limit_in_pages	== 0	&& \
+	(info)->seg_not_present	== 1	&& \
+	(info)->useable		== 0	)
+
+#ifdef CONFIG_X86_64
+#define LDT_empty(info) (_LDT_empty(info) && ((info)->lm == 0))
+#else
+#define LDT_empty(info) (_LDT_empty(info))
+#endif
+
+struct uml_arch_mm_context {
+	uml_ldt_t ldt;
+};
+
+#endif
diff --git a/arch/x86/um/asm/module.h b/arch/x86/um/asm/module.h
new file mode 100644
index 0000000..61af80e
--- /dev/null
+++ b/arch/x86/um/asm/module.h
@@ -0,0 +1,23 @@
+#ifndef __UM_MODULE_H
+#define __UM_MODULE_H
+
+/* UML is simple */
+struct mod_arch_specific
+{
+};
+
+#ifdef CONFIG_X86_32
+
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+#define Elf_Ehdr Elf32_Ehdr
+
+#else
+
+#define Elf_Shdr Elf64_Shdr
+#define Elf_Sym Elf64_Sym
+#define Elf_Ehdr Elf64_Ehdr
+
+#endif
+
+#endif
diff --git a/arch/x86/um/asm/processor.h b/arch/x86/um/asm/processor.h
new file mode 100644
index 0000000..118c143
--- /dev/null
+++ b/arch/x86/um/asm/processor.h
@@ -0,0 +1,22 @@
+#ifndef __UM_PROCESSOR_H
+#define __UM_PROCESSOR_H
+
+/* include faultinfo structure */
+#include <sysdep/faultinfo.h>
+
+#ifdef CONFIG_X86_32
+# include "processor_32.h"
+#else
+# include "processor_64.h"
+#endif
+
+#define KSTK_EIP(tsk) KSTK_REG(tsk, HOST_IP)
+#define KSTK_ESP(tsk) KSTK_REG(tsk, HOST_IP)
+#define KSTK_EBP(tsk) KSTK_REG(tsk, HOST_BP)
+
+#define ARCH_IS_STACKGROW(address) \
+       (address + 65536 + 32 * sizeof(unsigned long) >= UPT_SP(&current->thread.regs.regs))
+
+#include <asm/processor-generic.h>
+
+#endif
diff --git a/arch/x86/um/asm/processor_32.h b/arch/x86/um/asm/processor_32.h
new file mode 100644
index 0000000..018f732
--- /dev/null
+++ b/arch/x86/um/asm/processor_32.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_PROCESSOR_I386_H
+#define __UM_PROCESSOR_I386_H
+
+#include <linux/string.h>
+#include <asm/segment.h>
+#include <asm/ldt.h>
+
+extern int host_has_cmov;
+
+struct uml_tls_struct {
+	struct user_desc tls;
+	unsigned flushed:1;
+	unsigned present:1;
+};
+
+struct arch_thread {
+	struct uml_tls_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
+	unsigned long debugregs[8];
+	int debugregs_seq;
+	struct faultinfo faultinfo;
+};
+
+#define INIT_ARCH_THREAD { \
+	.tls_array  		= { [ 0 ... GDT_ENTRY_TLS_ENTRIES - 1 ] = \
+				    { .present = 0, .flushed = 0 } }, \
+	.debugregs  		= { [ 0 ... 7 ] = 0 }, \
+	.debugregs_seq		= 0, \
+	.faultinfo		= { 0, 0, 0 } \
+}
+
+static inline void arch_flush_thread(struct arch_thread *thread)
+{
+	/* Clear any TLS still hanging */
+	memset(&thread->tls_array, 0, sizeof(thread->tls_array));
+}
+
+static inline void arch_copy_thread(struct arch_thread *from,
+                                    struct arch_thread *to)
+{
+        memcpy(&to->tls_array, &from->tls_array, sizeof(from->tls_array));
+}
+
+#include <asm/user.h>
+
+/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
+static inline void rep_nop(void)
+{
+	__asm__ __volatile__("rep;nop": : :"memory");
+}
+
+#define cpu_relax()	rep_nop()
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter"). Stolen
+ * from asm-i386/processor.h
+ */
+#define current_text_addr() \
+	({ void *pc; __asm__("movl $1f,%0\n1:":"=g" (pc)); pc; })
+
+#endif
diff --git a/arch/x86/um/asm/processor_64.h b/arch/x86/um/asm/processor_64.h
new file mode 100644
index 0000000..61de92d
--- /dev/null
+++ b/arch/x86/um/asm/processor_64.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_PROCESSOR_X86_64_H
+#define __UM_PROCESSOR_X86_64_H
+
+struct arch_thread {
+        unsigned long debugregs[8];
+        int debugregs_seq;
+        unsigned long fs;
+        struct faultinfo faultinfo;
+};
+
+/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
+static inline void rep_nop(void)
+{
+	__asm__ __volatile__("rep;nop": : :"memory");
+}
+
+#define cpu_relax()   rep_nop()
+
+#define INIT_ARCH_THREAD { .debugregs  		= { [ 0 ... 7 ] = 0 }, \
+			   .debugregs_seq	= 0, \
+			   .fs			= 0, \
+			   .faultinfo		= { 0, 0, 0 } }
+
+static inline void arch_flush_thread(struct arch_thread *thread)
+{
+}
+
+static inline void arch_copy_thread(struct arch_thread *from,
+                                    struct arch_thread *to)
+{
+	to->fs = from->fs;
+}
+
+#include <asm/user.h>
+
+#define current_text_addr() \
+	({ void *pc; __asm__("movq $1f,%0\n1:":"=g" (pc)); pc; })
+
+#endif
diff --git a/arch/x86/um/asm/ptrace.h b/arch/x86/um/asm/ptrace.h
new file mode 100644
index 0000000..c8aca8c
--- /dev/null
+++ b/arch/x86/um/asm/ptrace.h
@@ -0,0 +1,5 @@
+#ifdef CONFIG_X86_32
+# include "ptrace_32.h"
+#else
+# include "ptrace_64.h"
+#endif
diff --git a/arch/x86/um/asm/ptrace_32.h b/arch/x86/um/asm/ptrace_32.h
new file mode 100644
index 0000000..5d2a591
--- /dev/null
+++ b/arch/x86/um/asm/ptrace_32.h
@@ -0,0 +1,51 @@
+/* 
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_PTRACE_I386_H
+#define __UM_PTRACE_I386_H
+
+#define HOST_AUDIT_ARCH AUDIT_ARCH_I386
+
+#include "linux/compiler.h"
+#include "asm/ptrace-generic.h"
+
+#define PT_REGS_EAX(r) UPT_EAX(&(r)->regs)
+#define PT_REGS_EBX(r) UPT_EBX(&(r)->regs)
+#define PT_REGS_ECX(r) UPT_ECX(&(r)->regs)
+#define PT_REGS_EDX(r) UPT_EDX(&(r)->regs)
+#define PT_REGS_ESI(r) UPT_ESI(&(r)->regs)
+#define PT_REGS_EDI(r) UPT_EDI(&(r)->regs)
+#define PT_REGS_EBP(r) UPT_EBP(&(r)->regs)
+
+#define PT_REGS_CS(r) UPT_CS(&(r)->regs)
+#define PT_REGS_SS(r) UPT_SS(&(r)->regs)
+#define PT_REGS_DS(r) UPT_DS(&(r)->regs)
+#define PT_REGS_ES(r) UPT_ES(&(r)->regs)
+#define PT_REGS_FS(r) UPT_FS(&(r)->regs)
+#define PT_REGS_GS(r) UPT_GS(&(r)->regs)
+
+#define PT_REGS_EFLAGS(r) UPT_EFLAGS(&(r)->regs)
+
+#define PT_REGS_ORIG_SYSCALL(r) PT_REGS_EAX(r)
+#define PT_REGS_SYSCALL_RET(r) PT_REGS_EAX(r)
+#define PT_FIX_EXEC_STACK(sp) do ; while(0)
+
+#define profile_pc(regs) PT_REGS_IP(regs)
+
+#define user_mode(r) UPT_IS_USER(&(r)->regs)
+
+/*
+ * Forward declaration to avoid including sysdep/tls.h, which causes a
+ * circular include, and compilation failures.
+ */
+struct user_desc;
+
+extern int ptrace_get_thread_area(struct task_struct *child, int idx,
+                                  struct user_desc __user *user_desc);
+
+extern int ptrace_set_thread_area(struct task_struct *child, int idx,
+                                  struct user_desc __user *user_desc);
+
+#endif
diff --git a/arch/x86/um/asm/ptrace_64.h b/arch/x86/um/asm/ptrace_64.h
new file mode 100644
index 0000000..706a0d8
--- /dev/null
+++ b/arch/x86/um/asm/ptrace_64.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_PTRACE_X86_64_H
+#define __UM_PTRACE_X86_64_H
+
+#include "linux/compiler.h"
+#include "asm/errno.h"
+
+#define __FRAME_OFFSETS /* Needed to get the R* macros */
+#include "asm/ptrace-generic.h"
+
+#define HOST_AUDIT_ARCH AUDIT_ARCH_X86_64
+
+#define PT_REGS_RBX(r) UPT_RBX(&(r)->regs)
+#define PT_REGS_RCX(r) UPT_RCX(&(r)->regs)
+#define PT_REGS_RDX(r) UPT_RDX(&(r)->regs)
+#define PT_REGS_RSI(r) UPT_RSI(&(r)->regs)
+#define PT_REGS_RDI(r) UPT_RDI(&(r)->regs)
+#define PT_REGS_RBP(r) UPT_RBP(&(r)->regs)
+#define PT_REGS_RAX(r) UPT_RAX(&(r)->regs)
+#define PT_REGS_R8(r) UPT_R8(&(r)->regs)
+#define PT_REGS_R9(r) UPT_R9(&(r)->regs)
+#define PT_REGS_R10(r) UPT_R10(&(r)->regs)
+#define PT_REGS_R11(r) UPT_R11(&(r)->regs)
+#define PT_REGS_R12(r) UPT_R12(&(r)->regs)
+#define PT_REGS_R13(r) UPT_R13(&(r)->regs)
+#define PT_REGS_R14(r) UPT_R14(&(r)->regs)
+#define PT_REGS_R15(r) UPT_R15(&(r)->regs)
+
+#define PT_REGS_FS(r) UPT_FS(&(r)->regs)
+#define PT_REGS_GS(r) UPT_GS(&(r)->regs)
+#define PT_REGS_DS(r) UPT_DS(&(r)->regs)
+#define PT_REGS_ES(r) UPT_ES(&(r)->regs)
+#define PT_REGS_SS(r) UPT_SS(&(r)->regs)
+#define PT_REGS_CS(r) UPT_CS(&(r)->regs)
+
+#define PT_REGS_ORIG_RAX(r) UPT_ORIG_RAX(&(r)->regs)
+#define PT_REGS_RIP(r) UPT_IP(&(r)->regs)
+#define PT_REGS_SP(r) UPT_SP(&(r)->regs)
+
+#define PT_REGS_EFLAGS(r) UPT_EFLAGS(&(r)->regs)
+
+/* XXX */
+#define user_mode(r) UPT_IS_USER(&(r)->regs)
+#define PT_REGS_ORIG_SYSCALL(r) PT_REGS_RAX(r)
+#define PT_REGS_SYSCALL_RET(r) PT_REGS_RAX(r)
+
+#define PT_FIX_EXEC_STACK(sp) do ; while(0)
+
+#define profile_pc(regs) PT_REGS_IP(regs)
+
+struct user_desc;
+
+static inline int ptrace_get_thread_area(struct task_struct *child, int idx,
+                                         struct user_desc __user *user_desc)
+{
+        return -ENOSYS;
+}
+
+static inline int ptrace_set_thread_area(struct task_struct *child, int idx,
+                                         struct user_desc __user *user_desc)
+{
+        return -ENOSYS;
+}
+
+extern long arch_prctl(struct task_struct *task, int code,
+		       unsigned long __user *addr);
+#endif
diff --git a/arch/x86/um/asm/required-features.h b/arch/x86/um/asm/required-features.h
new file mode 100644
index 0000000..dfb967b
--- /dev/null
+++ b/arch/x86/um/asm/required-features.h
@@ -0,0 +1,9 @@
+#ifndef __UM_REQUIRED_FEATURES_H
+#define __UM_REQUIRED_FEATURES_H
+
+/*
+ * Nothing to see, just need something for the i386 and x86_64 asm
+ * headers to include.
+ */
+
+#endif
diff --git a/arch/x86/um/asm/segment.h b/arch/x86/um/asm/segment.h
new file mode 100644
index 0000000..45183fc
--- /dev/null
+++ b/arch/x86/um/asm/segment.h
@@ -0,0 +1,10 @@
+#ifndef __UM_SEGMENT_H
+#define __UM_SEGMENT_H
+
+extern int host_gdt_entry_tls_min;
+
+#define GDT_ENTRY_TLS_ENTRIES 3
+#define GDT_ENTRY_TLS_MIN host_gdt_entry_tls_min
+#define GDT_ENTRY_TLS_MAX (GDT_ENTRY_TLS_MIN + GDT_ENTRY_TLS_ENTRIES - 1)
+
+#endif
diff --git a/arch/x86/um/asm/system.h b/arch/x86/um/asm/system.h
new file mode 100644
index 0000000..a459fd9
--- /dev/null
+++ b/arch/x86/um/asm/system.h
@@ -0,0 +1,135 @@
+#ifndef _ASM_X86_SYSTEM_H_
+#define _ASM_X86_SYSTEM_H_
+
+#include <asm/asm.h>
+#include <asm/segment.h>
+#include <asm/cpufeature.h>
+#include <asm/cmpxchg.h>
+#include <asm/nops.h>
+
+#include <linux/kernel.h>
+#include <linux/irqflags.h>
+
+/* entries in ARCH_DLINFO: */
+#ifdef CONFIG_IA32_EMULATION
+# define AT_VECTOR_SIZE_ARCH 2
+#else
+# define AT_VECTOR_SIZE_ARCH 1
+#endif
+
+extern unsigned long arch_align_stack(unsigned long sp);
+
+void default_idle(void);
+
+/*
+ * Force strict CPU ordering.
+ * And yes, this is required on UP too when we're talking
+ * to devices.
+ */
+#ifdef CONFIG_X86_32
+/*
+ * Some non-Intel clones support out of order store. wmb() ceases to be a
+ * nop for these.
+ */
+#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
+#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
+#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
+#else
+#define mb() 	asm volatile("mfence":::"memory")
+#define rmb()	asm volatile("lfence":::"memory")
+#define wmb()	asm volatile("sfence" ::: "memory")
+#endif
+
+/**
+ * read_barrier_depends - Flush all pending reads that subsequents reads
+ * depend on.
+ *
+ * No data-dependent reads from memory-like regions are ever reordered
+ * over this barrier.  All reads preceding this primitive are guaranteed
+ * to access memory (but not necessarily other CPUs' caches) before any
+ * reads following this primitive that depend on the data return by
+ * any of the preceding reads.  This primitive is much lighter weight than
+ * rmb() on most CPUs, and is never heavier weight than is
+ * rmb().
+ *
+ * These ordering constraints are respected by both the local CPU
+ * and the compiler.
+ *
+ * Ordering is not guaranteed by anything other than these primitives,
+ * not even by data dependencies.  See the documentation for
+ * memory_barrier() for examples and URLs to more information.
+ *
+ * For example, the following code would force ordering (the initial
+ * value of "a" is zero, "b" is one, and "p" is "&a"):
+ *
+ * <programlisting>
+ *	CPU 0				CPU 1
+ *
+ *	b = 2;
+ *	memory_barrier();
+ *	p = &b;				q = p;
+ *					read_barrier_depends();
+ *					d = *q;
+ * </programlisting>
+ *
+ * because the read of "*q" depends on the read of "p" and these
+ * two reads are separated by a read_barrier_depends().  However,
+ * the following code, with the same initial values for "a" and "b":
+ *
+ * <programlisting>
+ *	CPU 0				CPU 1
+ *
+ *	a = 2;
+ *	memory_barrier();
+ *	b = 3;				y = b;
+ *					read_barrier_depends();
+ *					x = a;
+ * </programlisting>
+ *
+ * does not enforce ordering, since there is no data dependency between
+ * the read of "a" and the read of "b".  Therefore, on some CPUs, such
+ * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
+ * in cases like this where there are no data dependencies.
+ **/
+
+#define read_barrier_depends()	do { } while (0)
+
+#ifdef CONFIG_SMP
+#define smp_mb()	mb()
+#ifdef CONFIG_X86_PPRO_FENCE
+# define smp_rmb()	rmb()
+#else
+# define smp_rmb()	barrier()
+#endif
+#ifdef CONFIG_X86_OOSTORE
+# define smp_wmb() 	wmb()
+#else
+# define smp_wmb()	barrier()
+#endif
+#define smp_read_barrier_depends()	read_barrier_depends()
+#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
+#else
+#define smp_mb()	barrier()
+#define smp_rmb()	barrier()
+#define smp_wmb()	barrier()
+#define smp_read_barrier_depends()	do { } while (0)
+#define set_mb(var, value) do { var = value; barrier(); } while (0)
+#endif
+
+/*
+ * Stop RDTSC speculation. This is needed when you need to use RDTSC
+ * (or get_cycles or vread that possibly accesses the TSC) in a defined
+ * code region.
+ *
+ * (Could use an alternative three way for this if there was one.)
+ */
+static inline void rdtsc_barrier(void)
+{
+	alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC);
+	alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
+}
+
+extern void *_switch_to(void *prev, void *next, void *last);
+#define switch_to(prev, next, last) prev = _switch_to(prev, next, last)
+
+#endif
diff --git a/arch/x86/um/asm/vm-flags.h b/arch/x86/um/asm/vm-flags.h
new file mode 100644
index 0000000..7c297e9
--- /dev/null
+++ b/arch/x86/um/asm/vm-flags.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
+ * Copyright 2003 PathScale, Inc.
+ * Licensed under the GPL
+ */
+
+#ifndef __VM_FLAGS_X86_H
+#define __VM_FLAGS_X86_H
+
+#ifdef CONFIG_X86_32
+
+#define VM_DATA_DEFAULT_FLAGS \
+	(VM_READ | VM_WRITE | \
+	((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
+		 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#else
+
+#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
+	VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+#define VM_STACK_DEFAULT_FLAGS (VM_GROWSDOWN | VM_READ | VM_WRITE | \
+	VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#endif
+#endif
diff --git a/arch/x86/um/bug.c b/arch/x86/um/bug.c
new file mode 100644
index 0000000..e8034e3
--- /dev/null
+++ b/arch/x86/um/bug.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL V2
+ */
+
+#include <linux/uaccess.h>
+
+/*
+ * Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because
+ * that's not relevant in skas mode.
+ */
+
+int is_valid_bugaddr(unsigned long eip)
+{
+	unsigned short ud2;
+
+	if (probe_kernel_address((unsigned short __user *)eip, ud2))
+		return 0;
+
+	return ud2 == 0x0b0f;
+}
diff --git a/arch/x86/um/bugs_32.c b/arch/x86/um/bugs_32.c
new file mode 100644
index 0000000..a1fba5f
--- /dev/null
+++ b/arch/x86/um/bugs_32.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#include <signal.h>
+#include "kern_util.h"
+#include "longjmp.h"
+#include "sysdep/ptrace.h"
+#include <generated/asm-offsets.h>
+
+/* Set during early boot */
+static int host_has_cmov = 1;
+static jmp_buf cmov_test_return;
+
+#define TASK_PID(task) *((int *) &(((char *) (task))[HOST_TASK_PID]))
+
+static void cmov_sigill_test_handler(int sig)
+{
+	host_has_cmov = 0;
+	longjmp(cmov_test_return, 1);
+}
+
+void arch_check_bugs(void)
+{
+	struct sigaction old, new;
+
+	printk(UM_KERN_INFO "Checking for host processor cmov support...");
+	new.sa_handler = cmov_sigill_test_handler;
+
+	/* Make sure that SIGILL is enabled after the handler longjmps back */
+	new.sa_flags = SA_NODEFER;
+	sigemptyset(&new.sa_mask);
+	sigaction(SIGILL, &new, &old);
+
+	if (setjmp(cmov_test_return) == 0) {
+		unsigned long foo = 0;
+		__asm__ __volatile__("cmovz %0, %1" : "=r" (foo) : "0" (foo));
+		printk(UM_KERN_CONT "Yes\n");
+	} else
+		printk(UM_KERN_CONT "No\n");
+
+	sigaction(SIGILL, &old, &new);
+}
+
+void arch_examine_signal(int sig, struct uml_pt_regs *regs)
+{
+	unsigned char tmp[2];
+
+	/*
+	 * This is testing for a cmov (0x0f 0x4x) instruction causing a
+	 * SIGILL in init.
+	 */
+	if ((sig != SIGILL) || (TASK_PID(get_current()) != 1))
+		return;
+
+	if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2)) {
+		printk(UM_KERN_ERR "SIGILL in init, could not read "
+		       "instructions!\n");
+		return;
+	}
+
+	if ((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40))
+		return;
+
+	if (host_has_cmov == 0)
+		printk(UM_KERN_ERR "SIGILL caused by cmov, which this "
+		       "processor doesn't implement.  Boot a filesystem "
+		       "compiled for older processors");
+	else if (host_has_cmov == 1)
+		printk(UM_KERN_ERR "SIGILL caused by cmov, which this "
+		       "processor claims to implement");
+	else
+		printk(UM_KERN_ERR "Bad value for host_has_cmov (%d)",
+			host_has_cmov);
+}
diff --git a/arch/x86/um/bugs_64.c b/arch/x86/um/bugs_64.c
new file mode 100644
index 0000000..44e02ba
--- /dev/null
+++ b/arch/x86/um/bugs_64.c
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#include "sysdep/ptrace.h"
+
+void arch_check_bugs(void)
+{
+}
+
+void arch_examine_signal(int sig, struct uml_pt_regs *regs)
+{
+}
diff --git a/arch/x86/um/checksum_32.S b/arch/x86/um/checksum_32.S
new file mode 100644
index 0000000..f058d2f
--- /dev/null
+++ b/arch/x86/um/checksum_32.S
@@ -0,0 +1,458 @@
+/*
+ * INET		An implementation of the TCP/IP protocol suite for the LINUX
+ *		operating system.  INET is implemented using the  BSD Socket
+ *		interface as the means of communication with the user level.
+ *
+ *		IP/TCP/UDP checksumming routines
+ *
+ * Authors:	Jorge Cwik, <jorge@laser.satlink.net>
+ *		Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ *		Tom May, <ftom@netcom.com>
+ *              Pentium Pro/II routines:
+ *              Alexander Kjeldaas <astor@guardian.no>
+ *              Finn Arne Gangstad <finnag@guardian.no>
+ *		Lots of code moved from tcp.c and ip.c; see those files
+ *		for more names.
+ *
+ * Changes:     Ingo Molnar, converted csum_partial_copy() to 2.1 exception
+ *			     handling.
+ *		Andi Kleen,  add zeroing on error
+ *                   converted to pure assembler
+ *
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ */
+
+#include <asm/errno.h>
+				
+/*
+ * computes a partial checksum, e.g. for TCP/UDP fragments
+ */
+
+/*	
+unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
+ */
+		
+.text
+.align 4
+.globl csum_partial
+		
+#ifndef CONFIG_X86_USE_PPRO_CHECKSUM
+
+	  /*		
+	   * Experiments with Ethernet and SLIP connections show that buff
+	   * is aligned on either a 2-byte or 4-byte boundary.  We get at
+	   * least a twofold speedup on 486 and Pentium if it is 4-byte aligned.
+	   * Fortunately, it is easy to convert 2-byte alignment to 4-byte
+	   * alignment for the unrolled loop.
+	   */		
+csum_partial:
+	pushl %esi
+	pushl %ebx
+	movl 20(%esp),%eax	# Function arg: unsigned int sum
+	movl 16(%esp),%ecx	# Function arg: int len
+	movl 12(%esp),%esi	# Function arg: unsigned char *buff
+	testl $2, %esi		# Check alignment.
+	jz 2f			# Jump if alignment is ok.
+	subl $2, %ecx		# Alignment uses up two bytes.
+	jae 1f			# Jump if we had at least two bytes.
+	addl $2, %ecx		# ecx was < 2.  Deal with it.
+	jmp 4f
+1:	movw (%esi), %bx
+	addl $2, %esi
+	addw %bx, %ax
+	adcl $0, %eax
+2:
+	movl %ecx, %edx
+	shrl $5, %ecx
+	jz 2f
+	testl %esi, %esi
+1:	movl (%esi), %ebx
+	adcl %ebx, %eax
+	movl 4(%esi), %ebx
+	adcl %ebx, %eax
+	movl 8(%esi), %ebx
+	adcl %ebx, %eax
+	movl 12(%esi), %ebx
+	adcl %ebx, %eax
+	movl 16(%esi), %ebx
+	adcl %ebx, %eax
+	movl 20(%esi), %ebx
+	adcl %ebx, %eax
+	movl 24(%esi), %ebx
+	adcl %ebx, %eax
+	movl 28(%esi), %ebx
+	adcl %ebx, %eax
+	lea 32(%esi), %esi
+	dec %ecx
+	jne 1b
+	adcl $0, %eax
+2:	movl %edx, %ecx
+	andl $0x1c, %edx
+	je 4f
+	shrl $2, %edx		# This clears CF
+3:	adcl (%esi), %eax
+	lea 4(%esi), %esi
+	dec %edx
+	jne 3b
+	adcl $0, %eax
+4:	andl $3, %ecx
+	jz 7f
+	cmpl $2, %ecx
+	jb 5f
+	movw (%esi),%cx
+	leal 2(%esi),%esi
+	je 6f
+	shll $16,%ecx
+5:	movb (%esi),%cl
+6:	addl %ecx,%eax
+	adcl $0, %eax 
+7:	
+	popl %ebx
+	popl %esi
+	ret
+
+#else
+
+/* Version for PentiumII/PPro */
+
+csum_partial:
+	pushl %esi
+	pushl %ebx
+	movl 20(%esp),%eax	# Function arg: unsigned int sum
+	movl 16(%esp),%ecx	# Function arg: int len
+	movl 12(%esp),%esi	# Function arg:	const unsigned char *buf
+
+	testl $2, %esi         
+	jnz 30f                 
+10:
+	movl %ecx, %edx
+	movl %ecx, %ebx
+	andl $0x7c, %ebx
+	shrl $7, %ecx
+	addl %ebx,%esi
+	shrl $2, %ebx  
+	negl %ebx
+	lea 45f(%ebx,%ebx,2), %ebx
+	testl %esi, %esi
+	jmp *%ebx
+
+	# Handle 2-byte-aligned regions
+20:	addw (%esi), %ax
+	lea 2(%esi), %esi
+	adcl $0, %eax
+	jmp 10b
+
+30:	subl $2, %ecx          
+	ja 20b                 
+	je 32f
+	movzbl (%esi),%ebx	# csumming 1 byte, 2-aligned
+	addl %ebx, %eax
+	adcl $0, %eax
+	jmp 80f
+32:
+	addw (%esi), %ax	# csumming 2 bytes, 2-aligned
+	adcl $0, %eax
+	jmp 80f
+
+40: 
+	addl -128(%esi), %eax
+	adcl -124(%esi), %eax
+	adcl -120(%esi), %eax
+	adcl -116(%esi), %eax   
+	adcl -112(%esi), %eax   
+	adcl -108(%esi), %eax
+	adcl -104(%esi), %eax
+	adcl -100(%esi), %eax
+	adcl -96(%esi), %eax
+	adcl -92(%esi), %eax
+	adcl -88(%esi), %eax
+	adcl -84(%esi), %eax
+	adcl -80(%esi), %eax
+	adcl -76(%esi), %eax
+	adcl -72(%esi), %eax
+	adcl -68(%esi), %eax
+	adcl -64(%esi), %eax     
+	adcl -60(%esi), %eax     
+	adcl -56(%esi), %eax     
+	adcl -52(%esi), %eax   
+	adcl -48(%esi), %eax   
+	adcl -44(%esi), %eax
+	adcl -40(%esi), %eax
+	adcl -36(%esi), %eax
+	adcl -32(%esi), %eax
+	adcl -28(%esi), %eax
+	adcl -24(%esi), %eax
+	adcl -20(%esi), %eax
+	adcl -16(%esi), %eax
+	adcl -12(%esi), %eax
+	adcl -8(%esi), %eax
+	adcl -4(%esi), %eax
+45:
+	lea 128(%esi), %esi
+	adcl $0, %eax
+	dec %ecx
+	jge 40b
+	movl %edx, %ecx
+50:	andl $3, %ecx
+	jz 80f
+
+	# Handle the last 1-3 bytes without jumping
+	notl %ecx		# 1->2, 2->1, 3->0, higher bits are masked
+	movl $0xffffff,%ebx	# by the shll and shrl instructions
+	shll $3,%ecx
+	shrl %cl,%ebx
+	andl -128(%esi),%ebx	# esi is 4-aligned so should be ok
+	addl %ebx,%eax
+	adcl $0,%eax
+80: 
+	popl %ebx
+	popl %esi
+	ret
+				
+#endif
+
+/*
+unsigned int csum_partial_copy_generic (const char *src, char *dst,
+				  int len, int sum, int *src_err_ptr, int *dst_err_ptr)
+ */ 
+
+/*
+ * Copy from ds while checksumming, otherwise like csum_partial
+ *
+ * The macros SRC and DST specify the type of access for the instruction.
+ * thus we can call a custom exception handler for all access types.
+ *
+ * FIXME: could someone double-check whether I haven't mixed up some SRC and
+ *	  DST definitions? It's damn hard to trigger all cases.  I hope I got
+ *	  them all but there's no guarantee.
+ */
+
+#define SRC(y...)			\
+	9999: y;			\
+	.section __ex_table, "a";	\
+	.long 9999b, 6001f	;	\
+	.previous
+
+#define DST(y...)			\
+	9999: y;			\
+	.section __ex_table, "a";	\
+	.long 9999b, 6002f	;	\
+	.previous
+
+.align 4
+
+#ifndef CONFIG_X86_USE_PPRO_CHECKSUM
+
+#define ARGBASE 16		
+#define FP		12
+
+csum_partial_copy_generic_i386:
+	subl  $4,%esp	
+	pushl %edi
+	pushl %esi
+	pushl %ebx
+	movl ARGBASE+16(%esp),%eax	# sum
+	movl ARGBASE+12(%esp),%ecx	# len
+	movl ARGBASE+4(%esp),%esi	# src
+	movl ARGBASE+8(%esp),%edi	# dst
+
+	testl $2, %edi			# Check alignment. 
+	jz 2f				# Jump if alignment is ok.
+	subl $2, %ecx			# Alignment uses up two bytes.
+	jae 1f				# Jump if we had at least two bytes.
+	addl $2, %ecx			# ecx was < 2.  Deal with it.
+	jmp 4f
+SRC(1:	movw (%esi), %bx	)
+	addl $2, %esi
+DST(	movw %bx, (%edi)	)
+	addl $2, %edi
+	addw %bx, %ax	
+	adcl $0, %eax
+2:
+	movl %ecx, FP(%esp)
+	shrl $5, %ecx
+	jz 2f
+	testl %esi, %esi
+SRC(1:	movl (%esi), %ebx	)
+SRC(	movl 4(%esi), %edx	)
+	adcl %ebx, %eax
+DST(	movl %ebx, (%edi)	)
+	adcl %edx, %eax
+DST(	movl %edx, 4(%edi)	)
+
+SRC(	movl 8(%esi), %ebx	)
+SRC(	movl 12(%esi), %edx	)
+	adcl %ebx, %eax
+DST(	movl %ebx, 8(%edi)	)
+	adcl %edx, %eax
+DST(	movl %edx, 12(%edi)	)
+
+SRC(	movl 16(%esi), %ebx 	)
+SRC(	movl 20(%esi), %edx	)
+	adcl %ebx, %eax
+DST(	movl %ebx, 16(%edi)	)
+	adcl %edx, %eax
+DST(	movl %edx, 20(%edi)	)
+
+SRC(	movl 24(%esi), %ebx	)
+SRC(	movl 28(%esi), %edx	)
+	adcl %ebx, %eax
+DST(	movl %ebx, 24(%edi)	)
+	adcl %edx, %eax
+DST(	movl %edx, 28(%edi)	)
+
+	lea 32(%esi), %esi
+	lea 32(%edi), %edi
+	dec %ecx
+	jne 1b
+	adcl $0, %eax
+2:	movl FP(%esp), %edx
+	movl %edx, %ecx
+	andl $0x1c, %edx
+	je 4f
+	shrl $2, %edx			# This clears CF
+SRC(3:	movl (%esi), %ebx	)
+	adcl %ebx, %eax
+DST(	movl %ebx, (%edi)	)
+	lea 4(%esi), %esi
+	lea 4(%edi), %edi
+	dec %edx
+	jne 3b
+	adcl $0, %eax
+4:	andl $3, %ecx
+	jz 7f
+	cmpl $2, %ecx
+	jb 5f
+SRC(	movw (%esi), %cx	)
+	leal 2(%esi), %esi
+DST(	movw %cx, (%edi)	)
+	leal 2(%edi), %edi
+	je 6f
+	shll $16,%ecx
+SRC(5:	movb (%esi), %cl	)
+DST(	movb %cl, (%edi)	)
+6:	addl %ecx, %eax
+	adcl $0, %eax
+7:
+5000:
+
+# Exception handler:
+.section .fixup, "ax"							
+
+6001:
+	movl ARGBASE+20(%esp), %ebx	# src_err_ptr
+	movl $-EFAULT, (%ebx)
+
+	# zero the complete destination - computing the rest
+	# is too much work 
+	movl ARGBASE+8(%esp), %edi	# dst
+	movl ARGBASE+12(%esp), %ecx	# len
+	xorl %eax,%eax
+	rep ; stosb
+
+	jmp 5000b
+
+6002:
+	movl ARGBASE+24(%esp), %ebx	# dst_err_ptr
+	movl $-EFAULT,(%ebx)
+	jmp 5000b
+
+.previous
+
+	popl %ebx
+	popl %esi
+	popl %edi
+	popl %ecx			# equivalent to addl $4,%esp
+	ret	
+
+#else
+
+/* Version for PentiumII/PPro */
+
+#define ROUND1(x) \
+	SRC(movl x(%esi), %ebx	)	;	\
+	addl %ebx, %eax			;	\
+	DST(movl %ebx, x(%edi)	)	; 
+
+#define ROUND(x) \
+	SRC(movl x(%esi), %ebx	)	;	\
+	adcl %ebx, %eax			;	\
+	DST(movl %ebx, x(%edi)	)	;
+
+#define ARGBASE 12
+		
+csum_partial_copy_generic_i386:
+	pushl %ebx
+	pushl %edi
+	pushl %esi
+	movl ARGBASE+4(%esp),%esi	#src
+	movl ARGBASE+8(%esp),%edi	#dst	
+	movl ARGBASE+12(%esp),%ecx	#len
+	movl ARGBASE+16(%esp),%eax	#sum
+#	movl %ecx, %edx  
+	movl %ecx, %ebx  
+	movl %esi, %edx
+	shrl $6, %ecx     
+	andl $0x3c, %ebx  
+	negl %ebx
+	subl %ebx, %esi  
+	subl %ebx, %edi  
+	lea  -1(%esi),%edx
+	andl $-32,%edx
+	lea 3f(%ebx,%ebx), %ebx
+	testl %esi, %esi 
+	jmp *%ebx
+1:	addl $64,%esi
+	addl $64,%edi 
+	SRC(movb -32(%edx),%bl)	; SRC(movb (%edx),%bl)
+	ROUND1(-64) ROUND(-60) ROUND(-56) ROUND(-52)	
+	ROUND (-48) ROUND(-44) ROUND(-40) ROUND(-36)	
+	ROUND (-32) ROUND(-28) ROUND(-24) ROUND(-20)	
+	ROUND (-16) ROUND(-12) ROUND(-8)  ROUND(-4)	
+3:	adcl $0,%eax
+	addl $64, %edx
+	dec %ecx
+	jge 1b
+4:	movl ARGBASE+12(%esp),%edx	#len
+	andl $3, %edx
+	jz 7f
+	cmpl $2, %edx
+	jb 5f
+SRC(	movw (%esi), %dx         )
+	leal 2(%esi), %esi
+DST(	movw %dx, (%edi)         )
+	leal 2(%edi), %edi
+	je 6f
+	shll $16,%edx
+5:
+SRC(	movb (%esi), %dl         )
+DST(	movb %dl, (%edi)         )
+6:	addl %edx, %eax
+	adcl $0, %eax
+7:
+.section .fixup, "ax"
+6001:	movl	ARGBASE+20(%esp), %ebx	# src_err_ptr	
+	movl $-EFAULT, (%ebx)
+	# zero the complete destination (computing the rest is too much work)
+	movl ARGBASE+8(%esp),%edi	# dst
+	movl ARGBASE+12(%esp),%ecx	# len
+	xorl %eax,%eax
+	rep; stosb
+	jmp 7b
+6002:	movl ARGBASE+24(%esp), %ebx	# dst_err_ptr
+	movl $-EFAULT, (%ebx)
+	jmp  7b			
+.previous				
+
+	popl %esi
+	popl %edi
+	popl %ebx
+	ret
+				
+#undef ROUND
+#undef ROUND1		
+		
+#endif
diff --git a/arch/x86/um/delay.c b/arch/x86/um/delay.c
new file mode 100644
index 0000000..f3fe1a6
--- /dev/null
+++ b/arch/x86/um/delay.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
+ * Mostly copied from arch/x86/lib/delay.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <asm/param.h>
+
+void __delay(unsigned long loops)
+{
+	asm volatile(
+		"test %0,%0\n"
+		"jz 3f\n"
+		"jmp 1f\n"
+
+		".align 16\n"
+		"1: jmp 2f\n"
+
+		".align 16\n"
+		"2: dec %0\n"
+		" jnz 2b\n"
+		"3: dec %0\n"
+
+		: /* we don't need output */
+		: "a" (loops)
+	);
+}
+EXPORT_SYMBOL(__delay);
+
+inline void __const_udelay(unsigned long xloops)
+{
+	int d0;
+
+	xloops *= 4;
+	asm("mull %%edx"
+		: "=d" (xloops), "=&a" (d0)
+		: "1" (xloops), "0"
+		(loops_per_jiffy * (HZ/4)));
+
+	__delay(++xloops);
+}
+EXPORT_SYMBOL(__const_udelay);
+
+void __udelay(unsigned long usecs)
+{
+	__const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */
+}
+EXPORT_SYMBOL(__udelay);
+
+void __ndelay(unsigned long nsecs)
+{
+	__const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */
+}
+EXPORT_SYMBOL(__ndelay);
diff --git a/arch/x86/um/elfcore.c b/arch/x86/um/elfcore.c
new file mode 100644
index 0000000..6bb49b6
--- /dev/null
+++ b/arch/x86/um/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/x86/um/fault.c b/arch/x86/um/fault.c
new file mode 100644
index 0000000..d670f68
--- /dev/null
+++ b/arch/x86/um/fault.c
@@ -0,0 +1,28 @@
+/* 
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#include "sysdep/ptrace.h"
+
+/* These two are from asm-um/uaccess.h and linux/module.h, check them. */
+struct exception_table_entry
+{
+	unsigned long insn;
+	unsigned long fixup;
+};
+
+const struct exception_table_entry *search_exception_tables(unsigned long add);
+
+/* Compare this to arch/i386/mm/extable.c:fixup_exception() */
+int arch_fixup(unsigned long address, struct uml_pt_regs *regs)
+{
+	const struct exception_table_entry *fixup;
+
+	fixup = search_exception_tables(address);
+	if (fixup != 0) {
+		UPT_IP(regs) = fixup->fixup;
+		return 1;
+	}
+	return 0;
+}
diff --git a/arch/x86/um/ksyms.c b/arch/x86/um/ksyms.c
new file mode 100644
index 0000000..2e8f43e
--- /dev/null
+++ b/arch/x86/um/ksyms.c
@@ -0,0 +1,13 @@
+#include <linux/module.h>
+#include <asm/string.h>
+#include <asm/checksum.h>
+
+#ifndef CONFIG_X86_32
+/*XXX: we need them because they would be exported by x86_64 */
+#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4
+EXPORT_SYMBOL(memcpy);
+#else
+EXPORT_SYMBOL(__memcpy);
+#endif
+#endif
+EXPORT_SYMBOL(csum_partial);
diff --git a/arch/x86/um/ldt.c b/arch/x86/um/ldt.c
new file mode 100644
index 0000000..26b0e39
--- /dev/null
+++ b/arch/x86/um/ldt.c
@@ -0,0 +1,502 @@
+/*
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <asm/unistd.h>
+#include "os.h"
+#include "proc_mm.h"
+#include "skas.h"
+#include "skas_ptrace.h"
+#include "sysdep/tls.h"
+
+extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
+
+static long write_ldt_entry(struct mm_id *mm_idp, int func,
+		     struct user_desc *desc, void **addr, int done)
+{
+	long res;
+
+	if (proc_mm) {
+		/*
+		 * This is a special handling for the case, that the mm to
+		 * modify isn't current->active_mm.
+		 * If this is called directly by modify_ldt,
+		 *     (current->active_mm->context.skas.u == mm_idp)
+		 * will be true. So no call to __switch_mm(mm_idp) is done.
+		 * If this is called in case of init_new_ldt or PTRACE_LDT,
+		 * mm_idp won't belong to current->active_mm, but child->mm.
+		 * So we need to switch child's mm into our userspace, then
+		 * later switch back.
+		 *
+		 * Note: I'm unsure: should interrupts be disabled here?
+		 */
+		if (!current->active_mm || current->active_mm == &init_mm ||
+		    mm_idp != &current->active_mm->context.id)
+			__switch_mm(mm_idp);
+	}
+
+	if (ptrace_ldt) {
+		struct ptrace_ldt ldt_op = (struct ptrace_ldt) {
+			.func = func,
+			.ptr = desc,
+			.bytecount = sizeof(*desc)};
+		u32 cpu;
+		int pid;
+
+		if (!proc_mm)
+			pid = mm_idp->u.pid;
+		else {
+			cpu = get_cpu();
+			pid = userspace_pid[cpu];
+		}
+
+		res = os_ptrace_ldt(pid, 0, (unsigned long) &ldt_op);
+
+		if (proc_mm)
+			put_cpu();
+	}
+	else {
+		void *stub_addr;
+		res = syscall_stub_data(mm_idp, (unsigned long *)desc,
+					(sizeof(*desc) + sizeof(long) - 1) &
+					    ~(sizeof(long) - 1),
+					addr, &stub_addr);
+		if (!res) {
+			unsigned long args[] = { func,
+						 (unsigned long)stub_addr,
+						 sizeof(*desc),
+						 0, 0, 0 };
+			res = run_syscall_stub(mm_idp, __NR_modify_ldt, args,
+					       0, addr, done);
+		}
+	}
+
+	if (proc_mm) {
+		/*
+		 * This is the second part of special handling, that makes
+		 * PTRACE_LDT possible to implement.
+		 */
+		if (current->active_mm && current->active_mm != &init_mm &&
+		    mm_idp != &current->active_mm->context.id)
+			__switch_mm(&current->active_mm->context.id);
+	}
+
+	return res;
+}
+
+static long read_ldt_from_host(void __user * ptr, unsigned long bytecount)
+{
+	int res, n;
+	struct ptrace_ldt ptrace_ldt = (struct ptrace_ldt) {
+			.func = 0,
+			.bytecount = bytecount,
+			.ptr = kmalloc(bytecount, GFP_KERNEL)};
+	u32 cpu;
+
+	if (ptrace_ldt.ptr == NULL)
+		return -ENOMEM;
+
+	/*
+	 * This is called from sys_modify_ldt only, so userspace_pid gives
+	 * us the right number
+	 */
+
+	cpu = get_cpu();
+	res = os_ptrace_ldt(userspace_pid[cpu], 0, (unsigned long) &ptrace_ldt);
+	put_cpu();
+	if (res < 0)
+		goto out;
+
+	n = copy_to_user(ptr, ptrace_ldt.ptr, res);
+	if (n != 0)
+		res = -EFAULT;
+
+  out:
+	kfree(ptrace_ldt.ptr);
+
+	return res;
+}
+
+/*
+ * In skas mode, we hold our own ldt data in UML.
+ * Thus, the code implementing sys_modify_ldt_skas
+ * is very similar to (and mostly stolen from) sys_modify_ldt
+ * for arch/i386/kernel/ldt.c
+ * The routines copied and modified in part are:
+ * - read_ldt
+ * - read_default_ldt
+ * - write_ldt
+ * - sys_modify_ldt_skas
+ */
+
+static int read_ldt(void __user * ptr, unsigned long bytecount)
+{
+	int i, err = 0;
+	unsigned long size;
+	uml_ldt_t *ldt = &current->mm->context.arch.ldt;
+
+	if (!ldt->entry_count)
+		goto out;
+	if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES)
+		bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES;
+	err = bytecount;
+
+	if (ptrace_ldt)
+		return read_ldt_from_host(ptr, bytecount);
+
+	mutex_lock(&ldt->lock);
+	if (ldt->entry_count <= LDT_DIRECT_ENTRIES) {
+		size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES;
+		if (size > bytecount)
+			size = bytecount;
+		if (copy_to_user(ptr, ldt->u.entries, size))
+			err = -EFAULT;
+		bytecount -= size;
+		ptr += size;
+	}
+	else {
+		for (i=0; i<ldt->entry_count/LDT_ENTRIES_PER_PAGE && bytecount;
+		     i++) {
+			size = PAGE_SIZE;
+			if (size > bytecount)
+				size = bytecount;
+			if (copy_to_user(ptr, ldt->u.pages[i], size)) {
+				err = -EFAULT;
+				break;
+			}
+			bytecount -= size;
+			ptr += size;
+		}
+	}
+	mutex_unlock(&ldt->lock);
+
+	if (bytecount == 0 || err == -EFAULT)
+		goto out;
+
+	if (clear_user(ptr, bytecount))
+		err = -EFAULT;
+
+out:
+	return err;
+}
+
+static int read_default_ldt(void __user * ptr, unsigned long bytecount)
+{
+	int err;
+
+	if (bytecount > 5*LDT_ENTRY_SIZE)
+		bytecount = 5*LDT_ENTRY_SIZE;
+
+	err = bytecount;
+	/*
+	 * UML doesn't support lcall7 and lcall27.
+	 * So, we don't really have a default ldt, but emulate
+	 * an empty ldt of common host default ldt size.
+	 */
+	if (clear_user(ptr, bytecount))
+		err = -EFAULT;
+
+	return err;
+}
+
+static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
+{
+	uml_ldt_t *ldt = &current->mm->context.arch.ldt;
+	struct mm_id * mm_idp = &current->mm->context.id;
+	int i, err;
+	struct user_desc ldt_info;
+	struct ldt_entry entry0, *ldt_p;
+	void *addr = NULL;
+
+	err = -EINVAL;
+	if (bytecount != sizeof(ldt_info))
+		goto out;
+	err = -EFAULT;
+	if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info)))
+		goto out;
+
+	err = -EINVAL;
+	if (ldt_info.entry_number >= LDT_ENTRIES)
+		goto out;
+	if (ldt_info.contents == 3) {
+		if (func == 1)
+			goto out;
+		if (ldt_info.seg_not_present == 0)
+			goto out;
+	}
+
+	if (!ptrace_ldt)
+		mutex_lock(&ldt->lock);
+
+	err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1);
+	if (err)
+		goto out_unlock;
+	else if (ptrace_ldt) {
+		/* With PTRACE_LDT available, this is used as a flag only */
+		ldt->entry_count = 1;
+		goto out;
+	}
+
+	if (ldt_info.entry_number >= ldt->entry_count &&
+	    ldt_info.entry_number >= LDT_DIRECT_ENTRIES) {
+		for (i=ldt->entry_count/LDT_ENTRIES_PER_PAGE;
+		     i*LDT_ENTRIES_PER_PAGE <= ldt_info.entry_number;
+		     i++) {
+			if (i == 0)
+				memcpy(&entry0, ldt->u.entries,
+				       sizeof(entry0));
+			ldt->u.pages[i] = (struct ldt_entry *)
+				__get_free_page(GFP_KERNEL|__GFP_ZERO);
+			if (!ldt->u.pages[i]) {
+				err = -ENOMEM;
+				/* Undo the change in host */
+				memset(&ldt_info, 0, sizeof(ldt_info));
+				write_ldt_entry(mm_idp, 1, &ldt_info, &addr, 1);
+				goto out_unlock;
+			}
+			if (i == 0) {
+				memcpy(ldt->u.pages[0], &entry0,
+				       sizeof(entry0));
+				memcpy(ldt->u.pages[0]+1, ldt->u.entries+1,
+				       sizeof(entry0)*(LDT_DIRECT_ENTRIES-1));
+			}
+			ldt->entry_count = (i + 1) * LDT_ENTRIES_PER_PAGE;
+		}
+	}
+	if (ldt->entry_count <= ldt_info.entry_number)
+		ldt->entry_count = ldt_info.entry_number + 1;
+
+	if (ldt->entry_count <= LDT_DIRECT_ENTRIES)
+		ldt_p = ldt->u.entries + ldt_info.entry_number;
+	else
+		ldt_p = ldt->u.pages[ldt_info.entry_number/LDT_ENTRIES_PER_PAGE] +
+			ldt_info.entry_number%LDT_ENTRIES_PER_PAGE;
+
+	if (ldt_info.base_addr == 0 && ldt_info.limit == 0 &&
+	   (func == 1 || LDT_empty(&ldt_info))) {
+		ldt_p->a = 0;
+		ldt_p->b = 0;
+	}
+	else{
+		if (func == 1)
+			ldt_info.useable = 0;
+		ldt_p->a = LDT_entry_a(&ldt_info);
+		ldt_p->b = LDT_entry_b(&ldt_info);
+	}
+	err = 0;
+
+out_unlock:
+	mutex_unlock(&ldt->lock);
+out:
+	return err;
+}
+
+static long do_modify_ldt_skas(int func, void __user *ptr,
+			       unsigned long bytecount)
+{
+	int ret = -ENOSYS;
+
+	switch (func) {
+		case 0:
+			ret = read_ldt(ptr, bytecount);
+			break;
+		case 1:
+		case 0x11:
+			ret = write_ldt(ptr, bytecount, func);
+			break;
+		case 2:
+			ret = read_default_ldt(ptr, bytecount);
+			break;
+	}
+	return ret;
+}
+
+static DEFINE_SPINLOCK(host_ldt_lock);
+static short dummy_list[9] = {0, -1};
+static short * host_ldt_entries = NULL;
+
+static void ldt_get_host_info(void)
+{
+	long ret;
+	struct ldt_entry * ldt;
+	short *tmp;
+	int i, size, k, order;
+
+	spin_lock(&host_ldt_lock);
+
+	if (host_ldt_entries != NULL) {
+		spin_unlock(&host_ldt_lock);
+		return;
+	}
+	host_ldt_entries = dummy_list+1;
+
+	spin_unlock(&host_ldt_lock);
+
+	for (i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++)
+		;
+
+	ldt = (struct ldt_entry *)
+	      __get_free_pages(GFP_KERNEL|__GFP_ZERO, order);
+	if (ldt == NULL) {
+		printk(KERN_ERR "ldt_get_host_info: couldn't allocate buffer "
+		       "for host ldt\n");
+		return;
+	}
+
+	ret = modify_ldt(0, ldt, (1<<order)*PAGE_SIZE);
+	if (ret < 0) {
+		printk(KERN_ERR "ldt_get_host_info: couldn't read host ldt\n");
+		goto out_free;
+	}
+	if (ret == 0) {
+		/* default_ldt is active, simply write an empty entry 0 */
+		host_ldt_entries = dummy_list;
+		goto out_free;
+	}
+
+	for (i=0, size=0; i<ret/LDT_ENTRY_SIZE; i++) {
+		if (ldt[i].a != 0 || ldt[i].b != 0)
+			size++;
+	}
+
+	if (size < ARRAY_SIZE(dummy_list))
+		host_ldt_entries = dummy_list;
+	else {
+		size = (size + 1) * sizeof(dummy_list[0]);
+		tmp = kmalloc(size, GFP_KERNEL);
+		if (tmp == NULL) {
+			printk(KERN_ERR "ldt_get_host_info: couldn't allocate "
+			       "host ldt list\n");
+			goto out_free;
+		}
+		host_ldt_entries = tmp;
+	}
+
+	for (i=0, k=0; i<ret/LDT_ENTRY_SIZE; i++) {
+		if (ldt[i].a != 0 || ldt[i].b != 0)
+			host_ldt_entries[k++] = i;
+	}
+	host_ldt_entries[k] = -1;
+
+out_free:
+	free_pages((unsigned long)ldt, order);
+}
+
+long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
+{
+	struct user_desc desc;
+	short * num_p;
+	int i;
+	long page, err=0;
+	void *addr = NULL;
+	struct proc_mm_op copy;
+
+
+	if (!ptrace_ldt)
+		mutex_init(&new_mm->arch.ldt.lock);
+
+	if (!from_mm) {
+		memset(&desc, 0, sizeof(desc));
+		/*
+		 * We have to initialize a clean ldt.
+		 */
+		if (proc_mm) {
+			/*
+			 * If the new mm was created using proc_mm, host's
+			 * default-ldt currently is assigned, which normally
+			 * contains the call-gates for lcall7 and lcall27.
+			 * To remove these gates, we simply write an empty
+			 * entry as number 0 to the host.
+			 */
+			err = write_ldt_entry(&new_mm->id, 1, &desc, &addr, 1);
+		}
+		else{
+			/*
+			 * Now we try to retrieve info about the ldt, we
+			 * inherited from the host. All ldt-entries found
+			 * will be reset in the following loop
+			 */
+			ldt_get_host_info();
+			for (num_p=host_ldt_entries; *num_p != -1; num_p++) {
+				desc.entry_number = *num_p;
+				err = write_ldt_entry(&new_mm->id, 1, &desc,
+						      &addr, *(num_p + 1) == -1);
+				if (err)
+					break;
+			}
+		}
+		new_mm->arch.ldt.entry_count = 0;
+
+		goto out;
+	}
+
+	if (proc_mm) {
+		/*
+		 * We have a valid from_mm, so we now have to copy the LDT of
+		 * from_mm to new_mm, because using proc_mm an new mm with
+		 * an empty/default LDT was created in new_mm()
+		 */
+		copy = ((struct proc_mm_op) { .op 	= MM_COPY_SEGMENTS,
+					      .u 	=
+					      { .copy_segments =
+							from_mm->id.u.mm_fd } } );
+		i = os_write_file(new_mm->id.u.mm_fd, &copy, sizeof(copy));
+		if (i != sizeof(copy))
+			printk(KERN_ERR "new_mm : /proc/mm copy_segments "
+			       "failed, err = %d\n", -i);
+	}
+
+	if (!ptrace_ldt) {
+		/*
+		 * Our local LDT is used to supply the data for
+		 * modify_ldt(READLDT), if PTRACE_LDT isn't available,
+		 * i.e., we have to use the stub for modify_ldt, which
+		 * can't handle the big read buffer of up to 64kB.
+		 */
+		mutex_lock(&from_mm->arch.ldt.lock);
+		if (from_mm->arch.ldt.entry_count <= LDT_DIRECT_ENTRIES)
+			memcpy(new_mm->arch.ldt.u.entries, from_mm->arch.ldt.u.entries,
+			       sizeof(new_mm->arch.ldt.u.entries));
+		else {
+			i = from_mm->arch.ldt.entry_count / LDT_ENTRIES_PER_PAGE;
+			while (i-->0) {
+				page = __get_free_page(GFP_KERNEL|__GFP_ZERO);
+				if (!page) {
+					err = -ENOMEM;
+					break;
+				}
+				new_mm->arch.ldt.u.pages[i] =
+					(struct ldt_entry *) page;
+				memcpy(new_mm->arch.ldt.u.pages[i],
+				       from_mm->arch.ldt.u.pages[i], PAGE_SIZE);
+			}
+		}
+		new_mm->arch.ldt.entry_count = from_mm->arch.ldt.entry_count;
+		mutex_unlock(&from_mm->arch.ldt.lock);
+	}
+
+    out:
+	return err;
+}
+
+
+void free_ldt(struct mm_context *mm)
+{
+	int i;
+
+	if (!ptrace_ldt && mm->arch.ldt.entry_count > LDT_DIRECT_ENTRIES) {
+		i = mm->arch.ldt.entry_count / LDT_ENTRIES_PER_PAGE;
+		while (i-- > 0)
+			free_page((long) mm->arch.ldt.u.pages[i]);
+	}
+	mm->arch.ldt.entry_count = 0;
+}
+
+int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
+{
+	return do_modify_ldt_skas(func, ptr, bytecount);
+}
diff --git a/arch/x86/um/mem_32.c b/arch/x86/um/mem_32.c
new file mode 100644
index 0000000..639900a
--- /dev/null
+++ b/arch/x86/um/mem_32.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <asm/mman.h>
+
+static struct vm_area_struct gate_vma;
+
+static int __init gate_vma_init(void)
+{
+	if (!FIXADDR_USER_START)
+		return 0;
+
+	gate_vma.vm_mm = NULL;
+	gate_vma.vm_start = FIXADDR_USER_START;
+	gate_vma.vm_end = FIXADDR_USER_END;
+	gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC;
+	gate_vma.vm_page_prot = __P101;
+
+	/*
+	 * Make sure the vDSO gets into every core dump.
+	 * Dumping its contents makes post-mortem fully interpretable later
+	 * without matching up the same kernel and hardware config to see
+	 * what PC values meant.
+	 */
+	gate_vma.vm_flags |= VM_ALWAYSDUMP;
+
+	return 0;
+}
+__initcall(gate_vma_init);
+
+struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
+{
+	return FIXADDR_USER_START ? &gate_vma : NULL;
+}
+
+int in_gate_area_no_mm(unsigned long addr)
+{
+	if (!FIXADDR_USER_START)
+		return 0;
+
+	if ((addr >= FIXADDR_USER_START) && (addr < FIXADDR_USER_END))
+		return 1;
+
+	return 0;
+}
+
+int in_gate_area(struct mm_struct *mm, unsigned long addr)
+{
+	struct vm_area_struct *vma = get_gate_vma(mm);
+
+	if (!vma)
+		return 0;
+
+	return (addr >= vma->vm_start) && (addr < vma->vm_end);
+}
diff --git a/arch/x86/um/mem_64.c b/arch/x86/um/mem_64.c
new file mode 100644
index 0000000..5465187
--- /dev/null
+++ b/arch/x86/um/mem_64.c
@@ -0,0 +1,26 @@
+#include "linux/mm.h"
+#include "asm/page.h"
+#include "asm/mman.h"
+
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+	if (vma->vm_mm && vma->vm_start == um_vdso_addr)
+		return "[vdso]";
+
+	return NULL;
+}
+
+struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
+{
+	return NULL;
+}
+
+int in_gate_area(struct mm_struct *mm, unsigned long addr)
+{
+	return 0;
+}
+
+int in_gate_area_no_mm(unsigned long addr)
+{
+	return 0;
+}
diff --git a/arch/x86/um/os-Linux/Makefile b/arch/x86/um/os-Linux/Makefile
new file mode 100644
index 0000000..253bfb8
--- /dev/null
+++ b/arch/x86/um/os-Linux/Makefile
@@ -0,0 +1,13 @@
+#
+# Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+# Licensed under the GPL
+#
+
+obj-y = registers.o task_size.o mcontext.o
+
+obj-$(CONFIG_X86_32) += tls.o
+obj-$(CONFIG_64BIT) += prctl.o
+
+USER_OBJS := $(obj-y)
+
+include arch/um/scripts/Makefile.rules
diff --git a/arch/x86/um/os-Linux/mcontext.c b/arch/x86/um/os-Linux/mcontext.c
new file mode 100644
index 0000000..1d33d72
--- /dev/null
+++ b/arch/x86/um/os-Linux/mcontext.c
@@ -0,0 +1,31 @@
+#include <sys/ucontext.h>
+#define __FRAME_OFFSETS
+#include <asm/ptrace.h>
+#include <sysdep/ptrace.h>
+
+void get_regs_from_mc(struct uml_pt_regs *regs, mcontext_t *mc)
+{
+#ifdef __i386__
+#define COPY2(X,Y) regs->gp[X] = mc->gregs[REG_##Y]
+#define COPY(X) regs->gp[X] = mc->gregs[REG_##X]
+#define COPY_SEG(X) regs->gp[X] = mc->gregs[REG_##X] & 0xffff;
+#define COPY_SEG_CPL3(X) regs->gp[X] = (mc->gregs[REG_##X] & 0xffff) | 3;
+	COPY_SEG(GS); COPY_SEG(FS); COPY_SEG(ES); COPY_SEG(DS);
+	COPY(EDI); COPY(ESI); COPY(EBP);
+	COPY2(UESP, ESP); /* sic */
+	COPY(EBX); COPY(EDX); COPY(ECX); COPY(EAX);
+	COPY(EIP); COPY_SEG_CPL3(CS); COPY(EFL); COPY_SEG_CPL3(SS);
+#else
+#define COPY2(X,Y) regs->gp[X/sizeof(unsigned long)] = mc->gregs[REG_##Y]
+#define COPY(X) regs->gp[X/sizeof(unsigned long)] = mc->gregs[REG_##X]
+	COPY(R8); COPY(R9); COPY(R10); COPY(R11);
+	COPY(R12); COPY(R13); COPY(R14); COPY(R15);
+	COPY(RDI); COPY(RSI); COPY(RBP); COPY(RBX);
+	COPY(RDX); COPY(RAX); COPY(RCX); COPY(RSP);
+	COPY(RIP);
+	COPY2(EFLAGS, EFL);
+	COPY2(CS, CSGSFS);
+	regs->gp[CS / sizeof(unsigned long)] &= 0xffff;
+	regs->gp[CS / sizeof(unsigned long)] |= 3;
+#endif
+}
diff --git a/arch/x86/um/os-Linux/prctl.c b/arch/x86/um/os-Linux/prctl.c
new file mode 100644
index 0000000..9d34edd
--- /dev/null
+++ b/arch/x86/um/os-Linux/prctl.c
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) 2007 Jeff Dike (jdike@{addtoit.com,linux.intel.com})
+ * Licensed under the GPL
+ */
+
+#include <sys/ptrace.h>
+#include <linux/ptrace.h>
+
+int os_arch_prctl(int pid, int code, unsigned long *addr)
+{
+        return ptrace(PTRACE_ARCH_PRCTL, pid, (unsigned long) addr, code);
+}
diff --git a/arch/x86/um/os-Linux/registers.c b/arch/x86/um/os-Linux/registers.c
new file mode 100644
index 0000000..0cdbb86
--- /dev/null
+++ b/arch/x86/um/os-Linux/registers.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2004 PathScale, Inc
+ * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#include <errno.h>
+#include <sys/ptrace.h>
+#ifdef __i386__
+#include <sys/user.h>
+#endif
+#include "longjmp.h"
+#include "sysdep/ptrace_user.h"
+
+int save_fp_registers(int pid, unsigned long *fp_regs)
+{
+	if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
+		return -errno;
+	return 0;
+}
+
+int restore_fp_registers(int pid, unsigned long *fp_regs)
+{
+	if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
+		return -errno;
+	return 0;
+}
+
+#ifdef __i386__
+int have_fpx_regs = 1;
+int save_fpx_registers(int pid, unsigned long *fp_regs)
+{
+	if (ptrace(PTRACE_GETFPXREGS, pid, 0, fp_regs) < 0)
+		return -errno;
+	return 0;
+}
+
+int restore_fpx_registers(int pid, unsigned long *fp_regs)
+{
+	if (ptrace(PTRACE_SETFPXREGS, pid, 0, fp_regs) < 0)
+		return -errno;
+	return 0;
+}
+
+int get_fp_registers(int pid, unsigned long *regs)
+{
+	if (have_fpx_regs)
+		return save_fpx_registers(pid, regs);
+	else
+		return save_fp_registers(pid, regs);
+}
+
+int put_fp_registers(int pid, unsigned long *regs)
+{
+	if (have_fpx_regs)
+		return restore_fpx_registers(pid, regs);
+	else
+		return restore_fp_registers(pid, regs);
+}
+
+void arch_init_registers(int pid)
+{
+	struct user_fpxregs_struct fpx_regs;
+	int err;
+
+	err = ptrace(PTRACE_GETFPXREGS, pid, 0, &fpx_regs);
+	if (!err)
+		return;
+
+	if (errno != EIO)
+		panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d",
+		      errno);
+
+	have_fpx_regs = 0;
+}
+#else
+
+int get_fp_registers(int pid, unsigned long *regs)
+{
+	return save_fp_registers(pid, regs);
+}
+
+int put_fp_registers(int pid, unsigned long *regs)
+{
+	return restore_fp_registers(pid, regs);
+}
+
+#endif
+
+unsigned long get_thread_reg(int reg, jmp_buf *buf)
+{
+	switch (reg) {
+#ifdef __i386__
+	case HOST_IP:
+		return buf[0]->__eip;
+	case HOST_SP:
+		return buf[0]->__esp;
+	case HOST_BP:
+		return buf[0]->__ebp;
+#else
+	case HOST_IP:
+		return buf[0]->__rip;
+	case HOST_SP:
+		return buf[0]->__rsp;
+	case HOST_BP:
+		return buf[0]->__rbp;
+#endif
+	default:
+		printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n",
+		       reg);
+		return 0;
+	}
+}
diff --git a/arch/x86/um/os-Linux/task_size.c b/arch/x86/um/os-Linux/task_size.c
new file mode 100644
index 0000000..efb16c5
--- /dev/null
+++ b/arch/x86/um/os-Linux/task_size.c
@@ -0,0 +1,150 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include "longjmp.h"
+
+#ifdef __i386__
+
+static jmp_buf buf;
+
+static void segfault(int sig)
+{
+	longjmp(buf, 1);
+}
+
+static int page_ok(unsigned long page)
+{
+	unsigned long *address = (unsigned long *) (page << UM_KERN_PAGE_SHIFT);
+	unsigned long n = ~0UL;
+	void *mapped = NULL;
+	int ok = 0;
+
+	/*
+	 * First see if the page is readable.  If it is, it may still
+	 * be a VDSO, so we go on to see if it's writable.  If not
+	 * then try mapping memory there.  If that fails, then we're
+	 * still in the kernel area.  As a sanity check, we'll fail if
+	 * the mmap succeeds, but gives us an address different from
+	 * what we wanted.
+	 */
+	if (setjmp(buf) == 0)
+		n = *address;
+	else {
+		mapped = mmap(address, UM_KERN_PAGE_SIZE,
+			      PROT_READ | PROT_WRITE,
+			      MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+		if (mapped == MAP_FAILED)
+			return 0;
+		if (mapped != address)
+			goto out;
+	}
+
+	/*
+	 * Now, is it writeable?  If so, then we're in user address
+	 * space.  If not, then try mprotecting it and try the write
+	 * again.
+	 */
+	if (setjmp(buf) == 0) {
+		*address = n;
+		ok = 1;
+		goto out;
+	} else if (mprotect(address, UM_KERN_PAGE_SIZE,
+			    PROT_READ | PROT_WRITE) != 0)
+		goto out;
+
+	if (setjmp(buf) == 0) {
+		*address = n;
+		ok = 1;
+	}
+
+ out:
+	if (mapped != NULL)
+		munmap(mapped, UM_KERN_PAGE_SIZE);
+	return ok;
+}
+
+unsigned long os_get_top_address(void)
+{
+	struct sigaction sa, old;
+	unsigned long bottom = 0;
+	/*
+	 * A 32-bit UML on a 64-bit host gets confused about the VDSO at
+	 * 0xffffe000.  It is mapped, is readable, can be reprotected writeable
+	 * and written.  However, exec discovers later that it can't be
+	 * unmapped.  So, just set the highest address to be checked to just
+	 * below it.  This might waste some address space on 4G/4G 32-bit
+	 * hosts, but shouldn't hurt otherwise.
+	 */
+	unsigned long top = 0xffffd000 >> UM_KERN_PAGE_SHIFT;
+	unsigned long test, original;
+
+	printf("Locating the bottom of the address space ... ");
+	fflush(stdout);
+
+	/*
+	 * We're going to be longjmping out of the signal handler, so
+	 * SA_DEFER needs to be set.
+	 */
+	sa.sa_handler = segfault;
+	sigemptyset(&sa.sa_mask);
+	sa.sa_flags = SA_NODEFER;
+	if (sigaction(SIGSEGV, &sa, &old)) {
+		perror("os_get_top_address");
+		exit(1);
+	}
+
+	/* Manually scan the address space, bottom-up, until we find
+	 * the first valid page (or run out of them).
+	 */
+	for (bottom = 0; bottom < top; bottom++) {
+		if (page_ok(bottom))
+			break;
+	}
+
+	/* If we've got this far, we ran out of pages. */
+	if (bottom == top) {
+		fprintf(stderr, "Unable to determine bottom of address "
+			"space.\n");
+		exit(1);
+	}
+
+	printf("0x%x\n", bottom << UM_KERN_PAGE_SHIFT);
+	printf("Locating the top of the address space ... ");
+	fflush(stdout);
+
+	original = bottom;
+
+	/* This could happen with a 4G/4G split */
+	if (page_ok(top))
+		goto out;
+
+	do {
+		test = bottom + (top - bottom) / 2;
+		if (page_ok(test))
+			bottom = test;
+		else
+			top = test;
+	} while (top - bottom > 1);
+
+out:
+	/* Restore the old SIGSEGV handling */
+	if (sigaction(SIGSEGV, &old, NULL)) {
+		perror("os_get_top_address");
+		exit(1);
+	}
+	top <<= UM_KERN_PAGE_SHIFT;
+	printf("0x%x\n", top);
+
+	return top;
+}
+
+#else
+
+unsigned long os_get_top_address(void)
+{
+	/* The old value of CONFIG_TOP_ADDR */
+	return 0x7fc0000000;
+}
+
+#endif
diff --git a/arch/x86/um/os-Linux/tls.c b/arch/x86/um/os-Linux/tls.c
new file mode 100644
index 0000000..82276b6
--- /dev/null
+++ b/arch/x86/um/os-Linux/tls.c
@@ -0,0 +1,67 @@
+#include <errno.h>
+#include <linux/unistd.h>
+
+#include <sys/ptrace.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+#include "sysdep/tls.h"
+
+#ifndef PTRACE_GET_THREAD_AREA
+#define PTRACE_GET_THREAD_AREA 25
+#endif
+
+#ifndef PTRACE_SET_THREAD_AREA
+#define PTRACE_SET_THREAD_AREA 26
+#endif
+
+/* Checks whether host supports TLS, and sets *tls_min according to the value
+ * valid on the host.
+ * i386 host have it == 6; x86_64 host have it == 12, for i386 emulation. */
+void check_host_supports_tls(int *supports_tls, int *tls_min)
+{
+	/* Values for x86 and x86_64.*/
+	int val[] = {GDT_ENTRY_TLS_MIN_I386, GDT_ENTRY_TLS_MIN_X86_64};
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(val); i++) {
+		user_desc_t info;
+		info.entry_number = val[i];
+
+		if (syscall(__NR_get_thread_area, &info) == 0) {
+			*tls_min = val[i];
+			*supports_tls = 1;
+			return;
+		} else {
+			if (errno == EINVAL)
+				continue;
+			else if (errno == ENOSYS)
+				*supports_tls = 0;
+				return;
+		}
+	}
+
+	*supports_tls = 0;
+}
+
+int os_set_thread_area(user_desc_t *info, int pid)
+{
+	int ret;
+
+	ret = ptrace(PTRACE_SET_THREAD_AREA, pid, info->entry_number,
+		     (unsigned long) info);
+	if (ret < 0)
+		ret = -errno;
+	return ret;
+}
+
+int os_get_thread_area(user_desc_t *info, int pid)
+{
+	int ret;
+
+	ret = ptrace(PTRACE_GET_THREAD_AREA, pid, info->entry_number,
+		     (unsigned long) info);
+	if (ret < 0)
+		ret = -errno;
+	return ret;
+}
diff --git a/arch/x86/um/ptrace_32.c b/arch/x86/um/ptrace_32.c
new file mode 100644
index 0000000..3b949da
--- /dev/null
+++ b/arch/x86/um/ptrace_32.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/mm.h"
+#include "linux/sched.h"
+#include "asm/uaccess.h"
+#include "skas.h"
+
+extern int arch_switch_tls(struct task_struct *to);
+
+void arch_switch_to(struct task_struct *to)
+{
+	int err = arch_switch_tls(to);
+	if (!err)
+		return;
+
+	if (err != -EINVAL)
+		printk(KERN_WARNING "arch_switch_tls failed, errno %d, "
+		       "not EINVAL\n", -err);
+	else
+		printk(KERN_WARNING "arch_switch_tls failed, errno = EINVAL\n");
+}
+
+int is_syscall(unsigned long addr)
+{
+	unsigned short instr;
+	int n;
+
+	n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
+	if (n) {
+		/* access_process_vm() grants access to vsyscall and stub,
+		 * while copy_from_user doesn't. Maybe access_process_vm is
+		 * slow, but that doesn't matter, since it will be called only
+		 * in case of singlestepping, if copy_from_user failed.
+		 */
+		n = access_process_vm(current, addr, &instr, sizeof(instr), 0);
+		if (n != sizeof(instr)) {
+			printk(KERN_ERR "is_syscall : failed to read "
+			       "instruction from 0x%lx\n", addr);
+			return 1;
+		}
+	}
+	/* int 0x80 or sysenter */
+	return (instr == 0x80cd) || (instr == 0x340f);
+}
+
+/* determines which flags the user has access to. */
+/* 1 = access 0 = no access */
+#define FLAG_MASK 0x00044dd5
+
+static const int reg_offsets[] = {
+	[EBX] = HOST_BX,
+	[ECX] = HOST_CX,
+	[EDX] = HOST_DX,
+	[ESI] = HOST_SI,
+	[EDI] = HOST_DI,
+	[EBP] = HOST_BP,
+	[EAX] = HOST_AX,
+	[DS] = HOST_DS,
+	[ES] = HOST_ES,
+	[FS] = HOST_FS,
+	[GS] = HOST_GS,
+	[EIP] = HOST_IP,
+	[CS] = HOST_CS,
+	[EFL] = HOST_EFLAGS,
+	[UESP] = HOST_SP,
+	[SS] = HOST_SS,
+};
+
+int putreg(struct task_struct *child, int regno, unsigned long value)
+{
+	regno >>= 2;
+	switch (regno) {
+	case EBX:
+	case ECX:
+	case EDX:
+	case ESI:
+	case EDI:
+	case EBP:
+	case EAX:
+	case EIP:
+	case UESP:
+		break;
+	case FS:
+		if (value && (value & 3) != 3)
+			return -EIO;
+		break;
+	case GS:
+		if (value && (value & 3) != 3)
+			return -EIO;
+		break;
+	case DS:
+	case ES:
+		if (value && (value & 3) != 3)
+			return -EIO;
+		value &= 0xffff;
+		break;
+	case SS:
+	case CS:
+		if ((value & 3) != 3)
+			return -EIO;
+		value &= 0xffff;
+		break;
+	case EFL:
+		value &= FLAG_MASK;
+		child->thread.regs.regs.gp[HOST_EFLAGS] |= value;
+		return 0;
+	case ORIG_EAX:
+		child->thread.regs.regs.syscall = value;
+		return 0;
+	default :
+		panic("Bad register in putreg() : %d\n", regno);
+	}
+	child->thread.regs.regs.gp[reg_offsets[regno]] = value;
+	return 0;
+}
+
+int poke_user(struct task_struct *child, long addr, long data)
+{
+	if ((addr & 3) || addr < 0)
+		return -EIO;
+
+	if (addr < MAX_REG_OFFSET)
+		return putreg(child, addr, data);
+	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
+		 (addr <= offsetof(struct user, u_debugreg[7]))) {
+		addr -= offsetof(struct user, u_debugreg[0]);
+		addr = addr >> 2;
+		if ((addr == 4) || (addr == 5))
+			return -EIO;
+		child->thread.arch.debugregs[addr] = data;
+		return 0;
+	}
+	return -EIO;
+}
+
+unsigned long getreg(struct task_struct *child, int regno)
+{
+	unsigned long mask = ~0UL;
+
+	regno >>= 2;
+	switch (regno) {
+	case ORIG_EAX:
+		return child->thread.regs.regs.syscall;
+	case FS:
+	case GS:
+	case DS:
+	case ES:
+	case SS:
+	case CS:
+		mask = 0xffff;
+		break;
+	case EIP:
+	case UESP:
+	case EAX:
+	case EBX:
+	case ECX:
+	case EDX:
+	case ESI:
+	case EDI:
+	case EBP:
+	case EFL:
+		break;
+	default:
+		panic("Bad register in getreg() : %d\n", regno);
+	}
+	return mask & child->thread.regs.regs.gp[reg_offsets[regno]];
+}
+
+/* read the word at location addr in the USER area. */
+int peek_user(struct task_struct *child, long addr, long data)
+{
+	unsigned long tmp;
+
+	if ((addr & 3) || addr < 0)
+		return -EIO;
+
+	tmp = 0;  /* Default return condition */
+	if (addr < MAX_REG_OFFSET) {
+		tmp = getreg(child, addr);
+	}
+	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
+		 (addr <= offsetof(struct user, u_debugreg[7]))) {
+		addr -= offsetof(struct user, u_debugreg[0]);
+		addr = addr >> 2;
+		tmp = child->thread.arch.debugregs[addr];
+	}
+	return put_user(tmp, (unsigned long __user *) data);
+}
+
+static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
+{
+	int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
+	struct user_i387_struct fpregs;
+
+	err = save_fp_registers(userspace_pid[cpu], (unsigned long *) &fpregs);
+	if (err)
+		return err;
+
+	n = copy_to_user(buf, &fpregs, sizeof(fpregs));
+	if(n > 0)
+		return -EFAULT;
+
+	return n;
+}
+
+static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
+{
+	int n, cpu = ((struct thread_info *) child->stack)->cpu;
+	struct user_i387_struct fpregs;
+
+	n = copy_from_user(&fpregs, buf, sizeof(fpregs));
+	if (n > 0)
+		return -EFAULT;
+
+	return restore_fp_registers(userspace_pid[cpu],
+				    (unsigned long *) &fpregs);
+}
+
+static int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child)
+{
+	int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
+	struct user_fxsr_struct fpregs;
+
+	err = save_fpx_registers(userspace_pid[cpu], (unsigned long *) &fpregs);
+	if (err)
+		return err;
+
+	n = copy_to_user(buf, &fpregs, sizeof(fpregs));
+	if(n > 0)
+		return -EFAULT;
+
+	return n;
+}
+
+static int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child)
+{
+	int n, cpu = ((struct thread_info *) child->stack)->cpu;
+	struct user_fxsr_struct fpregs;
+
+	n = copy_from_user(&fpregs, buf, sizeof(fpregs));
+	if (n > 0)
+		return -EFAULT;
+
+	return restore_fpx_registers(userspace_pid[cpu],
+				     (unsigned long *) &fpregs);
+}
+
+long subarch_ptrace(struct task_struct *child, long request,
+		    unsigned long addr, unsigned long data)
+{
+	int ret = -EIO;
+	void __user *datap = (void __user *) data;
+	switch (request) {
+	case PTRACE_GETFPREGS: /* Get the child FPU state. */
+		ret = get_fpregs(datap, child);
+		break;
+	case PTRACE_SETFPREGS: /* Set the child FPU state. */
+		ret = set_fpregs(datap, child);
+		break;
+	case PTRACE_GETFPXREGS: /* Get the child FPU state. */
+		ret = get_fpxregs(datap, child);
+		break;
+	case PTRACE_SETFPXREGS: /* Set the child FPU state. */
+		ret = set_fpxregs(datap, child);
+		break;
+	default:
+		ret = -EIO;
+	}
+	return ret;
+}
diff --git a/arch/x86/um/ptrace_64.c b/arch/x86/um/ptrace_64.c
new file mode 100644
index 0000000..3b52bf0
--- /dev/null
+++ b/arch/x86/um/ptrace_64.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ *
+ * Licensed under the GPL
+ */
+
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#define __FRAME_OFFSETS
+#include <asm/ptrace.h>
+#include <asm/uaccess.h>
+
+/*
+ * determines which flags the user has access to.
+ * 1 = access 0 = no access
+ */
+#define FLAG_MASK 0x44dd5UL
+
+static const int reg_offsets[] =
+{
+	[R8 >> 3] = HOST_R8,
+	[R9 >> 3] = HOST_R9,
+	[R10 >> 3] = HOST_R10,
+	[R11 >> 3] = HOST_R11,
+	[R12 >> 3] = HOST_R12,
+	[R13 >> 3] = HOST_R13,
+	[R14 >> 3] = HOST_R14,
+	[R15 >> 3] = HOST_R15,
+	[RIP >> 3] = HOST_IP,
+	[RSP >> 3] = HOST_SP,
+	[RAX >> 3] = HOST_AX,
+	[RBX >> 3] = HOST_BX,
+	[RCX >> 3] = HOST_CX,
+	[RDX >> 3] = HOST_DX,
+	[RSI >> 3] = HOST_SI,
+	[RDI >> 3] = HOST_DI,
+	[RBP >> 3] = HOST_BP,
+	[CS >> 3] = HOST_CS,
+	[SS >> 3] = HOST_SS,
+	[FS_BASE >> 3] = HOST_FS_BASE,
+	[GS_BASE >> 3] = HOST_GS_BASE,
+	[DS >> 3] = HOST_DS,
+	[ES >> 3] = HOST_ES,
+	[FS >> 3] = HOST_FS,
+	[GS >> 3] = HOST_GS,
+	[EFLAGS >> 3] = HOST_EFLAGS,
+	[ORIG_RAX >> 3] = HOST_ORIG_AX,
+};
+
+int putreg(struct task_struct *child, int regno, unsigned long value)
+{
+#ifdef TIF_IA32
+	/*
+	 * Some code in the 64bit emulation may not be 64bit clean.
+	 * Don't take any chances.
+	 */
+	if (test_tsk_thread_flag(child, TIF_IA32))
+		value &= 0xffffffff;
+#endif
+	switch (regno) {
+	case R8:
+	case R9:
+	case R10:
+	case R11:
+	case R12:
+	case R13:
+	case R14:
+	case R15:
+	case RIP:
+	case RSP:
+	case RAX:
+	case RBX:
+	case RCX:
+	case RDX:
+	case RSI:
+	case RDI:
+	case RBP:
+	case ORIG_RAX:
+		break;
+
+	case FS:
+	case GS:
+	case DS:
+	case ES:
+	case SS:
+	case CS:
+		if (value && (value & 3) != 3)
+			return -EIO;
+		value &= 0xffff;
+		break;
+
+	case FS_BASE:
+	case GS_BASE:
+		if (!((value >> 48) == 0 || (value >> 48) == 0xffff))
+			return -EIO;
+		break;
+
+	case EFLAGS:
+		value &= FLAG_MASK;
+		child->thread.regs.regs.gp[HOST_EFLAGS] |= value;
+		return 0;
+
+	default:
+		panic("Bad register in putreg(): %d\n", regno);
+	}
+
+	child->thread.regs.regs.gp[reg_offsets[regno >> 3]] = value;
+	return 0;
+}
+
+int poke_user(struct task_struct *child, long addr, long data)
+{
+	if ((addr & 3) || addr < 0)
+		return -EIO;
+
+	if (addr < MAX_REG_OFFSET)
+		return putreg(child, addr, data);
+	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
+		(addr <= offsetof(struct user, u_debugreg[7]))) {
+		addr -= offsetof(struct user, u_debugreg[0]);
+		addr = addr >> 2;
+		if ((addr == 4) || (addr == 5))
+			return -EIO;
+		child->thread.arch.debugregs[addr] = data;
+		return 0;
+	}
+	return -EIO;
+}
+
+unsigned long getreg(struct task_struct *child, int regno)
+{
+	unsigned long mask = ~0UL;
+#ifdef TIF_IA32
+	if (test_tsk_thread_flag(child, TIF_IA32))
+		mask = 0xffffffff;
+#endif
+	switch (regno) {
+	case R8:
+	case R9:
+	case R10:
+	case R11:
+	case R12:
+	case R13:
+	case R14:
+	case R15:
+	case RIP:
+	case RSP:
+	case RAX:
+	case RBX:
+	case RCX:
+	case RDX:
+	case RSI:
+	case RDI:
+	case RBP:
+	case ORIG_RAX:
+	case EFLAGS:
+	case FS_BASE:
+	case GS_BASE:
+		break;
+	case FS:
+	case GS:
+	case DS:
+	case ES:
+	case SS:
+	case CS:
+		mask = 0xffff;
+		break;
+	default:
+		panic("Bad register in getreg: %d\n", regno);
+	}
+	return mask & child->thread.regs.regs.gp[reg_offsets[regno >> 3]];
+}
+
+int peek_user(struct task_struct *child, long addr, long data)
+{
+	/* read the word at location addr in the USER area. */
+	unsigned long tmp;
+
+	if ((addr & 3) || addr < 0)
+		return -EIO;
+
+	tmp = 0;  /* Default return condition */
+	if (addr < MAX_REG_OFFSET)
+		tmp = getreg(child, addr);
+	else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
+		(addr <= offsetof(struct user, u_debugreg[7]))) {
+		addr -= offsetof(struct user, u_debugreg[0]);
+		addr = addr >> 2;
+		tmp = child->thread.arch.debugregs[addr];
+	}
+	return put_user(tmp, (unsigned long *) data);
+}
+
+/* XXX Mostly copied from sys-i386 */
+int is_syscall(unsigned long addr)
+{
+	unsigned short instr;
+	int n;
+
+	n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
+	if (n) {
+		/*
+		 * access_process_vm() grants access to vsyscall and stub,
+		 * while copy_from_user doesn't. Maybe access_process_vm is
+		 * slow, but that doesn't matter, since it will be called only
+		 * in case of singlestepping, if copy_from_user failed.
+		 */
+		n = access_process_vm(current, addr, &instr, sizeof(instr), 0);
+		if (n != sizeof(instr)) {
+			printk("is_syscall : failed to read instruction from "
+			       "0x%lx\n", addr);
+			return 1;
+		}
+	}
+	/* sysenter */
+	return instr == 0x050f;
+}
+
+static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
+{
+	int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
+	long fpregs[HOST_FP_SIZE];
+
+	BUG_ON(sizeof(*buf) != sizeof(fpregs));
+	err = save_fp_registers(userspace_pid[cpu], fpregs);
+	if (err)
+		return err;
+
+	n = copy_to_user(buf, fpregs, sizeof(fpregs));
+	if (n > 0)
+		return -EFAULT;
+
+	return n;
+}
+
+static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
+{
+	int n, cpu = ((struct thread_info *) child->stack)->cpu;
+	long fpregs[HOST_FP_SIZE];
+
+	BUG_ON(sizeof(*buf) != sizeof(fpregs));
+	n = copy_from_user(fpregs, buf, sizeof(fpregs));
+	if (n > 0)
+		return -EFAULT;
+
+	return restore_fp_registers(userspace_pid[cpu], fpregs);
+}
+
+long subarch_ptrace(struct task_struct *child, long request,
+		    unsigned long addr, unsigned long data)
+{
+	int ret = -EIO;
+	void __user *datap = (void __user *) data;
+
+	switch (request) {
+	case PTRACE_GETFPREGS: /* Get the child FPU state. */
+		ret = get_fpregs(datap, child);
+		break;
+	case PTRACE_SETFPREGS: /* Set the child FPU state. */
+		ret = set_fpregs(datap, child);
+		break;
+	case PTRACE_ARCH_PRCTL:
+		/* XXX Calls ptrace on the host - needs some SMP thinking */
+		ret = arch_prctl(child, data, (void __user *) addr);
+		break;
+	}
+
+	return ret;
+}
diff --git a/arch/x86/um/ptrace_user.c b/arch/x86/um/ptrace_user.c
new file mode 100644
index 0000000..3960ca1
--- /dev/null
+++ b/arch/x86/um/ptrace_user.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#include <errno.h>
+#include "ptrace_user.h"
+
+int ptrace_getregs(long pid, unsigned long *regs_out)
+{
+	if (ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0)
+		return -errno;
+	return 0;
+}
+
+int ptrace_setregs(long pid, unsigned long *regs)
+{
+	if (ptrace(PTRACE_SETREGS, pid, 0, regs) < 0)
+		return -errno;
+	return 0;
+}
diff --git a/arch/x86/um/setjmp_32.S b/arch/x86/um/setjmp_32.S
new file mode 100644
index 0000000..b766792
--- /dev/null
+++ b/arch/x86/um/setjmp_32.S
@@ -0,0 +1,58 @@
+#
+# arch/i386/setjmp.S
+#
+# setjmp/longjmp for the i386 architecture
+#
+
+#
+# The jmp_buf is assumed to contain the following, in order:
+#	%ebx
+#	%esp
+#	%ebp
+#	%esi
+#	%edi
+#	<return address>
+#
+
+	.text
+	.align 4
+	.globl setjmp
+	.type setjmp, @function
+setjmp:
+#ifdef _REGPARM
+	movl %eax,%edx
+#else
+	movl 4(%esp),%edx
+#endif
+	popl %ecx			# Return address, and adjust the stack
+	xorl %eax,%eax			# Return value
+	movl %ebx,(%edx)
+	movl %esp,4(%edx)		# Post-return %esp!
+	pushl %ecx			# Make the call/return stack happy
+	movl %ebp,8(%edx)
+	movl %esi,12(%edx)
+	movl %edi,16(%edx)
+	movl %ecx,20(%edx)		# Return address
+	ret
+
+	.size setjmp,.-setjmp
+
+	.text
+	.align 4
+	.globl longjmp
+	.type longjmp, @function
+longjmp:
+#ifdef _REGPARM
+	xchgl %eax,%edx
+#else
+	movl 4(%esp),%edx		# jmp_ptr address
+	movl 8(%esp),%eax		# Return value
+#endif
+	movl (%edx),%ebx
+	movl 4(%edx),%esp
+	movl 8(%edx),%ebp
+	movl 12(%edx),%esi
+	movl 16(%edx),%edi
+	jmp *20(%edx)
+
+	.size longjmp,.-longjmp
diff --git a/arch/x86/um/setjmp_64.S b/arch/x86/um/setjmp_64.S
new file mode 100644
index 0000000..45f547b
--- /dev/null
+++ b/arch/x86/um/setjmp_64.S
@@ -0,0 +1,54 @@
+#
+# arch/x86_64/setjmp.S
+#
+# setjmp/longjmp for the x86-64 architecture
+#
+
+#
+# The jmp_buf is assumed to contain the following, in order:
+#	%rbx
+#	%rsp (post-return)
+#	%rbp
+#	%r12
+#	%r13
+#	%r14
+#	%r15
+#	<return address>
+#
+
+	.text
+	.align 4
+	.globl setjmp
+	.type setjmp, @function
+setjmp:
+	pop  %rsi			# Return address, and adjust the stack
+	xorl %eax,%eax			# Return value
+	movq %rbx,(%rdi)
+	movq %rsp,8(%rdi)		# Post-return %rsp!
+	push %rsi			# Make the call/return stack happy
+	movq %rbp,16(%rdi)
+	movq %r12,24(%rdi)
+	movq %r13,32(%rdi)
+	movq %r14,40(%rdi)
+	movq %r15,48(%rdi)
+	movq %rsi,56(%rdi)		# Return address
+	ret
+
+	.size setjmp,.-setjmp
+
+	.text
+	.align 4
+	.globl longjmp
+	.type longjmp, @function
+longjmp:
+	movl %esi,%eax			# Return value (int)
+	movq (%rdi),%rbx
+	movq 8(%rdi),%rsp
+	movq 16(%rdi),%rbp
+	movq 24(%rdi),%r12
+	movq 32(%rdi),%r13
+	movq 40(%rdi),%r14
+	movq 48(%rdi),%r15
+	jmp *56(%rdi)
+
+	.size longjmp,.-longjmp
diff --git a/arch/x86/um/shared/sysdep/archsetjmp.h b/arch/x86/um/shared/sysdep/archsetjmp.h
new file mode 100644
index 0000000..ff7766d
--- /dev/null
+++ b/arch/x86/um/shared/sysdep/archsetjmp.h
@@ -0,0 +1,5 @@
+#ifdef __i386__
+#include "archsetjmp_32.h"
+#else
+#include "archsetjmp_64.h"
+#endif
diff --git a/arch/x86/um/shared/sysdep/archsetjmp_32.h b/arch/x86/um/shared/sysdep/archsetjmp_32.h
new file mode 100644
index 0000000..0f31208
--- /dev/null
+++ b/arch/x86/um/shared/sysdep/archsetjmp_32.h
@@ -0,0 +1,22 @@
+/*
+ * arch/um/include/sysdep-i386/archsetjmp.h
+ */
+
+#ifndef _KLIBC_ARCHSETJMP_H
+#define _KLIBC_ARCHSETJMP_H
+
+struct __jmp_buf {
+	unsigned int __ebx;
+	unsigned int __esp;
+	unsigned int __ebp;
+	unsigned int __esi;
+	unsigned int __edi;
+	unsigned int __eip;
+};
+
+typedef struct __jmp_buf jmp_buf[1];
+
+#define JB_IP __eip
+#define JB_SP __esp
+
+#endif				/* _SETJMP_H */
diff --git a/arch/x86/um/shared/sysdep/archsetjmp_64.h b/arch/x86/um/shared/sysdep/archsetjmp_64.h
new file mode 100644
index 0000000..2af8f12
--- /dev/null
+++ b/arch/x86/um/shared/sysdep/archsetjmp_64.h
@@ -0,0 +1,24 @@
+/*
+ * arch/um/include/sysdep-x86_64/archsetjmp.h
+ */
+
+#ifndef _KLIBC_ARCHSETJMP_H
+#define _KLIBC_ARCHSETJMP_H
+
+struct __jmp_buf {
+	unsigned long __rbx;
+	unsigned long __rsp;
+	unsigned long __rbp;
+	unsigned long __r12;
+	unsigned long __r13;
+	unsigned long __r14;
+	unsigned long __r15;
+	unsigned long __rip;
+};
+
+typedef struct __jmp_buf jmp_buf[1];
+
+#define JB_IP __rip
+#define JB_SP __rsp
+
+#endif				/* _SETJMP_H */
diff --git a/arch/x86/um/shared/sysdep/faultinfo.h b/arch/x86/um/shared/sysdep/faultinfo.h
new file mode 100644
index 0000000..862ecb1
--- /dev/null
+++ b/arch/x86/um/shared/sysdep/faultinfo.h
@@ -0,0 +1,5 @@
+#ifdef __i386__
+#include "faultinfo_32.h"
+#else
+#include "faultinfo_64.h"
+#endif
diff --git a/arch/x86/um/shared/sysdep/faultinfo_32.h b/arch/x86/um/shared/sysdep/faultinfo_32.h
new file mode 100644
index 0000000..a26086b
--- /dev/null
+++ b/arch/x86/um/shared/sysdep/faultinfo_32.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
+ * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
+ * Licensed under the GPL
+ */
+
+#ifndef __FAULTINFO_I386_H
+#define __FAULTINFO_I386_H
+
+/* this structure contains the full arch-specific faultinfo
+ * from the traps.
+ * On i386, ptrace_faultinfo unfortunately doesn't provide
+ * all the info, since trap_no is missing.
+ * All common elements are defined at the same position in
+ * both structures, thus making it easy to copy the
+ * contents without knowledge about the structure elements.
+ */
+struct faultinfo {
+        int error_code; /* in ptrace_faultinfo misleadingly called is_write */
+        unsigned long cr2; /* in ptrace_faultinfo called addr */
+        int trap_no; /* missing in ptrace_faultinfo */
+};
+
+#define FAULT_WRITE(fi) ((fi).error_code & 2)
+#define FAULT_ADDRESS(fi) ((fi).cr2)
+
+/* This is Page Fault */
+#define SEGV_IS_FIXABLE(fi)	((fi)->trap_no == 14)
+
+/* SKAS3 has no trap_no on i386, but get_skas_faultinfo() sets it to 0. */
+#define SEGV_MAYBE_FIXABLE(fi)	((fi)->trap_no == 0 && ptrace_faultinfo)
+
+#define PTRACE_FULL_FAULTINFO 0
+
+#endif
diff --git a/arch/x86/um/shared/sysdep/faultinfo_64.h b/arch/x86/um/shared/sysdep/faultinfo_64.h
new file mode 100644
index 0000000..f811cbe
--- /dev/null
+++ b/arch/x86/um/shared/sysdep/faultinfo_64.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
+ * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
+ * Licensed under the GPL
+ */
+
+#ifndef __FAULTINFO_X86_64_H
+#define __FAULTINFO_X86_64_H
+
+/* this structure contains the full arch-specific faultinfo
+ * from the traps.
+ * On i386, ptrace_faultinfo unfortunately doesn't provide
+ * all the info, since trap_no is missing.
+ * All common elements are defined at the same position in
+ * both structures, thus making it easy to copy the
+ * contents without knowledge about the structure elements.
+ */
+struct faultinfo {
+        int error_code; /* in ptrace_faultinfo misleadingly called is_write */
+        unsigned long cr2; /* in ptrace_faultinfo called addr */
+        int trap_no; /* missing in ptrace_faultinfo */
+};
+
+#define FAULT_WRITE(fi) ((fi).error_code & 2)
+#define FAULT_ADDRESS(fi) ((fi).cr2)
+
+/* This is Page Fault */
+#define SEGV_IS_FIXABLE(fi)	((fi)->trap_no == 14)
+
+/* No broken SKAS API, which doesn't pass trap_no, here. */
+#define SEGV_MAYBE_FIXABLE(fi)	0
+
+#define PTRACE_FULL_FAULTINFO 1
+
+#endif
diff --git a/arch/x86/um/shared/sysdep/kernel-offsets.h b/arch/x86/um/shared/sysdep/kernel-offsets.h
new file mode 100644
index 0000000..5868526
--- /dev/null
+++ b/arch/x86/um/shared/sysdep/kernel-offsets.h
@@ -0,0 +1,21 @@
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/elf.h>
+#include <linux/crypto.h>
+#include <asm/mman.h>
+
+#define DEFINE(sym, val) \
+	asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+#define STR(x) #x
+#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " STR(val) " " #val: : )
+
+#define BLANK() asm volatile("\n->" : : )
+
+#define OFFSET(sym, str, mem) \
+	DEFINE(sym, offsetof(struct str, mem));
+
+void foo(void)
+{
+#include <common-offsets.h>
+}
diff --git a/arch/x86/um/shared/sysdep/mcontext.h b/arch/x86/um/shared/sysdep/mcontext.h
new file mode 100644
index 0000000..b724c54
--- /dev/null
+++ b/arch/x86/um/shared/sysdep/mcontext.h
@@ -0,0 +1,31 @@
+/* 
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYS_SIGCONTEXT_X86_H
+#define __SYS_SIGCONTEXT_X86_H
+
+extern void get_regs_from_mc(struct uml_pt_regs *, mcontext_t *);
+
+#ifdef __i386__
+
+#define GET_FAULTINFO_FROM_MC(fi, mc) \
+	{ \
+		(fi).cr2 = (mc)->cr2; \
+		(fi).error_code = (mc)->gregs[REG_ERR]; \
+		(fi).trap_no = (mc)->gregs[REG_TRAPNO]; \
+	}
+
+#else
+
+#define GET_FAULTINFO_FROM_MC(fi, mc) \
+	{ \
+		(fi).cr2 = (mc)->gregs[REG_CR2]; \
+		(fi).error_code = (mc)->gregs[REG_ERR]; \
+		(fi).trap_no = (mc)->gregs[REG_TRAPNO]; \
+	}
+
+#endif
+
+#endif
diff --git a/arch/x86/um/shared/sysdep/ptrace.h b/arch/x86/um/shared/sysdep/ptrace.h
new file mode 100644
index 0000000..711b162
--- /dev/null
+++ b/arch/x86/um/shared/sysdep/ptrace.h
@@ -0,0 +1,5 @@
+#ifdef __i386__
+#include "ptrace_32.h"
+#else
+#include "ptrace_64.h"
+#endif
diff --git a/arch/x86/um/shared/sysdep/ptrace_32.h b/arch/x86/um/shared/sysdep/ptrace_32.h
new file mode 100644
index 0000000..befd1df
--- /dev/null
+++ b/arch/x86/um/shared/sysdep/ptrace_32.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_I386_PTRACE_H
+#define __SYSDEP_I386_PTRACE_H
+
+#include <generated/user_constants.h>
+#include "sysdep/faultinfo.h"
+
+#define MAX_REG_NR (UM_FRAME_SIZE / sizeof(unsigned long))
+#define MAX_REG_OFFSET (UM_FRAME_SIZE)
+
+static inline void update_debugregs(int seq) {}
+
+/* syscall emulation path in ptrace */
+
+#ifndef PTRACE_SYSEMU
+#define PTRACE_SYSEMU 31
+#endif
+
+void set_using_sysemu(int value);
+int get_using_sysemu(void);
+extern int sysemu_supported;
+
+#define REGS_IP(r) ((r)[HOST_IP])
+#define REGS_SP(r) ((r)[HOST_SP])
+#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS])
+#define REGS_EAX(r) ((r)[HOST_AX])
+#define REGS_EBX(r) ((r)[HOST_BX])
+#define REGS_ECX(r) ((r)[HOST_CX])
+#define REGS_EDX(r) ((r)[HOST_DX])
+#define REGS_ESI(r) ((r)[HOST_SI])
+#define REGS_EDI(r) ((r)[HOST_DI])
+#define REGS_EBP(r) ((r)[HOST_BP])
+#define REGS_CS(r) ((r)[HOST_CS])
+#define REGS_SS(r) ((r)[HOST_SS])
+#define REGS_DS(r) ((r)[HOST_DS])
+#define REGS_ES(r) ((r)[HOST_ES])
+#define REGS_FS(r) ((r)[HOST_FS])
+#define REGS_GS(r) ((r)[HOST_GS])
+
+#define REGS_SET_SYSCALL_RETURN(r, res) REGS_EAX(r) = (res)
+
+#define IP_RESTART_SYSCALL(ip) ((ip) -= 2)
+#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r))
+
+#ifndef PTRACE_SYSEMU_SINGLESTEP
+#define PTRACE_SYSEMU_SINGLESTEP 32
+#endif
+
+struct uml_pt_regs {
+	unsigned long gp[MAX_REG_NR];
+	unsigned long fp[HOST_FPX_SIZE];
+	struct faultinfo faultinfo;
+	long syscall;
+	int is_user;
+};
+
+#define EMPTY_UML_PT_REGS { }
+
+#define UPT_IP(r) REGS_IP((r)->gp)
+#define UPT_SP(r) REGS_SP((r)->gp)
+#define UPT_EFLAGS(r) REGS_EFLAGS((r)->gp)
+#define UPT_EAX(r) REGS_EAX((r)->gp)
+#define UPT_EBX(r) REGS_EBX((r)->gp)
+#define UPT_ECX(r) REGS_ECX((r)->gp)
+#define UPT_EDX(r) REGS_EDX((r)->gp)
+#define UPT_ESI(r) REGS_ESI((r)->gp)
+#define UPT_EDI(r) REGS_EDI((r)->gp)
+#define UPT_EBP(r) REGS_EBP((r)->gp)
+#define UPT_ORIG_EAX(r) ((r)->syscall)
+#define UPT_CS(r) REGS_CS((r)->gp)
+#define UPT_SS(r) REGS_SS((r)->gp)
+#define UPT_DS(r) REGS_DS((r)->gp)
+#define UPT_ES(r) REGS_ES((r)->gp)
+#define UPT_FS(r) REGS_FS((r)->gp)
+#define UPT_GS(r) REGS_GS((r)->gp)
+
+#define UPT_SYSCALL_ARG1(r) UPT_EBX(r)
+#define UPT_SYSCALL_ARG2(r) UPT_ECX(r)
+#define UPT_SYSCALL_ARG3(r) UPT_EDX(r)
+#define UPT_SYSCALL_ARG4(r) UPT_ESI(r)
+#define UPT_SYSCALL_ARG5(r) UPT_EDI(r)
+#define UPT_SYSCALL_ARG6(r) UPT_EBP(r)
+
+extern int user_context(unsigned long sp);
+
+#define UPT_IS_USER(r) ((r)->is_user)
+
+struct syscall_args {
+	unsigned long args[6];
+};
+
+#define SYSCALL_ARGS(r) ((struct syscall_args) \
+			 { .args = { UPT_SYSCALL_ARG1(r),	\
+				     UPT_SYSCALL_ARG2(r),	\
+				     UPT_SYSCALL_ARG3(r),	\
+				     UPT_SYSCALL_ARG4(r),	\
+				     UPT_SYSCALL_ARG5(r),	\
+				     UPT_SYSCALL_ARG6(r) } } )
+
+#define UPT_RESTART_SYSCALL(r) REGS_RESTART_SYSCALL((r)->gp)
+
+#define UPT_ORIG_SYSCALL(r) UPT_EAX(r)
+#define UPT_SYSCALL_NR(r) UPT_ORIG_EAX(r)
+#define UPT_SYSCALL_RET(r) UPT_EAX(r)
+
+#define UPT_FAULTINFO(r) (&(r)->faultinfo)
+
+extern void arch_init_registers(int pid);
+
+#endif
diff --git a/arch/x86/um/shared/sysdep/ptrace_64.h b/arch/x86/um/shared/sysdep/ptrace_64.h
new file mode 100644
index 0000000..031edc5
--- /dev/null
+++ b/arch/x86/um/shared/sysdep/ptrace_64.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ *
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_X86_64_PTRACE_H
+#define __SYSDEP_X86_64_PTRACE_H
+
+#include <generated/user_constants.h>
+#include "sysdep/faultinfo.h"
+
+#define MAX_REG_OFFSET (UM_FRAME_SIZE)
+#define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long))
+
+#define REGS_IP(r) ((r)[HOST_IP])
+#define REGS_SP(r) ((r)[HOST_SP])
+
+#define REGS_RBX(r) ((r)[HOST_BX])
+#define REGS_RCX(r) ((r)[HOST_CX])
+#define REGS_RDX(r) ((r)[HOST_DX])
+#define REGS_RSI(r) ((r)[HOST_SI])
+#define REGS_RDI(r) ((r)[HOST_DI])
+#define REGS_RBP(r) ((r)[HOST_BP])
+#define REGS_RAX(r) ((r)[HOST_AX])
+#define REGS_R8(r) ((r)[HOST_R8])
+#define REGS_R9(r) ((r)[HOST_R9])
+#define REGS_R10(r) ((r)[HOST_R10])
+#define REGS_R11(r) ((r)[HOST_R11])
+#define REGS_R12(r) ((r)[HOST_R12])
+#define REGS_R13(r) ((r)[HOST_R13])
+#define REGS_R14(r) ((r)[HOST_R14])
+#define REGS_R15(r) ((r)[HOST_R15])
+#define REGS_CS(r) ((r)[HOST_CS])
+#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS])
+#define REGS_SS(r) ((r)[HOST_SS])
+
+#define HOST_FS_BASE 21
+#define HOST_GS_BASE 22
+#define HOST_DS 23
+#define HOST_ES 24
+#define HOST_FS 25
+#define HOST_GS 26
+
+/* Also defined in asm/ptrace-x86_64.h, but not in libc headers.  So, these
+ * are already defined for kernel code, but not for userspace code.
+ */
+#ifndef FS_BASE
+/* These aren't defined in ptrace.h, but exist in struct user_regs_struct,
+ * which is what x86_64 ptrace actually uses.
+ */
+#define FS_BASE (HOST_FS_BASE * sizeof(long))
+#define GS_BASE (HOST_GS_BASE * sizeof(long))
+#define DS (HOST_DS * sizeof(long))
+#define ES (HOST_ES * sizeof(long))
+#define FS (HOST_FS * sizeof(long))
+#define GS (HOST_GS * sizeof(long))
+#endif
+
+#define REGS_FS_BASE(r) ((r)[HOST_FS_BASE])
+#define REGS_GS_BASE(r) ((r)[HOST_GS_BASE])
+#define REGS_DS(r) ((r)[HOST_DS])
+#define REGS_ES(r) ((r)[HOST_ES])
+#define REGS_FS(r) ((r)[HOST_FS])
+#define REGS_GS(r) ((r)[HOST_GS])
+
+#define REGS_ORIG_RAX(r) ((r)[HOST_ORIG_AX])
+
+#define REGS_SET_SYSCALL_RETURN(r, res) REGS_RAX(r) = (res)
+
+#define IP_RESTART_SYSCALL(ip) ((ip) -= 2)
+#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r))
+
+#define REGS_FAULT_ADDR(r) ((r)->fault_addr)
+
+#define REGS_FAULT_WRITE(r) FAULT_WRITE((r)->fault_type)
+
+#define REGS_TRAP(r) ((r)->trap_type)
+
+#define REGS_ERR(r) ((r)->fault_type)
+
+struct uml_pt_regs {
+	unsigned long gp[MAX_REG_NR];
+	unsigned long fp[HOST_FP_SIZE];
+	struct faultinfo faultinfo;
+	long syscall;
+	int is_user;
+};
+
+#define EMPTY_UML_PT_REGS { }
+
+#define UPT_RBX(r) REGS_RBX((r)->gp)
+#define UPT_RCX(r) REGS_RCX((r)->gp)
+#define UPT_RDX(r) REGS_RDX((r)->gp)
+#define UPT_RSI(r) REGS_RSI((r)->gp)
+#define UPT_RDI(r) REGS_RDI((r)->gp)
+#define UPT_RBP(r) REGS_RBP((r)->gp)
+#define UPT_RAX(r) REGS_RAX((r)->gp)
+#define UPT_R8(r) REGS_R8((r)->gp)
+#define UPT_R9(r) REGS_R9((r)->gp)
+#define UPT_R10(r) REGS_R10((r)->gp)
+#define UPT_R11(r) REGS_R11((r)->gp)
+#define UPT_R12(r) REGS_R12((r)->gp)
+#define UPT_R13(r) REGS_R13((r)->gp)
+#define UPT_R14(r) REGS_R14((r)->gp)
+#define UPT_R15(r) REGS_R15((r)->gp)
+#define UPT_CS(r) REGS_CS((r)->gp)
+#define UPT_FS_BASE(r) REGS_FS_BASE((r)->gp)
+#define UPT_FS(r) REGS_FS((r)->gp)
+#define UPT_GS_BASE(r) REGS_GS_BASE((r)->gp)
+#define UPT_GS(r) REGS_GS((r)->gp)
+#define UPT_DS(r) REGS_DS((r)->gp)
+#define UPT_ES(r) REGS_ES((r)->gp)
+#define UPT_CS(r) REGS_CS((r)->gp)
+#define UPT_SS(r) REGS_SS((r)->gp)
+#define UPT_ORIG_RAX(r) REGS_ORIG_RAX((r)->gp)
+
+#define UPT_IP(r) REGS_IP((r)->gp)
+#define UPT_SP(r) REGS_SP((r)->gp)
+
+#define UPT_EFLAGS(r) REGS_EFLAGS((r)->gp)
+#define UPT_SYSCALL_NR(r) ((r)->syscall)
+#define UPT_SYSCALL_RET(r) UPT_RAX(r)
+
+extern int user_context(unsigned long sp);
+
+#define UPT_IS_USER(r) ((r)->is_user)
+
+#define UPT_SYSCALL_ARG1(r) UPT_RDI(r)
+#define UPT_SYSCALL_ARG2(r) UPT_RSI(r)
+#define UPT_SYSCALL_ARG3(r) UPT_RDX(r)
+#define UPT_SYSCALL_ARG4(r) UPT_R10(r)
+#define UPT_SYSCALL_ARG5(r) UPT_R8(r)
+#define UPT_SYSCALL_ARG6(r) UPT_R9(r)
+
+struct syscall_args {
+	unsigned long args[6];
+};
+
+#define SYSCALL_ARGS(r) ((struct syscall_args) \
+			 { .args = { UPT_SYSCALL_ARG1(r),	 \
+				     UPT_SYSCALL_ARG2(r),	 \
+				     UPT_SYSCALL_ARG3(r),	 \
+				     UPT_SYSCALL_ARG4(r),	 \
+				     UPT_SYSCALL_ARG5(r),	 \
+				     UPT_SYSCALL_ARG6(r) } } )
+
+#define UPT_RESTART_SYSCALL(r) REGS_RESTART_SYSCALL((r)->gp)
+
+#define UPT_FAULTINFO(r) (&(r)->faultinfo)
+
+static inline void arch_init_registers(int pid)
+{
+}
+
+#endif
diff --git a/arch/x86/um/shared/sysdep/ptrace_user.h b/arch/x86/um/shared/sysdep/ptrace_user.h
new file mode 100644
index 0000000..16cd6b5
--- /dev/null
+++ b/arch/x86/um/shared/sysdep/ptrace_user.h
@@ -0,0 +1,27 @@
+#include <generated/user_constants.h>
+
+#define PT_OFFSET(r) ((r) * sizeof(long))
+
+#define PT_SYSCALL_NR(regs) ((regs)[HOST_ORIG_AX])
+#define PT_SYSCALL_NR_OFFSET PT_OFFSET(HOST_ORIG_AX)
+
+#define PT_SYSCALL_RET_OFFSET PT_OFFSET(HOST_AX)
+
+#define REGS_IP_INDEX HOST_IP
+#define REGS_SP_INDEX HOST_SP
+
+#ifdef __i386__
+#define FP_SIZE ((HOST_FPX_SIZE > HOST_FP_SIZE) ? HOST_FPX_SIZE : HOST_FP_SIZE)
+#else
+#define FP_SIZE HOST_FP_SIZE
+
+/*
+ * x86_64 FC3 doesn't define this in /usr/include/linux/ptrace.h even though
+ * it's defined in the kernel's include/linux/ptrace.h. Additionally, use the
+ * 2.4 name and value for 2.4 host compatibility.
+ */
+#ifndef PTRACE_OLDSETOPTIONS
+#define PTRACE_OLDSETOPTIONS 21
+#endif
+
+#endif
diff --git a/arch/x86/um/shared/sysdep/skas_ptrace.h b/arch/x86/um/shared/sysdep/skas_ptrace.h
new file mode 100644
index 0000000..453febe
--- /dev/null
+++ b/arch/x86/um/shared/sysdep/skas_ptrace.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_X86_SKAS_PTRACE_H
+#define __SYSDEP_X86_SKAS_PTRACE_H
+
+struct ptrace_faultinfo {
+        int is_write;
+        unsigned long addr;
+};
+
+struct ptrace_ldt {
+        int func;
+        void *ptr;
+        unsigned long bytecount;
+};
+
+#define PTRACE_LDT 54
+
+#endif
diff --git a/arch/x86/um/shared/sysdep/stub.h b/arch/x86/um/shared/sysdep/stub.h
new file mode 100644
index 0000000..bd161e3
--- /dev/null
+++ b/arch/x86/um/shared/sysdep/stub.h
@@ -0,0 +1,14 @@
+#include <asm/unistd.h>
+#include <sys/mman.h>
+#include <signal.h>
+#include "as-layout.h"
+#include "stub-data.h"
+
+#ifdef __i386__
+#include "stub_32.h"
+#else
+#include "stub_64.h"
+#endif
+
+extern void stub_segv_handler(int, siginfo_t *, void *);
+extern void stub_clone_handler(void);
diff --git a/arch/x86/um/shared/sysdep/stub_32.h b/arch/x86/um/shared/sysdep/stub_32.h
new file mode 100644
index 0000000..51fd256
--- /dev/null
+++ b/arch/x86/um/shared/sysdep/stub_32.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_STUB_H
+#define __SYSDEP_STUB_H
+
+#include <asm/ptrace.h>
+
+#define STUB_SYSCALL_RET EAX
+#define STUB_MMAP_NR __NR_mmap2
+#define MMAP_OFFSET(o) ((o) >> UM_KERN_PAGE_SHIFT)
+
+static inline long stub_syscall0(long syscall)
+{
+	long ret;
+
+	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall));
+
+	return ret;
+}
+
+static inline long stub_syscall1(long syscall, long arg1)
+{
+	long ret;
+
+	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1));
+
+	return ret;
+}
+
+static inline long stub_syscall2(long syscall, long arg1, long arg2)
+{
+	long ret;
+
+	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
+			"c" (arg2));
+
+	return ret;
+}
+
+static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3)
+{
+	long ret;
+
+	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
+			"c" (arg2), "d" (arg3));
+
+	return ret;
+}
+
+static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3,
+				 long arg4)
+{
+	long ret;
+
+	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
+			"c" (arg2), "d" (arg3), "S" (arg4));
+
+	return ret;
+}
+
+static inline long stub_syscall5(long syscall, long arg1, long arg2, long arg3,
+				 long arg4, long arg5)
+{
+	long ret;
+
+	__asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
+			"c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5));
+
+	return ret;
+}
+
+static inline void trap_myself(void)
+{
+	__asm("int3");
+}
+
+static inline void remap_stack(int fd, unsigned long offset)
+{
+	__asm__ volatile ("movl %%eax,%%ebp ; movl %0,%%eax ; int $0x80 ;"
+			  "movl %7, %%ebx ; movl %%eax, (%%ebx)"
+			  : : "g" (STUB_MMAP_NR), "b" (STUB_DATA),
+			    "c" (UM_KERN_PAGE_SIZE),
+			    "d" (PROT_READ | PROT_WRITE),
+			    "S" (MAP_FIXED | MAP_SHARED), "D" (fd),
+			    "a" (offset),
+			    "i" (&((struct stub_data *) STUB_DATA)->err)
+			  : "memory");
+}
+
+#endif
diff --git a/arch/x86/um/shared/sysdep/stub_64.h b/arch/x86/um/shared/sysdep/stub_64.h
new file mode 100644
index 0000000..994df93
--- /dev/null
+++ b/arch/x86/um/shared/sysdep/stub_64.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_STUB_H
+#define __SYSDEP_STUB_H
+
+#include <sysdep/ptrace_user.h>
+
+#define STUB_SYSCALL_RET PT_INDEX(RAX)
+#define STUB_MMAP_NR __NR_mmap
+#define MMAP_OFFSET(o) (o)
+
+#define __syscall_clobber "r11","rcx","memory"
+#define __syscall "syscall"
+
+static inline long stub_syscall0(long syscall)
+{
+	long ret;
+
+	__asm__ volatile (__syscall
+		: "=a" (ret)
+		: "0" (syscall) : __syscall_clobber );
+
+	return ret;
+}
+
+static inline long stub_syscall2(long syscall, long arg1, long arg2)
+{
+	long ret;
+
+	__asm__ volatile (__syscall
+		: "=a" (ret)
+		: "0" (syscall), "D" (arg1), "S" (arg2) : __syscall_clobber );
+
+	return ret;
+}
+
+static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3)
+{
+	long ret;
+
+	__asm__ volatile (__syscall
+		: "=a" (ret)
+		: "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3)
+		: __syscall_clobber );
+
+	return ret;
+}
+
+static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3,
+				 long arg4)
+{
+	long ret;
+
+	__asm__ volatile ("movq %5,%%r10 ; " __syscall
+		: "=a" (ret)
+		: "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3),
+		  "g" (arg4)
+		: __syscall_clobber, "r10" );
+
+	return ret;
+}
+
+static inline long stub_syscall5(long syscall, long arg1, long arg2, long arg3,
+				 long arg4, long arg5)
+{
+	long ret;
+
+	__asm__ volatile ("movq %5,%%r10 ; movq %6,%%r8 ; " __syscall
+		: "=a" (ret)
+		: "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3),
+		  "g" (arg4), "g" (arg5)
+		: __syscall_clobber, "r10", "r8" );
+
+	return ret;
+}
+
+static inline void trap_myself(void)
+{
+	__asm("int3");
+}
+
+static inline void remap_stack(long fd, unsigned long offset)
+{
+	__asm__ volatile ("movq %4,%%r10 ; movq %5,%%r8 ; "
+			  "movq %6, %%r9; " __syscall "; movq %7, %%rbx ; "
+			  "movq %%rax, (%%rbx)":
+			  : "a" (STUB_MMAP_NR), "D" (STUB_DATA),
+			    "S" (UM_KERN_PAGE_SIZE),
+			    "d" (PROT_READ | PROT_WRITE),
+                            "g" (MAP_FIXED | MAP_SHARED), "g" (fd),
+			    "g" (offset),
+			    "i" (&((struct stub_data *) STUB_DATA)->err)
+			  : __syscall_clobber, "r10", "r8", "r9" );
+}
+
+#endif
diff --git a/arch/x86/um/shared/sysdep/syscalls.h b/arch/x86/um/shared/sysdep/syscalls.h
new file mode 100644
index 0000000..bd9a89b
--- /dev/null
+++ b/arch/x86/um/shared/sysdep/syscalls.h
@@ -0,0 +1,5 @@
+#ifdef __i386__
+#include "syscalls_32.h"
+#else
+#include "syscalls_64.h"
+#endif
diff --git a/arch/x86/um/shared/sysdep/syscalls_32.h b/arch/x86/um/shared/sysdep/syscalls_32.h
new file mode 100644
index 0000000..05cb796
--- /dev/null
+++ b/arch/x86/um/shared/sysdep/syscalls_32.h
@@ -0,0 +1,20 @@
+/* 
+ * Copyright (C) 2000 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#include "asm/unistd.h"
+#include "sysdep/ptrace.h"
+
+typedef long syscall_handler_t(struct pt_regs);
+
+/* Not declared on x86, incompatible declarations on x86_64, so these have
+ * to go here rather than in sys_call_table.c
+ */
+extern syscall_handler_t sys_rt_sigaction;
+
+extern syscall_handler_t *sys_call_table[];
+
+#define EXECUTE_SYSCALL(syscall, regs) \
+	((long (*)(struct syscall_args)) \
+	 (*sys_call_table[syscall]))(SYSCALL_ARGS(&regs->regs))
diff --git a/arch/x86/um/shared/sysdep/syscalls_64.h b/arch/x86/um/shared/sysdep/syscalls_64.h
new file mode 100644
index 0000000..8a7d5e1
--- /dev/null
+++ b/arch/x86/um/shared/sysdep/syscalls_64.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_X86_64_SYSCALLS_H__
+#define __SYSDEP_X86_64_SYSCALLS_H__
+
+#include <linux/msg.h>
+#include <linux/shm.h>
+
+typedef long syscall_handler_t(void);
+
+extern syscall_handler_t *sys_call_table[];
+
+#define EXECUTE_SYSCALL(syscall, regs) \
+	(((long (*)(long, long, long, long, long, long)) \
+	  (*sys_call_table[syscall]))(UPT_SYSCALL_ARG1(&regs->regs), \
+		 		      UPT_SYSCALL_ARG2(&regs->regs), \
+				      UPT_SYSCALL_ARG3(&regs->regs), \
+				      UPT_SYSCALL_ARG4(&regs->regs), \
+				      UPT_SYSCALL_ARG5(&regs->regs), \
+				      UPT_SYSCALL_ARG6(&regs->regs)))
+
+extern long old_mmap(unsigned long addr, unsigned long len,
+		     unsigned long prot, unsigned long flags,
+		     unsigned long fd, unsigned long pgoff);
+extern syscall_handler_t sys_modify_ldt;
+extern syscall_handler_t sys_arch_prctl;
+
+#endif
diff --git a/arch/x86/um/shared/sysdep/tls.h b/arch/x86/um/shared/sysdep/tls.h
new file mode 100644
index 0000000..27cce00
--- /dev/null
+++ b/arch/x86/um/shared/sysdep/tls.h
@@ -0,0 +1,39 @@
+#ifndef _SYSDEP_TLS_H
+#define _SYSDEP_TLS_H
+
+# ifndef __KERNEL__
+
+/* Change name to avoid conflicts with the original one from <asm/ldt.h>, which
+ * may be named user_desc (but in 2.4 and in header matching its API was named
+ * modify_ldt_ldt_s). */
+
+typedef struct um_dup_user_desc {
+	unsigned int  entry_number;
+	unsigned int  base_addr;
+	unsigned int  limit;
+	unsigned int  seg_32bit:1;
+	unsigned int  contents:2;
+	unsigned int  read_exec_only:1;
+	unsigned int  limit_in_pages:1;
+	unsigned int  seg_not_present:1;
+	unsigned int  useable:1;
+#ifdef __x86_64__
+	unsigned int  lm:1;
+#endif
+} user_desc_t;
+
+# else /* __KERNEL__ */
+
+typedef struct user_desc user_desc_t;
+
+# endif /* __KERNEL__ */
+
+extern int os_set_thread_area(user_desc_t *info, int pid);
+extern int os_get_thread_area(user_desc_t *info, int pid);
+
+#ifdef __i386__
+#define GDT_ENTRY_TLS_MIN_I386 6
+#define GDT_ENTRY_TLS_MIN_X86_64 12
+#endif
+
+#endif /* _SYSDEP_TLS_H */
diff --git a/arch/x86/um/signal.c b/arch/x86/um/signal.c
new file mode 100644
index 0000000..4883b95
--- /dev/null
+++ b/arch/x86/um/signal.c
@@ -0,0 +1,624 @@
+/*
+ * Copyright (C) 2003 PathScale, Inc.
+ * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+
+#include <linux/personality.h>
+#include <linux/ptrace.h>
+#include <linux/kernel.h>
+#include <asm/unistd.h>
+#include <asm/uaccess.h>
+#include <asm/ucontext.h>
+#include "frame_kern.h"
+#include "skas.h"
+
+#ifdef CONFIG_X86_32
+
+/*
+ * FPU tag word conversions.
+ */
+
+static inline unsigned short twd_i387_to_fxsr(unsigned short twd)
+{
+	unsigned int tmp; /* to avoid 16 bit prefixes in the code */
+
+	/* Transform each pair of bits into 01 (valid) or 00 (empty) */
+	tmp = ~twd;
+	tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */
+	/* and move the valid bits to the lower byte. */
+	tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */
+	tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */
+	tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */
+	return tmp;
+}
+
+static inline unsigned long twd_fxsr_to_i387(struct user_fxsr_struct *fxsave)
+{
+	struct _fpxreg *st = NULL;
+	unsigned long twd = (unsigned long) fxsave->twd;
+	unsigned long tag;
+	unsigned long ret = 0xffff0000;
+	int i;
+
+#define FPREG_ADDR(f, n)	((char *)&(f)->st_space + (n) * 16)
+
+	for (i = 0; i < 8; i++) {
+		if (twd & 0x1) {
+			st = (struct _fpxreg *) FPREG_ADDR(fxsave, i);
+
+			switch (st->exponent & 0x7fff) {
+			case 0x7fff:
+				tag = 2;		/* Special */
+				break;
+			case 0x0000:
+				if ( !st->significand[0] &&
+				     !st->significand[1] &&
+				     !st->significand[2] &&
+				     !st->significand[3] ) {
+					tag = 1;	/* Zero */
+				} else {
+					tag = 2;	/* Special */
+				}
+				break;
+			default:
+				if (st->significand[3] & 0x8000) {
+					tag = 0;	/* Valid */
+				} else {
+					tag = 2;	/* Special */
+				}
+				break;
+			}
+		} else {
+			tag = 3;			/* Empty */
+		}
+		ret |= (tag << (2 * i));
+		twd = twd >> 1;
+	}
+	return ret;
+}
+
+static int convert_fxsr_to_user(struct _fpstate __user *buf,
+				struct user_fxsr_struct *fxsave)
+{
+	unsigned long env[7];
+	struct _fpreg __user *to;
+	struct _fpxreg *from;
+	int i;
+
+	env[0] = (unsigned long)fxsave->cwd | 0xffff0000ul;
+	env[1] = (unsigned long)fxsave->swd | 0xffff0000ul;
+	env[2] = twd_fxsr_to_i387(fxsave);
+	env[3] = fxsave->fip;
+	env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16);
+	env[5] = fxsave->foo;
+	env[6] = fxsave->fos;
+
+	if (__copy_to_user(buf, env, 7 * sizeof(unsigned long)))
+		return 1;
+
+	to = &buf->_st[0];
+	from = (struct _fpxreg *) &fxsave->st_space[0];
+	for (i = 0; i < 8; i++, to++, from++) {
+		unsigned long __user *t = (unsigned long __user *)to;
+		unsigned long *f = (unsigned long *)from;
+
+		if (__put_user(*f, t) ||
+				__put_user(*(f + 1), t + 1) ||
+				__put_user(from->exponent, &to->exponent))
+			return 1;
+	}
+	return 0;
+}
+
+static int convert_fxsr_from_user(struct user_fxsr_struct *fxsave,
+				  struct _fpstate __user *buf)
+{
+	unsigned long env[7];
+	struct _fpxreg *to;
+	struct _fpreg __user *from;
+	int i;
+
+	if (copy_from_user( env, buf, 7 * sizeof(long)))
+		return 1;
+
+	fxsave->cwd = (unsigned short)(env[0] & 0xffff);
+	fxsave->swd = (unsigned short)(env[1] & 0xffff);
+	fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff));
+	fxsave->fip = env[3];
+	fxsave->fop = (unsigned short)((env[4] & 0xffff0000ul) >> 16);
+	fxsave->fcs = (env[4] & 0xffff);
+	fxsave->foo = env[5];
+	fxsave->fos = env[6];
+
+	to = (struct _fpxreg *) &fxsave->st_space[0];
+	from = &buf->_st[0];
+	for (i = 0; i < 8; i++, to++, from++) {
+		unsigned long *t = (unsigned long *)to;
+		unsigned long __user *f = (unsigned long __user *)from;
+
+		if (__get_user(*t, f) ||
+		    __get_user(*(t + 1), f + 1) ||
+		    __get_user(to->exponent, &from->exponent))
+			return 1;
+	}
+	return 0;
+}
+
+extern int have_fpx_regs;
+
+#endif
+
+static int copy_sc_from_user(struct pt_regs *regs,
+			     struct sigcontext __user *from)
+{
+	struct sigcontext sc;
+	int err, pid;
+
+	err = copy_from_user(&sc, from, sizeof(sc));
+	if (err)
+		return err;
+
+#define GETREG(regno, regname) regs->regs.gp[HOST_##regno] = sc.regname
+
+#ifdef CONFIG_X86_32
+	GETREG(GS, gs);
+	GETREG(FS, fs);
+	GETREG(ES, es);
+	GETREG(DS, ds);
+#endif
+	GETREG(DI, di);
+	GETREG(SI, si);
+	GETREG(BP, bp);
+	GETREG(SP, sp);
+	GETREG(BX, bx);
+	GETREG(DX, dx);
+	GETREG(CX, cx);
+	GETREG(AX, ax);
+	GETREG(IP, ip);
+
+#ifdef CONFIG_X86_64
+	GETREG(R8, r8);
+	GETREG(R9, r9);
+	GETREG(R10, r10);
+	GETREG(R11, r11);
+	GETREG(R12, r12);
+	GETREG(R13, r13);
+	GETREG(R14, r14);
+	GETREG(R15, r15);
+#endif
+
+	GETREG(CS, cs);
+	GETREG(EFLAGS, flags);
+#ifdef CONFIG_X86_32
+	GETREG(SS, ss);
+#endif
+
+#undef GETREG
+
+	pid = userspace_pid[current_thread_info()->cpu];
+#ifdef CONFIG_X86_32
+	if (have_fpx_regs) {
+		struct user_fxsr_struct fpx;
+
+		err = copy_from_user(&fpx,
+			&((struct _fpstate __user *)sc.fpstate)->_fxsr_env[0],
+				     sizeof(struct user_fxsr_struct));
+		if (err)
+			return 1;
+
+		err = convert_fxsr_from_user(&fpx, sc.fpstate);
+		if (err)
+			return 1;
+
+		err = restore_fpx_registers(pid, (unsigned long *) &fpx);
+		if (err < 0) {
+			printk(KERN_ERR "copy_sc_from_user - "
+			       "restore_fpx_registers failed, errno = %d\n",
+			       -err);
+			return 1;
+		}
+	} else
+#endif
+	{
+		struct user_i387_struct fp;
+
+		err = copy_from_user(&fp, sc.fpstate,
+				     sizeof(struct user_i387_struct));
+		if (err)
+			return 1;
+
+		err = restore_fp_registers(pid, (unsigned long *) &fp);
+		if (err < 0) {
+			printk(KERN_ERR "copy_sc_from_user - "
+			       "restore_fp_registers failed, errno = %d\n",
+			       -err);
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static int copy_sc_to_user(struct sigcontext __user *to,
+			   struct _fpstate __user *to_fp, struct pt_regs *regs,
+			   unsigned long mask)
+{
+	struct sigcontext sc;
+	struct faultinfo * fi = &current->thread.arch.faultinfo;
+	int err, pid;
+	memset(&sc, 0, sizeof(struct sigcontext));
+
+#define PUTREG(regno, regname) sc.regname = regs->regs.gp[HOST_##regno]
+
+#ifdef CONFIG_X86_32
+	PUTREG(GS, gs);
+	PUTREG(FS, fs);
+	PUTREG(ES, es);
+	PUTREG(DS, ds);
+#endif
+	PUTREG(DI, di);
+	PUTREG(SI, si);
+	PUTREG(BP, bp);
+	PUTREG(SP, sp);
+	PUTREG(BX, bx);
+	PUTREG(DX, dx);
+	PUTREG(CX, cx);
+	PUTREG(AX, ax);
+#ifdef CONFIG_X86_64
+	PUTREG(R8, r8);
+	PUTREG(R9, r9);
+	PUTREG(R10, r10);
+	PUTREG(R11, r11);
+	PUTREG(R12, r12);
+	PUTREG(R13, r13);
+	PUTREG(R14, r14);
+	PUTREG(R15, r15);
+#endif
+
+	sc.cr2 = fi->cr2;
+	sc.err = fi->error_code;
+	sc.trapno = fi->trap_no;
+	PUTREG(IP, ip);
+	PUTREG(CS, cs);
+	PUTREG(EFLAGS, flags);
+#ifdef CONFIG_X86_32
+	PUTREG(SP, sp_at_signal);
+	PUTREG(SS, ss);
+#endif
+#undef PUTREG
+	sc.oldmask = mask;
+	sc.fpstate = to_fp;
+
+	err = copy_to_user(to, &sc, sizeof(struct sigcontext));
+	if (err)
+		return 1;
+
+	pid = userspace_pid[current_thread_info()->cpu];
+
+#ifdef CONFIG_X86_32
+	if (have_fpx_regs) {
+		struct user_fxsr_struct fpx;
+
+		err = save_fpx_registers(pid, (unsigned long *) &fpx);
+		if (err < 0){
+			printk(KERN_ERR "copy_sc_to_user - save_fpx_registers "
+			       "failed, errno = %d\n", err);
+			return 1;
+		}
+
+		err = convert_fxsr_to_user(to_fp, &fpx);
+		if (err)
+			return 1;
+
+		err |= __put_user(fpx.swd, &to_fp->status);
+		err |= __put_user(X86_FXSR_MAGIC, &to_fp->magic);
+		if (err)
+			return 1;
+
+		if (copy_to_user(&to_fp->_fxsr_env[0], &fpx,
+				 sizeof(struct user_fxsr_struct)))
+			return 1;
+	} else
+#endif
+	{
+		struct user_i387_struct fp;
+
+		err = save_fp_registers(pid, (unsigned long *) &fp);
+		if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct)))
+			return 1;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_X86_32
+static int copy_ucontext_to_user(struct ucontext __user *uc,
+				 struct _fpstate __user *fp, sigset_t *set,
+				 unsigned long sp)
+{
+	int err = 0;
+
+	err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp);
+	err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags);
+	err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size);
+	err |= copy_sc_to_user(&uc->uc_mcontext, fp, &current->thread.regs, 0);
+	err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set));
+	return err;
+}
+
+struct sigframe
+{
+	char __user *pretcode;
+	int sig;
+	struct sigcontext sc;
+	struct _fpstate fpstate;
+	unsigned long extramask[_NSIG_WORDS-1];
+	char retcode[8];
+};
+
+struct rt_sigframe
+{
+	char __user *pretcode;
+	int sig;
+	struct siginfo __user *pinfo;
+	void __user *puc;
+	struct siginfo info;
+	struct ucontext uc;
+	struct _fpstate fpstate;
+	char retcode[8];
+};
+
+int setup_signal_stack_sc(unsigned long stack_top, int sig,
+			  struct k_sigaction *ka, struct pt_regs *regs,
+			  sigset_t *mask)
+{
+	struct sigframe __user *frame;
+	void __user *restorer;
+	int err = 0;
+
+	/* This is the same calculation as i386 - ((sp + 4) & 15) == 0 */
+	stack_top = ((stack_top + 4) & -16UL) - 4;
+	frame = (struct sigframe __user *) stack_top - 1;
+	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+		return 1;
+
+	restorer = frame->retcode;
+	if (ka->sa.sa_flags & SA_RESTORER)
+		restorer = ka->sa.sa_restorer;
+
+	err |= __put_user(restorer, &frame->pretcode);
+	err |= __put_user(sig, &frame->sig);
+	err |= copy_sc_to_user(&frame->sc, &frame->fpstate, regs, mask->sig[0]);
+	if (_NSIG_WORDS > 1)
+		err |= __copy_to_user(&frame->extramask, &mask->sig[1],
+				      sizeof(frame->extramask));
+
+	/*
+	 * This is popl %eax ; movl $,%eax ; int $0x80
+	 *
+	 * WE DO NOT USE IT ANY MORE! It's only left here for historical
+	 * reasons and because gdb uses it as a signature to notice
+	 * signal handler stack frames.
+	 */
+	err |= __put_user(0xb858, (short __user *)(frame->retcode+0));
+	err |= __put_user(__NR_sigreturn, (int __user *)(frame->retcode+2));
+	err |= __put_user(0x80cd, (short __user *)(frame->retcode+6));
+
+	if (err)
+		return err;
+
+	PT_REGS_SP(regs) = (unsigned long) frame;
+	PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
+	PT_REGS_EAX(regs) = (unsigned long) sig;
+	PT_REGS_EDX(regs) = (unsigned long) 0;
+	PT_REGS_ECX(regs) = (unsigned long) 0;
+
+	if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
+		ptrace_notify(SIGTRAP);
+	return 0;
+}
+
+int setup_signal_stack_si(unsigned long stack_top, int sig,
+			  struct k_sigaction *ka, struct pt_regs *regs,
+			  siginfo_t *info, sigset_t *mask)
+{
+	struct rt_sigframe __user *frame;
+	void __user *restorer;
+	int err = 0;
+
+	stack_top &= -8UL;
+	frame = (struct rt_sigframe __user *) stack_top - 1;
+	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+		return 1;
+
+	restorer = frame->retcode;
+	if (ka->sa.sa_flags & SA_RESTORER)
+		restorer = ka->sa.sa_restorer;
+
+	err |= __put_user(restorer, &frame->pretcode);
+	err |= __put_user(sig, &frame->sig);
+	err |= __put_user(&frame->info, &frame->pinfo);
+	err |= __put_user(&frame->uc, &frame->puc);
+	err |= copy_siginfo_to_user(&frame->info, info);
+	err |= copy_ucontext_to_user(&frame->uc, &frame->fpstate, mask,
+					PT_REGS_SP(regs));
+
+	/*
+	 * This is movl $,%eax ; int $0x80
+	 *
+	 * WE DO NOT USE IT ANY MORE! It's only left here for historical
+	 * reasons and because gdb uses it as a signature to notice
+	 * signal handler stack frames.
+	 */
+	err |= __put_user(0xb8, (char __user *)(frame->retcode+0));
+	err |= __put_user(__NR_rt_sigreturn, (int __user *)(frame->retcode+1));
+	err |= __put_user(0x80cd, (short __user *)(frame->retcode+5));
+
+	if (err)
+		return err;
+
+	PT_REGS_SP(regs) = (unsigned long) frame;
+	PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
+	PT_REGS_EAX(regs) = (unsigned long) sig;
+	PT_REGS_EDX(regs) = (unsigned long) &frame->info;
+	PT_REGS_ECX(regs) = (unsigned long) &frame->uc;
+
+	if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
+		ptrace_notify(SIGTRAP);
+	return 0;
+}
+
+long sys_sigreturn(struct pt_regs *regs)
+{
+	unsigned long sp = PT_REGS_SP(&current->thread.regs);
+	struct sigframe __user *frame = (struct sigframe __user *)(sp - 8);
+	sigset_t set;
+	struct sigcontext __user *sc = &frame->sc;
+	unsigned long __user *oldmask = &sc->oldmask;
+	unsigned long __user *extramask = frame->extramask;
+	int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
+
+	if (copy_from_user(&set.sig[0], oldmask, sizeof(set.sig[0])) ||
+	    copy_from_user(&set.sig[1], extramask, sig_size))
+		goto segfault;
+
+	sigdelsetmask(&set, ~_BLOCKABLE);
+	set_current_blocked(&set);
+
+	if (copy_sc_from_user(&current->thread.regs, sc))
+		goto segfault;
+
+	/* Avoid ERESTART handling */
+	PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
+	return PT_REGS_SYSCALL_RET(&current->thread.regs);
+
+ segfault:
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+#else
+
+struct rt_sigframe
+{
+	char __user *pretcode;
+	struct ucontext uc;
+	struct siginfo info;
+	struct _fpstate fpstate;
+};
+
+int setup_signal_stack_si(unsigned long stack_top, int sig,
+			  struct k_sigaction *ka, struct pt_regs * regs,
+			  siginfo_t *info, sigset_t *set)
+{
+	struct rt_sigframe __user *frame;
+	int err = 0;
+	struct task_struct *me = current;
+
+	frame = (struct rt_sigframe __user *)
+		round_down(stack_top - sizeof(struct rt_sigframe), 16);
+	/* Subtract 128 for a red zone and 8 for proper alignment */
+	frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8);
+
+	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+		goto out;
+
+	if (ka->sa.sa_flags & SA_SIGINFO) {
+		err |= copy_siginfo_to_user(&frame->info, info);
+		if (err)
+			goto out;
+	}
+
+	/* Create the ucontext.  */
+	err |= __put_user(0, &frame->uc.uc_flags);
+	err |= __put_user(0, &frame->uc.uc_link);
+	err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+	err |= __put_user(sas_ss_flags(PT_REGS_SP(regs)),
+			  &frame->uc.uc_stack.ss_flags);
+	err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size);
+	err |= copy_sc_to_user(&frame->uc.uc_mcontext, &frame->fpstate, regs,
+			       set->sig[0]);
+	err |= __put_user(&frame->fpstate, &frame->uc.uc_mcontext.fpstate);
+	if (sizeof(*set) == 16) {
+		__put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]);
+		__put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]);
+	}
+	else
+		err |= __copy_to_user(&frame->uc.uc_sigmask, set,
+				      sizeof(*set));
+
+	/*
+	 * Set up to return from userspace.  If provided, use a stub
+	 * already in userspace.
+	 */
+	/* x86-64 should always use SA_RESTORER. */
+	if (ka->sa.sa_flags & SA_RESTORER)
+		err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
+	else
+		/* could use a vstub here */
+		return err;
+
+	if (err)
+		return err;
+
+	/* Set up registers for signal handler */
+	{
+		struct exec_domain *ed = current_thread_info()->exec_domain;
+		if (unlikely(ed && ed->signal_invmap && sig < 32))
+			sig = ed->signal_invmap[sig];
+	}
+
+	PT_REGS_SP(regs) = (unsigned long) frame;
+	PT_REGS_RDI(regs) = sig;
+	/* In case the signal handler was declared without prototypes */
+	PT_REGS_RAX(regs) = 0;
+
+	/*
+	 * This also works for non SA_SIGINFO handlers because they expect the
+	 * next argument after the signal number on the stack.
+	 */
+	PT_REGS_RSI(regs) = (unsigned long) &frame->info;
+	PT_REGS_RDX(regs) = (unsigned long) &frame->uc;
+	PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler;
+ out:
+	return err;
+}
+#endif
+
+long sys_rt_sigreturn(struct pt_regs *regs)
+{
+	unsigned long sp = PT_REGS_SP(&current->thread.regs);
+	struct rt_sigframe __user *frame =
+		(struct rt_sigframe __user *)(sp - sizeof(long));
+	struct ucontext __user *uc = &frame->uc;
+	sigset_t set;
+
+	if (copy_from_user(&set, &uc->uc_sigmask, sizeof(set)))
+		goto segfault;
+
+	sigdelsetmask(&set, ~_BLOCKABLE);
+	set_current_blocked(&set);
+
+	if (copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext))
+		goto segfault;
+
+	/* Avoid ERESTART handling */
+	PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
+	return PT_REGS_SYSCALL_RET(&current->thread.regs);
+
+ segfault:
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+#ifdef CONFIG_X86_32
+long ptregs_sigreturn(void)
+{
+	return sys_sigreturn(NULL);
+}
+long ptregs_rt_sigreturn(void)
+{
+	return sys_rt_sigreturn(NULL);
+}
+#endif
diff --git a/arch/x86/um/stub_32.S b/arch/x86/um/stub_32.S
new file mode 100644
index 0000000..54a36ec
--- /dev/null
+++ b/arch/x86/um/stub_32.S
@@ -0,0 +1,51 @@
+#include "as-layout.h"
+
+	.globl syscall_stub
+.section .__syscall_stub, "ax"
+
+	.globl batch_syscall_stub
+batch_syscall_stub:
+	/* load pointer to first operation */
+	mov	$(STUB_DATA+8), %esp
+
+again:
+	/* load length of additional data */
+	mov	0x0(%esp), %eax
+
+	/* if(length == 0) : end of list */
+	/* write possible 0 to header */
+	mov	%eax, STUB_DATA+4
+	cmpl	$0, %eax
+	jz	done
+
+	/* save current pointer */
+	mov	%esp, STUB_DATA+4
+
+	/* skip additional data */
+	add	%eax, %esp
+
+	/* load syscall-# */
+	pop	%eax
+
+	/* load syscall params */
+	pop	%ebx
+	pop	%ecx
+	pop	%edx
+	pop	%esi
+ 	pop	%edi
+	pop	%ebp
+
+	/* execute syscall */
+	int	$0x80
+
+	/* check return value */
+	pop	%ebx
+	cmp	%ebx, %eax
+	je	again
+
+done:
+	/* save return value */
+	mov	%eax, STUB_DATA
+
+	/* stop */
+	int3
diff --git a/arch/x86/um/stub_64.S b/arch/x86/um/stub_64.S
new file mode 100644
index 0000000..20e4a96
--- /dev/null
+++ b/arch/x86/um/stub_64.S
@@ -0,0 +1,66 @@
+#include "as-layout.h"
+
+	.globl syscall_stub
+.section .__syscall_stub, "ax"
+syscall_stub:
+	syscall
+	/* We don't have 64-bit constants, so this constructs the address
+	 * we need.
+	 */
+	movq	$(STUB_DATA >> 32), %rbx
+	salq	$32, %rbx
+	movq	$(STUB_DATA & 0xffffffff), %rcx
+	or	%rcx, %rbx
+	movq	%rax, (%rbx)
+	int3
+
+	.globl batch_syscall_stub
+batch_syscall_stub:
+	mov	$(STUB_DATA >> 32), %rbx
+	sal	$32, %rbx
+	mov	$(STUB_DATA & 0xffffffff), %rax
+	or	%rax, %rbx
+	/* load pointer to first operation */
+	mov	%rbx, %rsp
+	add	$0x10, %rsp
+again:
+	/* load length of additional data */
+	mov	0x0(%rsp), %rax
+
+	/* if(length == 0) : end of list */
+	/* write possible 0 to header */
+	mov	%rax, 8(%rbx)
+	cmp	$0, %rax
+	jz	done
+
+	/* save current pointer */
+	mov	%rsp, 8(%rbx)
+
+	/* skip additional data */
+	add	%rax, %rsp
+
+	/* load syscall-# */
+	pop	%rax
+
+	/* load syscall params */
+	pop	%rdi
+	pop	%rsi
+	pop	%rdx
+	pop	%r10
+ 	pop	%r8
+	pop	%r9
+
+	/* execute syscall */
+	syscall
+
+	/* check return value */
+	pop	%rcx
+	cmp	%rcx, %rax
+	je	again
+
+done:
+	/* save return value */
+	mov	%rax, (%rbx)
+
+	/* stop */
+	int3
diff --git a/arch/x86/um/stub_segv.c b/arch/x86/um/stub_segv.c
new file mode 100644
index 0000000..b7450bd
--- /dev/null
+++ b/arch/x86/um/stub_segv.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
+#include "sysdep/stub.h"
+#include "sysdep/faultinfo.h"
+#include "sysdep/mcontext.h"
+
+void __attribute__ ((__section__ (".__syscall_stub")))
+stub_segv_handler(int sig, siginfo_t *info, void *p)
+{
+	struct ucontext *uc = p;
+
+	GET_FAULTINFO_FROM_MC(*((struct faultinfo *) STUB_DATA),
+			      &uc->uc_mcontext);
+	trap_myself();
+}
+
diff --git a/arch/x86/um/sys_call_table_32.S b/arch/x86/um/sys_call_table_32.S
new file mode 100644
index 0000000..a7ca80d
--- /dev/null
+++ b/arch/x86/um/sys_call_table_32.S
@@ -0,0 +1,26 @@
+#include <linux/linkage.h>
+/* Steal i386 syscall table for our purposes, but with some slight changes.*/
+
+#define sys_iopl sys_ni_syscall
+#define sys_ioperm sys_ni_syscall
+
+#define sys_vm86old sys_ni_syscall
+#define sys_vm86 sys_ni_syscall
+
+#define old_mmap sys_old_mmap
+
+#define ptregs_fork sys_fork
+#define ptregs_execve sys_execve
+#define ptregs_iopl sys_iopl
+#define ptregs_vm86old sys_vm86old
+#define ptregs_clone sys_clone
+#define ptregs_vm86 sys_vm86
+#define ptregs_sigaltstack sys_sigaltstack
+#define ptregs_vfork sys_vfork
+
+.section .rodata,"a"
+
+#include "../kernel/syscall_table_32.S"
+
+ENTRY(syscall_table_size)
+.long .-sys_call_table
diff --git a/arch/x86/um/sys_call_table_64.c b/arch/x86/um/sys_call_table_64.c
new file mode 100644
index 0000000..99522f7
--- /dev/null
+++ b/arch/x86/um/sys_call_table_64.c
@@ -0,0 +1,64 @@
+/*
+ * System call table for UML/x86-64, copied from arch/x86_64/kernel/syscall.c
+ * with some changes for UML.
+ */
+
+#include <linux/linkage.h>
+#include <linux/sys.h>
+#include <linux/cache.h>
+
+#define __NO_STUBS
+
+/*
+ * Below you can see, in terms of #define's, the differences between the x86-64
+ * and the UML syscall table.
+ */
+
+/* Not going to be implemented by UML, since we have no hardware. */
+#define stub_iopl sys_ni_syscall
+#define sys_ioperm sys_ni_syscall
+
+/*
+ * The UML TLS problem. Note that x86_64 does not implement this, so the below
+ * is needed only for the ia32 compatibility.
+ */
+
+/* On UML we call it this way ("old" means it's not mmap2) */
+#define sys_mmap old_mmap
+
+#define stub_clone sys_clone
+#define stub_fork sys_fork
+#define stub_vfork sys_vfork
+#define stub_execve sys_execve
+#define stub_rt_sigsuspend sys_rt_sigsuspend
+#define stub_sigaltstack sys_sigaltstack
+#define stub_rt_sigreturn sys_rt_sigreturn
+
+#define __SYSCALL(nr, sym) extern asmlinkage void sym(void) ;
+#undef _ASM_X86_UNISTD_64_H
+#include "../../x86/include/asm/unistd_64.h"
+
+#undef __SYSCALL
+#define __SYSCALL(nr, sym) [ nr ] = sym,
+#undef _ASM_X86_UNISTD_64_H
+
+typedef void (*sys_call_ptr_t)(void);
+
+extern void sys_ni_syscall(void);
+
+/*
+ * We used to have a trick here which made sure that holes in the
+ * x86_64 table were filled in with sys_ni_syscall, but a comment in
+ * unistd_64.h says that holes aren't allowed, so the trick was
+ * removed.
+ * The trick looked like this
+ *	[0 ... UM_NR_syscall_max] = &sys_ni_syscall
+ * before including unistd_64.h - the later initializations overwrote
+ * the sys_ni_syscall filler.
+ */
+
+sys_call_ptr_t sys_call_table[] __cacheline_aligned = {
+#include <asm/unistd_64.h>
+};
+
+int syscall_table_size = sizeof(sys_call_table);
diff --git a/arch/x86/um/syscalls_32.c b/arch/x86/um/syscalls_32.c
new file mode 100644
index 0000000..70ca357
--- /dev/null
+++ b/arch/x86/um/syscalls_32.c
@@ -0,0 +1,66 @@
+/* 
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/sched.h"
+#include "linux/shm.h"
+#include "linux/ipc.h"
+#include "linux/syscalls.h"
+#include "asm/mman.h"
+#include "asm/uaccess.h"
+#include "asm/unistd.h"
+
+/*
+ * The prototype on i386 is:
+ *
+ *     int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls, int * child_tidptr)
+ *
+ * and the "newtls" arg. on i386 is read by copy_thread directly from the
+ * register saved on the stack.
+ */
+long sys_clone(unsigned long clone_flags, unsigned long newsp,
+	       int __user *parent_tid, void *newtls, int __user *child_tid)
+{
+	long ret;
+
+	if (!newsp)
+		newsp = UPT_SP(&current->thread.regs.regs);
+
+	current->thread.forking = 1;
+	ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
+		      child_tid);
+	current->thread.forking = 0;
+	return ret;
+}
+
+long sys_sigaction(int sig, const struct old_sigaction __user *act,
+			 struct old_sigaction __user *oact)
+{
+	struct k_sigaction new_ka, old_ka;
+	int ret;
+
+	if (act) {
+		old_sigset_t mask;
+		if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
+		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
+		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
+			return -EFAULT;
+		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
+		__get_user(mask, &act->sa_mask);
+		siginitset(&new_ka.sa.sa_mask, mask);
+	}
+
+	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+	if (!ret && oact) {
+		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
+		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
+		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
+			return -EFAULT;
+		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+	}
+
+	return ret;
+}
diff --git a/arch/x86/um/syscalls_64.c b/arch/x86/um/syscalls_64.c
new file mode 100644
index 0000000..f3d82bb
--- /dev/null
+++ b/arch/x86/um/syscalls_64.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#include "linux/linkage.h"
+#include "linux/personality.h"
+#include "linux/utsname.h"
+#include "asm/prctl.h" /* XXX This should get the constants from libc */
+#include "asm/uaccess.h"
+#include "os.h"
+
+long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
+{
+	unsigned long *ptr = addr, tmp;
+	long ret;
+	int pid = task->mm->context.id.u.pid;
+
+	/*
+	 * With ARCH_SET_FS (and ARCH_SET_GS is treated similarly to
+	 * be safe), we need to call arch_prctl on the host because
+	 * setting %fs may result in something else happening (like a
+	 * GDT or thread.fs being set instead).  So, we let the host
+	 * fiddle the registers and thread struct and restore the
+	 * registers afterwards.
+	 *
+	 * So, the saved registers are stored to the process (this
+	 * needed because a stub may have been the last thing to run),
+	 * arch_prctl is run on the host, then the registers are read
+	 * back.
+	 */
+	switch (code) {
+	case ARCH_SET_FS:
+	case ARCH_SET_GS:
+		ret = restore_registers(pid, &current->thread.regs.regs);
+		if (ret)
+			return ret;
+		break;
+	case ARCH_GET_FS:
+	case ARCH_GET_GS:
+		/*
+		 * With these two, we read to a local pointer and
+		 * put_user it to the userspace pointer that we were
+		 * given.  If addr isn't valid (because it hasn't been
+		 * faulted in or is just bogus), we want put_user to
+		 * fault it in (or return -EFAULT) instead of having
+		 * the host return -EFAULT.
+		 */
+		ptr = &tmp;
+	}
+
+	ret = os_arch_prctl(pid, code, ptr);
+	if (ret)
+		return ret;
+
+	switch (code) {
+	case ARCH_SET_FS:
+		current->thread.arch.fs = (unsigned long) ptr;
+		ret = save_registers(pid, &current->thread.regs.regs);
+		break;
+	case ARCH_SET_GS:
+		ret = save_registers(pid, &current->thread.regs.regs);
+		break;
+	case ARCH_GET_FS:
+		ret = put_user(tmp, addr);
+		break;
+	case ARCH_GET_GS:
+		ret = put_user(tmp, addr);
+		break;
+	}
+
+	return ret;
+}
+
+long sys_arch_prctl(int code, unsigned long addr)
+{
+	return arch_prctl(current, code, (unsigned long __user *) addr);
+}
+
+long sys_clone(unsigned long clone_flags, unsigned long newsp,
+	       void __user *parent_tid, void __user *child_tid)
+{
+	long ret;
+
+	if (!newsp)
+		newsp = UPT_SP(&current->thread.regs.regs);
+	current->thread.forking = 1;
+	ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
+		      child_tid);
+	current->thread.forking = 0;
+	return ret;
+}
+
+void arch_switch_to(struct task_struct *to)
+{
+	if ((to->thread.arch.fs == 0) || (to->mm == NULL))
+		return;
+
+	arch_prctl(to, ARCH_SET_FS, (void __user *) to->thread.arch.fs);
+}
diff --git a/arch/x86/um/sysrq_32.c b/arch/x86/um/sysrq_32.c
new file mode 100644
index 0000000..171b3e9
--- /dev/null
+++ b/arch/x86/um/sysrq_32.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/kernel.h"
+#include "linux/smp.h"
+#include "linux/sched.h"
+#include "linux/kallsyms.h"
+#include "asm/ptrace.h"
+#include "sysrq.h"
+
+/* This is declared by <linux/sched.h> */
+void show_regs(struct pt_regs *regs)
+{
+        printk("\n");
+        printk("EIP: %04lx:[<%08lx>] CPU: %d %s", 
+	       0xffff & PT_REGS_CS(regs), PT_REGS_IP(regs),
+	       smp_processor_id(), print_tainted());
+        if (PT_REGS_CS(regs) & 3)
+                printk(" ESP: %04lx:%08lx", 0xffff & PT_REGS_SS(regs),
+		       PT_REGS_SP(regs));
+        printk(" EFLAGS: %08lx\n    %s\n", PT_REGS_EFLAGS(regs),
+	       print_tainted());
+        printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
+                PT_REGS_EAX(regs), PT_REGS_EBX(regs), 
+	       PT_REGS_ECX(regs), 
+	       PT_REGS_EDX(regs));
+        printk("ESI: %08lx EDI: %08lx EBP: %08lx",
+	       PT_REGS_ESI(regs), PT_REGS_EDI(regs), 
+	       PT_REGS_EBP(regs));
+        printk(" DS: %04lx ES: %04lx\n",
+	       0xffff & PT_REGS_DS(regs), 
+	       0xffff & PT_REGS_ES(regs));
+
+        show_trace(NULL, (unsigned long *) &regs);
+}
+
+/* Copied from i386. */
+static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
+{
+	return	p > (void *)tinfo &&
+		p < (void *)tinfo + THREAD_SIZE - 3;
+}
+
+/* Adapted from i386 (we also print the address we read from). */
+static inline unsigned long print_context_stack(struct thread_info *tinfo,
+				unsigned long *stack, unsigned long ebp)
+{
+	unsigned long addr;
+
+#ifdef CONFIG_FRAME_POINTER
+	while (valid_stack_ptr(tinfo, (void *)ebp)) {
+		addr = *(unsigned long *)(ebp + 4);
+		printk("%08lx:  [<%08lx>]", ebp + 4, addr);
+		print_symbol(" %s", addr);
+		printk("\n");
+		ebp = *(unsigned long *)ebp;
+	}
+#else
+	while (valid_stack_ptr(tinfo, stack)) {
+		addr = *stack;
+		if (__kernel_text_address(addr)) {
+			printk("%08lx:  [<%08lx>]", (unsigned long) stack, addr);
+			print_symbol(" %s", addr);
+			printk("\n");
+		}
+		stack++;
+	}
+#endif
+	return ebp;
+}
+
+void show_trace(struct task_struct* task, unsigned long * stack)
+{
+	unsigned long ebp;
+	struct thread_info *context;
+
+	/* Turn this into BUG_ON if possible. */
+	if (!stack) {
+		stack = (unsigned long*) &stack;
+		printk("show_trace: got NULL stack, implicit assumption task == current");
+		WARN_ON(1);
+	}
+
+	if (!task)
+		task = current;
+
+	if (task != current) {
+		ebp = (unsigned long) KSTK_EBP(task);
+	} else {
+		asm ("movl %%ebp, %0" : "=r" (ebp) : );
+	}
+
+	context = (struct thread_info *)
+		((unsigned long)stack & (~(THREAD_SIZE - 1)));
+	print_context_stack(context, stack, ebp);
+
+	printk("\n");
+}
+
diff --git a/arch/x86/um/sysrq_64.c b/arch/x86/um/sysrq_64.c
new file mode 100644
index 0000000..e891343
--- /dev/null
+++ b/arch/x86/um/sysrq_64.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2003 PathScale, Inc.
+ *
+ * Licensed under the GPL
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/utsname.h>
+#include <asm/current.h>
+#include <asm/ptrace.h>
+#include "sysrq.h"
+
+void __show_regs(struct pt_regs *regs)
+{
+	printk("\n");
+	print_modules();
+	printk(KERN_INFO "Pid: %d, comm: %.20s %s %s\n", task_pid_nr(current),
+		current->comm, print_tainted(), init_utsname()->release);
+	printk(KERN_INFO "RIP: %04lx:[<%016lx>]\n", PT_REGS_CS(regs) & 0xffff,
+	       PT_REGS_RIP(regs));
+	printk(KERN_INFO "RSP: %016lx  EFLAGS: %08lx\n", PT_REGS_SP(regs),
+	       PT_REGS_EFLAGS(regs));
+	printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n",
+	       PT_REGS_RAX(regs), PT_REGS_RBX(regs), PT_REGS_RCX(regs));
+	printk(KERN_INFO "RDX: %016lx RSI: %016lx RDI: %016lx\n",
+	       PT_REGS_RDX(regs), PT_REGS_RSI(regs), PT_REGS_RDI(regs));
+	printk(KERN_INFO "RBP: %016lx R08: %016lx R09: %016lx\n",
+	       PT_REGS_RBP(regs), PT_REGS_R8(regs), PT_REGS_R9(regs));
+	printk(KERN_INFO "R10: %016lx R11: %016lx R12: %016lx\n",
+	       PT_REGS_R10(regs), PT_REGS_R11(regs), PT_REGS_R12(regs));
+	printk(KERN_INFO "R13: %016lx R14: %016lx R15: %016lx\n",
+	       PT_REGS_R13(regs), PT_REGS_R14(regs), PT_REGS_R15(regs));
+}
+
+void show_regs(struct pt_regs *regs)
+{
+	__show_regs(regs);
+	show_trace(current, (unsigned long *) &regs);
+}
diff --git a/arch/x86/um/tls_32.c b/arch/x86/um/tls_32.c
new file mode 100644
index 0000000..c6c7131
--- /dev/null
+++ b/arch/x86/um/tls_32.c
@@ -0,0 +1,396 @@
+/*
+ * Copyright (C) 2005 Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
+ * Licensed under the GPL
+ */
+
+#include "linux/percpu.h"
+#include "linux/sched.h"
+#include "asm/uaccess.h"
+#include "os.h"
+#include "skas.h"
+#include "sysdep/tls.h"
+
+/*
+ * If needed we can detect when it's uninitialized.
+ *
+ * These are initialized in an initcall and unchanged thereafter.
+ */
+static int host_supports_tls = -1;
+int host_gdt_entry_tls_min;
+
+int do_set_thread_area(struct user_desc *info)
+{
+	int ret;
+	u32 cpu;
+
+	cpu = get_cpu();
+	ret = os_set_thread_area(info, userspace_pid[cpu]);
+	put_cpu();
+
+	if (ret)
+		printk(KERN_ERR "PTRACE_SET_THREAD_AREA failed, err = %d, "
+		       "index = %d\n", ret, info->entry_number);
+
+	return ret;
+}
+
+int do_get_thread_area(struct user_desc *info)
+{
+	int ret;
+	u32 cpu;
+
+	cpu = get_cpu();
+	ret = os_get_thread_area(info, userspace_pid[cpu]);
+	put_cpu();
+
+	if (ret)
+		printk(KERN_ERR "PTRACE_GET_THREAD_AREA failed, err = %d, "
+		       "index = %d\n", ret, info->entry_number);
+
+	return ret;
+}
+
+/*
+ * sys_get_thread_area: get a yet unused TLS descriptor index.
+ * XXX: Consider leaving one free slot for glibc usage at first place. This must
+ * be done here (and by changing GDT_ENTRY_TLS_* macros) and nowhere else.
+ *
+ * Also, this must be tested when compiling in SKAS mode with dynamic linking
+ * and running against NPTL.
+ */
+static int get_free_idx(struct task_struct* task)
+{
+	struct thread_struct *t = &task->thread;
+	int idx;
+
+	if (!t->arch.tls_array)
+		return GDT_ENTRY_TLS_MIN;
+
+	for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++)
+		if (!t->arch.tls_array[idx].present)
+			return idx + GDT_ENTRY_TLS_MIN;
+	return -ESRCH;
+}
+
+static inline void clear_user_desc(struct user_desc* info)
+{
+	/* Postcondition: LDT_empty(info) returns true. */
+	memset(info, 0, sizeof(*info));
+
+	/*
+	 * Check the LDT_empty or the i386 sys_get_thread_area code - we obtain
+	 * indeed an empty user_desc.
+	 */
+	info->read_exec_only = 1;
+	info->seg_not_present = 1;
+}
+
+#define O_FORCE 1
+
+static int load_TLS(int flags, struct task_struct *to)
+{
+	int ret = 0;
+	int idx;
+
+	for (idx = GDT_ENTRY_TLS_MIN; idx < GDT_ENTRY_TLS_MAX; idx++) {
+		struct uml_tls_struct* curr =
+			&to->thread.arch.tls_array[idx - GDT_ENTRY_TLS_MIN];
+
+		/*
+		 * Actually, now if it wasn't flushed it gets cleared and
+		 * flushed to the host, which will clear it.
+		 */
+		if (!curr->present) {
+			if (!curr->flushed) {
+				clear_user_desc(&curr->tls);
+				curr->tls.entry_number = idx;
+			} else {
+				WARN_ON(!LDT_empty(&curr->tls));
+				continue;
+			}
+		}
+
+		if (!(flags & O_FORCE) && curr->flushed)
+			continue;
+
+		ret = do_set_thread_area(&curr->tls);
+		if (ret)
+			goto out;
+
+		curr->flushed = 1;
+	}
+out:
+	return ret;
+}
+
+/*
+ * Verify if we need to do a flush for the new process, i.e. if there are any
+ * present desc's, only if they haven't been flushed.
+ */
+static inline int needs_TLS_update(struct task_struct *task)
+{
+	int i;
+	int ret = 0;
+
+	for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) {
+		struct uml_tls_struct* curr =
+			&task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN];
+
+		/*
+		 * Can't test curr->present, we may need to clear a descriptor
+		 * which had a value.
+		 */
+		if (curr->flushed)
+			continue;
+		ret = 1;
+		break;
+	}
+	return ret;
+}
+
+/*
+ * On a newly forked process, the TLS descriptors haven't yet been flushed. So
+ * we mark them as such and the first switch_to will do the job.
+ */
+void clear_flushed_tls(struct task_struct *task)
+{
+	int i;
+
+	for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) {
+		struct uml_tls_struct* curr =
+			&task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN];
+
+		/*
+		 * Still correct to do this, if it wasn't present on the host it
+		 * will remain as flushed as it was.
+		 */
+		if (!curr->present)
+			continue;
+
+		curr->flushed = 0;
+	}
+}
+
+/*
+ * In SKAS0 mode, currently, multiple guest threads sharing the same ->mm have a
+ * common host process. So this is needed in SKAS0 too.
+ *
+ * However, if each thread had a different host process (and this was discussed
+ * for SMP support) this won't be needed.
+ *
+ * And this will not need be used when (and if) we'll add support to the host
+ * SKAS patch.
+ */
+
+int arch_switch_tls(struct task_struct *to)
+{
+	if (!host_supports_tls)
+		return 0;
+
+	/*
+	 * We have no need whatsoever to switch TLS for kernel threads; beyond
+	 * that, that would also result in us calling os_set_thread_area with
+	 * userspace_pid[cpu] == 0, which gives an error.
+	 */
+	if (likely(to->mm))
+		return load_TLS(O_FORCE, to);
+
+	return 0;
+}
+
+static int set_tls_entry(struct task_struct* task, struct user_desc *info,
+			 int idx, int flushed)
+{
+	struct thread_struct *t = &task->thread;
+
+	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
+		return -EINVAL;
+
+	t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].tls = *info;
+	t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].present = 1;
+	t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed = flushed;
+
+	return 0;
+}
+
+int arch_copy_tls(struct task_struct *new)
+{
+	struct user_desc info;
+	int idx, ret = -EFAULT;
+
+	if (copy_from_user(&info,
+			   (void __user *) UPT_ESI(&new->thread.regs.regs),
+			   sizeof(info)))
+		goto out;
+
+	ret = -EINVAL;
+	if (LDT_empty(&info))
+		goto out;
+
+	idx = info.entry_number;
+
+	ret = set_tls_entry(new, &info, idx, 0);
+out:
+	return ret;
+}
+
+/* XXX: use do_get_thread_area to read the host value? I'm not at all sure! */
+static int get_tls_entry(struct task_struct *task, struct user_desc *info,
+			 int idx)
+{
+	struct thread_struct *t = &task->thread;
+
+	if (!t->arch.tls_array)
+		goto clear;
+
+	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
+		return -EINVAL;
+
+	if (!t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].present)
+		goto clear;
+
+	*info = t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].tls;
+
+out:
+	/*
+	 * Temporary debugging check, to make sure that things have been
+	 * flushed. This could be triggered if load_TLS() failed.
+	 */
+	if (unlikely(task == current &&
+		     !t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed)) {
+		printk(KERN_ERR "get_tls_entry: task with pid %d got here "
+				"without flushed TLS.", current->pid);
+	}
+
+	return 0;
+clear:
+	/*
+	 * When the TLS entry has not been set, the values read to user in the
+	 * tls_array are 0 (because it's cleared at boot, see
+	 * arch/i386/kernel/head.S:cpu_gdt_table). Emulate that.
+	 */
+	clear_user_desc(info);
+	info->entry_number = idx;
+	goto out;
+}
+
+int sys_set_thread_area(struct user_desc __user *user_desc)
+{
+	struct user_desc info;
+	int idx, ret;
+
+	if (!host_supports_tls)
+		return -ENOSYS;
+
+	if (copy_from_user(&info, user_desc, sizeof(info)))
+		return -EFAULT;
+
+	idx = info.entry_number;
+
+	if (idx == -1) {
+		idx = get_free_idx(current);
+		if (idx < 0)
+			return idx;
+		info.entry_number = idx;
+		/* Tell the user which slot we chose for him.*/
+		if (put_user(idx, &user_desc->entry_number))
+			return -EFAULT;
+	}
+
+	ret = do_set_thread_area(&info);
+	if (ret)
+		return ret;
+	return set_tls_entry(current, &info, idx, 1);
+}
+
+/*
+ * Perform set_thread_area on behalf of the traced child.
+ * Note: error handling is not done on the deferred load, and this differ from
+ * i386. However the only possible error are caused by bugs.
+ */
+int ptrace_set_thread_area(struct task_struct *child, int idx,
+			   struct user_desc __user *user_desc)
+{
+	struct user_desc info;
+
+	if (!host_supports_tls)
+		return -EIO;
+
+	if (copy_from_user(&info, user_desc, sizeof(info)))
+		return -EFAULT;
+
+	return set_tls_entry(child, &info, idx, 0);
+}
+
+int sys_get_thread_area(struct user_desc __user *user_desc)
+{
+	struct user_desc info;
+	int idx, ret;
+
+	if (!host_supports_tls)
+		return -ENOSYS;
+
+	if (get_user(idx, &user_desc->entry_number))
+		return -EFAULT;
+
+	ret = get_tls_entry(current, &info, idx);
+	if (ret < 0)
+		goto out;
+
+	if (copy_to_user(user_desc, &info, sizeof(info)))
+		ret = -EFAULT;
+
+out:
+	return ret;
+}
+
+/*
+ * Perform get_thread_area on behalf of the traced child.
+ */
+int ptrace_get_thread_area(struct task_struct *child, int idx,
+		struct user_desc __user *user_desc)
+{
+	struct user_desc info;
+	int ret;
+
+	if (!host_supports_tls)
+		return -EIO;
+
+	ret = get_tls_entry(child, &info, idx);
+	if (ret < 0)
+		goto out;
+
+	if (copy_to_user(user_desc, &info, sizeof(info)))
+		ret = -EFAULT;
+out:
+	return ret;
+}
+
+/*
+ * This code is really i386-only, but it detects and logs x86_64 GDT indexes
+ * if a 32-bit UML is running on a 64-bit host.
+ */
+static int __init __setup_host_supports_tls(void)
+{
+	check_host_supports_tls(&host_supports_tls, &host_gdt_entry_tls_min);
+	if (host_supports_tls) {
+		printk(KERN_INFO "Host TLS support detected\n");
+		printk(KERN_INFO "Detected host type: ");
+		switch (host_gdt_entry_tls_min) {
+		case GDT_ENTRY_TLS_MIN_I386:
+			printk(KERN_CONT "i386");
+			break;
+		case GDT_ENTRY_TLS_MIN_X86_64:
+			printk(KERN_CONT "x86_64");
+			break;
+		}
+		printk(KERN_CONT " (GDT indexes %d to %d)\n",
+		       host_gdt_entry_tls_min,
+		       host_gdt_entry_tls_min + GDT_ENTRY_TLS_ENTRIES);
+	} else
+		printk(KERN_ERR "  Host TLS support NOT detected! "
+				"TLS support inside UML will not work\n");
+	return 0;
+}
+
+__initcall(__setup_host_supports_tls);
diff --git a/arch/x86/um/tls_64.c b/arch/x86/um/tls_64.c
new file mode 100644
index 0000000..f7ba462
--- /dev/null
+++ b/arch/x86/um/tls_64.c
@@ -0,0 +1,17 @@
+#include "linux/sched.h"
+
+void clear_flushed_tls(struct task_struct *task)
+{
+}
+
+int arch_copy_tls(struct task_struct *t)
+{
+	/*
+	 * If CLONE_SETTLS is set, we need to save the thread id
+	 * (which is argument 5, child_tid, of clone) so it can be set
+	 * during context switches.
+	 */
+	t->thread.arch.fs = t->thread.regs.regs.gp[R8 / sizeof(long)];
+
+	return 0;
+}
diff --git a/arch/x86/um/user-offsets.c b/arch/x86/um/user-offsets.c
new file mode 100644
index 0000000..ca49be8
--- /dev/null
+++ b/arch/x86/um/user-offsets.c
@@ -0,0 +1,80 @@
+#include <stdio.h>
+#include <stddef.h>
+#include <signal.h>
+#include <sys/poll.h>
+#include <sys/mman.h>
+#include <sys/user.h>
+#define __FRAME_OFFSETS
+#include <asm/ptrace.h>
+#include <asm/types.h>
+
+#define DEFINE(sym, val) \
+	asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+#define DEFINE_LONGS(sym, val) \
+	asm volatile("\n->" #sym " %0 " #val : : "i" (val/sizeof(unsigned long)))
+
+void foo(void)
+{
+#ifdef __i386__
+	DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_fpregs_struct));
+	DEFINE_LONGS(HOST_FPX_SIZE, sizeof(struct user_fpxregs_struct));
+
+	DEFINE(HOST_IP, EIP);
+	DEFINE(HOST_SP, UESP);
+	DEFINE(HOST_EFLAGS, EFL);
+	DEFINE(HOST_AX, EAX);
+	DEFINE(HOST_BX, EBX);
+	DEFINE(HOST_CX, ECX);
+	DEFINE(HOST_DX, EDX);
+	DEFINE(HOST_SI, ESI);
+	DEFINE(HOST_DI, EDI);
+	DEFINE(HOST_BP, EBP);
+	DEFINE(HOST_CS, CS);
+	DEFINE(HOST_SS, SS);
+	DEFINE(HOST_DS, DS);
+	DEFINE(HOST_FS, FS);
+	DEFINE(HOST_ES, ES);
+	DEFINE(HOST_GS, GS);
+	DEFINE(HOST_ORIG_AX, ORIG_EAX);
+#else
+	DEFINE(HOST_FP_SIZE, sizeof(struct _fpstate) / sizeof(unsigned long));
+	DEFINE_LONGS(HOST_BX, RBX);
+	DEFINE_LONGS(HOST_CX, RCX);
+	DEFINE_LONGS(HOST_DI, RDI);
+	DEFINE_LONGS(HOST_SI, RSI);
+	DEFINE_LONGS(HOST_DX, RDX);
+	DEFINE_LONGS(HOST_BP, RBP);
+	DEFINE_LONGS(HOST_AX, RAX);
+	DEFINE_LONGS(HOST_R8, R8);
+	DEFINE_LONGS(HOST_R9, R9);
+	DEFINE_LONGS(HOST_R10, R10);
+	DEFINE_LONGS(HOST_R11, R11);
+	DEFINE_LONGS(HOST_R12, R12);
+	DEFINE_LONGS(HOST_R13, R13);
+	DEFINE_LONGS(HOST_R14, R14);
+	DEFINE_LONGS(HOST_R15, R15);
+	DEFINE_LONGS(HOST_ORIG_AX, ORIG_RAX);
+	DEFINE_LONGS(HOST_CS, CS);
+	DEFINE_LONGS(HOST_SS, SS);
+	DEFINE_LONGS(HOST_EFLAGS, EFLAGS);
+#if 0
+	DEFINE_LONGS(HOST_FS, FS);
+	DEFINE_LONGS(HOST_GS, GS);
+	DEFINE_LONGS(HOST_DS, DS);
+	DEFINE_LONGS(HOST_ES, ES);
+#endif
+
+	DEFINE_LONGS(HOST_IP, RIP);
+	DEFINE_LONGS(HOST_SP, RSP);
+#endif
+
+	DEFINE(UM_FRAME_SIZE, sizeof(struct user_regs_struct));
+	DEFINE(UM_POLLIN, POLLIN);
+	DEFINE(UM_POLLPRI, POLLPRI);
+	DEFINE(UM_POLLOUT, POLLOUT);
+
+	DEFINE(UM_PROT_READ, PROT_READ);
+	DEFINE(UM_PROT_WRITE, PROT_WRITE);
+	DEFINE(UM_PROT_EXEC, PROT_EXEC);
+}
diff --git a/arch/x86/um/vdso/Makefile b/arch/x86/um/vdso/Makefile
new file mode 100644
index 0000000..6c803ca
--- /dev/null
+++ b/arch/x86/um/vdso/Makefile
@@ -0,0 +1,90 @@
+#
+# Building vDSO images for x86.
+#
+
+VDSO64-y		:= y
+
+vdso-install-$(VDSO64-y)	+= vdso.so
+
+
+# files to link into the vdso
+vobjs-y := vdso-note.o um_vdso.o
+
+# files to link into kernel
+obj-$(VDSO64-y)			+= vdso.o vma.o
+
+vobjs := $(foreach F,$(vobjs-y),$(obj)/$F)
+
+$(obj)/vdso.o: $(obj)/vdso.so
+
+targets += vdso.so vdso.so.dbg vdso.lds $(vobjs-y)
+
+export CPPFLAGS_vdso.lds += -P -C
+
+VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
+       -Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
+
+$(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so
+
+$(obj)/vdso.so.dbg: $(src)/vdso.lds $(vobjs) FORCE
+	$(call if_changed,vdso)
+
+$(obj)/%.so: OBJCOPYFLAGS := -S
+$(obj)/%.so: $(obj)/%.so.dbg FORCE
+	$(call if_changed,objcopy)
+
+#
+# Don't omit frame pointers for ease of userspace debugging, but do
+# optimize sibling calls.
+#
+CFL := $(PROFILING) -mcmodel=small -fPIC -O2 -fasynchronous-unwind-tables -m64 \
+       $(filter -g%,$(KBUILD_CFLAGS)) $(call cc-option, -fno-stack-protector) \
+       -fno-omit-frame-pointer -foptimize-sibling-calls
+
+$(vobjs): KBUILD_CFLAGS += $(CFL)
+
+#
+# vDSO code runs in userspace and -pg doesn't help with profiling anyway.
+#
+CFLAGS_REMOVE_vdso-note.o = -pg -fprofile-arcs -ftest-coverage
+CFLAGS_REMOVE_um_vdso.o = -pg -fprofile-arcs -ftest-coverage
+
+targets += vdso-syms.lds
+obj-$(VDSO64-y)			+= vdso-syms.lds
+
+#
+# Match symbols in the DSO that look like VDSO*; produce a file of constants.
+#
+sed-vdsosym := -e 's/^00*/0/' \
+	-e 's/^\([0-9a-fA-F]*\) . \(VDSO[a-zA-Z0-9_]*\)$$/\2 = 0x\1;/p'
+quiet_cmd_vdsosym = VDSOSYM $@
+define cmd_vdsosym
+	$(NM) $< | LC_ALL=C sed -n $(sed-vdsosym) | LC_ALL=C sort > $@
+endef
+
+$(obj)/%-syms.lds: $(obj)/%.so.dbg FORCE
+	$(call if_changed,vdsosym)
+
+#
+# The DSO images are built using a special linker script.
+#
+quiet_cmd_vdso = VDSO    $@
+      cmd_vdso = $(CC) -nostdlib -o $@ \
+		       $(VDSO_LDFLAGS) $(VDSO_LDFLAGS_$(filter %.lds,$(^F))) \
+		       -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) && \
+		 sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@'
+
+VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
+GCOV_PROFILE := n
+
+#
+# Install the unstripped copy of vdso*.so listed in $(vdso-install-y).
+#
+quiet_cmd_vdso_install = INSTALL $@
+      cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
+$(vdso-install-y): %.so: $(obj)/%.so.dbg FORCE
+	@mkdir -p $(MODLIB)/vdso
+	$(call cmd,vdso_install)
+
+PHONY += vdso_install $(vdso-install-y)
+vdso_install: $(vdso-install-y)
diff --git a/arch/x86/um/vdso/checkundef.sh b/arch/x86/um/vdso/checkundef.sh
new file mode 100644
index 0000000..7ee90a9
--- /dev/null
+++ b/arch/x86/um/vdso/checkundef.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+nm="$1"
+file="$2"
+$nm "$file" | grep '^ *U' > /dev/null 2>&1
+if [ $? -eq 1 ]; then
+    exit 0
+else
+    echo "$file: undefined symbols found" >&2
+    exit 1
+fi
diff --git a/arch/x86/um/vdso/um_vdso.c b/arch/x86/um/vdso/um_vdso.c
new file mode 100644
index 0000000..7c441b5
--- /dev/null
+++ b/arch/x86/um/vdso/um_vdso.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This vDSO turns all calls into a syscall so that UML can trap them.
+ */
+
+
+/* Disable profiling for userspace code */
+#define DISABLE_BRANCH_PROFILING
+
+#include <linux/time.h>
+#include <linux/getcpu.h>
+#include <asm/unistd.h>
+
+int __vdso_clock_gettime(clockid_t clock, struct timespec *ts)
+{
+	long ret;
+
+	asm("syscall" : "=a" (ret) :
+		"0" (__NR_clock_gettime), "D" (clock), "S" (ts) : "memory");
+
+	return ret;
+}
+int clock_gettime(clockid_t, struct timespec *)
+	__attribute__((weak, alias("__vdso_clock_gettime")));
+
+int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
+{
+	long ret;
+
+	asm("syscall" : "=a" (ret) :
+		"0" (__NR_gettimeofday), "D" (tv), "S" (tz) : "memory");
+
+	return ret;
+}
+int gettimeofday(struct timeval *, struct timezone *)
+	__attribute__((weak, alias("__vdso_gettimeofday")));
+
+time_t __vdso_time(time_t *t)
+{
+	long secs;
+
+	asm volatile("syscall"
+		: "=a" (secs)
+		: "0" (__NR_time), "D" (t) : "cc", "r11", "cx", "memory");
+
+	return secs;
+}
+int time(time_t *t) __attribute__((weak, alias("__vdso_time")));
+
+long
+__vdso_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *unused)
+{
+	/*
+	 * UML does not support SMP, we can cheat here. :)
+	 */
+
+	if (cpu)
+		*cpu = 0;
+	if (node)
+		*node = 0;
+
+	return 0;
+}
+
+long getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache)
+	__attribute__((weak, alias("__vdso_getcpu")));
diff --git a/arch/x86/um/vdso/vdso-layout.lds.S b/arch/x86/um/vdso/vdso-layout.lds.S
new file mode 100644
index 0000000..634a2cf
--- /dev/null
+++ b/arch/x86/um/vdso/vdso-layout.lds.S
@@ -0,0 +1,64 @@
+/*
+ * Linker script for vDSO.  This is an ELF shared object prelinked to
+ * its virtual address, and with only one read-only segment.
+ * This script controls its layout.
+ */
+
+SECTIONS
+{
+	. = VDSO_PRELINK + SIZEOF_HEADERS;
+
+	.hash		: { *(.hash) }			:text
+	.gnu.hash	: { *(.gnu.hash) }
+	.dynsym		: { *(.dynsym) }
+	.dynstr		: { *(.dynstr) }
+	.gnu.version	: { *(.gnu.version) }
+	.gnu.version_d	: { *(.gnu.version_d) }
+	.gnu.version_r	: { *(.gnu.version_r) }
+
+	.note		: { *(.note.*) }		:text	:note
+
+	.eh_frame_hdr	: { *(.eh_frame_hdr) }		:text	:eh_frame_hdr
+	.eh_frame	: { KEEP (*(.eh_frame)) }	:text
+
+	.dynamic	: { *(.dynamic) }		:text	:dynamic
+
+	.rodata		: { *(.rodata*) }		:text
+	.data		: {
+	      *(.data*)
+	      *(.sdata*)
+	      *(.got.plt) *(.got)
+	      *(.gnu.linkonce.d.*)
+	      *(.bss*)
+	      *(.dynbss*)
+	      *(.gnu.linkonce.b.*)
+	}
+
+	.altinstructions	: { *(.altinstructions) }
+	.altinstr_replacement	: { *(.altinstr_replacement) }
+
+	/*
+	 * Align the actual code well away from the non-instruction data.
+	 * This is the best thing for the I-cache.
+	 */
+	. = ALIGN(0x100);
+
+	.text		: { *(.text*) }			:text	=0x90909090
+}
+
+/*
+ * Very old versions of ld do not recognize this name token; use the constant.
+ */
+#define PT_GNU_EH_FRAME	0x6474e550
+
+/*
+ * We must supply the ELF program headers explicitly to get just one
+ * PT_LOAD segment, and set the flags explicitly to make segments read-only.
+ */
+PHDRS
+{
+	text		PT_LOAD		FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */
+	dynamic		PT_DYNAMIC	FLAGS(4);		/* PF_R */
+	note		PT_NOTE		FLAGS(4);		/* PF_R */
+	eh_frame_hdr	PT_GNU_EH_FRAME;
+}
diff --git a/arch/x86/um/vdso/vdso-note.S b/arch/x86/um/vdso/vdso-note.S
new file mode 100644
index 0000000..79a071e
--- /dev/null
+++ b/arch/x86/um/vdso/vdso-note.S
@@ -0,0 +1,12 @@
+/*
+ * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text.
+ * Here we can supply some information useful to userland.
+ */
+
+#include <linux/uts.h>
+#include <linux/version.h>
+#include <linux/elfnote.h>
+
+ELFNOTE_START(Linux, 0, "a")
+	.long LINUX_VERSION_CODE
+ELFNOTE_END
diff --git a/arch/x86/um/vdso/vdso.S b/arch/x86/um/vdso/vdso.S
new file mode 100644
index 0000000..1cb468a
--- /dev/null
+++ b/arch/x86/um/vdso/vdso.S
@@ -0,0 +1,10 @@
+#include <linux/init.h>
+
+__INITDATA
+
+	.globl vdso_start, vdso_end
+vdso_start:
+	.incbin "arch/x86/um/vdso/vdso.so"
+vdso_end:
+
+__FINIT
diff --git a/arch/x86/um/vdso/vdso.lds.S b/arch/x86/um/vdso/vdso.lds.S
new file mode 100644
index 0000000..b96b267
--- /dev/null
+++ b/arch/x86/um/vdso/vdso.lds.S
@@ -0,0 +1,32 @@
+/*
+ * Linker script for 64-bit vDSO.
+ * We #include the file to define the layout details.
+ * Here we only choose the prelinked virtual address.
+ *
+ * This file defines the version script giving the user-exported symbols in
+ * the DSO.  We can define local symbols here called VDSO* to make their
+ * values visible using the asm-x86/vdso.h macros from the kernel proper.
+ */
+
+#define VDSO_PRELINK 0xffffffffff700000
+#include "vdso-layout.lds.S"
+
+/*
+ * This controls what userland symbols we export from the vDSO.
+ */
+VERSION {
+	LINUX_2.6 {
+	global:
+		clock_gettime;
+		__vdso_clock_gettime;
+		gettimeofday;
+		__vdso_gettimeofday;
+		getcpu;
+		__vdso_getcpu;
+		time;
+		__vdso_time;
+	local: *;
+	};
+}
+
+VDSO64_PRELINK = VDSO_PRELINK;
diff --git a/arch/x86/um/vdso/vma.c b/arch/x86/um/vdso/vma.c
new file mode 100644
index 0000000..91f4ec9
--- /dev/null
+++ b/arch/x86/um/vdso/vma.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2011 Richard Weinberger <richrd@nod.at>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <linux/init.h>
+
+unsigned int __read_mostly vdso_enabled = 1;
+unsigned long um_vdso_addr;
+
+extern unsigned long task_size;
+extern char vdso_start[], vdso_end[];
+
+static struct page **vdsop;
+
+static int __init init_vdso(void)
+{
+	struct page *um_vdso;
+
+	BUG_ON(vdso_end - vdso_start > PAGE_SIZE);
+
+	um_vdso_addr = task_size - PAGE_SIZE;
+
+	vdsop = kmalloc(sizeof(struct page *), GFP_KERNEL);
+	if (!vdsop)
+		goto oom;
+
+	um_vdso = alloc_page(GFP_KERNEL);
+	if (!um_vdso) {
+		kfree(vdsop);
+
+		goto oom;
+	}
+
+	copy_page(page_address(um_vdso), vdso_start);
+	*vdsop = um_vdso;
+
+	return 0;
+
+oom:
+	printk(KERN_ERR "Cannot allocate vdso\n");
+	vdso_enabled = 0;
+
+	return -ENOMEM;
+}
+subsys_initcall(init_vdso);
+
+int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
+{
+	int err;
+	struct mm_struct *mm = current->mm;
+
+	if (!vdso_enabled)
+		return 0;
+
+	down_write(&mm->mmap_sem);
+
+	err = install_special_mapping(mm, um_vdso_addr, PAGE_SIZE,
+		VM_READ|VM_EXEC|
+		VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
+		VM_ALWAYSDUMP,
+		vdsop);
+
+	up_write(&mm->mmap_sem);
+
+	return err;
+}
diff --git a/crypto/Kconfig b/crypto/Kconfig
index ae27b753..527a857 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -100,6 +100,14 @@ config CRYPTO_MANAGER2
 	select CRYPTO_BLKCIPHER2
 	select CRYPTO_PCOMP2
 
+config CRYPTO_USER
+	tristate "Userspace cryptographic algorithm configuration"
+	depends on NET
+	select CRYPTO_MANAGER
+	help
+	  Userapace configuration for cryptographic instantiations such as
+	  cbc(aes).
+
 config CRYPTO_MANAGER_DISABLE_TESTS
 	bool "Disable run-time self tests"
 	default y
@@ -407,6 +415,16 @@ config CRYPTO_SHA1
 	help
 	  SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
 
+config CRYPTO_SHA1_SSSE3
+	tristate "SHA1 digest algorithm (SSSE3/AVX)"
+	depends on X86 && 64BIT
+	select CRYPTO_SHA1
+	select CRYPTO_HASH
+	help
+	  SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2) implemented
+	  using Supplemental SSE3 (SSSE3) instructions or Advanced Vector
+	  Extensions (AVX), when available.
+
 config CRYPTO_SHA256
 	tristate "SHA224 and SHA256 digest algorithm"
 	select CRYPTO_HASH
@@ -590,6 +608,7 @@ config CRYPTO_ARC4
 config CRYPTO_BLOWFISH
 	tristate "Blowfish cipher algorithm"
 	select CRYPTO_ALGAPI
+	select CRYPTO_BLOWFISH_COMMON
 	help
 	  Blowfish cipher algorithm, by Bruce Schneier.
 
@@ -600,6 +619,30 @@ config CRYPTO_BLOWFISH
 	  See also:
 	  <http://www.schneier.com/blowfish.html>
 
+config CRYPTO_BLOWFISH_COMMON
+	tristate
+	help
+	  Common parts of the Blowfish cipher algorithm shared by the
+	  generic c and the assembler implementations.
+
+	  See also:
+	  <http://www.schneier.com/blowfish.html>
+
+config CRYPTO_BLOWFISH_X86_64
+	tristate "Blowfish cipher algorithm (x86_64)"
+	depends on (X86 || UML_X86) && 64BIT
+	select CRYPTO_ALGAPI
+	select CRYPTO_BLOWFISH_COMMON
+	help
+	  Blowfish cipher algorithm (x86_64), by Bruce Schneier.
+
+	  This is a variable key length cipher which can use keys from 32
+	  bits to 448 bits in length.  It's fast, simple and specifically
+	  designed for use on "large microprocessors".
+
+	  See also:
+	  <http://www.schneier.com/blowfish.html>
+
 config CRYPTO_CAMELLIA
 	tristate "Camellia cipher algorithms"
 	depends on CRYPTO
@@ -793,6 +836,26 @@ config CRYPTO_TWOFISH_X86_64
 	  See also:
 	  <http://www.schneier.com/twofish.html>
 
+config CRYPTO_TWOFISH_X86_64_3WAY
+	tristate "Twofish cipher algorithm (x86_64, 3-way parallel)"
+	depends on (X86 || UML_X86) && 64BIT
+	select CRYPTO_ALGAPI
+	select CRYPTO_TWOFISH_COMMON
+	select CRYPTO_TWOFISH_X86_64
+	help
+	  Twofish cipher algorithm (x86_64, 3-way parallel).
+
+	  Twofish was submitted as an AES (Advanced Encryption Standard)
+	  candidate cipher by researchers at CounterPane Systems.  It is a
+	  16 round block cipher supporting key sizes of 128, 192, and 256
+	  bits.
+
+	  This module provides Twofish cipher algorithm that processes three
+	  blocks parallel, utilizing resources of out-of-order CPUs better.
+
+	  See also:
+	  <http://www.schneier.com/twofish.html>
+
 comment "Compression"
 
 config CRYPTO_DEFLATE
diff --git a/crypto/Makefile b/crypto/Makefile
index ce5a813..9e6eee2 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_CRYPTO_PCOMP2) += pcompress.o
 cryptomgr-y := algboss.o testmgr.o
 
 obj-$(CONFIG_CRYPTO_MANAGER2) += cryptomgr.o
+obj-$(CONFIG_CRYPTO_USER) += crypto_user.o
 obj-$(CONFIG_CRYPTO_HMAC) += hmac.o
 obj-$(CONFIG_CRYPTO_VMAC) += vmac.o
 obj-$(CONFIG_CRYPTO_XCBC) += xcbc.o
@@ -60,7 +61,8 @@ obj-$(CONFIG_CRYPTO_PCRYPT) += pcrypt.o
 obj-$(CONFIG_CRYPTO_CRYPTD) += cryptd.o
 obj-$(CONFIG_CRYPTO_DES) += des_generic.o
 obj-$(CONFIG_CRYPTO_FCRYPT) += fcrypt.o
-obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o
+obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish_generic.o
+obj-$(CONFIG_CRYPTO_BLOWFISH_COMMON) += blowfish_common.o
 obj-$(CONFIG_CRYPTO_TWOFISH) += twofish_generic.o
 obj-$(CONFIG_CRYPTO_TWOFISH_COMMON) += twofish_common.o
 obj-$(CONFIG_CRYPTO_SERPENT) += serpent.o
diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c
index fdc67d3..a816f24 100644
--- a/crypto/ablkcipher.c
+++ b/crypto/ablkcipher.c
@@ -23,6 +23,8 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/seq_file.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
 
 #include <crypto/scatterwalk.h>
 
@@ -381,6 +383,28 @@ static int crypto_init_ablkcipher_ops(struct crypto_tfm *tfm, u32 type,
 	return 0;
 }
 
+static int crypto_ablkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_blkcipher rblkcipher;
+
+	snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "ablkcipher");
+	snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s",
+		 alg->cra_ablkcipher.geniv ?: "<default>");
+
+	rblkcipher.blocksize = alg->cra_blocksize;
+	rblkcipher.min_keysize = alg->cra_ablkcipher.min_keysize;
+	rblkcipher.max_keysize = alg->cra_ablkcipher.max_keysize;
+	rblkcipher.ivsize = alg->cra_ablkcipher.ivsize;
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_BLKCIPHER,
+		sizeof(struct crypto_report_blkcipher), &rblkcipher);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
 static void crypto_ablkcipher_show(struct seq_file *m, struct crypto_alg *alg)
 	__attribute__ ((unused));
 static void crypto_ablkcipher_show(struct seq_file *m, struct crypto_alg *alg)
@@ -403,6 +427,7 @@ const struct crypto_type crypto_ablkcipher_type = {
 #ifdef CONFIG_PROC_FS
 	.show = crypto_ablkcipher_show,
 #endif
+	.report = crypto_ablkcipher_report,
 };
 EXPORT_SYMBOL_GPL(crypto_ablkcipher_type);
 
@@ -432,6 +457,28 @@ static int crypto_init_givcipher_ops(struct crypto_tfm *tfm, u32 type,
 	return 0;
 }
 
+static int crypto_givcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_blkcipher rblkcipher;
+
+	snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "givcipher");
+	snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s",
+		 alg->cra_ablkcipher.geniv ?: "<built-in>");
+
+	rblkcipher.blocksize = alg->cra_blocksize;
+	rblkcipher.min_keysize = alg->cra_ablkcipher.min_keysize;
+	rblkcipher.max_keysize = alg->cra_ablkcipher.max_keysize;
+	rblkcipher.ivsize = alg->cra_ablkcipher.ivsize;
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_BLKCIPHER,
+		sizeof(struct crypto_report_blkcipher), &rblkcipher);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
 static void crypto_givcipher_show(struct seq_file *m, struct crypto_alg *alg)
 	__attribute__ ((unused));
 static void crypto_givcipher_show(struct seq_file *m, struct crypto_alg *alg)
@@ -454,6 +501,7 @@ const struct crypto_type crypto_givcipher_type = {
 #ifdef CONFIG_PROC_FS
 	.show = crypto_givcipher_show,
 #endif
+	.report = crypto_givcipher_report,
 };
 EXPORT_SYMBOL_GPL(crypto_givcipher_type);
 
diff --git a/crypto/aead.c b/crypto/aead.c
index 6729e8f..701556f 100644
--- a/crypto/aead.c
+++ b/crypto/aead.c
@@ -21,6 +21,8 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/seq_file.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
 
 #include "internal.h"
 
@@ -109,6 +111,28 @@ static int crypto_init_aead_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
 	return 0;
 }
 
+static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_aead raead;
+	struct aead_alg *aead = &alg->cra_aead;
+
+	snprintf(raead.type, CRYPTO_MAX_ALG_NAME, "%s", "aead");
+	snprintf(raead.geniv, CRYPTO_MAX_ALG_NAME, "%s",
+		 aead->geniv ?: "<built-in>");
+
+	raead.blocksize = alg->cra_blocksize;
+	raead.maxauthsize = aead->maxauthsize;
+	raead.ivsize = aead->ivsize;
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_AEAD,
+		sizeof(struct crypto_report_aead), &raead);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
 static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg)
 	__attribute__ ((unused));
 static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg)
@@ -130,6 +154,7 @@ const struct crypto_type crypto_aead_type = {
 #ifdef CONFIG_PROC_FS
 	.show = crypto_aead_show,
 #endif
+	.report = crypto_aead_report,
 };
 EXPORT_SYMBOL_GPL(crypto_aead_type);
 
@@ -165,6 +190,28 @@ static int crypto_init_nivaead_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
 	return 0;
 }
 
+static int crypto_nivaead_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_aead raead;
+	struct aead_alg *aead = &alg->cra_aead;
+
+	snprintf(raead.type, CRYPTO_MAX_ALG_NAME, "%s", "nivaead");
+	snprintf(raead.geniv, CRYPTO_MAX_ALG_NAME, "%s", aead->geniv);
+
+	raead.blocksize = alg->cra_blocksize;
+	raead.maxauthsize = aead->maxauthsize;
+	raead.ivsize = aead->ivsize;
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_AEAD,
+		sizeof(struct crypto_report_aead), &raead);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
+
 static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg)
 	__attribute__ ((unused));
 static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg)
@@ -186,6 +233,7 @@ const struct crypto_type crypto_nivaead_type = {
 #ifdef CONFIG_PROC_FS
 	.show = crypto_nivaead_show,
 #endif
+	.report = crypto_nivaead_report,
 };
 EXPORT_SYMBOL_GPL(crypto_nivaead_type);
 
diff --git a/crypto/ahash.c b/crypto/ahash.c
index f669822..a3e6ef9 100644
--- a/crypto/ahash.c
+++ b/crypto/ahash.c
@@ -21,6 +21,8 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/seq_file.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
 
 #include "internal.h"
 
@@ -397,6 +399,24 @@ static unsigned int crypto_ahash_extsize(struct crypto_alg *alg)
 	return sizeof(struct crypto_shash *);
 }
 
+static int crypto_ahash_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_hash rhash;
+
+	snprintf(rhash.type, CRYPTO_MAX_ALG_NAME, "%s", "ahash");
+
+	rhash.blocksize = alg->cra_blocksize;
+	rhash.digestsize = __crypto_hash_alg_common(alg)->digestsize;
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_HASH,
+		sizeof(struct crypto_report_hash), &rhash);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
 static void crypto_ahash_show(struct seq_file *m, struct crypto_alg *alg)
 	__attribute__ ((unused));
 static void crypto_ahash_show(struct seq_file *m, struct crypto_alg *alg)
@@ -415,6 +435,7 @@ const struct crypto_type crypto_ahash_type = {
 #ifdef CONFIG_PROC_FS
 	.show = crypto_ahash_show,
 #endif
+	.report = crypto_ahash_report,
 	.maskclear = ~CRYPTO_ALG_TYPE_MASK,
 	.maskset = CRYPTO_ALG_TYPE_AHASH_MASK,
 	.type = CRYPTO_ALG_TYPE_AHASH,
diff --git a/crypto/algapi.c b/crypto/algapi.c
index c3cf1a6..54dd4e3 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -22,8 +22,6 @@
 
 #include "internal.h"
 
-static void crypto_remove_final(struct list_head *list);
-
 static LIST_HEAD(crypto_template_list);
 
 void crypto_larval_error(const char *name, u32 type, u32 mask)
@@ -129,9 +127,8 @@ static void crypto_remove_spawn(struct crypto_spawn *spawn,
 	BUG_ON(!list_empty(&inst->alg.cra_users));
 }
 
-static void crypto_remove_spawns(struct crypto_alg *alg,
-				 struct list_head *list,
-				 struct crypto_alg *nalg)
+void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,
+			  struct crypto_alg *nalg)
 {
 	u32 new_type = (nalg ?: alg)->cra_flags;
 	struct crypto_spawn *spawn, *n;
@@ -177,6 +174,7 @@ static void crypto_remove_spawns(struct crypto_alg *alg,
 			crypto_remove_spawn(spawn, list);
 	}
 }
+EXPORT_SYMBOL_GPL(crypto_remove_spawns);
 
 static struct crypto_larval *__crypto_register_alg(struct crypto_alg *alg)
 {
@@ -321,7 +319,7 @@ unlock:
 }
 EXPORT_SYMBOL_GPL(crypto_alg_tested);
 
-static void crypto_remove_final(struct list_head *list)
+void crypto_remove_final(struct list_head *list)
 {
 	struct crypto_alg *alg;
 	struct crypto_alg *n;
@@ -331,6 +329,7 @@ static void crypto_remove_final(struct list_head *list)
 		crypto_alg_put(alg);
 	}
 }
+EXPORT_SYMBOL_GPL(crypto_remove_final);
 
 static void crypto_wait_for_test(struct crypto_larval *larval)
 {
@@ -493,6 +492,7 @@ int crypto_register_instance(struct crypto_template *tmpl,
 		goto err;
 
 	inst->alg.cra_module = tmpl->module;
+	inst->alg.cra_flags |= CRYPTO_ALG_INSTANCE;
 
 	down_write(&crypto_alg_sem);
 
diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c
index 7a72192..2572d26 100644
--- a/crypto/blkcipher.c
+++ b/crypto/blkcipher.c
@@ -24,6 +24,8 @@
 #include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
 
 #include "internal.h"
 
@@ -492,6 +494,28 @@ static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
 		return crypto_init_blkcipher_ops_async(tfm);
 }
 
+static int crypto_blkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_blkcipher rblkcipher;
+
+	snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "blkcipher");
+	snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s",
+		 alg->cra_blkcipher.geniv ?: "<default>");
+
+	rblkcipher.blocksize = alg->cra_blocksize;
+	rblkcipher.min_keysize = alg->cra_blkcipher.min_keysize;
+	rblkcipher.max_keysize = alg->cra_blkcipher.max_keysize;
+	rblkcipher.ivsize = alg->cra_blkcipher.ivsize;
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_BLKCIPHER,
+		sizeof(struct crypto_report_blkcipher), &rblkcipher);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
 static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg)
 	__attribute__ ((unused));
 static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg)
@@ -511,6 +535,7 @@ const struct crypto_type crypto_blkcipher_type = {
 #ifdef CONFIG_PROC_FS
 	.show = crypto_blkcipher_show,
 #endif
+	.report = crypto_blkcipher_report,
 };
 EXPORT_SYMBOL_GPL(crypto_blkcipher_type);
 
diff --git a/crypto/blowfish.c b/crypto/blowfish.c
deleted file mode 100644
index a67d52e..0000000
--- a/crypto/blowfish.c
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
- * Cryptographic API.
- *
- * Blowfish Cipher Algorithm, by Bruce Schneier.
- * http://www.counterpane.com/blowfish.html
- *
- * Adapted from Kerneli implementation.
- *
- * Copyright (c) Herbert Valerio Riedel <hvr@hvrlab.org>
- * Copyright (c) Kyle McMartin <kyle@debian.org>
- * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <asm/byteorder.h>
-#include <linux/crypto.h>
-#include <linux/types.h>
-
-#define BF_BLOCK_SIZE 8
-#define BF_MIN_KEY_SIZE 4
-#define BF_MAX_KEY_SIZE 56
-
-struct bf_ctx {
-	u32 p[18];
-	u32 s[1024];
-};
-
-static const u32 bf_pbox[16 + 2] = {
-	0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
-	0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
-	0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
-	0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
-	0x9216d5d9, 0x8979fb1b,
-};
-
-static const u32 bf_sbox[256 * 4] = {
-	0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
-	0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
-	0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
-	0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
-	0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
-	0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
-	0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
-	0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
-	0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
-	0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
-	0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
-	0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
-	0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
-	0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
-	0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
-	0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
-	0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
-	0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
-	0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
-	0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
-	0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
-	0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
-	0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
-	0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
-	0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
-	0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
-	0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
-	0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
-	0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
-	0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
-	0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
-	0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
-	0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
-	0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
-	0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
-	0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
-	0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
-	0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
-	0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
-	0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
-	0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
-	0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
-	0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
-	0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
-	0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
-	0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
-	0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
-	0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
-	0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
-	0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
-	0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
-	0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
-	0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
-	0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
-	0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
-	0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
-	0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
-	0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
-	0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
-	0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
-	0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
-	0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
-	0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
-	0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
-	0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
-	0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
-	0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
-	0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
-	0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
-	0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
-	0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
-	0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
-	0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
-	0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
-	0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
-	0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
-	0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
-	0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
-	0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
-	0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
-	0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
-	0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
-	0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
-	0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
-	0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
-	0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
-	0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
-	0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
-	0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
-	0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
-	0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
-	0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
-	0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
-	0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
-	0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
-	0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
-	0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
-	0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
-	0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
-	0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
-	0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
-	0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
-	0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
-	0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
-	0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
-	0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
-	0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
-	0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
-	0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
-	0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
-	0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
-	0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
-	0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
-	0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
-	0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
-	0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
-	0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
-	0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
-	0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
-	0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
-	0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
-	0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
-	0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
-	0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
-	0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
-	0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
-	0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
-	0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
-	0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
-	0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
-	0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
-	0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
-	0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
-	0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
-	0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
-	0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
-	0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
-	0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
-	0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
-	0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
-	0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
-	0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
-	0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
-	0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
-	0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
-	0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
-	0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
-	0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
-	0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
-	0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
-	0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
-	0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
-	0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
-	0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
-	0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
-	0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
-	0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
-	0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
-	0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
-	0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
-	0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
-	0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
-	0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
-	0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
-	0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
-	0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
-	0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
-	0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
-	0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
-	0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
-	0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
-	0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
-	0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
-	0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
-	0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
-	0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
-	0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
-	0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
-	0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
-	0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
-	0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
-	0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
-	0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
-	0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
-	0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
-	0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
-	0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
-	0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
-	0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
-	0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
-	0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
-	0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
-	0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
-	0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
-	0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
-	0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
-	0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
-	0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
-	0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
-	0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
-	0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
-	0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
-	0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
-	0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
-	0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
-	0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
-	0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
-	0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
-	0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
-	0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
-	0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
-	0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
-	0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
-	0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
-	0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
-	0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
-	0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
-	0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
-	0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
-	0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
-	0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
-	0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
-	0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
-	0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
-	0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
-	0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
-	0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
-	0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
-	0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
-	0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
-	0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
-	0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
-	0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
-	0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
-	0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
-	0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
-	0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
-	0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
-	0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
-	0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
-	0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
-	0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
-	0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
-	0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
-	0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
-	0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
-	0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
-	0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
-	0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
-	0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
-	0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
-	0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
-	0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
-	0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
-	0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
-	0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6,
-};
-
-/*
- * Round loop unrolling macros, S is a pointer to a S-Box array
- * organized in 4 unsigned longs at a row.
- */
-#define GET32_3(x) (((x) & 0xff))
-#define GET32_2(x) (((x) >> (8)) & (0xff))
-#define GET32_1(x) (((x) >> (16)) & (0xff))
-#define GET32_0(x) (((x) >> (24)) & (0xff))
-
-#define bf_F(x) (((S[GET32_0(x)] + S[256 + GET32_1(x)]) ^ \
-          S[512 + GET32_2(x)]) + S[768 + GET32_3(x)])
-
-#define ROUND(a, b, n)  b ^= P[n]; a ^= bf_F (b)
-
-/*
- * The blowfish encipher, processes 64-bit blocks.
- * NOTE: This function MUSTN'T respect endianess
- */
-static void encrypt_block(struct bf_ctx *bctx, u32 *dst, u32 *src)
-{
-	const u32 *P = bctx->p;
-	const u32 *S = bctx->s;
-	u32 yl = src[0];
-	u32 yr = src[1];
-
-	ROUND(yr, yl, 0);
-	ROUND(yl, yr, 1);
-	ROUND(yr, yl, 2);
-	ROUND(yl, yr, 3);
-	ROUND(yr, yl, 4);
-	ROUND(yl, yr, 5);
-	ROUND(yr, yl, 6);
-	ROUND(yl, yr, 7);
-	ROUND(yr, yl, 8);
-	ROUND(yl, yr, 9);
-	ROUND(yr, yl, 10);
-	ROUND(yl, yr, 11);
-	ROUND(yr, yl, 12);
-	ROUND(yl, yr, 13);
-	ROUND(yr, yl, 14);
-	ROUND(yl, yr, 15);
-
-	yl ^= P[16];
-	yr ^= P[17];
-
-	dst[0] = yr;
-	dst[1] = yl;
-}
-
-static void bf_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
-{
-	const __be32 *in_blk = (const __be32 *)src;
-	__be32 *const out_blk = (__be32 *)dst;
-	u32 in32[2], out32[2];
-
-	in32[0] = be32_to_cpu(in_blk[0]);
-	in32[1] = be32_to_cpu(in_blk[1]);
-	encrypt_block(crypto_tfm_ctx(tfm), out32, in32);
-	out_blk[0] = cpu_to_be32(out32[0]);
-	out_blk[1] = cpu_to_be32(out32[1]);
-}
-
-static void bf_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
-{
-	struct bf_ctx *ctx = crypto_tfm_ctx(tfm);
-	const __be32 *in_blk = (const __be32 *)src;
-	__be32 *const out_blk = (__be32 *)dst;
-	const u32 *P = ctx->p;
-	const u32 *S = ctx->s;
-	u32 yl = be32_to_cpu(in_blk[0]);
-	u32 yr = be32_to_cpu(in_blk[1]);
-
-	ROUND(yr, yl, 17);
-	ROUND(yl, yr, 16);
-	ROUND(yr, yl, 15);
-	ROUND(yl, yr, 14);
-	ROUND(yr, yl, 13);
-	ROUND(yl, yr, 12);
-	ROUND(yr, yl, 11);
-	ROUND(yl, yr, 10);
-	ROUND(yr, yl, 9);
-	ROUND(yl, yr, 8);
-	ROUND(yr, yl, 7);
-	ROUND(yl, yr, 6);
-	ROUND(yr, yl, 5);
-	ROUND(yl, yr, 4);
-	ROUND(yr, yl, 3);
-	ROUND(yl, yr, 2);
-
-	yl ^= P[1];
-	yr ^= P[0];
-
-	out_blk[0] = cpu_to_be32(yr);
-	out_blk[1] = cpu_to_be32(yl);
-}
-
-/*
- * Calculates the blowfish S and P boxes for encryption and decryption.
- */
-static int bf_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
-{
-	struct bf_ctx *ctx = crypto_tfm_ctx(tfm);
-	u32 *P = ctx->p;
-	u32 *S = ctx->s;
-	short i, j, count;
-	u32 data[2], temp;
-
-	/* Copy the initialization s-boxes */
-	for (i = 0, count = 0; i < 256; i++)
-		for (j = 0; j < 4; j++, count++)
-			S[count] = bf_sbox[count];
-
-	/* Set the p-boxes */
-	for (i = 0; i < 16 + 2; i++)
-		P[i] = bf_pbox[i];
-
-	/* Actual subkey generation */
-	for (j = 0, i = 0; i < 16 + 2; i++) {
-		temp = (((u32)key[j] << 24) |
-			((u32)key[(j + 1) % keylen] << 16) |
-			((u32)key[(j + 2) % keylen] << 8) |
-			((u32)key[(j + 3) % keylen]));
-
-		P[i] = P[i] ^ temp;
-		j = (j + 4) % keylen;
-	}
-
-	data[0] = 0x00000000;
-	data[1] = 0x00000000;
-
-	for (i = 0; i < 16 + 2; i += 2) {
-		encrypt_block((struct bf_ctx *)ctx, data, data);
-
-		P[i] = data[0];
-		P[i + 1] = data[1];
-	}
-
-	for (i = 0; i < 4; i++) {
-		for (j = 0, count = i * 256; j < 256; j += 2, count += 2) {
-			encrypt_block((struct bf_ctx *)ctx, data, data);
-
-			S[count] = data[0];
-			S[count + 1] = data[1];
-		}
-	}
-
-	/* Bruce says not to bother with the weak key check. */
-	return 0;
-}
-
-static struct crypto_alg alg = {
-	.cra_name		=	"blowfish",
-	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
-	.cra_blocksize		=	BF_BLOCK_SIZE,
-	.cra_ctxsize		=	sizeof(struct bf_ctx),
-	.cra_alignmask		=	3,
-	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(alg.cra_list),
-	.cra_u			=	{ .cipher = {
-	.cia_min_keysize	=	BF_MIN_KEY_SIZE,
-	.cia_max_keysize	=	BF_MAX_KEY_SIZE,
-	.cia_setkey   		= 	bf_setkey,
-	.cia_encrypt 		=	bf_encrypt,
-	.cia_decrypt  		=	bf_decrypt } }
-};
-
-static int __init blowfish_mod_init(void)
-{
-	return crypto_register_alg(&alg);
-}
-
-static void __exit blowfish_mod_fini(void)
-{
-	crypto_unregister_alg(&alg);
-}
-
-module_init(blowfish_mod_init);
-module_exit(blowfish_mod_fini);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Blowfish Cipher Algorithm");
diff --git a/crypto/blowfish_common.c b/crypto/blowfish_common.c
new file mode 100644
index 0000000..f636aab
--- /dev/null
+++ b/crypto/blowfish_common.c
@@ -0,0 +1,402 @@
+/*
+ * Cryptographic API.
+ *
+ * Common Blowfish algorithm parts shared between the c and assembler
+ * implementations.
+ *
+ * Blowfish Cipher Algorithm, by Bruce Schneier.
+ * http://www.counterpane.com/blowfish.html
+ *
+ * Adapted from Kerneli implementation.
+ *
+ * Copyright (c) Herbert Valerio Riedel <hvr@hvrlab.org>
+ * Copyright (c) Kyle McMartin <kyle@debian.org>
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <asm/byteorder.h>
+#include <linux/crypto.h>
+#include <linux/types.h>
+#include <crypto/blowfish.h>
+
+static const u32 bf_pbox[16 + 2] = {
+	0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
+	0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
+	0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
+	0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
+	0x9216d5d9, 0x8979fb1b,
+};
+
+static const u32 bf_sbox[256 * 4] = {
+	0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
+	0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
+	0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
+	0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
+	0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
+	0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
+	0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
+	0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
+	0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
+	0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
+	0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
+	0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
+	0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
+	0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
+	0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
+	0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
+	0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
+	0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
+	0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
+	0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
+	0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
+	0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
+	0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
+	0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
+	0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
+	0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
+	0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
+	0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
+	0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
+	0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
+	0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
+	0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
+	0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
+	0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
+	0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
+	0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
+	0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
+	0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
+	0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
+	0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
+	0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
+	0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
+	0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
+	0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
+	0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
+	0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
+	0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
+	0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
+	0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
+	0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
+	0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
+	0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
+	0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
+	0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
+	0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
+	0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
+	0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
+	0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
+	0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
+	0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
+	0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
+	0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
+	0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
+	0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
+	0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
+	0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
+	0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
+	0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
+	0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
+	0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
+	0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
+	0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
+	0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
+	0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
+	0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
+	0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
+	0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
+	0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
+	0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
+	0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
+	0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
+	0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
+	0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
+	0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
+	0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
+	0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
+	0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
+	0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
+	0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
+	0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
+	0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
+	0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
+	0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
+	0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
+	0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
+	0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
+	0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
+	0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
+	0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
+	0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
+	0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
+	0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
+	0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
+	0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
+	0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
+	0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
+	0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
+	0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
+	0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
+	0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
+	0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
+	0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
+	0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
+	0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
+	0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
+	0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
+	0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
+	0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
+	0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
+	0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
+	0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
+	0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
+	0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
+	0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
+	0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
+	0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
+	0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
+	0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
+	0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
+	0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
+	0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
+	0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
+	0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
+	0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
+	0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
+	0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
+	0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
+	0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
+	0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
+	0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
+	0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
+	0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
+	0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
+	0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
+	0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
+	0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
+	0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
+	0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
+	0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
+	0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
+	0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
+	0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
+	0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
+	0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
+	0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
+	0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
+	0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
+	0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
+	0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
+	0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
+	0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
+	0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
+	0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
+	0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
+	0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
+	0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
+	0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
+	0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
+	0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
+	0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
+	0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
+	0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
+	0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
+	0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
+	0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
+	0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
+	0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
+	0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
+	0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
+	0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
+	0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
+	0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
+	0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
+	0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
+	0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
+	0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
+	0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
+	0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
+	0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
+	0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
+	0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
+	0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
+	0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
+	0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
+	0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
+	0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
+	0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
+	0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
+	0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
+	0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
+	0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
+	0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
+	0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
+	0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
+	0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
+	0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
+	0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
+	0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
+	0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
+	0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
+	0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
+	0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
+	0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
+	0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
+	0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
+	0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
+	0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
+	0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
+	0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
+	0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
+	0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
+	0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
+	0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
+	0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
+	0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
+	0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
+	0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
+	0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
+	0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
+	0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
+	0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
+	0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
+	0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
+	0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
+	0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
+	0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
+	0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
+	0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
+	0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
+	0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
+	0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
+	0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
+	0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
+	0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
+	0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
+	0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
+	0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
+	0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
+	0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
+	0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
+	0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
+	0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
+	0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
+	0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
+	0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
+	0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6,
+};
+
+/*
+ * Round loop unrolling macros, S is a pointer to a S-Box array
+ * organized in 4 unsigned longs at a row.
+ */
+#define GET32_3(x) (((x) & 0xff))
+#define GET32_2(x) (((x) >> (8)) & (0xff))
+#define GET32_1(x) (((x) >> (16)) & (0xff))
+#define GET32_0(x) (((x) >> (24)) & (0xff))
+
+#define bf_F(x) (((S[GET32_0(x)] + S[256 + GET32_1(x)]) ^ \
+		S[512 + GET32_2(x)]) + S[768 + GET32_3(x)])
+
+#define ROUND(a, b, n) ({ b ^= P[n]; a ^= bf_F(b); })
+
+/*
+ * The blowfish encipher, processes 64-bit blocks.
+ * NOTE: This function MUSTN'T respect endianess
+ */
+static void encrypt_block(struct bf_ctx *bctx, u32 *dst, u32 *src)
+{
+	const u32 *P = bctx->p;
+	const u32 *S = bctx->s;
+	u32 yl = src[0];
+	u32 yr = src[1];
+
+	ROUND(yr, yl, 0);
+	ROUND(yl, yr, 1);
+	ROUND(yr, yl, 2);
+	ROUND(yl, yr, 3);
+	ROUND(yr, yl, 4);
+	ROUND(yl, yr, 5);
+	ROUND(yr, yl, 6);
+	ROUND(yl, yr, 7);
+	ROUND(yr, yl, 8);
+	ROUND(yl, yr, 9);
+	ROUND(yr, yl, 10);
+	ROUND(yl, yr, 11);
+	ROUND(yr, yl, 12);
+	ROUND(yl, yr, 13);
+	ROUND(yr, yl, 14);
+	ROUND(yl, yr, 15);
+
+	yl ^= P[16];
+	yr ^= P[17];
+
+	dst[0] = yr;
+	dst[1] = yl;
+}
+
+/*
+ * Calculates the blowfish S and P boxes for encryption and decryption.
+ */
+int blowfish_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
+{
+	struct bf_ctx *ctx = crypto_tfm_ctx(tfm);
+	u32 *P = ctx->p;
+	u32 *S = ctx->s;
+	short i, j, count;
+	u32 data[2], temp;
+
+	/* Copy the initialization s-boxes */
+	for (i = 0, count = 0; i < 256; i++)
+		for (j = 0; j < 4; j++, count++)
+			S[count] = bf_sbox[count];
+
+	/* Set the p-boxes */
+	for (i = 0; i < 16 + 2; i++)
+		P[i] = bf_pbox[i];
+
+	/* Actual subkey generation */
+	for (j = 0, i = 0; i < 16 + 2; i++) {
+		temp = (((u32)key[j] << 24) |
+			((u32)key[(j + 1) % keylen] << 16) |
+			((u32)key[(j + 2) % keylen] << 8) |
+			((u32)key[(j + 3) % keylen]));
+
+		P[i] = P[i] ^ temp;
+		j = (j + 4) % keylen;
+	}
+
+	data[0] = 0x00000000;
+	data[1] = 0x00000000;
+
+	for (i = 0; i < 16 + 2; i += 2) {
+		encrypt_block((struct bf_ctx *)ctx, data, data);
+
+		P[i] = data[0];
+		P[i + 1] = data[1];
+	}
+
+	for (i = 0; i < 4; i++) {
+		for (j = 0, count = i * 256; j < 256; j += 2, count += 2) {
+			encrypt_block((struct bf_ctx *)ctx, data, data);
+
+			S[count] = data[0];
+			S[count + 1] = data[1];
+		}
+	}
+
+	/* Bruce says not to bother with the weak key check. */
+	return 0;
+}
+EXPORT_SYMBOL_GPL(blowfish_setkey);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Blowfish Cipher common functions");
diff --git a/crypto/blowfish_generic.c b/crypto/blowfish_generic.c
new file mode 100644
index 0000000..6f269b5
--- /dev/null
+++ b/crypto/blowfish_generic.c
@@ -0,0 +1,142 @@
+/*
+ * Cryptographic API.
+ *
+ * Blowfish Cipher Algorithm, by Bruce Schneier.
+ * http://www.counterpane.com/blowfish.html
+ *
+ * Adapted from Kerneli implementation.
+ *
+ * Copyright (c) Herbert Valerio Riedel <hvr@hvrlab.org>
+ * Copyright (c) Kyle McMartin <kyle@debian.org>
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <asm/byteorder.h>
+#include <linux/crypto.h>
+#include <linux/types.h>
+#include <crypto/blowfish.h>
+
+/*
+ * Round loop unrolling macros, S is a pointer to a S-Box array
+ * organized in 4 unsigned longs at a row.
+ */
+#define GET32_3(x) (((x) & 0xff))
+#define GET32_2(x) (((x) >> (8)) & (0xff))
+#define GET32_1(x) (((x) >> (16)) & (0xff))
+#define GET32_0(x) (((x) >> (24)) & (0xff))
+
+#define bf_F(x) (((S[GET32_0(x)] + S[256 + GET32_1(x)]) ^ \
+		S[512 + GET32_2(x)]) + S[768 + GET32_3(x)])
+
+#define ROUND(a, b, n) ({ b ^= P[n]; a ^= bf_F(b); })
+
+static void bf_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	struct bf_ctx *ctx = crypto_tfm_ctx(tfm);
+	const __be32 *in_blk = (const __be32 *)src;
+	__be32 *const out_blk = (__be32 *)dst;
+	const u32 *P = ctx->p;
+	const u32 *S = ctx->s;
+	u32 yl = be32_to_cpu(in_blk[0]);
+	u32 yr = be32_to_cpu(in_blk[1]);
+
+	ROUND(yr, yl, 0);
+	ROUND(yl, yr, 1);
+	ROUND(yr, yl, 2);
+	ROUND(yl, yr, 3);
+	ROUND(yr, yl, 4);
+	ROUND(yl, yr, 5);
+	ROUND(yr, yl, 6);
+	ROUND(yl, yr, 7);
+	ROUND(yr, yl, 8);
+	ROUND(yl, yr, 9);
+	ROUND(yr, yl, 10);
+	ROUND(yl, yr, 11);
+	ROUND(yr, yl, 12);
+	ROUND(yl, yr, 13);
+	ROUND(yr, yl, 14);
+	ROUND(yl, yr, 15);
+
+	yl ^= P[16];
+	yr ^= P[17];
+
+	out_blk[0] = cpu_to_be32(yr);
+	out_blk[1] = cpu_to_be32(yl);
+}
+
+static void bf_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	struct bf_ctx *ctx = crypto_tfm_ctx(tfm);
+	const __be32 *in_blk = (const __be32 *)src;
+	__be32 *const out_blk = (__be32 *)dst;
+	const u32 *P = ctx->p;
+	const u32 *S = ctx->s;
+	u32 yl = be32_to_cpu(in_blk[0]);
+	u32 yr = be32_to_cpu(in_blk[1]);
+
+	ROUND(yr, yl, 17);
+	ROUND(yl, yr, 16);
+	ROUND(yr, yl, 15);
+	ROUND(yl, yr, 14);
+	ROUND(yr, yl, 13);
+	ROUND(yl, yr, 12);
+	ROUND(yr, yl, 11);
+	ROUND(yl, yr, 10);
+	ROUND(yr, yl, 9);
+	ROUND(yl, yr, 8);
+	ROUND(yr, yl, 7);
+	ROUND(yl, yr, 6);
+	ROUND(yr, yl, 5);
+	ROUND(yl, yr, 4);
+	ROUND(yr, yl, 3);
+	ROUND(yl, yr, 2);
+
+	yl ^= P[1];
+	yr ^= P[0];
+
+	out_blk[0] = cpu_to_be32(yr);
+	out_blk[1] = cpu_to_be32(yl);
+}
+
+static struct crypto_alg alg = {
+	.cra_name		=	"blowfish",
+	.cra_driver_name	=	"blowfish-generic",
+	.cra_priority		=	100,
+	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize		=	BF_BLOCK_SIZE,
+	.cra_ctxsize		=	sizeof(struct bf_ctx),
+	.cra_alignmask		=	3,
+	.cra_module		=	THIS_MODULE,
+	.cra_list		=	LIST_HEAD_INIT(alg.cra_list),
+	.cra_u			=	{ .cipher = {
+	.cia_min_keysize	=	BF_MIN_KEY_SIZE,
+	.cia_max_keysize	=	BF_MAX_KEY_SIZE,
+	.cia_setkey		=	blowfish_setkey,
+	.cia_encrypt		=	bf_encrypt,
+	.cia_decrypt		=	bf_decrypt } }
+};
+
+static int __init blowfish_mod_init(void)
+{
+	return crypto_register_alg(&alg);
+}
+
+static void __exit blowfish_mod_fini(void)
+{
+	crypto_unregister_alg(&alg);
+}
+
+module_init(blowfish_mod_init);
+module_exit(blowfish_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Blowfish Cipher Algorithm");
+MODULE_ALIAS("blowfish");
diff --git a/crypto/cryptd.c b/crypto/cryptd.c
index e46d21a..671d4d6 100644
--- a/crypto/cryptd.c
+++ b/crypto/cryptd.c
@@ -945,7 +945,7 @@ static void __exit cryptd_exit(void)
 	crypto_unregister_template(&cryptd_tmpl);
 }
 
-module_init(cryptd_init);
+subsys_initcall(cryptd_init);
 module_exit(cryptd_exit);
 
 MODULE_LICENSE("GPL");
diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c
new file mode 100644
index 0000000..2abca78
--- /dev/null
+++ b/crypto/crypto_user.c
@@ -0,0 +1,438 @@
+/*
+ * Crypto user configuration API.
+ *
+ * Copyright (C) 2011 secunet Security Networks AG
+ * Copyright (C) 2011 Steffen Klassert <steffen.klassert@secunet.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <linux/crypto.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
+#include <linux/security.h>
+#include <net/net_namespace.h>
+#include "internal.h"
+
+DEFINE_MUTEX(crypto_cfg_mutex);
+
+/* The crypto netlink socket */
+static struct sock *crypto_nlsk;
+
+struct crypto_dump_info {
+	struct sk_buff *in_skb;
+	struct sk_buff *out_skb;
+	u32 nlmsg_seq;
+	u16 nlmsg_flags;
+};
+
+static struct crypto_alg *crypto_alg_match(struct crypto_user_alg *p, int exact)
+{
+	struct crypto_alg *q, *alg = NULL;
+
+	down_read(&crypto_alg_sem);
+
+	if (list_empty(&crypto_alg_list))
+		return NULL;
+
+	list_for_each_entry(q, &crypto_alg_list, cra_list) {
+		int match = 0;
+
+		if ((q->cra_flags ^ p->cru_type) & p->cru_mask)
+			continue;
+
+		if (strlen(p->cru_driver_name))
+			match = !strcmp(q->cra_driver_name,
+					p->cru_driver_name);
+		else if (!exact)
+			match = !strcmp(q->cra_name, p->cru_name);
+
+		if (match) {
+			alg = q;
+			break;
+		}
+	}
+
+	up_read(&crypto_alg_sem);
+
+	return alg;
+}
+
+static int crypto_report_cipher(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_cipher rcipher;
+
+	snprintf(rcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "cipher");
+
+	rcipher.blocksize = alg->cra_blocksize;
+	rcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
+	rcipher.max_keysize = alg->cra_cipher.cia_max_keysize;
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_CIPHER,
+		sizeof(struct crypto_report_cipher), &rcipher);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
+static int crypto_report_comp(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_comp rcomp;
+
+	snprintf(rcomp.type, CRYPTO_MAX_ALG_NAME, "%s", "compression");
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_COMPRESS,
+		sizeof(struct crypto_report_comp), &rcomp);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
+static int crypto_report_one(struct crypto_alg *alg,
+			     struct crypto_user_alg *ualg, struct sk_buff *skb)
+{
+	memcpy(&ualg->cru_name, &alg->cra_name, sizeof(ualg->cru_name));
+	memcpy(&ualg->cru_driver_name, &alg->cra_driver_name,
+	       sizeof(ualg->cru_driver_name));
+	memcpy(&ualg->cru_module_name, module_name(alg->cra_module),
+	       CRYPTO_MAX_ALG_NAME);
+
+	ualg->cru_flags = alg->cra_flags;
+	ualg->cru_refcnt = atomic_read(&alg->cra_refcnt);
+
+	NLA_PUT_U32(skb, CRYPTOCFGA_PRIORITY_VAL, alg->cra_priority);
+
+	if (alg->cra_flags & CRYPTO_ALG_LARVAL) {
+		struct crypto_report_larval rl;
+
+		snprintf(rl.type, CRYPTO_MAX_ALG_NAME, "%s", "larval");
+
+		NLA_PUT(skb, CRYPTOCFGA_REPORT_LARVAL,
+			sizeof(struct crypto_report_larval), &rl);
+
+		goto out;
+	}
+
+	if (alg->cra_type && alg->cra_type->report) {
+		if (alg->cra_type->report(skb, alg))
+			goto nla_put_failure;
+
+		goto out;
+	}
+
+	switch (alg->cra_flags & (CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_LARVAL)) {
+	case CRYPTO_ALG_TYPE_CIPHER:
+		if (crypto_report_cipher(skb, alg))
+			goto nla_put_failure;
+
+		break;
+	case CRYPTO_ALG_TYPE_COMPRESS:
+		if (crypto_report_comp(skb, alg))
+			goto nla_put_failure;
+
+		break;
+	}
+
+out:
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
+static int crypto_report_alg(struct crypto_alg *alg,
+			     struct crypto_dump_info *info)
+{
+	struct sk_buff *in_skb = info->in_skb;
+	struct sk_buff *skb = info->out_skb;
+	struct nlmsghdr *nlh;
+	struct crypto_user_alg *ualg;
+	int err = 0;
+
+	nlh = nlmsg_put(skb, NETLINK_CB(in_skb).pid, info->nlmsg_seq,
+			CRYPTO_MSG_GETALG, sizeof(*ualg), info->nlmsg_flags);
+	if (!nlh) {
+		err = -EMSGSIZE;
+		goto out;
+	}
+
+	ualg = nlmsg_data(nlh);
+
+	err = crypto_report_one(alg, ualg, skb);
+	if (err) {
+		nlmsg_cancel(skb, nlh);
+		goto out;
+	}
+
+	nlmsg_end(skb, nlh);
+
+out:
+	return err;
+}
+
+static int crypto_report(struct sk_buff *in_skb, struct nlmsghdr *in_nlh,
+			 struct nlattr **attrs)
+{
+	struct crypto_user_alg *p = nlmsg_data(in_nlh);
+	struct crypto_alg *alg;
+	struct sk_buff *skb;
+	struct crypto_dump_info info;
+	int err;
+
+	if (!p->cru_driver_name)
+		return -EINVAL;
+
+	alg = crypto_alg_match(p, 1);
+	if (!alg)
+		return -ENOENT;
+
+	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
+	if (!skb)
+		return -ENOMEM;
+
+	info.in_skb = in_skb;
+	info.out_skb = skb;
+	info.nlmsg_seq = in_nlh->nlmsg_seq;
+	info.nlmsg_flags = 0;
+
+	err = crypto_report_alg(alg, &info);
+	if (err)
+		return err;
+
+	return nlmsg_unicast(crypto_nlsk, skb, NETLINK_CB(in_skb).pid);
+}
+
+static int crypto_dump_report(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	struct crypto_alg *alg;
+	struct crypto_dump_info info;
+	int err;
+
+	if (cb->args[0])
+		goto out;
+
+	cb->args[0] = 1;
+
+	info.in_skb = cb->skb;
+	info.out_skb = skb;
+	info.nlmsg_seq = cb->nlh->nlmsg_seq;
+	info.nlmsg_flags = NLM_F_MULTI;
+
+	list_for_each_entry(alg, &crypto_alg_list, cra_list) {
+		err = crypto_report_alg(alg, &info);
+		if (err)
+			goto out_err;
+	}
+
+out:
+	return skb->len;
+out_err:
+	return err;
+}
+
+static int crypto_dump_report_done(struct netlink_callback *cb)
+{
+	return 0;
+}
+
+static int crypto_update_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
+			     struct nlattr **attrs)
+{
+	struct crypto_alg *alg;
+	struct crypto_user_alg *p = nlmsg_data(nlh);
+	struct nlattr *priority = attrs[CRYPTOCFGA_PRIORITY_VAL];
+	LIST_HEAD(list);
+
+	if (priority && !strlen(p->cru_driver_name))
+		return -EINVAL;
+
+	alg = crypto_alg_match(p, 1);
+	if (!alg)
+		return -ENOENT;
+
+	down_write(&crypto_alg_sem);
+
+	crypto_remove_spawns(alg, &list, NULL);
+
+	if (priority)
+		alg->cra_priority = nla_get_u32(priority);
+
+	up_write(&crypto_alg_sem);
+
+	crypto_remove_final(&list);
+
+	return 0;
+}
+
+static int crypto_del_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
+			  struct nlattr **attrs)
+{
+	struct crypto_alg *alg;
+	struct crypto_user_alg *p = nlmsg_data(nlh);
+
+	alg = crypto_alg_match(p, 1);
+	if (!alg)
+		return -ENOENT;
+
+	/* We can not unregister core algorithms such as aes-generic.
+	 * We would loose the reference in the crypto_alg_list to this algorithm
+	 * if we try to unregister. Unregistering such an algorithm without
+	 * removing the module is not possible, so we restrict to crypto
+	 * instances that are build from templates. */
+	if (!(alg->cra_flags & CRYPTO_ALG_INSTANCE))
+		return -EINVAL;
+
+	if (atomic_read(&alg->cra_refcnt) != 1)
+		return -EBUSY;
+
+	return crypto_unregister_alg(alg);
+}
+
+static int crypto_add_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
+			  struct nlattr **attrs)
+{
+	int exact;
+	const char *name;
+	struct crypto_alg *alg;
+	struct crypto_user_alg *p = nlmsg_data(nlh);
+	struct nlattr *priority = attrs[CRYPTOCFGA_PRIORITY_VAL];
+
+	if (strlen(p->cru_driver_name))
+		exact = 1;
+
+	if (priority && !exact)
+		return -EINVAL;
+
+	alg = crypto_alg_match(p, exact);
+	if (alg)
+		return -EEXIST;
+
+	if (strlen(p->cru_driver_name))
+		name = p->cru_driver_name;
+	else
+		name = p->cru_name;
+
+	alg = crypto_alg_mod_lookup(name, p->cru_type, p->cru_mask);
+	if (IS_ERR(alg))
+		return PTR_ERR(alg);
+
+	down_write(&crypto_alg_sem);
+
+	if (priority)
+		alg->cra_priority = nla_get_u32(priority);
+
+	up_write(&crypto_alg_sem);
+
+	crypto_mod_put(alg);
+
+	return 0;
+}
+
+#define MSGSIZE(type) sizeof(struct type)
+
+static const int crypto_msg_min[CRYPTO_NR_MSGTYPES] = {
+	[CRYPTO_MSG_NEWALG	- CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
+	[CRYPTO_MSG_DELALG	- CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
+	[CRYPTO_MSG_UPDATEALG	- CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
+	[CRYPTO_MSG_GETALG	- CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
+};
+
+static const struct nla_policy crypto_policy[CRYPTOCFGA_MAX+1] = {
+	[CRYPTOCFGA_PRIORITY_VAL]   = { .type = NLA_U32},
+};
+
+#undef MSGSIZE
+
+static struct crypto_link {
+	int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **);
+	int (*dump)(struct sk_buff *, struct netlink_callback *);
+	int (*done)(struct netlink_callback *);
+} crypto_dispatch[CRYPTO_NR_MSGTYPES] = {
+	[CRYPTO_MSG_NEWALG	- CRYPTO_MSG_BASE] = { .doit = crypto_add_alg},
+	[CRYPTO_MSG_DELALG	- CRYPTO_MSG_BASE] = { .doit = crypto_del_alg},
+	[CRYPTO_MSG_UPDATEALG	- CRYPTO_MSG_BASE] = { .doit = crypto_update_alg},
+	[CRYPTO_MSG_GETALG	- CRYPTO_MSG_BASE] = { .doit = crypto_report,
+						       .dump = crypto_dump_report,
+						       .done = crypto_dump_report_done},
+};
+
+static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+{
+	struct nlattr *attrs[CRYPTOCFGA_MAX+1];
+	struct crypto_link *link;
+	int type, err;
+
+	type = nlh->nlmsg_type;
+	if (type > CRYPTO_MSG_MAX)
+		return -EINVAL;
+
+	type -= CRYPTO_MSG_BASE;
+	link = &crypto_dispatch[type];
+
+	if (security_netlink_recv(skb, CAP_NET_ADMIN))
+		return -EPERM;
+
+	if ((type == (CRYPTO_MSG_GETALG - CRYPTO_MSG_BASE) &&
+	    (nlh->nlmsg_flags & NLM_F_DUMP))) {
+		if (link->dump == NULL)
+			return -EINVAL;
+
+		return netlink_dump_start(crypto_nlsk, skb, nlh,
+					  link->dump, link->done, 0);
+	}
+
+	err = nlmsg_parse(nlh, crypto_msg_min[type], attrs, CRYPTOCFGA_MAX,
+			  crypto_policy);
+	if (err < 0)
+		return err;
+
+	if (link->doit == NULL)
+		return -EINVAL;
+
+	return link->doit(skb, nlh, attrs);
+}
+
+static void crypto_netlink_rcv(struct sk_buff *skb)
+{
+	mutex_lock(&crypto_cfg_mutex);
+	netlink_rcv_skb(skb, &crypto_user_rcv_msg);
+	mutex_unlock(&crypto_cfg_mutex);
+}
+
+static int __init crypto_user_init(void)
+{
+	crypto_nlsk = netlink_kernel_create(&init_net, NETLINK_CRYPTO,
+					    0, crypto_netlink_rcv,
+					    NULL, THIS_MODULE);
+	if (!crypto_nlsk)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void __exit crypto_user_exit(void)
+{
+	netlink_kernel_release(crypto_nlsk);
+}
+
+module_init(crypto_user_init);
+module_exit(crypto_user_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");
+MODULE_DESCRIPTION("Crypto userspace configuration API");
diff --git a/crypto/internal.h b/crypto/internal.h
index d4384b0..b865ca1 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -86,6 +86,9 @@ struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask);
 void crypto_larval_error(const char *name, u32 type, u32 mask);
 void crypto_alg_tested(const char *name, int err);
 
+void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,
+			  struct crypto_alg *nalg);
+void crypto_remove_final(struct list_head *list);
 void crypto_shoot_alg(struct crypto_alg *alg);
 struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
 				      u32 mask);
diff --git a/crypto/pcompress.c b/crypto/pcompress.c
index f7c4a7d..fefda78 100644
--- a/crypto/pcompress.c
+++ b/crypto/pcompress.c
@@ -24,6 +24,8 @@
 #include <linux/module.h>
 #include <linux/seq_file.h>
 #include <linux/string.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
 
 #include <crypto/compress.h>
 #include <crypto/internal/compress.h>
@@ -46,6 +48,21 @@ static int crypto_pcomp_init_tfm(struct crypto_tfm *tfm)
 	return 0;
 }
 
+static int crypto_pcomp_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_comp rpcomp;
+
+	snprintf(rpcomp.type, CRYPTO_MAX_ALG_NAME, "%s", "pcomp");
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_COMPRESS,
+		sizeof(struct crypto_report_comp), &rpcomp);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
 static void crypto_pcomp_show(struct seq_file *m, struct crypto_alg *alg)
 	__attribute__ ((unused));
 static void crypto_pcomp_show(struct seq_file *m, struct crypto_alg *alg)
@@ -60,6 +77,7 @@ static const struct crypto_type crypto_pcomp_type = {
 #ifdef CONFIG_PROC_FS
 	.show		= crypto_pcomp_show,
 #endif
+	.report		= crypto_pcomp_report,
 	.maskclear	= ~CRYPTO_ALG_TYPE_MASK,
 	.maskset	= CRYPTO_ALG_TYPE_MASK,
 	.type		= CRYPTO_ALG_TYPE_PCOMPRESS,
diff --git a/crypto/rng.c b/crypto/rng.c
index 45229ae..feb7de0 100644
--- a/crypto/rng.c
+++ b/crypto/rng.c
@@ -21,6 +21,8 @@
 #include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
 
 static DEFINE_MUTEX(crypto_default_rng_lock);
 struct crypto_rng *crypto_default_rng;
@@ -58,6 +60,23 @@ static int crypto_init_rng_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
 	return 0;
 }
 
+static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_rng rrng;
+
+	snprintf(rrng.type, CRYPTO_MAX_ALG_NAME, "%s", "rng");
+
+	rrng.seedsize = alg->cra_rng.seedsize;
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_RNG,
+		sizeof(struct crypto_report_rng), &rrng);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
 static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
 	__attribute__ ((unused));
 static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
@@ -78,6 +97,7 @@ const struct crypto_type crypto_rng_type = {
 #ifdef CONFIG_PROC_FS
 	.show = crypto_rng_show,
 #endif
+	.report = crypto_rng_report,
 };
 EXPORT_SYMBOL_GPL(crypto_rng_type);
 
diff --git a/crypto/sha1_generic.c b/crypto/sha1_generic.c
index 00ae60e..4279480 100644
--- a/crypto/sha1_generic.c
+++ b/crypto/sha1_generic.c
@@ -36,7 +36,7 @@ static int sha1_init(struct shash_desc *desc)
 	return 0;
 }
 
-static int sha1_update(struct shash_desc *desc, const u8 *data,
+int crypto_sha1_update(struct shash_desc *desc, const u8 *data,
 			unsigned int len)
 {
 	struct sha1_state *sctx = shash_desc_ctx(desc);
@@ -71,6 +71,7 @@ static int sha1_update(struct shash_desc *desc, const u8 *data,
 
 	return 0;
 }
+EXPORT_SYMBOL(crypto_sha1_update);
 
 
 /* Add padding and return the message digest. */
@@ -87,10 +88,10 @@ static int sha1_final(struct shash_desc *desc, u8 *out)
 	/* Pad out to 56 mod 64 */
 	index = sctx->count & 0x3f;
 	padlen = (index < 56) ? (56 - index) : ((64+56) - index);
-	sha1_update(desc, padding, padlen);
+	crypto_sha1_update(desc, padding, padlen);
 
 	/* Append length */
-	sha1_update(desc, (const u8 *)&bits, sizeof(bits));
+	crypto_sha1_update(desc, (const u8 *)&bits, sizeof(bits));
 
 	/* Store state in digest */
 	for (i = 0; i < 5; i++)
@@ -121,7 +122,7 @@ static int sha1_import(struct shash_desc *desc, const void *in)
 static struct shash_alg alg = {
 	.digestsize	=	SHA1_DIGEST_SIZE,
 	.init		=	sha1_init,
-	.update		=	sha1_update,
+	.update		=	crypto_sha1_update,
 	.final		=	sha1_final,
 	.export		=	sha1_export,
 	.import		=	sha1_import,
diff --git a/crypto/shash.c b/crypto/shash.c
index 76f74b9..ea8a9c6 100644
--- a/crypto/shash.c
+++ b/crypto/shash.c
@@ -17,6 +17,8 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/seq_file.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
 
 #include "internal.h"
 
@@ -522,6 +524,24 @@ static unsigned int crypto_shash_extsize(struct crypto_alg *alg)
 	return alg->cra_ctxsize;
 }
 
+static int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_hash rhash;
+	struct shash_alg *salg = __crypto_shash_alg(alg);
+
+	snprintf(rhash.type, CRYPTO_MAX_ALG_NAME, "%s", "shash");
+	rhash.blocksize = alg->cra_blocksize;
+	rhash.digestsize = salg->digestsize;
+
+	NLA_PUT(skb, CRYPTOCFGA_REPORT_HASH,
+		sizeof(struct crypto_report_hash), &rhash);
+
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
 static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg)
 	__attribute__ ((unused));
 static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg)
@@ -541,6 +561,7 @@ static const struct crypto_type crypto_shash_type = {
 #ifdef CONFIG_PROC_FS
 	.show = crypto_shash_show,
 #endif
+	.report = crypto_shash_report,
 	.maskclear = ~CRYPTO_ALG_TYPE_MASK,
 	.maskset = CRYPTO_ALG_TYPE_MASK,
 	.type = CRYPTO_ALG_TYPE_SHASH,
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index 2222617..0c4e80f 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -782,11 +782,13 @@ static int do_test(int m)
 	case 7:
 		ret += tcrypt_test("ecb(blowfish)");
 		ret += tcrypt_test("cbc(blowfish)");
+		ret += tcrypt_test("ctr(blowfish)");
 		break;
 
 	case 8:
 		ret += tcrypt_test("ecb(twofish)");
 		ret += tcrypt_test("cbc(twofish)");
+		ret += tcrypt_test("ctr(twofish)");
 		break;
 
 	case 9:
@@ -1039,6 +1041,10 @@ static int do_test(int m)
 				speed_template_16_24_32);
 		test_cipher_speed("cbc(twofish)", DECRYPT, sec, NULL, 0,
 				speed_template_16_24_32);
+		test_cipher_speed("ctr(twofish)", ENCRYPT, sec, NULL, 0,
+				speed_template_16_24_32);
+		test_cipher_speed("ctr(twofish)", DECRYPT, sec, NULL, 0,
+				speed_template_16_24_32);
 		break;
 
 	case 203:
@@ -1050,6 +1056,10 @@ static int do_test(int m)
 				  speed_template_8_32);
 		test_cipher_speed("cbc(blowfish)", DECRYPT, sec, NULL, 0,
 				  speed_template_8_32);
+		test_cipher_speed("ctr(blowfish)", ENCRYPT, sec, NULL, 0,
+				  speed_template_8_32);
+		test_cipher_speed("ctr(blowfish)", DECRYPT, sec, NULL, 0,
+				  speed_template_8_32);
 		break;
 
 	case 204:
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index b6b93d4..e91c1eb 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -1756,6 +1756,36 @@ static const struct alg_test_desc alg_test_descs[] = {
 			}
 		}
 	}, {
+		.alg = "ctr(blowfish)",
+		.test = alg_test_skcipher,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = bf_ctr_enc_tv_template,
+					.count = BF_CTR_ENC_TEST_VECTORS
+				},
+				.dec = {
+					.vecs = bf_ctr_dec_tv_template,
+					.count = BF_CTR_DEC_TEST_VECTORS
+				}
+			}
+		}
+	}, {
+		.alg = "ctr(twofish)",
+		.test = alg_test_skcipher,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = tf_ctr_enc_tv_template,
+					.count = TF_CTR_ENC_TEST_VECTORS
+				},
+				.dec = {
+					.vecs = tf_ctr_dec_tv_template,
+					.count = TF_CTR_DEC_TEST_VECTORS
+				}
+			}
+		}
+	}, {
 		.alg = "cts(cbc(aes))",
 		.test = alg_test_skcipher,
 		.suite = {
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 27adc92..37b4d8f 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -2391,10 +2391,12 @@ static struct cipher_testvec des3_ede_cbc_dec_tv_template[] = {
 /*
  * Blowfish test vectors.
  */
-#define BF_ENC_TEST_VECTORS	6
-#define BF_DEC_TEST_VECTORS	6
-#define BF_CBC_ENC_TEST_VECTORS	1
-#define BF_CBC_DEC_TEST_VECTORS	1
+#define BF_ENC_TEST_VECTORS	7
+#define BF_DEC_TEST_VECTORS	7
+#define BF_CBC_ENC_TEST_VECTORS	2
+#define BF_CBC_DEC_TEST_VECTORS	2
+#define BF_CTR_ENC_TEST_VECTORS	2
+#define BF_CTR_DEC_TEST_VECTORS	2
 
 static struct cipher_testvec bf_enc_tv_template[] = {
 	{ /* DES test vectors from OpenSSL */
@@ -2448,6 +2450,24 @@ static struct cipher_testvec bf_enc_tv_template[] = {
 		.ilen	= 8,
 		.result	= "\xc0\x45\x04\x01\x2e\x4e\x1f\x53",
 		.rlen	= 8,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.input	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
+		.ilen	= 40,
+		.result	= "\x96\x87\x3D\x0C\x7B\xFB\xBD\x1F"
+			  "\xE3\xC1\x99\x6D\x39\xD4\xC2\x7D"
+			  "\xD7\x87\xA1\xF2\xDF\x51\x71\x26"
+			  "\xC2\xF4\x6D\xFF\xF6\xCD\x6B\x40"
+			  "\xE1\xB3\xBF\xD4\x38\x2B\xC8\x3B",
+		.rlen	= 40,
 	},
 };
 
@@ -2503,6 +2523,24 @@ static struct cipher_testvec bf_dec_tv_template[] = {
 		.ilen	= 8,
 		.result	= "\xfe\xdc\xba\x98\x76\x54\x32\x10",
 		.rlen	= 8,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.input	= "\x96\x87\x3D\x0C\x7B\xFB\xBD\x1F"
+			  "\xE3\xC1\x99\x6D\x39\xD4\xC2\x7D"
+			  "\xD7\x87\xA1\xF2\xDF\x51\x71\x26"
+			  "\xC2\xF4\x6D\xFF\xF6\xCD\x6B\x40"
+			  "\xE1\xB3\xBF\xD4\x38\x2B\xC8\x3B",
+		.ilen	= 40,
+		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
+		.rlen	= 40,
 	},
 };
 
@@ -2522,6 +2560,25 @@ static struct cipher_testvec bf_cbc_enc_tv_template[] = {
 			  "\x58\xde\xb9\xe7\x15\x46\x16\xd9"
 			  "\x59\xf1\x65\x2b\xd5\xff\x92\xcc",
 		.rlen	= 32,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
+		.input	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
+		.ilen	= 40,
+		.result	= "\xB4\xFE\xA5\xBB\x3D\x2C\x27\x06"
+			  "\x06\x2B\x3A\x92\xB2\xF5\x5E\x62"
+			  "\x84\xCD\xF7\x66\x7E\x41\x6C\x8E"
+			  "\x1B\xD9\x02\xB6\x48\xB0\x87\x25"
+			  "\x01\x9C\x93\x63\x51\x60\x82\xD2",
+		.rlen	= 40,
 	},
 };
 
@@ -2541,16 +2598,125 @@ static struct cipher_testvec bf_cbc_dec_tv_template[] = {
 			  "\x68\x65\x20\x74\x69\x6d\x65\x20"
 			  "\x66\x6f\x72\x20\x00\x00\x00\x00",
 		.rlen	= 32,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
+		.input	= "\xB4\xFE\xA5\xBB\x3D\x2C\x27\x06"
+			  "\x06\x2B\x3A\x92\xB2\xF5\x5E\x62"
+			  "\x84\xCD\xF7\x66\x7E\x41\x6C\x8E"
+			  "\x1B\xD9\x02\xB6\x48\xB0\x87\x25"
+			  "\x01\x9C\x93\x63\x51\x60\x82\xD2",
+		.ilen	= 40,
+		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
+		.rlen	= 40,
+	},
+};
+
+static struct cipher_testvec bf_ctr_enc_tv_template[] = {
+	{ /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
+		.input	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
+		.ilen	= 40,
+		.result	= "\xC7\xA3\xDF\xB9\x05\xF4\x9E\x8D"
+			  "\x9E\xDF\x38\x18\x83\x07\xEF\xC1"
+			  "\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
+			  "\x0D\x70\x86\x5A\x44\xAD\x85\x17"
+			  "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC",
+		.rlen	= 40,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
+		.input	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B",
+		.ilen	= 43,
+		.result	= "\xC7\xA3\xDF\xB9\x05\xF4\x9E\x8D"
+			  "\x9E\xDF\x38\x18\x83\x07\xEF\xC1"
+			  "\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
+			  "\x0D\x70\x86\x5A\x44\xAD\x85\x17"
+			  "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC"
+			  "\x3D\xA7\xE9",
+		.rlen	= 43,
+	},
+};
+
+static struct cipher_testvec bf_ctr_dec_tv_template[] = {
+	{ /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
+		.input	= "\xC7\xA3\xDF\xB9\x05\xF4\x9E\x8D"
+			  "\x9E\xDF\x38\x18\x83\x07\xEF\xC1"
+			  "\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
+			  "\x0D\x70\x86\x5A\x44\xAD\x85\x17"
+			  "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC",
+		.ilen	= 40,
+		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
+		.rlen	= 40,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
+		.input	= "\xC7\xA3\xDF\xB9\x05\xF4\x9E\x8D"
+			  "\x9E\xDF\x38\x18\x83\x07\xEF\xC1"
+			  "\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
+			  "\x0D\x70\x86\x5A\x44\xAD\x85\x17"
+			  "\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC"
+			  "\x3D\xA7\xE9",
+		.ilen	= 43,
+		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B",
+		.rlen	= 43,
 	},
 };
 
 /*
  * Twofish test vectors.
  */
-#define TF_ENC_TEST_VECTORS		3
-#define TF_DEC_TEST_VECTORS		3
-#define TF_CBC_ENC_TEST_VECTORS		4
-#define TF_CBC_DEC_TEST_VECTORS		4
+#define TF_ENC_TEST_VECTORS		4
+#define TF_DEC_TEST_VECTORS		4
+#define TF_CBC_ENC_TEST_VECTORS		5
+#define TF_CBC_DEC_TEST_VECTORS		5
+#define TF_CTR_ENC_TEST_VECTORS		2
+#define TF_CTR_DEC_TEST_VECTORS		2
 
 static struct cipher_testvec tf_enc_tv_template[] = {
 	{
@@ -2582,6 +2748,30 @@ static struct cipher_testvec tf_enc_tv_template[] = {
 		.result	= "\x37\x52\x7b\xe0\x05\x23\x34\xb8"
 			  "\x9f\x0c\xfc\xca\xe8\x7c\xfa\x20",
 		.rlen	= 16,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x3F\x85\x62\x3F\x1C\xF9\xD6\x1C"
+			  "\xF9\xD6\xB3\x90\x6D\x4A\x90\x6D"
+			  "\x4A\x27\x04\xE1\x27\x04\xE1\xBE"
+			  "\x9B\x78\xBE\x9B\x78\x55\x32\x0F",
+		.klen	= 32,
+		.input	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C",
+		.ilen	= 64,
+		.result	= "\x88\xCB\x1E\xC2\xAF\x8A\x97\xFF"
+			  "\xF6\x90\x46\x9C\x4A\x0F\x08\xDC"
+			  "\xDE\xAB\xAD\xFA\xFC\xA8\xC2\x3D"
+			  "\xE0\xE4\x8B\x3F\xD5\xA3\xF7\x14"
+			  "\x34\x9E\xB6\x08\xB2\xDD\xA8\xF5"
+			  "\xDF\xFA\xC7\xE8\x09\x50\x76\x08"
+			  "\xA2\xB6\x6A\x59\xC0\x2B\x6D\x05"
+			  "\x89\xF6\x82\xF0\xD3\xDB\x06\x02",
+		.rlen	= 64,
 	},
 };
 
@@ -2615,6 +2805,30 @@ static struct cipher_testvec tf_dec_tv_template[] = {
 		.ilen	= 16,
 		.result	= zeroed_string,
 		.rlen	= 16,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x3F\x85\x62\x3F\x1C\xF9\xD6\x1C"
+			  "\xF9\xD6\xB3\x90\x6D\x4A\x90\x6D"
+			  "\x4A\x27\x04\xE1\x27\x04\xE1\xBE"
+			  "\x9B\x78\xBE\x9B\x78\x55\x32\x0F",
+		.klen	= 32,
+		.input	= "\x88\xCB\x1E\xC2\xAF\x8A\x97\xFF"
+			  "\xF6\x90\x46\x9C\x4A\x0F\x08\xDC"
+			  "\xDE\xAB\xAD\xFA\xFC\xA8\xC2\x3D"
+			  "\xE0\xE4\x8B\x3F\xD5\xA3\xF7\x14"
+			  "\x34\x9E\xB6\x08\xB2\xDD\xA8\xF5"
+			  "\xDF\xFA\xC7\xE8\x09\x50\x76\x08"
+			  "\xA2\xB6\x6A\x59\xC0\x2B\x6D\x05"
+			  "\x89\xF6\x82\xF0\xD3\xDB\x06\x02",
+		.ilen	= 64,
+		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C",
+		.rlen	= 64,
 	},
 };
 
@@ -2661,6 +2875,32 @@ static struct cipher_testvec tf_cbc_enc_tv_template[] = {
 			  "\x05\xef\x8c\x61\xa8\x11\x58\x26"
 			  "\x34\xba\x5c\xb7\x10\x6a\xa6\x41",
 		.rlen	= 48,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
+			  "\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
+		.input	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C",
+		.ilen	= 64,
+		.result	= "\xC8\xFF\xF2\x53\xA6\x27\x09\xD1"
+			  "\x33\x38\xC2\xC0\x0C\x14\x7E\xB5"
+			  "\x26\x1B\x05\x0C\x05\x12\x3F\xC0"
+			  "\xF9\x1C\x02\x28\x40\x96\x6F\xD0"
+			  "\x3D\x32\xDF\xDA\x56\x00\x6E\xEE"
+			  "\x5B\x2A\x72\x9D\xC2\x4D\x19\xBC"
+			  "\x8C\x53\xFA\x87\x6F\xDD\x81\xA3"
+			  "\xB1\xD3\x44\x65\xDF\xE7\x63\x38",
+		.rlen	= 64,
 	},
 };
 
@@ -2707,6 +2947,148 @@ static struct cipher_testvec tf_cbc_dec_tv_template[] = {
 		.ilen	= 48,
 		.result	= zeroed_string,
 		.rlen	= 48,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
+			  "\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
+		.input	= "\xC8\xFF\xF2\x53\xA6\x27\x09\xD1"
+			  "\x33\x38\xC2\xC0\x0C\x14\x7E\xB5"
+			  "\x26\x1B\x05\x0C\x05\x12\x3F\xC0"
+			  "\xF9\x1C\x02\x28\x40\x96\x6F\xD0"
+			  "\x3D\x32\xDF\xDA\x56\x00\x6E\xEE"
+			  "\x5B\x2A\x72\x9D\xC2\x4D\x19\xBC"
+			  "\x8C\x53\xFA\x87\x6F\xDD\x81\xA3"
+			  "\xB1\xD3\x44\x65\xDF\xE7\x63\x38",
+		.ilen	= 64,
+		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C",
+		.rlen	= 64,
+	},
+};
+
+static struct cipher_testvec tf_ctr_enc_tv_template[] = {
+	{ /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
+			  "\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
+		.input	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C",
+		.ilen	= 64,
+		.result	= "\xDF\xDD\x69\xFA\xB0\x2E\xFD\xFE"
+			  "\x70\x9E\xC5\x4B\xC9\xD4\xA1\x30"
+			  "\x26\x9B\x89\xA1\xEE\x43\xE0\x52"
+			  "\x55\x17\x4E\xC7\x0E\x33\x1F\xF1"
+			  "\x9F\x8D\x40\x9F\x24\xFD\x92\xA0"
+			  "\xBC\x8F\x35\xDD\x67\x38\xD8\xAA"
+			  "\xCF\xF8\x48\xCA\xFB\xE4\x5C\x60"
+			  "\x01\x41\x21\x12\x38\xAB\x52\x4F",
+		.rlen	= 64,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
+			  "\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
+		.input	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE",
+		.ilen	= 67,
+		.result	= "\xDF\xDD\x69\xFA\xB0\x2E\xFD\xFE"
+			  "\x70\x9E\xC5\x4B\xC9\xD4\xA1\x30"
+			  "\x26\x9B\x89\xA1\xEE\x43\xE0\x52"
+			  "\x55\x17\x4E\xC7\x0E\x33\x1F\xF1"
+			  "\x9F\x8D\x40\x9F\x24\xFD\x92\xA0"
+			  "\xBC\x8F\x35\xDD\x67\x38\xD8\xAA"
+			  "\xCF\xF8\x48\xCA\xFB\xE4\x5C\x60"
+			  "\x01\x41\x21\x12\x38\xAB\x52\x4F"
+			  "\xA8\x57\x20",
+		.rlen	= 67,
+	},
+};
+
+static struct cipher_testvec tf_ctr_dec_tv_template[] = {
+	{ /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
+			  "\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
+		.input	= "\xDF\xDD\x69\xFA\xB0\x2E\xFD\xFE"
+			  "\x70\x9E\xC5\x4B\xC9\xD4\xA1\x30"
+			  "\x26\x9B\x89\xA1\xEE\x43\xE0\x52"
+			  "\x55\x17\x4E\xC7\x0E\x33\x1F\xF1"
+			  "\x9F\x8D\x40\x9F\x24\xFD\x92\xA0"
+			  "\xBC\x8F\x35\xDD\x67\x38\xD8\xAA"
+			  "\xCF\xF8\x48\xCA\xFB\xE4\x5C\x60"
+			  "\x01\x41\x21\x12\x38\xAB\x52\x4F",
+		.ilen	= 64,
+		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C",
+		.rlen	= 64,
+	}, { /* Generated with Crypto++ */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
+			  "\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
+		.input	= "\xDF\xDD\x69\xFA\xB0\x2E\xFD\xFE"
+			  "\x70\x9E\xC5\x4B\xC9\xD4\xA1\x30"
+			  "\x26\x9B\x89\xA1\xEE\x43\xE0\x52"
+			  "\x55\x17\x4E\xC7\x0E\x33\x1F\xF1"
+			  "\x9F\x8D\x40\x9F\x24\xFD\x92\xA0"
+			  "\xBC\x8F\x35\xDD\x67\x38\xD8\xAA"
+			  "\xCF\xF8\x48\xCA\xFB\xE4\x5C\x60"
+			  "\x01\x41\x21\x12\x38\xAB\x52\x4F"
+			  "\xA8\x57\x20",
+		.ilen	= 67,
+		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE",
+		.rlen	= 67,
 	},
 };
 
diff --git a/crypto/wp512.c b/crypto/wp512.c
index 7234272..71719a2 100644
--- a/crypto/wp512.c
+++ b/crypto/wp512.c
@@ -762,11 +762,17 @@ static const u64 C7[256] = {
 	0x86228644a411c286ULL,
 };
 
-static const u64 rc[WHIRLPOOL_ROUNDS + 1] = {
-	0x0000000000000000ULL, 0x1823c6e887b8014fULL, 0x36a6d2f5796f9152ULL,
-	0x60bc9b8ea30c7b35ULL, 0x1de0d7c22e4bfe57ULL, 0x157737e59ff04adaULL,
-	0x58c9290ab1a06b85ULL, 0xbd5d10f4cb3e0567ULL, 0xe427418ba77d95d8ULL,
-	0xfbee7c66dd17479eULL, 0xca2dbf07ad5a8333ULL,
+static const u64 rc[WHIRLPOOL_ROUNDS] = {
+	0x1823c6e887b8014fULL,
+	0x36a6d2f5796f9152ULL,
+	0x60bc9b8ea30c7b35ULL,
+	0x1de0d7c22e4bfe57ULL,
+	0x157737e59ff04adaULL,
+	0x58c9290ab1a06b85ULL,
+	0xbd5d10f4cb3e0567ULL,
+	0xe427418ba77d95d8ULL,
+	0xfbee7c66dd17479eULL,
+	0xca2dbf07ad5a8333ULL,
 };
 
 /**
@@ -793,7 +799,7 @@ static void wp512_process_buffer(struct wp512_ctx *wctx) {
 	state[6] = block[6] ^ (K[6] = wctx->hash[6]);
 	state[7] = block[7] ^ (K[7] = wctx->hash[7]);
 
-	for (r = 1; r <= WHIRLPOOL_ROUNDS; r++) {
+	for (r = 0; r < WHIRLPOOL_ROUNDS; r++) {
 
 		L[0] = C0[(int)(K[0] >> 56)       ] ^
 			   C1[(int)(K[7] >> 48) & 0xff] ^
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
index 2ca59dc..1274080 100644
--- a/drivers/acpi/apei/erst.c
+++ b/drivers/acpi/apei/erst.c
@@ -933,7 +933,7 @@ static int erst_open_pstore(struct pstore_info *psi);
 static int erst_close_pstore(struct pstore_info *psi);
 static ssize_t erst_reader(u64 *id, enum pstore_type_id *type,
 			   struct timespec *time, struct pstore_info *psi);
-static u64 erst_writer(enum pstore_type_id type, unsigned int part,
+static int erst_writer(enum pstore_type_id type, u64 *id, unsigned int part,
 		       size_t size, struct pstore_info *psi);
 static int erst_clearer(enum pstore_type_id type, u64 id,
 			struct pstore_info *psi);
@@ -1040,11 +1040,12 @@ out:
 	return (rc < 0) ? rc : (len - sizeof(*rcd));
 }
 
-static u64 erst_writer(enum pstore_type_id type, unsigned int part,
+static int erst_writer(enum pstore_type_id type, u64 *id, unsigned int part,
 		       size_t size, struct pstore_info *psi)
 {
 	struct cper_pstore_record *rcd = (struct cper_pstore_record *)
 					(erst_info.buf - sizeof(*rcd));
+	int ret;
 
 	memset(rcd, 0, sizeof(*rcd));
 	memcpy(rcd->hdr.signature, CPER_SIG_RECORD, CPER_SIG_SIZE);
@@ -1079,9 +1080,10 @@ static u64 erst_writer(enum pstore_type_id type, unsigned int part,
 	}
 	rcd->sec_hdr.section_severity = CPER_SEV_FATAL;
 
-	erst_write(&rcd->hdr);
+	ret = erst_write(&rcd->hdr);
+	*id = rcd->hdr.record_id;
 
-	return rcd->hdr.record_id;
+	return ret;
 }
 
 static int erst_clearer(enum pstore_type_id type, u64 id,
@@ -1165,7 +1167,7 @@ static int __init erst_init(void)
 		goto err_release_erange;
 
 	buf = kmalloc(erst_erange.size, GFP_KERNEL);
-	mutex_init(&erst_info.buf_mutex);
+	spin_lock_init(&erst_info.buf_lock);
 	if (buf) {
 		erst_info.buf = buf + sizeof(struct cper_pstore_record);
 		erst_info.bufsize = erst_erange.size -
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 079c088..e7a5750 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -8,10 +8,13 @@
 #include <linux/scatterlist.h>
 #include <linux/string_helpers.h>
 #include <scsi/scsi_cmnd.h>
+#include <linux/idr.h>
 
 #define PART_BITS 4
 
-static int major, index;
+static int major;
+static DEFINE_IDA(vd_index_ida);
+
 struct workqueue_struct *virtblk_wq;
 
 struct virtio_blk
@@ -35,6 +38,9 @@ struct virtio_blk
 	/* What host tells us, plus 2 for header & tailer. */
 	unsigned int sg_elems;
 
+	/* Ida index - used to track minor number allocations. */
+	int index;
+
 	/* Scatterlist: can be too big for stack. */
 	struct scatterlist sg[/*sg_elems*/];
 };
@@ -276,6 +282,11 @@ static int index_to_minor(int index)
 	return index << PART_BITS;
 }
 
+static int minor_to_index(int minor)
+{
+	return minor >> PART_BITS;
+}
+
 static ssize_t virtblk_serial_show(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
@@ -341,14 +352,17 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
 {
 	struct virtio_blk *vblk;
 	struct request_queue *q;
-	int err;
+	int err, index;
 	u64 cap;
 	u32 v, blk_size, sg_elems, opt_io_size;
 	u16 min_io_size;
 	u8 physical_block_exp, alignment_offset;
 
-	if (index_to_minor(index) >= 1 << MINORBITS)
-		return -ENOSPC;
+	err = ida_simple_get(&vd_index_ida, 0, minor_to_index(1 << MINORBITS),
+			     GFP_KERNEL);
+	if (err < 0)
+		goto out;
+	index = err;
 
 	/* We need to know how many segments before we allocate. */
 	err = virtio_config_val(vdev, VIRTIO_BLK_F_SEG_MAX,
@@ -365,7 +379,7 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
 				    sizeof(vblk->sg[0]) * sg_elems, GFP_KERNEL);
 	if (!vblk) {
 		err = -ENOMEM;
-		goto out;
+		goto out_free_index;
 	}
 
 	INIT_LIST_HEAD(&vblk->reqs);
@@ -421,7 +435,7 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
 	vblk->disk->private_data = vblk;
 	vblk->disk->fops = &virtblk_fops;
 	vblk->disk->driverfs_dev = &vdev->dev;
-	index++;
+	vblk->index = index;
 
 	/* configure queue flush support */
 	if (virtio_has_feature(vdev, VIRTIO_BLK_F_FLUSH))
@@ -516,6 +530,8 @@ out_free_vq:
 	vdev->config->del_vqs(vdev);
 out_free_vblk:
 	kfree(vblk);
+out_free_index:
+	ida_simple_remove(&vd_index_ida, index);
 out:
 	return err;
 }
@@ -523,6 +539,7 @@ out:
 static void __devexit virtblk_remove(struct virtio_device *vdev)
 {
 	struct virtio_blk *vblk = vdev->priv;
+	int index = vblk->index;
 
 	flush_work(&vblk->config_work);
 
@@ -538,6 +555,7 @@ static void __devexit virtblk_remove(struct virtio_device *vdev)
 	mempool_destroy(vblk->pool);
 	vdev->config->del_vqs(vdev);
 	kfree(vblk);
+	ida_simple_remove(&vd_index_ida, index);
 }
 
 static const struct virtio_device_id id_table[] = {
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 423fd56..4364303 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -298,7 +298,7 @@ if RTC_LIB=n
 config RTC
 	tristate "Enhanced Real Time Clock Support (legacy PC RTC driver)"
 	depends on !PPC && !PARISC && !IA64 && !M68K && !SPARC && !FRV \
-			&& !ARM && !SUPERH && !S390 && !AVR32 && !BLACKFIN
+			&& !ARM && !SUPERH && !S390 && !AVR32 && !BLACKFIN && !UML
 	---help---
 	  If you say Y here and create a character special file /dev/rtc with
 	  major number 10 and minor number 135 using mknod ("man mknod"), you
@@ -346,7 +346,7 @@ config JS_RTC
 
 config GEN_RTC
 	tristate "Generic /dev/rtc emulation"
-	depends on RTC!=y && !IA64 && !ARM && !M32R && !MIPS && !SPARC && !FRV && !S390 && !SUPERH && !AVR32 && !BLACKFIN
+	depends on RTC!=y && !IA64 && !ARM && !M32R && !MIPS && !SPARC && !FRV && !S390 && !SUPERH && !AVR32 && !BLACKFIN && !UML
 	---help---
 	  If you say Y here and create a character special file /dev/rtc with
 	  major number 10 and minor number 135 using mknod ("man mknod"), you
@@ -490,7 +490,7 @@ config SCx200_GPIO
 
 config PC8736x_GPIO
 	tristate "NatSemi PC8736x GPIO Support"
-	depends on X86_32
+	depends on X86_32 && !UML
 	default SCx200_GPIO	# mostly N
 	select NSC_GPIO		# needed for support routines
 	help
diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c
index 056b289..3695773 100644
--- a/drivers/char/agp/hp-agp.c
+++ b/drivers/char/agp/hp-agp.c
@@ -336,7 +336,8 @@ hp_zx1_insert_memory (struct agp_memory *mem, off_t pg_start, int type)
 	off_t j, io_pg_start;
 	int io_pg_count;
 
-	if (type != 0 || mem->type != 0) {
+	if (type != mem->type ||
+		agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type)) {
 		return -EINVAL;
 	}
 
@@ -380,7 +381,8 @@ hp_zx1_remove_memory (struct agp_memory *mem, off_t pg_start, int type)
 	struct _hp_private *hp = &hp_private;
 	int i, io_pg_start, io_pg_count;
 
-	if (type != 0 || mem->type != 0) {
+	if (type != mem->type ||
+		agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type)) {
 		return -EINVAL;
 	}
 
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index 1d2ebc7..0689bf6 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -60,6 +60,19 @@ config HW_RANDOM_AMD
 
 	  If unsure, say Y.
 
+config HW_RANDOM_ATMEL
+	tristate "Atmel Random Number Generator support"
+	depends on HW_RANDOM && ARCH_AT91SAM9G45
+	default HW_RANDOM
+	---help---
+	  This driver provides kernel-side support for the Random Number
+	  Generator hardware found on Atmel AT91 devices.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called atmel-rng.
+
+	  If unsure, say Y.
+
 config HW_RANDOM_GEODE
 	tristate "AMD Geode HW Random Number Generator support"
 	depends on HW_RANDOM && X86_32 && PCI
@@ -222,3 +235,18 @@ config HW_RANDOM_PPC4XX
 	 module will be called ppc4xx-rng.
 
 	 If unsure, say N.
+
+config UML_RANDOM
+	depends on UML
+	tristate "Hardware random number generator"
+	help
+	  This option enables UML's "hardware" random number generator.  It
+	  attaches itself to the host's /dev/random, supplying as much entropy
+	  as the host has, rather than the small amount the UML gets from its
+	  own drivers.  It registers itself as a standard hardware random number
+	  generator, major 10, minor 183, and the canonical device name is
+	  /dev/hwrng.
+	  The way to make use of this is to install the rng-tools package
+	  (check your distro, or download from
+	  http://sourceforge.net/projects/gkernel/).  rngd periodically reads
+	  /dev/hwrng and injects the entropy into /dev/random.
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index c88f244..b2ff526 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -7,6 +7,7 @@ rng-core-y := core.o
 obj-$(CONFIG_HW_RANDOM_TIMERIOMEM) += timeriomem-rng.o
 obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o
 obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o
+obj-$(CONFIG_HW_RANDOM_ATMEL) += atmel-rng.o
 obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o
 obj-$(CONFIG_HW_RANDOM_N2RNG) += n2-rng.o
 n2-rng-y := n2-drv.o n2-asm.o
diff --git a/drivers/char/hw_random/atmel-rng.c b/drivers/char/hw_random/atmel-rng.c
new file mode 100644
index 0000000..241df2e
--- /dev/null
+++ b/drivers/char/hw_random/atmel-rng.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2011 Peter Korsgaard <jacmet@sunsite.dk>
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/hw_random.h>
+#include <linux/platform_device.h>
+
+#define TRNG_CR		0x00
+#define TRNG_ISR	0x1c
+#define TRNG_ODATA	0x50
+
+#define TRNG_KEY	0x524e4700 /* RNG */
+
+struct atmel_trng {
+	struct clk *clk;
+	void __iomem *base;
+	struct hwrng rng;
+};
+
+static int atmel_trng_read(struct hwrng *rng, void *buf, size_t max,
+			   bool wait)
+{
+	struct atmel_trng *trng = container_of(rng, struct atmel_trng, rng);
+	u32 *data = buf;
+
+	/* data ready? */
+	if (readl(trng->base + TRNG_ODATA) & 1) {
+		*data = readl(trng->base + TRNG_ODATA);
+		return 4;
+	} else
+		return 0;
+}
+
+static int atmel_trng_probe(struct platform_device *pdev)
+{
+	struct atmel_trng *trng;
+	struct resource *res;
+	int ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
+
+	trng = devm_kzalloc(&pdev->dev, sizeof(*trng), GFP_KERNEL);
+	if (!trng)
+		return -ENOMEM;
+
+	if (!devm_request_mem_region(&pdev->dev, res->start,
+				     resource_size(res), pdev->name))
+		return -EBUSY;
+
+	trng->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!trng->base)
+		return -EBUSY;
+
+	trng->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(trng->clk))
+		return PTR_ERR(trng->clk);
+
+	ret = clk_enable(trng->clk);
+	if (ret)
+		goto err_enable;
+
+	writel(TRNG_KEY | 1, trng->base + TRNG_CR);
+	trng->rng.name = pdev->name;
+	trng->rng.read = atmel_trng_read;
+
+	ret = hwrng_register(&trng->rng);
+	if (ret)
+		goto err_register;
+
+	platform_set_drvdata(pdev, trng);
+
+	return 0;
+
+err_register:
+	clk_disable(trng->clk);
+err_enable:
+	clk_put(trng->clk);
+
+	return ret;
+}
+
+static int __devexit atmel_trng_remove(struct platform_device *pdev)
+{
+	struct atmel_trng *trng = platform_get_drvdata(pdev);
+
+	hwrng_unregister(&trng->rng);
+
+	writel(TRNG_KEY, trng->base + TRNG_CR);
+	clk_disable(trng->clk);
+	clk_put(trng->clk);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int atmel_trng_suspend(struct device *dev)
+{
+	struct atmel_trng *trng = dev_get_drvdata(dev);
+
+	clk_disable(trng->clk);
+
+	return 0;
+}
+
+static int atmel_trng_resume(struct device *dev)
+{
+	struct atmel_trng *trng = dev_get_drvdata(dev);
+
+	return clk_enable(trng->clk);
+}
+
+static const struct dev_pm_ops atmel_trng_pm_ops = {
+	.suspend	= atmel_trng_suspend,
+	.resume		= atmel_trng_resume,
+};
+#endif /* CONFIG_PM */
+
+static struct platform_driver atmel_trng_driver = {
+	.probe		= atmel_trng_probe,
+	.remove		= __devexit_p(atmel_trng_remove),
+	.driver		= {
+		.name	= "atmel-trng",
+		.owner	= THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm	= &atmel_trng_pm_ops,
+#endif /* CONFIG_PM */
+	},
+};
+
+static int __init atmel_trng_init(void)
+{
+	return platform_driver_register(&atmel_trng_driver);
+}
+module_init(atmel_trng_init);
+
+static void __exit atmel_trng_exit(void)
+{
+	platform_driver_unregister(&atmel_trng_driver);
+}
+module_exit(atmel_trng_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>");
+MODULE_DESCRIPTION("Atmel true random number generator driver");
diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c
index a1f68af..f228615 100644
--- a/drivers/char/ttyprintk.c
+++ b/drivers/char/ttyprintk.c
@@ -170,7 +170,7 @@ static const struct tty_operations ttyprintk_ops = {
 	.ioctl = tpk_ioctl,
 };
 
-struct tty_port_operations null_ops = { };
+static struct tty_port_operations null_ops = { };
 
 static struct tty_driver *ttyprintk_driver;
 
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index fb68b12..4ca181f 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -19,8 +19,10 @@
  */
 #include <linux/cdev.h>
 #include <linux/debugfs.h>
+#include <linux/completion.h>
 #include <linux/device.h>
 #include <linux/err.h>
+#include <linux/freezer.h>
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/list.h>
@@ -73,6 +75,7 @@ struct ports_driver_data {
 static struct ports_driver_data pdrvdata;
 
 DEFINE_SPINLOCK(pdrvdata_lock);
+DECLARE_COMPLETION(early_console_added);
 
 /* This struct holds information that's relevant only for console ports */
 struct console {
@@ -151,6 +154,10 @@ struct ports_device {
 	int chr_major;
 };
 
+struct port_stats {
+	unsigned long bytes_sent, bytes_received, bytes_discarded;
+};
+
 /* This struct holds the per-port data */
 struct port {
 	/* Next port in the list, head is in the ports_device */
@@ -179,6 +186,13 @@ struct port {
 	struct dentry *debugfs_file;
 
 	/*
+	 * Keep count of the bytes sent, received and discarded for
+	 * this port for accounting and debugging purposes.  These
+	 * counts are not reset across port open / close events.
+	 */
+	struct port_stats stats;
+
+	/*
 	 * The entries in this struct will be valid if this port is
 	 * hooked up to an hvc console
 	 */
@@ -347,17 +361,19 @@ fail:
 }
 
 /* Callers should take appropriate locks */
-static void *get_inbuf(struct port *port)
+static struct port_buffer *get_inbuf(struct port *port)
 {
 	struct port_buffer *buf;
-	struct virtqueue *vq;
 	unsigned int len;
 
-	vq = port->in_vq;
-	buf = virtqueue_get_buf(vq, &len);
+	if (port->inbuf)
+		return port->inbuf;
+
+	buf = virtqueue_get_buf(port->in_vq, &len);
 	if (buf) {
 		buf->len = len;
 		buf->offset = 0;
+		port->stats.bytes_received += len;
 	}
 	return buf;
 }
@@ -384,32 +400,27 @@ static int add_inbuf(struct virtqueue *vq, struct port_buffer *buf)
 static void discard_port_data(struct port *port)
 {
 	struct port_buffer *buf;
-	struct virtqueue *vq;
-	unsigned int len;
-	int ret;
+	unsigned int err;
 
 	if (!port->portdev) {
 		/* Device has been unplugged.  vqs are already gone. */
 		return;
 	}
-	vq = port->in_vq;
-	if (port->inbuf)
-		buf = port->inbuf;
-	else
-		buf = virtqueue_get_buf(vq, &len);
+	buf = get_inbuf(port);
 
-	ret = 0;
+	err = 0;
 	while (buf) {
-		if (add_inbuf(vq, buf) < 0) {
-			ret++;
+		port->stats.bytes_discarded += buf->len - buf->offset;
+		if (add_inbuf(port->in_vq, buf) < 0) {
+			err++;
 			free_buf(buf);
 		}
-		buf = virtqueue_get_buf(vq, &len);
+		port->inbuf = NULL;
+		buf = get_inbuf(port);
 	}
-	port->inbuf = NULL;
-	if (ret)
+	if (err)
 		dev_warn(port->dev, "Errors adding %d buffers back to vq\n",
-			 ret);
+			 err);
 }
 
 static bool port_has_data(struct port *port)
@@ -417,18 +428,12 @@ static bool port_has_data(struct port *port)
 	unsigned long flags;
 	bool ret;
 
+	ret = false;
 	spin_lock_irqsave(&port->inbuf_lock, flags);
-	if (port->inbuf) {
-		ret = true;
-		goto out;
-	}
 	port->inbuf = get_inbuf(port);
-	if (port->inbuf) {
+	if (port->inbuf)
 		ret = true;
-		goto out;
-	}
-	ret = false;
-out:
+
 	spin_unlock_irqrestore(&port->inbuf_lock, flags);
 	return ret;
 }
@@ -529,6 +534,8 @@ static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count,
 		cpu_relax();
 done:
 	spin_unlock_irqrestore(&port->outvq_lock, flags);
+
+	port->stats.bytes_sent += in_count;
 	/*
 	 * We're expected to return the amount of data we wrote -- all
 	 * of it
@@ -633,8 +640,8 @@ static ssize_t port_fops_read(struct file *filp, char __user *ubuf,
 		if (filp->f_flags & O_NONBLOCK)
 			return -EAGAIN;
 
-		ret = wait_event_interruptible(port->waitqueue,
-					       !will_read_block(port));
+		ret = wait_event_freezable(port->waitqueue,
+					   !will_read_block(port));
 		if (ret < 0)
 			return ret;
 	}
@@ -677,8 +684,8 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf,
 		if (nonblock)
 			return -EAGAIN;
 
-		ret = wait_event_interruptible(port->waitqueue,
-					       !will_write_block(port));
+		ret = wait_event_freezable(port->waitqueue,
+					   !will_write_block(port));
 		if (ret < 0)
 			return ret;
 	}
@@ -1059,6 +1066,14 @@ static ssize_t debugfs_read(struct file *filp, char __user *ubuf,
 	out_offset += snprintf(buf + out_offset, out_count - out_offset,
 			       "outvq_full: %d\n", port->outvq_full);
 	out_offset += snprintf(buf + out_offset, out_count - out_offset,
+			       "bytes_sent: %lu\n", port->stats.bytes_sent);
+	out_offset += snprintf(buf + out_offset, out_count - out_offset,
+			       "bytes_received: %lu\n",
+			       port->stats.bytes_received);
+	out_offset += snprintf(buf + out_offset, out_count - out_offset,
+			       "bytes_discarded: %lu\n",
+			       port->stats.bytes_discarded);
+	out_offset += snprintf(buf + out_offset, out_count - out_offset,
 			       "is_console: %s\n",
 			       is_console_port(port) ? "yes" : "no");
 	out_offset += snprintf(buf + out_offset, out_count - out_offset,
@@ -1143,6 +1158,7 @@ static int add_port(struct ports_device *portdev, u32 id)
 	port->cons.ws.ws_row = port->cons.ws.ws_col = 0;
 
 	port->host_connected = port->guest_connected = false;
+	port->stats = (struct port_stats) { 0 };
 
 	port->outvq_full = false;
 
@@ -1352,6 +1368,7 @@ static void handle_control_message(struct ports_device *portdev,
 			break;
 
 		init_port_console(port);
+		complete(&early_console_added);
 		/*
 		 * Could remove the port here in case init fails - but
 		 * have to notify the host first.
@@ -1394,6 +1411,13 @@ static void handle_control_message(struct ports_device *portdev,
 		break;
 	case VIRTIO_CONSOLE_PORT_NAME:
 		/*
+		 * If we woke up after hibernation, we can get this
+		 * again.  Skip it in that case.
+		 */
+		if (port->name)
+			break;
+
+		/*
 		 * Skip the size of the header and the cpkt to get the size
 		 * of the name that was sent
 		 */
@@ -1481,8 +1505,7 @@ static void in_intr(struct virtqueue *vq)
 		return;
 
 	spin_lock_irqsave(&port->inbuf_lock, flags);
-	if (!port->inbuf)
-		port->inbuf = get_inbuf(port);
+	port->inbuf = get_inbuf(port);
 
 	/*
 	 * Don't queue up data when port is closed.  This condition
@@ -1563,7 +1586,7 @@ static int init_vqs(struct ports_device *portdev)
 	portdev->out_vqs = kmalloc(nr_ports * sizeof(struct virtqueue *),
 				   GFP_KERNEL);
 	if (!vqs || !io_callbacks || !io_names || !portdev->in_vqs ||
-			!portdev->out_vqs) {
+	    !portdev->out_vqs) {
 		err = -ENOMEM;
 		goto free;
 	}
@@ -1648,6 +1671,10 @@ static int __devinit virtcons_probe(struct virtio_device *vdev)
 	struct ports_device *portdev;
 	int err;
 	bool multiport;
+	bool early = early_put_chars != NULL;
+
+	/* Ensure to read early_put_chars now */
+	barrier();
 
 	portdev = kmalloc(sizeof(*portdev), GFP_KERNEL);
 	if (!portdev) {
@@ -1675,13 +1702,11 @@ static int __devinit virtcons_probe(struct virtio_device *vdev)
 
 	multiport = false;
 	portdev->config.max_nr_ports = 1;
-	if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT)) {
+	if (virtio_config_val(vdev, VIRTIO_CONSOLE_F_MULTIPORT,
+			      offsetof(struct virtio_console_config,
+				       max_nr_ports),
+			      &portdev->config.max_nr_ports) == 0)
 		multiport = true;
-		vdev->config->get(vdev, offsetof(struct virtio_console_config,
-						 max_nr_ports),
-				  &portdev->config.max_nr_ports,
-				  sizeof(portdev->config.max_nr_ports));
-	}
 
 	err = init_vqs(portdev);
 	if (err < 0) {
@@ -1719,6 +1744,19 @@ static int __devinit virtcons_probe(struct virtio_device *vdev)
 
 	__send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID,
 			   VIRTIO_CONSOLE_DEVICE_READY, 1);
+
+	/*
+	 * If there was an early virtio console, assume that there are no
+	 * other consoles. We need to wait until the hvc_alloc matches the
+	 * hvc_instantiate, otherwise tty_open will complain, resulting in
+	 * a "Warning: unable to open an initial console" boot failure.
+	 * Without multiport this is done in add_port above. With multiport
+	 * this might take some host<->guest communication - thus we have to
+	 * wait.
+	 */
+	if (multiport && early)
+		wait_for_completion(&early_console_added);
+
 	return 0;
 
 free_vqs:
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 34e9c4f..999d6a0 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -15,3 +15,18 @@ config CLKSRC_MMIO
 
 config DW_APB_TIMER
 	bool
+
+config CLKSRC_DBX500_PRCMU
+	bool "Clocksource PRCMU Timer"
+	depends on UX500_SOC_DB5500 || UX500_SOC_DB8500
+	default y
+	help
+	  Use the always on PRCMU Timer as clocksource
+
+config CLKSRC_DBX500_PRCMU_SCHED_CLOCK
+	bool "Clocksource PRCMU Timer sched_clock"
+	depends on (CLKSRC_DBX500_PRCMU && !NOMADIK_MTU_SCHED_CLOCK)
+	select HAVE_SCHED_CLOCK
+	default y
+	help
+	  Use the always on PRCMU Timer as sched_clock
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 85ad1646..8d81a1d 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_SH_TIMER_TMU)	+= sh_tmu.o
 obj-$(CONFIG_CLKBLD_I8253)	+= i8253.o
 obj-$(CONFIG_CLKSRC_MMIO)	+= mmio.o
 obj-$(CONFIG_DW_APB_TIMER)	+= dw_apb_timer.o
+obj-$(CONFIG_CLKSRC_DBX500_PRCMU)	+= clksrc-dbx500-prcmu.o
\ No newline at end of file
diff --git a/drivers/clocksource/clksrc-dbx500-prcmu.c b/drivers/clocksource/clksrc-dbx500-prcmu.c
new file mode 100644
index 0000000..59feefe
--- /dev/null
+++ b/drivers/clocksource/clksrc-dbx500-prcmu.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Mattias Wallin <mattias.wallin@stericsson.com> for ST-Ericsson
+ * Author: Sundar Iyer for ST-Ericsson
+ * sched_clock implementation is based on:
+ * plat-nomadik/timer.c Linus Walleij <linus.walleij@stericsson.com>
+ *
+ * DBx500-PRCMU Timer
+ * The PRCMU has 5 timers which are available in a always-on
+ * power domain.  We use the Timer 4 for our always-on clock
+ * source on DB8500 and Timer 3 on DB5500.
+ */
+#include <linux/clockchips.h>
+#include <linux/clksrc-dbx500-prcmu.h>
+
+#include <asm/sched_clock.h>
+
+#include <mach/setup.h>
+#include <mach/hardware.h>
+
+#define RATE_32K		32768
+
+#define TIMER_MODE_CONTINOUS	0x1
+#define TIMER_DOWNCOUNT_VAL	0xffffffff
+
+#define PRCMU_TIMER_REF		0
+#define PRCMU_TIMER_DOWNCOUNT	0x4
+#define PRCMU_TIMER_MODE	0x8
+
+#define SCHED_CLOCK_MIN_WRAP 131072 /* 2^32 / 32768 */
+
+static void __iomem *clksrc_dbx500_timer_base;
+
+static cycle_t clksrc_dbx500_prcmu_read(struct clocksource *cs)
+{
+	u32 count, count2;
+
+	do {
+		count = readl(clksrc_dbx500_timer_base +
+			      PRCMU_TIMER_DOWNCOUNT);
+		count2 = readl(clksrc_dbx500_timer_base +
+			       PRCMU_TIMER_DOWNCOUNT);
+	} while (count2 != count);
+
+	/* Negate because the timer is a decrementing counter */
+	return ~count;
+}
+
+static struct clocksource clocksource_dbx500_prcmu = {
+	.name		= "dbx500-prcmu-timer",
+	.rating		= 300,
+	.read		= clksrc_dbx500_prcmu_read,
+	.shift		= 10,
+	.mask		= CLOCKSOURCE_MASK(32),
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+#ifdef CONFIG_CLKSRC_DBX500_PRCMU_SCHED_CLOCK
+static DEFINE_CLOCK_DATA(cd);
+
+unsigned long long notrace sched_clock(void)
+{
+	u32 cyc;
+
+	if (unlikely(!clksrc_dbx500_timer_base))
+		return 0;
+
+	cyc = clksrc_dbx500_prcmu_read(&clocksource_dbx500_prcmu);
+
+	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
+}
+
+static void notrace clksrc_dbx500_prcmu_update_sched_clock(void)
+{
+	u32 cyc = clksrc_dbx500_prcmu_read(&clocksource_dbx500_prcmu);
+	update_sched_clock(&cd, cyc, (u32)~0);
+}
+#endif
+
+void __init clksrc_dbx500_prcmu_init(void __iomem *base)
+{
+	clksrc_dbx500_timer_base = base;
+
+	/*
+	 * The A9 sub system expects the timer to be configured as
+	 * a continous looping timer.
+	 * The PRCMU should configure it but if it for some reason
+	 * don't we do it here.
+	 */
+	if (readl(clksrc_dbx500_timer_base + PRCMU_TIMER_MODE) !=
+	    TIMER_MODE_CONTINOUS) {
+		writel(TIMER_MODE_CONTINOUS,
+		       clksrc_dbx500_timer_base + PRCMU_TIMER_MODE);
+		writel(TIMER_DOWNCOUNT_VAL,
+		       clksrc_dbx500_timer_base + PRCMU_TIMER_REF);
+	}
+#ifdef CONFIG_CLKSRC_DBX500_PRCMU_SCHED_CLOCK
+	init_sched_clock(&cd, clksrc_dbx500_prcmu_update_sched_clock,
+			 32, RATE_32K);
+#endif
+	clocksource_calc_mult_shift(&clocksource_dbx500_prcmu,
+				    RATE_32K, SCHED_CLOCK_MIN_WRAP);
+	clocksource_register(&clocksource_dbx500_prcmu);
+}
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index e0b25de..6d16b4b 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -200,6 +200,7 @@ config CRYPTO_DEV_HIFN_795X
 	select CRYPTO_BLKCIPHER
 	select HW_RANDOM if CRYPTO_DEV_HIFN_795X_RNG
 	depends on PCI
+	depends on !ARCH_DMA_ADDR_T_64BIT
 	help
 	  This option allows you to have support for HIFN 795x crypto adapters.
 
@@ -266,7 +267,7 @@ config CRYPTO_DEV_OMAP_AES
 
 config CRYPTO_DEV_PICOXCELL
 	tristate "Support for picoXcell IPSEC and Layer2 crypto engines"
-	depends on ARCH_PICOXCELL
+	depends on ARCH_PICOXCELL && HAVE_CLK
 	select CRYPTO_AES
 	select CRYPTO_AUTHENC
 	select CRYPTO_ALGAPI
diff --git a/drivers/crypto/hifn_795x.c b/drivers/crypto/hifn_795x.c
index a84250a..fe765f4 100644
--- a/drivers/crypto/hifn_795x.c
+++ b/drivers/crypto/hifn_795x.c
@@ -2744,10 +2744,8 @@ static int __init hifn_init(void)
 	unsigned int freq;
 	int err;
 
-	if (sizeof(dma_addr_t) > 4) {
-		printk(KERN_INFO "HIFN supports only 32-bit addresses.\n");
-		return -EINVAL;
-	}
+	/* HIFN supports only 32-bit addresses */
+	BUILD_BUG_ON(sizeof(dma_addr_t) != 4);
 
 	if (strncmp(hifn_pll_ref, "ext", 3) &&
 	    strncmp(hifn_pll_ref, "pci", 3)) {
diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c
index d0183dd..8944dab 100644
--- a/drivers/crypto/n2_core.c
+++ b/drivers/crypto/n2_core.c
@@ -1006,9 +1006,9 @@ static int n2_do_ecb(struct ablkcipher_request *req, bool encrypt)
 
 	spin_unlock_irqrestore(&qp->lock, flags);
 
+out:
 	put_cpu();
 
-out:
 	n2_chunk_complete(req, NULL);
 	return err;
 }
@@ -1096,9 +1096,9 @@ static int n2_do_chaining(struct ablkcipher_request *req, bool encrypt)
 
 	spin_unlock_irqrestore(&qp->lock, flags);
 
+out:
 	put_cpu();
 
-out:
 	n2_chunk_complete(req, err ? NULL : final_iv_addr);
 	return err;
 }
diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c
index db33d30..29b9469 100644
--- a/drivers/crypto/padlock-aes.c
+++ b/drivers/crypto/padlock-aes.c
@@ -508,10 +508,8 @@ static int __init padlock_init(void)
 	int ret;
 	struct cpuinfo_x86 *c = &cpu_data(0);
 
-	if (!cpu_has_xcrypt) {
-		printk(KERN_NOTICE PFX "VIA PadLock not detected.\n");
+	if (!cpu_has_xcrypt)
 		return -ENODEV;
-	}
 
 	if (!cpu_has_xcrypt_enabled) {
 		printk(KERN_NOTICE PFX "VIA PadLock detected, but not enabled. Hmm, strange...\n");
diff --git a/drivers/crypto/picoxcell_crypto.c b/drivers/crypto/picoxcell_crypto.c
index 230b5b8..a2b553e 100644
--- a/drivers/crypto/picoxcell_crypto.c
+++ b/drivers/crypto/picoxcell_crypto.c
@@ -34,6 +34,7 @@
 #include <linux/io.h>
 #include <linux/list.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
 #include <linux/rtnetlink.h>
@@ -1241,8 +1242,8 @@ static void spacc_spacc_complete(unsigned long data)
 	spin_unlock_irqrestore(&engine->hw_lock, flags);
 
 	list_for_each_entry_safe(req, tmp, &completed, list) {
-		req->complete(req);
 		list_del(&req->list);
+		req->complete(req);
 	}
 }
 
@@ -1657,10 +1658,33 @@ static struct spacc_alg l2_engine_algs[] = {
 	},
 };
 
-static int __devinit spacc_probe(struct platform_device *pdev,
-				 unsigned max_ctxs, size_t cipher_pg_sz,
-				 size_t hash_pg_sz, size_t fifo_sz,
-				 struct spacc_alg *algs, size_t num_algs)
+#ifdef CONFIG_OF
+static const struct of_device_id spacc_of_id_table[] = {
+	{ .compatible = "picochip,spacc-ipsec" },
+	{ .compatible = "picochip,spacc-l2" },
+	{}
+};
+#else /* CONFIG_OF */
+#define spacc_of_id_table NULL
+#endif /* CONFIG_OF */
+
+static bool spacc_is_compatible(struct platform_device *pdev,
+				const char *spacc_type)
+{
+	const struct platform_device_id *platid = platform_get_device_id(pdev);
+
+	if (platid && !strcmp(platid->name, spacc_type))
+		return true;
+
+#ifdef CONFIG_OF
+	if (of_device_is_compatible(pdev->dev.of_node, spacc_type))
+		return true;
+#endif /* CONFIG_OF */
+
+	return false;
+}
+
+static int __devinit spacc_probe(struct platform_device *pdev)
 {
 	int i, err, ret = -EINVAL;
 	struct resource *mem, *irq;
@@ -1669,13 +1693,25 @@ static int __devinit spacc_probe(struct platform_device *pdev,
 	if (!engine)
 		return -ENOMEM;
 
-	engine->max_ctxs	= max_ctxs;
-	engine->cipher_pg_sz	= cipher_pg_sz;
-	engine->hash_pg_sz	= hash_pg_sz;
-	engine->fifo_sz		= fifo_sz;
-	engine->algs		= algs;
-	engine->num_algs	= num_algs;
-	engine->name		= dev_name(&pdev->dev);
+	if (spacc_is_compatible(pdev, "picochip,spacc-ipsec")) {
+		engine->max_ctxs	= SPACC_CRYPTO_IPSEC_MAX_CTXS;
+		engine->cipher_pg_sz	= SPACC_CRYPTO_IPSEC_CIPHER_PG_SZ;
+		engine->hash_pg_sz	= SPACC_CRYPTO_IPSEC_HASH_PG_SZ;
+		engine->fifo_sz		= SPACC_CRYPTO_IPSEC_FIFO_SZ;
+		engine->algs		= ipsec_engine_algs;
+		engine->num_algs	= ARRAY_SIZE(ipsec_engine_algs);
+	} else if (spacc_is_compatible(pdev, "picochip,spacc-l2")) {
+		engine->max_ctxs	= SPACC_CRYPTO_L2_MAX_CTXS;
+		engine->cipher_pg_sz	= SPACC_CRYPTO_L2_CIPHER_PG_SZ;
+		engine->hash_pg_sz	= SPACC_CRYPTO_L2_HASH_PG_SZ;
+		engine->fifo_sz		= SPACC_CRYPTO_L2_FIFO_SZ;
+		engine->algs		= l2_engine_algs;
+		engine->num_algs	= ARRAY_SIZE(l2_engine_algs);
+	} else {
+		return -EINVAL;
+	}
+
+	engine->name = dev_name(&pdev->dev);
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
@@ -1711,7 +1747,7 @@ static int __devinit spacc_probe(struct platform_device *pdev,
 
 	spin_lock_init(&engine->hw_lock);
 
-	engine->clk = clk_get(&pdev->dev, NULL);
+	engine->clk = clk_get(&pdev->dev, "ref");
 	if (IS_ERR(engine->clk)) {
 		dev_info(&pdev->dev, "clk unavailable\n");
 		device_remove_file(&pdev->dev, &dev_attr_stat_irq_thresh);
@@ -1800,72 +1836,33 @@ static int __devexit spacc_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devinit ipsec_probe(struct platform_device *pdev)
-{
-	return spacc_probe(pdev, SPACC_CRYPTO_IPSEC_MAX_CTXS,
-			   SPACC_CRYPTO_IPSEC_CIPHER_PG_SZ,
-			   SPACC_CRYPTO_IPSEC_HASH_PG_SZ,
-			   SPACC_CRYPTO_IPSEC_FIFO_SZ, ipsec_engine_algs,
-			   ARRAY_SIZE(ipsec_engine_algs));
-}
-
-static struct platform_driver ipsec_driver = {
-	.probe		= ipsec_probe,
-	.remove		= __devexit_p(spacc_remove),
-	.driver		= {
-		.name	= "picoxcell-ipsec",
-#ifdef CONFIG_PM
-		.pm	= &spacc_pm_ops,
-#endif /* CONFIG_PM */
-	},
+static const struct platform_device_id spacc_id_table[] = {
+	{ "picochip,spacc-ipsec", },
+	{ "picochip,spacc-l2", },
 };
 
-static int __devinit l2_probe(struct platform_device *pdev)
-{
-	return spacc_probe(pdev, SPACC_CRYPTO_L2_MAX_CTXS,
-			   SPACC_CRYPTO_L2_CIPHER_PG_SZ,
-			   SPACC_CRYPTO_L2_HASH_PG_SZ, SPACC_CRYPTO_L2_FIFO_SZ,
-			   l2_engine_algs, ARRAY_SIZE(l2_engine_algs));
-}
-
-static struct platform_driver l2_driver = {
-	.probe		= l2_probe,
+static struct platform_driver spacc_driver = {
+	.probe		= spacc_probe,
 	.remove		= __devexit_p(spacc_remove),
 	.driver		= {
-		.name	= "picoxcell-l2",
+		.name	= "picochip,spacc",
 #ifdef CONFIG_PM
 		.pm	= &spacc_pm_ops,
 #endif /* CONFIG_PM */
+		.of_match_table	= spacc_of_id_table,
 	},
+	.id_table	= spacc_id_table,
 };
 
 static int __init spacc_init(void)
 {
-	int ret = platform_driver_register(&ipsec_driver);
-	if (ret) {
-		pr_err("failed to register ipsec spacc driver");
-		goto out;
-	}
-
-	ret = platform_driver_register(&l2_driver);
-	if (ret) {
-		pr_err("failed to register l2 spacc driver");
-		goto l2_failed;
-	}
-
-	return 0;
-
-l2_failed:
-	platform_driver_unregister(&ipsec_driver);
-out:
-	return ret;
+	return platform_driver_register(&spacc_driver);
 }
 module_init(spacc_init);
 
 static void __exit spacc_exit(void)
 {
-	platform_driver_unregister(&ipsec_driver);
-	platform_driver_unregister(&l2_driver);
+	platform_driver_unregister(&spacc_driver);
 }
 module_exit(spacc_exit);
 
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index 8a0bb41..dbe76b5 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -416,7 +416,7 @@ static void talitos_done(unsigned long data)
 /*
  * locate current (offending) descriptor
  */
-static struct talitos_desc *current_desc(struct device *dev, int ch)
+static u32 current_desc_hdr(struct device *dev, int ch)
 {
 	struct talitos_private *priv = dev_get_drvdata(dev);
 	int tail = priv->chan[ch].tail;
@@ -428,23 +428,25 @@ static struct talitos_desc *current_desc(struct device *dev, int ch)
 		tail = (tail + 1) & (priv->fifo_len - 1);
 		if (tail == priv->chan[ch].tail) {
 			dev_err(dev, "couldn't locate current descriptor\n");
-			return NULL;
+			return 0;
 		}
 	}
 
-	return priv->chan[ch].fifo[tail].desc;
+	return priv->chan[ch].fifo[tail].desc->hdr;
 }
 
 /*
  * user diagnostics; report root cause of error based on execution unit status
  */
-static void report_eu_error(struct device *dev, int ch,
-			    struct talitos_desc *desc)
+static void report_eu_error(struct device *dev, int ch, u32 desc_hdr)
 {
 	struct talitos_private *priv = dev_get_drvdata(dev);
 	int i;
 
-	switch (desc->hdr & DESC_HDR_SEL0_MASK) {
+	if (!desc_hdr)
+		desc_hdr = in_be32(priv->reg + TALITOS_DESCBUF(ch));
+
+	switch (desc_hdr & DESC_HDR_SEL0_MASK) {
 	case DESC_HDR_SEL0_AFEU:
 		dev_err(dev, "AFEUISR 0x%08x_%08x\n",
 			in_be32(priv->reg + TALITOS_AFEUISR),
@@ -488,7 +490,7 @@ static void report_eu_error(struct device *dev, int ch,
 		break;
 	}
 
-	switch (desc->hdr & DESC_HDR_SEL1_MASK) {
+	switch (desc_hdr & DESC_HDR_SEL1_MASK) {
 	case DESC_HDR_SEL1_MDEUA:
 	case DESC_HDR_SEL1_MDEUB:
 		dev_err(dev, "MDEUISR 0x%08x_%08x\n",
@@ -550,7 +552,7 @@ static void talitos_error(unsigned long data, u32 isr, u32 isr_lo)
 		if (v_lo & TALITOS_CCPSR_LO_IEU)
 			dev_err(dev, "invalid execution unit error\n");
 		if (v_lo & TALITOS_CCPSR_LO_EU)
-			report_eu_error(dev, ch, current_desc(dev, ch));
+			report_eu_error(dev, ch, current_desc_hdr(dev, ch));
 		if (v_lo & TALITOS_CCPSR_LO_GB)
 			dev_err(dev, "gather boundary error\n");
 		if (v_lo & TALITOS_CCPSR_LO_GRL)
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index af1a17d..203361e 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -41,7 +41,7 @@ config EDAC_DEBUG
 
 config EDAC_DECODE_MCE
 	tristate "Decode MCEs in human-readable form (only on AMD for now)"
-	depends on CPU_SUP_AMD && X86_MCE
+	depends on CPU_SUP_AMD && X86_MCE_AMD
 	default y
 	---help---
 	  Enable this option if you want to decode Machine Check Exceptions
@@ -71,9 +71,6 @@ config EDAC_MM_EDAC
 	  occurred so that a particular failing memory module can be
 	  replaced.  If unsure, select 'Y'.
 
-config EDAC_MCE
-	bool
-
 config EDAC_AMD64
 	tristate "AMD64 (Opteron, Athlon64) K8, F10h"
 	depends on EDAC_MM_EDAC && AMD_NB && X86_64 && EDAC_DECODE_MCE
@@ -173,8 +170,7 @@ config EDAC_I5400
 
 config EDAC_I7CORE
 	tristate "Intel i7 Core (Nehalem) processors"
-	depends on EDAC_MM_EDAC && PCI && X86
-	select EDAC_MCE
+	depends on EDAC_MM_EDAC && PCI && X86 && X86_MCE_INTEL
 	help
 	  Support for error detection and correction the Intel
 	  i7 Core (Nehalem) Integrated Memory Controller that exists on
@@ -216,6 +212,14 @@ config EDAC_I7300
 	  Support for error detection and correction the Intel
 	  Clarksboro MCH (Intel 7300 chipset).
 
+config EDAC_SBRIDGE
+	tristate "Intel Sandy-Bridge Integrated MC"
+	depends on EDAC_MM_EDAC && PCI && X86 && X86_MCE_INTEL
+	depends on EXPERIMENTAL
+	help
+	  Support for error detection and correction the Intel
+	  Sandy Bridge Integrated Memory Controller.
+
 config EDAC_MPC85XX
 	tristate "Freescale MPC83xx / MPC85xx"
 	depends on EDAC_MM_EDAC && FSL_SOC && (PPC_83xx || PPC_85xx)
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index 3e23913..196a63d 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -8,7 +8,6 @@
 
 obj-$(CONFIG_EDAC)			:= edac_stub.o
 obj-$(CONFIG_EDAC_MM_EDAC)		+= edac_core.o
-obj-$(CONFIG_EDAC_MCE)			+= edac_mce.o
 
 edac_core-y	:= edac_mc.o edac_device.o edac_mc_sysfs.o edac_pci_sysfs.o
 edac_core-y	+= edac_module.o edac_device_sysfs.o
@@ -29,6 +28,7 @@ obj-$(CONFIG_EDAC_I5100)		+= i5100_edac.o
 obj-$(CONFIG_EDAC_I5400)		+= i5400_edac.o
 obj-$(CONFIG_EDAC_I7300)		+= i7300_edac.o
 obj-$(CONFIG_EDAC_I7CORE)		+= i7core_edac.o
+obj-$(CONFIG_EDAC_SBRIDGE)		+= sb_edac.o
 obj-$(CONFIG_EDAC_E7XXX)		+= e7xxx_edac.o
 obj-$(CONFIG_EDAC_E752X)		+= e752x_edac.o
 obj-$(CONFIG_EDAC_I82443BXGX)		+= i82443bxgx_edac.o
diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h
index 55b8278..fe90cd4 100644
--- a/drivers/edac/edac_core.h
+++ b/drivers/edac/edac_core.h
@@ -34,11 +34,10 @@
 #include <linux/platform_device.h>
 #include <linux/sysdev.h>
 #include <linux/workqueue.h>
+#include <linux/edac.h>
 
-#define EDAC_MC_LABEL_LEN	31
 #define EDAC_DEVICE_NAME_LEN	31
 #define EDAC_ATTRIB_VALUE_LEN	15
-#define MC_PROC_NAME_MAX_LEN	7
 
 #if PAGE_SHIFT < 20
 #define PAGES_TO_MiB(pages)	((pages) >> (20 - PAGE_SHIFT))
@@ -101,353 +100,6 @@ extern int edac_debug_level;
 
 #define edac_dev_name(dev) (dev)->dev_name
 
-/* memory devices */
-enum dev_type {
-	DEV_UNKNOWN = 0,
-	DEV_X1,
-	DEV_X2,
-	DEV_X4,
-	DEV_X8,
-	DEV_X16,
-	DEV_X32,		/* Do these parts exist? */
-	DEV_X64			/* Do these parts exist? */
-};
-
-#define DEV_FLAG_UNKNOWN	BIT(DEV_UNKNOWN)
-#define DEV_FLAG_X1		BIT(DEV_X1)
-#define DEV_FLAG_X2		BIT(DEV_X2)
-#define DEV_FLAG_X4		BIT(DEV_X4)
-#define DEV_FLAG_X8		BIT(DEV_X8)
-#define DEV_FLAG_X16		BIT(DEV_X16)
-#define DEV_FLAG_X32		BIT(DEV_X32)
-#define DEV_FLAG_X64		BIT(DEV_X64)
-
-/* memory types */
-enum mem_type {
-	MEM_EMPTY = 0,		/* Empty csrow */
-	MEM_RESERVED,		/* Reserved csrow type */
-	MEM_UNKNOWN,		/* Unknown csrow type */
-	MEM_FPM,		/* Fast page mode */
-	MEM_EDO,		/* Extended data out */
-	MEM_BEDO,		/* Burst Extended data out */
-	MEM_SDR,		/* Single data rate SDRAM */
-	MEM_RDR,		/* Registered single data rate SDRAM */
-	MEM_DDR,		/* Double data rate SDRAM */
-	MEM_RDDR,		/* Registered Double data rate SDRAM */
-	MEM_RMBS,		/* Rambus DRAM */
-	MEM_DDR2,		/* DDR2 RAM */
-	MEM_FB_DDR2,		/* fully buffered DDR2 */
-	MEM_RDDR2,		/* Registered DDR2 RAM */
-	MEM_XDR,		/* Rambus XDR */
-	MEM_DDR3,		/* DDR3 RAM */
-	MEM_RDDR3,		/* Registered DDR3 RAM */
-};
-
-#define MEM_FLAG_EMPTY		BIT(MEM_EMPTY)
-#define MEM_FLAG_RESERVED	BIT(MEM_RESERVED)
-#define MEM_FLAG_UNKNOWN	BIT(MEM_UNKNOWN)
-#define MEM_FLAG_FPM		BIT(MEM_FPM)
-#define MEM_FLAG_EDO		BIT(MEM_EDO)
-#define MEM_FLAG_BEDO		BIT(MEM_BEDO)
-#define MEM_FLAG_SDR		BIT(MEM_SDR)
-#define MEM_FLAG_RDR		BIT(MEM_RDR)
-#define MEM_FLAG_DDR		BIT(MEM_DDR)
-#define MEM_FLAG_RDDR		BIT(MEM_RDDR)
-#define MEM_FLAG_RMBS		BIT(MEM_RMBS)
-#define MEM_FLAG_DDR2           BIT(MEM_DDR2)
-#define MEM_FLAG_FB_DDR2        BIT(MEM_FB_DDR2)
-#define MEM_FLAG_RDDR2          BIT(MEM_RDDR2)
-#define MEM_FLAG_XDR            BIT(MEM_XDR)
-#define MEM_FLAG_DDR3		 BIT(MEM_DDR3)
-#define MEM_FLAG_RDDR3		 BIT(MEM_RDDR3)
-
-/* chipset Error Detection and Correction capabilities and mode */
-enum edac_type {
-	EDAC_UNKNOWN = 0,	/* Unknown if ECC is available */
-	EDAC_NONE,		/* Doesn't support ECC */
-	EDAC_RESERVED,		/* Reserved ECC type */
-	EDAC_PARITY,		/* Detects parity errors */
-	EDAC_EC,		/* Error Checking - no correction */
-	EDAC_SECDED,		/* Single bit error correction, Double detection */
-	EDAC_S2ECD2ED,		/* Chipkill x2 devices - do these exist? */
-	EDAC_S4ECD4ED,		/* Chipkill x4 devices */
-	EDAC_S8ECD8ED,		/* Chipkill x8 devices */
-	EDAC_S16ECD16ED,	/* Chipkill x16 devices */
-};
-
-#define EDAC_FLAG_UNKNOWN	BIT(EDAC_UNKNOWN)
-#define EDAC_FLAG_NONE		BIT(EDAC_NONE)
-#define EDAC_FLAG_PARITY	BIT(EDAC_PARITY)
-#define EDAC_FLAG_EC		BIT(EDAC_EC)
-#define EDAC_FLAG_SECDED	BIT(EDAC_SECDED)
-#define EDAC_FLAG_S2ECD2ED	BIT(EDAC_S2ECD2ED)
-#define EDAC_FLAG_S4ECD4ED	BIT(EDAC_S4ECD4ED)
-#define EDAC_FLAG_S8ECD8ED	BIT(EDAC_S8ECD8ED)
-#define EDAC_FLAG_S16ECD16ED	BIT(EDAC_S16ECD16ED)
-
-/* scrubbing capabilities */
-enum scrub_type {
-	SCRUB_UNKNOWN = 0,	/* Unknown if scrubber is available */
-	SCRUB_NONE,		/* No scrubber */
-	SCRUB_SW_PROG,		/* SW progressive (sequential) scrubbing */
-	SCRUB_SW_SRC,		/* Software scrub only errors */
-	SCRUB_SW_PROG_SRC,	/* Progressive software scrub from an error */
-	SCRUB_SW_TUNABLE,	/* Software scrub frequency is tunable */
-	SCRUB_HW_PROG,		/* HW progressive (sequential) scrubbing */
-	SCRUB_HW_SRC,		/* Hardware scrub only errors */
-	SCRUB_HW_PROG_SRC,	/* Progressive hardware scrub from an error */
-	SCRUB_HW_TUNABLE	/* Hardware scrub frequency is tunable */
-};
-
-#define SCRUB_FLAG_SW_PROG	BIT(SCRUB_SW_PROG)
-#define SCRUB_FLAG_SW_SRC	BIT(SCRUB_SW_SRC)
-#define SCRUB_FLAG_SW_PROG_SRC	BIT(SCRUB_SW_PROG_SRC)
-#define SCRUB_FLAG_SW_TUN	BIT(SCRUB_SW_SCRUB_TUNABLE)
-#define SCRUB_FLAG_HW_PROG	BIT(SCRUB_HW_PROG)
-#define SCRUB_FLAG_HW_SRC	BIT(SCRUB_HW_SRC)
-#define SCRUB_FLAG_HW_PROG_SRC	BIT(SCRUB_HW_PROG_SRC)
-#define SCRUB_FLAG_HW_TUN	BIT(SCRUB_HW_TUNABLE)
-
-/* FIXME - should have notify capabilities: NMI, LOG, PROC, etc */
-
-/* EDAC internal operation states */
-#define	OP_ALLOC		0x100
-#define OP_RUNNING_POLL		0x201
-#define OP_RUNNING_INTERRUPT	0x202
-#define OP_RUNNING_POLL_INTR	0x203
-#define OP_OFFLINE		0x300
-
-/*
- * There are several things to be aware of that aren't at all obvious:
- *
- *
- * SOCKETS, SOCKET SETS, BANKS, ROWS, CHIP-SELECT ROWS, CHANNELS, etc..
- *
- * These are some of the many terms that are thrown about that don't always
- * mean what people think they mean (Inconceivable!).  In the interest of
- * creating a common ground for discussion, terms and their definitions
- * will be established.
- *
- * Memory devices:	The individual chip on a memory stick.  These devices
- *			commonly output 4 and 8 bits each.  Grouping several
- *			of these in parallel provides 64 bits which is common
- *			for a memory stick.
- *
- * Memory Stick:	A printed circuit board that aggregates multiple
- *			memory devices in parallel.  This is the atomic
- *			memory component that is purchaseable by Joe consumer
- *			and loaded into a memory socket.
- *
- * Socket:		A physical connector on the motherboard that accepts
- *			a single memory stick.
- *
- * Channel:		Set of memory devices on a memory stick that must be
- *			grouped in parallel with one or more additional
- *			channels from other memory sticks.  This parallel
- *			grouping of the output from multiple channels are
- *			necessary for the smallest granularity of memory access.
- *			Some memory controllers are capable of single channel -
- *			which means that memory sticks can be loaded
- *			individually.  Other memory controllers are only
- *			capable of dual channel - which means that memory
- *			sticks must be loaded as pairs (see "socket set").
- *
- * Chip-select row:	All of the memory devices that are selected together.
- *			for a single, minimum grain of memory access.
- *			This selects all of the parallel memory devices across
- *			all of the parallel channels.  Common chip-select rows
- *			for single channel are 64 bits, for dual channel 128
- *			bits.
- *
- * Single-Ranked stick:	A Single-ranked stick has 1 chip-select row of memory.
- *			Motherboards commonly drive two chip-select pins to
- *			a memory stick. A single-ranked stick, will occupy
- *			only one of those rows. The other will be unused.
- *
- * Double-Ranked stick:	A double-ranked stick has two chip-select rows which
- *			access different sets of memory devices.  The two
- *			rows cannot be accessed concurrently.
- *
- * Double-sided stick:	DEPRECATED TERM, see Double-Ranked stick.
- *			A double-sided stick has two chip-select rows which
- *			access different sets of memory devices.  The two
- *			rows cannot be accessed concurrently.  "Double-sided"
- *			is irrespective of the memory devices being mounted
- *			on both sides of the memory stick.
- *
- * Socket set:		All of the memory sticks that are required for
- *			a single memory access or all of the memory sticks
- *			spanned by a chip-select row.  A single socket set
- *			has two chip-select rows and if double-sided sticks
- *			are used these will occupy those chip-select rows.
- *
- * Bank:		This term is avoided because it is unclear when
- *			needing to distinguish between chip-select rows and
- *			socket sets.
- *
- * Controller pages:
- *
- * Physical pages:
- *
- * Virtual pages:
- *
- *
- * STRUCTURE ORGANIZATION AND CHOICES
- *
- *
- *
- * PS - I enjoyed writing all that about as much as you enjoyed reading it.
- */
-
-struct channel_info {
-	int chan_idx;		/* channel index */
-	u32 ce_count;		/* Correctable Errors for this CHANNEL */
-	char label[EDAC_MC_LABEL_LEN + 1];	/* DIMM label on motherboard */
-	struct csrow_info *csrow;	/* the parent */
-};
-
-struct csrow_info {
-	unsigned long first_page;	/* first page number in dimm */
-	unsigned long last_page;	/* last page number in dimm */
-	unsigned long page_mask;	/* used for interleaving -
-					 * 0UL for non intlv
-					 */
-	u32 nr_pages;		/* number of pages in csrow */
-	u32 grain;		/* granularity of reported error in bytes */
-	int csrow_idx;		/* the chip-select row */
-	enum dev_type dtype;	/* memory device type */
-	u32 ue_count;		/* Uncorrectable Errors for this csrow */
-	u32 ce_count;		/* Correctable Errors for this csrow */
-	enum mem_type mtype;	/* memory csrow type */
-	enum edac_type edac_mode;	/* EDAC mode for this csrow */
-	struct mem_ctl_info *mci;	/* the parent */
-
-	struct kobject kobj;	/* sysfs kobject for this csrow */
-
-	/* channel information for this csrow */
-	u32 nr_channels;
-	struct channel_info *channels;
-};
-
-struct mcidev_sysfs_group {
-	const char *name;				/* group name */
-	const struct mcidev_sysfs_attribute *mcidev_attr; /* group attributes */
-};
-
-struct mcidev_sysfs_group_kobj {
-	struct list_head list;		/* list for all instances within a mc */
-
-	struct kobject kobj;		/* kobj for the group */
-
-	const struct mcidev_sysfs_group *grp;	/* group description table */
-	struct mem_ctl_info *mci;	/* the parent */
-};
-
-/* mcidev_sysfs_attribute structure
- *	used for driver sysfs attributes and in mem_ctl_info
- * 	sysfs top level entries
- */
-struct mcidev_sysfs_attribute {
-	/* It should use either attr or grp */
-	struct attribute attr;
-	const struct mcidev_sysfs_group *grp;	/* Points to a group of attributes */
-
-	/* Ops for show/store values at the attribute - not used on group */
-        ssize_t (*show)(struct mem_ctl_info *,char *);
-        ssize_t (*store)(struct mem_ctl_info *, const char *,size_t);
-};
-
-/* MEMORY controller information structure
- */
-struct mem_ctl_info {
-	struct list_head link;	/* for global list of mem_ctl_info structs */
-
-	struct module *owner;	/* Module owner of this control struct */
-
-	unsigned long mtype_cap;	/* memory types supported by mc */
-	unsigned long edac_ctl_cap;	/* Mem controller EDAC capabilities */
-	unsigned long edac_cap;	/* configuration capabilities - this is
-				 * closely related to edac_ctl_cap.  The
-				 * difference is that the controller may be
-				 * capable of s4ecd4ed which would be listed
-				 * in edac_ctl_cap, but if channels aren't
-				 * capable of s4ecd4ed then the edac_cap would
-				 * not have that capability.
-				 */
-	unsigned long scrub_cap;	/* chipset scrub capabilities */
-	enum scrub_type scrub_mode;	/* current scrub mode */
-
-	/* Translates sdram memory scrub rate given in bytes/sec to the
-	   internal representation and configures whatever else needs
-	   to be configured.
-	 */
-	int (*set_sdram_scrub_rate) (struct mem_ctl_info * mci, u32 bw);
-
-	/* Get the current sdram memory scrub rate from the internal
-	   representation and converts it to the closest matching
-	   bandwidth in bytes/sec.
-	 */
-	int (*get_sdram_scrub_rate) (struct mem_ctl_info * mci);
-
-
-	/* pointer to edac checking routine */
-	void (*edac_check) (struct mem_ctl_info * mci);
-
-	/*
-	 * Remaps memory pages: controller pages to physical pages.
-	 * For most MC's, this will be NULL.
-	 */
-	/* FIXME - why not send the phys page to begin with? */
-	unsigned long (*ctl_page_to_phys) (struct mem_ctl_info * mci,
-					   unsigned long page);
-	int mc_idx;
-	int nr_csrows;
-	struct csrow_info *csrows;
-	/*
-	 * FIXME - what about controllers on other busses? - IDs must be
-	 * unique.  dev pointer should be sufficiently unique, but
-	 * BUS:SLOT.FUNC numbers may not be unique.
-	 */
-	struct device *dev;
-	const char *mod_name;
-	const char *mod_ver;
-	const char *ctl_name;
-	const char *dev_name;
-	char proc_name[MC_PROC_NAME_MAX_LEN + 1];
-	void *pvt_info;
-	u32 ue_noinfo_count;	/* Uncorrectable Errors w/o info */
-	u32 ce_noinfo_count;	/* Correctable Errors w/o info */
-	u32 ue_count;		/* Total Uncorrectable Errors for this MC */
-	u32 ce_count;		/* Total Correctable Errors for this MC */
-	unsigned long start_time;	/* mci load start time (in jiffies) */
-
-	struct completion complete;
-
-	/* edac sysfs device control */
-	struct kobject edac_mci_kobj;
-
-	/* list for all grp instances within a mc */
-	struct list_head grp_kobj_list;
-
-	/* Additional top controller level attributes, but specified
-	 * by the low level driver.
-	 *
-	 * Set by the low level driver to provide attributes at the
-	 * controller level, same level as 'ue_count' and 'ce_count' above.
-	 * An array of structures, NULL terminated
-	 *
-	 * If attributes are desired, then set to array of attributes
-	 * If no attributes are desired, leave NULL
-	 */
-	const struct mcidev_sysfs_attribute *mc_driver_sysfs_attributes;
-
-	/* work struct for this MC */
-	struct delayed_work work;
-
-	/* the internal state of this controller instance */
-	int op_state;
-};
-
 /*
  * The following are the structures to provide for a generic
  * or abstract 'edac_device'. This set of structures and the
diff --git a/drivers/edac/edac_mce.c b/drivers/edac/edac_mce.c
deleted file mode 100644
index 9ccdc5b..0000000
--- a/drivers/edac/edac_mce.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Provides edac interface to mcelog events
- *
- * This file may be distributed under the terms of the
- * GNU General Public License version 2.
- *
- * Copyright (c) 2009 by:
- *	 Mauro Carvalho Chehab <mchehab@redhat.com>
- *
- * Red Hat Inc. http://www.redhat.com
- */
-
-#include <linux/module.h>
-#include <linux/edac_mce.h>
-#include <asm/mce.h>
-
-int edac_mce_enabled;
-EXPORT_SYMBOL_GPL(edac_mce_enabled);
-
-
-/*
- * Extension interface
- */
-
-static LIST_HEAD(edac_mce_list);
-static DEFINE_MUTEX(edac_mce_lock);
-
-int edac_mce_register(struct edac_mce *edac_mce)
-{
-	mutex_lock(&edac_mce_lock);
-	list_add_tail(&edac_mce->list, &edac_mce_list);
-	mutex_unlock(&edac_mce_lock);
-	return 0;
-}
-EXPORT_SYMBOL(edac_mce_register);
-
-void edac_mce_unregister(struct edac_mce *edac_mce)
-{
-	mutex_lock(&edac_mce_lock);
-	list_del(&edac_mce->list);
-	mutex_unlock(&edac_mce_lock);
-}
-EXPORT_SYMBOL(edac_mce_unregister);
-
-int edac_mce_parse(struct mce *mce)
-{
-	struct edac_mce *edac_mce;
-
-	list_for_each_entry(edac_mce, &edac_mce_list, list) {
-		if (edac_mce->check_error(edac_mce->priv, mce))
-			return 1;
-	}
-
-	/* Nobody queued the error */
-	return 0;
-}
-EXPORT_SYMBOL_GPL(edac_mce_parse);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
-MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
-MODULE_DESCRIPTION("EDAC Driver for mcelog captured errors");
diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c
index a76fe83..6104dba 100644
--- a/drivers/edac/i7300_edac.c
+++ b/drivers/edac/i7300_edac.c
@@ -372,7 +372,7 @@ static const char *get_err_from_table(const char *table[], int size, int pos)
 static void i7300_process_error_global(struct mem_ctl_info *mci)
 {
 	struct i7300_pvt *pvt;
-	u32 errnum, value;
+	u32 errnum, error_reg;
 	unsigned long errors;
 	const char *specific;
 	bool is_fatal;
@@ -381,9 +381,9 @@ static void i7300_process_error_global(struct mem_ctl_info *mci)
 
 	/* read in the 1st FATAL error register */
 	pci_read_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
-			      FERR_GLOBAL_HI, &value);
-	if (unlikely(value)) {
-		errors = value;
+			      FERR_GLOBAL_HI, &error_reg);
+	if (unlikely(error_reg)) {
+		errors = error_reg;
 		errnum = find_first_bit(&errors,
 					ARRAY_SIZE(ferr_global_hi_name));
 		specific = GET_ERR_FROM_TABLE(ferr_global_hi_name, errnum);
@@ -391,15 +391,15 @@ static void i7300_process_error_global(struct mem_ctl_info *mci)
 
 		/* Clear the error bit */
 		pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
-				       FERR_GLOBAL_HI, value);
+				       FERR_GLOBAL_HI, error_reg);
 
 		goto error_global;
 	}
 
 	pci_read_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
-			      FERR_GLOBAL_LO, &value);
-	if (unlikely(value)) {
-		errors = value;
+			      FERR_GLOBAL_LO, &error_reg);
+	if (unlikely(error_reg)) {
+		errors = error_reg;
 		errnum = find_first_bit(&errors,
 					ARRAY_SIZE(ferr_global_lo_name));
 		specific = GET_ERR_FROM_TABLE(ferr_global_lo_name, errnum);
@@ -407,7 +407,7 @@ static void i7300_process_error_global(struct mem_ctl_info *mci)
 
 		/* Clear the error bit */
 		pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
-				       FERR_GLOBAL_LO, value);
+				       FERR_GLOBAL_LO, error_reg);
 
 		goto error_global;
 	}
@@ -427,7 +427,7 @@ error_global:
 static void i7300_process_fbd_error(struct mem_ctl_info *mci)
 {
 	struct i7300_pvt *pvt;
-	u32 errnum, value;
+	u32 errnum, value, error_reg;
 	u16 val16;
 	unsigned branch, channel, bank, rank, cas, ras;
 	u32 syndrome;
@@ -440,14 +440,14 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci)
 
 	/* read in the 1st FATAL error register */
 	pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
-			      FERR_FAT_FBD, &value);
-	if (unlikely(value & FERR_FAT_FBD_ERR_MASK)) {
-		errors = value & FERR_FAT_FBD_ERR_MASK ;
+			      FERR_FAT_FBD, &error_reg);
+	if (unlikely(error_reg & FERR_FAT_FBD_ERR_MASK)) {
+		errors = error_reg & FERR_FAT_FBD_ERR_MASK ;
 		errnum = find_first_bit(&errors,
 					ARRAY_SIZE(ferr_fat_fbd_name));
 		specific = GET_ERR_FROM_TABLE(ferr_fat_fbd_name, errnum);
+		branch = (GET_FBD_FAT_IDX(error_reg) == 2) ? 1 : 0;
 
-		branch = (GET_FBD_FAT_IDX(value) == 2) ? 1 : 0;
 		pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map,
 				     NRECMEMA, &val16);
 		bank = NRECMEMA_BANK(val16);
@@ -455,11 +455,14 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci)
 
 		pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
 				NRECMEMB, &value);
-
 		is_wr = NRECMEMB_IS_WR(value);
 		cas = NRECMEMB_CAS(value);
 		ras = NRECMEMB_RAS(value);
 
+		/* Clean the error register */
+		pci_write_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
+				FERR_FAT_FBD, error_reg);
+
 		snprintf(pvt->tmp_prt_buffer, PAGE_SIZE,
 			"FATAL (Branch=%d DRAM-Bank=%d %s "
 			"RAS=%d CAS=%d Err=0x%lx (%s))",
@@ -476,21 +479,17 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci)
 
 	/* read in the 1st NON-FATAL error register */
 	pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
-			      FERR_NF_FBD, &value);
-	if (unlikely(value & FERR_NF_FBD_ERR_MASK)) {
-		errors = value & FERR_NF_FBD_ERR_MASK;
+			      FERR_NF_FBD, &error_reg);
+	if (unlikely(error_reg & FERR_NF_FBD_ERR_MASK)) {
+		errors = error_reg & FERR_NF_FBD_ERR_MASK;
 		errnum = find_first_bit(&errors,
 					ARRAY_SIZE(ferr_nf_fbd_name));
 		specific = GET_ERR_FROM_TABLE(ferr_nf_fbd_name, errnum);
-
-		/* Clear the error bit */
-		pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
-				       FERR_GLOBAL_LO, value);
+		branch = (GET_FBD_FAT_IDX(error_reg) == 2) ? 1 : 0;
 
 		pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
 			REDMEMA, &syndrome);
 
-		branch = (GET_FBD_FAT_IDX(value) == 2) ? 1 : 0;
 		pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map,
 				     RECMEMA, &val16);
 		bank = RECMEMA_BANK(val16);
@@ -498,18 +497,20 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci)
 
 		pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
 				RECMEMB, &value);
-
 		is_wr = RECMEMB_IS_WR(value);
 		cas = RECMEMB_CAS(value);
 		ras = RECMEMB_RAS(value);
 
 		pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
 				     REDMEMB, &value);
-
 		channel = (branch << 1);
 		if (IS_SECOND_CH(value))
 			channel++;
 
+		/* Clear the error bit */
+		pci_write_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
+				FERR_NF_FBD, error_reg);
+
 		/* Form out message */
 		snprintf(pvt->tmp_prt_buffer, PAGE_SIZE,
 			"Corrected error (Branch=%d, Channel %d), "
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
index f6cf448..70ad892 100644
--- a/drivers/edac/i7core_edac.c
+++ b/drivers/edac/i7core_edac.c
@@ -31,11 +31,13 @@
 #include <linux/pci_ids.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/dmi.h>
 #include <linux/edac.h>
 #include <linux/mmzone.h>
-#include <linux/edac_mce.h>
 #include <linux/smp.h>
+#include <asm/mce.h>
 #include <asm/processor.h>
+#include <asm/div64.h>
 
 #include "edac_core.h"
 
@@ -78,6 +80,8 @@ MODULE_PARM_DESC(use_pci_fixup, "Enable PCI fixup to seek for hidden devices");
 	/* OFFSETS for Device 0 Function 0 */
 
 #define MC_CFG_CONTROL	0x90
+  #define MC_CFG_UNLOCK		0x02
+  #define MC_CFG_LOCK		0x00
 
 	/* OFFSETS for Device 3 Function 0 */
 
@@ -98,6 +102,15 @@ MODULE_PARM_DESC(use_pci_fixup, "Enable PCI fixup to seek for hidden devices");
   #define DIMM0_COR_ERR(r)			((r) & 0x7fff)
 
 /* OFFSETS for Device 3 Function 2, as inicated on Xeon 5500 datasheet */
+#define MC_SSRCONTROL		0x48
+  #define SSR_MODE_DISABLE	0x00
+  #define SSR_MODE_ENABLE	0x01
+  #define SSR_MODE_MASK		0x03
+
+#define MC_SCRUB_CONTROL	0x4c
+  #define STARTSCRUB		(1 << 24)
+  #define SCRUBINTERVAL_MASK    0xffffff
+
 #define MC_COR_ECC_CNT_0	0x80
 #define MC_COR_ECC_CNT_1	0x84
 #define MC_COR_ECC_CNT_2	0x88
@@ -253,10 +266,7 @@ struct i7core_pvt {
 	unsigned long	rdimm_ce_count[NUM_CHANS][MAX_DIMMS];
 	int		rdimm_last_ce_count[NUM_CHANS][MAX_DIMMS];
 
-	unsigned int	is_registered;
-
-	/* mcelog glue */
-	struct edac_mce		edac_mce;
+	bool		is_registered, enable_scrub;
 
 	/* Fifo double buffers */
 	struct mce		mce_entry[MCE_LOG_LEN];
@@ -268,6 +278,9 @@ struct i7core_pvt {
 	/* Count indicator to show errors not got */
 	unsigned		mce_overrun;
 
+	/* DCLK Frequency used for computing scrub rate */
+	int			dclk_freq;
+
 	/* Struct to control EDAC polling */
 	struct edac_pci_ctl_info *i7core_pci;
 };
@@ -281,8 +294,7 @@ static const struct pci_id_descr pci_dev_descr_i7core_nehalem[] = {
 		/* Memory controller */
 	{ PCI_DESCR(3, 0, PCI_DEVICE_ID_INTEL_I7_MCR)     },
 	{ PCI_DESCR(3, 1, PCI_DEVICE_ID_INTEL_I7_MC_TAD)  },
-
-		/* Exists only for RDIMM */
+			/* Exists only for RDIMM */
 	{ PCI_DESCR(3, 2, PCI_DEVICE_ID_INTEL_I7_MC_RAS), .optional = 1  },
 	{ PCI_DESCR(3, 4, PCI_DEVICE_ID_INTEL_I7_MC_TEST) },
 
@@ -303,6 +315,16 @@ static const struct pci_id_descr pci_dev_descr_i7core_nehalem[] = {
 	{ PCI_DESCR(6, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH2_ADDR) },
 	{ PCI_DESCR(6, 2, PCI_DEVICE_ID_INTEL_I7_MC_CH2_RANK) },
 	{ PCI_DESCR(6, 3, PCI_DEVICE_ID_INTEL_I7_MC_CH2_TC)   },
+
+		/* Generic Non-core registers */
+	/*
+	 * This is the PCI device on i7core and on Xeon 35xx (8086:2c41)
+	 * On Xeon 55xx, however, it has a different id (8086:2c40). So,
+	 * the probing code needs to test for the other address in case of
+	 * failure of this one
+	 */
+	{ PCI_DESCR(0, 0, PCI_DEVICE_ID_INTEL_I7_NONCORE)  },
+
 };
 
 static const struct pci_id_descr pci_dev_descr_lynnfield[] = {
@@ -319,6 +341,12 @@ static const struct pci_id_descr pci_dev_descr_lynnfield[] = {
 	{ PCI_DESCR( 5, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_ADDR) },
 	{ PCI_DESCR( 5, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_RANK) },
 	{ PCI_DESCR( 5, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_TC)   },
+
+	/*
+	 * This is the PCI device has an alternate address on some
+	 * processors like Core i7 860
+	 */
+	{ PCI_DESCR( 0, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE)     },
 };
 
 static const struct pci_id_descr pci_dev_descr_i7core_westmere[] = {
@@ -346,6 +374,10 @@ static const struct pci_id_descr pci_dev_descr_i7core_westmere[] = {
 	{ PCI_DESCR(6, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_ADDR_REV2) },
 	{ PCI_DESCR(6, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_RANK_REV2) },
 	{ PCI_DESCR(6, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_TC_REV2)   },
+
+		/* Generic Non-core registers */
+	{ PCI_DESCR(0, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_REV2)  },
+
 };
 
 #define PCI_ID_TABLE_ENTRY(A) { .descr=A, .n_devs = ARRAY_SIZE(A) }
@@ -714,6 +746,10 @@ static int get_dimm_config(const struct mem_ctl_info *mci)
 
 			csr->edac_mode = mode;
 			csr->mtype = mtype;
+			snprintf(csr->channels[0].label,
+					sizeof(csr->channels[0].label),
+					"CPU#%uChannel#%u_DIMM#%u",
+					pvt->i7core_dev->socket, i, j);
 
 			csrow++;
 		}
@@ -731,7 +767,7 @@ static int get_dimm_config(const struct mem_ctl_info *mci)
 			debugf1("\t\t%#x\t%#x\t%#x\n",
 				(value[j] >> 27) & 0x1,
 				(value[j] >> 24) & 0x7,
-				(value[j] && ((1 << 24) - 1)));
+				(value[j] & ((1 << 24) - 1)));
 	}
 
 	return 0;
@@ -1324,6 +1360,20 @@ static int i7core_get_onedevice(struct pci_dev **prev,
 	pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
 			      dev_descr->dev_id, *prev);
 
+	/*
+	 * On Xeon 55xx, the Intel Quckpath Arch Generic Non-core regs
+	 * is at addr 8086:2c40, instead of 8086:2c41. So, we need
+	 * to probe for the alternate address in case of failure
+	 */
+	if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_I7_NONCORE && !pdev)
+		pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+				      PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT, *prev);
+
+	if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE && !pdev)
+		pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+				      PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_ALT,
+				      *prev);
+
 	if (!pdev) {
 		if (*prev) {
 			*prev = pdev;
@@ -1444,8 +1494,10 @@ static int mci_bind_devs(struct mem_ctl_info *mci,
 	struct i7core_pvt *pvt = mci->pvt_info;
 	struct pci_dev *pdev;
 	int i, func, slot;
+	char *family;
 
-	pvt->is_registered = 0;
+	pvt->is_registered = false;
+	pvt->enable_scrub  = false;
 	for (i = 0; i < i7core_dev->n_devs; i++) {
 		pdev = i7core_dev->pdev[i];
 		if (!pdev)
@@ -1461,9 +1513,37 @@ static int mci_bind_devs(struct mem_ctl_info *mci,
 			if (unlikely(func > MAX_CHAN_FUNC))
 				goto error;
 			pvt->pci_ch[slot - 4][func] = pdev;
-		} else if (!slot && !func)
+		} else if (!slot && !func) {
 			pvt->pci_noncore = pdev;
-		else
+
+			/* Detect the processor family */
+			switch (pdev->device) {
+			case PCI_DEVICE_ID_INTEL_I7_NONCORE:
+				family = "Xeon 35xx/ i7core";
+				pvt->enable_scrub = false;
+				break;
+			case PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_ALT:
+				family = "i7-800/i5-700";
+				pvt->enable_scrub = false;
+				break;
+			case PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE:
+				family = "Xeon 34xx";
+				pvt->enable_scrub = false;
+				break;
+			case PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT:
+				family = "Xeon 55xx";
+				pvt->enable_scrub = true;
+				break;
+			case PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_REV2:
+				family = "Xeon 56xx / i7-900";
+				pvt->enable_scrub = true;
+				break;
+			default:
+				family = "unknown";
+				pvt->enable_scrub = false;
+			}
+			debugf0("Detected a processor type %s\n", family);
+		} else
 			goto error;
 
 		debugf0("Associated fn %d.%d, dev = %p, socket %d\n",
@@ -1472,7 +1552,7 @@ static int mci_bind_devs(struct mem_ctl_info *mci,
 
 		if (PCI_SLOT(pdev->devfn) == 3 &&
 			PCI_FUNC(pdev->devfn) == 2)
-			pvt->is_registered = 1;
+			pvt->is_registered = true;
 	}
 
 	return 0;
@@ -1826,33 +1906,43 @@ check_ce_error:
  * WARNING: As this routine should be called at NMI time, extra care should
  * be taken to avoid deadlocks, and to be as fast as possible.
  */
-static int i7core_mce_check_error(void *priv, struct mce *mce)
+static int i7core_mce_check_error(struct notifier_block *nb, unsigned long val,
+				  void *data)
 {
-	struct mem_ctl_info *mci = priv;
-	struct i7core_pvt *pvt = mci->pvt_info;
+	struct mce *mce = (struct mce *)data;
+	struct i7core_dev *i7_dev;
+	struct mem_ctl_info *mci;
+	struct i7core_pvt *pvt;
+
+	i7_dev = get_i7core_dev(mce->socketid);
+	if (!i7_dev)
+		return NOTIFY_BAD;
+
+	mci = i7_dev->mci;
+	pvt = mci->pvt_info;
 
 	/*
 	 * Just let mcelog handle it if the error is
 	 * outside the memory controller
 	 */
 	if (((mce->status & 0xffff) >> 7) != 1)
-		return 0;
+		return NOTIFY_DONE;
 
 	/* Bank 8 registers are the only ones that we know how to handle */
 	if (mce->bank != 8)
-		return 0;
+		return NOTIFY_DONE;
 
 #ifdef CONFIG_SMP
 	/* Only handle if it is the right mc controller */
-	if (cpu_data(mce->cpu).phys_proc_id != pvt->i7core_dev->socket)
-		return 0;
+	if (mce->socketid != pvt->i7core_dev->socket)
+		return NOTIFY_DONE;
 #endif
 
 	smp_rmb();
 	if ((pvt->mce_out + 1) % MCE_LOG_LEN == pvt->mce_in) {
 		smp_wmb();
 		pvt->mce_overrun++;
-		return 0;
+		return NOTIFY_DONE;
 	}
 
 	/* Copy memory error at the ringbuffer */
@@ -1865,7 +1955,240 @@ static int i7core_mce_check_error(void *priv, struct mce *mce)
 		i7core_check_error(mci);
 
 	/* Advise mcelog that the errors were handled */
-	return 1;
+	return NOTIFY_STOP;
+}
+
+static struct notifier_block i7_mce_dec = {
+	.notifier_call	= i7core_mce_check_error,
+};
+
+struct memdev_dmi_entry {
+	u8 type;
+	u8 length;
+	u16 handle;
+	u16 phys_mem_array_handle;
+	u16 mem_err_info_handle;
+	u16 total_width;
+	u16 data_width;
+	u16 size;
+	u8 form;
+	u8 device_set;
+	u8 device_locator;
+	u8 bank_locator;
+	u8 memory_type;
+	u16 type_detail;
+	u16 speed;
+	u8 manufacturer;
+	u8 serial_number;
+	u8 asset_tag;
+	u8 part_number;
+	u8 attributes;
+	u32 extended_size;
+	u16 conf_mem_clk_speed;
+} __attribute__((__packed__));
+
+
+/*
+ * Decode the DRAM Clock Frequency, be paranoid, make sure that all
+ * memory devices show the same speed, and if they don't then consider
+ * all speeds to be invalid.
+ */
+static void decode_dclk(const struct dmi_header *dh, void *_dclk_freq)
+{
+	int *dclk_freq = _dclk_freq;
+	u16 dmi_mem_clk_speed;
+
+	if (*dclk_freq == -1)
+		return;
+
+	if (dh->type == DMI_ENTRY_MEM_DEVICE) {
+		struct memdev_dmi_entry *memdev_dmi_entry =
+			(struct memdev_dmi_entry *)dh;
+		unsigned long conf_mem_clk_speed_offset =
+			(unsigned long)&memdev_dmi_entry->conf_mem_clk_speed -
+			(unsigned long)&memdev_dmi_entry->type;
+		unsigned long speed_offset =
+			(unsigned long)&memdev_dmi_entry->speed -
+			(unsigned long)&memdev_dmi_entry->type;
+
+		/* Check that a DIMM is present */
+		if (memdev_dmi_entry->size == 0)
+			return;
+
+		/*
+		 * Pick the configured speed if it's available, otherwise
+		 * pick the DIMM speed, or we don't have a speed.
+		 */
+		if (memdev_dmi_entry->length > conf_mem_clk_speed_offset) {
+			dmi_mem_clk_speed =
+				memdev_dmi_entry->conf_mem_clk_speed;
+		} else if (memdev_dmi_entry->length > speed_offset) {
+			dmi_mem_clk_speed = memdev_dmi_entry->speed;
+		} else {
+			*dclk_freq = -1;
+			return;
+		}
+
+		if (*dclk_freq == 0) {
+			/* First pass, speed was 0 */
+			if (dmi_mem_clk_speed > 0) {
+				/* Set speed if a valid speed is read */
+				*dclk_freq = dmi_mem_clk_speed;
+			} else {
+				/* Otherwise we don't have a valid speed */
+				*dclk_freq = -1;
+			}
+		} else if (*dclk_freq > 0 &&
+			   *dclk_freq != dmi_mem_clk_speed) {
+			/*
+			 * If we have a speed, check that all DIMMS are the same
+			 * speed, otherwise set the speed as invalid.
+			 */
+			*dclk_freq = -1;
+		}
+	}
+}
+
+/*
+ * The default DCLK frequency is used as a fallback if we
+ * fail to find anything reliable in the DMI. The value
+ * is taken straight from the datasheet.
+ */
+#define DEFAULT_DCLK_FREQ 800
+
+static int get_dclk_freq(void)
+{
+	int dclk_freq = 0;
+
+	dmi_walk(decode_dclk, (void *)&dclk_freq);
+
+	if (dclk_freq < 1)
+		return DEFAULT_DCLK_FREQ;
+
+	return dclk_freq;
+}
+
+/*
+ * set_sdram_scrub_rate		This routine sets byte/sec bandwidth scrub rate
+ *				to hardware according to SCRUBINTERVAL formula
+ *				found in datasheet.
+ */
+static int set_sdram_scrub_rate(struct mem_ctl_info *mci, u32 new_bw)
+{
+	struct i7core_pvt *pvt = mci->pvt_info;
+	struct pci_dev *pdev;
+	u32 dw_scrub;
+	u32 dw_ssr;
+
+	/* Get data from the MC register, function 2 */
+	pdev = pvt->pci_mcr[2];
+	if (!pdev)
+		return -ENODEV;
+
+	pci_read_config_dword(pdev, MC_SCRUB_CONTROL, &dw_scrub);
+
+	if (new_bw == 0) {
+		/* Prepare to disable petrol scrub */
+		dw_scrub &= ~STARTSCRUB;
+		/* Stop the patrol scrub engine */
+		write_and_test(pdev, MC_SCRUB_CONTROL,
+			       dw_scrub & ~SCRUBINTERVAL_MASK);
+
+		/* Get current status of scrub rate and set bit to disable */
+		pci_read_config_dword(pdev, MC_SSRCONTROL, &dw_ssr);
+		dw_ssr &= ~SSR_MODE_MASK;
+		dw_ssr |= SSR_MODE_DISABLE;
+	} else {
+		const int cache_line_size = 64;
+		const u32 freq_dclk_mhz = pvt->dclk_freq;
+		unsigned long long scrub_interval;
+		/*
+		 * Translate the desired scrub rate to a register value and
+		 * program the corresponding register value.
+		 */
+		scrub_interval = (unsigned long long)freq_dclk_mhz *
+			cache_line_size * 1000000;
+		do_div(scrub_interval, new_bw);
+
+		if (!scrub_interval || scrub_interval > SCRUBINTERVAL_MASK)
+			return -EINVAL;
+
+		dw_scrub = SCRUBINTERVAL_MASK & scrub_interval;
+
+		/* Start the patrol scrub engine */
+		pci_write_config_dword(pdev, MC_SCRUB_CONTROL,
+				       STARTSCRUB | dw_scrub);
+
+		/* Get current status of scrub rate and set bit to enable */
+		pci_read_config_dword(pdev, MC_SSRCONTROL, &dw_ssr);
+		dw_ssr &= ~SSR_MODE_MASK;
+		dw_ssr |= SSR_MODE_ENABLE;
+	}
+	/* Disable or enable scrubbing */
+	pci_write_config_dword(pdev, MC_SSRCONTROL, dw_ssr);
+
+	return new_bw;
+}
+
+/*
+ * get_sdram_scrub_rate		This routine convert current scrub rate value
+ *				into byte/sec bandwidth accourding to
+ *				SCRUBINTERVAL formula found in datasheet.
+ */
+static int get_sdram_scrub_rate(struct mem_ctl_info *mci)
+{
+	struct i7core_pvt *pvt = mci->pvt_info;
+	struct pci_dev *pdev;
+	const u32 cache_line_size = 64;
+	const u32 freq_dclk_mhz = pvt->dclk_freq;
+	unsigned long long scrub_rate;
+	u32 scrubval;
+
+	/* Get data from the MC register, function 2 */
+	pdev = pvt->pci_mcr[2];
+	if (!pdev)
+		return -ENODEV;
+
+	/* Get current scrub control data */
+	pci_read_config_dword(pdev, MC_SCRUB_CONTROL, &scrubval);
+
+	/* Mask highest 8-bits to 0 */
+	scrubval &=  SCRUBINTERVAL_MASK;
+	if (!scrubval)
+		return 0;
+
+	/* Calculate scrub rate value into byte/sec bandwidth */
+	scrub_rate =  (unsigned long long)freq_dclk_mhz *
+		1000000 * cache_line_size;
+	do_div(scrub_rate, scrubval);
+	return (int)scrub_rate;
+}
+
+static void enable_sdram_scrub_setting(struct mem_ctl_info *mci)
+{
+	struct i7core_pvt *pvt = mci->pvt_info;
+	u32 pci_lock;
+
+	/* Unlock writes to pci registers */
+	pci_read_config_dword(pvt->pci_noncore, MC_CFG_CONTROL, &pci_lock);
+	pci_lock &= ~0x3;
+	pci_write_config_dword(pvt->pci_noncore, MC_CFG_CONTROL,
+			       pci_lock | MC_CFG_UNLOCK);
+
+	mci->set_sdram_scrub_rate = set_sdram_scrub_rate;
+	mci->get_sdram_scrub_rate = get_sdram_scrub_rate;
+}
+
+static void disable_sdram_scrub_setting(struct mem_ctl_info *mci)
+{
+	struct i7core_pvt *pvt = mci->pvt_info;
+	u32 pci_lock;
+
+	/* Lock writes to pci registers */
+	pci_read_config_dword(pvt->pci_noncore, MC_CFG_CONTROL, &pci_lock);
+	pci_lock &= ~0x3;
+	pci_write_config_dword(pvt->pci_noncore, MC_CFG_CONTROL,
+			       pci_lock | MC_CFG_LOCK);
 }
 
 static void i7core_pci_ctl_create(struct i7core_pvt *pvt)
@@ -1874,7 +2197,8 @@ static void i7core_pci_ctl_create(struct i7core_pvt *pvt)
 						&pvt->i7core_dev->pdev[0]->dev,
 						EDAC_MOD_STR);
 	if (unlikely(!pvt->i7core_pci))
-		pr_warn("Unable to setup PCI error report via EDAC\n");
+		i7core_printk(KERN_WARNING,
+			      "Unable to setup PCI error report via EDAC\n");
 }
 
 static void i7core_pci_ctl_release(struct i7core_pvt *pvt)
@@ -1906,8 +2230,11 @@ static void i7core_unregister_mci(struct i7core_dev *i7core_dev)
 	debugf0("MC: " __FILE__ ": %s(): mci = %p, dev = %p\n",
 		__func__, mci, &i7core_dev->pdev[0]->dev);
 
-	/* Disable MCE NMI handler */
-	edac_mce_unregister(&pvt->edac_mce);
+	/* Disable scrubrate setting */
+	if (pvt->enable_scrub)
+		disable_sdram_scrub_setting(mci);
+
+	atomic_notifier_chain_unregister(&x86_mce_decoder_chain, &i7_mce_dec);
 
 	/* Disable EDAC polling */
 	i7core_pci_ctl_release(pvt);
@@ -1979,6 +2306,10 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev)
 	/* Set the function pointer to an actual operation function */
 	mci->edac_check = i7core_check_error;
 
+	/* Enable scrubrate setting */
+	if (pvt->enable_scrub)
+		enable_sdram_scrub_setting(mci);
+
 	/* add this new MC control structure to EDAC's list of MCs */
 	if (unlikely(edac_mc_add_mc(mci))) {
 		debugf0("MC: " __FILE__
@@ -2002,21 +2333,13 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev)
 	/* allocating generic PCI control info */
 	i7core_pci_ctl_create(pvt);
 
-	/* Registers on edac_mce in order to receive memory errors */
-	pvt->edac_mce.priv = mci;
-	pvt->edac_mce.check_error = i7core_mce_check_error;
-	rc = edac_mce_register(&pvt->edac_mce);
-	if (unlikely(rc < 0)) {
-		debugf0("MC: " __FILE__
-			": %s(): failed edac_mce_register()\n", __func__);
-		goto fail1;
-	}
+	/* DCLK for scrub rate setting */
+	pvt->dclk_freq = get_dclk_freq();
+
+	atomic_notifier_chain_register(&x86_mce_decoder_chain, &i7_mce_dec);
 
 	return 0;
 
-fail1:
-	i7core_pci_ctl_release(pvt);
-	edac_mc_del_mc(mci->dev);
 fail0:
 	kfree(mci->ctl_name);
 	edac_mc_free(mci);
@@ -2035,7 +2358,7 @@ fail0:
 static int __devinit i7core_probe(struct pci_dev *pdev,
 				  const struct pci_device_id *id)
 {
-	int rc;
+	int rc, count = 0;
 	struct i7core_dev *i7core_dev;
 
 	/* get the pci devices we want to reserve for our use */
@@ -2055,12 +2378,28 @@ static int __devinit i7core_probe(struct pci_dev *pdev,
 		goto fail0;
 
 	list_for_each_entry(i7core_dev, &i7core_edac_list, list) {
+		count++;
 		rc = i7core_register_mci(i7core_dev);
 		if (unlikely(rc < 0))
 			goto fail1;
 	}
 
-	i7core_printk(KERN_INFO, "Driver loaded.\n");
+	/*
+	 * Nehalem-EX uses a different memory controller. However, as the
+	 * memory controller is not visible on some Nehalem/Nehalem-EP, we
+	 * need to indirectly probe via a X58 PCI device. The same devices
+	 * are found on (some) Nehalem-EX. So, on those machines, the
+	 * probe routine needs to return -ENODEV, as the actual Memory
+	 * Controller registers won't be detected.
+	 */
+	if (!count) {
+		rc = -ENODEV;
+		goto fail1;
+	}
+
+	i7core_printk(KERN_INFO,
+		      "Driver loaded, %d memory controller(s) found.\n",
+		      count);
 
 	mutex_unlock(&i7core_edac_lock);
 	return 0;
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
new file mode 100644
index 0000000..7a402bf
--- /dev/null
+++ b/drivers/edac/sb_edac.c
@@ -0,0 +1,1893 @@
+/* Intel Sandy Bridge -EN/-EP/-EX Memory Controller kernel module
+ *
+ * This driver supports the memory controllers found on the Intel
+ * processor family Sandy Bridge.
+ *
+ * This file may be distributed under the terms of the
+ * GNU General Public License version 2 only.
+ *
+ * Copyright (c) 2011 by:
+ *	 Mauro Carvalho Chehab <mchehab@redhat.com>
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/edac.h>
+#include <linux/mmzone.h>
+#include <linux/smp.h>
+#include <linux/bitmap.h>
+#include <asm/processor.h>
+#include <asm/mce.h>
+
+#include "edac_core.h"
+
+/* Static vars */
+static LIST_HEAD(sbridge_edac_list);
+static DEFINE_MUTEX(sbridge_edac_lock);
+static int probed;
+
+/*
+ * Alter this version for the module when modifications are made
+ */
+#define SBRIDGE_REVISION    " Ver: 1.0.0 "
+#define EDAC_MOD_STR      "sbridge_edac"
+
+/*
+ * Debug macros
+ */
+#define sbridge_printk(level, fmt, arg...)			\
+	edac_printk(level, "sbridge", fmt, ##arg)
+
+#define sbridge_mc_printk(mci, level, fmt, arg...)		\
+	edac_mc_chipset_printk(mci, level, "sbridge", fmt, ##arg)
+
+/*
+ * Get a bit field at register value <v>, from bit <lo> to bit <hi>
+ */
+#define GET_BITFIELD(v, lo, hi)	\
+	(((v) & ((1ULL << ((hi) - (lo) + 1)) - 1) << (lo)) >> (lo))
+
+/*
+ * sbridge Memory Controller Registers
+ */
+
+/*
+ * FIXME: For now, let's order by device function, as it makes
+ * easier for driver's development proccess. This table should be
+ * moved to pci_id.h when submitted upstream
+ */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0	0x3cf4	/* 12.6 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1	0x3cf6	/* 12.7 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_BR		0x3cf5	/* 13.6 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0	0x3ca0	/* 14.0 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA	0x3ca8	/* 15.0 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS	0x3c71	/* 15.1 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0	0x3caa	/* 15.2 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1	0x3cab	/* 15.3 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2	0x3cac	/* 15.4 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3	0x3cad	/* 15.5 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO	0x3cb8	/* 17.0 */
+
+	/*
+	 * Currently, unused, but will be needed in the future
+	 * implementations, as they hold the error counters
+	 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_ERR0	0x3c72	/* 16.2 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_ERR1	0x3c73	/* 16.3 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_ERR2	0x3c76	/* 16.6 */
+#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_ERR3	0x3c77	/* 16.7 */
+
+/* Devices 12 Function 6, Offsets 0x80 to 0xcc */
+static const u32 dram_rule[] = {
+	0x80, 0x88, 0x90, 0x98, 0xa0,
+	0xa8, 0xb0, 0xb8, 0xc0, 0xc8,
+};
+#define MAX_SAD		ARRAY_SIZE(dram_rule)
+
+#define SAD_LIMIT(reg)		((GET_BITFIELD(reg, 6, 25) << 26) | 0x3ffffff)
+#define DRAM_ATTR(reg)		GET_BITFIELD(reg, 2,  3)
+#define INTERLEAVE_MODE(reg)	GET_BITFIELD(reg, 1,  1)
+#define DRAM_RULE_ENABLE(reg)	GET_BITFIELD(reg, 0,  0)
+
+static char *get_dram_attr(u32 reg)
+{
+	switch(DRAM_ATTR(reg)) {
+		case 0:
+			return "DRAM";
+		case 1:
+			return "MMCFG";
+		case 2:
+			return "NXM";
+		default:
+			return "unknown";
+	}
+}
+
+static const u32 interleave_list[] = {
+	0x84, 0x8c, 0x94, 0x9c, 0xa4,
+	0xac, 0xb4, 0xbc, 0xc4, 0xcc,
+};
+#define MAX_INTERLEAVE	ARRAY_SIZE(interleave_list)
+
+#define SAD_PKG0(reg)		GET_BITFIELD(reg, 0, 2)
+#define SAD_PKG1(reg)		GET_BITFIELD(reg, 3, 5)
+#define SAD_PKG2(reg)		GET_BITFIELD(reg, 8, 10)
+#define SAD_PKG3(reg)		GET_BITFIELD(reg, 11, 13)
+#define SAD_PKG4(reg)		GET_BITFIELD(reg, 16, 18)
+#define SAD_PKG5(reg)		GET_BITFIELD(reg, 19, 21)
+#define SAD_PKG6(reg)		GET_BITFIELD(reg, 24, 26)
+#define SAD_PKG7(reg)		GET_BITFIELD(reg, 27, 29)
+
+static inline int sad_pkg(u32 reg, int interleave)
+{
+	switch (interleave) {
+	case 0:
+		return SAD_PKG0(reg);
+	case 1:
+		return SAD_PKG1(reg);
+	case 2:
+		return SAD_PKG2(reg);
+	case 3:
+		return SAD_PKG3(reg);
+	case 4:
+		return SAD_PKG4(reg);
+	case 5:
+		return SAD_PKG5(reg);
+	case 6:
+		return SAD_PKG6(reg);
+	case 7:
+		return SAD_PKG7(reg);
+	default:
+		return -EINVAL;
+	}
+}
+
+/* Devices 12 Function 7 */
+
+#define TOLM		0x80
+#define	TOHM		0x84
+
+#define GET_TOLM(reg)		((GET_BITFIELD(reg, 0,  3) << 28) | 0x3ffffff)
+#define GET_TOHM(reg)		((GET_BITFIELD(reg, 0, 20) << 25) | 0x3ffffff)
+
+/* Device 13 Function 6 */
+
+#define SAD_TARGET	0xf0
+
+#define SOURCE_ID(reg)		GET_BITFIELD(reg, 9, 11)
+
+#define SAD_CONTROL	0xf4
+
+#define NODE_ID(reg)		GET_BITFIELD(reg, 0, 2)
+
+/* Device 14 function 0 */
+
+static const u32 tad_dram_rule[] = {
+	0x40, 0x44, 0x48, 0x4c,
+	0x50, 0x54, 0x58, 0x5c,
+	0x60, 0x64, 0x68, 0x6c,
+};
+#define MAX_TAD	ARRAY_SIZE(tad_dram_rule)
+
+#define TAD_LIMIT(reg)		((GET_BITFIELD(reg, 12, 31) << 26) | 0x3ffffff)
+#define TAD_SOCK(reg)		GET_BITFIELD(reg, 10, 11)
+#define TAD_CH(reg)		GET_BITFIELD(reg,  8,  9)
+#define TAD_TGT3(reg)		GET_BITFIELD(reg,  6,  7)
+#define TAD_TGT2(reg)		GET_BITFIELD(reg,  4,  5)
+#define TAD_TGT1(reg)		GET_BITFIELD(reg,  2,  3)
+#define TAD_TGT0(reg)		GET_BITFIELD(reg,  0,  1)
+
+/* Device 15, function 0 */
+
+#define MCMTR			0x7c
+
+#define IS_ECC_ENABLED(mcmtr)		GET_BITFIELD(mcmtr, 2, 2)
+#define IS_LOCKSTEP_ENABLED(mcmtr)	GET_BITFIELD(mcmtr, 1, 1)
+#define IS_CLOSE_PG(mcmtr)		GET_BITFIELD(mcmtr, 0, 0)
+
+/* Device 15, function 1 */
+
+#define RASENABLES		0xac
+#define IS_MIRROR_ENABLED(reg)		GET_BITFIELD(reg, 0, 0)
+
+/* Device 15, functions 2-5 */
+
+static const int mtr_regs[] = {
+	0x80, 0x84, 0x88,
+};
+
+#define RANK_DISABLE(mtr)		GET_BITFIELD(mtr, 16, 19)
+#define IS_DIMM_PRESENT(mtr)		GET_BITFIELD(mtr, 14, 14)
+#define RANK_CNT_BITS(mtr)		GET_BITFIELD(mtr, 12, 13)
+#define RANK_WIDTH_BITS(mtr)		GET_BITFIELD(mtr, 2, 4)
+#define COL_WIDTH_BITS(mtr)		GET_BITFIELD(mtr, 0, 1)
+
+static const u32 tad_ch_nilv_offset[] = {
+	0x90, 0x94, 0x98, 0x9c,
+	0xa0, 0xa4, 0xa8, 0xac,
+	0xb0, 0xb4, 0xb8, 0xbc,
+};
+#define CHN_IDX_OFFSET(reg)		GET_BITFIELD(reg, 28, 29)
+#define TAD_OFFSET(reg)			(GET_BITFIELD(reg,  6, 25) << 26)
+
+static const u32 rir_way_limit[] = {
+	0x108, 0x10c, 0x110, 0x114, 0x118,
+};
+#define MAX_RIR_RANGES ARRAY_SIZE(rir_way_limit)
+
+#define IS_RIR_VALID(reg)	GET_BITFIELD(reg, 31, 31)
+#define RIR_WAY(reg)		GET_BITFIELD(reg, 28, 29)
+#define RIR_LIMIT(reg)		((GET_BITFIELD(reg,  1, 10) << 29)| 0x1fffffff)
+
+#define MAX_RIR_WAY	8
+
+static const u32 rir_offset[MAX_RIR_RANGES][MAX_RIR_WAY] = {
+	{ 0x120, 0x124, 0x128, 0x12c, 0x130, 0x134, 0x138, 0x13c },
+	{ 0x140, 0x144, 0x148, 0x14c, 0x150, 0x154, 0x158, 0x15c },
+	{ 0x160, 0x164, 0x168, 0x16c, 0x170, 0x174, 0x178, 0x17c },
+	{ 0x180, 0x184, 0x188, 0x18c, 0x190, 0x194, 0x198, 0x19c },
+	{ 0x1a0, 0x1a4, 0x1a8, 0x1ac, 0x1b0, 0x1b4, 0x1b8, 0x1bc },
+};
+
+#define RIR_RNK_TGT(reg)		GET_BITFIELD(reg, 16, 19)
+#define RIR_OFFSET(reg)		GET_BITFIELD(reg,  2, 14)
+
+/* Device 16, functions 2-7 */
+
+/*
+ * FIXME: Implement the error count reads directly
+ */
+
+static const u32 correrrcnt[] = {
+	0x104, 0x108, 0x10c, 0x110,
+};
+
+#define RANK_ODD_OV(reg)		GET_BITFIELD(reg, 31, 31)
+#define RANK_ODD_ERR_CNT(reg)		GET_BITFIELD(reg, 16, 30)
+#define RANK_EVEN_OV(reg)		GET_BITFIELD(reg, 15, 15)
+#define RANK_EVEN_ERR_CNT(reg)		GET_BITFIELD(reg,  0, 14)
+
+static const u32 correrrthrsld[] = {
+	0x11c, 0x120, 0x124, 0x128,
+};
+
+#define RANK_ODD_ERR_THRSLD(reg)	GET_BITFIELD(reg, 16, 30)
+#define RANK_EVEN_ERR_THRSLD(reg)	GET_BITFIELD(reg,  0, 14)
+
+
+/* Device 17, function 0 */
+
+#define RANK_CFG_A		0x0328
+
+#define IS_RDIMM_ENABLED(reg)		GET_BITFIELD(reg, 11, 11)
+
+/*
+ * sbridge structs
+ */
+
+#define NUM_CHANNELS	4
+#define MAX_DIMMS	3		/* Max DIMMS per channel */
+
+struct sbridge_info {
+	u32	mcmtr;
+};
+
+struct sbridge_channel {
+	u32		ranks;
+	u32		dimms;
+};
+
+struct pci_id_descr {
+	int			dev;
+	int			func;
+	int 			dev_id;
+	int			optional;
+};
+
+struct pci_id_table {
+	const struct pci_id_descr	*descr;
+	int				n_devs;
+};
+
+struct sbridge_dev {
+	struct list_head	list;
+	u8			bus, mc;
+	u8			node_id, source_id;
+	struct pci_dev		**pdev;
+	int			n_devs;
+	struct mem_ctl_info	*mci;
+};
+
+struct sbridge_pvt {
+	struct pci_dev		*pci_ta, *pci_ddrio, *pci_ras;
+	struct pci_dev		*pci_sad0, *pci_sad1, *pci_ha0;
+	struct pci_dev		*pci_br;
+	struct pci_dev		*pci_tad[NUM_CHANNELS];
+
+	struct sbridge_dev	*sbridge_dev;
+
+	struct sbridge_info	info;
+	struct sbridge_channel	channel[NUM_CHANNELS];
+
+	int 			csrow_map[NUM_CHANNELS][MAX_DIMMS];
+
+	/* Memory type detection */
+	bool			is_mirrored, is_lockstep, is_close_pg;
+
+	/* Fifo double buffers */
+	struct mce		mce_entry[MCE_LOG_LEN];
+	struct mce		mce_outentry[MCE_LOG_LEN];
+
+	/* Fifo in/out counters */
+	unsigned		mce_in, mce_out;
+
+	/* Count indicator to show errors not got */
+	unsigned		mce_overrun;
+
+	/* Memory description */
+	u64			tolm, tohm;
+};
+
+#define PCI_DESCR(device, function, device_id)	\
+	.dev = (device),			\
+	.func = (function),			\
+	.dev_id = (device_id)
+
+static const struct pci_id_descr pci_dev_descr_sbridge[] = {
+		/* Processor Home Agent */
+	{ PCI_DESCR(14, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0)		},
+
+		/* Memory controller */
+	{ PCI_DESCR(15, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA)		},
+	{ PCI_DESCR(15, 1, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS)		},
+	{ PCI_DESCR(15, 2, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0)	},
+	{ PCI_DESCR(15, 3, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1)	},
+	{ PCI_DESCR(15, 4, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2)	},
+	{ PCI_DESCR(15, 5, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3)	},
+	{ PCI_DESCR(17, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO)	},
+
+		/* System Address Decoder */
+	{ PCI_DESCR(12, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0)		},
+	{ PCI_DESCR(12, 7, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1)		},
+
+		/* Broadcast Registers */
+	{ PCI_DESCR(13, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_BR)		},
+};
+
+#define PCI_ID_TABLE_ENTRY(A) { .descr=A, .n_devs = ARRAY_SIZE(A) }
+static const struct pci_id_table pci_dev_descr_sbridge_table[] = {
+	PCI_ID_TABLE_ENTRY(pci_dev_descr_sbridge),
+	{0,}			/* 0 terminated list. */
+};
+
+/*
+ *	pci_device_id	table for which devices we are looking for
+ */
+static const struct pci_device_id sbridge_pci_tbl[] __devinitdata = {
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA)},
+	{0,}			/* 0 terminated list. */
+};
+
+
+/****************************************************************************
+			Anciliary status routines
+ ****************************************************************************/
+
+static inline int numrank(u32 mtr)
+{
+	int ranks = (1 << RANK_CNT_BITS(mtr));
+
+	if (ranks > 4) {
+		debugf0("Invalid number of ranks: %d (max = 4) raw value = %x (%04x)",
+			ranks, (unsigned int)RANK_CNT_BITS(mtr), mtr);
+		return -EINVAL;
+	}
+
+	return ranks;
+}
+
+static inline int numrow(u32 mtr)
+{
+	int rows = (RANK_WIDTH_BITS(mtr) + 12);
+
+	if (rows < 13 || rows > 18) {
+		debugf0("Invalid number of rows: %d (should be between 14 and 17) raw value = %x (%04x)",
+			rows, (unsigned int)RANK_WIDTH_BITS(mtr), mtr);
+		return -EINVAL;
+	}
+
+	return 1 << rows;
+}
+
+static inline int numcol(u32 mtr)
+{
+	int cols = (COL_WIDTH_BITS(mtr) + 10);
+
+	if (cols > 12) {
+		debugf0("Invalid number of cols: %d (max = 4) raw value = %x (%04x)",
+			cols, (unsigned int)COL_WIDTH_BITS(mtr), mtr);
+		return -EINVAL;
+	}
+
+	return 1 << cols;
+}
+
+static struct sbridge_dev *get_sbridge_dev(u8 bus)
+{
+	struct sbridge_dev *sbridge_dev;
+
+	list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) {
+		if (sbridge_dev->bus == bus)
+			return sbridge_dev;
+	}
+
+	return NULL;
+}
+
+static struct sbridge_dev *alloc_sbridge_dev(u8 bus,
+					   const struct pci_id_table *table)
+{
+	struct sbridge_dev *sbridge_dev;
+
+	sbridge_dev = kzalloc(sizeof(*sbridge_dev), GFP_KERNEL);
+	if (!sbridge_dev)
+		return NULL;
+
+	sbridge_dev->pdev = kzalloc(sizeof(*sbridge_dev->pdev) * table->n_devs,
+				   GFP_KERNEL);
+	if (!sbridge_dev->pdev) {
+		kfree(sbridge_dev);
+		return NULL;
+	}
+
+	sbridge_dev->bus = bus;
+	sbridge_dev->n_devs = table->n_devs;
+	list_add_tail(&sbridge_dev->list, &sbridge_edac_list);
+
+	return sbridge_dev;
+}
+
+static void free_sbridge_dev(struct sbridge_dev *sbridge_dev)
+{
+	list_del(&sbridge_dev->list);
+	kfree(sbridge_dev->pdev);
+	kfree(sbridge_dev);
+}
+
+/****************************************************************************
+			Memory check routines
+ ****************************************************************************/
+static struct pci_dev *get_pdev_slot_func(u8 bus, unsigned slot,
+					  unsigned func)
+{
+	struct sbridge_dev *sbridge_dev = get_sbridge_dev(bus);
+	int i;
+
+	if (!sbridge_dev)
+		return NULL;
+
+	for (i = 0; i < sbridge_dev->n_devs; i++) {
+		if (!sbridge_dev->pdev[i])
+			continue;
+
+		if (PCI_SLOT(sbridge_dev->pdev[i]->devfn) == slot &&
+		    PCI_FUNC(sbridge_dev->pdev[i]->devfn) == func) {
+			debugf1("Associated %02x.%02x.%d with %p\n",
+				bus, slot, func, sbridge_dev->pdev[i]);
+			return sbridge_dev->pdev[i];
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ * sbridge_get_active_channels() - gets the number of channels and csrows
+ * bus:		Device bus
+ * @channels:	Number of channels that will be returned
+ * @csrows:	Number of csrows found
+ *
+ * Since EDAC core needs to know in advance the number of available channels
+ * and csrows, in order to allocate memory for csrows/channels, it is needed
+ * to run two similar steps. At the first step, implemented on this function,
+ * it checks the number of csrows/channels present at one socket, identified
+ * by the associated PCI bus.
+ * this is used in order to properly allocate the size of mci components.
+ * Note: one csrow is one dimm.
+ */
+static int sbridge_get_active_channels(const u8 bus, unsigned *channels,
+				      unsigned *csrows)
+{
+	struct pci_dev *pdev = NULL;
+	int i, j;
+	u32 mcmtr;
+
+	*channels = 0;
+	*csrows = 0;
+
+	pdev = get_pdev_slot_func(bus, 15, 0);
+	if (!pdev) {
+		sbridge_printk(KERN_ERR, "Couldn't find PCI device "
+					"%2x.%02d.%d!!!\n",
+					bus, 15, 0);
+		return -ENODEV;
+	}
+
+	pci_read_config_dword(pdev, MCMTR, &mcmtr);
+	if (!IS_ECC_ENABLED(mcmtr)) {
+		sbridge_printk(KERN_ERR, "ECC is disabled. Aborting\n");
+		return -ENODEV;
+	}
+
+	for (i = 0; i < NUM_CHANNELS; i++) {
+		u32 mtr;
+
+		/* Device 15 functions 2 - 5  */
+		pdev = get_pdev_slot_func(bus, 15, 2 + i);
+		if (!pdev) {
+			sbridge_printk(KERN_ERR, "Couldn't find PCI device "
+						 "%2x.%02d.%d!!!\n",
+						 bus, 15, 2 + i);
+			return -ENODEV;
+		}
+		(*channels)++;
+
+		for (j = 0; j < ARRAY_SIZE(mtr_regs); j++) {
+			pci_read_config_dword(pdev, mtr_regs[j], &mtr);
+			debugf1("Bus#%02x channel #%d  MTR%d = %x\n", bus, i, j, mtr);
+			if (IS_DIMM_PRESENT(mtr))
+				(*csrows)++;
+		}
+	}
+
+	debugf0("Number of active channels: %d, number of active dimms: %d\n",
+		*channels, *csrows);
+
+	return 0;
+}
+
+static int get_dimm_config(const struct mem_ctl_info *mci)
+{
+	struct sbridge_pvt *pvt = mci->pvt_info;
+	struct csrow_info *csr;
+	int i, j, banks, ranks, rows, cols, size, npages;
+	int csrow = 0;
+	unsigned long last_page = 0;
+	u32 reg;
+	enum edac_type mode;
+	enum mem_type mtype;
+
+	pci_read_config_dword(pvt->pci_br, SAD_TARGET, &reg);
+	pvt->sbridge_dev->source_id = SOURCE_ID(reg);
+
+	pci_read_config_dword(pvt->pci_br, SAD_CONTROL, &reg);
+	pvt->sbridge_dev->node_id = NODE_ID(reg);
+	debugf0("mc#%d: Node ID: %d, source ID: %d\n",
+		pvt->sbridge_dev->mc,
+		pvt->sbridge_dev->node_id,
+		pvt->sbridge_dev->source_id);
+
+	pci_read_config_dword(pvt->pci_ras, RASENABLES, &reg);
+	if (IS_MIRROR_ENABLED(reg)) {
+		debugf0("Memory mirror is enabled\n");
+		pvt->is_mirrored = true;
+	} else {
+		debugf0("Memory mirror is disabled\n");
+		pvt->is_mirrored = false;
+	}
+
+	pci_read_config_dword(pvt->pci_ta, MCMTR, &pvt->info.mcmtr);
+	if (IS_LOCKSTEP_ENABLED(pvt->info.mcmtr)) {
+		debugf0("Lockstep is enabled\n");
+		mode = EDAC_S8ECD8ED;
+		pvt->is_lockstep = true;
+	} else {
+		debugf0("Lockstep is disabled\n");
+		mode = EDAC_S4ECD4ED;
+		pvt->is_lockstep = false;
+	}
+	if (IS_CLOSE_PG(pvt->info.mcmtr)) {
+		debugf0("address map is on closed page mode\n");
+		pvt->is_close_pg = true;
+	} else {
+		debugf0("address map is on open page mode\n");
+		pvt->is_close_pg = false;
+	}
+
+	pci_read_config_dword(pvt->pci_ta, RANK_CFG_A, &reg);
+	if (IS_RDIMM_ENABLED(reg)) {
+		/* FIXME: Can also be LRDIMM */
+		debugf0("Memory is registered\n");
+		mtype = MEM_RDDR3;
+	} else {
+		debugf0("Memory is unregistered\n");
+		mtype = MEM_DDR3;
+	}
+
+	/* On all supported DDR3 DIMM types, there are 8 banks available */
+	banks = 8;
+
+	for (i = 0; i < NUM_CHANNELS; i++) {
+		u32 mtr;
+
+		for (j = 0; j < ARRAY_SIZE(mtr_regs); j++) {
+			pci_read_config_dword(pvt->pci_tad[i],
+					      mtr_regs[j], &mtr);
+			debugf4("Channel #%d  MTR%d = %x\n", i, j, mtr);
+			if (IS_DIMM_PRESENT(mtr)) {
+				pvt->channel[i].dimms++;
+
+				ranks = numrank(mtr);
+				rows = numrow(mtr);
+				cols = numcol(mtr);
+
+				/* DDR3 has 8 I/O banks */
+				size = (rows * cols * banks * ranks) >> (20 - 3);
+				npages = MiB_TO_PAGES(size);
+
+				debugf0("mc#%d: channel %d, dimm %d, %d Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n",
+					pvt->sbridge_dev->mc, i, j,
+					size, npages,
+					banks, ranks, rows, cols);
+				csr = &mci->csrows[csrow];
+
+				csr->first_page = last_page;
+				csr->last_page = last_page + npages - 1;
+				csr->page_mask = 0UL;	/* Unused */
+				csr->nr_pages = npages;
+				csr->grain = 32;
+				csr->csrow_idx = csrow;
+				csr->dtype = (banks == 8) ? DEV_X8 : DEV_X4;
+				csr->ce_count = 0;
+				csr->ue_count = 0;
+				csr->mtype = mtype;
+				csr->edac_mode = mode;
+				csr->nr_channels = 1;
+				csr->channels[0].chan_idx = i;
+				csr->channels[0].ce_count = 0;
+				pvt->csrow_map[i][j] = csrow;
+				snprintf(csr->channels[0].label,
+					 sizeof(csr->channels[0].label),
+					 "CPU_SrcID#%u_Channel#%u_DIMM#%u",
+					 pvt->sbridge_dev->source_id, i, j);
+				last_page += npages;
+				csrow++;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static void get_memory_layout(const struct mem_ctl_info *mci)
+{
+	struct sbridge_pvt *pvt = mci->pvt_info;
+	int i, j, k, n_sads, n_tads, sad_interl;
+	u32 reg;
+	u64 limit, prv = 0;
+	u64 tmp_mb;
+	u32 rir_way;
+
+	/*
+	 * Step 1) Get TOLM/TOHM ranges
+	 */
+
+	/* Address range is 32:28 */
+	pci_read_config_dword(pvt->pci_sad1, TOLM,
+			      &reg);
+	pvt->tolm = GET_TOLM(reg);
+	tmp_mb = (1 + pvt->tolm) >> 20;
+
+	debugf0("TOLM: %Lu.%03Lu GB (0x%016Lx)\n",
+		tmp_mb / 1000, tmp_mb % 1000, (u64)pvt->tolm);
+
+	/* Address range is already 45:25 */
+	pci_read_config_dword(pvt->pci_sad1, TOHM,
+			      &reg);
+	pvt->tohm = GET_TOHM(reg);
+	tmp_mb = (1 + pvt->tohm) >> 20;
+
+	debugf0("TOHM: %Lu.%03Lu GB (0x%016Lx)",
+		tmp_mb / 1000, tmp_mb % 1000, (u64)pvt->tohm);
+
+	/*
+	 * Step 2) Get SAD range and SAD Interleave list
+	 * TAD registers contain the interleave wayness. However, it
+	 * seems simpler to just discover it indirectly, with the
+	 * algorithm bellow.
+	 */
+	prv = 0;
+	for (n_sads = 0; n_sads < MAX_SAD; n_sads++) {
+		/* SAD_LIMIT Address range is 45:26 */
+		pci_read_config_dword(pvt->pci_sad0, dram_rule[n_sads],
+				      &reg);
+		limit = SAD_LIMIT(reg);
+
+		if (!DRAM_RULE_ENABLE(reg))
+			continue;
+
+		if (limit <= prv)
+			break;
+
+		tmp_mb = (limit + 1) >> 20;
+		debugf0("SAD#%d %s up to %Lu.%03Lu GB (0x%016Lx) %s reg=0x%08x\n",
+			n_sads,
+			get_dram_attr(reg),
+			tmp_mb / 1000, tmp_mb % 1000,
+			((u64)tmp_mb) << 20L,
+			INTERLEAVE_MODE(reg) ? "Interleave: 8:6" : "Interleave: [8:6]XOR[18:16]",
+			reg);
+		prv = limit;
+
+		pci_read_config_dword(pvt->pci_sad0, interleave_list[n_sads],
+				      &reg);
+		sad_interl = sad_pkg(reg, 0);
+		for (j = 0; j < 8; j++) {
+			if (j > 0 && sad_interl == sad_pkg(reg, j))
+				break;
+
+			debugf0("SAD#%d, interleave #%d: %d\n",
+			n_sads, j, sad_pkg(reg, j));
+		}
+	}
+
+	/*
+	 * Step 3) Get TAD range
+	 */
+	prv = 0;
+	for (n_tads = 0; n_tads < MAX_TAD; n_tads++) {
+		pci_read_config_dword(pvt->pci_ha0, tad_dram_rule[n_tads],
+				      &reg);
+		limit = TAD_LIMIT(reg);
+		if (limit <= prv)
+			break;
+		tmp_mb = (limit + 1) >> 20;
+
+		debugf0("TAD#%d: up to %Lu.%03Lu GB (0x%016Lx), socket interleave %d, memory interleave %d, TGT: %d, %d, %d, %d, reg=0x%08x\n",
+			n_tads, tmp_mb / 1000, tmp_mb % 1000,
+			((u64)tmp_mb) << 20L,
+			(u32)TAD_SOCK(reg),
+			(u32)TAD_CH(reg),
+			(u32)TAD_TGT0(reg),
+			(u32)TAD_TGT1(reg),
+			(u32)TAD_TGT2(reg),
+			(u32)TAD_TGT3(reg),
+			reg);
+		prv = tmp_mb;
+	}
+
+	/*
+	 * Step 4) Get TAD offsets, per each channel
+	 */
+	for (i = 0; i < NUM_CHANNELS; i++) {
+		if (!pvt->channel[i].dimms)
+			continue;
+		for (j = 0; j < n_tads; j++) {
+			pci_read_config_dword(pvt->pci_tad[i],
+					      tad_ch_nilv_offset[j],
+					      &reg);
+			tmp_mb = TAD_OFFSET(reg) >> 20;
+			debugf0("TAD CH#%d, offset #%d: %Lu.%03Lu GB (0x%016Lx), reg=0x%08x\n",
+				i, j,
+				tmp_mb / 1000, tmp_mb % 1000,
+				((u64)tmp_mb) << 20L,
+				reg);
+		}
+	}
+
+	/*
+	 * Step 6) Get RIR Wayness/Limit, per each channel
+	 */
+	for (i = 0; i < NUM_CHANNELS; i++) {
+		if (!pvt->channel[i].dimms)
+			continue;
+		for (j = 0; j < MAX_RIR_RANGES; j++) {
+			pci_read_config_dword(pvt->pci_tad[i],
+					      rir_way_limit[j],
+					      &reg);
+
+			if (!IS_RIR_VALID(reg))
+				continue;
+
+			tmp_mb = RIR_LIMIT(reg) >> 20;
+			rir_way = 1 << RIR_WAY(reg);
+			debugf0("CH#%d RIR#%d, limit: %Lu.%03Lu GB (0x%016Lx), way: %d, reg=0x%08x\n",
+				i, j,
+				tmp_mb / 1000, tmp_mb % 1000,
+				((u64)tmp_mb) << 20L,
+				rir_way,
+				reg);
+
+			for (k = 0; k < rir_way; k++) {
+				pci_read_config_dword(pvt->pci_tad[i],
+						      rir_offset[j][k],
+						      &reg);
+				tmp_mb = RIR_OFFSET(reg) << 6;
+
+				debugf0("CH#%d RIR#%d INTL#%d, offset %Lu.%03Lu GB (0x%016Lx), tgt: %d, reg=0x%08x\n",
+					i, j, k,
+					tmp_mb / 1000, tmp_mb % 1000,
+					((u64)tmp_mb) << 20L,
+					(u32)RIR_RNK_TGT(reg),
+					reg);
+			}
+		}
+	}
+}
+
+struct mem_ctl_info *get_mci_for_node_id(u8 node_id)
+{
+	struct sbridge_dev *sbridge_dev;
+
+	list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) {
+		if (sbridge_dev->node_id == node_id)
+			return sbridge_dev->mci;
+	}
+	return NULL;
+}
+
+static int get_memory_error_data(struct mem_ctl_info *mci,
+				 u64 addr,
+				 u8 *socket,
+				 long *channel_mask,
+				 u8 *rank,
+				 char *area_type)
+{
+	struct mem_ctl_info	*new_mci;
+	struct sbridge_pvt *pvt = mci->pvt_info;
+	char			msg[256];
+	int 			n_rir, n_sads, n_tads, sad_way, sck_xch;
+	int			sad_interl, idx, base_ch;
+	int			interleave_mode;
+	unsigned		sad_interleave[MAX_INTERLEAVE];
+	u32			reg;
+	u8			ch_way,sck_way;
+	u32			tad_offset;
+	u32			rir_way;
+	u64			ch_addr, offset, limit, prv = 0;
+
+
+	/*
+	 * Step 0) Check if the address is at special memory ranges
+	 * The check bellow is probably enough to fill all cases where
+	 * the error is not inside a memory, except for the legacy
+	 * range (e. g. VGA addresses). It is unlikely, however, that the
+	 * memory controller would generate an error on that range.
+	 */
+	if ((addr > (u64) pvt->tolm) && (addr < (1L << 32))) {
+		sprintf(msg, "Error at TOLM area, on addr 0x%08Lx", addr);
+		edac_mc_handle_ce_no_info(mci, msg);
+		return -EINVAL;
+	}
+	if (addr >= (u64)pvt->tohm) {
+		sprintf(msg, "Error at MMIOH area, on addr 0x%016Lx", addr);
+		edac_mc_handle_ce_no_info(mci, msg);
+		return -EINVAL;
+	}
+
+	/*
+	 * Step 1) Get socket
+	 */
+	for (n_sads = 0; n_sads < MAX_SAD; n_sads++) {
+		pci_read_config_dword(pvt->pci_sad0, dram_rule[n_sads],
+				      &reg);
+
+		if (!DRAM_RULE_ENABLE(reg))
+			continue;
+
+		limit = SAD_LIMIT(reg);
+		if (limit <= prv) {
+			sprintf(msg, "Can't discover the memory socket");
+			edac_mc_handle_ce_no_info(mci, msg);
+			return -EINVAL;
+		}
+		if  (addr <= limit)
+			break;
+		prv = limit;
+	}
+	if (n_sads == MAX_SAD) {
+		sprintf(msg, "Can't discover the memory socket");
+		edac_mc_handle_ce_no_info(mci, msg);
+		return -EINVAL;
+	}
+	area_type = get_dram_attr(reg);
+	interleave_mode = INTERLEAVE_MODE(reg);
+
+	pci_read_config_dword(pvt->pci_sad0, interleave_list[n_sads],
+			      &reg);
+	sad_interl = sad_pkg(reg, 0);
+	for (sad_way = 0; sad_way < 8; sad_way++) {
+		if (sad_way > 0 && sad_interl == sad_pkg(reg, sad_way))
+			break;
+		sad_interleave[sad_way] = sad_pkg(reg, sad_way);
+		debugf0("SAD interleave #%d: %d\n",
+			sad_way, sad_interleave[sad_way]);
+	}
+	debugf0("mc#%d: Error detected on SAD#%d: address 0x%016Lx < 0x%016Lx, Interleave [%d:6]%s\n",
+		pvt->sbridge_dev->mc,
+		n_sads,
+		addr,
+		limit,
+		sad_way + 7,
+		INTERLEAVE_MODE(reg) ? "" : "XOR[18:16]");
+	if (interleave_mode)
+		idx = ((addr >> 6) ^ (addr >> 16)) & 7;
+	else
+		idx = (addr >> 6) & 7;
+	switch (sad_way) {
+	case 1:
+		idx = 0;
+		break;
+	case 2:
+		idx = idx & 1;
+		break;
+	case 4:
+		idx = idx & 3;
+		break;
+	case 8:
+		break;
+	default:
+		sprintf(msg, "Can't discover socket interleave");
+		edac_mc_handle_ce_no_info(mci, msg);
+		return -EINVAL;
+	}
+	*socket = sad_interleave[idx];
+	debugf0("SAD interleave index: %d (wayness %d) = CPU socket %d\n",
+		idx, sad_way, *socket);
+
+	/*
+	 * Move to the proper node structure, in order to access the
+	 * right PCI registers
+	 */
+	new_mci = get_mci_for_node_id(*socket);
+	if (!new_mci) {
+		sprintf(msg, "Struct for socket #%u wasn't initialized",
+			*socket);
+		edac_mc_handle_ce_no_info(mci, msg);
+		return -EINVAL;
+	}
+	mci = new_mci;
+	pvt = mci->pvt_info;
+
+	/*
+	 * Step 2) Get memory channel
+	 */
+	prv = 0;
+	for (n_tads = 0; n_tads < MAX_TAD; n_tads++) {
+		pci_read_config_dword(pvt->pci_ha0, tad_dram_rule[n_tads],
+				      &reg);
+		limit = TAD_LIMIT(reg);
+		if (limit <= prv) {
+			sprintf(msg, "Can't discover the memory channel");
+			edac_mc_handle_ce_no_info(mci, msg);
+			return -EINVAL;
+		}
+		if  (addr <= limit)
+			break;
+		prv = limit;
+	}
+	ch_way = TAD_CH(reg) + 1;
+	sck_way = TAD_SOCK(reg) + 1;
+	/*
+	 * FIXME: Is it right to always use channel 0 for offsets?
+	 */
+	pci_read_config_dword(pvt->pci_tad[0],
+				tad_ch_nilv_offset[n_tads],
+				&tad_offset);
+
+	if (ch_way == 3)
+		idx = addr >> 6;
+	else
+		idx = addr >> (6 + sck_way);
+	idx = idx % ch_way;
+
+	/*
+	 * FIXME: Shouldn't we use CHN_IDX_OFFSET() here, when ch_way == 3 ???
+	 */
+	switch (idx) {
+	case 0:
+		base_ch = TAD_TGT0(reg);
+		break;
+	case 1:
+		base_ch = TAD_TGT1(reg);
+		break;
+	case 2:
+		base_ch = TAD_TGT2(reg);
+		break;
+	case 3:
+		base_ch = TAD_TGT3(reg);
+		break;
+	default:
+		sprintf(msg, "Can't discover the TAD target");
+		edac_mc_handle_ce_no_info(mci, msg);
+		return -EINVAL;
+	}
+	*channel_mask = 1 << base_ch;
+
+	if (pvt->is_mirrored) {
+		*channel_mask |= 1 << ((base_ch + 2) % 4);
+		switch(ch_way) {
+		case 2:
+		case 4:
+			sck_xch = 1 << sck_way * (ch_way >> 1);
+			break;
+		default:
+			sprintf(msg, "Invalid mirror set. Can't decode addr");
+			edac_mc_handle_ce_no_info(mci, msg);
+			return -EINVAL;
+		}
+	} else
+		sck_xch = (1 << sck_way) * ch_way;
+
+	if (pvt->is_lockstep)
+		*channel_mask |= 1 << ((base_ch + 1) % 4);
+
+	offset = TAD_OFFSET(tad_offset);
+
+	debugf0("TAD#%d: address 0x%016Lx < 0x%016Lx, socket interleave %d, channel interleave %d (offset 0x%08Lx), index %d, base ch: %d, ch mask: 0x%02lx\n",
+		n_tads,
+		addr,
+		limit,
+		(u32)TAD_SOCK(reg),
+		ch_way,
+		offset,
+		idx,
+		base_ch,
+		*channel_mask);
+
+	/* Calculate channel address */
+	/* Remove the TAD offset */
+
+	if (offset > addr) {
+		sprintf(msg, "Can't calculate ch addr: TAD offset 0x%08Lx is too high for addr 0x%08Lx!",
+			offset, addr);
+		edac_mc_handle_ce_no_info(mci, msg);
+		return -EINVAL;
+	}
+	addr -= offset;
+	/* Store the low bits [0:6] of the addr */
+	ch_addr = addr & 0x7f;
+	/* Remove socket wayness and remove 6 bits */
+	addr >>= 6;
+	addr /= sck_xch;
+#if 0
+	/* Divide by channel way */
+	addr = addr / ch_way;
+#endif
+	/* Recover the last 6 bits */
+	ch_addr |= addr << 6;
+
+	/*
+	 * Step 3) Decode rank
+	 */
+	for (n_rir = 0; n_rir < MAX_RIR_RANGES; n_rir++) {
+		pci_read_config_dword(pvt->pci_tad[base_ch],
+				      rir_way_limit[n_rir],
+				      &reg);
+
+		if (!IS_RIR_VALID(reg))
+			continue;
+
+		limit = RIR_LIMIT(reg);
+
+		debugf0("RIR#%d, limit: %Lu.%03Lu GB (0x%016Lx), way: %d\n",
+			n_rir,
+			(limit >> 20) / 1000, (limit >> 20) % 1000,
+			limit,
+			1 << RIR_WAY(reg));
+		if  (ch_addr <= limit)
+			break;
+	}
+	if (n_rir == MAX_RIR_RANGES) {
+		sprintf(msg, "Can't discover the memory rank for ch addr 0x%08Lx",
+			ch_addr);
+		edac_mc_handle_ce_no_info(mci, msg);
+		return -EINVAL;
+	}
+	rir_way = RIR_WAY(reg);
+	if (pvt->is_close_pg)
+		idx = (ch_addr >> 6);
+	else
+		idx = (ch_addr >> 13);	/* FIXME: Datasheet says to shift by 15 */
+	idx %= 1 << rir_way;
+
+	pci_read_config_dword(pvt->pci_tad[base_ch],
+			      rir_offset[n_rir][idx],
+			      &reg);
+	*rank = RIR_RNK_TGT(reg);
+
+	debugf0("RIR#%d: channel address 0x%08Lx < 0x%08Lx, RIR interleave %d, index %d\n",
+		n_rir,
+		ch_addr,
+		limit,
+		rir_way,
+		idx);
+
+	return 0;
+}
+
+/****************************************************************************
+	Device initialization routines: put/get, init/exit
+ ****************************************************************************/
+
+/*
+ *	sbridge_put_all_devices	'put' all the devices that we have
+ *				reserved via 'get'
+ */
+static void sbridge_put_devices(struct sbridge_dev *sbridge_dev)
+{
+	int i;
+
+	debugf0(__FILE__ ": %s()\n", __func__);
+	for (i = 0; i < sbridge_dev->n_devs; i++) {
+		struct pci_dev *pdev = sbridge_dev->pdev[i];
+		if (!pdev)
+			continue;
+		debugf0("Removing dev %02x:%02x.%d\n",
+			pdev->bus->number,
+			PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
+		pci_dev_put(pdev);
+	}
+}
+
+static void sbridge_put_all_devices(void)
+{
+	struct sbridge_dev *sbridge_dev, *tmp;
+
+	list_for_each_entry_safe(sbridge_dev, tmp, &sbridge_edac_list, list) {
+		sbridge_put_devices(sbridge_dev);
+		free_sbridge_dev(sbridge_dev);
+	}
+}
+
+/*
+ *	sbridge_get_all_devices	Find and perform 'get' operation on the MCH's
+ *			device/functions we want to reference for this driver
+ *
+ *			Need to 'get' device 16 func 1 and func 2
+ */
+static int sbridge_get_onedevice(struct pci_dev **prev,
+				 u8 *num_mc,
+				 const struct pci_id_table *table,
+				 const unsigned devno)
+{
+	struct sbridge_dev *sbridge_dev;
+	const struct pci_id_descr *dev_descr = &table->descr[devno];
+
+	struct pci_dev *pdev = NULL;
+	u8 bus = 0;
+
+	sbridge_printk(KERN_INFO,
+		"Seeking for: dev %02x.%d PCI ID %04x:%04x\n",
+		dev_descr->dev, dev_descr->func,
+		PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
+
+	pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+			      dev_descr->dev_id, *prev);
+
+	if (!pdev) {
+		if (*prev) {
+			*prev = pdev;
+			return 0;
+		}
+
+		if (dev_descr->optional)
+			return 0;
+
+		if (devno == 0)
+			return -ENODEV;
+
+		sbridge_printk(KERN_INFO,
+			"Device not found: dev %02x.%d PCI ID %04x:%04x\n",
+			dev_descr->dev, dev_descr->func,
+			PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
+
+		/* End of list, leave */
+		return -ENODEV;
+	}
+	bus = pdev->bus->number;
+
+	sbridge_dev = get_sbridge_dev(bus);
+	if (!sbridge_dev) {
+		sbridge_dev = alloc_sbridge_dev(bus, table);
+		if (!sbridge_dev) {
+			pci_dev_put(pdev);
+			return -ENOMEM;
+		}
+		(*num_mc)++;
+	}
+
+	if (sbridge_dev->pdev[devno]) {
+		sbridge_printk(KERN_ERR,
+			"Duplicated device for "
+			"dev %02x:%d.%d PCI ID %04x:%04x\n",
+			bus, dev_descr->dev, dev_descr->func,
+			PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
+		pci_dev_put(pdev);
+		return -ENODEV;
+	}
+
+	sbridge_dev->pdev[devno] = pdev;
+
+	/* Sanity check */
+	if (unlikely(PCI_SLOT(pdev->devfn) != dev_descr->dev ||
+			PCI_FUNC(pdev->devfn) != dev_descr->func)) {
+		sbridge_printk(KERN_ERR,
+			"Device PCI ID %04x:%04x "
+			"has dev %02x:%d.%d instead of dev %02x:%02x.%d\n",
+			PCI_VENDOR_ID_INTEL, dev_descr->dev_id,
+			bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
+			bus, dev_descr->dev, dev_descr->func);
+		return -ENODEV;
+	}
+
+	/* Be sure that the device is enabled */
+	if (unlikely(pci_enable_device(pdev) < 0)) {
+		sbridge_printk(KERN_ERR,
+			"Couldn't enable "
+			"dev %02x:%d.%d PCI ID %04x:%04x\n",
+			bus, dev_descr->dev, dev_descr->func,
+			PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
+		return -ENODEV;
+	}
+
+	debugf0("Detected dev %02x:%d.%d PCI ID %04x:%04x\n",
+		bus, dev_descr->dev,
+		dev_descr->func,
+		PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
+
+	/*
+	 * As stated on drivers/pci/search.c, the reference count for
+	 * @from is always decremented if it is not %NULL. So, as we need
+	 * to get all devices up to null, we need to do a get for the device
+	 */
+	pci_dev_get(pdev);
+
+	*prev = pdev;
+
+	return 0;
+}
+
+static int sbridge_get_all_devices(u8 *num_mc)
+{
+	int i, rc;
+	struct pci_dev *pdev = NULL;
+	const struct pci_id_table *table = pci_dev_descr_sbridge_table;
+
+	while (table && table->descr) {
+		for (i = 0; i < table->n_devs; i++) {
+			pdev = NULL;
+			do {
+				rc = sbridge_get_onedevice(&pdev, num_mc,
+							   table, i);
+				if (rc < 0) {
+					if (i == 0) {
+						i = table->n_devs;
+						break;
+					}
+					sbridge_put_all_devices();
+					return -ENODEV;
+				}
+			} while (pdev);
+		}
+		table++;
+	}
+
+	return 0;
+}
+
+static int mci_bind_devs(struct mem_ctl_info *mci,
+			 struct sbridge_dev *sbridge_dev)
+{
+	struct sbridge_pvt *pvt = mci->pvt_info;
+	struct pci_dev *pdev;
+	int i, func, slot;
+
+	for (i = 0; i < sbridge_dev->n_devs; i++) {
+		pdev = sbridge_dev->pdev[i];
+		if (!pdev)
+			continue;
+		slot = PCI_SLOT(pdev->devfn);
+		func = PCI_FUNC(pdev->devfn);
+		switch (slot) {
+		case 12:
+			switch (func) {
+			case 6:
+				pvt->pci_sad0 = pdev;
+				break;
+			case 7:
+				pvt->pci_sad1 = pdev;
+				break;
+			default:
+				goto error;
+			}
+			break;
+		case 13:
+			switch (func) {
+			case 6:
+				pvt->pci_br = pdev;
+				break;
+			default:
+				goto error;
+			}
+			break;
+		case 14:
+			switch (func) {
+			case 0:
+				pvt->pci_ha0 = pdev;
+				break;
+			default:
+				goto error;
+			}
+			break;
+		case 15:
+			switch (func) {
+			case 0:
+				pvt->pci_ta = pdev;
+				break;
+			case 1:
+				pvt->pci_ras = pdev;
+				break;
+			case 2:
+			case 3:
+			case 4:
+			case 5:
+				pvt->pci_tad[func - 2] = pdev;
+				break;
+			default:
+				goto error;
+			}
+			break;
+		case 17:
+			switch (func) {
+			case 0:
+				pvt->pci_ddrio = pdev;
+				break;
+			default:
+				goto error;
+			}
+			break;
+		default:
+			goto error;
+		}
+
+		debugf0("Associated PCI %02x.%02d.%d with dev = %p\n",
+			sbridge_dev->bus,
+			PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
+			pdev);
+	}
+
+	/* Check if everything were registered */
+	if (!pvt->pci_sad0 || !pvt->pci_sad1 || !pvt->pci_ha0 ||
+	    !pvt-> pci_tad || !pvt->pci_ras  || !pvt->pci_ta ||
+	    !pvt->pci_ddrio)
+		goto enodev;
+
+	for (i = 0; i < NUM_CHANNELS; i++) {
+		if (!pvt->pci_tad[i])
+			goto enodev;
+	}
+	return 0;
+
+enodev:
+	sbridge_printk(KERN_ERR, "Some needed devices are missing\n");
+	return -ENODEV;
+
+error:
+	sbridge_printk(KERN_ERR, "Device %d, function %d "
+		      "is out of the expected range\n",
+		      slot, func);
+	return -EINVAL;
+}
+
+/****************************************************************************
+			Error check routines
+ ****************************************************************************/
+
+/*
+ * While Sandy Bridge has error count registers, SMI BIOS read values from
+ * and resets the counters. So, they are not reliable for the OS to read
+ * from them. So, we have no option but to just trust on whatever MCE is
+ * telling us about the errors.
+ */
+static void sbridge_mce_output_error(struct mem_ctl_info *mci,
+				    const struct mce *m)
+{
+	struct mem_ctl_info *new_mci;
+	struct sbridge_pvt *pvt = mci->pvt_info;
+	char *type, *optype, *msg, *recoverable_msg;
+	bool ripv = GET_BITFIELD(m->mcgstatus, 0, 0);
+	bool overflow = GET_BITFIELD(m->status, 62, 62);
+	bool uncorrected_error = GET_BITFIELD(m->status, 61, 61);
+	bool recoverable = GET_BITFIELD(m->status, 56, 56);
+	u32 core_err_cnt = GET_BITFIELD(m->status, 38, 52);
+	u32 mscod = GET_BITFIELD(m->status, 16, 31);
+	u32 errcode = GET_BITFIELD(m->status, 0, 15);
+	u32 channel = GET_BITFIELD(m->status, 0, 3);
+	u32 optypenum = GET_BITFIELD(m->status, 4, 6);
+	long channel_mask, first_channel;
+	u8  rank, socket;
+	int csrow, rc, dimm;
+	char *area_type = "Unknown";
+
+	if (ripv)
+		type = "NON_FATAL";
+	else
+		type = "FATAL";
+
+	/*
+	 * According with Table 15-9 of the Intel Archictecture spec vol 3A,
+	 * memory errors should fit in this mask:
+	 *	000f 0000 1mmm cccc (binary)
+	 * where:
+	 *	f = Correction Report Filtering Bit. If 1, subsequent errors
+	 *	    won't be shown
+	 *	mmm = error type
+	 *	cccc = channel
+	 * If the mask doesn't match, report an error to the parsing logic
+	 */
+	if (! ((errcode & 0xef80) == 0x80)) {
+		optype = "Can't parse: it is not a mem";
+	} else {
+		switch (optypenum) {
+		case 0:
+			optype = "generic undef request";
+			break;
+		case 1:
+			optype = "memory read";
+			break;
+		case 2:
+			optype = "memory write";
+			break;
+		case 3:
+			optype = "addr/cmd";
+			break;
+		case 4:
+			optype = "memory scrubbing";
+			break;
+		default:
+			optype = "reserved";
+			break;
+		}
+	}
+
+	rc = get_memory_error_data(mci, m->addr, &socket,
+				   &channel_mask, &rank, area_type);
+	if (rc < 0)
+		return;
+	new_mci = get_mci_for_node_id(socket);
+	if (!new_mci) {
+		edac_mc_handle_ce_no_info(mci, "Error: socket got corrupted!");
+		return;
+	}
+	mci = new_mci;
+	pvt = mci->pvt_info;
+
+	first_channel = find_first_bit(&channel_mask, NUM_CHANNELS);
+
+	if (rank < 4)
+		dimm = 0;
+	else if (rank < 8)
+		dimm = 1;
+	else
+		dimm = 2;
+
+	csrow = pvt->csrow_map[first_channel][dimm];
+
+	if (uncorrected_error && recoverable)
+		recoverable_msg = " recoverable";
+	else
+		recoverable_msg = "";
+
+	/*
+	 * FIXME: What should we do with "channel" information on mcelog?
+	 * Probably, we can just discard it, as the channel information
+	 * comes from the get_memory_error_data() address decoding
+	 */
+	msg = kasprintf(GFP_ATOMIC,
+			"%d %s error(s): %s on %s area %s%s: cpu=%d Err=%04x:%04x (ch=%d), "
+			"addr = 0x%08llx => socket=%d, Channel=%ld(mask=%ld), rank=%d\n",
+			core_err_cnt,
+			area_type,
+			optype,
+			type,
+			recoverable_msg,
+			overflow ? "OVERFLOW" : "",
+			m->cpu,
+			mscod, errcode,
+			channel,		/* 1111b means not specified */
+			(long long) m->addr,
+			socket,
+			first_channel,		/* This is the real channel on SB */
+			channel_mask,
+			rank);
+
+	debugf0("%s", msg);
+
+	/* Call the helper to output message */
+	if (uncorrected_error)
+		edac_mc_handle_fbd_ue(mci, csrow, 0, 0, msg);
+	else
+		edac_mc_handle_fbd_ce(mci, csrow, 0, msg);
+
+	kfree(msg);
+}
+
+/*
+ *	sbridge_check_error	Retrieve and process errors reported by the
+ *				hardware. Called by the Core module.
+ */
+static void sbridge_check_error(struct mem_ctl_info *mci)
+{
+	struct sbridge_pvt *pvt = mci->pvt_info;
+	int i;
+	unsigned count = 0;
+	struct mce *m;
+
+	/*
+	 * MCE first step: Copy all mce errors into a temporary buffer
+	 * We use a double buffering here, to reduce the risk of
+	 * loosing an error.
+	 */
+	smp_rmb();
+	count = (pvt->mce_out + MCE_LOG_LEN - pvt->mce_in)
+		% MCE_LOG_LEN;
+	if (!count)
+		return;
+
+	m = pvt->mce_outentry;
+	if (pvt->mce_in + count > MCE_LOG_LEN) {
+		unsigned l = MCE_LOG_LEN - pvt->mce_in;
+
+		memcpy(m, &pvt->mce_entry[pvt->mce_in], sizeof(*m) * l);
+		smp_wmb();
+		pvt->mce_in = 0;
+		count -= l;
+		m += l;
+	}
+	memcpy(m, &pvt->mce_entry[pvt->mce_in], sizeof(*m) * count);
+	smp_wmb();
+	pvt->mce_in += count;
+
+	smp_rmb();
+	if (pvt->mce_overrun) {
+		sbridge_printk(KERN_ERR, "Lost %d memory errors\n",
+			      pvt->mce_overrun);
+		smp_wmb();
+		pvt->mce_overrun = 0;
+	}
+
+	/*
+	 * MCE second step: parse errors and display
+	 */
+	for (i = 0; i < count; i++)
+		sbridge_mce_output_error(mci, &pvt->mce_outentry[i]);
+}
+
+/*
+ * sbridge_mce_check_error	Replicates mcelog routine to get errors
+ *				This routine simply queues mcelog errors, and
+ *				return. The error itself should be handled later
+ *				by sbridge_check_error.
+ * WARNING: As this routine should be called at NMI time, extra care should
+ * be taken to avoid deadlocks, and to be as fast as possible.
+ */
+static int sbridge_mce_check_error(struct notifier_block *nb, unsigned long val,
+				   void *data)
+{
+	struct mce *mce = (struct mce *)data;
+	struct mem_ctl_info *mci;
+	struct sbridge_pvt *pvt;
+
+	mci = get_mci_for_node_id(mce->socketid);
+	if (!mci)
+		return NOTIFY_BAD;
+	pvt = mci->pvt_info;
+
+	/*
+	 * Just let mcelog handle it if the error is
+	 * outside the memory controller. A memory error
+	 * is indicated by bit 7 = 1 and bits = 8-11,13-15 = 0.
+	 * bit 12 has an special meaning.
+	 */
+	if ((mce->status & 0xefff) >> 7 != 1)
+		return NOTIFY_DONE;
+
+	printk("sbridge: HANDLING MCE MEMORY ERROR\n");
+
+	printk("CPU %d: Machine Check Exception: %Lx Bank %d: %016Lx\n",
+	       mce->extcpu, mce->mcgstatus, mce->bank, mce->status);
+	printk("TSC %llx ", mce->tsc);
+	printk("ADDR %llx ", mce->addr);
+	printk("MISC %llx ", mce->misc);
+
+	printk("PROCESSOR %u:%x TIME %llu SOCKET %u APIC %x\n",
+		mce->cpuvendor, mce->cpuid, mce->time,
+		mce->socketid, mce->apicid);
+
+#ifdef CONFIG_SMP
+	/* Only handle if it is the right mc controller */
+	if (cpu_data(mce->cpu).phys_proc_id != pvt->sbridge_dev->mc)
+		return NOTIFY_DONE;
+#endif
+
+	smp_rmb();
+	if ((pvt->mce_out + 1) % MCE_LOG_LEN == pvt->mce_in) {
+		smp_wmb();
+		pvt->mce_overrun++;
+		return NOTIFY_DONE;
+	}
+
+	/* Copy memory error at the ringbuffer */
+	memcpy(&pvt->mce_entry[pvt->mce_out], mce, sizeof(*mce));
+	smp_wmb();
+	pvt->mce_out = (pvt->mce_out + 1) % MCE_LOG_LEN;
+
+	/* Handle fatal errors immediately */
+	if (mce->mcgstatus & 1)
+		sbridge_check_error(mci);
+
+	/* Advice mcelog that the error were handled */
+	return NOTIFY_STOP;
+}
+
+static struct notifier_block sbridge_mce_dec = {
+	.notifier_call      = sbridge_mce_check_error,
+};
+
+/****************************************************************************
+			EDAC register/unregister logic
+ ****************************************************************************/
+
+static void sbridge_unregister_mci(struct sbridge_dev *sbridge_dev)
+{
+	struct mem_ctl_info *mci = sbridge_dev->mci;
+	struct sbridge_pvt *pvt;
+
+	if (unlikely(!mci || !mci->pvt_info)) {
+		debugf0("MC: " __FILE__ ": %s(): dev = %p\n",
+			__func__, &sbridge_dev->pdev[0]->dev);
+
+		sbridge_printk(KERN_ERR, "Couldn't find mci handler\n");
+		return;
+	}
+
+	pvt = mci->pvt_info;
+
+	debugf0("MC: " __FILE__ ": %s(): mci = %p, dev = %p\n",
+		__func__, mci, &sbridge_dev->pdev[0]->dev);
+
+	atomic_notifier_chain_unregister(&x86_mce_decoder_chain,
+					 &sbridge_mce_dec);
+
+	/* Remove MC sysfs nodes */
+	edac_mc_del_mc(mci->dev);
+
+	debugf1("%s: free mci struct\n", mci->ctl_name);
+	kfree(mci->ctl_name);
+	edac_mc_free(mci);
+	sbridge_dev->mci = NULL;
+}
+
+static int sbridge_register_mci(struct sbridge_dev *sbridge_dev)
+{
+	struct mem_ctl_info *mci;
+	struct sbridge_pvt *pvt;
+	int rc, channels, csrows;
+
+	/* Check the number of active and not disabled channels */
+	rc = sbridge_get_active_channels(sbridge_dev->bus, &channels, &csrows);
+	if (unlikely(rc < 0))
+		return rc;
+
+	/* allocate a new MC control structure */
+	mci = edac_mc_alloc(sizeof(*pvt), csrows, channels, sbridge_dev->mc);
+	if (unlikely(!mci))
+		return -ENOMEM;
+
+	debugf0("MC: " __FILE__ ": %s(): mci = %p, dev = %p\n",
+		__func__, mci, &sbridge_dev->pdev[0]->dev);
+
+	pvt = mci->pvt_info;
+	memset(pvt, 0, sizeof(*pvt));
+
+	/* Associate sbridge_dev and mci for future usage */
+	pvt->sbridge_dev = sbridge_dev;
+	sbridge_dev->mci = mci;
+
+	mci->mtype_cap = MEM_FLAG_DDR3;
+	mci->edac_ctl_cap = EDAC_FLAG_NONE;
+	mci->edac_cap = EDAC_FLAG_NONE;
+	mci->mod_name = "sbridge_edac.c";
+	mci->mod_ver = SBRIDGE_REVISION;
+	mci->ctl_name = kasprintf(GFP_KERNEL, "Sandy Bridge Socket#%d", mci->mc_idx);
+	mci->dev_name = pci_name(sbridge_dev->pdev[0]);
+	mci->ctl_page_to_phys = NULL;
+
+	/* Set the function pointer to an actual operation function */
+	mci->edac_check = sbridge_check_error;
+
+	/* Store pci devices at mci for faster access */
+	rc = mci_bind_devs(mci, sbridge_dev);
+	if (unlikely(rc < 0))
+		goto fail0;
+
+	/* Get dimm basic config and the memory layout */
+	get_dimm_config(mci);
+	get_memory_layout(mci);
+
+	/* record ptr to the generic device */
+	mci->dev = &sbridge_dev->pdev[0]->dev;
+
+	/* add this new MC control structure to EDAC's list of MCs */
+	if (unlikely(edac_mc_add_mc(mci))) {
+		debugf0("MC: " __FILE__
+			": %s(): failed edac_mc_add_mc()\n", __func__);
+		rc = -EINVAL;
+		goto fail0;
+	}
+
+	atomic_notifier_chain_register(&x86_mce_decoder_chain,
+				       &sbridge_mce_dec);
+	return 0;
+
+fail0:
+	kfree(mci->ctl_name);
+	edac_mc_free(mci);
+	sbridge_dev->mci = NULL;
+	return rc;
+}
+
+/*
+ *	sbridge_probe	Probe for ONE instance of device to see if it is
+ *			present.
+ *	return:
+ *		0 for FOUND a device
+ *		< 0 for error code
+ */
+
+static int __devinit sbridge_probe(struct pci_dev *pdev,
+				  const struct pci_device_id *id)
+{
+	int rc;
+	u8 mc, num_mc = 0;
+	struct sbridge_dev *sbridge_dev;
+
+	/* get the pci devices we want to reserve for our use */
+	mutex_lock(&sbridge_edac_lock);
+
+	/*
+	 * All memory controllers are allocated at the first pass.
+	 */
+	if (unlikely(probed >= 1)) {
+		mutex_unlock(&sbridge_edac_lock);
+		return -ENODEV;
+	}
+	probed++;
+
+	rc = sbridge_get_all_devices(&num_mc);
+	if (unlikely(rc < 0))
+		goto fail0;
+	mc = 0;
+
+	list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) {
+		debugf0("Registering MC#%d (%d of %d)\n", mc, mc + 1, num_mc);
+		sbridge_dev->mc = mc++;
+		rc = sbridge_register_mci(sbridge_dev);
+		if (unlikely(rc < 0))
+			goto fail1;
+	}
+
+	sbridge_printk(KERN_INFO, "Driver loaded.\n");
+
+	mutex_unlock(&sbridge_edac_lock);
+	return 0;
+
+fail1:
+	list_for_each_entry(sbridge_dev, &sbridge_edac_list, list)
+		sbridge_unregister_mci(sbridge_dev);
+
+	sbridge_put_all_devices();
+fail0:
+	mutex_unlock(&sbridge_edac_lock);
+	return rc;
+}
+
+/*
+ *	sbridge_remove	destructor for one instance of device
+ *
+ */
+static void __devexit sbridge_remove(struct pci_dev *pdev)
+{
+	struct sbridge_dev *sbridge_dev;
+
+	debugf0(__FILE__ ": %s()\n", __func__);
+
+	/*
+	 * we have a trouble here: pdev value for removal will be wrong, since
+	 * it will point to the X58 register used to detect that the machine
+	 * is a Nehalem or upper design. However, due to the way several PCI
+	 * devices are grouped together to provide MC functionality, we need
+	 * to use a different method for releasing the devices
+	 */
+
+	mutex_lock(&sbridge_edac_lock);
+
+	if (unlikely(!probed)) {
+		mutex_unlock(&sbridge_edac_lock);
+		return;
+	}
+
+	list_for_each_entry(sbridge_dev, &sbridge_edac_list, list)
+		sbridge_unregister_mci(sbridge_dev);
+
+	/* Release PCI resources */
+	sbridge_put_all_devices();
+
+	probed--;
+
+	mutex_unlock(&sbridge_edac_lock);
+}
+
+MODULE_DEVICE_TABLE(pci, sbridge_pci_tbl);
+
+/*
+ *	sbridge_driver	pci_driver structure for this module
+ *
+ */
+static struct pci_driver sbridge_driver = {
+	.name     = "sbridge_edac",
+	.probe    = sbridge_probe,
+	.remove   = __devexit_p(sbridge_remove),
+	.id_table = sbridge_pci_tbl,
+};
+
+/*
+ *	sbridge_init		Module entry function
+ *			Try to initialize this module for its devices
+ */
+static int __init sbridge_init(void)
+{
+	int pci_rc;
+
+	debugf2("MC: " __FILE__ ": %s()\n", __func__);
+
+	/* Ensure that the OPSTATE is set correctly for POLL or NMI */
+	opstate_init();
+
+	pci_rc = pci_register_driver(&sbridge_driver);
+
+	if (pci_rc >= 0)
+		return 0;
+
+	sbridge_printk(KERN_ERR, "Failed to register device with error %d.\n",
+		      pci_rc);
+
+	return pci_rc;
+}
+
+/*
+ *	sbridge_exit()	Module exit function
+ *			Unregister the driver
+ */
+static void __exit sbridge_exit(void)
+{
+	debugf2("MC: " __FILE__ ": %s()\n", __func__);
+	pci_unregister_driver(&sbridge_driver);
+}
+
+module_init(sbridge_init);
+module_exit(sbridge_exit);
+
+module_param(edac_op_state, int, 0444);
+MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
+MODULE_DESCRIPTION("MC Driver for Intel Sandy Bridge memory controllers - "
+		   SBRIDGE_REVISION);
diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c
index 334b82a..855ab3f 100644
--- a/drivers/firewire/core-transaction.c
+++ b/drivers/firewire/core-transaction.c
@@ -1046,8 +1046,8 @@ static void update_split_timeout(struct fw_card *card)
 
 	cycles = card->split_timeout_hi * 8000 + (card->split_timeout_lo >> 19);
 
-	cycles = max(cycles, 800u); /* minimum as per the spec */
-	cycles = min(cycles, 3u * 8000u); /* maximum OHCI timeout */
+	/* minimum per IEEE 1394, maximum which doesn't overflow OHCI */
+	cycles = clamp(cycles, 800u, 3u * 8000u);
 
 	card->split_timeout_cycles = cycles;
 	card->split_timeout_jiffies = DIV_ROUND_UP(cycles * HZ, 8000);
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index 03a7a85..a20f45b 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -502,11 +502,7 @@ static struct fwnet_peer *fwnet_peer_find_by_node_id(struct fwnet_device *dev,
 static unsigned fwnet_max_payload(unsigned max_rec, unsigned speed)
 {
 	max_rec = min(max_rec, speed + 8);
-	max_rec = min(max_rec, 0xbU); /* <= 4096 */
-	if (max_rec < 8) {
-		fw_notify("max_rec %x out of range\n", max_rec);
-		max_rec = 8;
-	}
+	max_rec = clamp(max_rec, 8U, 11U); /* 512...4096 */
 
 	return (1 << (max_rec + 1)) - RFC2374_FRAG_HDR_SIZE;
 }
@@ -1125,17 +1121,12 @@ static int fwnet_broadcast_start(struct fwnet_device *dev)
 	unsigned u;
 
 	if (dev->local_fifo == FWNET_NO_FIFO_ADDR) {
-		/* outside OHCI posted write area? */
-		static const struct fw_address_region region = {
-			.start = 0xffff00000000ULL,
-			.end   = CSR_REGISTER_BASE,
-		};
-
 		dev->handler.length = 4096;
 		dev->handler.address_callback = fwnet_receive_packet;
 		dev->handler.callback_data = dev;
 
-		retval = fw_core_add_address_handler(&dev->handler, &region);
+		retval = fw_core_add_address_handler(&dev->handler,
+					&fw_high_memory_region);
 		if (retval < 0)
 			goto failed_initial;
 
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index fd7170a..6628fea 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -42,6 +42,7 @@
 #include <linux/string.h>
 #include <linux/time.h>
 #include <linux/vmalloc.h>
+#include <linux/workqueue.h>
 
 #include <asm/byteorder.h>
 #include <asm/page.h>
@@ -125,6 +126,7 @@ struct context {
 	struct fw_ohci *ohci;
 	u32 regs;
 	int total_allocation;
+	u32 current_bus;
 	bool running;
 	bool flushing;
 
@@ -226,7 +228,7 @@ struct fw_ohci {
 
 	__le32    *self_id_cpu;
 	dma_addr_t self_id_bus;
-	struct tasklet_struct bus_reset_tasklet;
+	struct work_struct bus_reset_work;
 
 	u32 self_id_buffer[512];
 };
@@ -263,6 +265,8 @@ static char ohci_driver_name[] = KBUILD_MODNAME;
 #define PCI_DEVICE_ID_AGERE_FW643	0x5901
 #define PCI_DEVICE_ID_JMICRON_JMB38X_FW	0x2380
 #define PCI_DEVICE_ID_TI_TSB12LV22	0x8009
+#define PCI_DEVICE_ID_TI_TSB12LV26	0x8020
+#define PCI_DEVICE_ID_TI_TSB82AA2	0x8025
 #define PCI_VENDOR_ID_PINNACLE_SYSTEMS	0x11bd
 
 #define QUIRK_CYCLE_TIMER		1
@@ -270,6 +274,7 @@ static char ohci_driver_name[] = KBUILD_MODNAME;
 #define QUIRK_BE_HEADERS		4
 #define QUIRK_NO_1394A			8
 #define QUIRK_NO_MSI			16
+#define QUIRK_TI_SLLZ059		32
 
 /* In case of multiple matches in ohci_quirks[], only the first one is used. */
 static const struct {
@@ -299,6 +304,12 @@ static const struct {
 	{PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, PCI_ANY_ID,
 		QUIRK_CYCLE_TIMER | QUIRK_RESET_PACKET | QUIRK_NO_1394A},
 
+	{PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV26, PCI_ANY_ID,
+		QUIRK_RESET_PACKET | QUIRK_TI_SLLZ059},
+
+	{PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB82AA2, PCI_ANY_ID,
+		QUIRK_RESET_PACKET | QUIRK_TI_SLLZ059},
+
 	{PCI_VENDOR_ID_TI, PCI_ANY_ID, PCI_ANY_ID,
 		QUIRK_RESET_PACKET},
 
@@ -315,6 +326,7 @@ MODULE_PARM_DESC(quirks, "Chip quirks (default = 0"
 	", AR/selfID endianess = "	__stringify(QUIRK_BE_HEADERS)
 	", no 1394a enhancements = "	__stringify(QUIRK_NO_1394A)
 	", disable MSI = "		__stringify(QUIRK_NO_MSI)
+	", TI SLLZ059 erratum = "	__stringify(QUIRK_TI_SLLZ059)
 	")");
 
 #define OHCI_PARAM_DEBUG_AT_AR		1
@@ -859,7 +871,7 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
 	 *
 	 * Alas some chips sometimes emit bus reset packets with a
 	 * wrong generation.  We set the correct generation for these
-	 * at a slightly incorrect time (in bus_reset_tasklet).
+	 * at a slightly incorrect time (in bus_reset_work).
 	 */
 	if (evt == OHCI1394_evt_bus_reset) {
 		if (!(ohci->quirks & QUIRK_RESET_PACKET))
@@ -1046,6 +1058,7 @@ static void context_tasklet(unsigned long data)
 		address = le32_to_cpu(last->branch_address);
 		z = address & 0xf;
 		address &= ~0xf;
+		ctx->current_bus = address;
 
 		/* If the branch address points to a buffer outside of the
 		 * current buffer, advance to the next buffer. */
@@ -1713,9 +1726,94 @@ static u32 update_bus_time(struct fw_ohci *ohci)
 	return ohci->bus_time | cycle_time_seconds;
 }
 
-static void bus_reset_tasklet(unsigned long data)
+static int get_status_for_port(struct fw_ohci *ohci, int port_index)
+{
+	int reg;
+
+	mutex_lock(&ohci->phy_reg_mutex);
+	reg = write_phy_reg(ohci, 7, port_index);
+	if (reg >= 0)
+		reg = read_phy_reg(ohci, 8);
+	mutex_unlock(&ohci->phy_reg_mutex);
+	if (reg < 0)
+		return reg;
+
+	switch (reg & 0x0f) {
+	case 0x06:
+		return 2;	/* is child node (connected to parent node) */
+	case 0x0e:
+		return 3;	/* is parent node (connected to child node) */
+	}
+	return 1;		/* not connected */
+}
+
+static int get_self_id_pos(struct fw_ohci *ohci, u32 self_id,
+	int self_id_count)
+{
+	int i;
+	u32 entry;
+
+	for (i = 0; i < self_id_count; i++) {
+		entry = ohci->self_id_buffer[i];
+		if ((self_id & 0xff000000) == (entry & 0xff000000))
+			return -1;
+		if ((self_id & 0xff000000) < (entry & 0xff000000))
+			return i;
+	}
+	return i;
+}
+
+/*
+ * TI TSB82AA2B and TSB12LV26 do not receive the selfID of a locally
+ * attached TSB41BA3D phy; see http://www.ti.com/litv/pdf/sllz059.
+ * Construct the selfID from phy register contents.
+ * FIXME:  How to determine the selfID.i flag?
+ */
+static int find_and_insert_self_id(struct fw_ohci *ohci, int self_id_count)
+{
+	int reg, i, pos, status;
+	/* link active 1, speed 3, bridge 0, contender 1, more packets 0 */
+	u32 self_id = 0x8040c800;
+
+	reg = reg_read(ohci, OHCI1394_NodeID);
+	if (!(reg & OHCI1394_NodeID_idValid)) {
+		fw_notify("node ID not valid, new bus reset in progress\n");
+		return -EBUSY;
+	}
+	self_id |= ((reg & 0x3f) << 24); /* phy ID */
+
+	reg = ohci_read_phy_reg(&ohci->card, 4);
+	if (reg < 0)
+		return reg;
+	self_id |= ((reg & 0x07) << 8); /* power class */
+
+	reg = ohci_read_phy_reg(&ohci->card, 1);
+	if (reg < 0)
+		return reg;
+	self_id |= ((reg & 0x3f) << 16); /* gap count */
+
+	for (i = 0; i < 3; i++) {
+		status = get_status_for_port(ohci, i);
+		if (status < 0)
+			return status;
+		self_id |= ((status & 0x3) << (6 - (i * 2)));
+	}
+
+	pos = get_self_id_pos(ohci, self_id, self_id_count);
+	if (pos >= 0) {
+		memmove(&(ohci->self_id_buffer[pos+1]),
+			&(ohci->self_id_buffer[pos]),
+			(self_id_count - pos) * sizeof(*ohci->self_id_buffer));
+		ohci->self_id_buffer[pos] = self_id;
+		self_id_count++;
+	}
+	return self_id_count;
+}
+
+static void bus_reset_work(struct work_struct *work)
 {
-	struct fw_ohci *ohci = (struct fw_ohci *)data;
+	struct fw_ohci *ohci =
+		container_of(work, struct fw_ohci, bus_reset_work);
 	int self_id_count, i, j, reg;
 	int generation, new_generation;
 	unsigned long flags;
@@ -1753,21 +1851,50 @@ static void bus_reset_tasklet(unsigned long data)
 	 * bit extra to get the actual number of self IDs.
 	 */
 	self_id_count = (reg >> 3) & 0xff;
-	if (self_id_count == 0 || self_id_count > 252) {
+
+	if (self_id_count > 252) {
 		fw_notify("inconsistent self IDs\n");
 		return;
 	}
+
 	generation = (cond_le32_to_cpu(ohci->self_id_cpu[0]) >> 16) & 0xff;
 	rmb();
 
 	for (i = 1, j = 0; j < self_id_count; i += 2, j++) {
 		if (ohci->self_id_cpu[i] != ~ohci->self_id_cpu[i + 1]) {
-			fw_notify("inconsistent self IDs\n");
-			return;
+			/*
+			 * If the invalid data looks like a cycle start packet,
+			 * it's likely to be the result of the cycle master
+			 * having a wrong gap count.  In this case, the self IDs
+			 * so far are valid and should be processed so that the
+			 * bus manager can then correct the gap count.
+			 */
+			if (cond_le32_to_cpu(ohci->self_id_cpu[i])
+							== 0xffff008f) {
+				fw_notify("ignoring spurious self IDs\n");
+				self_id_count = j;
+				break;
+			} else {
+				fw_notify("inconsistent self IDs\n");
+				return;
+			}
 		}
 		ohci->self_id_buffer[j] =
 				cond_le32_to_cpu(ohci->self_id_cpu[i]);
 	}
+
+	if (ohci->quirks & QUIRK_TI_SLLZ059) {
+		self_id_count = find_and_insert_self_id(ohci, self_id_count);
+		if (self_id_count < 0) {
+			fw_notify("could not construct local self ID\n");
+			return;
+		}
+	}
+
+	if (self_id_count == 0) {
+		fw_notify("inconsistent self IDs\n");
+		return;
+	}
 	rmb();
 
 	/*
@@ -1887,7 +2014,7 @@ static irqreturn_t irq_handler(int irq, void *data)
 	log_irqs(event);
 
 	if (event & OHCI1394_selfIDComplete)
-		tasklet_schedule(&ohci->bus_reset_tasklet);
+		queue_work(fw_workqueue, &ohci->bus_reset_work);
 
 	if (event & OHCI1394_RQPkt)
 		tasklet_schedule(&ohci->ar_request_ctx.tasklet);
@@ -1934,7 +2061,8 @@ static irqreturn_t irq_handler(int irq, void *data)
 		reg_read(ohci, OHCI1394_PostedWriteAddressLo);
 		reg_write(ohci, OHCI1394_IntEventClear,
 			  OHCI1394_postedWriteErr);
-		fw_error("PCI posted write error\n");
+		if (printk_ratelimit())
+			fw_error("PCI posted write error\n");
 	}
 
 	if (unlikely(event & OHCI1394_cycleTooLong)) {
@@ -2048,6 +2176,28 @@ static int configure_1394a_enhancements(struct fw_ohci *ohci)
 	return 0;
 }
 
+static int probe_tsb41ba3d(struct fw_ohci *ohci)
+{
+	/* TI vendor ID = 0x080028, TSB41BA3D product ID = 0x833005 (sic) */
+	static const u8 id[] = { 0x08, 0x00, 0x28, 0x83, 0x30, 0x05, };
+	int reg, i;
+
+	reg = read_phy_reg(ohci, 2);
+	if (reg < 0)
+		return reg;
+	if ((reg & PHY_EXTENDED_REGISTERS) != PHY_EXTENDED_REGISTERS)
+		return 0;
+
+	for (i = ARRAY_SIZE(id) - 1; i >= 0; i--) {
+		reg = read_paged_phy_reg(ohci, 1, i + 10);
+		if (reg < 0)
+			return reg;
+		if (reg != id[i])
+			return 0;
+	}
+	return 1;
+}
+
 static int ohci_enable(struct fw_card *card,
 		       const __be32 *config_rom, size_t length)
 {
@@ -2085,6 +2235,16 @@ static int ohci_enable(struct fw_card *card,
 		return -EIO;
 	}
 
+	if (ohci->quirks & QUIRK_TI_SLLZ059) {
+		ret = probe_tsb41ba3d(ohci);
+		if (ret < 0)
+			return ret;
+		if (ret)
+			fw_notify("local TSB41BA3D phy\n");
+		else
+			ohci->quirks &= ~QUIRK_TI_SLLZ059;
+	}
+
 	reg_write(ohci, OHCI1394_HCControlClear,
 		  OHCI1394_HCControl_noByteSwapData);
 
@@ -2260,7 +2420,7 @@ static int ohci_set_config_rom(struct fw_card *card,
 	 * then set up the real values for the two registers.
 	 *
 	 * We use ohci->lock to avoid racing with the code that sets
-	 * ohci->next_config_rom to NULL (see bus_reset_tasklet).
+	 * ohci->next_config_rom to NULL (see bus_reset_work).
 	 */
 
 	next_config_rom =
@@ -2539,6 +2699,7 @@ static int handle_ir_packet_per_buffer(struct context *context,
 	struct iso_context *ctx =
 		container_of(context, struct iso_context, context);
 	struct descriptor *pd;
+	u32 buffer_dma;
 	__le32 *ir_header;
 	void *p;
 
@@ -2549,6 +2710,16 @@ static int handle_ir_packet_per_buffer(struct context *context,
 		/* Descriptor(s) not done yet, stop iteration */
 		return 0;
 
+	while (!(d->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS))) {
+		d++;
+		buffer_dma = le32_to_cpu(d->data_address);
+		dma_sync_single_range_for_cpu(context->ohci->card.device,
+					      buffer_dma & PAGE_MASK,
+					      buffer_dma & ~PAGE_MASK,
+					      le16_to_cpu(d->req_count),
+					      DMA_FROM_DEVICE);
+	}
+
 	p = last + 1;
 	copy_iso_headers(ctx, p);
 
@@ -2571,11 +2742,19 @@ static int handle_ir_buffer_fill(struct context *context,
 {
 	struct iso_context *ctx =
 		container_of(context, struct iso_context, context);
+	u32 buffer_dma;
 
 	if (!last->transfer_status)
 		/* Descriptor(s) not done yet, stop iteration */
 		return 0;
 
+	buffer_dma = le32_to_cpu(last->data_address);
+	dma_sync_single_range_for_cpu(context->ohci->card.device,
+				      buffer_dma & PAGE_MASK,
+				      buffer_dma & ~PAGE_MASK,
+				      le16_to_cpu(last->req_count),
+				      DMA_FROM_DEVICE);
+
 	if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS)
 		ctx->base.callback.mc(&ctx->base,
 				      le32_to_cpu(last->data_address) +
@@ -2586,6 +2765,43 @@ static int handle_ir_buffer_fill(struct context *context,
 	return 1;
 }
 
+static inline void sync_it_packet_for_cpu(struct context *context,
+					  struct descriptor *pd)
+{
+	__le16 control;
+	u32 buffer_dma;
+
+	/* only packets beginning with OUTPUT_MORE* have data buffers */
+	if (pd->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS))
+		return;
+
+	/* skip over the OUTPUT_MORE_IMMEDIATE descriptor */
+	pd += 2;
+
+	/*
+	 * If the packet has a header, the first OUTPUT_MORE/LAST descriptor's
+	 * data buffer is in the context program's coherent page and must not
+	 * be synced.
+	 */
+	if ((le32_to_cpu(pd->data_address) & PAGE_MASK) ==
+	    (context->current_bus          & PAGE_MASK)) {
+		if (pd->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS))
+			return;
+		pd++;
+	}
+
+	do {
+		buffer_dma = le32_to_cpu(pd->data_address);
+		dma_sync_single_range_for_cpu(context->ohci->card.device,
+					      buffer_dma & PAGE_MASK,
+					      buffer_dma & ~PAGE_MASK,
+					      le16_to_cpu(pd->req_count),
+					      DMA_TO_DEVICE);
+		control = pd->control;
+		pd++;
+	} while (!(control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS)));
+}
+
 static int handle_it_packet(struct context *context,
 			    struct descriptor *d,
 			    struct descriptor *last)
@@ -2602,6 +2818,8 @@ static int handle_it_packet(struct context *context,
 		/* Descriptor(s) not done yet, stop iteration */
 		return 0;
 
+	sync_it_packet_for_cpu(context, d);
+
 	i = ctx->header_length;
 	if (i + 4 < PAGE_SIZE) {
 		/* Present this value as big-endian to match the receive code */
@@ -2971,6 +3189,10 @@ static int queue_iso_transmit(struct iso_context *ctx,
 		page_bus = page_private(buffer->pages[page]);
 		pd[i].data_address = cpu_to_le32(page_bus + offset);
 
+		dma_sync_single_range_for_device(ctx->context.ohci->card.device,
+						 page_bus, offset, length,
+						 DMA_TO_DEVICE);
+
 		payload_index += length;
 	}
 
@@ -2995,6 +3217,7 @@ static int queue_iso_packet_per_buffer(struct iso_context *ctx,
 				       struct fw_iso_buffer *buffer,
 				       unsigned long payload)
 {
+	struct device *device = ctx->context.ohci->card.device;
 	struct descriptor *d, *pd;
 	dma_addr_t d_bus, page_bus;
 	u32 z, header_z, rest;
@@ -3049,6 +3272,10 @@ static int queue_iso_packet_per_buffer(struct iso_context *ctx,
 			page_bus = page_private(buffer->pages[page]);
 			pd->data_address = cpu_to_le32(page_bus + offset);
 
+			dma_sync_single_range_for_device(device, page_bus,
+							 offset, length,
+							 DMA_FROM_DEVICE);
+
 			offset = (offset + length) & ~PAGE_MASK;
 			rest -= length;
 			if (offset == 0)
@@ -3108,6 +3335,10 @@ static int queue_iso_buffer_fill(struct iso_context *ctx,
 		page_bus = page_private(buffer->pages[page]);
 		d->data_address = cpu_to_le32(page_bus + offset);
 
+		dma_sync_single_range_for_device(ctx->context.ohci->card.device,
+						 page_bus, offset, length,
+						 DMA_FROM_DEVICE);
+
 		rest -= length;
 		offset = 0;
 		page++;
@@ -3239,8 +3470,7 @@ static int __devinit pci_probe(struct pci_dev *dev,
 	spin_lock_init(&ohci->lock);
 	mutex_init(&ohci->phy_reg_mutex);
 
-	tasklet_init(&ohci->bus_reset_tasklet,
-		     bus_reset_tasklet, (unsigned long)ohci);
+	INIT_WORK(&ohci->bus_reset_work, bus_reset_work);
 
 	err = pci_request_region(dev, 0, ohci_driver_name);
 	if (err) {
@@ -3382,6 +3612,7 @@ static void pci_remove(struct pci_dev *dev)
 	ohci = pci_get_drvdata(dev);
 	reg_write(ohci, OHCI1394_IntMaskClear, ~0);
 	flush_writes(ohci);
+	cancel_work_sync(&ohci->bus_reset_work);
 	fw_core_remove_card(&ohci->card);
 
 	/*
diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c
index 17cef86..68375bc 100644
--- a/drivers/firewire/sbp2.c
+++ b/drivers/firewire/sbp2.c
@@ -154,12 +154,16 @@ struct sbp2_logical_unit {
 	bool blocked;
 };
 
+static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay)
+{
+	queue_delayed_work(fw_workqueue, &lu->work, delay);
+}
+
 /*
  * We create one struct sbp2_target per IEEE 1212 Unit Directory
  * and one struct Scsi_Host per sbp2_target.
  */
 struct sbp2_target {
-	struct kref kref;
 	struct fw_unit *unit;
 	const char *bus_id;
 	struct list_head lu_list;
@@ -772,71 +776,6 @@ static int sbp2_lun2int(u16 lun)
 	return scsilun_to_int(&eight_bytes_lun);
 }
 
-static void sbp2_release_target(struct kref *kref)
-{
-	struct sbp2_target *tgt = container_of(kref, struct sbp2_target, kref);
-	struct sbp2_logical_unit *lu, *next;
-	struct Scsi_Host *shost =
-		container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
-	struct scsi_device *sdev;
-	struct fw_device *device = target_device(tgt);
-
-	/* prevent deadlocks */
-	sbp2_unblock(tgt);
-
-	list_for_each_entry_safe(lu, next, &tgt->lu_list, link) {
-		sdev = scsi_device_lookup(shost, 0, 0, sbp2_lun2int(lu->lun));
-		if (sdev) {
-			scsi_remove_device(sdev);
-			scsi_device_put(sdev);
-		}
-		if (lu->login_id != INVALID_LOGIN_ID) {
-			int generation, node_id;
-			/*
-			 * tgt->node_id may be obsolete here if we failed
-			 * during initial login or after a bus reset where
-			 * the topology changed.
-			 */
-			generation = device->generation;
-			smp_rmb(); /* node_id vs. generation */
-			node_id    = device->node_id;
-			sbp2_send_management_orb(lu, node_id, generation,
-						 SBP2_LOGOUT_REQUEST,
-						 lu->login_id, NULL);
-		}
-		fw_core_remove_address_handler(&lu->address_handler);
-		list_del(&lu->link);
-		kfree(lu);
-	}
-	scsi_remove_host(shost);
-	fw_notify("released %s, target %d:0:0\n", tgt->bus_id, shost->host_no);
-
-	fw_unit_put(tgt->unit);
-	scsi_host_put(shost);
-	fw_device_put(device);
-}
-
-static void sbp2_target_get(struct sbp2_target *tgt)
-{
-	kref_get(&tgt->kref);
-}
-
-static void sbp2_target_put(struct sbp2_target *tgt)
-{
-	kref_put(&tgt->kref, sbp2_release_target);
-}
-
-/*
- * Always get the target's kref when scheduling work on one its units.
- * Each workqueue job is responsible to call sbp2_target_put() upon return.
- */
-static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay)
-{
-	sbp2_target_get(lu->tgt);
-	if (!queue_delayed_work(fw_workqueue, &lu->work, delay))
-		sbp2_target_put(lu->tgt);
-}
-
 /*
  * Write retransmit retry values into the BUSY_TIMEOUT register.
  * - The single-phase retry protocol is supported by all SBP-2 devices, but the
@@ -877,7 +816,7 @@ static void sbp2_login(struct work_struct *work)
 	int generation, node_id, local_node_id;
 
 	if (fw_device_is_shutdown(device))
-		goto out;
+		return;
 
 	generation    = device->generation;
 	smp_rmb();    /* node IDs must not be older than generation */
@@ -899,7 +838,7 @@ static void sbp2_login(struct work_struct *work)
 			/* Let any waiting I/O fail from now on. */
 			sbp2_unblock(lu->tgt);
 		}
-		goto out;
+		return;
 	}
 
 	tgt->node_id	  = node_id;
@@ -925,7 +864,8 @@ static void sbp2_login(struct work_struct *work)
 	if (lu->has_sdev) {
 		sbp2_cancel_orbs(lu);
 		sbp2_conditionally_unblock(lu);
-		goto out;
+
+		return;
 	}
 
 	if (lu->tgt->workarounds & SBP2_WORKAROUND_DELAY_INQUIRY)
@@ -957,7 +897,8 @@ static void sbp2_login(struct work_struct *work)
 	lu->has_sdev = true;
 	scsi_device_put(sdev);
 	sbp2_allow_block(lu);
-	goto out;
+
+	return;
 
  out_logout_login:
 	smp_rmb(); /* generation may have changed */
@@ -971,8 +912,57 @@ static void sbp2_login(struct work_struct *work)
 	 * lu->work already.  Reset the work from reconnect to login.
 	 */
 	PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
- out:
-	sbp2_target_put(tgt);
+}
+
+static void sbp2_reconnect(struct work_struct *work)
+{
+	struct sbp2_logical_unit *lu =
+		container_of(work, struct sbp2_logical_unit, work.work);
+	struct sbp2_target *tgt = lu->tgt;
+	struct fw_device *device = target_device(tgt);
+	int generation, node_id, local_node_id;
+
+	if (fw_device_is_shutdown(device))
+		return;
+
+	generation    = device->generation;
+	smp_rmb();    /* node IDs must not be older than generation */
+	node_id       = device->node_id;
+	local_node_id = device->card->node_id;
+
+	if (sbp2_send_management_orb(lu, node_id, generation,
+				     SBP2_RECONNECT_REQUEST,
+				     lu->login_id, NULL) < 0) {
+		/*
+		 * If reconnect was impossible even though we are in the
+		 * current generation, fall back and try to log in again.
+		 *
+		 * We could check for "Function rejected" status, but
+		 * looking at the bus generation as simpler and more general.
+		 */
+		smp_rmb(); /* get current card generation */
+		if (generation == device->card->generation ||
+		    lu->retries++ >= 5) {
+			fw_error("%s: failed to reconnect\n", tgt->bus_id);
+			lu->retries = 0;
+			PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
+		}
+		sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
+
+		return;
+	}
+
+	tgt->node_id      = node_id;
+	tgt->address_high = local_node_id << 16;
+	smp_wmb();	  /* node IDs must not be older than generation */
+	lu->generation	  = generation;
+
+	fw_notify("%s: reconnected to LUN %04x (%d retries)\n",
+		  tgt->bus_id, lu->lun, lu->retries);
+
+	sbp2_agent_reset(lu);
+	sbp2_cancel_orbs(lu);
+	sbp2_conditionally_unblock(lu);
 }
 
 static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry)
@@ -1120,6 +1110,7 @@ static void sbp2_init_workarounds(struct sbp2_target *tgt, u32 model,
 }
 
 static struct scsi_host_template scsi_driver_template;
+static int sbp2_remove(struct device *dev);
 
 static int sbp2_probe(struct device *dev)
 {
@@ -1141,7 +1132,6 @@ static int sbp2_probe(struct device *dev)
 	tgt = (struct sbp2_target *)shost->hostdata;
 	dev_set_drvdata(&unit->device, tgt);
 	tgt->unit = unit;
-	kref_init(&tgt->kref);
 	INIT_LIST_HEAD(&tgt->lu_list);
 	tgt->bus_id = dev_name(&unit->device);
 	tgt->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4];
@@ -1154,9 +1144,6 @@ static int sbp2_probe(struct device *dev)
 	if (scsi_add_host(shost, &unit->device) < 0)
 		goto fail_shost_put;
 
-	fw_device_get(device);
-	fw_unit_get(unit);
-
 	/* implicit directory ID */
 	tgt->directory_id = ((unit->directory - device->config_rom) * 4
 			     + CSR_CONFIG_ROM) & 0xffffff;
@@ -1166,7 +1153,7 @@ static int sbp2_probe(struct device *dev)
 
 	if (sbp2_scan_unit_dir(tgt, unit->directory, &model,
 			       &firmware_revision) < 0)
-		goto fail_tgt_put;
+		goto fail_remove;
 
 	sbp2_clamp_management_orb_timeout(tgt);
 	sbp2_init_workarounds(tgt, model, firmware_revision);
@@ -1177,16 +1164,17 @@ static int sbp2_probe(struct device *dev)
 	 * specifies the max payload size as 2 ^ (max_payload + 2), so
 	 * if we set this to max_speed + 7, we get the right value.
 	 */
-	tgt->max_payload = min(device->max_speed + 7, 10U);
-	tgt->max_payload = min(tgt->max_payload, device->card->max_receive - 1);
+	tgt->max_payload = min3(device->max_speed + 7, 10U,
+				device->card->max_receive - 1);
 
 	/* Do the login in a workqueue so we can easily reschedule retries. */
 	list_for_each_entry(lu, &tgt->lu_list, link)
 		sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
+
 	return 0;
 
- fail_tgt_put:
-	sbp2_target_put(tgt);
+ fail_remove:
+	sbp2_remove(dev);
 	return -ENOMEM;
 
  fail_shost_put:
@@ -1194,71 +1182,6 @@ static int sbp2_probe(struct device *dev)
 	return -ENOMEM;
 }
 
-static int sbp2_remove(struct device *dev)
-{
-	struct fw_unit *unit = fw_unit(dev);
-	struct sbp2_target *tgt = dev_get_drvdata(&unit->device);
-	struct sbp2_logical_unit *lu;
-
-	list_for_each_entry(lu, &tgt->lu_list, link)
-		cancel_delayed_work_sync(&lu->work);
-
-	sbp2_target_put(tgt);
-	return 0;
-}
-
-static void sbp2_reconnect(struct work_struct *work)
-{
-	struct sbp2_logical_unit *lu =
-		container_of(work, struct sbp2_logical_unit, work.work);
-	struct sbp2_target *tgt = lu->tgt;
-	struct fw_device *device = target_device(tgt);
-	int generation, node_id, local_node_id;
-
-	if (fw_device_is_shutdown(device))
-		goto out;
-
-	generation    = device->generation;
-	smp_rmb();    /* node IDs must not be older than generation */
-	node_id       = device->node_id;
-	local_node_id = device->card->node_id;
-
-	if (sbp2_send_management_orb(lu, node_id, generation,
-				     SBP2_RECONNECT_REQUEST,
-				     lu->login_id, NULL) < 0) {
-		/*
-		 * If reconnect was impossible even though we are in the
-		 * current generation, fall back and try to log in again.
-		 *
-		 * We could check for "Function rejected" status, but
-		 * looking at the bus generation as simpler and more general.
-		 */
-		smp_rmb(); /* get current card generation */
-		if (generation == device->card->generation ||
-		    lu->retries++ >= 5) {
-			fw_error("%s: failed to reconnect\n", tgt->bus_id);
-			lu->retries = 0;
-			PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
-		}
-		sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
-		goto out;
-	}
-
-	tgt->node_id      = node_id;
-	tgt->address_high = local_node_id << 16;
-	smp_wmb();	  /* node IDs must not be older than generation */
-	lu->generation	  = generation;
-
-	fw_notify("%s: reconnected to LUN %04x (%d retries)\n",
-		  tgt->bus_id, lu->lun, lu->retries);
-
-	sbp2_agent_reset(lu);
-	sbp2_cancel_orbs(lu);
-	sbp2_conditionally_unblock(lu);
- out:
-	sbp2_target_put(tgt);
-}
-
 static void sbp2_update(struct fw_unit *unit)
 {
 	struct sbp2_target *tgt = dev_get_drvdata(&unit->device);
@@ -1277,6 +1200,51 @@ static void sbp2_update(struct fw_unit *unit)
 	}
 }
 
+static int sbp2_remove(struct device *dev)
+{
+	struct fw_unit *unit = fw_unit(dev);
+	struct fw_device *device = fw_parent_device(unit);
+	struct sbp2_target *tgt = dev_get_drvdata(&unit->device);
+	struct sbp2_logical_unit *lu, *next;
+	struct Scsi_Host *shost =
+		container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
+	struct scsi_device *sdev;
+
+	/* prevent deadlocks */
+	sbp2_unblock(tgt);
+
+	list_for_each_entry_safe(lu, next, &tgt->lu_list, link) {
+		cancel_delayed_work_sync(&lu->work);
+		sdev = scsi_device_lookup(shost, 0, 0, sbp2_lun2int(lu->lun));
+		if (sdev) {
+			scsi_remove_device(sdev);
+			scsi_device_put(sdev);
+		}
+		if (lu->login_id != INVALID_LOGIN_ID) {
+			int generation, node_id;
+			/*
+			 * tgt->node_id may be obsolete here if we failed
+			 * during initial login or after a bus reset where
+			 * the topology changed.
+			 */
+			generation = device->generation;
+			smp_rmb(); /* node_id vs. generation */
+			node_id    = device->node_id;
+			sbp2_send_management_orb(lu, node_id, generation,
+						 SBP2_LOGOUT_REQUEST,
+						 lu->login_id, NULL);
+		}
+		fw_core_remove_address_handler(&lu->address_handler);
+		list_del(&lu->link);
+		kfree(lu);
+	}
+	scsi_remove_host(shost);
+	fw_notify("released %s, target %d:0:0\n", tgt->bus_id, shost->host_no);
+
+	scsi_host_put(shost);
+	return 0;
+}
+
 #define SBP2_UNIT_SPEC_ID_ENTRY	0x0000609e
 #define SBP2_SW_VERSION_ENTRY	0x00010483
 
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index eb80b54..8370f72 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -490,8 +490,8 @@ static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
 	return 0;
 }
 
-static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part,
-			    size_t size, struct pstore_info *psi)
+static int efi_pstore_write(enum pstore_type_id type, u64 *id,
+		unsigned int part, size_t size, struct pstore_info *psi)
 {
 	char name[DUMP_NAME_LEN];
 	char stub_name[DUMP_NAME_LEN];
@@ -499,7 +499,7 @@ static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part,
 	efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
 	struct efivars *efivars = psi->data;
 	struct efivar_entry *entry, *found = NULL;
-	int i;
+	int i, ret = 0;
 
 	sprintf(stub_name, "dump-type%u-%u-", type, part);
 	sprintf(name, "%s%lu", stub_name, get_seconds());
@@ -548,18 +548,19 @@ static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part,
 		efivar_unregister(found);
 
 	if (size)
-		efivar_create_sysfs_entry(efivars,
+		ret = efivar_create_sysfs_entry(efivars,
 					  utf16_strsize(efi_name,
 							DUMP_NAME_LEN * 2),
 					  efi_name, &vendor);
 
-	return part;
+	*id = part;
+	return ret;
 };
 
 static int efi_pstore_erase(enum pstore_type_id type, u64 id,
 			    struct pstore_info *psi)
 {
-	efi_pstore_write(type, id, 0, psi);
+	efi_pstore_write(type, &id, (unsigned int)id, 0, psi);
 
 	return 0;
 }
@@ -580,8 +581,8 @@ static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
 	return -1;
 }
 
-static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part,
-			    size_t size, struct pstore_info *psi)
+static int efi_pstore_write(enum pstore_type_id type, u64 *id,
+		unsigned int part, size_t size, struct pstore_info *psi)
 {
 	return 0;
 }
@@ -978,7 +979,7 @@ int register_efivars(struct efivars *efivars,
 	if (efivars->efi_pstore_info.buf) {
 		efivars->efi_pstore_info.bufsize = 1024;
 		efivars->efi_pstore_info.data = efivars;
-		mutex_init(&efivars->efi_pstore_info.buf_mutex);
+		spin_lock_init(&efivars->efi_pstore_info.buf_lock);
 		pstore_register(&efivars->efi_pstore_info);
 	}
 
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index 82f7b65..b81c989 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -32,6 +32,8 @@
 #include <asm-generic/bug.h>
 #include <asm/mach/irq.h>
 
+#define irq_to_gpio(irq)	((irq) - MXC_GPIO_IRQ_START)
+
 enum mxc_gpio_hwtype {
 	IMX1_GPIO,	/* runs on i.mx1 */
 	IMX21_GPIO,	/* runs on i.mx21 and i.mx27 */
@@ -343,6 +345,15 @@ static void __devinit mxc_gpio_get_hw(struct platform_device *pdev)
 	mxc_gpio_hwtype = hwtype;
 }
 
+static int mxc_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
+{
+	struct bgpio_chip *bgc = to_bgpio_chip(gc);
+	struct mxc_gpio_port *port =
+		container_of(bgc, struct mxc_gpio_port, bgc);
+
+	return port->virtual_irq_start + offset;
+}
+
 static int __devinit mxc_gpio_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
@@ -409,6 +420,7 @@ static int __devinit mxc_gpio_probe(struct platform_device *pdev)
 	if (err)
 		goto out_iounmap;
 
+	port->bgc.gc.to_irq = mxc_gpio_to_irq;
 	port->bgc.gc.base = pdev->id * 32;
 	port->bgc.dir = port->bgc.read_reg(port->bgc.reg_dir);
 	port->bgc.data = port->bgc.read_reg(port->bgc.reg_set);
diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c
index af55a85..292b504 100644
--- a/drivers/gpio/gpio-mxs.c
+++ b/drivers/gpio/gpio-mxs.c
@@ -49,6 +49,8 @@
 #define GPIO_INT_LEV_MASK	(1 << 0)
 #define GPIO_INT_POL_MASK	(1 << 1)
 
+#define irq_to_gpio(irq)	((irq) - MXS_GPIO_IRQ_START)
+
 struct mxs_gpio_port {
 	void __iomem *base;
 	int id;
diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c
index 9052925..ee13771 100644
--- a/drivers/gpio/gpio-pxa.c
+++ b/drivers/gpio/gpio-pxa.c
@@ -122,7 +122,7 @@ static int __init pxa_init_gpio_chip(int gpio_end)
 		struct gpio_chip *c = &chips[i].chip;
 
 		sprintf(chips[i].label, "gpio-%d", i);
-		chips[i].regbase = (void __iomem *)GPIO_BANK(i);
+		chips[i].regbase = GPIO_BANK(i);
 
 		c->base  = gpio;
 		c->label = chips[i].label;
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
index 6b65207..61044c8 100644
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -20,10 +20,11 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
-
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
 
 #include <asm/mach/irq.h>
 
@@ -35,9 +36,7 @@
 #define GPIO_PORT(x)		(((x) >> 3) & 0x3)
 #define GPIO_BIT(x)		((x) & 0x7)
 
-#define GPIO_REG(x)		(IO_TO_VIRT(TEGRA_GPIO_BASE) +	\
-				 GPIO_BANK(x) * 0x80 +		\
-				 GPIO_PORT(x) * 4)
+#define GPIO_REG(x)		(GPIO_BANK(x) * 0x80 + GPIO_PORT(x) * 4)
 
 #define GPIO_CNF(x)		(GPIO_REG(x) + 0x00)
 #define GPIO_OE(x)		(GPIO_REG(x) + 0x10)
@@ -76,15 +75,18 @@ struct tegra_gpio_bank {
 };
 
 
-static struct tegra_gpio_bank tegra_gpio_banks[] = {
-	{.bank = 0, .irq = INT_GPIO1},
-	{.bank = 1, .irq = INT_GPIO2},
-	{.bank = 2, .irq = INT_GPIO3},
-	{.bank = 3, .irq = INT_GPIO4},
-	{.bank = 4, .irq = INT_GPIO5},
-	{.bank = 5, .irq = INT_GPIO6},
-	{.bank = 6, .irq = INT_GPIO7},
-};
+static void __iomem *regs;
+static struct tegra_gpio_bank tegra_gpio_banks[7];
+
+static inline void tegra_gpio_writel(u32 val, u32 reg)
+{
+	__raw_writel(val, regs + reg);
+}
+
+static inline u32 tegra_gpio_readl(u32 reg)
+{
+	return __raw_readl(regs + reg);
+}
 
 static int tegra_gpio_compose(int bank, int port, int bit)
 {
@@ -98,7 +100,7 @@ static void tegra_gpio_mask_write(u32 reg, int gpio, int value)
 	val = 0x100 << GPIO_BIT(gpio);
 	if (value)
 		val |= 1 << GPIO_BIT(gpio);
-	__raw_writel(val, reg);
+	tegra_gpio_writel(val, reg);
 }
 
 void tegra_gpio_enable(int gpio)
@@ -118,7 +120,7 @@ static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 
 static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
-	return (__raw_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1;
+	return (tegra_gpio_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1;
 }
 
 static int tegra_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
@@ -155,7 +157,7 @@ static void tegra_gpio_irq_ack(struct irq_data *d)
 {
 	int gpio = d->irq - INT_GPIO_BASE;
 
-	__raw_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio));
+	tegra_gpio_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio));
 }
 
 static void tegra_gpio_irq_mask(struct irq_data *d)
@@ -208,10 +210,10 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 
 	spin_lock_irqsave(&bank->lvl_lock[port], flags);
 
-	val = __raw_readl(GPIO_INT_LVL(gpio));
+	val = tegra_gpio_readl(GPIO_INT_LVL(gpio));
 	val &= ~(GPIO_INT_LVL_MASK << GPIO_BIT(gpio));
 	val |= lvl_type << GPIO_BIT(gpio);
-	__raw_writel(val, GPIO_INT_LVL(gpio));
+	tegra_gpio_writel(val, GPIO_INT_LVL(gpio));
 
 	spin_unlock_irqrestore(&bank->lvl_lock[port], flags);
 
@@ -237,12 +239,12 @@ static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 
 	for (port = 0; port < 4; port++) {
 		int gpio = tegra_gpio_compose(bank->bank, port, 0);
-		unsigned long sta = __raw_readl(GPIO_INT_STA(gpio)) &
-			__raw_readl(GPIO_INT_ENB(gpio));
-		u32 lvl = __raw_readl(GPIO_INT_LVL(gpio));
+		unsigned long sta = tegra_gpio_readl(GPIO_INT_STA(gpio)) &
+			tegra_gpio_readl(GPIO_INT_ENB(gpio));
+		u32 lvl = tegra_gpio_readl(GPIO_INT_LVL(gpio));
 
 		for_each_set_bit(pin, &sta, 8) {
-			__raw_writel(1 << pin, GPIO_INT_CLR(gpio));
+			tegra_gpio_writel(1 << pin, GPIO_INT_CLR(gpio));
 
 			/* if gpio is edge triggered, clear condition
 			 * before executing the hander so that we don't
@@ -276,11 +278,11 @@ void tegra_gpio_resume(void)
 
 		for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
 			unsigned int gpio = (b<<5) | (p<<3);
-			__raw_writel(bank->cnf[p], GPIO_CNF(gpio));
-			__raw_writel(bank->out[p], GPIO_OUT(gpio));
-			__raw_writel(bank->oe[p], GPIO_OE(gpio));
-			__raw_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio));
-			__raw_writel(bank->int_enb[p], GPIO_INT_ENB(gpio));
+			tegra_gpio_writel(bank->cnf[p], GPIO_CNF(gpio));
+			tegra_gpio_writel(bank->out[p], GPIO_OUT(gpio));
+			tegra_gpio_writel(bank->oe[p], GPIO_OE(gpio));
+			tegra_gpio_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio));
+			tegra_gpio_writel(bank->int_enb[p], GPIO_INT_ENB(gpio));
 		}
 	}
 
@@ -299,11 +301,11 @@ void tegra_gpio_suspend(void)
 
 		for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
 			unsigned int gpio = (b<<5) | (p<<3);
-			bank->cnf[p] = __raw_readl(GPIO_CNF(gpio));
-			bank->out[p] = __raw_readl(GPIO_OUT(gpio));
-			bank->oe[p] = __raw_readl(GPIO_OE(gpio));
-			bank->int_enb[p] = __raw_readl(GPIO_INT_ENB(gpio));
-			bank->int_lvl[p] = __raw_readl(GPIO_INT_LVL(gpio));
+			bank->cnf[p] = tegra_gpio_readl(GPIO_CNF(gpio));
+			bank->out[p] = tegra_gpio_readl(GPIO_OUT(gpio));
+			bank->oe[p] = tegra_gpio_readl(GPIO_OE(gpio));
+			bank->int_enb[p] = tegra_gpio_readl(GPIO_INT_ENB(gpio));
+			bank->int_lvl[p] = tegra_gpio_readl(GPIO_INT_LVL(gpio));
 		}
 	}
 	local_irq_restore(flags);
@@ -333,28 +335,55 @@ static struct irq_chip tegra_gpio_irq_chip = {
  */
 static struct lock_class_key gpio_lock_class;
 
-static int __init tegra_gpio_init(void)
+static int __devinit tegra_gpio_probe(struct platform_device *pdev)
 {
+	struct resource *res;
 	struct tegra_gpio_bank *bank;
 	int gpio;
 	int i;
 	int j;
 
+	for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) {
+		res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
+		if (!res) {
+			dev_err(&pdev->dev, "Missing IRQ resource\n");
+			return -ENODEV;
+		}
+
+		bank = &tegra_gpio_banks[i];
+		bank->bank = i;
+		bank->irq = res->start;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "Missing MEM resource\n");
+		return -ENODEV;
+	}
+
+	if (!devm_request_mem_region(&pdev->dev, res->start,
+				     resource_size(res),
+				     dev_name(&pdev->dev))) {
+		dev_err(&pdev->dev, "Couldn't request MEM resource\n");
+		return -ENODEV;
+	}
+
+	regs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!regs) {
+		dev_err(&pdev->dev, "Couldn't ioremap regs\n");
+		return -ENODEV;
+	}
+
 	for (i = 0; i < 7; i++) {
 		for (j = 0; j < 4; j++) {
 			int gpio = tegra_gpio_compose(i, j, 0);
-			__raw_writel(0x00, GPIO_INT_ENB(gpio));
+			tegra_gpio_writel(0x00, GPIO_INT_ENB(gpio));
 		}
 	}
 
 #ifdef CONFIG_OF_GPIO
-	/*
-	 * This isn't ideal, but it gets things hooked up until this
-	 * driver is converted into a platform_device
-	 */
-	tegra_gpio_chip.of_node = of_find_compatible_node(NULL, NULL,
-						"nvidia,tegra20-gpio");
-#endif /* CONFIG_OF_GPIO */
+	tegra_gpio_chip.of_node = pdev->dev.of_node;
+#endif
 
 	gpiochip_add(&tegra_gpio_chip);
 
@@ -384,6 +413,24 @@ static int __init tegra_gpio_init(void)
 	return 0;
 }
 
+static struct of_device_id tegra_gpio_of_match[] __devinitdata = {
+	{ .compatible = "nvidia,tegra20-gpio", },
+	{ },
+};
+
+static struct platform_driver tegra_gpio_driver = {
+	.driver		= {
+		.name	= "tegra-gpio",
+		.owner	= THIS_MODULE,
+		.of_match_table = tegra_gpio_of_match,
+	},
+	.probe		= tegra_gpio_probe,
+};
+
+static int __init tegra_gpio_init(void)
+{
+	return platform_driver_register(&tegra_gpio_driver);
+}
 postcore_initcall(tegra_gpio_init);
 
 void __init tegra_gpio_config(struct tegra_gpio_table *table, int num)
@@ -416,13 +463,13 @@ static int dbg_gpio_show(struct seq_file *s, void *unused)
 			seq_printf(s,
 				"%d:%d %02x %02x %02x %02x %02x %02x %06x\n",
 				i, j,
-				__raw_readl(GPIO_CNF(gpio)),
-				__raw_readl(GPIO_OE(gpio)),
-				__raw_readl(GPIO_OUT(gpio)),
-				__raw_readl(GPIO_IN(gpio)),
-				__raw_readl(GPIO_INT_STA(gpio)),
-				__raw_readl(GPIO_INT_ENB(gpio)),
-				__raw_readl(GPIO_INT_LVL(gpio)));
+				tegra_gpio_readl(GPIO_CNF(gpio)),
+				tegra_gpio_readl(GPIO_OE(gpio)),
+				tegra_gpio_readl(GPIO_OUT(gpio)),
+				tegra_gpio_readl(GPIO_IN(gpio)),
+				tegra_gpio_readl(GPIO_INT_STA(gpio)),
+				tegra_gpio_readl(GPIO_INT_ENB(gpio)),
+				tegra_gpio_readl(GPIO_INT_LVL(gpio)));
 		}
 	}
 	return 0;
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index d1fc5cf..b2b8562 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -350,15 +350,25 @@ config I2C_DAVINCI
 	  devices such as DaVinci NIC.
 	  For details please see http://www.ti.com/davinci
 
-config I2C_DESIGNWARE
-	tristate "Synopsys DesignWare"
+config I2C_DESIGNWARE_PLATFORM
+	tristate "Synopsys DesignWare Platfrom"
 	depends on HAVE_CLK
 	help
 	  If you say yes to this option, support will be included for the
 	  Synopsys DesignWare I2C adapter. Only master mode is supported.
 
 	  This driver can also be built as a module.  If so, the module
-	  will be called i2c-designware.
+	  will be called i2c-designware-platform.
+
+config I2C_DESIGNWARE_PCI
+	tristate "Synopsys DesignWare PCI"
+	depends on PCI
+	help
+	  If you say yes to this option, support will be included for the
+	  Synopsys DesignWare I2C adapter. Only master mode is supported.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-designware-pci.
 
 config I2C_GPIO
 	tristate "GPIO-based bitbanging I2C"
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index e6cf294..fba6da6 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -33,7 +33,10 @@ obj-$(CONFIG_I2C_AU1550)	+= i2c-au1550.o
 obj-$(CONFIG_I2C_BLACKFIN_TWI)	+= i2c-bfin-twi.o
 obj-$(CONFIG_I2C_CPM)		+= i2c-cpm.o
 obj-$(CONFIG_I2C_DAVINCI)	+= i2c-davinci.o
-obj-$(CONFIG_I2C_DESIGNWARE)	+= i2c-designware.o
+obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM)	+= i2c-designware-platform.o
+i2c-designware-platform-objs := i2c-designware-platdrv.o i2c-designware-core.o
+obj-$(CONFIG_I2C_DESIGNWARE_PCI)	+= i2c-designware-pci.o
+i2c-designware-pci-objs := i2c-designware-pcidrv.o i2c-designware-core.o
 obj-$(CONFIG_I2C_GPIO)		+= i2c-gpio.o
 obj-$(CONFIG_I2C_HIGHLANDER)	+= i2c-highlander.o
 obj-$(CONFIG_I2C_IBM_IIC)	+= i2c-ibm_iic.o
diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c
index 532828b..4f757a2 100644
--- a/drivers/i2c/busses/i2c-au1550.c
+++ b/drivers/i2c/busses/i2c-au1550.c
@@ -39,29 +39,41 @@
 #include <asm/mach-au1x00/au1xxx.h>
 #include <asm/mach-au1x00/au1xxx_psc.h>
 
+#define PSC_SEL		0x00
+#define PSC_CTRL	0x04
+#define PSC_SMBCFG	0x08
+#define PSC_SMBMSK	0x0C
+#define PSC_SMBPCR	0x10
+#define PSC_SMBSTAT	0x14
+#define PSC_SMBEVNT	0x18
+#define PSC_SMBTXRX	0x1C
+#define PSC_SMBTMR	0x20
+
 struct i2c_au1550_data {
-	u32	psc_base;
+	void __iomem *psc_base;
 	int	xfer_timeout;
-	int	ack_timeout;
 	struct i2c_adapter adap;
 	struct resource *ioarea;
 };
 
-static int
-wait_xfer_done(struct i2c_au1550_data *adap)
+static inline void WR(struct i2c_au1550_data *a, int r, unsigned long v)
 {
-	u32	stat;
-	int	i;
-	volatile psc_smb_t	*sp;
+	__raw_writel(v, a->psc_base + r);
+	wmb();
+}
 
-	sp = (volatile psc_smb_t *)(adap->psc_base);
+static inline unsigned long RD(struct i2c_au1550_data *a, int r)
+{
+	return __raw_readl(a->psc_base + r);
+}
 
-	/* Wait for Tx Buffer Empty
-	*/
+static int wait_xfer_done(struct i2c_au1550_data *adap)
+{
+	int i;
+
+	/* Wait for Tx Buffer Empty */
 	for (i = 0; i < adap->xfer_timeout; i++) {
-		stat = sp->psc_smbstat;
-		au_sync();
-		if ((stat & PSC_SMBSTAT_TE) != 0)
+		if (RD(adap, PSC_SMBSTAT) & PSC_SMBSTAT_TE)
 			return 0;
 
 		udelay(1);
@@ -70,41 +82,27 @@ wait_xfer_done(struct i2c_au1550_data *adap)
 	return -ETIMEDOUT;
 }
 
-static int
-wait_ack(struct i2c_au1550_data *adap)
+static int wait_ack(struct i2c_au1550_data *adap)
 {
-	u32	stat;
-	volatile psc_smb_t	*sp;
+	unsigned long stat;
 
 	if (wait_xfer_done(adap))
 		return -ETIMEDOUT;
 
-	sp = (volatile psc_smb_t *)(adap->psc_base);
-
-	stat = sp->psc_smbevnt;
-	au_sync();
-
+	stat = RD(adap, PSC_SMBEVNT);
 	if ((stat & (PSC_SMBEVNT_DN | PSC_SMBEVNT_AN | PSC_SMBEVNT_AL)) != 0)
 		return -ETIMEDOUT;
 
 	return 0;
 }
 
-static int
-wait_master_done(struct i2c_au1550_data *adap)
+static int wait_master_done(struct i2c_au1550_data *adap)
 {
-	u32	stat;
-	int	i;
-	volatile psc_smb_t	*sp;
+	int i;
 
-	sp = (volatile psc_smb_t *)(adap->psc_base);
-
-	/* Wait for Master Done.
-	*/
-	for (i = 0; i < adap->xfer_timeout; i++) {
-		stat = sp->psc_smbevnt;
-		au_sync();
-		if ((stat & PSC_SMBEVNT_MD) != 0)
+	/* Wait for Master Done. */
+	for (i = 0; i < 2 * adap->xfer_timeout; i++) {
+		if ((RD(adap, PSC_SMBEVNT) & PSC_SMBEVNT_MD) != 0)
 			return 0;
 		udelay(1);
 	}
@@ -115,29 +113,20 @@ wait_master_done(struct i2c_au1550_data *adap)
 static int
 do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd, int q)
 {
-	volatile psc_smb_t	*sp;
-	u32			stat;
+	unsigned long stat;
 
-	sp = (volatile psc_smb_t *)(adap->psc_base);
-
-	/* Reset the FIFOs, clear events.
-	*/
-	stat = sp->psc_smbstat;
-	sp->psc_smbevnt = PSC_SMBEVNT_ALLCLR;
-	au_sync();
+	/* Reset the FIFOs, clear events. */
+	stat = RD(adap, PSC_SMBSTAT);
+	WR(adap, PSC_SMBEVNT, PSC_SMBEVNT_ALLCLR);
 
 	if (!(stat & PSC_SMBSTAT_TE) || !(stat & PSC_SMBSTAT_RE)) {
-		sp->psc_smbpcr = PSC_SMBPCR_DC;
-		au_sync();
-		do {
-			stat = sp->psc_smbpcr;
-			au_sync();
-		} while ((stat & PSC_SMBPCR_DC) != 0);
+		WR(adap, PSC_SMBPCR, PSC_SMBPCR_DC);
+		while ((RD(adap, PSC_SMBPCR) & PSC_SMBPCR_DC) != 0)
+			cpu_relax();
 		udelay(50);
 	}
 
-	/* Write out the i2c chip address and specify operation
-	*/
+	/* Write out the i2c chip address and specify operation */
 	addr <<= 1;
 	if (rd)
 		addr |= 1;
@@ -146,56 +135,42 @@ do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd, int q)
 	if (q)
 		addr |= PSC_SMBTXRX_STP;
 
-	/* Put byte into fifo, start up master.
-	*/
-	sp->psc_smbtxrx = addr;
-	au_sync();
-	sp->psc_smbpcr = PSC_SMBPCR_MS;
-	au_sync();
+	/* Put byte into fifo, start up master. */
+	WR(adap, PSC_SMBTXRX, addr);
+	WR(adap, PSC_SMBPCR, PSC_SMBPCR_MS);
 	if (wait_ack(adap))
 		return -EIO;
 	return (q) ? wait_master_done(adap) : 0;
 }
 
-static u32
-wait_for_rx_byte(struct i2c_au1550_data *adap, u32 *ret_data)
+static int wait_for_rx_byte(struct i2c_au1550_data *adap, unsigned char *out)
 {
-	int	j;
-	u32	data, stat;
-	volatile psc_smb_t	*sp;
+	int j;
 
 	if (wait_xfer_done(adap))
 		return -EIO;
 
-	sp = (volatile psc_smb_t *)(adap->psc_base);
-
 	j =  adap->xfer_timeout * 100;
 	do {
 		j--;
 		if (j <= 0)
 			return -EIO;
 
-		stat = sp->psc_smbstat;
-		au_sync();
-		if ((stat & PSC_SMBSTAT_RE) == 0)
+		if ((RD(adap, PSC_SMBSTAT) & PSC_SMBSTAT_RE) == 0)
 			j = 0;
 		else
 			udelay(1);
 	} while (j > 0);
-	data = sp->psc_smbtxrx;
-	au_sync();
-	*ret_data = data;
+
+	*out = RD(adap, PSC_SMBTXRX);
 
 	return 0;
 }
 
-static int
-i2c_read(struct i2c_au1550_data *adap, unsigned char *buf,
+static int i2c_read(struct i2c_au1550_data *adap, unsigned char *buf,
 		    unsigned int len)
 {
-	int	i;
-	u32	data;
-	volatile psc_smb_t	*sp;
+	int i;
 
 	if (len == 0)
 		return 0;
@@ -204,62 +179,46 @@ i2c_read(struct i2c_au1550_data *adap, unsigned char *buf,
 	 * zero bytes for timing, waiting for bytes to appear in the
 	 * receive fifo, then reading the bytes.
 	 */
-
-	sp = (volatile psc_smb_t *)(adap->psc_base);
-
 	i = 0;
-	while (i < (len-1)) {
-		sp->psc_smbtxrx = 0;
-		au_sync();
-		if (wait_for_rx_byte(adap, &data))
+	while (i < (len - 1)) {
+		WR(adap, PSC_SMBTXRX, 0);
+		if (wait_for_rx_byte(adap, &buf[i]))
 			return -EIO;
 
-		buf[i] = data;
 		i++;
 	}
 
-	/* The last byte has to indicate transfer done.
-	*/
-	sp->psc_smbtxrx = PSC_SMBTXRX_STP;
-	au_sync();
+	/* The last byte has to indicate transfer done. */
+	WR(adap, PSC_SMBTXRX, PSC_SMBTXRX_STP);
 	if (wait_master_done(adap))
 		return -EIO;
 
-	data = sp->psc_smbtxrx;
-	au_sync();
-	buf[i] = data;
+	buf[i] = (unsigned char)(RD(adap, PSC_SMBTXRX) & 0xff);
 	return 0;
 }
 
-static int
-i2c_write(struct i2c_au1550_data *adap, unsigned char *buf,
+static int i2c_write(struct i2c_au1550_data *adap, unsigned char *buf,
 		     unsigned int len)
 {
-	int	i;
-	u32	data;
-	volatile psc_smb_t	*sp;
+	int i;
+	unsigned long data;
 
 	if (len == 0)
 		return 0;
 
-	sp = (volatile psc_smb_t *)(adap->psc_base);
-
 	i = 0;
 	while (i < (len-1)) {
 		data = buf[i];
-		sp->psc_smbtxrx = data;
-		au_sync();
+		WR(adap, PSC_SMBTXRX, data);
 		if (wait_ack(adap))
 			return -EIO;
 		i++;
 	}
 
-	/* The last byte has to indicate transfer done.
-	*/
+	/* The last byte has to indicate transfer done. */
 	data = buf[i];
 	data |= PSC_SMBTXRX_STP;
-	sp->psc_smbtxrx = data;
-	au_sync();
+	WR(adap, PSC_SMBTXRX, data);
 	if (wait_master_done(adap))
 		return -EIO;
 	return 0;
@@ -269,12 +228,10 @@ static int
 au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
 {
 	struct i2c_au1550_data *adap = i2c_adap->algo_data;
-	volatile psc_smb_t *sp = (volatile psc_smb_t *)adap->psc_base;
 	struct i2c_msg *p;
 	int i, err = 0;
 
-	sp->psc_ctrl = PSC_CTRL_ENABLE;
-	au_sync();
+	WR(adap, PSC_CTRL, PSC_CTRL_ENABLE);
 
 	for (i = 0; !err && i < num; i++) {
 		p = &msgs[i];
@@ -293,14 +250,12 @@ au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
 	if (err == 0)
 		err = num;
 
-	sp->psc_ctrl = PSC_CTRL_SUSPEND;
-	au_sync();
+	WR(adap, PSC_CTRL, PSC_CTRL_SUSPEND);
 
 	return err;
 }
 
-static u32
-au1550_func(struct i2c_adapter *adap)
+static u32 au1550_func(struct i2c_adapter *adap)
 {
 	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
@@ -312,57 +267,45 @@ static const struct i2c_algorithm au1550_algo = {
 
 static void i2c_au1550_setup(struct i2c_au1550_data *priv)
 {
-	volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
-	u32 stat;
-
-	sp->psc_ctrl = PSC_CTRL_DISABLE;
-	au_sync();
-	sp->psc_sel = PSC_SEL_PS_SMBUSMODE;
-	sp->psc_smbcfg = 0;
-	au_sync();
-	sp->psc_ctrl = PSC_CTRL_ENABLE;
-	au_sync();
-	do {
-		stat = sp->psc_smbstat;
-		au_sync();
-	} while ((stat & PSC_SMBSTAT_SR) == 0);
+	unsigned long cfg;
 
-	sp->psc_smbcfg = (PSC_SMBCFG_RT_FIFO8 | PSC_SMBCFG_TT_FIFO8 |
-				PSC_SMBCFG_DD_DISABLE);
+	WR(priv, PSC_CTRL, PSC_CTRL_DISABLE);
+	WR(priv, PSC_SEL, PSC_SEL_PS_SMBUSMODE);
+	WR(priv, PSC_SMBCFG, 0);
+	WR(priv, PSC_CTRL, PSC_CTRL_ENABLE);
+	while ((RD(priv, PSC_SMBSTAT) & PSC_SMBSTAT_SR) == 0)
+		cpu_relax();
+
+	cfg = PSC_SMBCFG_RT_FIFO8 | PSC_SMBCFG_TT_FIFO8 | PSC_SMBCFG_DD_DISABLE;
+	WR(priv, PSC_SMBCFG, cfg);
 
 	/* Divide by 8 to get a 6.25 MHz clock.  The later protocol
 	 * timings are based on this clock.
 	 */
-	sp->psc_smbcfg |= PSC_SMBCFG_SET_DIV(PSC_SMBCFG_DIV8);
-	sp->psc_smbmsk = PSC_SMBMSK_ALLMASK;
-	au_sync();
+	cfg |= PSC_SMBCFG_SET_DIV(PSC_SMBCFG_DIV8);
+	WR(priv, PSC_SMBCFG, cfg);
+	WR(priv, PSC_SMBMSK, PSC_SMBMSK_ALLMASK);
 
 	/* Set the protocol timer values.  See Table 71 in the
 	 * Au1550 Data Book for standard timing values.
 	 */
-	sp->psc_smbtmr = PSC_SMBTMR_SET_TH(0) | PSC_SMBTMR_SET_PS(15) | \
+	WR(priv, PSC_SMBTMR, PSC_SMBTMR_SET_TH(0) | PSC_SMBTMR_SET_PS(15) | \
 		PSC_SMBTMR_SET_PU(15) | PSC_SMBTMR_SET_SH(15) | \
 		PSC_SMBTMR_SET_SU(15) | PSC_SMBTMR_SET_CL(15) | \
-		PSC_SMBTMR_SET_CH(15);
-	au_sync();
+		PSC_SMBTMR_SET_CH(15));
 
-	sp->psc_smbcfg |= PSC_SMBCFG_DE_ENABLE;
-	do {
-		stat = sp->psc_smbstat;
-		au_sync();
-	} while ((stat & PSC_SMBSTAT_SR) == 0);
+	cfg |= PSC_SMBCFG_DE_ENABLE;
+	WR(priv, PSC_SMBCFG, cfg);
+	while ((RD(priv, PSC_SMBSTAT) & PSC_SMBSTAT_SR) == 0)
+		cpu_relax();
 
-	sp->psc_ctrl = PSC_CTRL_SUSPEND;
-	au_sync();
+	WR(priv, PSC_CTRL, PSC_CTRL_SUSPEND);
 }
 
 static void i2c_au1550_disable(struct i2c_au1550_data *priv)
 {
-	volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
-
-	sp->psc_smbcfg = 0;
-	sp->psc_ctrl = PSC_CTRL_DISABLE;
-	au_sync();
+	WR(priv, PSC_SMBCFG, 0);
+	WR(priv, PSC_CTRL, PSC_CTRL_DISABLE);
 }
 
 /*
@@ -396,9 +339,12 @@ i2c_au1550_probe(struct platform_device *pdev)
 		goto out_mem;
 	}
 
-	priv->psc_base = CKSEG1ADDR(r->start);
+	priv->psc_base = ioremap(r->start, resource_size(r));
+	if (!priv->psc_base) {
+		ret = -EIO;
+		goto out_map;
+	}
 	priv->xfer_timeout = 200;
-	priv->ack_timeout = 200;
 
 	priv->adap.nr = pdev->id;
 	priv->adap.algo = &au1550_algo;
@@ -406,8 +352,7 @@ i2c_au1550_probe(struct platform_device *pdev)
 	priv->adap.dev.parent = &pdev->dev;
 	strlcpy(priv->adap.name, "Au1xxx PSC I2C", sizeof(priv->adap.name));
 
-	/* Now, set up the PSC for SMBus PIO mode.
-	*/
+	/* Now, set up the PSC for SMBus PIO mode. */
 	i2c_au1550_setup(priv);
 
 	ret = i2c_add_numbered_adapter(&priv->adap);
@@ -417,7 +362,8 @@ i2c_au1550_probe(struct platform_device *pdev)
 	}
 
 	i2c_au1550_disable(priv);
-
+	iounmap(priv->psc_base);
+out_map:
 	release_resource(priv->ioarea);
 	kfree(priv->ioarea);
 out_mem:
@@ -426,14 +372,14 @@ out:
 	return ret;
 }
 
-static int __devexit
-i2c_au1550_remove(struct platform_device *pdev)
+static int __devexit i2c_au1550_remove(struct platform_device *pdev)
 {
 	struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
 
 	platform_set_drvdata(pdev, NULL);
 	i2c_del_adapter(&priv->adap);
 	i2c_au1550_disable(priv);
+	iounmap(priv->psc_base);
 	release_resource(priv->ioarea);
 	kfree(priv->ioarea);
 	kfree(priv);
@@ -441,49 +387,51 @@ i2c_au1550_remove(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_PM
-static int
-i2c_au1550_suspend(struct platform_device *pdev, pm_message_t state)
+static int i2c_au1550_suspend(struct device *dev)
 {
-	struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
+	struct i2c_au1550_data *priv = dev_get_drvdata(dev);
 
 	i2c_au1550_disable(priv);
 
 	return 0;
 }
 
-static int
-i2c_au1550_resume(struct platform_device *pdev)
+static int i2c_au1550_resume(struct device *dev)
 {
-	struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
+	struct i2c_au1550_data *priv = dev_get_drvdata(dev);
 
 	i2c_au1550_setup(priv);
 
 	return 0;
 }
+
+static const struct dev_pm_ops i2c_au1550_pmops = {
+	.suspend	= i2c_au1550_suspend,
+	.resume		= i2c_au1550_resume,
+};
+
+#define AU1XPSC_SMBUS_PMOPS (&i2c_au1550_pmops)
+
 #else
-#define i2c_au1550_suspend	NULL
-#define i2c_au1550_resume	NULL
+#define AU1XPSC_SMBUS_PMOPS NULL
 #endif
 
 static struct platform_driver au1xpsc_smbus_driver = {
 	.driver = {
 		.name	= "au1xpsc_smbus",
 		.owner	= THIS_MODULE,
+		.pm	= AU1XPSC_SMBUS_PMOPS,
 	},
 	.probe		= i2c_au1550_probe,
 	.remove		= __devexit_p(i2c_au1550_remove),
-	.suspend	= i2c_au1550_suspend,
-	.resume		= i2c_au1550_resume,
 };
 
-static int __init
-i2c_au1550_init(void)
+static int __init i2c_au1550_init(void)
 {
 	return platform_driver_register(&au1xpsc_smbus_driver);
 }
 
-static void __exit
-i2c_au1550_exit(void)
+static void __exit i2c_au1550_exit(void)
 {
 	platform_driver_unregister(&au1xpsc_smbus_driver);
 }
diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c
index cbc98ae..cdb59e5 100644
--- a/drivers/i2c/busses/i2c-bfin-twi.c
+++ b/drivers/i2c/busses/i2c-bfin-twi.c
@@ -631,7 +631,7 @@ static int i2c_bfin_twi_resume(struct platform_device *pdev)
 	struct bfin_twi_iface *iface = platform_get_drvdata(pdev);
 
 	int rc = request_irq(iface->irq, bfin_twi_interrupt_entry,
-		IRQF_DISABLED, pdev->name, iface);
+		0, pdev->name, iface);
 	if (rc) {
 		dev_err(&pdev->dev, "Can't get IRQ %d !\n", iface->irq);
 		return -ENODEV;
@@ -702,7 +702,7 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev)
 	}
 
 	rc = request_irq(iface->irq, bfin_twi_interrupt_entry,
-		IRQF_DISABLED, pdev->name, iface);
+		0, pdev->name, iface);
 	if (rc) {
 		dev_err(&pdev->dev, "Can't get IRQ %d !\n", iface->irq);
 		rc = -ENODEV;
diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c
new file mode 100644
index 0000000..df87992
--- /dev/null
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -0,0 +1,705 @@
+/*
+ * Synopsys DesignWare I2C adapter driver (master only).
+ *
+ * Based on the TI DAVINCI I2C adapter driver.
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software Inc.
+ * Copyright (C) 2009 Provigent Ltd.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ *
+ */
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
+#include "i2c-designware-core.h"
+
+/*
+ * Registers offset
+ */
+#define DW_IC_CON		0x0
+#define DW_IC_TAR		0x4
+#define DW_IC_DATA_CMD		0x10
+#define DW_IC_SS_SCL_HCNT	0x14
+#define DW_IC_SS_SCL_LCNT	0x18
+#define DW_IC_FS_SCL_HCNT	0x1c
+#define DW_IC_FS_SCL_LCNT	0x20
+#define DW_IC_INTR_STAT		0x2c
+#define DW_IC_INTR_MASK		0x30
+#define DW_IC_RAW_INTR_STAT	0x34
+#define DW_IC_RX_TL		0x38
+#define DW_IC_TX_TL		0x3c
+#define DW_IC_CLR_INTR		0x40
+#define DW_IC_CLR_RX_UNDER	0x44
+#define DW_IC_CLR_RX_OVER	0x48
+#define DW_IC_CLR_TX_OVER	0x4c
+#define DW_IC_CLR_RD_REQ	0x50
+#define DW_IC_CLR_TX_ABRT	0x54
+#define DW_IC_CLR_RX_DONE	0x58
+#define DW_IC_CLR_ACTIVITY	0x5c
+#define DW_IC_CLR_STOP_DET	0x60
+#define DW_IC_CLR_START_DET	0x64
+#define DW_IC_CLR_GEN_CALL	0x68
+#define DW_IC_ENABLE		0x6c
+#define DW_IC_STATUS		0x70
+#define DW_IC_TXFLR		0x74
+#define DW_IC_RXFLR		0x78
+#define DW_IC_TX_ABRT_SOURCE	0x80
+#define DW_IC_COMP_PARAM_1	0xf4
+#define DW_IC_COMP_TYPE		0xfc
+#define DW_IC_COMP_TYPE_VALUE	0x44570140
+
+#define DW_IC_INTR_RX_UNDER	0x001
+#define DW_IC_INTR_RX_OVER	0x002
+#define DW_IC_INTR_RX_FULL	0x004
+#define DW_IC_INTR_TX_OVER	0x008
+#define DW_IC_INTR_TX_EMPTY	0x010
+#define DW_IC_INTR_RD_REQ	0x020
+#define DW_IC_INTR_TX_ABRT	0x040
+#define DW_IC_INTR_RX_DONE	0x080
+#define DW_IC_INTR_ACTIVITY	0x100
+#define DW_IC_INTR_STOP_DET	0x200
+#define DW_IC_INTR_START_DET	0x400
+#define DW_IC_INTR_GEN_CALL	0x800
+
+#define DW_IC_INTR_DEFAULT_MASK		(DW_IC_INTR_RX_FULL | \
+					 DW_IC_INTR_TX_EMPTY | \
+					 DW_IC_INTR_TX_ABRT | \
+					 DW_IC_INTR_STOP_DET)
+
+#define DW_IC_STATUS_ACTIVITY	0x1
+
+#define DW_IC_ERR_TX_ABRT	0x1
+
+/*
+ * status codes
+ */
+#define STATUS_IDLE			0x0
+#define STATUS_WRITE_IN_PROGRESS	0x1
+#define STATUS_READ_IN_PROGRESS		0x2
+
+#define TIMEOUT			20 /* ms */
+
+/*
+ * hardware abort codes from the DW_IC_TX_ABRT_SOURCE register
+ *
+ * only expected abort codes are listed here
+ * refer to the datasheet for the full list
+ */
+#define ABRT_7B_ADDR_NOACK	0
+#define ABRT_10ADDR1_NOACK	1
+#define ABRT_10ADDR2_NOACK	2
+#define ABRT_TXDATA_NOACK	3
+#define ABRT_GCALL_NOACK	4
+#define ABRT_GCALL_READ		5
+#define ABRT_SBYTE_ACKDET	7
+#define ABRT_SBYTE_NORSTRT	9
+#define ABRT_10B_RD_NORSTRT	10
+#define ABRT_MASTER_DIS		11
+#define ARB_LOST		12
+
+#define DW_IC_TX_ABRT_7B_ADDR_NOACK	(1UL << ABRT_7B_ADDR_NOACK)
+#define DW_IC_TX_ABRT_10ADDR1_NOACK	(1UL << ABRT_10ADDR1_NOACK)
+#define DW_IC_TX_ABRT_10ADDR2_NOACK	(1UL << ABRT_10ADDR2_NOACK)
+#define DW_IC_TX_ABRT_TXDATA_NOACK	(1UL << ABRT_TXDATA_NOACK)
+#define DW_IC_TX_ABRT_GCALL_NOACK	(1UL << ABRT_GCALL_NOACK)
+#define DW_IC_TX_ABRT_GCALL_READ	(1UL << ABRT_GCALL_READ)
+#define DW_IC_TX_ABRT_SBYTE_ACKDET	(1UL << ABRT_SBYTE_ACKDET)
+#define DW_IC_TX_ABRT_SBYTE_NORSTRT	(1UL << ABRT_SBYTE_NORSTRT)
+#define DW_IC_TX_ABRT_10B_RD_NORSTRT	(1UL << ABRT_10B_RD_NORSTRT)
+#define DW_IC_TX_ABRT_MASTER_DIS	(1UL << ABRT_MASTER_DIS)
+#define DW_IC_TX_ARB_LOST		(1UL << ARB_LOST)
+
+#define DW_IC_TX_ABRT_NOACK		(DW_IC_TX_ABRT_7B_ADDR_NOACK | \
+					 DW_IC_TX_ABRT_10ADDR1_NOACK | \
+					 DW_IC_TX_ABRT_10ADDR2_NOACK | \
+					 DW_IC_TX_ABRT_TXDATA_NOACK | \
+					 DW_IC_TX_ABRT_GCALL_NOACK)
+
+static char *abort_sources[] = {
+	[ABRT_7B_ADDR_NOACK] =
+		"slave address not acknowledged (7bit mode)",
+	[ABRT_10ADDR1_NOACK] =
+		"first address byte not acknowledged (10bit mode)",
+	[ABRT_10ADDR2_NOACK] =
+		"second address byte not acknowledged (10bit mode)",
+	[ABRT_TXDATA_NOACK] =
+		"data not acknowledged",
+	[ABRT_GCALL_NOACK] =
+		"no acknowledgement for a general call",
+	[ABRT_GCALL_READ] =
+		"read after general call",
+	[ABRT_SBYTE_ACKDET] =
+		"start byte acknowledged",
+	[ABRT_SBYTE_NORSTRT] =
+		"trying to send start byte when restart is disabled",
+	[ABRT_10B_RD_NORSTRT] =
+		"trying to read when restart is disabled (10bit mode)",
+	[ABRT_MASTER_DIS] =
+		"trying to use disabled adapter",
+	[ARB_LOST] =
+		"lost arbitration",
+};
+
+u32 dw_readl(struct dw_i2c_dev *dev, int offset)
+{
+	u32 value = readl(dev->base + offset);
+
+	if (dev->swab)
+		return swab32(value);
+	else
+		return value;
+}
+
+void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset)
+{
+	if (dev->swab)
+		b = swab32(b);
+
+	writel(b, dev->base + offset);
+}
+
+static u32
+i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
+{
+	/*
+	 * DesignWare I2C core doesn't seem to have solid strategy to meet
+	 * the tHD;STA timing spec.  Configuring _HCNT based on tHIGH spec
+	 * will result in violation of the tHD;STA spec.
+	 */
+	if (cond)
+		/*
+		 * Conditional expression:
+		 *
+		 *   IC_[FS]S_SCL_HCNT + (1+4+3) >= IC_CLK * tHIGH
+		 *
+		 * This is based on the DW manuals, and represents an ideal
+		 * configuration.  The resulting I2C bus speed will be
+		 * faster than any of the others.
+		 *
+		 * If your hardware is free from tHD;STA issue, try this one.
+		 */
+		return (ic_clk * tSYMBOL + 5000) / 10000 - 8 + offset;
+	else
+		/*
+		 * Conditional expression:
+		 *
+		 *   IC_[FS]S_SCL_HCNT + 3 >= IC_CLK * (tHD;STA + tf)
+		 *
+		 * This is just experimental rule; the tHD;STA period turned
+		 * out to be proportinal to (_HCNT + 3).  With this setting,
+		 * we could meet both tHIGH and tHD;STA timing specs.
+		 *
+		 * If unsure, you'd better to take this alternative.
+		 *
+		 * The reason why we need to take into account "tf" here,
+		 * is the same as described in i2c_dw_scl_lcnt().
+		 */
+		return (ic_clk * (tSYMBOL + tf) + 5000) / 10000 - 3 + offset;
+}
+
+static u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
+{
+	/*
+	 * Conditional expression:
+	 *
+	 *   IC_[FS]S_SCL_LCNT + 1 >= IC_CLK * (tLOW + tf)
+	 *
+	 * DW I2C core starts counting the SCL CNTs for the LOW period
+	 * of the SCL clock (tLOW) as soon as it pulls the SCL line.
+	 * In order to meet the tLOW timing spec, we need to take into
+	 * account the fall time of SCL signal (tf).  Default tf value
+	 * should be 0.3 us, for safety.
+	 */
+	return ((ic_clk * (tLOW + tf) + 5000) / 10000) - 1 + offset;
+}
+
+/**
+ * i2c_dw_init() - initialize the designware i2c master hardware
+ * @dev: device private data
+ *
+ * This functions configures and enables the I2C master.
+ * This function is called during I2C init function, and in case of timeout at
+ * run time.
+ */
+int i2c_dw_init(struct dw_i2c_dev *dev)
+{
+	u32 input_clock_khz;
+	u32 hcnt, lcnt;
+	u32 reg;
+
+	input_clock_khz = dev->get_clk_rate_khz(dev);
+
+	/* Configure register endianess access */
+	reg = dw_readl(dev, DW_IC_COMP_TYPE);
+	if (reg == ___constant_swab32(DW_IC_COMP_TYPE_VALUE)) {
+		dev->swab = 1;
+		reg = DW_IC_COMP_TYPE_VALUE;
+	}
+
+	if (reg != DW_IC_COMP_TYPE_VALUE) {
+		dev_err(dev->dev, "Unknown Synopsys component type: "
+			"0x%08x\n", reg);
+		return -ENODEV;
+	}
+
+	/* Disable the adapter */
+	dw_writel(dev, 0, DW_IC_ENABLE);
+
+	/* set standard and fast speed deviders for high/low periods */
+
+	/* Standard-mode */
+	hcnt = i2c_dw_scl_hcnt(input_clock_khz,
+				40,	/* tHD;STA = tHIGH = 4.0 us */
+				3,	/* tf = 0.3 us */
+				0,	/* 0: DW default, 1: Ideal */
+				0);	/* No offset */
+	lcnt = i2c_dw_scl_lcnt(input_clock_khz,
+				47,	/* tLOW = 4.7 us */
+				3,	/* tf = 0.3 us */
+				0);	/* No offset */
+	dw_writel(dev, hcnt, DW_IC_SS_SCL_HCNT);
+	dw_writel(dev, lcnt, DW_IC_SS_SCL_LCNT);
+	dev_dbg(dev->dev, "Standard-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
+
+	/* Fast-mode */
+	hcnt = i2c_dw_scl_hcnt(input_clock_khz,
+				6,	/* tHD;STA = tHIGH = 0.6 us */
+				3,	/* tf = 0.3 us */
+				0,	/* 0: DW default, 1: Ideal */
+				0);	/* No offset */
+	lcnt = i2c_dw_scl_lcnt(input_clock_khz,
+				13,	/* tLOW = 1.3 us */
+				3,	/* tf = 0.3 us */
+				0);	/* No offset */
+	dw_writel(dev, hcnt, DW_IC_FS_SCL_HCNT);
+	dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT);
+	dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
+
+	/* Configure Tx/Rx FIFO threshold levels */
+	dw_writel(dev, dev->tx_fifo_depth - 1, DW_IC_TX_TL);
+	dw_writel(dev, 0, DW_IC_RX_TL);
+
+	/* configure the i2c master */
+	dw_writel(dev, dev->master_cfg , DW_IC_CON);
+	return 0;
+}
+
+/*
+ * Waiting for bus not busy
+ */
+static int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)
+{
+	int timeout = TIMEOUT;
+
+	while (dw_readl(dev, DW_IC_STATUS) & DW_IC_STATUS_ACTIVITY) {
+		if (timeout <= 0) {
+			dev_warn(dev->dev, "timeout waiting for bus ready\n");
+			return -ETIMEDOUT;
+		}
+		timeout--;
+		mdelay(1);
+	}
+
+	return 0;
+}
+
+static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
+{
+	struct i2c_msg *msgs = dev->msgs;
+	u32 ic_con;
+
+	/* Disable the adapter */
+	dw_writel(dev, 0, DW_IC_ENABLE);
+
+	/* set the slave (target) address */
+	dw_writel(dev, msgs[dev->msg_write_idx].addr, DW_IC_TAR);
+
+	/* if the slave address is ten bit address, enable 10BITADDR */
+	ic_con = dw_readl(dev, DW_IC_CON);
+	if (msgs[dev->msg_write_idx].flags & I2C_M_TEN)
+		ic_con |= DW_IC_CON_10BITADDR_MASTER;
+	else
+		ic_con &= ~DW_IC_CON_10BITADDR_MASTER;
+	dw_writel(dev, ic_con, DW_IC_CON);
+
+	/* Enable the adapter */
+	dw_writel(dev, 1, DW_IC_ENABLE);
+
+	/* Enable interrupts */
+	dw_writel(dev, DW_IC_INTR_DEFAULT_MASK, DW_IC_INTR_MASK);
+}
+
+/*
+ * Initiate (and continue) low level master read/write transaction.
+ * This function is only called from i2c_dw_isr, and pumping i2c_msg
+ * messages into the tx buffer.  Even if the size of i2c_msg data is
+ * longer than the size of the tx buffer, it handles everything.
+ */
+void
+i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
+{
+	struct i2c_msg *msgs = dev->msgs;
+	u32 intr_mask;
+	int tx_limit, rx_limit;
+	u32 addr = msgs[dev->msg_write_idx].addr;
+	u32 buf_len = dev->tx_buf_len;
+	u8 *buf = dev->tx_buf;
+
+	intr_mask = DW_IC_INTR_DEFAULT_MASK;
+
+	for (; dev->msg_write_idx < dev->msgs_num; dev->msg_write_idx++) {
+		/*
+		 * if target address has changed, we need to
+		 * reprogram the target address in the i2c
+		 * adapter when we are done with this transfer
+		 */
+		if (msgs[dev->msg_write_idx].addr != addr) {
+			dev_err(dev->dev,
+				"%s: invalid target address\n", __func__);
+			dev->msg_err = -EINVAL;
+			break;
+		}
+
+		if (msgs[dev->msg_write_idx].len == 0) {
+			dev_err(dev->dev,
+				"%s: invalid message length\n", __func__);
+			dev->msg_err = -EINVAL;
+			break;
+		}
+
+		if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) {
+			/* new i2c_msg */
+			buf = msgs[dev->msg_write_idx].buf;
+			buf_len = msgs[dev->msg_write_idx].len;
+		}
+
+		tx_limit = dev->tx_fifo_depth - dw_readl(dev, DW_IC_TXFLR);
+		rx_limit = dev->rx_fifo_depth - dw_readl(dev, DW_IC_RXFLR);
+
+		while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) {
+			if (msgs[dev->msg_write_idx].flags & I2C_M_RD) {
+				dw_writel(dev, 0x100, DW_IC_DATA_CMD);
+				rx_limit--;
+			} else
+				dw_writel(dev, *buf++, DW_IC_DATA_CMD);
+			tx_limit--; buf_len--;
+		}
+
+		dev->tx_buf = buf;
+		dev->tx_buf_len = buf_len;
+
+		if (buf_len > 0) {
+			/* more bytes to be written */
+			dev->status |= STATUS_WRITE_IN_PROGRESS;
+			break;
+		} else
+			dev->status &= ~STATUS_WRITE_IN_PROGRESS;
+	}
+
+	/*
+	 * If i2c_msg index search is completed, we don't need TX_EMPTY
+	 * interrupt any more.
+	 */
+	if (dev->msg_write_idx == dev->msgs_num)
+		intr_mask &= ~DW_IC_INTR_TX_EMPTY;
+
+	if (dev->msg_err)
+		intr_mask = 0;
+
+	dw_writel(dev, intr_mask,  DW_IC_INTR_MASK);
+}
+
+static void
+i2c_dw_read(struct dw_i2c_dev *dev)
+{
+	struct i2c_msg *msgs = dev->msgs;
+	int rx_valid;
+
+	for (; dev->msg_read_idx < dev->msgs_num; dev->msg_read_idx++) {
+		u32 len;
+		u8 *buf;
+
+		if (!(msgs[dev->msg_read_idx].flags & I2C_M_RD))
+			continue;
+
+		if (!(dev->status & STATUS_READ_IN_PROGRESS)) {
+			len = msgs[dev->msg_read_idx].len;
+			buf = msgs[dev->msg_read_idx].buf;
+		} else {
+			len = dev->rx_buf_len;
+			buf = dev->rx_buf;
+		}
+
+		rx_valid = dw_readl(dev, DW_IC_RXFLR);
+
+		for (; len > 0 && rx_valid > 0; len--, rx_valid--)
+			*buf++ = dw_readl(dev, DW_IC_DATA_CMD);
+
+		if (len > 0) {
+			dev->status |= STATUS_READ_IN_PROGRESS;
+			dev->rx_buf_len = len;
+			dev->rx_buf = buf;
+			return;
+		} else
+			dev->status &= ~STATUS_READ_IN_PROGRESS;
+	}
+}
+
+static int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
+{
+	unsigned long abort_source = dev->abort_source;
+	int i;
+
+	if (abort_source & DW_IC_TX_ABRT_NOACK) {
+		for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
+			dev_dbg(dev->dev,
+				"%s: %s\n", __func__, abort_sources[i]);
+		return -EREMOTEIO;
+	}
+
+	for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
+		dev_err(dev->dev, "%s: %s\n", __func__, abort_sources[i]);
+
+	if (abort_source & DW_IC_TX_ARB_LOST)
+		return -EAGAIN;
+	else if (abort_source & DW_IC_TX_ABRT_GCALL_READ)
+		return -EINVAL; /* wrong msgs[] data */
+	else
+		return -EIO;
+}
+
+/*
+ * Prepare controller for a transaction and call i2c_dw_xfer_msg
+ */
+int
+i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+{
+	struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
+	int ret;
+
+	dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num);
+
+	mutex_lock(&dev->lock);
+	pm_runtime_get_sync(dev->dev);
+
+	INIT_COMPLETION(dev->cmd_complete);
+	dev->msgs = msgs;
+	dev->msgs_num = num;
+	dev->cmd_err = 0;
+	dev->msg_write_idx = 0;
+	dev->msg_read_idx = 0;
+	dev->msg_err = 0;
+	dev->status = STATUS_IDLE;
+	dev->abort_source = 0;
+
+	ret = i2c_dw_wait_bus_not_busy(dev);
+	if (ret < 0)
+		goto done;
+
+	/* start the transfers */
+	i2c_dw_xfer_init(dev);
+
+	/* wait for tx to complete */
+	ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, HZ);
+	if (ret == 0) {
+		dev_err(dev->dev, "controller timed out\n");
+		i2c_dw_init(dev);
+		ret = -ETIMEDOUT;
+		goto done;
+	} else if (ret < 0)
+		goto done;
+
+	if (dev->msg_err) {
+		ret = dev->msg_err;
+		goto done;
+	}
+
+	/* no error */
+	if (likely(!dev->cmd_err)) {
+		/* Disable the adapter */
+		dw_writel(dev, 0, DW_IC_ENABLE);
+		ret = num;
+		goto done;
+	}
+
+	/* We have an error */
+	if (dev->cmd_err == DW_IC_ERR_TX_ABRT) {
+		ret = i2c_dw_handle_tx_abort(dev);
+		goto done;
+	}
+	ret = -EIO;
+
+done:
+	pm_runtime_put(dev->dev);
+	mutex_unlock(&dev->lock);
+
+	return ret;
+}
+
+u32 i2c_dw_func(struct i2c_adapter *adap)
+{
+	struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
+	return dev->functionality;
+}
+
+static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
+{
+	u32 stat;
+
+	/*
+	 * The IC_INTR_STAT register just indicates "enabled" interrupts.
+	 * Ths unmasked raw version of interrupt status bits are available
+	 * in the IC_RAW_INTR_STAT register.
+	 *
+	 * That is,
+	 *   stat = dw_readl(IC_INTR_STAT);
+	 * equals to,
+	 *   stat = dw_readl(IC_RAW_INTR_STAT) & dw_readl(IC_INTR_MASK);
+	 *
+	 * The raw version might be useful for debugging purposes.
+	 */
+	stat = dw_readl(dev, DW_IC_INTR_STAT);
+
+	/*
+	 * Do not use the IC_CLR_INTR register to clear interrupts, or
+	 * you'll miss some interrupts, triggered during the period from
+	 * dw_readl(IC_INTR_STAT) to dw_readl(IC_CLR_INTR).
+	 *
+	 * Instead, use the separately-prepared IC_CLR_* registers.
+	 */
+	if (stat & DW_IC_INTR_RX_UNDER)
+		dw_readl(dev, DW_IC_CLR_RX_UNDER);
+	if (stat & DW_IC_INTR_RX_OVER)
+		dw_readl(dev, DW_IC_CLR_RX_OVER);
+	if (stat & DW_IC_INTR_TX_OVER)
+		dw_readl(dev, DW_IC_CLR_TX_OVER);
+	if (stat & DW_IC_INTR_RD_REQ)
+		dw_readl(dev, DW_IC_CLR_RD_REQ);
+	if (stat & DW_IC_INTR_TX_ABRT) {
+		/*
+		 * The IC_TX_ABRT_SOURCE register is cleared whenever
+		 * the IC_CLR_TX_ABRT is read.  Preserve it beforehand.
+		 */
+		dev->abort_source = dw_readl(dev, DW_IC_TX_ABRT_SOURCE);
+		dw_readl(dev, DW_IC_CLR_TX_ABRT);
+	}
+	if (stat & DW_IC_INTR_RX_DONE)
+		dw_readl(dev, DW_IC_CLR_RX_DONE);
+	if (stat & DW_IC_INTR_ACTIVITY)
+		dw_readl(dev, DW_IC_CLR_ACTIVITY);
+	if (stat & DW_IC_INTR_STOP_DET)
+		dw_readl(dev, DW_IC_CLR_STOP_DET);
+	if (stat & DW_IC_INTR_START_DET)
+		dw_readl(dev, DW_IC_CLR_START_DET);
+	if (stat & DW_IC_INTR_GEN_CALL)
+		dw_readl(dev, DW_IC_CLR_GEN_CALL);
+
+	return stat;
+}
+
+/*
+ * Interrupt service routine. This gets called whenever an I2C interrupt
+ * occurs.
+ */
+irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
+{
+	struct dw_i2c_dev *dev = dev_id;
+	u32 stat, enabled;
+
+	enabled = dw_readl(dev, DW_IC_ENABLE);
+	stat = dw_readl(dev, DW_IC_RAW_INTR_STAT);
+	dev_dbg(dev->dev, "%s:  %s enabled= 0x%x stat=0x%x\n", __func__,
+		dev->adapter.name, enabled, stat);
+	if (!enabled || !(stat & ~DW_IC_INTR_ACTIVITY))
+		return IRQ_NONE;
+
+	stat = i2c_dw_read_clear_intrbits(dev);
+
+	if (stat & DW_IC_INTR_TX_ABRT) {
+		dev->cmd_err |= DW_IC_ERR_TX_ABRT;
+		dev->status = STATUS_IDLE;
+
+		/*
+		 * Anytime TX_ABRT is set, the contents of the tx/rx
+		 * buffers are flushed.  Make sure to skip them.
+		 */
+		dw_writel(dev, 0, DW_IC_INTR_MASK);
+		goto tx_aborted;
+	}
+
+	if (stat & DW_IC_INTR_RX_FULL)
+		i2c_dw_read(dev);
+
+	if (stat & DW_IC_INTR_TX_EMPTY)
+		i2c_dw_xfer_msg(dev);
+
+	/*
+	 * No need to modify or disable the interrupt mask here.
+	 * i2c_dw_xfer_msg() will take care of it according to
+	 * the current transmit status.
+	 */
+
+tx_aborted:
+	if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err)
+		complete(&dev->cmd_complete);
+
+	return IRQ_HANDLED;
+}
+
+void i2c_dw_enable(struct dw_i2c_dev *dev)
+{
+       /* Enable the adapter */
+	dw_writel(dev, 1, DW_IC_ENABLE);
+}
+
+u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev)
+{
+	return dw_readl(dev, DW_IC_ENABLE);
+}
+
+void i2c_dw_disable(struct dw_i2c_dev *dev)
+{
+	/* Disable controller */
+	dw_writel(dev, 0, DW_IC_ENABLE);
+
+	/* Disable all interupts */
+	dw_writel(dev, 0, DW_IC_INTR_MASK);
+	dw_readl(dev, DW_IC_CLR_INTR);
+}
+
+void i2c_dw_clear_int(struct dw_i2c_dev *dev)
+{
+	dw_readl(dev, DW_IC_CLR_INTR);
+}
+
+void i2c_dw_disable_int(struct dw_i2c_dev *dev)
+{
+	dw_writel(dev, 0, DW_IC_INTR_MASK);
+}
+
+u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev)
+{
+	return dw_readl(dev, DW_IC_COMP_PARAM_1);
+}
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
new file mode 100644
index 0000000..02d1a2d
--- /dev/null
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -0,0 +1,105 @@
+/*
+ * Synopsys DesignWare I2C adapter driver (master only).
+ *
+ * Based on the TI DAVINCI I2C adapter driver.
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software Inc.
+ * Copyright (C) 2009 Provigent Ltd.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ *
+ */
+
+
+#define DW_IC_CON_MASTER		0x1
+#define DW_IC_CON_SPEED_STD		0x2
+#define DW_IC_CON_SPEED_FAST		0x4
+#define DW_IC_CON_10BITADDR_MASTER	0x10
+#define DW_IC_CON_RESTART_EN		0x20
+#define DW_IC_CON_SLAVE_DISABLE		0x40
+
+
+/**
+ * struct dw_i2c_dev - private i2c-designware data
+ * @dev: driver model device node
+ * @base: IO registers pointer
+ * @cmd_complete: tx completion indicator
+ * @lock: protect this struct and IO registers
+ * @clk: input reference clock
+ * @cmd_err: run time hadware error code
+ * @msgs: points to an array of messages currently being transfered
+ * @msgs_num: the number of elements in msgs
+ * @msg_write_idx: the element index of the current tx message in the msgs
+ *	array
+ * @tx_buf_len: the length of the current tx buffer
+ * @tx_buf: the current tx buffer
+ * @msg_read_idx: the element index of the current rx message in the msgs
+ *	array
+ * @rx_buf_len: the length of the current rx buffer
+ * @rx_buf: the current rx buffer
+ * @msg_err: error status of the current transfer
+ * @status: i2c master status, one of STATUS_*
+ * @abort_source: copy of the TX_ABRT_SOURCE register
+ * @irq: interrupt number for the i2c master
+ * @adapter: i2c subsystem adapter node
+ * @tx_fifo_depth: depth of the hardware tx fifo
+ * @rx_fifo_depth: depth of the hardware rx fifo
+ */
+struct dw_i2c_dev {
+	struct device		*dev;
+	void __iomem		*base;
+	struct completion	cmd_complete;
+	struct mutex		lock;
+	struct clk		*clk;
+	u32			(*get_clk_rate_khz) (struct dw_i2c_dev *dev);
+	struct dw_pci_controller *controller;
+	int			cmd_err;
+	struct i2c_msg		*msgs;
+	int			msgs_num;
+	int			msg_write_idx;
+	u32			tx_buf_len;
+	u8			*tx_buf;
+	int			msg_read_idx;
+	u32			rx_buf_len;
+	u8			*rx_buf;
+	int			msg_err;
+	unsigned int		status;
+	u32			abort_source;
+	int			irq;
+	int			swab;
+	struct i2c_adapter	adapter;
+	u32			functionality;
+	u32			master_cfg;
+	unsigned int		tx_fifo_depth;
+	unsigned int		rx_fifo_depth;
+};
+
+extern u32 dw_readl(struct dw_i2c_dev *dev, int offset);
+extern void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset);
+extern int i2c_dw_init(struct dw_i2c_dev *dev);
+extern int i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
+		int num);
+extern u32 i2c_dw_func(struct i2c_adapter *adap);
+extern irqreturn_t i2c_dw_isr(int this_irq, void *dev_id);
+extern void i2c_dw_enable(struct dw_i2c_dev *dev);
+extern u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev);
+extern void i2c_dw_disable(struct dw_i2c_dev *dev);
+extern void i2c_dw_clear_int(struct dw_i2c_dev *dev);
+extern void i2c_dw_disable_int(struct dw_i2c_dev *dev);
+extern u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev);
diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c
new file mode 100644
index 0000000..9e89e73
--- /dev/null
+++ b/drivers/i2c/busses/i2c-designware-pcidrv.c
@@ -0,0 +1,392 @@
+/*
+ * Synopsys DesignWare I2C adapter driver (master only).
+ *
+ * Based on the TI DAVINCI I2C adapter driver.
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software Inc.
+ * Copyright (C) 2009 Provigent Ltd.
+ * Copyright (C) 2011 Intel corporation.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/pm_runtime.h>
+#include "i2c-designware-core.h"
+
+#define DRIVER_NAME "i2c-designware-pci"
+
+enum dw_pci_ctl_id_t {
+	moorestown_0,
+	moorestown_1,
+	moorestown_2,
+
+	medfield_0,
+	medfield_1,
+	medfield_2,
+	medfield_3,
+	medfield_4,
+	medfield_5,
+};
+
+struct dw_pci_controller {
+	u32 bus_num;
+	u32 bus_cfg;
+	u32 tx_fifo_depth;
+	u32 rx_fifo_depth;
+	u32 clk_khz;
+};
+
+#define INTEL_MID_STD_CFG  (DW_IC_CON_MASTER |			\
+				DW_IC_CON_SLAVE_DISABLE |	\
+				DW_IC_CON_RESTART_EN)
+
+static struct  dw_pci_controller  dw_pci_controllers[] = {
+	[moorestown_0] = {
+		.bus_num     = 0,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+		.tx_fifo_depth = 32,
+		.rx_fifo_depth = 32,
+		.clk_khz      = 25000,
+	},
+	[moorestown_1] = {
+		.bus_num     = 1,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+		.tx_fifo_depth = 32,
+		.rx_fifo_depth = 32,
+		.clk_khz      = 25000,
+	},
+	[moorestown_2] = {
+		.bus_num     = 2,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+		.tx_fifo_depth = 32,
+		.rx_fifo_depth = 32,
+		.clk_khz      = 25000,
+	},
+	[medfield_0] = {
+		.bus_num     = 0,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+		.tx_fifo_depth = 32,
+		.rx_fifo_depth = 32,
+		.clk_khz      = 25000,
+	},
+	[medfield_1] = {
+		.bus_num     = 1,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+		.tx_fifo_depth = 32,
+		.rx_fifo_depth = 32,
+		.clk_khz      = 25000,
+	},
+	[medfield_2] = {
+		.bus_num     = 2,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+		.tx_fifo_depth = 32,
+		.rx_fifo_depth = 32,
+		.clk_khz      = 25000,
+	},
+	[medfield_3] = {
+		.bus_num     = 3,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_STD,
+		.tx_fifo_depth = 32,
+		.rx_fifo_depth = 32,
+		.clk_khz      = 25000,
+	},
+	[medfield_4] = {
+		.bus_num     = 4,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+		.tx_fifo_depth = 32,
+		.rx_fifo_depth = 32,
+		.clk_khz      = 25000,
+	},
+	[medfield_5] = {
+		.bus_num     = 5,
+		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+		.tx_fifo_depth = 32,
+		.rx_fifo_depth = 32,
+		.clk_khz      = 25000,
+	},
+};
+static struct i2c_algorithm i2c_dw_algo = {
+	.master_xfer	= i2c_dw_xfer,
+	.functionality	= i2c_dw_func,
+};
+
+static int i2c_dw_pci_suspend(struct device *dev)
+{
+	struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+	struct dw_i2c_dev *i2c = pci_get_drvdata(pdev);
+	int err;
+
+
+	i2c_dw_disable(i2c);
+
+	err = pci_save_state(pdev);
+	if (err) {
+		dev_err(&pdev->dev, "pci_save_state failed\n");
+		return err;
+	}
+
+	err = pci_set_power_state(pdev, PCI_D3hot);
+	if (err) {
+		dev_err(&pdev->dev, "pci_set_power_state failed\n");
+		return err;
+	}
+
+	return 0;
+}
+
+static int i2c_dw_pci_resume(struct device *dev)
+{
+	struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+	struct dw_i2c_dev *i2c = pci_get_drvdata(pdev);
+	int err;
+	u32 enabled;
+
+	enabled = i2c_dw_is_enabled(i2c);
+	if (enabled)
+		return 0;
+
+	err = pci_set_power_state(pdev, PCI_D0);
+	if (err) {
+		dev_err(&pdev->dev, "pci_set_power_state() failed\n");
+		return err;
+	}
+
+	pci_restore_state(pdev);
+
+	i2c_dw_init(i2c);
+	i2c_dw_enable(i2c);
+	return 0;
+}
+
+static int i2c_dw_pci_runtime_idle(struct device *dev)
+{
+	int err = pm_schedule_suspend(dev, 500);
+	dev_dbg(dev, "runtime_idle called\n");
+
+	if (err != 0)
+		return 0;
+	return -EBUSY;
+}
+
+static const struct dev_pm_ops i2c_dw_pm_ops = {
+	.resume         = i2c_dw_pci_resume,
+	.suspend        = i2c_dw_pci_suspend,
+	SET_RUNTIME_PM_OPS(i2c_dw_pci_suspend, i2c_dw_pci_resume,
+			   i2c_dw_pci_runtime_idle)
+};
+
+static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
+{
+	return dev->controller->clk_khz;
+}
+
+static int __devinit i2c_dw_pci_probe(struct pci_dev *pdev,
+const struct pci_device_id *id)
+{
+	struct dw_i2c_dev *dev;
+	struct i2c_adapter *adap;
+	unsigned long start, len;
+	void __iomem *base;
+	int r;
+	struct  dw_pci_controller *controller;
+
+	if (id->driver_data >= ARRAY_SIZE(dw_pci_controllers)) {
+		printk(KERN_ERR "dw_i2c_pci_probe: invalid driver data %ld\n",
+			id->driver_data);
+		return -EINVAL;
+	}
+
+	controller = &dw_pci_controllers[id->driver_data];
+
+	r = pci_enable_device(pdev);
+	if (r) {
+		dev_err(&pdev->dev, "Failed to enable I2C PCI device (%d)\n",
+			r);
+		goto exit;
+	}
+
+	/* Determine the address of the I2C area */
+	start = pci_resource_start(pdev, 0);
+	len = pci_resource_len(pdev, 0);
+	if (!start || len == 0) {
+		dev_err(&pdev->dev, "base address not set\n");
+		r = -ENODEV;
+		goto exit;
+	}
+
+	r = pci_request_region(pdev, 0, DRIVER_NAME);
+	if (r) {
+		dev_err(&pdev->dev, "failed to request I2C region "
+			"0x%lx-0x%lx\n", start,
+			(unsigned long)pci_resource_end(pdev, 0));
+		goto exit;
+	}
+
+	base = ioremap_nocache(start, len);
+	if (!base) {
+		dev_err(&pdev->dev, "I/O memory remapping failed\n");
+		r = -ENOMEM;
+		goto err_release_region;
+	}
+
+
+	dev = kzalloc(sizeof(struct dw_i2c_dev), GFP_KERNEL);
+	if (!dev) {
+		r = -ENOMEM;
+		goto err_release_region;
+	}
+
+	init_completion(&dev->cmd_complete);
+	mutex_init(&dev->lock);
+	dev->clk = NULL;
+	dev->controller = controller;
+	dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz;
+	dev->base = base;
+	dev->dev = get_device(&pdev->dev);
+	dev->functionality =
+		I2C_FUNC_I2C |
+		I2C_FUNC_SMBUS_BYTE |
+		I2C_FUNC_SMBUS_BYTE_DATA |
+		I2C_FUNC_SMBUS_WORD_DATA |
+		I2C_FUNC_SMBUS_I2C_BLOCK;
+	dev->master_cfg =  controller->bus_cfg;
+
+	pci_set_drvdata(pdev, dev);
+
+	dev->tx_fifo_depth = controller->tx_fifo_depth;
+	dev->rx_fifo_depth = controller->rx_fifo_depth;
+	r = i2c_dw_init(dev);
+	if (r)
+		goto err_iounmap;
+
+	adap = &dev->adapter;
+	i2c_set_adapdata(adap, dev);
+	adap->owner = THIS_MODULE;
+	adap->class = 0;
+	adap->algo = &i2c_dw_algo;
+	adap->dev.parent = &pdev->dev;
+	adap->nr = controller->bus_num;
+	snprintf(adap->name, sizeof(adap->name), "i2c-designware-pci-%d",
+		adap->nr);
+
+	r = request_irq(pdev->irq, i2c_dw_isr, IRQF_SHARED, adap->name, dev);
+	if (r) {
+		dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
+		goto err_iounmap;
+	}
+
+	i2c_dw_disable_int(dev);
+	i2c_dw_clear_int(dev);
+	r = i2c_add_numbered_adapter(adap);
+	if (r) {
+		dev_err(&pdev->dev, "failure adding adapter\n");
+		goto err_free_irq;
+	}
+
+	pm_runtime_put_noidle(&pdev->dev);
+	pm_runtime_allow(&pdev->dev);
+
+	return 0;
+
+err_free_irq:
+	free_irq(pdev->irq, dev);
+err_iounmap:
+	iounmap(dev->base);
+	pci_set_drvdata(pdev, NULL);
+	put_device(&pdev->dev);
+	kfree(dev);
+err_release_region:
+	pci_release_region(pdev, 0);
+exit:
+	return r;
+}
+
+static void __devexit i2c_dw_pci_remove(struct pci_dev *pdev)
+{
+	struct dw_i2c_dev *dev = pci_get_drvdata(pdev);
+
+	i2c_dw_disable(dev);
+	pm_runtime_forbid(&pdev->dev);
+	pm_runtime_get_noresume(&pdev->dev);
+
+	pci_set_drvdata(pdev, NULL);
+	i2c_del_adapter(&dev->adapter);
+	put_device(&pdev->dev);
+
+	free_irq(dev->irq, dev);
+	kfree(dev);
+	pci_release_region(pdev, 0);
+}
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("i2c_designware-pci");
+
+DEFINE_PCI_DEVICE_TABLE(i2_designware_pci_ids) = {
+	/* Moorestown */
+	{ PCI_VDEVICE(INTEL, 0x0802), moorestown_0 },
+	{ PCI_VDEVICE(INTEL, 0x0803), moorestown_1 },
+	{ PCI_VDEVICE(INTEL, 0x0804), moorestown_2 },
+	/* Medfield */
+	{ PCI_VDEVICE(INTEL, 0x0817), medfield_3,},
+	{ PCI_VDEVICE(INTEL, 0x0818), medfield_4 },
+	{ PCI_VDEVICE(INTEL, 0x0819), medfield_5 },
+	{ PCI_VDEVICE(INTEL, 0x082C), medfield_0 },
+	{ PCI_VDEVICE(INTEL, 0x082D), medfield_1 },
+	{ PCI_VDEVICE(INTEL, 0x082E), medfield_2 },
+	{ 0,}
+};
+MODULE_DEVICE_TABLE(pci, i2_designware_pci_ids);
+
+static struct pci_driver dw_i2c_driver = {
+	.name		= DRIVER_NAME,
+	.id_table	= i2_designware_pci_ids,
+	.probe		= i2c_dw_pci_probe,
+	.remove		= __devexit_p(i2c_dw_pci_remove),
+	.driver         = {
+		.pm     = &i2c_dw_pm_ops,
+	},
+};
+
+static int __init dw_i2c_init_driver(void)
+{
+	return  pci_register_driver(&dw_i2c_driver);
+}
+module_init(dw_i2c_init_driver);
+
+static void __exit dw_i2c_exit_driver(void)
+{
+	pci_unregister_driver(&dw_i2c_driver);
+}
+module_exit(dw_i2c_exit_driver);
+
+MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
+MODULE_DESCRIPTION("Synopsys DesignWare PCI I2C bus adapter");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
new file mode 100644
index 0000000..2d3657a
--- /dev/null
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -0,0 +1,215 @@
+/*
+ * Synopsys DesignWare I2C adapter driver (master only).
+ *
+ * Based on the TI DAVINCI I2C adapter driver.
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software Inc.
+ * Copyright (C) 2009 Provigent Ltd.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include "i2c-designware-core.h"
+
+static struct i2c_algorithm i2c_dw_algo = {
+	.master_xfer	= i2c_dw_xfer,
+	.functionality	= i2c_dw_func,
+};
+static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
+{
+	return clk_get_rate(dev->clk)/1000;
+}
+
+static int __devinit dw_i2c_probe(struct platform_device *pdev)
+{
+	struct dw_i2c_dev *dev;
+	struct i2c_adapter *adap;
+	struct resource *mem, *ioarea;
+	int irq, r;
+
+	/* NOTE: driver uses the static register mapping */
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "no mem resource?\n");
+		return -EINVAL;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "no irq resource?\n");
+		return irq; /* -ENXIO */
+	}
+
+	ioarea = request_mem_region(mem->start, resource_size(mem),
+			pdev->name);
+	if (!ioarea) {
+		dev_err(&pdev->dev, "I2C region already claimed\n");
+		return -EBUSY;
+	}
+
+	dev = kzalloc(sizeof(struct dw_i2c_dev), GFP_KERNEL);
+	if (!dev) {
+		r = -ENOMEM;
+		goto err_release_region;
+	}
+
+	init_completion(&dev->cmd_complete);
+	mutex_init(&dev->lock);
+	dev->dev = get_device(&pdev->dev);
+	dev->irq = irq;
+	platform_set_drvdata(pdev, dev);
+
+	dev->clk = clk_get(&pdev->dev, NULL);
+	dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz;
+
+	if (IS_ERR(dev->clk)) {
+		r = -ENODEV;
+		goto err_free_mem;
+	}
+	clk_enable(dev->clk);
+
+	dev->functionality =
+		I2C_FUNC_I2C |
+		I2C_FUNC_10BIT_ADDR |
+		I2C_FUNC_SMBUS_BYTE |
+		I2C_FUNC_SMBUS_BYTE_DATA |
+		I2C_FUNC_SMBUS_WORD_DATA |
+		I2C_FUNC_SMBUS_I2C_BLOCK;
+	dev->master_cfg =  DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
+		DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST;
+
+	dev->base = ioremap(mem->start, resource_size(mem));
+	if (dev->base == NULL) {
+		dev_err(&pdev->dev, "failure mapping io resources\n");
+		r = -EBUSY;
+		goto err_unuse_clocks;
+	}
+	{
+		u32 param1 = i2c_dw_read_comp_param(dev);
+
+		dev->tx_fifo_depth = ((param1 >> 16) & 0xff) + 1;
+		dev->rx_fifo_depth = ((param1 >> 8)  & 0xff) + 1;
+	}
+	r = i2c_dw_init(dev);
+	if (r)
+		goto err_iounmap;
+
+	i2c_dw_disable_int(dev);
+	r = request_irq(dev->irq, i2c_dw_isr, IRQF_DISABLED, pdev->name, dev);
+	if (r) {
+		dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
+		goto err_iounmap;
+	}
+
+	adap = &dev->adapter;
+	i2c_set_adapdata(adap, dev);
+	adap->owner = THIS_MODULE;
+	adap->class = I2C_CLASS_HWMON;
+	strlcpy(adap->name, "Synopsys DesignWare I2C adapter",
+			sizeof(adap->name));
+	adap->algo = &i2c_dw_algo;
+	adap->dev.parent = &pdev->dev;
+
+	adap->nr = pdev->id;
+	r = i2c_add_numbered_adapter(adap);
+	if (r) {
+		dev_err(&pdev->dev, "failure adding adapter\n");
+		goto err_free_irq;
+	}
+
+	return 0;
+
+err_free_irq:
+	free_irq(dev->irq, dev);
+err_iounmap:
+	iounmap(dev->base);
+err_unuse_clocks:
+	clk_disable(dev->clk);
+	clk_put(dev->clk);
+	dev->clk = NULL;
+err_free_mem:
+	platform_set_drvdata(pdev, NULL);
+	put_device(&pdev->dev);
+	kfree(dev);
+err_release_region:
+	release_mem_region(mem->start, resource_size(mem));
+
+	return r;
+}
+
+static int __devexit dw_i2c_remove(struct platform_device *pdev)
+{
+	struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
+	struct resource *mem;
+
+	platform_set_drvdata(pdev, NULL);
+	i2c_del_adapter(&dev->adapter);
+	put_device(&pdev->dev);
+
+	clk_disable(dev->clk);
+	clk_put(dev->clk);
+	dev->clk = NULL;
+
+	i2c_dw_disable(dev);
+	free_irq(dev->irq, dev);
+	kfree(dev);
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(mem->start, resource_size(mem));
+	return 0;
+}
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:i2c_designware");
+
+static struct platform_driver dw_i2c_driver = {
+	.remove		= __devexit_p(dw_i2c_remove),
+	.driver		= {
+		.name	= "i2c_designware",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init dw_i2c_init_driver(void)
+{
+	return platform_driver_probe(&dw_i2c_driver, dw_i2c_probe);
+}
+module_init(dw_i2c_init_driver);
+
+static void __exit dw_i2c_exit_driver(void)
+{
+	platform_driver_unregister(&dw_i2c_driver);
+}
+module_exit(dw_i2c_exit_driver);
+
+MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
+MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-designware.c b/drivers/i2c/busses/i2c-designware.c
deleted file mode 100644
index 1b42b50..0000000
--- a/drivers/i2c/busses/i2c-designware.c
+++ /dev/null
@@ -1,847 +0,0 @@
-/*
- * Synopsys DesignWare I2C adapter driver (master only).
- *
- * Based on the TI DAVINCI I2C adapter driver.
- *
- * Copyright (C) 2006 Texas Instruments.
- * Copyright (C) 2007 MontaVista Software Inc.
- * Copyright (C) 2009 Provigent Ltd.
- *
- * ----------------------------------------------------------------------------
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- * ----------------------------------------------------------------------------
- *
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include <linux/clk.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-/*
- * Registers offset
- */
-#define DW_IC_CON		0x0
-#define DW_IC_TAR		0x4
-#define DW_IC_DATA_CMD		0x10
-#define DW_IC_SS_SCL_HCNT	0x14
-#define DW_IC_SS_SCL_LCNT	0x18
-#define DW_IC_FS_SCL_HCNT	0x1c
-#define DW_IC_FS_SCL_LCNT	0x20
-#define DW_IC_INTR_STAT		0x2c
-#define DW_IC_INTR_MASK		0x30
-#define DW_IC_RAW_INTR_STAT	0x34
-#define DW_IC_RX_TL		0x38
-#define DW_IC_TX_TL		0x3c
-#define DW_IC_CLR_INTR		0x40
-#define DW_IC_CLR_RX_UNDER	0x44
-#define DW_IC_CLR_RX_OVER	0x48
-#define DW_IC_CLR_TX_OVER	0x4c
-#define DW_IC_CLR_RD_REQ	0x50
-#define DW_IC_CLR_TX_ABRT	0x54
-#define DW_IC_CLR_RX_DONE	0x58
-#define DW_IC_CLR_ACTIVITY	0x5c
-#define DW_IC_CLR_STOP_DET	0x60
-#define DW_IC_CLR_START_DET	0x64
-#define DW_IC_CLR_GEN_CALL	0x68
-#define DW_IC_ENABLE		0x6c
-#define DW_IC_STATUS		0x70
-#define DW_IC_TXFLR		0x74
-#define DW_IC_RXFLR		0x78
-#define DW_IC_COMP_PARAM_1	0xf4
-#define DW_IC_TX_ABRT_SOURCE	0x80
-
-#define DW_IC_CON_MASTER		0x1
-#define DW_IC_CON_SPEED_STD		0x2
-#define DW_IC_CON_SPEED_FAST		0x4
-#define DW_IC_CON_10BITADDR_MASTER	0x10
-#define DW_IC_CON_RESTART_EN		0x20
-#define DW_IC_CON_SLAVE_DISABLE		0x40
-
-#define DW_IC_INTR_RX_UNDER	0x001
-#define DW_IC_INTR_RX_OVER	0x002
-#define DW_IC_INTR_RX_FULL	0x004
-#define DW_IC_INTR_TX_OVER	0x008
-#define DW_IC_INTR_TX_EMPTY	0x010
-#define DW_IC_INTR_RD_REQ	0x020
-#define DW_IC_INTR_TX_ABRT	0x040
-#define DW_IC_INTR_RX_DONE	0x080
-#define DW_IC_INTR_ACTIVITY	0x100
-#define DW_IC_INTR_STOP_DET	0x200
-#define DW_IC_INTR_START_DET	0x400
-#define DW_IC_INTR_GEN_CALL	0x800
-
-#define DW_IC_INTR_DEFAULT_MASK		(DW_IC_INTR_RX_FULL | \
-					 DW_IC_INTR_TX_EMPTY | \
-					 DW_IC_INTR_TX_ABRT | \
-					 DW_IC_INTR_STOP_DET)
-
-#define DW_IC_STATUS_ACTIVITY	0x1
-
-#define DW_IC_ERR_TX_ABRT	0x1
-
-/*
- * status codes
- */
-#define STATUS_IDLE			0x0
-#define STATUS_WRITE_IN_PROGRESS	0x1
-#define STATUS_READ_IN_PROGRESS		0x2
-
-#define TIMEOUT			20 /* ms */
-
-/*
- * hardware abort codes from the DW_IC_TX_ABRT_SOURCE register
- *
- * only expected abort codes are listed here
- * refer to the datasheet for the full list
- */
-#define ABRT_7B_ADDR_NOACK	0
-#define ABRT_10ADDR1_NOACK	1
-#define ABRT_10ADDR2_NOACK	2
-#define ABRT_TXDATA_NOACK	3
-#define ABRT_GCALL_NOACK	4
-#define ABRT_GCALL_READ		5
-#define ABRT_SBYTE_ACKDET	7
-#define ABRT_SBYTE_NORSTRT	9
-#define ABRT_10B_RD_NORSTRT	10
-#define ABRT_MASTER_DIS		11
-#define ARB_LOST		12
-
-#define DW_IC_TX_ABRT_7B_ADDR_NOACK	(1UL << ABRT_7B_ADDR_NOACK)
-#define DW_IC_TX_ABRT_10ADDR1_NOACK	(1UL << ABRT_10ADDR1_NOACK)
-#define DW_IC_TX_ABRT_10ADDR2_NOACK	(1UL << ABRT_10ADDR2_NOACK)
-#define DW_IC_TX_ABRT_TXDATA_NOACK	(1UL << ABRT_TXDATA_NOACK)
-#define DW_IC_TX_ABRT_GCALL_NOACK	(1UL << ABRT_GCALL_NOACK)
-#define DW_IC_TX_ABRT_GCALL_READ	(1UL << ABRT_GCALL_READ)
-#define DW_IC_TX_ABRT_SBYTE_ACKDET	(1UL << ABRT_SBYTE_ACKDET)
-#define DW_IC_TX_ABRT_SBYTE_NORSTRT	(1UL << ABRT_SBYTE_NORSTRT)
-#define DW_IC_TX_ABRT_10B_RD_NORSTRT	(1UL << ABRT_10B_RD_NORSTRT)
-#define DW_IC_TX_ABRT_MASTER_DIS	(1UL << ABRT_MASTER_DIS)
-#define DW_IC_TX_ARB_LOST		(1UL << ARB_LOST)
-
-#define DW_IC_TX_ABRT_NOACK		(DW_IC_TX_ABRT_7B_ADDR_NOACK | \
-					 DW_IC_TX_ABRT_10ADDR1_NOACK | \
-					 DW_IC_TX_ABRT_10ADDR2_NOACK | \
-					 DW_IC_TX_ABRT_TXDATA_NOACK | \
-					 DW_IC_TX_ABRT_GCALL_NOACK)
-
-static char *abort_sources[] = {
-	[ABRT_7B_ADDR_NOACK] =
-		"slave address not acknowledged (7bit mode)",
-	[ABRT_10ADDR1_NOACK] =
-		"first address byte not acknowledged (10bit mode)",
-	[ABRT_10ADDR2_NOACK] =
-		"second address byte not acknowledged (10bit mode)",
-	[ABRT_TXDATA_NOACK] =
-		"data not acknowledged",
-	[ABRT_GCALL_NOACK] =
-		"no acknowledgement for a general call",
-	[ABRT_GCALL_READ] =
-		"read after general call",
-	[ABRT_SBYTE_ACKDET] =
-		"start byte acknowledged",
-	[ABRT_SBYTE_NORSTRT] =
-		"trying to send start byte when restart is disabled",
-	[ABRT_10B_RD_NORSTRT] =
-		"trying to read when restart is disabled (10bit mode)",
-	[ABRT_MASTER_DIS] =
-		"trying to use disabled adapter",
-	[ARB_LOST] =
-		"lost arbitration",
-};
-
-/**
- * struct dw_i2c_dev - private i2c-designware data
- * @dev: driver model device node
- * @base: IO registers pointer
- * @cmd_complete: tx completion indicator
- * @lock: protect this struct and IO registers
- * @clk: input reference clock
- * @cmd_err: run time hadware error code
- * @msgs: points to an array of messages currently being transferred
- * @msgs_num: the number of elements in msgs
- * @msg_write_idx: the element index of the current tx message in the msgs
- *	array
- * @tx_buf_len: the length of the current tx buffer
- * @tx_buf: the current tx buffer
- * @msg_read_idx: the element index of the current rx message in the msgs
- *	array
- * @rx_buf_len: the length of the current rx buffer
- * @rx_buf: the current rx buffer
- * @msg_err: error status of the current transfer
- * @status: i2c master status, one of STATUS_*
- * @abort_source: copy of the TX_ABRT_SOURCE register
- * @irq: interrupt number for the i2c master
- * @adapter: i2c subsystem adapter node
- * @tx_fifo_depth: depth of the hardware tx fifo
- * @rx_fifo_depth: depth of the hardware rx fifo
- */
-struct dw_i2c_dev {
-	struct device		*dev;
-	void __iomem		*base;
-	struct completion	cmd_complete;
-	struct mutex		lock;
-	struct clk		*clk;
-	int			cmd_err;
-	struct i2c_msg		*msgs;
-	int			msgs_num;
-	int			msg_write_idx;
-	u32			tx_buf_len;
-	u8			*tx_buf;
-	int			msg_read_idx;
-	u32			rx_buf_len;
-	u8			*rx_buf;
-	int			msg_err;
-	unsigned int		status;
-	u32			abort_source;
-	int			irq;
-	struct i2c_adapter	adapter;
-	unsigned int		tx_fifo_depth;
-	unsigned int		rx_fifo_depth;
-};
-
-static u32
-i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
-{
-	/*
-	 * DesignWare I2C core doesn't seem to have solid strategy to meet
-	 * the tHD;STA timing spec.  Configuring _HCNT based on tHIGH spec
-	 * will result in violation of the tHD;STA spec.
-	 */
-	if (cond)
-		/*
-		 * Conditional expression:
-		 *
-		 *   IC_[FS]S_SCL_HCNT + (1+4+3) >= IC_CLK * tHIGH
-		 *
-		 * This is based on the DW manuals, and represents an ideal
-		 * configuration.  The resulting I2C bus speed will be
-		 * faster than any of the others.
-		 *
-		 * If your hardware is free from tHD;STA issue, try this one.
-		 */
-		return (ic_clk * tSYMBOL + 5000) / 10000 - 8 + offset;
-	else
-		/*
-		 * Conditional expression:
-		 *
-		 *   IC_[FS]S_SCL_HCNT + 3 >= IC_CLK * (tHD;STA + tf)
-		 *
-		 * This is just experimental rule; the tHD;STA period turned
-		 * out to be proportinal to (_HCNT + 3).  With this setting,
-		 * we could meet both tHIGH and tHD;STA timing specs.
-		 *
-		 * If unsure, you'd better to take this alternative.
-		 *
-		 * The reason why we need to take into account "tf" here,
-		 * is the same as described in i2c_dw_scl_lcnt().
-		 */
-		return (ic_clk * (tSYMBOL + tf) + 5000) / 10000 - 3 + offset;
-}
-
-static u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
-{
-	/*
-	 * Conditional expression:
-	 *
-	 *   IC_[FS]S_SCL_LCNT + 1 >= IC_CLK * (tLOW + tf)
-	 *
-	 * DW I2C core starts counting the SCL CNTs for the LOW period
-	 * of the SCL clock (tLOW) as soon as it pulls the SCL line.
-	 * In order to meet the tLOW timing spec, we need to take into
-	 * account the fall time of SCL signal (tf).  Default tf value
-	 * should be 0.3 us, for safety.
-	 */
-	return ((ic_clk * (tLOW + tf) + 5000) / 10000) - 1 + offset;
-}
-
-/**
- * i2c_dw_init() - initialize the designware i2c master hardware
- * @dev: device private data
- *
- * This functions configures and enables the I2C master.
- * This function is called during I2C init function, and in case of timeout at
- * run time.
- */
-static void i2c_dw_init(struct dw_i2c_dev *dev)
-{
-	u32 input_clock_khz = clk_get_rate(dev->clk) / 1000;
-	u32 ic_con, hcnt, lcnt;
-
-	/* Disable the adapter */
-	writel(0, dev->base + DW_IC_ENABLE);
-
-	/* set standard and fast speed deviders for high/low periods */
-
-	/* Standard-mode */
-	hcnt = i2c_dw_scl_hcnt(input_clock_khz,
-				40,	/* tHD;STA = tHIGH = 4.0 us */
-				3,	/* tf = 0.3 us */
-				0,	/* 0: DW default, 1: Ideal */
-				0);	/* No offset */
-	lcnt = i2c_dw_scl_lcnt(input_clock_khz,
-				47,	/* tLOW = 4.7 us */
-				3,	/* tf = 0.3 us */
-				0);	/* No offset */
-	writel(hcnt, dev->base + DW_IC_SS_SCL_HCNT);
-	writel(lcnt, dev->base + DW_IC_SS_SCL_LCNT);
-	dev_dbg(dev->dev, "Standard-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
-
-	/* Fast-mode */
-	hcnt = i2c_dw_scl_hcnt(input_clock_khz,
-				6,	/* tHD;STA = tHIGH = 0.6 us */
-				3,	/* tf = 0.3 us */
-				0,	/* 0: DW default, 1: Ideal */
-				0);	/* No offset */
-	lcnt = i2c_dw_scl_lcnt(input_clock_khz,
-				13,	/* tLOW = 1.3 us */
-				3,	/* tf = 0.3 us */
-				0);	/* No offset */
-	writel(hcnt, dev->base + DW_IC_FS_SCL_HCNT);
-	writel(lcnt, dev->base + DW_IC_FS_SCL_LCNT);
-	dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
-
-	/* Configure Tx/Rx FIFO threshold levels */
-	writel(dev->tx_fifo_depth - 1, dev->base + DW_IC_TX_TL);
-	writel(0, dev->base + DW_IC_RX_TL);
-
-	/* configure the i2c master */
-	ic_con = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
-		DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST;
-	writel(ic_con, dev->base + DW_IC_CON);
-}
-
-/*
- * Waiting for bus not busy
- */
-static int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)
-{
-	int timeout = TIMEOUT;
-
-	while (readl(dev->base + DW_IC_STATUS) & DW_IC_STATUS_ACTIVITY) {
-		if (timeout <= 0) {
-			dev_warn(dev->dev, "timeout waiting for bus ready\n");
-			return -ETIMEDOUT;
-		}
-		timeout--;
-		mdelay(1);
-	}
-
-	return 0;
-}
-
-static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
-{
-	struct i2c_msg *msgs = dev->msgs;
-	u32 ic_con;
-
-	/* Disable the adapter */
-	writel(0, dev->base + DW_IC_ENABLE);
-
-	/* set the slave (target) address */
-	writel(msgs[dev->msg_write_idx].addr, dev->base + DW_IC_TAR);
-
-	/* if the slave address is ten bit address, enable 10BITADDR */
-	ic_con = readl(dev->base + DW_IC_CON);
-	if (msgs[dev->msg_write_idx].flags & I2C_M_TEN)
-		ic_con |= DW_IC_CON_10BITADDR_MASTER;
-	else
-		ic_con &= ~DW_IC_CON_10BITADDR_MASTER;
-	writel(ic_con, dev->base + DW_IC_CON);
-
-	/* Enable the adapter */
-	writel(1, dev->base + DW_IC_ENABLE);
-
-	/* Enable interrupts */
-	writel(DW_IC_INTR_DEFAULT_MASK, dev->base + DW_IC_INTR_MASK);
-}
-
-/*
- * Initiate (and continue) low level master read/write transaction.
- * This function is only called from i2c_dw_isr, and pumping i2c_msg
- * messages into the tx buffer.  Even if the size of i2c_msg data is
- * longer than the size of the tx buffer, it handles everything.
- */
-static void
-i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
-{
-	struct i2c_msg *msgs = dev->msgs;
-	u32 intr_mask;
-	int tx_limit, rx_limit;
-	u32 addr = msgs[dev->msg_write_idx].addr;
-	u32 buf_len = dev->tx_buf_len;
-	u8 *buf = dev->tx_buf;
-
-	intr_mask = DW_IC_INTR_DEFAULT_MASK;
-
-	for (; dev->msg_write_idx < dev->msgs_num; dev->msg_write_idx++) {
-		/*
-		 * if target address has changed, we need to
-		 * reprogram the target address in the i2c
-		 * adapter when we are done with this transfer
-		 */
-		if (msgs[dev->msg_write_idx].addr != addr) {
-			dev_err(dev->dev,
-				"%s: invalid target address\n", __func__);
-			dev->msg_err = -EINVAL;
-			break;
-		}
-
-		if (msgs[dev->msg_write_idx].len == 0) {
-			dev_err(dev->dev,
-				"%s: invalid message length\n", __func__);
-			dev->msg_err = -EINVAL;
-			break;
-		}
-
-		if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) {
-			/* new i2c_msg */
-			buf = msgs[dev->msg_write_idx].buf;
-			buf_len = msgs[dev->msg_write_idx].len;
-		}
-
-		tx_limit = dev->tx_fifo_depth - readl(dev->base + DW_IC_TXFLR);
-		rx_limit = dev->rx_fifo_depth - readl(dev->base + DW_IC_RXFLR);
-
-		while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) {
-			if (msgs[dev->msg_write_idx].flags & I2C_M_RD) {
-				writel(0x100, dev->base + DW_IC_DATA_CMD);
-				rx_limit--;
-			} else
-				writel(*buf++, dev->base + DW_IC_DATA_CMD);
-			tx_limit--; buf_len--;
-		}
-
-		dev->tx_buf = buf;
-		dev->tx_buf_len = buf_len;
-
-		if (buf_len > 0) {
-			/* more bytes to be written */
-			dev->status |= STATUS_WRITE_IN_PROGRESS;
-			break;
-		} else
-			dev->status &= ~STATUS_WRITE_IN_PROGRESS;
-	}
-
-	/*
-	 * If i2c_msg index search is completed, we don't need TX_EMPTY
-	 * interrupt any more.
-	 */
-	if (dev->msg_write_idx == dev->msgs_num)
-		intr_mask &= ~DW_IC_INTR_TX_EMPTY;
-
-	if (dev->msg_err)
-		intr_mask = 0;
-
-	writel(intr_mask, dev->base + DW_IC_INTR_MASK);
-}
-
-static void
-i2c_dw_read(struct dw_i2c_dev *dev)
-{
-	struct i2c_msg *msgs = dev->msgs;
-	int rx_valid;
-
-	for (; dev->msg_read_idx < dev->msgs_num; dev->msg_read_idx++) {
-		u32 len;
-		u8 *buf;
-
-		if (!(msgs[dev->msg_read_idx].flags & I2C_M_RD))
-			continue;
-
-		if (!(dev->status & STATUS_READ_IN_PROGRESS)) {
-			len = msgs[dev->msg_read_idx].len;
-			buf = msgs[dev->msg_read_idx].buf;
-		} else {
-			len = dev->rx_buf_len;
-			buf = dev->rx_buf;
-		}
-
-		rx_valid = readl(dev->base + DW_IC_RXFLR);
-
-		for (; len > 0 && rx_valid > 0; len--, rx_valid--)
-			*buf++ = readl(dev->base + DW_IC_DATA_CMD);
-
-		if (len > 0) {
-			dev->status |= STATUS_READ_IN_PROGRESS;
-			dev->rx_buf_len = len;
-			dev->rx_buf = buf;
-			return;
-		} else
-			dev->status &= ~STATUS_READ_IN_PROGRESS;
-	}
-}
-
-static int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
-{
-	unsigned long abort_source = dev->abort_source;
-	int i;
-
-	if (abort_source & DW_IC_TX_ABRT_NOACK) {
-		for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
-			dev_dbg(dev->dev,
-				"%s: %s\n", __func__, abort_sources[i]);
-		return -EREMOTEIO;
-	}
-
-	for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
-		dev_err(dev->dev, "%s: %s\n", __func__, abort_sources[i]);
-
-	if (abort_source & DW_IC_TX_ARB_LOST)
-		return -EAGAIN;
-	else if (abort_source & DW_IC_TX_ABRT_GCALL_READ)
-		return -EINVAL; /* wrong msgs[] data */
-	else
-		return -EIO;
-}
-
-/*
- * Prepare controller for a transaction and call i2c_dw_xfer_msg
- */
-static int
-i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
-{
-	struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
-	int ret;
-
-	dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num);
-
-	mutex_lock(&dev->lock);
-
-	INIT_COMPLETION(dev->cmd_complete);
-	dev->msgs = msgs;
-	dev->msgs_num = num;
-	dev->cmd_err = 0;
-	dev->msg_write_idx = 0;
-	dev->msg_read_idx = 0;
-	dev->msg_err = 0;
-	dev->status = STATUS_IDLE;
-	dev->abort_source = 0;
-
-	ret = i2c_dw_wait_bus_not_busy(dev);
-	if (ret < 0)
-		goto done;
-
-	/* start the transfers */
-	i2c_dw_xfer_init(dev);
-
-	/* wait for tx to complete */
-	ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, HZ);
-	if (ret == 0) {
-		dev_err(dev->dev, "controller timed out\n");
-		i2c_dw_init(dev);
-		ret = -ETIMEDOUT;
-		goto done;
-	} else if (ret < 0)
-		goto done;
-
-	if (dev->msg_err) {
-		ret = dev->msg_err;
-		goto done;
-	}
-
-	/* no error */
-	if (likely(!dev->cmd_err)) {
-		/* Disable the adapter */
-		writel(0, dev->base + DW_IC_ENABLE);
-		ret = num;
-		goto done;
-	}
-
-	/* We have an error */
-	if (dev->cmd_err == DW_IC_ERR_TX_ABRT) {
-		ret = i2c_dw_handle_tx_abort(dev);
-		goto done;
-	}
-	ret = -EIO;
-
-done:
-	mutex_unlock(&dev->lock);
-
-	return ret;
-}
-
-static u32 i2c_dw_func(struct i2c_adapter *adap)
-{
-	return	I2C_FUNC_I2C |
-		I2C_FUNC_10BIT_ADDR |
-		I2C_FUNC_SMBUS_BYTE |
-		I2C_FUNC_SMBUS_BYTE_DATA |
-		I2C_FUNC_SMBUS_WORD_DATA |
-		I2C_FUNC_SMBUS_I2C_BLOCK;
-}
-
-static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
-{
-	u32 stat;
-
-	/*
-	 * The IC_INTR_STAT register just indicates "enabled" interrupts.
-	 * Ths unmasked raw version of interrupt status bits are available
-	 * in the IC_RAW_INTR_STAT register.
-	 *
-	 * That is,
-	 *   stat = readl(IC_INTR_STAT);
-	 * equals to,
-	 *   stat = readl(IC_RAW_INTR_STAT) & readl(IC_INTR_MASK);
-	 *
-	 * The raw version might be useful for debugging purposes.
-	 */
-	stat = readl(dev->base + DW_IC_INTR_STAT);
-
-	/*
-	 * Do not use the IC_CLR_INTR register to clear interrupts, or
-	 * you'll miss some interrupts, triggered during the period from
-	 * readl(IC_INTR_STAT) to readl(IC_CLR_INTR).
-	 *
-	 * Instead, use the separately-prepared IC_CLR_* registers.
-	 */
-	if (stat & DW_IC_INTR_RX_UNDER)
-		readl(dev->base + DW_IC_CLR_RX_UNDER);
-	if (stat & DW_IC_INTR_RX_OVER)
-		readl(dev->base + DW_IC_CLR_RX_OVER);
-	if (stat & DW_IC_INTR_TX_OVER)
-		readl(dev->base + DW_IC_CLR_TX_OVER);
-	if (stat & DW_IC_INTR_RD_REQ)
-		readl(dev->base + DW_IC_CLR_RD_REQ);
-	if (stat & DW_IC_INTR_TX_ABRT) {
-		/*
-		 * The IC_TX_ABRT_SOURCE register is cleared whenever
-		 * the IC_CLR_TX_ABRT is read.  Preserve it beforehand.
-		 */
-		dev->abort_source = readl(dev->base + DW_IC_TX_ABRT_SOURCE);
-		readl(dev->base + DW_IC_CLR_TX_ABRT);
-	}
-	if (stat & DW_IC_INTR_RX_DONE)
-		readl(dev->base + DW_IC_CLR_RX_DONE);
-	if (stat & DW_IC_INTR_ACTIVITY)
-		readl(dev->base + DW_IC_CLR_ACTIVITY);
-	if (stat & DW_IC_INTR_STOP_DET)
-		readl(dev->base + DW_IC_CLR_STOP_DET);
-	if (stat & DW_IC_INTR_START_DET)
-		readl(dev->base + DW_IC_CLR_START_DET);
-	if (stat & DW_IC_INTR_GEN_CALL)
-		readl(dev->base + DW_IC_CLR_GEN_CALL);
-
-	return stat;
-}
-
-/*
- * Interrupt service routine. This gets called whenever an I2C interrupt
- * occurs.
- */
-static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
-{
-	struct dw_i2c_dev *dev = dev_id;
-	u32 stat;
-
-	stat = i2c_dw_read_clear_intrbits(dev);
-	dev_dbg(dev->dev, "%s: stat=0x%x\n", __func__, stat);
-
-	if (stat & DW_IC_INTR_TX_ABRT) {
-		dev->cmd_err |= DW_IC_ERR_TX_ABRT;
-		dev->status = STATUS_IDLE;
-
-		/*
-		 * Anytime TX_ABRT is set, the contents of the tx/rx
-		 * buffers are flushed.  Make sure to skip them.
-		 */
-		writel(0, dev->base + DW_IC_INTR_MASK);
-		goto tx_aborted;
-	}
-
-	if (stat & DW_IC_INTR_RX_FULL)
-		i2c_dw_read(dev);
-
-	if (stat & DW_IC_INTR_TX_EMPTY)
-		i2c_dw_xfer_msg(dev);
-
-	/*
-	 * No need to modify or disable the interrupt mask here.
-	 * i2c_dw_xfer_msg() will take care of it according to
-	 * the current transmit status.
-	 */
-
-tx_aborted:
-	if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err)
-		complete(&dev->cmd_complete);
-
-	return IRQ_HANDLED;
-}
-
-static struct i2c_algorithm i2c_dw_algo = {
-	.master_xfer	= i2c_dw_xfer,
-	.functionality	= i2c_dw_func,
-};
-
-static int __devinit dw_i2c_probe(struct platform_device *pdev)
-{
-	struct dw_i2c_dev *dev;
-	struct i2c_adapter *adap;
-	struct resource *mem, *ioarea;
-	int irq, r;
-
-	/* NOTE: driver uses the static register mapping */
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!mem) {
-		dev_err(&pdev->dev, "no mem resource?\n");
-		return -EINVAL;
-	}
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		dev_err(&pdev->dev, "no irq resource?\n");
-		return irq; /* -ENXIO */
-	}
-
-	ioarea = request_mem_region(mem->start, resource_size(mem),
-			pdev->name);
-	if (!ioarea) {
-		dev_err(&pdev->dev, "I2C region already claimed\n");
-		return -EBUSY;
-	}
-
-	dev = kzalloc(sizeof(struct dw_i2c_dev), GFP_KERNEL);
-	if (!dev) {
-		r = -ENOMEM;
-		goto err_release_region;
-	}
-
-	init_completion(&dev->cmd_complete);
-	mutex_init(&dev->lock);
-	dev->dev = get_device(&pdev->dev);
-	dev->irq = irq;
-	platform_set_drvdata(pdev, dev);
-
-	dev->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(dev->clk)) {
-		r = -ENODEV;
-		goto err_free_mem;
-	}
-	clk_enable(dev->clk);
-
-	dev->base = ioremap(mem->start, resource_size(mem));
-	if (dev->base == NULL) {
-		dev_err(&pdev->dev, "failure mapping io resources\n");
-		r = -EBUSY;
-		goto err_unuse_clocks;
-	}
-	{
-		u32 param1 = readl(dev->base + DW_IC_COMP_PARAM_1);
-
-		dev->tx_fifo_depth = ((param1 >> 16) & 0xff) + 1;
-		dev->rx_fifo_depth = ((param1 >> 8)  & 0xff) + 1;
-	}
-	i2c_dw_init(dev);
-
-	writel(0, dev->base + DW_IC_INTR_MASK); /* disable IRQ */
-	r = request_irq(dev->irq, i2c_dw_isr, IRQF_DISABLED, pdev->name, dev);
-	if (r) {
-		dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
-		goto err_iounmap;
-	}
-
-	adap = &dev->adapter;
-	i2c_set_adapdata(adap, dev);
-	adap->owner = THIS_MODULE;
-	adap->class = I2C_CLASS_HWMON;
-	strlcpy(adap->name, "Synopsys DesignWare I2C adapter",
-			sizeof(adap->name));
-	adap->algo = &i2c_dw_algo;
-	adap->dev.parent = &pdev->dev;
-
-	adap->nr = pdev->id;
-	r = i2c_add_numbered_adapter(adap);
-	if (r) {
-		dev_err(&pdev->dev, "failure adding adapter\n");
-		goto err_free_irq;
-	}
-
-	return 0;
-
-err_free_irq:
-	free_irq(dev->irq, dev);
-err_iounmap:
-	iounmap(dev->base);
-err_unuse_clocks:
-	clk_disable(dev->clk);
-	clk_put(dev->clk);
-	dev->clk = NULL;
-err_free_mem:
-	platform_set_drvdata(pdev, NULL);
-	put_device(&pdev->dev);
-	kfree(dev);
-err_release_region:
-	release_mem_region(mem->start, resource_size(mem));
-
-	return r;
-}
-
-static int __devexit dw_i2c_remove(struct platform_device *pdev)
-{
-	struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
-	struct resource *mem;
-
-	platform_set_drvdata(pdev, NULL);
-	i2c_del_adapter(&dev->adapter);
-	put_device(&pdev->dev);
-
-	clk_disable(dev->clk);
-	clk_put(dev->clk);
-	dev->clk = NULL;
-
-	writel(0, dev->base + DW_IC_ENABLE);
-	free_irq(dev->irq, dev);
-	kfree(dev);
-
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(mem->start, resource_size(mem));
-	return 0;
-}
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:i2c_designware");
-
-static struct platform_driver dw_i2c_driver = {
-	.remove		= __devexit_p(dw_i2c_remove),
-	.driver		= {
-		.name	= "i2c_designware",
-		.owner	= THIS_MODULE,
-	},
-};
-
-static int __init dw_i2c_init_driver(void)
-{
-	return platform_driver_probe(&dw_i2c_driver, dw_i2c_probe);
-}
-module_init(dw_i2c_init_driver);
-
-static void __exit dw_i2c_exit_driver(void)
-{
-	platform_driver_unregister(&dw_i2c_driver);
-}
-module_exit(dw_i2c_exit_driver);
-
-MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
-MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter");
-MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-eg20t.c b/drivers/i2c/busses/i2c-eg20t.c
index ce1a32b..8cebef4 100644
--- a/drivers/i2c/busses/i2c-eg20t.c
+++ b/drivers/i2c/busses/i2c-eg20t.c
@@ -64,6 +64,7 @@
 #define TEN_BIT_ADDR_DEFAULT	0xF000
 #define TEN_BIT_ADDR_MASK	0xF0
 #define PCH_START		0x0020
+#define PCH_RESTART		0x0004
 #define PCH_ESR_START		0x0001
 #define PCH_BUFF_START		0x1
 #define PCH_REPSTART		0x0004
@@ -273,23 +274,24 @@ static s32 pch_i2c_wait_for_bus_idle(struct i2c_algo_pch_data *adap,
 				     s32 timeout)
 {
 	void __iomem *p = adap->pch_base_address;
+	ktime_t ns_val;
+
+	if ((ioread32(p + PCH_I2CSR) & I2CMBB_BIT) == 0)
+		return 0;
 
 	/* MAX timeout value is timeout*1000*1000nsec */
-	ktime_t ns_val = ktime_add_ns(ktime_get(), timeout*1000*1000);
+	ns_val = ktime_add_ns(ktime_get(), timeout*1000*1000);
 	do {
-		if ((ioread32(p + PCH_I2CSR) & I2CMBB_BIT) == 0)
-			break;
 		msleep(20);
+		if ((ioread32(p + PCH_I2CSR) & I2CMBB_BIT) == 0)
+			return 0;
 	} while (ktime_lt(ktime_get(), ns_val));
 
 	pch_dbg(adap, "I2CSR = %x\n", ioread32(p + PCH_I2CSR));
+	pch_err(adap, "%s: Timeout Error.return%d\n", __func__, -ETIME);
+	pch_i2c_init(adap);
 
-	if (timeout == 0) {
-		pch_err(adap, "%s: Timeout Error.return%d\n", __func__, -ETIME);
-		return -ETIME;
-	}
-
-	return 0;
+	return -ETIME;
 }
 
 /**
@@ -311,21 +313,19 @@ static void pch_i2c_start(struct i2c_algo_pch_data *adap)
  */
 static s32 pch_i2c_wait_for_xfer_complete(struct i2c_algo_pch_data *adap)
 {
-	s32 ret;
+	long ret;
 	ret = wait_event_timeout(pch_event,
 			(adap->pch_event_flag != 0), msecs_to_jiffies(50));
-	if (ret < 0) {
-		pch_err(adap, "timeout: %x\n", adap->pch_event_flag);
-		return ret;
-	}
 
 	if (ret == 0) {
 		pch_err(adap, "timeout: %x\n", adap->pch_event_flag);
+		adap->pch_event_flag = 0;
 		return -ETIMEDOUT;
 	}
 
 	if (adap->pch_event_flag & I2C_ERROR_MASK) {
 		pch_err(adap, "error bits set: %x\n", adap->pch_event_flag);
+		adap->pch_event_flag = 0;
 		return -EIO;
 	}
 
@@ -394,6 +394,7 @@ static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap,
 	u32 addr_2_msb;
 	u32 addr_8_lsb;
 	s32 wrcount;
+	s32 rtn;
 	void __iomem *p = adap->pch_base_address;
 
 	length = msgs->len;
@@ -412,15 +413,29 @@ static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap,
 	}
 
 	if (msgs->flags & I2C_M_TEN) {
-		addr_2_msb = ((addr & I2C_MSB_2B_MSK) >> 7);
+		addr_2_msb = ((addr & I2C_MSB_2B_MSK) >> 7) & 0x06;
 		iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR);
 		if (first)
 			pch_i2c_start(adap);
-		if (pch_i2c_wait_for_xfer_complete(adap) == 0 &&
-		    pch_i2c_getack(adap) == 0) {
+
+		rtn = pch_i2c_wait_for_xfer_complete(adap);
+		if (rtn == 0) {
+			if (pch_i2c_getack(adap)) {
+				pch_dbg(adap, "Receive NACK for slave address"
+					"setting\n");
+				return -EIO;
+			}
 			addr_8_lsb = (addr & I2C_ADDR_MSK);
 			iowrite32(addr_8_lsb, p + PCH_I2CDR);
-		} else {
+		} else if (rtn == -EIO) { /* Arbitration Lost */
+			pch_err(adap, "Lost Arbitration\n");
+			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+				   I2CMAL_BIT);
+			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+				   I2CMIF_BIT);
+			pch_i2c_init(adap);
+			return -EAGAIN;
+		} else { /* wait-event timeout */
 			pch_i2c_stop(adap);
 			return -ETIME;
 		}
@@ -431,30 +446,51 @@ static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap,
 			pch_i2c_start(adap);
 	}
 
-	if ((pch_i2c_wait_for_xfer_complete(adap) == 0) &&
-	    (pch_i2c_getack(adap) == 0)) {
-		for (wrcount = 0; wrcount < length; ++wrcount) {
-			/* write buffer value to I2C data register */
-			iowrite32(buf[wrcount], p + PCH_I2CDR);
-			pch_dbg(adap, "writing %x to Data register\n",
-				buf[wrcount]);
+	rtn = pch_i2c_wait_for_xfer_complete(adap);
+	if (rtn == 0) {
+		if (pch_i2c_getack(adap)) {
+			pch_dbg(adap, "Receive NACK for slave address"
+				"setting\n");
+			return -EIO;
+		}
+	} else if (rtn == -EIO) { /* Arbitration Lost */
+		pch_err(adap, "Lost Arbitration\n");
+		pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMAL_BIT);
+		pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMIF_BIT);
+		pch_i2c_init(adap);
+		return -EAGAIN;
+	} else { /* wait-event timeout */
+		pch_i2c_stop(adap);
+		return -ETIME;
+	}
 
-			if (pch_i2c_wait_for_xfer_complete(adap) != 0)
-				return -ETIME;
+	for (wrcount = 0; wrcount < length; ++wrcount) {
+		/* write buffer value to I2C data register */
+		iowrite32(buf[wrcount], p + PCH_I2CDR);
+		pch_dbg(adap, "writing %x to Data register\n", buf[wrcount]);
 
-			if (pch_i2c_getack(adap))
+		rtn = pch_i2c_wait_for_xfer_complete(adap);
+		if (rtn == 0) {
+			if (pch_i2c_getack(adap)) {
+				pch_dbg(adap, "Receive NACK for slave address"
+					"setting\n");
 				return -EIO;
+			}
+			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+				   I2CMCF_BIT);
+			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+				   I2CMIF_BIT);
+		} else { /* wait-event timeout */
+			pch_i2c_stop(adap);
+			return -ETIME;
 		}
+	}
 
-		/* check if this is the last message */
-		if (last)
-			pch_i2c_stop(adap);
-		else
-			pch_i2c_repstart(adap);
-	} else {
+	/* check if this is the last message */
+	if (last)
 		pch_i2c_stop(adap);
-		return -EIO;
-	}
+	else
+		pch_i2c_repstart(adap);
 
 	pch_dbg(adap, "return=%d\n", wrcount);
 
@@ -484,6 +520,19 @@ static void pch_i2c_sendnack(struct i2c_algo_pch_data *adap)
 }
 
 /**
+ * pch_i2c_restart() - Generate I2C restart condition in normal mode.
+ * @adap:	Pointer to struct i2c_algo_pch_data.
+ *
+ * Generate I2C restart condition in normal mode by setting I2CCTL.I2CRSTA.
+ */
+static void pch_i2c_restart(struct i2c_algo_pch_data *adap)
+{
+	void __iomem *p = adap->pch_base_address;
+	pch_dbg(adap, "I2CCTL = %x\n", ioread32(p + PCH_I2CCTL));
+	pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_RESTART);
+}
+
+/**
  * pch_i2c_readbytes() - read data  from I2C bus in normal mode.
  * @i2c_adap:	Pointer to the struct i2c_adapter.
  * @msgs:	Pointer to i2c_msg structure.
@@ -500,7 +549,9 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
 	u32 length;
 	u32 addr;
 	u32 addr_2_msb;
+	u32 addr_8_lsb;
 	void __iomem *p = adap->pch_base_address;
+	s32 rtn;
 
 	length = msgs->len;
 	buf = msgs->buf;
@@ -515,9 +566,55 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
 	}
 
 	if (msgs->flags & I2C_M_TEN) {
-		addr_2_msb = (((addr & I2C_MSB_2B_MSK) >> 7) | (I2C_RD));
+		addr_2_msb = ((addr & I2C_MSB_2B_MSK) >> 7);
 		iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR);
+		if (first)
+			pch_i2c_start(adap);
 
+		rtn = pch_i2c_wait_for_xfer_complete(adap);
+		if (rtn == 0) {
+			if (pch_i2c_getack(adap)) {
+				pch_dbg(adap, "Receive NACK for slave address"
+					"setting\n");
+				return -EIO;
+			}
+			addr_8_lsb = (addr & I2C_ADDR_MSK);
+			iowrite32(addr_8_lsb, p + PCH_I2CDR);
+		} else if (rtn == -EIO) { /* Arbitration Lost */
+			pch_err(adap, "Lost Arbitration\n");
+			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+				   I2CMAL_BIT);
+			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+				   I2CMIF_BIT);
+			pch_i2c_init(adap);
+			return -EAGAIN;
+		} else { /* wait-event timeout */
+			pch_i2c_stop(adap);
+			return -ETIME;
+		}
+		pch_i2c_restart(adap);
+		rtn = pch_i2c_wait_for_xfer_complete(adap);
+		if (rtn == 0) {
+			if (pch_i2c_getack(adap)) {
+				pch_dbg(adap, "Receive NACK for slave address"
+					"setting\n");
+				return -EIO;
+			}
+			addr_2_msb |= I2C_RD;
+			iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK,
+				  p + PCH_I2CDR);
+		} else if (rtn == -EIO) { /* Arbitration Lost */
+			pch_err(adap, "Lost Arbitration\n");
+			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+				   I2CMAL_BIT);
+			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
+				   I2CMIF_BIT);
+			pch_i2c_init(adap);
+			return -EAGAIN;
+		} else { /* wait-event timeout */
+			pch_i2c_stop(adap);
+			return -ETIME;
+		}
 	} else {
 		/* 7 address bits + R/W bit */
 		addr = (((addr) << 1) | (I2C_RD));
@@ -528,56 +625,81 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
 	if (first)
 		pch_i2c_start(adap);
 
-	if ((pch_i2c_wait_for_xfer_complete(adap) == 0) &&
-	    (pch_i2c_getack(adap) == 0)) {
-		pch_dbg(adap, "return %d\n", 0);
+	rtn = pch_i2c_wait_for_xfer_complete(adap);
+	if (rtn == 0) {
+		if (pch_i2c_getack(adap)) {
+			pch_dbg(adap, "Receive NACK for slave address"
+				"setting\n");
+			return -EIO;
+		}
+	} else if (rtn == -EIO) { /* Arbitration Lost */
+		pch_err(adap, "Lost Arbitration\n");
+		pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMAL_BIT);
+		pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMIF_BIT);
+		pch_i2c_init(adap);
+		return -EAGAIN;
+	} else { /* wait-event timeout */
+		pch_i2c_stop(adap);
+		return -ETIME;
+	}
 
-		if (length == 0) {
-			pch_i2c_stop(adap);
-			ioread32(p + PCH_I2CDR); /* Dummy read needs */
+	if (length == 0) {
+		pch_i2c_stop(adap);
+		ioread32(p + PCH_I2CDR); /* Dummy read needs */
 
-			count = length;
-		} else {
-			int read_index;
-			int loop;
-			pch_i2c_sendack(adap);
+		count = length;
+	} else {
+		int read_index;
+		int loop;
+		pch_i2c_sendack(adap);
 
-			/* Dummy read */
-			for (loop = 1, read_index = 0; loop < length; loop++) {
-				buf[read_index] = ioread32(p + PCH_I2CDR);
+		/* Dummy read */
+		for (loop = 1, read_index = 0; loop < length; loop++) {
+			buf[read_index] = ioread32(p + PCH_I2CDR);
 
-				if (loop != 1)
-					read_index++;
+			if (loop != 1)
+				read_index++;
 
-				if (pch_i2c_wait_for_xfer_complete(adap) != 0) {
-					pch_i2c_stop(adap);
-					return -ETIME;
+			rtn = pch_i2c_wait_for_xfer_complete(adap);
+			if (rtn == 0) {
+				if (pch_i2c_getack(adap)) {
+					pch_dbg(adap, "Receive NACK for slave"
+						"address setting\n");
+					return -EIO;
 				}
-			}	/* end for */
+			} else { /* wait-event timeout */
+				pch_i2c_stop(adap);
+				return -ETIME;
+			}
 
-			pch_i2c_sendnack(adap);
+		}	/* end for */
 
-			buf[read_index] = ioread32(p + PCH_I2CDR);
+		pch_i2c_sendnack(adap);
 
-			if (length != 1)
-				read_index++;
+		buf[read_index] = ioread32(p + PCH_I2CDR); /* Read final - 1 */
 
-			if (pch_i2c_wait_for_xfer_complete(adap) == 0) {
-				if (last)
-					pch_i2c_stop(adap);
-				else
-					pch_i2c_repstart(adap);
+		if (length != 1)
+			read_index++;
 
-				buf[read_index++] = ioread32(p + PCH_I2CDR);
-				count = read_index;
-			} else {
-				count = -ETIME;
+		rtn = pch_i2c_wait_for_xfer_complete(adap);
+		if (rtn == 0) {
+			if (pch_i2c_getack(adap)) {
+				pch_dbg(adap, "Receive NACK for slave"
+					"address setting\n");
+				return -EIO;
 			}
-
+		} else { /* wait-event timeout */
+			pch_i2c_stop(adap);
+			return -ETIME;
 		}
-	} else {
-		count = -ETIME;
-		pch_i2c_stop(adap);
+
+		if (last)
+			pch_i2c_stop(adap);
+		else
+			pch_i2c_repstart(adap);
+
+		buf[read_index++] = ioread32(p + PCH_I2CDR); /* Read Final */
+		count = read_index;
 	}
 
 	return count;
diff --git a/drivers/i2c/busses/i2c-highlander.c b/drivers/i2c/busses/i2c-highlander.c
index 3876a24..63bb1cc 100644
--- a/drivers/i2c/busses/i2c-highlander.c
+++ b/drivers/i2c/busses/i2c-highlander.c
@@ -387,7 +387,7 @@ static int __devinit highlander_i2c_probe(struct platform_device *pdev)
 		dev->irq = 0;
 
 	if (dev->irq) {
-		ret = request_irq(dev->irq, highlander_i2c_irq, IRQF_DISABLED,
+		ret = request_irq(dev->irq, highlander_i2c_irq, 0,
 				  pdev->name, dev);
 		if (unlikely(ret))
 			goto err_unmap;
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 4c2a62b..58832e5 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -48,6 +48,9 @@
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_i2c.h>
 
 #include <mach/irqs.h>
 #include <mach/hardware.h>
@@ -125,6 +128,11 @@ struct imx_i2c_struct {
 	unsigned int		ifdr; /* IMX_I2C_IFDR */
 };
 
+static const struct of_device_id i2c_imx_dt_ids[] = {
+	{ .compatible = "fsl,imx1-i2c", },
+	{ /* sentinel */ }
+};
+
 /** Functions for IMX I2C adapter driver ***************************************
 *******************************************************************************/
 
@@ -466,10 +474,10 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
 {
 	struct imx_i2c_struct *i2c_imx;
 	struct resource *res;
-	struct imxi2c_platform_data *pdata;
+	struct imxi2c_platform_data *pdata = pdev->dev.platform_data;
 	void __iomem *base;
 	resource_size_t res_size;
-	int irq;
+	int irq, bitrate;
 	int ret;
 
 	dev_dbg(&pdev->dev, "<%s>\n", __func__);
@@ -485,19 +493,11 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
 		return -ENOENT;
 	}
 
-	pdata = pdev->dev.platform_data;
-
-	if (pdata && pdata->init) {
-		ret = pdata->init(&pdev->dev);
-		if (ret)
-			return ret;
-	}
-
 	res_size = resource_size(res);
 
 	if (!request_mem_region(res->start, res_size, DRIVER_NAME)) {
-		ret = -EBUSY;
-		goto fail0;
+		dev_err(&pdev->dev, "request_mem_region failed\n");
+		return -EBUSY;
 	}
 
 	base = ioremap(res->start, res_size);
@@ -520,6 +520,7 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
 	i2c_imx->adapter.algo		= &i2c_imx_algo;
 	i2c_imx->adapter.dev.parent	= &pdev->dev;
 	i2c_imx->adapter.nr 		= pdev->id;
+	i2c_imx->adapter.dev.of_node	= pdev->dev.of_node;
 	i2c_imx->irq			= irq;
 	i2c_imx->base			= base;
 	i2c_imx->res			= res;
@@ -546,10 +547,12 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
 	i2c_set_adapdata(&i2c_imx->adapter, i2c_imx);
 
 	/* Set up clock divider */
-	if (pdata && pdata->bitrate)
-		i2c_imx_set_clk(i2c_imx, pdata->bitrate);
-	else
-		i2c_imx_set_clk(i2c_imx, IMX_I2C_BIT_RATE);
+	bitrate = IMX_I2C_BIT_RATE;
+	ret = of_property_read_u32(pdev->dev.of_node,
+				   "clock-frequency", &bitrate);
+	if (ret < 0 && pdata && pdata->bitrate)
+		bitrate = pdata->bitrate;
+	i2c_imx_set_clk(i2c_imx, bitrate);
 
 	/* Set up chip registers to defaults */
 	writeb(0, i2c_imx->base + IMX_I2C_I2CR);
@@ -562,6 +565,8 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
 		goto fail5;
 	}
 
+	of_i2c_register_devices(&i2c_imx->adapter);
+
 	/* Set up platform driver data */
 	platform_set_drvdata(pdev, i2c_imx);
 
@@ -586,16 +591,12 @@ fail2:
 	iounmap(base);
 fail1:
 	release_mem_region(res->start, resource_size(res));
-fail0:
-	if (pdata && pdata->exit)
-		pdata->exit(&pdev->dev);
 	return ret; /* Return error number */
 }
 
 static int __exit i2c_imx_remove(struct platform_device *pdev)
 {
 	struct imx_i2c_struct *i2c_imx = platform_get_drvdata(pdev);
-	struct imxi2c_platform_data *pdata = pdev->dev.platform_data;
 
 	/* remove adapter */
 	dev_dbg(&i2c_imx->adapter.dev, "adapter removed\n");
@@ -611,10 +612,6 @@ static int __exit i2c_imx_remove(struct platform_device *pdev)
 	writeb(0, i2c_imx->base + IMX_I2C_I2CR);
 	writeb(0, i2c_imx->base + IMX_I2C_I2SR);
 
-	/* Shut down hardware */
-	if (pdata && pdata->exit)
-		pdata->exit(&pdev->dev);
-
 	clk_put(i2c_imx->clk);
 
 	iounmap(i2c_imx->base);
@@ -628,6 +625,7 @@ static struct platform_driver i2c_imx_driver = {
 	.driver	= {
 		.name	= DRIVER_NAME,
 		.owner	= THIS_MODULE,
+		.of_match_table = i2c_imx_dt_ids,
 	}
 };
 
diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c
index b228e09..5267ab9 100644
--- a/drivers/i2c/busses/i2c-nomadik.c
+++ b/drivers/i2c/busses/i2c-nomadik.c
@@ -63,11 +63,11 @@
 /* Master controller (MCR) register */
 #define I2C_MCR_OP		(0x1 << 0)	/* Operation */
 #define I2C_MCR_A7		(0x7f << 1)	/* 7-bit address */
-#define I2C_MCR_EA10		(0x7 << 8) 	/* 10-bit Extended address */
+#define I2C_MCR_EA10		(0x7 << 8)	/* 10-bit Extended address */
 #define I2C_MCR_SB		(0x1 << 11)	/* Extended address */
 #define I2C_MCR_AM		(0x3 << 12)	/* Address type */
-#define I2C_MCR_STOP		(0x1 << 14) 	/* Stop condition */
-#define I2C_MCR_LENGTH		(0x7ff << 15) 	/* Transaction length */
+#define I2C_MCR_STOP		(0x1 << 14)	/* Stop condition */
+#define I2C_MCR_LENGTH		(0x7ff << 15)	/* Transaction length */
 
 /* Status register (SR) */
 #define I2C_SR_OP		(0x3 << 0)	/* Operation */
@@ -77,7 +77,7 @@
 #define I2C_SR_LENGTH		(0x7ff << 9)	/* Transfer length */
 
 /* Interrupt mask set/clear (IMSCR) bits */
-#define I2C_IT_TXFE 		(0x1 << 0)
+#define I2C_IT_TXFE		(0x1 << 0)
 #define I2C_IT_TXFNE		(0x1 << 1)
 #define I2C_IT_TXFF		(0x1 << 2)
 #define I2C_IT_TXFOVR		(0x1 << 3)
@@ -135,31 +135,31 @@ struct i2c_nmk_client {
 };
 
 /**
- * struct nmk_i2c_dev - private data structure of the controller
- * @pdev: parent platform device
- * @adap: corresponding I2C adapter
- * @irq: interrupt line for the controller
- * @virtbase: virtual io memory area
- * @clk: hardware i2c block clock
- * @cfg: machine provided controller configuration
- * @cli: holder of client specific data
- * @stop: stop condition
- * @xfer_complete: acknowledge completion for a I2C message
- * @result: controller propogated result
- * @regulator: pointer to i2c regulator
- * @busy: Busy doing transfer
+ * struct nmk_i2c_dev - private data structure of the controller.
+ * @pdev: parent platform device.
+ * @adap: corresponding I2C adapter.
+ * @irq: interrupt line for the controller.
+ * @virtbase: virtual io memory area.
+ * @clk: hardware i2c block clock.
+ * @cfg: machine provided controller configuration.
+ * @cli: holder of client specific data.
+ * @stop: stop condition.
+ * @xfer_complete: acknowledge completion for a I2C message.
+ * @result: controller propogated result.
+ * @regulator: pointer to i2c regulator.
+ * @busy: Busy doing transfer.
  */
 struct nmk_i2c_dev {
 	struct platform_device		*pdev;
-	struct i2c_adapter 		adap;
-	int 				irq;
+	struct i2c_adapter		adap;
+	int				irq;
 	void __iomem			*virtbase;
 	struct clk			*clk;
 	struct nmk_i2c_controller	cfg;
 	struct i2c_nmk_client		cli;
-	int 				stop;
+	int				stop;
 	struct completion		xfer_complete;
-	int 				result;
+	int				result;
 	struct regulator		*regulator;
 	bool				busy;
 };
@@ -217,8 +217,9 @@ static int flush_i2c_fifo(struct nmk_i2c_dev *dev)
 		}
 	}
 
-	dev_err(&dev->pdev->dev, "flushing operation timed out "
-		"giving up after %d attempts", LOOP_ATTEMPTS);
+	dev_err(&dev->pdev->dev,
+		"flushing operation timed out giving up after %d attempts",
+		LOOP_ATTEMPTS);
 
 	return -ETIMEDOUT;
 }
@@ -270,7 +271,7 @@ exit:
 }
 
 /* enable peripheral, master mode operation */
-#define DEFAULT_I2C_REG_CR 	((1 << 1) | I2C_CR_PE)
+#define DEFAULT_I2C_REG_CR	((1 << 1) | I2C_CR_PE)
 
 /**
  * load_i2c_mcr_reg() - load the MCR register
@@ -363,8 +364,8 @@ static void setup_i2c_controller(struct nmk_i2c_dev *dev)
 	 * and high speed (up to 3.4 Mb/s)
 	 */
 	if (dev->cfg.sm > I2C_FREQ_MODE_FAST) {
-		dev_err(&dev->pdev->dev, "do not support this mode "
-			"defaulting to std. mode\n");
+		dev_err(&dev->pdev->dev,
+			"do not support this mode defaulting to std. mode\n");
 		brcr2 = i2c_clk/(100000 * 2) & 0xffff;
 		writel((brcr1 | brcr2), dev->virtbase + I2C_BRCR);
 		writel(I2C_FREQ_MODE_STANDARD << 4,
@@ -423,7 +424,7 @@ static int read_i2c(struct nmk_i2c_dev *dev)
 
 	if (timeout < 0) {
 		dev_err(&dev->pdev->dev,
-			"wait_for_completion_timeout"
+			"wait_for_completion_timeout "
 			"returned %d waiting for event\n", timeout);
 		status = timeout;
 	}
@@ -556,8 +557,8 @@ static int nmk_i2c_xfer_one(struct nmk_i2c_dev *dev, u16 flags)
 		if (((i2c_sr >> 2) & 0x3) == 0x3) {
 			/* get the abort cause */
 			cause =	(i2c_sr >> 4) & 0x7;
-			dev_err(&dev->pdev->dev, "%s\n", cause
-				>= ARRAY_SIZE(abort_causes) ?
+			dev_err(&dev->pdev->dev, "%s\n",
+				cause >= ARRAY_SIZE(abort_causes) ?
 				"unknown reason" :
 				abort_causes[cause]);
 		}
@@ -582,13 +583,13 @@ static int nmk_i2c_xfer_one(struct nmk_i2c_dev *dev, u16 flags)
  *
  * NOTE:
  * READ TRANSFER : We impose a restriction of the first message to be the
- * 		index message for any read transaction.
- * 		- a no index is coded as '0',
- * 		- 2byte big endian index is coded as '3'
- * 		!!! msg[0].buf holds the actual index.
- * 		This is compatible with generic messages of smbus emulator
- * 		that send a one byte index.
- * 		eg. a I2C transation to read 2 bytes from index 0
+ *		index message for any read transaction.
+ *		- a no index is coded as '0',
+ *		- 2byte big endian index is coded as '3'
+ *		!!! msg[0].buf holds the actual index.
+ *		This is compatible with generic messages of smbus emulator
+ *		that send a one byte index.
+ *		eg. a I2C transation to read 2 bytes from index 0
  *			idx = 0;
  *			msg[0].addr = client->addr;
  *			msg[0].flags = 0x0;
@@ -644,8 +645,8 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
 
 		for (i = 0; i < num_msgs; i++) {
 			if (unlikely(msgs[i].flags & I2C_M_TEN)) {
-				dev_err(&dev->pdev->dev, "10 bit addressing"
-						"not supported\n");
+				dev_err(&dev->pdev->dev,
+					"10 bit addressing not supported\n");
 
 				status = -EINVAL;
 				goto out;
@@ -789,8 +790,9 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg)
 
 		if (dev->cli.count) {
 			dev->result = -EIO;
-			dev_err(&dev->pdev->dev, "%lu bytes still remain to be"
-					"xfered\n", dev->cli.count);
+			dev_err(&dev->pdev->dev,
+				"%lu bytes still remain to be xfered\n",
+				dev->cli.count);
 			(void) init_hw(dev);
 		}
 		complete(&dev->xfer_complete);
@@ -923,7 +925,7 @@ static int __devinit nmk_i2c_probe(struct platform_device *pdev)
 	}
 
 	if (request_mem_region(res->start, resource_size(res),
-		DRIVER_NAME "I/O region") == 	NULL)	{
+		DRIVER_NAME "I/O region") == NULL) {
 		ret = -EBUSY;
 		goto err_no_region;
 	}
@@ -935,7 +937,7 @@ static int __devinit nmk_i2c_probe(struct platform_device *pdev)
 	}
 
 	dev->irq = platform_get_irq(pdev, 0);
-	ret = request_irq(dev->irq, i2c_irq_handler, IRQF_DISABLED,
+	ret = request_irq(dev->irq, i2c_irq_handler, 0,
 				DRIVER_NAME, dev);
 	if (ret) {
 		dev_err(&pdev->dev, "cannot claim the irq %d\n", dev->irq);
@@ -980,8 +982,9 @@ static int __devinit nmk_i2c_probe(struct platform_device *pdev)
 
 	i2c_set_adapdata(adap, dev);
 
-	dev_info(&pdev->dev, "initialize %s on virtual "
-		"base %p\n", adap->name, dev->virtbase);
+	dev_info(&pdev->dev,
+		 "initialize %s on virtual base %p\n",
+		 adap->name, dev->virtbase);
 
 	ret = i2c_add_numbered_adapter(adap);
 	if (ret) {
diff --git a/drivers/i2c/busses/i2c-nuc900.c b/drivers/i2c/busses/i2c-nuc900.c
index 7243426..835e47b 100644
--- a/drivers/i2c/busses/i2c-nuc900.c
+++ b/drivers/i2c/busses/i2c-nuc900.c
@@ -610,7 +610,7 @@ static int __devinit nuc900_i2c_probe(struct platform_device *pdev)
 		goto err_iomap;
 	}
 
-	ret = request_irq(i2c->irq, nuc900_i2c_irq, IRQF_DISABLED | IRQF_SHARED,
+	ret = request_irq(i2c->irq, nuc900_i2c_irq, IRQF_SHARED,
 			  dev_name(&pdev->dev), i2c);
 
 	if (ret != 0) {
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 2dfb631..a43d002 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -42,12 +42,12 @@
 #include <linux/pm_runtime.h>
 
 /* I2C controller revisions */
-#define OMAP_I2C_REV_2			0x20
+#define OMAP_I2C_OMAP1_REV_2		0x20
 
 /* I2C controller revisions present on specific hardware */
 #define OMAP_I2C_REV_ON_2430		0x36
 #define OMAP_I2C_REV_ON_3430		0x3C
-#define OMAP_I2C_REV_ON_4430		0x40
+#define OMAP_I2C_REV_ON_3530_4430	0x40
 
 /* timeout waiting for the controller to respond */
 #define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
@@ -72,11 +72,12 @@ enum {
 	OMAP_I2C_SCLH_REG,
 	OMAP_I2C_SYSTEST_REG,
 	OMAP_I2C_BUFSTAT_REG,
-	OMAP_I2C_REVNB_LO,
-	OMAP_I2C_REVNB_HI,
-	OMAP_I2C_IRQSTATUS_RAW,
-	OMAP_I2C_IRQENABLE_SET,
-	OMAP_I2C_IRQENABLE_CLR,
+	/* only on OMAP4430 */
+	OMAP_I2C_IP_V2_REVNB_LO,
+	OMAP_I2C_IP_V2_REVNB_HI,
+	OMAP_I2C_IP_V2_IRQSTATUS_RAW,
+	OMAP_I2C_IP_V2_IRQENABLE_SET,
+	OMAP_I2C_IP_V2_IRQENABLE_CLR,
 };
 
 /* I2C Interrupt Enable Register (OMAP_I2C_IE): */
@@ -193,7 +194,6 @@ struct omap_i2c_dev {
 						 */
 	u8			rev;
 	unsigned		b_hw:1;		/* bad h/w fixes */
-	unsigned		idle:1;
 	u16			iestate;	/* Saved interrupt register */
 	u16			pscstate;
 	u16			scllstate;
@@ -204,7 +204,7 @@ struct omap_i2c_dev {
 	u16			errata;
 };
 
-static const u8 reg_map[] = {
+static const u8 reg_map_ip_v1[] = {
 	[OMAP_I2C_REV_REG] = 0x00,
 	[OMAP_I2C_IE_REG] = 0x01,
 	[OMAP_I2C_STAT_REG] = 0x02,
@@ -225,7 +225,7 @@ static const u8 reg_map[] = {
 	[OMAP_I2C_BUFSTAT_REG] = 0x10,
 };
 
-static const u8 omap4_reg_map[] = {
+static const u8 reg_map_ip_v2[] = {
 	[OMAP_I2C_REV_REG] = 0x04,
 	[OMAP_I2C_IE_REG] = 0x2c,
 	[OMAP_I2C_STAT_REG] = 0x28,
@@ -244,11 +244,11 @@ static const u8 omap4_reg_map[] = {
 	[OMAP_I2C_SCLH_REG] = 0xb8,
 	[OMAP_I2C_SYSTEST_REG] = 0xbC,
 	[OMAP_I2C_BUFSTAT_REG] = 0xc0,
-	[OMAP_I2C_REVNB_LO] = 0x00,
-	[OMAP_I2C_REVNB_HI] = 0x04,
-	[OMAP_I2C_IRQSTATUS_RAW] = 0x24,
-	[OMAP_I2C_IRQENABLE_SET] = 0x2c,
-	[OMAP_I2C_IRQENABLE_CLR] = 0x30,
+	[OMAP_I2C_IP_V2_REVNB_LO] = 0x00,
+	[OMAP_I2C_IP_V2_REVNB_HI] = 0x04,
+	[OMAP_I2C_IP_V2_IRQSTATUS_RAW] = 0x24,
+	[OMAP_I2C_IP_V2_IRQENABLE_SET] = 0x2c,
+	[OMAP_I2C_IP_V2_IRQENABLE_CLR] = 0x30,
 };
 
 static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev,
@@ -266,17 +266,11 @@ static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg)
 
 static void omap_i2c_unidle(struct omap_i2c_dev *dev)
 {
-	struct platform_device *pdev;
 	struct omap_i2c_bus_platform_data *pdata;
 
-	WARN_ON(!dev->idle);
+	pdata = dev->dev->platform_data;
 
-	pdev = to_platform_device(dev->dev);
-	pdata = pdev->dev.platform_data;
-
-	pm_runtime_get_sync(&pdev->dev);
-
-	if (cpu_is_omap34xx()) {
+	if (pdata->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) {
 		omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
 		omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, dev->pscstate);
 		omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, dev->scllstate);
@@ -286,7 +280,6 @@ static void omap_i2c_unidle(struct omap_i2c_dev *dev)
 		omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate);
 		omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
 	}
-	dev->idle = 0;
 
 	/*
 	 * Don't write to this register if the IE state is 0 as it can
@@ -298,32 +291,25 @@ static void omap_i2c_unidle(struct omap_i2c_dev *dev)
 
 static void omap_i2c_idle(struct omap_i2c_dev *dev)
 {
-	struct platform_device *pdev;
 	struct omap_i2c_bus_platform_data *pdata;
 	u16 iv;
 
-	WARN_ON(dev->idle);
-
-	pdev = to_platform_device(dev->dev);
-	pdata = pdev->dev.platform_data;
+	pdata = dev->dev->platform_data;
 
 	dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
-	if (dev->rev >= OMAP_I2C_REV_ON_4430)
-		omap_i2c_write_reg(dev, OMAP_I2C_IRQENABLE_CLR, 1);
+	if (pdata->rev == OMAP_I2C_IP_VERSION_2)
+		omap_i2c_write_reg(dev, OMAP_I2C_IP_V2_IRQENABLE_CLR, 1);
 	else
 		omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0);
 
-	if (dev->rev < OMAP_I2C_REV_2) {
+	if (dev->rev < OMAP_I2C_OMAP1_REV_2) {
 		iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */
 	} else {
 		omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, dev->iestate);
 
-		/* Flush posted write before the dev->idle store occurs */
+		/* Flush posted write */
 		omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
 	}
-	dev->idle = 1;
-
-	pm_runtime_put_sync(&pdev->dev);
 }
 
 static int omap_i2c_init(struct omap_i2c_dev *dev)
@@ -334,8 +320,11 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
 	unsigned long timeout;
 	unsigned long internal_clk = 0;
 	struct clk *fclk;
+	struct omap_i2c_bus_platform_data *pdata;
+
+	pdata = dev->dev->platform_data;
 
-	if (dev->rev >= OMAP_I2C_REV_2) {
+	if (dev->rev >= OMAP_I2C_OMAP1_REV_2) {
 		/* Disable I2C controller before soft reset */
 		omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
 			omap_i2c_read_reg(dev, OMAP_I2C_CON_REG) &
@@ -378,12 +367,13 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
 			 * REVISIT: Some wkup sources might not be needed.
 			 */
 			dev->westate = OMAP_I2C_WE_ALL;
-			omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate);
+			omap_i2c_write_reg(dev, OMAP_I2C_WE_REG,
+							dev->westate);
 		}
 	}
 	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
 
-	if (cpu_class_is_omap1()) {
+	if (pdata->flags & OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK) {
 		/*
 		 * The I2C functional clock is the armxor_ck, so there's
 		 * no need to get "armxor_ck" separately.  Now, if OMAP2420
@@ -407,7 +397,7 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
 			psc = fclk_rate / 12000000;
 	}
 
-	if (!(cpu_class_is_omap1() || cpu_is_omap2420())) {
+	if (!(pdata->flags & OMAP_I2C_FLAG_SIMPLE_CLOCK)) {
 
 		/*
 		 * HSI2C controller internal clk rate should be 19.2 Mhz for
@@ -415,7 +405,8 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
 		 * to get longer filter period for better noise suppression.
 		 * The filter is iclk (fclk for HS) period.
 		 */
-		if (dev->speed > 400 || cpu_is_omap2430())
+		if (dev->speed > 400 ||
+			       pdata->flags & OMAP_I2C_FLAG_FORCE_19200_INT_CLK)
 			internal_clk = 19200;
 		else if (dev->speed > 100)
 			internal_clk = 9600;
@@ -484,7 +475,7 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
 
 	dev->errata = 0;
 
-	if (cpu_is_omap2430() || cpu_is_omap34xx())
+	if (pdata->flags & OMAP_I2C_FLAG_APPLY_ERRATA_I207)
 		dev->errata |= I2C_OMAP_ERRATA_I207;
 
 	/* Enable interrupts */
@@ -493,7 +484,7 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
 			OMAP_I2C_IE_AL)  | ((dev->fifo_size) ?
 				(OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0);
 	omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
-	if (cpu_is_omap34xx()) {
+	if (pdata->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) {
 		dev->pscstate = psc;
 		dev->scllstate = scll;
 		dev->sclhstate = sclh;
@@ -642,7 +633,7 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 	int i;
 	int r;
 
-	omap_i2c_unidle(dev);
+	pm_runtime_get_sync(dev->dev);
 
 	r = omap_i2c_wait_for_bb(dev);
 	if (r < 0)
@@ -665,7 +656,7 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 
 	omap_i2c_wait_for_bb(dev);
 out:
-	omap_i2c_idle(dev);
+	pm_runtime_put(dev->dev);
 	return r;
 }
 
@@ -720,12 +711,12 @@ static inline void i2c_omap_errata_i207(struct omap_i2c_dev *dev, u16 stat)
 #ifdef CONFIG_ARCH_OMAP15XX
 
 static irqreturn_t
-omap_i2c_rev1_isr(int this_irq, void *dev_id)
+omap_i2c_omap1_isr(int this_irq, void *dev_id)
 {
 	struct omap_i2c_dev *dev = dev_id;
 	u16 iv, w;
 
-	if (dev->idle)
+	if (pm_runtime_suspended(dev->dev))
 		return IRQ_NONE;
 
 	iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG);
@@ -774,7 +765,7 @@ omap_i2c_rev1_isr(int this_irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 #else
-#define omap_i2c_rev1_isr		NULL
+#define omap_i2c_omap1_isr		NULL
 #endif
 
 /*
@@ -813,8 +804,11 @@ omap_i2c_isr(int this_irq, void *dev_id)
 	u16 bits;
 	u16 stat, w;
 	int err, count = 0;
+	struct omap_i2c_bus_platform_data *pdata;
 
-	if (dev->idle)
+	pdata = dev->dev->platform_data;
+
+	if (pm_runtime_suspended(dev->dev))
 		return IRQ_NONE;
 
 	bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
@@ -881,8 +875,8 @@ complete:
 					 * Data reg in 2430, omap3 and
 					 * omap4 is 8 bit wide
 					 */
-					if (cpu_class_is_omap1() ||
-							cpu_is_omap2420()) {
+					if (pdata->flags &
+						 OMAP_I2C_FLAG_16BIT_DATA_REG) {
 						if (dev->buf_len) {
 							*dev->buf++ = w >> 8;
 							dev->buf_len--;
@@ -924,8 +918,8 @@ complete:
 					 * Data reg in 2430, omap3 and
 					 * omap4 is 8 bit wide
 					 */
-					if (cpu_class_is_omap1() ||
-							cpu_is_omap2420()) {
+					if (pdata->flags &
+						 OMAP_I2C_FLAG_16BIT_DATA_REG) {
 						if (dev->buf_len) {
 							w |= *dev->buf++ << 8;
 							dev->buf_len--;
@@ -1016,7 +1010,6 @@ omap_i2c_probe(struct platform_device *pdev)
 	}
 
 	dev->speed = speed;
-	dev->idle = 1;
 	dev->dev = &pdev->dev;
 	dev->irq = irq->start;
 	dev->base = ioremap(mem->start, resource_size(mem));
@@ -1027,27 +1020,22 @@ omap_i2c_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, dev);
 
-	if (cpu_is_omap7xx())
-		dev->reg_shift = 1;
-	else if (cpu_is_omap44xx())
-		dev->reg_shift = 0;
-	else
-		dev->reg_shift = 2;
+	dev->reg_shift = (pdata->flags >> OMAP_I2C_FLAG_BUS_SHIFT__SHIFT) & 3;
 
-	if (cpu_is_omap44xx())
-		dev->regs = (u8 *) omap4_reg_map;
+	if (pdata->rev == OMAP_I2C_IP_VERSION_2)
+		dev->regs = (u8 *)reg_map_ip_v2;
 	else
-		dev->regs = (u8 *) reg_map;
+		dev->regs = (u8 *)reg_map_ip_v1;
 
-	pm_runtime_enable(&pdev->dev);
-	omap_i2c_unidle(dev);
+	pm_runtime_enable(dev->dev);
+	pm_runtime_get_sync(dev->dev);
 
 	dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff;
 
 	if (dev->rev <= OMAP_I2C_REV_ON_3430)
 		dev->errata |= I2C_OMAP3_1P153;
 
-	if (!(cpu_class_is_omap1() || cpu_is_omap2420())) {
+	if (!(pdata->flags & OMAP_I2C_FLAG_NO_FIFO)) {
 		u16 s;
 
 		/* Set up the fifo size - Get total size */
@@ -1059,7 +1047,7 @@ omap_i2c_probe(struct platform_device *pdev)
 		 * size. This is to ensure that we can handle the status on int
 		 * call back latencies.
 		 */
-		if (dev->rev >= OMAP_I2C_REV_ON_4430) {
+		if (dev->rev >= OMAP_I2C_REV_ON_3530_4430) {
 			dev->fifo_size = 0;
 			dev->b_hw = 0; /* Disable hardware fixes */
 		} else {
@@ -1075,7 +1063,8 @@ omap_i2c_probe(struct platform_device *pdev)
 	/* reset ASAP, clearing any IRQs */
 	omap_i2c_init(dev);
 
-	isr = (dev->rev < OMAP_I2C_REV_2) ? omap_i2c_rev1_isr : omap_i2c_isr;
+	isr = (dev->rev < OMAP_I2C_OMAP1_REV_2) ? omap_i2c_omap1_isr :
+								   omap_i2c_isr;
 	r = request_irq(dev->irq, isr, 0, pdev->name, dev);
 
 	if (r) {
@@ -1083,10 +1072,10 @@ omap_i2c_probe(struct platform_device *pdev)
 		goto err_unuse_clocks;
 	}
 
-	dev_info(dev->dev, "bus %d rev%d.%d at %d kHz\n",
-		 pdev->id, dev->rev >> 4, dev->rev & 0xf, dev->speed);
+	dev_info(dev->dev, "bus %d rev%d.%d.%d at %d kHz\n", pdev->id,
+		 pdata->rev, dev->rev >> 4, dev->rev & 0xf, dev->speed);
 
-	omap_i2c_idle(dev);
+	pm_runtime_put(dev->dev);
 
 	adap = &dev->adapter;
 	i2c_set_adapdata(adap, dev);
@@ -1110,7 +1099,7 @@ err_free_irq:
 	free_irq(dev->irq, dev);
 err_unuse_clocks:
 	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
-	omap_i2c_idle(dev);
+	pm_runtime_put(dev->dev);
 	iounmap(dev->base);
 err_free_mem:
 	platform_set_drvdata(pdev, NULL);
@@ -1139,12 +1128,43 @@ omap_i2c_remove(struct platform_device *pdev)
 	return 0;
 }
 
+#ifdef CONFIG_PM_RUNTIME
+static int omap_i2c_runtime_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct omap_i2c_dev *_dev = platform_get_drvdata(pdev);
+
+	omap_i2c_idle(_dev);
+
+	return 0;
+}
+
+static int omap_i2c_runtime_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct omap_i2c_dev *_dev = platform_get_drvdata(pdev);
+
+	omap_i2c_unidle(_dev);
+
+	return 0;
+}
+
+static struct dev_pm_ops omap_i2c_pm_ops = {
+	.runtime_suspend = omap_i2c_runtime_suspend,
+	.runtime_resume = omap_i2c_runtime_resume,
+};
+#define OMAP_I2C_PM_OPS (&omap_i2c_pm_ops)
+#else
+#define OMAP_I2C_PM_OPS NULL
+#endif
+
 static struct platform_driver omap_i2c_driver = {
 	.probe		= omap_i2c_probe,
 	.remove		= omap_i2c_remove,
 	.driver		= {
 		.name	= "omap_i2c",
 		.owner	= THIS_MODULE,
+		.pm	= OMAP_I2C_PM_OPS,
 	},
 };
 
diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c
index dfa7ae9..127051b 100644
--- a/drivers/i2c/busses/i2c-pmcmsp.c
+++ b/drivers/i2c/busses/i2c-pmcmsp.c
@@ -306,7 +306,7 @@ static int __devinit pmcmsptwi_probe(struct platform_device *pldev)
 	pmcmsptwi_data.irq = platform_get_irq(pldev, 0);
 	if (pmcmsptwi_data.irq) {
 		rc = request_irq(pmcmsptwi_data.irq, &pmcmsptwi_interrupt,
-			IRQF_SHARED | IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
+			IRQF_SHARED | IRQF_SAMPLE_RANDOM,
 			pldev->name, &pmcmsptwi_data);
 		if (rc == 0) {
 			/*
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index f84a63c..2754cef 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -35,6 +35,8 @@
 #include <linux/cpufreq.h>
 #include <linux/slab.h>
 #include <linux/io.h>
+#include <linux/of_i2c.h>
+#include <linux/of_gpio.h>
 
 #include <asm/irq.h>
 
@@ -78,6 +80,8 @@ struct s3c24xx_i2c {
 	struct resource		*ioarea;
 	struct i2c_adapter	adap;
 
+	struct s3c2410_platform_i2c	*pdata;
+	int			gpios[2];
 #ifdef CONFIG_CPU_FREQ
 	struct notifier_block	freq_transition;
 #endif
@@ -95,6 +99,12 @@ static inline int s3c24xx_i2c_is2440(struct s3c24xx_i2c *i2c)
 	struct platform_device *pdev = to_platform_device(i2c->dev);
 	enum s3c24xx_i2c_type type;
 
+#ifdef CONFIG_OF
+	if (i2c->dev->of_node)
+		return of_device_is_compatible(i2c->dev->of_node,
+				"samsung,s3c2440-i2c");
+#endif
+
 	type = platform_get_device_id(pdev)->driver_data;
 	return type == TYPE_S3C2440;
 }
@@ -625,7 +635,7 @@ static int s3c24xx_i2c_calcdivisor(unsigned long clkin, unsigned int wanted,
 
 static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got)
 {
-	struct s3c2410_platform_i2c *pdata = i2c->dev->platform_data;
+	struct s3c2410_platform_i2c *pdata = i2c->pdata;
 	unsigned long clkin = clk_get_rate(i2c->clk);
 	unsigned int divs, div1;
 	unsigned long target_frequency;
@@ -741,6 +751,49 @@ static inline void s3c24xx_i2c_deregister_cpufreq(struct s3c24xx_i2c *i2c)
 }
 #endif
 
+#ifdef CONFIG_OF
+static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c)
+{
+	int idx, gpio, ret;
+
+	for (idx = 0; idx < 2; idx++) {
+		gpio = of_get_gpio(i2c->dev->of_node, idx);
+		if (!gpio_is_valid(gpio)) {
+			dev_err(i2c->dev, "invalid gpio[%d]: %d\n", idx, gpio);
+			goto free_gpio;
+		}
+
+		ret = gpio_request(gpio, "i2c-bus");
+		if (ret) {
+			dev_err(i2c->dev, "gpio [%d] request failed\n", gpio);
+			goto free_gpio;
+		}
+	}
+	return 0;
+
+free_gpio:
+	while (--idx >= 0)
+		gpio_free(i2c->gpios[idx]);
+	return -EINVAL;
+}
+
+static void s3c24xx_i2c_dt_gpio_free(struct s3c24xx_i2c *i2c)
+{
+	unsigned int idx;
+	for (idx = 0; idx < 2; idx++)
+		gpio_free(i2c->gpios[idx]);
+}
+#else
+static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c)
+{
+	return -EINVAL;
+}
+
+static void s3c24xx_i2c_dt_gpio_free(struct s3c24xx_i2c *i2c)
+{
+}
+#endif
+
 /* s3c24xx_i2c_init
  *
  * initialise the controller, set the IO lines and frequency
@@ -754,12 +807,15 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
 
 	/* get the plafrom data */
 
-	pdata = i2c->dev->platform_data;
+	pdata = i2c->pdata;
 
 	/* inititalise the gpio */
 
 	if (pdata->cfg_gpio)
 		pdata->cfg_gpio(to_platform_device(i2c->dev));
+	else
+		if (s3c24xx_i2c_parse_dt_gpio(i2c))
+			return -EINVAL;
 
 	/* write slave address */
 
@@ -785,6 +841,34 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
 	return 0;
 }
 
+#ifdef CONFIG_OF
+/* s3c24xx_i2c_parse_dt
+ *
+ * Parse the device tree node and retreive the platform data.
+*/
+
+static void
+s3c24xx_i2c_parse_dt(struct device_node *np, struct s3c24xx_i2c *i2c)
+{
+	struct s3c2410_platform_i2c *pdata = i2c->pdata;
+
+	if (!np)
+		return;
+
+	pdata->bus_num = -1; /* i2c bus number is dynamically assigned */
+	of_property_read_u32(np, "samsung,i2c-sda-delay", &pdata->sda_delay);
+	of_property_read_u32(np, "samsung,i2c-slave-addr", &pdata->slave_addr);
+	of_property_read_u32(np, "samsung,i2c-max-bus-freq",
+				(u32 *)&pdata->frequency);
+}
+#else
+static void
+s3c24xx_i2c_parse_dt(struct device_node *np, struct s3c24xx_i2c *i2c)
+{
+	return;
+}
+#endif
+
 /* s3c24xx_i2c_probe
  *
  * called by the bus driver when a suitable device is found
@@ -793,14 +877,16 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
 static int s3c24xx_i2c_probe(struct platform_device *pdev)
 {
 	struct s3c24xx_i2c *i2c;
-	struct s3c2410_platform_i2c *pdata;
+	struct s3c2410_platform_i2c *pdata = NULL;
 	struct resource *res;
 	int ret;
 
-	pdata = pdev->dev.platform_data;
-	if (!pdata) {
-		dev_err(&pdev->dev, "no platform data\n");
-		return -EINVAL;
+	if (!pdev->dev.of_node) {
+		pdata = pdev->dev.platform_data;
+		if (!pdata) {
+			dev_err(&pdev->dev, "no platform data\n");
+			return -EINVAL;
+		}
 	}
 
 	i2c = kzalloc(sizeof(struct s3c24xx_i2c), GFP_KERNEL);
@@ -809,6 +895,17 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
+	i2c->pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!i2c->pdata) {
+		ret = -ENOMEM;
+		goto err_noclk;
+	}
+
+	if (pdata)
+		memcpy(i2c->pdata, pdata, sizeof(*pdata));
+	else
+		s3c24xx_i2c_parse_dt(pdev->dev.of_node, i2c);
+
 	strlcpy(i2c->adap.name, "s3c2410-i2c", sizeof(i2c->adap.name));
 	i2c->adap.owner   = THIS_MODULE;
 	i2c->adap.algo    = &s3c24xx_i2c_algorithm;
@@ -883,7 +980,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
 		goto err_iomap;
 	}
 
-	ret = request_irq(i2c->irq, s3c24xx_i2c_irq, IRQF_DISABLED,
+	ret = request_irq(i2c->irq, s3c24xx_i2c_irq, 0,
 			  dev_name(&pdev->dev), i2c);
 
 	if (ret != 0) {
@@ -903,7 +1000,8 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
 	 * being bus 0.
 	 */
 
-	i2c->adap.nr = pdata->bus_num;
+	i2c->adap.nr = i2c->pdata->bus_num;
+	i2c->adap.dev.of_node = pdev->dev.of_node;
 
 	ret = i2c_add_numbered_adapter(&i2c->adap);
 	if (ret < 0) {
@@ -911,6 +1009,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
 		goto err_cpufreq;
 	}
 
+	of_i2c_register_devices(&i2c->adap);
 	platform_set_drvdata(pdev, i2c);
 
 	dev_info(&pdev->dev, "%s: S3C I2C adapter\n", dev_name(&i2c->adap.dev));
@@ -959,6 +1058,7 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
 	iounmap(i2c->regs);
 
 	release_resource(i2c->ioarea);
+	s3c24xx_i2c_dt_gpio_free(i2c);
 	kfree(i2c->ioarea);
 	kfree(i2c);
 
@@ -1012,6 +1112,17 @@ static struct platform_device_id s3c24xx_driver_ids[] = {
 };
 MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids);
 
+#ifdef CONFIG_OF
+static const struct of_device_id s3c24xx_i2c_match[] = {
+	{ .compatible = "samsung,s3c2410-i2c" },
+	{ .compatible = "samsung,s3c2440-i2c" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, s3c24xx_i2c_match);
+#else
+#define s3c24xx_i2c_match NULL
+#endif
+
 static struct platform_driver s3c24xx_i2c_driver = {
 	.probe		= s3c24xx_i2c_probe,
 	.remove		= s3c24xx_i2c_remove,
@@ -1020,6 +1131,7 @@ static struct platform_driver s3c24xx_i2c_driver = {
 		.owner	= THIS_MODULE,
 		.name	= "s3c-i2c",
 		.pm	= S3C24XX_DEV_PM_OPS,
+		.of_match_table = s3c24xx_i2c_match,
 	},
 };
 
diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c
index 3cad8fe..c418c41 100644
--- a/drivers/i2c/busses/i2c-sh7760.c
+++ b/drivers/i2c/busses/i2c-sh7760.c
@@ -502,7 +502,7 @@ static int __devinit sh7760_i2c_probe(struct platform_device *pdev)
 	}
 	OUT32(id, I2CCCR, ret);
 
-	if (request_irq(id->irq, sh7760_i2c_irq, IRQF_DISABLED,
+	if (request_irq(id->irq, sh7760_i2c_irq, 0,
 			SH7760_I2C_DEVNAME, id)) {
 		dev_err(&pdev->dev, "cannot get irq %d\n", id->irq);
 		ret = -EBUSY;
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c
index f633a53..675c969 100644
--- a/drivers/i2c/busses/i2c-sh_mobile.c
+++ b/drivers/i2c/busses/i2c-sh_mobile.c
@@ -543,7 +543,7 @@ static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook)
 
 	while ((res = platform_get_resource(dev, IORESOURCE_IRQ, k))) {
 		for (n = res->start; hook && n <= res->end; n++) {
-			if (request_irq(n, sh_mobile_i2c_isr, IRQF_DISABLED,
+			if (request_irq(n, sh_mobile_i2c_isr, 0,
 					dev_name(&dev->dev), dev)) {
 				for (n--; n >= res->start; n--)
 					free_irq(n, dev);
diff --git a/drivers/i2c/busses/i2c-stu300.c b/drivers/i2c/busses/i2c-stu300.c
index 9987961..4d44af1 100644
--- a/drivers/i2c/busses/i2c-stu300.c
+++ b/drivers/i2c/busses/i2c-stu300.c
@@ -916,7 +916,7 @@ stu300_probe(struct platform_device *pdev)
 	}
 
 	dev->irq = platform_get_irq(pdev, 0);
-	if (request_irq(dev->irq, stu300_irh, IRQF_DISABLED,
+	if (request_irq(dev->irq, stu300_irh, 0,
 			NAME, dev)) {
 		ret = -EIO;
 		goto err_no_irq;
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 3c94c4a..b050530 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -566,7 +566,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
 	struct clk *clk;
 	struct clk *i2c_clk;
 	const unsigned int *prop;
-	void *base;
+	void __iomem *base;
 	int irq;
 	int ret = 0;
 
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index fc0f2bd..4104ea2 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -889,6 +889,8 @@ retest:
 		break;
 	case IB_CM_ESTABLISHED:
 		spin_unlock_irq(&cm_id_priv->lock);
+		if (cm_id_priv->qp_type == IB_QPT_XRC_TGT)
+			break;
 		ib_send_cm_dreq(cm_id, NULL, 0);
 		goto retest;
 	case IB_CM_DREQ_SENT:
@@ -1008,7 +1010,6 @@ static void cm_format_req(struct cm_req_msg *req_msg,
 	req_msg->service_id = param->service_id;
 	req_msg->local_ca_guid = cm_id_priv->id.device->node_guid;
 	cm_req_set_local_qpn(req_msg, cpu_to_be32(param->qp_num));
-	cm_req_set_resp_res(req_msg, param->responder_resources);
 	cm_req_set_init_depth(req_msg, param->initiator_depth);
 	cm_req_set_remote_resp_timeout(req_msg,
 				       param->remote_cm_response_timeout);
@@ -1017,12 +1018,16 @@ static void cm_format_req(struct cm_req_msg *req_msg,
 	cm_req_set_starting_psn(req_msg, cpu_to_be32(param->starting_psn));
 	cm_req_set_local_resp_timeout(req_msg,
 				      param->local_cm_response_timeout);
-	cm_req_set_retry_count(req_msg, param->retry_count);
 	req_msg->pkey = param->primary_path->pkey;
 	cm_req_set_path_mtu(req_msg, param->primary_path->mtu);
-	cm_req_set_rnr_retry_count(req_msg, param->rnr_retry_count);
 	cm_req_set_max_cm_retries(req_msg, param->max_cm_retries);
-	cm_req_set_srq(req_msg, param->srq);
+
+	if (param->qp_type != IB_QPT_XRC_INI) {
+		cm_req_set_resp_res(req_msg, param->responder_resources);
+		cm_req_set_retry_count(req_msg, param->retry_count);
+		cm_req_set_rnr_retry_count(req_msg, param->rnr_retry_count);
+		cm_req_set_srq(req_msg, param->srq);
+	}
 
 	if (pri_path->hop_limit <= 1) {
 		req_msg->primary_local_lid = pri_path->slid;
@@ -1080,7 +1085,8 @@ static int cm_validate_req_param(struct ib_cm_req_param *param)
 	if (!param->primary_path)
 		return -EINVAL;
 
-	if (param->qp_type != IB_QPT_RC && param->qp_type != IB_QPT_UC)
+	if (param->qp_type != IB_QPT_RC && param->qp_type != IB_QPT_UC &&
+	    param->qp_type != IB_QPT_XRC_INI)
 		return -EINVAL;
 
 	if (param->private_data &&
@@ -1601,18 +1607,24 @@ static void cm_format_rep(struct cm_rep_msg *rep_msg,
 	cm_format_mad_hdr(&rep_msg->hdr, CM_REP_ATTR_ID, cm_id_priv->tid);
 	rep_msg->local_comm_id = cm_id_priv->id.local_id;
 	rep_msg->remote_comm_id = cm_id_priv->id.remote_id;
-	cm_rep_set_local_qpn(rep_msg, cpu_to_be32(param->qp_num));
 	cm_rep_set_starting_psn(rep_msg, cpu_to_be32(param->starting_psn));
 	rep_msg->resp_resources = param->responder_resources;
-	rep_msg->initiator_depth = param->initiator_depth;
 	cm_rep_set_target_ack_delay(rep_msg,
 				    cm_id_priv->av.port->cm_dev->ack_delay);
 	cm_rep_set_failover(rep_msg, param->failover_accepted);
-	cm_rep_set_flow_ctrl(rep_msg, param->flow_control);
 	cm_rep_set_rnr_retry_count(rep_msg, param->rnr_retry_count);
-	cm_rep_set_srq(rep_msg, param->srq);
 	rep_msg->local_ca_guid = cm_id_priv->id.device->node_guid;
 
+	if (cm_id_priv->qp_type != IB_QPT_XRC_TGT) {
+		rep_msg->initiator_depth = param->initiator_depth;
+		cm_rep_set_flow_ctrl(rep_msg, param->flow_control);
+		cm_rep_set_srq(rep_msg, param->srq);
+		cm_rep_set_local_qpn(rep_msg, cpu_to_be32(param->qp_num));
+	} else {
+		cm_rep_set_srq(rep_msg, 1);
+		cm_rep_set_local_eecn(rep_msg, cpu_to_be32(param->qp_num));
+	}
+
 	if (param->private_data && param->private_data_len)
 		memcpy(rep_msg->private_data, param->private_data,
 		       param->private_data_len);
@@ -1660,7 +1672,7 @@ int ib_send_cm_rep(struct ib_cm_id *cm_id,
 	cm_id_priv->initiator_depth = param->initiator_depth;
 	cm_id_priv->responder_resources = param->responder_resources;
 	cm_id_priv->rq_psn = cm_rep_get_starting_psn(rep_msg);
-	cm_id_priv->local_qpn = cm_rep_get_local_qpn(rep_msg);
+	cm_id_priv->local_qpn = cpu_to_be32(param->qp_num & 0xFFFFFF);
 
 out:	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 	return ret;
@@ -1731,7 +1743,7 @@ error:	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 }
 EXPORT_SYMBOL(ib_send_cm_rtu);
 
-static void cm_format_rep_event(struct cm_work *work)
+static void cm_format_rep_event(struct cm_work *work, enum ib_qp_type qp_type)
 {
 	struct cm_rep_msg *rep_msg;
 	struct ib_cm_rep_event_param *param;
@@ -1740,7 +1752,7 @@ static void cm_format_rep_event(struct cm_work *work)
 	param = &work->cm_event.param.rep_rcvd;
 	param->remote_ca_guid = rep_msg->local_ca_guid;
 	param->remote_qkey = be32_to_cpu(rep_msg->local_qkey);
-	param->remote_qpn = be32_to_cpu(cm_rep_get_local_qpn(rep_msg));
+	param->remote_qpn = be32_to_cpu(cm_rep_get_qpn(rep_msg, qp_type));
 	param->starting_psn = be32_to_cpu(cm_rep_get_starting_psn(rep_msg));
 	param->responder_resources = rep_msg->initiator_depth;
 	param->initiator_depth = rep_msg->resp_resources;
@@ -1808,7 +1820,7 @@ static int cm_rep_handler(struct cm_work *work)
 		return -EINVAL;
 	}
 
-	cm_format_rep_event(work);
+	cm_format_rep_event(work, cm_id_priv->qp_type);
 
 	spin_lock_irq(&cm_id_priv->lock);
 	switch (cm_id_priv->id.state) {
@@ -1823,7 +1835,7 @@ static int cm_rep_handler(struct cm_work *work)
 
 	cm_id_priv->timewait_info->work.remote_id = rep_msg->local_comm_id;
 	cm_id_priv->timewait_info->remote_ca_guid = rep_msg->local_ca_guid;
-	cm_id_priv->timewait_info->remote_qpn = cm_rep_get_local_qpn(rep_msg);
+	cm_id_priv->timewait_info->remote_qpn = cm_rep_get_qpn(rep_msg, cm_id_priv->qp_type);
 
 	spin_lock(&cm.lock);
 	/* Check for duplicate REP. */
@@ -1850,7 +1862,7 @@ static int cm_rep_handler(struct cm_work *work)
 
 	cm_id_priv->id.state = IB_CM_REP_RCVD;
 	cm_id_priv->id.remote_id = rep_msg->local_comm_id;
-	cm_id_priv->remote_qpn = cm_rep_get_local_qpn(rep_msg);
+	cm_id_priv->remote_qpn = cm_rep_get_qpn(rep_msg, cm_id_priv->qp_type);
 	cm_id_priv->initiator_depth = rep_msg->resp_resources;
 	cm_id_priv->responder_resources = rep_msg->initiator_depth;
 	cm_id_priv->sq_psn = cm_rep_get_starting_psn(rep_msg);
@@ -3492,7 +3504,8 @@ static int cm_init_qp_rtr_attr(struct cm_id_private *cm_id_priv,
 		qp_attr->path_mtu = cm_id_priv->path_mtu;
 		qp_attr->dest_qp_num = be32_to_cpu(cm_id_priv->remote_qpn);
 		qp_attr->rq_psn = be32_to_cpu(cm_id_priv->rq_psn);
-		if (cm_id_priv->qp_type == IB_QPT_RC) {
+		if (cm_id_priv->qp_type == IB_QPT_RC ||
+		    cm_id_priv->qp_type == IB_QPT_XRC_TGT) {
 			*qp_attr_mask |= IB_QP_MAX_DEST_RD_ATOMIC |
 					 IB_QP_MIN_RNR_TIMER;
 			qp_attr->max_dest_rd_atomic =
@@ -3537,15 +3550,21 @@ static int cm_init_qp_rts_attr(struct cm_id_private *cm_id_priv,
 		if (cm_id_priv->id.lap_state == IB_CM_LAP_UNINIT) {
 			*qp_attr_mask = IB_QP_STATE | IB_QP_SQ_PSN;
 			qp_attr->sq_psn = be32_to_cpu(cm_id_priv->sq_psn);
-			if (cm_id_priv->qp_type == IB_QPT_RC) {
-				*qp_attr_mask |= IB_QP_TIMEOUT | IB_QP_RETRY_CNT |
-						 IB_QP_RNR_RETRY |
+			switch (cm_id_priv->qp_type) {
+			case IB_QPT_RC:
+			case IB_QPT_XRC_INI:
+				*qp_attr_mask |= IB_QP_RETRY_CNT | IB_QP_RNR_RETRY |
 						 IB_QP_MAX_QP_RD_ATOMIC;
-				qp_attr->timeout = cm_id_priv->av.timeout;
 				qp_attr->retry_cnt = cm_id_priv->retry_count;
 				qp_attr->rnr_retry = cm_id_priv->rnr_retry_count;
-				qp_attr->max_rd_atomic =
-					cm_id_priv->initiator_depth;
+				qp_attr->max_rd_atomic = cm_id_priv->initiator_depth;
+				/* fall through */
+			case IB_QPT_XRC_TGT:
+				*qp_attr_mask |= IB_QP_TIMEOUT;
+				qp_attr->timeout = cm_id_priv->av.timeout;
+				break;
+			default:
+				break;
 			}
 			if (cm_id_priv->alt_av.ah_attr.dlid) {
 				*qp_attr_mask |= IB_QP_PATH_MIG_STATE;
diff --git a/drivers/infiniband/core/cm_msgs.h b/drivers/infiniband/core/cm_msgs.h
index 7e63c08..505db2a 100644
--- a/drivers/infiniband/core/cm_msgs.h
+++ b/drivers/infiniband/core/cm_msgs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2004, 2011 Intel Corporation.  All rights reserved.
  * Copyright (c) 2004 Topspin Corporation.  All rights reserved.
  * Copyright (c) 2004 Voltaire Corporation.  All rights reserved.
  *
@@ -86,7 +86,7 @@ struct cm_req_msg {
 	__be16 pkey;
 	/* path MTU:4, RDC exists:1, RNR retry count:3. */
 	u8 offset50;
-	/* max CM Retries:4, SRQ:1, rsvd:3 */
+	/* max CM Retries:4, SRQ:1, extended transport type:3 */
 	u8 offset51;
 
 	__be16 primary_local_lid;
@@ -175,6 +175,11 @@ static inline enum ib_qp_type cm_req_get_qp_type(struct cm_req_msg *req_msg)
 	switch(transport_type) {
 	case 0: return IB_QPT_RC;
 	case 1: return IB_QPT_UC;
+	case 3:
+		switch (req_msg->offset51 & 0x7) {
+		case 1: return IB_QPT_XRC_TGT;
+		default: return 0;
+		}
 	default: return 0;
 	}
 }
@@ -188,6 +193,12 @@ static inline void cm_req_set_qp_type(struct cm_req_msg *req_msg,
 						  req_msg->offset40) &
 						   0xFFFFFFF9) | 0x2);
 		break;
+	case IB_QPT_XRC_INI:
+		req_msg->offset40 = cpu_to_be32((be32_to_cpu(
+						 req_msg->offset40) &
+						   0xFFFFFFF9) | 0x6);
+		req_msg->offset51 = (req_msg->offset51 & 0xF8) | 1;
+		break;
 	default:
 		req_msg->offset40 = cpu_to_be32(be32_to_cpu(
 						 req_msg->offset40) &
@@ -527,6 +538,23 @@ static inline void cm_rep_set_local_qpn(struct cm_rep_msg *rep_msg, __be32 qpn)
 			    (be32_to_cpu(rep_msg->offset12) & 0x000000FF));
 }
 
+static inline __be32 cm_rep_get_local_eecn(struct cm_rep_msg *rep_msg)
+{
+	return cpu_to_be32(be32_to_cpu(rep_msg->offset16) >> 8);
+}
+
+static inline void cm_rep_set_local_eecn(struct cm_rep_msg *rep_msg, __be32 eecn)
+{
+	rep_msg->offset16 = cpu_to_be32((be32_to_cpu(eecn) << 8) |
+			    (be32_to_cpu(rep_msg->offset16) & 0x000000FF));
+}
+
+static inline __be32 cm_rep_get_qpn(struct cm_rep_msg *rep_msg, enum ib_qp_type qp_type)
+{
+	return (qp_type == IB_QPT_XRC_INI) ?
+		cm_rep_get_local_eecn(rep_msg) : cm_rep_get_local_qpn(rep_msg);
+}
+
 static inline __be32 cm_rep_get_starting_psn(struct cm_rep_msg *rep_msg)
 {
 	return cpu_to_be32(be32_to_cpu(rep_msg->offset20) >> 8);
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index ca4c5dc..872b184 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -81,6 +81,7 @@ static DEFINE_IDR(sdp_ps);
 static DEFINE_IDR(tcp_ps);
 static DEFINE_IDR(udp_ps);
 static DEFINE_IDR(ipoib_ps);
+static DEFINE_IDR(ib_ps);
 
 struct cma_device {
 	struct list_head	list;
@@ -1179,6 +1180,15 @@ static void cma_set_req_event_data(struct rdma_cm_event *event,
 	event->param.conn.qp_num = req_data->remote_qpn;
 }
 
+static int cma_check_req_qp_type(struct rdma_cm_id *id, struct ib_cm_event *ib_event)
+{
+	return (((ib_event->event == IB_CM_REQ_RECEIVED) ||
+		 (ib_event->param.req_rcvd.qp_type == id->qp_type)) ||
+		((ib_event->event == IB_CM_SIDR_REQ_RECEIVED) &&
+		 (id->qp_type == IB_QPT_UD)) ||
+		(!id->qp_type));
+}
+
 static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
 {
 	struct rdma_id_private *listen_id, *conn_id;
@@ -1186,13 +1196,16 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
 	int offset, ret;
 
 	listen_id = cm_id->context;
+	if (!cma_check_req_qp_type(&listen_id->id, ib_event))
+		return -EINVAL;
+
 	if (cma_disable_callback(listen_id, RDMA_CM_LISTEN))
 		return -ECONNABORTED;
 
 	memset(&event, 0, sizeof event);
 	offset = cma_user_data_offset(listen_id->id.ps);
 	event.event = RDMA_CM_EVENT_CONNECT_REQUEST;
-	if (listen_id->id.qp_type == IB_QPT_UD) {
+	if (ib_event->event == IB_CM_SIDR_REQ_RECEIVED) {
 		conn_id = cma_new_udp_id(&listen_id->id, ib_event);
 		event.param.ud.private_data = ib_event->private_data + offset;
 		event.param.ud.private_data_len =
@@ -1328,6 +1341,8 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event)
 		switch (iw_event->status) {
 		case 0:
 			event.event = RDMA_CM_EVENT_ESTABLISHED;
+			event.param.conn.initiator_depth = iw_event->ird;
+			event.param.conn.responder_resources = iw_event->ord;
 			break;
 		case -ECONNRESET:
 		case -ECONNREFUSED:
@@ -1343,6 +1358,8 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event)
 		break;
 	case IW_CM_EVENT_ESTABLISHED:
 		event.event = RDMA_CM_EVENT_ESTABLISHED;
+		event.param.conn.initiator_depth = iw_event->ird;
+		event.param.conn.responder_resources = iw_event->ord;
 		break;
 	default:
 		BUG_ON(1);
@@ -1433,8 +1450,8 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
 	event.event = RDMA_CM_EVENT_CONNECT_REQUEST;
 	event.param.conn.private_data = iw_event->private_data;
 	event.param.conn.private_data_len = iw_event->private_data_len;
-	event.param.conn.initiator_depth = attr.max_qp_init_rd_atom;
-	event.param.conn.responder_resources = attr.max_qp_rd_atom;
+	event.param.conn.initiator_depth = iw_event->ird;
+	event.param.conn.responder_resources = iw_event->ord;
 
 	/*
 	 * Protect against the user destroying conn_id from another thread
@@ -2234,6 +2251,9 @@ static int cma_get_port(struct rdma_id_private *id_priv)
 	case RDMA_PS_IPOIB:
 		ps = &ipoib_ps;
 		break;
+	case RDMA_PS_IB:
+		ps = &ib_ps;
+		break;
 	default:
 		return -EPROTONOSUPPORT;
 	}
@@ -2569,7 +2589,7 @@ static int cma_connect_ib(struct rdma_id_private *id_priv,
 	req.service_id = cma_get_service_id(id_priv->id.ps,
 					    (struct sockaddr *) &route->addr.dst_addr);
 	req.qp_num = id_priv->qp_num;
-	req.qp_type = IB_QPT_RC;
+	req.qp_type = id_priv->id.qp_type;
 	req.starting_psn = id_priv->seq_num;
 	req.responder_resources = conn_param->responder_resources;
 	req.initiator_depth = conn_param->initiator_depth;
@@ -2616,14 +2636,16 @@ static int cma_connect_iw(struct rdma_id_private *id_priv,
 	if (ret)
 		goto out;
 
-	iw_param.ord = conn_param->initiator_depth;
-	iw_param.ird = conn_param->responder_resources;
-	iw_param.private_data = conn_param->private_data;
-	iw_param.private_data_len = conn_param->private_data_len;
-	if (id_priv->id.qp)
+	if (conn_param) {
+		iw_param.ord = conn_param->initiator_depth;
+		iw_param.ird = conn_param->responder_resources;
+		iw_param.private_data = conn_param->private_data;
+		iw_param.private_data_len = conn_param->private_data_len;
+		iw_param.qpn = id_priv->id.qp ? id_priv->qp_num : conn_param->qp_num;
+	} else {
+		memset(&iw_param, 0, sizeof iw_param);
 		iw_param.qpn = id_priv->qp_num;
-	else
-		iw_param.qpn = conn_param->qp_num;
+	}
 	ret = iw_cm_connect(cm_id, &iw_param);
 out:
 	if (ret) {
@@ -2765,14 +2787,20 @@ int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
 
 	switch (rdma_node_get_transport(id->device->node_type)) {
 	case RDMA_TRANSPORT_IB:
-		if (id->qp_type == IB_QPT_UD)
-			ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS,
-						conn_param->private_data,
-						conn_param->private_data_len);
-		else if (conn_param)
-			ret = cma_accept_ib(id_priv, conn_param);
-		else
-			ret = cma_rep_recv(id_priv);
+		if (id->qp_type == IB_QPT_UD) {
+			if (conn_param)
+				ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS,
+							conn_param->private_data,
+							conn_param->private_data_len);
+			else
+				ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS,
+							NULL, 0);
+		} else {
+			if (conn_param)
+				ret = cma_accept_ib(id_priv, conn_param);
+			else
+				ret = cma_rep_recv(id_priv);
+		}
 		break;
 	case RDMA_TRANSPORT_IWARP:
 		ret = cma_accept_iw(id_priv, conn_param);
@@ -3460,6 +3488,7 @@ static void __exit cma_cleanup(void)
 	idr_destroy(&tcp_ps);
 	idr_destroy(&udp_ps);
 	idr_destroy(&ipoib_ps);
+	idr_destroy(&ib_ps);
 }
 
 module_init(cma_init);
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index b4d8672..0563892 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -1596,6 +1596,9 @@ find_mad_agent(struct ib_mad_port_private *port_priv,
 					mad->mad_hdr.class_version].class;
 			if (!class)
 				goto out;
+			if (convert_mgmt_class(mad->mad_hdr.mgmt_class) >=
+			    IB_MGMT_MAX_METHODS)
+				goto out;
 			method = class->method_table[convert_mgmt_class(
 							mad->mad_hdr.mgmt_class)];
 			if (method)
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index 9ab5df7..2b59b72 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -185,17 +185,35 @@ static ssize_t rate_show(struct ib_port *p, struct port_attribute *unused,
 	if (ret)
 		return ret;
 
+	rate = (25 * attr.active_speed) / 10;
+
 	switch (attr.active_speed) {
-	case 2: speed = " DDR"; break;
-	case 4: speed = " QDR"; break;
+	case 2:
+		speed = " DDR";
+		break;
+	case 4:
+		speed = " QDR";
+		break;
+	case 8:
+		speed = " FDR10";
+		rate = 10;
+		break;
+	case 16:
+		speed = " FDR";
+		rate = 14;
+		break;
+	case 32:
+		speed = " EDR";
+		rate = 25;
+		break;
 	}
 
-	rate = 25 * ib_width_enum_to_int(attr.active_width) * attr.active_speed;
+	rate *= ib_width_enum_to_int(attr.active_width);
 	if (rate < 0)
 		return -EINVAL;
 
 	return sprintf(buf, "%d%s Gb/sec (%dX%s)\n",
-		       rate / 10, rate % 10 ? ".5" : "",
+		       rate, (attr.active_speed == 1) ? ".5" : "",
 		       ib_width_enum_to_int(attr.active_width), speed);
 }
 
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index 08f948d..b8a0b4a 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -1122,7 +1122,7 @@ static ssize_t ib_ucm_write(struct file *filp, const char __user *buf,
 	if (copy_from_user(&hdr, buf, sizeof(hdr)))
 		return -EFAULT;
 
-	if (hdr.cmd < 0 || hdr.cmd >= ARRAY_SIZE(ucm_cmd_table))
+	if (hdr.cmd >= ARRAY_SIZE(ucm_cmd_table))
 		return -EINVAL;
 
 	if (hdr.in + sizeof(hdr) > len)
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
index 71be5ee..b69307f 100644
--- a/drivers/infiniband/core/ucma.c
+++ b/drivers/infiniband/core/ucma.c
@@ -276,7 +276,7 @@ static int ucma_event_handler(struct rdma_cm_id *cm_id,
 	ucma_set_event_context(ctx, event, uevent);
 	uevent->resp.event = event->event;
 	uevent->resp.status = event->status;
-	if (cm_id->ps == RDMA_PS_UDP || cm_id->ps == RDMA_PS_IPOIB)
+	if (cm_id->qp_type == IB_QPT_UD)
 		ucma_copy_ud_event(&uevent->resp.param.ud, &event->param.ud);
 	else
 		ucma_copy_conn_event(&uevent->resp.param.conn,
@@ -377,6 +377,9 @@ static int ucma_get_qp_type(struct rdma_ucm_create_id *cmd, enum ib_qp_type *qp_
 	case RDMA_PS_IPOIB:
 		*qp_type = IB_QPT_UD;
 		return 0;
+	case RDMA_PS_IB:
+		*qp_type = cmd->qp_type;
+		return 0;
 	default:
 		return -EINVAL;
 	}
@@ -1270,7 +1273,7 @@ static ssize_t ucma_write(struct file *filp, const char __user *buf,
 	if (copy_from_user(&hdr, buf, sizeof(hdr)))
 		return -EFAULT;
 
-	if (hdr.cmd < 0 || hdr.cmd >= ARRAY_SIZE(ucma_cmd_table))
+	if (hdr.cmd >= ARRAY_SIZE(ucma_cmd_table))
 		return -EINVAL;
 
 	if (hdr.in + sizeof(hdr) > len)
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index 8d261b6..07db229 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -458,8 +458,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
 		goto err;
 	}
 
-	if (packet->mad.hdr.id < 0 ||
-	    packet->mad.hdr.id >= IB_UMAD_MAX_AGENTS) {
+	if (packet->mad.hdr.id >= IB_UMAD_MAX_AGENTS) {
 		ret = -EINVAL;
 		goto err;
 	}
@@ -703,7 +702,7 @@ static int ib_umad_unreg_agent(struct ib_umad_file *file, u32 __user *arg)
 	mutex_lock(&file->port->file_mutex);
 	mutex_lock(&file->mutex);
 
-	if (id < 0 || id >= IB_UMAD_MAX_AGENTS || !__get_agent(file, id)) {
+	if (id >= IB_UMAD_MAX_AGENTS || !__get_agent(file, id)) {
 		ret = -EINVAL;
 		goto out;
 	}
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index a078e56..5bcb2af 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -76,6 +76,8 @@ struct ib_uverbs_device {
 	struct ib_device		       *ib_dev;
 	int					devnum;
 	struct cdev			        cdev;
+	struct rb_root				xrcd_tree;
+	struct mutex				xrcd_tree_mutex;
 };
 
 struct ib_uverbs_event_file {
@@ -120,6 +122,16 @@ struct ib_uevent_object {
 	u32			events_reported;
 };
 
+struct ib_uxrcd_object {
+	struct ib_uobject	uobject;
+	atomic_t		refcnt;
+};
+
+struct ib_usrq_object {
+	struct ib_uevent_object	uevent;
+	struct ib_uxrcd_object *uxrcd;
+};
+
 struct ib_uqp_object {
 	struct ib_uevent_object	uevent;
 	struct list_head 	mcast_list;
@@ -142,6 +154,7 @@ extern struct idr ib_uverbs_ah_idr;
 extern struct idr ib_uverbs_cq_idr;
 extern struct idr ib_uverbs_qp_idr;
 extern struct idr ib_uverbs_srq_idr;
+extern struct idr ib_uverbs_xrcd_idr;
 
 void idr_remove_uobj(struct idr *idp, struct ib_uobject *uobj);
 
@@ -161,6 +174,7 @@ void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr);
 void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr);
 void ib_uverbs_event_handler(struct ib_event_handler *handler,
 			     struct ib_event *event);
+void ib_uverbs_dealloc_xrcd(struct ib_uverbs_device *dev, struct ib_xrcd *xrcd);
 
 #define IB_UVERBS_DECLARE_CMD(name)					\
 	ssize_t ib_uverbs_##name(struct ib_uverbs_file *file,		\
@@ -181,6 +195,7 @@ IB_UVERBS_DECLARE_CMD(poll_cq);
 IB_UVERBS_DECLARE_CMD(req_notify_cq);
 IB_UVERBS_DECLARE_CMD(destroy_cq);
 IB_UVERBS_DECLARE_CMD(create_qp);
+IB_UVERBS_DECLARE_CMD(open_qp);
 IB_UVERBS_DECLARE_CMD(query_qp);
 IB_UVERBS_DECLARE_CMD(modify_qp);
 IB_UVERBS_DECLARE_CMD(destroy_qp);
@@ -195,5 +210,8 @@ IB_UVERBS_DECLARE_CMD(create_srq);
 IB_UVERBS_DECLARE_CMD(modify_srq);
 IB_UVERBS_DECLARE_CMD(query_srq);
 IB_UVERBS_DECLARE_CMD(destroy_srq);
+IB_UVERBS_DECLARE_CMD(create_xsrq);
+IB_UVERBS_DECLARE_CMD(open_xrcd);
+IB_UVERBS_DECLARE_CMD(close_xrcd);
 
 #endif /* UVERBS_H */
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index c426992..254f164 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -47,6 +47,7 @@ static struct lock_class_key cq_lock_key;
 static struct lock_class_key qp_lock_key;
 static struct lock_class_key ah_lock_key;
 static struct lock_class_key srq_lock_key;
+static struct lock_class_key xrcd_lock_key;
 
 #define INIT_UDATA(udata, ibuf, obuf, ilen, olen)			\
 	do {								\
@@ -255,6 +256,18 @@ static void put_srq_read(struct ib_srq *srq)
 	put_uobj_read(srq->uobject);
 }
 
+static struct ib_xrcd *idr_read_xrcd(int xrcd_handle, struct ib_ucontext *context,
+				     struct ib_uobject **uobj)
+{
+	*uobj = idr_read_uobj(&ib_uverbs_xrcd_idr, xrcd_handle, context, 0);
+	return *uobj ? (*uobj)->object : NULL;
+}
+
+static void put_xrcd_read(struct ib_uobject *uobj)
+{
+	put_uobj_read(uobj);
+}
+
 ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
 			      const char __user *buf,
 			      int in_len, int out_len)
@@ -298,6 +311,7 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
 	INIT_LIST_HEAD(&ucontext->qp_list);
 	INIT_LIST_HEAD(&ucontext->srq_list);
 	INIT_LIST_HEAD(&ucontext->ah_list);
+	INIT_LIST_HEAD(&ucontext->xrcd_list);
 	ucontext->closing = 0;
 
 	resp.num_comp_vectors = file->device->num_comp_vectors;
@@ -579,6 +593,310 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file,
 	return in_len;
 }
 
+struct xrcd_table_entry {
+	struct rb_node  node;
+	struct ib_xrcd *xrcd;
+	struct inode   *inode;
+};
+
+static int xrcd_table_insert(struct ib_uverbs_device *dev,
+			    struct inode *inode,
+			    struct ib_xrcd *xrcd)
+{
+	struct xrcd_table_entry *entry, *scan;
+	struct rb_node **p = &dev->xrcd_tree.rb_node;
+	struct rb_node *parent = NULL;
+
+	entry = kmalloc(sizeof *entry, GFP_KERNEL);
+	if (!entry)
+		return -ENOMEM;
+
+	entry->xrcd  = xrcd;
+	entry->inode = inode;
+
+	while (*p) {
+		parent = *p;
+		scan = rb_entry(parent, struct xrcd_table_entry, node);
+
+		if (inode < scan->inode) {
+			p = &(*p)->rb_left;
+		} else if (inode > scan->inode) {
+			p = &(*p)->rb_right;
+		} else {
+			kfree(entry);
+			return -EEXIST;
+		}
+	}
+
+	rb_link_node(&entry->node, parent, p);
+	rb_insert_color(&entry->node, &dev->xrcd_tree);
+	igrab(inode);
+	return 0;
+}
+
+static struct xrcd_table_entry *xrcd_table_search(struct ib_uverbs_device *dev,
+						  struct inode *inode)
+{
+	struct xrcd_table_entry *entry;
+	struct rb_node *p = dev->xrcd_tree.rb_node;
+
+	while (p) {
+		entry = rb_entry(p, struct xrcd_table_entry, node);
+
+		if (inode < entry->inode)
+			p = p->rb_left;
+		else if (inode > entry->inode)
+			p = p->rb_right;
+		else
+			return entry;
+	}
+
+	return NULL;
+}
+
+static struct ib_xrcd *find_xrcd(struct ib_uverbs_device *dev, struct inode *inode)
+{
+	struct xrcd_table_entry *entry;
+
+	entry = xrcd_table_search(dev, inode);
+	if (!entry)
+		return NULL;
+
+	return entry->xrcd;
+}
+
+static void xrcd_table_delete(struct ib_uverbs_device *dev,
+			      struct inode *inode)
+{
+	struct xrcd_table_entry *entry;
+
+	entry = xrcd_table_search(dev, inode);
+	if (entry) {
+		iput(inode);
+		rb_erase(&entry->node, &dev->xrcd_tree);
+		kfree(entry);
+	}
+}
+
+ssize_t ib_uverbs_open_xrcd(struct ib_uverbs_file *file,
+			    const char __user *buf, int in_len,
+			    int out_len)
+{
+	struct ib_uverbs_open_xrcd	cmd;
+	struct ib_uverbs_open_xrcd_resp	resp;
+	struct ib_udata			udata;
+	struct ib_uxrcd_object         *obj;
+	struct ib_xrcd                 *xrcd = NULL;
+	struct file                    *f = NULL;
+	struct inode                   *inode = NULL;
+	int				ret = 0;
+	int				new_xrcd = 0;
+
+	if (out_len < sizeof resp)
+		return -ENOSPC;
+
+	if (copy_from_user(&cmd, buf, sizeof cmd))
+		return -EFAULT;
+
+	INIT_UDATA(&udata, buf + sizeof cmd,
+		   (unsigned long) cmd.response + sizeof resp,
+		   in_len - sizeof cmd, out_len - sizeof  resp);
+
+	mutex_lock(&file->device->xrcd_tree_mutex);
+
+	if (cmd.fd != -1) {
+		/* search for file descriptor */
+		f = fget(cmd.fd);
+		if (!f) {
+			ret = -EBADF;
+			goto err_tree_mutex_unlock;
+		}
+
+		inode = f->f_dentry->d_inode;
+		if (!inode) {
+			ret = -EBADF;
+			goto err_tree_mutex_unlock;
+		}
+
+		xrcd = find_xrcd(file->device, inode);
+		if (!xrcd && !(cmd.oflags & O_CREAT)) {
+			/* no file descriptor. Need CREATE flag */
+			ret = -EAGAIN;
+			goto err_tree_mutex_unlock;
+		}
+
+		if (xrcd && cmd.oflags & O_EXCL) {
+			ret = -EINVAL;
+			goto err_tree_mutex_unlock;
+		}
+	}
+
+	obj = kmalloc(sizeof *obj, GFP_KERNEL);
+	if (!obj) {
+		ret = -ENOMEM;
+		goto err_tree_mutex_unlock;
+	}
+
+	init_uobj(&obj->uobject, 0, file->ucontext, &xrcd_lock_key);
+
+	down_write(&obj->uobject.mutex);
+
+	if (!xrcd) {
+		xrcd = file->device->ib_dev->alloc_xrcd(file->device->ib_dev,
+							file->ucontext, &udata);
+		if (IS_ERR(xrcd)) {
+			ret = PTR_ERR(xrcd);
+			goto err;
+		}
+
+		xrcd->inode   = inode;
+		xrcd->device  = file->device->ib_dev;
+		atomic_set(&xrcd->usecnt, 0);
+		mutex_init(&xrcd->tgt_qp_mutex);
+		INIT_LIST_HEAD(&xrcd->tgt_qp_list);
+		new_xrcd = 1;
+	}
+
+	atomic_set(&obj->refcnt, 0);
+	obj->uobject.object = xrcd;
+	ret = idr_add_uobj(&ib_uverbs_xrcd_idr, &obj->uobject);
+	if (ret)
+		goto err_idr;
+
+	memset(&resp, 0, sizeof resp);
+	resp.xrcd_handle = obj->uobject.id;
+
+	if (inode) {
+		if (new_xrcd) {
+			/* create new inode/xrcd table entry */
+			ret = xrcd_table_insert(file->device, inode, xrcd);
+			if (ret)
+				goto err_insert_xrcd;
+		}
+		atomic_inc(&xrcd->usecnt);
+	}
+
+	if (copy_to_user((void __user *) (unsigned long) cmd.response,
+			 &resp, sizeof resp)) {
+		ret = -EFAULT;
+		goto err_copy;
+	}
+
+	if (f)
+		fput(f);
+
+	mutex_lock(&file->mutex);
+	list_add_tail(&obj->uobject.list, &file->ucontext->xrcd_list);
+	mutex_unlock(&file->mutex);
+
+	obj->uobject.live = 1;
+	up_write(&obj->uobject.mutex);
+
+	mutex_unlock(&file->device->xrcd_tree_mutex);
+	return in_len;
+
+err_copy:
+	if (inode) {
+		if (new_xrcd)
+			xrcd_table_delete(file->device, inode);
+		atomic_dec(&xrcd->usecnt);
+	}
+
+err_insert_xrcd:
+	idr_remove_uobj(&ib_uverbs_xrcd_idr, &obj->uobject);
+
+err_idr:
+	ib_dealloc_xrcd(xrcd);
+
+err:
+	put_uobj_write(&obj->uobject);
+
+err_tree_mutex_unlock:
+	if (f)
+		fput(f);
+
+	mutex_unlock(&file->device->xrcd_tree_mutex);
+
+	return ret;
+}
+
+ssize_t ib_uverbs_close_xrcd(struct ib_uverbs_file *file,
+			     const char __user *buf, int in_len,
+			     int out_len)
+{
+	struct ib_uverbs_close_xrcd cmd;
+	struct ib_uobject           *uobj;
+	struct ib_xrcd              *xrcd = NULL;
+	struct inode                *inode = NULL;
+	struct ib_uxrcd_object      *obj;
+	int                         live;
+	int                         ret = 0;
+
+	if (copy_from_user(&cmd, buf, sizeof cmd))
+		return -EFAULT;
+
+	mutex_lock(&file->device->xrcd_tree_mutex);
+	uobj = idr_write_uobj(&ib_uverbs_xrcd_idr, cmd.xrcd_handle, file->ucontext);
+	if (!uobj) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	xrcd  = uobj->object;
+	inode = xrcd->inode;
+	obj   = container_of(uobj, struct ib_uxrcd_object, uobject);
+	if (atomic_read(&obj->refcnt)) {
+		put_uobj_write(uobj);
+		ret = -EBUSY;
+		goto out;
+	}
+
+	if (!inode || atomic_dec_and_test(&xrcd->usecnt)) {
+		ret = ib_dealloc_xrcd(uobj->object);
+		if (!ret)
+			uobj->live = 0;
+	}
+
+	live = uobj->live;
+	if (inode && ret)
+		atomic_inc(&xrcd->usecnt);
+
+	put_uobj_write(uobj);
+
+	if (ret)
+		goto out;
+
+	if (inode && !live)
+		xrcd_table_delete(file->device, inode);
+
+	idr_remove_uobj(&ib_uverbs_xrcd_idr, uobj);
+	mutex_lock(&file->mutex);
+	list_del(&uobj->list);
+	mutex_unlock(&file->mutex);
+
+	put_uobj(uobj);
+	ret = in_len;
+
+out:
+	mutex_unlock(&file->device->xrcd_tree_mutex);
+	return ret;
+}
+
+void ib_uverbs_dealloc_xrcd(struct ib_uverbs_device *dev,
+			    struct ib_xrcd *xrcd)
+{
+	struct inode *inode;
+
+	inode = xrcd->inode;
+	if (inode && !atomic_dec_and_test(&xrcd->usecnt))
+		return;
+
+	ib_dealloc_xrcd(xrcd);
+
+	if (inode)
+		xrcd_table_delete(dev, inode);
+}
+
 ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
 			 const char __user *buf, int in_len,
 			 int out_len)
@@ -1052,9 +1370,12 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
 	struct ib_uverbs_create_qp_resp resp;
 	struct ib_udata                 udata;
 	struct ib_uqp_object           *obj;
-	struct ib_pd                   *pd;
-	struct ib_cq                   *scq, *rcq;
-	struct ib_srq                  *srq;
+	struct ib_device	       *device;
+	struct ib_pd                   *pd = NULL;
+	struct ib_xrcd		       *xrcd = NULL;
+	struct ib_uobject	       *uninitialized_var(xrcd_uobj);
+	struct ib_cq                   *scq = NULL, *rcq = NULL;
+	struct ib_srq                  *srq = NULL;
 	struct ib_qp                   *qp;
 	struct ib_qp_init_attr          attr;
 	int ret;
@@ -1076,15 +1397,39 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
 	init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_key);
 	down_write(&obj->uevent.uobject.mutex);
 
-	srq = cmd.is_srq ? idr_read_srq(cmd.srq_handle, file->ucontext) : NULL;
-	pd  = idr_read_pd(cmd.pd_handle, file->ucontext);
-	scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, 0);
-	rcq = cmd.recv_cq_handle == cmd.send_cq_handle ?
-		scq : idr_read_cq(cmd.recv_cq_handle, file->ucontext, 1);
+	if (cmd.qp_type == IB_QPT_XRC_TGT) {
+		xrcd = idr_read_xrcd(cmd.pd_handle, file->ucontext, &xrcd_uobj);
+		if (!xrcd) {
+			ret = -EINVAL;
+			goto err_put;
+		}
+		device = xrcd->device;
+	} else {
+		pd  = idr_read_pd(cmd.pd_handle, file->ucontext);
+		scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, 0);
+		if (!pd || !scq) {
+			ret = -EINVAL;
+			goto err_put;
+		}
 
-	if (!pd || !scq || !rcq || (cmd.is_srq && !srq)) {
-		ret = -EINVAL;
-		goto err_put;
+		if (cmd.qp_type == IB_QPT_XRC_INI) {
+			cmd.max_recv_wr = cmd.max_recv_sge = 0;
+		} else {
+			if (cmd.is_srq) {
+				srq = idr_read_srq(cmd.srq_handle, file->ucontext);
+				if (!srq || srq->srq_type != IB_SRQT_BASIC) {
+					ret = -EINVAL;
+					goto err_put;
+				}
+			}
+			rcq = (cmd.recv_cq_handle == cmd.send_cq_handle) ?
+			       scq : idr_read_cq(cmd.recv_cq_handle, file->ucontext, 1);
+			if (!rcq) {
+				ret = -EINVAL;
+				goto err_put;
+			}
+		}
+		device = pd->device;
 	}
 
 	attr.event_handler = ib_uverbs_qp_event_handler;
@@ -1092,6 +1437,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
 	attr.send_cq       = scq;
 	attr.recv_cq       = rcq;
 	attr.srq           = srq;
+	attr.xrcd	   = xrcd;
 	attr.sq_sig_type   = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR;
 	attr.qp_type       = cmd.qp_type;
 	attr.create_flags  = 0;
@@ -1106,26 +1452,34 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
 	INIT_LIST_HEAD(&obj->uevent.event_list);
 	INIT_LIST_HEAD(&obj->mcast_list);
 
-	qp = pd->device->create_qp(pd, &attr, &udata);
+	if (cmd.qp_type == IB_QPT_XRC_TGT)
+		qp = ib_create_qp(pd, &attr);
+	else
+		qp = device->create_qp(pd, &attr, &udata);
+
 	if (IS_ERR(qp)) {
 		ret = PTR_ERR(qp);
 		goto err_put;
 	}
 
-	qp->device     	  = pd->device;
-	qp->pd         	  = pd;
-	qp->send_cq    	  = attr.send_cq;
-	qp->recv_cq    	  = attr.recv_cq;
-	qp->srq	       	  = attr.srq;
-	qp->uobject       = &obj->uevent.uobject;
-	qp->event_handler = attr.event_handler;
-	qp->qp_context    = attr.qp_context;
-	qp->qp_type	  = attr.qp_type;
-	atomic_inc(&pd->usecnt);
-	atomic_inc(&attr.send_cq->usecnt);
-	atomic_inc(&attr.recv_cq->usecnt);
-	if (attr.srq)
-		atomic_inc(&attr.srq->usecnt);
+	if (cmd.qp_type != IB_QPT_XRC_TGT) {
+		qp->real_qp	  = qp;
+		qp->device	  = device;
+		qp->pd		  = pd;
+		qp->send_cq	  = attr.send_cq;
+		qp->recv_cq	  = attr.recv_cq;
+		qp->srq		  = attr.srq;
+		qp->event_handler = attr.event_handler;
+		qp->qp_context	  = attr.qp_context;
+		qp->qp_type	  = attr.qp_type;
+		atomic_inc(&pd->usecnt);
+		atomic_inc(&attr.send_cq->usecnt);
+		if (attr.recv_cq)
+			atomic_inc(&attr.recv_cq->usecnt);
+		if (attr.srq)
+			atomic_inc(&attr.srq->usecnt);
+	}
+	qp->uobject = &obj->uevent.uobject;
 
 	obj->uevent.uobject.object = qp;
 	ret = idr_add_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
@@ -1147,9 +1501,13 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
 		goto err_copy;
 	}
 
-	put_pd_read(pd);
-	put_cq_read(scq);
-	if (rcq != scq)
+	if (xrcd)
+		put_xrcd_read(xrcd_uobj);
+	if (pd)
+		put_pd_read(pd);
+	if (scq)
+		put_cq_read(scq);
+	if (rcq && rcq != scq)
 		put_cq_read(rcq);
 	if (srq)
 		put_srq_read(srq);
@@ -1171,6 +1529,8 @@ err_destroy:
 	ib_destroy_qp(qp);
 
 err_put:
+	if (xrcd)
+		put_xrcd_read(xrcd_uobj);
 	if (pd)
 		put_pd_read(pd);
 	if (scq)
@@ -1184,6 +1544,98 @@ err_put:
 	return ret;
 }
 
+ssize_t ib_uverbs_open_qp(struct ib_uverbs_file *file,
+			  const char __user *buf, int in_len, int out_len)
+{
+	struct ib_uverbs_open_qp        cmd;
+	struct ib_uverbs_create_qp_resp resp;
+	struct ib_udata                 udata;
+	struct ib_uqp_object           *obj;
+	struct ib_xrcd		       *xrcd;
+	struct ib_uobject	       *uninitialized_var(xrcd_uobj);
+	struct ib_qp                   *qp;
+	struct ib_qp_open_attr          attr;
+	int ret;
+
+	if (out_len < sizeof resp)
+		return -ENOSPC;
+
+	if (copy_from_user(&cmd, buf, sizeof cmd))
+		return -EFAULT;
+
+	INIT_UDATA(&udata, buf + sizeof cmd,
+		   (unsigned long) cmd.response + sizeof resp,
+		   in_len - sizeof cmd, out_len - sizeof resp);
+
+	obj = kmalloc(sizeof *obj, GFP_KERNEL);
+	if (!obj)
+		return -ENOMEM;
+
+	init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_key);
+	down_write(&obj->uevent.uobject.mutex);
+
+	xrcd = idr_read_xrcd(cmd.pd_handle, file->ucontext, &xrcd_uobj);
+	if (!xrcd) {
+		ret = -EINVAL;
+		goto err_put;
+	}
+
+	attr.event_handler = ib_uverbs_qp_event_handler;
+	attr.qp_context    = file;
+	attr.qp_num        = cmd.qpn;
+	attr.qp_type       = cmd.qp_type;
+
+	obj->uevent.events_reported = 0;
+	INIT_LIST_HEAD(&obj->uevent.event_list);
+	INIT_LIST_HEAD(&obj->mcast_list);
+
+	qp = ib_open_qp(xrcd, &attr);
+	if (IS_ERR(qp)) {
+		ret = PTR_ERR(qp);
+		goto err_put;
+	}
+
+	qp->uobject = &obj->uevent.uobject;
+
+	obj->uevent.uobject.object = qp;
+	ret = idr_add_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
+	if (ret)
+		goto err_destroy;
+
+	memset(&resp, 0, sizeof resp);
+	resp.qpn       = qp->qp_num;
+	resp.qp_handle = obj->uevent.uobject.id;
+
+	if (copy_to_user((void __user *) (unsigned long) cmd.response,
+			 &resp, sizeof resp)) {
+		ret = -EFAULT;
+		goto err_remove;
+	}
+
+	put_xrcd_read(xrcd_uobj);
+
+	mutex_lock(&file->mutex);
+	list_add_tail(&obj->uevent.uobject.list, &file->ucontext->qp_list);
+	mutex_unlock(&file->mutex);
+
+	obj->uevent.uobject.live = 1;
+
+	up_write(&obj->uevent.uobject.mutex);
+
+	return in_len;
+
+err_remove:
+	idr_remove_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
+
+err_destroy:
+	ib_destroy_qp(qp);
+
+err_put:
+	put_xrcd_read(xrcd_uobj);
+	put_uobj_write(&obj->uevent.uobject);
+	return ret;
+}
+
 ssize_t ib_uverbs_query_qp(struct ib_uverbs_file *file,
 			   const char __user *buf, int in_len,
 			   int out_len)
@@ -1284,6 +1736,20 @@ out:
 	return ret ? ret : in_len;
 }
 
+/* Remove ignored fields set in the attribute mask */
+static int modify_qp_mask(enum ib_qp_type qp_type, int mask)
+{
+	switch (qp_type) {
+	case IB_QPT_XRC_INI:
+		return mask & ~(IB_QP_MAX_DEST_RD_ATOMIC | IB_QP_MIN_RNR_TIMER);
+	case IB_QPT_XRC_TGT:
+		return mask & ~(IB_QP_MAX_QP_RD_ATOMIC | IB_QP_RETRY_CNT |
+				IB_QP_RNR_RETRY);
+	default:
+		return mask;
+	}
+}
+
 ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
 			    const char __user *buf, int in_len,
 			    int out_len)
@@ -1356,7 +1822,12 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
 	attr->alt_ah_attr.ah_flags 	    = cmd.alt_dest.is_global ? IB_AH_GRH : 0;
 	attr->alt_ah_attr.port_num 	    = cmd.alt_dest.port_num;
 
-	ret = qp->device->modify_qp(qp, attr, cmd.attr_mask, &udata);
+	if (qp->real_qp == qp) {
+		ret = qp->device->modify_qp(qp, attr,
+			modify_qp_mask(qp->qp_type, cmd.attr_mask), &udata);
+	} else {
+		ret = ib_modify_qp(qp, attr, modify_qp_mask(qp->qp_type, cmd.attr_mask));
+	}
 
 	put_qp_read(qp);
 
@@ -1553,7 +2024,7 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
 	}
 
 	resp.bad_wr = 0;
-	ret = qp->device->post_send(qp, wr, &bad_wr);
+	ret = qp->device->post_send(qp->real_qp, wr, &bad_wr);
 	if (ret)
 		for (next = wr; next; next = next->next) {
 			++resp.bad_wr;
@@ -1691,7 +2162,7 @@ ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file,
 		goto out;
 
 	resp.bad_wr = 0;
-	ret = qp->device->post_recv(qp, wr, &bad_wr);
+	ret = qp->device->post_recv(qp->real_qp, wr, &bad_wr);
 
 	put_qp_read(qp);
 
@@ -1975,107 +2446,199 @@ out_put:
 	return ret ? ret : in_len;
 }
 
-ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
-			     const char __user *buf, int in_len,
-			     int out_len)
+int __uverbs_create_xsrq(struct ib_uverbs_file *file,
+			 struct ib_uverbs_create_xsrq *cmd,
+			 struct ib_udata *udata)
 {
-	struct ib_uverbs_create_srq      cmd;
 	struct ib_uverbs_create_srq_resp resp;
-	struct ib_udata                  udata;
-	struct ib_uevent_object         *obj;
+	struct ib_usrq_object           *obj;
 	struct ib_pd                    *pd;
 	struct ib_srq                   *srq;
+	struct ib_uobject               *uninitialized_var(xrcd_uobj);
 	struct ib_srq_init_attr          attr;
 	int ret;
 
-	if (out_len < sizeof resp)
-		return -ENOSPC;
-
-	if (copy_from_user(&cmd, buf, sizeof cmd))
-		return -EFAULT;
-
-	INIT_UDATA(&udata, buf + sizeof cmd,
-		   (unsigned long) cmd.response + sizeof resp,
-		   in_len - sizeof cmd, out_len - sizeof resp);
-
 	obj = kmalloc(sizeof *obj, GFP_KERNEL);
 	if (!obj)
 		return -ENOMEM;
 
-	init_uobj(&obj->uobject, cmd.user_handle, file->ucontext, &srq_lock_key);
-	down_write(&obj->uobject.mutex);
+	init_uobj(&obj->uevent.uobject, cmd->user_handle, file->ucontext, &srq_lock_key);
+	down_write(&obj->uevent.uobject.mutex);
 
-	pd  = idr_read_pd(cmd.pd_handle, file->ucontext);
+	pd  = idr_read_pd(cmd->pd_handle, file->ucontext);
 	if (!pd) {
 		ret = -EINVAL;
 		goto err;
 	}
 
+	if (cmd->srq_type == IB_SRQT_XRC) {
+		attr.ext.xrc.cq  = idr_read_cq(cmd->cq_handle, file->ucontext, 0);
+		if (!attr.ext.xrc.cq) {
+			ret = -EINVAL;
+			goto err_put_pd;
+		}
+
+		attr.ext.xrc.xrcd  = idr_read_xrcd(cmd->xrcd_handle, file->ucontext, &xrcd_uobj);
+		if (!attr.ext.xrc.xrcd) {
+			ret = -EINVAL;
+			goto err_put_cq;
+		}
+
+		obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object, uobject);
+		atomic_inc(&obj->uxrcd->refcnt);
+	}
+
 	attr.event_handler  = ib_uverbs_srq_event_handler;
 	attr.srq_context    = file;
-	attr.attr.max_wr    = cmd.max_wr;
-	attr.attr.max_sge   = cmd.max_sge;
-	attr.attr.srq_limit = cmd.srq_limit;
+	attr.srq_type       = cmd->srq_type;
+	attr.attr.max_wr    = cmd->max_wr;
+	attr.attr.max_sge   = cmd->max_sge;
+	attr.attr.srq_limit = cmd->srq_limit;
 
-	obj->events_reported     = 0;
-	INIT_LIST_HEAD(&obj->event_list);
+	obj->uevent.events_reported = 0;
+	INIT_LIST_HEAD(&obj->uevent.event_list);
 
-	srq = pd->device->create_srq(pd, &attr, &udata);
+	srq = pd->device->create_srq(pd, &attr, udata);
 	if (IS_ERR(srq)) {
 		ret = PTR_ERR(srq);
 		goto err_put;
 	}
 
-	srq->device    	   = pd->device;
-	srq->pd        	   = pd;
-	srq->uobject       = &obj->uobject;
+	srq->device        = pd->device;
+	srq->pd            = pd;
+	srq->srq_type	   = cmd->srq_type;
+	srq->uobject       = &obj->uevent.uobject;
 	srq->event_handler = attr.event_handler;
 	srq->srq_context   = attr.srq_context;
+
+	if (cmd->srq_type == IB_SRQT_XRC) {
+		srq->ext.xrc.cq   = attr.ext.xrc.cq;
+		srq->ext.xrc.xrcd = attr.ext.xrc.xrcd;
+		atomic_inc(&attr.ext.xrc.cq->usecnt);
+		atomic_inc(&attr.ext.xrc.xrcd->usecnt);
+	}
+
 	atomic_inc(&pd->usecnt);
 	atomic_set(&srq->usecnt, 0);
 
-	obj->uobject.object = srq;
-	ret = idr_add_uobj(&ib_uverbs_srq_idr, &obj->uobject);
+	obj->uevent.uobject.object = srq;
+	ret = idr_add_uobj(&ib_uverbs_srq_idr, &obj->uevent.uobject);
 	if (ret)
 		goto err_destroy;
 
 	memset(&resp, 0, sizeof resp);
-	resp.srq_handle = obj->uobject.id;
+	resp.srq_handle = obj->uevent.uobject.id;
 	resp.max_wr     = attr.attr.max_wr;
 	resp.max_sge    = attr.attr.max_sge;
+	if (cmd->srq_type == IB_SRQT_XRC)
+		resp.srqn = srq->ext.xrc.srq_num;
 
-	if (copy_to_user((void __user *) (unsigned long) cmd.response,
+	if (copy_to_user((void __user *) (unsigned long) cmd->response,
 			 &resp, sizeof resp)) {
 		ret = -EFAULT;
 		goto err_copy;
 	}
 
+	if (cmd->srq_type == IB_SRQT_XRC) {
+		put_uobj_read(xrcd_uobj);
+		put_cq_read(attr.ext.xrc.cq);
+	}
 	put_pd_read(pd);
 
 	mutex_lock(&file->mutex);
-	list_add_tail(&obj->uobject.list, &file->ucontext->srq_list);
+	list_add_tail(&obj->uevent.uobject.list, &file->ucontext->srq_list);
 	mutex_unlock(&file->mutex);
 
-	obj->uobject.live = 1;
+	obj->uevent.uobject.live = 1;
 
-	up_write(&obj->uobject.mutex);
+	up_write(&obj->uevent.uobject.mutex);
 
-	return in_len;
+	return 0;
 
 err_copy:
-	idr_remove_uobj(&ib_uverbs_srq_idr, &obj->uobject);
+	idr_remove_uobj(&ib_uverbs_srq_idr, &obj->uevent.uobject);
 
 err_destroy:
 	ib_destroy_srq(srq);
 
 err_put:
+	if (cmd->srq_type == IB_SRQT_XRC) {
+		atomic_dec(&obj->uxrcd->refcnt);
+		put_uobj_read(xrcd_uobj);
+	}
+
+err_put_cq:
+	if (cmd->srq_type == IB_SRQT_XRC)
+		put_cq_read(attr.ext.xrc.cq);
+
+err_put_pd:
 	put_pd_read(pd);
 
 err:
-	put_uobj_write(&obj->uobject);
+	put_uobj_write(&obj->uevent.uobject);
 	return ret;
 }
 
+ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
+			     const char __user *buf, int in_len,
+			     int out_len)
+{
+	struct ib_uverbs_create_srq      cmd;
+	struct ib_uverbs_create_xsrq     xcmd;
+	struct ib_uverbs_create_srq_resp resp;
+	struct ib_udata                  udata;
+	int ret;
+
+	if (out_len < sizeof resp)
+		return -ENOSPC;
+
+	if (copy_from_user(&cmd, buf, sizeof cmd))
+		return -EFAULT;
+
+	xcmd.response	 = cmd.response;
+	xcmd.user_handle = cmd.user_handle;
+	xcmd.srq_type	 = IB_SRQT_BASIC;
+	xcmd.pd_handle	 = cmd.pd_handle;
+	xcmd.max_wr	 = cmd.max_wr;
+	xcmd.max_sge	 = cmd.max_sge;
+	xcmd.srq_limit	 = cmd.srq_limit;
+
+	INIT_UDATA(&udata, buf + sizeof cmd,
+		   (unsigned long) cmd.response + sizeof resp,
+		   in_len - sizeof cmd, out_len - sizeof resp);
+
+	ret = __uverbs_create_xsrq(file, &xcmd, &udata);
+	if (ret)
+		return ret;
+
+	return in_len;
+}
+
+ssize_t ib_uverbs_create_xsrq(struct ib_uverbs_file *file,
+			      const char __user *buf, int in_len, int out_len)
+{
+	struct ib_uverbs_create_xsrq     cmd;
+	struct ib_uverbs_create_srq_resp resp;
+	struct ib_udata                  udata;
+	int ret;
+
+	if (out_len < sizeof resp)
+		return -ENOSPC;
+
+	if (copy_from_user(&cmd, buf, sizeof cmd))
+		return -EFAULT;
+
+	INIT_UDATA(&udata, buf + sizeof cmd,
+		   (unsigned long) cmd.response + sizeof resp,
+		   in_len - sizeof cmd, out_len - sizeof resp);
+
+	ret = __uverbs_create_xsrq(file, &cmd, &udata);
+	if (ret)
+		return ret;
+
+	return in_len;
+}
+
 ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
 			     const char __user *buf, int in_len,
 			     int out_len)
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 56898b6..8796367 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -72,6 +72,7 @@ DEFINE_IDR(ib_uverbs_ah_idr);
 DEFINE_IDR(ib_uverbs_cq_idr);
 DEFINE_IDR(ib_uverbs_qp_idr);
 DEFINE_IDR(ib_uverbs_srq_idr);
+DEFINE_IDR(ib_uverbs_xrcd_idr);
 
 static DEFINE_SPINLOCK(map_lock);
 static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES);
@@ -107,6 +108,10 @@ static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,
 	[IB_USER_VERBS_CMD_MODIFY_SRQ]		= ib_uverbs_modify_srq,
 	[IB_USER_VERBS_CMD_QUERY_SRQ]		= ib_uverbs_query_srq,
 	[IB_USER_VERBS_CMD_DESTROY_SRQ]		= ib_uverbs_destroy_srq,
+	[IB_USER_VERBS_CMD_OPEN_XRCD]		= ib_uverbs_open_xrcd,
+	[IB_USER_VERBS_CMD_CLOSE_XRCD]		= ib_uverbs_close_xrcd,
+	[IB_USER_VERBS_CMD_CREATE_XSRQ]		= ib_uverbs_create_xsrq,
+	[IB_USER_VERBS_CMD_OPEN_QP]		= ib_uverbs_open_qp
 };
 
 static void ib_uverbs_add_one(struct ib_device *device);
@@ -202,8 +207,12 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
 			container_of(uobj, struct ib_uqp_object, uevent.uobject);
 
 		idr_remove_uobj(&ib_uverbs_qp_idr, uobj);
-		ib_uverbs_detach_umcast(qp, uqp);
-		ib_destroy_qp(qp);
+		if (qp != qp->real_qp) {
+			ib_close_qp(qp);
+		} else {
+			ib_uverbs_detach_umcast(qp, uqp);
+			ib_destroy_qp(qp);
+		}
 		ib_uverbs_release_uevent(file, &uqp->uevent);
 		kfree(uqp);
 	}
@@ -241,6 +250,18 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
 		kfree(uobj);
 	}
 
+	mutex_lock(&file->device->xrcd_tree_mutex);
+	list_for_each_entry_safe(uobj, tmp, &context->xrcd_list, list) {
+		struct ib_xrcd *xrcd = uobj->object;
+		struct ib_uxrcd_object *uxrcd =
+			container_of(uobj, struct ib_uxrcd_object, uobject);
+
+		idr_remove_uobj(&ib_uverbs_xrcd_idr, uobj);
+		ib_uverbs_dealloc_xrcd(file->device, xrcd);
+		kfree(uxrcd);
+	}
+	mutex_unlock(&file->device->xrcd_tree_mutex);
+
 	list_for_each_entry_safe(uobj, tmp, &context->pd_list, list) {
 		struct ib_pd *pd = uobj->object;
 
@@ -557,8 +578,7 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
 	if (hdr.in_words * 4 != count)
 		return -EINVAL;
 
-	if (hdr.command < 0				||
-	    hdr.command >= ARRAY_SIZE(uverbs_cmd_table) ||
+	if (hdr.command >= ARRAY_SIZE(uverbs_cmd_table) ||
 	    !uverbs_cmd_table[hdr.command])
 		return -EINVAL;
 
@@ -741,6 +761,8 @@ static void ib_uverbs_add_one(struct ib_device *device)
 
 	kref_init(&uverbs_dev->ref);
 	init_completion(&uverbs_dev->comp);
+	uverbs_dev->xrcd_tree = RB_ROOT;
+	mutex_init(&uverbs_dev->xrcd_tree_mutex);
 
 	spin_lock(&map_lock);
 	devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES);
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index af7a8b0..4251750 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -39,6 +39,7 @@
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/string.h>
+#include <linux/slab.h>
 
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_cache.h>
@@ -77,6 +78,31 @@ enum ib_rate mult_to_ib_rate(int mult)
 }
 EXPORT_SYMBOL(mult_to_ib_rate);
 
+int ib_rate_to_mbps(enum ib_rate rate)
+{
+	switch (rate) {
+	case IB_RATE_2_5_GBPS: return 2500;
+	case IB_RATE_5_GBPS:   return 5000;
+	case IB_RATE_10_GBPS:  return 10000;
+	case IB_RATE_20_GBPS:  return 20000;
+	case IB_RATE_30_GBPS:  return 30000;
+	case IB_RATE_40_GBPS:  return 40000;
+	case IB_RATE_60_GBPS:  return 60000;
+	case IB_RATE_80_GBPS:  return 80000;
+	case IB_RATE_120_GBPS: return 120000;
+	case IB_RATE_14_GBPS:  return 14062;
+	case IB_RATE_56_GBPS:  return 56250;
+	case IB_RATE_112_GBPS: return 112500;
+	case IB_RATE_168_GBPS: return 168750;
+	case IB_RATE_25_GBPS:  return 25781;
+	case IB_RATE_100_GBPS: return 103125;
+	case IB_RATE_200_GBPS: return 206250;
+	case IB_RATE_300_GBPS: return 309375;
+	default:	       return -1;
+	}
+}
+EXPORT_SYMBOL(ib_rate_to_mbps);
+
 enum rdma_transport_type
 rdma_node_get_transport(enum rdma_node_type node_type)
 {
@@ -250,6 +276,13 @@ struct ib_srq *ib_create_srq(struct ib_pd *pd,
 		srq->uobject       = NULL;
 		srq->event_handler = srq_init_attr->event_handler;
 		srq->srq_context   = srq_init_attr->srq_context;
+		srq->srq_type      = srq_init_attr->srq_type;
+		if (srq->srq_type == IB_SRQT_XRC) {
+			srq->ext.xrc.xrcd = srq_init_attr->ext.xrc.xrcd;
+			srq->ext.xrc.cq   = srq_init_attr->ext.xrc.cq;
+			atomic_inc(&srq->ext.xrc.xrcd->usecnt);
+			atomic_inc(&srq->ext.xrc.cq->usecnt);
+		}
 		atomic_inc(&pd->usecnt);
 		atomic_set(&srq->usecnt, 0);
 	}
@@ -279,16 +312,29 @@ EXPORT_SYMBOL(ib_query_srq);
 int ib_destroy_srq(struct ib_srq *srq)
 {
 	struct ib_pd *pd;
+	enum ib_srq_type srq_type;
+	struct ib_xrcd *uninitialized_var(xrcd);
+	struct ib_cq *uninitialized_var(cq);
 	int ret;
 
 	if (atomic_read(&srq->usecnt))
 		return -EBUSY;
 
 	pd = srq->pd;
+	srq_type = srq->srq_type;
+	if (srq_type == IB_SRQT_XRC) {
+		xrcd = srq->ext.xrc.xrcd;
+		cq = srq->ext.xrc.cq;
+	}
 
 	ret = srq->device->destroy_srq(srq);
-	if (!ret)
+	if (!ret) {
 		atomic_dec(&pd->usecnt);
+		if (srq_type == IB_SRQT_XRC) {
+			atomic_dec(&xrcd->usecnt);
+			atomic_dec(&cq->usecnt);
+		}
+	}
 
 	return ret;
 }
@@ -296,28 +342,123 @@ EXPORT_SYMBOL(ib_destroy_srq);
 
 /* Queue pairs */
 
+static void __ib_shared_qp_event_handler(struct ib_event *event, void *context)
+{
+	struct ib_qp *qp = context;
+
+	list_for_each_entry(event->element.qp, &qp->open_list, open_list)
+		event->element.qp->event_handler(event, event->element.qp->qp_context);
+}
+
+static void __ib_insert_xrcd_qp(struct ib_xrcd *xrcd, struct ib_qp *qp)
+{
+	mutex_lock(&xrcd->tgt_qp_mutex);
+	list_add(&qp->xrcd_list, &xrcd->tgt_qp_list);
+	mutex_unlock(&xrcd->tgt_qp_mutex);
+}
+
+static struct ib_qp *__ib_open_qp(struct ib_qp *real_qp,
+				  void (*event_handler)(struct ib_event *, void *),
+				  void *qp_context)
+{
+	struct ib_qp *qp;
+	unsigned long flags;
+
+	qp = kzalloc(sizeof *qp, GFP_KERNEL);
+	if (!qp)
+		return ERR_PTR(-ENOMEM);
+
+	qp->real_qp = real_qp;
+	atomic_inc(&real_qp->usecnt);
+	qp->device = real_qp->device;
+	qp->event_handler = event_handler;
+	qp->qp_context = qp_context;
+	qp->qp_num = real_qp->qp_num;
+	qp->qp_type = real_qp->qp_type;
+
+	spin_lock_irqsave(&real_qp->device->event_handler_lock, flags);
+	list_add(&qp->open_list, &real_qp->open_list);
+	spin_unlock_irqrestore(&real_qp->device->event_handler_lock, flags);
+
+	return qp;
+}
+
+struct ib_qp *ib_open_qp(struct ib_xrcd *xrcd,
+			 struct ib_qp_open_attr *qp_open_attr)
+{
+	struct ib_qp *qp, *real_qp;
+
+	if (qp_open_attr->qp_type != IB_QPT_XRC_TGT)
+		return ERR_PTR(-EINVAL);
+
+	qp = ERR_PTR(-EINVAL);
+	mutex_lock(&xrcd->tgt_qp_mutex);
+	list_for_each_entry(real_qp, &xrcd->tgt_qp_list, xrcd_list) {
+		if (real_qp->qp_num == qp_open_attr->qp_num) {
+			qp = __ib_open_qp(real_qp, qp_open_attr->event_handler,
+					  qp_open_attr->qp_context);
+			break;
+		}
+	}
+	mutex_unlock(&xrcd->tgt_qp_mutex);
+	return qp;
+}
+EXPORT_SYMBOL(ib_open_qp);
+
 struct ib_qp *ib_create_qp(struct ib_pd *pd,
 			   struct ib_qp_init_attr *qp_init_attr)
 {
-	struct ib_qp *qp;
+	struct ib_qp *qp, *real_qp;
+	struct ib_device *device;
 
-	qp = pd->device->create_qp(pd, qp_init_attr, NULL);
+	device = pd ? pd->device : qp_init_attr->xrcd->device;
+	qp = device->create_qp(pd, qp_init_attr, NULL);
 
 	if (!IS_ERR(qp)) {
-		qp->device     	  = pd->device;
-		qp->pd         	  = pd;
-		qp->send_cq    	  = qp_init_attr->send_cq;
-		qp->recv_cq    	  = qp_init_attr->recv_cq;
-		qp->srq	       	  = qp_init_attr->srq;
-		qp->uobject       = NULL;
-		qp->event_handler = qp_init_attr->event_handler;
-		qp->qp_context    = qp_init_attr->qp_context;
-		qp->qp_type	  = qp_init_attr->qp_type;
-		atomic_inc(&pd->usecnt);
-		atomic_inc(&qp_init_attr->send_cq->usecnt);
-		atomic_inc(&qp_init_attr->recv_cq->usecnt);
-		if (qp_init_attr->srq)
-			atomic_inc(&qp_init_attr->srq->usecnt);
+		qp->device     = device;
+		qp->real_qp    = qp;
+		qp->uobject    = NULL;
+		qp->qp_type    = qp_init_attr->qp_type;
+
+		if (qp_init_attr->qp_type == IB_QPT_XRC_TGT) {
+			qp->event_handler = __ib_shared_qp_event_handler;
+			qp->qp_context = qp;
+			qp->pd = NULL;
+			qp->send_cq = qp->recv_cq = NULL;
+			qp->srq = NULL;
+			qp->xrcd = qp_init_attr->xrcd;
+			atomic_inc(&qp_init_attr->xrcd->usecnt);
+			INIT_LIST_HEAD(&qp->open_list);
+			atomic_set(&qp->usecnt, 0);
+
+			real_qp = qp;
+			qp = __ib_open_qp(real_qp, qp_init_attr->event_handler,
+					  qp_init_attr->qp_context);
+			if (!IS_ERR(qp))
+				__ib_insert_xrcd_qp(qp_init_attr->xrcd, real_qp);
+			else
+				real_qp->device->destroy_qp(real_qp);
+		} else {
+			qp->event_handler = qp_init_attr->event_handler;
+			qp->qp_context = qp_init_attr->qp_context;
+			if (qp_init_attr->qp_type == IB_QPT_XRC_INI) {
+				qp->recv_cq = NULL;
+				qp->srq = NULL;
+			} else {
+				qp->recv_cq = qp_init_attr->recv_cq;
+				atomic_inc(&qp_init_attr->recv_cq->usecnt);
+				qp->srq = qp_init_attr->srq;
+				if (qp->srq)
+					atomic_inc(&qp_init_attr->srq->usecnt);
+			}
+
+			qp->pd	    = pd;
+			qp->send_cq = qp_init_attr->send_cq;
+			qp->xrcd    = NULL;
+
+			atomic_inc(&pd->usecnt);
+			atomic_inc(&qp_init_attr->send_cq->usecnt);
+		}
 	}
 
 	return qp;
@@ -326,8 +467,8 @@ EXPORT_SYMBOL(ib_create_qp);
 
 static const struct {
 	int			valid;
-	enum ib_qp_attr_mask	req_param[IB_QPT_RAW_ETHERTYPE + 1];
-	enum ib_qp_attr_mask	opt_param[IB_QPT_RAW_ETHERTYPE + 1];
+	enum ib_qp_attr_mask	req_param[IB_QPT_MAX];
+	enum ib_qp_attr_mask	opt_param[IB_QPT_MAX];
 } qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = {
 	[IB_QPS_RESET] = {
 		[IB_QPS_RESET] = { .valid = 1 },
@@ -343,6 +484,12 @@ static const struct {
 				[IB_QPT_RC]  = (IB_QP_PKEY_INDEX		|
 						IB_QP_PORT			|
 						IB_QP_ACCESS_FLAGS),
+				[IB_QPT_XRC_INI] = (IB_QP_PKEY_INDEX		|
+						IB_QP_PORT			|
+						IB_QP_ACCESS_FLAGS),
+				[IB_QPT_XRC_TGT] = (IB_QP_PKEY_INDEX		|
+						IB_QP_PORT			|
+						IB_QP_ACCESS_FLAGS),
 				[IB_QPT_SMI] = (IB_QP_PKEY_INDEX		|
 						IB_QP_QKEY),
 				[IB_QPT_GSI] = (IB_QP_PKEY_INDEX		|
@@ -365,6 +512,12 @@ static const struct {
 				[IB_QPT_RC]  = (IB_QP_PKEY_INDEX		|
 						IB_QP_PORT			|
 						IB_QP_ACCESS_FLAGS),
+				[IB_QPT_XRC_INI] = (IB_QP_PKEY_INDEX		|
+						IB_QP_PORT			|
+						IB_QP_ACCESS_FLAGS),
+				[IB_QPT_XRC_TGT] = (IB_QP_PKEY_INDEX		|
+						IB_QP_PORT			|
+						IB_QP_ACCESS_FLAGS),
 				[IB_QPT_SMI] = (IB_QP_PKEY_INDEX		|
 						IB_QP_QKEY),
 				[IB_QPT_GSI] = (IB_QP_PKEY_INDEX		|
@@ -384,6 +537,16 @@ static const struct {
 						IB_QP_RQ_PSN			|
 						IB_QP_MAX_DEST_RD_ATOMIC	|
 						IB_QP_MIN_RNR_TIMER),
+				[IB_QPT_XRC_INI] = (IB_QP_AV			|
+						IB_QP_PATH_MTU			|
+						IB_QP_DEST_QPN			|
+						IB_QP_RQ_PSN),
+				[IB_QPT_XRC_TGT] = (IB_QP_AV			|
+						IB_QP_PATH_MTU			|
+						IB_QP_DEST_QPN			|
+						IB_QP_RQ_PSN			|
+						IB_QP_MAX_DEST_RD_ATOMIC	|
+						IB_QP_MIN_RNR_TIMER),
 			},
 			.opt_param = {
 				 [IB_QPT_UD]  = (IB_QP_PKEY_INDEX		|
@@ -394,6 +557,12 @@ static const struct {
 				 [IB_QPT_RC]  = (IB_QP_ALT_PATH			|
 						 IB_QP_ACCESS_FLAGS		|
 						 IB_QP_PKEY_INDEX),
+				 [IB_QPT_XRC_INI] = (IB_QP_ALT_PATH		|
+						 IB_QP_ACCESS_FLAGS		|
+						 IB_QP_PKEY_INDEX),
+				 [IB_QPT_XRC_TGT] = (IB_QP_ALT_PATH		|
+						 IB_QP_ACCESS_FLAGS		|
+						 IB_QP_PKEY_INDEX),
 				 [IB_QPT_SMI] = (IB_QP_PKEY_INDEX		|
 						 IB_QP_QKEY),
 				 [IB_QPT_GSI] = (IB_QP_PKEY_INDEX		|
@@ -414,6 +583,13 @@ static const struct {
 						IB_QP_RNR_RETRY			|
 						IB_QP_SQ_PSN			|
 						IB_QP_MAX_QP_RD_ATOMIC),
+				[IB_QPT_XRC_INI] = (IB_QP_TIMEOUT		|
+						IB_QP_RETRY_CNT			|
+						IB_QP_RNR_RETRY			|
+						IB_QP_SQ_PSN			|
+						IB_QP_MAX_QP_RD_ATOMIC),
+				[IB_QPT_XRC_TGT] = (IB_QP_TIMEOUT		|
+						IB_QP_SQ_PSN),
 				[IB_QPT_SMI] = IB_QP_SQ_PSN,
 				[IB_QPT_GSI] = IB_QP_SQ_PSN,
 			},
@@ -429,6 +605,15 @@ static const struct {
 						 IB_QP_ACCESS_FLAGS		|
 						 IB_QP_MIN_RNR_TIMER		|
 						 IB_QP_PATH_MIG_STATE),
+				 [IB_QPT_XRC_INI] = (IB_QP_CUR_STATE		|
+						 IB_QP_ALT_PATH			|
+						 IB_QP_ACCESS_FLAGS		|
+						 IB_QP_PATH_MIG_STATE),
+				 [IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE		|
+						 IB_QP_ALT_PATH			|
+						 IB_QP_ACCESS_FLAGS		|
+						 IB_QP_MIN_RNR_TIMER		|
+						 IB_QP_PATH_MIG_STATE),
 				 [IB_QPT_SMI] = (IB_QP_CUR_STATE		|
 						 IB_QP_QKEY),
 				 [IB_QPT_GSI] = (IB_QP_CUR_STATE		|
@@ -453,6 +638,15 @@ static const struct {
 						IB_QP_ALT_PATH			|
 						IB_QP_PATH_MIG_STATE		|
 						IB_QP_MIN_RNR_TIMER),
+				[IB_QPT_XRC_INI] = (IB_QP_CUR_STATE		|
+						IB_QP_ACCESS_FLAGS		|
+						IB_QP_ALT_PATH			|
+						IB_QP_PATH_MIG_STATE),
+				[IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE		|
+						IB_QP_ACCESS_FLAGS		|
+						IB_QP_ALT_PATH			|
+						IB_QP_PATH_MIG_STATE		|
+						IB_QP_MIN_RNR_TIMER),
 				[IB_QPT_SMI] = (IB_QP_CUR_STATE			|
 						IB_QP_QKEY),
 				[IB_QPT_GSI] = (IB_QP_CUR_STATE			|
@@ -465,6 +659,8 @@ static const struct {
 				[IB_QPT_UD]  = IB_QP_EN_SQD_ASYNC_NOTIFY,
 				[IB_QPT_UC]  = IB_QP_EN_SQD_ASYNC_NOTIFY,
 				[IB_QPT_RC]  = IB_QP_EN_SQD_ASYNC_NOTIFY,
+				[IB_QPT_XRC_INI] = IB_QP_EN_SQD_ASYNC_NOTIFY,
+				[IB_QPT_XRC_TGT] = IB_QP_EN_SQD_ASYNC_NOTIFY, /* ??? */
 				[IB_QPT_SMI] = IB_QP_EN_SQD_ASYNC_NOTIFY,
 				[IB_QPT_GSI] = IB_QP_EN_SQD_ASYNC_NOTIFY
 			}
@@ -487,6 +683,15 @@ static const struct {
 						IB_QP_ACCESS_FLAGS		|
 						IB_QP_MIN_RNR_TIMER		|
 						IB_QP_PATH_MIG_STATE),
+				[IB_QPT_XRC_INI] = (IB_QP_CUR_STATE		|
+						IB_QP_ALT_PATH			|
+						IB_QP_ACCESS_FLAGS		|
+						IB_QP_PATH_MIG_STATE),
+				[IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE		|
+						IB_QP_ALT_PATH			|
+						IB_QP_ACCESS_FLAGS		|
+						IB_QP_MIN_RNR_TIMER		|
+						IB_QP_PATH_MIG_STATE),
 				[IB_QPT_SMI] = (IB_QP_CUR_STATE			|
 						IB_QP_QKEY),
 				[IB_QPT_GSI] = (IB_QP_CUR_STATE			|
@@ -515,6 +720,25 @@ static const struct {
 						IB_QP_PKEY_INDEX		|
 						IB_QP_MIN_RNR_TIMER		|
 						IB_QP_PATH_MIG_STATE),
+				[IB_QPT_XRC_INI] = (IB_QP_PORT			|
+						IB_QP_AV			|
+						IB_QP_TIMEOUT			|
+						IB_QP_RETRY_CNT			|
+						IB_QP_RNR_RETRY			|
+						IB_QP_MAX_QP_RD_ATOMIC		|
+						IB_QP_ALT_PATH			|
+						IB_QP_ACCESS_FLAGS		|
+						IB_QP_PKEY_INDEX		|
+						IB_QP_PATH_MIG_STATE),
+				[IB_QPT_XRC_TGT] = (IB_QP_PORT			|
+						IB_QP_AV			|
+						IB_QP_TIMEOUT			|
+						IB_QP_MAX_DEST_RD_ATOMIC	|
+						IB_QP_ALT_PATH			|
+						IB_QP_ACCESS_FLAGS		|
+						IB_QP_PKEY_INDEX		|
+						IB_QP_MIN_RNR_TIMER		|
+						IB_QP_PATH_MIG_STATE),
 				[IB_QPT_SMI] = (IB_QP_PKEY_INDEX		|
 						IB_QP_QKEY),
 				[IB_QPT_GSI] = (IB_QP_PKEY_INDEX		|
@@ -579,7 +803,7 @@ int ib_modify_qp(struct ib_qp *qp,
 		 struct ib_qp_attr *qp_attr,
 		 int qp_attr_mask)
 {
-	return qp->device->modify_qp(qp, qp_attr, qp_attr_mask, NULL);
+	return qp->device->modify_qp(qp->real_qp, qp_attr, qp_attr_mask, NULL);
 }
 EXPORT_SYMBOL(ib_modify_qp);
 
@@ -589,11 +813,59 @@ int ib_query_qp(struct ib_qp *qp,
 		struct ib_qp_init_attr *qp_init_attr)
 {
 	return qp->device->query_qp ?
-		qp->device->query_qp(qp, qp_attr, qp_attr_mask, qp_init_attr) :
+		qp->device->query_qp(qp->real_qp, qp_attr, qp_attr_mask, qp_init_attr) :
 		-ENOSYS;
 }
 EXPORT_SYMBOL(ib_query_qp);
 
+int ib_close_qp(struct ib_qp *qp)
+{
+	struct ib_qp *real_qp;
+	unsigned long flags;
+
+	real_qp = qp->real_qp;
+	if (real_qp == qp)
+		return -EINVAL;
+
+	spin_lock_irqsave(&real_qp->device->event_handler_lock, flags);
+	list_del(&qp->open_list);
+	spin_unlock_irqrestore(&real_qp->device->event_handler_lock, flags);
+
+	atomic_dec(&real_qp->usecnt);
+	kfree(qp);
+
+	return 0;
+}
+EXPORT_SYMBOL(ib_close_qp);
+
+static int __ib_destroy_shared_qp(struct ib_qp *qp)
+{
+	struct ib_xrcd *xrcd;
+	struct ib_qp *real_qp;
+	int ret;
+
+	real_qp = qp->real_qp;
+	xrcd = real_qp->xrcd;
+
+	mutex_lock(&xrcd->tgt_qp_mutex);
+	ib_close_qp(qp);
+	if (atomic_read(&real_qp->usecnt) == 0)
+		list_del(&real_qp->xrcd_list);
+	else
+		real_qp = NULL;
+	mutex_unlock(&xrcd->tgt_qp_mutex);
+
+	if (real_qp) {
+		ret = ib_destroy_qp(real_qp);
+		if (!ret)
+			atomic_dec(&xrcd->usecnt);
+		else
+			__ib_insert_xrcd_qp(xrcd, real_qp);
+	}
+
+	return 0;
+}
+
 int ib_destroy_qp(struct ib_qp *qp)
 {
 	struct ib_pd *pd;
@@ -601,16 +873,25 @@ int ib_destroy_qp(struct ib_qp *qp)
 	struct ib_srq *srq;
 	int ret;
 
-	pd  = qp->pd;
-	scq = qp->send_cq;
-	rcq = qp->recv_cq;
-	srq = qp->srq;
+	if (atomic_read(&qp->usecnt))
+		return -EBUSY;
+
+	if (qp->real_qp != qp)
+		return __ib_destroy_shared_qp(qp);
+
+	pd   = qp->pd;
+	scq  = qp->send_cq;
+	rcq  = qp->recv_cq;
+	srq  = qp->srq;
 
 	ret = qp->device->destroy_qp(qp);
 	if (!ret) {
-		atomic_dec(&pd->usecnt);
-		atomic_dec(&scq->usecnt);
-		atomic_dec(&rcq->usecnt);
+		if (pd)
+			atomic_dec(&pd->usecnt);
+		if (scq)
+			atomic_dec(&scq->usecnt);
+		if (rcq)
+			atomic_dec(&rcq->usecnt);
 		if (srq)
 			atomic_dec(&srq->usecnt);
 	}
@@ -920,3 +1201,42 @@ int ib_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid)
 	return qp->device->detach_mcast(qp, gid, lid);
 }
 EXPORT_SYMBOL(ib_detach_mcast);
+
+struct ib_xrcd *ib_alloc_xrcd(struct ib_device *device)
+{
+	struct ib_xrcd *xrcd;
+
+	if (!device->alloc_xrcd)
+		return ERR_PTR(-ENOSYS);
+
+	xrcd = device->alloc_xrcd(device, NULL, NULL);
+	if (!IS_ERR(xrcd)) {
+		xrcd->device = device;
+		xrcd->inode = NULL;
+		atomic_set(&xrcd->usecnt, 0);
+		mutex_init(&xrcd->tgt_qp_mutex);
+		INIT_LIST_HEAD(&xrcd->tgt_qp_list);
+	}
+
+	return xrcd;
+}
+EXPORT_SYMBOL(ib_alloc_xrcd);
+
+int ib_dealloc_xrcd(struct ib_xrcd *xrcd)
+{
+	struct ib_qp *qp;
+	int ret;
+
+	if (atomic_read(&xrcd->usecnt))
+		return -EBUSY;
+
+	while (!list_empty(&xrcd->tgt_qp_list)) {
+		qp = list_entry(xrcd->tgt_qp_list.next, struct ib_qp, xrcd_list);
+		ret = ib_destroy_qp(qp);
+		if (ret)
+			return ret;
+	}
+
+	return xrcd->device->dealloc_xrcd(xrcd);
+}
+EXPORT_SYMBOL(ib_dealloc_xrcd);
diff --git a/drivers/infiniband/hw/amso1100/c2_ae.c b/drivers/infiniband/hw/amso1100/c2_ae.c
index 24f9e3a..32d34e8 100644
--- a/drivers/infiniband/hw/amso1100/c2_ae.c
+++ b/drivers/infiniband/hw/amso1100/c2_ae.c
@@ -288,6 +288,11 @@ void c2_ae_event(struct c2_dev *c2dev, u32 mq_index)
 		cm_event.private_data_len =
 			be32_to_cpu(req->private_data_length);
 		cm_event.private_data = req->private_data;
+		/*
+		 * Until ird/ord negotiation via MPAv2 support is added, send
+		 * max supported values
+		 */
+		cm_event.ird = cm_event.ord = 128;
 
 		if (cm_id->event_handler)
 			cm_id->event_handler(cm_id, &cm_event);
diff --git a/drivers/infiniband/hw/amso1100/c2_intr.c b/drivers/infiniband/hw/amso1100/c2_intr.c
index 0ebe4e8..8951db4 100644
--- a/drivers/infiniband/hw/amso1100/c2_intr.c
+++ b/drivers/infiniband/hw/amso1100/c2_intr.c
@@ -183,6 +183,11 @@ static void handle_vq(struct c2_dev *c2dev, u32 mq_index)
 	case IW_CM_EVENT_ESTABLISHED:
 		c2_set_qp_state(req->qp,
 				C2_QP_STATE_RTS);
+		/*
+		 * Until ird/ord negotiation via MPAv2 support is added, send
+		 * max supported values
+		 */
+		cm_event.ird = cm_event.ord = 128;
 	case IW_CM_EVENT_CLOSE:
 
 		/*
diff --git a/drivers/infiniband/hw/amso1100/c2_provider.c b/drivers/infiniband/hw/amso1100/c2_provider.c
index f101bb7..12f923d 100644
--- a/drivers/infiniband/hw/amso1100/c2_provider.c
+++ b/drivers/infiniband/hw/amso1100/c2_provider.c
@@ -753,10 +753,7 @@ static struct net_device *c2_pseudo_netdev_init(struct c2_dev *c2dev)
 	memcpy_fromio(netdev->dev_addr, c2dev->kva + C2_REGS_RDMA_ENADDR, 6);
 
 	/* Print out the MAC address */
-	pr_debug("%s: MAC %02X:%02X:%02X:%02X:%02X:%02X\n",
-		netdev->name,
-		netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2],
-		netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]);
+	pr_debug("%s: MAC %pM\n", netdev->name, netdev->dev_addr);
 
 #if 0
 	/* Disable network packets */
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
index 6cd642a..de6d077 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
@@ -753,6 +753,11 @@ static void connect_request_upcall(struct iwch_ep *ep)
 	event.private_data_len = ep->plen;
 	event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
 	event.provider_data = ep;
+	/*
+	 * Until ird/ord negotiation via MPAv2 support is added, send max
+	 * supported values
+	 */
+	event.ird = event.ord = 8;
 	if (state_read(&ep->parent_ep->com) != DEAD) {
 		get_ep(&ep->com);
 		ep->parent_ep->com.cm_id->event_handler(
@@ -770,6 +775,11 @@ static void established_upcall(struct iwch_ep *ep)
 	PDBG("%s ep %p\n", __func__, ep);
 	memset(&event, 0, sizeof(event));
 	event.event = IW_CM_EVENT_ESTABLISHED;
+	/*
+	 * Until ird/ord negotiation via MPAv2 support is added, send max
+	 * supported values
+	 */
+	event.ird = event.ord = 8;
 	if (ep->com.cm_id) {
 		PDBG("%s ep %p tid %d\n", __func__, ep, ep->hwtid);
 		ep->com.cm_id->event_handler(ep->com.cm_id, &event);
diff --git a/drivers/infiniband/hw/cxgb3/iwch_ev.c b/drivers/infiniband/hw/cxgb3/iwch_ev.c
index 71e0d84..abcc9e7 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_ev.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_ev.c
@@ -46,6 +46,7 @@ static void post_qp_event(struct iwch_dev *rnicp, struct iwch_cq *chp,
 	struct ib_event event;
 	struct iwch_qp_attributes attrs;
 	struct iwch_qp *qhp;
+	unsigned long flag;
 
 	spin_lock(&rnicp->lock);
 	qhp = get_qhp(rnicp, CQE_QPID(rsp_msg->cqe));
@@ -94,7 +95,9 @@ static void post_qp_event(struct iwch_dev *rnicp, struct iwch_cq *chp,
 	if (qhp->ibqp.event_handler)
 		(*qhp->ibqp.event_handler)(&event, qhp->ibqp.qp_context);
 
+	spin_lock_irqsave(&chp->comp_handler_lock, flag);
 	(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
+	spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
 
 	if (atomic_dec_and_test(&qhp->refcnt))
 		wake_up(&qhp->wait);
@@ -107,6 +110,7 @@ void iwch_ev_dispatch(struct cxio_rdev *rdev_p, struct sk_buff *skb)
 	struct iwch_cq *chp;
 	struct iwch_qp *qhp;
 	u32 cqid = RSPQ_CQID(rsp_msg);
+	unsigned long flag;
 
 	rnicp = (struct iwch_dev *) rdev_p->ulp;
 	spin_lock(&rnicp->lock);
@@ -170,7 +174,9 @@ void iwch_ev_dispatch(struct cxio_rdev *rdev_p, struct sk_buff *skb)
 		 */
 		if (qhp->ep && SQ_TYPE(rsp_msg->cqe))
 			dst_confirm(qhp->ep->dst);
+		spin_lock_irqsave(&chp->comp_handler_lock, flag);
 		(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
+		spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
 		break;
 
 	case TPT_ERR_STAG:
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index c7d9411..37c224f 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -190,6 +190,7 @@ static struct ib_cq *iwch_create_cq(struct ib_device *ibdev, int entries, int ve
 	chp->rhp = rhp;
 	chp->ibcq.cqe = 1 << chp->cq.size_log2;
 	spin_lock_init(&chp->lock);
+	spin_lock_init(&chp->comp_handler_lock);
 	atomic_set(&chp->refcnt, 1);
 	init_waitqueue_head(&chp->wait);
 	if (insert_handle(rhp, &rhp->cqidr, chp, chp->cq.cqid)) {
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.h b/drivers/infiniband/hw/cxgb3/iwch_provider.h
index 9a342c9..87c14b0 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.h
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.h
@@ -103,6 +103,7 @@ struct iwch_cq {
 	struct iwch_dev *rhp;
 	struct t3_cq cq;
 	spinlock_t lock;
+	spinlock_t comp_handler_lock;
 	atomic_t refcnt;
 	wait_queue_head_t wait;
 	u32 __user *user_rptr_addr;
diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c
index ecd313f..bea5839 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_qp.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c
@@ -822,8 +822,11 @@ static void __flush_qp(struct iwch_qp *qhp, struct iwch_cq *rchp,
 	flushed = cxio_flush_rq(&qhp->wq, &rchp->cq, count);
 	spin_unlock(&qhp->lock);
 	spin_unlock_irqrestore(&rchp->lock, *flag);
-	if (flushed)
+	if (flushed) {
+		spin_lock_irqsave(&rchp->comp_handler_lock, *flag);
 		(*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
+		spin_unlock_irqrestore(&rchp->comp_handler_lock, *flag);
+	}
 
 	/* locking hierarchy: cq lock first, then qp lock. */
 	spin_lock_irqsave(&schp->lock, *flag);
@@ -833,8 +836,11 @@ static void __flush_qp(struct iwch_qp *qhp, struct iwch_cq *rchp,
 	flushed = cxio_flush_sq(&qhp->wq, &schp->cq, count);
 	spin_unlock(&qhp->lock);
 	spin_unlock_irqrestore(&schp->lock, *flag);
-	if (flushed)
+	if (flushed) {
+		spin_lock_irqsave(&schp->comp_handler_lock, *flag);
 		(*schp->ibcq.comp_handler)(&schp->ibcq, schp->ibcq.cq_context);
+		spin_unlock_irqrestore(&schp->comp_handler_lock, *flag);
+	}
 
 	/* deref */
 	if (atomic_dec_and_test(&qhp->refcnt))
@@ -853,11 +859,15 @@ static void flush_qp(struct iwch_qp *qhp, unsigned long *flag)
 	if (qhp->ibqp.uobject) {
 		cxio_set_wq_in_error(&qhp->wq);
 		cxio_set_cq_in_error(&rchp->cq);
+		spin_lock_irqsave(&rchp->comp_handler_lock, *flag);
 		(*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
+		spin_unlock_irqrestore(&rchp->comp_handler_lock, *flag);
 		if (schp != rchp) {
 			cxio_set_cq_in_error(&schp->cq);
+			spin_lock_irqsave(&schp->comp_handler_lock, *flag);
 			(*schp->ibcq.comp_handler)(&schp->ibcq,
 						   schp->ibcq.cq_context);
+			spin_unlock_irqrestore(&schp->comp_handler_lock, *flag);
 		}
 		return;
 	}
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
index 77f769d..b36cdac 100644
--- a/drivers/infiniband/hw/cxgb4/cm.c
+++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -103,7 +103,8 @@ MODULE_PARM_DESC(ep_timeout_secs, "CM Endpoint operation timeout "
 static int mpa_rev = 1;
 module_param(mpa_rev, int, 0644);
 MODULE_PARM_DESC(mpa_rev, "MPA Revision, 0 supports amso1100, "
-		 "1 is spec compliant. (default=1)");
+		"1 is RFC0544 spec compliant, 2 is IETF MPA Peer Connect Draft"
+		" compliant (default=1)");
 
 static int markers_enabled;
 module_param(markers_enabled, int, 0644);
@@ -497,17 +498,21 @@ static int send_connect(struct c4iw_ep *ep)
 	return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
 }
 
-static void send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb)
+static void send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb,
+		u8 mpa_rev_to_use)
 {
 	int mpalen, wrlen;
 	struct fw_ofld_tx_data_wr *req;
 	struct mpa_message *mpa;
+	struct mpa_v2_conn_params mpa_v2_params;
 
 	PDBG("%s ep %p tid %u pd_len %d\n", __func__, ep, ep->hwtid, ep->plen);
 
 	BUG_ON(skb_cloned(skb));
 
 	mpalen = sizeof(*mpa) + ep->plen;
+	if (mpa_rev_to_use == 2)
+		mpalen += sizeof(struct mpa_v2_conn_params);
 	wrlen = roundup(mpalen + sizeof *req, 16);
 	skb = get_skb(skb, wrlen, GFP_KERNEL);
 	if (!skb) {
@@ -533,12 +538,39 @@ static void send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb)
 	mpa = (struct mpa_message *)(req + 1);
 	memcpy(mpa->key, MPA_KEY_REQ, sizeof(mpa->key));
 	mpa->flags = (crc_enabled ? MPA_CRC : 0) |
-		     (markers_enabled ? MPA_MARKERS : 0);
+		     (markers_enabled ? MPA_MARKERS : 0) |
+		     (mpa_rev_to_use == 2 ? MPA_ENHANCED_RDMA_CONN : 0);
 	mpa->private_data_size = htons(ep->plen);
-	mpa->revision = mpa_rev;
+	mpa->revision = mpa_rev_to_use;
+	if (mpa_rev_to_use == 1)
+		ep->tried_with_mpa_v1 = 1;
+
+	if (mpa_rev_to_use == 2) {
+		mpa->private_data_size +=
+			htons(sizeof(struct mpa_v2_conn_params));
+		mpa_v2_params.ird = htons((u16)ep->ird);
+		mpa_v2_params.ord = htons((u16)ep->ord);
+
+		if (peer2peer) {
+			mpa_v2_params.ird |= htons(MPA_V2_PEER2PEER_MODEL);
+			if (p2p_type == FW_RI_INIT_P2PTYPE_RDMA_WRITE)
+				mpa_v2_params.ord |=
+					htons(MPA_V2_RDMA_WRITE_RTR);
+			else if (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ)
+				mpa_v2_params.ord |=
+					htons(MPA_V2_RDMA_READ_RTR);
+		}
+		memcpy(mpa->private_data, &mpa_v2_params,
+		       sizeof(struct mpa_v2_conn_params));
 
-	if (ep->plen)
-		memcpy(mpa->private_data, ep->mpa_pkt + sizeof(*mpa), ep->plen);
+		if (ep->plen)
+			memcpy(mpa->private_data +
+			       sizeof(struct mpa_v2_conn_params),
+			       ep->mpa_pkt + sizeof(*mpa), ep->plen);
+	} else
+		if (ep->plen)
+			memcpy(mpa->private_data,
+					ep->mpa_pkt + sizeof(*mpa), ep->plen);
 
 	/*
 	 * Reference the mpa skb.  This ensures the data area
@@ -562,10 +594,13 @@ static int send_mpa_reject(struct c4iw_ep *ep, const void *pdata, u8 plen)
 	struct fw_ofld_tx_data_wr *req;
 	struct mpa_message *mpa;
 	struct sk_buff *skb;
+	struct mpa_v2_conn_params mpa_v2_params;
 
 	PDBG("%s ep %p tid %u pd_len %d\n", __func__, ep, ep->hwtid, ep->plen);
 
 	mpalen = sizeof(*mpa) + plen;
+	if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn)
+		mpalen += sizeof(struct mpa_v2_conn_params);
 	wrlen = roundup(mpalen + sizeof *req, 16);
 
 	skb = get_skb(NULL, wrlen, GFP_KERNEL);
@@ -595,8 +630,29 @@ static int send_mpa_reject(struct c4iw_ep *ep, const void *pdata, u8 plen)
 	mpa->flags = MPA_REJECT;
 	mpa->revision = mpa_rev;
 	mpa->private_data_size = htons(plen);
-	if (plen)
-		memcpy(mpa->private_data, pdata, plen);
+
+	if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) {
+		mpa->flags |= MPA_ENHANCED_RDMA_CONN;
+		mpa->private_data_size +=
+			htons(sizeof(struct mpa_v2_conn_params));
+		mpa_v2_params.ird = htons(((u16)ep->ird) |
+					  (peer2peer ? MPA_V2_PEER2PEER_MODEL :
+					   0));
+		mpa_v2_params.ord = htons(((u16)ep->ord) | (peer2peer ?
+					  (p2p_type ==
+					   FW_RI_INIT_P2PTYPE_RDMA_WRITE ?
+					   MPA_V2_RDMA_WRITE_RTR : p2p_type ==
+					   FW_RI_INIT_P2PTYPE_READ_REQ ?
+					   MPA_V2_RDMA_READ_RTR : 0) : 0));
+		memcpy(mpa->private_data, &mpa_v2_params,
+		       sizeof(struct mpa_v2_conn_params));
+
+		if (ep->plen)
+			memcpy(mpa->private_data +
+			       sizeof(struct mpa_v2_conn_params), pdata, plen);
+	} else
+		if (plen)
+			memcpy(mpa->private_data, pdata, plen);
 
 	/*
 	 * Reference the mpa skb again.  This ensures the data area
@@ -617,10 +673,13 @@ static int send_mpa_reply(struct c4iw_ep *ep, const void *pdata, u8 plen)
 	struct fw_ofld_tx_data_wr *req;
 	struct mpa_message *mpa;
 	struct sk_buff *skb;
+	struct mpa_v2_conn_params mpa_v2_params;
 
 	PDBG("%s ep %p tid %u pd_len %d\n", __func__, ep, ep->hwtid, ep->plen);
 
 	mpalen = sizeof(*mpa) + plen;
+	if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn)
+		mpalen += sizeof(struct mpa_v2_conn_params);
 	wrlen = roundup(mpalen + sizeof *req, 16);
 
 	skb = get_skb(NULL, wrlen, GFP_KERNEL);
@@ -649,10 +708,36 @@ static int send_mpa_reply(struct c4iw_ep *ep, const void *pdata, u8 plen)
 	memcpy(mpa->key, MPA_KEY_REP, sizeof(mpa->key));
 	mpa->flags = (ep->mpa_attr.crc_enabled ? MPA_CRC : 0) |
 		     (markers_enabled ? MPA_MARKERS : 0);
-	mpa->revision = mpa_rev;
+	mpa->revision = ep->mpa_attr.version;
 	mpa->private_data_size = htons(plen);
-	if (plen)
-		memcpy(mpa->private_data, pdata, plen);
+
+	if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) {
+		mpa->flags |= MPA_ENHANCED_RDMA_CONN;
+		mpa->private_data_size +=
+			htons(sizeof(struct mpa_v2_conn_params));
+		mpa_v2_params.ird = htons((u16)ep->ird);
+		mpa_v2_params.ord = htons((u16)ep->ord);
+		if (peer2peer && (ep->mpa_attr.p2p_type !=
+					FW_RI_INIT_P2PTYPE_DISABLED)) {
+			mpa_v2_params.ird |= htons(MPA_V2_PEER2PEER_MODEL);
+
+			if (p2p_type == FW_RI_INIT_P2PTYPE_RDMA_WRITE)
+				mpa_v2_params.ord |=
+					htons(MPA_V2_RDMA_WRITE_RTR);
+			else if (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ)
+				mpa_v2_params.ord |=
+					htons(MPA_V2_RDMA_READ_RTR);
+		}
+
+		memcpy(mpa->private_data, &mpa_v2_params,
+		       sizeof(struct mpa_v2_conn_params));
+
+		if (ep->plen)
+			memcpy(mpa->private_data +
+			       sizeof(struct mpa_v2_conn_params), pdata, plen);
+	} else
+		if (plen)
+			memcpy(mpa->private_data, pdata, plen);
 
 	/*
 	 * Reference the mpa skb.  This ensures the data area
@@ -695,7 +780,10 @@ static int act_establish(struct c4iw_dev *dev, struct sk_buff *skb)
 
 	/* start MPA negotiation */
 	send_flowc(ep, NULL);
-	send_mpa_req(ep, skb);
+	if (ep->retry_with_mpa_v1)
+		send_mpa_req(ep, skb, 1);
+	else
+		send_mpa_req(ep, skb, mpa_rev);
 
 	return 0;
 }
@@ -769,8 +857,19 @@ static void connect_reply_upcall(struct c4iw_ep *ep, int status)
 	event.remote_addr = ep->com.remote_addr;
 
 	if ((status == 0) || (status == -ECONNREFUSED)) {
-		event.private_data_len = ep->plen;
-		event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
+		if (!ep->tried_with_mpa_v1) {
+			/* this means MPA_v2 is used */
+			event.private_data_len = ep->plen -
+				sizeof(struct mpa_v2_conn_params);
+			event.private_data = ep->mpa_pkt +
+				sizeof(struct mpa_message) +
+				sizeof(struct mpa_v2_conn_params);
+		} else {
+			/* this means MPA_v1 is used */
+			event.private_data_len = ep->plen;
+			event.private_data = ep->mpa_pkt +
+				sizeof(struct mpa_message);
+		}
 	}
 
 	PDBG("%s ep %p tid %u status %d\n", __func__, ep,
@@ -793,9 +892,22 @@ static void connect_request_upcall(struct c4iw_ep *ep)
 	event.event = IW_CM_EVENT_CONNECT_REQUEST;
 	event.local_addr = ep->com.local_addr;
 	event.remote_addr = ep->com.remote_addr;
-	event.private_data_len = ep->plen;
-	event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
 	event.provider_data = ep;
+	if (!ep->tried_with_mpa_v1) {
+		/* this means MPA_v2 is used */
+		event.ord = ep->ord;
+		event.ird = ep->ird;
+		event.private_data_len = ep->plen -
+			sizeof(struct mpa_v2_conn_params);
+		event.private_data = ep->mpa_pkt + sizeof(struct mpa_message) +
+			sizeof(struct mpa_v2_conn_params);
+	} else {
+		/* this means MPA_v1 is used. Send max supported */
+		event.ord = c4iw_max_read_depth;
+		event.ird = c4iw_max_read_depth;
+		event.private_data_len = ep->plen;
+		event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
+	}
 	if (state_read(&ep->parent_ep->com) != DEAD) {
 		c4iw_get_ep(&ep->com);
 		ep->parent_ep->com.cm_id->event_handler(
@@ -813,6 +925,8 @@ static void established_upcall(struct c4iw_ep *ep)
 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
 	memset(&event, 0, sizeof(event));
 	event.event = IW_CM_EVENT_ESTABLISHED;
+	event.ird = ep->ird;
+	event.ord = ep->ord;
 	if (ep->com.cm_id) {
 		PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
 		ep->com.cm_id->event_handler(ep->com.cm_id, &event);
@@ -848,7 +962,10 @@ static int update_rx_credits(struct c4iw_ep *ep, u32 credits)
 static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
 {
 	struct mpa_message *mpa;
+	struct mpa_v2_conn_params *mpa_v2_params;
 	u16 plen;
+	u16 resp_ird, resp_ord;
+	u8 rtr_mismatch = 0, insuff_ird = 0;
 	struct c4iw_qp_attributes attrs;
 	enum c4iw_qp_attr_mask mask;
 	int err;
@@ -888,7 +1005,9 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
 	mpa = (struct mpa_message *) ep->mpa_pkt;
 
 	/* Validate MPA header. */
-	if (mpa->revision != mpa_rev) {
+	if (mpa->revision > mpa_rev) {
+		printk(KERN_ERR MOD "%s MPA version mismatch. Local = %d,"
+		       " Received = %d\n", __func__, mpa_rev, mpa->revision);
 		err = -EPROTO;
 		goto err;
 	}
@@ -938,13 +1057,66 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
 	ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0;
 	ep->mpa_attr.recv_marker_enabled = markers_enabled;
 	ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0;
-	ep->mpa_attr.version = mpa_rev;
-	ep->mpa_attr.p2p_type = peer2peer ? p2p_type :
-					    FW_RI_INIT_P2PTYPE_DISABLED;
+	ep->mpa_attr.version = mpa->revision;
+	ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED;
+
+	if (mpa->revision == 2) {
+		ep->mpa_attr.enhanced_rdma_conn =
+			mpa->flags & MPA_ENHANCED_RDMA_CONN ? 1 : 0;
+		if (ep->mpa_attr.enhanced_rdma_conn) {
+			mpa_v2_params = (struct mpa_v2_conn_params *)
+				(ep->mpa_pkt + sizeof(*mpa));
+			resp_ird = ntohs(mpa_v2_params->ird) &
+				MPA_V2_IRD_ORD_MASK;
+			resp_ord = ntohs(mpa_v2_params->ord) &
+				MPA_V2_IRD_ORD_MASK;
+
+			/*
+			 * This is a double-check. Ideally, below checks are
+			 * not required since ird/ord stuff has been taken
+			 * care of in c4iw_accept_cr
+			 */
+			if ((ep->ird < resp_ord) || (ep->ord > resp_ird)) {
+				err = -ENOMEM;
+				ep->ird = resp_ord;
+				ep->ord = resp_ird;
+				insuff_ird = 1;
+			}
+
+			if (ntohs(mpa_v2_params->ird) &
+					MPA_V2_PEER2PEER_MODEL) {
+				if (ntohs(mpa_v2_params->ord) &
+						MPA_V2_RDMA_WRITE_RTR)
+					ep->mpa_attr.p2p_type =
+						FW_RI_INIT_P2PTYPE_RDMA_WRITE;
+				else if (ntohs(mpa_v2_params->ord) &
+						MPA_V2_RDMA_READ_RTR)
+					ep->mpa_attr.p2p_type =
+						FW_RI_INIT_P2PTYPE_READ_REQ;
+			}
+		}
+	} else if (mpa->revision == 1)
+		if (peer2peer)
+			ep->mpa_attr.p2p_type = p2p_type;
+
 	PDBG("%s - crc_enabled=%d, recv_marker_enabled=%d, "
-	     "xmit_marker_enabled=%d, version=%d\n", __func__,
-	     ep->mpa_attr.crc_enabled, ep->mpa_attr.recv_marker_enabled,
-	     ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version);
+	     "xmit_marker_enabled=%d, version=%d p2p_type=%d local-p2p_type = "
+	     "%d\n", __func__, ep->mpa_attr.crc_enabled,
+	     ep->mpa_attr.recv_marker_enabled,
+	     ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version,
+	     ep->mpa_attr.p2p_type, p2p_type);
+
+	/*
+	 * If responder's RTR does not match with that of initiator, assign
+	 * FW_RI_INIT_P2PTYPE_DISABLED in mpa attributes so that RTR is not
+	 * generated when moving QP to RTS state.
+	 * A TERM message will be sent after QP has moved to RTS state
+	 */
+	if ((ep->mpa_attr.version == 2) &&
+			(ep->mpa_attr.p2p_type != p2p_type)) {
+		ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED;
+		rtr_mismatch = 1;
+	}
 
 	attrs.mpa_attr = ep->mpa_attr;
 	attrs.max_ird = ep->ird;
@@ -961,6 +1133,39 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
 			     ep->com.qp, mask, &attrs, 1);
 	if (err)
 		goto err;
+
+	/*
+	 * If responder's RTR requirement did not match with what initiator
+	 * supports, generate TERM message
+	 */
+	if (rtr_mismatch) {
+		printk(KERN_ERR "%s: RTR mismatch, sending TERM\n", __func__);
+		attrs.layer_etype = LAYER_MPA | DDP_LLP;
+		attrs.ecode = MPA_NOMATCH_RTR;
+		attrs.next_state = C4IW_QP_STATE_TERMINATE;
+		err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
+				C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
+		err = -ENOMEM;
+		goto out;
+	}
+
+	/*
+	 * Generate TERM if initiator IRD is not sufficient for responder
+	 * provided ORD. Currently, we do the same behaviour even when
+	 * responder provided IRD is also not sufficient as regards to
+	 * initiator ORD.
+	 */
+	if (insuff_ird) {
+		printk(KERN_ERR "%s: Insufficient IRD, sending TERM\n",
+				__func__);
+		attrs.layer_etype = LAYER_MPA | DDP_LLP;
+		attrs.ecode = MPA_INSUFF_IRD;
+		attrs.next_state = C4IW_QP_STATE_TERMINATE;
+		err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
+				C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
+		err = -ENOMEM;
+		goto out;
+	}
 	goto out;
 err:
 	state_set(&ep->com, ABORTING);
@@ -973,6 +1178,7 @@ out:
 static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
 {
 	struct mpa_message *mpa;
+	struct mpa_v2_conn_params *mpa_v2_params;
 	u16 plen;
 
 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
@@ -1013,7 +1219,9 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
 	/*
 	 * Validate MPA Header.
 	 */
-	if (mpa->revision != mpa_rev) {
+	if (mpa->revision > mpa_rev) {
+		printk(KERN_ERR MOD "%s MPA version mismatch. Local = %d,"
+		       " Received = %d\n", __func__, mpa_rev, mpa->revision);
 		abort_connection(ep, skb, GFP_KERNEL);
 		return;
 	}
@@ -1056,9 +1264,37 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
 	ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0;
 	ep->mpa_attr.recv_marker_enabled = markers_enabled;
 	ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0;
-	ep->mpa_attr.version = mpa_rev;
-	ep->mpa_attr.p2p_type = peer2peer ? p2p_type :
-					    FW_RI_INIT_P2PTYPE_DISABLED;
+	ep->mpa_attr.version = mpa->revision;
+	if (mpa->revision == 1)
+		ep->tried_with_mpa_v1 = 1;
+	ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED;
+
+	if (mpa->revision == 2) {
+		ep->mpa_attr.enhanced_rdma_conn =
+			mpa->flags & MPA_ENHANCED_RDMA_CONN ? 1 : 0;
+		if (ep->mpa_attr.enhanced_rdma_conn) {
+			mpa_v2_params = (struct mpa_v2_conn_params *)
+				(ep->mpa_pkt + sizeof(*mpa));
+			ep->ird = ntohs(mpa_v2_params->ird) &
+				MPA_V2_IRD_ORD_MASK;
+			ep->ord = ntohs(mpa_v2_params->ord) &
+				MPA_V2_IRD_ORD_MASK;
+			if (ntohs(mpa_v2_params->ird) & MPA_V2_PEER2PEER_MODEL)
+				if (peer2peer) {
+					if (ntohs(mpa_v2_params->ord) &
+							MPA_V2_RDMA_WRITE_RTR)
+						ep->mpa_attr.p2p_type =
+						FW_RI_INIT_P2PTYPE_RDMA_WRITE;
+					else if (ntohs(mpa_v2_params->ord) &
+							MPA_V2_RDMA_READ_RTR)
+						ep->mpa_attr.p2p_type =
+						FW_RI_INIT_P2PTYPE_READ_REQ;
+				}
+		}
+	} else if (mpa->revision == 1)
+		if (peer2peer)
+			ep->mpa_attr.p2p_type = p2p_type;
+
 	PDBG("%s - crc_enabled=%d, recv_marker_enabled=%d, "
 	     "xmit_marker_enabled=%d, version=%d p2p_type=%d\n", __func__,
 	     ep->mpa_attr.crc_enabled, ep->mpa_attr.recv_marker_enabled,
@@ -1550,6 +1786,112 @@ static int is_neg_adv_abort(unsigned int status)
 	       status == CPL_ERR_PERSIST_NEG_ADVICE;
 }
 
+static int c4iw_reconnect(struct c4iw_ep *ep)
+{
+	int err = 0;
+	struct rtable *rt;
+	struct net_device *pdev;
+	struct neighbour *neigh;
+	int step;
+
+	PDBG("%s qp %p cm_id %p\n", __func__, ep->com.qp, ep->com.cm_id);
+	init_timer(&ep->timer);
+
+	/*
+	 * Allocate an active TID to initiate a TCP connection.
+	 */
+	ep->atid = cxgb4_alloc_atid(ep->com.dev->rdev.lldi.tids, ep);
+	if (ep->atid == -1) {
+		printk(KERN_ERR MOD "%s - cannot alloc atid.\n", __func__);
+		err = -ENOMEM;
+		goto fail2;
+	}
+
+	/* find a route */
+	rt = find_route(ep->com.dev,
+			ep->com.cm_id->local_addr.sin_addr.s_addr,
+			ep->com.cm_id->remote_addr.sin_addr.s_addr,
+			ep->com.cm_id->local_addr.sin_port,
+			ep->com.cm_id->remote_addr.sin_port, 0);
+	if (!rt) {
+		printk(KERN_ERR MOD "%s - cannot find route.\n", __func__);
+		err = -EHOSTUNREACH;
+		goto fail3;
+	}
+	ep->dst = &rt->dst;
+
+	neigh = dst_get_neighbour(ep->dst);
+
+	/* get a l2t entry */
+	if (neigh->dev->flags & IFF_LOOPBACK) {
+		PDBG("%s LOOPBACK\n", __func__);
+		pdev = ip_dev_find(&init_net,
+				   ep->com.cm_id->remote_addr.sin_addr.s_addr);
+		ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t,
+					neigh, pdev, 0);
+		ep->mtu = pdev->mtu;
+		ep->tx_chan = cxgb4_port_chan(pdev);
+		ep->smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1;
+		step = ep->com.dev->rdev.lldi.ntxq /
+			ep->com.dev->rdev.lldi.nchan;
+		ep->txq_idx = cxgb4_port_idx(pdev) * step;
+		step = ep->com.dev->rdev.lldi.nrxq /
+			ep->com.dev->rdev.lldi.nchan;
+		ep->ctrlq_idx = cxgb4_port_idx(pdev);
+		ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[
+			cxgb4_port_idx(pdev) * step];
+		dev_put(pdev);
+	} else {
+		ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t,
+					neigh, neigh->dev, 0);
+		ep->mtu = dst_mtu(ep->dst);
+		ep->tx_chan = cxgb4_port_chan(neigh->dev);
+		ep->smac_idx = (cxgb4_port_viid(neigh->dev) & 0x7F) << 1;
+		step = ep->com.dev->rdev.lldi.ntxq /
+			ep->com.dev->rdev.lldi.nchan;
+		ep->txq_idx = cxgb4_port_idx(neigh->dev) * step;
+		ep->ctrlq_idx = cxgb4_port_idx(neigh->dev);
+		step = ep->com.dev->rdev.lldi.nrxq /
+			ep->com.dev->rdev.lldi.nchan;
+		ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[
+			cxgb4_port_idx(neigh->dev) * step];
+	}
+	if (!ep->l2t) {
+		printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
+		err = -ENOMEM;
+		goto fail4;
+	}
+
+	PDBG("%s txq_idx %u tx_chan %u smac_idx %u rss_qid %u l2t_idx %u\n",
+	     __func__, ep->txq_idx, ep->tx_chan, ep->smac_idx, ep->rss_qid,
+	     ep->l2t->idx);
+
+	state_set(&ep->com, CONNECTING);
+	ep->tos = 0;
+
+	/* send connect request to rnic */
+	err = send_connect(ep);
+	if (!err)
+		goto out;
+
+	cxgb4_l2t_release(ep->l2t);
+fail4:
+	dst_release(ep->dst);
+fail3:
+	cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid);
+fail2:
+	/*
+	 * remember to send notification to upper layer.
+	 * We are in here so the upper layer is not aware that this is
+	 * re-connect attempt and so, upper layer is still waiting for
+	 * response of 1st connect request.
+	 */
+	connect_reply_upcall(ep, -ECONNRESET);
+	c4iw_put_ep(&ep->com);
+out:
+	return err;
+}
+
 static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
 {
 	struct cpl_abort_req_rss *req = cplhdr(skb);
@@ -1573,8 +1915,11 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
 
 	/*
 	 * Wake up any threads in rdma_init() or rdma_fini().
+	 * However, this is not needed if com state is just
+	 * MPA_REQ_SENT
 	 */
-	c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
+	if (ep->com.state != MPA_REQ_SENT)
+		c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
 
 	mutex_lock(&ep->com.mutex);
 	switch (ep->com.state) {
@@ -1585,7 +1930,21 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
 		break;
 	case MPA_REQ_SENT:
 		stop_ep_timer(ep);
-		connect_reply_upcall(ep, -ECONNRESET);
+		if (mpa_rev == 2 && ep->tried_with_mpa_v1)
+			connect_reply_upcall(ep, -ECONNRESET);
+		else {
+			/*
+			 * we just don't send notification upwards because we
+			 * want to retry with mpa_v1 without upper layers even
+			 * knowing it.
+			 *
+			 * do some housekeeping so as to re-initiate the
+			 * connection
+			 */
+			PDBG("%s: mpa_rev=%d. Retrying with mpav1\n", __func__,
+			     mpa_rev);
+			ep->retry_with_mpa_v1 = 1;
+		}
 		break;
 	case MPA_REP_SENT:
 		break;
@@ -1621,7 +1980,9 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
 	dst_confirm(ep->dst);
 	if (ep->com.state != ABORTING) {
 		__state_set(&ep->com, DEAD);
-		release = 1;
+		/* we don't release if we want to retry with mpa_v1 */
+		if (!ep->retry_with_mpa_v1)
+			release = 1;
 	}
 	mutex_unlock(&ep->com.mutex);
 
@@ -1641,6 +2002,15 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
 out:
 	if (release)
 		release_ep_resources(ep);
+
+	/* retry with mpa-v1 */
+	if (ep && ep->retry_with_mpa_v1) {
+		cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, ep->hwtid);
+		dst_release(ep->dst);
+		cxgb4_l2t_release(ep->l2t);
+		c4iw_reconnect(ep);
+	}
+
 	return 0;
 }
 
@@ -1792,18 +2162,40 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 		goto err;
 	}
 
-	cm_id->add_ref(cm_id);
-	ep->com.cm_id = cm_id;
-	ep->com.qp = qp;
+	if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) {
+		if (conn_param->ord > ep->ird) {
+			ep->ird = conn_param->ird;
+			ep->ord = conn_param->ord;
+			send_mpa_reject(ep, conn_param->private_data,
+					conn_param->private_data_len);
+			abort_connection(ep, NULL, GFP_KERNEL);
+			err = -ENOMEM;
+			goto err;
+		}
+		if (conn_param->ird > ep->ord) {
+			if (!ep->ord)
+				conn_param->ird = 1;
+			else {
+				abort_connection(ep, NULL, GFP_KERNEL);
+				err = -ENOMEM;
+				goto err;
+			}
+		}
 
+	}
 	ep->ird = conn_param->ird;
 	ep->ord = conn_param->ord;
 
-	if (peer2peer && ep->ird == 0)
-		ep->ird = 1;
+	if (ep->mpa_attr.version != 2)
+		if (peer2peer && ep->ird == 0)
+			ep->ird = 1;
 
 	PDBG("%s %d ird %d ord %d\n", __func__, __LINE__, ep->ird, ep->ord);
 
+	cm_id->add_ref(cm_id);
+	ep->com.cm_id = cm_id;
+	ep->com.qp = qp;
+
 	/* bind QP to EP and move to RTS */
 	attrs.mpa_attr = ep->mpa_attr;
 	attrs.max_ird = ep->ird;
@@ -1944,6 +2336,8 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 		       ep->com.dev->rdev.lldi.nchan;
 		ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[
 			      cxgb4_port_idx(neigh->dev) * step];
+		ep->retry_with_mpa_v1 = 0;
+		ep->tried_with_mpa_v1 = 0;
 	}
 	if (!ep->l2t) {
 		printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
@@ -2323,8 +2717,11 @@ static int peer_abort_intr(struct c4iw_dev *dev, struct sk_buff *skb)
 
 	/*
 	 * Wake up any threads in rdma_init() or rdma_fini().
+	 * However, this is not needed if com state is just
+	 * MPA_REQ_SENT
 	 */
-	c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
+	if (ep->com.state != MPA_REQ_SENT)
+		c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
 	sched(dev, skb);
 	return 0;
 }
diff --git a/drivers/infiniband/hw/cxgb4/cq.c b/drivers/infiniband/hw/cxgb4/cq.c
index 1720dc7..f35a935 100644
--- a/drivers/infiniband/hw/cxgb4/cq.c
+++ b/drivers/infiniband/hw/cxgb4/cq.c
@@ -185,7 +185,7 @@ static void insert_recv_cqe(struct t4_wq *wq, struct t4_cq *cq)
 				 V_CQE_OPCODE(FW_RI_SEND) |
 				 V_CQE_TYPE(0) |
 				 V_CQE_SWCQE(1) |
-				 V_CQE_QPID(wq->rq.qid));
+				 V_CQE_QPID(wq->sq.qid));
 	cqe.bits_type_ts = cpu_to_be64(V_CQE_GENBIT((u64)cq->gen));
 	cq->sw_queue[cq->sw_pidx] = cqe;
 	t4_swcq_produce(cq);
@@ -818,6 +818,7 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, int entries,
 	chp->cq.size--;				/* status page */
 	chp->ibcq.cqe = entries - 2;
 	spin_lock_init(&chp->lock);
+	spin_lock_init(&chp->comp_handler_lock);
 	atomic_set(&chp->refcnt, 1);
 	init_waitqueue_head(&chp->wait);
 	ret = insert_handle(rhp, &rhp->cqidr, chp, chp->cq.cqid);
diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c
index 40a13cc..6d0df6e 100644
--- a/drivers/infiniband/hw/cxgb4/device.c
+++ b/drivers/infiniband/hw/cxgb4/device.c
@@ -376,10 +376,8 @@ struct uld_ctx {
 	struct c4iw_dev *dev;
 };
 
-static void c4iw_remove(struct uld_ctx *ctx)
+static void c4iw_dealloc(struct uld_ctx *ctx)
 {
-	PDBG("%s c4iw_dev %p\n", __func__,  ctx->dev);
-	c4iw_unregister_device(ctx->dev);
 	c4iw_rdev_close(&ctx->dev->rdev);
 	idr_destroy(&ctx->dev->cqidr);
 	idr_destroy(&ctx->dev->qpidr);
@@ -389,11 +387,30 @@ static void c4iw_remove(struct uld_ctx *ctx)
 	ctx->dev = NULL;
 }
 
+static void c4iw_remove(struct uld_ctx *ctx)
+{
+	PDBG("%s c4iw_dev %p\n", __func__,  ctx->dev);
+	c4iw_unregister_device(ctx->dev);
+	c4iw_dealloc(ctx);
+}
+
+static int rdma_supported(const struct cxgb4_lld_info *infop)
+{
+	return infop->vr->stag.size > 0 && infop->vr->pbl.size > 0 &&
+	       infop->vr->rq.size > 0 && infop->vr->qp.size > 0 &&
+	       infop->vr->cq.size > 0 && infop->vr->ocq.size > 0;
+}
+
 static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
 {
 	struct c4iw_dev *devp;
 	int ret;
 
+	if (!rdma_supported(infop)) {
+		printk(KERN_INFO MOD "%s: RDMA not supported on this device.\n",
+		       pci_name(infop->pdev));
+		return ERR_PTR(-ENOSYS);
+	}
 	devp = (struct c4iw_dev *)ib_alloc_device(sizeof(*devp));
 	if (!devp) {
 		printk(KERN_ERR MOD "Cannot allocate ib device\n");
@@ -414,7 +431,6 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
 
 	ret = c4iw_rdev_open(&devp->rdev);
 	if (ret) {
-		mutex_unlock(&dev_mutex);
 		printk(KERN_ERR MOD "Unable to open CXIO rdev err %d\n", ret);
 		ib_dealloc_device(&devp->ibdev);
 		return ERR_PTR(ret);
@@ -519,15 +535,24 @@ static int c4iw_uld_state_change(void *handle, enum cxgb4_state new_state)
 	case CXGB4_STATE_UP:
 		printk(KERN_INFO MOD "%s: Up\n", pci_name(ctx->lldi.pdev));
 		if (!ctx->dev) {
-			int ret = 0;
+			int ret;
 
 			ctx->dev = c4iw_alloc(&ctx->lldi);
-			if (!IS_ERR(ctx->dev))
-				ret = c4iw_register_device(ctx->dev);
-			if (IS_ERR(ctx->dev) || ret)
+			if (IS_ERR(ctx->dev)) {
+				printk(KERN_ERR MOD
+				       "%s: initialization failed: %ld\n",
+				       pci_name(ctx->lldi.pdev),
+				       PTR_ERR(ctx->dev));
+				ctx->dev = NULL;
+				break;
+			}
+			ret = c4iw_register_device(ctx->dev);
+			if (ret) {
 				printk(KERN_ERR MOD
 				       "%s: RDMA registration failed: %d\n",
 				       pci_name(ctx->lldi.pdev), ret);
+				c4iw_dealloc(ctx);
+			}
 		}
 		break;
 	case CXGB4_STATE_DOWN:
diff --git a/drivers/infiniband/hw/cxgb4/ev.c b/drivers/infiniband/hw/cxgb4/ev.c
index c13041a..397cb36 100644
--- a/drivers/infiniband/hw/cxgb4/ev.c
+++ b/drivers/infiniband/hw/cxgb4/ev.c
@@ -42,6 +42,7 @@ static void post_qp_event(struct c4iw_dev *dev, struct c4iw_cq *chp,
 {
 	struct ib_event event;
 	struct c4iw_qp_attributes attrs;
+	unsigned long flag;
 
 	if ((qhp->attr.state == C4IW_QP_STATE_ERROR) ||
 	    (qhp->attr.state == C4IW_QP_STATE_TERMINATE)) {
@@ -72,7 +73,9 @@ static void post_qp_event(struct c4iw_dev *dev, struct c4iw_cq *chp,
 	if (qhp->ibqp.event_handler)
 		(*qhp->ibqp.event_handler)(&event, qhp->ibqp.qp_context);
 
+	spin_lock_irqsave(&chp->comp_handler_lock, flag);
 	(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
+	spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
 }
 
 void c4iw_ev_dispatch(struct c4iw_dev *dev, struct t4_cqe *err_cqe)
@@ -183,11 +186,14 @@ out:
 int c4iw_ev_handler(struct c4iw_dev *dev, u32 qid)
 {
 	struct c4iw_cq *chp;
+	unsigned long flag;
 
 	chp = get_chp(dev, qid);
-	if (chp)
+	if (chp) {
+		spin_lock_irqsave(&chp->comp_handler_lock, flag);
 		(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
-	else
+		spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
+	} else
 		PDBG("%s unknown cqid 0x%x\n", __func__, qid);
 	return 0;
 }
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
index 4f04537..1357c5b 100644
--- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
+++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
@@ -309,6 +309,7 @@ struct c4iw_cq {
 	struct c4iw_dev *rhp;
 	struct t4_cq cq;
 	spinlock_t lock;
+	spinlock_t comp_handler_lock;
 	atomic_t refcnt;
 	wait_queue_head_t wait;
 };
@@ -323,6 +324,7 @@ struct c4iw_mpa_attributes {
 	u8 recv_marker_enabled;
 	u8 xmit_marker_enabled;
 	u8 crc_enabled;
+	u8 enhanced_rdma_conn;
 	u8 version;
 	u8 p2p_type;
 };
@@ -349,6 +351,8 @@ struct c4iw_qp_attributes {
 	u8 is_terminate_local;
 	struct c4iw_mpa_attributes mpa_attr;
 	struct c4iw_ep *llp_stream_handle;
+	u8 layer_etype;
+	u8 ecode;
 };
 
 struct c4iw_qp {
@@ -501,11 +505,18 @@ enum c4iw_mmid_state {
 #define MPA_KEY_REP "MPA ID Rep Frame"
 
 #define MPA_MAX_PRIVATE_DATA	256
+#define MPA_ENHANCED_RDMA_CONN	0x10
 #define MPA_REJECT		0x20
 #define MPA_CRC			0x40
 #define MPA_MARKERS		0x80
 #define MPA_FLAGS_MASK		0xE0
 
+#define MPA_V2_PEER2PEER_MODEL          0x8000
+#define MPA_V2_ZERO_LEN_FPDU_RTR        0x4000
+#define MPA_V2_RDMA_WRITE_RTR           0x8000
+#define MPA_V2_RDMA_READ_RTR            0x4000
+#define MPA_V2_IRD_ORD_MASK             0x3FFF
+
 #define c4iw_put_ep(ep) { \
 	PDBG("put_ep (via %s:%u) ep %p refcnt %d\n", __func__, __LINE__,  \
 	     ep, atomic_read(&((ep)->kref.refcount))); \
@@ -528,6 +539,11 @@ struct mpa_message {
 	u8 private_data[0];
 };
 
+struct mpa_v2_conn_params {
+	__be16 ird;
+	__be16 ord;
+};
+
 struct terminate_message {
 	u8 layer_etype;
 	u8 ecode;
@@ -580,7 +596,10 @@ enum c4iw_ddp_ecodes {
 
 enum c4iw_mpa_ecodes {
 	MPA_CRC_ERR		= 0x02,
-	MPA_MARKER_ERR		= 0x03
+	MPA_MARKER_ERR          = 0x03,
+	MPA_LOCAL_CATA          = 0x05,
+	MPA_INSUFF_IRD          = 0x06,
+	MPA_NOMATCH_RTR         = 0x07,
 };
 
 enum c4iw_ep_state {
@@ -651,6 +670,8 @@ struct c4iw_ep {
 	u16 txq_idx;
 	u16 ctrlq_idx;
 	u8 tos;
+	u8 retry_with_mpa_v1;
+	u8 tried_with_mpa_v1;
 };
 
 static inline struct c4iw_ep *to_ep(struct iw_cm_id *cm_id)
diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c
index a41578e..d6ccc7e 100644
--- a/drivers/infiniband/hw/cxgb4/qp.c
+++ b/drivers/infiniband/hw/cxgb4/qp.c
@@ -917,7 +917,11 @@ static void post_terminate(struct c4iw_qp *qhp, struct t4_cqe *err_cqe,
 	wqe->u.terminate.type = FW_RI_TYPE_TERMINATE;
 	wqe->u.terminate.immdlen = cpu_to_be32(sizeof *term);
 	term = (struct terminate_message *)wqe->u.terminate.termmsg;
-	build_term_codes(err_cqe, &term->layer_etype, &term->ecode);
+	if (qhp->attr.layer_etype == (LAYER_MPA|DDP_LLP)) {
+		term->layer_etype = qhp->attr.layer_etype;
+		term->ecode = qhp->attr.ecode;
+	} else
+		build_term_codes(err_cqe, &term->layer_etype, &term->ecode);
 	c4iw_ofld_send(&qhp->rhp->rdev, skb);
 }
 
@@ -941,8 +945,11 @@ static void __flush_qp(struct c4iw_qp *qhp, struct c4iw_cq *rchp,
 	flushed = c4iw_flush_rq(&qhp->wq, &rchp->cq, count);
 	spin_unlock(&qhp->lock);
 	spin_unlock_irqrestore(&rchp->lock, flag);
-	if (flushed)
+	if (flushed) {
+		spin_lock_irqsave(&rchp->comp_handler_lock, flag);
 		(*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
+		spin_unlock_irqrestore(&rchp->comp_handler_lock, flag);
+	}
 
 	/* locking hierarchy: cq lock first, then qp lock. */
 	spin_lock_irqsave(&schp->lock, flag);
@@ -952,13 +959,17 @@ static void __flush_qp(struct c4iw_qp *qhp, struct c4iw_cq *rchp,
 	flushed = c4iw_flush_sq(&qhp->wq, &schp->cq, count);
 	spin_unlock(&qhp->lock);
 	spin_unlock_irqrestore(&schp->lock, flag);
-	if (flushed)
+	if (flushed) {
+		spin_lock_irqsave(&schp->comp_handler_lock, flag);
 		(*schp->ibcq.comp_handler)(&schp->ibcq, schp->ibcq.cq_context);
+		spin_unlock_irqrestore(&schp->comp_handler_lock, flag);
+	}
 }
 
 static void flush_qp(struct c4iw_qp *qhp)
 {
 	struct c4iw_cq *rchp, *schp;
+	unsigned long flag;
 
 	rchp = get_chp(qhp->rhp, qhp->attr.rcq);
 	schp = get_chp(qhp->rhp, qhp->attr.scq);
@@ -966,8 +977,16 @@ static void flush_qp(struct c4iw_qp *qhp)
 	if (qhp->ibqp.uobject) {
 		t4_set_wq_in_error(&qhp->wq);
 		t4_set_cq_in_error(&rchp->cq);
-		if (schp != rchp)
+		spin_lock_irqsave(&rchp->comp_handler_lock, flag);
+		(*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
+		spin_unlock_irqrestore(&rchp->comp_handler_lock, flag);
+		if (schp != rchp) {
 			t4_set_cq_in_error(&schp->cq);
+			spin_lock_irqsave(&schp->comp_handler_lock, flag);
+			(*schp->ibcq.comp_handler)(&schp->ibcq,
+					schp->ibcq.cq_context);
+			spin_unlock_irqrestore(&schp->comp_handler_lock, flag);
+		}
 		return;
 	}
 	__flush_qp(qhp, rchp, schp);
@@ -1012,6 +1031,7 @@ out:
 
 static void build_rtr_msg(u8 p2p_type, struct fw_ri_init *init)
 {
+	PDBG("%s p2p_type = %d\n", __func__, p2p_type);
 	memset(&init->u, 0, sizeof init->u);
 	switch (p2p_type) {
 	case FW_RI_INIT_P2PTYPE_RDMA_WRITE:
@@ -1206,12 +1226,16 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
 				disconnect = 1;
 				c4iw_get_ep(&qhp->ep->com);
 			}
+			if (qhp->ibqp.uobject)
+				t4_set_wq_in_error(&qhp->wq);
 			ret = rdma_fini(rhp, qhp, ep);
 			if (ret)
 				goto err;
 			break;
 		case C4IW_QP_STATE_TERMINATE:
 			set_state(qhp, C4IW_QP_STATE_TERMINATE);
+			qhp->attr.layer_etype = attrs->layer_etype;
+			qhp->attr.ecode = attrs->ecode;
 			if (qhp->ibqp.uobject)
 				t4_set_wq_in_error(&qhp->wq);
 			ep = qhp->ep;
@@ -1222,6 +1246,8 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
 			break;
 		case C4IW_QP_STATE_ERROR:
 			set_state(qhp, C4IW_QP_STATE_ERROR);
+			if (qhp->ibqp.uobject)
+				t4_set_wq_in_error(&qhp->wq);
 			if (!internal) {
 				abort = 1;
 				disconnect = 1;
@@ -1334,7 +1360,10 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp)
 	rhp = qhp->rhp;
 
 	attrs.next_state = C4IW_QP_STATE_ERROR;
-	c4iw_modify_qp(rhp, qhp, C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
+	if (qhp->attr.state == C4IW_QP_STATE_TERMINATE)
+		c4iw_modify_qp(rhp, qhp, C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
+	else
+		c4iw_modify_qp(rhp, qhp, C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
 	wait_event(qhp->wait, !qhp->ep);
 
 	remove_handle(rhp, &rhp->qpidr, qhp->wq.sq.qid);
diff --git a/drivers/infiniband/hw/ehca/ehca_eq.c b/drivers/infiniband/hw/ehca/ehca_eq.c
index d9b1bb4..818d721 100644
--- a/drivers/infiniband/hw/ehca/ehca_eq.c
+++ b/drivers/infiniband/hw/ehca/ehca_eq.c
@@ -125,7 +125,7 @@ int ehca_create_eq(struct ehca_shca *shca,
 		tasklet_init(&eq->interrupt_task, ehca_tasklet_eq, (long)shca);
 
 		ret = ibmebus_request_irq(eq->ist, ehca_interrupt_eq,
-					  IRQF_DISABLED, "ehca_eq",
+					  0, "ehca_eq",
 					  (void *)shca);
 		if (ret < 0)
 			ehca_err(ib_dev, "Can't map interrupt handler.");
@@ -133,7 +133,7 @@ int ehca_create_eq(struct ehca_shca *shca,
 		tasklet_init(&eq->interrupt_task, ehca_tasklet_neq, (long)shca);
 
 		ret = ibmebus_request_irq(eq->ist, ehca_interrupt_neq,
-					  IRQF_DISABLED, "ehca_neq",
+					  0, "ehca_neq",
 					  (void *)shca);
 		if (ret < 0)
 			ehca_err(ib_dev, "Can't map interrupt handler.");
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index 32fb342..964f855 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -977,6 +977,9 @@ struct ib_srq *ehca_create_srq(struct ib_pd *pd,
 	struct hcp_modify_qp_control_block *mqpcb;
 	u64 hret, update_mask;
 
+	if (srq_init_attr->srq_type != IB_SRQT_BASIC)
+		return ERR_PTR(-ENOSYS);
+
 	/* For common attributes, internal_create_qp() takes its info
 	 * out of qp_init_attr, so copy all common attrs there.
 	 */
diff --git a/drivers/infiniband/hw/ipath/ipath_init_chip.c b/drivers/infiniband/hw/ipath/ipath_init_chip.c
index 7c1eebe..824a4d5 100644
--- a/drivers/infiniband/hw/ipath/ipath_init_chip.c
+++ b/drivers/infiniband/hw/ipath/ipath_init_chip.c
@@ -34,6 +34,7 @@
 #include <linux/pci.h>
 #include <linux/netdevice.h>
 #include <linux/slab.h>
+#include <linux/stat.h>
 #include <linux/vmalloc.h>
 
 #include "ipath_kernel.h"
diff --git a/drivers/infiniband/hw/ipath/ipath_srq.c b/drivers/infiniband/hw/ipath/ipath_srq.c
index 386e2c7..2627198 100644
--- a/drivers/infiniband/hw/ipath/ipath_srq.c
+++ b/drivers/infiniband/hw/ipath/ipath_srq.c
@@ -107,6 +107,11 @@ struct ib_srq *ipath_create_srq(struct ib_pd *ibpd,
 	u32 sz;
 	struct ib_srq *ret;
 
+	if (srq_init_attr->srq_type != IB_SRQT_BASIC) {
+		ret = ERR_PTR(-ENOSYS);
+		goto done;
+	}
+
 	if (srq_init_attr->attr.max_wr == 0) {
 		ret = ERR_PTR(-EINVAL);
 		goto done;
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index fa643f4..77f3dbc 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -128,6 +128,8 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
 	    (dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_REMOTE_INV) &&
 	    (dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_FAST_REG_WR))
 		props->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS;
+	if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC)
+		props->device_cap_flags |= IB_DEVICE_XRC;
 
 	props->vendor_id	   = be32_to_cpup((__be32 *) (out_mad->data + 36)) &
 		0xffffff;
@@ -181,8 +183,12 @@ mlx4_ib_port_link_layer(struct ib_device *device, u8 port_num)
 
 static int ib_link_query_port(struct ib_device *ibdev, u8 port,
 			      struct ib_port_attr *props,
+			      struct ib_smp *in_mad,
 			      struct ib_smp *out_mad)
 {
+	int ext_active_speed;
+	int err;
+
 	props->lid		= be16_to_cpup((__be16 *) (out_mad->data + 16));
 	props->lmc		= out_mad->data[34] & 0x7;
 	props->sm_lid		= be16_to_cpup((__be16 *) (out_mad->data + 18));
@@ -203,6 +209,39 @@ static int ib_link_query_port(struct ib_device *ibdev, u8 port,
 	props->max_vl_num	= out_mad->data[37] >> 4;
 	props->init_type_reply	= out_mad->data[41] >> 4;
 
+	/* Check if extended speeds (EDR/FDR/...) are supported */
+	if (props->port_cap_flags & IB_PORT_EXTENDED_SPEEDS_SUP) {
+		ext_active_speed = out_mad->data[62] >> 4;
+
+		switch (ext_active_speed) {
+		case 1:
+			props->active_speed = 16; /* FDR */
+			break;
+		case 2:
+			props->active_speed = 32; /* EDR */
+			break;
+		}
+	}
+
+	/* If reported active speed is QDR, check if is FDR-10 */
+	if (props->active_speed == 4) {
+		if (to_mdev(ibdev)->dev->caps.ext_port_cap[port] &
+		    MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO) {
+			init_query_mad(in_mad);
+			in_mad->attr_id = MLX4_ATTR_EXTENDED_PORT_INFO;
+			in_mad->attr_mod = cpu_to_be32(port);
+
+			err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port,
+					   NULL, NULL, in_mad, out_mad);
+			if (err)
+				return err;
+
+			/* Checking LinkSpeedActive for FDR-10 */
+			if (out_mad->data[15] & 0x1)
+				props->active_speed = 8;
+		}
+	}
+
 	return 0;
 }
 
@@ -227,7 +266,7 @@ static int eth_link_query_port(struct ib_device *ibdev, u8 port,
 	props->pkey_tbl_len	= 1;
 	props->bad_pkey_cntr	= be16_to_cpup((__be16 *) (out_mad->data + 46));
 	props->qkey_viol_cntr	= be16_to_cpup((__be16 *) (out_mad->data + 48));
-	props->max_mtu		= IB_MTU_2048;
+	props->max_mtu		= IB_MTU_4096;
 	props->subnet_timeout	= 0;
 	props->max_vl_num	= out_mad->data[37] >> 4;
 	props->init_type_reply	= 0;
@@ -274,7 +313,7 @@ static int mlx4_ib_query_port(struct ib_device *ibdev, u8 port,
 		goto out;
 
 	err = mlx4_ib_port_link_layer(ibdev, port) == IB_LINK_LAYER_INFINIBAND ?
-		ib_link_query_port(ibdev, port, props, out_mad) :
+		ib_link_query_port(ibdev, port, props, in_mad, out_mad) :
 		eth_link_query_port(ibdev, port, props, out_mad);
 
 out:
@@ -566,6 +605,57 @@ static int mlx4_ib_dealloc_pd(struct ib_pd *pd)
 	return 0;
 }
 
+static struct ib_xrcd *mlx4_ib_alloc_xrcd(struct ib_device *ibdev,
+					  struct ib_ucontext *context,
+					  struct ib_udata *udata)
+{
+	struct mlx4_ib_xrcd *xrcd;
+	int err;
+
+	if (!(to_mdev(ibdev)->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC))
+		return ERR_PTR(-ENOSYS);
+
+	xrcd = kmalloc(sizeof *xrcd, GFP_KERNEL);
+	if (!xrcd)
+		return ERR_PTR(-ENOMEM);
+
+	err = mlx4_xrcd_alloc(to_mdev(ibdev)->dev, &xrcd->xrcdn);
+	if (err)
+		goto err1;
+
+	xrcd->pd = ib_alloc_pd(ibdev);
+	if (IS_ERR(xrcd->pd)) {
+		err = PTR_ERR(xrcd->pd);
+		goto err2;
+	}
+
+	xrcd->cq = ib_create_cq(ibdev, NULL, NULL, xrcd, 1, 0);
+	if (IS_ERR(xrcd->cq)) {
+		err = PTR_ERR(xrcd->cq);
+		goto err3;
+	}
+
+	return &xrcd->ibxrcd;
+
+err3:
+	ib_dealloc_pd(xrcd->pd);
+err2:
+	mlx4_xrcd_free(to_mdev(ibdev)->dev, xrcd->xrcdn);
+err1:
+	kfree(xrcd);
+	return ERR_PTR(err);
+}
+
+static int mlx4_ib_dealloc_xrcd(struct ib_xrcd *xrcd)
+{
+	ib_destroy_cq(to_mxrcd(xrcd)->cq);
+	ib_dealloc_pd(to_mxrcd(xrcd)->pd);
+	mlx4_xrcd_free(to_mdev(xrcd->device)->dev, to_mxrcd(xrcd)->xrcdn);
+	kfree(xrcd);
+
+	return 0;
+}
+
 static int add_gid_entry(struct ib_qp *ibqp, union ib_gid *gid)
 {
 	struct mlx4_ib_qp *mqp = to_mqp(ibqp);
@@ -1044,7 +1134,9 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
 		(1ull << IB_USER_VERBS_CMD_CREATE_SRQ)		|
 		(1ull << IB_USER_VERBS_CMD_MODIFY_SRQ)		|
 		(1ull << IB_USER_VERBS_CMD_QUERY_SRQ)		|
-		(1ull << IB_USER_VERBS_CMD_DESTROY_SRQ);
+		(1ull << IB_USER_VERBS_CMD_DESTROY_SRQ)		|
+		(1ull << IB_USER_VERBS_CMD_CREATE_XSRQ)		|
+		(1ull << IB_USER_VERBS_CMD_OPEN_QP);
 
 	ibdev->ib_dev.query_device	= mlx4_ib_query_device;
 	ibdev->ib_dev.query_port	= mlx4_ib_query_port;
@@ -1093,6 +1185,14 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
 	ibdev->ib_dev.unmap_fmr		= mlx4_ib_unmap_fmr;
 	ibdev->ib_dev.dealloc_fmr	= mlx4_ib_fmr_dealloc;
 
+	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) {
+		ibdev->ib_dev.alloc_xrcd = mlx4_ib_alloc_xrcd;
+		ibdev->ib_dev.dealloc_xrcd = mlx4_ib_dealloc_xrcd;
+		ibdev->ib_dev.uverbs_cmd_mask |=
+			(1ull << IB_USER_VERBS_CMD_OPEN_XRCD) |
+			(1ull << IB_USER_VERBS_CMD_CLOSE_XRCD);
+	}
+
 	spin_lock_init(&iboe->lock);
 
 	if (init_node_data(ibdev))
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index e4bf2cf..ed80345 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -56,6 +56,13 @@ struct mlx4_ib_pd {
 	u32			pdn;
 };
 
+struct mlx4_ib_xrcd {
+	struct ib_xrcd		ibxrcd;
+	u32			xrcdn;
+	struct ib_pd	       *pd;
+	struct ib_cq	       *cq;
+};
+
 struct mlx4_ib_cq_buf {
 	struct mlx4_buf		buf;
 	struct mlx4_mtt		mtt;
@@ -138,6 +145,7 @@ struct mlx4_ib_qp {
 	struct mlx4_mtt		mtt;
 	int			buf_size;
 	struct mutex		mutex;
+	u16			xrcdn;
 	u32			flags;
 	u8			port;
 	u8			alt_port;
@@ -211,6 +219,11 @@ static inline struct mlx4_ib_pd *to_mpd(struct ib_pd *ibpd)
 	return container_of(ibpd, struct mlx4_ib_pd, ibpd);
 }
 
+static inline struct mlx4_ib_xrcd *to_mxrcd(struct ib_xrcd *ibxrcd)
+{
+	return container_of(ibxrcd, struct mlx4_ib_xrcd, ibxrcd);
+}
+
 static inline struct mlx4_ib_cq *to_mcq(struct ib_cq *ibcq)
 {
 	return container_of(ibcq, struct mlx4_ib_cq, ibcq);
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 3a91d9d..a16f0c8 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -302,15 +302,14 @@ static int send_wqe_overhead(enum ib_qp_type type, u32 flags)
 }
 
 static int set_rq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
-		       int is_user, int has_srq, struct mlx4_ib_qp *qp)
+		       int is_user, int has_rq, struct mlx4_ib_qp *qp)
 {
 	/* Sanity check RQ size before proceeding */
 	if (cap->max_recv_wr  > dev->dev->caps.max_wqes  ||
 	    cap->max_recv_sge > dev->dev->caps.max_rq_sg)
 		return -EINVAL;
 
-	if (has_srq) {
-		/* QPs attached to an SRQ should have no RQ */
+	if (!has_rq) {
 		if (cap->max_recv_wr)
 			return -EINVAL;
 
@@ -463,6 +462,14 @@ static int set_user_sq_size(struct mlx4_ib_dev *dev,
 	return 0;
 }
 
+static int qp_has_rq(struct ib_qp_init_attr *attr)
+{
+	if (attr->qp_type == IB_QPT_XRC_INI || attr->qp_type == IB_QPT_XRC_TGT)
+		return 0;
+
+	return !attr->srq;
+}
+
 static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
 			    struct ib_qp_init_attr *init_attr,
 			    struct ib_udata *udata, int sqpn, struct mlx4_ib_qp *qp)
@@ -479,7 +486,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
 	if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR)
 		qp->sq_signal_bits = cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE);
 
-	err = set_rq_size(dev, &init_attr->cap, !!pd->uobject, !!init_attr->srq, qp);
+	err = set_rq_size(dev, &init_attr->cap, !!pd->uobject, qp_has_rq(init_attr), qp);
 	if (err)
 		goto err;
 
@@ -513,7 +520,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
 		if (err)
 			goto err_mtt;
 
-		if (!init_attr->srq) {
+		if (qp_has_rq(init_attr)) {
 			err = mlx4_ib_db_map_user(to_mucontext(pd->uobject->context),
 						  ucmd.db_addr, &qp->db);
 			if (err)
@@ -532,7 +539,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
 		if (err)
 			goto err;
 
-		if (!init_attr->srq) {
+		if (qp_has_rq(init_attr)) {
 			err = mlx4_db_alloc(dev->dev, &qp->db, 0);
 			if (err)
 				goto err;
@@ -575,6 +582,9 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
 	if (err)
 		goto err_qpn;
 
+	if (init_attr->qp_type == IB_QPT_XRC_TGT)
+		qp->mqp.qpn |= (1 << 23);
+
 	/*
 	 * Hardware wants QPN written in big-endian order (after
 	 * shifting) for send doorbell.  Precompute this value to save
@@ -592,9 +602,8 @@ err_qpn:
 
 err_wrid:
 	if (pd->uobject) {
-		if (!init_attr->srq)
-			mlx4_ib_db_unmap_user(to_mucontext(pd->uobject->context),
-					      &qp->db);
+		if (qp_has_rq(init_attr))
+			mlx4_ib_db_unmap_user(to_mucontext(pd->uobject->context), &qp->db);
 	} else {
 		kfree(qp->sq.wrid);
 		kfree(qp->rq.wrid);
@@ -610,7 +619,7 @@ err_buf:
 		mlx4_buf_free(dev->dev, qp->buf_size, &qp->buf);
 
 err_db:
-	if (!pd->uobject && !init_attr->srq)
+	if (!pd->uobject && qp_has_rq(init_attr))
 		mlx4_db_free(dev->dev, &qp->db);
 
 err:
@@ -671,6 +680,33 @@ static void del_gid_entries(struct mlx4_ib_qp *qp)
 	}
 }
 
+static struct mlx4_ib_pd *get_pd(struct mlx4_ib_qp *qp)
+{
+	if (qp->ibqp.qp_type == IB_QPT_XRC_TGT)
+		return to_mpd(to_mxrcd(qp->ibqp.xrcd)->pd);
+	else
+		return to_mpd(qp->ibqp.pd);
+}
+
+static void get_cqs(struct mlx4_ib_qp *qp,
+		    struct mlx4_ib_cq **send_cq, struct mlx4_ib_cq **recv_cq)
+{
+	switch (qp->ibqp.qp_type) {
+	case IB_QPT_XRC_TGT:
+		*send_cq = to_mcq(to_mxrcd(qp->ibqp.xrcd)->cq);
+		*recv_cq = *send_cq;
+		break;
+	case IB_QPT_XRC_INI:
+		*send_cq = to_mcq(qp->ibqp.send_cq);
+		*recv_cq = *send_cq;
+		break;
+	default:
+		*send_cq = to_mcq(qp->ibqp.send_cq);
+		*recv_cq = to_mcq(qp->ibqp.recv_cq);
+		break;
+	}
+}
+
 static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
 			      int is_user)
 {
@@ -682,8 +718,7 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
 			printk(KERN_WARNING "mlx4_ib: modify QP %06x to RESET failed.\n",
 			       qp->mqp.qpn);
 
-	send_cq = to_mcq(qp->ibqp.send_cq);
-	recv_cq = to_mcq(qp->ibqp.recv_cq);
+	get_cqs(qp, &send_cq, &recv_cq);
 
 	mlx4_ib_lock_cqs(send_cq, recv_cq);
 
@@ -706,7 +741,7 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
 	mlx4_mtt_cleanup(dev->dev, &qp->mtt);
 
 	if (is_user) {
-		if (!qp->ibqp.srq)
+		if (qp->rq.wqe_cnt)
 			mlx4_ib_db_unmap_user(to_mucontext(qp->ibqp.uobject->context),
 					      &qp->db);
 		ib_umem_release(qp->umem);
@@ -714,7 +749,7 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
 		kfree(qp->sq.wrid);
 		kfree(qp->rq.wrid);
 		mlx4_buf_free(dev->dev, qp->buf_size, &qp->buf);
-		if (!qp->ibqp.srq)
+		if (qp->rq.wqe_cnt)
 			mlx4_db_free(dev->dev, &qp->db);
 	}
 
@@ -725,10 +760,10 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
 				struct ib_qp_init_attr *init_attr,
 				struct ib_udata *udata)
 {
-	struct mlx4_ib_dev *dev = to_mdev(pd->device);
 	struct mlx4_ib_sqp *sqp;
 	struct mlx4_ib_qp *qp;
 	int err;
+	u16 xrcdn = 0;
 
 	/*
 	 * We only support LSO and multicast loopback blocking, and
@@ -739,10 +774,20 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
 		return ERR_PTR(-EINVAL);
 
 	if (init_attr->create_flags &&
-	    (pd->uobject || init_attr->qp_type != IB_QPT_UD))
+	    (udata || init_attr->qp_type != IB_QPT_UD))
 		return ERR_PTR(-EINVAL);
 
 	switch (init_attr->qp_type) {
+	case IB_QPT_XRC_TGT:
+		pd = to_mxrcd(init_attr->xrcd)->pd;
+		xrcdn = to_mxrcd(init_attr->xrcd)->xrcdn;
+		init_attr->send_cq = to_mxrcd(init_attr->xrcd)->cq;
+		/* fall through */
+	case IB_QPT_XRC_INI:
+		if (!(to_mdev(pd->device)->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC))
+			return ERR_PTR(-ENOSYS);
+		init_attr->recv_cq = init_attr->send_cq;
+		/* fall through */
 	case IB_QPT_RC:
 	case IB_QPT_UC:
 	case IB_QPT_UD:
@@ -751,13 +796,14 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
 		if (!qp)
 			return ERR_PTR(-ENOMEM);
 
-		err = create_qp_common(dev, pd, init_attr, udata, 0, qp);
+		err = create_qp_common(to_mdev(pd->device), pd, init_attr, udata, 0, qp);
 		if (err) {
 			kfree(qp);
 			return ERR_PTR(err);
 		}
 
 		qp->ibqp.qp_num = qp->mqp.qpn;
+		qp->xrcdn = xrcdn;
 
 		break;
 	}
@@ -765,7 +811,7 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
 	case IB_QPT_GSI:
 	{
 		/* Userspace is not allowed to create special QPs: */
-		if (pd->uobject)
+		if (udata)
 			return ERR_PTR(-EINVAL);
 
 		sqp = kzalloc(sizeof *sqp, GFP_KERNEL);
@@ -774,8 +820,8 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
 
 		qp = &sqp->qp;
 
-		err = create_qp_common(dev, pd, init_attr, udata,
-				       dev->dev->caps.sqp_start +
+		err = create_qp_common(to_mdev(pd->device), pd, init_attr, udata,
+				       to_mdev(pd->device)->dev->caps.sqp_start +
 				       (init_attr->qp_type == IB_QPT_SMI ? 0 : 2) +
 				       init_attr->port_num - 1,
 				       qp);
@@ -801,11 +847,13 @@ int mlx4_ib_destroy_qp(struct ib_qp *qp)
 {
 	struct mlx4_ib_dev *dev = to_mdev(qp->device);
 	struct mlx4_ib_qp *mqp = to_mqp(qp);
+	struct mlx4_ib_pd *pd;
 
 	if (is_qp0(dev, mqp))
 		mlx4_CLOSE_PORT(dev->dev, mqp->port);
 
-	destroy_qp_common(dev, mqp, !!qp->pd->uobject);
+	pd = get_pd(mqp);
+	destroy_qp_common(dev, mqp, !!pd->ibpd.uobject);
 
 	if (is_sqp(dev, mqp))
 		kfree(to_msqp(mqp));
@@ -821,6 +869,8 @@ static int to_mlx4_st(enum ib_qp_type type)
 	case IB_QPT_RC:		return MLX4_QP_ST_RC;
 	case IB_QPT_UC:		return MLX4_QP_ST_UC;
 	case IB_QPT_UD:		return MLX4_QP_ST_UD;
+	case IB_QPT_XRC_INI:
+	case IB_QPT_XRC_TGT:	return MLX4_QP_ST_XRC;
 	case IB_QPT_SMI:
 	case IB_QPT_GSI:	return MLX4_QP_ST_MLX;
 	default:		return -1;
@@ -959,6 +1009,8 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
 {
 	struct mlx4_ib_dev *dev = to_mdev(ibqp->device);
 	struct mlx4_ib_qp *qp = to_mqp(ibqp);
+	struct mlx4_ib_pd *pd;
+	struct mlx4_ib_cq *send_cq, *recv_cq;
 	struct mlx4_qp_context *context;
 	enum mlx4_qp_optpar optpar = 0;
 	int sqd_event;
@@ -1014,8 +1066,10 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
 		context->sq_size_stride = ilog2(qp->sq.wqe_cnt) << 3;
 	context->sq_size_stride |= qp->sq.wqe_shift - 4;
 
-	if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
+	if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) {
 		context->sq_size_stride |= !!qp->sq_no_prefetch << 7;
+		context->xrcd = cpu_to_be32((u32) qp->xrcdn);
+	}
 
 	if (qp->ibqp.uobject)
 		context->usr_page = cpu_to_be32(to_mucontext(ibqp->uobject->context)->uar.index);
@@ -1079,8 +1133,12 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
 		optpar |= MLX4_QP_OPTPAR_ALT_ADDR_PATH;
 	}
 
-	context->pd	    = cpu_to_be32(to_mpd(ibqp->pd)->pdn);
-	context->params1    = cpu_to_be32(MLX4_IB_ACK_REQ_FREQ << 28);
+	pd = get_pd(qp);
+	get_cqs(qp, &send_cq, &recv_cq);
+	context->pd       = cpu_to_be32(pd->pdn);
+	context->cqn_send = cpu_to_be32(send_cq->mcq.cqn);
+	context->cqn_recv = cpu_to_be32(recv_cq->mcq.cqn);
+	context->params1  = cpu_to_be32(MLX4_IB_ACK_REQ_FREQ << 28);
 
 	/* Set "fast registration enabled" for all kernel QPs */
 	if (!qp->ibqp.uobject)
@@ -1106,8 +1164,6 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
 	if (attr_mask & IB_QP_SQ_PSN)
 		context->next_send_psn = cpu_to_be32(attr->sq_psn);
 
-	context->cqn_send = cpu_to_be32(to_mcq(ibqp->send_cq)->mcq.cqn);
-
 	if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) {
 		if (attr->max_dest_rd_atomic)
 			context->params2 |=
@@ -1130,8 +1186,6 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
 	if (attr_mask & IB_QP_RQ_PSN)
 		context->rnr_nextrecvpsn |= cpu_to_be32(attr->rq_psn);
 
-	context->cqn_recv = cpu_to_be32(to_mcq(ibqp->recv_cq)->mcq.cqn);
-
 	if (attr_mask & IB_QP_QKEY) {
 		context->qkey = cpu_to_be32(attr->qkey);
 		optpar |= MLX4_QP_OPTPAR_Q_KEY;
@@ -1140,7 +1194,7 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
 	if (ibqp->srq)
 		context->srqn = cpu_to_be32(1 << 24 | to_msrq(ibqp->srq)->msrq.srqn);
 
-	if (!ibqp->srq && cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
+	if (qp->rq.wqe_cnt && cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
 		context->db_rec_addr = cpu_to_be64(qp->db.dma);
 
 	if (cur_state == IB_QPS_INIT &&
@@ -1225,17 +1279,17 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
 	 * entries and reinitialize the QP.
 	 */
 	if (new_state == IB_QPS_RESET && !ibqp->uobject) {
-		mlx4_ib_cq_clean(to_mcq(ibqp->recv_cq), qp->mqp.qpn,
+		mlx4_ib_cq_clean(recv_cq, qp->mqp.qpn,
 				 ibqp->srq ? to_msrq(ibqp->srq): NULL);
-		if (ibqp->send_cq != ibqp->recv_cq)
-			mlx4_ib_cq_clean(to_mcq(ibqp->send_cq), qp->mqp.qpn, NULL);
+		if (send_cq != recv_cq)
+			mlx4_ib_cq_clean(send_cq, qp->mqp.qpn, NULL);
 
 		qp->rq.head = 0;
 		qp->rq.tail = 0;
 		qp->sq.head = 0;
 		qp->sq.tail = 0;
 		qp->sq_next_wqe = 0;
-		if (!ibqp->srq)
+		if (qp->rq.wqe_cnt)
 			*qp->db.db  = 0;
 	}
 
@@ -1547,14 +1601,13 @@ static void set_masked_atomic_seg(struct mlx4_wqe_masked_atomic_seg *aseg,
 }
 
 static void set_datagram_seg(struct mlx4_wqe_datagram_seg *dseg,
-			     struct ib_send_wr *wr, __be16 *vlan)
+			     struct ib_send_wr *wr)
 {
 	memcpy(dseg->av, &to_mah(wr->wr.ud.ah)->av, sizeof (struct mlx4_av));
 	dseg->dqpn = cpu_to_be32(wr->wr.ud.remote_qpn);
 	dseg->qkey = cpu_to_be32(wr->wr.ud.remote_qkey);
 	dseg->vlan = to_mah(wr->wr.ud.ah)->av.eth.vlan;
 	memcpy(dseg->mac, to_mah(wr->wr.ud.ah)->av.eth.mac, 6);
-	*vlan = dseg->vlan;
 }
 
 static void set_mlx_icrc_seg(void *dseg)
@@ -1657,7 +1710,6 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 	__be32 uninitialized_var(lso_hdr_sz);
 	__be32 blh;
 	int i;
-	__be16 vlan = cpu_to_be16(0xffff);
 
 	spin_lock_irqsave(&qp->sq.lock, flags);
 
@@ -1761,7 +1813,7 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 			break;
 
 		case IB_QPT_UD:
-			set_datagram_seg(wqe, wr, &vlan);
+			set_datagram_seg(wqe, wr);
 			wqe  += sizeof (struct mlx4_wqe_datagram_seg);
 			size += sizeof (struct mlx4_wqe_datagram_seg) / 16;
 
@@ -1824,11 +1876,6 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 		ctrl->fence_size = (wr->send_flags & IB_SEND_FENCE ?
 				    MLX4_WQE_CTRL_FENCE : 0) | size;
 
-		if (be16_to_cpu(vlan) < 0x1000) {
-			ctrl->ins_vlan = 1 << 6;
-			ctrl->vlan_tag = vlan;
-		}
-
 		/*
 		 * Make sure descriptor is fully written before
 		 * setting ownership bit (because HW can start
diff --git a/drivers/infiniband/hw/mlx4/srq.c b/drivers/infiniband/hw/mlx4/srq.c
index 818b7ec..39542f3 100644
--- a/drivers/infiniband/hw/mlx4/srq.c
+++ b/drivers/infiniband/hw/mlx4/srq.c
@@ -76,6 +76,8 @@ struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd,
 	struct mlx4_ib_srq *srq;
 	struct mlx4_wqe_srq_next_seg *next;
 	struct mlx4_wqe_data_seg *scatter;
+	u32 cqn;
+	u16 xrcdn;
 	int desc_size;
 	int buf_size;
 	int err;
@@ -174,12 +176,18 @@ struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd,
 		}
 	}
 
-	err = mlx4_srq_alloc(dev->dev, to_mpd(pd)->pdn, &srq->mtt,
+	cqn = (init_attr->srq_type == IB_SRQT_XRC) ?
+		to_mcq(init_attr->ext.xrc.cq)->mcq.cqn : 0;
+	xrcdn = (init_attr->srq_type == IB_SRQT_XRC) ?
+		to_mxrcd(init_attr->ext.xrc.xrcd)->xrcdn :
+		(u16) dev->dev->caps.reserved_xrcds;
+	err = mlx4_srq_alloc(dev->dev, to_mpd(pd)->pdn, cqn, xrcdn, &srq->mtt,
 			     srq->db.dma, &srq->msrq);
 	if (err)
 		goto err_wrid;
 
 	srq->msrq.event = mlx4_ib_srq_event;
+	srq->ibsrq.ext.xrc.srq_num = srq->msrq.srqn;
 
 	if (pd->uobject)
 		if (ib_copy_to_udata(udata, &srq->msrq.srqn, sizeof (__u32))) {
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 365fe0e..cb9a0b9 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -438,6 +438,9 @@ static struct ib_srq *mthca_create_srq(struct ib_pd *pd,
 	struct mthca_srq *srq;
 	int err;
 
+	if (init_attr->srq_type != IB_SRQT_BASIC)
+		return ERR_PTR(-ENOSYS);
+
 	srq = kmalloc(sizeof *srq, GFP_KERNEL);
 	if (!srq)
 		return ERR_PTR(-ENOMEM);
diff --git a/drivers/infiniband/hw/nes/Makefile b/drivers/infiniband/hw/nes/Makefile
index 3514851..97820c2 100644
--- a/drivers/infiniband/hw/nes/Makefile
+++ b/drivers/infiniband/hw/nes/Makefile
@@ -1,3 +1,3 @@
 obj-$(CONFIG_INFINIBAND_NES) += iw_nes.o
 
-iw_nes-objs := nes.o nes_hw.o nes_nic.o nes_utils.o nes_verbs.o nes_cm.o
+iw_nes-objs := nes.o nes_hw.o nes_nic.o nes_utils.o nes_verbs.o nes_cm.o nes_mgt.o
diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c
index 2d668c6..5965b3d 100644
--- a/drivers/infiniband/hw/nes/nes.c
+++ b/drivers/infiniband/hw/nes/nes.c
@@ -84,7 +84,7 @@ module_param(send_first, int, 0644);
 MODULE_PARM_DESC(send_first, "Send RDMA Message First on Active Connection");
 
 
-unsigned int nes_drv_opt = 0;
+unsigned int nes_drv_opt = NES_DRV_OPT_DISABLE_INT_MOD | NES_DRV_OPT_ENABLE_PAU;
 module_param(nes_drv_opt, int, 0644);
 MODULE_PARM_DESC(nes_drv_opt, "Driver option parameters");
 
@@ -130,9 +130,6 @@ static struct notifier_block nes_net_notifier = {
 	.notifier_call = nes_net_event
 };
 
-
-
-
 /**
  * nes_inetaddr_event
  */
@@ -321,6 +318,9 @@ void nes_rem_ref(struct ib_qp *ibqp)
 	}
 
 	if (atomic_dec_and_test(&nesqp->refcount)) {
+		if (nesqp->pau_mode)
+			nes_destroy_pau_qp(nesdev, nesqp);
+
 		/* Destroy the QP */
 		cqp_request = nes_get_cqp_request(nesdev);
 		if (cqp_request == NULL) {
diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h
index 6fe7987..568b4f1 100644
--- a/drivers/infiniband/hw/nes/nes.h
+++ b/drivers/infiniband/hw/nes/nes.h
@@ -102,6 +102,7 @@
 #define NES_DRV_OPT_NO_INLINE_DATA       0x00000080
 #define NES_DRV_OPT_DISABLE_INT_MOD      0x00000100
 #define NES_DRV_OPT_DISABLE_VIRT_WQ      0x00000200
+#define NES_DRV_OPT_ENABLE_PAU           0x00000400
 
 #define NES_AEQ_EVENT_TIMEOUT         2500
 #define NES_DISCONNECT_EVENT_TIMEOUT  2000
@@ -128,6 +129,7 @@
 #define NES_DBG_IW_RX       0x00020000
 #define NES_DBG_IW_TX       0x00040000
 #define NES_DBG_SHUTDOWN    0x00080000
+#define NES_DBG_PAU         0x00100000
 #define NES_DBG_RSVD1       0x10000000
 #define NES_DBG_RSVD2       0x20000000
 #define NES_DBG_RSVD3       0x40000000
@@ -162,6 +164,7 @@ do { \
 #include "nes_context.h"
 #include "nes_user.h"
 #include "nes_cm.h"
+#include "nes_mgt.h"
 
 extern int max_mtu;
 #define max_frame_len (max_mtu+ETH_HLEN)
@@ -202,6 +205,8 @@ extern atomic_t cm_nodes_created;
 extern atomic_t cm_nodes_destroyed;
 extern atomic_t cm_accel_dropped_pkts;
 extern atomic_t cm_resets_recvd;
+extern atomic_t pau_qps_created;
+extern atomic_t pau_qps_destroyed;
 
 extern u32 int_mod_timer_init;
 extern u32 int_mod_cq_depth_256;
@@ -273,6 +278,14 @@ struct nes_device {
 	u8                     link_recheck;
 };
 
+/* Receive skb private area - must fit in skb->cb area */
+struct nes_rskb_cb {
+	u64                    busaddr;
+	u32                    maplen;
+	u32                    seqnum;
+	u8                     *data_start;
+	struct nes_qp          *nesqp;
+};
 
 static inline __le32 get_crc_value(struct nes_v4_quad *nes_quad)
 {
@@ -305,8 +318,8 @@ set_wqe_32bit_value(__le32 *wqe_words, u32 index, u32 value)
 static inline void
 nes_fill_init_cqp_wqe(struct nes_hw_cqp_wqe *cqp_wqe, struct nes_device *nesdev)
 {
-	set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_COMP_CTX_LOW_IDX,
-			(u64)((unsigned long) &nesdev->cqp));
+	cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_LOW_IDX]       = 0;
+	cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX]      = 0;
 	cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX]   = 0;
 	cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX]  = 0;
 	cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PBL_BLK_COUNT_IDX] = 0;
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index c118663..dfce9ea 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -77,26 +77,19 @@ atomic_t cm_nodes_destroyed;
 atomic_t cm_accel_dropped_pkts;
 atomic_t cm_resets_recvd;
 
-static inline int mini_cm_accelerated(struct nes_cm_core *,
-	struct nes_cm_node *);
-static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *,
-	struct nes_vnic *, struct nes_cm_info *);
+static inline int mini_cm_accelerated(struct nes_cm_core *, struct nes_cm_node *);
+static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *, struct nes_vnic *, struct nes_cm_info *);
 static int mini_cm_del_listen(struct nes_cm_core *, struct nes_cm_listener *);
-static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *,
-	struct nes_vnic *, u16, void *, struct nes_cm_info *);
+static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *, struct nes_vnic *, u16, void *, struct nes_cm_info *);
 static int mini_cm_close(struct nes_cm_core *, struct nes_cm_node *);
-static int mini_cm_accept(struct nes_cm_core *, struct ietf_mpa_frame *,
-	struct nes_cm_node *);
-static int mini_cm_reject(struct nes_cm_core *, struct ietf_mpa_frame *,
-	struct nes_cm_node *);
-static int mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *,
-	struct sk_buff *);
+static int mini_cm_accept(struct nes_cm_core *, struct nes_cm_node *);
+static int mini_cm_reject(struct nes_cm_core *, struct nes_cm_node *);
+static int mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *, struct sk_buff *);
 static int mini_cm_dealloc_core(struct nes_cm_core *);
 static int mini_cm_get(struct nes_cm_core *);
 static int mini_cm_set(struct nes_cm_core *, u32, u32);
 
-static void form_cm_frame(struct sk_buff *, struct nes_cm_node *,
-	void *, u32, void *, u32, u8);
+static void form_cm_frame(struct sk_buff *, struct nes_cm_node *, void *, u32, void *, u32, u8);
 static int add_ref_cm_node(struct nes_cm_node *);
 static int rem_ref_cm_node(struct nes_cm_core *, struct nes_cm_node *);
 
@@ -111,16 +104,14 @@ static int send_syn(struct nes_cm_node *, u32, struct sk_buff *);
 static int send_reset(struct nes_cm_node *, struct sk_buff *);
 static int send_ack(struct nes_cm_node *cm_node, struct sk_buff *skb);
 static int send_fin(struct nes_cm_node *cm_node, struct sk_buff *skb);
-static void process_packet(struct nes_cm_node *, struct sk_buff *,
-	struct nes_cm_core *);
+static void process_packet(struct nes_cm_node *, struct sk_buff *, struct nes_cm_core *);
 
 static void active_open_err(struct nes_cm_node *, struct sk_buff *, int);
 static void passive_open_err(struct nes_cm_node *, struct sk_buff *, int);
 static void cleanup_retrans_entry(struct nes_cm_node *);
 static void handle_rcv_mpa(struct nes_cm_node *, struct sk_buff *);
 static void free_retrans_entry(struct nes_cm_node *cm_node);
-static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph,
-	struct sk_buff *skb, int optionsize, int passive);
+static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph, struct sk_buff *skb, int optionsize, int passive);
 
 /* CM event handler functions */
 static void cm_event_connected(struct nes_cm_event *);
@@ -130,6 +121,12 @@ static void cm_event_mpa_req(struct nes_cm_event *);
 static void cm_event_mpa_reject(struct nes_cm_event *);
 static void handle_recv_entry(struct nes_cm_node *cm_node, u32 rem_node);
 
+/* MPA build functions */
+static int cm_build_mpa_frame(struct nes_cm_node *, u8 **, u16 *, u8 *, u8);
+static void build_mpa_v2(struct nes_cm_node *, void *, u8);
+static void build_mpa_v1(struct nes_cm_node *, void *, u8);
+static void build_rdma0_msg(struct nes_cm_node *, struct nes_qp **);
+
 static void print_core(struct nes_cm_core *core);
 
 /* External CM API Interface */
@@ -159,12 +156,21 @@ atomic_t cm_connecteds;
 atomic_t cm_connect_reqs;
 atomic_t cm_rejects;
 
+int nes_add_ref_cm_node(struct nes_cm_node *cm_node)
+{
+	return add_ref_cm_node(cm_node);
+}
+
+int nes_rem_ref_cm_node(struct nes_cm_node *cm_node)
+{
+	return rem_ref_cm_node(cm_node->cm_core, cm_node);
+}
 
 /**
  * create_event
  */
-static struct nes_cm_event *create_event(struct nes_cm_node *cm_node,
-		enum nes_cm_event_type type)
+static struct nes_cm_event *create_event(struct nes_cm_node *	cm_node,
+					 enum nes_cm_event_type type)
 {
 	struct nes_cm_event *event;
 
@@ -186,10 +192,10 @@ static struct nes_cm_event *create_event(struct nes_cm_node *cm_node,
 	event->cm_info.cm_id = cm_node->cm_id;
 
 	nes_debug(NES_DBG_CM, "cm_node=%p Created event=%p, type=%u, "
-		"dst_addr=%08x[%x], src_addr=%08x[%x]\n",
-		cm_node, event, type, event->cm_info.loc_addr,
-		event->cm_info.loc_port, event->cm_info.rem_addr,
-		event->cm_info.rem_port);
+		  "dst_addr=%08x[%x], src_addr=%08x[%x]\n",
+		  cm_node, event, type, event->cm_info.loc_addr,
+		  event->cm_info.loc_port, event->cm_info.rem_addr,
+		  event->cm_info.rem_port);
 
 	nes_cm_post_event(event);
 	return event;
@@ -201,14 +207,19 @@ static struct nes_cm_event *create_event(struct nes_cm_node *cm_node,
  */
 static int send_mpa_request(struct nes_cm_node *cm_node, struct sk_buff *skb)
 {
+	u8 start_addr = 0;
+	u8 *start_ptr = &start_addr;
+	u8 **start_buff = &start_ptr;
+	u16 buff_len = 0;
+
 	if (!skb) {
 		nes_debug(NES_DBG_CM, "skb set to NULL\n");
 		return -1;
 	}
 
 	/* send an MPA Request frame */
-	form_cm_frame(skb, cm_node, NULL, 0, &cm_node->mpa_frame,
-			cm_node->mpa_frame_size, SET_ACK);
+	cm_build_mpa_frame(cm_node, start_buff, &buff_len, NULL, MPA_KEY_REQUEST);
+	form_cm_frame(skb, cm_node, NULL, 0, *start_buff, buff_len, SET_ACK);
 
 	return schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0);
 }
@@ -217,7 +228,11 @@ static int send_mpa_request(struct nes_cm_node *cm_node, struct sk_buff *skb)
 
 static int send_mpa_reject(struct nes_cm_node *cm_node)
 {
-	struct sk_buff  *skb = NULL;
+	struct sk_buff *skb = NULL;
+	u8 start_addr = 0;
+	u8 *start_ptr = &start_addr;
+	u8 **start_buff = &start_ptr;
+	u16 buff_len = 0;
 
 	skb = dev_alloc_skb(MAX_CM_BUFFER);
 	if (!skb) {
@@ -226,8 +241,8 @@ static int send_mpa_reject(struct nes_cm_node *cm_node)
 	}
 
 	/* send an MPA reject frame */
-	form_cm_frame(skb, cm_node, NULL, 0, &cm_node->mpa_frame,
-			cm_node->mpa_frame_size, SET_ACK | SET_FIN);
+	cm_build_mpa_frame(cm_node, start_buff, &buff_len, NULL, MPA_KEY_REPLY);
+	form_cm_frame(skb, cm_node, NULL, 0, *start_buff, buff_len, SET_ACK | SET_FIN);
 
 	cm_node->state = NES_CM_STATE_FIN_WAIT1;
 	return schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0);
@@ -239,24 +254,31 @@ static int send_mpa_reject(struct nes_cm_node *cm_node)
  * IETF MPA frame
  */
 static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 *type,
-		u32 len)
+		     u32 len)
 {
-	struct ietf_mpa_frame *mpa_frame;
+	struct ietf_mpa_v1 *mpa_frame;
+	struct ietf_mpa_v2 *mpa_v2_frame;
+	struct ietf_rtr_msg *rtr_msg;
+	int mpa_hdr_len;
+	int priv_data_len;
 
 	*type = NES_MPA_REQUEST_ACCEPT;
 
 	/* assume req frame is in tcp data payload */
-	if (len < sizeof(struct ietf_mpa_frame)) {
+	if (len < sizeof(struct ietf_mpa_v1)) {
 		nes_debug(NES_DBG_CM, "The received ietf buffer was too small (%x)\n", len);
 		return -EINVAL;
 	}
 
-	mpa_frame = (struct ietf_mpa_frame *)buffer;
-	cm_node->mpa_frame_size = ntohs(mpa_frame->priv_data_len);
+	/* points to the beginning of the frame, which could be MPA V1 or V2 */
+	mpa_frame = (struct ietf_mpa_v1 *)buffer;
+	mpa_hdr_len = sizeof(struct ietf_mpa_v1);
+	priv_data_len = ntohs(mpa_frame->priv_data_len);
+
 	/* make sure mpa private data len is less than 512 bytes */
-	if (cm_node->mpa_frame_size > IETF_MAX_PRIV_DATA_LEN) {
+	if (priv_data_len > IETF_MAX_PRIV_DATA_LEN) {
 		nes_debug(NES_DBG_CM, "The received Length of Private"
-			" Data field exceeds 512 octets\n");
+			  " Data field exceeds 512 octets\n");
 		return -EINVAL;
 	}
 	/*
@@ -264,11 +286,22 @@ static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 *type,
 	 * received MPA version and MPA key information
 	 *
 	 */
-	if (mpa_frame->rev != mpa_version) {
+	if (mpa_frame->rev != IETF_MPA_V1 && mpa_frame->rev != IETF_MPA_V2) {
+		nes_debug(NES_DBG_CM, "The received mpa version"
+			  " is not supported\n");
+		return -EINVAL;
+	}
+	/*
+	* backwards compatibility only
+	*/
+	if (mpa_frame->rev > cm_node->mpa_frame_rev) {
 		nes_debug(NES_DBG_CM, "The received mpa version"
-				" can not be interoperated\n");
+			" can not be interoperated\n");
 		return -EINVAL;
+	} else {
+		cm_node->mpa_frame_rev = mpa_frame->rev;
 	}
+
 	if (cm_node->state != NES_CM_STATE_MPAREQ_SENT) {
 		if (memcmp(mpa_frame->key, IEFT_MPA_KEY_REQ, IETF_MPA_KEY_SIZE)) {
 			nes_debug(NES_DBG_CM, "Unexpected MPA Key received \n");
@@ -281,25 +314,75 @@ static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 *type,
 		}
 	}
 
-	if (cm_node->mpa_frame_size + sizeof(struct ietf_mpa_frame) != len) {
+
+	if (priv_data_len + mpa_hdr_len != len) {
 		nes_debug(NES_DBG_CM, "The received ietf buffer was not right"
-				" complete (%x + %x != %x)\n",
-				cm_node->mpa_frame_size,
-				(u32)sizeof(struct ietf_mpa_frame), len);
+			" complete (%x + %x != %x)\n",
+			priv_data_len, mpa_hdr_len, len);
 		return -EINVAL;
 	}
 	/* make sure it does not exceed the max size */
 	if (len > MAX_CM_BUFFER) {
 		nes_debug(NES_DBG_CM, "The received ietf buffer was too large"
-				" (%x + %x != %x)\n",
-				cm_node->mpa_frame_size,
-				(u32)sizeof(struct ietf_mpa_frame), len);
+			" (%x + %x != %x)\n",
+			priv_data_len, mpa_hdr_len, len);
 		return -EINVAL;
 	}
 
+	cm_node->mpa_frame_size = priv_data_len;
+
+	switch (mpa_frame->rev) {
+	case IETF_MPA_V2: {
+		u16 ird_size;
+		u16 ord_size;
+		mpa_v2_frame = (struct ietf_mpa_v2 *)buffer;
+		mpa_hdr_len += IETF_RTR_MSG_SIZE;
+		cm_node->mpa_frame_size -= IETF_RTR_MSG_SIZE;
+		rtr_msg = &mpa_v2_frame->rtr_msg;
+
+		/* parse rtr message */
+		rtr_msg->ctrl_ird = ntohs(rtr_msg->ctrl_ird);
+		rtr_msg->ctrl_ord = ntohs(rtr_msg->ctrl_ord);
+		ird_size = rtr_msg->ctrl_ird & IETF_NO_IRD_ORD;
+		ord_size = rtr_msg->ctrl_ord & IETF_NO_IRD_ORD;
+
+		if (!(rtr_msg->ctrl_ird & IETF_PEER_TO_PEER)) {
+			/* send reset */
+			return -EINVAL;
+		}
+
+		if (cm_node->state != NES_CM_STATE_MPAREQ_SENT) {
+			/* responder */
+			if (cm_node->ord_size > ird_size)
+				cm_node->ord_size = ird_size;
+		} else {
+			/* initiator */
+			if (cm_node->ord_size > ird_size)
+				cm_node->ord_size = ird_size;
+
+			if (cm_node->ird_size < ord_size) {
+				/* no resources available */
+				/* send terminate message */
+				return -EINVAL;
+			}
+		}
+
+		if (rtr_msg->ctrl_ord & IETF_RDMA0_READ) {
+			cm_node->send_rdma0_op = SEND_RDMA_READ_ZERO;
+		} else if (rtr_msg->ctrl_ord & IETF_RDMA0_WRITE) {
+			cm_node->send_rdma0_op = SEND_RDMA_WRITE_ZERO;
+		} else {        /* Not supported RDMA0 operation */
+			return -EINVAL;
+		}
+		break;
+	}
+	case IETF_MPA_V1:
+	default:
+		break;
+	}
+
 	/* copy entire MPA frame to our cm_node's frame */
-	memcpy(cm_node->mpa_frame_buf, buffer + sizeof(struct ietf_mpa_frame),
-			cm_node->mpa_frame_size);
+	memcpy(cm_node->mpa_frame_buf, buffer + mpa_hdr_len, cm_node->mpa_frame_size);
 
 	if (mpa_frame->flags & IETF_MPA_FLAGS_REJECT)
 		*type = NES_MPA_REQUEST_REJECT;
@@ -312,8 +395,8 @@ static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 *type,
  * node info to build.
  */
 static void form_cm_frame(struct sk_buff *skb,
-	struct nes_cm_node *cm_node, void *options, u32 optionsize,
-	void *data, u32 datasize, u8 flags)
+			  struct nes_cm_node *cm_node, void *options, u32 optionsize,
+			  void *data, u32 datasize, u8 flags)
 {
 	struct tcphdr *tcph;
 	struct iphdr *iph;
@@ -322,14 +405,14 @@ static void form_cm_frame(struct sk_buff *skb,
 	u16 packetsize = sizeof(*iph);
 
 	packetsize += sizeof(*tcph);
-	packetsize +=  optionsize + datasize;
+	packetsize += optionsize + datasize;
 
+	skb_trim(skb, 0);
 	memset(skb->data, 0x00, ETH_HLEN + sizeof(*iph) + sizeof(*tcph));
 
-	skb->len = 0;
 	buf = skb_put(skb, packetsize + ETH_HLEN);
 
-	ethh = (struct ethhdr *) buf;
+	ethh = (struct ethhdr *)buf;
 	buf += ETH_HLEN;
 
 	iph = (struct iphdr *)buf;
@@ -337,7 +420,7 @@ static void form_cm_frame(struct sk_buff *skb,
 	tcph = (struct tcphdr *)buf;
 	skb_reset_mac_header(skb);
 	skb_set_network_header(skb, ETH_HLEN);
-	skb_set_transport_header(skb, ETH_HLEN+sizeof(*iph));
+	skb_set_transport_header(skb, ETH_HLEN + sizeof(*iph));
 	buf += sizeof(*tcph);
 
 	skb->ip_summed = CHECKSUM_PARTIAL;
@@ -350,14 +433,14 @@ static void form_cm_frame(struct sk_buff *skb,
 	ethh->h_proto = htons(0x0800);
 
 	iph->version = IPVERSION;
-	iph->ihl = 5;		/* 5 * 4Byte words, IP headr len */
+	iph->ihl = 5;           /* 5 * 4Byte words, IP headr len */
 	iph->tos = 0;
 	iph->tot_len = htons(packetsize);
 	iph->id = htons(++cm_node->tcp_cntxt.loc_id);
 
 	iph->frag_off = htons(0x4000);
 	iph->ttl = 0x40;
-	iph->protocol = 0x06;	/* IPPROTO_TCP */
+	iph->protocol = 0x06;   /* IPPROTO_TCP */
 
 	iph->saddr = htonl(cm_node->loc_addr);
 	iph->daddr = htonl(cm_node->rem_addr);
@@ -370,14 +453,16 @@ static void form_cm_frame(struct sk_buff *skb,
 		cm_node->tcp_cntxt.loc_ack_num = cm_node->tcp_cntxt.rcv_nxt;
 		tcph->ack_seq = htonl(cm_node->tcp_cntxt.loc_ack_num);
 		tcph->ack = 1;
-	} else
+	} else {
 		tcph->ack_seq = 0;
+	}
 
 	if (flags & SET_SYN) {
 		cm_node->tcp_cntxt.loc_seq_num++;
 		tcph->syn = 1;
-	} else
+	} else {
 		cm_node->tcp_cntxt.loc_seq_num += datasize;
+	}
 
 	if (flags & SET_FIN) {
 		cm_node->tcp_cntxt.loc_seq_num++;
@@ -398,10 +483,8 @@ static void form_cm_frame(struct sk_buff *skb,
 
 	skb_shinfo(skb)->nr_frags = 0;
 	cm_packets_created++;
-
 }
 
-
 /**
  * print_core - dump a cm core
  */
@@ -413,7 +496,7 @@ static void print_core(struct nes_cm_core *core)
 		return;
 	nes_debug(NES_DBG_CM, "---------------------------------------------\n");
 
-	nes_debug(NES_DBG_CM, "State         : %u \n",  core->state);
+	nes_debug(NES_DBG_CM, "State         : %u \n", core->state);
 
 	nes_debug(NES_DBG_CM, "Listen Nodes  : %u \n", atomic_read(&core->listen_node_cnt));
 	nes_debug(NES_DBG_CM, "Active Nodes  : %u \n", atomic_read(&core->node_cnt));
@@ -423,6 +506,147 @@ static void print_core(struct nes_cm_core *core)
 	nes_debug(NES_DBG_CM, "-------------- end core ---------------\n");
 }
 
+/**
+ * cm_build_mpa_frame - build a MPA V1 frame or MPA V2 frame
+ */
+static int cm_build_mpa_frame(struct nes_cm_node *cm_node, u8 **start_buff,
+			      u16 *buff_len, u8 *pci_mem, u8 mpa_key)
+{
+	int ret = 0;
+
+	*start_buff = (pci_mem) ? pci_mem : &cm_node->mpa_frame_buf[0];
+
+	switch (cm_node->mpa_frame_rev) {
+	case IETF_MPA_V1:
+		*start_buff = (u8 *)*start_buff + sizeof(struct ietf_rtr_msg);
+		*buff_len = sizeof(struct ietf_mpa_v1) + cm_node->mpa_frame_size;
+		build_mpa_v1(cm_node, *start_buff, mpa_key);
+		break;
+	case IETF_MPA_V2:
+		*buff_len = sizeof(struct ietf_mpa_v2) + cm_node->mpa_frame_size;
+		build_mpa_v2(cm_node, *start_buff, mpa_key);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+/**
+ * build_mpa_v2 - build a MPA V2 frame
+ */
+static void build_mpa_v2(struct nes_cm_node *cm_node,
+			 void *start_addr, u8 mpa_key)
+{
+	struct ietf_mpa_v2 *mpa_frame = (struct ietf_mpa_v2 *)start_addr;
+	struct ietf_rtr_msg *rtr_msg = &mpa_frame->rtr_msg;
+
+	/* initialize the upper 5 bytes of the frame */
+	build_mpa_v1(cm_node, start_addr, mpa_key);
+	mpa_frame->flags |= IETF_MPA_V2_FLAG; /* set a bit to indicate MPA V2 */
+	mpa_frame->priv_data_len += htons(IETF_RTR_MSG_SIZE);
+
+	/* initialize RTR msg */
+	rtr_msg->ctrl_ird = (cm_node->ird_size > IETF_NO_IRD_ORD) ?
+			    IETF_NO_IRD_ORD : cm_node->ird_size;
+	rtr_msg->ctrl_ord = (cm_node->ord_size > IETF_NO_IRD_ORD) ?
+			    IETF_NO_IRD_ORD : cm_node->ord_size;
+
+	rtr_msg->ctrl_ird |= IETF_PEER_TO_PEER;
+	rtr_msg->ctrl_ird |= IETF_FLPDU_ZERO_LEN;
+
+	switch (mpa_key) {
+	case MPA_KEY_REQUEST:
+		rtr_msg->ctrl_ord |= IETF_RDMA0_WRITE;
+		rtr_msg->ctrl_ord |= IETF_RDMA0_READ;
+		break;
+	case MPA_KEY_REPLY:
+		switch (cm_node->send_rdma0_op) {
+		case SEND_RDMA_WRITE_ZERO:
+			rtr_msg->ctrl_ord |= IETF_RDMA0_WRITE;
+			break;
+		case SEND_RDMA_READ_ZERO:
+			rtr_msg->ctrl_ord |= IETF_RDMA0_READ;
+			break;
+		}
+	}
+	rtr_msg->ctrl_ird = htons(rtr_msg->ctrl_ird);
+	rtr_msg->ctrl_ord = htons(rtr_msg->ctrl_ord);
+}
+
+/**
+ * build_mpa_v1 - build a MPA V1 frame
+ */
+static void build_mpa_v1(struct nes_cm_node *cm_node, void *start_addr, u8 mpa_key)
+{
+	struct ietf_mpa_v1 *mpa_frame = (struct ietf_mpa_v1 *)start_addr;
+
+	switch (mpa_key) {
+	case MPA_KEY_REQUEST:
+		memcpy(mpa_frame->key, IEFT_MPA_KEY_REQ, IETF_MPA_KEY_SIZE);
+		break;
+	case MPA_KEY_REPLY:
+		memcpy(mpa_frame->key, IEFT_MPA_KEY_REP, IETF_MPA_KEY_SIZE);
+		break;
+	}
+	mpa_frame->flags = IETF_MPA_FLAGS_CRC;
+	mpa_frame->rev = cm_node->mpa_frame_rev;
+	mpa_frame->priv_data_len = htons(cm_node->mpa_frame_size);
+}
+
+static void build_rdma0_msg(struct nes_cm_node *cm_node, struct nes_qp **nesqp_addr)
+{
+	u64 u64temp;
+	struct nes_qp *nesqp = *nesqp_addr;
+	struct nes_hw_qp_wqe *wqe = &nesqp->hwqp.sq_vbase[0];
+
+	u64temp = (unsigned long)nesqp;
+	u64temp |= NES_SW_CONTEXT_ALIGN >> 1;
+	set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX, u64temp);
+
+	wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] = 0;
+	wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] = 0;
+
+	switch (cm_node->send_rdma0_op) {
+	case SEND_RDMA_WRITE_ZERO:
+		nes_debug(NES_DBG_CM, "Sending first write.\n");
+		wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] =
+			cpu_to_le32(NES_IWARP_SQ_OP_RDMAW);
+		wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = 0;
+		wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = 0;
+		wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0;
+		break;
+
+	case SEND_RDMA_READ_ZERO:
+	default:
+		if (cm_node->send_rdma0_op != SEND_RDMA_READ_ZERO) {
+			printk(KERN_ERR "%s[%u]: Unsupported RDMA0 len operation=%u\n",
+				 __func__, __LINE__, cm_node->send_rdma0_op);
+			WARN_ON(1);
+		}
+		nes_debug(NES_DBG_CM, "Sending first rdma operation.\n");
+		wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] =
+			cpu_to_le32(NES_IWARP_SQ_OP_RDMAR);
+		wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_TO_LOW_IDX] = 1;
+		wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_TO_HIGH_IDX] = 0;
+		wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX] = 0;
+		wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_STAG_IDX] = 1;
+		wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 1;
+		break;
+	}
+
+	if (nesqp->sq_kmapped) {
+		nesqp->sq_kmapped = 0;
+		kunmap(nesqp->page);
+	}
+
+	/*use the reserved spot on the WQ for the extra first WQE*/
+	nesqp->nesqp_context->ird_ord_sizes &= cpu_to_le32(~(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT |
+							     NES_QPCONTEXT_ORDIRD_WRPDU |
+							     NES_QPCONTEXT_ORDIRD_ALSMM));
+	nesqp->skip_lsmm = 1;
+	nesqp->hwqp.sq_tail = 0;
+}
 
 /**
  * schedule_nes_timer
@@ -430,10 +654,10 @@ static void print_core(struct nes_cm_core *core)
  *			rem_ref_cm_node(cm_core, cm_node);add_ref_cm_node(cm_node);
  */
 int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
-		enum nes_timer_type type, int send_retrans,
-		int close_when_complete)
+		       enum nes_timer_type type, int send_retrans,
+		       int close_when_complete)
 {
-	unsigned long  flags;
+	unsigned long flags;
 	struct nes_cm_core *cm_core = cm_node->cm_core;
 	struct nes_timer_entry *new_send;
 	int ret = 0;
@@ -454,7 +678,7 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
 	new_send->close_when_complete = close_when_complete;
 
 	if (type == NES_TIMER_TYPE_CLOSE) {
-		new_send->timetosend += (HZ/10);
+		new_send->timetosend += (HZ / 10);
 		if (cm_node->recv_entry) {
 			kfree(new_send);
 			WARN_ON(1);
@@ -475,7 +699,7 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
 		ret = nes_nic_cm_xmit(new_send->skb, cm_node->netdev);
 		if (ret != NETDEV_TX_OK) {
 			nes_debug(NES_DBG_CM, "Error sending packet %p "
-				"(jiffies = %lu)\n", new_send, jiffies);
+				  "(jiffies = %lu)\n", new_send, jiffies);
 			new_send->timetosend = jiffies;
 			ret = NETDEV_TX_OK;
 		} else {
@@ -504,6 +728,7 @@ static void nes_retrans_expired(struct nes_cm_node *cm_node)
 	struct iw_cm_id *cm_id = cm_node->cm_id;
 	enum nes_cm_node_state state = cm_node->state;
 	cm_node->state = NES_CM_STATE_CLOSED;
+
 	switch (state) {
 	case NES_CM_STATE_SYN_RCVD:
 	case NES_CM_STATE_CLOSING:
@@ -536,10 +761,10 @@ static void handle_recv_entry(struct nes_cm_node *cm_node, u32 rem_node)
 		spin_lock_irqsave(&nesqp->lock, qplockflags);
 		if (nesqp->cm_id) {
 			nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, "
-				"refcount = %d: HIT A "
-				"NES_TIMER_TYPE_CLOSE with something "
-				"to do!!!\n", nesqp->hwqp.qp_id, cm_id,
-				atomic_read(&nesqp->refcount));
+				  "refcount = %d: HIT A "
+				  "NES_TIMER_TYPE_CLOSE with something "
+				  "to do!!!\n", nesqp->hwqp.qp_id, cm_id,
+				  atomic_read(&nesqp->refcount));
 			nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
 			nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT;
 			nesqp->ibqp_state = IB_QPS_ERR;
@@ -548,10 +773,10 @@ static void handle_recv_entry(struct nes_cm_node *cm_node, u32 rem_node)
 		} else {
 			spin_unlock_irqrestore(&nesqp->lock, qplockflags);
 			nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, "
-				"refcount = %d: HIT A "
-				"NES_TIMER_TYPE_CLOSE with nothing "
-				"to do!!!\n", nesqp->hwqp.qp_id, cm_id,
-				atomic_read(&nesqp->refcount));
+				  "refcount = %d: HIT A "
+				  "NES_TIMER_TYPE_CLOSE with nothing "
+				  "to do!!!\n", nesqp->hwqp.qp_id, cm_id,
+				  atomic_read(&nesqp->refcount));
 		}
 	} else if (rem_node) {
 		/* TIME_WAIT state */
@@ -580,11 +805,12 @@ static void nes_cm_timer_tick(unsigned long pass)
 	int ret = NETDEV_TX_OK;
 
 	struct list_head timer_list;
+
 	INIT_LIST_HEAD(&timer_list);
 	spin_lock_irqsave(&cm_core->ht_lock, flags);
 
 	list_for_each_safe(list_node, list_core_temp,
-				&cm_core->connected_nodes) {
+			   &cm_core->connected_nodes) {
 		cm_node = container_of(list_node, struct nes_cm_node, list);
 		if ((cm_node->recv_entry) || (cm_node->send_entry)) {
 			add_ref_cm_node(cm_node);
@@ -595,18 +821,19 @@ static void nes_cm_timer_tick(unsigned long pass)
 
 	list_for_each_safe(list_node, list_core_temp, &timer_list) {
 		cm_node = container_of(list_node, struct nes_cm_node,
-					timer_entry);
+				       timer_entry);
 		recv_entry = cm_node->recv_entry;
 
 		if (recv_entry) {
 			if (time_after(recv_entry->timetosend, jiffies)) {
 				if (nexttimeout > recv_entry->timetosend ||
-						!settimer) {
+				    !settimer) {
 					nexttimeout = recv_entry->timetosend;
 					settimer = 1;
 				}
-			} else
+			} else {
 				handle_recv_entry(cm_node, 1);
+			}
 		}
 
 		spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
@@ -617,8 +844,8 @@ static void nes_cm_timer_tick(unsigned long pass)
 			if (time_after(send_entry->timetosend, jiffies)) {
 				if (cm_node->state != NES_CM_STATE_TSA) {
 					if ((nexttimeout >
-						send_entry->timetosend) ||
-						!settimer) {
+					     send_entry->timetosend) ||
+					    !settimer) {
 						nexttimeout =
 							send_entry->timetosend;
 						settimer = 1;
@@ -630,13 +857,13 @@ static void nes_cm_timer_tick(unsigned long pass)
 			}
 
 			if ((cm_node->state == NES_CM_STATE_TSA) ||
-				(cm_node->state == NES_CM_STATE_CLOSED)) {
+			    (cm_node->state == NES_CM_STATE_CLOSED)) {
 				free_retrans_entry(cm_node);
 				break;
 			}
 
 			if (!send_entry->retranscount ||
-				!send_entry->retrycount) {
+			    !send_entry->retrycount) {
 				cm_packets_dropped++;
 				free_retrans_entry(cm_node);
 
@@ -645,28 +872,28 @@ static void nes_cm_timer_tick(unsigned long pass)
 				nes_retrans_expired(cm_node);
 				cm_node->state = NES_CM_STATE_CLOSED;
 				spin_lock_irqsave(&cm_node->retrans_list_lock,
-					flags);
+						  flags);
 				break;
 			}
 			atomic_inc(&send_entry->skb->users);
 			cm_packets_retrans++;
 			nes_debug(NES_DBG_CM, "Retransmitting send_entry %p "
-				"for node %p, jiffies = %lu, time to send = "
-				"%lu, retranscount = %u, send_entry->seq_num = "
-				"0x%08X, cm_node->tcp_cntxt.rem_ack_num = "
-				"0x%08X\n", send_entry, cm_node, jiffies,
-				send_entry->timetosend,
-				send_entry->retranscount,
-				send_entry->seq_num,
-				cm_node->tcp_cntxt.rem_ack_num);
+				  "for node %p, jiffies = %lu, time to send = "
+				  "%lu, retranscount = %u, send_entry->seq_num = "
+				  "0x%08X, cm_node->tcp_cntxt.rem_ack_num = "
+				  "0x%08X\n", send_entry, cm_node, jiffies,
+				  send_entry->timetosend,
+				  send_entry->retranscount,
+				  send_entry->seq_num,
+				  cm_node->tcp_cntxt.rem_ack_num);
 
 			spin_unlock_irqrestore(&cm_node->retrans_list_lock,
-				flags);
+					       flags);
 			ret = nes_nic_cm_xmit(send_entry->skb, cm_node->netdev);
 			spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
 			if (ret != NETDEV_TX_OK) {
 				nes_debug(NES_DBG_CM, "rexmit failed for "
-					"node=%p\n", cm_node);
+					  "node=%p\n", cm_node);
 				cm_packets_bounced++;
 				send_entry->retrycount--;
 				nexttimeout = jiffies + NES_SHORT_TIME;
@@ -676,18 +903,18 @@ static void nes_cm_timer_tick(unsigned long pass)
 				cm_packets_sent++;
 			}
 			nes_debug(NES_DBG_CM, "Packet Sent: retrans count = "
-				"%u, retry count = %u.\n",
-				send_entry->retranscount,
-				send_entry->retrycount);
+				  "%u, retry count = %u.\n",
+				  send_entry->retranscount,
+				  send_entry->retrycount);
 			if (send_entry->send_retrans) {
 				send_entry->retranscount--;
 				timetosend = (NES_RETRY_TIMEOUT <<
-					(NES_DEFAULT_RETRANS - send_entry->retranscount));
+					      (NES_DEFAULT_RETRANS - send_entry->retranscount));
 
 				send_entry->timetosend = jiffies +
-					min(timetosend, NES_MAX_TIMEOUT);
+							 min(timetosend, NES_MAX_TIMEOUT);
 				if (nexttimeout > send_entry->timetosend ||
-					!settimer) {
+				    !settimer) {
 					nexttimeout = send_entry->timetosend;
 					settimer = 1;
 				}
@@ -696,11 +923,11 @@ static void nes_cm_timer_tick(unsigned long pass)
 				close_when_complete =
 					send_entry->close_when_complete;
 				nes_debug(NES_DBG_CM, "cm_node=%p state=%d\n",
-					cm_node, cm_node->state);
+					  cm_node, cm_node->state);
 				free_retrans_entry(cm_node);
 				if (close_when_complete)
 					rem_ref_cm_node(cm_node->cm_core,
-						cm_node);
+							cm_node);
 			}
 		} while (0);
 
@@ -710,7 +937,7 @@ static void nes_cm_timer_tick(unsigned long pass)
 
 	if (settimer) {
 		if (!timer_pending(&cm_core->tcp_timer)) {
-			cm_core->tcp_timer.expires  = nexttimeout;
+			cm_core->tcp_timer.expires = nexttimeout;
 			add_timer(&cm_core->tcp_timer);
 		}
 	}
@@ -721,13 +948,13 @@ static void nes_cm_timer_tick(unsigned long pass)
  * send_syn
  */
 static int send_syn(struct nes_cm_node *cm_node, u32 sendack,
-	struct sk_buff *skb)
+		    struct sk_buff *skb)
 {
 	int ret;
 	int flags = SET_SYN;
 	char optionsbuffer[sizeof(struct option_mss) +
-		sizeof(struct option_windowscale) + sizeof(struct option_base) +
-		TCP_OPTIONS_PADDING];
+			   sizeof(struct option_windowscale) + sizeof(struct option_base) +
+			   TCP_OPTIONS_PADDING];
 
 	int optionssize = 0;
 	/* Sending MSS option */
@@ -854,7 +1081,7 @@ static int send_fin(struct nes_cm_node *cm_node, struct sk_buff *skb)
  * find_node - find a cm node that matches the reference cm node
  */
 static struct nes_cm_node *find_node(struct nes_cm_core *cm_core,
-		u16 rem_port, nes_addr_t rem_addr, u16 loc_port, nes_addr_t loc_addr)
+				     u16 rem_port, nes_addr_t rem_addr, u16 loc_port, nes_addr_t loc_addr)
 {
 	unsigned long flags;
 	struct list_head *hte;
@@ -868,12 +1095,12 @@ static struct nes_cm_node *find_node(struct nes_cm_core *cm_core,
 	list_for_each_entry(cm_node, hte, list) {
 		/* compare quad, return node handle if a match */
 		nes_debug(NES_DBG_CM, "finding node %x:%x =? %x:%x ^ %x:%x =? %x:%x\n",
-				cm_node->loc_addr, cm_node->loc_port,
-				loc_addr, loc_port,
-				cm_node->rem_addr, cm_node->rem_port,
-				rem_addr, rem_port);
+			  cm_node->loc_addr, cm_node->loc_port,
+			  loc_addr, loc_port,
+			  cm_node->rem_addr, cm_node->rem_port,
+			  rem_addr, rem_port);
 		if ((cm_node->loc_addr == loc_addr) && (cm_node->loc_port == loc_port) &&
-				(cm_node->rem_addr == rem_addr) && (cm_node->rem_port == rem_port)) {
+		    (cm_node->rem_addr == rem_addr) && (cm_node->rem_port == rem_port)) {
 			add_ref_cm_node(cm_node);
 			spin_unlock_irqrestore(&cm_core->ht_lock, flags);
 			return cm_node;
@@ -890,7 +1117,7 @@ static struct nes_cm_node *find_node(struct nes_cm_core *cm_core,
  * find_listener - find a cm node listening on this addr-port pair
  */
 static struct nes_cm_listener *find_listener(struct nes_cm_core *cm_core,
-		nes_addr_t dst_addr, u16 dst_port, enum nes_cm_listener_state listener_state)
+					     nes_addr_t dst_addr, u16 dst_port, enum nes_cm_listener_state listener_state)
 {
 	unsigned long flags;
 	struct nes_cm_listener *listen_node;
@@ -900,9 +1127,9 @@ static struct nes_cm_listener *find_listener(struct nes_cm_core *cm_core,
 	list_for_each_entry(listen_node, &cm_core->listen_list.list, list) {
 		/* compare node pair, return node handle if a match */
 		if (((listen_node->loc_addr == dst_addr) ||
-				listen_node->loc_addr == 0x00000000) &&
-				(listen_node->loc_port == dst_port) &&
-				(listener_state & listen_node->listener_state)) {
+		     listen_node->loc_addr == 0x00000000) &&
+		    (listen_node->loc_port == dst_port) &&
+		    (listener_state & listen_node->listener_state)) {
 			atomic_inc(&listen_node->ref_count);
 			spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);
 			return listen_node;
@@ -927,7 +1154,7 @@ static int add_hte_node(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node
 		return -EINVAL;
 
 	nes_debug(NES_DBG_CM, "Adding Node %p to Active Connection HT\n",
-		cm_node);
+		  cm_node);
 
 	spin_lock_irqsave(&cm_core->ht_lock, flags);
 
@@ -946,7 +1173,7 @@ static int add_hte_node(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node
  * mini_cm_dec_refcnt_listen
  */
 static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
-	struct nes_cm_listener *listener, int free_hanging_nodes)
+				     struct nes_cm_listener *listener, int free_hanging_nodes)
 {
 	int ret = -EINVAL;
 	int err = 0;
@@ -957,8 +1184,8 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
 	struct list_head reset_list;
 
 	nes_debug(NES_DBG_CM, "attempting listener= %p free_nodes= %d, "
-		"refcnt=%d\n", listener, free_hanging_nodes,
-		atomic_read(&listener->ref_count));
+		  "refcnt=%d\n", listener, free_hanging_nodes,
+		  atomic_read(&listener->ref_count));
 	/* free non-accelerated child nodes for this listener */
 	INIT_LIST_HEAD(&reset_list);
 	if (free_hanging_nodes) {
@@ -966,7 +1193,7 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
 		list_for_each_safe(list_pos, list_temp,
 				   &g_cm_core->connected_nodes) {
 			cm_node = container_of(list_pos, struct nes_cm_node,
-				list);
+					       list);
 			if ((cm_node->listener == listener) &&
 			    (!cm_node->accelerated)) {
 				add_ref_cm_node(cm_node);
@@ -978,7 +1205,7 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
 
 	list_for_each_safe(list_pos, list_temp, &reset_list) {
 		cm_node = container_of(list_pos, struct nes_cm_node,
-				reset_entry);
+				       reset_entry);
 		{
 			struct nes_cm_node *loopback = cm_node->loopbackpartner;
 			enum nes_cm_node_state old_state;
@@ -990,7 +1217,7 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
 					err = send_reset(cm_node, NULL);
 					if (err) {
 						cm_node->state =
-							 NES_CM_STATE_CLOSED;
+							NES_CM_STATE_CLOSED;
 						WARN_ON(1);
 					} else {
 						old_state = cm_node->state;
@@ -1035,10 +1262,9 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
 
 		spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);
 
-		if (listener->nesvnic) {
+		if (listener->nesvnic)
 			nes_manage_apbvt(listener->nesvnic, listener->loc_port,
-					PCI_FUNC(listener->nesvnic->nesdev->pcidev->devfn), NES_MANAGE_APBVT_DEL);
-		}
+					 PCI_FUNC(listener->nesvnic->nesdev->pcidev->devfn), NES_MANAGE_APBVT_DEL);
 
 		nes_debug(NES_DBG_CM, "destroying listener (%p)\n", listener);
 
@@ -1052,8 +1278,8 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
 	if (listener) {
 		if (atomic_read(&listener->pend_accepts_cnt) > 0)
 			nes_debug(NES_DBG_CM, "destroying listener (%p)"
-					" with non-zero pending accepts=%u\n",
-					listener, atomic_read(&listener->pend_accepts_cnt));
+				  " with non-zero pending accepts=%u\n",
+				  listener, atomic_read(&listener->pend_accepts_cnt));
 	}
 
 	return ret;
@@ -1064,7 +1290,7 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
  * mini_cm_del_listen
  */
 static int mini_cm_del_listen(struct nes_cm_core *cm_core,
-		struct nes_cm_listener *listener)
+			      struct nes_cm_listener *listener)
 {
 	listener->listener_state = NES_CM_LISTENER_PASSIVE_STATE;
 	listener->cm_id = NULL; /* going to be destroyed pretty soon */
@@ -1076,9 +1302,10 @@ static int mini_cm_del_listen(struct nes_cm_core *cm_core,
  * mini_cm_accelerated
  */
 static inline int mini_cm_accelerated(struct nes_cm_core *cm_core,
-		struct nes_cm_node *cm_node)
+				      struct nes_cm_node *cm_node)
 {
 	u32 was_timer_set;
+
 	cm_node->accelerated = 1;
 
 	if (cm_node->accept_pend) {
@@ -1112,7 +1339,7 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
 	rt = ip_route_output(&init_net, htonl(dst_ip), 0, 0, 0);
 	if (IS_ERR(rt)) {
 		printk(KERN_ERR "%s: ip_route_output_key failed for 0x%08X\n",
-				__func__, dst_ip);
+		       __func__, dst_ip);
 		return rc;
 	}
 
@@ -1130,7 +1357,7 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
 
 			if (arpindex >= 0) {
 				if (!memcmp(nesadapter->arp_table[arpindex].mac_addr,
-							neigh->ha, ETH_ALEN)){
+					    neigh->ha, ETH_ALEN)) {
 					/* Mac address same as in nes_arp_table */
 					neigh_release(neigh);
 					ip_rt_put(rt);
@@ -1138,8 +1365,8 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
 				}
 
 				nes_manage_arp_cache(nesvnic->netdev,
-						nesadapter->arp_table[arpindex].mac_addr,
-						dst_ip, NES_ARP_DELETE);
+						     nesadapter->arp_table[arpindex].mac_addr,
+						     dst_ip, NES_ARP_DELETE);
 			}
 
 			nes_manage_arp_cache(nesvnic->netdev, neigh->ha,
@@ -1161,8 +1388,8 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
  * make_cm_node - create a new instance of a cm node
  */
 static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
-		struct nes_vnic *nesvnic, struct nes_cm_info *cm_info,
-		struct nes_cm_listener *listener)
+					struct nes_vnic *nesvnic, struct nes_cm_info *cm_info,
+					struct nes_cm_listener *listener)
 {
 	struct nes_cm_node *cm_node;
 	struct timespec ts;
@@ -1181,7 +1408,12 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
 	cm_node->rem_addr = cm_info->rem_addr;
 	cm_node->loc_port = cm_info->loc_port;
 	cm_node->rem_port = cm_info->rem_port;
-	cm_node->send_write0 = send_first;
+
+	cm_node->mpa_frame_rev = mpa_version;
+	cm_node->send_rdma0_op = SEND_RDMA_READ_ZERO;
+	cm_node->ird_size = IETF_NO_IRD_ORD;
+	cm_node->ord_size = IETF_NO_IRD_ORD;
+
 	nes_debug(NES_DBG_CM, "Make node addresses : loc = %pI4:%x, rem = %pI4:%x\n",
 		  &cm_node->loc_addr, cm_node->loc_port,
 		  &cm_node->rem_addr, cm_node->rem_port);
@@ -1191,7 +1423,7 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
 	memcpy(cm_node->loc_mac, nesvnic->netdev->dev_addr, ETH_ALEN);
 
 	nes_debug(NES_DBG_CM, "listener=%p, cm_id=%p\n", cm_node->listener,
-			cm_node->cm_id);
+		  cm_node->cm_id);
 
 	spin_lock_init(&cm_node->retrans_list_lock);
 
@@ -1202,11 +1434,11 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
 	cm_node->tcp_cntxt.loc_id = NES_CM_DEF_LOCAL_ID;
 	cm_node->tcp_cntxt.rcv_wscale = NES_CM_DEFAULT_RCV_WND_SCALE;
 	cm_node->tcp_cntxt.rcv_wnd = NES_CM_DEFAULT_RCV_WND_SCALED >>
-			NES_CM_DEFAULT_RCV_WND_SCALE;
+				     NES_CM_DEFAULT_RCV_WND_SCALE;
 	ts = current_kernel_time();
 	cm_node->tcp_cntxt.loc_seq_num = htonl(ts.tv_nsec);
 	cm_node->tcp_cntxt.mss = nesvnic->max_frame_size - sizeof(struct iphdr) -
-			sizeof(struct tcphdr) - ETH_HLEN - VLAN_HLEN;
+				 sizeof(struct tcphdr) - ETH_HLEN - VLAN_HLEN;
 	cm_node->tcp_cntxt.rcv_nxt = 0;
 	/* get a unique session ID , add thread_id to an upcounter to handle race */
 	atomic_inc(&cm_core->node_cnt);
@@ -1222,12 +1454,11 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
 	cm_node->loopbackpartner = NULL;
 
 	/* get the mac addr for the remote node */
-	if (ipv4_is_loopback(htonl(cm_node->rem_addr)))
+	if (ipv4_is_loopback(htonl(cm_node->rem_addr))) {
 		arpindex = nes_arp_table(nesdev, ntohl(nesvnic->local_ipaddr), NULL, NES_ARP_RESOLVE);
-	else {
+	} else {
 		oldarpindex = nes_arp_table(nesdev, cm_node->rem_addr, NULL, NES_ARP_RESOLVE);
 		arpindex = nes_addr_resolve_neigh(nesvnic, cm_info->rem_addr, oldarpindex);
-
 	}
 	if (arpindex < 0) {
 		kfree(cm_node);
@@ -1260,7 +1491,7 @@ static int add_ref_cm_node(struct nes_cm_node *cm_node)
  * rem_ref_cm_node - destroy an instance of a cm node
  */
 static int rem_ref_cm_node(struct nes_cm_core *cm_core,
-	struct nes_cm_node *cm_node)
+			   struct nes_cm_node *cm_node)
 {
 	unsigned long flags;
 	struct nes_qp *nesqp;
@@ -1291,9 +1522,9 @@ static int rem_ref_cm_node(struct nes_cm_core *cm_core,
 	} else {
 		if (cm_node->apbvt_set && cm_node->nesvnic) {
 			nes_manage_apbvt(cm_node->nesvnic, cm_node->loc_port,
-				PCI_FUNC(
-				cm_node->nesvnic->nesdev->pcidev->devfn),
-				NES_MANAGE_APBVT_DEL);
+					 PCI_FUNC(
+						 cm_node->nesvnic->nesdev->pcidev->devfn),
+					 NES_MANAGE_APBVT_DEL);
 		}
 	}
 
@@ -1314,7 +1545,7 @@ static int rem_ref_cm_node(struct nes_cm_core *cm_core,
  * process_options
  */
 static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc,
-	u32 optionsize, u32 syn_packet)
+			   u32 optionsize, u32 syn_packet)
 {
 	u32 tmp;
 	u32 offset = 0;
@@ -1332,15 +1563,15 @@ static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc,
 			continue;
 		case OPTION_NUMBER_MSS:
 			nes_debug(NES_DBG_CM, "%s: MSS Length: %d Offset: %d "
-				"Size: %d\n", __func__,
-				all_options->as_mss.length, offset, optionsize);
+				  "Size: %d\n", __func__,
+				  all_options->as_mss.length, offset, optionsize);
 			got_mss_option = 1;
 			if (all_options->as_mss.length != 4) {
 				return 1;
 			} else {
 				tmp = ntohs(all_options->as_mss.mss);
 				if (tmp > 0 && tmp <
-					cm_node->tcp_cntxt.mss)
+				    cm_node->tcp_cntxt.mss)
 					cm_node->tcp_cntxt.mss = tmp;
 			}
 			break;
@@ -1348,12 +1579,9 @@ static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc,
 			cm_node->tcp_cntxt.snd_wscale =
 				all_options->as_windowscale.shiftcount;
 			break;
-		case OPTION_NUMBER_WRITE0:
-			cm_node->send_write0 = 1;
-			break;
 		default:
 			nes_debug(NES_DBG_CM, "TCP Option not understood: %x\n",
-				all_options->as_base.optionnum);
+				  all_options->as_base.optionnum);
 			break;
 		}
 		offset += all_options->as_base.length;
@@ -1372,8 +1600,8 @@ static void drop_packet(struct sk_buff *skb)
 static void handle_fin_pkt(struct nes_cm_node *cm_node)
 {
 	nes_debug(NES_DBG_CM, "Received FIN, cm_node = %p, state = %u. "
-		"refcnt=%d\n", cm_node, cm_node->state,
-		atomic_read(&cm_node->ref_count));
+		  "refcnt=%d\n", cm_node, cm_node->state,
+		  atomic_read(&cm_node->ref_count));
 	switch (cm_node->state) {
 	case NES_CM_STATE_SYN_RCVD:
 	case NES_CM_STATE_SYN_SENT:
@@ -1439,7 +1667,20 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
 		nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p "
 			"listener=%p state=%d\n", __func__, __LINE__, cm_node,
 			cm_node->listener, cm_node->state);
-		active_open_err(cm_node, skb, reset);
+		switch (cm_node->mpa_frame_rev) {
+		case IETF_MPA_V2:
+			cm_node->mpa_frame_rev = IETF_MPA_V1;
+			/* send a syn and goto syn sent state */
+			cm_node->state = NES_CM_STATE_SYN_SENT;
+			if (send_syn(cm_node, 0, NULL)) {
+				active_open_err(cm_node, skb, reset);
+			}
+			break;
+		case IETF_MPA_V1:
+		default:
+			active_open_err(cm_node, skb, reset);
+			break;
+		}
 		break;
 	case NES_CM_STATE_MPAREQ_RCVD:
 		atomic_inc(&cm_node->passive_state);
@@ -1475,21 +1716,21 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
 
 static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb)
 {
-
-	int	ret = 0;
+	int ret = 0;
 	int datasize = skb->len;
 	u8 *dataloc = skb->data;
 
 	enum nes_cm_event_type type = NES_CM_EVENT_UNKNOWN;
-	u32     res_type;
+	u32 res_type;
+
 	ret = parse_mpa(cm_node, dataloc, &res_type, datasize);
 	if (ret) {
 		nes_debug(NES_DBG_CM, "didn't like MPA Request\n");
 		if (cm_node->state == NES_CM_STATE_MPAREQ_SENT) {
 			nes_debug(NES_DBG_CM, "%s[%u] create abort for "
-				"cm_node=%p listener=%p state=%d\n", __func__,
-				__LINE__, cm_node, cm_node->listener,
-				cm_node->state);
+				  "cm_node=%p listener=%p state=%d\n", __func__,
+				  __LINE__, cm_node, cm_node->listener,
+				  cm_node->state);
 			active_open_err(cm_node, skb, 1);
 		} else {
 			passive_open_err(cm_node, skb, 1);
@@ -1499,16 +1740,15 @@ static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb)
 
 	switch (cm_node->state) {
 	case NES_CM_STATE_ESTABLISHED:
-		if (res_type == NES_MPA_REQUEST_REJECT) {
+		if (res_type == NES_MPA_REQUEST_REJECT)
 			/*BIG problem as we are receiving the MPA.. So should
-			* not be REJECT.. This is Passive Open.. We can
-			* only receive it Reject for Active Open...*/
+			 * not be REJECT.. This is Passive Open.. We can
+			 * only receive it Reject for Active Open...*/
 			WARN_ON(1);
-		}
 		cm_node->state = NES_CM_STATE_MPAREQ_RCVD;
 		type = NES_CM_EVENT_MPA_REQ;
 		atomic_set(&cm_node->passive_state,
-				NES_PASSIVE_STATE_INDICATED);
+			   NES_PASSIVE_STATE_INDICATED);
 		break;
 	case NES_CM_STATE_MPAREQ_SENT:
 		cleanup_retrans_entry(cm_node);
@@ -1535,8 +1775,8 @@ static void indicate_pkt_err(struct nes_cm_node *cm_node, struct sk_buff *skb)
 	case NES_CM_STATE_SYN_SENT:
 	case NES_CM_STATE_MPAREQ_SENT:
 		nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p "
-			"listener=%p state=%d\n", __func__, __LINE__, cm_node,
-			cm_node->listener, cm_node->state);
+			  "listener=%p state=%d\n", __func__, __LINE__, cm_node,
+			  cm_node->listener, cm_node->state);
 		active_open_err(cm_node, skb, 1);
 		break;
 	case NES_CM_STATE_ESTABLISHED:
@@ -1550,11 +1790,11 @@ static void indicate_pkt_err(struct nes_cm_node *cm_node, struct sk_buff *skb)
 }
 
 static int check_syn(struct nes_cm_node *cm_node, struct tcphdr *tcph,
-	struct sk_buff *skb)
+		     struct sk_buff *skb)
 {
 	int err;
 
-	err = ((ntohl(tcph->ack_seq) == cm_node->tcp_cntxt.loc_seq_num))? 0 : 1;
+	err = ((ntohl(tcph->ack_seq) == cm_node->tcp_cntxt.loc_seq_num)) ? 0 : 1;
 	if (err)
 		active_open_err(cm_node, skb, 1);
 
@@ -1562,7 +1802,7 @@ static int check_syn(struct nes_cm_node *cm_node, struct tcphdr *tcph,
 }
 
 static int check_seq(struct nes_cm_node *cm_node, struct tcphdr *tcph,
-	struct sk_buff *skb)
+		     struct sk_buff *skb)
 {
 	int err = 0;
 	u32 seq;
@@ -1570,21 +1810,22 @@ static int check_seq(struct nes_cm_node *cm_node, struct tcphdr *tcph,
 	u32 loc_seq_num = cm_node->tcp_cntxt.loc_seq_num;
 	u32 rcv_nxt = cm_node->tcp_cntxt.rcv_nxt;
 	u32 rcv_wnd;
+
 	seq = ntohl(tcph->seq);
 	ack_seq = ntohl(tcph->ack_seq);
 	rcv_wnd = cm_node->tcp_cntxt.rcv_wnd;
 	if (ack_seq != loc_seq_num)
 		err = 1;
-	else if (!between(seq, rcv_nxt, (rcv_nxt+rcv_wnd)))
+	else if (!between(seq, rcv_nxt, (rcv_nxt + rcv_wnd)))
 		err = 1;
 	if (err) {
 		nes_debug(NES_DBG_CM, "%s[%u] create abort for cm_node=%p "
-			"listener=%p state=%d\n", __func__, __LINE__, cm_node,
-			cm_node->listener, cm_node->state);
+			  "listener=%p state=%d\n", __func__, __LINE__, cm_node,
+			  cm_node->listener, cm_node->state);
 		indicate_pkt_err(cm_node, skb);
 		nes_debug(NES_DBG_CM, "seq ERROR cm_node =%p seq=0x%08X "
-			"rcv_nxt=0x%08X rcv_wnd=0x%x\n", cm_node, seq, rcv_nxt,
-			rcv_wnd);
+			  "rcv_nxt=0x%08X rcv_wnd=0x%x\n", cm_node, seq, rcv_nxt,
+			  rcv_wnd);
 	}
 	return err;
 }
@@ -1594,9 +1835,8 @@ static int check_seq(struct nes_cm_node *cm_node, struct tcphdr *tcph,
  * is created with a listener or it may comein as rexmitted packet which in
  * that case will be just dropped.
  */
-
 static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
-	struct tcphdr *tcph)
+			   struct tcphdr *tcph)
 {
 	int ret;
 	u32 inc_sequence;
@@ -1615,15 +1855,15 @@ static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
 	case NES_CM_STATE_LISTENING:
 		/* Passive OPEN */
 		if (atomic_read(&cm_node->listener->pend_accepts_cnt) >
-				cm_node->listener->backlog) {
+		    cm_node->listener->backlog) {
 			nes_debug(NES_DBG_CM, "drop syn due to backlog "
-				"pressure \n");
+				  "pressure \n");
 			cm_backlog_drops++;
 			passive_open_err(cm_node, skb, 0);
 			break;
 		}
 		ret = handle_tcp_options(cm_node, tcph, skb, optionsize,
-			1);
+					 1);
 		if (ret) {
 			passive_open_err(cm_node, skb, 0);
 			/* drop pkt */
@@ -1657,9 +1897,8 @@ static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
 }
 
 static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
-	struct tcphdr *tcph)
+			      struct tcphdr *tcph)
 {
-
 	int ret;
 	u32 inc_sequence;
 	int optionsize;
@@ -1678,7 +1917,7 @@ static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
 		ret = handle_tcp_options(cm_node, tcph, skb, optionsize, 0);
 		if (ret) {
 			nes_debug(NES_DBG_CM, "cm_node=%p tcp_options failed\n",
-				cm_node);
+				  cm_node);
 			break;
 		}
 		cleanup_retrans_entry(cm_node);
@@ -1717,12 +1956,13 @@ static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
 }
 
 static int handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
-	struct tcphdr *tcph)
+			  struct tcphdr *tcph)
 {
 	int datasize = 0;
 	u32 inc_sequence;
 	int ret = 0;
 	int optionsize;
+
 	optionsize = (tcph->doff << 2) - sizeof(struct tcphdr);
 
 	if (check_seq(cm_node, tcph, skb))
@@ -1743,8 +1983,9 @@ static int handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
 		if (datasize) {
 			cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
 			handle_rcv_mpa(cm_node, skb);
-		} else  /* rcvd ACK only */
+		} else { /* rcvd ACK only */
 			dev_kfree_skb_any(skb);
+		}
 		break;
 	case NES_CM_STATE_ESTABLISHED:
 		/* Passive OPEN */
@@ -1752,16 +1993,18 @@ static int handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
 		if (datasize) {
 			cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
 			handle_rcv_mpa(cm_node, skb);
-		} else
+		} else {
 			drop_packet(skb);
+		}
 		break;
 	case NES_CM_STATE_MPAREQ_SENT:
 		cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq);
 		if (datasize) {
 			cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
 			handle_rcv_mpa(cm_node, skb);
-		} else  /* Could be just an ack pkt.. */
+		} else { /* Could be just an ack pkt.. */
 			dev_kfree_skb_any(skb);
+		}
 		break;
 	case NES_CM_STATE_LISTENING:
 		cleanup_retrans_entry(cm_node);
@@ -1802,14 +2045,15 @@ static int handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
 
 
 static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph,
-	struct sk_buff *skb, int optionsize, int passive)
+			      struct sk_buff *skb, int optionsize, int passive)
 {
 	u8 *optionsloc = (u8 *)&tcph[1];
+
 	if (optionsize) {
 		if (process_options(cm_node, optionsloc, optionsize,
-			(u32)tcph->syn)) {
+				    (u32)tcph->syn)) {
 			nes_debug(NES_DBG_CM, "%s: Node %p, Sending RESET\n",
-				__func__, cm_node);
+				  __func__, cm_node);
 			if (passive)
 				passive_open_err(cm_node, skb, 1);
 			else
@@ -1819,7 +2063,7 @@ static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph,
 	}
 
 	cm_node->tcp_cntxt.snd_wnd = ntohs(tcph->window) <<
-			cm_node->tcp_cntxt.snd_wscale;
+				     cm_node->tcp_cntxt.snd_wscale;
 
 	if (cm_node->tcp_cntxt.snd_wnd > cm_node->tcp_cntxt.max_snd_wnd)
 		cm_node->tcp_cntxt.max_snd_wnd = cm_node->tcp_cntxt.snd_wnd;
@@ -1830,18 +2074,18 @@ static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph,
  * active_open_err() will send reset() if flag set..
  * It will also send ABORT event.
  */
-
 static void active_open_err(struct nes_cm_node *cm_node, struct sk_buff *skb,
-	int reset)
+			    int reset)
 {
 	cleanup_retrans_entry(cm_node);
 	if (reset) {
 		nes_debug(NES_DBG_CM, "ERROR active err called for cm_node=%p, "
-				"state=%d\n", cm_node, cm_node->state);
+			  "state=%d\n", cm_node, cm_node->state);
 		add_ref_cm_node(cm_node);
 		send_reset(cm_node, skb);
-	} else
+	} else {
 		dev_kfree_skb_any(skb);
+	}
 
 	cm_node->state = NES_CM_STATE_CLOSED;
 	create_event(cm_node, NES_CM_EVENT_ABORTED);
@@ -1851,15 +2095,14 @@ static void active_open_err(struct nes_cm_node *cm_node, struct sk_buff *skb,
  * passive_open_err() will either do a reset() or will free up the skb and
  * remove the cm_node.
  */
-
 static void passive_open_err(struct nes_cm_node *cm_node, struct sk_buff *skb,
-	int reset)
+			     int reset)
 {
 	cleanup_retrans_entry(cm_node);
 	cm_node->state = NES_CM_STATE_CLOSED;
 	if (reset) {
 		nes_debug(NES_DBG_CM, "passive_open_err sending RST for "
-			"cm_node=%p state =%d\n", cm_node, cm_node->state);
+			  "cm_node=%p state =%d\n", cm_node, cm_node->state);
 		send_reset(cm_node, skb);
 	} else {
 		dev_kfree_skb_any(skb);
@@ -1874,6 +2117,7 @@ static void passive_open_err(struct nes_cm_node *cm_node, struct sk_buff *skb,
 static void free_retrans_entry(struct nes_cm_node *cm_node)
 {
 	struct nes_timer_entry *send_entry;
+
 	send_entry = cm_node->send_entry;
 	if (send_entry) {
 		cm_node->send_entry = NULL;
@@ -1897,26 +2141,28 @@ static void cleanup_retrans_entry(struct nes_cm_node *cm_node)
  * Returns skb if to be freed, else it will return NULL if already used..
  */
 static void process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb,
-	struct nes_cm_core *cm_core)
+			   struct nes_cm_core *cm_core)
 {
-	enum nes_tcpip_pkt_type	pkt_type = NES_PKT_TYPE_UNKNOWN;
+	enum nes_tcpip_pkt_type pkt_type = NES_PKT_TYPE_UNKNOWN;
 	struct tcphdr *tcph = tcp_hdr(skb);
-	u32     fin_set = 0;
+	u32 fin_set = 0;
 	int ret = 0;
+
 	skb_pull(skb, ip_hdr(skb)->ihl << 2);
 
 	nes_debug(NES_DBG_CM, "process_packet: cm_node=%p state =%d syn=%d "
-		"ack=%d rst=%d fin=%d\n", cm_node, cm_node->state, tcph->syn,
-		tcph->ack, tcph->rst, tcph->fin);
+		  "ack=%d rst=%d fin=%d\n", cm_node, cm_node->state, tcph->syn,
+		  tcph->ack, tcph->rst, tcph->fin);
 
-	if (tcph->rst)
+	if (tcph->rst) {
 		pkt_type = NES_PKT_TYPE_RST;
-	else if (tcph->syn) {
+	} else if (tcph->syn) {
 		pkt_type = NES_PKT_TYPE_SYN;
 		if (tcph->ack)
 			pkt_type = NES_PKT_TYPE_SYNACK;
-	} else if (tcph->ack)
+	} else if (tcph->ack) {
 		pkt_type = NES_PKT_TYPE_ACK;
+	}
 	if (tcph->fin)
 		fin_set = 1;
 
@@ -1947,17 +2193,17 @@ static void process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb,
  * mini_cm_listen - create a listen node with params
  */
 static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core,
-	struct nes_vnic *nesvnic, struct nes_cm_info *cm_info)
+					      struct nes_vnic *nesvnic, struct nes_cm_info *cm_info)
 {
 	struct nes_cm_listener *listener;
 	unsigned long flags;
 
 	nes_debug(NES_DBG_CM, "Search for 0x%08x : 0x%04x\n",
-		cm_info->loc_addr, cm_info->loc_port);
+		  cm_info->loc_addr, cm_info->loc_port);
 
 	/* cannot have multiple matching listeners */
 	listener = find_listener(cm_core, htonl(cm_info->loc_addr),
-			htons(cm_info->loc_port), NES_CM_LISTENER_EITHER_STATE);
+				 htons(cm_info->loc_port), NES_CM_LISTENER_EITHER_STATE);
 	if (listener && listener->listener_state == NES_CM_LISTENER_ACTIVE_STATE) {
 		/* find automatically incs ref count ??? */
 		atomic_dec(&listener->ref_count);
@@ -2003,9 +2249,9 @@ static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core,
 	}
 
 	nes_debug(NES_DBG_CM, "Api - listen(): addr=0x%08X, port=0x%04x,"
-			" listener = %p, backlog = %d, cm_id = %p.\n",
-			cm_info->loc_addr, cm_info->loc_port,
-			listener, listener->backlog, listener->cm_id);
+		  " listener = %p, backlog = %d, cm_id = %p.\n",
+		  cm_info->loc_addr, cm_info->loc_port,
+		  listener, listener->backlog, listener->cm_id);
 
 	return listener;
 }
@@ -2015,26 +2261,20 @@ static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core,
  * mini_cm_connect - make a connection node with params
  */
 static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
-	struct nes_vnic *nesvnic, u16 private_data_len,
-	void *private_data, struct nes_cm_info *cm_info)
+					   struct nes_vnic *nesvnic, u16 private_data_len,
+					   void *private_data, struct nes_cm_info *cm_info)
 {
 	int ret = 0;
 	struct nes_cm_node *cm_node;
 	struct nes_cm_listener *loopbackremotelistener;
 	struct nes_cm_node *loopbackremotenode;
 	struct nes_cm_info loopback_cm_info;
-	u16 mpa_frame_size = sizeof(struct ietf_mpa_frame) + private_data_len;
-	struct ietf_mpa_frame *mpa_frame = NULL;
+	u8 *start_buff;
 
 	/* create a CM connection node */
 	cm_node = make_cm_node(cm_core, nesvnic, cm_info, NULL);
 	if (!cm_node)
 		return NULL;
-	mpa_frame = &cm_node->mpa_frame;
-	memcpy(mpa_frame->key, IEFT_MPA_KEY_REQ, IETF_MPA_KEY_SIZE);
-	mpa_frame->flags = IETF_MPA_FLAGS_CRC;
-	mpa_frame->rev =  IETF_MPA_VERSION;
-	mpa_frame->priv_data_len = htons(private_data_len);
 
 	/* set our node side to client (active) side */
 	cm_node->tcp_cntxt.client = 1;
@@ -2042,8 +2282,8 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
 
 	if (cm_info->loc_addr == cm_info->rem_addr) {
 		loopbackremotelistener = find_listener(cm_core,
-				ntohl(nesvnic->local_ipaddr), cm_node->rem_port,
-				NES_CM_LISTENER_ACTIVE_STATE);
+						       ntohl(nesvnic->local_ipaddr), cm_node->rem_port,
+						       NES_CM_LISTENER_ACTIVE_STATE);
 		if (loopbackremotelistener == NULL) {
 			create_event(cm_node, NES_CM_EVENT_ABORTED);
 		} else {
@@ -2052,7 +2292,7 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
 			loopback_cm_info.rem_port = cm_info->loc_port;
 			loopback_cm_info.cm_id = loopbackremotelistener->cm_id;
 			loopbackremotenode = make_cm_node(cm_core, nesvnic,
-				&loopback_cm_info, loopbackremotelistener);
+							  &loopback_cm_info, loopbackremotelistener);
 			if (!loopbackremotenode) {
 				rem_ref_cm_node(cm_node->cm_core, cm_node);
 				return NULL;
@@ -2063,7 +2303,7 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
 				NES_CM_DEFAULT_RCV_WND_SCALE;
 			cm_node->loopbackpartner = loopbackremotenode;
 			memcpy(loopbackremotenode->mpa_frame_buf, private_data,
-				private_data_len);
+			       private_data_len);
 			loopbackremotenode->mpa_frame_size = private_data_len;
 
 			/* we are done handling this state. */
@@ -2091,12 +2331,10 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
 		return cm_node;
 	}
 
-	/* set our node side to client (active) side */
-	cm_node->tcp_cntxt.client = 1;
-	/* init our MPA frame ptr */
-	memcpy(mpa_frame->priv_data, private_data, private_data_len);
+	start_buff = &cm_node->mpa_frame_buf[0] + sizeof(struct ietf_mpa_v2);
+	cm_node->mpa_frame_size = private_data_len;
 
-	cm_node->mpa_frame_size = mpa_frame_size;
+	memcpy(start_buff, private_data, private_data_len);
 
 	/* send a syn and goto syn sent state */
 	cm_node->state = NES_CM_STATE_SYN_SENT;
@@ -2105,18 +2343,19 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
 	if (ret) {
 		/* error in sending the syn free up the cm_node struct */
 		nes_debug(NES_DBG_CM, "Api - connect() FAILED: dest "
-			"addr=0x%08X, port=0x%04x, cm_node=%p, cm_id = %p.\n",
-			cm_node->rem_addr, cm_node->rem_port, cm_node,
-			cm_node->cm_id);
+			  "addr=0x%08X, port=0x%04x, cm_node=%p, cm_id = %p.\n",
+			  cm_node->rem_addr, cm_node->rem_port, cm_node,
+			  cm_node->cm_id);
 		rem_ref_cm_node(cm_node->cm_core, cm_node);
 		cm_node = NULL;
 	}
 
-	if (cm_node)
+	if (cm_node) {
 		nes_debug(NES_DBG_CM, "Api - connect(): dest addr=0x%08X,"
-			"port=0x%04x, cm_node=%p, cm_id = %p.\n",
-			cm_node->rem_addr, cm_node->rem_port, cm_node,
-			cm_node->cm_id);
+			  "port=0x%04x, cm_node=%p, cm_id = %p.\n",
+			  cm_node->rem_addr, cm_node->rem_port, cm_node,
+			  cm_node->cm_id);
+	}
 
 	return cm_node;
 }
@@ -2126,8 +2365,7 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
  * mini_cm_accept - accept a connection
  * This function is never called
  */
-static int mini_cm_accept(struct nes_cm_core *cm_core,
-	struct ietf_mpa_frame *mpa_frame, struct nes_cm_node *cm_node)
+static int mini_cm_accept(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node)
 {
 	return 0;
 }
@@ -2136,8 +2374,7 @@ static int mini_cm_accept(struct nes_cm_core *cm_core,
 /**
  * mini_cm_reject - reject and teardown a connection
  */
-static int mini_cm_reject(struct nes_cm_core *cm_core,
-	struct ietf_mpa_frame *mpa_frame, struct nes_cm_node *cm_node)
+static int mini_cm_reject(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node)
 {
 	int ret = 0;
 	int err = 0;
@@ -2147,7 +2384,7 @@ static int mini_cm_reject(struct nes_cm_core *cm_core,
 	struct nes_cm_node *loopback = cm_node->loopbackpartner;
 
 	nes_debug(NES_DBG_CM, "%s cm_node=%p type=%d state=%d\n",
-		__func__, cm_node, cm_node->tcp_cntxt.client, cm_node->state);
+		  __func__, cm_node, cm_node->tcp_cntxt.client, cm_node->state);
 
 	if (cm_node->tcp_cntxt.client)
 		return ret;
@@ -2168,8 +2405,9 @@ static int mini_cm_reject(struct nes_cm_core *cm_core,
 					err = send_reset(cm_node, NULL);
 					if (err)
 						WARN_ON(1);
-				} else
+				} else {
 					cm_id->add_ref(cm_id);
+				}
 			}
 		}
 	} else {
@@ -2244,7 +2482,7 @@ static int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_nod
 	case NES_CM_STATE_TSA:
 		if (cm_node->send_entry)
 			printk(KERN_ERR "ERROR Close got called from STATE_TSA "
-				"send_entry=%p\n", cm_node->send_entry);
+			       "send_entry=%p\n", cm_node->send_entry);
 		ret = rem_ref_cm_node(cm_core, cm_node);
 		break;
 	}
@@ -2257,7 +2495,7 @@ static int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_nod
  * node state machine
  */
 static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,
-	struct nes_vnic *nesvnic, struct sk_buff *skb)
+			    struct nes_vnic *nesvnic, struct sk_buff *skb)
 {
 	struct nes_cm_node *cm_node = NULL;
 	struct nes_cm_listener *listener = NULL;
@@ -2269,9 +2507,8 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,
 
 	if (!skb)
 		return 0;
-	if (skb->len < sizeof(struct iphdr) + sizeof(struct tcphdr)) {
+	if (skb->len < sizeof(struct iphdr) + sizeof(struct tcphdr))
 		return 0;
-	}
 
 	iph = (struct iphdr *)skb->data;
 	tcph = (struct tcphdr *)(skb->data + sizeof(struct iphdr));
@@ -2289,8 +2526,8 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,
 
 	do {
 		cm_node = find_node(cm_core,
-			nfo.rem_port, nfo.rem_addr,
-			nfo.loc_port, nfo.loc_addr);
+				    nfo.rem_port, nfo.rem_addr,
+				    nfo.loc_port, nfo.loc_addr);
 
 		if (!cm_node) {
 			/* Only type of packet accepted are for */
@@ -2300,8 +2537,8 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,
 				break;
 			}
 			listener = find_listener(cm_core, nfo.loc_addr,
-				nfo.loc_port,
-				NES_CM_LISTENER_ACTIVE_STATE);
+						 nfo.loc_port,
+						 NES_CM_LISTENER_ACTIVE_STATE);
 			if (!listener) {
 				nfo.cm_id = NULL;
 				nfo.conn_type = 0;
@@ -2312,10 +2549,10 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,
 			nfo.cm_id = listener->cm_id;
 			nfo.conn_type = listener->conn_type;
 			cm_node = make_cm_node(cm_core, nesvnic, &nfo,
-				listener);
+					       listener);
 			if (!cm_node) {
 				nes_debug(NES_DBG_CM, "Unable to allocate "
-					"node\n");
+					  "node\n");
 				cm_packets_dropped++;
 				atomic_dec(&listener->ref_count);
 				dev_kfree_skb_any(skb);
@@ -2331,9 +2568,13 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,
 			}
 			add_ref_cm_node(cm_node);
 		} else if (cm_node->state == NES_CM_STATE_TSA) {
-			rem_ref_cm_node(cm_core, cm_node);
-			atomic_inc(&cm_accel_dropped_pkts);
-			dev_kfree_skb_any(skb);
+			if (cm_node->nesqp->pau_mode)
+				nes_queue_mgt_skbs(skb, nesvnic, cm_node->nesqp);
+			else {
+				rem_ref_cm_node(cm_core, cm_node);
+				atomic_inc(&cm_accel_dropped_pkts);
+				dev_kfree_skb_any(skb);
+			}
 			break;
 		}
 		skb_reset_network_header(skb);
@@ -2363,7 +2604,7 @@ static struct nes_cm_core *nes_cm_alloc_core(void)
 	init_timer(&cm_core->tcp_timer);
 	cm_core->tcp_timer.function = nes_cm_timer_tick;
 
-	cm_core->mtu   = NES_CM_DEFAULT_MTU;
+	cm_core->mtu = NES_CM_DEFAULT_MTU;
 	cm_core->state = NES_CM_STATE_INITED;
 	cm_core->free_tx_pkt_max = NES_CM_DEFAULT_FREE_PKTS;
 
@@ -2401,9 +2642,8 @@ static int mini_cm_dealloc_core(struct nes_cm_core *cm_core)
 
 	barrier();
 
-	if (timer_pending(&cm_core->tcp_timer)) {
+	if (timer_pending(&cm_core->tcp_timer))
 		del_timer(&cm_core->tcp_timer);
-	}
 
 	destroy_workqueue(cm_core->event_wq);
 	destroy_workqueue(cm_core->disconn_wq);
@@ -2458,8 +2698,8 @@ static int nes_cm_init_tsa_conn(struct nes_qp *nesqp, struct nes_cm_node *cm_nod
 		return -EINVAL;
 
 	nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_IPV4 |
-			NES_QPCONTEXT_MISC_NO_NAGLE | NES_QPCONTEXT_MISC_DO_NOT_FRAG |
-			NES_QPCONTEXT_MISC_DROS);
+						  NES_QPCONTEXT_MISC_NO_NAGLE | NES_QPCONTEXT_MISC_DO_NOT_FRAG |
+						  NES_QPCONTEXT_MISC_DROS);
 
 	if (cm_node->tcp_cntxt.snd_wscale || cm_node->tcp_cntxt.rcv_wscale)
 		nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_WSCALE);
@@ -2469,15 +2709,15 @@ static int nes_cm_init_tsa_conn(struct nes_qp *nesqp, struct nes_cm_node *cm_nod
 	nesqp->nesqp_context->mss |= cpu_to_le32(((u32)cm_node->tcp_cntxt.mss) << 16);
 
 	nesqp->nesqp_context->tcp_state_flow_label |= cpu_to_le32(
-			(u32)NES_QPCONTEXT_TCPSTATE_EST << NES_QPCONTEXT_TCPFLOW_TCP_STATE_SHIFT);
+		(u32)NES_QPCONTEXT_TCPSTATE_EST << NES_QPCONTEXT_TCPFLOW_TCP_STATE_SHIFT);
 
 	nesqp->nesqp_context->pd_index_wscale |= cpu_to_le32(
-			(cm_node->tcp_cntxt.snd_wscale << NES_QPCONTEXT_PDWSCALE_SND_WSCALE_SHIFT) &
-			NES_QPCONTEXT_PDWSCALE_SND_WSCALE_MASK);
+		(cm_node->tcp_cntxt.snd_wscale << NES_QPCONTEXT_PDWSCALE_SND_WSCALE_SHIFT) &
+		NES_QPCONTEXT_PDWSCALE_SND_WSCALE_MASK);
 
 	nesqp->nesqp_context->pd_index_wscale |= cpu_to_le32(
-			(cm_node->tcp_cntxt.rcv_wscale << NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_SHIFT) &
-			NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_MASK);
+		(cm_node->tcp_cntxt.rcv_wscale << NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_SHIFT) &
+		NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_MASK);
 
 	nesqp->nesqp_context->keepalive = cpu_to_le32(0x80);
 	nesqp->nesqp_context->ts_recent = 0;
@@ -2486,24 +2726,24 @@ static int nes_cm_init_tsa_conn(struct nes_qp *nesqp, struct nes_cm_node *cm_nod
 	nesqp->nesqp_context->snd_wnd = cpu_to_le32(cm_node->tcp_cntxt.snd_wnd);
 	nesqp->nesqp_context->rcv_nxt = cpu_to_le32(cm_node->tcp_cntxt.rcv_nxt);
 	nesqp->nesqp_context->rcv_wnd = cpu_to_le32(cm_node->tcp_cntxt.rcv_wnd <<
-			cm_node->tcp_cntxt.rcv_wscale);
+						    cm_node->tcp_cntxt.rcv_wscale);
 	nesqp->nesqp_context->snd_max = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num);
 	nesqp->nesqp_context->snd_una = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num);
 	nesqp->nesqp_context->srtt = 0;
 	nesqp->nesqp_context->rttvar = cpu_to_le32(0x6);
 	nesqp->nesqp_context->ssthresh = cpu_to_le32(0x3FFFC000);
-	nesqp->nesqp_context->cwnd = cpu_to_le32(2*cm_node->tcp_cntxt.mss);
+	nesqp->nesqp_context->cwnd = cpu_to_le32(2 * cm_node->tcp_cntxt.mss);
 	nesqp->nesqp_context->snd_wl1 = cpu_to_le32(cm_node->tcp_cntxt.rcv_nxt);
 	nesqp->nesqp_context->snd_wl2 = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num);
 	nesqp->nesqp_context->max_snd_wnd = cpu_to_le32(cm_node->tcp_cntxt.max_snd_wnd);
 
 	nes_debug(NES_DBG_CM, "QP%u: rcv_nxt = 0x%08X, snd_nxt = 0x%08X,"
-			" Setting MSS to %u, PDWscale = 0x%08X, rcv_wnd = %u, context misc = 0x%08X.\n",
-			nesqp->hwqp.qp_id, le32_to_cpu(nesqp->nesqp_context->rcv_nxt),
-			le32_to_cpu(nesqp->nesqp_context->snd_nxt),
-			cm_node->tcp_cntxt.mss, le32_to_cpu(nesqp->nesqp_context->pd_index_wscale),
-			le32_to_cpu(nesqp->nesqp_context->rcv_wnd),
-			le32_to_cpu(nesqp->nesqp_context->misc));
+		  " Setting MSS to %u, PDWscale = 0x%08X, rcv_wnd = %u, context misc = 0x%08X.\n",
+		  nesqp->hwqp.qp_id, le32_to_cpu(nesqp->nesqp_context->rcv_nxt),
+		  le32_to_cpu(nesqp->nesqp_context->snd_nxt),
+		  cm_node->tcp_cntxt.mss, le32_to_cpu(nesqp->nesqp_context->pd_index_wscale),
+		  le32_to_cpu(nesqp->nesqp_context->rcv_wnd),
+		  le32_to_cpu(nesqp->nesqp_context->misc));
 	nes_debug(NES_DBG_CM, "  snd_wnd  = 0x%08X.\n", le32_to_cpu(nesqp->nesqp_context->snd_wnd));
 	nes_debug(NES_DBG_CM, "  snd_cwnd = 0x%08X.\n", le32_to_cpu(nesqp->nesqp_context->cwnd));
 	nes_debug(NES_DBG_CM, "  max_swnd = 0x%08X.\n", le32_to_cpu(nesqp->nesqp_context->max_snd_wnd));
@@ -2524,7 +2764,7 @@ int nes_cm_disconn(struct nes_qp *nesqp)
 
 	work = kzalloc(sizeof *work, GFP_ATOMIC);
 	if (!work)
-		return -ENOMEM; /* Timer will clean up */
+		return -ENOMEM;  /* Timer will clean up */
 
 	nes_add_ref(&nesqp->ibqp);
 	work->nesqp = nesqp;
@@ -2544,7 +2784,7 @@ static void nes_disconnect_worker(struct work_struct *work)
 
 	kfree(dwork);
 	nes_debug(NES_DBG_CM, "processing AEQE id 0x%04X for QP%u.\n",
-			nesqp->last_aeq, nesqp->hwqp.qp_id);
+		  nesqp->last_aeq, nesqp->hwqp.qp_id);
 	nes_cm_disconn_true(nesqp);
 	nes_rem_ref(&nesqp->ibqp);
 }
@@ -2580,7 +2820,7 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
 	/* make sure we havent already closed this connection */
 	if (!cm_id) {
 		nes_debug(NES_DBG_CM, "QP%u disconnect_worker cmid is NULL\n",
-				nesqp->hwqp.qp_id);
+			  nesqp->hwqp.qp_id);
 		spin_unlock_irqrestore(&nesqp->lock, flags);
 		return -1;
 	}
@@ -2589,7 +2829,7 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
 	nes_debug(NES_DBG_CM, "Disconnecting QP%u\n", nesqp->hwqp.qp_id);
 
 	original_hw_tcp_state = nesqp->hw_tcp_state;
-	original_ibqp_state   = nesqp->ibqp_state;
+	original_ibqp_state = nesqp->ibqp_state;
 	last_ae = nesqp->last_aeq;
 
 	if (nesqp->term_flags) {
@@ -2647,16 +2887,16 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
 			cm_event.private_data_len = 0;
 
 			nes_debug(NES_DBG_CM, "Generating a CM Disconnect Event"
-				" for  QP%u, SQ Head = %u, SQ Tail = %u. "
-				"cm_id = %p, refcount = %u.\n",
-				nesqp->hwqp.qp_id, nesqp->hwqp.sq_head,
-				nesqp->hwqp.sq_tail, cm_id,
-				atomic_read(&nesqp->refcount));
+				  " for  QP%u, SQ Head = %u, SQ Tail = %u. "
+				  "cm_id = %p, refcount = %u.\n",
+				  nesqp->hwqp.qp_id, nesqp->hwqp.sq_head,
+				  nesqp->hwqp.sq_tail, cm_id,
+				  atomic_read(&nesqp->refcount));
 
 			ret = cm_id->event_handler(cm_id, &cm_event);
 			if (ret)
 				nes_debug(NES_DBG_CM, "OFA CM event_handler "
-					"returned, ret=%d\n", ret);
+					  "returned, ret=%d\n", ret);
 		}
 
 		if (issue_close) {
@@ -2674,9 +2914,8 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
 			cm_event.private_data_len = 0;
 
 			ret = cm_id->event_handler(cm_id, &cm_event);
-			if (ret) {
+			if (ret)
 				nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret);
-			}
 
 			cm_id->rem_ref(cm_id);
 		}
@@ -2716,8 +2955,8 @@ static int nes_disconnect(struct nes_qp *nesqp, int abrupt)
 			if (nesqp->lsmm_mr)
 				nesibdev->ibdev.dereg_mr(nesqp->lsmm_mr);
 			pci_free_consistent(nesdev->pcidev,
-					nesqp->private_data_len+sizeof(struct ietf_mpa_frame),
-					nesqp->ietf_frame, nesqp->ietf_frame_pbase);
+					    nesqp->private_data_len + nesqp->ietf_frame_size,
+					    nesqp->ietf_frame, nesqp->ietf_frame_pbase);
 		}
 	}
 
@@ -2756,6 +2995,12 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 	struct ib_phys_buf ibphysbuf;
 	struct nes_pd *nespd;
 	u64 tagged_offset;
+	u8 mpa_frame_offset = 0;
+	struct ietf_mpa_v2 *mpa_v2_frame;
+	u8 start_addr = 0;
+	u8 *start_ptr = &start_addr;
+	u8 **start_buff = &start_ptr;
+	u16 buff_len = 0;
 
 	ibqp = nes_get_qp(cm_id->device, conn_param->qpn);
 	if (!ibqp)
@@ -2796,53 +3041,49 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 	nes_debug(NES_DBG_CM, "netdev refcnt = %u.\n",
 			netdev_refcnt_read(nesvnic->netdev));
 
+	nesqp->ietf_frame_size = sizeof(struct ietf_mpa_v2);
 	/* allocate the ietf frame and space for private data */
 	nesqp->ietf_frame = pci_alloc_consistent(nesdev->pcidev,
-		sizeof(struct ietf_mpa_frame) + conn_param->private_data_len,
-		&nesqp->ietf_frame_pbase);
+						 nesqp->ietf_frame_size + conn_param->private_data_len,
+						 &nesqp->ietf_frame_pbase);
 
 	if (!nesqp->ietf_frame) {
-		nes_debug(NES_DBG_CM, "Unable to allocate memory for private "
-			"data\n");
+		nes_debug(NES_DBG_CM, "Unable to allocate memory for private data\n");
 		return -ENOMEM;
 	}
+	mpa_v2_frame = (struct ietf_mpa_v2 *)nesqp->ietf_frame;
 
+	if (cm_node->mpa_frame_rev == IETF_MPA_V1)
+		mpa_frame_offset = 4;
 
-	/* setup the MPA frame */
-	nesqp->private_data_len = conn_param->private_data_len;
-	memcpy(nesqp->ietf_frame->key, IEFT_MPA_KEY_REP, IETF_MPA_KEY_SIZE);
-
-	memcpy(nesqp->ietf_frame->priv_data, conn_param->private_data,
-			conn_param->private_data_len);
+	memcpy(mpa_v2_frame->priv_data, conn_param->private_data,
+	       conn_param->private_data_len);
 
-	nesqp->ietf_frame->priv_data_len =
-		cpu_to_be16(conn_param->private_data_len);
-	nesqp->ietf_frame->rev = mpa_version;
-	nesqp->ietf_frame->flags = IETF_MPA_FLAGS_CRC;
+	cm_build_mpa_frame(cm_node, start_buff, &buff_len, nesqp->ietf_frame, MPA_KEY_REPLY);
+	nesqp->private_data_len = conn_param->private_data_len;
 
 	/* setup our first outgoing iWarp send WQE (the IETF frame response) */
 	wqe = &nesqp->hwqp.sq_vbase[0];
 
 	if (cm_id->remote_addr.sin_addr.s_addr !=
-			cm_id->local_addr.sin_addr.s_addr) {
+	    cm_id->local_addr.sin_addr.s_addr) {
 		u64temp = (unsigned long)nesqp;
 		nesibdev = nesvnic->nesibdev;
 		nespd = nesqp->nespd;
-		ibphysbuf.addr = nesqp->ietf_frame_pbase;
-		ibphysbuf.size = conn_param->private_data_len +
-					sizeof(struct ietf_mpa_frame);
-		tagged_offset = (u64)(unsigned long)nesqp->ietf_frame;
+		ibphysbuf.addr = nesqp->ietf_frame_pbase + mpa_frame_offset;
+		ibphysbuf.size = buff_len;
+		tagged_offset = (u64)(unsigned long)*start_buff;
 		ibmr = nesibdev->ibdev.reg_phys_mr((struct ib_pd *)nespd,
-						&ibphysbuf, 1,
-						IB_ACCESS_LOCAL_WRITE,
-						&tagged_offset);
+						   &ibphysbuf, 1,
+						   IB_ACCESS_LOCAL_WRITE,
+						   &tagged_offset);
 		if (!ibmr) {
 			nes_debug(NES_DBG_CM, "Unable to register memory region"
-					"for lSMM for cm_node = %p \n",
-					cm_node);
+				  "for lSMM for cm_node = %p \n",
+				  cm_node);
 			pci_free_consistent(nesdev->pcidev,
-				nesqp->private_data_len+sizeof(struct ietf_mpa_frame),
-				nesqp->ietf_frame, nesqp->ietf_frame_pbase);
+					    nesqp->private_data_len + nesqp->ietf_frame_size,
+					    nesqp->ietf_frame, nesqp->ietf_frame_pbase);
 			return -ENOMEM;
 		}
 
@@ -2850,22 +3091,20 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 		ibmr->device = nespd->ibpd.device;
 		nesqp->lsmm_mr = ibmr;
 
-		u64temp |= NES_SW_CONTEXT_ALIGN>>1;
+		u64temp |= NES_SW_CONTEXT_ALIGN >> 1;
 		set_wqe_64bit_value(wqe->wqe_words,
-			NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX,
-			u64temp);
+				    NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX,
+				    u64temp);
 		wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] =
 			cpu_to_le32(NES_IWARP_SQ_WQE_STREAMING |
-			NES_IWARP_SQ_WQE_WRPDU);
+				    NES_IWARP_SQ_WQE_WRPDU);
 		wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] =
-			cpu_to_le32(conn_param->private_data_len +
-			sizeof(struct ietf_mpa_frame));
+			cpu_to_le32(buff_len);
 		set_wqe_64bit_value(wqe->wqe_words,
-					NES_IWARP_SQ_WQE_FRAG0_LOW_IDX,
-					(u64)(unsigned long)nesqp->ietf_frame);
+				    NES_IWARP_SQ_WQE_FRAG0_LOW_IDX,
+				    (u64)(unsigned long)(*start_buff));
 		wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] =
-			cpu_to_le32(conn_param->private_data_len +
-			sizeof(struct ietf_mpa_frame));
+			cpu_to_le32(buff_len);
 		wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = ibmr->lkey;
 		if (nesqp->sq_kmapped) {
 			nesqp->sq_kmapped = 0;
@@ -2874,7 +3113,7 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 
 		nesqp->nesqp_context->ird_ord_sizes |=
 			cpu_to_le32(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT |
-			NES_QPCONTEXT_ORDIRD_WRPDU);
+				    NES_QPCONTEXT_ORDIRD_WRPDU);
 	} else {
 		nesqp->nesqp_context->ird_ord_sizes |=
 			cpu_to_le32(NES_QPCONTEXT_ORDIRD_WRPDU);
@@ -2888,11 +3127,11 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 
 	/*  nesqp->cm_node = (void *)cm_id->provider_data; */
 	cm_id->provider_data = nesqp;
-	nesqp->active_conn   = 0;
+	nesqp->active_conn = 0;
 
 	if (cm_node->state == NES_CM_STATE_TSA)
 		nes_debug(NES_DBG_CM, "Already state = TSA for cm_node=%p\n",
-			cm_node);
+			  cm_node);
 
 	nes_cm_init_tsa_conn(nesqp, cm_node);
 
@@ -2909,13 +3148,13 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 			cpu_to_le32(ntohl(cm_id->remote_addr.sin_addr.s_addr));
 
 	nesqp->nesqp_context->misc2 |= cpu_to_le32(
-			(u32)PCI_FUNC(nesdev->pcidev->devfn) <<
-			NES_QPCONTEXT_MISC2_SRC_IP_SHIFT);
+		(u32)PCI_FUNC(nesdev->pcidev->devfn) <<
+		NES_QPCONTEXT_MISC2_SRC_IP_SHIFT);
 
 	nesqp->nesqp_context->arp_index_vlan |=
 		cpu_to_le32(nes_arp_table(nesdev,
-			le32_to_cpu(nesqp->nesqp_context->ip0), NULL,
-			NES_ARP_RESOLVE) << 16);
+					  le32_to_cpu(nesqp->nesqp_context->ip0), NULL,
+					  NES_ARP_RESOLVE) << 16);
 
 	nesqp->nesqp_context->ts_val_delta = cpu_to_le32(
 		jiffies - nes_read_indexed(nesdev, NES_IDX_TCP_NOW));
@@ -2941,7 +3180,7 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 	crc_value = get_crc_value(&nes_quad);
 	nesqp->hte_index = cpu_to_be32(crc_value ^ 0xffffffff);
 	nes_debug(NES_DBG_CM, "HTE Index = 0x%08X, CRC = 0x%08X\n",
-		nesqp->hte_index, nesqp->hte_index & adapter->hte_index_mask);
+		  nesqp->hte_index, nesqp->hte_index & adapter->hte_index_mask);
 
 	nesqp->hte_index &= adapter->hte_index_mask;
 	nesqp->nesqp_context->hte_index = cpu_to_le32(nesqp->hte_index);
@@ -2949,17 +3188,15 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 	cm_node->cm_core->api->accelerated(cm_node->cm_core, cm_node);
 
 	nes_debug(NES_DBG_CM, "QP%u, Destination IP = 0x%08X:0x%04X, local = "
-			"0x%08X:0x%04X, rcv_nxt=0x%08X, snd_nxt=0x%08X, mpa + "
-			"private data length=%zu.\n", nesqp->hwqp.qp_id,
-			ntohl(cm_id->remote_addr.sin_addr.s_addr),
-			ntohs(cm_id->remote_addr.sin_port),
-			ntohl(cm_id->local_addr.sin_addr.s_addr),
-			ntohs(cm_id->local_addr.sin_port),
-			le32_to_cpu(nesqp->nesqp_context->rcv_nxt),
-			le32_to_cpu(nesqp->nesqp_context->snd_nxt),
-			conn_param->private_data_len +
-			sizeof(struct ietf_mpa_frame));
-
+		  "0x%08X:0x%04X, rcv_nxt=0x%08X, snd_nxt=0x%08X, mpa + "
+		  "private data length=%u.\n", nesqp->hwqp.qp_id,
+		  ntohl(cm_id->remote_addr.sin_addr.s_addr),
+		  ntohs(cm_id->remote_addr.sin_port),
+		  ntohl(cm_id->local_addr.sin_addr.s_addr),
+		  ntohs(cm_id->local_addr.sin_port),
+		  le32_to_cpu(nesqp->nesqp_context->rcv_nxt),
+		  le32_to_cpu(nesqp->nesqp_context->snd_nxt),
+		  buff_len);
 
 	/* notify OF layer that accept event was successful */
 	cm_id->add_ref(cm_id);
@@ -2980,12 +3217,12 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 			nesqp->private_data_len;
 		/* copy entire MPA frame to our cm_node's frame */
 		memcpy(cm_node->loopbackpartner->mpa_frame_buf,
-			nesqp->ietf_frame->priv_data, nesqp->private_data_len);
+		       conn_param->private_data, conn_param->private_data_len);
 		create_event(cm_node->loopbackpartner, NES_CM_EVENT_CONNECTED);
 	}
 	if (ret)
 		printk(KERN_ERR "%s[%u] OFA CM event_handler returned, "
-			"ret=%d\n", __func__, __LINE__, ret);
+		       "ret=%d\n", __func__, __LINE__, ret);
 
 	return 0;
 }
@@ -2998,34 +3235,28 @@ int nes_reject(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
 {
 	struct nes_cm_node *cm_node;
 	struct nes_cm_node *loopback;
-
 	struct nes_cm_core *cm_core;
+	u8 *start_buff;
 
 	atomic_inc(&cm_rejects);
-	cm_node = (struct nes_cm_node *) cm_id->provider_data;
+	cm_node = (struct nes_cm_node *)cm_id->provider_data;
 	loopback = cm_node->loopbackpartner;
 	cm_core = cm_node->cm_core;
 	cm_node->cm_id = cm_id;
-	cm_node->mpa_frame_size = sizeof(struct ietf_mpa_frame) + pdata_len;
 
-	if (cm_node->mpa_frame_size > MAX_CM_BUFFER)
+	if (pdata_len + sizeof(struct ietf_mpa_v2) > MAX_CM_BUFFER)
 		return -EINVAL;
 
-	memcpy(&cm_node->mpa_frame.key[0], IEFT_MPA_KEY_REP, IETF_MPA_KEY_SIZE);
 	if (loopback) {
 		memcpy(&loopback->mpa_frame.priv_data, pdata, pdata_len);
 		loopback->mpa_frame.priv_data_len = pdata_len;
-		loopback->mpa_frame_size = sizeof(struct ietf_mpa_frame) +
-				pdata_len;
+		loopback->mpa_frame_size = pdata_len;
 	} else {
-		memcpy(&cm_node->mpa_frame.priv_data, pdata, pdata_len);
-		cm_node->mpa_frame.priv_data_len = cpu_to_be16(pdata_len);
+		start_buff = &cm_node->mpa_frame_buf[0] + sizeof(struct ietf_mpa_v2);
+		cm_node->mpa_frame_size = pdata_len;
+		memcpy(start_buff, pdata, pdata_len);
 	}
-
-	cm_node->mpa_frame.rev = mpa_version;
-	cm_node->mpa_frame.flags = IETF_MPA_FLAGS_CRC | IETF_MPA_FLAGS_REJECT;
-
-	return cm_core->api->reject(cm_core, &cm_node->mpa_frame, cm_node);
+	return cm_core->api->reject(cm_core, cm_node);
 }
 
 
@@ -3052,7 +3283,7 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 	nesvnic = to_nesvnic(nesqp->ibqp.device);
 	if (!nesvnic)
 		return -EINVAL;
-	nesdev  = nesvnic->nesdev;
+	nesdev = nesvnic->nesdev;
 	if (!nesdev)
 		return -EINVAL;
 
@@ -3060,12 +3291,12 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 		return -EINVAL;
 
 	nes_debug(NES_DBG_CM, "QP%u, current IP = 0x%08X, Destination IP = "
-		"0x%08X:0x%04X, local = 0x%08X:0x%04X.\n", nesqp->hwqp.qp_id,
-		ntohl(nesvnic->local_ipaddr),
-		ntohl(cm_id->remote_addr.sin_addr.s_addr),
-		ntohs(cm_id->remote_addr.sin_port),
-		ntohl(cm_id->local_addr.sin_addr.s_addr),
-		ntohs(cm_id->local_addr.sin_port));
+		  "0x%08X:0x%04X, local = 0x%08X:0x%04X.\n", nesqp->hwqp.qp_id,
+		  ntohl(nesvnic->local_ipaddr),
+		  ntohl(cm_id->remote_addr.sin_addr.s_addr),
+		  ntohs(cm_id->remote_addr.sin_port),
+		  ntohl(cm_id->local_addr.sin_addr.s_addr),
+		  ntohs(cm_id->local_addr.sin_port));
 
 	atomic_inc(&cm_connects);
 	nesqp->active_conn = 1;
@@ -3079,12 +3310,12 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 	nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32((u32)conn_param->ord);
 	nes_debug(NES_DBG_CM, "requested ord = 0x%08X.\n", (u32)conn_param->ord);
 	nes_debug(NES_DBG_CM, "mpa private data len =%u\n",
-		conn_param->private_data_len);
+		  conn_param->private_data_len);
 
 	if (cm_id->local_addr.sin_addr.s_addr !=
-		cm_id->remote_addr.sin_addr.s_addr) {
+	    cm_id->remote_addr.sin_addr.s_addr) {
 		nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port),
-			PCI_FUNC(nesdev->pcidev->devfn), NES_MANAGE_APBVT_ADD);
+				 PCI_FUNC(nesdev->pcidev->devfn), NES_MANAGE_APBVT_ADD);
 		apbvt_set = 1;
 	}
 
@@ -3100,13 +3331,13 @@ int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 
 	/* create a connect CM node connection */
 	cm_node = g_cm_core->api->connect(g_cm_core, nesvnic,
-		conn_param->private_data_len, (void *)conn_param->private_data,
-		&cm_info);
+					  conn_param->private_data_len, (void *)conn_param->private_data,
+					  &cm_info);
 	if (!cm_node) {
 		if (apbvt_set)
 			nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port),
-				PCI_FUNC(nesdev->pcidev->devfn),
-				NES_MANAGE_APBVT_DEL);
+					 PCI_FUNC(nesdev->pcidev->devfn),
+					 NES_MANAGE_APBVT_DEL);
 
 		cm_id->rem_ref(cm_id);
 		return -ENOMEM;
@@ -3156,7 +3387,7 @@ int nes_create_listen(struct iw_cm_id *cm_id, int backlog)
 	cm_node = g_cm_core->api->listen(g_cm_core, nesvnic, &cm_info);
 	if (!cm_node) {
 		printk(KERN_ERR "%s[%u] Error returned from listen API call\n",
-				__func__, __LINE__);
+		       __func__, __LINE__);
 		return -ENOMEM;
 	}
 
@@ -3164,12 +3395,12 @@ int nes_create_listen(struct iw_cm_id *cm_id, int backlog)
 
 	if (!cm_node->reused_node) {
 		err = nes_manage_apbvt(nesvnic,
-			ntohs(cm_id->local_addr.sin_port),
-			PCI_FUNC(nesvnic->nesdev->pcidev->devfn),
-			NES_MANAGE_APBVT_ADD);
+				       ntohs(cm_id->local_addr.sin_port),
+				       PCI_FUNC(nesvnic->nesdev->pcidev->devfn),
+				       NES_MANAGE_APBVT_ADD);
 		if (err) {
 			printk(KERN_ERR "nes_manage_apbvt call returned %d.\n",
-				err);
+			       err);
 			g_cm_core->api->stop_listener(g_cm_core, (void *)cm_node);
 			return err;
 		}
@@ -3206,13 +3437,13 @@ int nes_destroy_listen(struct iw_cm_id *cm_id)
 int nes_cm_recv(struct sk_buff *skb, struct net_device *netdevice)
 {
 	int rc = 0;
+
 	cm_packets_received++;
-	if ((g_cm_core) && (g_cm_core->api)) {
+	if ((g_cm_core) && (g_cm_core->api))
 		rc = g_cm_core->api->recv_pkt(g_cm_core, netdev_priv(netdevice), skb);
-	} else {
+	else
 		nes_debug(NES_DBG_CM, "Unable to process packet for CM,"
-				" cm is not setup properly.\n");
-	}
+			  " cm is not setup properly.\n");
 
 	return rc;
 }
@@ -3227,11 +3458,10 @@ int nes_cm_start(void)
 	nes_debug(NES_DBG_CM, "\n");
 	/* create the primary CM core, pass this handle to subsequent core inits */
 	g_cm_core = nes_cm_alloc_core();
-	if (g_cm_core) {
+	if (g_cm_core)
 		return 0;
-	} else {
+	else
 		return -ENOMEM;
-	}
 }
 
 
@@ -3252,7 +3482,6 @@ int nes_cm_stop(void)
  */
 static void cm_event_connected(struct nes_cm_event *event)
 {
-	u64 u64temp;
 	struct nes_qp *nesqp;
 	struct nes_vnic *nesvnic;
 	struct nes_device *nesdev;
@@ -3261,7 +3490,6 @@ static void cm_event_connected(struct nes_cm_event *event)
 	struct ib_qp_attr attr;
 	struct iw_cm_id *cm_id;
 	struct iw_cm_event cm_event;
-	struct nes_hw_qp_wqe *wqe;
 	struct nes_v4_quad nes_quad;
 	u32 crc_value;
 	int ret;
@@ -3275,17 +3503,16 @@ static void cm_event_connected(struct nes_cm_event *event)
 	nesdev = nesvnic->nesdev;
 	nesadapter = nesdev->nesadapter;
 
-	if (nesqp->destroyed) {
+	if (nesqp->destroyed)
 		return;
-	}
 	atomic_inc(&cm_connecteds);
 	nes_debug(NES_DBG_CM, "QP%u attempting to connect to  0x%08X:0x%04X on"
-			" local port 0x%04X. jiffies = %lu.\n",
-			nesqp->hwqp.qp_id,
-			ntohl(cm_id->remote_addr.sin_addr.s_addr),
-			ntohs(cm_id->remote_addr.sin_port),
-			ntohs(cm_id->local_addr.sin_port),
-			jiffies);
+		  " local port 0x%04X. jiffies = %lu.\n",
+		  nesqp->hwqp.qp_id,
+		  ntohl(cm_id->remote_addr.sin_addr.s_addr),
+		  ntohs(cm_id->remote_addr.sin_port),
+		  ntohs(cm_id->local_addr.sin_port),
+		  jiffies);
 
 	nes_cm_init_tsa_conn(nesqp, cm_node);
 
@@ -3316,40 +3543,12 @@ static void cm_event_connected(struct nes_cm_event *event)
 			NES_QPCONTEXT_ORDIRD_IWARP_MODE_SHIFT);
 
 	/* Adjust tail for not having a LSMM */
-	nesqp->hwqp.sq_tail = 1;
+	/*nesqp->hwqp.sq_tail = 1;*/
 
-#if defined(NES_SEND_FIRST_WRITE)
-	if (cm_node->send_write0) {
-		nes_debug(NES_DBG_CM, "Sending first write.\n");
-		wqe = &nesqp->hwqp.sq_vbase[0];
-		u64temp = (unsigned long)nesqp;
-		u64temp |= NES_SW_CONTEXT_ALIGN>>1;
-		set_wqe_64bit_value(wqe->wqe_words,
-				NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX, u64temp);
-		wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] =
-			cpu_to_le32(NES_IWARP_SQ_OP_RDMAW);
-		wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = 0;
-		wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] = 0;
-		wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] = 0;
-		wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = 0;
-		wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0;
+	build_rdma0_msg(cm_node, &nesqp);
 
-		if (nesqp->sq_kmapped) {
-			nesqp->sq_kmapped = 0;
-			kunmap(nesqp->page);
-		}
-
-		/* use the reserved spot on the WQ for the extra first WQE */
-		nesqp->nesqp_context->ird_ord_sizes &=
-			cpu_to_le32(~(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT |
-						NES_QPCONTEXT_ORDIRD_WRPDU |
-						NES_QPCONTEXT_ORDIRD_ALSMM));
-		nesqp->skip_lsmm = 1;
-		nesqp->hwqp.sq_tail = 0;
-		nes_write32(nesdev->regs + NES_WQE_ALLOC,
-				(1 << 24) | 0x00800000 | nesqp->hwqp.qp_id);
-	}
-#endif
+	nes_write32(nesdev->regs + NES_WQE_ALLOC,
+		    (1 << 24) | 0x00800000 | nesqp->hwqp.qp_id);
 
 	memset(&nes_quad, 0, sizeof(nes_quad));
 
@@ -3366,13 +3565,13 @@ static void cm_event_connected(struct nes_cm_event *event)
 	crc_value = get_crc_value(&nes_quad);
 	nesqp->hte_index = cpu_to_be32(crc_value ^ 0xffffffff);
 	nes_debug(NES_DBG_CM, "HTE Index = 0x%08X, After CRC = 0x%08X\n",
-			nesqp->hte_index, nesqp->hte_index & nesadapter->hte_index_mask);
+		  nesqp->hte_index, nesqp->hte_index & nesadapter->hte_index_mask);
 
 	nesqp->hte_index &= nesadapter->hte_index_mask;
 	nesqp->nesqp_context->hte_index = cpu_to_le32(nesqp->hte_index);
 
 	nesqp->ietf_frame = &cm_node->mpa_frame;
-	nesqp->private_data_len = (u8) cm_node->mpa_frame_size;
+	nesqp->private_data_len = (u8)cm_node->mpa_frame_size;
 	cm_node->cm_core->api->accelerated(cm_node->cm_core, cm_node);
 
 	/* notify OF layer we successfully created the requested connection */
@@ -3384,7 +3583,9 @@ static void cm_event_connected(struct nes_cm_event *event)
 	cm_event.remote_addr = cm_id->remote_addr;
 
 	cm_event.private_data = (void *)event->cm_node->mpa_frame_buf;
-	cm_event.private_data_len = (u8) event->cm_node->mpa_frame_size;
+	cm_event.private_data_len = (u8)event->cm_node->mpa_frame_size;
+	cm_event.ird = cm_node->ird_size;
+	cm_event.ord = cm_node->ord_size;
 
 	cm_event.local_addr.sin_addr.s_addr = event->cm_info.rem_addr;
 	ret = cm_id->event_handler(cm_id, &cm_event);
@@ -3392,12 +3593,12 @@ static void cm_event_connected(struct nes_cm_event *event)
 
 	if (ret)
 		printk(KERN_ERR "%s[%u] OFA CM event_handler returned, "
-			"ret=%d\n", __func__, __LINE__, ret);
+		       "ret=%d\n", __func__, __LINE__, ret);
 	attr.qp_state = IB_QPS_RTS;
 	nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL);
 
 	nes_debug(NES_DBG_CM, "Exiting connect thread for QP%u. jiffies = "
-		"%lu\n", nesqp->hwqp.qp_id, jiffies);
+		  "%lu\n", nesqp->hwqp.qp_id, jiffies);
 
 	return;
 }
@@ -3418,16 +3619,14 @@ static void cm_event_connect_error(struct nes_cm_event *event)
 		return;
 
 	cm_id = event->cm_node->cm_id;
-	if (!cm_id) {
+	if (!cm_id)
 		return;
-	}
 
 	nes_debug(NES_DBG_CM, "cm_node=%p, cm_id=%p\n", event->cm_node, cm_id);
 	nesqp = cm_id->provider_data;
 
-	if (!nesqp) {
+	if (!nesqp)
 		return;
-	}
 
 	/* notify OF layer about this connection error event */
 	/* cm_id->rem_ref(cm_id); */
@@ -3442,14 +3641,14 @@ static void cm_event_connect_error(struct nes_cm_event *event)
 	cm_event.private_data_len = 0;
 
 	nes_debug(NES_DBG_CM, "call CM_EVENT REJECTED, local_addr=%08x, "
-		"remove_addr=%08x\n", cm_event.local_addr.sin_addr.s_addr,
-		cm_event.remote_addr.sin_addr.s_addr);
+		  "remove_addr=%08x\n", cm_event.local_addr.sin_addr.s_addr,
+		  cm_event.remote_addr.sin_addr.s_addr);
 
 	ret = cm_id->event_handler(cm_id, &cm_event);
 	nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret);
 	if (ret)
 		printk(KERN_ERR "%s[%u] OFA CM event_handler returned, "
-			"ret=%d\n", __func__, __LINE__, ret);
+		       "ret=%d\n", __func__, __LINE__, ret);
 	cm_id->rem_ref(cm_id);
 
 	rem_ref_cm_node(event->cm_node->cm_core, event->cm_node);
@@ -3519,7 +3718,7 @@ static void cm_event_reset(struct nes_cm_event *event)
  */
 static void cm_event_mpa_req(struct nes_cm_event *event)
 {
-	struct iw_cm_id   *cm_id;
+	struct iw_cm_id *cm_id;
 	struct iw_cm_event cm_event;
 	int ret;
 	struct nes_cm_node *cm_node;
@@ -3531,7 +3730,7 @@ static void cm_event_mpa_req(struct nes_cm_event *event)
 
 	atomic_inc(&cm_connect_reqs);
 	nes_debug(NES_DBG_CM, "cm_node = %p - cm_id = %p, jiffies = %lu\n",
-			cm_node, cm_id, jiffies);
+		  cm_node, cm_id, jiffies);
 
 	cm_event.event = IW_CM_EVENT_CONNECT_REQUEST;
 	cm_event.status = 0;
@@ -3545,19 +3744,21 @@ static void cm_event_mpa_req(struct nes_cm_event *event)
 	cm_event.remote_addr.sin_port = htons(event->cm_info.rem_port);
 	cm_event.remote_addr.sin_addr.s_addr = htonl(event->cm_info.rem_addr);
 	cm_event.private_data = cm_node->mpa_frame_buf;
-	cm_event.private_data_len  = (u8) cm_node->mpa_frame_size;
+	cm_event.private_data_len = (u8)cm_node->mpa_frame_size;
+	cm_event.ird = cm_node->ird_size;
+	cm_event.ord = cm_node->ord_size;
 
 	ret = cm_id->event_handler(cm_id, &cm_event);
 	if (ret)
 		printk(KERN_ERR "%s[%u] OFA CM event_handler returned, ret=%d\n",
-				__func__, __LINE__, ret);
+		       __func__, __LINE__, ret);
 	return;
 }
 
 
 static void cm_event_mpa_reject(struct nes_cm_event *event)
 {
-	struct iw_cm_id   *cm_id;
+	struct iw_cm_id *cm_id;
 	struct iw_cm_event cm_event;
 	struct nes_cm_node *cm_node;
 	int ret;
@@ -3569,7 +3770,7 @@ static void cm_event_mpa_reject(struct nes_cm_event *event)
 
 	atomic_inc(&cm_connect_reqs);
 	nes_debug(NES_DBG_CM, "cm_node = %p - cm_id = %p, jiffies = %lu\n",
-			cm_node, cm_id, jiffies);
+		  cm_node, cm_id, jiffies);
 
 	cm_event.event = IW_CM_EVENT_CONNECT_REPLY;
 	cm_event.status = -ECONNREFUSED;
@@ -3584,17 +3785,17 @@ static void cm_event_mpa_reject(struct nes_cm_event *event)
 	cm_event.remote_addr.sin_addr.s_addr = htonl(event->cm_info.rem_addr);
 
 	cm_event.private_data = cm_node->mpa_frame_buf;
-	cm_event.private_data_len = (u8) cm_node->mpa_frame_size;
+	cm_event.private_data_len = (u8)cm_node->mpa_frame_size;
 
 	nes_debug(NES_DBG_CM, "call CM_EVENT_MPA_REJECTED, local_addr=%08x, "
-			"remove_addr=%08x\n",
-			cm_event.local_addr.sin_addr.s_addr,
-			cm_event.remote_addr.sin_addr.s_addr);
+		  "remove_addr=%08x\n",
+		  cm_event.local_addr.sin_addr.s_addr,
+		  cm_event.remote_addr.sin_addr.s_addr);
 
 	ret = cm_id->event_handler(cm_id, &cm_event);
 	if (ret)
 		printk(KERN_ERR "%s[%u] OFA CM event_handler returned, ret=%d\n",
-				__func__, __LINE__, ret);
+		       __func__, __LINE__, ret);
 
 	return;
 }
@@ -3613,7 +3814,7 @@ static int nes_cm_post_event(struct nes_cm_event *event)
 	event->cm_info.cm_id->add_ref(event->cm_info.cm_id);
 	INIT_WORK(&event->event_work, nes_cm_event_handler);
 	nes_debug(NES_DBG_CM, "cm_node=%p queue_work, event=%p\n",
-		event->cm_node, event);
+		  event->cm_node, event);
 
 	queue_work(event->cm_node->cm_core->event_wq, &event->event_work);
 
@@ -3630,7 +3831,7 @@ static int nes_cm_post_event(struct nes_cm_event *event)
 static void nes_cm_event_handler(struct work_struct *work)
 {
 	struct nes_cm_event *event = container_of(work, struct nes_cm_event,
-			event_work);
+						  event_work);
 	struct nes_cm_core *cm_core;
 
 	if ((!event) || (!event->cm_node) || (!event->cm_node->cm_core))
@@ -3638,29 +3839,29 @@ static void nes_cm_event_handler(struct work_struct *work)
 
 	cm_core = event->cm_node->cm_core;
 	nes_debug(NES_DBG_CM, "event=%p, event->type=%u, events posted=%u\n",
-		event, event->type, atomic_read(&cm_core->events_posted));
+		  event, event->type, atomic_read(&cm_core->events_posted));
 
 	switch (event->type) {
 	case NES_CM_EVENT_MPA_REQ:
 		cm_event_mpa_req(event);
 		nes_debug(NES_DBG_CM, "cm_node=%p CM Event: MPA REQUEST\n",
-			event->cm_node);
+			  event->cm_node);
 		break;
 	case NES_CM_EVENT_RESET:
 		nes_debug(NES_DBG_CM, "cm_node = %p CM Event: RESET\n",
-			event->cm_node);
+			  event->cm_node);
 		cm_event_reset(event);
 		break;
 	case NES_CM_EVENT_CONNECTED:
 		if ((!event->cm_node->cm_id) ||
-			(event->cm_node->state != NES_CM_STATE_TSA))
+		    (event->cm_node->state != NES_CM_STATE_TSA))
 			break;
 		cm_event_connected(event);
 		nes_debug(NES_DBG_CM, "CM Event: CONNECTED\n");
 		break;
 	case NES_CM_EVENT_MPA_REJECT:
 		if ((!event->cm_node->cm_id) ||
-				(event->cm_node->state == NES_CM_STATE_TSA))
+		    (event->cm_node->state == NES_CM_STATE_TSA))
 			break;
 		cm_event_mpa_reject(event);
 		nes_debug(NES_DBG_CM, "CM Event: REJECT\n");
@@ -3668,7 +3869,7 @@ static void nes_cm_event_handler(struct work_struct *work)
 
 	case NES_CM_EVENT_ABORTED:
 		if ((!event->cm_node->cm_id) ||
-			(event->cm_node->state == NES_CM_STATE_TSA))
+		    (event->cm_node->state == NES_CM_STATE_TSA))
 			break;
 		cm_event_connect_error(event);
 		nes_debug(NES_DBG_CM, "CM Event: ABORTED\n");
diff --git a/drivers/infiniband/hw/nes/nes_cm.h b/drivers/infiniband/hw/nes/nes_cm.h
index d9825fd..bdfa1fb 100644
--- a/drivers/infiniband/hw/nes/nes_cm.h
+++ b/drivers/infiniband/hw/nes/nes_cm.h
@@ -48,7 +48,16 @@
 #define IETF_MPA_KEY_SIZE 16
 #define IETF_MPA_VERSION  1
 #define IETF_MAX_PRIV_DATA_LEN 512
-#define IETF_MPA_FRAME_SIZE     20
+#define IETF_MPA_FRAME_SIZE    20
+#define IETF_RTR_MSG_SIZE      4
+#define IETF_MPA_V2_FLAG       0x10
+
+/* IETF RTR MSG Fields               */
+#define IETF_PEER_TO_PEER       0x8000
+#define IETF_FLPDU_ZERO_LEN     0x4000
+#define IETF_RDMA0_WRITE        0x8000
+#define IETF_RDMA0_READ         0x4000
+#define IETF_NO_IRD_ORD         0x3FFF
 
 enum ietf_mpa_flags {
 	IETF_MPA_FLAGS_MARKERS = 0x80,	/* receive Markers */
@@ -56,7 +65,7 @@ enum ietf_mpa_flags {
 	IETF_MPA_FLAGS_REJECT  = 0x20,	/* Reject */
 };
 
-struct ietf_mpa_frame {
+struct ietf_mpa_v1 {
 	u8 key[IETF_MPA_KEY_SIZE];
 	u8 flags;
 	u8 rev;
@@ -66,6 +75,20 @@ struct ietf_mpa_frame {
 
 #define ietf_mpa_req_resp_frame ietf_mpa_frame
 
+struct ietf_rtr_msg {
+	__be16 ctrl_ird;
+	__be16 ctrl_ord;
+};
+
+struct ietf_mpa_v2 {
+	u8 key[IETF_MPA_KEY_SIZE];
+	u8 flags;
+	u8 rev;
+	 __be16 priv_data_len;
+	struct ietf_rtr_msg rtr_msg;
+	u8 priv_data[0];
+};
+
 struct nes_v4_quad {
 	u32 rsvd0;
 	__le32 DstIpAdrIndex;	/* Only most significant 5 bits are valid */
@@ -171,8 +194,7 @@ struct nes_timer_entry {
 
 #define NES_CM_DEF_SEQ2      0x18ed5740
 #define NES_CM_DEF_LOCAL_ID2 0xb807
-#define	MAX_CM_BUFFER	(IETF_MPA_FRAME_SIZE + IETF_MAX_PRIV_DATA_LEN)
-
+#define	MAX_CM_BUFFER	(IETF_MPA_FRAME_SIZE + IETF_RTR_MSG_SIZE + IETF_MAX_PRIV_DATA_LEN)
 
 typedef u32 nes_addr_t;
 
@@ -204,6 +226,21 @@ enum nes_cm_node_state {
 	NES_CM_STATE_CLOSED
 };
 
+enum mpa_frame_version {
+	IETF_MPA_V1 = 1,
+	IETF_MPA_V2 = 2
+};
+
+enum mpa_frame_key {
+	MPA_KEY_REQUEST,
+	MPA_KEY_REPLY
+};
+
+enum send_rdma0 {
+	SEND_RDMA_READ_ZERO = 1,
+	SEND_RDMA_WRITE_ZERO = 2
+};
+
 enum nes_tcpip_pkt_type {
 	NES_PKT_TYPE_UNKNOWN,
 	NES_PKT_TYPE_SYN,
@@ -245,9 +282,9 @@ struct nes_cm_tcp_context {
 
 
 enum nes_cm_listener_state {
-	NES_CM_LISTENER_PASSIVE_STATE=1,
-	NES_CM_LISTENER_ACTIVE_STATE=2,
-	NES_CM_LISTENER_EITHER_STATE=3
+	NES_CM_LISTENER_PASSIVE_STATE = 1,
+	NES_CM_LISTENER_ACTIVE_STATE = 2,
+	NES_CM_LISTENER_EITHER_STATE = 3
 };
 
 struct nes_cm_listener {
@@ -283,16 +320,20 @@ struct nes_cm_node {
 
 	struct nes_cm_node        *loopbackpartner;
 
-	struct nes_timer_entry	*send_entry;
-
+	struct nes_timer_entry	  *send_entry;
+	struct nes_timer_entry    *recv_entry;
 	spinlock_t                retrans_list_lock;
-	struct nes_timer_entry  *recv_entry;
+	enum send_rdma0           send_rdma0_op;
 
-	int                       send_write0;
 	union {
-		struct ietf_mpa_frame mpa_frame;
-		u8                    mpa_frame_buf[MAX_CM_BUFFER];
+		struct ietf_mpa_v1 mpa_frame;
+		struct ietf_mpa_v2 mpa_v2_frame;
+		u8                 mpa_frame_buf[MAX_CM_BUFFER];
 	};
+	enum mpa_frame_version    mpa_frame_rev;
+	u16			  ird_size;
+	u16                       ord_size;
+
 	u16                       mpa_frame_size;
 	struct iw_cm_id           *cm_id;
 	struct list_head          list;
@@ -399,10 +440,8 @@ struct nes_cm_ops {
 			struct nes_vnic *, u16, void *,
 			struct nes_cm_info *);
 	int (*close)(struct nes_cm_core *, struct nes_cm_node *);
-	int (*accept)(struct nes_cm_core *, struct ietf_mpa_frame *,
-			struct nes_cm_node *);
-	int (*reject)(struct nes_cm_core *, struct ietf_mpa_frame *,
-			struct nes_cm_node *);
+	int (*accept)(struct nes_cm_core *, struct nes_cm_node *);
+	int (*reject)(struct nes_cm_core *, struct nes_cm_node *);
 	int (*recv_pkt)(struct nes_cm_core *, struct nes_vnic *,
 			struct sk_buff *);
 	int (*destroy_cm_core)(struct nes_cm_core *);
@@ -422,5 +461,7 @@ int nes_destroy_listen(struct iw_cm_id *);
 int nes_cm_recv(struct sk_buff *, struct net_device *);
 int nes_cm_start(void);
 int nes_cm_stop(void);
+int nes_add_ref_cm_node(struct nes_cm_node *cm_node);
+int nes_rem_ref_cm_node(struct nes_cm_node *cm_node);
 
 #endif			/* NES_CM_H */
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c
index be36cbe..7c0ff19 100644
--- a/drivers/infiniband/hw/nes/nes_hw.c
+++ b/drivers/infiniband/hw/nes/nes_hw.c
@@ -110,6 +110,14 @@ static unsigned char *nes_tcp_state_str[] = {
 };
 #endif
 
+static inline void print_ip(struct nes_cm_node *cm_node)
+{
+	unsigned char *rem_addr;
+	if (cm_node) {
+		rem_addr = (unsigned char *)&cm_node->rem_addr;
+		printk(KERN_ERR PFX "Remote IP addr: %pI4\n", rem_addr);
+	}
+}
 
 /**
  * nes_nic_init_timer_defaults
@@ -1555,6 +1563,7 @@ static void nes_replenish_nic_rq(struct nes_vnic *nesvnic)
 	struct nes_hw_nic_rq_wqe *nic_rqe;
 	struct nes_hw_nic *nesnic;
 	struct nes_device *nesdev;
+	struct nes_rskb_cb *cb;
 	u32 rx_wqes_posted = 0;
 
 	nesnic = &nesvnic->nic;
@@ -1580,6 +1589,9 @@ static void nes_replenish_nic_rq(struct nes_vnic *nesvnic)
 
 			bus_address = pci_map_single(nesdev->pcidev,
 					skb->data, nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
+			cb = (struct nes_rskb_cb *)&skb->cb[0];
+			cb->busaddr = bus_address;
+			cb->maplen = nesvnic->max_frame_size;
 
 			nic_rqe = &nesnic->rq_vbase[nesvnic->nic.rq_head];
 			nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] =
@@ -1669,6 +1681,7 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
 	u32 cqp_head;
 	u32 counter;
 	u32 wqe_count;
+	struct nes_rskb_cb *cb;
 	u8 jumbomode=0;
 
 	/* Allocate fragment, SQ, RQ, and CQ; Reuse CEQ based on the PCI function */
@@ -1845,6 +1858,9 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
 
 		pmem = pci_map_single(nesdev->pcidev, skb->data,
 				nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
+		cb = (struct nes_rskb_cb *)&skb->cb[0];
+		cb->busaddr = pmem;
+		cb->maplen = nesvnic->max_frame_size;
 
 		nic_rqe = &nesvnic->nic.rq_vbase[counter];
 		nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] = cpu_to_le32(nesvnic->max_frame_size);
@@ -1873,6 +1889,13 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
 			jumbomode = 1;
 		nes_nic_init_timer_defaults(nesdev, jumbomode);
 	}
+	if ((nesdev->nesadapter->allow_unaligned_fpdus) &&
+		(nes_init_mgt_qp(nesdev, netdev, nesvnic))) {
+			nes_debug(NES_DBG_INIT, "%s: Out of memory for pau nic\n", netdev->name);
+			nes_destroy_nic_qp(nesvnic);
+		return -ENOMEM;
+	}
+
 	nesvnic->lro_mgr.max_aggr       = nes_lro_max_aggr;
 	nesvnic->lro_mgr.max_desc       = NES_MAX_LRO_DESCRIPTORS;
 	nesvnic->lro_mgr.lro_arr        = nesvnic->lro_desc;
@@ -1895,28 +1918,29 @@ void nes_destroy_nic_qp(struct nes_vnic *nesvnic)
 	struct nes_device *nesdev = nesvnic->nesdev;
 	struct nes_hw_cqp_wqe *cqp_wqe;
 	struct nes_hw_nic_sq_wqe *nic_sqe;
-	struct nes_hw_nic_rq_wqe *nic_rqe;
 	__le16 *wqe_fragment_length;
 	u16  wqe_fragment_index;
-	u64 wqe_frag;
 	u32 cqp_head;
 	u32 wqm_cfg0;
 	unsigned long flags;
+	struct sk_buff *rx_skb;
+	struct nes_rskb_cb *cb;
 	int ret;
 
+	if (nesdev->nesadapter->allow_unaligned_fpdus)
+		nes_destroy_mgt(nesvnic);
+
 	/* clear wqe stall before destroying NIC QP */
 	wqm_cfg0 = nes_read_indexed(nesdev, NES_IDX_WQM_CONFIG0);
 	nes_write_indexed(nesdev, NES_IDX_WQM_CONFIG0, wqm_cfg0 & 0xFFFF7FFF);
 
 	/* Free remaining NIC receive buffers */
 	while (nesvnic->nic.rq_head != nesvnic->nic.rq_tail) {
-		nic_rqe   = &nesvnic->nic.rq_vbase[nesvnic->nic.rq_tail];
-		wqe_frag  = (u64)le32_to_cpu(
-			nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]);
-		wqe_frag |= ((u64)le32_to_cpu(
-			nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX]))<<32;
-		pci_unmap_single(nesdev->pcidev, (dma_addr_t)wqe_frag,
-				nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
+		rx_skb = nesvnic->nic.rx_skb[nesvnic->nic.rq_tail];
+		cb = (struct nes_rskb_cb *)&rx_skb->cb[0];
+		pci_unmap_single(nesdev->pcidev, cb->busaddr, cb->maplen,
+			PCI_DMA_FROMDEVICE);
+
 		dev_kfree_skb(nesvnic->nic.rx_skb[nesvnic->nic.rq_tail++]);
 		nesvnic->nic.rq_tail &= (nesvnic->nic.rq_size - 1);
 	}
@@ -2775,6 +2799,7 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
 	struct nes_hw_nic_sq_wqe *nic_sqe;
 	struct sk_buff *skb;
 	struct sk_buff *rx_skb;
+	struct nes_rskb_cb *cb;
 	__le16 *wqe_fragment_length;
 	u32 head;
 	u32 cq_size;
@@ -2859,6 +2884,8 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
 				bus_address += ((u64)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX])) << 32;
 				pci_unmap_single(nesdev->pcidev, bus_address,
 						nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
+				cb = (struct nes_rskb_cb *)&rx_skb->cb[0];
+				cb->busaddr = 0;
 				/* rx_skb->tail = rx_skb->data + rx_pkt_size; */
 				/* rx_skb->len = rx_pkt_size; */
 				rx_skb->len = 0;  /* TODO: see if this is necessary */
@@ -2983,6 +3010,7 @@ skip_rx_indicate0:
 }
 
 
+
 /**
  * nes_cqp_ce_handler
  */
@@ -2997,6 +3025,8 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
 	u32 cq_size;
 	u32 cqe_count=0;
 	u32 error_code;
+	u32 opcode;
+	u32 ctx_index;
 	/* u32 counter; */
 
 	head = cq->cq_head;
@@ -3007,12 +3037,9 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
 		/* nes_debug(NES_DBG_CQP, "head=%u cqe_words=%08X\n", head,
 			  le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX])); */
 
-		if (le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]) & NES_CQE_VALID) {
-			u64temp = (((u64)(le32_to_cpu(cq->cq_vbase[head].
-					cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX]))) << 32) |
-					((u64)(le32_to_cpu(cq->cq_vbase[head].
-					cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX])));
-			cqp = *((struct nes_hw_cqp **)&u64temp);
+		opcode = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]);
+		if (opcode & NES_CQE_VALID) {
+			cqp = &nesdev->cqp;
 
 			error_code = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_ERROR_CODE_IDX]);
 			if (error_code) {
@@ -3021,15 +3048,14 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
 						le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX])&0x3f,
 						(u16)(error_code >> 16),
 						(u16)error_code);
-				nes_debug(NES_DBG_CQP, "cqp: qp_id=%u, sq_head=%u, sq_tail=%u\n",
-						cqp->qp_id, cqp->sq_head, cqp->sq_tail);
 			}
 
-			u64temp = (((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail].
-					wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX]))) << 32) |
-					((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail].
-					wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX])));
-			cqp_request = *((struct nes_cqp_request **)&u64temp);
+			u64temp = (((u64)(le32_to_cpu(cq->cq_vbase[head].
+					cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX]))) << 32) |
+					((u64)(le32_to_cpu(cq->cq_vbase[head].
+					cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX])));
+
+			cqp_request = (struct nes_cqp_request *)(unsigned long)u64temp;
 			if (cqp_request) {
 				if (cqp_request->waiting) {
 					/* nes_debug(NES_DBG_CQP, "%s: Waking up requestor\n"); */
@@ -3075,9 +3101,15 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
 		cqp_wqe = &nesdev->cqp.sq_vbase[head];
 		memcpy(cqp_wqe, &cqp_request->cqp_wqe, sizeof(*cqp_wqe));
 		barrier();
-		cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] =
+
+		opcode = cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX];
+		if ((opcode & NES_CQP_OPCODE_MASK) == NES_CQP_DOWNLOAD_SEGMENT)
+			ctx_index = NES_CQP_WQE_DL_COMP_CTX_LOW_IDX;
+		else
+			ctx_index = NES_CQP_WQE_COMP_CTX_LOW_IDX;
+		cqp_wqe->wqe_words[ctx_index] =
 			cpu_to_le32((u32)((unsigned long)cqp_request));
-		cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] =
+		cqp_wqe->wqe_words[ctx_index + 1] =
 			cpu_to_le32((u32)(upper_32_bits((unsigned long)cqp_request)));
 		nes_debug(NES_DBG_CQP, "CQP request %p (opcode 0x%02X) put on CQPs SQ wqe%u.\n",
 				cqp_request, le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f, head);
@@ -3093,7 +3125,6 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
 	nes_read32(nesdev->regs+NES_CQE_ALLOC);
 }
 
-
 static u8 *locate_mpa(u8 *pkt, u32 aeq_info)
 {
 	if (aeq_info & NES_AEQE_Q2_DATA_ETHERNET) {
@@ -3553,9 +3584,9 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
 
 	aeqe_cq_id = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]);
 	if (aeq_info & NES_AEQE_QP) {
-		if ((!nes_is_resource_allocated(nesadapter, nesadapter->allocated_qps,
-				aeqe_cq_id)) ||
-				(atomic_read(&nesqp->close_timer_started)))
+		if (!nes_is_resource_allocated(nesadapter,
+				nesadapter->allocated_qps,
+				aeqe_cq_id))
 			return;
 	}
 
@@ -3566,8 +3597,7 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
 
 			if (atomic_inc_return(&nesqp->close_timer_started) == 1) {
 				if ((tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) &&
-					(nesqp->ibqp_state == IB_QPS_RTS) &&
-					((nesadapter->eeprom_version >> 16) != NES_A0)) {
+					(nesqp->ibqp_state == IB_QPS_RTS)) {
 					spin_lock_irqsave(&nesqp->lock, flags);
 					nesqp->hw_iwarp_state = iwarp_state;
 					nesqp->hw_tcp_state = tcp_state;
@@ -3594,9 +3624,10 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
 				return;
 			}
 			spin_lock_irqsave(&nesqp->lock, flags);
-			nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_CLOSING;
+			nesqp->hw_iwarp_state = iwarp_state;
+			nesqp->hw_tcp_state = tcp_state;
+			nesqp->last_aeq = async_event_id;
 			spin_unlock_irqrestore(&nesqp->lock, flags);
-			nes_hw_modify_qp(nesdev, nesqp, NES_CQP_QP_IWARP_STATE_CLOSING, 0, 0);
 			nes_cm_disconn(nesqp);
 			break;
 
@@ -3694,7 +3725,9 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
 		case NES_AEQE_AEID_ROE_INVALID_RDMA_WRITE_OR_READ_RESP:
 			printk(KERN_ERR PFX "QP[%u] async_event_id=0x%04X IB_EVENT_QP_FATAL\n",
 					nesqp->hwqp.qp_id, async_event_id);
-			nes_terminate_connection(nesdev, nesqp, aeqe, IB_EVENT_QP_FATAL);
+			print_ip(nesqp->cm_node);
+			if (!atomic_read(&nesqp->close_timer_started))
+				nes_terminate_connection(nesdev, nesqp, aeqe, IB_EVENT_QP_FATAL);
 			break;
 
 		case NES_AEQE_AEID_CQ_OPERATION_ERROR:
diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h
index c324147..0b590e1 100644
--- a/drivers/infiniband/hw/nes/nes_hw.h
+++ b/drivers/infiniband/hw/nes/nes_hw.h
@@ -47,6 +47,11 @@
 #define NES_MULTICAST_PF_MAX 8
 #define NES_A0 3
 
+#define NES_ENABLE_PAU 0x07000001
+#define NES_DISABLE_PAU 0x07000000
+#define NES_PAU_COUNTER 10
+#define NES_CQP_OPCODE_MASK 0x3f
+
 enum pci_regs {
 	NES_INT_STAT = 0x0000,
 	NES_INT_MASK = 0x0004,
@@ -73,8 +78,10 @@ enum indexed_regs {
 	NES_IDX_QP_CONTROL = 0x0040,
 	NES_IDX_FLM_CONTROL = 0x0080,
 	NES_IDX_INT_CPU_STATUS = 0x00a0,
+	NES_IDX_GPR_TRIGGER = 0x00bc,
 	NES_IDX_GPIO_CONTROL = 0x00f0,
 	NES_IDX_GPIO_DATA = 0x00f4,
+	NES_IDX_GPR2 = 0x010c,
 	NES_IDX_TCP_CONFIG0 = 0x01e4,
 	NES_IDX_TCP_TIMER_CONFIG = 0x01ec,
 	NES_IDX_TCP_NOW = 0x01f0,
@@ -202,6 +209,7 @@ enum nes_cqp_opcodes {
 	NES_CQP_REGISTER_SHARED_STAG = 0x0c,
 	NES_CQP_DEALLOCATE_STAG = 0x0d,
 	NES_CQP_MANAGE_ARP_CACHE = 0x0f,
+	NES_CQP_DOWNLOAD_SEGMENT = 0x10,
 	NES_CQP_SUSPEND_QPS = 0x11,
 	NES_CQP_UPLOAD_CONTEXT = 0x13,
 	NES_CQP_CREATE_CEQ = 0x16,
@@ -210,7 +218,8 @@ enum nes_cqp_opcodes {
 	NES_CQP_DESTROY_AEQ = 0x1b,
 	NES_CQP_LMI_ACCESS = 0x20,
 	NES_CQP_FLUSH_WQES = 0x22,
-	NES_CQP_MANAGE_APBVT = 0x23
+	NES_CQP_MANAGE_APBVT = 0x23,
+	NES_CQP_MANAGE_QUAD_HASH = 0x25
 };
 
 enum nes_cqp_wqe_word_idx {
@@ -222,6 +231,14 @@ enum nes_cqp_wqe_word_idx {
 	NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX = 5,
 };
 
+enum nes_cqp_wqe_word_download_idx { /* format differs from other cqp ops */
+	NES_CQP_WQE_DL_OPCODE_IDX = 0,
+	NES_CQP_WQE_DL_COMP_CTX_LOW_IDX = 1,
+	NES_CQP_WQE_DL_COMP_CTX_HIGH_IDX = 2,
+	NES_CQP_WQE_DL_LENGTH_0_TOTAL_IDX = 3
+	/* For index values 4-15 use NES_NIC_SQ_WQE_ values */
+};
+
 enum nes_cqp_cq_wqeword_idx {
 	NES_CQP_CQ_WQE_PBL_LOW_IDX = 6,
 	NES_CQP_CQ_WQE_PBL_HIGH_IDX = 7,
@@ -242,6 +259,7 @@ enum nes_cqp_stag_wqeword_idx {
 	NES_CQP_STAG_WQE_PBL_LEN_IDX = 14
 };
 
+#define NES_CQP_OP_LOGICAL_PORT_SHIFT 26
 #define NES_CQP_OP_IWARP_STATE_SHIFT 28
 #define NES_CQP_OP_TERMLEN_SHIFT     28
 
@@ -599,6 +617,7 @@ enum nes_nic_sq_wqe_bits {
 
 enum nes_nic_cqe_word_idx {
 	NES_NIC_CQE_ACCQP_ID_IDX = 0,
+	NES_NIC_CQE_HASH_RCVNXT = 1,
 	NES_NIC_CQE_TAG_PKT_TYPE_IDX = 2,
 	NES_NIC_CQE_MISC_IDX = 3,
 };
@@ -1005,6 +1024,11 @@ struct nes_arp_entry {
 #define NES_NIC_CQ_DOWNWARD_TREND   16
 #define NES_PFT_SIZE		    48
 
+#define NES_MGT_WQ_COUNT 32
+#define NES_MGT_CTX_SIZE ((NES_NIC_CTX_RQ_SIZE_32) | (NES_NIC_CTX_SQ_SIZE_32))
+#define NES_MGT_QP_OFFSET 36
+#define NES_MGT_QP_COUNT 4
+
 struct nes_hw_tune_timer {
     /* u16 cq_count; */
     u16 threshold_low;
@@ -1118,6 +1142,7 @@ struct nes_adapter {
 	u32 et_rate_sample_interval;
 	u32 timer_int_limit;
 	u32 wqm_quanta;
+	u8 allow_unaligned_fpdus;
 
 	/* Adapter base MAC address */
 	u32 mac_addr_low;
@@ -1251,6 +1276,14 @@ struct nes_vnic {
 	enum ib_event_type delayed_event;
 	enum ib_event_type last_dispatched_event;
 	spinlock_t port_ibevent_lock;
+	u32 mgt_mem_size;
+	void *mgt_vbase;
+	dma_addr_t mgt_pbase;
+	struct nes_vnic_mgt *mgtvnic[NES_MGT_QP_COUNT];
+	struct task_struct *mgt_thread;
+	wait_queue_head_t mgt_wait_queue;
+	struct sk_buff_head mgt_skb_list;
+
 };
 
 struct nes_ib_device {
diff --git a/drivers/infiniband/hw/nes/nes_mgt.c b/drivers/infiniband/hw/nes/nes_mgt.c
new file mode 100644
index 0000000..b3b2a24
--- /dev/null
+++ b/drivers/infiniband/hw/nes/nes_mgt.c
@@ -0,0 +1,1162 @@
+/*
+ * Copyright (c) 2006 - 2009 Intel-NE, Inc.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/kthread.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <net/tcp.h>
+#include "nes.h"
+#include "nes_mgt.h"
+
+atomic_t pau_qps_created;
+atomic_t pau_qps_destroyed;
+
+static void nes_replenish_mgt_rq(struct nes_vnic_mgt *mgtvnic)
+{
+	unsigned long flags;
+	dma_addr_t bus_address;
+	struct sk_buff *skb;
+	struct nes_hw_nic_rq_wqe *nic_rqe;
+	struct nes_hw_mgt *nesmgt;
+	struct nes_device *nesdev;
+	struct nes_rskb_cb *cb;
+	u32 rx_wqes_posted = 0;
+
+	nesmgt = &mgtvnic->mgt;
+	nesdev = mgtvnic->nesvnic->nesdev;
+	spin_lock_irqsave(&nesmgt->rq_lock, flags);
+	if (nesmgt->replenishing_rq != 0) {
+		if (((nesmgt->rq_size - 1) == atomic_read(&mgtvnic->rx_skbs_needed)) &&
+		    (atomic_read(&mgtvnic->rx_skb_timer_running) == 0)) {
+			atomic_set(&mgtvnic->rx_skb_timer_running, 1);
+			spin_unlock_irqrestore(&nesmgt->rq_lock, flags);
+			mgtvnic->rq_wqes_timer.expires = jiffies + (HZ / 2);      /* 1/2 second */
+			add_timer(&mgtvnic->rq_wqes_timer);
+		} else {
+			spin_unlock_irqrestore(&nesmgt->rq_lock, flags);
+		}
+		return;
+	}
+	nesmgt->replenishing_rq = 1;
+	spin_unlock_irqrestore(&nesmgt->rq_lock, flags);
+	do {
+		skb = dev_alloc_skb(mgtvnic->nesvnic->max_frame_size);
+		if (skb) {
+			skb->dev = mgtvnic->nesvnic->netdev;
+
+			bus_address = pci_map_single(nesdev->pcidev,
+						     skb->data, mgtvnic->nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
+			cb = (struct nes_rskb_cb *)&skb->cb[0];
+			cb->busaddr = bus_address;
+			cb->maplen = mgtvnic->nesvnic->max_frame_size;
+
+			nic_rqe = &nesmgt->rq_vbase[mgtvnic->mgt.rq_head];
+			nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] =
+				cpu_to_le32(mgtvnic->nesvnic->max_frame_size);
+			nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_3_2_IDX] = 0;
+			nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX] =
+				cpu_to_le32((u32)bus_address);
+			nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX] =
+				cpu_to_le32((u32)((u64)bus_address >> 32));
+			nesmgt->rx_skb[nesmgt->rq_head] = skb;
+			nesmgt->rq_head++;
+			nesmgt->rq_head &= nesmgt->rq_size - 1;
+			atomic_dec(&mgtvnic->rx_skbs_needed);
+			barrier();
+			if (++rx_wqes_posted == 255) {
+				nes_write32(nesdev->regs + NES_WQE_ALLOC, (rx_wqes_posted << 24) | nesmgt->qp_id);
+				rx_wqes_posted = 0;
+			}
+		} else {
+			spin_lock_irqsave(&nesmgt->rq_lock, flags);
+			if (((nesmgt->rq_size - 1) == atomic_read(&mgtvnic->rx_skbs_needed)) &&
+			    (atomic_read(&mgtvnic->rx_skb_timer_running) == 0)) {
+				atomic_set(&mgtvnic->rx_skb_timer_running, 1);
+				spin_unlock_irqrestore(&nesmgt->rq_lock, flags);
+				mgtvnic->rq_wqes_timer.expires = jiffies + (HZ / 2);      /* 1/2 second */
+				add_timer(&mgtvnic->rq_wqes_timer);
+			} else {
+				spin_unlock_irqrestore(&nesmgt->rq_lock, flags);
+			}
+			break;
+		}
+	} while (atomic_read(&mgtvnic->rx_skbs_needed));
+	barrier();
+	if (rx_wqes_posted)
+		nes_write32(nesdev->regs + NES_WQE_ALLOC, (rx_wqes_posted << 24) | nesmgt->qp_id);
+	nesmgt->replenishing_rq = 0;
+}
+
+/**
+ * nes_mgt_rq_wqes_timeout
+ */
+static void nes_mgt_rq_wqes_timeout(unsigned long parm)
+{
+	struct nes_vnic_mgt *mgtvnic = (struct nes_vnic_mgt *)parm;
+
+	atomic_set(&mgtvnic->rx_skb_timer_running, 0);
+	if (atomic_read(&mgtvnic->rx_skbs_needed))
+		nes_replenish_mgt_rq(mgtvnic);
+}
+
+/**
+ * nes_mgt_free_skb - unmap and free skb
+ */
+static void nes_mgt_free_skb(struct nes_device *nesdev, struct sk_buff *skb, u32 dir)
+{
+	struct nes_rskb_cb *cb;
+
+	cb = (struct nes_rskb_cb *)&skb->cb[0];
+	pci_unmap_single(nesdev->pcidev, cb->busaddr, cb->maplen, dir);
+	cb->busaddr = 0;
+	dev_kfree_skb_any(skb);
+}
+
+/**
+ * nes_download_callback - handle download completions
+ */
+static void nes_download_callback(struct nes_device *nesdev, struct nes_cqp_request *cqp_request)
+{
+	struct pau_fpdu_info *fpdu_info = cqp_request->cqp_callback_pointer;
+	struct nes_qp *nesqp = fpdu_info->nesqp;
+	struct sk_buff *skb;
+	int i;
+
+	for (i = 0; i < fpdu_info->frag_cnt; i++) {
+		skb = fpdu_info->frags[i].skb;
+		if (fpdu_info->frags[i].cmplt) {
+			nes_mgt_free_skb(nesdev, skb, PCI_DMA_TODEVICE);
+			nes_rem_ref_cm_node(nesqp->cm_node);
+		}
+	}
+
+	if (fpdu_info->hdr_vbase)
+		pci_free_consistent(nesdev->pcidev, fpdu_info->hdr_len,
+				    fpdu_info->hdr_vbase, fpdu_info->hdr_pbase);
+	kfree(fpdu_info);
+}
+
+/**
+ * nes_get_seq - Get the seq, ack_seq and window from the packet
+ */
+static u32 nes_get_seq(struct sk_buff *skb, u32 *ack, u16 *wnd, u32 *fin_rcvd, u32 *rst_rcvd)
+{
+	struct nes_rskb_cb *cb = (struct nes_rskb_cb *)&skb->cb[0];
+	struct iphdr *iph = (struct iphdr *)(cb->data_start + ETH_HLEN);
+	struct tcphdr *tcph = (struct tcphdr *)(((char *)iph) + (4 * iph->ihl));
+
+	*ack = be32_to_cpu(tcph->ack_seq);
+	*wnd = be16_to_cpu(tcph->window);
+	*fin_rcvd = tcph->fin;
+	*rst_rcvd = tcph->rst;
+	return be32_to_cpu(tcph->seq);
+}
+
+/**
+ * nes_get_next_skb - Get the next skb based on where current skb is in the queue
+ */
+static struct sk_buff *nes_get_next_skb(struct nes_device *nesdev, struct nes_qp *nesqp,
+					struct sk_buff *skb, u32 nextseq, u32 *ack,
+					u16 *wnd, u32 *fin_rcvd, u32 *rst_rcvd)
+{
+	u32 seq;
+	bool processacks;
+	struct sk_buff *old_skb;
+
+	if (skb) {
+		/* Continue processing fpdu */
+		if (skb->next == (struct sk_buff *)&nesqp->pau_list)
+			goto out;
+		skb = skb->next;
+		processacks = false;
+	} else {
+		/* Starting a new one */
+		if (skb_queue_empty(&nesqp->pau_list))
+			goto out;
+		skb = skb_peek(&nesqp->pau_list);
+		processacks = true;
+	}
+
+	while (1) {
+		seq = nes_get_seq(skb, ack, wnd, fin_rcvd, rst_rcvd);
+		if (seq == nextseq) {
+			if (skb->len || processacks)
+				break;
+		} else if (after(seq, nextseq)) {
+			goto out;
+		}
+
+		if (skb->next == (struct sk_buff *)&nesqp->pau_list)
+			goto out;
+
+		old_skb = skb;
+		skb = skb->next;
+		skb_unlink(old_skb, &nesqp->pau_list);
+		nes_mgt_free_skb(nesdev, old_skb, PCI_DMA_TODEVICE);
+		nes_rem_ref_cm_node(nesqp->cm_node);
+	}
+	return skb;
+
+out:
+	return NULL;
+}
+
+/**
+ * get_fpdu_info - Find the next complete fpdu and return its fragments.
+ */
+static int get_fpdu_info(struct nes_device *nesdev, struct nes_qp *nesqp,
+			 struct pau_fpdu_info **pau_fpdu_info)
+{
+	struct sk_buff *skb;
+	struct iphdr *iph;
+	struct tcphdr *tcph;
+	struct nes_rskb_cb *cb;
+	struct pau_fpdu_info *fpdu_info = NULL;
+	struct pau_fpdu_frag frags[MAX_FPDU_FRAGS];
+	unsigned long flags;
+	u32 fpdu_len = 0;
+	u32 tmp_len;
+	int frag_cnt = 0;
+	u32 tot_len;
+	u32 frag_tot;
+	u32 ack;
+	u32 fin_rcvd;
+	u32 rst_rcvd;
+	u16 wnd;
+	int i;
+	int rc = 0;
+
+	*pau_fpdu_info = NULL;
+
+	spin_lock_irqsave(&nesqp->pau_lock, flags);
+	skb = nes_get_next_skb(nesdev, nesqp, NULL, nesqp->pau_rcv_nxt, &ack, &wnd, &fin_rcvd, &rst_rcvd);
+	if (!skb) {
+		spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+		goto out;
+	}
+	cb = (struct nes_rskb_cb *)&skb->cb[0];
+	if (skb->len) {
+		fpdu_len = be16_to_cpu(*(__be16 *) skb->data) + MPA_FRAMING;
+		fpdu_len = (fpdu_len + 3) & 0xfffffffc;
+		tmp_len = fpdu_len;
+
+		/* See if we have all of the fpdu */
+		frag_tot = 0;
+		memset(&frags, 0, sizeof frags);
+		for (i = 0; i < MAX_FPDU_FRAGS; i++) {
+			frags[i].physaddr = cb->busaddr;
+			frags[i].physaddr += skb->data - cb->data_start;
+			frags[i].frag_len = min(tmp_len, skb->len);
+			frags[i].skb = skb;
+			frags[i].cmplt = (skb->len == frags[i].frag_len);
+			frag_tot += frags[i].frag_len;
+			frag_cnt++;
+
+			tmp_len -= frags[i].frag_len;
+			if (tmp_len == 0)
+				break;
+
+			skb = nes_get_next_skb(nesdev, nesqp, skb,
+					       nesqp->pau_rcv_nxt + frag_tot, &ack, &wnd, &fin_rcvd, &rst_rcvd);
+			if (!skb) {
+				spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+				goto out;
+			} else if (rst_rcvd) {
+				/* rst received in the middle of fpdu */
+				for (; i >= 0; i--) {
+					skb_unlink(frags[i].skb, &nesqp->pau_list);
+					nes_mgt_free_skb(nesdev, frags[i].skb, PCI_DMA_TODEVICE);
+				}
+				cb = (struct nes_rskb_cb *)&skb->cb[0];
+				frags[0].physaddr = cb->busaddr;
+				frags[0].physaddr += skb->data - cb->data_start;
+				frags[0].frag_len = skb->len;
+				frags[0].skb = skb;
+				frags[0].cmplt = true;
+				frag_cnt = 1;
+				break;
+			}
+
+			cb = (struct nes_rskb_cb *)&skb->cb[0];
+		}
+	} else {
+		/* no data */
+		frags[0].physaddr = cb->busaddr;
+		frags[0].frag_len = 0;
+		frags[0].skb = skb;
+		frags[0].cmplt = true;
+		frag_cnt = 1;
+	}
+
+	spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+
+	/* Found one */
+	fpdu_info = kzalloc(sizeof(*fpdu_info), GFP_ATOMIC);
+	if (fpdu_info == NULL) {
+		nes_debug(NES_DBG_PAU, "Failed to alloc a fpdu_info.\n");
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	fpdu_info->cqp_request = nes_get_cqp_request(nesdev);
+	if (fpdu_info->cqp_request == NULL) {
+		nes_debug(NES_DBG_PAU, "Failed to get a cqp_request.\n");
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	cb = (struct nes_rskb_cb *)&frags[0].skb->cb[0];
+	iph = (struct iphdr *)(cb->data_start + ETH_HLEN);
+	tcph = (struct tcphdr *)(((char *)iph) + (4 * iph->ihl));
+	fpdu_info->hdr_len = (((unsigned char *)tcph) + 4 * (tcph->doff)) - cb->data_start;
+	fpdu_info->data_len = fpdu_len;
+	tot_len = fpdu_info->hdr_len + fpdu_len - ETH_HLEN;
+
+	if (frags[0].cmplt) {
+		fpdu_info->hdr_pbase = cb->busaddr;
+		fpdu_info->hdr_vbase = NULL;
+	} else {
+		fpdu_info->hdr_vbase = pci_alloc_consistent(nesdev->pcidev,
+							    fpdu_info->hdr_len, &fpdu_info->hdr_pbase);
+		if (!fpdu_info->hdr_vbase) {
+			nes_debug(NES_DBG_PAU, "Unable to allocate memory for pau first frag\n");
+			rc = -ENOMEM;
+			goto out;
+		}
+
+		/* Copy hdrs, adjusting len and seqnum */
+		memcpy(fpdu_info->hdr_vbase, cb->data_start, fpdu_info->hdr_len);
+		iph = (struct iphdr *)(fpdu_info->hdr_vbase + ETH_HLEN);
+		tcph = (struct tcphdr *)(((char *)iph) + (4 * iph->ihl));
+	}
+
+	iph->tot_len = cpu_to_be16(tot_len);
+	iph->saddr = cpu_to_be32(0x7f000001);
+
+	tcph->seq = cpu_to_be32(nesqp->pau_rcv_nxt);
+	tcph->ack_seq = cpu_to_be32(ack);
+	tcph->window = cpu_to_be16(wnd);
+
+	nesqp->pau_rcv_nxt += fpdu_len + fin_rcvd;
+
+	memcpy(fpdu_info->frags, frags, sizeof(fpdu_info->frags));
+	fpdu_info->frag_cnt = frag_cnt;
+	fpdu_info->nesqp = nesqp;
+	*pau_fpdu_info = fpdu_info;
+
+	/* Update skb's for next pass */
+	for (i = 0; i < frag_cnt; i++) {
+		cb = (struct nes_rskb_cb *)&frags[i].skb->cb[0];
+		skb_pull(frags[i].skb, frags[i].frag_len);
+
+		if (frags[i].skb->len == 0) {
+			/* Pull skb off the list - it will be freed in the callback */
+			spin_lock_irqsave(&nesqp->pau_lock, flags);
+			skb_unlink(frags[i].skb, &nesqp->pau_list);
+			spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+		} else {
+			/* Last skb still has data so update the seq */
+			iph = (struct iphdr *)(cb->data_start + ETH_HLEN);
+			tcph = (struct tcphdr *)(((char *)iph) + (4 * iph->ihl));
+			tcph->seq = cpu_to_be32(nesqp->pau_rcv_nxt);
+		}
+	}
+
+out:
+	if (rc) {
+		if (fpdu_info) {
+			if (fpdu_info->cqp_request)
+				nes_put_cqp_request(nesdev, fpdu_info->cqp_request);
+			kfree(fpdu_info);
+		}
+	}
+	return rc;
+}
+
+/**
+ * forward_fpdu - send complete fpdus, one at a time
+ */
+static int forward_fpdus(struct nes_vnic *nesvnic, struct nes_qp *nesqp)
+{
+	struct nes_device *nesdev = nesvnic->nesdev;
+	struct pau_fpdu_info *fpdu_info;
+	struct nes_hw_cqp_wqe *cqp_wqe;
+	struct nes_cqp_request *cqp_request;
+	u64 u64tmp;
+	u32 u32tmp;
+	int rc;
+
+	while (1) {
+		rc = get_fpdu_info(nesdev, nesqp, &fpdu_info);
+		if (fpdu_info == NULL)
+			return rc;
+
+		cqp_request = fpdu_info->cqp_request;
+		cqp_wqe = &cqp_request->cqp_wqe;
+		nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_DL_OPCODE_IDX,
+				    NES_CQP_DOWNLOAD_SEGMENT |
+				    (((u32)nesvnic->logical_port) << NES_CQP_OP_LOGICAL_PORT_SHIFT));
+
+		u32tmp = fpdu_info->hdr_len << 16;
+		u32tmp |= fpdu_info->hdr_len + (u32)fpdu_info->data_len;
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_DL_LENGTH_0_TOTAL_IDX,
+				    u32tmp);
+
+		u32tmp = (fpdu_info->frags[1].frag_len << 16) | fpdu_info->frags[0].frag_len;
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_LENGTH_2_1_IDX,
+				    u32tmp);
+
+		u32tmp = (fpdu_info->frags[3].frag_len << 16) | fpdu_info->frags[2].frag_len;
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_LENGTH_4_3_IDX,
+				    u32tmp);
+
+		u64tmp = (u64)fpdu_info->hdr_pbase;
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_LOW_IDX,
+				    lower_32_bits(u64tmp));
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_HIGH_IDX,
+				    upper_32_bits(u64tmp >> 32));
+
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG1_LOW_IDX,
+				    lower_32_bits(fpdu_info->frags[0].physaddr));
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG1_HIGH_IDX,
+				    upper_32_bits(fpdu_info->frags[0].physaddr));
+
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG2_LOW_IDX,
+				    lower_32_bits(fpdu_info->frags[1].physaddr));
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG2_HIGH_IDX,
+				    upper_32_bits(fpdu_info->frags[1].physaddr));
+
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG3_LOW_IDX,
+				    lower_32_bits(fpdu_info->frags[2].physaddr));
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG3_HIGH_IDX,
+				    upper_32_bits(fpdu_info->frags[2].physaddr));
+
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG4_LOW_IDX,
+				    lower_32_bits(fpdu_info->frags[3].physaddr));
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_NIC_SQ_WQE_FRAG4_HIGH_IDX,
+				    upper_32_bits(fpdu_info->frags[3].physaddr));
+
+		cqp_request->cqp_callback_pointer = fpdu_info;
+		cqp_request->callback = 1;
+		cqp_request->cqp_callback = nes_download_callback;
+
+		atomic_set(&cqp_request->refcount, 1);
+		nes_post_cqp_request(nesdev, cqp_request);
+	}
+
+	return 0;
+}
+
+static void process_fpdus(struct nes_vnic *nesvnic, struct nes_qp *nesqp)
+{
+	int again = 1;
+	unsigned long flags;
+
+	do {
+		/* Ignore rc - if it failed, tcp retries will cause it to try again */
+		forward_fpdus(nesvnic, nesqp);
+
+		spin_lock_irqsave(&nesqp->pau_lock, flags);
+		if (nesqp->pau_pending) {
+			nesqp->pau_pending = 0;
+		} else {
+			nesqp->pau_busy = 0;
+			again = 0;
+		}
+
+		spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+	} while (again);
+}
+
+/**
+ * queue_fpdus - Handle fpdu's that hw passed up to sw
+ */
+static void queue_fpdus(struct sk_buff *skb, struct nes_vnic *nesvnic, struct nes_qp *nesqp)
+{
+	struct sk_buff *tmpskb;
+	struct nes_rskb_cb *cb;
+	struct iphdr *iph;
+	struct tcphdr *tcph;
+	unsigned char *tcph_end;
+	u32 rcv_nxt;
+	u32 rcv_wnd;
+	u32 seqnum;
+	u32 len;
+	bool process_it = false;
+	unsigned long flags;
+
+	/* Move data ptr to after tcp header */
+	iph = (struct iphdr *)skb->data;
+	tcph = (struct tcphdr *)(((char *)iph) + (4 * iph->ihl));
+	seqnum = be32_to_cpu(tcph->seq);
+	tcph_end = (((char *)tcph) + (4 * tcph->doff));
+
+	len = be16_to_cpu(iph->tot_len);
+	if (skb->len > len)
+		skb_trim(skb, len);
+	skb_pull(skb, tcph_end - skb->data);
+
+	/* Initialize tracking values */
+	cb = (struct nes_rskb_cb *)&skb->cb[0];
+	cb->seqnum = seqnum;
+
+	/* Make sure data is in the receive window */
+	rcv_nxt = nesqp->pau_rcv_nxt;
+	rcv_wnd = le32_to_cpu(nesqp->nesqp_context->rcv_wnd);
+	if (!between(seqnum, rcv_nxt, (rcv_nxt + rcv_wnd))) {
+		nes_mgt_free_skb(nesvnic->nesdev, skb, PCI_DMA_TODEVICE);
+		nes_rem_ref_cm_node(nesqp->cm_node);
+		return;
+	}
+
+	spin_lock_irqsave(&nesqp->pau_lock, flags);
+
+	if (nesqp->pau_busy)
+		nesqp->pau_pending = 1;
+	else
+		nesqp->pau_busy = 1;
+
+	/* Queue skb by sequence number */
+	if (skb_queue_len(&nesqp->pau_list) == 0) {
+		skb_queue_head(&nesqp->pau_list, skb);
+	} else {
+		tmpskb = nesqp->pau_list.next;
+		while (tmpskb != (struct sk_buff *)&nesqp->pau_list) {
+			cb = (struct nes_rskb_cb *)&tmpskb->cb[0];
+			if (before(seqnum, cb->seqnum))
+				break;
+			tmpskb = tmpskb->next;
+		}
+		skb_insert(tmpskb, skb, &nesqp->pau_list);
+	}
+	if (nesqp->pau_state == PAU_READY)
+		process_it = true;
+	spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+
+	if (process_it)
+		process_fpdus(nesvnic, nesqp);
+
+	return;
+}
+
+/**
+ * mgt_thread - Handle mgt skbs in a safe context
+ */
+static int mgt_thread(void *context)
+{
+	struct nes_vnic *nesvnic = context;
+	struct sk_buff *skb;
+	struct nes_rskb_cb *cb;
+
+	while (!kthread_should_stop()) {
+		wait_event_interruptible(nesvnic->mgt_wait_queue,
+					 skb_queue_len(&nesvnic->mgt_skb_list) || kthread_should_stop());
+		while ((skb_queue_len(&nesvnic->mgt_skb_list)) && !kthread_should_stop()) {
+			skb = skb_dequeue(&nesvnic->mgt_skb_list);
+			cb = (struct nes_rskb_cb *)&skb->cb[0];
+			cb->data_start = skb->data - ETH_HLEN;
+			cb->busaddr = pci_map_single(nesvnic->nesdev->pcidev, cb->data_start,
+						     nesvnic->max_frame_size, PCI_DMA_TODEVICE);
+			queue_fpdus(skb, nesvnic, cb->nesqp);
+		}
+	}
+
+	/* Closing down so delete any entries on the queue */
+	while (skb_queue_len(&nesvnic->mgt_skb_list)) {
+		skb = skb_dequeue(&nesvnic->mgt_skb_list);
+		cb = (struct nes_rskb_cb *)&skb->cb[0];
+		nes_rem_ref_cm_node(cb->nesqp->cm_node);
+		dev_kfree_skb_any(skb);
+	}
+	return 0;
+}
+
+/**
+ * nes_queue_skbs - Queue skb so it can be handled in a thread context
+ */
+void nes_queue_mgt_skbs(struct sk_buff *skb, struct nes_vnic *nesvnic, struct nes_qp *nesqp)
+{
+	struct nes_rskb_cb *cb;
+
+	cb = (struct nes_rskb_cb *)&skb->cb[0];
+	cb->nesqp = nesqp;
+	skb_queue_tail(&nesvnic->mgt_skb_list, skb);
+	wake_up_interruptible(&nesvnic->mgt_wait_queue);
+}
+
+void nes_destroy_pau_qp(struct nes_device *nesdev, struct nes_qp *nesqp)
+{
+	struct sk_buff *skb;
+	unsigned long flags;
+	atomic_inc(&pau_qps_destroyed);
+
+	/* Free packets that have not yet been forwarded */
+	/* Lock is acquired by skb_dequeue when removing the skb */
+	spin_lock_irqsave(&nesqp->pau_lock, flags);
+	while (skb_queue_len(&nesqp->pau_list)) {
+		skb = skb_dequeue(&nesqp->pau_list);
+		nes_mgt_free_skb(nesdev, skb, PCI_DMA_TODEVICE);
+		nes_rem_ref_cm_node(nesqp->cm_node);
+	}
+	spin_unlock_irqrestore(&nesqp->pau_lock, flags);
+}
+
+static void nes_chg_qh_handler(struct nes_device *nesdev, struct nes_cqp_request *cqp_request)
+{
+	struct pau_qh_chg *qh_chg = cqp_request->cqp_callback_pointer;
+	struct nes_cqp_request *new_request;
+	struct nes_hw_cqp_wqe *cqp_wqe;
+	struct nes_adapter *nesadapter;
+	struct nes_qp *nesqp;
+	struct nes_v4_quad nes_quad;
+	u32 crc_value;
+	u64 u64temp;
+
+	nesadapter = nesdev->nesadapter;
+	nesqp = qh_chg->nesqp;
+
+	/* Should we handle the bad completion */
+	if (cqp_request->major_code) {
+		printk(KERN_ERR PFX "Invalid cqp_request major_code=0x%x\n",
+		       cqp_request->major_code);
+		WARN_ON(1);
+	}
+
+	switch (nesqp->pau_state) {
+	case PAU_DEL_QH:
+		/* Old hash code deleted, now set the new one */
+		nesqp->pau_state = PAU_ADD_LB_QH;
+		new_request = nes_get_cqp_request(nesdev);
+		if (new_request == NULL) {
+			nes_debug(NES_DBG_PAU, "Failed to get a new_request.\n");
+			WARN_ON(1);
+			return;
+		}
+
+		memset(&nes_quad, 0, sizeof(nes_quad));
+		nes_quad.DstIpAdrIndex =
+			cpu_to_le32((u32)PCI_FUNC(nesdev->pcidev->devfn) << 24);
+		nes_quad.SrcIpadr = cpu_to_be32(0x7f000001);
+		nes_quad.TcpPorts[0] = swab16(nesqp->nesqp_context->tcpPorts[1]);
+		nes_quad.TcpPorts[1] = swab16(nesqp->nesqp_context->tcpPorts[0]);
+
+		/* Produce hash key */
+		crc_value = get_crc_value(&nes_quad);
+		nesqp->hte_index = cpu_to_be32(crc_value ^ 0xffffffff);
+		nes_debug(NES_DBG_PAU, "new HTE Index = 0x%08X, CRC = 0x%08X\n",
+			  nesqp->hte_index, nesqp->hte_index & nesadapter->hte_index_mask);
+
+		nesqp->hte_index &= nesadapter->hte_index_mask;
+		nesqp->nesqp_context->hte_index = cpu_to_le32(nesqp->hte_index);
+		nesqp->nesqp_context->ip0 = cpu_to_le32(0x7f000001);
+		nesqp->nesqp_context->rcv_nxt = cpu_to_le32(nesqp->pau_rcv_nxt);
+
+		cqp_wqe = &new_request->cqp_wqe;
+		nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
+		set_wqe_32bit_value(cqp_wqe->wqe_words,
+				    NES_CQP_WQE_OPCODE_IDX, NES_CQP_MANAGE_QUAD_HASH |
+				    NES_CQP_QP_TYPE_IWARP | NES_CQP_QP_CONTEXT_VALID | NES_CQP_QP_IWARP_STATE_RTS);
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, nesqp->hwqp.qp_id);
+		u64temp = (u64)nesqp->nesqp_context_pbase;
+		set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, u64temp);
+
+		nes_debug(NES_DBG_PAU, "Waiting for CQP completion for adding the quad hash.\n");
+
+		new_request->cqp_callback_pointer = qh_chg;
+		new_request->callback = 1;
+		new_request->cqp_callback = nes_chg_qh_handler;
+		atomic_set(&new_request->refcount, 1);
+		nes_post_cqp_request(nesdev, new_request);
+		break;
+
+	case PAU_ADD_LB_QH:
+		/* Start processing the queued fpdu's */
+		nesqp->pau_state = PAU_READY;
+		process_fpdus(qh_chg->nesvnic, qh_chg->nesqp);
+		kfree(qh_chg);
+		break;
+	}
+}
+
+/**
+ * nes_change_quad_hash
+ */
+static int nes_change_quad_hash(struct nes_device *nesdev,
+				struct nes_vnic *nesvnic, struct nes_qp *nesqp)
+{
+	struct nes_cqp_request *cqp_request = NULL;
+	struct pau_qh_chg *qh_chg = NULL;
+	u64 u64temp;
+	struct nes_hw_cqp_wqe *cqp_wqe;
+	int ret = 0;
+
+	cqp_request = nes_get_cqp_request(nesdev);
+	if (cqp_request == NULL) {
+		nes_debug(NES_DBG_PAU, "Failed to get a cqp_request.\n");
+		ret = -ENOMEM;
+		goto chg_qh_err;
+	}
+
+	qh_chg = kmalloc(sizeof *qh_chg, GFP_ATOMIC);
+	if (qh_chg == NULL) {
+		nes_debug(NES_DBG_PAU, "Failed to get a cqp_request.\n");
+		ret = -ENOMEM;
+		goto chg_qh_err;
+	}
+	qh_chg->nesdev = nesdev;
+	qh_chg->nesvnic = nesvnic;
+	qh_chg->nesqp = nesqp;
+	nesqp->pau_state = PAU_DEL_QH;
+
+	cqp_wqe = &cqp_request->cqp_wqe;
+	nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
+	set_wqe_32bit_value(cqp_wqe->wqe_words,
+			    NES_CQP_WQE_OPCODE_IDX, NES_CQP_MANAGE_QUAD_HASH | NES_CQP_QP_DEL_HTE |
+			    NES_CQP_QP_TYPE_IWARP | NES_CQP_QP_CONTEXT_VALID | NES_CQP_QP_IWARP_STATE_RTS);
+	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, nesqp->hwqp.qp_id);
+	u64temp = (u64)nesqp->nesqp_context_pbase;
+	set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, u64temp);
+
+	nes_debug(NES_DBG_PAU, "Waiting for CQP completion for deleting the quad hash.\n");
+
+	cqp_request->cqp_callback_pointer = qh_chg;
+	cqp_request->callback = 1;
+	cqp_request->cqp_callback = nes_chg_qh_handler;
+	atomic_set(&cqp_request->refcount, 1);
+	nes_post_cqp_request(nesdev, cqp_request);
+
+	return ret;
+
+chg_qh_err:
+	kfree(qh_chg);
+	if (cqp_request)
+		nes_put_cqp_request(nesdev, cqp_request);
+	return ret;
+}
+
+/**
+ * nes_mgt_ce_handler
+ * This management code deals with any packed and unaligned (pau) fpdu's
+ * that the hardware cannot handle.
+ */
+static void nes_mgt_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
+{
+	struct nes_vnic_mgt *mgtvnic = container_of(cq, struct nes_vnic_mgt, mgt_cq);
+	struct nes_adapter *nesadapter = nesdev->nesadapter;
+	u32 head;
+	u32 cq_size;
+	u32 cqe_count = 0;
+	u32 cqe_misc;
+	u32 qp_id = 0;
+	u32 skbs_needed;
+	unsigned long context;
+	struct nes_qp *nesqp;
+	struct sk_buff *rx_skb;
+	struct nes_rskb_cb *cb;
+
+	head = cq->cq_head;
+	cq_size = cq->cq_size;
+
+	while (1) {
+		cqe_misc = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX]);
+		if (!(cqe_misc & NES_NIC_CQE_VALID))
+			break;
+
+		nesqp = NULL;
+		if (cqe_misc & NES_NIC_CQE_ACCQP_VALID) {
+			qp_id = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_ACCQP_ID_IDX]);
+			qp_id &= 0x001fffff;
+			if (qp_id < nesadapter->max_qp) {
+				context = (unsigned long)nesadapter->qp_table[qp_id - NES_FIRST_QPN];
+				nesqp = (struct nes_qp *)context;
+			}
+		}
+
+		if (nesqp) {
+			if (nesqp->pau_mode == false) {
+				nesqp->pau_mode = true; /* First time for this qp */
+				nesqp->pau_rcv_nxt = le32_to_cpu(
+					cq->cq_vbase[head].cqe_words[NES_NIC_CQE_HASH_RCVNXT]);
+				skb_queue_head_init(&nesqp->pau_list);
+				spin_lock_init(&nesqp->pau_lock);
+				atomic_inc(&pau_qps_created);
+				nes_change_quad_hash(nesdev, mgtvnic->nesvnic, nesqp);
+			}
+
+			rx_skb = mgtvnic->mgt.rx_skb[mgtvnic->mgt.rq_tail];
+			rx_skb->len = 0;
+			skb_put(rx_skb, cqe_misc & 0x0000ffff);
+			rx_skb->protocol = eth_type_trans(rx_skb, mgtvnic->nesvnic->netdev);
+			cb = (struct nes_rskb_cb *)&rx_skb->cb[0];
+			pci_unmap_single(nesdev->pcidev, cb->busaddr, cb->maplen, PCI_DMA_FROMDEVICE);
+			cb->busaddr = 0;
+			mgtvnic->mgt.rq_tail++;
+			mgtvnic->mgt.rq_tail &= mgtvnic->mgt.rq_size - 1;
+
+			nes_add_ref_cm_node(nesqp->cm_node);
+			nes_queue_mgt_skbs(rx_skb, mgtvnic->nesvnic, nesqp);
+		} else {
+			printk(KERN_ERR PFX "Invalid QP %d for packed/unaligned handling\n", qp_id);
+		}
+
+		cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX] = 0;
+		cqe_count++;
+		if (++head >= cq_size)
+			head = 0;
+
+		if (cqe_count == 255) {
+			/* Replenish mgt CQ */
+			nes_write32(nesdev->regs + NES_CQE_ALLOC, cq->cq_number | (cqe_count << 16));
+			nesdev->currcq_count += cqe_count;
+			cqe_count = 0;
+		}
+
+		skbs_needed = atomic_inc_return(&mgtvnic->rx_skbs_needed);
+		if (skbs_needed > (mgtvnic->mgt.rq_size >> 1))
+			nes_replenish_mgt_rq(mgtvnic);
+	}
+
+	cq->cq_head = head;
+	nes_write32(nesdev->regs + NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT |
+		    cq->cq_number | (cqe_count << 16));
+	nes_read32(nesdev->regs + NES_CQE_ALLOC);
+	nesdev->currcq_count += cqe_count;
+}
+
+/**
+ * nes_init_mgt_qp
+ */
+int nes_init_mgt_qp(struct nes_device *nesdev, struct net_device *netdev, struct nes_vnic *nesvnic)
+{
+	struct nes_vnic_mgt *mgtvnic;
+	u32 counter;
+	void *vmem;
+	dma_addr_t pmem;
+	struct nes_hw_cqp_wqe *cqp_wqe;
+	u32 cqp_head;
+	unsigned long flags;
+	struct nes_hw_nic_qp_context *mgt_context;
+	u64 u64temp;
+	struct nes_hw_nic_rq_wqe *mgt_rqe;
+	struct sk_buff *skb;
+	u32 wqe_count;
+	struct nes_rskb_cb *cb;
+	u32 mgt_mem_size;
+	void *mgt_vbase;
+	dma_addr_t mgt_pbase;
+	int i;
+	int ret;
+
+	/* Allocate space the all mgt QPs once */
+	mgtvnic = kzalloc(NES_MGT_QP_COUNT * sizeof(struct nes_vnic_mgt), GFP_KERNEL);
+	if (mgtvnic == NULL) {
+		nes_debug(NES_DBG_INIT, "Unable to allocate memory for mgt structure\n");
+		return -ENOMEM;
+	}
+
+	/* Allocate fragment, RQ, and CQ; Reuse CEQ based on the PCI function */
+	/* We are not sending from this NIC so sq is not allocated */
+	mgt_mem_size = 256 +
+		       (NES_MGT_WQ_COUNT * sizeof(struct nes_hw_nic_rq_wqe)) +
+		       (NES_MGT_WQ_COUNT * sizeof(struct nes_hw_nic_cqe)) +
+		       sizeof(struct nes_hw_nic_qp_context);
+	mgt_mem_size = (mgt_mem_size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
+	mgt_vbase = pci_alloc_consistent(nesdev->pcidev, NES_MGT_QP_COUNT * mgt_mem_size, &mgt_pbase);
+	if (!mgt_vbase) {
+		kfree(mgtvnic);
+		nes_debug(NES_DBG_INIT, "Unable to allocate memory for mgt host descriptor rings\n");
+		return -ENOMEM;
+	}
+
+	nesvnic->mgt_mem_size = NES_MGT_QP_COUNT * mgt_mem_size;
+	nesvnic->mgt_vbase = mgt_vbase;
+	nesvnic->mgt_pbase = mgt_pbase;
+
+	skb_queue_head_init(&nesvnic->mgt_skb_list);
+	init_waitqueue_head(&nesvnic->mgt_wait_queue);
+	nesvnic->mgt_thread = kthread_run(mgt_thread, nesvnic, "nes_mgt_thread");
+
+	for (i = 0; i < NES_MGT_QP_COUNT; i++) {
+		mgtvnic->nesvnic = nesvnic;
+		mgtvnic->mgt.qp_id = nesdev->mac_index + NES_MGT_QP_OFFSET + i;
+		memset(mgt_vbase, 0, mgt_mem_size);
+		nes_debug(NES_DBG_INIT, "Allocated mgt QP structures at %p (phys = %016lX), size = %u.\n",
+			  mgt_vbase, (unsigned long)mgt_pbase, mgt_mem_size);
+
+		vmem = (void *)(((unsigned long)mgt_vbase + (256 - 1)) &
+				~(unsigned long)(256 - 1));
+		pmem = (dma_addr_t)(((unsigned long long)mgt_pbase + (256 - 1)) &
+				    ~(unsigned long long)(256 - 1));
+
+		spin_lock_init(&mgtvnic->mgt.rq_lock);
+
+		/* setup the RQ */
+		mgtvnic->mgt.rq_vbase = vmem;
+		mgtvnic->mgt.rq_pbase = pmem;
+		mgtvnic->mgt.rq_head = 0;
+		mgtvnic->mgt.rq_tail = 0;
+		mgtvnic->mgt.rq_size = NES_MGT_WQ_COUNT;
+
+		/* setup the CQ */
+		vmem += (NES_MGT_WQ_COUNT * sizeof(struct nes_hw_nic_rq_wqe));
+		pmem += (NES_MGT_WQ_COUNT * sizeof(struct nes_hw_nic_rq_wqe));
+
+		mgtvnic->mgt_cq.cq_number = mgtvnic->mgt.qp_id;
+		mgtvnic->mgt_cq.cq_vbase = vmem;
+		mgtvnic->mgt_cq.cq_pbase = pmem;
+		mgtvnic->mgt_cq.cq_head = 0;
+		mgtvnic->mgt_cq.cq_size = NES_MGT_WQ_COUNT;
+
+		mgtvnic->mgt_cq.ce_handler = nes_mgt_ce_handler;
+
+		/* Send CreateCQ request to CQP */
+		spin_lock_irqsave(&nesdev->cqp.lock, flags);
+		cqp_head = nesdev->cqp.sq_head;
+
+		cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
+		nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
+
+		cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(
+			NES_CQP_CREATE_CQ | NES_CQP_CQ_CEQ_VALID |
+			((u32)mgtvnic->mgt_cq.cq_size << 16));
+		cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(
+			mgtvnic->mgt_cq.cq_number | ((u32)nesdev->ceq_index << 16));
+		u64temp = (u64)mgtvnic->mgt_cq.cq_pbase;
+		set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);
+		cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] = 0;
+		u64temp = (unsigned long)&mgtvnic->mgt_cq;
+		cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_LOW_IDX] = cpu_to_le32((u32)(u64temp >> 1));
+		cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] =
+			cpu_to_le32(((u32)((u64temp) >> 33)) & 0x7FFFFFFF);
+		cqp_wqe->wqe_words[NES_CQP_CQ_WQE_DOORBELL_INDEX_HIGH_IDX] = 0;
+
+		if (++cqp_head >= nesdev->cqp.sq_size)
+			cqp_head = 0;
+		cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
+		nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
+
+		/* Send CreateQP request to CQP */
+		mgt_context = (void *)(&mgtvnic->mgt_cq.cq_vbase[mgtvnic->mgt_cq.cq_size]);
+		mgt_context->context_words[NES_NIC_CTX_MISC_IDX] =
+			cpu_to_le32((u32)NES_MGT_CTX_SIZE |
+				    ((u32)PCI_FUNC(nesdev->pcidev->devfn) << 12));
+		nes_debug(NES_DBG_INIT, "RX_WINDOW_BUFFER_PAGE_TABLE_SIZE = 0x%08X, RX_WINDOW_BUFFER_SIZE = 0x%08X\n",
+			  nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_PAGE_TABLE_SIZE),
+			  nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_SIZE));
+		if (nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_SIZE) != 0)
+			mgt_context->context_words[NES_NIC_CTX_MISC_IDX] |= cpu_to_le32(NES_NIC_BACK_STORE);
+
+		u64temp = (u64)mgtvnic->mgt.rq_pbase;
+		mgt_context->context_words[NES_NIC_CTX_SQ_LOW_IDX] = cpu_to_le32((u32)u64temp);
+		mgt_context->context_words[NES_NIC_CTX_SQ_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32));
+		u64temp = (u64)mgtvnic->mgt.rq_pbase;
+		mgt_context->context_words[NES_NIC_CTX_RQ_LOW_IDX] = cpu_to_le32((u32)u64temp);
+		mgt_context->context_words[NES_NIC_CTX_RQ_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32));
+
+		cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_CREATE_QP |
+									 NES_CQP_QP_TYPE_NIC);
+		cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(mgtvnic->mgt.qp_id);
+		u64temp = (u64)mgtvnic->mgt_cq.cq_pbase +
+			  (mgtvnic->mgt_cq.cq_size * sizeof(struct nes_hw_nic_cqe));
+		set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, u64temp);
+
+		if (++cqp_head >= nesdev->cqp.sq_size)
+			cqp_head = 0;
+		nesdev->cqp.sq_head = cqp_head;
+
+		barrier();
+
+		/* Ring doorbell (2 WQEs) */
+		nes_write32(nesdev->regs + NES_WQE_ALLOC, 0x02800000 | nesdev->cqp.qp_id);
+
+		spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
+		nes_debug(NES_DBG_INIT, "Waiting for create MGT QP%u to complete.\n",
+			  mgtvnic->mgt.qp_id);
+
+		ret = wait_event_timeout(nesdev->cqp.waitq, (nesdev->cqp.sq_tail == cqp_head),
+					 NES_EVENT_TIMEOUT);
+		nes_debug(NES_DBG_INIT, "Create MGT QP%u completed, wait_event_timeout ret = %u.\n",
+			  mgtvnic->mgt.qp_id, ret);
+		if (!ret) {
+			nes_debug(NES_DBG_INIT, "MGT QP%u create timeout expired\n", mgtvnic->mgt.qp_id);
+			if (i == 0) {
+				pci_free_consistent(nesdev->pcidev, nesvnic->mgt_mem_size, nesvnic->mgt_vbase,
+						    nesvnic->mgt_pbase);
+				kfree(mgtvnic);
+			} else {
+				nes_destroy_mgt(nesvnic);
+			}
+			return -EIO;
+		}
+
+		/* Populate the RQ */
+		for (counter = 0; counter < (NES_MGT_WQ_COUNT - 1); counter++) {
+			skb = dev_alloc_skb(nesvnic->max_frame_size);
+			if (!skb) {
+				nes_debug(NES_DBG_INIT, "%s: out of memory for receive skb\n", netdev->name);
+				return -ENOMEM;
+			}
+
+			skb->dev = netdev;
+
+			pmem = pci_map_single(nesdev->pcidev, skb->data,
+					      nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
+			cb = (struct nes_rskb_cb *)&skb->cb[0];
+			cb->busaddr = pmem;
+			cb->maplen = nesvnic->max_frame_size;
+
+			mgt_rqe = &mgtvnic->mgt.rq_vbase[counter];
+			mgt_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] = cpu_to_le32((u32)nesvnic->max_frame_size);
+			mgt_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_3_2_IDX] = 0;
+			mgt_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX] = cpu_to_le32((u32)pmem);
+			mgt_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX] = cpu_to_le32((u32)((u64)pmem >> 32));
+			mgtvnic->mgt.rx_skb[counter] = skb;
+		}
+
+		init_timer(&mgtvnic->rq_wqes_timer);
+		mgtvnic->rq_wqes_timer.function = nes_mgt_rq_wqes_timeout;
+		mgtvnic->rq_wqes_timer.data = (unsigned long)mgtvnic;
+
+		wqe_count = NES_MGT_WQ_COUNT - 1;
+		mgtvnic->mgt.rq_head = wqe_count;
+		barrier();
+		do {
+			counter = min(wqe_count, ((u32)255));
+			wqe_count -= counter;
+			nes_write32(nesdev->regs + NES_WQE_ALLOC, (counter << 24) | mgtvnic->mgt.qp_id);
+		} while (wqe_count);
+
+		nes_write32(nesdev->regs + NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT |
+			    mgtvnic->mgt_cq.cq_number);
+		nes_read32(nesdev->regs + NES_CQE_ALLOC);
+
+		mgt_vbase += mgt_mem_size;
+		mgt_pbase += mgt_mem_size;
+		nesvnic->mgtvnic[i] = mgtvnic++;
+	}
+	return 0;
+}
+
+
+void nes_destroy_mgt(struct nes_vnic *nesvnic)
+{
+	struct nes_device *nesdev = nesvnic->nesdev;
+	struct nes_vnic_mgt *mgtvnic;
+	struct nes_vnic_mgt *first_mgtvnic;
+	unsigned long flags;
+	struct nes_hw_cqp_wqe *cqp_wqe;
+	u32 cqp_head;
+	struct sk_buff *rx_skb;
+	int i;
+	int ret;
+
+	kthread_stop(nesvnic->mgt_thread);
+
+	/* Free remaining NIC receive buffers */
+	first_mgtvnic = nesvnic->mgtvnic[0];
+	for (i = 0; i < NES_MGT_QP_COUNT; i++) {
+		mgtvnic = nesvnic->mgtvnic[i];
+		if (mgtvnic == NULL)
+			continue;
+
+		while (mgtvnic->mgt.rq_head != mgtvnic->mgt.rq_tail) {
+			rx_skb = mgtvnic->mgt.rx_skb[mgtvnic->mgt.rq_tail];
+			nes_mgt_free_skb(nesdev, rx_skb, PCI_DMA_FROMDEVICE);
+			mgtvnic->mgt.rq_tail++;
+			mgtvnic->mgt.rq_tail &= (mgtvnic->mgt.rq_size - 1);
+		}
+
+		spin_lock_irqsave(&nesdev->cqp.lock, flags);
+
+		/* Destroy NIC QP */
+		cqp_head = nesdev->cqp.sq_head;
+		cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
+		nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
+
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
+				    (NES_CQP_DESTROY_QP | NES_CQP_QP_TYPE_NIC));
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,
+				    mgtvnic->mgt.qp_id);
+
+		if (++cqp_head >= nesdev->cqp.sq_size)
+			cqp_head = 0;
+
+		cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
+
+		/* Destroy NIC CQ */
+		nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
+				    (NES_CQP_DESTROY_CQ | ((u32)mgtvnic->mgt_cq.cq_size << 16)));
+		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,
+				    (mgtvnic->mgt_cq.cq_number | ((u32)nesdev->ceq_index << 16)));
+
+		if (++cqp_head >= nesdev->cqp.sq_size)
+			cqp_head = 0;
+
+		nesdev->cqp.sq_head = cqp_head;
+		barrier();
+
+		/* Ring doorbell (2 WQEs) */
+		nes_write32(nesdev->regs + NES_WQE_ALLOC, 0x02800000 | nesdev->cqp.qp_id);
+
+		spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
+		nes_debug(NES_DBG_SHUTDOWN, "Waiting for CQP, cqp_head=%u, cqp.sq_head=%u,"
+			  " cqp.sq_tail=%u, cqp.sq_size=%u\n",
+			  cqp_head, nesdev->cqp.sq_head,
+			  nesdev->cqp.sq_tail, nesdev->cqp.sq_size);
+
+		ret = wait_event_timeout(nesdev->cqp.waitq, (nesdev->cqp.sq_tail == cqp_head),
+					 NES_EVENT_TIMEOUT);
+
+		nes_debug(NES_DBG_SHUTDOWN, "Destroy MGT QP returned, wait_event_timeout ret = %u, cqp_head=%u,"
+			  " cqp.sq_head=%u, cqp.sq_tail=%u\n",
+			  ret, cqp_head, nesdev->cqp.sq_head, nesdev->cqp.sq_tail);
+		if (!ret)
+			nes_debug(NES_DBG_SHUTDOWN, "MGT QP%u destroy timeout expired\n",
+				  mgtvnic->mgt.qp_id);
+
+		nesvnic->mgtvnic[i] = NULL;
+	}
+
+	if (nesvnic->mgt_vbase) {
+		pci_free_consistent(nesdev->pcidev, nesvnic->mgt_mem_size, nesvnic->mgt_vbase,
+				    nesvnic->mgt_pbase);
+		nesvnic->mgt_vbase = NULL;
+		nesvnic->mgt_pbase = 0;
+	}
+
+	kfree(first_mgtvnic);
+}
diff --git a/drivers/infiniband/hw/nes/nes_mgt.h b/drivers/infiniband/hw/nes/nes_mgt.h
new file mode 100644
index 0000000..8c8af25
--- /dev/null
+++ b/drivers/infiniband/hw/nes/nes_mgt.h
@@ -0,0 +1,97 @@
+/*
+* Copyright (c) 2010 Intel-NE, Inc.  All rights reserved.
+*
+* This software is available to you under a choice of one of two
+* licenses.  You may choose to be licensed under the terms of the GNU
+* General Public License (GPL) Version 2, available from the file
+* COPYING in the main directory of this source tree, or the
+* OpenIB.org BSD license below:
+*
+*     Redistribution and use in source and binary forms, with or
+*     without modification, are permitted provided that the following
+*     conditions are met:
+*
+*      - Redistributions of source code must retain the above
+*        copyright notice, this list of conditions and the following
+*        disclaimer.
+*
+*      - Redistributions in binary form must reproduce the above
+*        copyright notice, this list of conditions and the following
+*        disclaimer in the documentation and/or other materials
+*        provided with the distribution.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*/
+
+#ifndef __NES_MGT_H
+#define __NES_MGT_H
+
+#define MPA_FRAMING 6	/* length is 2 bytes, crc is 4 bytes */
+
+int nes_init_mgt_qp(struct nes_device *nesdev, struct net_device *netdev, struct nes_vnic *nesvnic);
+void nes_queue_mgt_skbs(struct sk_buff *skb, struct nes_vnic *nesvnic, struct nes_qp *nesqp);
+void nes_destroy_mgt(struct nes_vnic *nesvnic);
+void nes_destroy_pau_qp(struct nes_device *nesdev, struct nes_qp *nesqp);
+
+struct nes_hw_mgt {
+	struct nes_hw_nic_rq_wqe *rq_vbase;	/* virtual address of rq */
+	dma_addr_t rq_pbase;			/* PCI memory for host rings */
+	struct sk_buff *rx_skb[NES_NIC_WQ_SIZE];
+	u16 qp_id;
+	u16 sq_head;
+	u16 rq_head;
+	u16 rq_tail;
+	u16 rq_size;
+	u8 replenishing_rq;
+	u8 reserved;
+	spinlock_t rq_lock;
+};
+
+struct nes_vnic_mgt {
+	struct nes_vnic        *nesvnic;
+	struct nes_hw_mgt      mgt;
+	struct nes_hw_nic_cq   mgt_cq;
+	atomic_t               rx_skbs_needed;
+	struct timer_list      rq_wqes_timer;
+	atomic_t               rx_skb_timer_running;
+};
+
+#define MAX_FPDU_FRAGS 4
+struct pau_fpdu_frag {
+	struct sk_buff         *skb;
+	u64                    physaddr;
+	u32                    frag_len;
+	bool                   cmplt;
+};
+
+struct pau_fpdu_info {
+	struct nes_qp          *nesqp;
+	struct nes_cqp_request *cqp_request;
+	void                   *hdr_vbase;
+	dma_addr_t             hdr_pbase;
+	int                    hdr_len;
+	u16                    data_len;
+	u16                    frag_cnt;
+	struct pau_fpdu_frag   frags[MAX_FPDU_FRAGS];
+};
+
+enum pau_qh_state {
+	PAU_DEL_QH,
+	PAU_ADD_LB_QH,
+	PAU_READY
+};
+
+struct pau_qh_chg {
+	struct nes_device *nesdev;
+	struct nes_vnic *nesvnic;
+	struct nes_qp *nesqp;
+};
+
+#endif          /* __NES_MGT_H */
diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c
index 47b2ee4..c00d2f3 100644
--- a/drivers/infiniband/hw/nes/nes_nic.c
+++ b/drivers/infiniband/hw/nes/nes_nic.c
@@ -1091,6 +1091,8 @@ static const char nes_ethtool_stringset[][ETH_GSTRING_LEN] = {
 	"LRO aggregated",
 	"LRO flushed",
 	"LRO no_desc",
+	"PAU CreateQPs",
+	"PAU DestroyQPs",
 };
 #define NES_ETHTOOL_STAT_COUNT  ARRAY_SIZE(nes_ethtool_stringset)
 
@@ -1306,6 +1308,8 @@ static void nes_netdev_get_ethtool_stats(struct net_device *netdev,
 	target_stat_values[++index] = nesvnic->lro_mgr.stats.aggregated;
 	target_stat_values[++index] = nesvnic->lro_mgr.stats.flushed;
 	target_stat_values[++index] = nesvnic->lro_mgr.stats.no_desc;
+	target_stat_values[++index] = atomic_read(&pau_qps_created);
+	target_stat_values[++index] = atomic_read(&pau_qps_destroyed);
 }
 
 /**
diff --git a/drivers/infiniband/hw/nes/nes_utils.c b/drivers/infiniband/hw/nes/nes_utils.c
index f9c417c..cd10968 100644
--- a/drivers/infiniband/hw/nes/nes_utils.c
+++ b/drivers/infiniband/hw/nes/nes_utils.c
@@ -51,13 +51,34 @@
 
 #include "nes.h"
 
-
-
 static u16 nes_read16_eeprom(void __iomem *addr, u16 offset);
 
 u32 mh_detected;
 u32 mh_pauses_sent;
 
+u32 nes_set_pau(struct nes_device *nesdev)
+{
+	u32 ret = 0;
+	u32 counter;
+
+	nes_write_indexed(nesdev, NES_IDX_GPR2, NES_ENABLE_PAU);
+	nes_write_indexed(nesdev, NES_IDX_GPR_TRIGGER, 1);
+
+	for (counter = 0; counter < NES_PAU_COUNTER; counter++) {
+		udelay(30);
+		if (!nes_read_indexed(nesdev, NES_IDX_GPR2)) {
+			printk(KERN_INFO PFX "PAU is supported.\n");
+			break;
+		}
+		nes_write_indexed(nesdev, NES_IDX_GPR_TRIGGER, 1);
+	}
+	if (counter == NES_PAU_COUNTER) {
+		printk(KERN_INFO PFX "PAU is not supported.\n");
+		return -EPERM;
+	}
+	return ret;
+}
+
 /**
  * nes_read_eeprom_values -
  */
@@ -187,6 +208,11 @@ int nes_read_eeprom_values(struct nes_device *nesdev, struct nes_adapter *nesada
 		if (((major_ver == 3) && (minor_ver >= 16)) || (major_ver > 3))
 			nesadapter->send_term_ok = 1;
 
+		if (nes_drv_opt & NES_DRV_OPT_ENABLE_PAU) {
+			if (!nes_set_pau(nesdev))
+				nesadapter->allow_unaligned_fpdus = 1;
+		}
+
 		nesadapter->firmware_version = (((u32)(u8)(eeprom_data>>8))  <<  16) +
 				(u32)((u8)eeprom_data);
 
@@ -594,6 +620,7 @@ void nes_put_cqp_request(struct nes_device *nesdev,
 		nes_free_cqp_request(nesdev, cqp_request);
 }
 
+
 /**
  * nes_post_cqp_request
  */
@@ -604,6 +631,8 @@ void nes_post_cqp_request(struct nes_device *nesdev,
 	unsigned long flags;
 	u32 cqp_head;
 	u64 u64temp;
+	u32 opcode;
+	int ctx_index = NES_CQP_WQE_COMP_CTX_LOW_IDX;
 
 	spin_lock_irqsave(&nesdev->cqp.lock, flags);
 
@@ -614,17 +643,20 @@ void nes_post_cqp_request(struct nes_device *nesdev,
 		nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;
 		cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
 		memcpy(cqp_wqe, &cqp_request->cqp_wqe, sizeof(*cqp_wqe));
+		opcode = le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX]);
+		if ((opcode & NES_CQP_OPCODE_MASK) == NES_CQP_DOWNLOAD_SEGMENT)
+			ctx_index = NES_CQP_WQE_DL_COMP_CTX_LOW_IDX;
 		barrier();
 		u64temp = (unsigned long)cqp_request;
-		set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_COMP_SCRATCH_LOW_IDX,
-				    u64temp);
+		set_wqe_64bit_value(cqp_wqe->wqe_words, ctx_index, u64temp);
 		nes_debug(NES_DBG_CQP, "CQP request (opcode 0x%02X), line 1 = 0x%08X put on CQPs SQ,"
-				" request = %p, cqp_head = %u, cqp_tail = %u, cqp_size = %u,"
-				" waiting = %d, refcount = %d.\n",
-				le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f,
-				le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX]), cqp_request,
-				nesdev->cqp.sq_head, nesdev->cqp.sq_tail, nesdev->cqp.sq_size,
-				cqp_request->waiting, atomic_read(&cqp_request->refcount));
+			" request = %p, cqp_head = %u, cqp_tail = %u, cqp_size = %u,"
+			" waiting = %d, refcount = %d.\n",
+			opcode & NES_CQP_OPCODE_MASK,
+			le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX]), cqp_request,
+			nesdev->cqp.sq_head, nesdev->cqp.sq_tail, nesdev->cqp.sq_size,
+			cqp_request->waiting, atomic_read(&cqp_request->refcount));
+
 		barrier();
 
 		/* Ring doorbell (1 WQEs) */
@@ -645,7 +677,6 @@ void nes_post_cqp_request(struct nes_device *nesdev,
 	return;
 }
 
-
 /**
  * nes_arp_table
  */
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
index 9f2f7d4..5095bc4 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.c
+++ b/drivers/infiniband/hw/nes/nes_verbs.c
@@ -1458,7 +1458,7 @@ static int nes_destroy_qp(struct ib_qp *ibqp)
 	struct ib_qp_attr attr;
 	struct iw_cm_id *cm_id;
 	struct iw_cm_event cm_event;
-	int ret;
+	int ret = 0;
 
 	atomic_inc(&sw_qps_destroyed);
 	nesqp->destroyed = 1;
@@ -1511,7 +1511,6 @@ static int nes_destroy_qp(struct ib_qp *ibqp)
 		if ((nesqp->nesrcq) && (nesqp->nesrcq != nesqp->nesscq))
 			nes_clean_cq(nesqp, nesqp->nesrcq);
 	}
-
 	nes_rem_ref(&nesqp->ibqp);
 	return 0;
 }
@@ -2338,8 +2337,10 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
 
 	skip_pages = ((u32)region->offset) >> 12;
 
-	if (ib_copy_from_udata(&req, udata, sizeof(req)))
+	if (ib_copy_from_udata(&req, udata, sizeof(req))) {
+		ib_umem_release(region);
 		return ERR_PTR(-EFAULT);
+	}
 	nes_debug(NES_DBG_MR, "Memory Registration type = %08X.\n", req.reg_type);
 
 	switch (req.reg_type) {
@@ -2631,6 +2632,7 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
 			return &nesmr->ibmr;
 	}
 
+	ib_umem_release(region);
 	return ERR_PTR(-ENOSYS);
 }
 
diff --git a/drivers/infiniband/hw/nes/nes_verbs.h b/drivers/infiniband/hw/nes/nes_verbs.h
index 2df9993e..fe6b6e9 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.h
+++ b/drivers/infiniband/hw/nes/nes_verbs.h
@@ -139,7 +139,8 @@ struct nes_qp {
 	struct nes_cq         *nesrcq;
 	struct nes_pd         *nespd;
 	void *cm_node; /* handle of the node this QP is associated with */
-	struct ietf_mpa_frame *ietf_frame;
+	void                  *ietf_frame;
+	u8                    ietf_frame_size;
 	dma_addr_t            ietf_frame_pbase;
 	struct ib_mr          *lsmm_mr;
 	struct nes_hw_qp      hwqp;
@@ -154,6 +155,7 @@ struct nes_qp {
 	u32                   mmap_sq_db_index;
 	u32                   mmap_rq_db_index;
 	spinlock_t            lock;
+	spinlock_t            pau_lock;
 	struct nes_qp_context *nesqp_context;
 	dma_addr_t            nesqp_context_pbase;
 	void	              *pbl_vbase;
@@ -161,6 +163,8 @@ struct nes_qp {
 	struct page           *page;
 	struct timer_list     terminate_timer;
 	enum ib_event_type    terminate_eventtype;
+	struct sk_buff_head   pau_list;
+	u32                   pau_rcv_nxt;
 	u16                   active_conn:1;
 	u16                   skip_lsmm:1;
 	u16                   user_mode:1;
@@ -168,7 +172,8 @@ struct nes_qp {
 	u16                   flush_issued:1;
 	u16                   destroyed:1;
 	u16                   sig_all:1;
-	u16                   rsvd:9;
+	u16                   pau_mode:1;
+	u16                   rsvd:8;
 	u16                   private_data_len;
 	u16                   term_sq_flush_code;
 	u16                   term_rq_flush_code;
@@ -176,5 +181,8 @@ struct nes_qp {
 	u8                    hw_tcp_state;
 	u8                    term_flags;
 	u8                    sq_kmapped;
+	u8                    pau_busy;
+	u8                    pau_pending;
+	u8                    pau_state;
 };
 #endif			/* NES_VERBS_H */
diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h
index c9624ea..b881bdc 100644
--- a/drivers/infiniband/hw/qib/qib.h
+++ b/drivers/infiniband/hw/qib/qib.h
@@ -171,7 +171,9 @@ struct qib_ctxtdata {
 	/* how many alloc_pages() chunks in rcvegrbuf_pages */
 	u32 rcvegrbuf_chunks;
 	/* how many egrbufs per chunk */
-	u32 rcvegrbufs_perchunk;
+	u16 rcvegrbufs_perchunk;
+	/* ilog2 of above */
+	u16 rcvegrbufs_perchunk_shift;
 	/* order for rcvegrbuf_pages */
 	size_t rcvegrbuf_size;
 	/* rcvhdrq size (for freeing) */
@@ -221,6 +223,9 @@ struct qib_ctxtdata {
 	/* ctxt rcvhdrq head offset */
 	u32 head;
 	u32 pkt_count;
+	/* lookaside fields */
+	struct qib_qp *lookaside_qp;
+	u32 lookaside_qpn;
 	/* QPs waiting for context processing */
 	struct list_head qp_wait_list;
 };
@@ -807,6 +812,10 @@ struct qib_devdata {
 	 * supports, less gives more pio bufs/ctxt, etc.
 	 */
 	u32 cfgctxts;
+	/*
+	 * number of ctxts available for PSM open
+	 */
+	u32 freectxts;
 
 	/*
 	 * hint that we should update pioavailshadow before
@@ -936,7 +945,9 @@ struct qib_devdata {
 	/* chip address space used by 4k pio buffers */
 	u32 align4k;
 	/* size of each rcvegrbuffer */
-	u32 rcvegrbufsize;
+	u16 rcvegrbufsize;
+	/* log2 of above */
+	u16 rcvegrbufsize_shift;
 	/* localbus width (1, 2,4,8,16,32) from config space  */
 	u32 lbus_width;
 	/* localbus speed in MHz */
diff --git a/drivers/infiniband/hw/qib/qib_driver.c b/drivers/infiniband/hw/qib/qib_driver.c
index 23e584f..9a9047f 100644
--- a/drivers/infiniband/hw/qib/qib_driver.c
+++ b/drivers/infiniband/hw/qib/qib_driver.c
@@ -279,10 +279,10 @@ bail:
  */
 static inline void *qib_get_egrbuf(const struct qib_ctxtdata *rcd, u32 etail)
 {
-	const u32 chunk = etail / rcd->rcvegrbufs_perchunk;
-	const u32 idx =  etail % rcd->rcvegrbufs_perchunk;
+	const u32 chunk = etail >> rcd->rcvegrbufs_perchunk_shift;
+	const u32 idx =  etail & ((u32)rcd->rcvegrbufs_perchunk - 1);
 
-	return rcd->rcvegrbuf[chunk] + idx * rcd->dd->rcvegrbufsize;
+	return rcd->rcvegrbuf[chunk] + (idx << rcd->dd->rcvegrbufsize_shift);
 }
 
 /*
@@ -310,7 +310,6 @@ static u32 qib_rcv_hdrerr(struct qib_ctxtdata *rcd, struct qib_pportdata *ppd,
 		u32 opcode;
 		u32 psn;
 		int diff;
-		unsigned long flags;
 
 		/* Sanity check packet */
 		if (tlen < 24)
@@ -365,7 +364,6 @@ static u32 qib_rcv_hdrerr(struct qib_ctxtdata *rcd, struct qib_pportdata *ppd,
 
 			switch (qp->ibqp.qp_type) {
 			case IB_QPT_RC:
-				spin_lock_irqsave(&qp->s_lock, flags);
 				ruc_res =
 					qib_ruc_check_hdr(
 						ibp, hdr,
@@ -373,11 +371,8 @@ static u32 qib_rcv_hdrerr(struct qib_ctxtdata *rcd, struct qib_pportdata *ppd,
 						qp,
 						be32_to_cpu(ohdr->bth[0]));
 				if (ruc_res) {
-					spin_unlock_irqrestore(&qp->s_lock,
-							       flags);
 					goto unlock;
 				}
-				spin_unlock_irqrestore(&qp->s_lock, flags);
 
 				/* Only deal with RDMA Writes for now */
 				if (opcode <
@@ -547,6 +542,15 @@ move_along:
 			updegr = 0;
 		}
 	}
+	/*
+	 * Notify qib_destroy_qp() if it is waiting
+	 * for lookaside_qp to finish.
+	 */
+	if (rcd->lookaside_qp) {
+		if (atomic_dec_and_test(&rcd->lookaside_qp->refcount))
+			wake_up(&rcd->lookaside_qp->wait);
+		rcd->lookaside_qp = NULL;
+	}
 
 	rcd->head = l;
 	rcd->pkt_count += i;
diff --git a/drivers/infiniband/hw/qib/qib_file_ops.c b/drivers/infiniband/hw/qib/qib_file_ops.c
index 2625303..7763366 100644
--- a/drivers/infiniband/hw/qib/qib_file_ops.c
+++ b/drivers/infiniband/hw/qib/qib_file_ops.c
@@ -1284,6 +1284,7 @@ static int setup_ctxt(struct qib_pportdata *ppd, int ctxt,
 	strlcpy(rcd->comm, current->comm, sizeof(rcd->comm));
 	ctxt_fp(fp) = rcd;
 	qib_stats.sps_ctxts++;
+	dd->freectxts++;
 	ret = 0;
 	goto bail;
 
@@ -1792,6 +1793,7 @@ static int qib_close(struct inode *in, struct file *fp)
 		if (dd->pageshadow)
 			unlock_expected_tids(rcd);
 		qib_stats.sps_ctxts--;
+		dd->freectxts--;
 	}
 
 	mutex_unlock(&qib_mutex);
diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c
index d8ca0a0..781a802 100644
--- a/drivers/infiniband/hw/qib/qib_iba6120.c
+++ b/drivers/infiniband/hw/qib/qib_iba6120.c
@@ -3273,6 +3273,8 @@ static int init_6120_variables(struct qib_devdata *dd)
 	/* we always allocate at least 2048 bytes for eager buffers */
 	ret = ib_mtu_enum_to_int(qib_ibmtu);
 	dd->rcvegrbufsize = ret != -1 ? max(ret, 2048) : QIB_DEFAULT_MTU;
+	BUG_ON(!is_power_of_2(dd->rcvegrbufsize));
+	dd->rcvegrbufsize_shift = ilog2(dd->rcvegrbufsize);
 
 	qib_6120_tidtemplate(dd);
 
diff --git a/drivers/infiniband/hw/qib/qib_iba7220.c b/drivers/infiniband/hw/qib/qib_iba7220.c
index e1f9474..3f1d562 100644
--- a/drivers/infiniband/hw/qib/qib_iba7220.c
+++ b/drivers/infiniband/hw/qib/qib_iba7220.c
@@ -4085,6 +4085,8 @@ static int qib_init_7220_variables(struct qib_devdata *dd)
 	/* we always allocate at least 2048 bytes for eager buffers */
 	ret = ib_mtu_enum_to_int(qib_ibmtu);
 	dd->rcvegrbufsize = ret != -1 ? max(ret, 2048) : QIB_DEFAULT_MTU;
+	BUG_ON(!is_power_of_2(dd->rcvegrbufsize));
+	dd->rcvegrbufsize_shift = ilog2(dd->rcvegrbufsize);
 
 	qib_7220_tidtemplate(dd);
 
diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c
index 5ea9ece..efd0a11 100644
--- a/drivers/infiniband/hw/qib/qib_iba7322.c
+++ b/drivers/infiniband/hw/qib/qib_iba7322.c
@@ -2310,12 +2310,15 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd)
 	val = ppd->cpspec->ibcctrl_a | (QLOGIC_IB_IBCC_LINKINITCMD_DISABLE <<
 		QLOGIC_IB_IBCC_LINKINITCMD_SHIFT);
 
+	ppd->cpspec->ibcctrl_a = val;
 	/*
 	 * Reset the PCS interface to the serdes (and also ibc, which is still
 	 * in reset from above).  Writes new value of ibcctrl_a as last step.
 	 */
 	qib_7322_mini_pcs_reset(ppd);
 	qib_write_kreg(dd, kr_scratch, 0ULL);
+	/* clear the linkinit cmds */
+	ppd->cpspec->ibcctrl_a &= ~SYM_MASK(IBCCtrlA_0, LinkInitCmd);
 
 	if (!ppd->cpspec->ibcctrl_b) {
 		unsigned lse = ppd->link_speed_enabled;
@@ -2387,11 +2390,6 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd)
 	qib_write_kreg_port(ppd, krp_rcvctrl, ppd->p_rcvctrl);
 	spin_unlock_irqrestore(&dd->cspec->rcvmod_lock, flags);
 
-	/* Hold the link state machine for mezz boards */
-	if (IS_QMH(dd) || IS_QME(dd))
-		qib_set_ib_7322_lstate(ppd, 0,
-				       QLOGIC_IB_IBCC_LINKINITCMD_DISABLE);
-
 	/* Also enable IBSTATUSCHG interrupt.  */
 	val = qib_read_kreg_port(ppd, krp_errmask);
 	qib_write_kreg_port(ppd, krp_errmask,
@@ -2853,9 +2851,8 @@ static irqreturn_t qib_7322intr(int irq, void *data)
 		for (i = 0; i < dd->first_user_ctxt; i++) {
 			if (ctxtrbits & rmask) {
 				ctxtrbits &= ~rmask;
-				if (dd->rcd[i]) {
+				if (dd->rcd[i])
 					qib_kreceive(dd->rcd[i], NULL, &npkts);
-				}
 			}
 			rmask <<= 1;
 		}
@@ -5230,6 +5227,8 @@ static int qib_7322_ib_updown(struct qib_pportdata *ppd, int ibup, u64 ibcs)
 				     QIBL_IB_AUTONEG_INPROG)))
 			set_7322_ibspeed_fast(ppd, ppd->link_speed_enabled);
 		if (!(ppd->lflags & QIBL_IB_AUTONEG_INPROG)) {
+			struct qib_qsfp_data *qd =
+				&ppd->cpspec->qsfp_data;
 			/* unlock the Tx settings, speed may change */
 			qib_write_kreg_port(ppd, krp_tx_deemph_override,
 				SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
@@ -5237,6 +5236,12 @@ static int qib_7322_ib_updown(struct qib_pportdata *ppd, int ibup, u64 ibcs)
 			qib_cancel_sends(ppd);
 			/* on link down, ensure sane pcs state */
 			qib_7322_mini_pcs_reset(ppd);
+			/* schedule the qsfp refresh which should turn the link
+			   off */
+			if (ppd->dd->flags & QIB_HAS_QSFP) {
+				qd->t_insert = get_jiffies_64();
+				schedule_work(&qd->work);
+			}
 			spin_lock_irqsave(&ppd->sdma_lock, flags);
 			if (__qib_sdma_running(ppd))
 				__qib_sdma_process_event(ppd,
@@ -5587,43 +5592,79 @@ static void qsfp_7322_event(struct work_struct *work)
 	struct qib_qsfp_data *qd;
 	struct qib_pportdata *ppd;
 	u64 pwrup;
+	unsigned long flags;
 	int ret;
 	u32 le2;
 
 	qd = container_of(work, struct qib_qsfp_data, work);
 	ppd = qd->ppd;
-	pwrup = qd->t_insert + msecs_to_jiffies(QSFP_PWR_LAG_MSEC);
+	pwrup = qd->t_insert +
+		msecs_to_jiffies(QSFP_PWR_LAG_MSEC - QSFP_MODPRS_LAG_MSEC);
 
-	/*
-	 * Some QSFP's not only do not respond until the full power-up
-	 * time, but may behave badly if we try. So hold off responding
-	 * to insertion.
-	 */
-	while (1) {
-		u64 now = get_jiffies_64();
-		if (time_after64(now, pwrup))
-			break;
-		msleep(20);
-	}
-	ret = qib_refresh_qsfp_cache(ppd, &qd->cache);
-	/*
-	 * Need to change LE2 back to defaults if we couldn't
-	 * read the cable type (to handle cable swaps), so do this
-	 * even on failure to read cable information.  We don't
-	 * get here for QME, so IS_QME check not needed here.
-	 */
-	if (!ret && !ppd->dd->cspec->r1) {
-		if (QSFP_IS_ACTIVE_FAR(qd->cache.tech))
-			le2 = LE2_QME;
-		else if (qd->cache.atten[1] >= qib_long_atten &&
-			 QSFP_IS_CU(qd->cache.tech))
-			le2 = LE2_5m;
-		else
+	/* Delay for 20 msecs to allow ModPrs resistor to setup */
+	mdelay(QSFP_MODPRS_LAG_MSEC);
+
+	if (!qib_qsfp_mod_present(ppd)) {
+		ppd->cpspec->qsfp_data.modpresent = 0;
+		/* Set the physical link to disabled */
+		qib_set_ib_7322_lstate(ppd, 0,
+				       QLOGIC_IB_IBCC_LINKINITCMD_DISABLE);
+		spin_lock_irqsave(&ppd->lflags_lock, flags);
+		ppd->lflags &= ~QIBL_LINKV;
+		spin_unlock_irqrestore(&ppd->lflags_lock, flags);
+	} else {
+		/*
+		 * Some QSFP's not only do not respond until the full power-up
+		 * time, but may behave badly if we try. So hold off responding
+		 * to insertion.
+		 */
+		while (1) {
+			u64 now = get_jiffies_64();
+			if (time_after64(now, pwrup))
+				break;
+			msleep(20);
+		}
+
+		ret = qib_refresh_qsfp_cache(ppd, &qd->cache);
+
+		/*
+		 * Need to change LE2 back to defaults if we couldn't
+		 * read the cable type (to handle cable swaps), so do this
+		 * even on failure to read cable information.  We don't
+		 * get here for QME, so IS_QME check not needed here.
+		 */
+		if (!ret && !ppd->dd->cspec->r1) {
+			if (QSFP_IS_ACTIVE_FAR(qd->cache.tech))
+				le2 = LE2_QME;
+			else if (qd->cache.atten[1] >= qib_long_atten &&
+				 QSFP_IS_CU(qd->cache.tech))
+				le2 = LE2_5m;
+			else
+				le2 = LE2_DEFAULT;
+		} else
 			le2 = LE2_DEFAULT;
-	} else
-		le2 = LE2_DEFAULT;
-	ibsd_wr_allchans(ppd, 13, (le2 << 7), BMASK(9, 7));
-	init_txdds_table(ppd, 0);
+		ibsd_wr_allchans(ppd, 13, (le2 << 7), BMASK(9, 7));
+		/*
+		 * We always change parameteters, since we can choose
+		 * values for cables without eeproms, and the cable may have
+		 * changed from a cable with full or partial eeprom content
+		 * to one with partial or no content.
+		 */
+		init_txdds_table(ppd, 0);
+		/* The physical link is being re-enabled only when the
+		 * previous state was DISABLED and the VALID bit is not
+		 * set. This should only happen when  the cable has been
+		 * physically pulled. */
+		if (!ppd->cpspec->qsfp_data.modpresent &&
+		    (ppd->lflags & (QIBL_LINKV | QIBL_IB_LINK_DISABLED))) {
+			ppd->cpspec->qsfp_data.modpresent = 1;
+			qib_set_ib_7322_lstate(ppd, 0,
+				QLOGIC_IB_IBCC_LINKINITCMD_SLEEP);
+			spin_lock_irqsave(&ppd->lflags_lock, flags);
+			ppd->lflags |= QIBL_LINKV;
+			spin_unlock_irqrestore(&ppd->lflags_lock, flags);
+		}
+	}
 }
 
 /*
@@ -5727,7 +5768,8 @@ static void set_no_qsfp_atten(struct qib_devdata *dd, int change)
 			/* now change the IBC and serdes, overriding generic */
 			init_txdds_table(ppd, 1);
 			/* Re-enable the physical state machine on mezz boards
-			 * now that the correct settings have been set. */
+			 * now that the correct settings have been set.
+			 * QSFP boards are handles by the QSFP event handler */
 			if (IS_QMH(dd) || IS_QME(dd))
 				qib_set_ib_7322_lstate(ppd, 0,
 					    QLOGIC_IB_IBCC_LINKINITCMD_SLEEP);
@@ -6205,6 +6247,8 @@ static int qib_init_7322_variables(struct qib_devdata *dd)
 
 	/* we always allocate at least 2048 bytes for eager buffers */
 	dd->rcvegrbufsize = max(mtu, 2048);
+	BUG_ON(!is_power_of_2(dd->rcvegrbufsize));
+	dd->rcvegrbufsize_shift = ilog2(dd->rcvegrbufsize);
 
 	qib_7322_tidtemplate(dd);
 
@@ -7147,7 +7191,8 @@ static void find_best_ent(struct qib_pportdata *ppd,
 		}
 	}
 
-	/* Lookup serdes setting by cable type and attenuation */
+	/* Active cables don't have attenuation so we only set SERDES
+	 * settings to account for the attenuation of the board traces. */
 	if (!override && QSFP_IS_ACTIVE(qd->tech)) {
 		*sdr_dds = txdds_sdr + ppd->dd->board_atten;
 		*ddr_dds = txdds_ddr + ppd->dd->board_atten;
@@ -7464,12 +7509,6 @@ static int serdes_7322_init_new(struct qib_pportdata *ppd)
 	u32 le_val, rxcaldone;
 	int chan, chan_done = (1 << SERDES_CHANS) - 1;
 
-	/*
-	 * Initialize the Tx DDS tables.  Also done every QSFP event,
-	 * for adapters with QSFP
-	 */
-	init_txdds_table(ppd, 0);
-
 	/* Clear cmode-override, may be set from older driver */
 	ahb_mod(ppd->dd, IBSD(ppd->hw_pidx), 5, 10, 0 << 14, 1 << 14);
 
@@ -7655,6 +7694,12 @@ static int serdes_7322_init_new(struct qib_pportdata *ppd)
 	/* VGA output common mode */
 	ibsd_wr_allchans(ppd, 12, (3 << 2), BMASK(3, 2));
 
+	/*
+	 * Initialize the Tx DDS tables.  Also done every QSFP event,
+	 * for adapters with QSFP
+	 */
+	init_txdds_table(ppd, 0);
+
 	return 0;
 }
 
diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c
index a01f3fc..b093a0b 100644
--- a/drivers/infiniband/hw/qib/qib_init.c
+++ b/drivers/infiniband/hw/qib/qib_init.c
@@ -183,6 +183,9 @@ struct qib_ctxtdata *qib_create_ctxtdata(struct qib_pportdata *ppd, u32 ctxt)
 		rcd->rcvegrbuf_chunks = (rcd->rcvegrcnt +
 			rcd->rcvegrbufs_perchunk - 1) /
 			rcd->rcvegrbufs_perchunk;
+		BUG_ON(!is_power_of_2(rcd->rcvegrbufs_perchunk));
+		rcd->rcvegrbufs_perchunk_shift =
+			ilog2(rcd->rcvegrbufs_perchunk);
 	}
 	return rcd;
 }
@@ -398,6 +401,7 @@ static void enable_chip(struct qib_devdata *dd)
 		if (rcd)
 			dd->f_rcvctrl(rcd->ppd, rcvmask, i);
 	}
+	dd->freectxts = dd->cfgctxts - dd->first_user_ctxt;
 }
 
 static void verify_interrupt(unsigned long opaque)
@@ -581,10 +585,6 @@ int qib_init(struct qib_devdata *dd, int reinit)
 			continue;
 		}
 
-		/* let link come up, and enable IBC */
-		spin_lock_irqsave(&ppd->lflags_lock, flags);
-		ppd->lflags &= ~QIBL_IB_LINK_DISABLED;
-		spin_unlock_irqrestore(&ppd->lflags_lock, flags);
 		portok++;
 	}
 
diff --git a/drivers/infiniband/hw/qib/qib_qp.c b/drivers/infiniband/hw/qib/qib_qp.c
index e16751f..7e7e16f 100644
--- a/drivers/infiniband/hw/qib/qib_qp.c
+++ b/drivers/infiniband/hw/qib/qib_qp.c
@@ -34,6 +34,7 @@
 
 #include <linux/err.h>
 #include <linux/vmalloc.h>
+#include <linux/jhash.h>
 
 #include "qib.h"
 
@@ -204,6 +205,13 @@ static void free_qpn(struct qib_qpn_table *qpt, u32 qpn)
 		clear_bit(qpn & BITS_PER_PAGE_MASK, map->page);
 }
 
+static inline unsigned qpn_hash(struct qib_ibdev *dev, u32 qpn)
+{
+	return jhash_1word(qpn, dev->qp_rnd) &
+		(dev->qp_table_size - 1);
+}
+
+
 /*
  * Put the QP into the hash table.
  * The hash table holds a reference to the QP.
@@ -211,22 +219,23 @@ static void free_qpn(struct qib_qpn_table *qpt, u32 qpn)
 static void insert_qp(struct qib_ibdev *dev, struct qib_qp *qp)
 {
 	struct qib_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num);
-	unsigned n = qp->ibqp.qp_num % dev->qp_table_size;
 	unsigned long flags;
+	unsigned n = qpn_hash(dev, qp->ibqp.qp_num);
 
 	spin_lock_irqsave(&dev->qpt_lock, flags);
+	atomic_inc(&qp->refcount);
 
 	if (qp->ibqp.qp_num == 0)
-		ibp->qp0 = qp;
+		rcu_assign_pointer(ibp->qp0, qp);
 	else if (qp->ibqp.qp_num == 1)
-		ibp->qp1 = qp;
+		rcu_assign_pointer(ibp->qp1, qp);
 	else {
 		qp->next = dev->qp_table[n];
-		dev->qp_table[n] = qp;
+		rcu_assign_pointer(dev->qp_table[n], qp);
 	}
-	atomic_inc(&qp->refcount);
 
 	spin_unlock_irqrestore(&dev->qpt_lock, flags);
+	synchronize_rcu();
 }
 
 /*
@@ -236,29 +245,32 @@ static void insert_qp(struct qib_ibdev *dev, struct qib_qp *qp)
 static void remove_qp(struct qib_ibdev *dev, struct qib_qp *qp)
 {
 	struct qib_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num);
-	struct qib_qp *q, **qpp;
+	unsigned n = qpn_hash(dev, qp->ibqp.qp_num);
 	unsigned long flags;
 
-	qpp = &dev->qp_table[qp->ibqp.qp_num % dev->qp_table_size];
-
 	spin_lock_irqsave(&dev->qpt_lock, flags);
 
 	if (ibp->qp0 == qp) {
-		ibp->qp0 = NULL;
 		atomic_dec(&qp->refcount);
+		rcu_assign_pointer(ibp->qp0, NULL);
 	} else if (ibp->qp1 == qp) {
-		ibp->qp1 = NULL;
 		atomic_dec(&qp->refcount);
-	} else
+		rcu_assign_pointer(ibp->qp1, NULL);
+	} else {
+		struct qib_qp *q, **qpp;
+
+		qpp = &dev->qp_table[n];
 		for (; (q = *qpp) != NULL; qpp = &q->next)
 			if (q == qp) {
-				*qpp = qp->next;
-				qp->next = NULL;
 				atomic_dec(&qp->refcount);
+				rcu_assign_pointer(*qpp, qp->next);
+				qp->next = NULL;
 				break;
 			}
+	}
 
 	spin_unlock_irqrestore(&dev->qpt_lock, flags);
+	synchronize_rcu();
 }
 
 /**
@@ -280,21 +292,24 @@ unsigned qib_free_all_qps(struct qib_devdata *dd)
 
 		if (!qib_mcast_tree_empty(ibp))
 			qp_inuse++;
-		if (ibp->qp0)
+		rcu_read_lock();
+		if (rcu_dereference(ibp->qp0))
 			qp_inuse++;
-		if (ibp->qp1)
+		if (rcu_dereference(ibp->qp1))
 			qp_inuse++;
+		rcu_read_unlock();
 	}
 
 	spin_lock_irqsave(&dev->qpt_lock, flags);
 	for (n = 0; n < dev->qp_table_size; n++) {
 		qp = dev->qp_table[n];
-		dev->qp_table[n] = NULL;
+		rcu_assign_pointer(dev->qp_table[n], NULL);
 
 		for (; qp; qp = qp->next)
 			qp_inuse++;
 	}
 	spin_unlock_irqrestore(&dev->qpt_lock, flags);
+	synchronize_rcu();
 
 	return qp_inuse;
 }
@@ -309,25 +324,28 @@ unsigned qib_free_all_qps(struct qib_devdata *dd)
  */
 struct qib_qp *qib_lookup_qpn(struct qib_ibport *ibp, u32 qpn)
 {
-	struct qib_ibdev *dev = &ppd_from_ibp(ibp)->dd->verbs_dev;
-	unsigned long flags;
-	struct qib_qp *qp;
+	struct qib_qp *qp = NULL;
 
-	spin_lock_irqsave(&dev->qpt_lock, flags);
+	if (unlikely(qpn <= 1)) {
+		rcu_read_lock();
+		if (qpn == 0)
+			qp = rcu_dereference(ibp->qp0);
+		else
+			qp = rcu_dereference(ibp->qp1);
+	} else {
+		struct qib_ibdev *dev = &ppd_from_ibp(ibp)->dd->verbs_dev;
+		unsigned n = qpn_hash(dev, qpn);
 
-	if (qpn == 0)
-		qp = ibp->qp0;
-	else if (qpn == 1)
-		qp = ibp->qp1;
-	else
-		for (qp = dev->qp_table[qpn % dev->qp_table_size]; qp;
-		     qp = qp->next)
+		rcu_read_lock();
+		for (qp = dev->qp_table[n]; rcu_dereference(qp); qp = qp->next)
 			if (qp->ibqp.qp_num == qpn)
 				break;
+	}
 	if (qp)
-		atomic_inc(&qp->refcount);
+		if (unlikely(!atomic_inc_not_zero(&qp->refcount)))
+			qp = NULL;
 
-	spin_unlock_irqrestore(&dev->qpt_lock, flags);
+	rcu_read_unlock();
 	return qp;
 }
 
@@ -765,8 +783,10 @@ int qib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 		}
 	}
 
-	if (attr_mask & IB_QP_PATH_MTU)
+	if (attr_mask & IB_QP_PATH_MTU) {
 		qp->path_mtu = pmtu;
+		qp->pmtu = ib_mtu_enum_to_int(pmtu);
+	}
 
 	if (attr_mask & IB_QP_RETRY_CNT) {
 		qp->s_retry_cnt = attr->retry_cnt;
@@ -781,8 +801,12 @@ int qib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 	if (attr_mask & IB_QP_MIN_RNR_TIMER)
 		qp->r_min_rnr_timer = attr->min_rnr_timer;
 
-	if (attr_mask & IB_QP_TIMEOUT)
+	if (attr_mask & IB_QP_TIMEOUT) {
 		qp->timeout = attr->timeout;
+		qp->timeout_jiffies =
+			usecs_to_jiffies((4096UL * (1UL << qp->timeout)) /
+				1000UL);
+	}
 
 	if (attr_mask & IB_QP_QKEY)
 		qp->qkey = attr->qkey;
@@ -1013,6 +1037,10 @@ struct ib_qp *qib_create_qp(struct ib_pd *ibpd,
 			ret = ERR_PTR(-ENOMEM);
 			goto bail_swq;
 		}
+		RCU_INIT_POINTER(qp->next, NULL);
+		qp->timeout_jiffies =
+			usecs_to_jiffies((4096UL * (1UL << qp->timeout)) /
+				1000UL);
 		if (init_attr->srq)
 			sz = 0;
 		else {
diff --git a/drivers/infiniband/hw/qib/qib_qsfp.c b/drivers/infiniband/hw/qib/qib_qsfp.c
index 3374a52..e06c4ed 100644
--- a/drivers/infiniband/hw/qib/qib_qsfp.c
+++ b/drivers/infiniband/hw/qib/qib_qsfp.c
@@ -273,18 +273,12 @@ int qib_refresh_qsfp_cache(struct qib_pportdata *ppd, struct qib_qsfp_cache *cp)
 	int ret;
 	int idx;
 	u16 cks;
-	u32 mask;
 	u8 peek[4];
 
 	/* ensure sane contents on invalid reads, for cable swaps */
 	memset(cp, 0, sizeof(*cp));
 
-	mask = QSFP_GPIO_MOD_PRS_N;
-	if (ppd->hw_pidx)
-		mask <<= QSFP_GPIO_PORT2_SHIFT;
-
-	ret = ppd->dd->f_gpio_mod(ppd->dd, 0, 0, 0);
-	if (ret & mask) {
+	if (!qib_qsfp_mod_present(ppd)) {
 		ret = -ENODEV;
 		goto bail;
 	}
@@ -444,6 +438,19 @@ const char * const qib_qsfp_devtech[16] = {
 
 static const char *pwr_codes = "1.5W2.0W2.5W3.5W";
 
+int qib_qsfp_mod_present(struct qib_pportdata *ppd)
+{
+	u32 mask;
+	int ret;
+
+	mask = QSFP_GPIO_MOD_PRS_N <<
+		(ppd->hw_pidx * QSFP_GPIO_PORT2_SHIFT);
+	ret = ppd->dd->f_gpio_mod(ppd->dd, 0, 0, 0);
+
+	return !((ret & mask) >>
+		 ((ppd->hw_pidx * QSFP_GPIO_PORT2_SHIFT) + 3));
+}
+
 /*
  * Initialize structures that control access to QSFP. Called once per port
  * on cards that support QSFP.
@@ -452,7 +459,6 @@ void qib_qsfp_init(struct qib_qsfp_data *qd,
 		   void (*fevent)(struct work_struct *))
 {
 	u32 mask, highs;
-	int pins;
 
 	struct qib_devdata *dd = qd->ppd->dd;
 
@@ -480,8 +486,7 @@ void qib_qsfp_init(struct qib_qsfp_data *qd,
 		mask <<= QSFP_GPIO_PORT2_SHIFT;
 
 	/* Do not try to wait here. Better to let event handle it */
-	pins = dd->f_gpio_mod(dd, 0, 0, 0);
-	if (pins & mask)
+	if (!qib_qsfp_mod_present(qd->ppd))
 		goto bail;
 	/* We see a module, but it may be unwise to look yet. Just schedule */
 	qd->t_insert = get_jiffies_64();
diff --git a/drivers/infiniband/hw/qib/qib_qsfp.h b/drivers/infiniband/hw/qib/qib_qsfp.h
index c109bbd..46002a9 100644
--- a/drivers/infiniband/hw/qib/qib_qsfp.h
+++ b/drivers/infiniband/hw/qib/qib_qsfp.h
@@ -34,6 +34,7 @@
 
 #define QSFP_DEV 0xA0
 #define QSFP_PWR_LAG_MSEC 2000
+#define QSFP_MODPRS_LAG_MSEC 20
 
 /*
  * Below are masks for various QSFP signals, for Port 1.
@@ -177,10 +178,12 @@ struct qib_qsfp_data {
 	struct work_struct work;
 	struct qib_qsfp_cache cache;
 	u64 t_insert;
+	u8 modpresent;
 };
 
 extern int qib_refresh_qsfp_cache(struct qib_pportdata *ppd,
 				  struct qib_qsfp_cache *cp);
+extern int qib_qsfp_mod_present(struct qib_pportdata *ppd);
 extern void qib_qsfp_init(struct qib_qsfp_data *qd,
 			  void (*fevent)(struct work_struct *));
 extern void qib_qsfp_deinit(struct qib_qsfp_data *qd);
diff --git a/drivers/infiniband/hw/qib/qib_rc.c b/drivers/infiniband/hw/qib/qib_rc.c
index eca0c41..afaf4ac 100644
--- a/drivers/infiniband/hw/qib/qib_rc.c
+++ b/drivers/infiniband/hw/qib/qib_rc.c
@@ -59,8 +59,7 @@ static void start_timer(struct qib_qp *qp)
 	qp->s_flags |= QIB_S_TIMER;
 	qp->s_timer.function = rc_timeout;
 	/* 4.096 usec. * (1 << qp->timeout) */
-	qp->s_timer.expires = jiffies +
-		usecs_to_jiffies((4096UL * (1UL << qp->timeout)) / 1000UL);
+	qp->s_timer.expires = jiffies + qp->timeout_jiffies;
 	add_timer(&qp->s_timer);
 }
 
@@ -239,7 +238,7 @@ int qib_make_rc_req(struct qib_qp *qp)
 	u32 len;
 	u32 bth0;
 	u32 bth2;
-	u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+	u32 pmtu = qp->pmtu;
 	char newreq;
 	unsigned long flags;
 	int ret = 0;
@@ -1519,9 +1518,7 @@ read_middle:
 		 * 4.096 usec. * (1 << qp->timeout)
 		 */
 		qp->s_flags |= QIB_S_TIMER;
-		mod_timer(&qp->s_timer, jiffies +
-			usecs_to_jiffies((4096UL * (1UL << qp->timeout)) /
-					 1000UL));
+		mod_timer(&qp->s_timer, jiffies + qp->timeout_jiffies);
 		if (qp->s_flags & QIB_S_WAIT_ACK) {
 			qp->s_flags &= ~QIB_S_WAIT_ACK;
 			qib_schedule_send(qp);
@@ -1732,7 +1729,7 @@ static int qib_rc_rcv_error(struct qib_other_headers *ohdr,
 		 * same request.
 		 */
 		offset = ((psn - e->psn) & QIB_PSN_MASK) *
-			ib_mtu_enum_to_int(qp->path_mtu);
+			qp->pmtu;
 		len = be32_to_cpu(reth->length);
 		if (unlikely(offset + len != e->rdma_sge.sge_length))
 			goto unlock_done;
@@ -1876,7 +1873,7 @@ void qib_rc_rcv(struct qib_ctxtdata *rcd, struct qib_ib_header *hdr,
 	u32 psn;
 	u32 pad;
 	struct ib_wc wc;
-	u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+	u32 pmtu = qp->pmtu;
 	int diff;
 	struct ib_reth *reth;
 	unsigned long flags;
@@ -1892,10 +1889,8 @@ void qib_rc_rcv(struct qib_ctxtdata *rcd, struct qib_ib_header *hdr,
 	}
 
 	opcode = be32_to_cpu(ohdr->bth[0]);
-	spin_lock_irqsave(&qp->s_lock, flags);
 	if (qib_ruc_check_hdr(ibp, hdr, has_grh, qp, opcode))
-		goto sunlock;
-	spin_unlock_irqrestore(&qp->s_lock, flags);
+		return;
 
 	psn = be32_to_cpu(ohdr->bth[2]);
 	opcode >>= 24;
@@ -1955,8 +1950,6 @@ void qib_rc_rcv(struct qib_ctxtdata *rcd, struct qib_ib_header *hdr,
 		break;
 	}
 
-	memset(&wc, 0, sizeof wc);
-
 	if (qp->state == IB_QPS_RTR && !(qp->r_flags & QIB_R_COMM_EST)) {
 		qp->r_flags |= QIB_R_COMM_EST;
 		if (qp->ibqp.event_handler) {
@@ -2009,16 +2002,19 @@ send_middle:
 			goto rnr_nak;
 		qp->r_rcv_len = 0;
 		if (opcode == OP(SEND_ONLY))
-			goto send_last;
-		/* FALLTHROUGH */
+			goto no_immediate_data;
+		/* FALLTHROUGH for SEND_ONLY_WITH_IMMEDIATE */
 	case OP(SEND_LAST_WITH_IMMEDIATE):
 send_last_imm:
 		wc.ex.imm_data = ohdr->u.imm_data;
 		hdrsize += 4;
 		wc.wc_flags = IB_WC_WITH_IMM;
-		/* FALLTHROUGH */
+		goto send_last;
 	case OP(SEND_LAST):
 	case OP(RDMA_WRITE_LAST):
+no_immediate_data:
+		wc.wc_flags = 0;
+		wc.ex.imm_data = 0;
 send_last:
 		/* Get the number of bytes the message was padded by. */
 		pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
@@ -2051,6 +2047,12 @@ send_last:
 		wc.src_qp = qp->remote_qpn;
 		wc.slid = qp->remote_ah_attr.dlid;
 		wc.sl = qp->remote_ah_attr.sl;
+		/* zero fields that are N/A */
+		wc.vendor_err = 0;
+		wc.pkey_index = 0;
+		wc.dlid_path_bits = 0;
+		wc.port_num = 0;
+		wc.csum_ok = 0;
 		/* Signal completion event if the solicited bit is set. */
 		qib_cq_enter(to_icq(qp->ibqp.recv_cq), &wc,
 			     (ohdr->bth[0] &
@@ -2089,7 +2091,7 @@ send_last:
 		if (opcode == OP(RDMA_WRITE_FIRST))
 			goto send_middle;
 		else if (opcode == OP(RDMA_WRITE_ONLY))
-			goto send_last;
+			goto no_immediate_data;
 		ret = qib_get_rwqe(qp, 1);
 		if (ret < 0)
 			goto nack_op_err;
diff --git a/drivers/infiniband/hw/qib/qib_ruc.c b/drivers/infiniband/hw/qib/qib_ruc.c
index eb78d93..b4b37e4 100644
--- a/drivers/infiniband/hw/qib/qib_ruc.c
+++ b/drivers/infiniband/hw/qib/qib_ruc.c
@@ -260,12 +260,15 @@ static int gid_ok(union ib_gid *gid, __be64 gid_prefix, __be64 id)
 
 /*
  *
- * This should be called with the QP s_lock held.
+ * This should be called with the QP r_lock held.
+ *
+ * The s_lock will be acquired around the qib_migrate_qp() call.
  */
 int qib_ruc_check_hdr(struct qib_ibport *ibp, struct qib_ib_header *hdr,
 		      int has_grh, struct qib_qp *qp, u32 bth0)
 {
 	__be64 guid;
+	unsigned long flags;
 
 	if (qp->s_mig_state == IB_MIG_ARMED && (bth0 & IB_BTH_MIG_REQ)) {
 		if (!has_grh) {
@@ -295,7 +298,9 @@ int qib_ruc_check_hdr(struct qib_ibport *ibp, struct qib_ib_header *hdr,
 		if (be16_to_cpu(hdr->lrh[3]) != qp->alt_ah_attr.dlid ||
 		    ppd_from_ibp(ibp)->port != qp->alt_ah_attr.port_num)
 			goto err;
+		spin_lock_irqsave(&qp->s_lock, flags);
 		qib_migrate_qp(qp);
+		spin_unlock_irqrestore(&qp->s_lock, flags);
 	} else {
 		if (!has_grh) {
 			if (qp->remote_ah_attr.ah_flags & IB_AH_GRH)
diff --git a/drivers/infiniband/hw/qib/qib_srq.c b/drivers/infiniband/hw/qib/qib_srq.c
index c3ec8ef..d623593 100644
--- a/drivers/infiniband/hw/qib/qib_srq.c
+++ b/drivers/infiniband/hw/qib/qib_srq.c
@@ -107,6 +107,11 @@ struct ib_srq *qib_create_srq(struct ib_pd *ibpd,
 	u32 sz;
 	struct ib_srq *ret;
 
+	if (srq_init_attr->srq_type != IB_SRQT_BASIC) {
+		ret = ERR_PTR(-ENOSYS);
+		goto done;
+	}
+
 	if (srq_init_attr->attr.max_sge == 0 ||
 	    srq_init_attr->attr.max_sge > ib_qib_max_srq_sges ||
 	    srq_init_attr->attr.max_wr == 0 ||
diff --git a/drivers/infiniband/hw/qib/qib_sysfs.c b/drivers/infiniband/hw/qib/qib_sysfs.c
index 14d129d..78fbd56 100644
--- a/drivers/infiniband/hw/qib/qib_sysfs.c
+++ b/drivers/infiniband/hw/qib/qib_sysfs.c
@@ -515,8 +515,7 @@ static ssize_t show_nfreectxts(struct device *device,
 	struct qib_devdata *dd = dd_from_dev(dev);
 
 	/* Return the number of free user ports (contexts) available. */
-	return scnprintf(buf, PAGE_SIZE, "%u\n", dd->cfgctxts -
-		dd->first_user_ctxt - (u32)qib_stats.sps_ctxts);
+	return scnprintf(buf, PAGE_SIZE, "%u\n", dd->freectxts);
 }
 
 static ssize_t show_serial(struct device *device,
diff --git a/drivers/infiniband/hw/qib/qib_uc.c b/drivers/infiniband/hw/qib/qib_uc.c
index 32ccf3c..847e7af 100644
--- a/drivers/infiniband/hw/qib/qib_uc.c
+++ b/drivers/infiniband/hw/qib/qib_uc.c
@@ -51,7 +51,7 @@ int qib_make_uc_req(struct qib_qp *qp)
 	u32 hwords;
 	u32 bth0;
 	u32 len;
-	u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+	u32 pmtu = qp->pmtu;
 	int ret = 0;
 
 	spin_lock_irqsave(&qp->s_lock, flags);
@@ -243,13 +243,12 @@ void qib_uc_rcv(struct qib_ibport *ibp, struct qib_ib_header *hdr,
 		int has_grh, void *data, u32 tlen, struct qib_qp *qp)
 {
 	struct qib_other_headers *ohdr;
-	unsigned long flags;
 	u32 opcode;
 	u32 hdrsize;
 	u32 psn;
 	u32 pad;
 	struct ib_wc wc;
-	u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+	u32 pmtu = qp->pmtu;
 	struct ib_reth *reth;
 	int ret;
 
@@ -263,14 +262,11 @@ void qib_uc_rcv(struct qib_ibport *ibp, struct qib_ib_header *hdr,
 	}
 
 	opcode = be32_to_cpu(ohdr->bth[0]);
-	spin_lock_irqsave(&qp->s_lock, flags);
 	if (qib_ruc_check_hdr(ibp, hdr, has_grh, qp, opcode))
-		goto sunlock;
-	spin_unlock_irqrestore(&qp->s_lock, flags);
+		return;
 
 	psn = be32_to_cpu(ohdr->bth[2]);
 	opcode >>= 24;
-	memset(&wc, 0, sizeof wc);
 
 	/* Compare the PSN verses the expected PSN. */
 	if (unlikely(qib_cmp24(psn, qp->r_psn) != 0)) {
@@ -370,7 +366,7 @@ send_first:
 		}
 		qp->r_rcv_len = 0;
 		if (opcode == OP(SEND_ONLY))
-			goto send_last;
+			goto no_immediate_data;
 		else if (opcode == OP(SEND_ONLY_WITH_IMMEDIATE))
 			goto send_last_imm;
 		/* FALLTHROUGH */
@@ -389,8 +385,11 @@ send_last_imm:
 		wc.ex.imm_data = ohdr->u.imm_data;
 		hdrsize += 4;
 		wc.wc_flags = IB_WC_WITH_IMM;
-		/* FALLTHROUGH */
+		goto send_last;
 	case OP(SEND_LAST):
+no_immediate_data:
+		wc.ex.imm_data = 0;
+		wc.wc_flags = 0;
 send_last:
 		/* Get the number of bytes the message was padded by. */
 		pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
@@ -418,6 +417,12 @@ last_imm:
 		wc.src_qp = qp->remote_qpn;
 		wc.slid = qp->remote_ah_attr.dlid;
 		wc.sl = qp->remote_ah_attr.sl;
+		/* zero fields that are N/A */
+		wc.vendor_err = 0;
+		wc.pkey_index = 0;
+		wc.dlid_path_bits = 0;
+		wc.port_num = 0;
+		wc.csum_ok = 0;
 		/* Signal completion event if the solicited bit is set. */
 		qib_cq_enter(to_icq(qp->ibqp.recv_cq), &wc,
 			     (ohdr->bth[0] &
@@ -546,6 +551,4 @@ op_err:
 	qib_rc_error(qp, IB_WC_LOC_QP_OP_ERR);
 	return;
 
-sunlock:
-	spin_unlock_irqrestore(&qp->s_lock, flags);
 }
diff --git a/drivers/infiniband/hw/qib/qib_verbs.c b/drivers/infiniband/hw/qib/qib_verbs.c
index 9fab404..9627cb7 100644
--- a/drivers/infiniband/hw/qib/qib_verbs.c
+++ b/drivers/infiniband/hw/qib/qib_verbs.c
@@ -38,11 +38,12 @@
 #include <linux/utsname.h>
 #include <linux/rculist.h>
 #include <linux/mm.h>
+#include <linux/random.h>
 
 #include "qib.h"
 #include "qib_common.h"
 
-static unsigned int ib_qib_qp_table_size = 251;
+static unsigned int ib_qib_qp_table_size = 256;
 module_param_named(qp_table_size, ib_qib_qp_table_size, uint, S_IRUGO);
 MODULE_PARM_DESC(qp_table_size, "QP table size");
 
@@ -659,17 +660,25 @@ void qib_ib_rcv(struct qib_ctxtdata *rcd, void *rhdr, void *data, u32 tlen)
 		if (atomic_dec_return(&mcast->refcount) <= 1)
 			wake_up(&mcast->wait);
 	} else {
-		qp = qib_lookup_qpn(ibp, qp_num);
-		if (!qp)
-			goto drop;
+		if (rcd->lookaside_qp) {
+			if (rcd->lookaside_qpn != qp_num) {
+				if (atomic_dec_and_test(
+					&rcd->lookaside_qp->refcount))
+					wake_up(
+					 &rcd->lookaside_qp->wait);
+					rcd->lookaside_qp = NULL;
+				}
+		}
+		if (!rcd->lookaside_qp) {
+			qp = qib_lookup_qpn(ibp, qp_num);
+			if (!qp)
+				goto drop;
+			rcd->lookaside_qp = qp;
+			rcd->lookaside_qpn = qp_num;
+		} else
+			qp = rcd->lookaside_qp;
 		ibp->n_unicast_rcv++;
 		qib_qp_rcv(rcd, hdr, lnh == QIB_LRH_GRH, data, tlen, qp);
-		/*
-		 * Notify qib_destroy_qp() if it is waiting
-		 * for us to finish.
-		 */
-		if (atomic_dec_and_test(&qp->refcount))
-			wake_up(&qp->wait);
 	}
 	return;
 
@@ -1974,6 +1983,8 @@ static void init_ibport(struct qib_pportdata *ppd)
 	ibp->z_excessive_buffer_overrun_errors =
 		cntrs.excessive_buffer_overrun_errors;
 	ibp->z_vl15_dropped = cntrs.vl15_dropped;
+	RCU_INIT_POINTER(ibp->qp0, NULL);
+	RCU_INIT_POINTER(ibp->qp1, NULL);
 }
 
 /**
@@ -1990,12 +2001,15 @@ int qib_register_ib_device(struct qib_devdata *dd)
 	int ret;
 
 	dev->qp_table_size = ib_qib_qp_table_size;
-	dev->qp_table = kzalloc(dev->qp_table_size * sizeof *dev->qp_table,
+	get_random_bytes(&dev->qp_rnd, sizeof(dev->qp_rnd));
+	dev->qp_table = kmalloc(dev->qp_table_size * sizeof *dev->qp_table,
 				GFP_KERNEL);
 	if (!dev->qp_table) {
 		ret = -ENOMEM;
 		goto err_qpt;
 	}
+	for (i = 0; i < dev->qp_table_size; i++)
+		RCU_INIT_POINTER(dev->qp_table[i], NULL);
 
 	for (i = 0; i < dd->num_pports; i++)
 		init_ibport(ppd + i);
diff --git a/drivers/infiniband/hw/qib/qib_verbs.h b/drivers/infiniband/hw/qib/qib_verbs.h
index 95e5b47..0c19ef0 100644
--- a/drivers/infiniband/hw/qib/qib_verbs.h
+++ b/drivers/infiniband/hw/qib/qib_verbs.h
@@ -485,6 +485,7 @@ struct qib_qp {
 	u8 alt_timeout;         /* Alternate path timeout for this QP */
 	u8 port_num;
 	enum ib_mtu path_mtu;
+	u32 pmtu;		/* decoded from path_mtu */
 	u32 remote_qpn;
 	u32 qkey;               /* QKEY for this QP (for UD or RD) */
 	u32 s_size;             /* send work queue size */
@@ -495,6 +496,7 @@ struct qib_qp {
 	u32 s_last;             /* last completed entry */
 	u32 s_ssn;              /* SSN of tail entry */
 	u32 s_lsn;              /* limit sequence number (credit) */
+	unsigned long timeout_jiffies;  /* computed from timeout */
 	struct qib_swqe *s_wq;  /* send work queue */
 	struct qib_swqe *s_wqe;
 	struct qib_rq r_rq;             /* receive work queue */
@@ -723,7 +725,8 @@ struct qib_ibdev {
 	dma_addr_t pio_hdrs_phys;
 	/* list of QPs waiting for RNR timer */
 	spinlock_t pending_lock; /* protect wait lists, PMA counters, etc. */
-	unsigned qp_table_size; /* size of the hash table */
+	u32 qp_table_size; /* size of the hash table */
+	u32 qp_rnd; /* random bytes for hash */
 	spinlock_t qpt_lock;
 
 	u32 n_piowait;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index c74548a..231c2f2 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -84,7 +84,7 @@ static void ipoib_cm_dma_unmap_rx(struct ipoib_dev_priv *priv, int frags,
 	ib_dma_unmap_single(priv->ca, mapping[0], IPOIB_CM_HEAD_SIZE, DMA_FROM_DEVICE);
 
 	for (i = 0; i < frags; ++i)
-		ib_dma_unmap_single(priv->ca, mapping[i + 1], PAGE_SIZE, DMA_FROM_DEVICE);
+		ib_dma_unmap_page(priv->ca, mapping[i + 1], PAGE_SIZE, DMA_FROM_DEVICE);
 }
 
 static int ipoib_cm_post_receive_srq(struct net_device *dev, int id)
@@ -183,7 +183,7 @@ partial_error:
 	ib_dma_unmap_single(priv->ca, mapping[0], IPOIB_CM_HEAD_SIZE, DMA_FROM_DEVICE);
 
 	for (; i > 0; --i)
-		ib_dma_unmap_single(priv->ca, mapping[i], PAGE_SIZE, DMA_FROM_DEVICE);
+		ib_dma_unmap_page(priv->ca, mapping[i], PAGE_SIZE, DMA_FROM_DEVICE);
 
 	dev_kfree_skb_any(skb);
 	return NULL;
@@ -1497,6 +1497,7 @@ static void ipoib_cm_create_srq(struct net_device *dev, int max_sge)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	struct ib_srq_init_attr srq_init_attr = {
+		.srq_type = IB_SRQT_BASIC,
 		.attr = {
 			.max_wr  = ipoib_recvq_size,
 			.max_sge = max_sge
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_fs.c b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
index 86eae22..0e2fe46 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_fs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
@@ -212,16 +212,15 @@ static int ipoib_path_seq_show(struct seq_file *file, void *iter_ptr)
 		   gid_buf, path.pathrec.dlid ? "yes" : "no");
 
 	if (path.pathrec.dlid) {
-		rate = ib_rate_to_mult(path.pathrec.rate) * 25;
+		rate = ib_rate_to_mbps(path.pathrec.rate);
 
 		seq_printf(file,
 			   "  DLID:     0x%04x\n"
 			   "  SL: %12d\n"
-			   "  rate: %*d%s Gb/sec\n",
+			   "  rate: %8d.%d Gb/sec\n",
 			   be16_to_cpu(path.pathrec.dlid),
 			   path.pathrec.sl,
-			   10 - ((rate % 10) ? 2 : 0),
-			   rate / 10, rate % 10 ? ".5" : "");
+			   rate / 1000, rate % 1000);
 	}
 
 	seq_putc(file, '\n');
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
index 23e82e4..001b147 100644
--- a/drivers/input/Kconfig
+++ b/drivers/input/Kconfig
@@ -3,7 +3,7 @@
 #
 
 menu "Input device support"
-	depends on !S390
+	depends on !S390 && !UML
 
 config INPUT
 	tristate "Generic input layer (needed for keyboard, mouse, ...)" if EXPERT
diff --git a/drivers/isdn/Kconfig b/drivers/isdn/Kconfig
index 4fb6016..a233ed5 100644
--- a/drivers/isdn/Kconfig
+++ b/drivers/isdn/Kconfig
@@ -5,7 +5,7 @@
 menuconfig ISDN
 	bool "ISDN support"
 	depends on NET
-	depends on !S390
+	depends on !S390 && !UML
 	---help---
 	  ISDN ("Integrated Services Digital Network", called RNIS in France)
 	  is a fully digital telephone service that can be used for voice and
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index f75a66e..faa4741 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -208,6 +208,16 @@ config DM_DEBUG
 
 	  If unsure, say N.
 
+config DM_BUFIO
+       tristate
+       depends on BLK_DEV_DM && EXPERIMENTAL
+       ---help---
+	 This interface allows you to do buffered I/O on a device and acts
+	 as a cache, holding recently-read blocks in memory and performing
+	 delayed writes.
+
+source "drivers/md/persistent-data/Kconfig"
+
 config DM_CRYPT
 	tristate "Crypt target support"
 	depends on BLK_DEV_DM
@@ -233,6 +243,32 @@ config DM_SNAPSHOT
        ---help---
          Allow volume managers to take writable snapshots of a device.
 
+config DM_THIN_PROVISIONING
+       tristate "Thin provisioning target (EXPERIMENTAL)"
+       depends on BLK_DEV_DM && EXPERIMENTAL
+       select DM_PERSISTENT_DATA
+       ---help---
+         Provides thin provisioning and snapshots that share a data store.
+
+config DM_DEBUG_BLOCK_STACK_TRACING
+	boolean "Keep stack trace of thin provisioning block lock holders"
+	depends on STACKTRACE_SUPPORT && DM_THIN_PROVISIONING
+	select STACKTRACE
+	---help---
+	  Enable this for messages that may help debug problems with the
+	  block manager locking used by thin provisioning.
+
+	  If unsure, say N.
+
+config DM_DEBUG_SPACE_MAPS
+	boolean "Extra validation for thin provisioning space maps"
+	depends on DM_THIN_PROVISIONING
+	---help---
+	  Enable this for messages that may help debug problems with the
+	  space maps used by thin provisioning.
+
+          If unsure, say N.
+
 config DM_MIRROR
        tristate "Mirror target"
        depends on BLK_DEV_DM
diff --git a/drivers/md/Makefile b/drivers/md/Makefile
index 448838b..046860c 100644
--- a/drivers/md/Makefile
+++ b/drivers/md/Makefile
@@ -10,6 +10,7 @@ dm-snapshot-y	+= dm-snap.o dm-exception-store.o dm-snap-transient.o \
 dm-mirror-y	+= dm-raid1.o
 dm-log-userspace-y \
 		+= dm-log-userspace-base.o dm-log-userspace-transfer.o
+dm-thin-pool-y	+= dm-thin.o dm-thin-metadata.o
 md-mod-y	+= md.o bitmap.o
 raid456-y	+= raid5.o
 
@@ -27,6 +28,7 @@ obj-$(CONFIG_MD_MULTIPATH)	+= multipath.o
 obj-$(CONFIG_MD_FAULTY)		+= faulty.o
 obj-$(CONFIG_BLK_DEV_MD)	+= md-mod.o
 obj-$(CONFIG_BLK_DEV_DM)	+= dm-mod.o
+obj-$(CONFIG_DM_BUFIO)		+= dm-bufio.o
 obj-$(CONFIG_DM_CRYPT)		+= dm-crypt.o
 obj-$(CONFIG_DM_DELAY)		+= dm-delay.o
 obj-$(CONFIG_DM_FLAKEY)		+= dm-flakey.o
@@ -34,10 +36,12 @@ obj-$(CONFIG_DM_MULTIPATH)	+= dm-multipath.o dm-round-robin.o
 obj-$(CONFIG_DM_MULTIPATH_QL)	+= dm-queue-length.o
 obj-$(CONFIG_DM_MULTIPATH_ST)	+= dm-service-time.o
 obj-$(CONFIG_DM_SNAPSHOT)	+= dm-snapshot.o
+obj-$(CONFIG_DM_PERSISTENT_DATA)	+= persistent-data/
 obj-$(CONFIG_DM_MIRROR)		+= dm-mirror.o dm-log.o dm-region-hash.o
 obj-$(CONFIG_DM_LOG_USERSPACE)	+= dm-log-userspace.o
 obj-$(CONFIG_DM_ZERO)		+= dm-zero.o
 obj-$(CONFIG_DM_RAID)	+= dm-raid.o
+obj-$(CONFIG_DM_THIN_PROVISIONING)	+= dm-thin-pool.o
 
 ifeq ($(CONFIG_DM_UEVENT),y)
 dm-mod-objs			+= dm-uevent.o
diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c
new file mode 100644
index 0000000..cb24666
--- /dev/null
+++ b/drivers/md/dm-bufio.c
@@ -0,0 +1,1699 @@
+/*
+ * Copyright (C) 2009-2011 Red Hat, Inc.
+ *
+ * Author: Mikulas Patocka <mpatocka@redhat.com>
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-bufio.h"
+
+#include <linux/device-mapper.h>
+#include <linux/dm-io.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/version.h>
+#include <linux/shrinker.h>
+
+#define DM_MSG_PREFIX "bufio"
+
+/*
+ * Memory management policy:
+ *	Limit the number of buffers to DM_BUFIO_MEMORY_PERCENT of main memory
+ *	or DM_BUFIO_VMALLOC_PERCENT of vmalloc memory (whichever is lower).
+ *	Always allocate at least DM_BUFIO_MIN_BUFFERS buffers.
+ *	Start background writeback when there are DM_BUFIO_WRITEBACK_PERCENT
+ *	dirty buffers.
+ */
+#define DM_BUFIO_MIN_BUFFERS		8
+
+#define DM_BUFIO_MEMORY_PERCENT		2
+#define DM_BUFIO_VMALLOC_PERCENT	25
+#define DM_BUFIO_WRITEBACK_PERCENT	75
+
+/*
+ * Check buffer ages in this interval (seconds)
+ */
+#define DM_BUFIO_WORK_TIMER_SECS	10
+
+/*
+ * Free buffers when they are older than this (seconds)
+ */
+#define DM_BUFIO_DEFAULT_AGE_SECS	60
+
+/*
+ * The number of bvec entries that are embedded directly in the buffer.
+ * If the chunk size is larger, dm-io is used to do the io.
+ */
+#define DM_BUFIO_INLINE_VECS		16
+
+/*
+ * Buffer hash
+ */
+#define DM_BUFIO_HASH_BITS	20
+#define DM_BUFIO_HASH(block) \
+	((((block) >> DM_BUFIO_HASH_BITS) ^ (block)) & \
+	 ((1 << DM_BUFIO_HASH_BITS) - 1))
+
+/*
+ * Don't try to use kmem_cache_alloc for blocks larger than this.
+ * For explanation, see alloc_buffer_data below.
+ */
+#define DM_BUFIO_BLOCK_SIZE_SLAB_LIMIT	(PAGE_SIZE >> 1)
+#define DM_BUFIO_BLOCK_SIZE_GFP_LIMIT	(PAGE_SIZE << (MAX_ORDER - 1))
+
+/*
+ * dm_buffer->list_mode
+ */
+#define LIST_CLEAN	0
+#define LIST_DIRTY	1
+#define LIST_SIZE	2
+
+/*
+ * Linking of buffers:
+ *	All buffers are linked to cache_hash with their hash_list field.
+ *
+ *	Clean buffers that are not being written (B_WRITING not set)
+ *	are linked to lru[LIST_CLEAN] with their lru_list field.
+ *
+ *	Dirty and clean buffers that are being written are linked to
+ *	lru[LIST_DIRTY] with their lru_list field. When the write
+ *	finishes, the buffer cannot be relinked immediately (because we
+ *	are in an interrupt context and relinking requires process
+ *	context), so some clean-not-writing buffers can be held on
+ *	dirty_lru too.  They are later added to lru in the process
+ *	context.
+ */
+struct dm_bufio_client {
+	struct mutex lock;
+
+	struct list_head lru[LIST_SIZE];
+	unsigned long n_buffers[LIST_SIZE];
+
+	struct block_device *bdev;
+	unsigned block_size;
+	unsigned char sectors_per_block_bits;
+	unsigned char pages_per_block_bits;
+	unsigned char blocks_per_page_bits;
+	unsigned aux_size;
+	void (*alloc_callback)(struct dm_buffer *);
+	void (*write_callback)(struct dm_buffer *);
+
+	struct dm_io_client *dm_io;
+
+	struct list_head reserved_buffers;
+	unsigned need_reserved_buffers;
+
+	struct hlist_head *cache_hash;
+	wait_queue_head_t free_buffer_wait;
+
+	int async_write_error;
+
+	struct list_head client_list;
+	struct shrinker shrinker;
+};
+
+/*
+ * Buffer state bits.
+ */
+#define B_READING	0
+#define B_WRITING	1
+#define B_DIRTY		2
+
+/*
+ * Describes how the block was allocated:
+ * kmem_cache_alloc(), __get_free_pages() or vmalloc().
+ * See the comment at alloc_buffer_data.
+ */
+enum data_mode {
+	DATA_MODE_SLAB = 0,
+	DATA_MODE_GET_FREE_PAGES = 1,
+	DATA_MODE_VMALLOC = 2,
+	DATA_MODE_LIMIT = 3
+};
+
+struct dm_buffer {
+	struct hlist_node hash_list;
+	struct list_head lru_list;
+	sector_t block;
+	void *data;
+	enum data_mode data_mode;
+	unsigned char list_mode;		/* LIST_* */
+	unsigned hold_count;
+	int read_error;
+	int write_error;
+	unsigned long state;
+	unsigned long last_accessed;
+	struct dm_bufio_client *c;
+	struct bio bio;
+	struct bio_vec bio_vec[DM_BUFIO_INLINE_VECS];
+};
+
+/*----------------------------------------------------------------*/
+
+static struct kmem_cache *dm_bufio_caches[PAGE_SHIFT - SECTOR_SHIFT];
+static char *dm_bufio_cache_names[PAGE_SHIFT - SECTOR_SHIFT];
+
+static inline int dm_bufio_cache_index(struct dm_bufio_client *c)
+{
+	unsigned ret = c->blocks_per_page_bits - 1;
+
+	BUG_ON(ret >= ARRAY_SIZE(dm_bufio_caches));
+
+	return ret;
+}
+
+#define DM_BUFIO_CACHE(c)	(dm_bufio_caches[dm_bufio_cache_index(c)])
+#define DM_BUFIO_CACHE_NAME(c)	(dm_bufio_cache_names[dm_bufio_cache_index(c)])
+
+#define dm_bufio_in_request()	(!!current->bio_list)
+
+static void dm_bufio_lock(struct dm_bufio_client *c)
+{
+	mutex_lock_nested(&c->lock, dm_bufio_in_request());
+}
+
+static int dm_bufio_trylock(struct dm_bufio_client *c)
+{
+	return mutex_trylock(&c->lock);
+}
+
+static void dm_bufio_unlock(struct dm_bufio_client *c)
+{
+	mutex_unlock(&c->lock);
+}
+
+/*
+ * FIXME Move to sched.h?
+ */
+#ifdef CONFIG_PREEMPT_VOLUNTARY
+#  define dm_bufio_cond_resched()		\
+do {						\
+	if (unlikely(need_resched()))		\
+		_cond_resched();		\
+} while (0)
+#else
+#  define dm_bufio_cond_resched()                do { } while (0)
+#endif
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Default cache size: available memory divided by the ratio.
+ */
+static unsigned long dm_bufio_default_cache_size;
+
+/*
+ * Total cache size set by the user.
+ */
+static unsigned long dm_bufio_cache_size;
+
+/*
+ * A copy of dm_bufio_cache_size because dm_bufio_cache_size can change
+ * at any time.  If it disagrees, the user has changed cache size.
+ */
+static unsigned long dm_bufio_cache_size_latch;
+
+static DEFINE_SPINLOCK(param_spinlock);
+
+/*
+ * Buffers are freed after this timeout
+ */
+static unsigned dm_bufio_max_age = DM_BUFIO_DEFAULT_AGE_SECS;
+
+static unsigned long dm_bufio_peak_allocated;
+static unsigned long dm_bufio_allocated_kmem_cache;
+static unsigned long dm_bufio_allocated_get_free_pages;
+static unsigned long dm_bufio_allocated_vmalloc;
+static unsigned long dm_bufio_current_allocated;
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Per-client cache: dm_bufio_cache_size / dm_bufio_client_count
+ */
+static unsigned long dm_bufio_cache_size_per_client;
+
+/*
+ * The current number of clients.
+ */
+static int dm_bufio_client_count;
+
+/*
+ * The list of all clients.
+ */
+static LIST_HEAD(dm_bufio_all_clients);
+
+/*
+ * This mutex protects dm_bufio_cache_size_latch,
+ * dm_bufio_cache_size_per_client and dm_bufio_client_count
+ */
+static DEFINE_MUTEX(dm_bufio_clients_lock);
+
+/*----------------------------------------------------------------*/
+
+static void adjust_total_allocated(enum data_mode data_mode, long diff)
+{
+	static unsigned long * const class_ptr[DATA_MODE_LIMIT] = {
+		&dm_bufio_allocated_kmem_cache,
+		&dm_bufio_allocated_get_free_pages,
+		&dm_bufio_allocated_vmalloc,
+	};
+
+	spin_lock(&param_spinlock);
+
+	*class_ptr[data_mode] += diff;
+
+	dm_bufio_current_allocated += diff;
+
+	if (dm_bufio_current_allocated > dm_bufio_peak_allocated)
+		dm_bufio_peak_allocated = dm_bufio_current_allocated;
+
+	spin_unlock(&param_spinlock);
+}
+
+/*
+ * Change the number of clients and recalculate per-client limit.
+ */
+static void __cache_size_refresh(void)
+{
+	BUG_ON(!mutex_is_locked(&dm_bufio_clients_lock));
+	BUG_ON(dm_bufio_client_count < 0);
+
+	dm_bufio_cache_size_latch = dm_bufio_cache_size;
+
+	barrier();
+
+	/*
+	 * Use default if set to 0 and report the actual cache size used.
+	 */
+	if (!dm_bufio_cache_size_latch) {
+		(void)cmpxchg(&dm_bufio_cache_size, 0,
+			      dm_bufio_default_cache_size);
+		dm_bufio_cache_size_latch = dm_bufio_default_cache_size;
+	}
+
+	dm_bufio_cache_size_per_client = dm_bufio_cache_size_latch /
+					 (dm_bufio_client_count ? : 1);
+}
+
+/*
+ * Allocating buffer data.
+ *
+ * Small buffers are allocated with kmem_cache, to use space optimally.
+ *
+ * For large buffers, we choose between get_free_pages and vmalloc.
+ * Each has advantages and disadvantages.
+ *
+ * __get_free_pages can randomly fail if the memory is fragmented.
+ * __vmalloc won't randomly fail, but vmalloc space is limited (it may be
+ * as low as 128M) so using it for caching is not appropriate.
+ *
+ * If the allocation may fail we use __get_free_pages. Memory fragmentation
+ * won't have a fatal effect here, but it just causes flushes of some other
+ * buffers and more I/O will be performed. Don't use __get_free_pages if it
+ * always fails (i.e. order >= MAX_ORDER).
+ *
+ * If the allocation shouldn't fail we use __vmalloc. This is only for the
+ * initial reserve allocation, so there's no risk of wasting all vmalloc
+ * space.
+ */
+static void *alloc_buffer_data(struct dm_bufio_client *c, gfp_t gfp_mask,
+			       enum data_mode *data_mode)
+{
+	if (c->block_size <= DM_BUFIO_BLOCK_SIZE_SLAB_LIMIT) {
+		*data_mode = DATA_MODE_SLAB;
+		return kmem_cache_alloc(DM_BUFIO_CACHE(c), gfp_mask);
+	}
+
+	if (c->block_size <= DM_BUFIO_BLOCK_SIZE_GFP_LIMIT &&
+	    gfp_mask & __GFP_NORETRY) {
+		*data_mode = DATA_MODE_GET_FREE_PAGES;
+		return (void *)__get_free_pages(gfp_mask,
+						c->pages_per_block_bits);
+	}
+
+	*data_mode = DATA_MODE_VMALLOC;
+	return __vmalloc(c->block_size, gfp_mask, PAGE_KERNEL);
+}
+
+/*
+ * Free buffer's data.
+ */
+static void free_buffer_data(struct dm_bufio_client *c,
+			     void *data, enum data_mode data_mode)
+{
+	switch (data_mode) {
+	case DATA_MODE_SLAB:
+		kmem_cache_free(DM_BUFIO_CACHE(c), data);
+		break;
+
+	case DATA_MODE_GET_FREE_PAGES:
+		free_pages((unsigned long)data, c->pages_per_block_bits);
+		break;
+
+	case DATA_MODE_VMALLOC:
+		vfree(data);
+		break;
+
+	default:
+		DMCRIT("dm_bufio_free_buffer_data: bad data mode: %d",
+		       data_mode);
+		BUG();
+	}
+}
+
+/*
+ * Allocate buffer and its data.
+ */
+static struct dm_buffer *alloc_buffer(struct dm_bufio_client *c, gfp_t gfp_mask)
+{
+	struct dm_buffer *b = kmalloc(sizeof(struct dm_buffer) + c->aux_size,
+				      gfp_mask);
+
+	if (!b)
+		return NULL;
+
+	b->c = c;
+
+	b->data = alloc_buffer_data(c, gfp_mask, &b->data_mode);
+	if (!b->data) {
+		kfree(b);
+		return NULL;
+	}
+
+	adjust_total_allocated(b->data_mode, (long)c->block_size);
+
+	return b;
+}
+
+/*
+ * Free buffer and its data.
+ */
+static void free_buffer(struct dm_buffer *b)
+{
+	struct dm_bufio_client *c = b->c;
+
+	adjust_total_allocated(b->data_mode, -(long)c->block_size);
+
+	free_buffer_data(c, b->data, b->data_mode);
+	kfree(b);
+}
+
+/*
+ * Link buffer to the hash list and clean or dirty queue.
+ */
+static void __link_buffer(struct dm_buffer *b, sector_t block, int dirty)
+{
+	struct dm_bufio_client *c = b->c;
+
+	c->n_buffers[dirty]++;
+	b->block = block;
+	b->list_mode = dirty;
+	list_add(&b->lru_list, &c->lru[dirty]);
+	hlist_add_head(&b->hash_list, &c->cache_hash[DM_BUFIO_HASH(block)]);
+	b->last_accessed = jiffies;
+}
+
+/*
+ * Unlink buffer from the hash list and dirty or clean queue.
+ */
+static void __unlink_buffer(struct dm_buffer *b)
+{
+	struct dm_bufio_client *c = b->c;
+
+	BUG_ON(!c->n_buffers[b->list_mode]);
+
+	c->n_buffers[b->list_mode]--;
+	hlist_del(&b->hash_list);
+	list_del(&b->lru_list);
+}
+
+/*
+ * Place the buffer to the head of dirty or clean LRU queue.
+ */
+static void __relink_lru(struct dm_buffer *b, int dirty)
+{
+	struct dm_bufio_client *c = b->c;
+
+	BUG_ON(!c->n_buffers[b->list_mode]);
+
+	c->n_buffers[b->list_mode]--;
+	c->n_buffers[dirty]++;
+	b->list_mode = dirty;
+	list_del(&b->lru_list);
+	list_add(&b->lru_list, &c->lru[dirty]);
+}
+
+/*----------------------------------------------------------------
+ * Submit I/O on the buffer.
+ *
+ * Bio interface is faster but it has some problems:
+ *	the vector list is limited (increasing this limit increases
+ *	memory-consumption per buffer, so it is not viable);
+ *
+ *	the memory must be direct-mapped, not vmalloced;
+ *
+ *	the I/O driver can reject requests spuriously if it thinks that
+ *	the requests are too big for the device or if they cross a
+ *	controller-defined memory boundary.
+ *
+ * If the buffer is small enough (up to DM_BUFIO_INLINE_VECS pages) and
+ * it is not vmalloced, try using the bio interface.
+ *
+ * If the buffer is big, if it is vmalloced or if the underlying device
+ * rejects the bio because it is too large, use dm-io layer to do the I/O.
+ * The dm-io layer splits the I/O into multiple requests, avoiding the above
+ * shortcomings.
+ *--------------------------------------------------------------*/
+
+/*
+ * dm-io completion routine. It just calls b->bio.bi_end_io, pretending
+ * that the request was handled directly with bio interface.
+ */
+static void dmio_complete(unsigned long error, void *context)
+{
+	struct dm_buffer *b = context;
+
+	b->bio.bi_end_io(&b->bio, error ? -EIO : 0);
+}
+
+static void use_dmio(struct dm_buffer *b, int rw, sector_t block,
+		     bio_end_io_t *end_io)
+{
+	int r;
+	struct dm_io_request io_req = {
+		.bi_rw = rw,
+		.notify.fn = dmio_complete,
+		.notify.context = b,
+		.client = b->c->dm_io,
+	};
+	struct dm_io_region region = {
+		.bdev = b->c->bdev,
+		.sector = block << b->c->sectors_per_block_bits,
+		.count = b->c->block_size >> SECTOR_SHIFT,
+	};
+
+	if (b->data_mode != DATA_MODE_VMALLOC) {
+		io_req.mem.type = DM_IO_KMEM;
+		io_req.mem.ptr.addr = b->data;
+	} else {
+		io_req.mem.type = DM_IO_VMA;
+		io_req.mem.ptr.vma = b->data;
+	}
+
+	b->bio.bi_end_io = end_io;
+
+	r = dm_io(&io_req, 1, &region, NULL);
+	if (r)
+		end_io(&b->bio, r);
+}
+
+static void use_inline_bio(struct dm_buffer *b, int rw, sector_t block,
+			   bio_end_io_t *end_io)
+{
+	char *ptr;
+	int len;
+
+	bio_init(&b->bio);
+	b->bio.bi_io_vec = b->bio_vec;
+	b->bio.bi_max_vecs = DM_BUFIO_INLINE_VECS;
+	b->bio.bi_sector = block << b->c->sectors_per_block_bits;
+	b->bio.bi_bdev = b->c->bdev;
+	b->bio.bi_end_io = end_io;
+
+	/*
+	 * We assume that if len >= PAGE_SIZE ptr is page-aligned.
+	 * If len < PAGE_SIZE the buffer doesn't cross page boundary.
+	 */
+	ptr = b->data;
+	len = b->c->block_size;
+
+	if (len >= PAGE_SIZE)
+		BUG_ON((unsigned long)ptr & (PAGE_SIZE - 1));
+	else
+		BUG_ON((unsigned long)ptr & (len - 1));
+
+	do {
+		if (!bio_add_page(&b->bio, virt_to_page(ptr),
+				  len < PAGE_SIZE ? len : PAGE_SIZE,
+				  virt_to_phys(ptr) & (PAGE_SIZE - 1))) {
+			BUG_ON(b->c->block_size <= PAGE_SIZE);
+			use_dmio(b, rw, block, end_io);
+			return;
+		}
+
+		len -= PAGE_SIZE;
+		ptr += PAGE_SIZE;
+	} while (len > 0);
+
+	submit_bio(rw, &b->bio);
+}
+
+static void submit_io(struct dm_buffer *b, int rw, sector_t block,
+		      bio_end_io_t *end_io)
+{
+	if (rw == WRITE && b->c->write_callback)
+		b->c->write_callback(b);
+
+	if (b->c->block_size <= DM_BUFIO_INLINE_VECS * PAGE_SIZE &&
+	    b->data_mode != DATA_MODE_VMALLOC)
+		use_inline_bio(b, rw, block, end_io);
+	else
+		use_dmio(b, rw, block, end_io);
+}
+
+/*----------------------------------------------------------------
+ * Writing dirty buffers
+ *--------------------------------------------------------------*/
+
+/*
+ * The endio routine for write.
+ *
+ * Set the error, clear B_WRITING bit and wake anyone who was waiting on
+ * it.
+ */
+static void write_endio(struct bio *bio, int error)
+{
+	struct dm_buffer *b = container_of(bio, struct dm_buffer, bio);
+
+	b->write_error = error;
+	if (error) {
+		struct dm_bufio_client *c = b->c;
+		(void)cmpxchg(&c->async_write_error, 0, error);
+	}
+
+	BUG_ON(!test_bit(B_WRITING, &b->state));
+
+	smp_mb__before_clear_bit();
+	clear_bit(B_WRITING, &b->state);
+	smp_mb__after_clear_bit();
+
+	wake_up_bit(&b->state, B_WRITING);
+}
+
+/*
+ * This function is called when wait_on_bit is actually waiting.
+ */
+static int do_io_schedule(void *word)
+{
+	io_schedule();
+
+	return 0;
+}
+
+/*
+ * Initiate a write on a dirty buffer, but don't wait for it.
+ *
+ * - If the buffer is not dirty, exit.
+ * - If there some previous write going on, wait for it to finish (we can't
+ *   have two writes on the same buffer simultaneously).
+ * - Submit our write and don't wait on it. We set B_WRITING indicating
+ *   that there is a write in progress.
+ */
+static void __write_dirty_buffer(struct dm_buffer *b)
+{
+	if (!test_bit(B_DIRTY, &b->state))
+		return;
+
+	clear_bit(B_DIRTY, &b->state);
+	wait_on_bit_lock(&b->state, B_WRITING,
+			 do_io_schedule, TASK_UNINTERRUPTIBLE);
+
+	submit_io(b, WRITE, b->block, write_endio);
+}
+
+/*
+ * Wait until any activity on the buffer finishes.  Possibly write the
+ * buffer if it is dirty.  When this function finishes, there is no I/O
+ * running on the buffer and the buffer is not dirty.
+ */
+static void __make_buffer_clean(struct dm_buffer *b)
+{
+	BUG_ON(b->hold_count);
+
+	if (!b->state)	/* fast case */
+		return;
+
+	wait_on_bit(&b->state, B_READING, do_io_schedule, TASK_UNINTERRUPTIBLE);
+	__write_dirty_buffer(b);
+	wait_on_bit(&b->state, B_WRITING, do_io_schedule, TASK_UNINTERRUPTIBLE);
+}
+
+/*
+ * Find some buffer that is not held by anybody, clean it, unlink it and
+ * return it.
+ */
+static struct dm_buffer *__get_unclaimed_buffer(struct dm_bufio_client *c)
+{
+	struct dm_buffer *b;
+
+	list_for_each_entry_reverse(b, &c->lru[LIST_CLEAN], lru_list) {
+		BUG_ON(test_bit(B_WRITING, &b->state));
+		BUG_ON(test_bit(B_DIRTY, &b->state));
+
+		if (!b->hold_count) {
+			__make_buffer_clean(b);
+			__unlink_buffer(b);
+			return b;
+		}
+		dm_bufio_cond_resched();
+	}
+
+	list_for_each_entry_reverse(b, &c->lru[LIST_DIRTY], lru_list) {
+		BUG_ON(test_bit(B_READING, &b->state));
+
+		if (!b->hold_count) {
+			__make_buffer_clean(b);
+			__unlink_buffer(b);
+			return b;
+		}
+		dm_bufio_cond_resched();
+	}
+
+	return NULL;
+}
+
+/*
+ * Wait until some other threads free some buffer or release hold count on
+ * some buffer.
+ *
+ * This function is entered with c->lock held, drops it and regains it
+ * before exiting.
+ */
+static void __wait_for_free_buffer(struct dm_bufio_client *c)
+{
+	DECLARE_WAITQUEUE(wait, current);
+
+	add_wait_queue(&c->free_buffer_wait, &wait);
+	set_task_state(current, TASK_UNINTERRUPTIBLE);
+	dm_bufio_unlock(c);
+
+	io_schedule();
+
+	set_task_state(current, TASK_RUNNING);
+	remove_wait_queue(&c->free_buffer_wait, &wait);
+
+	dm_bufio_lock(c);
+}
+
+/*
+ * Allocate a new buffer. If the allocation is not possible, wait until
+ * some other thread frees a buffer.
+ *
+ * May drop the lock and regain it.
+ */
+static struct dm_buffer *__alloc_buffer_wait_no_callback(struct dm_bufio_client *c)
+{
+	struct dm_buffer *b;
+
+	/*
+	 * dm-bufio is resistant to allocation failures (it just keeps
+	 * one buffer reserved in cases all the allocations fail).
+	 * So set flags to not try too hard:
+	 *	GFP_NOIO: don't recurse into the I/O layer
+	 *	__GFP_NORETRY: don't retry and rather return failure
+	 *	__GFP_NOMEMALLOC: don't use emergency reserves
+	 *	__GFP_NOWARN: don't print a warning in case of failure
+	 *
+	 * For debugging, if we set the cache size to 1, no new buffers will
+	 * be allocated.
+	 */
+	while (1) {
+		if (dm_bufio_cache_size_latch != 1) {
+			b = alloc_buffer(c, GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN);
+			if (b)
+				return b;
+		}
+
+		if (!list_empty(&c->reserved_buffers)) {
+			b = list_entry(c->reserved_buffers.next,
+				       struct dm_buffer, lru_list);
+			list_del(&b->lru_list);
+			c->need_reserved_buffers++;
+
+			return b;
+		}
+
+		b = __get_unclaimed_buffer(c);
+		if (b)
+			return b;
+
+		__wait_for_free_buffer(c);
+	}
+}
+
+static struct dm_buffer *__alloc_buffer_wait(struct dm_bufio_client *c)
+{
+	struct dm_buffer *b = __alloc_buffer_wait_no_callback(c);
+
+	if (c->alloc_callback)
+		c->alloc_callback(b);
+
+	return b;
+}
+
+/*
+ * Free a buffer and wake other threads waiting for free buffers.
+ */
+static void __free_buffer_wake(struct dm_buffer *b)
+{
+	struct dm_bufio_client *c = b->c;
+
+	if (!c->need_reserved_buffers)
+		free_buffer(b);
+	else {
+		list_add(&b->lru_list, &c->reserved_buffers);
+		c->need_reserved_buffers--;
+	}
+
+	wake_up(&c->free_buffer_wait);
+}
+
+static void __write_dirty_buffers_async(struct dm_bufio_client *c, int no_wait)
+{
+	struct dm_buffer *b, *tmp;
+
+	list_for_each_entry_safe_reverse(b, tmp, &c->lru[LIST_DIRTY], lru_list) {
+		BUG_ON(test_bit(B_READING, &b->state));
+
+		if (!test_bit(B_DIRTY, &b->state) &&
+		    !test_bit(B_WRITING, &b->state)) {
+			__relink_lru(b, LIST_CLEAN);
+			continue;
+		}
+
+		if (no_wait && test_bit(B_WRITING, &b->state))
+			return;
+
+		__write_dirty_buffer(b);
+		dm_bufio_cond_resched();
+	}
+}
+
+/*
+ * Get writeback threshold and buffer limit for a given client.
+ */
+static void __get_memory_limit(struct dm_bufio_client *c,
+			       unsigned long *threshold_buffers,
+			       unsigned long *limit_buffers)
+{
+	unsigned long buffers;
+
+	if (dm_bufio_cache_size != dm_bufio_cache_size_latch) {
+		mutex_lock(&dm_bufio_clients_lock);
+		__cache_size_refresh();
+		mutex_unlock(&dm_bufio_clients_lock);
+	}
+
+	buffers = dm_bufio_cache_size_per_client >>
+		  (c->sectors_per_block_bits + SECTOR_SHIFT);
+
+	if (buffers < DM_BUFIO_MIN_BUFFERS)
+		buffers = DM_BUFIO_MIN_BUFFERS;
+
+	*limit_buffers = buffers;
+	*threshold_buffers = buffers * DM_BUFIO_WRITEBACK_PERCENT / 100;
+}
+
+/*
+ * Check if we're over watermark.
+ * If we are over threshold_buffers, start freeing buffers.
+ * If we're over "limit_buffers", block until we get under the limit.
+ */
+static void __check_watermark(struct dm_bufio_client *c)
+{
+	unsigned long threshold_buffers, limit_buffers;
+
+	__get_memory_limit(c, &threshold_buffers, &limit_buffers);
+
+	while (c->n_buffers[LIST_CLEAN] + c->n_buffers[LIST_DIRTY] >
+	       limit_buffers) {
+
+		struct dm_buffer *b = __get_unclaimed_buffer(c);
+
+		if (!b)
+			return;
+
+		__free_buffer_wake(b);
+		dm_bufio_cond_resched();
+	}
+
+	if (c->n_buffers[LIST_DIRTY] > threshold_buffers)
+		__write_dirty_buffers_async(c, 1);
+}
+
+/*
+ * Find a buffer in the hash.
+ */
+static struct dm_buffer *__find(struct dm_bufio_client *c, sector_t block)
+{
+	struct dm_buffer *b;
+	struct hlist_node *hn;
+
+	hlist_for_each_entry(b, hn, &c->cache_hash[DM_BUFIO_HASH(block)],
+			     hash_list) {
+		dm_bufio_cond_resched();
+		if (b->block == block)
+			return b;
+	}
+
+	return NULL;
+}
+
+/*----------------------------------------------------------------
+ * Getting a buffer
+ *--------------------------------------------------------------*/
+
+enum new_flag {
+	NF_FRESH = 0,
+	NF_READ = 1,
+	NF_GET = 2
+};
+
+static struct dm_buffer *__bufio_new(struct dm_bufio_client *c, sector_t block,
+				     enum new_flag nf, struct dm_buffer **bp,
+				     int *need_submit)
+{
+	struct dm_buffer *b, *new_b = NULL;
+
+	*need_submit = 0;
+
+	b = __find(c, block);
+	if (b) {
+		b->hold_count++;
+		__relink_lru(b, test_bit(B_DIRTY, &b->state) ||
+			     test_bit(B_WRITING, &b->state));
+		return b;
+	}
+
+	if (nf == NF_GET)
+		return NULL;
+
+	new_b = __alloc_buffer_wait(c);
+
+	/*
+	 * We've had a period where the mutex was unlocked, so need to
+	 * recheck the hash table.
+	 */
+	b = __find(c, block);
+	if (b) {
+		__free_buffer_wake(new_b);
+		b->hold_count++;
+		__relink_lru(b, test_bit(B_DIRTY, &b->state) ||
+			     test_bit(B_WRITING, &b->state));
+		return b;
+	}
+
+	__check_watermark(c);
+
+	b = new_b;
+	b->hold_count = 1;
+	b->read_error = 0;
+	b->write_error = 0;
+	__link_buffer(b, block, LIST_CLEAN);
+
+	if (nf == NF_FRESH) {
+		b->state = 0;
+		return b;
+	}
+
+	b->state = 1 << B_READING;
+	*need_submit = 1;
+
+	return b;
+}
+
+/*
+ * The endio routine for reading: set the error, clear the bit and wake up
+ * anyone waiting on the buffer.
+ */
+static void read_endio(struct bio *bio, int error)
+{
+	struct dm_buffer *b = container_of(bio, struct dm_buffer, bio);
+
+	b->read_error = error;
+
+	BUG_ON(!test_bit(B_READING, &b->state));
+
+	smp_mb__before_clear_bit();
+	clear_bit(B_READING, &b->state);
+	smp_mb__after_clear_bit();
+
+	wake_up_bit(&b->state, B_READING);
+}
+
+/*
+ * A common routine for dm_bufio_new and dm_bufio_read.  Operation of these
+ * functions is similar except that dm_bufio_new doesn't read the
+ * buffer from the disk (assuming that the caller overwrites all the data
+ * and uses dm_bufio_mark_buffer_dirty to write new data back).
+ */
+static void *new_read(struct dm_bufio_client *c, sector_t block,
+		      enum new_flag nf, struct dm_buffer **bp)
+{
+	int need_submit;
+	struct dm_buffer *b;
+
+	dm_bufio_lock(c);
+	b = __bufio_new(c, block, nf, bp, &need_submit);
+	dm_bufio_unlock(c);
+
+	if (!b || IS_ERR(b))
+		return b;
+
+	if (need_submit)
+		submit_io(b, READ, b->block, read_endio);
+
+	wait_on_bit(&b->state, B_READING, do_io_schedule, TASK_UNINTERRUPTIBLE);
+
+	if (b->read_error) {
+		int error = b->read_error;
+
+		dm_bufio_release(b);
+
+		return ERR_PTR(error);
+	}
+
+	*bp = b;
+
+	return b->data;
+}
+
+void *dm_bufio_get(struct dm_bufio_client *c, sector_t block,
+		   struct dm_buffer **bp)
+{
+	return new_read(c, block, NF_GET, bp);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_get);
+
+void *dm_bufio_read(struct dm_bufio_client *c, sector_t block,
+		    struct dm_buffer **bp)
+{
+	BUG_ON(dm_bufio_in_request());
+
+	return new_read(c, block, NF_READ, bp);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_read);
+
+void *dm_bufio_new(struct dm_bufio_client *c, sector_t block,
+		   struct dm_buffer **bp)
+{
+	BUG_ON(dm_bufio_in_request());
+
+	return new_read(c, block, NF_FRESH, bp);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_new);
+
+void dm_bufio_release(struct dm_buffer *b)
+{
+	struct dm_bufio_client *c = b->c;
+
+	dm_bufio_lock(c);
+
+	BUG_ON(test_bit(B_READING, &b->state));
+	BUG_ON(!b->hold_count);
+
+	b->hold_count--;
+	if (!b->hold_count) {
+		wake_up(&c->free_buffer_wait);
+
+		/*
+		 * If there were errors on the buffer, and the buffer is not
+		 * to be written, free the buffer. There is no point in caching
+		 * invalid buffer.
+		 */
+		if ((b->read_error || b->write_error) &&
+		    !test_bit(B_WRITING, &b->state) &&
+		    !test_bit(B_DIRTY, &b->state)) {
+			__unlink_buffer(b);
+			__free_buffer_wake(b);
+		}
+	}
+
+	dm_bufio_unlock(c);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_release);
+
+void dm_bufio_mark_buffer_dirty(struct dm_buffer *b)
+{
+	struct dm_bufio_client *c = b->c;
+
+	dm_bufio_lock(c);
+
+	if (!test_and_set_bit(B_DIRTY, &b->state))
+		__relink_lru(b, LIST_DIRTY);
+
+	dm_bufio_unlock(c);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_mark_buffer_dirty);
+
+void dm_bufio_write_dirty_buffers_async(struct dm_bufio_client *c)
+{
+	BUG_ON(dm_bufio_in_request());
+
+	dm_bufio_lock(c);
+	__write_dirty_buffers_async(c, 0);
+	dm_bufio_unlock(c);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_write_dirty_buffers_async);
+
+/*
+ * For performance, it is essential that the buffers are written asynchronously
+ * and simultaneously (so that the block layer can merge the writes) and then
+ * waited upon.
+ *
+ * Finally, we flush hardware disk cache.
+ */
+int dm_bufio_write_dirty_buffers(struct dm_bufio_client *c)
+{
+	int a, f;
+	unsigned long buffers_processed = 0;
+	struct dm_buffer *b, *tmp;
+
+	dm_bufio_lock(c);
+	__write_dirty_buffers_async(c, 0);
+
+again:
+	list_for_each_entry_safe_reverse(b, tmp, &c->lru[LIST_DIRTY], lru_list) {
+		int dropped_lock = 0;
+
+		if (buffers_processed < c->n_buffers[LIST_DIRTY])
+			buffers_processed++;
+
+		BUG_ON(test_bit(B_READING, &b->state));
+
+		if (test_bit(B_WRITING, &b->state)) {
+			if (buffers_processed < c->n_buffers[LIST_DIRTY]) {
+				dropped_lock = 1;
+				b->hold_count++;
+				dm_bufio_unlock(c);
+				wait_on_bit(&b->state, B_WRITING,
+					    do_io_schedule,
+					    TASK_UNINTERRUPTIBLE);
+				dm_bufio_lock(c);
+				b->hold_count--;
+			} else
+				wait_on_bit(&b->state, B_WRITING,
+					    do_io_schedule,
+					    TASK_UNINTERRUPTIBLE);
+		}
+
+		if (!test_bit(B_DIRTY, &b->state) &&
+		    !test_bit(B_WRITING, &b->state))
+			__relink_lru(b, LIST_CLEAN);
+
+		dm_bufio_cond_resched();
+
+		/*
+		 * If we dropped the lock, the list is no longer consistent,
+		 * so we must restart the search.
+		 *
+		 * In the most common case, the buffer just processed is
+		 * relinked to the clean list, so we won't loop scanning the
+		 * same buffer again and again.
+		 *
+		 * This may livelock if there is another thread simultaneously
+		 * dirtying buffers, so we count the number of buffers walked
+		 * and if it exceeds the total number of buffers, it means that
+		 * someone is doing some writes simultaneously with us.  In
+		 * this case, stop, dropping the lock.
+		 */
+		if (dropped_lock)
+			goto again;
+	}
+	wake_up(&c->free_buffer_wait);
+	dm_bufio_unlock(c);
+
+	a = xchg(&c->async_write_error, 0);
+	f = dm_bufio_issue_flush(c);
+	if (a)
+		return a;
+
+	return f;
+}
+EXPORT_SYMBOL_GPL(dm_bufio_write_dirty_buffers);
+
+/*
+ * Use dm-io to send and empty barrier flush the device.
+ */
+int dm_bufio_issue_flush(struct dm_bufio_client *c)
+{
+	struct dm_io_request io_req = {
+		.bi_rw = REQ_FLUSH,
+		.mem.type = DM_IO_KMEM,
+		.mem.ptr.addr = NULL,
+		.client = c->dm_io,
+	};
+	struct dm_io_region io_reg = {
+		.bdev = c->bdev,
+		.sector = 0,
+		.count = 0,
+	};
+
+	BUG_ON(dm_bufio_in_request());
+
+	return dm_io(&io_req, 1, &io_reg, NULL);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_issue_flush);
+
+/*
+ * We first delete any other buffer that may be at that new location.
+ *
+ * Then, we write the buffer to the original location if it was dirty.
+ *
+ * Then, if we are the only one who is holding the buffer, relink the buffer
+ * in the hash queue for the new location.
+ *
+ * If there was someone else holding the buffer, we write it to the new
+ * location but not relink it, because that other user needs to have the buffer
+ * at the same place.
+ */
+void dm_bufio_release_move(struct dm_buffer *b, sector_t new_block)
+{
+	struct dm_bufio_client *c = b->c;
+	struct dm_buffer *new;
+
+	BUG_ON(dm_bufio_in_request());
+
+	dm_bufio_lock(c);
+
+retry:
+	new = __find(c, new_block);
+	if (new) {
+		if (new->hold_count) {
+			__wait_for_free_buffer(c);
+			goto retry;
+		}
+
+		/*
+		 * FIXME: Is there any point waiting for a write that's going
+		 * to be overwritten in a bit?
+		 */
+		__make_buffer_clean(new);
+		__unlink_buffer(new);
+		__free_buffer_wake(new);
+	}
+
+	BUG_ON(!b->hold_count);
+	BUG_ON(test_bit(B_READING, &b->state));
+
+	__write_dirty_buffer(b);
+	if (b->hold_count == 1) {
+		wait_on_bit(&b->state, B_WRITING,
+			    do_io_schedule, TASK_UNINTERRUPTIBLE);
+		set_bit(B_DIRTY, &b->state);
+		__unlink_buffer(b);
+		__link_buffer(b, new_block, LIST_DIRTY);
+	} else {
+		sector_t old_block;
+		wait_on_bit_lock(&b->state, B_WRITING,
+				 do_io_schedule, TASK_UNINTERRUPTIBLE);
+		/*
+		 * Relink buffer to "new_block" so that write_callback
+		 * sees "new_block" as a block number.
+		 * After the write, link the buffer back to old_block.
+		 * All this must be done in bufio lock, so that block number
+		 * change isn't visible to other threads.
+		 */
+		old_block = b->block;
+		__unlink_buffer(b);
+		__link_buffer(b, new_block, b->list_mode);
+		submit_io(b, WRITE, new_block, write_endio);
+		wait_on_bit(&b->state, B_WRITING,
+			    do_io_schedule, TASK_UNINTERRUPTIBLE);
+		__unlink_buffer(b);
+		__link_buffer(b, old_block, b->list_mode);
+	}
+
+	dm_bufio_unlock(c);
+	dm_bufio_release(b);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_release_move);
+
+unsigned dm_bufio_get_block_size(struct dm_bufio_client *c)
+{
+	return c->block_size;
+}
+EXPORT_SYMBOL_GPL(dm_bufio_get_block_size);
+
+sector_t dm_bufio_get_device_size(struct dm_bufio_client *c)
+{
+	return i_size_read(c->bdev->bd_inode) >>
+			   (SECTOR_SHIFT + c->sectors_per_block_bits);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_get_device_size);
+
+sector_t dm_bufio_get_block_number(struct dm_buffer *b)
+{
+	return b->block;
+}
+EXPORT_SYMBOL_GPL(dm_bufio_get_block_number);
+
+void *dm_bufio_get_block_data(struct dm_buffer *b)
+{
+	return b->data;
+}
+EXPORT_SYMBOL_GPL(dm_bufio_get_block_data);
+
+void *dm_bufio_get_aux_data(struct dm_buffer *b)
+{
+	return b + 1;
+}
+EXPORT_SYMBOL_GPL(dm_bufio_get_aux_data);
+
+struct dm_bufio_client *dm_bufio_get_client(struct dm_buffer *b)
+{
+	return b->c;
+}
+EXPORT_SYMBOL_GPL(dm_bufio_get_client);
+
+static void drop_buffers(struct dm_bufio_client *c)
+{
+	struct dm_buffer *b;
+	int i;
+
+	BUG_ON(dm_bufio_in_request());
+
+	/*
+	 * An optimization so that the buffers are not written one-by-one.
+	 */
+	dm_bufio_write_dirty_buffers_async(c);
+
+	dm_bufio_lock(c);
+
+	while ((b = __get_unclaimed_buffer(c)))
+		__free_buffer_wake(b);
+
+	for (i = 0; i < LIST_SIZE; i++)
+		list_for_each_entry(b, &c->lru[i], lru_list)
+			DMERR("leaked buffer %llx, hold count %u, list %d",
+			      (unsigned long long)b->block, b->hold_count, i);
+
+	for (i = 0; i < LIST_SIZE; i++)
+		BUG_ON(!list_empty(&c->lru[i]));
+
+	dm_bufio_unlock(c);
+}
+
+/*
+ * Test if the buffer is unused and too old, and commit it.
+ * At if noio is set, we must not do any I/O because we hold
+ * dm_bufio_clients_lock and we would risk deadlock if the I/O gets rerouted to
+ * different bufio client.
+ */
+static int __cleanup_old_buffer(struct dm_buffer *b, gfp_t gfp,
+				unsigned long max_jiffies)
+{
+	if (jiffies - b->last_accessed < max_jiffies)
+		return 1;
+
+	if (!(gfp & __GFP_IO)) {
+		if (test_bit(B_READING, &b->state) ||
+		    test_bit(B_WRITING, &b->state) ||
+		    test_bit(B_DIRTY, &b->state))
+			return 1;
+	}
+
+	if (b->hold_count)
+		return 1;
+
+	__make_buffer_clean(b);
+	__unlink_buffer(b);
+	__free_buffer_wake(b);
+
+	return 0;
+}
+
+static void __scan(struct dm_bufio_client *c, unsigned long nr_to_scan,
+		   struct shrink_control *sc)
+{
+	int l;
+	struct dm_buffer *b, *tmp;
+
+	for (l = 0; l < LIST_SIZE; l++) {
+		list_for_each_entry_safe_reverse(b, tmp, &c->lru[l], lru_list)
+			if (!__cleanup_old_buffer(b, sc->gfp_mask, 0) &&
+			    !--nr_to_scan)
+				return;
+		dm_bufio_cond_resched();
+	}
+}
+
+static int shrink(struct shrinker *shrinker, struct shrink_control *sc)
+{
+	struct dm_bufio_client *c =
+	    container_of(shrinker, struct dm_bufio_client, shrinker);
+	unsigned long r;
+	unsigned long nr_to_scan = sc->nr_to_scan;
+
+	if (sc->gfp_mask & __GFP_IO)
+		dm_bufio_lock(c);
+	else if (!dm_bufio_trylock(c))
+		return !nr_to_scan ? 0 : -1;
+
+	if (nr_to_scan)
+		__scan(c, nr_to_scan, sc);
+
+	r = c->n_buffers[LIST_CLEAN] + c->n_buffers[LIST_DIRTY];
+	if (r > INT_MAX)
+		r = INT_MAX;
+
+	dm_bufio_unlock(c);
+
+	return r;
+}
+
+/*
+ * Create the buffering interface
+ */
+struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsigned block_size,
+					       unsigned reserved_buffers, unsigned aux_size,
+					       void (*alloc_callback)(struct dm_buffer *),
+					       void (*write_callback)(struct dm_buffer *))
+{
+	int r;
+	struct dm_bufio_client *c;
+	unsigned i;
+
+	BUG_ON(block_size < 1 << SECTOR_SHIFT ||
+	       (block_size & (block_size - 1)));
+
+	c = kmalloc(sizeof(*c), GFP_KERNEL);
+	if (!c) {
+		r = -ENOMEM;
+		goto bad_client;
+	}
+	c->cache_hash = vmalloc(sizeof(struct hlist_head) << DM_BUFIO_HASH_BITS);
+	if (!c->cache_hash) {
+		r = -ENOMEM;
+		goto bad_hash;
+	}
+
+	c->bdev = bdev;
+	c->block_size = block_size;
+	c->sectors_per_block_bits = ffs(block_size) - 1 - SECTOR_SHIFT;
+	c->pages_per_block_bits = (ffs(block_size) - 1 >= PAGE_SHIFT) ?
+				  ffs(block_size) - 1 - PAGE_SHIFT : 0;
+	c->blocks_per_page_bits = (ffs(block_size) - 1 < PAGE_SHIFT ?
+				  PAGE_SHIFT - (ffs(block_size) - 1) : 0);
+
+	c->aux_size = aux_size;
+	c->alloc_callback = alloc_callback;
+	c->write_callback = write_callback;
+
+	for (i = 0; i < LIST_SIZE; i++) {
+		INIT_LIST_HEAD(&c->lru[i]);
+		c->n_buffers[i] = 0;
+	}
+
+	for (i = 0; i < 1 << DM_BUFIO_HASH_BITS; i++)
+		INIT_HLIST_HEAD(&c->cache_hash[i]);
+
+	mutex_init(&c->lock);
+	INIT_LIST_HEAD(&c->reserved_buffers);
+	c->need_reserved_buffers = reserved_buffers;
+
+	init_waitqueue_head(&c->free_buffer_wait);
+	c->async_write_error = 0;
+
+	c->dm_io = dm_io_client_create();
+	if (IS_ERR(c->dm_io)) {
+		r = PTR_ERR(c->dm_io);
+		goto bad_dm_io;
+	}
+
+	mutex_lock(&dm_bufio_clients_lock);
+	if (c->blocks_per_page_bits) {
+		if (!DM_BUFIO_CACHE_NAME(c)) {
+			DM_BUFIO_CACHE_NAME(c) = kasprintf(GFP_KERNEL, "dm_bufio_cache-%u", c->block_size);
+			if (!DM_BUFIO_CACHE_NAME(c)) {
+				r = -ENOMEM;
+				mutex_unlock(&dm_bufio_clients_lock);
+				goto bad_cache;
+			}
+		}
+
+		if (!DM_BUFIO_CACHE(c)) {
+			DM_BUFIO_CACHE(c) = kmem_cache_create(DM_BUFIO_CACHE_NAME(c),
+							      c->block_size,
+							      c->block_size, 0, NULL);
+			if (!DM_BUFIO_CACHE(c)) {
+				r = -ENOMEM;
+				mutex_unlock(&dm_bufio_clients_lock);
+				goto bad_cache;
+			}
+		}
+	}
+	mutex_unlock(&dm_bufio_clients_lock);
+
+	while (c->need_reserved_buffers) {
+		struct dm_buffer *b = alloc_buffer(c, GFP_KERNEL);
+
+		if (!b) {
+			r = -ENOMEM;
+			goto bad_buffer;
+		}
+		__free_buffer_wake(b);
+	}
+
+	mutex_lock(&dm_bufio_clients_lock);
+	dm_bufio_client_count++;
+	list_add(&c->client_list, &dm_bufio_all_clients);
+	__cache_size_refresh();
+	mutex_unlock(&dm_bufio_clients_lock);
+
+	c->shrinker.shrink = shrink;
+	c->shrinker.seeks = 1;
+	c->shrinker.batch = 0;
+	register_shrinker(&c->shrinker);
+
+	return c;
+
+bad_buffer:
+bad_cache:
+	while (!list_empty(&c->reserved_buffers)) {
+		struct dm_buffer *b = list_entry(c->reserved_buffers.next,
+						 struct dm_buffer, lru_list);
+		list_del(&b->lru_list);
+		free_buffer(b);
+	}
+	dm_io_client_destroy(c->dm_io);
+bad_dm_io:
+	vfree(c->cache_hash);
+bad_hash:
+	kfree(c);
+bad_client:
+	return ERR_PTR(r);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_client_create);
+
+/*
+ * Free the buffering interface.
+ * It is required that there are no references on any buffers.
+ */
+void dm_bufio_client_destroy(struct dm_bufio_client *c)
+{
+	unsigned i;
+
+	drop_buffers(c);
+
+	unregister_shrinker(&c->shrinker);
+
+	mutex_lock(&dm_bufio_clients_lock);
+
+	list_del(&c->client_list);
+	dm_bufio_client_count--;
+	__cache_size_refresh();
+
+	mutex_unlock(&dm_bufio_clients_lock);
+
+	for (i = 0; i < 1 << DM_BUFIO_HASH_BITS; i++)
+		BUG_ON(!hlist_empty(&c->cache_hash[i]));
+
+	BUG_ON(c->need_reserved_buffers);
+
+	while (!list_empty(&c->reserved_buffers)) {
+		struct dm_buffer *b = list_entry(c->reserved_buffers.next,
+						 struct dm_buffer, lru_list);
+		list_del(&b->lru_list);
+		free_buffer(b);
+	}
+
+	for (i = 0; i < LIST_SIZE; i++)
+		if (c->n_buffers[i])
+			DMERR("leaked buffer count %d: %ld", i, c->n_buffers[i]);
+
+	for (i = 0; i < LIST_SIZE; i++)
+		BUG_ON(c->n_buffers[i]);
+
+	dm_io_client_destroy(c->dm_io);
+	vfree(c->cache_hash);
+	kfree(c);
+}
+EXPORT_SYMBOL_GPL(dm_bufio_client_destroy);
+
+static void cleanup_old_buffers(void)
+{
+	unsigned long max_age = dm_bufio_max_age;
+	struct dm_bufio_client *c;
+
+	barrier();
+
+	if (max_age > ULONG_MAX / HZ)
+		max_age = ULONG_MAX / HZ;
+
+	mutex_lock(&dm_bufio_clients_lock);
+	list_for_each_entry(c, &dm_bufio_all_clients, client_list) {
+		if (!dm_bufio_trylock(c))
+			continue;
+
+		while (!list_empty(&c->lru[LIST_CLEAN])) {
+			struct dm_buffer *b;
+			b = list_entry(c->lru[LIST_CLEAN].prev,
+				       struct dm_buffer, lru_list);
+			if (__cleanup_old_buffer(b, 0, max_age * HZ))
+				break;
+			dm_bufio_cond_resched();
+		}
+
+		dm_bufio_unlock(c);
+		dm_bufio_cond_resched();
+	}
+	mutex_unlock(&dm_bufio_clients_lock);
+}
+
+static struct workqueue_struct *dm_bufio_wq;
+static struct delayed_work dm_bufio_work;
+
+static void work_fn(struct work_struct *w)
+{
+	cleanup_old_buffers();
+
+	queue_delayed_work(dm_bufio_wq, &dm_bufio_work,
+			   DM_BUFIO_WORK_TIMER_SECS * HZ);
+}
+
+/*----------------------------------------------------------------
+ * Module setup
+ *--------------------------------------------------------------*/
+
+/*
+ * This is called only once for the whole dm_bufio module.
+ * It initializes memory limit.
+ */
+static int __init dm_bufio_init(void)
+{
+	__u64 mem;
+
+	memset(&dm_bufio_caches, 0, sizeof dm_bufio_caches);
+	memset(&dm_bufio_cache_names, 0, sizeof dm_bufio_cache_names);
+
+	mem = (__u64)((totalram_pages - totalhigh_pages) *
+		      DM_BUFIO_MEMORY_PERCENT / 100) << PAGE_SHIFT;
+
+	if (mem > ULONG_MAX)
+		mem = ULONG_MAX;
+
+#ifdef CONFIG_MMU
+	/*
+	 * Get the size of vmalloc space the same way as VMALLOC_TOTAL
+	 * in fs/proc/internal.h
+	 */
+	if (mem > (VMALLOC_END - VMALLOC_START) * DM_BUFIO_VMALLOC_PERCENT / 100)
+		mem = (VMALLOC_END - VMALLOC_START) * DM_BUFIO_VMALLOC_PERCENT / 100;
+#endif
+
+	dm_bufio_default_cache_size = mem;
+
+	mutex_lock(&dm_bufio_clients_lock);
+	__cache_size_refresh();
+	mutex_unlock(&dm_bufio_clients_lock);
+
+	dm_bufio_wq = create_singlethread_workqueue("dm_bufio_cache");
+	if (!dm_bufio_wq)
+		return -ENOMEM;
+
+	INIT_DELAYED_WORK(&dm_bufio_work, work_fn);
+	queue_delayed_work(dm_bufio_wq, &dm_bufio_work,
+			   DM_BUFIO_WORK_TIMER_SECS * HZ);
+
+	return 0;
+}
+
+/*
+ * This is called once when unloading the dm_bufio module.
+ */
+static void __exit dm_bufio_exit(void)
+{
+	int bug = 0;
+	int i;
+
+	cancel_delayed_work_sync(&dm_bufio_work);
+	destroy_workqueue(dm_bufio_wq);
+
+	for (i = 0; i < ARRAY_SIZE(dm_bufio_caches); i++) {
+		struct kmem_cache *kc = dm_bufio_caches[i];
+
+		if (kc)
+			kmem_cache_destroy(kc);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(dm_bufio_cache_names); i++)
+		kfree(dm_bufio_cache_names[i]);
+
+	if (dm_bufio_client_count) {
+		DMCRIT("%s: dm_bufio_client_count leaked: %d",
+			__func__, dm_bufio_client_count);
+		bug = 1;
+	}
+
+	if (dm_bufio_current_allocated) {
+		DMCRIT("%s: dm_bufio_current_allocated leaked: %lu",
+			__func__, dm_bufio_current_allocated);
+		bug = 1;
+	}
+
+	if (dm_bufio_allocated_get_free_pages) {
+		DMCRIT("%s: dm_bufio_allocated_get_free_pages leaked: %lu",
+		       __func__, dm_bufio_allocated_get_free_pages);
+		bug = 1;
+	}
+
+	if (dm_bufio_allocated_vmalloc) {
+		DMCRIT("%s: dm_bufio_vmalloc leaked: %lu",
+		       __func__, dm_bufio_allocated_vmalloc);
+		bug = 1;
+	}
+
+	if (bug)
+		BUG();
+}
+
+module_init(dm_bufio_init)
+module_exit(dm_bufio_exit)
+
+module_param_named(max_cache_size_bytes, dm_bufio_cache_size, ulong, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(max_cache_size_bytes, "Size of metadata cache");
+
+module_param_named(max_age_seconds, dm_bufio_max_age, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(max_age_seconds, "Max age of a buffer in seconds");
+
+module_param_named(peak_allocated_bytes, dm_bufio_peak_allocated, ulong, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(peak_allocated_bytes, "Tracks the maximum allocated memory");
+
+module_param_named(allocated_kmem_cache_bytes, dm_bufio_allocated_kmem_cache, ulong, S_IRUGO);
+MODULE_PARM_DESC(allocated_kmem_cache_bytes, "Memory allocated with kmem_cache_alloc");
+
+module_param_named(allocated_get_free_pages_bytes, dm_bufio_allocated_get_free_pages, ulong, S_IRUGO);
+MODULE_PARM_DESC(allocated_get_free_pages_bytes, "Memory allocated with get_free_pages");
+
+module_param_named(allocated_vmalloc_bytes, dm_bufio_allocated_vmalloc, ulong, S_IRUGO);
+MODULE_PARM_DESC(allocated_vmalloc_bytes, "Memory allocated with vmalloc");
+
+module_param_named(current_allocated_bytes, dm_bufio_current_allocated, ulong, S_IRUGO);
+MODULE_PARM_DESC(current_allocated_bytes, "Memory currently used by the cache");
+
+MODULE_AUTHOR("Mikulas Patocka <dm-devel@redhat.com>");
+MODULE_DESCRIPTION(DM_NAME " buffered I/O library");
+MODULE_LICENSE("GPL");
diff --git a/drivers/md/dm-bufio.h b/drivers/md/dm-bufio.h
new file mode 100644
index 0000000..5c4c3a0
--- /dev/null
+++ b/drivers/md/dm-bufio.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2009-2011 Red Hat, Inc.
+ *
+ * Author: Mikulas Patocka <mpatocka@redhat.com>
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef DM_BUFIO_H
+#define DM_BUFIO_H
+
+#include <linux/blkdev.h>
+#include <linux/types.h>
+
+/*----------------------------------------------------------------*/
+
+struct dm_bufio_client;
+struct dm_buffer;
+
+/*
+ * Create a buffered IO cache on a given device
+ */
+struct dm_bufio_client *
+dm_bufio_client_create(struct block_device *bdev, unsigned block_size,
+		       unsigned reserved_buffers, unsigned aux_size,
+		       void (*alloc_callback)(struct dm_buffer *),
+		       void (*write_callback)(struct dm_buffer *));
+
+/*
+ * Release a buffered IO cache.
+ */
+void dm_bufio_client_destroy(struct dm_bufio_client *c);
+
+/*
+ * WARNING: to avoid deadlocks, these conditions are observed:
+ *
+ * - At most one thread can hold at most "reserved_buffers" simultaneously.
+ * - Each other threads can hold at most one buffer.
+ * - Threads which call only dm_bufio_get can hold unlimited number of
+ *   buffers.
+ */
+
+/*
+ * Read a given block from disk. Returns pointer to data.  Returns a
+ * pointer to dm_buffer that can be used to release the buffer or to make
+ * it dirty.
+ */
+void *dm_bufio_read(struct dm_bufio_client *c, sector_t block,
+		    struct dm_buffer **bp);
+
+/*
+ * Like dm_bufio_read, but return buffer from cache, don't read
+ * it. If the buffer is not in the cache, return NULL.
+ */
+void *dm_bufio_get(struct dm_bufio_client *c, sector_t block,
+		   struct dm_buffer **bp);
+
+/*
+ * Like dm_bufio_read, but don't read anything from the disk.  It is
+ * expected that the caller initializes the buffer and marks it dirty.
+ */
+void *dm_bufio_new(struct dm_bufio_client *c, sector_t block,
+		   struct dm_buffer **bp);
+
+/*
+ * Release a reference obtained with dm_bufio_{read,get,new}. The data
+ * pointer and dm_buffer pointer is no longer valid after this call.
+ */
+void dm_bufio_release(struct dm_buffer *b);
+
+/*
+ * Mark a buffer dirty. It should be called after the buffer is modified.
+ *
+ * In case of memory pressure, the buffer may be written after
+ * dm_bufio_mark_buffer_dirty, but before dm_bufio_write_dirty_buffers.  So
+ * dm_bufio_write_dirty_buffers guarantees that the buffer is on-disk but
+ * the actual writing may occur earlier.
+ */
+void dm_bufio_mark_buffer_dirty(struct dm_buffer *b);
+
+/*
+ * Initiate writing of dirty buffers, without waiting for completion.
+ */
+void dm_bufio_write_dirty_buffers_async(struct dm_bufio_client *c);
+
+/*
+ * Write all dirty buffers. Guarantees that all dirty buffers created prior
+ * to this call are on disk when this call exits.
+ */
+int dm_bufio_write_dirty_buffers(struct dm_bufio_client *c);
+
+/*
+ * Send an empty write barrier to the device to flush hardware disk cache.
+ */
+int dm_bufio_issue_flush(struct dm_bufio_client *c);
+
+/*
+ * Like dm_bufio_release but also move the buffer to the new
+ * block. dm_bufio_write_dirty_buffers is needed to commit the new block.
+ */
+void dm_bufio_release_move(struct dm_buffer *b, sector_t new_block);
+
+unsigned dm_bufio_get_block_size(struct dm_bufio_client *c);
+sector_t dm_bufio_get_device_size(struct dm_bufio_client *c);
+sector_t dm_bufio_get_block_number(struct dm_buffer *b);
+void *dm_bufio_get_block_data(struct dm_buffer *b);
+void *dm_bufio_get_aux_data(struct dm_buffer *b);
+struct dm_bufio_client *dm_bufio_get_client(struct dm_buffer *b);
+
+/*----------------------------------------------------------------*/
+
+#endif
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 2e9a3ca..31c2dc2 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1215,6 +1215,7 @@ static int table_load(struct dm_ioctl *param, size_t param_size)
 	struct hash_cell *hc;
 	struct dm_table *t;
 	struct mapped_device *md;
+	struct target_type *immutable_target_type;
 
 	md = find_device(param);
 	if (!md)
@@ -1230,6 +1231,16 @@ static int table_load(struct dm_ioctl *param, size_t param_size)
 		goto out;
 	}
 
+	immutable_target_type = dm_get_immutable_target_type(md);
+	if (immutable_target_type &&
+	    (immutable_target_type != dm_table_get_immutable_target_type(t))) {
+		DMWARN("can't replace immutable target type %s",
+		       immutable_target_type->name);
+		dm_table_destroy(t);
+		r = -EINVAL;
+		goto out;
+	}
+
 	/* Protect md->type and md->queue against concurrent table loads. */
 	dm_lock_md_type(md);
 	if (dm_get_md_type(md) == DM_TYPE_NONE)
diff --git a/drivers/md/dm-kcopyd.c b/drivers/md/dm-kcopyd.c
index 32ac708..bed444c 100644
--- a/drivers/md/dm-kcopyd.c
+++ b/drivers/md/dm-kcopyd.c
@@ -66,6 +66,8 @@ struct dm_kcopyd_client {
 	struct list_head pages_jobs;
 };
 
+static struct page_list zero_page_list;
+
 static void wake(struct dm_kcopyd_client *kc)
 {
 	queue_work(kc->kcopyd_wq, &kc->kcopyd_work);
@@ -254,6 +256,9 @@ int __init dm_kcopyd_init(void)
 	if (!_job_cache)
 		return -ENOMEM;
 
+	zero_page_list.next = &zero_page_list;
+	zero_page_list.page = ZERO_PAGE(0);
+
 	return 0;
 }
 
@@ -322,7 +327,7 @@ static int run_complete_job(struct kcopyd_job *job)
 	dm_kcopyd_notify_fn fn = job->fn;
 	struct dm_kcopyd_client *kc = job->kc;
 
-	if (job->pages)
+	if (job->pages && job->pages != &zero_page_list)
 		kcopyd_put_pages(kc, job->pages);
 	/*
 	 * If this is the master job, the sub jobs have already
@@ -484,6 +489,8 @@ static void dispatch_job(struct kcopyd_job *job)
 	atomic_inc(&kc->nr_jobs);
 	if (unlikely(!job->source.count))
 		push(&kc->complete_jobs, job);
+	else if (job->pages == &zero_page_list)
+		push(&kc->io_jobs, job);
 	else
 		push(&kc->pages_jobs, job);
 	wake(kc);
@@ -592,14 +599,20 @@ int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
 	job->flags = flags;
 	job->read_err = 0;
 	job->write_err = 0;
-	job->rw = READ;
-
-	job->source = *from;
 
 	job->num_dests = num_dests;
 	memcpy(&job->dests, dests, sizeof(*dests) * num_dests);
 
-	job->pages = NULL;
+	if (from) {
+		job->source = *from;
+		job->pages = NULL;
+		job->rw = READ;
+	} else {
+		memset(&job->source, 0, sizeof job->source);
+		job->source.count = job->dests[0].count;
+		job->pages = &zero_page_list;
+		job->rw = WRITE;
+	}
 
 	job->fn = fn;
 	job->context = context;
@@ -617,6 +630,14 @@ int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
 }
 EXPORT_SYMBOL(dm_kcopyd_copy);
 
+int dm_kcopyd_zero(struct dm_kcopyd_client *kc,
+		   unsigned num_dests, struct dm_io_region *dests,
+		   unsigned flags, dm_kcopyd_notify_fn fn, void *context)
+{
+	return dm_kcopyd_copy(kc, NULL, num_dests, dests, flags, fn, context);
+}
+EXPORT_SYMBOL(dm_kcopyd_zero);
+
 void *dm_kcopyd_prepare_callback(struct dm_kcopyd_client *kc,
 				 dm_kcopyd_notify_fn fn, void *context)
 {
diff --git a/drivers/md/dm-log-userspace-base.c b/drivers/md/dm-log-userspace-base.c
index 1021c89..8db3862 100644
--- a/drivers/md/dm-log-userspace-base.c
+++ b/drivers/md/dm-log-userspace-base.c
@@ -30,6 +30,7 @@ struct flush_entry {
 
 struct log_c {
 	struct dm_target *ti;
+	struct dm_dev *log_dev;
 	uint32_t region_size;
 	region_t region_count;
 	uint64_t luid;
@@ -146,7 +147,7 @@ static int build_constructor_string(struct dm_target *ti,
  *	<UUID> <other args>
  * Where 'other args' is the userspace implementation specific log
  * arguments.  An example might be:
- *	<UUID> clustered_disk <arg count> <log dev> <region_size> [[no]sync]
+ *	<UUID> clustered-disk <arg count> <log dev> <region_size> [[no]sync]
  *
  * So, this module will strip off the <UUID> for identification purposes
  * when communicating with userspace about a log; but will pass on everything
@@ -161,13 +162,15 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti,
 	struct log_c *lc = NULL;
 	uint64_t rdata;
 	size_t rdata_size = sizeof(rdata);
+	char *devices_rdata = NULL;
+	size_t devices_rdata_size = DM_NAME_LEN;
 
 	if (argc < 3) {
 		DMWARN("Too few arguments to userspace dirty log");
 		return -EINVAL;
 	}
 
-	lc = kmalloc(sizeof(*lc), GFP_KERNEL);
+	lc = kzalloc(sizeof(*lc), GFP_KERNEL);
 	if (!lc) {
 		DMWARN("Unable to allocate userspace log context.");
 		return -ENOMEM;
@@ -195,9 +198,19 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti,
 		return str_size;
 	}
 
-	/* Send table string */
+	devices_rdata = kzalloc(devices_rdata_size, GFP_KERNEL);
+	if (!devices_rdata) {
+		DMERR("Failed to allocate memory for device information");
+		r = -ENOMEM;
+		goto out;
+	}
+
+	/*
+	 * Send table string and get back any opened device.
+	 */
 	r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_CTR,
-				 ctr_str, str_size, NULL, NULL);
+				 ctr_str, str_size,
+				 devices_rdata, &devices_rdata_size);
 
 	if (r < 0) {
 		if (r == -ESRCH)
@@ -220,7 +233,20 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti,
 	lc->region_size = (uint32_t)rdata;
 	lc->region_count = dm_sector_div_up(ti->len, lc->region_size);
 
+	if (devices_rdata_size) {
+		if (devices_rdata[devices_rdata_size - 1] != '\0') {
+			DMERR("DM_ULOG_CTR device return string not properly terminated");
+			r = -EINVAL;
+			goto out;
+		}
+		r = dm_get_device(ti, devices_rdata,
+				  dm_table_get_mode(ti->table), &lc->log_dev);
+		if (r)
+			DMERR("Failed to register %s with device-mapper",
+			      devices_rdata);
+	}
 out:
+	kfree(devices_rdata);
 	if (r) {
 		kfree(lc);
 		kfree(ctr_str);
@@ -241,6 +267,9 @@ static void userspace_dtr(struct dm_dirty_log *log)
 				 NULL, 0,
 				 NULL, NULL);
 
+	if (lc->log_dev)
+		dm_put_device(lc->ti, lc->log_dev);
+
 	kfree(lc->usr_argv_str);
 	kfree(lc);
 
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index 37a3726..11fa96d 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -1017,30 +1017,56 @@ static int raid_status(struct dm_target *ti, status_type_t type,
 	struct raid_set *rs = ti->private;
 	unsigned raid_param_cnt = 1; /* at least 1 for chunksize */
 	unsigned sz = 0;
-	int i;
+	int i, array_in_sync = 0;
 	sector_t sync;
 
 	switch (type) {
 	case STATUSTYPE_INFO:
 		DMEMIT("%s %d ", rs->raid_type->name, rs->md.raid_disks);
 
-		for (i = 0; i < rs->md.raid_disks; i++) {
-			if (test_bit(Faulty, &rs->dev[i].rdev.flags))
-				DMEMIT("D");
-			else if (test_bit(In_sync, &rs->dev[i].rdev.flags))
-				DMEMIT("A");
-			else
-				DMEMIT("a");
-		}
-
 		if (test_bit(MD_RECOVERY_RUNNING, &rs->md.recovery))
 			sync = rs->md.curr_resync_completed;
 		else
 			sync = rs->md.recovery_cp;
 
-		if (sync > rs->md.resync_max_sectors)
+		if (sync >= rs->md.resync_max_sectors) {
+			array_in_sync = 1;
 			sync = rs->md.resync_max_sectors;
+		} else {
+			/*
+			 * The array may be doing an initial sync, or it may
+			 * be rebuilding individual components.  If all the
+			 * devices are In_sync, then it is the array that is
+			 * being initialized.
+			 */
+			for (i = 0; i < rs->md.raid_disks; i++)
+				if (!test_bit(In_sync, &rs->dev[i].rdev.flags))
+					array_in_sync = 1;
+		}
+		/*
+		 * Status characters:
+		 *  'D' = Dead/Failed device
+		 *  'a' = Alive but not in-sync
+		 *  'A' = Alive and in-sync
+		 */
+		for (i = 0; i < rs->md.raid_disks; i++) {
+			if (test_bit(Faulty, &rs->dev[i].rdev.flags))
+				DMEMIT("D");
+			else if (!array_in_sync ||
+				 !test_bit(In_sync, &rs->dev[i].rdev.flags))
+				DMEMIT("a");
+			else
+				DMEMIT("A");
+		}
 
+		/*
+		 * In-sync ratio:
+		 *  The in-sync ratio shows the progress of:
+		 *   - Initializing the array
+		 *   - Rebuilding a subset of devices of the array
+		 *  The user can distinguish between the two by referring
+		 *  to the status characters.
+		 */
 		DMEMIT(" %llu/%llu",
 		       (unsigned long long) sync,
 		       (unsigned long long) rs->md.resync_max_sectors);
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index bc04518..8e91321 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -54,7 +54,9 @@ struct dm_table {
 	sector_t *highs;
 	struct dm_target *targets;
 
+	struct target_type *immutable_target_type;
 	unsigned integrity_supported:1;
+	unsigned singleton:1;
 
 	/*
 	 * Indicates the rw permissions for the new logical
@@ -740,6 +742,12 @@ int dm_table_add_target(struct dm_table *t, const char *type,
 	char **argv;
 	struct dm_target *tgt;
 
+	if (t->singleton) {
+		DMERR("%s: target type %s must appear alone in table",
+		      dm_device_name(t->md), t->targets->type->name);
+		return -EINVAL;
+	}
+
 	if ((r = check_space(t)))
 		return r;
 
@@ -758,6 +766,36 @@ int dm_table_add_target(struct dm_table *t, const char *type,
 		return -EINVAL;
 	}
 
+	if (dm_target_needs_singleton(tgt->type)) {
+		if (t->num_targets) {
+			DMERR("%s: target type %s must appear alone in table",
+			      dm_device_name(t->md), type);
+			return -EINVAL;
+		}
+		t->singleton = 1;
+	}
+
+	if (dm_target_always_writeable(tgt->type) && !(t->mode & FMODE_WRITE)) {
+		DMERR("%s: target type %s may not be included in read-only tables",
+		      dm_device_name(t->md), type);
+		return -EINVAL;
+	}
+
+	if (t->immutable_target_type) {
+		if (t->immutable_target_type != tgt->type) {
+			DMERR("%s: immutable target type %s cannot be mixed with other target types",
+			      dm_device_name(t->md), t->immutable_target_type->name);
+			return -EINVAL;
+		}
+	} else if (dm_target_is_immutable(tgt->type)) {
+		if (t->num_targets) {
+			DMERR("%s: immutable target type %s cannot be mixed with other target types",
+			      dm_device_name(t->md), tgt->type->name);
+			return -EINVAL;
+		}
+		t->immutable_target_type = tgt->type;
+	}
+
 	tgt->table = t;
 	tgt->begin = start;
 	tgt->len = len;
@@ -915,6 +953,11 @@ unsigned dm_table_get_type(struct dm_table *t)
 	return t->type;
 }
 
+struct target_type *dm_table_get_immutable_target_type(struct dm_table *t)
+{
+	return t->immutable_target_type;
+}
+
 bool dm_table_request_based(struct dm_table *t)
 {
 	return dm_table_get_type(t) == DM_TYPE_REQUEST_BASED;
@@ -1299,6 +1342,31 @@ static bool dm_table_discard_zeroes_data(struct dm_table *t)
 	return 1;
 }
 
+static int device_is_nonrot(struct dm_target *ti, struct dm_dev *dev,
+			    sector_t start, sector_t len, void *data)
+{
+	struct request_queue *q = bdev_get_queue(dev->bdev);
+
+	return q && blk_queue_nonrot(q);
+}
+
+static bool dm_table_is_nonrot(struct dm_table *t)
+{
+	struct dm_target *ti;
+	unsigned i = 0;
+
+	/* Ensure that all underlying device are non-rotational. */
+	while (i < dm_table_get_num_targets(t)) {
+		ti = dm_table_get_target(t, i++);
+
+		if (!ti->type->iterate_devices ||
+		    !ti->type->iterate_devices(ti, device_is_nonrot, NULL))
+			return 0;
+	}
+
+	return 1;
+}
+
 void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
 			       struct queue_limits *limits)
 {
@@ -1324,6 +1392,11 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
 	if (!dm_table_discard_zeroes_data(t))
 		q->limits.discard_zeroes_data = 0;
 
+	if (dm_table_is_nonrot(t))
+		queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q);
+	else
+		queue_flag_clear_unlocked(QUEUE_FLAG_NONROT, q);
+
 	dm_table_set_integrity(t);
 
 	/*
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
new file mode 100644
index 0000000..59c4f04
--- /dev/null
+++ b/drivers/md/dm-thin-metadata.c
@@ -0,0 +1,1391 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-thin-metadata.h"
+#include "persistent-data/dm-btree.h"
+#include "persistent-data/dm-space-map.h"
+#include "persistent-data/dm-space-map-disk.h"
+#include "persistent-data/dm-transaction-manager.h"
+
+#include <linux/list.h>
+#include <linux/device-mapper.h>
+#include <linux/workqueue.h>
+
+/*--------------------------------------------------------------------------
+ * As far as the metadata goes, there is:
+ *
+ * - A superblock in block zero, taking up fewer than 512 bytes for
+ *   atomic writes.
+ *
+ * - A space map managing the metadata blocks.
+ *
+ * - A space map managing the data blocks.
+ *
+ * - A btree mapping our internal thin dev ids onto struct disk_device_details.
+ *
+ * - A hierarchical btree, with 2 levels which effectively maps (thin
+ *   dev id, virtual block) -> block_time.  Block time is a 64-bit
+ *   field holding the time in the low 24 bits, and block in the top 48
+ *   bits.
+ *
+ * BTrees consist solely of btree_nodes, that fill a block.  Some are
+ * internal nodes, as such their values are a __le64 pointing to other
+ * nodes.  Leaf nodes can store data of any reasonable size (ie. much
+ * smaller than the block size).  The nodes consist of the header,
+ * followed by an array of keys, followed by an array of values.  We have
+ * to binary search on the keys so they're all held together to help the
+ * cpu cache.
+ *
+ * Space maps have 2 btrees:
+ *
+ * - One maps a uint64_t onto a struct index_entry.  Which points to a
+ *   bitmap block, and has some details about how many free entries there
+ *   are etc.
+ *
+ * - The bitmap blocks have a header (for the checksum).  Then the rest
+ *   of the block is pairs of bits.  With the meaning being:
+ *
+ *   0 - ref count is 0
+ *   1 - ref count is 1
+ *   2 - ref count is 2
+ *   3 - ref count is higher than 2
+ *
+ * - If the count is higher than 2 then the ref count is entered in a
+ *   second btree that directly maps the block_address to a uint32_t ref
+ *   count.
+ *
+ * The space map metadata variant doesn't have a bitmaps btree.  Instead
+ * it has one single blocks worth of index_entries.  This avoids
+ * recursive issues with the bitmap btree needing to allocate space in
+ * order to insert.  With a small data block size such as 64k the
+ * metadata support data devices that are hundreds of terrabytes.
+ *
+ * The space maps allocate space linearly from front to back.  Space that
+ * is freed in a transaction is never recycled within that transaction.
+ * To try and avoid fragmenting _free_ space the allocator always goes
+ * back and fills in gaps.
+ *
+ * All metadata io is in THIN_METADATA_BLOCK_SIZE sized/aligned chunks
+ * from the block manager.
+ *--------------------------------------------------------------------------*/
+
+#define DM_MSG_PREFIX   "thin metadata"
+
+#define THIN_SUPERBLOCK_MAGIC 27022010
+#define THIN_SUPERBLOCK_LOCATION 0
+#define THIN_VERSION 1
+#define THIN_METADATA_CACHE_SIZE 64
+#define SECTOR_TO_BLOCK_SHIFT 3
+
+/* This should be plenty */
+#define SPACE_MAP_ROOT_SIZE 128
+
+/*
+ * Little endian on-disk superblock and device details.
+ */
+struct thin_disk_superblock {
+	__le32 csum;	/* Checksum of superblock except for this field. */
+	__le32 flags;
+	__le64 blocknr;	/* This block number, dm_block_t. */
+
+	__u8 uuid[16];
+	__le64 magic;
+	__le32 version;
+	__le32 time;
+
+	__le64 trans_id;
+
+	/*
+	 * Root held by userspace transactions.
+	 */
+	__le64 held_root;
+
+	__u8 data_space_map_root[SPACE_MAP_ROOT_SIZE];
+	__u8 metadata_space_map_root[SPACE_MAP_ROOT_SIZE];
+
+	/*
+	 * 2-level btree mapping (dev_id, (dev block, time)) -> data block
+	 */
+	__le64 data_mapping_root;
+
+	/*
+	 * Device detail root mapping dev_id -> device_details
+	 */
+	__le64 device_details_root;
+
+	__le32 data_block_size;		/* In 512-byte sectors. */
+
+	__le32 metadata_block_size;	/* In 512-byte sectors. */
+	__le64 metadata_nr_blocks;
+
+	__le32 compat_flags;
+	__le32 compat_ro_flags;
+	__le32 incompat_flags;
+} __packed;
+
+struct disk_device_details {
+	__le64 mapped_blocks;
+	__le64 transaction_id;		/* When created. */
+	__le32 creation_time;
+	__le32 snapshotted_time;
+} __packed;
+
+struct dm_pool_metadata {
+	struct hlist_node hash;
+
+	struct block_device *bdev;
+	struct dm_block_manager *bm;
+	struct dm_space_map *metadata_sm;
+	struct dm_space_map *data_sm;
+	struct dm_transaction_manager *tm;
+	struct dm_transaction_manager *nb_tm;
+
+	/*
+	 * Two-level btree.
+	 * First level holds thin_dev_t.
+	 * Second level holds mappings.
+	 */
+	struct dm_btree_info info;
+
+	/*
+	 * Non-blocking version of the above.
+	 */
+	struct dm_btree_info nb_info;
+
+	/*
+	 * Just the top level for deleting whole devices.
+	 */
+	struct dm_btree_info tl_info;
+
+	/*
+	 * Just the bottom level for creating new devices.
+	 */
+	struct dm_btree_info bl_info;
+
+	/*
+	 * Describes the device details btree.
+	 */
+	struct dm_btree_info details_info;
+
+	struct rw_semaphore root_lock;
+	uint32_t time;
+	int need_commit;
+	dm_block_t root;
+	dm_block_t details_root;
+	struct list_head thin_devices;
+	uint64_t trans_id;
+	unsigned long flags;
+	sector_t data_block_size;
+};
+
+struct dm_thin_device {
+	struct list_head list;
+	struct dm_pool_metadata *pmd;
+	dm_thin_id id;
+
+	int open_count;
+	int changed;
+	uint64_t mapped_blocks;
+	uint64_t transaction_id;
+	uint32_t creation_time;
+	uint32_t snapshotted_time;
+};
+
+/*----------------------------------------------------------------
+ * superblock validator
+ *--------------------------------------------------------------*/
+
+#define SUPERBLOCK_CSUM_XOR 160774
+
+static void sb_prepare_for_write(struct dm_block_validator *v,
+				 struct dm_block *b,
+				 size_t block_size)
+{
+	struct thin_disk_superblock *disk_super = dm_block_data(b);
+
+	disk_super->blocknr = cpu_to_le64(dm_block_location(b));
+	disk_super->csum = cpu_to_le32(dm_bm_checksum(&disk_super->flags,
+						      block_size - sizeof(__le32),
+						      SUPERBLOCK_CSUM_XOR));
+}
+
+static int sb_check(struct dm_block_validator *v,
+		    struct dm_block *b,
+		    size_t block_size)
+{
+	struct thin_disk_superblock *disk_super = dm_block_data(b);
+	__le32 csum_le;
+
+	if (dm_block_location(b) != le64_to_cpu(disk_super->blocknr)) {
+		DMERR("sb_check failed: blocknr %llu: "
+		      "wanted %llu", le64_to_cpu(disk_super->blocknr),
+		      (unsigned long long)dm_block_location(b));
+		return -ENOTBLK;
+	}
+
+	if (le64_to_cpu(disk_super->magic) != THIN_SUPERBLOCK_MAGIC) {
+		DMERR("sb_check failed: magic %llu: "
+		      "wanted %llu", le64_to_cpu(disk_super->magic),
+		      (unsigned long long)THIN_SUPERBLOCK_MAGIC);
+		return -EILSEQ;
+	}
+
+	csum_le = cpu_to_le32(dm_bm_checksum(&disk_super->flags,
+					     block_size - sizeof(__le32),
+					     SUPERBLOCK_CSUM_XOR));
+	if (csum_le != disk_super->csum) {
+		DMERR("sb_check failed: csum %u: wanted %u",
+		      le32_to_cpu(csum_le), le32_to_cpu(disk_super->csum));
+		return -EILSEQ;
+	}
+
+	return 0;
+}
+
+static struct dm_block_validator sb_validator = {
+	.name = "superblock",
+	.prepare_for_write = sb_prepare_for_write,
+	.check = sb_check
+};
+
+/*----------------------------------------------------------------
+ * Methods for the btree value types
+ *--------------------------------------------------------------*/
+
+static uint64_t pack_block_time(dm_block_t b, uint32_t t)
+{
+	return (b << 24) | t;
+}
+
+static void unpack_block_time(uint64_t v, dm_block_t *b, uint32_t *t)
+{
+	*b = v >> 24;
+	*t = v & ((1 << 24) - 1);
+}
+
+static void data_block_inc(void *context, void *value_le)
+{
+	struct dm_space_map *sm = context;
+	__le64 v_le;
+	uint64_t b;
+	uint32_t t;
+
+	memcpy(&v_le, value_le, sizeof(v_le));
+	unpack_block_time(le64_to_cpu(v_le), &b, &t);
+	dm_sm_inc_block(sm, b);
+}
+
+static void data_block_dec(void *context, void *value_le)
+{
+	struct dm_space_map *sm = context;
+	__le64 v_le;
+	uint64_t b;
+	uint32_t t;
+
+	memcpy(&v_le, value_le, sizeof(v_le));
+	unpack_block_time(le64_to_cpu(v_le), &b, &t);
+	dm_sm_dec_block(sm, b);
+}
+
+static int data_block_equal(void *context, void *value1_le, void *value2_le)
+{
+	__le64 v1_le, v2_le;
+	uint64_t b1, b2;
+	uint32_t t;
+
+	memcpy(&v1_le, value1_le, sizeof(v1_le));
+	memcpy(&v2_le, value2_le, sizeof(v2_le));
+	unpack_block_time(le64_to_cpu(v1_le), &b1, &t);
+	unpack_block_time(le64_to_cpu(v2_le), &b2, &t);
+
+	return b1 == b2;
+}
+
+static void subtree_inc(void *context, void *value)
+{
+	struct dm_btree_info *info = context;
+	__le64 root_le;
+	uint64_t root;
+
+	memcpy(&root_le, value, sizeof(root_le));
+	root = le64_to_cpu(root_le);
+	dm_tm_inc(info->tm, root);
+}
+
+static void subtree_dec(void *context, void *value)
+{
+	struct dm_btree_info *info = context;
+	__le64 root_le;
+	uint64_t root;
+
+	memcpy(&root_le, value, sizeof(root_le));
+	root = le64_to_cpu(root_le);
+	if (dm_btree_del(info, root))
+		DMERR("btree delete failed\n");
+}
+
+static int subtree_equal(void *context, void *value1_le, void *value2_le)
+{
+	__le64 v1_le, v2_le;
+	memcpy(&v1_le, value1_le, sizeof(v1_le));
+	memcpy(&v2_le, value2_le, sizeof(v2_le));
+
+	return v1_le == v2_le;
+}
+
+/*----------------------------------------------------------------*/
+
+static int superblock_all_zeroes(struct dm_block_manager *bm, int *result)
+{
+	int r;
+	unsigned i;
+	struct dm_block *b;
+	__le64 *data_le, zero = cpu_to_le64(0);
+	unsigned block_size = dm_bm_block_size(bm) / sizeof(__le64);
+
+	/*
+	 * We can't use a validator here - it may be all zeroes.
+	 */
+	r = dm_bm_read_lock(bm, THIN_SUPERBLOCK_LOCATION, NULL, &b);
+	if (r)
+		return r;
+
+	data_le = dm_block_data(b);
+	*result = 1;
+	for (i = 0; i < block_size; i++) {
+		if (data_le[i] != zero) {
+			*result = 0;
+			break;
+		}
+	}
+
+	return dm_bm_unlock(b);
+}
+
+static int init_pmd(struct dm_pool_metadata *pmd,
+		    struct dm_block_manager *bm,
+		    dm_block_t nr_blocks, int create)
+{
+	int r;
+	struct dm_space_map *sm, *data_sm;
+	struct dm_transaction_manager *tm;
+	struct dm_block *sblock;
+
+	if (create) {
+		r = dm_tm_create_with_sm(bm, THIN_SUPERBLOCK_LOCATION,
+					 &sb_validator, &tm, &sm, &sblock);
+		if (r < 0) {
+			DMERR("tm_create_with_sm failed");
+			return r;
+		}
+
+		data_sm = dm_sm_disk_create(tm, nr_blocks);
+		if (IS_ERR(data_sm)) {
+			DMERR("sm_disk_create failed");
+			r = PTR_ERR(data_sm);
+			goto bad;
+		}
+	} else {
+		struct thin_disk_superblock *disk_super = NULL;
+		size_t space_map_root_offset =
+			offsetof(struct thin_disk_superblock, metadata_space_map_root);
+
+		r = dm_tm_open_with_sm(bm, THIN_SUPERBLOCK_LOCATION,
+				       &sb_validator, space_map_root_offset,
+				       SPACE_MAP_ROOT_SIZE, &tm, &sm, &sblock);
+		if (r < 0) {
+			DMERR("tm_open_with_sm failed");
+			return r;
+		}
+
+		disk_super = dm_block_data(sblock);
+		data_sm = dm_sm_disk_open(tm, disk_super->data_space_map_root,
+					  sizeof(disk_super->data_space_map_root));
+		if (IS_ERR(data_sm)) {
+			DMERR("sm_disk_open failed");
+			r = PTR_ERR(data_sm);
+			goto bad;
+		}
+	}
+
+
+	r = dm_tm_unlock(tm, sblock);
+	if (r < 0) {
+		DMERR("couldn't unlock superblock");
+		goto bad_data_sm;
+	}
+
+	pmd->bm = bm;
+	pmd->metadata_sm = sm;
+	pmd->data_sm = data_sm;
+	pmd->tm = tm;
+	pmd->nb_tm = dm_tm_create_non_blocking_clone(tm);
+	if (!pmd->nb_tm) {
+		DMERR("could not create clone tm");
+		r = -ENOMEM;
+		goto bad_data_sm;
+	}
+
+	pmd->info.tm = tm;
+	pmd->info.levels = 2;
+	pmd->info.value_type.context = pmd->data_sm;
+	pmd->info.value_type.size = sizeof(__le64);
+	pmd->info.value_type.inc = data_block_inc;
+	pmd->info.value_type.dec = data_block_dec;
+	pmd->info.value_type.equal = data_block_equal;
+
+	memcpy(&pmd->nb_info, &pmd->info, sizeof(pmd->nb_info));
+	pmd->nb_info.tm = pmd->nb_tm;
+
+	pmd->tl_info.tm = tm;
+	pmd->tl_info.levels = 1;
+	pmd->tl_info.value_type.context = &pmd->info;
+	pmd->tl_info.value_type.size = sizeof(__le64);
+	pmd->tl_info.value_type.inc = subtree_inc;
+	pmd->tl_info.value_type.dec = subtree_dec;
+	pmd->tl_info.value_type.equal = subtree_equal;
+
+	pmd->bl_info.tm = tm;
+	pmd->bl_info.levels = 1;
+	pmd->bl_info.value_type.context = pmd->data_sm;
+	pmd->bl_info.value_type.size = sizeof(__le64);
+	pmd->bl_info.value_type.inc = data_block_inc;
+	pmd->bl_info.value_type.dec = data_block_dec;
+	pmd->bl_info.value_type.equal = data_block_equal;
+
+	pmd->details_info.tm = tm;
+	pmd->details_info.levels = 1;
+	pmd->details_info.value_type.context = NULL;
+	pmd->details_info.value_type.size = sizeof(struct disk_device_details);
+	pmd->details_info.value_type.inc = NULL;
+	pmd->details_info.value_type.dec = NULL;
+	pmd->details_info.value_type.equal = NULL;
+
+	pmd->root = 0;
+
+	init_rwsem(&pmd->root_lock);
+	pmd->time = 0;
+	pmd->need_commit = 0;
+	pmd->details_root = 0;
+	pmd->trans_id = 0;
+	pmd->flags = 0;
+	INIT_LIST_HEAD(&pmd->thin_devices);
+
+	return 0;
+
+bad_data_sm:
+	dm_sm_destroy(data_sm);
+bad:
+	dm_tm_destroy(tm);
+	dm_sm_destroy(sm);
+
+	return r;
+}
+
+static int __begin_transaction(struct dm_pool_metadata *pmd)
+{
+	int r;
+	u32 features;
+	struct thin_disk_superblock *disk_super;
+	struct dm_block *sblock;
+
+	/*
+	 * __maybe_commit_transaction() resets these
+	 */
+	WARN_ON(pmd->need_commit);
+
+	/*
+	 * We re-read the superblock every time.  Shouldn't need to do this
+	 * really.
+	 */
+	r = dm_bm_read_lock(pmd->bm, THIN_SUPERBLOCK_LOCATION,
+			    &sb_validator, &sblock);
+	if (r)
+		return r;
+
+	disk_super = dm_block_data(sblock);
+	pmd->time = le32_to_cpu(disk_super->time);
+	pmd->root = le64_to_cpu(disk_super->data_mapping_root);
+	pmd->details_root = le64_to_cpu(disk_super->device_details_root);
+	pmd->trans_id = le64_to_cpu(disk_super->trans_id);
+	pmd->flags = le32_to_cpu(disk_super->flags);
+	pmd->data_block_size = le32_to_cpu(disk_super->data_block_size);
+
+	features = le32_to_cpu(disk_super->incompat_flags) & ~THIN_FEATURE_INCOMPAT_SUPP;
+	if (features) {
+		DMERR("could not access metadata due to "
+		      "unsupported optional features (%lx).",
+		      (unsigned long)features);
+		r = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * Check for read-only metadata to skip the following RDWR checks.
+	 */
+	if (get_disk_ro(pmd->bdev->bd_disk))
+		goto out;
+
+	features = le32_to_cpu(disk_super->compat_ro_flags) & ~THIN_FEATURE_COMPAT_RO_SUPP;
+	if (features) {
+		DMERR("could not access metadata RDWR due to "
+		      "unsupported optional features (%lx).",
+		      (unsigned long)features);
+		r = -EINVAL;
+	}
+
+out:
+	dm_bm_unlock(sblock);
+	return r;
+}
+
+static int __write_changed_details(struct dm_pool_metadata *pmd)
+{
+	int r;
+	struct dm_thin_device *td, *tmp;
+	struct disk_device_details details;
+	uint64_t key;
+
+	list_for_each_entry_safe(td, tmp, &pmd->thin_devices, list) {
+		if (!td->changed)
+			continue;
+
+		key = td->id;
+
+		details.mapped_blocks = cpu_to_le64(td->mapped_blocks);
+		details.transaction_id = cpu_to_le64(td->transaction_id);
+		details.creation_time = cpu_to_le32(td->creation_time);
+		details.snapshotted_time = cpu_to_le32(td->snapshotted_time);
+		__dm_bless_for_disk(&details);
+
+		r = dm_btree_insert(&pmd->details_info, pmd->details_root,
+				    &key, &details, &pmd->details_root);
+		if (r)
+			return r;
+
+		if (td->open_count)
+			td->changed = 0;
+		else {
+			list_del(&td->list);
+			kfree(td);
+		}
+
+		pmd->need_commit = 1;
+	}
+
+	return 0;
+}
+
+static int __commit_transaction(struct dm_pool_metadata *pmd)
+{
+	/*
+	 * FIXME: Associated pool should be made read-only on failure.
+	 */
+	int r;
+	size_t metadata_len, data_len;
+	struct thin_disk_superblock *disk_super;
+	struct dm_block *sblock;
+
+	/*
+	 * We need to know if the thin_disk_superblock exceeds a 512-byte sector.
+	 */
+	BUILD_BUG_ON(sizeof(struct thin_disk_superblock) > 512);
+
+	r = __write_changed_details(pmd);
+	if (r < 0)
+		goto out;
+
+	if (!pmd->need_commit)
+		goto out;
+
+	r = dm_sm_commit(pmd->data_sm);
+	if (r < 0)
+		goto out;
+
+	r = dm_tm_pre_commit(pmd->tm);
+	if (r < 0)
+		goto out;
+
+	r = dm_sm_root_size(pmd->metadata_sm, &metadata_len);
+	if (r < 0)
+		goto out;
+
+	r = dm_sm_root_size(pmd->metadata_sm, &data_len);
+	if (r < 0)
+		goto out;
+
+	r = dm_bm_write_lock(pmd->bm, THIN_SUPERBLOCK_LOCATION,
+			     &sb_validator, &sblock);
+	if (r)
+		goto out;
+
+	disk_super = dm_block_data(sblock);
+	disk_super->time = cpu_to_le32(pmd->time);
+	disk_super->data_mapping_root = cpu_to_le64(pmd->root);
+	disk_super->device_details_root = cpu_to_le64(pmd->details_root);
+	disk_super->trans_id = cpu_to_le64(pmd->trans_id);
+	disk_super->flags = cpu_to_le32(pmd->flags);
+
+	r = dm_sm_copy_root(pmd->metadata_sm, &disk_super->metadata_space_map_root,
+			    metadata_len);
+	if (r < 0)
+		goto out_locked;
+
+	r = dm_sm_copy_root(pmd->data_sm, &disk_super->data_space_map_root,
+			    data_len);
+	if (r < 0)
+		goto out_locked;
+
+	r = dm_tm_commit(pmd->tm, sblock);
+	if (!r)
+		pmd->need_commit = 0;
+
+out:
+	return r;
+
+out_locked:
+	dm_bm_unlock(sblock);
+	return r;
+}
+
+struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev,
+					       sector_t data_block_size)
+{
+	int r;
+	struct thin_disk_superblock *disk_super;
+	struct dm_pool_metadata *pmd;
+	sector_t bdev_size = i_size_read(bdev->bd_inode) >> SECTOR_SHIFT;
+	struct dm_block_manager *bm;
+	int create;
+	struct dm_block *sblock;
+
+	pmd = kmalloc(sizeof(*pmd), GFP_KERNEL);
+	if (!pmd) {
+		DMERR("could not allocate metadata struct");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/*
+	 * Max hex locks:
+	 *  3 for btree insert +
+	 *  2 for btree lookup used within space map
+	 */
+	bm = dm_block_manager_create(bdev, THIN_METADATA_BLOCK_SIZE,
+				     THIN_METADATA_CACHE_SIZE, 5);
+	if (!bm) {
+		DMERR("could not create block manager");
+		kfree(pmd);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	r = superblock_all_zeroes(bm, &create);
+	if (r) {
+		dm_block_manager_destroy(bm);
+		kfree(pmd);
+		return ERR_PTR(r);
+	}
+
+
+	r = init_pmd(pmd, bm, 0, create);
+	if (r) {
+		dm_block_manager_destroy(bm);
+		kfree(pmd);
+		return ERR_PTR(r);
+	}
+	pmd->bdev = bdev;
+
+	if (!create) {
+		r = __begin_transaction(pmd);
+		if (r < 0)
+			goto bad;
+		return pmd;
+	}
+
+	/*
+	 * Create.
+	 */
+	r = dm_bm_write_lock(pmd->bm, THIN_SUPERBLOCK_LOCATION,
+			     &sb_validator, &sblock);
+	if (r)
+		goto bad;
+
+	disk_super = dm_block_data(sblock);
+	disk_super->magic = cpu_to_le64(THIN_SUPERBLOCK_MAGIC);
+	disk_super->version = cpu_to_le32(THIN_VERSION);
+	disk_super->time = 0;
+	disk_super->metadata_block_size = cpu_to_le32(THIN_METADATA_BLOCK_SIZE >> SECTOR_SHIFT);
+	disk_super->metadata_nr_blocks = cpu_to_le64(bdev_size >> SECTOR_TO_BLOCK_SHIFT);
+	disk_super->data_block_size = cpu_to_le32(data_block_size);
+
+	r = dm_bm_unlock(sblock);
+	if (r < 0)
+		goto bad;
+
+	r = dm_btree_empty(&pmd->info, &pmd->root);
+	if (r < 0)
+		goto bad;
+
+	r = dm_btree_empty(&pmd->details_info, &pmd->details_root);
+	if (r < 0) {
+		DMERR("couldn't create devices root");
+		goto bad;
+	}
+
+	pmd->flags = 0;
+	pmd->need_commit = 1;
+	r = dm_pool_commit_metadata(pmd);
+	if (r < 0) {
+		DMERR("%s: dm_pool_commit_metadata() failed, error = %d",
+		      __func__, r);
+		goto bad;
+	}
+
+	return pmd;
+
+bad:
+	if (dm_pool_metadata_close(pmd) < 0)
+		DMWARN("%s: dm_pool_metadata_close() failed.", __func__);
+	return ERR_PTR(r);
+}
+
+int dm_pool_metadata_close(struct dm_pool_metadata *pmd)
+{
+	int r;
+	unsigned open_devices = 0;
+	struct dm_thin_device *td, *tmp;
+
+	down_read(&pmd->root_lock);
+	list_for_each_entry_safe(td, tmp, &pmd->thin_devices, list) {
+		if (td->open_count)
+			open_devices++;
+		else {
+			list_del(&td->list);
+			kfree(td);
+		}
+	}
+	up_read(&pmd->root_lock);
+
+	if (open_devices) {
+		DMERR("attempt to close pmd when %u device(s) are still open",
+		       open_devices);
+		return -EBUSY;
+	}
+
+	r = __commit_transaction(pmd);
+	if (r < 0)
+		DMWARN("%s: __commit_transaction() failed, error = %d",
+		       __func__, r);
+
+	dm_tm_destroy(pmd->tm);
+	dm_tm_destroy(pmd->nb_tm);
+	dm_block_manager_destroy(pmd->bm);
+	dm_sm_destroy(pmd->metadata_sm);
+	dm_sm_destroy(pmd->data_sm);
+	kfree(pmd);
+
+	return 0;
+}
+
+static int __open_device(struct dm_pool_metadata *pmd,
+			 dm_thin_id dev, int create,
+			 struct dm_thin_device **td)
+{
+	int r, changed = 0;
+	struct dm_thin_device *td2;
+	uint64_t key = dev;
+	struct disk_device_details details_le;
+
+	/*
+	 * Check the device isn't already open.
+	 */
+	list_for_each_entry(td2, &pmd->thin_devices, list)
+		if (td2->id == dev) {
+			td2->open_count++;
+			*td = td2;
+			return 0;
+		}
+
+	/*
+	 * Check the device exists.
+	 */
+	r = dm_btree_lookup(&pmd->details_info, pmd->details_root,
+			    &key, &details_le);
+	if (r) {
+		if (r != -ENODATA || !create)
+			return r;
+
+		changed = 1;
+		details_le.mapped_blocks = 0;
+		details_le.transaction_id = cpu_to_le64(pmd->trans_id);
+		details_le.creation_time = cpu_to_le32(pmd->time);
+		details_le.snapshotted_time = cpu_to_le32(pmd->time);
+	}
+
+	*td = kmalloc(sizeof(**td), GFP_NOIO);
+	if (!*td)
+		return -ENOMEM;
+
+	(*td)->pmd = pmd;
+	(*td)->id = dev;
+	(*td)->open_count = 1;
+	(*td)->changed = changed;
+	(*td)->mapped_blocks = le64_to_cpu(details_le.mapped_blocks);
+	(*td)->transaction_id = le64_to_cpu(details_le.transaction_id);
+	(*td)->creation_time = le32_to_cpu(details_le.creation_time);
+	(*td)->snapshotted_time = le32_to_cpu(details_le.snapshotted_time);
+
+	list_add(&(*td)->list, &pmd->thin_devices);
+
+	return 0;
+}
+
+static void __close_device(struct dm_thin_device *td)
+{
+	--td->open_count;
+}
+
+static int __create_thin(struct dm_pool_metadata *pmd,
+			 dm_thin_id dev)
+{
+	int r;
+	dm_block_t dev_root;
+	uint64_t key = dev;
+	struct disk_device_details details_le;
+	struct dm_thin_device *td;
+	__le64 value;
+
+	r = dm_btree_lookup(&pmd->details_info, pmd->details_root,
+			    &key, &details_le);
+	if (!r)
+		return -EEXIST;
+
+	/*
+	 * Create an empty btree for the mappings.
+	 */
+	r = dm_btree_empty(&pmd->bl_info, &dev_root);
+	if (r)
+		return r;
+
+	/*
+	 * Insert it into the main mapping tree.
+	 */
+	value = cpu_to_le64(dev_root);
+	__dm_bless_for_disk(&value);
+	r = dm_btree_insert(&pmd->tl_info, pmd->root, &key, &value, &pmd->root);
+	if (r) {
+		dm_btree_del(&pmd->bl_info, dev_root);
+		return r;
+	}
+
+	r = __open_device(pmd, dev, 1, &td);
+	if (r) {
+		__close_device(td);
+		dm_btree_remove(&pmd->tl_info, pmd->root, &key, &pmd->root);
+		dm_btree_del(&pmd->bl_info, dev_root);
+		return r;
+	}
+	td->changed = 1;
+	__close_device(td);
+
+	return r;
+}
+
+int dm_pool_create_thin(struct dm_pool_metadata *pmd, dm_thin_id dev)
+{
+	int r;
+
+	down_write(&pmd->root_lock);
+	r = __create_thin(pmd, dev);
+	up_write(&pmd->root_lock);
+
+	return r;
+}
+
+static int __set_snapshot_details(struct dm_pool_metadata *pmd,
+				  struct dm_thin_device *snap,
+				  dm_thin_id origin, uint32_t time)
+{
+	int r;
+	struct dm_thin_device *td;
+
+	r = __open_device(pmd, origin, 0, &td);
+	if (r)
+		return r;
+
+	td->changed = 1;
+	td->snapshotted_time = time;
+
+	snap->mapped_blocks = td->mapped_blocks;
+	snap->snapshotted_time = time;
+	__close_device(td);
+
+	return 0;
+}
+
+static int __create_snap(struct dm_pool_metadata *pmd,
+			 dm_thin_id dev, dm_thin_id origin)
+{
+	int r;
+	dm_block_t origin_root;
+	uint64_t key = origin, dev_key = dev;
+	struct dm_thin_device *td;
+	struct disk_device_details details_le;
+	__le64 value;
+
+	/* check this device is unused */
+	r = dm_btree_lookup(&pmd->details_info, pmd->details_root,
+			    &dev_key, &details_le);
+	if (!r)
+		return -EEXIST;
+
+	/* find the mapping tree for the origin */
+	r = dm_btree_lookup(&pmd->tl_info, pmd->root, &key, &value);
+	if (r)
+		return r;
+	origin_root = le64_to_cpu(value);
+
+	/* clone the origin, an inc will do */
+	dm_tm_inc(pmd->tm, origin_root);
+
+	/* insert into the main mapping tree */
+	value = cpu_to_le64(origin_root);
+	__dm_bless_for_disk(&value);
+	key = dev;
+	r = dm_btree_insert(&pmd->tl_info, pmd->root, &key, &value, &pmd->root);
+	if (r) {
+		dm_tm_dec(pmd->tm, origin_root);
+		return r;
+	}
+
+	pmd->time++;
+
+	r = __open_device(pmd, dev, 1, &td);
+	if (r)
+		goto bad;
+
+	r = __set_snapshot_details(pmd, td, origin, pmd->time);
+	if (r)
+		goto bad;
+
+	__close_device(td);
+	return 0;
+
+bad:
+	__close_device(td);
+	dm_btree_remove(&pmd->tl_info, pmd->root, &key, &pmd->root);
+	dm_btree_remove(&pmd->details_info, pmd->details_root,
+			&key, &pmd->details_root);
+	return r;
+}
+
+int dm_pool_create_snap(struct dm_pool_metadata *pmd,
+				 dm_thin_id dev,
+				 dm_thin_id origin)
+{
+	int r;
+
+	down_write(&pmd->root_lock);
+	r = __create_snap(pmd, dev, origin);
+	up_write(&pmd->root_lock);
+
+	return r;
+}
+
+static int __delete_device(struct dm_pool_metadata *pmd, dm_thin_id dev)
+{
+	int r;
+	uint64_t key = dev;
+	struct dm_thin_device *td;
+
+	/* TODO: failure should mark the transaction invalid */
+	r = __open_device(pmd, dev, 0, &td);
+	if (r)
+		return r;
+
+	if (td->open_count > 1) {
+		__close_device(td);
+		return -EBUSY;
+	}
+
+	list_del(&td->list);
+	kfree(td);
+	r = dm_btree_remove(&pmd->details_info, pmd->details_root,
+			    &key, &pmd->details_root);
+	if (r)
+		return r;
+
+	r = dm_btree_remove(&pmd->tl_info, pmd->root, &key, &pmd->root);
+	if (r)
+		return r;
+
+	pmd->need_commit = 1;
+
+	return 0;
+}
+
+int dm_pool_delete_thin_device(struct dm_pool_metadata *pmd,
+			       dm_thin_id dev)
+{
+	int r;
+
+	down_write(&pmd->root_lock);
+	r = __delete_device(pmd, dev);
+	up_write(&pmd->root_lock);
+
+	return r;
+}
+
+int dm_pool_set_metadata_transaction_id(struct dm_pool_metadata *pmd,
+					uint64_t current_id,
+					uint64_t new_id)
+{
+	down_write(&pmd->root_lock);
+	if (pmd->trans_id != current_id) {
+		up_write(&pmd->root_lock);
+		DMERR("mismatched transaction id");
+		return -EINVAL;
+	}
+
+	pmd->trans_id = new_id;
+	pmd->need_commit = 1;
+	up_write(&pmd->root_lock);
+
+	return 0;
+}
+
+int dm_pool_get_metadata_transaction_id(struct dm_pool_metadata *pmd,
+					uint64_t *result)
+{
+	down_read(&pmd->root_lock);
+	*result = pmd->trans_id;
+	up_read(&pmd->root_lock);
+
+	return 0;
+}
+
+static int __get_held_metadata_root(struct dm_pool_metadata *pmd,
+				    dm_block_t *result)
+{
+	int r;
+	struct thin_disk_superblock *disk_super;
+	struct dm_block *sblock;
+
+	r = dm_bm_write_lock(pmd->bm, THIN_SUPERBLOCK_LOCATION,
+			     &sb_validator, &sblock);
+	if (r)
+		return r;
+
+	disk_super = dm_block_data(sblock);
+	*result = le64_to_cpu(disk_super->held_root);
+
+	return dm_bm_unlock(sblock);
+}
+
+int dm_pool_get_held_metadata_root(struct dm_pool_metadata *pmd,
+				   dm_block_t *result)
+{
+	int r;
+
+	down_read(&pmd->root_lock);
+	r = __get_held_metadata_root(pmd, result);
+	up_read(&pmd->root_lock);
+
+	return r;
+}
+
+int dm_pool_open_thin_device(struct dm_pool_metadata *pmd, dm_thin_id dev,
+			     struct dm_thin_device **td)
+{
+	int r;
+
+	down_write(&pmd->root_lock);
+	r = __open_device(pmd, dev, 0, td);
+	up_write(&pmd->root_lock);
+
+	return r;
+}
+
+int dm_pool_close_thin_device(struct dm_thin_device *td)
+{
+	down_write(&td->pmd->root_lock);
+	__close_device(td);
+	up_write(&td->pmd->root_lock);
+
+	return 0;
+}
+
+dm_thin_id dm_thin_dev_id(struct dm_thin_device *td)
+{
+	return td->id;
+}
+
+static int __snapshotted_since(struct dm_thin_device *td, uint32_t time)
+{
+	return td->snapshotted_time > time;
+}
+
+int dm_thin_find_block(struct dm_thin_device *td, dm_block_t block,
+		       int can_block, struct dm_thin_lookup_result *result)
+{
+	int r;
+	uint64_t block_time = 0;
+	__le64 value;
+	struct dm_pool_metadata *pmd = td->pmd;
+	dm_block_t keys[2] = { td->id, block };
+
+	if (can_block) {
+		down_read(&pmd->root_lock);
+		r = dm_btree_lookup(&pmd->info, pmd->root, keys, &value);
+		if (!r)
+			block_time = le64_to_cpu(value);
+		up_read(&pmd->root_lock);
+
+	} else if (down_read_trylock(&pmd->root_lock)) {
+		r = dm_btree_lookup(&pmd->nb_info, pmd->root, keys, &value);
+		if (!r)
+			block_time = le64_to_cpu(value);
+		up_read(&pmd->root_lock);
+
+	} else
+		return -EWOULDBLOCK;
+
+	if (!r) {
+		dm_block_t exception_block;
+		uint32_t exception_time;
+		unpack_block_time(block_time, &exception_block,
+				  &exception_time);
+		result->block = exception_block;
+		result->shared = __snapshotted_since(td, exception_time);
+	}
+
+	return r;
+}
+
+static int __insert(struct dm_thin_device *td, dm_block_t block,
+		    dm_block_t data_block)
+{
+	int r, inserted;
+	__le64 value;
+	struct dm_pool_metadata *pmd = td->pmd;
+	dm_block_t keys[2] = { td->id, block };
+
+	pmd->need_commit = 1;
+	value = cpu_to_le64(pack_block_time(data_block, pmd->time));
+	__dm_bless_for_disk(&value);
+
+	r = dm_btree_insert_notify(&pmd->info, pmd->root, keys, &value,
+				   &pmd->root, &inserted);
+	if (r)
+		return r;
+
+	if (inserted) {
+		td->mapped_blocks++;
+		td->changed = 1;
+	}
+
+	return 0;
+}
+
+int dm_thin_insert_block(struct dm_thin_device *td, dm_block_t block,
+			 dm_block_t data_block)
+{
+	int r;
+
+	down_write(&td->pmd->root_lock);
+	r = __insert(td, block, data_block);
+	up_write(&td->pmd->root_lock);
+
+	return r;
+}
+
+static int __remove(struct dm_thin_device *td, dm_block_t block)
+{
+	int r;
+	struct dm_pool_metadata *pmd = td->pmd;
+	dm_block_t keys[2] = { td->id, block };
+
+	r = dm_btree_remove(&pmd->info, pmd->root, keys, &pmd->root);
+	if (r)
+		return r;
+
+	pmd->need_commit = 1;
+
+	return 0;
+}
+
+int dm_thin_remove_block(struct dm_thin_device *td, dm_block_t block)
+{
+	int r;
+
+	down_write(&td->pmd->root_lock);
+	r = __remove(td, block);
+	up_write(&td->pmd->root_lock);
+
+	return r;
+}
+
+int dm_pool_alloc_data_block(struct dm_pool_metadata *pmd, dm_block_t *result)
+{
+	int r;
+
+	down_write(&pmd->root_lock);
+
+	r = dm_sm_new_block(pmd->data_sm, result);
+	pmd->need_commit = 1;
+
+	up_write(&pmd->root_lock);
+
+	return r;
+}
+
+int dm_pool_commit_metadata(struct dm_pool_metadata *pmd)
+{
+	int r;
+
+	down_write(&pmd->root_lock);
+
+	r = __commit_transaction(pmd);
+	if (r <= 0)
+		goto out;
+
+	/*
+	 * Open the next transaction.
+	 */
+	r = __begin_transaction(pmd);
+out:
+	up_write(&pmd->root_lock);
+	return r;
+}
+
+int dm_pool_get_free_block_count(struct dm_pool_metadata *pmd, dm_block_t *result)
+{
+	int r;
+
+	down_read(&pmd->root_lock);
+	r = dm_sm_get_nr_free(pmd->data_sm, result);
+	up_read(&pmd->root_lock);
+
+	return r;
+}
+
+int dm_pool_get_free_metadata_block_count(struct dm_pool_metadata *pmd,
+					  dm_block_t *result)
+{
+	int r;
+
+	down_read(&pmd->root_lock);
+	r = dm_sm_get_nr_free(pmd->metadata_sm, result);
+	up_read(&pmd->root_lock);
+
+	return r;
+}
+
+int dm_pool_get_metadata_dev_size(struct dm_pool_metadata *pmd,
+				  dm_block_t *result)
+{
+	int r;
+
+	down_read(&pmd->root_lock);
+	r = dm_sm_get_nr_blocks(pmd->metadata_sm, result);
+	up_read(&pmd->root_lock);
+
+	return r;
+}
+
+int dm_pool_get_data_block_size(struct dm_pool_metadata *pmd, sector_t *result)
+{
+	down_read(&pmd->root_lock);
+	*result = pmd->data_block_size;
+	up_read(&pmd->root_lock);
+
+	return 0;
+}
+
+int dm_pool_get_data_dev_size(struct dm_pool_metadata *pmd, dm_block_t *result)
+{
+	int r;
+
+	down_read(&pmd->root_lock);
+	r = dm_sm_get_nr_blocks(pmd->data_sm, result);
+	up_read(&pmd->root_lock);
+
+	return r;
+}
+
+int dm_thin_get_mapped_count(struct dm_thin_device *td, dm_block_t *result)
+{
+	struct dm_pool_metadata *pmd = td->pmd;
+
+	down_read(&pmd->root_lock);
+	*result = td->mapped_blocks;
+	up_read(&pmd->root_lock);
+
+	return 0;
+}
+
+static int __highest_block(struct dm_thin_device *td, dm_block_t *result)
+{
+	int r;
+	__le64 value_le;
+	dm_block_t thin_root;
+	struct dm_pool_metadata *pmd = td->pmd;
+
+	r = dm_btree_lookup(&pmd->tl_info, pmd->root, &td->id, &value_le);
+	if (r)
+		return r;
+
+	thin_root = le64_to_cpu(value_le);
+
+	return dm_btree_find_highest_key(&pmd->bl_info, thin_root, result);
+}
+
+int dm_thin_get_highest_mapped_block(struct dm_thin_device *td,
+				     dm_block_t *result)
+{
+	int r;
+	struct dm_pool_metadata *pmd = td->pmd;
+
+	down_read(&pmd->root_lock);
+	r = __highest_block(td, result);
+	up_read(&pmd->root_lock);
+
+	return r;
+}
+
+static int __resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_count)
+{
+	int r;
+	dm_block_t old_count;
+
+	r = dm_sm_get_nr_blocks(pmd->data_sm, &old_count);
+	if (r)
+		return r;
+
+	if (new_count == old_count)
+		return 0;
+
+	if (new_count < old_count) {
+		DMERR("cannot reduce size of data device");
+		return -EINVAL;
+	}
+
+	r = dm_sm_extend(pmd->data_sm, new_count - old_count);
+	if (!r)
+		pmd->need_commit = 1;
+
+	return r;
+}
+
+int dm_pool_resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_count)
+{
+	int r;
+
+	down_write(&pmd->root_lock);
+	r = __resize_data_dev(pmd, new_count);
+	up_write(&pmd->root_lock);
+
+	return r;
+}
diff --git a/drivers/md/dm-thin-metadata.h b/drivers/md/dm-thin-metadata.h
new file mode 100644
index 0000000..859c168
--- /dev/null
+++ b/drivers/md/dm-thin-metadata.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2010-2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef DM_THIN_METADATA_H
+#define DM_THIN_METADATA_H
+
+#include "persistent-data/dm-block-manager.h"
+
+#define THIN_METADATA_BLOCK_SIZE 4096
+
+/*----------------------------------------------------------------*/
+
+struct dm_pool_metadata;
+struct dm_thin_device;
+
+/*
+ * Device identifier
+ */
+typedef uint64_t dm_thin_id;
+
+/*
+ * Reopens or creates a new, empty metadata volume.
+ */
+struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev,
+					       sector_t data_block_size);
+
+int dm_pool_metadata_close(struct dm_pool_metadata *pmd);
+
+/*
+ * Compat feature flags.  Any incompat flags beyond the ones
+ * specified below will prevent use of the thin metadata.
+ */
+#define THIN_FEATURE_COMPAT_SUPP	  0UL
+#define THIN_FEATURE_COMPAT_RO_SUPP	  0UL
+#define THIN_FEATURE_INCOMPAT_SUPP	  0UL
+
+/*
+ * Device creation/deletion.
+ */
+int dm_pool_create_thin(struct dm_pool_metadata *pmd, dm_thin_id dev);
+
+/*
+ * An internal snapshot.
+ *
+ * You can only snapshot a quiesced origin i.e. one that is either
+ * suspended or not instanced at all.
+ */
+int dm_pool_create_snap(struct dm_pool_metadata *pmd, dm_thin_id dev,
+			dm_thin_id origin);
+
+/*
+ * Deletes a virtual device from the metadata.  It _is_ safe to call this
+ * when that device is open.  Operations on that device will just start
+ * failing.  You still need to call close() on the device.
+ */
+int dm_pool_delete_thin_device(struct dm_pool_metadata *pmd,
+			       dm_thin_id dev);
+
+/*
+ * Commits _all_ metadata changes: device creation, deletion, mapping
+ * updates.
+ */
+int dm_pool_commit_metadata(struct dm_pool_metadata *pmd);
+
+/*
+ * Set/get userspace transaction id.
+ */
+int dm_pool_set_metadata_transaction_id(struct dm_pool_metadata *pmd,
+					uint64_t current_id,
+					uint64_t new_id);
+
+int dm_pool_get_metadata_transaction_id(struct dm_pool_metadata *pmd,
+					uint64_t *result);
+
+/*
+ * Hold/get root for userspace transaction.
+ */
+int dm_pool_hold_metadata_root(struct dm_pool_metadata *pmd);
+
+int dm_pool_get_held_metadata_root(struct dm_pool_metadata *pmd,
+				   dm_block_t *result);
+
+/*
+ * Actions on a single virtual device.
+ */
+
+/*
+ * Opening the same device more than once will fail with -EBUSY.
+ */
+int dm_pool_open_thin_device(struct dm_pool_metadata *pmd, dm_thin_id dev,
+			     struct dm_thin_device **td);
+
+int dm_pool_close_thin_device(struct dm_thin_device *td);
+
+dm_thin_id dm_thin_dev_id(struct dm_thin_device *td);
+
+struct dm_thin_lookup_result {
+	dm_block_t block;
+	int shared;
+};
+
+/*
+ * Returns:
+ *   -EWOULDBLOCK iff @can_block is set and would block.
+ *   -ENODATA iff that mapping is not present.
+ *   0 success
+ */
+int dm_thin_find_block(struct dm_thin_device *td, dm_block_t block,
+		       int can_block, struct dm_thin_lookup_result *result);
+
+/*
+ * Obtain an unused block.
+ */
+int dm_pool_alloc_data_block(struct dm_pool_metadata *pmd, dm_block_t *result);
+
+/*
+ * Insert or remove block.
+ */
+int dm_thin_insert_block(struct dm_thin_device *td, dm_block_t block,
+			 dm_block_t data_block);
+
+int dm_thin_remove_block(struct dm_thin_device *td, dm_block_t block);
+
+/*
+ * Queries.
+ */
+int dm_thin_get_highest_mapped_block(struct dm_thin_device *td,
+				     dm_block_t *highest_mapped);
+
+int dm_thin_get_mapped_count(struct dm_thin_device *td, dm_block_t *result);
+
+int dm_pool_get_free_block_count(struct dm_pool_metadata *pmd,
+				 dm_block_t *result);
+
+int dm_pool_get_free_metadata_block_count(struct dm_pool_metadata *pmd,
+					  dm_block_t *result);
+
+int dm_pool_get_metadata_dev_size(struct dm_pool_metadata *pmd,
+				  dm_block_t *result);
+
+int dm_pool_get_data_block_size(struct dm_pool_metadata *pmd, sector_t *result);
+
+int dm_pool_get_data_dev_size(struct dm_pool_metadata *pmd, dm_block_t *result);
+
+/*
+ * Returns -ENOSPC if the new size is too small and already allocated
+ * blocks would be lost.
+ */
+int dm_pool_resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_size);
+
+/*----------------------------------------------------------------*/
+
+#endif
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
new file mode 100644
index 0000000..c308757
--- /dev/null
+++ b/drivers/md/dm-thin.c
@@ -0,0 +1,2428 @@
+/*
+ * Copyright (C) 2011 Red Hat UK.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-thin-metadata.h"
+
+#include <linux/device-mapper.h>
+#include <linux/dm-io.h>
+#include <linux/dm-kcopyd.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#define	DM_MSG_PREFIX	"thin"
+
+/*
+ * Tunable constants
+ */
+#define ENDIO_HOOK_POOL_SIZE 10240
+#define DEFERRED_SET_SIZE 64
+#define MAPPING_POOL_SIZE 1024
+#define PRISON_CELLS 1024
+
+/*
+ * The block size of the device holding pool data must be
+ * between 64KB and 1GB.
+ */
+#define DATA_DEV_BLOCK_SIZE_MIN_SECTORS (64 * 1024 >> SECTOR_SHIFT)
+#define DATA_DEV_BLOCK_SIZE_MAX_SECTORS (1024 * 1024 * 1024 >> SECTOR_SHIFT)
+
+/*
+ * The metadata device is currently limited in size.  The limitation is
+ * checked lower down in dm-space-map-metadata, but we also check it here
+ * so we can fail early.
+ *
+ * We have one block of index, which can hold 255 index entries.  Each
+ * index entry contains allocation info about 16k metadata blocks.
+ */
+#define METADATA_DEV_MAX_SECTORS (255 * (1 << 14) * (THIN_METADATA_BLOCK_SIZE / (1 << SECTOR_SHIFT)))
+
+/*
+ * Device id is restricted to 24 bits.
+ */
+#define MAX_DEV_ID ((1 << 24) - 1)
+
+/*
+ * How do we handle breaking sharing of data blocks?
+ * =================================================
+ *
+ * We use a standard copy-on-write btree to store the mappings for the
+ * devices (note I'm talking about copy-on-write of the metadata here, not
+ * the data).  When you take an internal snapshot you clone the root node
+ * of the origin btree.  After this there is no concept of an origin or a
+ * snapshot.  They are just two device trees that happen to point to the
+ * same data blocks.
+ *
+ * When we get a write in we decide if it's to a shared data block using
+ * some timestamp magic.  If it is, we have to break sharing.
+ *
+ * Let's say we write to a shared block in what was the origin.  The
+ * steps are:
+ *
+ * i) plug io further to this physical block. (see bio_prison code).
+ *
+ * ii) quiesce any read io to that shared data block.  Obviously
+ * including all devices that share this block.  (see deferred_set code)
+ *
+ * iii) copy the data block to a newly allocate block.  This step can be
+ * missed out if the io covers the block. (schedule_copy).
+ *
+ * iv) insert the new mapping into the origin's btree
+ * (process_prepared_mappings).  This act of inserting breaks some
+ * sharing of btree nodes between the two devices.  Breaking sharing only
+ * effects the btree of that specific device.  Btrees for the other
+ * devices that share the block never change.  The btree for the origin
+ * device as it was after the last commit is untouched, ie. we're using
+ * persistent data structures in the functional programming sense.
+ *
+ * v) unplug io to this physical block, including the io that triggered
+ * the breaking of sharing.
+ *
+ * Steps (ii) and (iii) occur in parallel.
+ *
+ * The metadata _doesn't_ need to be committed before the io continues.  We
+ * get away with this because the io is always written to a _new_ block.
+ * If there's a crash, then:
+ *
+ * - The origin mapping will point to the old origin block (the shared
+ * one).  This will contain the data as it was before the io that triggered
+ * the breaking of sharing came in.
+ *
+ * - The snap mapping still points to the old block.  As it would after
+ * the commit.
+ *
+ * The downside of this scheme is the timestamp magic isn't perfect, and
+ * will continue to think that data block in the snapshot device is shared
+ * even after the write to the origin has broken sharing.  I suspect data
+ * blocks will typically be shared by many different devices, so we're
+ * breaking sharing n + 1 times, rather than n, where n is the number of
+ * devices that reference this data block.  At the moment I think the
+ * benefits far, far outweigh the disadvantages.
+ */
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Sometimes we can't deal with a bio straight away.  We put them in prison
+ * where they can't cause any mischief.  Bios are put in a cell identified
+ * by a key, multiple bios can be in the same cell.  When the cell is
+ * subsequently unlocked the bios become available.
+ */
+struct bio_prison;
+
+struct cell_key {
+	int virtual;
+	dm_thin_id dev;
+	dm_block_t block;
+};
+
+struct cell {
+	struct hlist_node list;
+	struct bio_prison *prison;
+	struct cell_key key;
+	unsigned count;
+	struct bio_list bios;
+};
+
+struct bio_prison {
+	spinlock_t lock;
+	mempool_t *cell_pool;
+
+	unsigned nr_buckets;
+	unsigned hash_mask;
+	struct hlist_head *cells;
+};
+
+static uint32_t calc_nr_buckets(unsigned nr_cells)
+{
+	uint32_t n = 128;
+
+	nr_cells /= 4;
+	nr_cells = min(nr_cells, 8192u);
+
+	while (n < nr_cells)
+		n <<= 1;
+
+	return n;
+}
+
+/*
+ * @nr_cells should be the number of cells you want in use _concurrently_.
+ * Don't confuse it with the number of distinct keys.
+ */
+static struct bio_prison *prison_create(unsigned nr_cells)
+{
+	unsigned i;
+	uint32_t nr_buckets = calc_nr_buckets(nr_cells);
+	size_t len = sizeof(struct bio_prison) +
+		(sizeof(struct hlist_head) * nr_buckets);
+	struct bio_prison *prison = kmalloc(len, GFP_KERNEL);
+
+	if (!prison)
+		return NULL;
+
+	spin_lock_init(&prison->lock);
+	prison->cell_pool = mempool_create_kmalloc_pool(nr_cells,
+							sizeof(struct cell));
+	if (!prison->cell_pool) {
+		kfree(prison);
+		return NULL;
+	}
+
+	prison->nr_buckets = nr_buckets;
+	prison->hash_mask = nr_buckets - 1;
+	prison->cells = (struct hlist_head *) (prison + 1);
+	for (i = 0; i < nr_buckets; i++)
+		INIT_HLIST_HEAD(prison->cells + i);
+
+	return prison;
+}
+
+static void prison_destroy(struct bio_prison *prison)
+{
+	mempool_destroy(prison->cell_pool);
+	kfree(prison);
+}
+
+static uint32_t hash_key(struct bio_prison *prison, struct cell_key *key)
+{
+	const unsigned long BIG_PRIME = 4294967291UL;
+	uint64_t hash = key->block * BIG_PRIME;
+
+	return (uint32_t) (hash & prison->hash_mask);
+}
+
+static int keys_equal(struct cell_key *lhs, struct cell_key *rhs)
+{
+	       return (lhs->virtual == rhs->virtual) &&
+		       (lhs->dev == rhs->dev) &&
+		       (lhs->block == rhs->block);
+}
+
+static struct cell *__search_bucket(struct hlist_head *bucket,
+				    struct cell_key *key)
+{
+	struct cell *cell;
+	struct hlist_node *tmp;
+
+	hlist_for_each_entry(cell, tmp, bucket, list)
+		if (keys_equal(&cell->key, key))
+			return cell;
+
+	return NULL;
+}
+
+/*
+ * This may block if a new cell needs allocating.  You must ensure that
+ * cells will be unlocked even if the calling thread is blocked.
+ *
+ * Returns the number of entries in the cell prior to the new addition
+ * or < 0 on failure.
+ */
+static int bio_detain(struct bio_prison *prison, struct cell_key *key,
+		      struct bio *inmate, struct cell **ref)
+{
+	int r;
+	unsigned long flags;
+	uint32_t hash = hash_key(prison, key);
+	struct cell *uninitialized_var(cell), *cell2 = NULL;
+
+	BUG_ON(hash > prison->nr_buckets);
+
+	spin_lock_irqsave(&prison->lock, flags);
+	cell = __search_bucket(prison->cells + hash, key);
+
+	if (!cell) {
+		/*
+		 * Allocate a new cell
+		 */
+		spin_unlock_irqrestore(&prison->lock, flags);
+		cell2 = mempool_alloc(prison->cell_pool, GFP_NOIO);
+		spin_lock_irqsave(&prison->lock, flags);
+
+		/*
+		 * We've been unlocked, so we have to double check that
+		 * nobody else has inserted this cell in the meantime.
+		 */
+		cell = __search_bucket(prison->cells + hash, key);
+
+		if (!cell) {
+			cell = cell2;
+			cell2 = NULL;
+
+			cell->prison = prison;
+			memcpy(&cell->key, key, sizeof(cell->key));
+			cell->count = 0;
+			bio_list_init(&cell->bios);
+			hlist_add_head(&cell->list, prison->cells + hash);
+		}
+	}
+
+	r = cell->count++;
+	bio_list_add(&cell->bios, inmate);
+	spin_unlock_irqrestore(&prison->lock, flags);
+
+	if (cell2)
+		mempool_free(cell2, prison->cell_pool);
+
+	*ref = cell;
+
+	return r;
+}
+
+/*
+ * @inmates must have been initialised prior to this call
+ */
+static void __cell_release(struct cell *cell, struct bio_list *inmates)
+{
+	struct bio_prison *prison = cell->prison;
+
+	hlist_del(&cell->list);
+
+	if (inmates)
+		bio_list_merge(inmates, &cell->bios);
+
+	mempool_free(cell, prison->cell_pool);
+}
+
+static void cell_release(struct cell *cell, struct bio_list *bios)
+{
+	unsigned long flags;
+	struct bio_prison *prison = cell->prison;
+
+	spin_lock_irqsave(&prison->lock, flags);
+	__cell_release(cell, bios);
+	spin_unlock_irqrestore(&prison->lock, flags);
+}
+
+/*
+ * There are a couple of places where we put a bio into a cell briefly
+ * before taking it out again.  In these situations we know that no other
+ * bio may be in the cell.  This function releases the cell, and also does
+ * a sanity check.
+ */
+static void cell_release_singleton(struct cell *cell, struct bio *bio)
+{
+	struct bio_prison *prison = cell->prison;
+	struct bio_list bios;
+	struct bio *b;
+	unsigned long flags;
+
+	bio_list_init(&bios);
+
+	spin_lock_irqsave(&prison->lock, flags);
+	__cell_release(cell, &bios);
+	spin_unlock_irqrestore(&prison->lock, flags);
+
+	b = bio_list_pop(&bios);
+	BUG_ON(b != bio);
+	BUG_ON(!bio_list_empty(&bios));
+}
+
+static void cell_error(struct cell *cell)
+{
+	struct bio_prison *prison = cell->prison;
+	struct bio_list bios;
+	struct bio *bio;
+	unsigned long flags;
+
+	bio_list_init(&bios);
+
+	spin_lock_irqsave(&prison->lock, flags);
+	__cell_release(cell, &bios);
+	spin_unlock_irqrestore(&prison->lock, flags);
+
+	while ((bio = bio_list_pop(&bios)))
+		bio_io_error(bio);
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * We use the deferred set to keep track of pending reads to shared blocks.
+ * We do this to ensure the new mapping caused by a write isn't performed
+ * until these prior reads have completed.  Otherwise the insertion of the
+ * new mapping could free the old block that the read bios are mapped to.
+ */
+
+struct deferred_set;
+struct deferred_entry {
+	struct deferred_set *ds;
+	unsigned count;
+	struct list_head work_items;
+};
+
+struct deferred_set {
+	spinlock_t lock;
+	unsigned current_entry;
+	unsigned sweeper;
+	struct deferred_entry entries[DEFERRED_SET_SIZE];
+};
+
+static void ds_init(struct deferred_set *ds)
+{
+	int i;
+
+	spin_lock_init(&ds->lock);
+	ds->current_entry = 0;
+	ds->sweeper = 0;
+	for (i = 0; i < DEFERRED_SET_SIZE; i++) {
+		ds->entries[i].ds = ds;
+		ds->entries[i].count = 0;
+		INIT_LIST_HEAD(&ds->entries[i].work_items);
+	}
+}
+
+static struct deferred_entry *ds_inc(struct deferred_set *ds)
+{
+	unsigned long flags;
+	struct deferred_entry *entry;
+
+	spin_lock_irqsave(&ds->lock, flags);
+	entry = ds->entries + ds->current_entry;
+	entry->count++;
+	spin_unlock_irqrestore(&ds->lock, flags);
+
+	return entry;
+}
+
+static unsigned ds_next(unsigned index)
+{
+	return (index + 1) % DEFERRED_SET_SIZE;
+}
+
+static void __sweep(struct deferred_set *ds, struct list_head *head)
+{
+	while ((ds->sweeper != ds->current_entry) &&
+	       !ds->entries[ds->sweeper].count) {
+		list_splice_init(&ds->entries[ds->sweeper].work_items, head);
+		ds->sweeper = ds_next(ds->sweeper);
+	}
+
+	if ((ds->sweeper == ds->current_entry) && !ds->entries[ds->sweeper].count)
+		list_splice_init(&ds->entries[ds->sweeper].work_items, head);
+}
+
+static void ds_dec(struct deferred_entry *entry, struct list_head *head)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&entry->ds->lock, flags);
+	BUG_ON(!entry->count);
+	--entry->count;
+	__sweep(entry->ds, head);
+	spin_unlock_irqrestore(&entry->ds->lock, flags);
+}
+
+/*
+ * Returns 1 if deferred or 0 if no pending items to delay job.
+ */
+static int ds_add_work(struct deferred_set *ds, struct list_head *work)
+{
+	int r = 1;
+	unsigned long flags;
+	unsigned next_entry;
+
+	spin_lock_irqsave(&ds->lock, flags);
+	if ((ds->sweeper == ds->current_entry) &&
+	    !ds->entries[ds->current_entry].count)
+		r = 0;
+	else {
+		list_add(work, &ds->entries[ds->current_entry].work_items);
+		next_entry = ds_next(ds->current_entry);
+		if (!ds->entries[next_entry].count)
+			ds->current_entry = next_entry;
+	}
+	spin_unlock_irqrestore(&ds->lock, flags);
+
+	return r;
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Key building.
+ */
+static void build_data_key(struct dm_thin_device *td,
+			   dm_block_t b, struct cell_key *key)
+{
+	key->virtual = 0;
+	key->dev = dm_thin_dev_id(td);
+	key->block = b;
+}
+
+static void build_virtual_key(struct dm_thin_device *td, dm_block_t b,
+			      struct cell_key *key)
+{
+	key->virtual = 1;
+	key->dev = dm_thin_dev_id(td);
+	key->block = b;
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * A pool device ties together a metadata device and a data device.  It
+ * also provides the interface for creating and destroying internal
+ * devices.
+ */
+struct new_mapping;
+struct pool {
+	struct list_head list;
+	struct dm_target *ti;	/* Only set if a pool target is bound */
+
+	struct mapped_device *pool_md;
+	struct block_device *md_dev;
+	struct dm_pool_metadata *pmd;
+
+	uint32_t sectors_per_block;
+	unsigned block_shift;
+	dm_block_t offset_mask;
+	dm_block_t low_water_blocks;
+
+	unsigned zero_new_blocks:1;
+	unsigned low_water_triggered:1;	/* A dm event has been sent */
+	unsigned no_free_space:1;	/* A -ENOSPC warning has been issued */
+
+	struct bio_prison *prison;
+	struct dm_kcopyd_client *copier;
+
+	struct workqueue_struct *wq;
+	struct work_struct worker;
+
+	unsigned ref_count;
+
+	spinlock_t lock;
+	struct bio_list deferred_bios;
+	struct bio_list deferred_flush_bios;
+	struct list_head prepared_mappings;
+
+	struct bio_list retry_on_resume_list;
+
+	struct deferred_set ds;	/* FIXME: move to thin_c */
+
+	struct new_mapping *next_mapping;
+	mempool_t *mapping_pool;
+	mempool_t *endio_hook_pool;
+};
+
+/*
+ * Target context for a pool.
+ */
+struct pool_c {
+	struct dm_target *ti;
+	struct pool *pool;
+	struct dm_dev *data_dev;
+	struct dm_dev *metadata_dev;
+	struct dm_target_callbacks callbacks;
+
+	dm_block_t low_water_blocks;
+	unsigned zero_new_blocks:1;
+};
+
+/*
+ * Target context for a thin.
+ */
+struct thin_c {
+	struct dm_dev *pool_dev;
+	dm_thin_id dev_id;
+
+	struct pool *pool;
+	struct dm_thin_device *td;
+};
+
+/*----------------------------------------------------------------*/
+
+/*
+ * A global list of pools that uses a struct mapped_device as a key.
+ */
+static struct dm_thin_pool_table {
+	struct mutex mutex;
+	struct list_head pools;
+} dm_thin_pool_table;
+
+static void pool_table_init(void)
+{
+	mutex_init(&dm_thin_pool_table.mutex);
+	INIT_LIST_HEAD(&dm_thin_pool_table.pools);
+}
+
+static void __pool_table_insert(struct pool *pool)
+{
+	BUG_ON(!mutex_is_locked(&dm_thin_pool_table.mutex));
+	list_add(&pool->list, &dm_thin_pool_table.pools);
+}
+
+static void __pool_table_remove(struct pool *pool)
+{
+	BUG_ON(!mutex_is_locked(&dm_thin_pool_table.mutex));
+	list_del(&pool->list);
+}
+
+static struct pool *__pool_table_lookup(struct mapped_device *md)
+{
+	struct pool *pool = NULL, *tmp;
+
+	BUG_ON(!mutex_is_locked(&dm_thin_pool_table.mutex));
+
+	list_for_each_entry(tmp, &dm_thin_pool_table.pools, list) {
+		if (tmp->pool_md == md) {
+			pool = tmp;
+			break;
+		}
+	}
+
+	return pool;
+}
+
+static struct pool *__pool_table_lookup_metadata_dev(struct block_device *md_dev)
+{
+	struct pool *pool = NULL, *tmp;
+
+	BUG_ON(!mutex_is_locked(&dm_thin_pool_table.mutex));
+
+	list_for_each_entry(tmp, &dm_thin_pool_table.pools, list) {
+		if (tmp->md_dev == md_dev) {
+			pool = tmp;
+			break;
+		}
+	}
+
+	return pool;
+}
+
+/*----------------------------------------------------------------*/
+
+static void __requeue_bio_list(struct thin_c *tc, struct bio_list *master)
+{
+	struct bio *bio;
+	struct bio_list bios;
+
+	bio_list_init(&bios);
+	bio_list_merge(&bios, master);
+	bio_list_init(master);
+
+	while ((bio = bio_list_pop(&bios))) {
+		if (dm_get_mapinfo(bio)->ptr == tc)
+			bio_endio(bio, DM_ENDIO_REQUEUE);
+		else
+			bio_list_add(master, bio);
+	}
+}
+
+static void requeue_io(struct thin_c *tc)
+{
+	struct pool *pool = tc->pool;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pool->lock, flags);
+	__requeue_bio_list(tc, &pool->deferred_bios);
+	__requeue_bio_list(tc, &pool->retry_on_resume_list);
+	spin_unlock_irqrestore(&pool->lock, flags);
+}
+
+/*
+ * This section of code contains the logic for processing a thin device's IO.
+ * Much of the code depends on pool object resources (lists, workqueues, etc)
+ * but most is exclusively called from the thin target rather than the thin-pool
+ * target.
+ */
+
+static dm_block_t get_bio_block(struct thin_c *tc, struct bio *bio)
+{
+	return bio->bi_sector >> tc->pool->block_shift;
+}
+
+static void remap(struct thin_c *tc, struct bio *bio, dm_block_t block)
+{
+	struct pool *pool = tc->pool;
+
+	bio->bi_bdev = tc->pool_dev->bdev;
+	bio->bi_sector = (block << pool->block_shift) +
+		(bio->bi_sector & pool->offset_mask);
+}
+
+static void remap_and_issue(struct thin_c *tc, struct bio *bio,
+			    dm_block_t block)
+{
+	struct pool *pool = tc->pool;
+	unsigned long flags;
+
+	remap(tc, bio, block);
+
+	/*
+	 * Batch together any FUA/FLUSH bios we find and then issue
+	 * a single commit for them in process_deferred_bios().
+	 */
+	if (bio->bi_rw & (REQ_FLUSH | REQ_FUA)) {
+		spin_lock_irqsave(&pool->lock, flags);
+		bio_list_add(&pool->deferred_flush_bios, bio);
+		spin_unlock_irqrestore(&pool->lock, flags);
+	} else
+		generic_make_request(bio);
+}
+
+/*
+ * wake_worker() is used when new work is queued and when pool_resume is
+ * ready to continue deferred IO processing.
+ */
+static void wake_worker(struct pool *pool)
+{
+	queue_work(pool->wq, &pool->worker);
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Bio endio functions.
+ */
+struct endio_hook {
+	struct thin_c *tc;
+	bio_end_io_t *saved_bi_end_io;
+	struct deferred_entry *entry;
+};
+
+struct new_mapping {
+	struct list_head list;
+
+	int prepared;
+
+	struct thin_c *tc;
+	dm_block_t virt_block;
+	dm_block_t data_block;
+	struct cell *cell;
+	int err;
+
+	/*
+	 * If the bio covers the whole area of a block then we can avoid
+	 * zeroing or copying.  Instead this bio is hooked.  The bio will
+	 * still be in the cell, so care has to be taken to avoid issuing
+	 * the bio twice.
+	 */
+	struct bio *bio;
+	bio_end_io_t *saved_bi_end_io;
+};
+
+static void __maybe_add_mapping(struct new_mapping *m)
+{
+	struct pool *pool = m->tc->pool;
+
+	if (list_empty(&m->list) && m->prepared) {
+		list_add(&m->list, &pool->prepared_mappings);
+		wake_worker(pool);
+	}
+}
+
+static void copy_complete(int read_err, unsigned long write_err, void *context)
+{
+	unsigned long flags;
+	struct new_mapping *m = context;
+	struct pool *pool = m->tc->pool;
+
+	m->err = read_err || write_err ? -EIO : 0;
+
+	spin_lock_irqsave(&pool->lock, flags);
+	m->prepared = 1;
+	__maybe_add_mapping(m);
+	spin_unlock_irqrestore(&pool->lock, flags);
+}
+
+static void overwrite_endio(struct bio *bio, int err)
+{
+	unsigned long flags;
+	struct new_mapping *m = dm_get_mapinfo(bio)->ptr;
+	struct pool *pool = m->tc->pool;
+
+	m->err = err;
+
+	spin_lock_irqsave(&pool->lock, flags);
+	m->prepared = 1;
+	__maybe_add_mapping(m);
+	spin_unlock_irqrestore(&pool->lock, flags);
+}
+
+static void shared_read_endio(struct bio *bio, int err)
+{
+	struct list_head mappings;
+	struct new_mapping *m, *tmp;
+	struct endio_hook *h = dm_get_mapinfo(bio)->ptr;
+	unsigned long flags;
+	struct pool *pool = h->tc->pool;
+
+	bio->bi_end_io = h->saved_bi_end_io;
+	bio_endio(bio, err);
+
+	INIT_LIST_HEAD(&mappings);
+	ds_dec(h->entry, &mappings);
+
+	spin_lock_irqsave(&pool->lock, flags);
+	list_for_each_entry_safe(m, tmp, &mappings, list) {
+		list_del(&m->list);
+		INIT_LIST_HEAD(&m->list);
+		__maybe_add_mapping(m);
+	}
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	mempool_free(h, pool->endio_hook_pool);
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Workqueue.
+ */
+
+/*
+ * Prepared mapping jobs.
+ */
+
+/*
+ * This sends the bios in the cell back to the deferred_bios list.
+ */
+static void cell_defer(struct thin_c *tc, struct cell *cell,
+		       dm_block_t data_block)
+{
+	struct pool *pool = tc->pool;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pool->lock, flags);
+	cell_release(cell, &pool->deferred_bios);
+	spin_unlock_irqrestore(&tc->pool->lock, flags);
+
+	wake_worker(pool);
+}
+
+/*
+ * Same as cell_defer above, except it omits one particular detainee,
+ * a write bio that covers the block and has already been processed.
+ */
+static void cell_defer_except(struct thin_c *tc, struct cell *cell,
+			      struct bio *exception)
+{
+	struct bio_list bios;
+	struct bio *bio;
+	struct pool *pool = tc->pool;
+	unsigned long flags;
+
+	bio_list_init(&bios);
+	cell_release(cell, &bios);
+
+	spin_lock_irqsave(&pool->lock, flags);
+	while ((bio = bio_list_pop(&bios)))
+		if (bio != exception)
+			bio_list_add(&pool->deferred_bios, bio);
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	wake_worker(pool);
+}
+
+static void process_prepared_mapping(struct new_mapping *m)
+{
+	struct thin_c *tc = m->tc;
+	struct bio *bio;
+	int r;
+
+	bio = m->bio;
+	if (bio)
+		bio->bi_end_io = m->saved_bi_end_io;
+
+	if (m->err) {
+		cell_error(m->cell);
+		return;
+	}
+
+	/*
+	 * Commit the prepared block into the mapping btree.
+	 * Any I/O for this block arriving after this point will get
+	 * remapped to it directly.
+	 */
+	r = dm_thin_insert_block(tc->td, m->virt_block, m->data_block);
+	if (r) {
+		DMERR("dm_thin_insert_block() failed");
+		cell_error(m->cell);
+		return;
+	}
+
+	/*
+	 * Release any bios held while the block was being provisioned.
+	 * If we are processing a write bio that completely covers the block,
+	 * we already processed it so can ignore it now when processing
+	 * the bios in the cell.
+	 */
+	if (bio) {
+		cell_defer_except(tc, m->cell, bio);
+		bio_endio(bio, 0);
+	} else
+		cell_defer(tc, m->cell, m->data_block);
+
+	list_del(&m->list);
+	mempool_free(m, tc->pool->mapping_pool);
+}
+
+static void process_prepared_mappings(struct pool *pool)
+{
+	unsigned long flags;
+	struct list_head maps;
+	struct new_mapping *m, *tmp;
+
+	INIT_LIST_HEAD(&maps);
+	spin_lock_irqsave(&pool->lock, flags);
+	list_splice_init(&pool->prepared_mappings, &maps);
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	list_for_each_entry_safe(m, tmp, &maps, list)
+		process_prepared_mapping(m);
+}
+
+/*
+ * Deferred bio jobs.
+ */
+static int io_overwrites_block(struct pool *pool, struct bio *bio)
+{
+	return ((bio_data_dir(bio) == WRITE) &&
+		!(bio->bi_sector & pool->offset_mask)) &&
+		(bio->bi_size == (pool->sectors_per_block << SECTOR_SHIFT));
+}
+
+static void save_and_set_endio(struct bio *bio, bio_end_io_t **save,
+			       bio_end_io_t *fn)
+{
+	*save = bio->bi_end_io;
+	bio->bi_end_io = fn;
+}
+
+static int ensure_next_mapping(struct pool *pool)
+{
+	if (pool->next_mapping)
+		return 0;
+
+	pool->next_mapping = mempool_alloc(pool->mapping_pool, GFP_ATOMIC);
+
+	return pool->next_mapping ? 0 : -ENOMEM;
+}
+
+static struct new_mapping *get_next_mapping(struct pool *pool)
+{
+	struct new_mapping *r = pool->next_mapping;
+
+	BUG_ON(!pool->next_mapping);
+
+	pool->next_mapping = NULL;
+
+	return r;
+}
+
+static void schedule_copy(struct thin_c *tc, dm_block_t virt_block,
+			  dm_block_t data_origin, dm_block_t data_dest,
+			  struct cell *cell, struct bio *bio)
+{
+	int r;
+	struct pool *pool = tc->pool;
+	struct new_mapping *m = get_next_mapping(pool);
+
+	INIT_LIST_HEAD(&m->list);
+	m->prepared = 0;
+	m->tc = tc;
+	m->virt_block = virt_block;
+	m->data_block = data_dest;
+	m->cell = cell;
+	m->err = 0;
+	m->bio = NULL;
+
+	ds_add_work(&pool->ds, &m->list);
+
+	/*
+	 * IO to pool_dev remaps to the pool target's data_dev.
+	 *
+	 * If the whole block of data is being overwritten, we can issue the
+	 * bio immediately. Otherwise we use kcopyd to clone the data first.
+	 */
+	if (io_overwrites_block(pool, bio)) {
+		m->bio = bio;
+		save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio);
+		dm_get_mapinfo(bio)->ptr = m;
+		remap_and_issue(tc, bio, data_dest);
+	} else {
+		struct dm_io_region from, to;
+
+		from.bdev = tc->pool_dev->bdev;
+		from.sector = data_origin * pool->sectors_per_block;
+		from.count = pool->sectors_per_block;
+
+		to.bdev = tc->pool_dev->bdev;
+		to.sector = data_dest * pool->sectors_per_block;
+		to.count = pool->sectors_per_block;
+
+		r = dm_kcopyd_copy(pool->copier, &from, 1, &to,
+				   0, copy_complete, m);
+		if (r < 0) {
+			mempool_free(m, pool->mapping_pool);
+			DMERR("dm_kcopyd_copy() failed");
+			cell_error(cell);
+		}
+	}
+}
+
+static void schedule_zero(struct thin_c *tc, dm_block_t virt_block,
+			  dm_block_t data_block, struct cell *cell,
+			  struct bio *bio)
+{
+	struct pool *pool = tc->pool;
+	struct new_mapping *m = get_next_mapping(pool);
+
+	INIT_LIST_HEAD(&m->list);
+	m->prepared = 0;
+	m->tc = tc;
+	m->virt_block = virt_block;
+	m->data_block = data_block;
+	m->cell = cell;
+	m->err = 0;
+	m->bio = NULL;
+
+	/*
+	 * If the whole block of data is being overwritten or we are not
+	 * zeroing pre-existing data, we can issue the bio immediately.
+	 * Otherwise we use kcopyd to zero the data first.
+	 */
+	if (!pool->zero_new_blocks)
+		process_prepared_mapping(m);
+
+	else if (io_overwrites_block(pool, bio)) {
+		m->bio = bio;
+		save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio);
+		dm_get_mapinfo(bio)->ptr = m;
+		remap_and_issue(tc, bio, data_block);
+
+	} else {
+		int r;
+		struct dm_io_region to;
+
+		to.bdev = tc->pool_dev->bdev;
+		to.sector = data_block * pool->sectors_per_block;
+		to.count = pool->sectors_per_block;
+
+		r = dm_kcopyd_zero(pool->copier, 1, &to, 0, copy_complete, m);
+		if (r < 0) {
+			mempool_free(m, pool->mapping_pool);
+			DMERR("dm_kcopyd_zero() failed");
+			cell_error(cell);
+		}
+	}
+}
+
+static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
+{
+	int r;
+	dm_block_t free_blocks;
+	unsigned long flags;
+	struct pool *pool = tc->pool;
+
+	r = dm_pool_get_free_block_count(pool->pmd, &free_blocks);
+	if (r)
+		return r;
+
+	if (free_blocks <= pool->low_water_blocks && !pool->low_water_triggered) {
+		DMWARN("%s: reached low water mark, sending event.",
+		       dm_device_name(pool->pool_md));
+		spin_lock_irqsave(&pool->lock, flags);
+		pool->low_water_triggered = 1;
+		spin_unlock_irqrestore(&pool->lock, flags);
+		dm_table_event(pool->ti->table);
+	}
+
+	if (!free_blocks) {
+		if (pool->no_free_space)
+			return -ENOSPC;
+		else {
+			/*
+			 * Try to commit to see if that will free up some
+			 * more space.
+			 */
+			r = dm_pool_commit_metadata(pool->pmd);
+			if (r) {
+				DMERR("%s: dm_pool_commit_metadata() failed, error = %d",
+				      __func__, r);
+				return r;
+			}
+
+			r = dm_pool_get_free_block_count(pool->pmd, &free_blocks);
+			if (r)
+				return r;
+
+			/*
+			 * If we still have no space we set a flag to avoid
+			 * doing all this checking and return -ENOSPC.
+			 */
+			if (!free_blocks) {
+				DMWARN("%s: no free space available.",
+				       dm_device_name(pool->pool_md));
+				spin_lock_irqsave(&pool->lock, flags);
+				pool->no_free_space = 1;
+				spin_unlock_irqrestore(&pool->lock, flags);
+				return -ENOSPC;
+			}
+		}
+	}
+
+	r = dm_pool_alloc_data_block(pool->pmd, result);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+/*
+ * If we have run out of space, queue bios until the device is
+ * resumed, presumably after having been reloaded with more space.
+ */
+static void retry_on_resume(struct bio *bio)
+{
+	struct thin_c *tc = dm_get_mapinfo(bio)->ptr;
+	struct pool *pool = tc->pool;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pool->lock, flags);
+	bio_list_add(&pool->retry_on_resume_list, bio);
+	spin_unlock_irqrestore(&pool->lock, flags);
+}
+
+static void no_space(struct cell *cell)
+{
+	struct bio *bio;
+	struct bio_list bios;
+
+	bio_list_init(&bios);
+	cell_release(cell, &bios);
+
+	while ((bio = bio_list_pop(&bios)))
+		retry_on_resume(bio);
+}
+
+static void break_sharing(struct thin_c *tc, struct bio *bio, dm_block_t block,
+			  struct cell_key *key,
+			  struct dm_thin_lookup_result *lookup_result,
+			  struct cell *cell)
+{
+	int r;
+	dm_block_t data_block;
+
+	r = alloc_data_block(tc, &data_block);
+	switch (r) {
+	case 0:
+		schedule_copy(tc, block, lookup_result->block,
+			      data_block, cell, bio);
+		break;
+
+	case -ENOSPC:
+		no_space(cell);
+		break;
+
+	default:
+		DMERR("%s: alloc_data_block() failed, error = %d", __func__, r);
+		cell_error(cell);
+		break;
+	}
+}
+
+static void process_shared_bio(struct thin_c *tc, struct bio *bio,
+			       dm_block_t block,
+			       struct dm_thin_lookup_result *lookup_result)
+{
+	struct cell *cell;
+	struct pool *pool = tc->pool;
+	struct cell_key key;
+
+	/*
+	 * If cell is already occupied, then sharing is already in the process
+	 * of being broken so we have nothing further to do here.
+	 */
+	build_data_key(tc->td, lookup_result->block, &key);
+	if (bio_detain(pool->prison, &key, bio, &cell))
+		return;
+
+	if (bio_data_dir(bio) == WRITE)
+		break_sharing(tc, bio, block, &key, lookup_result, cell);
+	else {
+		struct endio_hook *h;
+		h = mempool_alloc(pool->endio_hook_pool, GFP_NOIO);
+
+		h->tc = tc;
+		h->entry = ds_inc(&pool->ds);
+		save_and_set_endio(bio, &h->saved_bi_end_io, shared_read_endio);
+		dm_get_mapinfo(bio)->ptr = h;
+
+		cell_release_singleton(cell, bio);
+		remap_and_issue(tc, bio, lookup_result->block);
+	}
+}
+
+static void provision_block(struct thin_c *tc, struct bio *bio, dm_block_t block,
+			    struct cell *cell)
+{
+	int r;
+	dm_block_t data_block;
+
+	/*
+	 * Remap empty bios (flushes) immediately, without provisioning.
+	 */
+	if (!bio->bi_size) {
+		cell_release_singleton(cell, bio);
+		remap_and_issue(tc, bio, 0);
+		return;
+	}
+
+	/*
+	 * Fill read bios with zeroes and complete them immediately.
+	 */
+	if (bio_data_dir(bio) == READ) {
+		zero_fill_bio(bio);
+		cell_release_singleton(cell, bio);
+		bio_endio(bio, 0);
+		return;
+	}
+
+	r = alloc_data_block(tc, &data_block);
+	switch (r) {
+	case 0:
+		schedule_zero(tc, block, data_block, cell, bio);
+		break;
+
+	case -ENOSPC:
+		no_space(cell);
+		break;
+
+	default:
+		DMERR("%s: alloc_data_block() failed, error = %d", __func__, r);
+		cell_error(cell);
+		break;
+	}
+}
+
+static void process_bio(struct thin_c *tc, struct bio *bio)
+{
+	int r;
+	dm_block_t block = get_bio_block(tc, bio);
+	struct cell *cell;
+	struct cell_key key;
+	struct dm_thin_lookup_result lookup_result;
+
+	/*
+	 * If cell is already occupied, then the block is already
+	 * being provisioned so we have nothing further to do here.
+	 */
+	build_virtual_key(tc->td, block, &key);
+	if (bio_detain(tc->pool->prison, &key, bio, &cell))
+		return;
+
+	r = dm_thin_find_block(tc->td, block, 1, &lookup_result);
+	switch (r) {
+	case 0:
+		/*
+		 * We can release this cell now.  This thread is the only
+		 * one that puts bios into a cell, and we know there were
+		 * no preceding bios.
+		 */
+		/*
+		 * TODO: this will probably have to change when discard goes
+		 * back in.
+		 */
+		cell_release_singleton(cell, bio);
+
+		if (lookup_result.shared)
+			process_shared_bio(tc, bio, block, &lookup_result);
+		else
+			remap_and_issue(tc, bio, lookup_result.block);
+		break;
+
+	case -ENODATA:
+		provision_block(tc, bio, block, cell);
+		break;
+
+	default:
+		DMERR("dm_thin_find_block() failed, error = %d", r);
+		bio_io_error(bio);
+		break;
+	}
+}
+
+static void process_deferred_bios(struct pool *pool)
+{
+	unsigned long flags;
+	struct bio *bio;
+	struct bio_list bios;
+	int r;
+
+	bio_list_init(&bios);
+
+	spin_lock_irqsave(&pool->lock, flags);
+	bio_list_merge(&bios, &pool->deferred_bios);
+	bio_list_init(&pool->deferred_bios);
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	while ((bio = bio_list_pop(&bios))) {
+		struct thin_c *tc = dm_get_mapinfo(bio)->ptr;
+		/*
+		 * If we've got no free new_mapping structs, and processing
+		 * this bio might require one, we pause until there are some
+		 * prepared mappings to process.
+		 */
+		if (ensure_next_mapping(pool)) {
+			spin_lock_irqsave(&pool->lock, flags);
+			bio_list_merge(&pool->deferred_bios, &bios);
+			spin_unlock_irqrestore(&pool->lock, flags);
+
+			break;
+		}
+		process_bio(tc, bio);
+	}
+
+	/*
+	 * If there are any deferred flush bios, we must commit
+	 * the metadata before issuing them.
+	 */
+	bio_list_init(&bios);
+	spin_lock_irqsave(&pool->lock, flags);
+	bio_list_merge(&bios, &pool->deferred_flush_bios);
+	bio_list_init(&pool->deferred_flush_bios);
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	if (bio_list_empty(&bios))
+		return;
+
+	r = dm_pool_commit_metadata(pool->pmd);
+	if (r) {
+		DMERR("%s: dm_pool_commit_metadata() failed, error = %d",
+		      __func__, r);
+		while ((bio = bio_list_pop(&bios)))
+			bio_io_error(bio);
+		return;
+	}
+
+	while ((bio = bio_list_pop(&bios)))
+		generic_make_request(bio);
+}
+
+static void do_worker(struct work_struct *ws)
+{
+	struct pool *pool = container_of(ws, struct pool, worker);
+
+	process_prepared_mappings(pool);
+	process_deferred_bios(pool);
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Mapping functions.
+ */
+
+/*
+ * Called only while mapping a thin bio to hand it over to the workqueue.
+ */
+static void thin_defer_bio(struct thin_c *tc, struct bio *bio)
+{
+	unsigned long flags;
+	struct pool *pool = tc->pool;
+
+	spin_lock_irqsave(&pool->lock, flags);
+	bio_list_add(&pool->deferred_bios, bio);
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	wake_worker(pool);
+}
+
+/*
+ * Non-blocking function called from the thin target's map function.
+ */
+static int thin_bio_map(struct dm_target *ti, struct bio *bio,
+			union map_info *map_context)
+{
+	int r;
+	struct thin_c *tc = ti->private;
+	dm_block_t block = get_bio_block(tc, bio);
+	struct dm_thin_device *td = tc->td;
+	struct dm_thin_lookup_result result;
+
+	/*
+	 * Save the thin context for easy access from the deferred bio later.
+	 */
+	map_context->ptr = tc;
+
+	if (bio->bi_rw & (REQ_FLUSH | REQ_FUA)) {
+		thin_defer_bio(tc, bio);
+		return DM_MAPIO_SUBMITTED;
+	}
+
+	r = dm_thin_find_block(td, block, 0, &result);
+
+	/*
+	 * Note that we defer readahead too.
+	 */
+	switch (r) {
+	case 0:
+		if (unlikely(result.shared)) {
+			/*
+			 * We have a race condition here between the
+			 * result.shared value returned by the lookup and
+			 * snapshot creation, which may cause new
+			 * sharing.
+			 *
+			 * To avoid this always quiesce the origin before
+			 * taking the snap.  You want to do this anyway to
+			 * ensure a consistent application view
+			 * (i.e. lockfs).
+			 *
+			 * More distant ancestors are irrelevant. The
+			 * shared flag will be set in their case.
+			 */
+			thin_defer_bio(tc, bio);
+			r = DM_MAPIO_SUBMITTED;
+		} else {
+			remap(tc, bio, result.block);
+			r = DM_MAPIO_REMAPPED;
+		}
+		break;
+
+	case -ENODATA:
+		/*
+		 * In future, the failed dm_thin_find_block above could
+		 * provide the hint to load the metadata into cache.
+		 */
+	case -EWOULDBLOCK:
+		thin_defer_bio(tc, bio);
+		r = DM_MAPIO_SUBMITTED;
+		break;
+	}
+
+	return r;
+}
+
+static int pool_is_congested(struct dm_target_callbacks *cb, int bdi_bits)
+{
+	int r;
+	unsigned long flags;
+	struct pool_c *pt = container_of(cb, struct pool_c, callbacks);
+
+	spin_lock_irqsave(&pt->pool->lock, flags);
+	r = !bio_list_empty(&pt->pool->retry_on_resume_list);
+	spin_unlock_irqrestore(&pt->pool->lock, flags);
+
+	if (!r) {
+		struct request_queue *q = bdev_get_queue(pt->data_dev->bdev);
+		r = bdi_congested(&q->backing_dev_info, bdi_bits);
+	}
+
+	return r;
+}
+
+static void __requeue_bios(struct pool *pool)
+{
+	bio_list_merge(&pool->deferred_bios, &pool->retry_on_resume_list);
+	bio_list_init(&pool->retry_on_resume_list);
+}
+
+/*----------------------------------------------------------------
+ * Binding of control targets to a pool object
+ *--------------------------------------------------------------*/
+static int bind_control_target(struct pool *pool, struct dm_target *ti)
+{
+	struct pool_c *pt = ti->private;
+
+	pool->ti = ti;
+	pool->low_water_blocks = pt->low_water_blocks;
+	pool->zero_new_blocks = pt->zero_new_blocks;
+
+	return 0;
+}
+
+static void unbind_control_target(struct pool *pool, struct dm_target *ti)
+{
+	if (pool->ti == ti)
+		pool->ti = NULL;
+}
+
+/*----------------------------------------------------------------
+ * Pool creation
+ *--------------------------------------------------------------*/
+static void __pool_destroy(struct pool *pool)
+{
+	__pool_table_remove(pool);
+
+	if (dm_pool_metadata_close(pool->pmd) < 0)
+		DMWARN("%s: dm_pool_metadata_close() failed.", __func__);
+
+	prison_destroy(pool->prison);
+	dm_kcopyd_client_destroy(pool->copier);
+
+	if (pool->wq)
+		destroy_workqueue(pool->wq);
+
+	if (pool->next_mapping)
+		mempool_free(pool->next_mapping, pool->mapping_pool);
+	mempool_destroy(pool->mapping_pool);
+	mempool_destroy(pool->endio_hook_pool);
+	kfree(pool);
+}
+
+static struct pool *pool_create(struct mapped_device *pool_md,
+				struct block_device *metadata_dev,
+				unsigned long block_size, char **error)
+{
+	int r;
+	void *err_p;
+	struct pool *pool;
+	struct dm_pool_metadata *pmd;
+
+	pmd = dm_pool_metadata_open(metadata_dev, block_size);
+	if (IS_ERR(pmd)) {
+		*error = "Error creating metadata object";
+		return (struct pool *)pmd;
+	}
+
+	pool = kmalloc(sizeof(*pool), GFP_KERNEL);
+	if (!pool) {
+		*error = "Error allocating memory for pool";
+		err_p = ERR_PTR(-ENOMEM);
+		goto bad_pool;
+	}
+
+	pool->pmd = pmd;
+	pool->sectors_per_block = block_size;
+	pool->block_shift = ffs(block_size) - 1;
+	pool->offset_mask = block_size - 1;
+	pool->low_water_blocks = 0;
+	pool->zero_new_blocks = 1;
+	pool->prison = prison_create(PRISON_CELLS);
+	if (!pool->prison) {
+		*error = "Error creating pool's bio prison";
+		err_p = ERR_PTR(-ENOMEM);
+		goto bad_prison;
+	}
+
+	pool->copier = dm_kcopyd_client_create();
+	if (IS_ERR(pool->copier)) {
+		r = PTR_ERR(pool->copier);
+		*error = "Error creating pool's kcopyd client";
+		err_p = ERR_PTR(r);
+		goto bad_kcopyd_client;
+	}
+
+	/*
+	 * Create singlethreaded workqueue that will service all devices
+	 * that use this metadata.
+	 */
+	pool->wq = alloc_ordered_workqueue("dm-" DM_MSG_PREFIX, WQ_MEM_RECLAIM);
+	if (!pool->wq) {
+		*error = "Error creating pool's workqueue";
+		err_p = ERR_PTR(-ENOMEM);
+		goto bad_wq;
+	}
+
+	INIT_WORK(&pool->worker, do_worker);
+	spin_lock_init(&pool->lock);
+	bio_list_init(&pool->deferred_bios);
+	bio_list_init(&pool->deferred_flush_bios);
+	INIT_LIST_HEAD(&pool->prepared_mappings);
+	pool->low_water_triggered = 0;
+	pool->no_free_space = 0;
+	bio_list_init(&pool->retry_on_resume_list);
+	ds_init(&pool->ds);
+
+	pool->next_mapping = NULL;
+	pool->mapping_pool =
+		mempool_create_kmalloc_pool(MAPPING_POOL_SIZE, sizeof(struct new_mapping));
+	if (!pool->mapping_pool) {
+		*error = "Error creating pool's mapping mempool";
+		err_p = ERR_PTR(-ENOMEM);
+		goto bad_mapping_pool;
+	}
+
+	pool->endio_hook_pool =
+		mempool_create_kmalloc_pool(ENDIO_HOOK_POOL_SIZE, sizeof(struct endio_hook));
+	if (!pool->endio_hook_pool) {
+		*error = "Error creating pool's endio_hook mempool";
+		err_p = ERR_PTR(-ENOMEM);
+		goto bad_endio_hook_pool;
+	}
+	pool->ref_count = 1;
+	pool->pool_md = pool_md;
+	pool->md_dev = metadata_dev;
+	__pool_table_insert(pool);
+
+	return pool;
+
+bad_endio_hook_pool:
+	mempool_destroy(pool->mapping_pool);
+bad_mapping_pool:
+	destroy_workqueue(pool->wq);
+bad_wq:
+	dm_kcopyd_client_destroy(pool->copier);
+bad_kcopyd_client:
+	prison_destroy(pool->prison);
+bad_prison:
+	kfree(pool);
+bad_pool:
+	if (dm_pool_metadata_close(pmd))
+		DMWARN("%s: dm_pool_metadata_close() failed.", __func__);
+
+	return err_p;
+}
+
+static void __pool_inc(struct pool *pool)
+{
+	BUG_ON(!mutex_is_locked(&dm_thin_pool_table.mutex));
+	pool->ref_count++;
+}
+
+static void __pool_dec(struct pool *pool)
+{
+	BUG_ON(!mutex_is_locked(&dm_thin_pool_table.mutex));
+	BUG_ON(!pool->ref_count);
+	if (!--pool->ref_count)
+		__pool_destroy(pool);
+}
+
+static struct pool *__pool_find(struct mapped_device *pool_md,
+				struct block_device *metadata_dev,
+				unsigned long block_size, char **error)
+{
+	struct pool *pool = __pool_table_lookup_metadata_dev(metadata_dev);
+
+	if (pool) {
+		if (pool->pool_md != pool_md)
+			return ERR_PTR(-EBUSY);
+		__pool_inc(pool);
+
+	} else {
+		pool = __pool_table_lookup(pool_md);
+		if (pool) {
+			if (pool->md_dev != metadata_dev)
+				return ERR_PTR(-EINVAL);
+			__pool_inc(pool);
+
+		} else
+			pool = pool_create(pool_md, metadata_dev, block_size, error);
+	}
+
+	return pool;
+}
+
+/*----------------------------------------------------------------
+ * Pool target methods
+ *--------------------------------------------------------------*/
+static void pool_dtr(struct dm_target *ti)
+{
+	struct pool_c *pt = ti->private;
+
+	mutex_lock(&dm_thin_pool_table.mutex);
+
+	unbind_control_target(pt->pool, ti);
+	__pool_dec(pt->pool);
+	dm_put_device(ti, pt->metadata_dev);
+	dm_put_device(ti, pt->data_dev);
+	kfree(pt);
+
+	mutex_unlock(&dm_thin_pool_table.mutex);
+}
+
+struct pool_features {
+	unsigned zero_new_blocks:1;
+};
+
+static int parse_pool_features(struct dm_arg_set *as, struct pool_features *pf,
+			       struct dm_target *ti)
+{
+	int r;
+	unsigned argc;
+	const char *arg_name;
+
+	static struct dm_arg _args[] = {
+		{0, 1, "Invalid number of pool feature arguments"},
+	};
+
+	/*
+	 * No feature arguments supplied.
+	 */
+	if (!as->argc)
+		return 0;
+
+	r = dm_read_arg_group(_args, as, &argc, &ti->error);
+	if (r)
+		return -EINVAL;
+
+	while (argc && !r) {
+		arg_name = dm_shift_arg(as);
+		argc--;
+
+		if (!strcasecmp(arg_name, "skip_block_zeroing")) {
+			pf->zero_new_blocks = 0;
+			continue;
+		}
+
+		ti->error = "Unrecognised pool feature requested";
+		r = -EINVAL;
+	}
+
+	return r;
+}
+
+/*
+ * thin-pool <metadata dev> <data dev>
+ *	     <data block size (sectors)>
+ *	     <low water mark (blocks)>
+ *	     [<#feature args> [<arg>]*]
+ *
+ * Optional feature arguments are:
+ *	     skip_block_zeroing: skips the zeroing of newly-provisioned blocks.
+ */
+static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
+{
+	int r;
+	struct pool_c *pt;
+	struct pool *pool;
+	struct pool_features pf;
+	struct dm_arg_set as;
+	struct dm_dev *data_dev;
+	unsigned long block_size;
+	dm_block_t low_water_blocks;
+	struct dm_dev *metadata_dev;
+	sector_t metadata_dev_size;
+
+	/*
+	 * FIXME Remove validation from scope of lock.
+	 */
+	mutex_lock(&dm_thin_pool_table.mutex);
+
+	if (argc < 4) {
+		ti->error = "Invalid argument count";
+		r = -EINVAL;
+		goto out_unlock;
+	}
+	as.argc = argc;
+	as.argv = argv;
+
+	r = dm_get_device(ti, argv[0], FMODE_READ | FMODE_WRITE, &metadata_dev);
+	if (r) {
+		ti->error = "Error opening metadata block device";
+		goto out_unlock;
+	}
+
+	metadata_dev_size = i_size_read(metadata_dev->bdev->bd_inode) >> SECTOR_SHIFT;
+	if (metadata_dev_size > METADATA_DEV_MAX_SECTORS) {
+		ti->error = "Metadata device is too large";
+		r = -EINVAL;
+		goto out_metadata;
+	}
+
+	r = dm_get_device(ti, argv[1], FMODE_READ | FMODE_WRITE, &data_dev);
+	if (r) {
+		ti->error = "Error getting data device";
+		goto out_metadata;
+	}
+
+	if (kstrtoul(argv[2], 10, &block_size) || !block_size ||
+	    block_size < DATA_DEV_BLOCK_SIZE_MIN_SECTORS ||
+	    block_size > DATA_DEV_BLOCK_SIZE_MAX_SECTORS ||
+	    !is_power_of_2(block_size)) {
+		ti->error = "Invalid block size";
+		r = -EINVAL;
+		goto out;
+	}
+
+	if (kstrtoull(argv[3], 10, (unsigned long long *)&low_water_blocks)) {
+		ti->error = "Invalid low water mark";
+		r = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * Set default pool features.
+	 */
+	memset(&pf, 0, sizeof(pf));
+	pf.zero_new_blocks = 1;
+
+	dm_consume_args(&as, 4);
+	r = parse_pool_features(&as, &pf, ti);
+	if (r)
+		goto out;
+
+	pt = kzalloc(sizeof(*pt), GFP_KERNEL);
+	if (!pt) {
+		r = -ENOMEM;
+		goto out;
+	}
+
+	pool = __pool_find(dm_table_get_md(ti->table), metadata_dev->bdev,
+			   block_size, &ti->error);
+	if (IS_ERR(pool)) {
+		r = PTR_ERR(pool);
+		goto out_free_pt;
+	}
+
+	pt->pool = pool;
+	pt->ti = ti;
+	pt->metadata_dev = metadata_dev;
+	pt->data_dev = data_dev;
+	pt->low_water_blocks = low_water_blocks;
+	pt->zero_new_blocks = pf.zero_new_blocks;
+	ti->num_flush_requests = 1;
+	ti->num_discard_requests = 0;
+	ti->private = pt;
+
+	pt->callbacks.congested_fn = pool_is_congested;
+	dm_table_add_target_callbacks(ti->table, &pt->callbacks);
+
+	mutex_unlock(&dm_thin_pool_table.mutex);
+
+	return 0;
+
+out_free_pt:
+	kfree(pt);
+out:
+	dm_put_device(ti, data_dev);
+out_metadata:
+	dm_put_device(ti, metadata_dev);
+out_unlock:
+	mutex_unlock(&dm_thin_pool_table.mutex);
+
+	return r;
+}
+
+static int pool_map(struct dm_target *ti, struct bio *bio,
+		    union map_info *map_context)
+{
+	int r;
+	struct pool_c *pt = ti->private;
+	struct pool *pool = pt->pool;
+	unsigned long flags;
+
+	/*
+	 * As this is a singleton target, ti->begin is always zero.
+	 */
+	spin_lock_irqsave(&pool->lock, flags);
+	bio->bi_bdev = pt->data_dev->bdev;
+	r = DM_MAPIO_REMAPPED;
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	return r;
+}
+
+/*
+ * Retrieves the number of blocks of the data device from
+ * the superblock and compares it to the actual device size,
+ * thus resizing the data device in case it has grown.
+ *
+ * This both copes with opening preallocated data devices in the ctr
+ * being followed by a resume
+ * -and-
+ * calling the resume method individually after userspace has
+ * grown the data device in reaction to a table event.
+ */
+static int pool_preresume(struct dm_target *ti)
+{
+	int r;
+	struct pool_c *pt = ti->private;
+	struct pool *pool = pt->pool;
+	dm_block_t data_size, sb_data_size;
+
+	/*
+	 * Take control of the pool object.
+	 */
+	r = bind_control_target(pool, ti);
+	if (r)
+		return r;
+
+	data_size = ti->len >> pool->block_shift;
+	r = dm_pool_get_data_dev_size(pool->pmd, &sb_data_size);
+	if (r) {
+		DMERR("failed to retrieve data device size");
+		return r;
+	}
+
+	if (data_size < sb_data_size) {
+		DMERR("pool target too small, is %llu blocks (expected %llu)",
+		      data_size, sb_data_size);
+		return -EINVAL;
+
+	} else if (data_size > sb_data_size) {
+		r = dm_pool_resize_data_dev(pool->pmd, data_size);
+		if (r) {
+			DMERR("failed to resize data device");
+			return r;
+		}
+
+		r = dm_pool_commit_metadata(pool->pmd);
+		if (r) {
+			DMERR("%s: dm_pool_commit_metadata() failed, error = %d",
+			      __func__, r);
+			return r;
+		}
+	}
+
+	return 0;
+}
+
+static void pool_resume(struct dm_target *ti)
+{
+	struct pool_c *pt = ti->private;
+	struct pool *pool = pt->pool;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pool->lock, flags);
+	pool->low_water_triggered = 0;
+	pool->no_free_space = 0;
+	__requeue_bios(pool);
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	wake_worker(pool);
+}
+
+static void pool_postsuspend(struct dm_target *ti)
+{
+	int r;
+	struct pool_c *pt = ti->private;
+	struct pool *pool = pt->pool;
+
+	flush_workqueue(pool->wq);
+
+	r = dm_pool_commit_metadata(pool->pmd);
+	if (r < 0) {
+		DMERR("%s: dm_pool_commit_metadata() failed, error = %d",
+		      __func__, r);
+		/* FIXME: invalidate device? error the next FUA or FLUSH bio ?*/
+	}
+}
+
+static int check_arg_count(unsigned argc, unsigned args_required)
+{
+	if (argc != args_required) {
+		DMWARN("Message received with %u arguments instead of %u.",
+		       argc, args_required);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int read_dev_id(char *arg, dm_thin_id *dev_id, int warning)
+{
+	if (!kstrtoull(arg, 10, (unsigned long long *)dev_id) &&
+	    *dev_id <= MAX_DEV_ID)
+		return 0;
+
+	if (warning)
+		DMWARN("Message received with invalid device id: %s", arg);
+
+	return -EINVAL;
+}
+
+static int process_create_thin_mesg(unsigned argc, char **argv, struct pool *pool)
+{
+	dm_thin_id dev_id;
+	int r;
+
+	r = check_arg_count(argc, 2);
+	if (r)
+		return r;
+
+	r = read_dev_id(argv[1], &dev_id, 1);
+	if (r)
+		return r;
+
+	r = dm_pool_create_thin(pool->pmd, dev_id);
+	if (r) {
+		DMWARN("Creation of new thinly-provisioned device with id %s failed.",
+		       argv[1]);
+		return r;
+	}
+
+	return 0;
+}
+
+static int process_create_snap_mesg(unsigned argc, char **argv, struct pool *pool)
+{
+	dm_thin_id dev_id;
+	dm_thin_id origin_dev_id;
+	int r;
+
+	r = check_arg_count(argc, 3);
+	if (r)
+		return r;
+
+	r = read_dev_id(argv[1], &dev_id, 1);
+	if (r)
+		return r;
+
+	r = read_dev_id(argv[2], &origin_dev_id, 1);
+	if (r)
+		return r;
+
+	r = dm_pool_create_snap(pool->pmd, dev_id, origin_dev_id);
+	if (r) {
+		DMWARN("Creation of new snapshot %s of device %s failed.",
+		       argv[1], argv[2]);
+		return r;
+	}
+
+	return 0;
+}
+
+static int process_delete_mesg(unsigned argc, char **argv, struct pool *pool)
+{
+	dm_thin_id dev_id;
+	int r;
+
+	r = check_arg_count(argc, 2);
+	if (r)
+		return r;
+
+	r = read_dev_id(argv[1], &dev_id, 1);
+	if (r)
+		return r;
+
+	r = dm_pool_delete_thin_device(pool->pmd, dev_id);
+	if (r)
+		DMWARN("Deletion of thin device %s failed.", argv[1]);
+
+	return r;
+}
+
+static int process_set_transaction_id_mesg(unsigned argc, char **argv, struct pool *pool)
+{
+	dm_thin_id old_id, new_id;
+	int r;
+
+	r = check_arg_count(argc, 3);
+	if (r)
+		return r;
+
+	if (kstrtoull(argv[1], 10, (unsigned long long *)&old_id)) {
+		DMWARN("set_transaction_id message: Unrecognised id %s.", argv[1]);
+		return -EINVAL;
+	}
+
+	if (kstrtoull(argv[2], 10, (unsigned long long *)&new_id)) {
+		DMWARN("set_transaction_id message: Unrecognised new id %s.", argv[2]);
+		return -EINVAL;
+	}
+
+	r = dm_pool_set_metadata_transaction_id(pool->pmd, old_id, new_id);
+	if (r) {
+		DMWARN("Failed to change transaction id from %s to %s.",
+		       argv[1], argv[2]);
+		return r;
+	}
+
+	return 0;
+}
+
+/*
+ * Messages supported:
+ *   create_thin	<dev_id>
+ *   create_snap	<dev_id> <origin_id>
+ *   delete		<dev_id>
+ *   trim		<dev_id> <new_size_in_sectors>
+ *   set_transaction_id <current_trans_id> <new_trans_id>
+ */
+static int pool_message(struct dm_target *ti, unsigned argc, char **argv)
+{
+	int r = -EINVAL;
+	struct pool_c *pt = ti->private;
+	struct pool *pool = pt->pool;
+
+	if (!strcasecmp(argv[0], "create_thin"))
+		r = process_create_thin_mesg(argc, argv, pool);
+
+	else if (!strcasecmp(argv[0], "create_snap"))
+		r = process_create_snap_mesg(argc, argv, pool);
+
+	else if (!strcasecmp(argv[0], "delete"))
+		r = process_delete_mesg(argc, argv, pool);
+
+	else if (!strcasecmp(argv[0], "set_transaction_id"))
+		r = process_set_transaction_id_mesg(argc, argv, pool);
+
+	else
+		DMWARN("Unrecognised thin pool target message received: %s", argv[0]);
+
+	if (!r) {
+		r = dm_pool_commit_metadata(pool->pmd);
+		if (r)
+			DMERR("%s message: dm_pool_commit_metadata() failed, error = %d",
+			      argv[0], r);
+	}
+
+	return r;
+}
+
+/*
+ * Status line is:
+ *    <transaction id> <used metadata sectors>/<total metadata sectors>
+ *    <used data sectors>/<total data sectors> <held metadata root>
+ */
+static int pool_status(struct dm_target *ti, status_type_t type,
+		       char *result, unsigned maxlen)
+{
+	int r;
+	unsigned sz = 0;
+	uint64_t transaction_id;
+	dm_block_t nr_free_blocks_data;
+	dm_block_t nr_free_blocks_metadata;
+	dm_block_t nr_blocks_data;
+	dm_block_t nr_blocks_metadata;
+	dm_block_t held_root;
+	char buf[BDEVNAME_SIZE];
+	char buf2[BDEVNAME_SIZE];
+	struct pool_c *pt = ti->private;
+	struct pool *pool = pt->pool;
+
+	switch (type) {
+	case STATUSTYPE_INFO:
+		r = dm_pool_get_metadata_transaction_id(pool->pmd,
+							&transaction_id);
+		if (r)
+			return r;
+
+		r = dm_pool_get_free_metadata_block_count(pool->pmd,
+							  &nr_free_blocks_metadata);
+		if (r)
+			return r;
+
+		r = dm_pool_get_metadata_dev_size(pool->pmd, &nr_blocks_metadata);
+		if (r)
+			return r;
+
+		r = dm_pool_get_free_block_count(pool->pmd,
+						 &nr_free_blocks_data);
+		if (r)
+			return r;
+
+		r = dm_pool_get_data_dev_size(pool->pmd, &nr_blocks_data);
+		if (r)
+			return r;
+
+		r = dm_pool_get_held_metadata_root(pool->pmd, &held_root);
+		if (r)
+			return r;
+
+		DMEMIT("%llu %llu/%llu %llu/%llu ",
+		       (unsigned long long)transaction_id,
+		       (unsigned long long)(nr_blocks_metadata - nr_free_blocks_metadata),
+		       (unsigned long long)nr_blocks_metadata,
+		       (unsigned long long)(nr_blocks_data - nr_free_blocks_data),
+		       (unsigned long long)nr_blocks_data);
+
+		if (held_root)
+			DMEMIT("%llu", held_root);
+		else
+			DMEMIT("-");
+
+		break;
+
+	case STATUSTYPE_TABLE:
+		DMEMIT("%s %s %lu %llu ",
+		       format_dev_t(buf, pt->metadata_dev->bdev->bd_dev),
+		       format_dev_t(buf2, pt->data_dev->bdev->bd_dev),
+		       (unsigned long)pool->sectors_per_block,
+		       (unsigned long long)pt->low_water_blocks);
+
+		DMEMIT("%u ", !pool->zero_new_blocks);
+
+		if (!pool->zero_new_blocks)
+			DMEMIT("skip_block_zeroing ");
+		break;
+	}
+
+	return 0;
+}
+
+static int pool_iterate_devices(struct dm_target *ti,
+				iterate_devices_callout_fn fn, void *data)
+{
+	struct pool_c *pt = ti->private;
+
+	return fn(ti, pt->data_dev, 0, ti->len, data);
+}
+
+static int pool_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
+		      struct bio_vec *biovec, int max_size)
+{
+	struct pool_c *pt = ti->private;
+	struct request_queue *q = bdev_get_queue(pt->data_dev->bdev);
+
+	if (!q->merge_bvec_fn)
+		return max_size;
+
+	bvm->bi_bdev = pt->data_dev->bdev;
+
+	return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
+}
+
+static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits)
+{
+	struct pool_c *pt = ti->private;
+	struct pool *pool = pt->pool;
+
+	blk_limits_io_min(limits, 0);
+	blk_limits_io_opt(limits, pool->sectors_per_block << SECTOR_SHIFT);
+}
+
+static struct target_type pool_target = {
+	.name = "thin-pool",
+	.features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE |
+		    DM_TARGET_IMMUTABLE,
+	.version = {1, 0, 0},
+	.module = THIS_MODULE,
+	.ctr = pool_ctr,
+	.dtr = pool_dtr,
+	.map = pool_map,
+	.postsuspend = pool_postsuspend,
+	.preresume = pool_preresume,
+	.resume = pool_resume,
+	.message = pool_message,
+	.status = pool_status,
+	.merge = pool_merge,
+	.iterate_devices = pool_iterate_devices,
+	.io_hints = pool_io_hints,
+};
+
+/*----------------------------------------------------------------
+ * Thin target methods
+ *--------------------------------------------------------------*/
+static void thin_dtr(struct dm_target *ti)
+{
+	struct thin_c *tc = ti->private;
+
+	mutex_lock(&dm_thin_pool_table.mutex);
+
+	__pool_dec(tc->pool);
+	dm_pool_close_thin_device(tc->td);
+	dm_put_device(ti, tc->pool_dev);
+	kfree(tc);
+
+	mutex_unlock(&dm_thin_pool_table.mutex);
+}
+
+/*
+ * Thin target parameters:
+ *
+ * <pool_dev> <dev_id>
+ *
+ * pool_dev: the path to the pool (eg, /dev/mapper/my_pool)
+ * dev_id: the internal device identifier
+ */
+static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
+{
+	int r;
+	struct thin_c *tc;
+	struct dm_dev *pool_dev;
+	struct mapped_device *pool_md;
+
+	mutex_lock(&dm_thin_pool_table.mutex);
+
+	if (argc != 2) {
+		ti->error = "Invalid argument count";
+		r = -EINVAL;
+		goto out_unlock;
+	}
+
+	tc = ti->private = kzalloc(sizeof(*tc), GFP_KERNEL);
+	if (!tc) {
+		ti->error = "Out of memory";
+		r = -ENOMEM;
+		goto out_unlock;
+	}
+
+	r = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &pool_dev);
+	if (r) {
+		ti->error = "Error opening pool device";
+		goto bad_pool_dev;
+	}
+	tc->pool_dev = pool_dev;
+
+	if (read_dev_id(argv[1], (unsigned long long *)&tc->dev_id, 0)) {
+		ti->error = "Invalid device id";
+		r = -EINVAL;
+		goto bad_common;
+	}
+
+	pool_md = dm_get_md(tc->pool_dev->bdev->bd_dev);
+	if (!pool_md) {
+		ti->error = "Couldn't get pool mapped device";
+		r = -EINVAL;
+		goto bad_common;
+	}
+
+	tc->pool = __pool_table_lookup(pool_md);
+	if (!tc->pool) {
+		ti->error = "Couldn't find pool object";
+		r = -EINVAL;
+		goto bad_pool_lookup;
+	}
+	__pool_inc(tc->pool);
+
+	r = dm_pool_open_thin_device(tc->pool->pmd, tc->dev_id, &tc->td);
+	if (r) {
+		ti->error = "Couldn't open thin internal device";
+		goto bad_thin_open;
+	}
+
+	ti->split_io = tc->pool->sectors_per_block;
+	ti->num_flush_requests = 1;
+	ti->num_discard_requests = 0;
+	ti->discards_supported = 0;
+
+	dm_put(pool_md);
+
+	mutex_unlock(&dm_thin_pool_table.mutex);
+
+	return 0;
+
+bad_thin_open:
+	__pool_dec(tc->pool);
+bad_pool_lookup:
+	dm_put(pool_md);
+bad_common:
+	dm_put_device(ti, tc->pool_dev);
+bad_pool_dev:
+	kfree(tc);
+out_unlock:
+	mutex_unlock(&dm_thin_pool_table.mutex);
+
+	return r;
+}
+
+static int thin_map(struct dm_target *ti, struct bio *bio,
+		    union map_info *map_context)
+{
+	bio->bi_sector -= ti->begin;
+
+	return thin_bio_map(ti, bio, map_context);
+}
+
+static void thin_postsuspend(struct dm_target *ti)
+{
+	if (dm_noflush_suspending(ti))
+		requeue_io((struct thin_c *)ti->private);
+}
+
+/*
+ * <nr mapped sectors> <highest mapped sector>
+ */
+static int thin_status(struct dm_target *ti, status_type_t type,
+		       char *result, unsigned maxlen)
+{
+	int r;
+	ssize_t sz = 0;
+	dm_block_t mapped, highest;
+	char buf[BDEVNAME_SIZE];
+	struct thin_c *tc = ti->private;
+
+	if (!tc->td)
+		DMEMIT("-");
+	else {
+		switch (type) {
+		case STATUSTYPE_INFO:
+			r = dm_thin_get_mapped_count(tc->td, &mapped);
+			if (r)
+				return r;
+
+			r = dm_thin_get_highest_mapped_block(tc->td, &highest);
+			if (r < 0)
+				return r;
+
+			DMEMIT("%llu ", mapped * tc->pool->sectors_per_block);
+			if (r)
+				DMEMIT("%llu", ((highest + 1) *
+						tc->pool->sectors_per_block) - 1);
+			else
+				DMEMIT("-");
+			break;
+
+		case STATUSTYPE_TABLE:
+			DMEMIT("%s %lu",
+			       format_dev_t(buf, tc->pool_dev->bdev->bd_dev),
+			       (unsigned long) tc->dev_id);
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static int thin_iterate_devices(struct dm_target *ti,
+				iterate_devices_callout_fn fn, void *data)
+{
+	dm_block_t blocks;
+	struct thin_c *tc = ti->private;
+
+	/*
+	 * We can't call dm_pool_get_data_dev_size() since that blocks.  So
+	 * we follow a more convoluted path through to the pool's target.
+	 */
+	if (!tc->pool->ti)
+		return 0;	/* nothing is bound */
+
+	blocks = tc->pool->ti->len >> tc->pool->block_shift;
+	if (blocks)
+		return fn(ti, tc->pool_dev, 0, tc->pool->sectors_per_block * blocks, data);
+
+	return 0;
+}
+
+static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits)
+{
+	struct thin_c *tc = ti->private;
+
+	blk_limits_io_min(limits, 0);
+	blk_limits_io_opt(limits, tc->pool->sectors_per_block << SECTOR_SHIFT);
+}
+
+static struct target_type thin_target = {
+	.name = "thin",
+	.version = {1, 0, 0},
+	.module	= THIS_MODULE,
+	.ctr = thin_ctr,
+	.dtr = thin_dtr,
+	.map = thin_map,
+	.postsuspend = thin_postsuspend,
+	.status = thin_status,
+	.iterate_devices = thin_iterate_devices,
+	.io_hints = thin_io_hints,
+};
+
+/*----------------------------------------------------------------*/
+
+static int __init dm_thin_init(void)
+{
+	int r;
+
+	pool_table_init();
+
+	r = dm_register_target(&thin_target);
+	if (r)
+		return r;
+
+	r = dm_register_target(&pool_target);
+	if (r)
+		dm_unregister_target(&thin_target);
+
+	return r;
+}
+
+static void dm_thin_exit(void)
+{
+	dm_unregister_target(&thin_target);
+	dm_unregister_target(&pool_target);
+}
+
+module_init(dm_thin_init);
+module_exit(dm_thin_exit);
+
+MODULE_DESCRIPTION(DM_NAME "device-mapper thin provisioning target");
+MODULE_AUTHOR("Joe Thornber <dm-devel@redhat.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 52b39f3..6b6616a 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -25,6 +25,16 @@
 
 #define DM_MSG_PREFIX "core"
 
+#ifdef CONFIG_PRINTK
+/*
+ * ratelimit state to be used in DMXXX_LIMIT().
+ */
+DEFINE_RATELIMIT_STATE(dm_ratelimit_state,
+		       DEFAULT_RATELIMIT_INTERVAL,
+		       DEFAULT_RATELIMIT_BURST);
+EXPORT_SYMBOL(dm_ratelimit_state);
+#endif
+
 /*
  * Cookies are numeric values sent with CHANGE and REMOVE
  * uevents while resuming, removing or renaming the device.
@@ -130,6 +140,8 @@ struct mapped_device {
 	/* Protect queue and type against concurrent access. */
 	struct mutex type_lock;
 
+	struct target_type *immutable_target_type;
+
 	struct gendisk *disk;
 	char name[16];
 
@@ -2086,6 +2098,8 @@ static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t,
 	write_lock_irqsave(&md->map_lock, flags);
 	old_map = md->map;
 	md->map = t;
+	md->immutable_target_type = dm_table_get_immutable_target_type(t);
+
 	dm_table_set_restrictions(t, q, limits);
 	if (merge_is_optional)
 		set_bit(DMF_MERGE_IS_OPTIONAL, &md->flags);
@@ -2156,6 +2170,11 @@ unsigned dm_get_md_type(struct mapped_device *md)
 	return md->type;
 }
 
+struct target_type *dm_get_immutable_target_type(struct mapped_device *md)
+{
+	return md->immutable_target_type;
+}
+
 /*
  * Fully initialize a request-based queue (->elevator, ->request_fn, etc).
  */
@@ -2231,6 +2250,7 @@ struct mapped_device *dm_get_md(dev_t dev)
 
 	return md;
 }
+EXPORT_SYMBOL_GPL(dm_get_md);
 
 void *dm_get_mdptr(struct mapped_device *md)
 {
@@ -2316,7 +2336,6 @@ static int dm_wait_for_completion(struct mapped_device *md, int interruptible)
 	while (1) {
 		set_current_state(interruptible);
 
-		smp_mb();
 		if (!md_in_flight(md))
 			break;
 
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index 6745dbd..b7dacd5 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -60,6 +60,7 @@ int dm_table_resume_targets(struct dm_table *t);
 int dm_table_any_congested(struct dm_table *t, int bdi_bits);
 int dm_table_any_busy_target(struct dm_table *t);
 unsigned dm_table_get_type(struct dm_table *t);
+struct target_type *dm_table_get_immutable_target_type(struct dm_table *t);
 bool dm_table_request_based(struct dm_table *t);
 bool dm_table_supports_discards(struct dm_table *t);
 int dm_table_alloc_md_mempools(struct dm_table *t);
@@ -72,6 +73,7 @@ void dm_lock_md_type(struct mapped_device *md);
 void dm_unlock_md_type(struct mapped_device *md);
 void dm_set_md_type(struct mapped_device *md, unsigned type);
 unsigned dm_get_md_type(struct mapped_device *md);
+struct target_type *dm_get_immutable_target_type(struct mapped_device *md);
 
 int dm_setup_md_queue(struct mapped_device *md);
 
diff --git a/drivers/md/persistent-data/Kconfig b/drivers/md/persistent-data/Kconfig
new file mode 100644
index 0000000..ceb3590
--- /dev/null
+++ b/drivers/md/persistent-data/Kconfig
@@ -0,0 +1,8 @@
+config DM_PERSISTENT_DATA
+       tristate
+       depends on BLK_DEV_DM && EXPERIMENTAL
+       select LIBCRC32C
+       select DM_BUFIO
+       ---help---
+	 Library providing immutable on-disk data structure support for
+	 device-mapper targets such as the thin provisioning target.
diff --git a/drivers/md/persistent-data/Makefile b/drivers/md/persistent-data/Makefile
new file mode 100644
index 0000000..cfa95f6
--- /dev/null
+++ b/drivers/md/persistent-data/Makefile
@@ -0,0 +1,11 @@
+obj-$(CONFIG_DM_PERSISTENT_DATA) += dm-persistent-data.o
+dm-persistent-data-objs := \
+	dm-block-manager.o \
+	dm-space-map-checker.o \
+	dm-space-map-common.o \
+	dm-space-map-disk.o \
+	dm-space-map-metadata.o \
+	dm-transaction-manager.o \
+	dm-btree.o \
+	dm-btree-remove.o \
+	dm-btree-spine.o
diff --git a/drivers/md/persistent-data/dm-block-manager.c b/drivers/md/persistent-data/dm-block-manager.c
new file mode 100644
index 0000000..0317ecd
--- /dev/null
+++ b/drivers/md/persistent-data/dm-block-manager.c
@@ -0,0 +1,620 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+#include "dm-block-manager.h"
+#include "dm-persistent-data-internal.h"
+#include "../dm-bufio.h"
+
+#include <linux/crc32c.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/rwsem.h>
+#include <linux/device-mapper.h>
+#include <linux/stacktrace.h>
+
+#define DM_MSG_PREFIX "block manager"
+
+/*----------------------------------------------------------------*/
+
+/*
+ * This is a read/write semaphore with a couple of differences.
+ *
+ * i) There is a restriction on the number of concurrent read locks that
+ * may be held at once.  This is just an implementation detail.
+ *
+ * ii) Recursive locking attempts are detected and return EINVAL.  A stack
+ * trace is also emitted for the previous lock aquisition.
+ *
+ * iii) Priority is given to write locks.
+ */
+#define MAX_HOLDERS 4
+#define MAX_STACK 10
+
+typedef unsigned long stack_entries[MAX_STACK];
+
+struct block_lock {
+	spinlock_t lock;
+	__s32 count;
+	struct list_head waiters;
+	struct task_struct *holders[MAX_HOLDERS];
+
+#ifdef CONFIG_DM_DEBUG_BLOCK_STACK_TRACING
+	struct stack_trace traces[MAX_HOLDERS];
+	stack_entries entries[MAX_HOLDERS];
+#endif
+};
+
+struct waiter {
+	struct list_head list;
+	struct task_struct *task;
+	int wants_write;
+};
+
+static unsigned __find_holder(struct block_lock *lock,
+			      struct task_struct *task)
+{
+	unsigned i;
+
+	for (i = 0; i < MAX_HOLDERS; i++)
+		if (lock->holders[i] == task)
+			break;
+
+	BUG_ON(i == MAX_HOLDERS);
+	return i;
+}
+
+/* call this *after* you increment lock->count */
+static void __add_holder(struct block_lock *lock, struct task_struct *task)
+{
+	unsigned h = __find_holder(lock, NULL);
+#ifdef CONFIG_DM_DEBUG_BLOCK_STACK_TRACING
+	struct stack_trace *t;
+#endif
+
+	get_task_struct(task);
+	lock->holders[h] = task;
+
+#ifdef CONFIG_DM_DEBUG_BLOCK_STACK_TRACING
+	t = lock->traces + h;
+	t->nr_entries = 0;
+	t->max_entries = MAX_STACK;
+	t->entries = lock->entries[h];
+	t->skip = 2;
+	save_stack_trace(t);
+#endif
+}
+
+/* call this *before* you decrement lock->count */
+static void __del_holder(struct block_lock *lock, struct task_struct *task)
+{
+	unsigned h = __find_holder(lock, task);
+	lock->holders[h] = NULL;
+	put_task_struct(task);
+}
+
+static int __check_holder(struct block_lock *lock)
+{
+	unsigned i;
+#ifdef CONFIG_DM_DEBUG_BLOCK_STACK_TRACING
+	static struct stack_trace t;
+	static stack_entries entries;
+#endif
+
+	for (i = 0; i < MAX_HOLDERS; i++) {
+		if (lock->holders[i] == current) {
+			DMERR("recursive lock detected in pool metadata");
+#ifdef CONFIG_DM_DEBUG_BLOCK_STACK_TRACING
+			DMERR("previously held here:");
+			print_stack_trace(lock->traces + i, 4);
+
+			DMERR("subsequent aquisition attempted here:");
+			t.nr_entries = 0;
+			t.max_entries = MAX_STACK;
+			t.entries = entries;
+			t.skip = 3;
+			save_stack_trace(&t);
+			print_stack_trace(&t, 4);
+#endif
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static void __wait(struct waiter *w)
+{
+	for (;;) {
+		set_task_state(current, TASK_UNINTERRUPTIBLE);
+
+		if (!w->task)
+			break;
+
+		schedule();
+	}
+
+	set_task_state(current, TASK_RUNNING);
+}
+
+static void __wake_waiter(struct waiter *w)
+{
+	struct task_struct *task;
+
+	list_del(&w->list);
+	task = w->task;
+	smp_mb();
+	w->task = NULL;
+	wake_up_process(task);
+}
+
+/*
+ * We either wake a few readers or a single writer.
+ */
+static void __wake_many(struct block_lock *lock)
+{
+	struct waiter *w, *tmp;
+
+	BUG_ON(lock->count < 0);
+	list_for_each_entry_safe(w, tmp, &lock->waiters, list) {
+		if (lock->count >= MAX_HOLDERS)
+			return;
+
+		if (w->wants_write) {
+			if (lock->count > 0)
+				return; /* still read locked */
+
+			lock->count = -1;
+			__add_holder(lock, w->task);
+			__wake_waiter(w);
+			return;
+		}
+
+		lock->count++;
+		__add_holder(lock, w->task);
+		__wake_waiter(w);
+	}
+}
+
+static void bl_init(struct block_lock *lock)
+{
+	int i;
+
+	spin_lock_init(&lock->lock);
+	lock->count = 0;
+	INIT_LIST_HEAD(&lock->waiters);
+	for (i = 0; i < MAX_HOLDERS; i++)
+		lock->holders[i] = NULL;
+}
+
+static int __available_for_read(struct block_lock *lock)
+{
+	return lock->count >= 0 &&
+		lock->count < MAX_HOLDERS &&
+		list_empty(&lock->waiters);
+}
+
+static int bl_down_read(struct block_lock *lock)
+{
+	int r;
+	struct waiter w;
+
+	spin_lock(&lock->lock);
+	r = __check_holder(lock);
+	if (r) {
+		spin_unlock(&lock->lock);
+		return r;
+	}
+
+	if (__available_for_read(lock)) {
+		lock->count++;
+		__add_holder(lock, current);
+		spin_unlock(&lock->lock);
+		return 0;
+	}
+
+	get_task_struct(current);
+
+	w.task = current;
+	w.wants_write = 0;
+	list_add_tail(&w.list, &lock->waiters);
+	spin_unlock(&lock->lock);
+
+	__wait(&w);
+	put_task_struct(current);
+	return 0;
+}
+
+static int bl_down_read_nonblock(struct block_lock *lock)
+{
+	int r;
+
+	spin_lock(&lock->lock);
+	r = __check_holder(lock);
+	if (r)
+		goto out;
+
+	if (__available_for_read(lock)) {
+		lock->count++;
+		__add_holder(lock, current);
+		r = 0;
+	} else
+		r = -EWOULDBLOCK;
+
+out:
+	spin_unlock(&lock->lock);
+	return r;
+}
+
+static void bl_up_read(struct block_lock *lock)
+{
+	spin_lock(&lock->lock);
+	BUG_ON(lock->count <= 0);
+	__del_holder(lock, current);
+	--lock->count;
+	if (!list_empty(&lock->waiters))
+		__wake_many(lock);
+	spin_unlock(&lock->lock);
+}
+
+static int bl_down_write(struct block_lock *lock)
+{
+	int r;
+	struct waiter w;
+
+	spin_lock(&lock->lock);
+	r = __check_holder(lock);
+	if (r) {
+		spin_unlock(&lock->lock);
+		return r;
+	}
+
+	if (lock->count == 0 && list_empty(&lock->waiters)) {
+		lock->count = -1;
+		__add_holder(lock, current);
+		spin_unlock(&lock->lock);
+		return 0;
+	}
+
+	get_task_struct(current);
+	w.task = current;
+	w.wants_write = 1;
+
+	/*
+	 * Writers given priority. We know there's only one mutator in the
+	 * system, so ignoring the ordering reversal.
+	 */
+	list_add(&w.list, &lock->waiters);
+	spin_unlock(&lock->lock);
+
+	__wait(&w);
+	put_task_struct(current);
+
+	return 0;
+}
+
+static void bl_up_write(struct block_lock *lock)
+{
+	spin_lock(&lock->lock);
+	__del_holder(lock, current);
+	lock->count = 0;
+	if (!list_empty(&lock->waiters))
+		__wake_many(lock);
+	spin_unlock(&lock->lock);
+}
+
+static void report_recursive_bug(dm_block_t b, int r)
+{
+	if (r == -EINVAL)
+		DMERR("recursive acquisition of block %llu requested.",
+		      (unsigned long long) b);
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Block manager is currently implemented using dm-bufio.  struct
+ * dm_block_manager and struct dm_block map directly onto a couple of
+ * structs in the bufio interface.  I want to retain the freedom to move
+ * away from bufio in the future.  So these structs are just cast within
+ * this .c file, rather than making it through to the public interface.
+ */
+static struct dm_buffer *to_buffer(struct dm_block *b)
+{
+	return (struct dm_buffer *) b;
+}
+
+static struct dm_bufio_client *to_bufio(struct dm_block_manager *bm)
+{
+	return (struct dm_bufio_client *) bm;
+}
+
+dm_block_t dm_block_location(struct dm_block *b)
+{
+	return dm_bufio_get_block_number(to_buffer(b));
+}
+EXPORT_SYMBOL_GPL(dm_block_location);
+
+void *dm_block_data(struct dm_block *b)
+{
+	return dm_bufio_get_block_data(to_buffer(b));
+}
+EXPORT_SYMBOL_GPL(dm_block_data);
+
+struct buffer_aux {
+	struct dm_block_validator *validator;
+	struct block_lock lock;
+	int write_locked;
+};
+
+static void dm_block_manager_alloc_callback(struct dm_buffer *buf)
+{
+	struct buffer_aux *aux = dm_bufio_get_aux_data(buf);
+	aux->validator = NULL;
+	bl_init(&aux->lock);
+}
+
+static void dm_block_manager_write_callback(struct dm_buffer *buf)
+{
+	struct buffer_aux *aux = dm_bufio_get_aux_data(buf);
+	if (aux->validator) {
+		aux->validator->prepare_for_write(aux->validator, (struct dm_block *) buf,
+			 dm_bufio_get_block_size(dm_bufio_get_client(buf)));
+	}
+}
+
+/*----------------------------------------------------------------
+ * Public interface
+ *--------------------------------------------------------------*/
+struct dm_block_manager *dm_block_manager_create(struct block_device *bdev,
+						 unsigned block_size,
+						 unsigned cache_size,
+						 unsigned max_held_per_thread)
+{
+	return (struct dm_block_manager *)
+		dm_bufio_client_create(bdev, block_size, max_held_per_thread,
+				       sizeof(struct buffer_aux),
+				       dm_block_manager_alloc_callback,
+				       dm_block_manager_write_callback);
+}
+EXPORT_SYMBOL_GPL(dm_block_manager_create);
+
+void dm_block_manager_destroy(struct dm_block_manager *bm)
+{
+	return dm_bufio_client_destroy(to_bufio(bm));
+}
+EXPORT_SYMBOL_GPL(dm_block_manager_destroy);
+
+unsigned dm_bm_block_size(struct dm_block_manager *bm)
+{
+	return dm_bufio_get_block_size(to_bufio(bm));
+}
+EXPORT_SYMBOL_GPL(dm_bm_block_size);
+
+dm_block_t dm_bm_nr_blocks(struct dm_block_manager *bm)
+{
+	return dm_bufio_get_device_size(to_bufio(bm));
+}
+
+static int dm_bm_validate_buffer(struct dm_block_manager *bm,
+				 struct dm_buffer *buf,
+				 struct buffer_aux *aux,
+				 struct dm_block_validator *v)
+{
+	if (unlikely(!aux->validator)) {
+		int r;
+		if (!v)
+			return 0;
+		r = v->check(v, (struct dm_block *) buf, dm_bufio_get_block_size(to_bufio(bm)));
+		if (unlikely(r))
+			return r;
+		aux->validator = v;
+	} else {
+		if (unlikely(aux->validator != v)) {
+			DMERR("validator mismatch (old=%s vs new=%s) for block %llu",
+				aux->validator->name, v ? v->name : "NULL",
+				(unsigned long long)
+					dm_bufio_get_block_number(buf));
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+int dm_bm_read_lock(struct dm_block_manager *bm, dm_block_t b,
+		    struct dm_block_validator *v,
+		    struct dm_block **result)
+{
+	struct buffer_aux *aux;
+	void *p;
+	int r;
+
+	p = dm_bufio_read(to_bufio(bm), b, (struct dm_buffer **) result);
+	if (unlikely(IS_ERR(p)))
+		return PTR_ERR(p);
+
+	aux = dm_bufio_get_aux_data(to_buffer(*result));
+	r = bl_down_read(&aux->lock);
+	if (unlikely(r)) {
+		dm_bufio_release(to_buffer(*result));
+		report_recursive_bug(b, r);
+		return r;
+	}
+
+	aux->write_locked = 0;
+
+	r = dm_bm_validate_buffer(bm, to_buffer(*result), aux, v);
+	if (unlikely(r)) {
+		bl_up_read(&aux->lock);
+		dm_bufio_release(to_buffer(*result));
+		return r;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dm_bm_read_lock);
+
+int dm_bm_write_lock(struct dm_block_manager *bm,
+		     dm_block_t b, struct dm_block_validator *v,
+		     struct dm_block **result)
+{
+	struct buffer_aux *aux;
+	void *p;
+	int r;
+
+	p = dm_bufio_read(to_bufio(bm), b, (struct dm_buffer **) result);
+	if (unlikely(IS_ERR(p)))
+		return PTR_ERR(p);
+
+	aux = dm_bufio_get_aux_data(to_buffer(*result));
+	r = bl_down_write(&aux->lock);
+	if (r) {
+		dm_bufio_release(to_buffer(*result));
+		report_recursive_bug(b, r);
+		return r;
+	}
+
+	aux->write_locked = 1;
+
+	r = dm_bm_validate_buffer(bm, to_buffer(*result), aux, v);
+	if (unlikely(r)) {
+		bl_up_write(&aux->lock);
+		dm_bufio_release(to_buffer(*result));
+		return r;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dm_bm_write_lock);
+
+int dm_bm_read_try_lock(struct dm_block_manager *bm,
+			dm_block_t b, struct dm_block_validator *v,
+			struct dm_block **result)
+{
+	struct buffer_aux *aux;
+	void *p;
+	int r;
+
+	p = dm_bufio_get(to_bufio(bm), b, (struct dm_buffer **) result);
+	if (unlikely(IS_ERR(p)))
+		return PTR_ERR(p);
+	if (unlikely(!p))
+		return -EWOULDBLOCK;
+
+	aux = dm_bufio_get_aux_data(to_buffer(*result));
+	r = bl_down_read_nonblock(&aux->lock);
+	if (r < 0) {
+		dm_bufio_release(to_buffer(*result));
+		report_recursive_bug(b, r);
+		return r;
+	}
+	aux->write_locked = 0;
+
+	r = dm_bm_validate_buffer(bm, to_buffer(*result), aux, v);
+	if (unlikely(r)) {
+		bl_up_read(&aux->lock);
+		dm_bufio_release(to_buffer(*result));
+		return r;
+	}
+
+	return 0;
+}
+
+int dm_bm_write_lock_zero(struct dm_block_manager *bm,
+			  dm_block_t b, struct dm_block_validator *v,
+			  struct dm_block **result)
+{
+	int r;
+	struct buffer_aux *aux;
+	void *p;
+
+	p = dm_bufio_new(to_bufio(bm), b, (struct dm_buffer **) result);
+	if (unlikely(IS_ERR(p)))
+		return PTR_ERR(p);
+
+	memset(p, 0, dm_bm_block_size(bm));
+
+	aux = dm_bufio_get_aux_data(to_buffer(*result));
+	r = bl_down_write(&aux->lock);
+	if (r) {
+		dm_bufio_release(to_buffer(*result));
+		return r;
+	}
+
+	aux->write_locked = 1;
+	aux->validator = v;
+
+	return 0;
+}
+
+int dm_bm_unlock(struct dm_block *b)
+{
+	struct buffer_aux *aux;
+	aux = dm_bufio_get_aux_data(to_buffer(b));
+
+	if (aux->write_locked) {
+		dm_bufio_mark_buffer_dirty(to_buffer(b));
+		bl_up_write(&aux->lock);
+	} else
+		bl_up_read(&aux->lock);
+
+	dm_bufio_release(to_buffer(b));
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dm_bm_unlock);
+
+int dm_bm_unlock_move(struct dm_block *b, dm_block_t n)
+{
+	struct buffer_aux *aux;
+
+	aux = dm_bufio_get_aux_data(to_buffer(b));
+
+	if (aux->write_locked) {
+		dm_bufio_mark_buffer_dirty(to_buffer(b));
+		bl_up_write(&aux->lock);
+	} else
+		bl_up_read(&aux->lock);
+
+	dm_bufio_release_move(to_buffer(b), n);
+	return 0;
+}
+
+int dm_bm_flush_and_unlock(struct dm_block_manager *bm,
+			   struct dm_block *superblock)
+{
+	int r;
+
+	r = dm_bufio_write_dirty_buffers(to_bufio(bm));
+	if (unlikely(r))
+		return r;
+	r = dm_bufio_issue_flush(to_bufio(bm));
+	if (unlikely(r))
+		return r;
+
+	dm_bm_unlock(superblock);
+
+	r = dm_bufio_write_dirty_buffers(to_bufio(bm));
+	if (unlikely(r))
+		return r;
+	r = dm_bufio_issue_flush(to_bufio(bm));
+	if (unlikely(r))
+		return r;
+
+	return 0;
+}
+
+u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor)
+{
+	return crc32c(~(u32) 0, data, len) ^ init_xor;
+}
+EXPORT_SYMBOL_GPL(dm_bm_checksum);
+
+/*----------------------------------------------------------------*/
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Joe Thornber <dm-devel@redhat.com>");
+MODULE_DESCRIPTION("Immutable metadata library for dm");
+
+/*----------------------------------------------------------------*/
diff --git a/drivers/md/persistent-data/dm-block-manager.h b/drivers/md/persistent-data/dm-block-manager.h
new file mode 100644
index 0000000..924833d
--- /dev/null
+++ b/drivers/md/persistent-data/dm-block-manager.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef _LINUX_DM_BLOCK_MANAGER_H
+#define _LINUX_DM_BLOCK_MANAGER_H
+
+#include <linux/types.h>
+#include <linux/blkdev.h>
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Block number.
+ */
+typedef uint64_t dm_block_t;
+struct dm_block;
+
+dm_block_t dm_block_location(struct dm_block *b);
+void *dm_block_data(struct dm_block *b);
+
+/*----------------------------------------------------------------*/
+
+/*
+ * @name should be a unique identifier for the block manager, no longer
+ * than 32 chars.
+ *
+ * @max_held_per_thread should be the maximum number of locks, read or
+ * write, that an individual thread holds at any one time.
+ */
+struct dm_block_manager;
+struct dm_block_manager *dm_block_manager_create(
+	struct block_device *bdev, unsigned block_size,
+	unsigned cache_size, unsigned max_held_per_thread);
+void dm_block_manager_destroy(struct dm_block_manager *bm);
+
+unsigned dm_bm_block_size(struct dm_block_manager *bm);
+dm_block_t dm_bm_nr_blocks(struct dm_block_manager *bm);
+
+/*----------------------------------------------------------------*/
+
+/*
+ * The validator allows the caller to verify newly-read data and modify
+ * the data just before writing, e.g. to calculate checksums.  It's
+ * important to be consistent with your use of validators.  The only time
+ * you can change validators is if you call dm_bm_write_lock_zero.
+ */
+struct dm_block_validator {
+	const char *name;
+	void (*prepare_for_write)(struct dm_block_validator *v, struct dm_block *b, size_t block_size);
+
+	/*
+	 * Return 0 if the checksum is valid or < 0 on error.
+	 */
+	int (*check)(struct dm_block_validator *v, struct dm_block *b, size_t block_size);
+};
+
+/*----------------------------------------------------------------*/
+
+/*
+ * You can have multiple concurrent readers or a single writer holding a
+ * block lock.
+ */
+
+/*
+ * dm_bm_lock() locks a block and returns through @result a pointer to
+ * memory that holds a copy of that block.  If you have write-locked the
+ * block then any changes you make to memory pointed to by @result will be
+ * written back to the disk sometime after dm_bm_unlock is called.
+ */
+int dm_bm_read_lock(struct dm_block_manager *bm, dm_block_t b,
+		    struct dm_block_validator *v,
+		    struct dm_block **result);
+
+int dm_bm_write_lock(struct dm_block_manager *bm, dm_block_t b,
+		     struct dm_block_validator *v,
+		     struct dm_block **result);
+
+/*
+ * The *_try_lock variants return -EWOULDBLOCK if the block isn't
+ * available immediately.
+ */
+int dm_bm_read_try_lock(struct dm_block_manager *bm, dm_block_t b,
+			struct dm_block_validator *v,
+			struct dm_block **result);
+
+/*
+ * Use dm_bm_write_lock_zero() when you know you're going to
+ * overwrite the block completely.  It saves a disk read.
+ */
+int dm_bm_write_lock_zero(struct dm_block_manager *bm, dm_block_t b,
+			  struct dm_block_validator *v,
+			  struct dm_block **result);
+
+int dm_bm_unlock(struct dm_block *b);
+
+/*
+ * An optimisation; we often want to copy a block's contents to a new
+ * block.  eg, as part of the shadowing operation.  It's far better for
+ * bufio to do this move behind the scenes than hold 2 locks and memcpy the
+ * data.
+ */
+int dm_bm_unlock_move(struct dm_block *b, dm_block_t n);
+
+/*
+ * It's a common idiom to have a superblock that should be committed last.
+ *
+ * @superblock should be write-locked on entry. It will be unlocked during
+ * this function.  All dirty blocks are guaranteed to be written and flushed
+ * before the superblock.
+ *
+ * This method always blocks.
+ */
+int dm_bm_flush_and_unlock(struct dm_block_manager *bm,
+			   struct dm_block *superblock);
+
+u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor);
+
+/*----------------------------------------------------------------*/
+
+#endif	/* _LINUX_DM_BLOCK_MANAGER_H */
diff --git a/drivers/md/persistent-data/dm-btree-internal.h b/drivers/md/persistent-data/dm-btree-internal.h
new file mode 100644
index 0000000..d279c76
--- /dev/null
+++ b/drivers/md/persistent-data/dm-btree-internal.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef DM_BTREE_INTERNAL_H
+#define DM_BTREE_INTERNAL_H
+
+#include "dm-btree.h"
+
+/*----------------------------------------------------------------*/
+
+/*
+ * We'll need 2 accessor functions for n->csum and n->blocknr
+ * to support dm-btree-spine.c in that case.
+ */
+
+enum node_flags {
+	INTERNAL_NODE = 1,
+	LEAF_NODE = 1 << 1
+};
+
+/*
+ * Every btree node begins with this structure.  Make sure it's a multiple
+ * of 8-bytes in size, otherwise the 64bit keys will be mis-aligned.
+ */
+struct node_header {
+	__le32 csum;
+	__le32 flags;
+	__le64 blocknr; /* Block this node is supposed to live in. */
+
+	__le32 nr_entries;
+	__le32 max_entries;
+	__le32 value_size;
+	__le32 padding;
+} __packed;
+
+struct node {
+	struct node_header header;
+	__le64 keys[0];
+} __packed;
+
+
+void inc_children(struct dm_transaction_manager *tm, struct node *n,
+		  struct dm_btree_value_type *vt);
+
+int new_block(struct dm_btree_info *info, struct dm_block **result);
+int unlock_block(struct dm_btree_info *info, struct dm_block *b);
+
+/*
+ * Spines keep track of the rolling locks.  There are 2 variants, read-only
+ * and one that uses shadowing.  These are separate structs to allow the
+ * type checker to spot misuse, for example accidentally calling read_lock
+ * on a shadow spine.
+ */
+struct ro_spine {
+	struct dm_btree_info *info;
+
+	int count;
+	struct dm_block *nodes[2];
+};
+
+void init_ro_spine(struct ro_spine *s, struct dm_btree_info *info);
+int exit_ro_spine(struct ro_spine *s);
+int ro_step(struct ro_spine *s, dm_block_t new_child);
+struct node *ro_node(struct ro_spine *s);
+
+struct shadow_spine {
+	struct dm_btree_info *info;
+
+	int count;
+	struct dm_block *nodes[2];
+
+	dm_block_t root;
+};
+
+void init_shadow_spine(struct shadow_spine *s, struct dm_btree_info *info);
+int exit_shadow_spine(struct shadow_spine *s);
+
+int shadow_step(struct shadow_spine *s, dm_block_t b,
+		struct dm_btree_value_type *vt);
+
+/*
+ * The spine must have at least one entry before calling this.
+ */
+struct dm_block *shadow_current(struct shadow_spine *s);
+
+/*
+ * The spine must have at least two entries before calling this.
+ */
+struct dm_block *shadow_parent(struct shadow_spine *s);
+
+int shadow_has_parent(struct shadow_spine *s);
+
+int shadow_root(struct shadow_spine *s);
+
+/*
+ * Some inlines.
+ */
+static inline __le64 *key_ptr(struct node *n, uint32_t index)
+{
+	return n->keys + index;
+}
+
+static inline void *value_base(struct node *n)
+{
+	return &n->keys[le32_to_cpu(n->header.max_entries)];
+}
+
+/*
+ * FIXME: Now that value size is stored in node we don't need the third parm.
+ */
+static inline void *value_ptr(struct node *n, uint32_t index, size_t value_size)
+{
+	BUG_ON(value_size != le32_to_cpu(n->header.value_size));
+	return value_base(n) + (value_size * index);
+}
+
+/*
+ * Assumes the values are suitably-aligned and converts to core format.
+ */
+static inline uint64_t value64(struct node *n, uint32_t index)
+{
+	__le64 *values_le = value_base(n);
+
+	return le64_to_cpu(values_le[index]);
+}
+
+/*
+ * Searching for a key within a single node.
+ */
+int lower_bound(struct node *n, uint64_t key);
+
+extern struct dm_block_validator btree_node_validator;
+
+#endif	/* DM_BTREE_INTERNAL_H */
diff --git a/drivers/md/persistent-data/dm-btree-remove.c b/drivers/md/persistent-data/dm-btree-remove.c
new file mode 100644
index 0000000..65fd85e
--- /dev/null
+++ b/drivers/md/persistent-data/dm-btree-remove.c
@@ -0,0 +1,566 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-btree.h"
+#include "dm-btree-internal.h"
+#include "dm-transaction-manager.h"
+
+#include <linux/module.h>
+
+/*
+ * Removing an entry from a btree
+ * ==============================
+ *
+ * A very important constraint for our btree is that no node, except the
+ * root, may have fewer than a certain number of entries.
+ * (MIN_ENTRIES <= nr_entries <= MAX_ENTRIES).
+ *
+ * Ensuring this is complicated by the way we want to only ever hold the
+ * locks on 2 nodes concurrently, and only change nodes in a top to bottom
+ * fashion.
+ *
+ * Each node may have a left or right sibling.  When decending the spine,
+ * if a node contains only MIN_ENTRIES then we try and increase this to at
+ * least MIN_ENTRIES + 1.  We do this in the following ways:
+ *
+ * [A] No siblings => this can only happen if the node is the root, in which
+ *     case we copy the childs contents over the root.
+ *
+ * [B] No left sibling
+ *     ==> rebalance(node, right sibling)
+ *
+ * [C] No right sibling
+ *     ==> rebalance(left sibling, node)
+ *
+ * [D] Both siblings, total_entries(left, node, right) <= DEL_THRESHOLD
+ *     ==> delete node adding it's contents to left and right
+ *
+ * [E] Both siblings, total_entries(left, node, right) > DEL_THRESHOLD
+ *     ==> rebalance(left, node, right)
+ *
+ * After these operations it's possible that the our original node no
+ * longer contains the desired sub tree.  For this reason this rebalancing
+ * is performed on the children of the current node.  This also avoids
+ * having a special case for the root.
+ *
+ * Once this rebalancing has occurred we can then step into the child node
+ * for internal nodes.  Or delete the entry for leaf nodes.
+ */
+
+/*
+ * Some little utilities for moving node data around.
+ */
+static void node_shift(struct node *n, int shift)
+{
+	uint32_t nr_entries = le32_to_cpu(n->header.nr_entries);
+	uint32_t value_size = le32_to_cpu(n->header.value_size);
+
+	if (shift < 0) {
+		shift = -shift;
+		BUG_ON(shift > nr_entries);
+		BUG_ON((void *) key_ptr(n, shift) >= value_ptr(n, shift, value_size));
+		memmove(key_ptr(n, 0),
+			key_ptr(n, shift),
+			(nr_entries - shift) * sizeof(__le64));
+		memmove(value_ptr(n, 0, value_size),
+			value_ptr(n, shift, value_size),
+			(nr_entries - shift) * value_size);
+	} else {
+		BUG_ON(nr_entries + shift > le32_to_cpu(n->header.max_entries));
+		memmove(key_ptr(n, shift),
+			key_ptr(n, 0),
+			nr_entries * sizeof(__le64));
+		memmove(value_ptr(n, shift, value_size),
+			value_ptr(n, 0, value_size),
+			nr_entries * value_size);
+	}
+}
+
+static void node_copy(struct node *left, struct node *right, int shift)
+{
+	uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
+	uint32_t value_size = le32_to_cpu(left->header.value_size);
+	BUG_ON(value_size != le32_to_cpu(right->header.value_size));
+
+	if (shift < 0) {
+		shift = -shift;
+		BUG_ON(nr_left + shift > le32_to_cpu(left->header.max_entries));
+		memcpy(key_ptr(left, nr_left),
+		       key_ptr(right, 0),
+		       shift * sizeof(__le64));
+		memcpy(value_ptr(left, nr_left, value_size),
+		       value_ptr(right, 0, value_size),
+		       shift * value_size);
+	} else {
+		BUG_ON(shift > le32_to_cpu(right->header.max_entries));
+		memcpy(key_ptr(right, 0),
+		       key_ptr(left, nr_left - shift),
+		       shift * sizeof(__le64));
+		memcpy(value_ptr(right, 0, value_size),
+		       value_ptr(left, nr_left - shift, value_size),
+		       shift * value_size);
+	}
+}
+
+/*
+ * Delete a specific entry from a leaf node.
+ */
+static void delete_at(struct node *n, unsigned index)
+{
+	unsigned nr_entries = le32_to_cpu(n->header.nr_entries);
+	unsigned nr_to_copy = nr_entries - (index + 1);
+	uint32_t value_size = le32_to_cpu(n->header.value_size);
+	BUG_ON(index >= nr_entries);
+
+	if (nr_to_copy) {
+		memmove(key_ptr(n, index),
+			key_ptr(n, index + 1),
+			nr_to_copy * sizeof(__le64));
+
+		memmove(value_ptr(n, index, value_size),
+			value_ptr(n, index + 1, value_size),
+			nr_to_copy * value_size);
+	}
+
+	n->header.nr_entries = cpu_to_le32(nr_entries - 1);
+}
+
+static unsigned del_threshold(struct node *n)
+{
+	return le32_to_cpu(n->header.max_entries) / 3;
+}
+
+static unsigned merge_threshold(struct node *n)
+{
+	/*
+	 * The extra one is because we know we're potentially going to
+	 * delete an entry.
+	 */
+	return 2 * (le32_to_cpu(n->header.max_entries) / 3) + 1;
+}
+
+struct child {
+	unsigned index;
+	struct dm_block *block;
+	struct node *n;
+};
+
+static struct dm_btree_value_type le64_type = {
+	.context = NULL,
+	.size = sizeof(__le64),
+	.inc = NULL,
+	.dec = NULL,
+	.equal = NULL
+};
+
+static int init_child(struct dm_btree_info *info, struct node *parent,
+		      unsigned index, struct child *result)
+{
+	int r, inc;
+	dm_block_t root;
+
+	result->index = index;
+	root = value64(parent, index);
+
+	r = dm_tm_shadow_block(info->tm, root, &btree_node_validator,
+			       &result->block, &inc);
+	if (r)
+		return r;
+
+	result->n = dm_block_data(result->block);
+
+	if (inc)
+		inc_children(info->tm, result->n, &le64_type);
+
+	*((__le64 *) value_ptr(parent, index, sizeof(__le64))) =
+		cpu_to_le64(dm_block_location(result->block));
+
+	return 0;
+}
+
+static int exit_child(struct dm_btree_info *info, struct child *c)
+{
+	return dm_tm_unlock(info->tm, c->block);
+}
+
+static void shift(struct node *left, struct node *right, int count)
+{
+	if (!count)
+		return;
+
+	if (count > 0) {
+		node_shift(right, count);
+		node_copy(left, right, count);
+	} else {
+		node_copy(left, right, count);
+		node_shift(right, count);
+	}
+
+	left->header.nr_entries =
+		cpu_to_le32(le32_to_cpu(left->header.nr_entries) - count);
+	BUG_ON(le32_to_cpu(left->header.nr_entries) > le32_to_cpu(left->header.max_entries));
+
+	right->header.nr_entries =
+		cpu_to_le32(le32_to_cpu(right->header.nr_entries) + count);
+	BUG_ON(le32_to_cpu(right->header.nr_entries) > le32_to_cpu(right->header.max_entries));
+}
+
+static void __rebalance2(struct dm_btree_info *info, struct node *parent,
+			 struct child *l, struct child *r)
+{
+	struct node *left = l->n;
+	struct node *right = r->n;
+	uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
+	uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
+
+	if (nr_left + nr_right <= merge_threshold(left)) {
+		/*
+		 * Merge
+		 */
+		node_copy(left, right, -nr_right);
+		left->header.nr_entries = cpu_to_le32(nr_left + nr_right);
+		delete_at(parent, r->index);
+
+		/*
+		 * We need to decrement the right block, but not it's
+		 * children, since they're still referenced by left.
+		 */
+		dm_tm_dec(info->tm, dm_block_location(r->block));
+	} else {
+		/*
+		 * Rebalance.
+		 */
+		unsigned target_left = (nr_left + nr_right) / 2;
+		unsigned shift_ = nr_left - target_left;
+		BUG_ON(le32_to_cpu(left->header.max_entries) <= nr_left - shift_);
+		BUG_ON(le32_to_cpu(right->header.max_entries) <= nr_right + shift_);
+		shift(left, right, nr_left - target_left);
+		*key_ptr(parent, r->index) = right->keys[0];
+	}
+}
+
+static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info,
+		      unsigned left_index)
+{
+	int r;
+	struct node *parent;
+	struct child left, right;
+
+	parent = dm_block_data(shadow_current(s));
+
+	r = init_child(info, parent, left_index, &left);
+	if (r)
+		return r;
+
+	r = init_child(info, parent, left_index + 1, &right);
+	if (r) {
+		exit_child(info, &left);
+		return r;
+	}
+
+	__rebalance2(info, parent, &left, &right);
+
+	r = exit_child(info, &left);
+	if (r) {
+		exit_child(info, &right);
+		return r;
+	}
+
+	return exit_child(info, &right);
+}
+
+static void __rebalance3(struct dm_btree_info *info, struct node *parent,
+			 struct child *l, struct child *c, struct child *r)
+{
+	struct node *left = l->n;
+	struct node *center = c->n;
+	struct node *right = r->n;
+
+	uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
+	uint32_t nr_center = le32_to_cpu(center->header.nr_entries);
+	uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
+	uint32_t max_entries = le32_to_cpu(left->header.max_entries);
+
+	unsigned target;
+
+	BUG_ON(left->header.max_entries != center->header.max_entries);
+	BUG_ON(center->header.max_entries != right->header.max_entries);
+
+	if (((nr_left + nr_center + nr_right) / 2) < merge_threshold(center)) {
+		/*
+		 * Delete center node:
+		 *
+		 * We dump as many entries from center as possible into
+		 * left, then the rest in right, then rebalance2.  This
+		 * wastes some cpu, but I want something simple atm.
+		 */
+		unsigned shift = min(max_entries - nr_left, nr_center);
+
+		BUG_ON(nr_left + shift > max_entries);
+		node_copy(left, center, -shift);
+		left->header.nr_entries = cpu_to_le32(nr_left + shift);
+
+		if (shift != nr_center) {
+			shift = nr_center - shift;
+			BUG_ON((nr_right + shift) >= max_entries);
+			node_shift(right, shift);
+			node_copy(center, right, shift);
+			right->header.nr_entries = cpu_to_le32(nr_right + shift);
+		}
+		*key_ptr(parent, r->index) = right->keys[0];
+
+		delete_at(parent, c->index);
+		r->index--;
+
+		dm_tm_dec(info->tm, dm_block_location(c->block));
+		__rebalance2(info, parent, l, r);
+
+		return;
+	}
+
+	/*
+	 * Rebalance
+	 */
+	target = (nr_left + nr_center + nr_right) / 3;
+	BUG_ON(target > max_entries);
+
+	/*
+	 * Adjust the left node
+	 */
+	shift(left, center, nr_left - target);
+
+	/*
+	 * Adjust the right node
+	 */
+	shift(center, right, target - nr_right);
+	*key_ptr(parent, c->index) = center->keys[0];
+	*key_ptr(parent, r->index) = right->keys[0];
+}
+
+static int rebalance3(struct shadow_spine *s, struct dm_btree_info *info,
+		      unsigned left_index)
+{
+	int r;
+	struct node *parent = dm_block_data(shadow_current(s));
+	struct child left, center, right;
+
+	/*
+	 * FIXME: fill out an array?
+	 */
+	r = init_child(info, parent, left_index, &left);
+	if (r)
+		return r;
+
+	r = init_child(info, parent, left_index + 1, &center);
+	if (r) {
+		exit_child(info, &left);
+		return r;
+	}
+
+	r = init_child(info, parent, left_index + 2, &right);
+	if (r) {
+		exit_child(info, &left);
+		exit_child(info, &center);
+		return r;
+	}
+
+	__rebalance3(info, parent, &left, &center, &right);
+
+	r = exit_child(info, &left);
+	if (r) {
+		exit_child(info, &center);
+		exit_child(info, &right);
+		return r;
+	}
+
+	r = exit_child(info, &center);
+	if (r) {
+		exit_child(info, &right);
+		return r;
+	}
+
+	r = exit_child(info, &right);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+static int get_nr_entries(struct dm_transaction_manager *tm,
+			  dm_block_t b, uint32_t *result)
+{
+	int r;
+	struct dm_block *block;
+	struct node *n;
+
+	r = dm_tm_read_lock(tm, b, &btree_node_validator, &block);
+	if (r)
+		return r;
+
+	n = dm_block_data(block);
+	*result = le32_to_cpu(n->header.nr_entries);
+
+	return dm_tm_unlock(tm, block);
+}
+
+static int rebalance_children(struct shadow_spine *s,
+			      struct dm_btree_info *info, uint64_t key)
+{
+	int i, r, has_left_sibling, has_right_sibling;
+	uint32_t child_entries;
+	struct node *n;
+
+	n = dm_block_data(shadow_current(s));
+
+	if (le32_to_cpu(n->header.nr_entries) == 1) {
+		struct dm_block *child;
+		dm_block_t b = value64(n, 0);
+
+		r = dm_tm_read_lock(info->tm, b, &btree_node_validator, &child);
+		if (r)
+			return r;
+
+		memcpy(n, dm_block_data(child),
+		       dm_bm_block_size(dm_tm_get_bm(info->tm)));
+		r = dm_tm_unlock(info->tm, child);
+		if (r)
+			return r;
+
+		dm_tm_dec(info->tm, dm_block_location(child));
+		return 0;
+	}
+
+	i = lower_bound(n, key);
+	if (i < 0)
+		return -ENODATA;
+
+	r = get_nr_entries(info->tm, value64(n, i), &child_entries);
+	if (r)
+		return r;
+
+	if (child_entries > del_threshold(n))
+		return 0;
+
+	has_left_sibling = i > 0;
+	has_right_sibling = i < (le32_to_cpu(n->header.nr_entries) - 1);
+
+	if (!has_left_sibling)
+		r = rebalance2(s, info, i);
+
+	else if (!has_right_sibling)
+		r = rebalance2(s, info, i - 1);
+
+	else
+		r = rebalance3(s, info, i - 1);
+
+	return r;
+}
+
+static int do_leaf(struct node *n, uint64_t key, unsigned *index)
+{
+	int i = lower_bound(n, key);
+
+	if ((i < 0) ||
+	    (i >= le32_to_cpu(n->header.nr_entries)) ||
+	    (le64_to_cpu(n->keys[i]) != key))
+		return -ENODATA;
+
+	*index = i;
+
+	return 0;
+}
+
+/*
+ * Prepares for removal from one level of the hierarchy.  The caller must
+ * call delete_at() to remove the entry at index.
+ */
+static int remove_raw(struct shadow_spine *s, struct dm_btree_info *info,
+		      struct dm_btree_value_type *vt, dm_block_t root,
+		      uint64_t key, unsigned *index)
+{
+	int i = *index, r;
+	struct node *n;
+
+	for (;;) {
+		r = shadow_step(s, root, vt);
+		if (r < 0)
+			break;
+
+		/*
+		 * We have to patch up the parent node, ugly, but I don't
+		 * see a way to do this automatically as part of the spine
+		 * op.
+		 */
+		if (shadow_has_parent(s)) {
+			__le64 location = cpu_to_le64(dm_block_location(shadow_current(s)));
+			memcpy(value_ptr(dm_block_data(shadow_parent(s)), i, sizeof(__le64)),
+			       &location, sizeof(__le64));
+		}
+
+		n = dm_block_data(shadow_current(s));
+
+		if (le32_to_cpu(n->header.flags) & LEAF_NODE)
+			return do_leaf(n, key, index);
+
+		r = rebalance_children(s, info, key);
+		if (r)
+			break;
+
+		n = dm_block_data(shadow_current(s));
+		if (le32_to_cpu(n->header.flags) & LEAF_NODE)
+			return do_leaf(n, key, index);
+
+		i = lower_bound(n, key);
+
+		/*
+		 * We know the key is present, or else
+		 * rebalance_children would have returned
+		 * -ENODATA
+		 */
+		root = value64(n, i);
+	}
+
+	return r;
+}
+
+int dm_btree_remove(struct dm_btree_info *info, dm_block_t root,
+		    uint64_t *keys, dm_block_t *new_root)
+{
+	unsigned level, last_level = info->levels - 1;
+	int index = 0, r = 0;
+	struct shadow_spine spine;
+	struct node *n;
+
+	init_shadow_spine(&spine, info);
+	for (level = 0; level < info->levels; level++) {
+		r = remove_raw(&spine, info,
+			       (level == last_level ?
+				&info->value_type : &le64_type),
+			       root, keys[level], (unsigned *)&index);
+		if (r < 0)
+			break;
+
+		n = dm_block_data(shadow_current(&spine));
+		if (level != last_level) {
+			root = value64(n, index);
+			continue;
+		}
+
+		BUG_ON(index < 0 || index >= le32_to_cpu(n->header.nr_entries));
+
+		if (info->value_type.dec)
+			info->value_type.dec(info->value_type.context,
+					     value_ptr(n, index, info->value_type.size));
+
+		delete_at(n, index);
+	}
+
+	*new_root = shadow_root(&spine);
+	exit_shadow_spine(&spine);
+
+	return r;
+}
+EXPORT_SYMBOL_GPL(dm_btree_remove);
diff --git a/drivers/md/persistent-data/dm-btree-spine.c b/drivers/md/persistent-data/dm-btree-spine.c
new file mode 100644
index 0000000..d9a7912
--- /dev/null
+++ b/drivers/md/persistent-data/dm-btree-spine.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-btree-internal.h"
+#include "dm-transaction-manager.h"
+
+#include <linux/device-mapper.h>
+
+#define DM_MSG_PREFIX "btree spine"
+
+/*----------------------------------------------------------------*/
+
+#define BTREE_CSUM_XOR 121107
+
+static int node_check(struct dm_block_validator *v,
+		      struct dm_block *b,
+		      size_t block_size);
+
+static void node_prepare_for_write(struct dm_block_validator *v,
+				   struct dm_block *b,
+				   size_t block_size)
+{
+	struct node *n = dm_block_data(b);
+	struct node_header *h = &n->header;
+
+	h->blocknr = cpu_to_le64(dm_block_location(b));
+	h->csum = cpu_to_le32(dm_bm_checksum(&h->flags,
+					     block_size - sizeof(__le32),
+					     BTREE_CSUM_XOR));
+
+	BUG_ON(node_check(v, b, 4096));
+}
+
+static int node_check(struct dm_block_validator *v,
+		      struct dm_block *b,
+		      size_t block_size)
+{
+	struct node *n = dm_block_data(b);
+	struct node_header *h = &n->header;
+	size_t value_size;
+	__le32 csum_disk;
+	uint32_t flags;
+
+	if (dm_block_location(b) != le64_to_cpu(h->blocknr)) {
+		DMERR("node_check failed blocknr %llu wanted %llu",
+		      le64_to_cpu(h->blocknr), dm_block_location(b));
+		return -ENOTBLK;
+	}
+
+	csum_disk = cpu_to_le32(dm_bm_checksum(&h->flags,
+					       block_size - sizeof(__le32),
+					       BTREE_CSUM_XOR));
+	if (csum_disk != h->csum) {
+		DMERR("node_check failed csum %u wanted %u",
+		      le32_to_cpu(csum_disk), le32_to_cpu(h->csum));
+		return -EILSEQ;
+	}
+
+	value_size = le32_to_cpu(h->value_size);
+
+	if (sizeof(struct node_header) +
+	    (sizeof(__le64) + value_size) * le32_to_cpu(h->max_entries) > block_size) {
+		DMERR("node_check failed: max_entries too large");
+		return -EILSEQ;
+	}
+
+	if (le32_to_cpu(h->nr_entries) > le32_to_cpu(h->max_entries)) {
+		DMERR("node_check failed, too many entries");
+		return -EILSEQ;
+	}
+
+	/*
+	 * The node must be either INTERNAL or LEAF.
+	 */
+	flags = le32_to_cpu(h->flags);
+	if (!(flags & INTERNAL_NODE) && !(flags & LEAF_NODE)) {
+		DMERR("node_check failed, node is neither INTERNAL or LEAF");
+		return -EILSEQ;
+	}
+
+	return 0;
+}
+
+struct dm_block_validator btree_node_validator = {
+	.name = "btree_node",
+	.prepare_for_write = node_prepare_for_write,
+	.check = node_check
+};
+
+/*----------------------------------------------------------------*/
+
+static int bn_read_lock(struct dm_btree_info *info, dm_block_t b,
+		 struct dm_block **result)
+{
+	return dm_tm_read_lock(info->tm, b, &btree_node_validator, result);
+}
+
+static int bn_shadow(struct dm_btree_info *info, dm_block_t orig,
+	      struct dm_btree_value_type *vt,
+	      struct dm_block **result)
+{
+	int r, inc;
+
+	r = dm_tm_shadow_block(info->tm, orig, &btree_node_validator,
+			       result, &inc);
+	if (!r && inc)
+		inc_children(info->tm, dm_block_data(*result), vt);
+
+	return r;
+}
+
+int new_block(struct dm_btree_info *info, struct dm_block **result)
+{
+	return dm_tm_new_block(info->tm, &btree_node_validator, result);
+}
+
+int unlock_block(struct dm_btree_info *info, struct dm_block *b)
+{
+	return dm_tm_unlock(info->tm, b);
+}
+
+/*----------------------------------------------------------------*/
+
+void init_ro_spine(struct ro_spine *s, struct dm_btree_info *info)
+{
+	s->info = info;
+	s->count = 0;
+	s->nodes[0] = NULL;
+	s->nodes[1] = NULL;
+}
+
+int exit_ro_spine(struct ro_spine *s)
+{
+	int r = 0, i;
+
+	for (i = 0; i < s->count; i++) {
+		int r2 = unlock_block(s->info, s->nodes[i]);
+		if (r2 < 0)
+			r = r2;
+	}
+
+	return r;
+}
+
+int ro_step(struct ro_spine *s, dm_block_t new_child)
+{
+	int r;
+
+	if (s->count == 2) {
+		r = unlock_block(s->info, s->nodes[0]);
+		if (r < 0)
+			return r;
+		s->nodes[0] = s->nodes[1];
+		s->count--;
+	}
+
+	r = bn_read_lock(s->info, new_child, s->nodes + s->count);
+	if (!r)
+		s->count++;
+
+	return r;
+}
+
+struct node *ro_node(struct ro_spine *s)
+{
+	struct dm_block *block;
+
+	BUG_ON(!s->count);
+	block = s->nodes[s->count - 1];
+
+	return dm_block_data(block);
+}
+
+/*----------------------------------------------------------------*/
+
+void init_shadow_spine(struct shadow_spine *s, struct dm_btree_info *info)
+{
+	s->info = info;
+	s->count = 0;
+}
+
+int exit_shadow_spine(struct shadow_spine *s)
+{
+	int r = 0, i;
+
+	for (i = 0; i < s->count; i++) {
+		int r2 = unlock_block(s->info, s->nodes[i]);
+		if (r2 < 0)
+			r = r2;
+	}
+
+	return r;
+}
+
+int shadow_step(struct shadow_spine *s, dm_block_t b,
+		struct dm_btree_value_type *vt)
+{
+	int r;
+
+	if (s->count == 2) {
+		r = unlock_block(s->info, s->nodes[0]);
+		if (r < 0)
+			return r;
+		s->nodes[0] = s->nodes[1];
+		s->count--;
+	}
+
+	r = bn_shadow(s->info, b, vt, s->nodes + s->count);
+	if (!r) {
+		if (!s->count)
+			s->root = dm_block_location(s->nodes[0]);
+
+		s->count++;
+	}
+
+	return r;
+}
+
+struct dm_block *shadow_current(struct shadow_spine *s)
+{
+	BUG_ON(!s->count);
+
+	return s->nodes[s->count - 1];
+}
+
+struct dm_block *shadow_parent(struct shadow_spine *s)
+{
+	BUG_ON(s->count != 2);
+
+	return s->count == 2 ? s->nodes[0] : NULL;
+}
+
+int shadow_has_parent(struct shadow_spine *s)
+{
+	return s->count >= 2;
+}
+
+int shadow_root(struct shadow_spine *s)
+{
+	return s->root;
+}
diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-data/dm-btree.c
new file mode 100644
index 0000000..e0638be
--- /dev/null
+++ b/drivers/md/persistent-data/dm-btree.c
@@ -0,0 +1,805 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-btree-internal.h"
+#include "dm-space-map.h"
+#include "dm-transaction-manager.h"
+
+#include <linux/module.h>
+#include <linux/device-mapper.h>
+
+#define DM_MSG_PREFIX "btree"
+
+/*----------------------------------------------------------------
+ * Array manipulation
+ *--------------------------------------------------------------*/
+static void memcpy_disk(void *dest, const void *src, size_t len)
+	__dm_written_to_disk(src)
+{
+	memcpy(dest, src, len);
+	__dm_unbless_for_disk(src);
+}
+
+static void array_insert(void *base, size_t elt_size, unsigned nr_elts,
+			 unsigned index, void *elt)
+	__dm_written_to_disk(elt)
+{
+	if (index < nr_elts)
+		memmove(base + (elt_size * (index + 1)),
+			base + (elt_size * index),
+			(nr_elts - index) * elt_size);
+
+	memcpy_disk(base + (elt_size * index), elt, elt_size);
+}
+
+/*----------------------------------------------------------------*/
+
+/* makes the assumption that no two keys are the same. */
+static int bsearch(struct node *n, uint64_t key, int want_hi)
+{
+	int lo = -1, hi = le32_to_cpu(n->header.nr_entries);
+
+	while (hi - lo > 1) {
+		int mid = lo + ((hi - lo) / 2);
+		uint64_t mid_key = le64_to_cpu(n->keys[mid]);
+
+		if (mid_key == key)
+			return mid;
+
+		if (mid_key < key)
+			lo = mid;
+		else
+			hi = mid;
+	}
+
+	return want_hi ? hi : lo;
+}
+
+int lower_bound(struct node *n, uint64_t key)
+{
+	return bsearch(n, key, 0);
+}
+
+void inc_children(struct dm_transaction_manager *tm, struct node *n,
+		  struct dm_btree_value_type *vt)
+{
+	unsigned i;
+	uint32_t nr_entries = le32_to_cpu(n->header.nr_entries);
+
+	if (le32_to_cpu(n->header.flags) & INTERNAL_NODE)
+		for (i = 0; i < nr_entries; i++)
+			dm_tm_inc(tm, value64(n, i));
+	else if (vt->inc)
+		for (i = 0; i < nr_entries; i++)
+			vt->inc(vt->context,
+				value_ptr(n, i, vt->size));
+}
+
+static int insert_at(size_t value_size, struct node *node, unsigned index,
+		      uint64_t key, void *value)
+		      __dm_written_to_disk(value)
+{
+	uint32_t nr_entries = le32_to_cpu(node->header.nr_entries);
+	__le64 key_le = cpu_to_le64(key);
+
+	if (index > nr_entries ||
+	    index >= le32_to_cpu(node->header.max_entries)) {
+		DMERR("too many entries in btree node for insert");
+		__dm_unbless_for_disk(value);
+		return -ENOMEM;
+	}
+
+	__dm_bless_for_disk(&key_le);
+
+	array_insert(node->keys, sizeof(*node->keys), nr_entries, index, &key_le);
+	array_insert(value_base(node), value_size, nr_entries, index, value);
+	node->header.nr_entries = cpu_to_le32(nr_entries + 1);
+
+	return 0;
+}
+
+/*----------------------------------------------------------------*/
+
+/*
+ * We want 3n entries (for some n).  This works more nicely for repeated
+ * insert remove loops than (2n + 1).
+ */
+static uint32_t calc_max_entries(size_t value_size, size_t block_size)
+{
+	uint32_t total, n;
+	size_t elt_size = sizeof(uint64_t) + value_size; /* key + value */
+
+	block_size -= sizeof(struct node_header);
+	total = block_size / elt_size;
+	n = total / 3;		/* rounds down */
+
+	return 3 * n;
+}
+
+int dm_btree_empty(struct dm_btree_info *info, dm_block_t *root)
+{
+	int r;
+	struct dm_block *b;
+	struct node *n;
+	size_t block_size;
+	uint32_t max_entries;
+
+	r = new_block(info, &b);
+	if (r < 0)
+		return r;
+
+	block_size = dm_bm_block_size(dm_tm_get_bm(info->tm));
+	max_entries = calc_max_entries(info->value_type.size, block_size);
+
+	n = dm_block_data(b);
+	memset(n, 0, block_size);
+	n->header.flags = cpu_to_le32(LEAF_NODE);
+	n->header.nr_entries = cpu_to_le32(0);
+	n->header.max_entries = cpu_to_le32(max_entries);
+	n->header.value_size = cpu_to_le32(info->value_type.size);
+
+	*root = dm_block_location(b);
+	return unlock_block(info, b);
+}
+EXPORT_SYMBOL_GPL(dm_btree_empty);
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Deletion uses a recursive algorithm, since we have limited stack space
+ * we explicitly manage our own stack on the heap.
+ */
+#define MAX_SPINE_DEPTH 64
+struct frame {
+	struct dm_block *b;
+	struct node *n;
+	unsigned level;
+	unsigned nr_children;
+	unsigned current_child;
+};
+
+struct del_stack {
+	struct dm_transaction_manager *tm;
+	int top;
+	struct frame spine[MAX_SPINE_DEPTH];
+};
+
+static int top_frame(struct del_stack *s, struct frame **f)
+{
+	if (s->top < 0) {
+		DMERR("btree deletion stack empty");
+		return -EINVAL;
+	}
+
+	*f = s->spine + s->top;
+
+	return 0;
+}
+
+static int unprocessed_frames(struct del_stack *s)
+{
+	return s->top >= 0;
+}
+
+static int push_frame(struct del_stack *s, dm_block_t b, unsigned level)
+{
+	int r;
+	uint32_t ref_count;
+
+	if (s->top >= MAX_SPINE_DEPTH - 1) {
+		DMERR("btree deletion stack out of memory");
+		return -ENOMEM;
+	}
+
+	r = dm_tm_ref(s->tm, b, &ref_count);
+	if (r)
+		return r;
+
+	if (ref_count > 1)
+		/*
+		 * This is a shared node, so we can just decrement it's
+		 * reference counter and leave the children.
+		 */
+		dm_tm_dec(s->tm, b);
+
+	else {
+		struct frame *f = s->spine + ++s->top;
+
+		r = dm_tm_read_lock(s->tm, b, &btree_node_validator, &f->b);
+		if (r) {
+			s->top--;
+			return r;
+		}
+
+		f->n = dm_block_data(f->b);
+		f->level = level;
+		f->nr_children = le32_to_cpu(f->n->header.nr_entries);
+		f->current_child = 0;
+	}
+
+	return 0;
+}
+
+static void pop_frame(struct del_stack *s)
+{
+	struct frame *f = s->spine + s->top--;
+
+	dm_tm_dec(s->tm, dm_block_location(f->b));
+	dm_tm_unlock(s->tm, f->b);
+}
+
+int dm_btree_del(struct dm_btree_info *info, dm_block_t root)
+{
+	int r;
+	struct del_stack *s;
+
+	s = kmalloc(sizeof(*s), GFP_KERNEL);
+	if (!s)
+		return -ENOMEM;
+	s->tm = info->tm;
+	s->top = -1;
+
+	r = push_frame(s, root, 1);
+	if (r)
+		goto out;
+
+	while (unprocessed_frames(s)) {
+		uint32_t flags;
+		struct frame *f;
+		dm_block_t b;
+
+		r = top_frame(s, &f);
+		if (r)
+			goto out;
+
+		if (f->current_child >= f->nr_children) {
+			pop_frame(s);
+			continue;
+		}
+
+		flags = le32_to_cpu(f->n->header.flags);
+		if (flags & INTERNAL_NODE) {
+			b = value64(f->n, f->current_child);
+			f->current_child++;
+			r = push_frame(s, b, f->level);
+			if (r)
+				goto out;
+
+		} else if (f->level != (info->levels - 1)) {
+			b = value64(f->n, f->current_child);
+			f->current_child++;
+			r = push_frame(s, b, f->level + 1);
+			if (r)
+				goto out;
+
+		} else {
+			if (info->value_type.dec) {
+				unsigned i;
+
+				for (i = 0; i < f->nr_children; i++)
+					info->value_type.dec(info->value_type.context,
+							     value_ptr(f->n, i, info->value_type.size));
+			}
+			f->current_child = f->nr_children;
+		}
+	}
+
+out:
+	kfree(s);
+	return r;
+}
+EXPORT_SYMBOL_GPL(dm_btree_del);
+
+/*----------------------------------------------------------------*/
+
+static int btree_lookup_raw(struct ro_spine *s, dm_block_t block, uint64_t key,
+			    int (*search_fn)(struct node *, uint64_t),
+			    uint64_t *result_key, void *v, size_t value_size)
+{
+	int i, r;
+	uint32_t flags, nr_entries;
+
+	do {
+		r = ro_step(s, block);
+		if (r < 0)
+			return r;
+
+		i = search_fn(ro_node(s), key);
+
+		flags = le32_to_cpu(ro_node(s)->header.flags);
+		nr_entries = le32_to_cpu(ro_node(s)->header.nr_entries);
+		if (i < 0 || i >= nr_entries)
+			return -ENODATA;
+
+		if (flags & INTERNAL_NODE)
+			block = value64(ro_node(s), i);
+
+	} while (!(flags & LEAF_NODE));
+
+	*result_key = le64_to_cpu(ro_node(s)->keys[i]);
+	memcpy(v, value_ptr(ro_node(s), i, value_size), value_size);
+
+	return 0;
+}
+
+int dm_btree_lookup(struct dm_btree_info *info, dm_block_t root,
+		    uint64_t *keys, void *value_le)
+{
+	unsigned level, last_level = info->levels - 1;
+	int r = -ENODATA;
+	uint64_t rkey;
+	__le64 internal_value_le;
+	struct ro_spine spine;
+
+	init_ro_spine(&spine, info);
+	for (level = 0; level < info->levels; level++) {
+		size_t size;
+		void *value_p;
+
+		if (level == last_level) {
+			value_p = value_le;
+			size = info->value_type.size;
+
+		} else {
+			value_p = &internal_value_le;
+			size = sizeof(uint64_t);
+		}
+
+		r = btree_lookup_raw(&spine, root, keys[level],
+				     lower_bound, &rkey,
+				     value_p, size);
+
+		if (!r) {
+			if (rkey != keys[level]) {
+				exit_ro_spine(&spine);
+				return -ENODATA;
+			}
+		} else {
+			exit_ro_spine(&spine);
+			return r;
+		}
+
+		root = le64_to_cpu(internal_value_le);
+	}
+	exit_ro_spine(&spine);
+
+	return r;
+}
+EXPORT_SYMBOL_GPL(dm_btree_lookup);
+
+/*
+ * Splits a node by creating a sibling node and shifting half the nodes
+ * contents across.  Assumes there is a parent node, and it has room for
+ * another child.
+ *
+ * Before:
+ *	  +--------+
+ *	  | Parent |
+ *	  +--------+
+ *	     |
+ *	     v
+ *	+----------+
+ *	| A ++++++ |
+ *	+----------+
+ *
+ *
+ * After:
+ *		+--------+
+ *		| Parent |
+ *		+--------+
+ *		  |	|
+ *		  v	+------+
+ *	    +---------+	       |
+ *	    | A* +++  |	       v
+ *	    +---------+	  +-------+
+ *			  | B +++ |
+ *			  +-------+
+ *
+ * Where A* is a shadow of A.
+ */
+static int btree_split_sibling(struct shadow_spine *s, dm_block_t root,
+			       unsigned parent_index, uint64_t key)
+{
+	int r;
+	size_t size;
+	unsigned nr_left, nr_right;
+	struct dm_block *left, *right, *parent;
+	struct node *ln, *rn, *pn;
+	__le64 location;
+
+	left = shadow_current(s);
+
+	r = new_block(s->info, &right);
+	if (r < 0)
+		return r;
+
+	ln = dm_block_data(left);
+	rn = dm_block_data(right);
+
+	nr_left = le32_to_cpu(ln->header.nr_entries) / 2;
+	nr_right = le32_to_cpu(ln->header.nr_entries) - nr_left;
+
+	ln->header.nr_entries = cpu_to_le32(nr_left);
+
+	rn->header.flags = ln->header.flags;
+	rn->header.nr_entries = cpu_to_le32(nr_right);
+	rn->header.max_entries = ln->header.max_entries;
+	rn->header.value_size = ln->header.value_size;
+	memcpy(rn->keys, ln->keys + nr_left, nr_right * sizeof(rn->keys[0]));
+
+	size = le32_to_cpu(ln->header.flags) & INTERNAL_NODE ?
+		sizeof(uint64_t) : s->info->value_type.size;
+	memcpy(value_ptr(rn, 0, size), value_ptr(ln, nr_left, size),
+	       size * nr_right);
+
+	/*
+	 * Patch up the parent
+	 */
+	parent = shadow_parent(s);
+
+	pn = dm_block_data(parent);
+	location = cpu_to_le64(dm_block_location(left));
+	__dm_bless_for_disk(&location);
+	memcpy_disk(value_ptr(pn, parent_index, sizeof(__le64)),
+		    &location, sizeof(__le64));
+
+	location = cpu_to_le64(dm_block_location(right));
+	__dm_bless_for_disk(&location);
+
+	r = insert_at(sizeof(__le64), pn, parent_index + 1,
+		      le64_to_cpu(rn->keys[0]), &location);
+	if (r)
+		return r;
+
+	if (key < le64_to_cpu(rn->keys[0])) {
+		unlock_block(s->info, right);
+		s->nodes[1] = left;
+	} else {
+		unlock_block(s->info, left);
+		s->nodes[1] = right;
+	}
+
+	return 0;
+}
+
+/*
+ * Splits a node by creating two new children beneath the given node.
+ *
+ * Before:
+ *	  +----------+
+ *	  | A ++++++ |
+ *	  +----------+
+ *
+ *
+ * After:
+ *	+------------+
+ *	| A (shadow) |
+ *	+------------+
+ *	    |	|
+ *   +------+	+----+
+ *   |		     |
+ *   v		     v
+ * +-------+	 +-------+
+ * | B +++ |	 | C +++ |
+ * +-------+	 +-------+
+ */
+static int btree_split_beneath(struct shadow_spine *s, uint64_t key)
+{
+	int r;
+	size_t size;
+	unsigned nr_left, nr_right;
+	struct dm_block *left, *right, *new_parent;
+	struct node *pn, *ln, *rn;
+	__le64 val;
+
+	new_parent = shadow_current(s);
+
+	r = new_block(s->info, &left);
+	if (r < 0)
+		return r;
+
+	r = new_block(s->info, &right);
+	if (r < 0) {
+		/* FIXME: put left */
+		return r;
+	}
+
+	pn = dm_block_data(new_parent);
+	ln = dm_block_data(left);
+	rn = dm_block_data(right);
+
+	nr_left = le32_to_cpu(pn->header.nr_entries) / 2;
+	nr_right = le32_to_cpu(pn->header.nr_entries) - nr_left;
+
+	ln->header.flags = pn->header.flags;
+	ln->header.nr_entries = cpu_to_le32(nr_left);
+	ln->header.max_entries = pn->header.max_entries;
+	ln->header.value_size = pn->header.value_size;
+
+	rn->header.flags = pn->header.flags;
+	rn->header.nr_entries = cpu_to_le32(nr_right);
+	rn->header.max_entries = pn->header.max_entries;
+	rn->header.value_size = pn->header.value_size;
+
+	memcpy(ln->keys, pn->keys, nr_left * sizeof(pn->keys[0]));
+	memcpy(rn->keys, pn->keys + nr_left, nr_right * sizeof(pn->keys[0]));
+
+	size = le32_to_cpu(pn->header.flags) & INTERNAL_NODE ?
+		sizeof(__le64) : s->info->value_type.size;
+	memcpy(value_ptr(ln, 0, size), value_ptr(pn, 0, size), nr_left * size);
+	memcpy(value_ptr(rn, 0, size), value_ptr(pn, nr_left, size),
+	       nr_right * size);
+
+	/* new_parent should just point to l and r now */
+	pn->header.flags = cpu_to_le32(INTERNAL_NODE);
+	pn->header.nr_entries = cpu_to_le32(2);
+	pn->header.max_entries = cpu_to_le32(
+		calc_max_entries(sizeof(__le64),
+				 dm_bm_block_size(
+					 dm_tm_get_bm(s->info->tm))));
+	pn->header.value_size = cpu_to_le32(sizeof(__le64));
+
+	val = cpu_to_le64(dm_block_location(left));
+	__dm_bless_for_disk(&val);
+	pn->keys[0] = ln->keys[0];
+	memcpy_disk(value_ptr(pn, 0, sizeof(__le64)), &val, sizeof(__le64));
+
+	val = cpu_to_le64(dm_block_location(right));
+	__dm_bless_for_disk(&val);
+	pn->keys[1] = rn->keys[0];
+	memcpy_disk(value_ptr(pn, 1, sizeof(__le64)), &val, sizeof(__le64));
+
+	/*
+	 * rejig the spine.  This is ugly, since it knows too
+	 * much about the spine
+	 */
+	if (s->nodes[0] != new_parent) {
+		unlock_block(s->info, s->nodes[0]);
+		s->nodes[0] = new_parent;
+	}
+	if (key < le64_to_cpu(rn->keys[0])) {
+		unlock_block(s->info, right);
+		s->nodes[1] = left;
+	} else {
+		unlock_block(s->info, left);
+		s->nodes[1] = right;
+	}
+	s->count = 2;
+
+	return 0;
+}
+
+static int btree_insert_raw(struct shadow_spine *s, dm_block_t root,
+			    struct dm_btree_value_type *vt,
+			    uint64_t key, unsigned *index)
+{
+	int r, i = *index, top = 1;
+	struct node *node;
+
+	for (;;) {
+		r = shadow_step(s, root, vt);
+		if (r < 0)
+			return r;
+
+		node = dm_block_data(shadow_current(s));
+
+		/*
+		 * We have to patch up the parent node, ugly, but I don't
+		 * see a way to do this automatically as part of the spine
+		 * op.
+		 */
+		if (shadow_has_parent(s) && i >= 0) { /* FIXME: second clause unness. */
+			__le64 location = cpu_to_le64(dm_block_location(shadow_current(s)));
+
+			__dm_bless_for_disk(&location);
+			memcpy_disk(value_ptr(dm_block_data(shadow_parent(s)), i, sizeof(uint64_t)),
+				    &location, sizeof(__le64));
+		}
+
+		node = dm_block_data(shadow_current(s));
+
+		if (node->header.nr_entries == node->header.max_entries) {
+			if (top)
+				r = btree_split_beneath(s, key);
+			else
+				r = btree_split_sibling(s, root, i, key);
+
+			if (r < 0)
+				return r;
+		}
+
+		node = dm_block_data(shadow_current(s));
+
+		i = lower_bound(node, key);
+
+		if (le32_to_cpu(node->header.flags) & LEAF_NODE)
+			break;
+
+		if (i < 0) {
+			/* change the bounds on the lowest key */
+			node->keys[0] = cpu_to_le64(key);
+			i = 0;
+		}
+
+		root = value64(node, i);
+		top = 0;
+	}
+
+	if (i < 0 || le64_to_cpu(node->keys[i]) != key)
+		i++;
+
+	*index = i;
+	return 0;
+}
+
+static int insert(struct dm_btree_info *info, dm_block_t root,
+		  uint64_t *keys, void *value, dm_block_t *new_root,
+		  int *inserted)
+		  __dm_written_to_disk(value)
+{
+	int r, need_insert;
+	unsigned level, index = -1, last_level = info->levels - 1;
+	dm_block_t block = root;
+	struct shadow_spine spine;
+	struct node *n;
+	struct dm_btree_value_type le64_type;
+
+	le64_type.context = NULL;
+	le64_type.size = sizeof(__le64);
+	le64_type.inc = NULL;
+	le64_type.dec = NULL;
+	le64_type.equal = NULL;
+
+	init_shadow_spine(&spine, info);
+
+	for (level = 0; level < (info->levels - 1); level++) {
+		r = btree_insert_raw(&spine, block, &le64_type, keys[level], &index);
+		if (r < 0)
+			goto bad;
+
+		n = dm_block_data(shadow_current(&spine));
+		need_insert = ((index >= le32_to_cpu(n->header.nr_entries)) ||
+			       (le64_to_cpu(n->keys[index]) != keys[level]));
+
+		if (need_insert) {
+			dm_block_t new_tree;
+			__le64 new_le;
+
+			r = dm_btree_empty(info, &new_tree);
+			if (r < 0)
+				goto bad;
+
+			new_le = cpu_to_le64(new_tree);
+			__dm_bless_for_disk(&new_le);
+
+			r = insert_at(sizeof(uint64_t), n, index,
+				      keys[level], &new_le);
+			if (r)
+				goto bad;
+		}
+
+		if (level < last_level)
+			block = value64(n, index);
+	}
+
+	r = btree_insert_raw(&spine, block, &info->value_type,
+			     keys[level], &index);
+	if (r < 0)
+		goto bad;
+
+	n = dm_block_data(shadow_current(&spine));
+	need_insert = ((index >= le32_to_cpu(n->header.nr_entries)) ||
+		       (le64_to_cpu(n->keys[index]) != keys[level]));
+
+	if (need_insert) {
+		if (inserted)
+			*inserted = 1;
+
+		r = insert_at(info->value_type.size, n, index,
+			      keys[level], value);
+		if (r)
+			goto bad_unblessed;
+	} else {
+		if (inserted)
+			*inserted = 0;
+
+		if (info->value_type.dec &&
+		    (!info->value_type.equal ||
+		     !info->value_type.equal(
+			     info->value_type.context,
+			     value_ptr(n, index, info->value_type.size),
+			     value))) {
+			info->value_type.dec(info->value_type.context,
+					     value_ptr(n, index, info->value_type.size));
+		}
+		memcpy_disk(value_ptr(n, index, info->value_type.size),
+			    value, info->value_type.size);
+	}
+
+	*new_root = shadow_root(&spine);
+	exit_shadow_spine(&spine);
+
+	return 0;
+
+bad:
+	__dm_unbless_for_disk(value);
+bad_unblessed:
+	exit_shadow_spine(&spine);
+	return r;
+}
+
+int dm_btree_insert(struct dm_btree_info *info, dm_block_t root,
+		    uint64_t *keys, void *value, dm_block_t *new_root)
+		    __dm_written_to_disk(value)
+{
+	return insert(info, root, keys, value, new_root, NULL);
+}
+EXPORT_SYMBOL_GPL(dm_btree_insert);
+
+int dm_btree_insert_notify(struct dm_btree_info *info, dm_block_t root,
+			   uint64_t *keys, void *value, dm_block_t *new_root,
+			   int *inserted)
+			   __dm_written_to_disk(value)
+{
+	return insert(info, root, keys, value, new_root, inserted);
+}
+EXPORT_SYMBOL_GPL(dm_btree_insert_notify);
+
+/*----------------------------------------------------------------*/
+
+static int find_highest_key(struct ro_spine *s, dm_block_t block,
+			    uint64_t *result_key, dm_block_t *next_block)
+{
+	int i, r;
+	uint32_t flags;
+
+	do {
+		r = ro_step(s, block);
+		if (r < 0)
+			return r;
+
+		flags = le32_to_cpu(ro_node(s)->header.flags);
+		i = le32_to_cpu(ro_node(s)->header.nr_entries);
+		if (!i)
+			return -ENODATA;
+		else
+			i--;
+
+		*result_key = le64_to_cpu(ro_node(s)->keys[i]);
+		if (next_block || flags & INTERNAL_NODE)
+			block = value64(ro_node(s), i);
+
+	} while (flags & INTERNAL_NODE);
+
+	if (next_block)
+		*next_block = block;
+	return 0;
+}
+
+int dm_btree_find_highest_key(struct dm_btree_info *info, dm_block_t root,
+			      uint64_t *result_keys)
+{
+	int r = 0, count = 0, level;
+	struct ro_spine spine;
+
+	init_ro_spine(&spine, info);
+	for (level = 0; level < info->levels; level++) {
+		r = find_highest_key(&spine, root, result_keys + level,
+				     level == info->levels - 1 ? NULL : &root);
+		if (r == -ENODATA) {
+			r = 0;
+			break;
+
+		} else if (r)
+			break;
+
+		count++;
+	}
+	exit_ro_spine(&spine);
+
+	return r ? r : count;
+}
+EXPORT_SYMBOL_GPL(dm_btree_find_highest_key);
diff --git a/drivers/md/persistent-data/dm-btree.h b/drivers/md/persistent-data/dm-btree.h
new file mode 100644
index 0000000..ae02c84
--- /dev/null
+++ b/drivers/md/persistent-data/dm-btree.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+#ifndef _LINUX_DM_BTREE_H
+#define _LINUX_DM_BTREE_H
+
+#include "dm-block-manager.h"
+
+struct dm_transaction_manager;
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Annotations used to check on-disk metadata is handled as little-endian.
+ */
+#ifdef __CHECKER__
+#  define __dm_written_to_disk(x) __releases(x)
+#  define __dm_reads_from_disk(x) __acquires(x)
+#  define __dm_bless_for_disk(x) __acquire(x)
+#  define __dm_unbless_for_disk(x) __release(x)
+#else
+#  define __dm_written_to_disk(x)
+#  define __dm_reads_from_disk(x)
+#  define __dm_bless_for_disk(x)
+#  define __dm_unbless_for_disk(x)
+#endif
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Manipulates hierarchical B+ trees with 64-bit keys and arbitrary-sized
+ * values.
+ */
+
+/*
+ * Infomation about the values stored within the btree.
+ */
+struct dm_btree_value_type {
+	void *context;
+
+	/*
+	 * The size in bytes of each value.
+	 */
+	uint32_t size;
+
+	/*
+	 * Any of these methods can be safely set to NULL if you do not
+	 * need the corresponding feature.
+	 */
+
+	/*
+	 * The btree is making a duplicate of the value, for instance
+	 * because previously-shared btree nodes have now diverged.
+	 * @value argument is the new copy that the copy function may modify.
+	 * (Probably it just wants to increment a reference count
+	 * somewhere.) This method is _not_ called for insertion of a new
+	 * value: It is assumed the ref count is already 1.
+	 */
+	void (*inc)(void *context, void *value);
+
+	/*
+	 * This value is being deleted.  The btree takes care of freeing
+	 * the memory pointed to by @value.  Often the del function just
+	 * needs to decrement a reference count somewhere.
+	 */
+	void (*dec)(void *context, void *value);
+
+	/*
+	 * A test for equality between two values.  When a value is
+	 * overwritten with a new one, the old one has the dec method
+	 * called _unless_ the new and old value are deemed equal.
+	 */
+	int (*equal)(void *context, void *value1, void *value2);
+};
+
+/*
+ * The shape and contents of a btree.
+ */
+struct dm_btree_info {
+	struct dm_transaction_manager *tm;
+
+	/*
+	 * Number of nested btrees. (Not the depth of a single tree.)
+	 */
+	unsigned levels;
+	struct dm_btree_value_type value_type;
+};
+
+/*
+ * Set up an empty tree.  O(1).
+ */
+int dm_btree_empty(struct dm_btree_info *info, dm_block_t *root);
+
+/*
+ * Delete a tree.  O(n) - this is the slow one!  It can also block, so
+ * please don't call it on an IO path.
+ */
+int dm_btree_del(struct dm_btree_info *info, dm_block_t root);
+
+/*
+ * All the lookup functions return -ENODATA if the key cannot be found.
+ */
+
+/*
+ * Tries to find a key that matches exactly.  O(ln(n))
+ */
+int dm_btree_lookup(struct dm_btree_info *info, dm_block_t root,
+		    uint64_t *keys, void *value_le);
+
+/*
+ * Insertion (or overwrite an existing value).  O(ln(n))
+ */
+int dm_btree_insert(struct dm_btree_info *info, dm_block_t root,
+		    uint64_t *keys, void *value, dm_block_t *new_root)
+		    __dm_written_to_disk(value);
+
+/*
+ * A variant of insert that indicates whether it actually inserted or just
+ * overwrote.  Useful if you're keeping track of the number of entries in a
+ * tree.
+ */
+int dm_btree_insert_notify(struct dm_btree_info *info, dm_block_t root,
+			   uint64_t *keys, void *value, dm_block_t *new_root,
+			   int *inserted)
+			   __dm_written_to_disk(value);
+
+/*
+ * Remove a key if present.  This doesn't remove empty sub trees.  Normally
+ * subtrees represent a separate entity, like a snapshot map, so this is
+ * correct behaviour.  O(ln(n)).
+ */
+int dm_btree_remove(struct dm_btree_info *info, dm_block_t root,
+		    uint64_t *keys, dm_block_t *new_root);
+
+/*
+ * Returns < 0 on failure.  Otherwise the number of key entries that have
+ * been filled out.  Remember trees can have zero entries, and as such have
+ * no highest key.
+ */
+int dm_btree_find_highest_key(struct dm_btree_info *info, dm_block_t root,
+			      uint64_t *result_keys);
+
+#endif	/* _LINUX_DM_BTREE_H */
diff --git a/drivers/md/persistent-data/dm-persistent-data-internal.h b/drivers/md/persistent-data/dm-persistent-data-internal.h
new file mode 100644
index 0000000..c49e26f
--- /dev/null
+++ b/drivers/md/persistent-data/dm-persistent-data-internal.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef _DM_PERSISTENT_DATA_INTERNAL_H
+#define _DM_PERSISTENT_DATA_INTERNAL_H
+
+#include "dm-block-manager.h"
+
+static inline unsigned dm_hash_block(dm_block_t b, unsigned hash_mask)
+{
+	const unsigned BIG_PRIME = 4294967291UL;
+
+	return (((unsigned) b) * BIG_PRIME) & hash_mask;
+}
+
+#endif	/* _PERSISTENT_DATA_INTERNAL_H */
diff --git a/drivers/md/persistent-data/dm-space-map-checker.c b/drivers/md/persistent-data/dm-space-map-checker.c
new file mode 100644
index 0000000..bb44a93
--- /dev/null
+++ b/drivers/md/persistent-data/dm-space-map-checker.c
@@ -0,0 +1,437 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-space-map-checker.h"
+
+#include <linux/device-mapper.h>
+
+#ifdef CONFIG_DM_DEBUG_SPACE_MAPS
+
+#define DM_MSG_PREFIX "space map checker"
+
+/*----------------------------------------------------------------*/
+
+struct count_array {
+	dm_block_t nr;
+	dm_block_t nr_free;
+
+	uint32_t *counts;
+};
+
+static int ca_get_count(struct count_array *ca, dm_block_t b, uint32_t *count)
+{
+	if (b >= ca->nr)
+		return -EINVAL;
+
+	*count = ca->counts[b];
+	return 0;
+}
+
+static int ca_count_more_than_one(struct count_array *ca, dm_block_t b, int *r)
+{
+	if (b >= ca->nr)
+		return -EINVAL;
+
+	*r = ca->counts[b] > 1;
+	return 0;
+}
+
+static int ca_set_count(struct count_array *ca, dm_block_t b, uint32_t count)
+{
+	uint32_t old_count;
+
+	if (b >= ca->nr)
+		return -EINVAL;
+
+	old_count = ca->counts[b];
+
+	if (!count && old_count)
+		ca->nr_free++;
+
+	else if (count && !old_count)
+		ca->nr_free--;
+
+	ca->counts[b] = count;
+	return 0;
+}
+
+static int ca_inc_block(struct count_array *ca, dm_block_t b)
+{
+	if (b >= ca->nr)
+		return -EINVAL;
+
+	ca_set_count(ca, b, ca->counts[b] + 1);
+	return 0;
+}
+
+static int ca_dec_block(struct count_array *ca, dm_block_t b)
+{
+	if (b >= ca->nr)
+		return -EINVAL;
+
+	BUG_ON(ca->counts[b] == 0);
+	ca_set_count(ca, b, ca->counts[b] - 1);
+	return 0;
+}
+
+static int ca_create(struct count_array *ca, struct dm_space_map *sm)
+{
+	int r;
+	dm_block_t nr_blocks;
+
+	r = dm_sm_get_nr_blocks(sm, &nr_blocks);
+	if (r)
+		return r;
+
+	ca->nr = nr_blocks;
+	ca->nr_free = nr_blocks;
+	ca->counts = kzalloc(sizeof(*ca->counts) * nr_blocks, GFP_KERNEL);
+	if (!ca->counts)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int ca_load(struct count_array *ca, struct dm_space_map *sm)
+{
+	int r;
+	uint32_t count;
+	dm_block_t nr_blocks, i;
+
+	r = dm_sm_get_nr_blocks(sm, &nr_blocks);
+	if (r)
+		return r;
+
+	BUG_ON(ca->nr != nr_blocks);
+
+	DMWARN("Loading debug space map from disk.  This may take some time");
+	for (i = 0; i < nr_blocks; i++) {
+		r = dm_sm_get_count(sm, i, &count);
+		if (r) {
+			DMERR("load failed");
+			return r;
+		}
+
+		ca_set_count(ca, i, count);
+	}
+	DMWARN("Load complete");
+
+	return 0;
+}
+
+static int ca_extend(struct count_array *ca, dm_block_t extra_blocks)
+{
+	dm_block_t nr_blocks = ca->nr + extra_blocks;
+	uint32_t *counts = kzalloc(sizeof(*counts) * nr_blocks, GFP_KERNEL);
+	if (!counts)
+		return -ENOMEM;
+
+	memcpy(counts, ca->counts, sizeof(*counts) * ca->nr);
+	kfree(ca->counts);
+	ca->nr = nr_blocks;
+	ca->nr_free += extra_blocks;
+	ca->counts = counts;
+	return 0;
+}
+
+static int ca_commit(struct count_array *old, struct count_array *new)
+{
+	if (old->nr != new->nr) {
+		BUG_ON(old->nr > new->nr);
+		ca_extend(old, new->nr - old->nr);
+	}
+
+	BUG_ON(old->nr != new->nr);
+	old->nr_free = new->nr_free;
+	memcpy(old->counts, new->counts, sizeof(*old->counts) * old->nr);
+	return 0;
+}
+
+static void ca_destroy(struct count_array *ca)
+{
+	kfree(ca->counts);
+}
+
+/*----------------------------------------------------------------*/
+
+struct sm_checker {
+	struct dm_space_map sm;
+
+	struct count_array old_counts;
+	struct count_array counts;
+
+	struct dm_space_map *real_sm;
+};
+
+static void sm_checker_destroy(struct dm_space_map *sm)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+
+	dm_sm_destroy(smc->real_sm);
+	ca_destroy(&smc->old_counts);
+	ca_destroy(&smc->counts);
+	kfree(smc);
+}
+
+static int sm_checker_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	int r = dm_sm_get_nr_blocks(smc->real_sm, count);
+	if (!r)
+		BUG_ON(smc->old_counts.nr != *count);
+	return r;
+}
+
+static int sm_checker_get_nr_free(struct dm_space_map *sm, dm_block_t *count)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	int r = dm_sm_get_nr_free(smc->real_sm, count);
+	if (!r) {
+		/*
+		 * Slow, but we know it's correct.
+		 */
+		dm_block_t b, n = 0;
+		for (b = 0; b < smc->old_counts.nr; b++)
+			if (smc->old_counts.counts[b] == 0 &&
+			    smc->counts.counts[b] == 0)
+				n++;
+
+		if (n != *count)
+			DMERR("free block counts differ, checker %u, sm-disk:%u",
+			      (unsigned) n, (unsigned) *count);
+	}
+	return r;
+}
+
+static int sm_checker_new_block(struct dm_space_map *sm, dm_block_t *b)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	int r = dm_sm_new_block(smc->real_sm, b);
+
+	if (!r) {
+		BUG_ON(*b >= smc->old_counts.nr);
+		BUG_ON(smc->old_counts.counts[*b] != 0);
+		BUG_ON(*b >= smc->counts.nr);
+		BUG_ON(smc->counts.counts[*b] != 0);
+		ca_set_count(&smc->counts, *b, 1);
+	}
+
+	return r;
+}
+
+static int sm_checker_inc_block(struct dm_space_map *sm, dm_block_t b)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	int r = dm_sm_inc_block(smc->real_sm, b);
+	int r2 = ca_inc_block(&smc->counts, b);
+	BUG_ON(r != r2);
+	return r;
+}
+
+static int sm_checker_dec_block(struct dm_space_map *sm, dm_block_t b)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	int r = dm_sm_dec_block(smc->real_sm, b);
+	int r2 = ca_dec_block(&smc->counts, b);
+	BUG_ON(r != r2);
+	return r;
+}
+
+static int sm_checker_get_count(struct dm_space_map *sm, dm_block_t b, uint32_t *result)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	uint32_t result2 = 0;
+	int r = dm_sm_get_count(smc->real_sm, b, result);
+	int r2 = ca_get_count(&smc->counts, b, &result2);
+
+	BUG_ON(r != r2);
+	if (!r)
+		BUG_ON(*result != result2);
+	return r;
+}
+
+static int sm_checker_count_more_than_one(struct dm_space_map *sm, dm_block_t b, int *result)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	int result2 = 0;
+	int r = dm_sm_count_is_more_than_one(smc->real_sm, b, result);
+	int r2 = ca_count_more_than_one(&smc->counts, b, &result2);
+
+	BUG_ON(r != r2);
+	if (!r)
+		BUG_ON(!(*result) && result2);
+	return r;
+}
+
+static int sm_checker_set_count(struct dm_space_map *sm, dm_block_t b, uint32_t count)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	uint32_t old_rc;
+	int r = dm_sm_set_count(smc->real_sm, b, count);
+	int r2;
+
+	BUG_ON(b >= smc->counts.nr);
+	old_rc = smc->counts.counts[b];
+	r2 = ca_set_count(&smc->counts, b, count);
+	BUG_ON(r != r2);
+
+	return r;
+}
+
+static int sm_checker_commit(struct dm_space_map *sm)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	int r;
+
+	r = dm_sm_commit(smc->real_sm);
+	if (r)
+		return r;
+
+	r = ca_commit(&smc->old_counts, &smc->counts);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+static int sm_checker_extend(struct dm_space_map *sm, dm_block_t extra_blocks)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	int r = dm_sm_extend(smc->real_sm, extra_blocks);
+	if (r)
+		return r;
+
+	return ca_extend(&smc->counts, extra_blocks);
+}
+
+static int sm_checker_root_size(struct dm_space_map *sm, size_t *result)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	return dm_sm_root_size(smc->real_sm, result);
+}
+
+static int sm_checker_copy_root(struct dm_space_map *sm, void *copy_to_here_le, size_t len)
+{
+	struct sm_checker *smc = container_of(sm, struct sm_checker, sm);
+	return dm_sm_copy_root(smc->real_sm, copy_to_here_le, len);
+}
+
+/*----------------------------------------------------------------*/
+
+static struct dm_space_map ops_ = {
+	.destroy = sm_checker_destroy,
+	.get_nr_blocks = sm_checker_get_nr_blocks,
+	.get_nr_free = sm_checker_get_nr_free,
+	.inc_block = sm_checker_inc_block,
+	.dec_block = sm_checker_dec_block,
+	.new_block = sm_checker_new_block,
+	.get_count = sm_checker_get_count,
+	.count_is_more_than_one = sm_checker_count_more_than_one,
+	.set_count = sm_checker_set_count,
+	.commit = sm_checker_commit,
+	.extend = sm_checker_extend,
+	.root_size = sm_checker_root_size,
+	.copy_root = sm_checker_copy_root
+};
+
+struct dm_space_map *dm_sm_checker_create(struct dm_space_map *sm)
+{
+	int r;
+	struct sm_checker *smc;
+
+	if (!sm)
+		return NULL;
+
+	smc = kmalloc(sizeof(*smc), GFP_KERNEL);
+	if (!smc)
+		return NULL;
+
+	memcpy(&smc->sm, &ops_, sizeof(smc->sm));
+	r = ca_create(&smc->old_counts, sm);
+	if (r) {
+		kfree(smc);
+		return NULL;
+	}
+
+	r = ca_create(&smc->counts, sm);
+	if (r) {
+		ca_destroy(&smc->old_counts);
+		kfree(smc);
+		return NULL;
+	}
+
+	smc->real_sm = sm;
+
+	r = ca_load(&smc->counts, sm);
+	if (r) {
+		ca_destroy(&smc->counts);
+		ca_destroy(&smc->old_counts);
+		kfree(smc);
+		return NULL;
+	}
+
+	r = ca_commit(&smc->old_counts, &smc->counts);
+	if (r) {
+		ca_destroy(&smc->counts);
+		ca_destroy(&smc->old_counts);
+		kfree(smc);
+		return NULL;
+	}
+
+	return &smc->sm;
+}
+EXPORT_SYMBOL_GPL(dm_sm_checker_create);
+
+struct dm_space_map *dm_sm_checker_create_fresh(struct dm_space_map *sm)
+{
+	int r;
+	struct sm_checker *smc;
+
+	if (!sm)
+		return NULL;
+
+	smc = kmalloc(sizeof(*smc), GFP_KERNEL);
+	if (!smc)
+		return NULL;
+
+	memcpy(&smc->sm, &ops_, sizeof(smc->sm));
+	r = ca_create(&smc->old_counts, sm);
+	if (r) {
+		kfree(smc);
+		return NULL;
+	}
+
+	r = ca_create(&smc->counts, sm);
+	if (r) {
+		ca_destroy(&smc->old_counts);
+		kfree(smc);
+		return NULL;
+	}
+
+	smc->real_sm = sm;
+	return &smc->sm;
+}
+EXPORT_SYMBOL_GPL(dm_sm_checker_create_fresh);
+
+/*----------------------------------------------------------------*/
+
+#else
+
+struct dm_space_map *dm_sm_checker_create(struct dm_space_map *sm)
+{
+	return sm;
+}
+EXPORT_SYMBOL_GPL(dm_sm_checker_create);
+
+struct dm_space_map *dm_sm_checker_create_fresh(struct dm_space_map *sm)
+{
+	return sm;
+}
+EXPORT_SYMBOL_GPL(dm_sm_checker_create_fresh);
+
+/*----------------------------------------------------------------*/
+
+#endif
diff --git a/drivers/md/persistent-data/dm-space-map-checker.h b/drivers/md/persistent-data/dm-space-map-checker.h
new file mode 100644
index 0000000..444dccf
--- /dev/null
+++ b/drivers/md/persistent-data/dm-space-map-checker.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef SNAPSHOTS_SPACE_MAP_CHECKER_H
+#define SNAPSHOTS_SPACE_MAP_CHECKER_H
+
+#include "dm-space-map.h"
+
+/*----------------------------------------------------------------*/
+
+/*
+ * This space map wraps a real on-disk space map, and verifies all of its
+ * operations.  It uses a lot of memory, so only use if you have a specific
+ * problem that you're debugging.
+ *
+ * Ownership of @sm passes.
+ */
+struct dm_space_map *dm_sm_checker_create(struct dm_space_map *sm);
+struct dm_space_map *dm_sm_checker_create_fresh(struct dm_space_map *sm);
+
+/*----------------------------------------------------------------*/
+
+#endif
diff --git a/drivers/md/persistent-data/dm-space-map-common.c b/drivers/md/persistent-data/dm-space-map-common.c
new file mode 100644
index 0000000..df2494c
--- /dev/null
+++ b/drivers/md/persistent-data/dm-space-map-common.c
@@ -0,0 +1,705 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-space-map-common.h"
+#include "dm-transaction-manager.h"
+
+#include <linux/bitops.h>
+#include <linux/device-mapper.h>
+
+#define DM_MSG_PREFIX "space map common"
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Index validator.
+ */
+#define INDEX_CSUM_XOR 160478
+
+static void index_prepare_for_write(struct dm_block_validator *v,
+				    struct dm_block *b,
+				    size_t block_size)
+{
+	struct disk_metadata_index *mi_le = dm_block_data(b);
+
+	mi_le->blocknr = cpu_to_le64(dm_block_location(b));
+	mi_le->csum = cpu_to_le32(dm_bm_checksum(&mi_le->padding,
+						 block_size - sizeof(__le32),
+						 INDEX_CSUM_XOR));
+}
+
+static int index_check(struct dm_block_validator *v,
+		       struct dm_block *b,
+		       size_t block_size)
+{
+	struct disk_metadata_index *mi_le = dm_block_data(b);
+	__le32 csum_disk;
+
+	if (dm_block_location(b) != le64_to_cpu(mi_le->blocknr)) {
+		DMERR("index_check failed blocknr %llu wanted %llu",
+		      le64_to_cpu(mi_le->blocknr), dm_block_location(b));
+		return -ENOTBLK;
+	}
+
+	csum_disk = cpu_to_le32(dm_bm_checksum(&mi_le->padding,
+					       block_size - sizeof(__le32),
+					       INDEX_CSUM_XOR));
+	if (csum_disk != mi_le->csum) {
+		DMERR("index_check failed csum %u wanted %u",
+		      le32_to_cpu(csum_disk), le32_to_cpu(mi_le->csum));
+		return -EILSEQ;
+	}
+
+	return 0;
+}
+
+static struct dm_block_validator index_validator = {
+	.name = "index",
+	.prepare_for_write = index_prepare_for_write,
+	.check = index_check
+};
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Bitmap validator
+ */
+#define BITMAP_CSUM_XOR 240779
+
+static void bitmap_prepare_for_write(struct dm_block_validator *v,
+				     struct dm_block *b,
+				     size_t block_size)
+{
+	struct disk_bitmap_header *disk_header = dm_block_data(b);
+
+	disk_header->blocknr = cpu_to_le64(dm_block_location(b));
+	disk_header->csum = cpu_to_le32(dm_bm_checksum(&disk_header->not_used,
+						       block_size - sizeof(__le32),
+						       BITMAP_CSUM_XOR));
+}
+
+static int bitmap_check(struct dm_block_validator *v,
+			struct dm_block *b,
+			size_t block_size)
+{
+	struct disk_bitmap_header *disk_header = dm_block_data(b);
+	__le32 csum_disk;
+
+	if (dm_block_location(b) != le64_to_cpu(disk_header->blocknr)) {
+		DMERR("bitmap check failed blocknr %llu wanted %llu",
+		      le64_to_cpu(disk_header->blocknr), dm_block_location(b));
+		return -ENOTBLK;
+	}
+
+	csum_disk = cpu_to_le32(dm_bm_checksum(&disk_header->not_used,
+					       block_size - sizeof(__le32),
+					       BITMAP_CSUM_XOR));
+	if (csum_disk != disk_header->csum) {
+		DMERR("bitmap check failed csum %u wanted %u",
+		      le32_to_cpu(csum_disk), le32_to_cpu(disk_header->csum));
+		return -EILSEQ;
+	}
+
+	return 0;
+}
+
+static struct dm_block_validator dm_sm_bitmap_validator = {
+	.name = "sm_bitmap",
+	.prepare_for_write = bitmap_prepare_for_write,
+	.check = bitmap_check
+};
+
+/*----------------------------------------------------------------*/
+
+#define ENTRIES_PER_WORD 32
+#define ENTRIES_SHIFT	5
+
+static void *dm_bitmap_data(struct dm_block *b)
+{
+	return dm_block_data(b) + sizeof(struct disk_bitmap_header);
+}
+
+#define WORD_MASK_HIGH 0xAAAAAAAAAAAAAAAAULL
+
+static unsigned bitmap_word_used(void *addr, unsigned b)
+{
+	__le64 *words_le = addr;
+	__le64 *w_le = words_le + (b >> ENTRIES_SHIFT);
+
+	uint64_t bits = le64_to_cpu(*w_le);
+	uint64_t mask = (bits + WORD_MASK_HIGH + 1) & WORD_MASK_HIGH;
+
+	return !(~bits & mask);
+}
+
+static unsigned sm_lookup_bitmap(void *addr, unsigned b)
+{
+	__le64 *words_le = addr;
+	__le64 *w_le = words_le + (b >> ENTRIES_SHIFT);
+	unsigned hi, lo;
+
+	b = (b & (ENTRIES_PER_WORD - 1)) << 1;
+	hi = !!test_bit_le(b, (void *) w_le);
+	lo = !!test_bit_le(b + 1, (void *) w_le);
+	return (hi << 1) | lo;
+}
+
+static void sm_set_bitmap(void *addr, unsigned b, unsigned val)
+{
+	__le64 *words_le = addr;
+	__le64 *w_le = words_le + (b >> ENTRIES_SHIFT);
+
+	b = (b & (ENTRIES_PER_WORD - 1)) << 1;
+
+	if (val & 2)
+		__set_bit_le(b, (void *) w_le);
+	else
+		__clear_bit_le(b, (void *) w_le);
+
+	if (val & 1)
+		__set_bit_le(b + 1, (void *) w_le);
+	else
+		__clear_bit_le(b + 1, (void *) w_le);
+}
+
+static int sm_find_free(void *addr, unsigned begin, unsigned end,
+			unsigned *result)
+{
+	while (begin < end) {
+		if (!(begin & (ENTRIES_PER_WORD - 1)) &&
+		    bitmap_word_used(addr, begin)) {
+			begin += ENTRIES_PER_WORD;
+			continue;
+		}
+
+		if (!sm_lookup_bitmap(addr, begin)) {
+			*result = begin;
+			return 0;
+		}
+
+		begin++;
+	}
+
+	return -ENOSPC;
+}
+
+/*----------------------------------------------------------------*/
+
+static int sm_ll_init(struct ll_disk *ll, struct dm_transaction_manager *tm)
+{
+	ll->tm = tm;
+
+	ll->bitmap_info.tm = tm;
+	ll->bitmap_info.levels = 1;
+
+	/*
+	 * Because the new bitmap blocks are created via a shadow
+	 * operation, the old entry has already had its reference count
+	 * decremented and we don't need the btree to do any bookkeeping.
+	 */
+	ll->bitmap_info.value_type.size = sizeof(struct disk_index_entry);
+	ll->bitmap_info.value_type.inc = NULL;
+	ll->bitmap_info.value_type.dec = NULL;
+	ll->bitmap_info.value_type.equal = NULL;
+
+	ll->ref_count_info.tm = tm;
+	ll->ref_count_info.levels = 1;
+	ll->ref_count_info.value_type.size = sizeof(uint32_t);
+	ll->ref_count_info.value_type.inc = NULL;
+	ll->ref_count_info.value_type.dec = NULL;
+	ll->ref_count_info.value_type.equal = NULL;
+
+	ll->block_size = dm_bm_block_size(dm_tm_get_bm(tm));
+
+	if (ll->block_size > (1 << 30)) {
+		DMERR("block size too big to hold bitmaps");
+		return -EINVAL;
+	}
+
+	ll->entries_per_block = (ll->block_size - sizeof(struct disk_bitmap_header)) *
+		ENTRIES_PER_BYTE;
+	ll->nr_blocks = 0;
+	ll->bitmap_root = 0;
+	ll->ref_count_root = 0;
+
+	return 0;
+}
+
+int sm_ll_extend(struct ll_disk *ll, dm_block_t extra_blocks)
+{
+	int r;
+	dm_block_t i, nr_blocks, nr_indexes;
+	unsigned old_blocks, blocks;
+
+	nr_blocks = ll->nr_blocks + extra_blocks;
+	old_blocks = dm_sector_div_up(ll->nr_blocks, ll->entries_per_block);
+	blocks = dm_sector_div_up(nr_blocks, ll->entries_per_block);
+
+	nr_indexes = dm_sector_div_up(nr_blocks, ll->entries_per_block);
+	if (nr_indexes > ll->max_entries(ll)) {
+		DMERR("space map too large");
+		return -EINVAL;
+	}
+
+	for (i = old_blocks; i < blocks; i++) {
+		struct dm_block *b;
+		struct disk_index_entry idx;
+
+		r = dm_tm_new_block(ll->tm, &dm_sm_bitmap_validator, &b);
+		if (r < 0)
+			return r;
+		idx.blocknr = cpu_to_le64(dm_block_location(b));
+
+		r = dm_tm_unlock(ll->tm, b);
+		if (r < 0)
+			return r;
+
+		idx.nr_free = cpu_to_le32(ll->entries_per_block);
+		idx.none_free_before = 0;
+
+		r = ll->save_ie(ll, i, &idx);
+		if (r < 0)
+			return r;
+	}
+
+	ll->nr_blocks = nr_blocks;
+	return 0;
+}
+
+int sm_ll_lookup_bitmap(struct ll_disk *ll, dm_block_t b, uint32_t *result)
+{
+	int r;
+	dm_block_t index = b;
+	struct disk_index_entry ie_disk;
+	struct dm_block *blk;
+
+	b = do_div(index, ll->entries_per_block);
+	r = ll->load_ie(ll, index, &ie_disk);
+	if (r < 0)
+		return r;
+
+	r = dm_tm_read_lock(ll->tm, le64_to_cpu(ie_disk.blocknr),
+			    &dm_sm_bitmap_validator, &blk);
+	if (r < 0)
+		return r;
+
+	*result = sm_lookup_bitmap(dm_bitmap_data(blk), b);
+
+	return dm_tm_unlock(ll->tm, blk);
+}
+
+int sm_ll_lookup(struct ll_disk *ll, dm_block_t b, uint32_t *result)
+{
+	__le32 le_rc;
+	int r = sm_ll_lookup_bitmap(ll, b, result);
+
+	if (r)
+		return r;
+
+	if (*result != 3)
+		return r;
+
+	r = dm_btree_lookup(&ll->ref_count_info, ll->ref_count_root, &b, &le_rc);
+	if (r < 0)
+		return r;
+
+	*result = le32_to_cpu(le_rc);
+
+	return r;
+}
+
+int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin,
+			  dm_block_t end, dm_block_t *result)
+{
+	int r;
+	struct disk_index_entry ie_disk;
+	dm_block_t i, index_begin = begin;
+	dm_block_t index_end = dm_sector_div_up(end, ll->entries_per_block);
+
+	/*
+	 * FIXME: Use shifts
+	 */
+	begin = do_div(index_begin, ll->entries_per_block);
+	end = do_div(end, ll->entries_per_block);
+
+	for (i = index_begin; i < index_end; i++, begin = 0) {
+		struct dm_block *blk;
+		unsigned position;
+		uint32_t bit_end;
+
+		r = ll->load_ie(ll, i, &ie_disk);
+		if (r < 0)
+			return r;
+
+		if (le32_to_cpu(ie_disk.nr_free) == 0)
+			continue;
+
+		r = dm_tm_read_lock(ll->tm, le64_to_cpu(ie_disk.blocknr),
+				    &dm_sm_bitmap_validator, &blk);
+		if (r < 0)
+			return r;
+
+		bit_end = (i == index_end - 1) ?  end : ll->entries_per_block;
+
+		r = sm_find_free(dm_bitmap_data(blk),
+				 max_t(unsigned, begin, le32_to_cpu(ie_disk.none_free_before)),
+				 bit_end, &position);
+		if (r == -ENOSPC) {
+			/*
+			 * This might happen because we started searching
+			 * part way through the bitmap.
+			 */
+			dm_tm_unlock(ll->tm, blk);
+			continue;
+
+		} else if (r < 0) {
+			dm_tm_unlock(ll->tm, blk);
+			return r;
+		}
+
+		r = dm_tm_unlock(ll->tm, blk);
+		if (r < 0)
+			return r;
+
+		*result = i * ll->entries_per_block + (dm_block_t) position;
+		return 0;
+	}
+
+	return -ENOSPC;
+}
+
+int sm_ll_insert(struct ll_disk *ll, dm_block_t b,
+		 uint32_t ref_count, enum allocation_event *ev)
+{
+	int r;
+	uint32_t bit, old;
+	struct dm_block *nb;
+	dm_block_t index = b;
+	struct disk_index_entry ie_disk;
+	void *bm_le;
+	int inc;
+
+	bit = do_div(index, ll->entries_per_block);
+	r = ll->load_ie(ll, index, &ie_disk);
+	if (r < 0)
+		return r;
+
+	r = dm_tm_shadow_block(ll->tm, le64_to_cpu(ie_disk.blocknr),
+			       &dm_sm_bitmap_validator, &nb, &inc);
+	if (r < 0) {
+		DMERR("dm_tm_shadow_block() failed");
+		return r;
+	}
+	ie_disk.blocknr = cpu_to_le64(dm_block_location(nb));
+
+	bm_le = dm_bitmap_data(nb);
+	old = sm_lookup_bitmap(bm_le, bit);
+
+	if (ref_count <= 2) {
+		sm_set_bitmap(bm_le, bit, ref_count);
+
+		r = dm_tm_unlock(ll->tm, nb);
+		if (r < 0)
+			return r;
+
+#if 0
+		/* FIXME: dm_btree_remove doesn't handle this yet */
+		if (old > 2) {
+			r = dm_btree_remove(&ll->ref_count_info,
+					    ll->ref_count_root,
+					    &b, &ll->ref_count_root);
+			if (r)
+				return r;
+		}
+#endif
+
+	} else {
+		__le32 le_rc = cpu_to_le32(ref_count);
+
+		sm_set_bitmap(bm_le, bit, 3);
+		r = dm_tm_unlock(ll->tm, nb);
+		if (r < 0)
+			return r;
+
+		__dm_bless_for_disk(&le_rc);
+		r = dm_btree_insert(&ll->ref_count_info, ll->ref_count_root,
+				    &b, &le_rc, &ll->ref_count_root);
+		if (r < 0) {
+			DMERR("ref count insert failed");
+			return r;
+		}
+	}
+
+	if (ref_count && !old) {
+		*ev = SM_ALLOC;
+		ll->nr_allocated++;
+		ie_disk.nr_free = cpu_to_le32(le32_to_cpu(ie_disk.nr_free) - 1);
+		if (le32_to_cpu(ie_disk.none_free_before) == bit)
+			ie_disk.none_free_before = cpu_to_le32(bit + 1);
+
+	} else if (old && !ref_count) {
+		*ev = SM_FREE;
+		ll->nr_allocated--;
+		ie_disk.nr_free = cpu_to_le32(le32_to_cpu(ie_disk.nr_free) + 1);
+		ie_disk.none_free_before = cpu_to_le32(min(le32_to_cpu(ie_disk.none_free_before), bit));
+	}
+
+	return ll->save_ie(ll, index, &ie_disk);
+}
+
+int sm_ll_inc(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev)
+{
+	int r;
+	uint32_t rc;
+
+	r = sm_ll_lookup(ll, b, &rc);
+	if (r)
+		return r;
+
+	return sm_ll_insert(ll, b, rc + 1, ev);
+}
+
+int sm_ll_dec(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev)
+{
+	int r;
+	uint32_t rc;
+
+	r = sm_ll_lookup(ll, b, &rc);
+	if (r)
+		return r;
+
+	if (!rc)
+		return -EINVAL;
+
+	return sm_ll_insert(ll, b, rc - 1, ev);
+}
+
+int sm_ll_commit(struct ll_disk *ll)
+{
+	return ll->commit(ll);
+}
+
+/*----------------------------------------------------------------*/
+
+static int metadata_ll_load_ie(struct ll_disk *ll, dm_block_t index,
+			       struct disk_index_entry *ie)
+{
+	memcpy(ie, ll->mi_le.index + index, sizeof(*ie));
+	return 0;
+}
+
+static int metadata_ll_save_ie(struct ll_disk *ll, dm_block_t index,
+			       struct disk_index_entry *ie)
+{
+	memcpy(ll->mi_le.index + index, ie, sizeof(*ie));
+	return 0;
+}
+
+static int metadata_ll_init_index(struct ll_disk *ll)
+{
+	int r;
+	struct dm_block *b;
+
+	r = dm_tm_new_block(ll->tm, &index_validator, &b);
+	if (r < 0)
+		return r;
+
+	memcpy(dm_block_data(b), &ll->mi_le, sizeof(ll->mi_le));
+	ll->bitmap_root = dm_block_location(b);
+
+	return dm_tm_unlock(ll->tm, b);
+}
+
+static int metadata_ll_open(struct ll_disk *ll)
+{
+	int r;
+	struct dm_block *block;
+
+	r = dm_tm_read_lock(ll->tm, ll->bitmap_root,
+			    &index_validator, &block);
+	if (r)
+		return r;
+
+	memcpy(&ll->mi_le, dm_block_data(block), sizeof(ll->mi_le));
+	return dm_tm_unlock(ll->tm, block);
+}
+
+static dm_block_t metadata_ll_max_entries(struct ll_disk *ll)
+{
+	return MAX_METADATA_BITMAPS;
+}
+
+static int metadata_ll_commit(struct ll_disk *ll)
+{
+	int r, inc;
+	struct dm_block *b;
+
+	r = dm_tm_shadow_block(ll->tm, ll->bitmap_root, &index_validator, &b, &inc);
+	if (r)
+		return r;
+
+	memcpy(dm_block_data(b), &ll->mi_le, sizeof(ll->mi_le));
+	ll->bitmap_root = dm_block_location(b);
+
+	return dm_tm_unlock(ll->tm, b);
+}
+
+int sm_ll_new_metadata(struct ll_disk *ll, struct dm_transaction_manager *tm)
+{
+	int r;
+
+	r = sm_ll_init(ll, tm);
+	if (r < 0)
+		return r;
+
+	ll->load_ie = metadata_ll_load_ie;
+	ll->save_ie = metadata_ll_save_ie;
+	ll->init_index = metadata_ll_init_index;
+	ll->open_index = metadata_ll_open;
+	ll->max_entries = metadata_ll_max_entries;
+	ll->commit = metadata_ll_commit;
+
+	ll->nr_blocks = 0;
+	ll->nr_allocated = 0;
+
+	r = ll->init_index(ll);
+	if (r < 0)
+		return r;
+
+	r = dm_btree_empty(&ll->ref_count_info, &ll->ref_count_root);
+	if (r < 0)
+		return r;
+
+	return 0;
+}
+
+int sm_ll_open_metadata(struct ll_disk *ll, struct dm_transaction_manager *tm,
+			void *root_le, size_t len)
+{
+	int r;
+	struct disk_sm_root *smr = root_le;
+
+	if (len < sizeof(struct disk_sm_root)) {
+		DMERR("sm_metadata root too small");
+		return -ENOMEM;
+	}
+
+	r = sm_ll_init(ll, tm);
+	if (r < 0)
+		return r;
+
+	ll->load_ie = metadata_ll_load_ie;
+	ll->save_ie = metadata_ll_save_ie;
+	ll->init_index = metadata_ll_init_index;
+	ll->open_index = metadata_ll_open;
+	ll->max_entries = metadata_ll_max_entries;
+	ll->commit = metadata_ll_commit;
+
+	ll->nr_blocks = le64_to_cpu(smr->nr_blocks);
+	ll->nr_allocated = le64_to_cpu(smr->nr_allocated);
+	ll->bitmap_root = le64_to_cpu(smr->bitmap_root);
+	ll->ref_count_root = le64_to_cpu(smr->ref_count_root);
+
+	return ll->open_index(ll);
+}
+
+/*----------------------------------------------------------------*/
+
+static int disk_ll_load_ie(struct ll_disk *ll, dm_block_t index,
+			   struct disk_index_entry *ie)
+{
+	return dm_btree_lookup(&ll->bitmap_info, ll->bitmap_root, &index, ie);
+}
+
+static int disk_ll_save_ie(struct ll_disk *ll, dm_block_t index,
+			   struct disk_index_entry *ie)
+{
+	__dm_bless_for_disk(ie);
+	return dm_btree_insert(&ll->bitmap_info, ll->bitmap_root,
+			       &index, ie, &ll->bitmap_root);
+}
+
+static int disk_ll_init_index(struct ll_disk *ll)
+{
+	return dm_btree_empty(&ll->bitmap_info, &ll->bitmap_root);
+}
+
+static int disk_ll_open(struct ll_disk *ll)
+{
+	/* nothing to do */
+	return 0;
+}
+
+static dm_block_t disk_ll_max_entries(struct ll_disk *ll)
+{
+	return -1ULL;
+}
+
+static int disk_ll_commit(struct ll_disk *ll)
+{
+	return 0;
+}
+
+int sm_ll_new_disk(struct ll_disk *ll, struct dm_transaction_manager *tm)
+{
+	int r;
+
+	r = sm_ll_init(ll, tm);
+	if (r < 0)
+		return r;
+
+	ll->load_ie = disk_ll_load_ie;
+	ll->save_ie = disk_ll_save_ie;
+	ll->init_index = disk_ll_init_index;
+	ll->open_index = disk_ll_open;
+	ll->max_entries = disk_ll_max_entries;
+	ll->commit = disk_ll_commit;
+
+	ll->nr_blocks = 0;
+	ll->nr_allocated = 0;
+
+	r = ll->init_index(ll);
+	if (r < 0)
+		return r;
+
+	r = dm_btree_empty(&ll->ref_count_info, &ll->ref_count_root);
+	if (r < 0)
+		return r;
+
+	return 0;
+}
+
+int sm_ll_open_disk(struct ll_disk *ll, struct dm_transaction_manager *tm,
+		    void *root_le, size_t len)
+{
+	int r;
+	struct disk_sm_root *smr = root_le;
+
+	if (len < sizeof(struct disk_sm_root)) {
+		DMERR("sm_metadata root too small");
+		return -ENOMEM;
+	}
+
+	r = sm_ll_init(ll, tm);
+	if (r < 0)
+		return r;
+
+	ll->load_ie = disk_ll_load_ie;
+	ll->save_ie = disk_ll_save_ie;
+	ll->init_index = disk_ll_init_index;
+	ll->open_index = disk_ll_open;
+	ll->max_entries = disk_ll_max_entries;
+	ll->commit = disk_ll_commit;
+
+	ll->nr_blocks = le64_to_cpu(smr->nr_blocks);
+	ll->nr_allocated = le64_to_cpu(smr->nr_allocated);
+	ll->bitmap_root = le64_to_cpu(smr->bitmap_root);
+	ll->ref_count_root = le64_to_cpu(smr->ref_count_root);
+
+	return ll->open_index(ll);
+}
+
+/*----------------------------------------------------------------*/
diff --git a/drivers/md/persistent-data/dm-space-map-common.h b/drivers/md/persistent-data/dm-space-map-common.h
new file mode 100644
index 0000000..8f22082
--- /dev/null
+++ b/drivers/md/persistent-data/dm-space-map-common.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef DM_SPACE_MAP_COMMON_H
+#define DM_SPACE_MAP_COMMON_H
+
+#include "dm-btree.h"
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Low level disk format
+ *
+ * Bitmap btree
+ * ------------
+ *
+ * Each value stored in the btree is an index_entry.  This points to a
+ * block that is used as a bitmap.  Within the bitmap hold 2 bits per
+ * entry, which represent UNUSED = 0, REF_COUNT = 1, REF_COUNT = 2 and
+ * REF_COUNT = many.
+ *
+ * Refcount btree
+ * --------------
+ *
+ * Any entry that has a ref count higher than 2 gets entered in the ref
+ * count tree.  The leaf values for this tree is the 32-bit ref count.
+ */
+
+struct disk_index_entry {
+	__le64 blocknr;
+	__le32 nr_free;
+	__le32 none_free_before;
+} __packed;
+
+
+#define MAX_METADATA_BITMAPS 255
+struct disk_metadata_index {
+	__le32 csum;
+	__le32 padding;
+	__le64 blocknr;
+
+	struct disk_index_entry index[MAX_METADATA_BITMAPS];
+} __packed;
+
+struct ll_disk;
+
+typedef int (*load_ie_fn)(struct ll_disk *ll, dm_block_t index, struct disk_index_entry *result);
+typedef int (*save_ie_fn)(struct ll_disk *ll, dm_block_t index, struct disk_index_entry *ie);
+typedef int (*init_index_fn)(struct ll_disk *ll);
+typedef int (*open_index_fn)(struct ll_disk *ll);
+typedef dm_block_t (*max_index_entries_fn)(struct ll_disk *ll);
+typedef int (*commit_fn)(struct ll_disk *ll);
+
+struct ll_disk {
+	struct dm_transaction_manager *tm;
+	struct dm_btree_info bitmap_info;
+	struct dm_btree_info ref_count_info;
+
+	uint32_t block_size;
+	uint32_t entries_per_block;
+	dm_block_t nr_blocks;
+	dm_block_t nr_allocated;
+
+	/*
+	 * bitmap_root may be a btree root or a simple index.
+	 */
+	dm_block_t bitmap_root;
+
+	dm_block_t ref_count_root;
+
+	struct disk_metadata_index mi_le;
+	load_ie_fn load_ie;
+	save_ie_fn save_ie;
+	init_index_fn init_index;
+	open_index_fn open_index;
+	max_index_entries_fn max_entries;
+	commit_fn commit;
+};
+
+struct disk_sm_root {
+	__le64 nr_blocks;
+	__le64 nr_allocated;
+	__le64 bitmap_root;
+	__le64 ref_count_root;
+} __packed;
+
+#define ENTRIES_PER_BYTE 4
+
+struct disk_bitmap_header {
+	__le32 csum;
+	__le32 not_used;
+	__le64 blocknr;
+} __packed;
+
+enum allocation_event {
+	SM_NONE,
+	SM_ALLOC,
+	SM_FREE,
+};
+
+/*----------------------------------------------------------------*/
+
+int sm_ll_extend(struct ll_disk *ll, dm_block_t extra_blocks);
+int sm_ll_lookup_bitmap(struct ll_disk *ll, dm_block_t b, uint32_t *result);
+int sm_ll_lookup(struct ll_disk *ll, dm_block_t b, uint32_t *result);
+int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin,
+			  dm_block_t end, dm_block_t *result);
+int sm_ll_insert(struct ll_disk *ll, dm_block_t b, uint32_t ref_count, enum allocation_event *ev);
+int sm_ll_inc(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev);
+int sm_ll_dec(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev);
+int sm_ll_commit(struct ll_disk *ll);
+
+int sm_ll_new_metadata(struct ll_disk *ll, struct dm_transaction_manager *tm);
+int sm_ll_open_metadata(struct ll_disk *ll, struct dm_transaction_manager *tm,
+			void *root_le, size_t len);
+
+int sm_ll_new_disk(struct ll_disk *ll, struct dm_transaction_manager *tm);
+int sm_ll_open_disk(struct ll_disk *ll, struct dm_transaction_manager *tm,
+		    void *root_le, size_t len);
+
+/*----------------------------------------------------------------*/
+
+#endif	/* DM_SPACE_MAP_COMMON_H */
diff --git a/drivers/md/persistent-data/dm-space-map-disk.c b/drivers/md/persistent-data/dm-space-map-disk.c
new file mode 100644
index 0000000..aeff785
--- /dev/null
+++ b/drivers/md/persistent-data/dm-space-map-disk.c
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-space-map-checker.h"
+#include "dm-space-map-common.h"
+#include "dm-space-map-disk.h"
+#include "dm-space-map.h"
+#include "dm-transaction-manager.h"
+
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/device-mapper.h>
+
+#define DM_MSG_PREFIX "space map disk"
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Space map interface.
+ */
+struct sm_disk {
+	struct dm_space_map sm;
+
+	struct ll_disk ll;
+	struct ll_disk old_ll;
+
+	dm_block_t begin;
+	dm_block_t nr_allocated_this_transaction;
+};
+
+static void sm_disk_destroy(struct dm_space_map *sm)
+{
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+
+	kfree(smd);
+}
+
+static int sm_disk_extend(struct dm_space_map *sm, dm_block_t extra_blocks)
+{
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+
+	return sm_ll_extend(&smd->ll, extra_blocks);
+}
+
+static int sm_disk_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count)
+{
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+	*count = smd->old_ll.nr_blocks;
+
+	return 0;
+}
+
+static int sm_disk_get_nr_free(struct dm_space_map *sm, dm_block_t *count)
+{
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+	*count = (smd->old_ll.nr_blocks - smd->old_ll.nr_allocated) - smd->nr_allocated_this_transaction;
+
+	return 0;
+}
+
+static int sm_disk_get_count(struct dm_space_map *sm, dm_block_t b,
+			     uint32_t *result)
+{
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+	return sm_ll_lookup(&smd->ll, b, result);
+}
+
+static int sm_disk_count_is_more_than_one(struct dm_space_map *sm, dm_block_t b,
+					  int *result)
+{
+	int r;
+	uint32_t count;
+
+	r = sm_disk_get_count(sm, b, &count);
+	if (r)
+		return r;
+
+	return count > 1;
+}
+
+static int sm_disk_set_count(struct dm_space_map *sm, dm_block_t b,
+			     uint32_t count)
+{
+	int r;
+	uint32_t old_count;
+	enum allocation_event ev;
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+
+	r = sm_ll_insert(&smd->ll, b, count, &ev);
+	if (!r) {
+		switch (ev) {
+		case SM_NONE:
+			break;
+
+		case SM_ALLOC:
+			/*
+			 * This _must_ be free in the prior transaction
+			 * otherwise we've lost atomicity.
+			 */
+			smd->nr_allocated_this_transaction++;
+			break;
+
+		case SM_FREE:
+			/*
+			 * It's only free if it's also free in the last
+			 * transaction.
+			 */
+			r = sm_ll_lookup(&smd->old_ll, b, &old_count);
+			if (r)
+				return r;
+
+			if (!old_count)
+				smd->nr_allocated_this_transaction--;
+			break;
+		}
+	}
+
+	return r;
+}
+
+static int sm_disk_inc_block(struct dm_space_map *sm, dm_block_t b)
+{
+	int r;
+	enum allocation_event ev;
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+
+	r = sm_ll_inc(&smd->ll, b, &ev);
+	if (!r && (ev == SM_ALLOC))
+		/*
+		 * This _must_ be free in the prior transaction
+		 * otherwise we've lost atomicity.
+		 */
+		smd->nr_allocated_this_transaction++;
+
+	return r;
+}
+
+static int sm_disk_dec_block(struct dm_space_map *sm, dm_block_t b)
+{
+	int r;
+	uint32_t old_count;
+	enum allocation_event ev;
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+
+	r = sm_ll_dec(&smd->ll, b, &ev);
+	if (!r && (ev == SM_FREE)) {
+		/*
+		 * It's only free if it's also free in the last
+		 * transaction.
+		 */
+		r = sm_ll_lookup(&smd->old_ll, b, &old_count);
+		if (r)
+			return r;
+
+		if (!old_count)
+			smd->nr_allocated_this_transaction--;
+	}
+
+	return r;
+}
+
+static int sm_disk_new_block(struct dm_space_map *sm, dm_block_t *b)
+{
+	int r;
+	enum allocation_event ev;
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+
+	/* FIXME: we should loop round a couple of times */
+	r = sm_ll_find_free_block(&smd->old_ll, smd->begin, smd->old_ll.nr_blocks, b);
+	if (r)
+		return r;
+
+	smd->begin = *b + 1;
+	r = sm_ll_inc(&smd->ll, *b, &ev);
+	if (!r) {
+		BUG_ON(ev != SM_ALLOC);
+		smd->nr_allocated_this_transaction++;
+	}
+
+	return r;
+}
+
+static int sm_disk_commit(struct dm_space_map *sm)
+{
+	int r;
+	dm_block_t nr_free;
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+
+	r = sm_disk_get_nr_free(sm, &nr_free);
+	if (r)
+		return r;
+
+	r = sm_ll_commit(&smd->ll);
+	if (r)
+		return r;
+
+	memcpy(&smd->old_ll, &smd->ll, sizeof(smd->old_ll));
+	smd->begin = 0;
+	smd->nr_allocated_this_transaction = 0;
+
+	r = sm_disk_get_nr_free(sm, &nr_free);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+static int sm_disk_root_size(struct dm_space_map *sm, size_t *result)
+{
+	*result = sizeof(struct disk_sm_root);
+
+	return 0;
+}
+
+static int sm_disk_copy_root(struct dm_space_map *sm, void *where_le, size_t max)
+{
+	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
+	struct disk_sm_root root_le;
+
+	root_le.nr_blocks = cpu_to_le64(smd->ll.nr_blocks);
+	root_le.nr_allocated = cpu_to_le64(smd->ll.nr_allocated);
+	root_le.bitmap_root = cpu_to_le64(smd->ll.bitmap_root);
+	root_le.ref_count_root = cpu_to_le64(smd->ll.ref_count_root);
+
+	if (max < sizeof(root_le))
+		return -ENOSPC;
+
+	memcpy(where_le, &root_le, sizeof(root_le));
+
+	return 0;
+}
+
+/*----------------------------------------------------------------*/
+
+static struct dm_space_map ops = {
+	.destroy = sm_disk_destroy,
+	.extend = sm_disk_extend,
+	.get_nr_blocks = sm_disk_get_nr_blocks,
+	.get_nr_free = sm_disk_get_nr_free,
+	.get_count = sm_disk_get_count,
+	.count_is_more_than_one = sm_disk_count_is_more_than_one,
+	.set_count = sm_disk_set_count,
+	.inc_block = sm_disk_inc_block,
+	.dec_block = sm_disk_dec_block,
+	.new_block = sm_disk_new_block,
+	.commit = sm_disk_commit,
+	.root_size = sm_disk_root_size,
+	.copy_root = sm_disk_copy_root
+};
+
+static struct dm_space_map *dm_sm_disk_create_real(
+	struct dm_transaction_manager *tm,
+	dm_block_t nr_blocks)
+{
+	int r;
+	struct sm_disk *smd;
+
+	smd = kmalloc(sizeof(*smd), GFP_KERNEL);
+	if (!smd)
+		return ERR_PTR(-ENOMEM);
+
+	smd->begin = 0;
+	smd->nr_allocated_this_transaction = 0;
+	memcpy(&smd->sm, &ops, sizeof(smd->sm));
+
+	r = sm_ll_new_disk(&smd->ll, tm);
+	if (r)
+		goto bad;
+
+	r = sm_ll_extend(&smd->ll, nr_blocks);
+	if (r)
+		goto bad;
+
+	r = sm_disk_commit(&smd->sm);
+	if (r)
+		goto bad;
+
+	return &smd->sm;
+
+bad:
+	kfree(smd);
+	return ERR_PTR(r);
+}
+
+struct dm_space_map *dm_sm_disk_create(struct dm_transaction_manager *tm,
+				       dm_block_t nr_blocks)
+{
+	struct dm_space_map *sm = dm_sm_disk_create_real(tm, nr_blocks);
+	return dm_sm_checker_create_fresh(sm);
+}
+EXPORT_SYMBOL_GPL(dm_sm_disk_create);
+
+static struct dm_space_map *dm_sm_disk_open_real(
+	struct dm_transaction_manager *tm,
+	void *root_le, size_t len)
+{
+	int r;
+	struct sm_disk *smd;
+
+	smd = kmalloc(sizeof(*smd), GFP_KERNEL);
+	if (!smd)
+		return ERR_PTR(-ENOMEM);
+
+	smd->begin = 0;
+	smd->nr_allocated_this_transaction = 0;
+	memcpy(&smd->sm, &ops, sizeof(smd->sm));
+
+	r = sm_ll_open_disk(&smd->ll, tm, root_le, len);
+	if (r)
+		goto bad;
+
+	r = sm_disk_commit(&smd->sm);
+	if (r)
+		goto bad;
+
+	return &smd->sm;
+
+bad:
+	kfree(smd);
+	return ERR_PTR(r);
+}
+
+struct dm_space_map *dm_sm_disk_open(struct dm_transaction_manager *tm,
+				     void *root_le, size_t len)
+{
+	return dm_sm_checker_create(
+		dm_sm_disk_open_real(tm, root_le, len));
+}
+EXPORT_SYMBOL_GPL(dm_sm_disk_open);
+
+/*----------------------------------------------------------------*/
diff --git a/drivers/md/persistent-data/dm-space-map-disk.h b/drivers/md/persistent-data/dm-space-map-disk.h
new file mode 100644
index 0000000..447a0a9
--- /dev/null
+++ b/drivers/md/persistent-data/dm-space-map-disk.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef _LINUX_DM_SPACE_MAP_DISK_H
+#define _LINUX_DM_SPACE_MAP_DISK_H
+
+#include "dm-block-manager.h"
+
+struct dm_space_map;
+struct dm_transaction_manager;
+
+/*
+ * Unfortunately we have to use two-phase construction due to the cycle
+ * between the tm and sm.
+ */
+struct dm_space_map *dm_sm_disk_create(struct dm_transaction_manager *tm,
+				       dm_block_t nr_blocks);
+
+struct dm_space_map *dm_sm_disk_open(struct dm_transaction_manager *tm,
+				     void *root, size_t len);
+
+#endif /* _LINUX_DM_SPACE_MAP_DISK_H */
diff --git a/drivers/md/persistent-data/dm-space-map-metadata.c b/drivers/md/persistent-data/dm-space-map-metadata.c
new file mode 100644
index 0000000..e89ae5e
--- /dev/null
+++ b/drivers/md/persistent-data/dm-space-map-metadata.c
@@ -0,0 +1,596 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-space-map.h"
+#include "dm-space-map-common.h"
+#include "dm-space-map-metadata.h"
+
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/device-mapper.h>
+
+#define DM_MSG_PREFIX "space map metadata"
+
+/*----------------------------------------------------------------*/
+
+/*
+ * Space map interface.
+ *
+ * The low level disk format is written using the standard btree and
+ * transaction manager.  This means that performing disk operations may
+ * cause us to recurse into the space map in order to allocate new blocks.
+ * For this reason we have a pool of pre-allocated blocks large enough to
+ * service any metadata_ll_disk operation.
+ */
+
+/*
+ * FIXME: we should calculate this based on the size of the device.
+ * Only the metadata space map needs this functionality.
+ */
+#define MAX_RECURSIVE_ALLOCATIONS 1024
+
+enum block_op_type {
+	BOP_INC,
+	BOP_DEC
+};
+
+struct block_op {
+	enum block_op_type type;
+	dm_block_t block;
+};
+
+struct sm_metadata {
+	struct dm_space_map sm;
+
+	struct ll_disk ll;
+	struct ll_disk old_ll;
+
+	dm_block_t begin;
+
+	unsigned recursion_count;
+	unsigned allocated_this_transaction;
+	unsigned nr_uncommitted;
+	struct block_op uncommitted[MAX_RECURSIVE_ALLOCATIONS];
+};
+
+static int add_bop(struct sm_metadata *smm, enum block_op_type type, dm_block_t b)
+{
+	struct block_op *op;
+
+	if (smm->nr_uncommitted == MAX_RECURSIVE_ALLOCATIONS) {
+		DMERR("too many recursive allocations");
+		return -ENOMEM;
+	}
+
+	op = smm->uncommitted + smm->nr_uncommitted++;
+	op->type = type;
+	op->block = b;
+
+	return 0;
+}
+
+static int commit_bop(struct sm_metadata *smm, struct block_op *op)
+{
+	int r = 0;
+	enum allocation_event ev;
+
+	switch (op->type) {
+	case BOP_INC:
+		r = sm_ll_inc(&smm->ll, op->block, &ev);
+		break;
+
+	case BOP_DEC:
+		r = sm_ll_dec(&smm->ll, op->block, &ev);
+		break;
+	}
+
+	return r;
+}
+
+static void in(struct sm_metadata *smm)
+{
+	smm->recursion_count++;
+}
+
+static int out(struct sm_metadata *smm)
+{
+	int r = 0;
+
+	/*
+	 * If we're not recursing then very bad things are happening.
+	 */
+	if (!smm->recursion_count) {
+		DMERR("lost track of recursion depth");
+		return -ENOMEM;
+	}
+
+	if (smm->recursion_count == 1 && smm->nr_uncommitted) {
+		while (smm->nr_uncommitted && !r) {
+			smm->nr_uncommitted--;
+			r = commit_bop(smm, smm->uncommitted +
+				       smm->nr_uncommitted);
+			if (r)
+				break;
+		}
+	}
+
+	smm->recursion_count--;
+
+	return r;
+}
+
+/*
+ * When using the out() function above, we often want to combine an error
+ * code for the operation run in the recursive context with that from
+ * out().
+ */
+static int combine_errors(int r1, int r2)
+{
+	return r1 ? r1 : r2;
+}
+
+static int recursing(struct sm_metadata *smm)
+{
+	return smm->recursion_count;
+}
+
+static void sm_metadata_destroy(struct dm_space_map *sm)
+{
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	kfree(smm);
+}
+
+static int sm_metadata_extend(struct dm_space_map *sm, dm_block_t extra_blocks)
+{
+	DMERR("doesn't support extend");
+	return -EINVAL;
+}
+
+static int sm_metadata_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count)
+{
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	*count = smm->ll.nr_blocks;
+
+	return 0;
+}
+
+static int sm_metadata_get_nr_free(struct dm_space_map *sm, dm_block_t *count)
+{
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	*count = smm->old_ll.nr_blocks - smm->old_ll.nr_allocated -
+		 smm->allocated_this_transaction;
+
+	return 0;
+}
+
+static int sm_metadata_get_count(struct dm_space_map *sm, dm_block_t b,
+				 uint32_t *result)
+{
+	int r, i;
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+	unsigned adjustment = 0;
+
+	/*
+	 * We may have some uncommitted adjustments to add.  This list
+	 * should always be really short.
+	 */
+	for (i = 0; i < smm->nr_uncommitted; i++) {
+		struct block_op *op = smm->uncommitted + i;
+
+		if (op->block != b)
+			continue;
+
+		switch (op->type) {
+		case BOP_INC:
+			adjustment++;
+			break;
+
+		case BOP_DEC:
+			adjustment--;
+			break;
+		}
+	}
+
+	r = sm_ll_lookup(&smm->ll, b, result);
+	if (r)
+		return r;
+
+	*result += adjustment;
+
+	return 0;
+}
+
+static int sm_metadata_count_is_more_than_one(struct dm_space_map *sm,
+					      dm_block_t b, int *result)
+{
+	int r, i, adjustment = 0;
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+	uint32_t rc;
+
+	/*
+	 * We may have some uncommitted adjustments to add.  This list
+	 * should always be really short.
+	 */
+	for (i = 0; i < smm->nr_uncommitted; i++) {
+		struct block_op *op = smm->uncommitted + i;
+
+		if (op->block != b)
+			continue;
+
+		switch (op->type) {
+		case BOP_INC:
+			adjustment++;
+			break;
+
+		case BOP_DEC:
+			adjustment--;
+			break;
+		}
+	}
+
+	if (adjustment > 1) {
+		*result = 1;
+		return 0;
+	}
+
+	r = sm_ll_lookup_bitmap(&smm->ll, b, &rc);
+	if (r)
+		return r;
+
+	if (rc == 3)
+		/*
+		 * We err on the side of caution, and always return true.
+		 */
+		*result = 1;
+	else
+		*result = rc + adjustment > 1;
+
+	return 0;
+}
+
+static int sm_metadata_set_count(struct dm_space_map *sm, dm_block_t b,
+				 uint32_t count)
+{
+	int r, r2;
+	enum allocation_event ev;
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	if (smm->recursion_count) {
+		DMERR("cannot recurse set_count()");
+		return -EINVAL;
+	}
+
+	in(smm);
+	r = sm_ll_insert(&smm->ll, b, count, &ev);
+	r2 = out(smm);
+
+	return combine_errors(r, r2);
+}
+
+static int sm_metadata_inc_block(struct dm_space_map *sm, dm_block_t b)
+{
+	int r, r2 = 0;
+	enum allocation_event ev;
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	if (recursing(smm))
+		r = add_bop(smm, BOP_INC, b);
+	else {
+		in(smm);
+		r = sm_ll_inc(&smm->ll, b, &ev);
+		r2 = out(smm);
+	}
+
+	return combine_errors(r, r2);
+}
+
+static int sm_metadata_dec_block(struct dm_space_map *sm, dm_block_t b)
+{
+	int r, r2 = 0;
+	enum allocation_event ev;
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	if (recursing(smm))
+		r = add_bop(smm, BOP_DEC, b);
+	else {
+		in(smm);
+		r = sm_ll_dec(&smm->ll, b, &ev);
+		r2 = out(smm);
+	}
+
+	return combine_errors(r, r2);
+}
+
+static int sm_metadata_new_block_(struct dm_space_map *sm, dm_block_t *b)
+{
+	int r, r2 = 0;
+	enum allocation_event ev;
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	r = sm_ll_find_free_block(&smm->old_ll, smm->begin, smm->old_ll.nr_blocks, b);
+	if (r)
+		return r;
+
+	smm->begin = *b + 1;
+
+	if (recursing(smm))
+		r = add_bop(smm, BOP_INC, *b);
+	else {
+		in(smm);
+		r = sm_ll_inc(&smm->ll, *b, &ev);
+		r2 = out(smm);
+	}
+
+	if (!r)
+		smm->allocated_this_transaction++;
+
+	return combine_errors(r, r2);
+}
+
+static int sm_metadata_new_block(struct dm_space_map *sm, dm_block_t *b)
+{
+	int r = sm_metadata_new_block_(sm, b);
+	if (r)
+		DMERR("out of metadata space");
+	return r;
+}
+
+static int sm_metadata_commit(struct dm_space_map *sm)
+{
+	int r;
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	r = sm_ll_commit(&smm->ll);
+	if (r)
+		return r;
+
+	memcpy(&smm->old_ll, &smm->ll, sizeof(smm->old_ll));
+	smm->begin = 0;
+	smm->allocated_this_transaction = 0;
+
+	return 0;
+}
+
+static int sm_metadata_root_size(struct dm_space_map *sm, size_t *result)
+{
+	*result = sizeof(struct disk_sm_root);
+
+	return 0;
+}
+
+static int sm_metadata_copy_root(struct dm_space_map *sm, void *where_le, size_t max)
+{
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+	struct disk_sm_root root_le;
+
+	root_le.nr_blocks = cpu_to_le64(smm->ll.nr_blocks);
+	root_le.nr_allocated = cpu_to_le64(smm->ll.nr_allocated);
+	root_le.bitmap_root = cpu_to_le64(smm->ll.bitmap_root);
+	root_le.ref_count_root = cpu_to_le64(smm->ll.ref_count_root);
+
+	if (max < sizeof(root_le))
+		return -ENOSPC;
+
+	memcpy(where_le, &root_le, sizeof(root_le));
+
+	return 0;
+}
+
+static struct dm_space_map ops = {
+	.destroy = sm_metadata_destroy,
+	.extend = sm_metadata_extend,
+	.get_nr_blocks = sm_metadata_get_nr_blocks,
+	.get_nr_free = sm_metadata_get_nr_free,
+	.get_count = sm_metadata_get_count,
+	.count_is_more_than_one = sm_metadata_count_is_more_than_one,
+	.set_count = sm_metadata_set_count,
+	.inc_block = sm_metadata_inc_block,
+	.dec_block = sm_metadata_dec_block,
+	.new_block = sm_metadata_new_block,
+	.commit = sm_metadata_commit,
+	.root_size = sm_metadata_root_size,
+	.copy_root = sm_metadata_copy_root
+};
+
+/*----------------------------------------------------------------*/
+
+/*
+ * When a new space map is created that manages its own space.  We use
+ * this tiny bootstrap allocator.
+ */
+static void sm_bootstrap_destroy(struct dm_space_map *sm)
+{
+}
+
+static int sm_bootstrap_extend(struct dm_space_map *sm, dm_block_t extra_blocks)
+{
+	DMERR("boostrap doesn't support extend");
+
+	return -EINVAL;
+}
+
+static int sm_bootstrap_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count)
+{
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	return smm->ll.nr_blocks;
+}
+
+static int sm_bootstrap_get_nr_free(struct dm_space_map *sm, dm_block_t *count)
+{
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	*count = smm->ll.nr_blocks - smm->begin;
+
+	return 0;
+}
+
+static int sm_bootstrap_get_count(struct dm_space_map *sm, dm_block_t b,
+				  uint32_t *result)
+{
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	return b < smm->begin ? 1 : 0;
+}
+
+static int sm_bootstrap_count_is_more_than_one(struct dm_space_map *sm,
+					       dm_block_t b, int *result)
+{
+	*result = 0;
+
+	return 0;
+}
+
+static int sm_bootstrap_set_count(struct dm_space_map *sm, dm_block_t b,
+				  uint32_t count)
+{
+	DMERR("boostrap doesn't support set_count");
+
+	return -EINVAL;
+}
+
+static int sm_bootstrap_new_block(struct dm_space_map *sm, dm_block_t *b)
+{
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	/*
+	 * We know the entire device is unused.
+	 */
+	if (smm->begin == smm->ll.nr_blocks)
+		return -ENOSPC;
+
+	*b = smm->begin++;
+
+	return 0;
+}
+
+static int sm_bootstrap_inc_block(struct dm_space_map *sm, dm_block_t b)
+{
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	return add_bop(smm, BOP_INC, b);
+}
+
+static int sm_bootstrap_dec_block(struct dm_space_map *sm, dm_block_t b)
+{
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	return add_bop(smm, BOP_DEC, b);
+}
+
+static int sm_bootstrap_commit(struct dm_space_map *sm)
+{
+	return 0;
+}
+
+static int sm_bootstrap_root_size(struct dm_space_map *sm, size_t *result)
+{
+	DMERR("boostrap doesn't support root_size");
+
+	return -EINVAL;
+}
+
+static int sm_bootstrap_copy_root(struct dm_space_map *sm, void *where,
+				  size_t max)
+{
+	DMERR("boostrap doesn't support copy_root");
+
+	return -EINVAL;
+}
+
+static struct dm_space_map bootstrap_ops = {
+	.destroy = sm_bootstrap_destroy,
+	.extend = sm_bootstrap_extend,
+	.get_nr_blocks = sm_bootstrap_get_nr_blocks,
+	.get_nr_free = sm_bootstrap_get_nr_free,
+	.get_count = sm_bootstrap_get_count,
+	.count_is_more_than_one = sm_bootstrap_count_is_more_than_one,
+	.set_count = sm_bootstrap_set_count,
+	.inc_block = sm_bootstrap_inc_block,
+	.dec_block = sm_bootstrap_dec_block,
+	.new_block = sm_bootstrap_new_block,
+	.commit = sm_bootstrap_commit,
+	.root_size = sm_bootstrap_root_size,
+	.copy_root = sm_bootstrap_copy_root
+};
+
+/*----------------------------------------------------------------*/
+
+struct dm_space_map *dm_sm_metadata_init(void)
+{
+	struct sm_metadata *smm;
+
+	smm = kmalloc(sizeof(*smm), GFP_KERNEL);
+	if (!smm)
+		return ERR_PTR(-ENOMEM);
+
+	memcpy(&smm->sm, &ops, sizeof(smm->sm));
+
+	return &smm->sm;
+}
+
+int dm_sm_metadata_create(struct dm_space_map *sm,
+			  struct dm_transaction_manager *tm,
+			  dm_block_t nr_blocks,
+			  dm_block_t superblock)
+{
+	int r;
+	dm_block_t i;
+	enum allocation_event ev;
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	smm->begin = superblock + 1;
+	smm->recursion_count = 0;
+	smm->allocated_this_transaction = 0;
+	smm->nr_uncommitted = 0;
+
+	memcpy(&smm->sm, &bootstrap_ops, sizeof(smm->sm));
+
+	r = sm_ll_new_metadata(&smm->ll, tm);
+	if (r)
+		return r;
+
+	r = sm_ll_extend(&smm->ll, nr_blocks);
+	if (r)
+		return r;
+
+	memcpy(&smm->sm, &ops, sizeof(smm->sm));
+
+	/*
+	 * Now we need to update the newly created data structures with the
+	 * allocated blocks that they were built from.
+	 */
+	for (i = superblock; !r && i < smm->begin; i++)
+		r = sm_ll_inc(&smm->ll, i, &ev);
+
+	if (r)
+		return r;
+
+	return sm_metadata_commit(sm);
+}
+
+int dm_sm_metadata_open(struct dm_space_map *sm,
+			struct dm_transaction_manager *tm,
+			void *root_le, size_t len)
+{
+	int r;
+	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+	r = sm_ll_open_metadata(&smm->ll, tm, root_le, len);
+	if (r)
+		return r;
+
+	smm->begin = 0;
+	smm->recursion_count = 0;
+	smm->allocated_this_transaction = 0;
+	smm->nr_uncommitted = 0;
+
+	memcpy(&smm->old_ll, &smm->ll, sizeof(smm->old_ll));
+	return 0;
+}
diff --git a/drivers/md/persistent-data/dm-space-map-metadata.h b/drivers/md/persistent-data/dm-space-map-metadata.h
new file mode 100644
index 0000000..39bba08
--- /dev/null
+++ b/drivers/md/persistent-data/dm-space-map-metadata.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef DM_SPACE_MAP_METADATA_H
+#define DM_SPACE_MAP_METADATA_H
+
+#include "dm-transaction-manager.h"
+
+/*
+ * Unfortunately we have to use two-phase construction due to the cycle
+ * between the tm and sm.
+ */
+struct dm_space_map *dm_sm_metadata_init(void);
+
+/*
+ * Create a fresh space map.
+ */
+int dm_sm_metadata_create(struct dm_space_map *sm,
+			  struct dm_transaction_manager *tm,
+			  dm_block_t nr_blocks,
+			  dm_block_t superblock);
+
+/*
+ * Open from a previously-recorded root.
+ */
+int dm_sm_metadata_open(struct dm_space_map *sm,
+			struct dm_transaction_manager *tm,
+			void *root_le, size_t len);
+
+#endif	/* DM_SPACE_MAP_METADATA_H */
diff --git a/drivers/md/persistent-data/dm-space-map.h b/drivers/md/persistent-data/dm-space-map.h
new file mode 100644
index 0000000..1cbfc6b
--- /dev/null
+++ b/drivers/md/persistent-data/dm-space-map.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef _LINUX_DM_SPACE_MAP_H
+#define _LINUX_DM_SPACE_MAP_H
+
+#include "dm-block-manager.h"
+
+/*
+ * struct dm_space_map keeps a record of how many times each block in a device
+ * is referenced.  It needs to be fixed on disk as part of the transaction.
+ */
+struct dm_space_map {
+	void (*destroy)(struct dm_space_map *sm);
+
+	/*
+	 * You must commit before allocating the newly added space.
+	 */
+	int (*extend)(struct dm_space_map *sm, dm_block_t extra_blocks);
+
+	/*
+	 * Extensions do not appear in this count until after commit has
+	 * been called.
+	 */
+	int (*get_nr_blocks)(struct dm_space_map *sm, dm_block_t *count);
+
+	/*
+	 * Space maps must never allocate a block from the previous
+	 * transaction, in case we need to rollback.  This complicates the
+	 * semantics of get_nr_free(), it should return the number of blocks
+	 * that are available for allocation _now_.  For instance you may
+	 * have blocks with a zero reference count that will not be
+	 * available for allocation until after the next commit.
+	 */
+	int (*get_nr_free)(struct dm_space_map *sm, dm_block_t *count);
+
+	int (*get_count)(struct dm_space_map *sm, dm_block_t b, uint32_t *result);
+	int (*count_is_more_than_one)(struct dm_space_map *sm, dm_block_t b,
+				      int *result);
+	int (*set_count)(struct dm_space_map *sm, dm_block_t b, uint32_t count);
+
+	int (*commit)(struct dm_space_map *sm);
+
+	int (*inc_block)(struct dm_space_map *sm, dm_block_t b);
+	int (*dec_block)(struct dm_space_map *sm, dm_block_t b);
+
+	/*
+	 * new_block will increment the returned block.
+	 */
+	int (*new_block)(struct dm_space_map *sm, dm_block_t *b);
+
+	/*
+	 * The root contains all the information needed to fix the space map.
+	 * Generally this info is small, so squirrel it away in a disk block
+	 * along with other info.
+	 */
+	int (*root_size)(struct dm_space_map *sm, size_t *result);
+	int (*copy_root)(struct dm_space_map *sm, void *copy_to_here_le, size_t len);
+};
+
+/*----------------------------------------------------------------*/
+
+static inline void dm_sm_destroy(struct dm_space_map *sm)
+{
+	sm->destroy(sm);
+}
+
+static inline int dm_sm_extend(struct dm_space_map *sm, dm_block_t extra_blocks)
+{
+	return sm->extend(sm, extra_blocks);
+}
+
+static inline int dm_sm_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count)
+{
+	return sm->get_nr_blocks(sm, count);
+}
+
+static inline int dm_sm_get_nr_free(struct dm_space_map *sm, dm_block_t *count)
+{
+	return sm->get_nr_free(sm, count);
+}
+
+static inline int dm_sm_get_count(struct dm_space_map *sm, dm_block_t b,
+				  uint32_t *result)
+{
+	return sm->get_count(sm, b, result);
+}
+
+static inline int dm_sm_count_is_more_than_one(struct dm_space_map *sm,
+					       dm_block_t b, int *result)
+{
+	return sm->count_is_more_than_one(sm, b, result);
+}
+
+static inline int dm_sm_set_count(struct dm_space_map *sm, dm_block_t b,
+				  uint32_t count)
+{
+	return sm->set_count(sm, b, count);
+}
+
+static inline int dm_sm_commit(struct dm_space_map *sm)
+{
+	return sm->commit(sm);
+}
+
+static inline int dm_sm_inc_block(struct dm_space_map *sm, dm_block_t b)
+{
+	return sm->inc_block(sm, b);
+}
+
+static inline int dm_sm_dec_block(struct dm_space_map *sm, dm_block_t b)
+{
+	return sm->dec_block(sm, b);
+}
+
+static inline int dm_sm_new_block(struct dm_space_map *sm, dm_block_t *b)
+{
+	return sm->new_block(sm, b);
+}
+
+static inline int dm_sm_root_size(struct dm_space_map *sm, size_t *result)
+{
+	return sm->root_size(sm, result);
+}
+
+static inline int dm_sm_copy_root(struct dm_space_map *sm, void *copy_to_here_le, size_t len)
+{
+	return sm->copy_root(sm, copy_to_here_le, len);
+}
+
+#endif	/* _LINUX_DM_SPACE_MAP_H */
diff --git a/drivers/md/persistent-data/dm-transaction-manager.c b/drivers/md/persistent-data/dm-transaction-manager.c
new file mode 100644
index 0000000..728e89a
--- /dev/null
+++ b/drivers/md/persistent-data/dm-transaction-manager.c
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+#include "dm-transaction-manager.h"
+#include "dm-space-map.h"
+#include "dm-space-map-checker.h"
+#include "dm-space-map-disk.h"
+#include "dm-space-map-metadata.h"
+#include "dm-persistent-data-internal.h"
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/device-mapper.h>
+
+#define DM_MSG_PREFIX "transaction manager"
+
+/*----------------------------------------------------------------*/
+
+struct shadow_info {
+	struct hlist_node hlist;
+	dm_block_t where;
+};
+
+/*
+ * It would be nice if we scaled with the size of transaction.
+ */
+#define HASH_SIZE 256
+#define HASH_MASK (HASH_SIZE - 1)
+
+struct dm_transaction_manager {
+	int is_clone;
+	struct dm_transaction_manager *real;
+
+	struct dm_block_manager *bm;
+	struct dm_space_map *sm;
+
+	spinlock_t lock;
+	struct hlist_head buckets[HASH_SIZE];
+};
+
+/*----------------------------------------------------------------*/
+
+static int is_shadow(struct dm_transaction_manager *tm, dm_block_t b)
+{
+	int r = 0;
+	unsigned bucket = dm_hash_block(b, HASH_MASK);
+	struct shadow_info *si;
+	struct hlist_node *n;
+
+	spin_lock(&tm->lock);
+	hlist_for_each_entry(si, n, tm->buckets + bucket, hlist)
+		if (si->where == b) {
+			r = 1;
+			break;
+		}
+	spin_unlock(&tm->lock);
+
+	return r;
+}
+
+/*
+ * This can silently fail if there's no memory.  We're ok with this since
+ * creating redundant shadows causes no harm.
+ */
+static void insert_shadow(struct dm_transaction_manager *tm, dm_block_t b)
+{
+	unsigned bucket;
+	struct shadow_info *si;
+
+	si = kmalloc(sizeof(*si), GFP_NOIO);
+	if (si) {
+		si->where = b;
+		bucket = dm_hash_block(b, HASH_MASK);
+		spin_lock(&tm->lock);
+		hlist_add_head(&si->hlist, tm->buckets + bucket);
+		spin_unlock(&tm->lock);
+	}
+}
+
+static void wipe_shadow_table(struct dm_transaction_manager *tm)
+{
+	struct shadow_info *si;
+	struct hlist_node *n, *tmp;
+	struct hlist_head *bucket;
+	int i;
+
+	spin_lock(&tm->lock);
+	for (i = 0; i < HASH_SIZE; i++) {
+		bucket = tm->buckets + i;
+		hlist_for_each_entry_safe(si, n, tmp, bucket, hlist)
+			kfree(si);
+
+		INIT_HLIST_HEAD(bucket);
+	}
+
+	spin_unlock(&tm->lock);
+}
+
+/*----------------------------------------------------------------*/
+
+static struct dm_transaction_manager *dm_tm_create(struct dm_block_manager *bm,
+						   struct dm_space_map *sm)
+{
+	int i;
+	struct dm_transaction_manager *tm;
+
+	tm = kmalloc(sizeof(*tm), GFP_KERNEL);
+	if (!tm)
+		return ERR_PTR(-ENOMEM);
+
+	tm->is_clone = 0;
+	tm->real = NULL;
+	tm->bm = bm;
+	tm->sm = sm;
+
+	spin_lock_init(&tm->lock);
+	for (i = 0; i < HASH_SIZE; i++)
+		INIT_HLIST_HEAD(tm->buckets + i);
+
+	return tm;
+}
+
+struct dm_transaction_manager *dm_tm_create_non_blocking_clone(struct dm_transaction_manager *real)
+{
+	struct dm_transaction_manager *tm;
+
+	tm = kmalloc(sizeof(*tm), GFP_KERNEL);
+	if (tm) {
+		tm->is_clone = 1;
+		tm->real = real;
+	}
+
+	return tm;
+}
+EXPORT_SYMBOL_GPL(dm_tm_create_non_blocking_clone);
+
+void dm_tm_destroy(struct dm_transaction_manager *tm)
+{
+	kfree(tm);
+}
+EXPORT_SYMBOL_GPL(dm_tm_destroy);
+
+int dm_tm_pre_commit(struct dm_transaction_manager *tm)
+{
+	int r;
+
+	if (tm->is_clone)
+		return -EWOULDBLOCK;
+
+	r = dm_sm_commit(tm->sm);
+	if (r < 0)
+		return r;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dm_tm_pre_commit);
+
+int dm_tm_commit(struct dm_transaction_manager *tm, struct dm_block *root)
+{
+	if (tm->is_clone)
+		return -EWOULDBLOCK;
+
+	wipe_shadow_table(tm);
+
+	return dm_bm_flush_and_unlock(tm->bm, root);
+}
+EXPORT_SYMBOL_GPL(dm_tm_commit);
+
+int dm_tm_new_block(struct dm_transaction_manager *tm,
+		    struct dm_block_validator *v,
+		    struct dm_block **result)
+{
+	int r;
+	dm_block_t new_block;
+
+	if (tm->is_clone)
+		return -EWOULDBLOCK;
+
+	r = dm_sm_new_block(tm->sm, &new_block);
+	if (r < 0)
+		return r;
+
+	r = dm_bm_write_lock_zero(tm->bm, new_block, v, result);
+	if (r < 0) {
+		dm_sm_dec_block(tm->sm, new_block);
+		return r;
+	}
+
+	/*
+	 * New blocks count as shadows in that they don't need to be
+	 * shadowed again.
+	 */
+	insert_shadow(tm, new_block);
+
+	return 0;
+}
+
+static int __shadow_block(struct dm_transaction_manager *tm, dm_block_t orig,
+			  struct dm_block_validator *v,
+			  struct dm_block **result)
+{
+	int r;
+	dm_block_t new;
+	struct dm_block *orig_block;
+
+	r = dm_sm_new_block(tm->sm, &new);
+	if (r < 0)
+		return r;
+
+	r = dm_sm_dec_block(tm->sm, orig);
+	if (r < 0)
+		return r;
+
+	r = dm_bm_read_lock(tm->bm, orig, v, &orig_block);
+	if (r < 0)
+		return r;
+
+	r = dm_bm_unlock_move(orig_block, new);
+	if (r < 0) {
+		dm_bm_unlock(orig_block);
+		return r;
+	}
+
+	return dm_bm_write_lock(tm->bm, new, v, result);
+}
+
+int dm_tm_shadow_block(struct dm_transaction_manager *tm, dm_block_t orig,
+		       struct dm_block_validator *v, struct dm_block **result,
+		       int *inc_children)
+{
+	int r;
+
+	if (tm->is_clone)
+		return -EWOULDBLOCK;
+
+	r = dm_sm_count_is_more_than_one(tm->sm, orig, inc_children);
+	if (r < 0)
+		return r;
+
+	if (is_shadow(tm, orig) && !*inc_children)
+		return dm_bm_write_lock(tm->bm, orig, v, result);
+
+	r = __shadow_block(tm, orig, v, result);
+	if (r < 0)
+		return r;
+	insert_shadow(tm, dm_block_location(*result));
+
+	return r;
+}
+
+int dm_tm_read_lock(struct dm_transaction_manager *tm, dm_block_t b,
+		    struct dm_block_validator *v,
+		    struct dm_block **blk)
+{
+	if (tm->is_clone)
+		return dm_bm_read_try_lock(tm->real->bm, b, v, blk);
+
+	return dm_bm_read_lock(tm->bm, b, v, blk);
+}
+
+int dm_tm_unlock(struct dm_transaction_manager *tm, struct dm_block *b)
+{
+	return dm_bm_unlock(b);
+}
+EXPORT_SYMBOL_GPL(dm_tm_unlock);
+
+void dm_tm_inc(struct dm_transaction_manager *tm, dm_block_t b)
+{
+	/*
+	 * The non-blocking clone doesn't support this.
+	 */
+	BUG_ON(tm->is_clone);
+
+	dm_sm_inc_block(tm->sm, b);
+}
+EXPORT_SYMBOL_GPL(dm_tm_inc);
+
+void dm_tm_dec(struct dm_transaction_manager *tm, dm_block_t b)
+{
+	/*
+	 * The non-blocking clone doesn't support this.
+	 */
+	BUG_ON(tm->is_clone);
+
+	dm_sm_dec_block(tm->sm, b);
+}
+EXPORT_SYMBOL_GPL(dm_tm_dec);
+
+int dm_tm_ref(struct dm_transaction_manager *tm, dm_block_t b,
+	      uint32_t *result)
+{
+	if (tm->is_clone)
+		return -EWOULDBLOCK;
+
+	return dm_sm_get_count(tm->sm, b, result);
+}
+
+struct dm_block_manager *dm_tm_get_bm(struct dm_transaction_manager *tm)
+{
+	return tm->bm;
+}
+
+/*----------------------------------------------------------------*/
+
+static int dm_tm_create_internal(struct dm_block_manager *bm,
+				 dm_block_t sb_location,
+				 struct dm_block_validator *sb_validator,
+				 size_t root_offset, size_t root_max_len,
+				 struct dm_transaction_manager **tm,
+				 struct dm_space_map **sm,
+				 struct dm_block **sblock,
+				 int create)
+{
+	int r;
+	struct dm_space_map *inner;
+
+	inner = dm_sm_metadata_init();
+	if (IS_ERR(inner))
+		return PTR_ERR(inner);
+
+	*tm = dm_tm_create(bm, inner);
+	if (IS_ERR(*tm)) {
+		dm_sm_destroy(inner);
+		return PTR_ERR(*tm);
+	}
+
+	if (create) {
+		r = dm_bm_write_lock_zero(dm_tm_get_bm(*tm), sb_location,
+					  sb_validator, sblock);
+		if (r < 0) {
+			DMERR("couldn't lock superblock");
+			goto bad1;
+		}
+
+		r = dm_sm_metadata_create(inner, *tm, dm_bm_nr_blocks(bm),
+					  sb_location);
+		if (r) {
+			DMERR("couldn't create metadata space map");
+			goto bad2;
+		}
+
+		*sm = dm_sm_checker_create(inner);
+		if (!*sm)
+			goto bad2;
+
+	} else {
+		r = dm_bm_write_lock(dm_tm_get_bm(*tm), sb_location,
+				     sb_validator, sblock);
+		if (r < 0) {
+			DMERR("couldn't lock superblock");
+			goto bad1;
+		}
+
+		r = dm_sm_metadata_open(inner, *tm,
+					dm_block_data(*sblock) + root_offset,
+					root_max_len);
+		if (r) {
+			DMERR("couldn't open metadata space map");
+			goto bad2;
+		}
+
+		*sm = dm_sm_checker_create(inner);
+		if (!*sm)
+			goto bad2;
+	}
+
+	return 0;
+
+bad2:
+	dm_tm_unlock(*tm, *sblock);
+bad1:
+	dm_tm_destroy(*tm);
+	dm_sm_destroy(inner);
+	return r;
+}
+
+int dm_tm_create_with_sm(struct dm_block_manager *bm, dm_block_t sb_location,
+			 struct dm_block_validator *sb_validator,
+			 struct dm_transaction_manager **tm,
+			 struct dm_space_map **sm, struct dm_block **sblock)
+{
+	return dm_tm_create_internal(bm, sb_location, sb_validator,
+				     0, 0, tm, sm, sblock, 1);
+}
+EXPORT_SYMBOL_GPL(dm_tm_create_with_sm);
+
+int dm_tm_open_with_sm(struct dm_block_manager *bm, dm_block_t sb_location,
+		       struct dm_block_validator *sb_validator,
+		       size_t root_offset, size_t root_max_len,
+		       struct dm_transaction_manager **tm,
+		       struct dm_space_map **sm, struct dm_block **sblock)
+{
+	return dm_tm_create_internal(bm, sb_location, sb_validator, root_offset,
+				     root_max_len, tm, sm, sblock, 0);
+}
+EXPORT_SYMBOL_GPL(dm_tm_open_with_sm);
+
+/*----------------------------------------------------------------*/
diff --git a/drivers/md/persistent-data/dm-transaction-manager.h b/drivers/md/persistent-data/dm-transaction-manager.h
new file mode 100644
index 0000000..6da7848
--- /dev/null
+++ b/drivers/md/persistent-data/dm-transaction-manager.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef _LINUX_DM_TRANSACTION_MANAGER_H
+#define _LINUX_DM_TRANSACTION_MANAGER_H
+
+#include "dm-block-manager.h"
+
+struct dm_transaction_manager;
+struct dm_space_map;
+
+/*----------------------------------------------------------------*/
+
+/*
+ * This manages the scope of a transaction.  It also enforces immutability
+ * of the on-disk data structures by limiting access to writeable blocks.
+ *
+ * Clients should not fiddle with the block manager directly.
+ */
+
+void dm_tm_destroy(struct dm_transaction_manager *tm);
+
+/*
+ * The non-blocking version of a transaction manager is intended for use in
+ * fast path code that needs to do lookups e.g. a dm mapping function.
+ * You create the non-blocking variant from a normal tm.  The interface is
+ * the same, except that most functions will just return -EWOULDBLOCK.
+ * Methods that return void yet may block should not be called on a clone
+ * viz. dm_tm_inc, dm_tm_dec.  Call dm_tm_destroy() as you would with a normal
+ * tm when you've finished with it.  You may not destroy the original prior
+ * to clones.
+ */
+struct dm_transaction_manager *dm_tm_create_non_blocking_clone(struct dm_transaction_manager *real);
+
+/*
+ * We use a 2-phase commit here.
+ *
+ * i) In the first phase the block manager is told to start flushing, and
+ * the changes to the space map are written to disk.  You should interrogate
+ * your particular space map to get detail of its root node etc. to be
+ * included in your superblock.
+ *
+ * ii) @root will be committed last.  You shouldn't use more than the
+ * first 512 bytes of @root if you wish the transaction to survive a power
+ * failure.  You *must* have a write lock held on @root for both stage (i)
+ * and (ii).  The commit will drop the write lock.
+ */
+int dm_tm_pre_commit(struct dm_transaction_manager *tm);
+int dm_tm_commit(struct dm_transaction_manager *tm, struct dm_block *root);
+
+/*
+ * These methods are the only way to get hold of a writeable block.
+ */
+
+/*
+ * dm_tm_new_block() is pretty self-explanatory.  Make sure you do actually
+ * write to the whole of @data before you unlock, otherwise you could get
+ * a data leak.  (The other option is for tm_new_block() to zero new blocks
+ * before handing them out, which will be redundant in most, if not all,
+ * cases).
+ * Zeroes the new block and returns with write lock held.
+ */
+int dm_tm_new_block(struct dm_transaction_manager *tm,
+		    struct dm_block_validator *v,
+		    struct dm_block **result);
+
+/*
+ * dm_tm_shadow_block() allocates a new block and copies the data from @orig
+ * to it.  It then decrements the reference count on original block.  Use
+ * this to update the contents of a block in a data structure, don't
+ * confuse this with a clone - you shouldn't access the orig block after
+ * this operation.  Because the tm knows the scope of the transaction it
+ * can optimise requests for a shadow of a shadow to a no-op.  Don't forget
+ * to unlock when you've finished with the shadow.
+ *
+ * The @inc_children flag is used to tell the caller whether it needs to
+ * adjust reference counts for children.  (Data in the block may refer to
+ * other blocks.)
+ *
+ * Shadowing implicitly drops a reference on @orig so you must not have
+ * it locked when you call this.
+ */
+int dm_tm_shadow_block(struct dm_transaction_manager *tm, dm_block_t orig,
+		       struct dm_block_validator *v,
+		       struct dm_block **result, int *inc_children);
+
+/*
+ * Read access.  You can lock any block you want.  If there's a write lock
+ * on it outstanding then it'll block.
+ */
+int dm_tm_read_lock(struct dm_transaction_manager *tm, dm_block_t b,
+		    struct dm_block_validator *v,
+		    struct dm_block **result);
+
+int dm_tm_unlock(struct dm_transaction_manager *tm, struct dm_block *b);
+
+/*
+ * Functions for altering the reference count of a block directly.
+ */
+void dm_tm_inc(struct dm_transaction_manager *tm, dm_block_t b);
+
+void dm_tm_dec(struct dm_transaction_manager *tm, dm_block_t b);
+
+int dm_tm_ref(struct dm_transaction_manager *tm, dm_block_t b,
+	      uint32_t *result);
+
+struct dm_block_manager *dm_tm_get_bm(struct dm_transaction_manager *tm);
+
+/*
+ * A little utility that ties the knot by producing a transaction manager
+ * that has a space map managed by the transaction manager...
+ *
+ * Returns a tm that has an open transaction to write the new disk sm.
+ * Caller should store the new sm root and commit.
+ */
+int dm_tm_create_with_sm(struct dm_block_manager *bm, dm_block_t sb_location,
+			 struct dm_block_validator *sb_validator,
+			 struct dm_transaction_manager **tm,
+			 struct dm_space_map **sm, struct dm_block **sblock);
+
+int dm_tm_open_with_sm(struct dm_block_manager *bm, dm_block_t sb_location,
+		       struct dm_block_validator *sb_validator,
+		       size_t root_offset, size_t root_max_len,
+		       struct dm_transaction_manager **tm,
+		       struct dm_space_map **sm, struct dm_block **sblock);
+
+#endif	/* _LINUX_DM_TRANSACTION_MANAGER_H */
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 50d5f27..d593878 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -63,7 +63,7 @@ config AD525X_DPOT_SPI
 
 config ATMEL_PWM
 	tristate "Atmel AT32/AT91 PWM support"
-	depends on AVR32 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91CAP9
+	depends on HAVE_CLK
 	help
 	  This option enables device driver support for the PWM channels
 	  on certain Atmel processors.  Pulse Width Modulation is used for
diff --git a/drivers/misc/vmw_balloon.c b/drivers/misc/vmw_balloon.c
index 053d36c..cd41d40 100644
--- a/drivers/misc/vmw_balloon.c
+++ b/drivers/misc/vmw_balloon.c
@@ -151,7 +151,7 @@ MODULE_LICENSE("GPL");
 struct vmballoon_stats {
 	unsigned int timer;
 
-	/* allocation statustics */
+	/* allocation statistics */
 	unsigned int alloc;
 	unsigned int alloc_fail;
 	unsigned int sleep_alloc;
@@ -412,6 +412,7 @@ static int vmballoon_reserve_page(struct vmballoon *b, bool can_sleep)
 	gfp_t flags;
 	unsigned int hv_status;
 	bool locked = false;
+	flags = can_sleep ? VMW_PAGE_ALLOC_CANSLEEP : VMW_PAGE_ALLOC_NOSLEEP;
 
 	do {
 		if (!can_sleep)
@@ -419,7 +420,6 @@ static int vmballoon_reserve_page(struct vmballoon *b, bool can_sleep)
 		else
 			STATS_INC(b->stats.sleep_alloc);
 
-		flags = can_sleep ? VMW_PAGE_ALLOC_CANSLEEP : VMW_PAGE_ALLOC_NOSLEEP;
 		page = alloc_page(flags);
 		if (!page) {
 			if (!can_sleep)
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
index 0076c74..64a8325 100644
--- a/drivers/mmc/host/davinci_mmc.c
+++ b/drivers/mmc/host/davinci_mmc.c
@@ -807,12 +807,25 @@ static void calculate_clk_divider(struct mmc_host *mmc, struct mmc_ios *ios)
 static void mmc_davinci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct mmc_davinci_host *host = mmc_priv(mmc);
+	struct platform_device *pdev = to_platform_device(mmc->parent);
+	struct davinci_mmc_config *config = pdev->dev.platform_data;
 
 	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);
 
+	switch (ios->power_mode) {
+	case MMC_POWER_OFF:
+		if (config && config->set_power)
+			config->set_power(pdev->id, false);
+		break;
+	case MMC_POWER_UP:
+		if (config && config->set_power)
+			config->set_power(pdev->id, true);
+		break;
+	}
+
 	switch (ios->bus_width) {
 	case MMC_BUS_WIDTH_8:
 		dev_dbg(mmc_dev(host->mmc), "Enabling 8 bit mode\n");
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c
index f48743d..325ea61 100644
--- a/drivers/mmc/host/mxcmmc.c
+++ b/drivers/mmc/host/mxcmmc.c
@@ -40,6 +40,7 @@
 #include <mach/mmc.h>
 
 #include <mach/dma.h>
+#include <mach/hardware.h>
 
 #define DRIVER_NAME "mxc-mmc"
 
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index f1af222..61086ea 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -1144,7 +1144,7 @@ static void mtdchar_notify_remove(struct mtd_info *mtd)
 
 	if (mtd_ino) {
 		/* Destroy the inode if it exists */
-		mtd_ino->i_nlink = 0;
+		clear_nlink(mtd_ino);
 		iput(mtd_ino);
 	}
 }
diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c
index 1ad1f60..869a2c2 100644
--- a/drivers/net/ethernet/mellanox/mlx4/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/eq.c
@@ -484,7 +484,7 @@ static void mlx4_free_eq(struct mlx4_dev *dev,
 
 	mlx4_mtt_cleanup(dev, &eq->mtt);
 	for (i = 0; i < npages; ++i)
-		pci_free_consistent(dev->pdev, PAGE_SIZE,
+		dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
 				    eq->page_list[i].buf,
 				    eq->page_list[i].map);
 
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c
index ed452dd..abdfbac 100644
--- a/drivers/net/ethernet/mellanox/mlx4/fw.c
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.c
@@ -205,6 +205,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 #define QUERY_DEV_CAP_MAX_MCG_OFFSET		0x63
 #define QUERY_DEV_CAP_RSVD_PD_OFFSET		0x64
 #define QUERY_DEV_CAP_MAX_PD_OFFSET		0x65
+#define QUERY_DEV_CAP_RSVD_XRC_OFFSET		0x66
+#define QUERY_DEV_CAP_MAX_XRC_OFFSET		0x67
 #define QUERY_DEV_CAP_MAX_COUNTERS_OFFSET	0x68
 #define QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET	0x80
 #define QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET	0x82
@@ -319,6 +321,10 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 	dev_cap->reserved_pds = field >> 4;
 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PD_OFFSET);
 	dev_cap->max_pds = 1 << (field & 0x3f);
+	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_XRC_OFFSET);
+	dev_cap->reserved_xrcds = field >> 4;
+	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PD_OFFSET);
+	dev_cap->max_xrcds = 1 << (field & 0x1f);
 
 	MLX4_GET(size, outbox, QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET);
 	dev_cap->rdmarc_entry_sz = size;
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.h b/drivers/net/ethernet/mellanox/mlx4/fw.h
index 1e8ecc3..bf5ec22 100644
--- a/drivers/net/ethernet/mellanox/mlx4/fw.h
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.h
@@ -93,6 +93,8 @@ struct mlx4_dev_cap {
 	int max_mcgs;
 	int reserved_pds;
 	int max_pds;
+	int reserved_xrcds;
+	int max_xrcds;
 	int qpc_entry_sz;
 	int rdmarc_entry_sz;
 	int altc_entry_sz;
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index f0ee35d..94bbc85 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -96,6 +96,8 @@ MODULE_PARM_DESC(log_num_mac, "Log2 max number of MACs per ETH port (1-7)");
 static int log_num_vlan;
 module_param_named(log_num_vlan, log_num_vlan, int, 0444);
 MODULE_PARM_DESC(log_num_vlan, "Log2 max number of VLANs per ETH port (0-7)");
+/* Log2 max number of VLANs per ETH port (0-7) */
+#define MLX4_LOG_NUM_VLANS 7
 
 static int use_prio;
 module_param_named(use_prio, use_prio, bool, 0444);
@@ -220,6 +222,10 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 	dev->caps.reserved_mrws	     = dev_cap->reserved_mrws;
 	dev->caps.reserved_uars	     = dev_cap->reserved_uars;
 	dev->caps.reserved_pds	     = dev_cap->reserved_pds;
+	dev->caps.reserved_xrcds     = (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) ?
+					dev_cap->reserved_xrcds : 0;
+	dev->caps.max_xrcds          = (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) ?
+					dev_cap->max_xrcds : 0;
 	dev->caps.mtt_entry_sz	     = dev->caps.mtts_per_seg * dev_cap->mtt_entry_sz;
 	dev->caps.max_msg_sz         = dev_cap->max_msg_sz;
 	dev->caps.page_size_cap	     = ~(u32) (dev_cap->min_page_sz - 1);
@@ -230,7 +236,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 	dev->caps.max_gso_sz	     = dev_cap->max_gso_sz;
 
 	dev->caps.log_num_macs  = log_num_mac;
-	dev->caps.log_num_vlans = log_num_vlan;
+	dev->caps.log_num_vlans = MLX4_LOG_NUM_VLANS;
 	dev->caps.log_num_prios = use_prio ? 3 : 0;
 
 	for (i = 1; i <= dev->caps.num_ports; ++i) {
@@ -912,11 +918,18 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
 		goto err_kar_unmap;
 	}
 
+	err = mlx4_init_xrcd_table(dev);
+	if (err) {
+		mlx4_err(dev, "Failed to initialize "
+			 "reliable connection domain table, aborting.\n");
+		goto err_pd_table_free;
+	}
+
 	err = mlx4_init_mr_table(dev);
 	if (err) {
 		mlx4_err(dev, "Failed to initialize "
 			 "memory region table, aborting.\n");
-		goto err_pd_table_free;
+		goto err_xrcd_table_free;
 	}
 
 	err = mlx4_init_eq_table(dev);
@@ -998,6 +1011,13 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
 				  "ib capabilities (%d). Continuing with "
 				  "caps = 0\n", port, err);
 		dev->caps.ib_port_def_cap[port] = ib_port_default_caps;
+
+		err = mlx4_check_ext_port_caps(dev, port);
+		if (err)
+			mlx4_warn(dev, "failed to get port %d extended "
+				  "port capabilities support info (%d)."
+				  " Assuming not supported\n", port, err);
+
 		err = mlx4_SET_PORT(dev, port);
 		if (err) {
 			mlx4_err(dev, "Failed to set port %d, aborting\n",
@@ -1033,6 +1053,9 @@ err_eq_table_free:
 err_mr_table_free:
 	mlx4_cleanup_mr_table(dev);
 
+err_xrcd_table_free:
+	mlx4_cleanup_xrcd_table(dev);
+
 err_pd_table_free:
 	mlx4_cleanup_pd_table(dev);
 
@@ -1355,6 +1378,7 @@ err_port:
 	mlx4_cmd_use_polling(dev);
 	mlx4_cleanup_eq_table(dev);
 	mlx4_cleanup_mr_table(dev);
+	mlx4_cleanup_xrcd_table(dev);
 	mlx4_cleanup_pd_table(dev);
 	mlx4_cleanup_uar_table(dev);
 
@@ -1416,6 +1440,7 @@ static void mlx4_remove_one(struct pci_dev *pdev)
 		mlx4_cmd_use_polling(dev);
 		mlx4_cleanup_eq_table(dev);
 		mlx4_cleanup_mr_table(dev);
+		mlx4_cleanup_xrcd_table(dev);
 		mlx4_cleanup_pd_table(dev);
 
 		iounmap(priv->kar);
@@ -1489,10 +1514,9 @@ static int __init mlx4_verify_params(void)
 		return -1;
 	}
 
-	if ((log_num_vlan < 0) || (log_num_vlan > 7)) {
-		pr_warning("mlx4_core: bad num_vlan: %d\n", log_num_vlan);
-		return -1;
-	}
+	if (log_num_vlan != 0)
+		pr_warning("mlx4_core: log_num_vlan - obsolete module param, using %d\n",
+			   MLX4_LOG_NUM_VLANS);
 
 	if ((log_mtts_per_seg < 1) || (log_mtts_per_seg > 7)) {
 		pr_warning("mlx4_core: bad log_mtts_per_seg: %d\n", log_mtts_per_seg);
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
index a2fcd84..5dfa68f 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
@@ -335,6 +335,7 @@ struct mlx4_priv {
 	struct mlx4_cmd		cmd;
 
 	struct mlx4_bitmap	pd_bitmap;
+	struct mlx4_bitmap	xrcd_bitmap;
 	struct mlx4_uar_table	uar_table;
 	struct mlx4_mr_table	mr_table;
 	struct mlx4_cq_table	cq_table;
@@ -384,6 +385,7 @@ int mlx4_alloc_eq_table(struct mlx4_dev *dev);
 void mlx4_free_eq_table(struct mlx4_dev *dev);
 
 int mlx4_init_pd_table(struct mlx4_dev *dev);
+int mlx4_init_xrcd_table(struct mlx4_dev *dev);
 int mlx4_init_uar_table(struct mlx4_dev *dev);
 int mlx4_init_mr_table(struct mlx4_dev *dev);
 int mlx4_init_eq_table(struct mlx4_dev *dev);
@@ -393,6 +395,7 @@ int mlx4_init_srq_table(struct mlx4_dev *dev);
 int mlx4_init_mcg_table(struct mlx4_dev *dev);
 
 void mlx4_cleanup_pd_table(struct mlx4_dev *dev);
+void mlx4_cleanup_xrcd_table(struct mlx4_dev *dev);
 void mlx4_cleanup_uar_table(struct mlx4_dev *dev);
 void mlx4_cleanup_mr_table(struct mlx4_dev *dev);
 void mlx4_cleanup_eq_table(struct mlx4_dev *dev);
@@ -450,6 +453,7 @@ void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table);
 
 int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port);
 int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps);
+int mlx4_check_ext_port_caps(struct mlx4_dev *dev, u8 port);
 
 int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
 			  enum mlx4_protocol prot, enum mlx4_steer_type steer);
diff --git a/drivers/net/ethernet/mellanox/mlx4/mr.c b/drivers/net/ethernet/mellanox/mlx4/mr.c
index 9c188bd..ab639cf 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mr.c
+++ b/drivers/net/ethernet/mellanox/mlx4/mr.c
@@ -139,7 +139,7 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order)
 
 	buddy->bits = kzalloc((buddy->max_order + 1) * sizeof (long *),
 			      GFP_KERNEL);
-	buddy->num_free = kzalloc((buddy->max_order + 1) * sizeof (int *),
+	buddy->num_free = kcalloc((buddy->max_order + 1), sizeof *buddy->num_free,
 				  GFP_KERNEL);
 	if (!buddy->bits || !buddy->num_free)
 		goto err_out;
diff --git a/drivers/net/ethernet/mellanox/mlx4/pd.c b/drivers/net/ethernet/mellanox/mlx4/pd.c
index 1286b88..3736163 100644
--- a/drivers/net/ethernet/mellanox/mlx4/pd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/pd.c
@@ -61,6 +61,24 @@ void mlx4_pd_free(struct mlx4_dev *dev, u32 pdn)
 }
 EXPORT_SYMBOL_GPL(mlx4_pd_free);
 
+int mlx4_xrcd_alloc(struct mlx4_dev *dev, u32 *xrcdn)
+{
+	struct mlx4_priv *priv = mlx4_priv(dev);
+
+	*xrcdn = mlx4_bitmap_alloc(&priv->xrcd_bitmap);
+	if (*xrcdn == -1)
+		return -ENOMEM;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mlx4_xrcd_alloc);
+
+void mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn)
+{
+	mlx4_bitmap_free(&mlx4_priv(dev)->xrcd_bitmap, xrcdn);
+}
+EXPORT_SYMBOL_GPL(mlx4_xrcd_free);
+
 int mlx4_init_pd_table(struct mlx4_dev *dev)
 {
 	struct mlx4_priv *priv = mlx4_priv(dev);
@@ -74,6 +92,18 @@ void mlx4_cleanup_pd_table(struct mlx4_dev *dev)
 	mlx4_bitmap_cleanup(&mlx4_priv(dev)->pd_bitmap);
 }
 
+int mlx4_init_xrcd_table(struct mlx4_dev *dev)
+{
+	struct mlx4_priv *priv = mlx4_priv(dev);
+
+	return mlx4_bitmap_init(&priv->xrcd_bitmap, (1 << 16),
+				(1 << 16) - 1, dev->caps.reserved_xrcds + 1, 0);
+}
+
+void mlx4_cleanup_xrcd_table(struct mlx4_dev *dev)
+{
+	mlx4_bitmap_cleanup(&mlx4_priv(dev)->xrcd_bitmap);
+}
 
 int mlx4_uar_alloc(struct mlx4_dev *dev, struct mlx4_uar *uar)
 {
diff --git a/drivers/net/ethernet/mellanox/mlx4/port.c b/drivers/net/ethernet/mellanox/mlx4/port.c
index 163a314..a44f080 100644
--- a/drivers/net/ethernet/mellanox/mlx4/port.c
+++ b/drivers/net/ethernet/mellanox/mlx4/port.c
@@ -148,22 +148,26 @@ int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn, u8 wrap)
 
 	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) {
 		err = mlx4_uc_steer_add(dev, port, mac, qpn, 1);
-		if (!err) {
-			entry = kmalloc(sizeof *entry, GFP_KERNEL);
-			if (!entry) {
-				mlx4_uc_steer_release(dev, port, mac, *qpn, 1);
-				return -ENOMEM;
-			}
-			entry->mac = mac;
-			err = radix_tree_insert(&info->mac_tree, *qpn, entry);
-			if (err) {
-				mlx4_uc_steer_release(dev, port, mac, *qpn, 1);
-				return err;
-			}
-		} else
+		if (err)
 			return err;
+
+		entry = kmalloc(sizeof *entry, GFP_KERNEL);
+		if (!entry) {
+			mlx4_uc_steer_release(dev, port, mac, *qpn, 1);
+			return -ENOMEM;
+		}
+
+		entry->mac = mac;
+		err = radix_tree_insert(&info->mac_tree, *qpn, entry);
+		if (err) {
+			kfree(entry);
+			mlx4_uc_steer_release(dev, port, mac, *qpn, 1);
+			return err;
+		}
 	}
+
 	mlx4_dbg(dev, "Registering MAC: 0x%llx\n", (unsigned long long) mac);
+
 	mutex_lock(&table->mutex);
 	for (i = 0; i < MLX4_MAX_MAC_NUM - 1; i++) {
 		if (free < 0 && !table->refs[i]) {
@@ -465,6 +469,48 @@ int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps)
 	return err;
 }
 
+int mlx4_check_ext_port_caps(struct mlx4_dev *dev, u8 port)
+{
+	struct mlx4_cmd_mailbox *inmailbox, *outmailbox;
+	u8 *inbuf, *outbuf;
+	int err, packet_error;
+
+	inmailbox = mlx4_alloc_cmd_mailbox(dev);
+	if (IS_ERR(inmailbox))
+		return PTR_ERR(inmailbox);
+
+	outmailbox = mlx4_alloc_cmd_mailbox(dev);
+	if (IS_ERR(outmailbox)) {
+		mlx4_free_cmd_mailbox(dev, inmailbox);
+		return PTR_ERR(outmailbox);
+	}
+
+	inbuf = inmailbox->buf;
+	outbuf = outmailbox->buf;
+	memset(inbuf, 0, 256);
+	memset(outbuf, 0, 256);
+	inbuf[0] = 1;
+	inbuf[1] = 1;
+	inbuf[2] = 1;
+	inbuf[3] = 1;
+
+	*(__be16 *) (&inbuf[16]) = MLX4_ATTR_EXTENDED_PORT_INFO;
+	*(__be32 *) (&inbuf[20]) = cpu_to_be32(port);
+
+	err = mlx4_cmd_box(dev, inmailbox->dma, outmailbox->dma, port, 3,
+			   MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C);
+
+	packet_error = be16_to_cpu(*(__be16 *) (outbuf + 4));
+
+	dev->caps.ext_port_cap[port] = (!err && !packet_error) ?
+				       MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO
+				       : 0;
+
+	mlx4_free_cmd_mailbox(dev, inmailbox);
+	mlx4_free_cmd_mailbox(dev, outmailbox);
+	return err;
+}
+
 int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port)
 {
 	struct mlx4_cmd_mailbox *mailbox;
diff --git a/drivers/net/ethernet/mellanox/mlx4/qp.c b/drivers/net/ethernet/mellanox/mlx4/qp.c
index ec9350e..51c5389 100644
--- a/drivers/net/ethernet/mellanox/mlx4/qp.c
+++ b/drivers/net/ethernet/mellanox/mlx4/qp.c
@@ -280,6 +280,9 @@ int mlx4_init_qp_table(struct mlx4_dev *dev)
 	 * We reserve 2 extra QPs per port for the special QPs.  The
 	 * block of special QPs must be aligned to a multiple of 8, so
 	 * round up.
+	 *
+	 * We also reserve the MSB of the 24-bit QP number to indicate
+	 * that a QP is an XRC QP.
 	 */
 	dev->caps.sqp_start =
 		ALIGN(dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW], 8);
diff --git a/drivers/net/ethernet/mellanox/mlx4/srq.c b/drivers/net/ethernet/mellanox/mlx4/srq.c
index 3b07b80..a20b141 100644
--- a/drivers/net/ethernet/mellanox/mlx4/srq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/srq.c
@@ -40,20 +40,20 @@
 struct mlx4_srq_context {
 	__be32			state_logsize_srqn;
 	u8			logstride;
-	u8			reserved1[3];
-	u8			pg_offset;
-	u8			reserved2[3];
-	u32			reserved3;
+	u8			reserved1;
+	__be16			xrcd;
+	__be32			pg_offset_cqn;
+	u32			reserved2;
 	u8			log_page_size;
-	u8			reserved4[2];
+	u8			reserved3[2];
 	u8			mtt_base_addr_h;
 	__be32			mtt_base_addr_l;
 	__be32			pd;
 	__be16			limit_watermark;
 	__be16			wqe_cnt;
-	u16			reserved5;
+	u16			reserved4;
 	__be16			wqe_counter;
-	u32			reserved6;
+	u32			reserved5;
 	__be64			db_rec_addr;
 };
 
@@ -109,8 +109,8 @@ static int mlx4_QUERY_SRQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox
 			    MLX4_CMD_TIME_CLASS_A);
 }
 
-int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, struct mlx4_mtt *mtt,
-		   u64 db_rec, struct mlx4_srq *srq)
+int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, u32 cqn, u16 xrcd,
+		   struct mlx4_mtt *mtt, u64 db_rec, struct mlx4_srq *srq)
 {
 	struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
 	struct mlx4_cmd_mailbox *mailbox;
@@ -148,6 +148,8 @@ int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, struct mlx4_mtt *mtt,
 	srq_context->state_logsize_srqn = cpu_to_be32((ilog2(srq->max) << 24) |
 						      srq->srqn);
 	srq_context->logstride          = srq->wqe_shift - 4;
+	srq_context->xrcd		= cpu_to_be16(xrcd);
+	srq_context->pg_offset_cqn	= cpu_to_be32(cqn & 0xffffff);
 	srq_context->log_page_size      = mtt->page_shift - MLX4_ICM_PAGE_SHIFT;
 
 	mtt_addr = mlx4_mtt_addr(dev, mtt);
diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c
index 3bb1311..7145714 100644
--- a/drivers/net/rionet.c
+++ b/drivers/net/rionet.c
@@ -88,8 +88,8 @@ static struct rio_dev **rionet_active;
 #define dev_rionet_capable(dev) \
 	is_rionet_capable(dev->src_ops, dev->dst_ops)
 
-#define RIONET_MAC_MATCH(x)	(*(u32 *)x == 0x00010001)
-#define RIONET_GET_DESTID(x)	(*(u16 *)(x + 4))
+#define RIONET_MAC_MATCH(x)	(!memcmp((x), "\00\01\00\01", 4))
+#define RIONET_GET_DESTID(x)	((*((u8 *)x + 4) << 8) | *((u8 *)x + 5))
 
 static int rionet_rx_clean(struct net_device *ndev)
 {
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 91039ab..6ee8410 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -925,12 +925,10 @@ static void virtnet_update_status(struct virtnet_info *vi)
 {
 	u16 v;
 
-	if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS))
-		return;
-
-	vi->vdev->config->get(vi->vdev,
+	if (virtio_config_val(vi->vdev, VIRTIO_NET_F_STATUS,
 			      offsetof(struct virtio_net_config, status),
-			      &v, sizeof(v));
+			      &v) < 0)
+		return;
 
 	/* Ignore unknown (future) status bits */
 	v &= VIRTIO_NET_S_LINK_UP;
@@ -1006,11 +1004,9 @@ static int virtnet_probe(struct virtio_device *vdev)
 	}
 
 	/* Configuration may specify what MAC to use.  Otherwise random. */
-	if (virtio_has_feature(vdev, VIRTIO_NET_F_MAC)) {
-		vdev->config->get(vdev,
+	if (virtio_config_val_len(vdev, VIRTIO_NET_F_MAC,
 				  offsetof(struct virtio_net_config, mac),
-				  dev->dev_addr, dev->addr_len);
-	} else
+				  dev->dev_addr, dev->addr_len) < 0)
 		random_ether_addr(dev->dev_addr);
 
 	/* Set up our device-specific information */
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig
index 0735488..0960224 100644
--- a/drivers/net/wireless/ath/Kconfig
+++ b/drivers/net/wireless/ath/Kconfig
@@ -1,6 +1,6 @@
 menuconfig ATH_COMMON
 	tristate "Atheros Wireless Cards"
-	depends on CFG80211
+	depends on CFG80211 && (!UML || BROKEN)
 	---help---
 	  This will enable the support for the Atheros wireless drivers.
 	  ath5k, ath9k, ath9k_htc and ar9170 drivers share some common code, this option
diff --git a/drivers/net/wireless/rtlwifi/Kconfig b/drivers/net/wireless/rtlwifi/Kconfig
index 45e1476..d6c42e6 100644
--- a/drivers/net/wireless/rtlwifi/Kconfig
+++ b/drivers/net/wireless/rtlwifi/Kconfig
@@ -12,7 +12,7 @@ config RTL8192CE
 
 config RTL8192SE
 	tristate "Realtek RTL8192SE/RTL8191SE PCIe Wireless Network Adapter"
-	depends on MAC80211 && EXPERIMENTAL
+	depends on MAC80211 && EXPERIMENTAL && PCI
 	select FW_LOADER
 	select RTLWIFI
 	---help---
@@ -23,7 +23,7 @@ config RTL8192SE
 
 config RTL8192DE
 	tristate "Realtek RTL8192DE/RTL8188DE PCIe Wireless Network Adapter"
-	depends on MAC80211 && EXPERIMENTAL
+	depends on MAC80211 && EXPERIMENTAL && PCI
 	select FW_LOADER
 	select RTLWIFI
 	---help---
diff --git a/drivers/of/base.c b/drivers/of/base.c
index b970562..9b6588e 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -716,6 +716,90 @@ int of_property_read_string(struct device_node *np, const char *propname,
 EXPORT_SYMBOL_GPL(of_property_read_string);
 
 /**
+ * of_property_read_string_index - Find and read a string from a multiple
+ * strings property.
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ * @index:	index of the string in the list of strings
+ * @out_string:	pointer to null terminated return string, modified only if
+ *		return value is 0.
+ *
+ * Search for a property in a device tree node and retrieve a null
+ * terminated string value (pointer to data, not a copy) in the list of strings
+ * contained in that property.
+ * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if
+ * property does not have a value, and -EILSEQ if the string is not
+ * null-terminated within the length of the property data.
+ *
+ * The out_string pointer is modified only if a valid string can be decoded.
+ */
+int of_property_read_string_index(struct device_node *np, const char *propname,
+				  int index, const char **output)
+{
+	struct property *prop = of_find_property(np, propname, NULL);
+	int i = 0;
+	size_t l = 0, total = 0;
+	const char *p;
+
+	if (!prop)
+		return -EINVAL;
+	if (!prop->value)
+		return -ENODATA;
+	if (strnlen(prop->value, prop->length) >= prop->length)
+		return -EILSEQ;
+
+	p = prop->value;
+
+	for (i = 0; total < prop->length; total += l, p += l) {
+		l = strlen(p) + 1;
+		if ((*p != 0) && (i++ == index)) {
+			*output = p;
+			return 0;
+		}
+	}
+	return -ENODATA;
+}
+EXPORT_SYMBOL_GPL(of_property_read_string_index);
+
+
+/**
+ * of_property_count_strings - Find and return the number of strings from a
+ * multiple strings property.
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ *
+ * Search for a property in a device tree node and retrieve the number of null
+ * terminated string contain in it. Returns the number of strings on
+ * success, -EINVAL if the property does not exist, -ENODATA if property
+ * does not have a value, and -EILSEQ if the string is not null-terminated
+ * within the length of the property data.
+ */
+int of_property_count_strings(struct device_node *np, const char *propname)
+{
+	struct property *prop = of_find_property(np, propname, NULL);
+	int i = 0;
+	size_t l = 0, total = 0;
+	const char *p;
+
+	if (!prop)
+		return -EINVAL;
+	if (!prop->value)
+		return -ENODATA;
+	if (strnlen(prop->value, prop->length) >= prop->length)
+		return -EILSEQ;
+
+	p = prop->value;
+
+	for (i = 0; total < prop->length; total += l, p += l) {
+		l = strlen(p) + 1;
+		if (*p != 0)
+			i++;
+	}
+	return i;
+}
+EXPORT_SYMBOL_GPL(of_property_count_strings);
+
+/**
  * of_parse_phandle - Resolve a phandle property to a device_node pointer
  * @np: Pointer to device node holding phandle property
  * @phandle_name: Name of property holding a phandle value
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 6a5b5e7..6d3dd39 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -19,10 +19,12 @@
  */
 
 #include <linux/errno.h>
+#include <linux/list.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
 #include <linux/string.h>
+#include <linux/slab.h>
 
 /* For archs that don't support NO_IRQ (such as x86), provide a dummy value */
 #ifndef NO_IRQ
@@ -386,3 +388,108 @@ int of_irq_to_resource_table(struct device_node *dev, struct resource *res,
 
 	return i;
 }
+
+struct intc_desc {
+	struct list_head	list;
+	struct device_node	*dev;
+	struct device_node	*interrupt_parent;
+};
+
+/**
+ * of_irq_init - Scan and init matching interrupt controllers in DT
+ * @matches: 0 terminated array of nodes to match and init function to call
+ *
+ * This function scans the device tree for matching interrupt controller nodes,
+ * and calls their initialization functions in order with parents first.
+ */
+void __init of_irq_init(const struct of_device_id *matches)
+{
+	struct device_node *np, *parent = NULL;
+	struct intc_desc *desc, *temp_desc;
+	struct list_head intc_desc_list, intc_parent_list;
+
+	INIT_LIST_HEAD(&intc_desc_list);
+	INIT_LIST_HEAD(&intc_parent_list);
+
+	for_each_matching_node(np, matches) {
+		if (!of_find_property(np, "interrupt-controller", NULL))
+			continue;
+		/*
+		 * Here, we allocate and populate an intc_desc with the node
+		 * pointer, interrupt-parent device_node etc.
+		 */
+		desc = kzalloc(sizeof(*desc), GFP_KERNEL);
+		if (WARN_ON(!desc))
+			goto err;
+
+		desc->dev = np;
+		desc->interrupt_parent = of_irq_find_parent(np);
+		list_add_tail(&desc->list, &intc_desc_list);
+	}
+
+	/*
+	 * The root irq controller is the one without an interrupt-parent.
+	 * That one goes first, followed by the controllers that reference it,
+	 * followed by the ones that reference the 2nd level controllers, etc.
+	 */
+	while (!list_empty(&intc_desc_list)) {
+		/*
+		 * Process all controllers with the current 'parent'.
+		 * First pass will be looking for NULL as the parent.
+		 * The assumption is that NULL parent means a root controller.
+		 */
+		list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {
+			const struct of_device_id *match;
+			int ret;
+			of_irq_init_cb_t irq_init_cb;
+
+			if (desc->interrupt_parent != parent)
+				continue;
+
+			list_del(&desc->list);
+			match = of_match_node(matches, desc->dev);
+			if (WARN(!match->data,
+			    "of_irq_init: no init function for %s\n",
+			    match->compatible)) {
+				kfree(desc);
+				continue;
+			}
+
+			pr_debug("of_irq_init: init %s @ %p, parent %p\n",
+				 match->compatible,
+				 desc->dev, desc->interrupt_parent);
+			irq_init_cb = match->data;
+			ret = irq_init_cb(desc->dev, desc->interrupt_parent);
+			if (ret) {
+				kfree(desc);
+				continue;
+			}
+
+			/*
+			 * This one is now set up; add it to the parent list so
+			 * its children can get processed in a subsequent pass.
+			 */
+			list_add_tail(&desc->list, &intc_parent_list);
+		}
+
+		/* Get the next pending parent that might have children */
+		desc = list_first_entry(&intc_parent_list, typeof(*desc), list);
+		if (list_empty(&intc_parent_list) || !desc) {
+			pr_err("of_irq_init: children remain, but no parents\n");
+			break;
+		}
+		list_del(&desc->list);
+		parent = desc->dev;
+		kfree(desc);
+	}
+
+	list_for_each_entry_safe(desc, temp_desc, &intc_parent_list, list) {
+		list_del(&desc->list);
+		kfree(desc);
+	}
+err:
+	list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {
+		list_del(&desc->list);
+		kfree(desc);
+	}
+}
diff --git a/drivers/pcmcia/pxa2xx_balloon3.c b/drivers/pcmcia/pxa2xx_balloon3.c
index f56d7de..22a75e6 100644
--- a/drivers/pcmcia/pxa2xx_balloon3.c
+++ b/drivers/pcmcia/pxa2xx_balloon3.c
@@ -97,7 +97,7 @@ static void balloon3_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
 static int balloon3_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
 				       const socket_state_t *state)
 {
-	__raw_writew(BALLOON3_CF_RESET, BALLOON3_CF_CONTROL_REG |
+	__raw_writew(BALLOON3_CF_RESET, BALLOON3_CF_CONTROL_REG +
 			((state->flags & SS_RESET) ?
 			BALLOON3_FPGA_SETnCLR : 0));
 	return 0;
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 57de051..9f88641 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -70,6 +70,7 @@ config BATTERY_DS2760
 
 config BATTERY_DS2780
 	tristate "DS2780 battery driver"
+	depends on HAS_IOMEM
 	select W1
 	select W1_SLAVE_DS2780
 	help
diff --git a/drivers/power/ds2780_battery.c b/drivers/power/ds2780_battery.c
index 1fefe82..91a783d 100644
--- a/drivers/power/ds2780_battery.c
+++ b/drivers/power/ds2780_battery.c
@@ -39,6 +39,7 @@ struct ds2780_device_info {
 	struct device *dev;
 	struct power_supply bat;
 	struct device *w1_dev;
+	struct task_struct *mutex_holder;
 };
 
 enum current_types {
@@ -49,8 +50,8 @@ enum current_types {
 static const char model[] = "DS2780";
 static const char manufacturer[] = "Maxim/Dallas";
 
-static inline struct ds2780_device_info *to_ds2780_device_info(
-	struct power_supply *psy)
+static inline struct ds2780_device_info *
+to_ds2780_device_info(struct power_supply *psy)
 {
 	return container_of(psy, struct ds2780_device_info, bat);
 }
@@ -60,17 +61,28 @@ static inline struct power_supply *to_power_supply(struct device *dev)
 	return dev_get_drvdata(dev);
 }
 
-static inline int ds2780_read8(struct device *dev, u8 *val, int addr)
+static inline int ds2780_battery_io(struct ds2780_device_info *dev_info,
+	char *buf, int addr, size_t count, int io)
 {
-	return w1_ds2780_io(dev, val, addr, sizeof(u8), 0);
+	if (dev_info->mutex_holder == current)
+		return w1_ds2780_io_nolock(dev_info->w1_dev, buf, addr, count, io);
+	else
+		return w1_ds2780_io(dev_info->w1_dev, buf, addr, count, io);
+}
+
+static inline int ds2780_read8(struct ds2780_device_info *dev_info, u8 *val,
+	int addr)
+{
+	return ds2780_battery_io(dev_info, val, addr, sizeof(u8), 0);
 }
 
-static int ds2780_read16(struct device *dev, s16 *val, int addr)
+static int ds2780_read16(struct ds2780_device_info *dev_info, s16 *val,
+	int addr)
 {
 	int ret;
 	u8 raw[2];
 
-	ret = w1_ds2780_io(dev, raw, addr, sizeof(u8) * 2, 0);
+	ret = ds2780_battery_io(dev_info, raw, addr, sizeof(raw), 0);
 	if (ret < 0)
 		return ret;
 
@@ -79,16 +91,16 @@ static int ds2780_read16(struct device *dev, s16 *val, int addr)
 	return 0;
 }
 
-static inline int ds2780_read_block(struct device *dev, u8 *val, int addr,
-	size_t count)
+static inline int ds2780_read_block(struct ds2780_device_info *dev_info,
+	u8 *val, int addr, size_t count)
 {
-	return w1_ds2780_io(dev, val, addr, count, 0);
+	return ds2780_battery_io(dev_info, val, addr, count, 0);
 }
 
-static inline int ds2780_write(struct device *dev, u8 *val, int addr,
-	size_t count)
+static inline int ds2780_write(struct ds2780_device_info *dev_info, u8 *val,
+	int addr, size_t count)
 {
-	return w1_ds2780_io(dev, val, addr, count, 1);
+	return ds2780_battery_io(dev_info, val, addr, count, 1);
 }
 
 static inline int ds2780_store_eeprom(struct device *dev, int addr)
@@ -122,7 +134,7 @@ static int ds2780_set_sense_register(struct ds2780_device_info *dev_info,
 {
 	int ret;
 
-	ret = ds2780_write(dev_info->w1_dev, &conductance,
+	ret = ds2780_write(dev_info, &conductance,
 				DS2780_RSNSP_REG, sizeof(u8));
 	if (ret < 0)
 		return ret;
@@ -134,7 +146,7 @@ static int ds2780_set_sense_register(struct ds2780_device_info *dev_info,
 static int ds2780_get_rsgain_register(struct ds2780_device_info *dev_info,
 	u16 *rsgain)
 {
-	return ds2780_read16(dev_info->w1_dev, rsgain, DS2780_RSGAIN_MSB_REG);
+	return ds2780_read16(dev_info, rsgain, DS2780_RSGAIN_MSB_REG);
 }
 
 /* Set RSGAIN value from 0 to 1.999 in steps of 0.001 */
@@ -144,8 +156,8 @@ static int ds2780_set_rsgain_register(struct ds2780_device_info *dev_info,
 	int ret;
 	u8 raw[] = {rsgain >> 8, rsgain & 0xFF};
 
-	ret = ds2780_write(dev_info->w1_dev, raw,
-				DS2780_RSGAIN_MSB_REG, sizeof(u8) * 2);
+	ret = ds2780_write(dev_info, raw,
+				DS2780_RSGAIN_MSB_REG, sizeof(raw));
 	if (ret < 0)
 		return ret;
 
@@ -167,7 +179,7 @@ static int ds2780_get_voltage(struct ds2780_device_info *dev_info,
 	 * Bits 2 - 0 of the voltage value are in bits 7 - 5 of the
 	 * voltage LSB register
 	 */
-	ret = ds2780_read16(dev_info->w1_dev, &voltage_raw,
+	ret = ds2780_read16(dev_info, &voltage_raw,
 				DS2780_VOLT_MSB_REG);
 	if (ret < 0)
 		return ret;
@@ -196,7 +208,7 @@ static int ds2780_get_temperature(struct ds2780_device_info *dev_info,
 	 * Bits 2 - 0 of the temperature value are in bits 7 - 5 of the
 	 * temperature LSB register
 	 */
-	ret = ds2780_read16(dev_info->w1_dev, &temperature_raw,
+	ret = ds2780_read16(dev_info, &temperature_raw,
 				DS2780_TEMP_MSB_REG);
 	if (ret < 0)
 		return ret;
@@ -222,13 +234,13 @@ static int ds2780_get_current(struct ds2780_device_info *dev_info,
 	 * The units of measurement for current are dependent on the value of
 	 * the sense resistor.
 	 */
-	ret = ds2780_read8(dev_info->w1_dev, &sense_res_raw, DS2780_RSNSP_REG);
+	ret = ds2780_read8(dev_info, &sense_res_raw, DS2780_RSNSP_REG);
 	if (ret < 0)
 		return ret;
 
 	if (sense_res_raw == 0) {
 		dev_err(dev_info->dev, "sense resistor value is 0\n");
-		return -ENXIO;
+		return -EINVAL;
 	}
 	sense_res = 1000 / sense_res_raw;
 
@@ -248,7 +260,7 @@ static int ds2780_get_current(struct ds2780_device_info *dev_info,
 	 * Bits 7 - 0 of the current value are in bits 7 - 0 of the current
 	 * LSB register
 	 */
-	ret = ds2780_read16(dev_info->w1_dev, &current_raw, reg_msb);
+	ret = ds2780_read16(dev_info, &current_raw, reg_msb);
 	if (ret < 0)
 		return ret;
 
@@ -267,7 +279,7 @@ static int ds2780_get_accumulated_current(struct ds2780_device_info *dev_info,
 	 * The units of measurement for accumulated current are dependent on
 	 * the value of the sense resistor.
 	 */
-	ret = ds2780_read8(dev_info->w1_dev, &sense_res_raw, DS2780_RSNSP_REG);
+	ret = ds2780_read8(dev_info, &sense_res_raw, DS2780_RSNSP_REG);
 	if (ret < 0)
 		return ret;
 
@@ -285,7 +297,7 @@ static int ds2780_get_accumulated_current(struct ds2780_device_info *dev_info,
 	 * Bits 7 - 0 of the ACR value are in bits 7 - 0 of the ACR
 	 * LSB register
 	 */
-	ret = ds2780_read16(dev_info->w1_dev, &current_raw, DS2780_ACR_MSB_REG);
+	ret = ds2780_read16(dev_info, &current_raw, DS2780_ACR_MSB_REG);
 	if (ret < 0)
 		return ret;
 
@@ -299,7 +311,7 @@ static int ds2780_get_capacity(struct ds2780_device_info *dev_info,
 	int ret;
 	u8 raw;
 
-	ret = ds2780_read8(dev_info->w1_dev, &raw, DS2780_RARC_REG);
+	ret = ds2780_read8(dev_info, &raw, DS2780_RARC_REG);
 	if (ret < 0)
 		return ret;
 
@@ -345,7 +357,7 @@ static int ds2780_get_charge_now(struct ds2780_device_info *dev_info,
 	 * Bits 7 - 0 of the RAAC value are in bits 7 - 0 of the RAAC
 	 * LSB register
 	 */
-	ret = ds2780_read16(dev_info->w1_dev, &charge_raw, DS2780_RAAC_MSB_REG);
+	ret = ds2780_read16(dev_info, &charge_raw, DS2780_RAAC_MSB_REG);
 	if (ret < 0)
 		return ret;
 
@@ -356,7 +368,7 @@ static int ds2780_get_charge_now(struct ds2780_device_info *dev_info,
 static int ds2780_get_control_register(struct ds2780_device_info *dev_info,
 	u8 *control_reg)
 {
-	return ds2780_read8(dev_info->w1_dev, control_reg, DS2780_CONTROL_REG);
+	return ds2780_read8(dev_info, control_reg, DS2780_CONTROL_REG);
 }
 
 static int ds2780_set_control_register(struct ds2780_device_info *dev_info,
@@ -364,7 +376,7 @@ static int ds2780_set_control_register(struct ds2780_device_info *dev_info,
 {
 	int ret;
 
-	ret = ds2780_write(dev_info->w1_dev, &control_reg,
+	ret = ds2780_write(dev_info, &control_reg,
 				DS2780_CONTROL_REG, sizeof(u8));
 	if (ret < 0)
 		return ret;
@@ -503,7 +515,7 @@ static ssize_t ds2780_get_sense_resistor_value(struct device *dev,
 	struct power_supply *psy = to_power_supply(dev);
 	struct ds2780_device_info *dev_info = to_ds2780_device_info(psy);
 
-	ret = ds2780_read8(dev_info->w1_dev, &sense_resistor, DS2780_RSNSP_REG);
+	ret = ds2780_read8(dev_info, &sense_resistor, DS2780_RSNSP_REG);
 	if (ret < 0)
 		return ret;
 
@@ -584,7 +596,7 @@ static ssize_t ds2780_get_pio_pin(struct device *dev,
 	struct power_supply *psy = to_power_supply(dev);
 	struct ds2780_device_info *dev_info = to_ds2780_device_info(psy);
 
-	ret = ds2780_read8(dev_info->w1_dev, &sfr, DS2780_SFR_REG);
+	ret = ds2780_read8(dev_info, &sfr, DS2780_SFR_REG);
 	if (ret < 0)
 		return ret;
 
@@ -611,7 +623,7 @@ static ssize_t ds2780_set_pio_pin(struct device *dev,
 		return -EINVAL;
 	}
 
-	ret = ds2780_write(dev_info->w1_dev, &new_setting,
+	ret = ds2780_write(dev_info, &new_setting,
 				DS2780_SFR_REG, sizeof(u8));
 	if (ret < 0)
 		return ret;
@@ -632,7 +644,7 @@ static ssize_t ds2780_read_param_eeprom_bin(struct file *filp,
 		DS2780_EEPROM_BLOCK1_END -
 		DS2780_EEPROM_BLOCK1_START + 1 - off);
 
-	return ds2780_read_block(dev_info->w1_dev, buf,
+	return ds2780_read_block(dev_info, buf,
 				DS2780_EEPROM_BLOCK1_START + off, count);
 }
 
@@ -650,7 +662,7 @@ static ssize_t ds2780_write_param_eeprom_bin(struct file *filp,
 		DS2780_EEPROM_BLOCK1_END -
 		DS2780_EEPROM_BLOCK1_START + 1 - off);
 
-	ret = ds2780_write(dev_info->w1_dev, buf,
+	ret = ds2780_write(dev_info, buf,
 				DS2780_EEPROM_BLOCK1_START + off, count);
 	if (ret < 0)
 		return ret;
@@ -685,9 +697,8 @@ static ssize_t ds2780_read_user_eeprom_bin(struct file *filp,
 		DS2780_EEPROM_BLOCK0_END -
 		DS2780_EEPROM_BLOCK0_START + 1 - off);
 
-	return ds2780_read_block(dev_info->w1_dev, buf,
+	return ds2780_read_block(dev_info, buf,
 				DS2780_EEPROM_BLOCK0_START + off, count);
-
 }
 
 static ssize_t ds2780_write_user_eeprom_bin(struct file *filp,
@@ -704,7 +715,7 @@ static ssize_t ds2780_write_user_eeprom_bin(struct file *filp,
 		DS2780_EEPROM_BLOCK0_END -
 		DS2780_EEPROM_BLOCK0_START + 1 - off);
 
-	ret = ds2780_write(dev_info->w1_dev, buf,
+	ret = ds2780_write(dev_info, buf,
 				DS2780_EEPROM_BLOCK0_START + off, count);
 	if (ret < 0)
 		return ret;
@@ -768,6 +779,7 @@ static int __devinit ds2780_battery_probe(struct platform_device *pdev)
 	dev_info->bat.properties	= ds2780_battery_props;
 	dev_info->bat.num_properties	= ARRAY_SIZE(ds2780_battery_props);
 	dev_info->bat.get_property	= ds2780_battery_get_property;
+	dev_info->mutex_holder		= current;
 
 	ret = power_supply_register(&pdev->dev, &dev_info->bat);
 	if (ret) {
@@ -797,6 +809,8 @@ static int __devinit ds2780_battery_probe(struct platform_device *pdev)
 		goto fail_remove_bin_file;
 	}
 
+	dev_info->mutex_holder = NULL;
+
 	return 0;
 
 fail_remove_bin_file:
@@ -816,6 +830,8 @@ static int __devexit ds2780_battery_remove(struct platform_device *pdev)
 {
 	struct ds2780_device_info *dev_info = platform_get_drvdata(pdev);
 
+	dev_info->mutex_holder = current;
+
 	/* remove attributes */
 	sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2780_attr_group);
 
diff --git a/drivers/pps/clients/Kconfig b/drivers/pps/clients/Kconfig
index 8520a7f..445197d 100644
--- a/drivers/pps/clients/Kconfig
+++ b/drivers/pps/clients/Kconfig
@@ -29,4 +29,13 @@ config PPS_CLIENT_PARPORT
 	  If you say yes here you get support for a PPS source connected
 	  with the interrupt pin of your parallel port.
 
+config PPS_CLIENT_GPIO
+	tristate "PPS client using GPIO"
+	depends on PPS && GENERIC_HARDIRQS
+	help
+	  If you say yes here you get support for a PPS source using
+	  GPIO. To be useful you must also register a platform device
+	  specifying the GPIO pin and other options, usually in your board
+	  setup.
+
 endif
diff --git a/drivers/pps/clients/Makefile b/drivers/pps/clients/Makefile
index 4feb7e9..a461d15 100644
--- a/drivers/pps/clients/Makefile
+++ b/drivers/pps/clients/Makefile
@@ -5,5 +5,6 @@
 obj-$(CONFIG_PPS_CLIENT_KTIMER)	+= pps-ktimer.o
 obj-$(CONFIG_PPS_CLIENT_LDISC)	+= pps-ldisc.o
 obj-$(CONFIG_PPS_CLIENT_PARPORT) += pps_parport.o
+obj-$(CONFIG_PPS_CLIENT_GPIO)	+= pps-gpio.o
 
 ccflags-$(CONFIG_PPS_DEBUG) := -DDEBUG
diff --git a/drivers/pps/clients/pps-gpio.c b/drivers/pps/clients/pps-gpio.c
new file mode 100644
index 0000000..6550555
--- /dev/null
+++ b/drivers/pps/clients/pps-gpio.c
@@ -0,0 +1,227 @@
+/*
+ * pps-gpio.c -- PPS client driver using GPIO
+ *
+ *
+ * Copyright (C) 2010 Ricardo Martins <rasm@fe.up.pt>
+ * Copyright (C) 2011 James Nuss <jamesnuss@nanometrics.ca>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define PPS_GPIO_NAME "pps-gpio"
+#define pr_fmt(fmt) PPS_GPIO_NAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/pps_kernel.h>
+#include <linux/pps-gpio.h>
+#include <linux/gpio.h>
+#include <linux/list.h>
+
+/* Info for each registered platform device */
+struct pps_gpio_device_data {
+	int irq;			/* IRQ used as PPS source */
+	struct pps_device *pps;		/* PPS source device */
+	struct pps_source_info info;	/* PPS source information */
+	const struct pps_gpio_platform_data *pdata;
+};
+
+/*
+ * Report the PPS event
+ */
+
+static irqreturn_t pps_gpio_irq_handler(int irq, void *data)
+{
+	const struct pps_gpio_device_data *info;
+	struct pps_event_time ts;
+	int rising_edge;
+
+	/* Get the time stamp first */
+	pps_get_ts(&ts);
+
+	info = data;
+
+	rising_edge = gpio_get_value(info->pdata->gpio_pin);
+	if ((rising_edge && !info->pdata->assert_falling_edge) ||
+			(!rising_edge && info->pdata->assert_falling_edge))
+		pps_event(info->pps, &ts, PPS_CAPTUREASSERT, NULL);
+	else if (info->pdata->capture_clear &&
+			((rising_edge && info->pdata->assert_falling_edge) ||
+			 (!rising_edge && !info->pdata->assert_falling_edge)))
+		pps_event(info->pps, &ts, PPS_CAPTURECLEAR, NULL);
+
+	return IRQ_HANDLED;
+}
+
+static int pps_gpio_setup(struct platform_device *pdev)
+{
+	int ret;
+	const struct pps_gpio_platform_data *pdata = pdev->dev.platform_data;
+
+	ret = gpio_request(pdata->gpio_pin, pdata->gpio_label);
+	if (ret) {
+		pr_warning("failed to request GPIO %u\n", pdata->gpio_pin);
+		return -EINVAL;
+	}
+
+	ret = gpio_direction_input(pdata->gpio_pin);
+	if (ret) {
+		pr_warning("failed to set pin direction\n");
+		gpio_free(pdata->gpio_pin);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static unsigned long
+get_irqf_trigger_flags(const struct pps_gpio_platform_data *pdata)
+{
+	unsigned long flags = pdata->assert_falling_edge ?
+		IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
+
+	if (pdata->capture_clear) {
+		flags |= ((flags & IRQF_TRIGGER_RISING) ?
+				IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING);
+	}
+
+	return flags;
+}
+
+static int pps_gpio_probe(struct platform_device *pdev)
+{
+	struct pps_gpio_device_data *data;
+	int irq;
+	int ret;
+	int err;
+	int pps_default_params;
+	const struct pps_gpio_platform_data *pdata = pdev->dev.platform_data;
+
+
+	/* GPIO setup */
+	ret = pps_gpio_setup(pdev);
+	if (ret)
+		return -EINVAL;
+
+	/* IRQ setup */
+	irq = gpio_to_irq(pdata->gpio_pin);
+	if (irq < 0) {
+		pr_err("failed to map GPIO to IRQ: %d\n", irq);
+		err = -EINVAL;
+		goto return_error;
+	}
+
+	/* allocate space for device info */
+	data = kzalloc(sizeof(struct pps_gpio_device_data), GFP_KERNEL);
+	if (data == NULL) {
+		err = -ENOMEM;
+		goto return_error;
+	}
+
+	/* initialize PPS specific parts of the bookkeeping data structure. */
+	data->info.mode = PPS_CAPTUREASSERT | PPS_OFFSETASSERT |
+		PPS_ECHOASSERT | PPS_CANWAIT | PPS_TSFMT_TSPEC;
+	if (pdata->capture_clear)
+		data->info.mode |= PPS_CAPTURECLEAR | PPS_OFFSETCLEAR |
+			PPS_ECHOCLEAR;
+	data->info.owner = THIS_MODULE;
+	snprintf(data->info.name, PPS_MAX_NAME_LEN - 1, "%s.%d",
+		 pdev->name, pdev->id);
+
+	/* register PPS source */
+	pps_default_params = PPS_CAPTUREASSERT | PPS_OFFSETASSERT;
+	if (pdata->capture_clear)
+		pps_default_params |= PPS_CAPTURECLEAR | PPS_OFFSETCLEAR;
+	data->pps = pps_register_source(&data->info, pps_default_params);
+	if (data->pps == NULL) {
+		kfree(data);
+		pr_err("failed to register IRQ %d as PPS source\n", irq);
+		err = -EINVAL;
+		goto return_error;
+	}
+
+	data->irq = irq;
+	data->pdata = pdata;
+
+	/* register IRQ interrupt handler */
+	ret = request_irq(irq, pps_gpio_irq_handler,
+			get_irqf_trigger_flags(pdata), data->info.name, data);
+	if (ret) {
+		pps_unregister_source(data->pps);
+		kfree(data);
+		pr_err("failed to acquire IRQ %d\n", irq);
+		err = -EINVAL;
+		goto return_error;
+	}
+
+	platform_set_drvdata(pdev, data);
+	dev_info(data->pps->dev, "Registered IRQ %d as PPS source\n", irq);
+
+	return 0;
+
+return_error:
+	gpio_free(pdata->gpio_pin);
+	return err;
+}
+
+static int pps_gpio_remove(struct platform_device *pdev)
+{
+	struct pps_gpio_device_data *data = platform_get_drvdata(pdev);
+	const struct pps_gpio_platform_data *pdata = data->pdata;
+
+	platform_set_drvdata(pdev, NULL);
+	free_irq(data->irq, data);
+	gpio_free(pdata->gpio_pin);
+	pps_unregister_source(data->pps);
+	pr_info("removed IRQ %d as PPS source\n", data->irq);
+	kfree(data);
+	return 0;
+}
+
+static struct platform_driver pps_gpio_driver = {
+	.probe		= pps_gpio_probe,
+	.remove		=  __devexit_p(pps_gpio_remove),
+	.driver		= {
+		.name	= PPS_GPIO_NAME,
+		.owner	= THIS_MODULE
+	},
+};
+
+static int __init pps_gpio_init(void)
+{
+	int ret = platform_driver_register(&pps_gpio_driver);
+	if (ret < 0)
+		pr_err("failed to register platform driver\n");
+	return ret;
+}
+
+static void __exit pps_gpio_exit(void)
+{
+	platform_driver_unregister(&pps_gpio_driver);
+	pr_debug("unregistered platform driver\n");
+}
+
+module_init(pps_gpio_init);
+module_exit(pps_gpio_exit);
+
+MODULE_AUTHOR("Ricardo Martins <rasm@fe.up.pt>");
+MODULE_AUTHOR("James Nuss <jamesnuss@nanometrics.ca>");
+MODULE_DESCRIPTION("Use GPIO pin as PPS source");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0.0");
diff --git a/drivers/pps/clients/pps-ktimer.c b/drivers/pps/clients/pps-ktimer.c
index 82583b0..436b4e4 100644
--- a/drivers/pps/clients/pps-ktimer.c
+++ b/drivers/pps/clients/pps-ktimer.c
@@ -52,17 +52,6 @@ static void pps_ktimer_event(unsigned long ptr)
 }
 
 /*
- * The echo function
- */
-
-static void pps_ktimer_echo(struct pps_device *pps, int event, void *data)
-{
-	dev_info(pps->dev, "echo %s %s\n",
-		event & PPS_CAPTUREASSERT ? "assert" : "",
-		event & PPS_CAPTURECLEAR ? "clear" : "");
-}
-
-/*
  * The PPS info struct
  */
 
@@ -72,7 +61,6 @@ static struct pps_source_info pps_ktimer_info = {
 	.mode		= PPS_CAPTUREASSERT | PPS_OFFSETASSERT |
 			  PPS_ECHOASSERT |
 			  PPS_CANWAIT | PPS_TSFMT_TSPEC,
-	.echo		= pps_ktimer_echo,
 	.owner		= THIS_MODULE,
 };
 
diff --git a/drivers/pps/clients/pps_parport.c b/drivers/pps/clients/pps_parport.c
index c571d6d..e1b4705 100644
--- a/drivers/pps/clients/pps_parport.c
+++ b/drivers/pps/clients/pps_parport.c
@@ -133,14 +133,6 @@ out_both:
 	return;
 }
 
-/* the PPS echo function */
-static void pps_echo(struct pps_device *pps, int event, void *data)
-{
-	dev_info(pps->dev, "echo %s %s\n",
-		event & PPS_CAPTUREASSERT ? "assert" : "",
-		event & PPS_CAPTURECLEAR ? "clear" : "");
-}
-
 static void parport_attach(struct parport *port)
 {
 	struct pps_client_pp *device;
@@ -151,7 +143,6 @@ static void parport_attach(struct parport *port)
 				  PPS_OFFSETASSERT | PPS_OFFSETCLEAR | \
 				  PPS_ECHOASSERT | PPS_ECHOCLEAR | \
 				  PPS_CANWAIT | PPS_TSFMT_TSPEC,
-		.echo		= pps_echo,
 		.owner		= THIS_MODULE,
 		.dev		= NULL
 	};
diff --git a/drivers/pps/kapi.c b/drivers/pps/kapi.c
index a4e8eb9..f197e8e 100644
--- a/drivers/pps/kapi.c
+++ b/drivers/pps/kapi.c
@@ -52,6 +52,14 @@ static void pps_add_offset(struct pps_ktime *ts, struct pps_ktime *offset)
 	ts->sec += offset->sec;
 }
 
+static void pps_echo_client_default(struct pps_device *pps, int event,
+		void *data)
+{
+	dev_info(pps->dev, "echo %s %s\n",
+		event & PPS_CAPTUREASSERT ? "assert" : "",
+		event & PPS_CAPTURECLEAR ? "clear" : "");
+}
+
 /*
  * Exported functions
  */
@@ -80,13 +88,6 @@ struct pps_device *pps_register_source(struct pps_source_info *info,
 		err = -EINVAL;
 		goto pps_register_source_exit;
 	}
-	if ((info->mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR)) != 0 &&
-			info->echo == NULL) {
-		pr_err("%s: echo function is not defined\n",
-					info->name);
-		err = -EINVAL;
-		goto pps_register_source_exit;
-	}
 	if ((info->mode & (PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)) == 0) {
 		pr_err("%s: unspecified time format\n",
 					info->name);
@@ -108,6 +109,11 @@ struct pps_device *pps_register_source(struct pps_source_info *info,
 	pps->params.mode = default_params;
 	pps->info = *info;
 
+	/* check for default echo function */
+	if ((pps->info.mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR)) &&
+			pps->info.echo == NULL)
+		pps->info.echo = pps_echo_client_default;
+
 	init_waitqueue_head(&pps->queue);
 	spin_lock_init(&pps->lock);
 
diff --git a/drivers/rapidio/Kconfig b/drivers/rapidio/Kconfig
index 070211a..bc87192 100644
--- a/drivers/rapidio/Kconfig
+++ b/drivers/rapidio/Kconfig
@@ -1,6 +1,8 @@
 #
 # RapidIO configuration
 #
+source "drivers/rapidio/devices/Kconfig"
+
 config RAPIDIO_DISC_TIMEOUT
 	int "Discovery timeout duration (seconds)"
 	depends on RAPIDIO
@@ -20,8 +22,6 @@ config RAPIDIO_ENABLE_RX_TX_PORTS
 	  ports for Input/Output direction to allow other traffic
 	  than Maintenance transfers.
 
-source "drivers/rapidio/switches/Kconfig"
-
 config RAPIDIO_DEBUG
 	bool "RapidIO subsystem debug messages"
 	depends on RAPIDIO
@@ -32,3 +32,5 @@ config RAPIDIO_DEBUG
 	  going on.
 
 	  If you are unsure about this, say N here.
+
+source "drivers/rapidio/switches/Kconfig"
diff --git a/drivers/rapidio/Makefile b/drivers/rapidio/Makefile
index 89b8eca..ec3fb81 100644
--- a/drivers/rapidio/Makefile
+++ b/drivers/rapidio/Makefile
@@ -4,5 +4,6 @@
 obj-y += rio.o rio-access.o rio-driver.o rio-scan.o rio-sysfs.o
 
 obj-$(CONFIG_RAPIDIO)		+= switches/
+obj-$(CONFIG_RAPIDIO)		+= devices/
 
 subdir-ccflags-$(CONFIG_RAPIDIO_DEBUG) := -DDEBUG
diff --git a/drivers/rapidio/devices/Kconfig b/drivers/rapidio/devices/Kconfig
new file mode 100644
index 0000000..12a9d7f
--- /dev/null
+++ b/drivers/rapidio/devices/Kconfig
@@ -0,0 +1,10 @@
+#
+# RapidIO master port configuration
+#
+
+config RAPIDIO_TSI721
+	bool "IDT Tsi721 PCI Express SRIO Controller support"
+	depends on RAPIDIO && PCIEPORTBUS
+	default "n"
+	---help---
+	  Include support for IDT Tsi721 PCI Express Serial RapidIO controller.
diff --git a/drivers/rapidio/devices/Makefile b/drivers/rapidio/devices/Makefile
new file mode 100644
index 0000000..3b7b4e2
--- /dev/null
+++ b/drivers/rapidio/devices/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for RapidIO devices
+#
+
+obj-$(CONFIG_RAPIDIO_TSI721)	+= tsi721.o
diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c
new file mode 100644
index 0000000..5225930
--- /dev/null
+++ b/drivers/rapidio/devices/tsi721.c
@@ -0,0 +1,2360 @@
+/*
+ * RapidIO mport driver for Tsi721 PCIExpress-to-SRIO bridge
+ *
+ * Copyright 2011 Integrated Device Technology, Inc.
+ * Alexandre Bounine <alexandre.bounine@idt.com>
+ * Chul Kim <chul.kim@idt.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You 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/io.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/rio.h>
+#include <linux/rio_drv.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/kfifo.h>
+#include <linux/delay.h>
+
+#include "tsi721.h"
+
+#define DEBUG_PW	/* Inbound Port-Write debugging */
+
+static void tsi721_omsg_handler(struct tsi721_device *priv, int ch);
+static void tsi721_imsg_handler(struct tsi721_device *priv, int ch);
+
+/**
+ * tsi721_lcread - read from local SREP config space
+ * @mport: RapidIO master port info
+ * @index: ID of RapdiIO interface
+ * @offset: Offset into configuration space
+ * @len: Length (in bytes) of the maintenance transaction
+ * @data: Value to be read into
+ *
+ * Generates a local SREP space read. Returns %0 on
+ * success or %-EINVAL on failure.
+ */
+static int tsi721_lcread(struct rio_mport *mport, int index, u32 offset,
+			 int len, u32 *data)
+{
+	struct tsi721_device *priv = mport->priv;
+
+	if (len != sizeof(u32))
+		return -EINVAL; /* only 32-bit access is supported */
+
+	*data = ioread32(priv->regs + offset);
+
+	return 0;
+}
+
+/**
+ * tsi721_lcwrite - write into local SREP config space
+ * @mport: RapidIO master port info
+ * @index: ID of RapdiIO interface
+ * @offset: Offset into configuration space
+ * @len: Length (in bytes) of the maintenance transaction
+ * @data: Value to be written
+ *
+ * Generates a local write into SREP configuration space. Returns %0 on
+ * success or %-EINVAL on failure.
+ */
+static int tsi721_lcwrite(struct rio_mport *mport, int index, u32 offset,
+			  int len, u32 data)
+{
+	struct tsi721_device *priv = mport->priv;
+
+	if (len != sizeof(u32))
+		return -EINVAL; /* only 32-bit access is supported */
+
+	iowrite32(data, priv->regs + offset);
+
+	return 0;
+}
+
+/**
+ * tsi721_maint_dma - Helper function to generate RapidIO maintenance
+ *                    transactions using designated Tsi721 DMA channel.
+ * @priv: pointer to tsi721 private data
+ * @sys_size: RapdiIO transport system size
+ * @destid: Destination ID of transaction
+ * @hopcount: Number of hops to target device
+ * @offset: Offset into configuration space
+ * @len: Length (in bytes) of the maintenance transaction
+ * @data: Location to be read from or write into
+ * @do_wr: Operation flag (1 == MAINT_WR)
+ *
+ * Generates a RapidIO maintenance transaction (Read or Write).
+ * Returns %0 on success and %-EINVAL or %-EFAULT on failure.
+ */
+static int tsi721_maint_dma(struct tsi721_device *priv, u32 sys_size,
+			u16 destid, u8 hopcount, u32 offset, int len,
+			u32 *data, int do_wr)
+{
+	struct tsi721_dma_desc *bd_ptr;
+	u32 rd_count, swr_ptr, ch_stat;
+	int i, err = 0;
+	u32 op = do_wr ? MAINT_WR : MAINT_RD;
+
+	if (offset > (RIO_MAINT_SPACE_SZ - len) || (len != sizeof(u32)))
+		return -EINVAL;
+
+	bd_ptr = priv->bdma[TSI721_DMACH_MAINT].bd_base;
+
+	rd_count = ioread32(
+			priv->regs + TSI721_DMAC_DRDCNT(TSI721_DMACH_MAINT));
+
+	/* Initialize DMA descriptor */
+	bd_ptr[0].type_id = cpu_to_le32((DTYPE2 << 29) | (op << 19) | destid);
+	bd_ptr[0].bcount = cpu_to_le32((sys_size << 26) | 0x04);
+	bd_ptr[0].raddr_lo = cpu_to_le32((hopcount << 24) | offset);
+	bd_ptr[0].raddr_hi = 0;
+	if (do_wr)
+		bd_ptr[0].data[0] = cpu_to_be32p(data);
+	else
+		bd_ptr[0].data[0] = 0xffffffff;
+
+	mb();
+
+	/* Start DMA operation */
+	iowrite32(rd_count + 2,
+		priv->regs + TSI721_DMAC_DWRCNT(TSI721_DMACH_MAINT));
+	ioread32(priv->regs + TSI721_DMAC_DWRCNT(TSI721_DMACH_MAINT));
+	i = 0;
+
+	/* Wait until DMA transfer is finished */
+	while ((ch_stat = ioread32(priv->regs +
+		TSI721_DMAC_STS(TSI721_DMACH_MAINT))) & TSI721_DMAC_STS_RUN) {
+		udelay(1);
+		if (++i >= 5000000) {
+			dev_dbg(&priv->pdev->dev,
+				"%s : DMA[%d] read timeout ch_status=%x\n",
+				__func__, TSI721_DMACH_MAINT, ch_stat);
+			if (!do_wr)
+				*data = 0xffffffff;
+			err = -EIO;
+			goto err_out;
+		}
+	}
+
+	if (ch_stat & TSI721_DMAC_STS_ABORT) {
+		/* If DMA operation aborted due to error,
+		 * reinitialize DMA channel
+		 */
+		dev_dbg(&priv->pdev->dev, "%s : DMA ABORT ch_stat=%x\n",
+			__func__, ch_stat);
+		dev_dbg(&priv->pdev->dev, "OP=%d : destid=%x hc=%x off=%x\n",
+			do_wr ? MAINT_WR : MAINT_RD, destid, hopcount, offset);
+		iowrite32(TSI721_DMAC_INT_ALL,
+			priv->regs + TSI721_DMAC_INT(TSI721_DMACH_MAINT));
+		iowrite32(TSI721_DMAC_CTL_INIT,
+			priv->regs + TSI721_DMAC_CTL(TSI721_DMACH_MAINT));
+		udelay(10);
+		iowrite32(0, priv->regs +
+				TSI721_DMAC_DWRCNT(TSI721_DMACH_MAINT));
+		udelay(1);
+		if (!do_wr)
+			*data = 0xffffffff;
+		err = -EIO;
+		goto err_out;
+	}
+
+	if (!do_wr)
+		*data = be32_to_cpu(bd_ptr[0].data[0]);
+
+	/*
+	 * Update descriptor status FIFO RD pointer.
+	 * NOTE: Skipping check and clear FIFO entries because we are waiting
+	 * for transfer to be completed.
+	 */
+	swr_ptr = ioread32(priv->regs + TSI721_DMAC_DSWP(TSI721_DMACH_MAINT));
+	iowrite32(swr_ptr, priv->regs + TSI721_DMAC_DSRP(TSI721_DMACH_MAINT));
+err_out:
+
+	return err;
+}
+
+/**
+ * tsi721_cread_dma - Generate a RapidIO maintenance read transaction
+ *                    using Tsi721 BDMA engine.
+ * @mport: RapidIO master port control structure
+ * @index: ID of RapdiIO interface
+ * @destid: Destination ID of transaction
+ * @hopcount: Number of hops to target device
+ * @offset: Offset into configuration space
+ * @len: Length (in bytes) of the maintenance transaction
+ * @val: Location to be read into
+ *
+ * Generates a RapidIO maintenance read transaction.
+ * Returns %0 on success and %-EINVAL or %-EFAULT on failure.
+ */
+static int tsi721_cread_dma(struct rio_mport *mport, int index, u16 destid,
+			u8 hopcount, u32 offset, int len, u32 *data)
+{
+	struct tsi721_device *priv = mport->priv;
+
+	return tsi721_maint_dma(priv, mport->sys_size, destid, hopcount,
+				offset, len, data, 0);
+}
+
+/**
+ * tsi721_cwrite_dma - Generate a RapidIO maintenance write transaction
+ *                     using Tsi721 BDMA engine
+ * @mport: RapidIO master port control structure
+ * @index: ID of RapdiIO interface
+ * @destid: Destination ID of transaction
+ * @hopcount: Number of hops to target device
+ * @offset: Offset into configuration space
+ * @len: Length (in bytes) of the maintenance transaction
+ * @val: Value to be written
+ *
+ * Generates a RapidIO maintenance write transaction.
+ * Returns %0 on success and %-EINVAL or %-EFAULT on failure.
+ */
+static int tsi721_cwrite_dma(struct rio_mport *mport, int index, u16 destid,
+			 u8 hopcount, u32 offset, int len, u32 data)
+{
+	struct tsi721_device *priv = mport->priv;
+	u32 temp = data;
+
+	return tsi721_maint_dma(priv, mport->sys_size, destid, hopcount,
+				offset, len, &temp, 1);
+}
+
+/**
+ * tsi721_pw_handler - Tsi721 inbound port-write interrupt handler
+ * @mport: RapidIO master port structure
+ *
+ * Handles inbound port-write interrupts. Copies PW message from an internal
+ * buffer into PW message FIFO and schedules deferred routine to process
+ * queued messages.
+ */
+static int
+tsi721_pw_handler(struct rio_mport *mport)
+{
+	struct tsi721_device *priv = mport->priv;
+	u32 pw_stat;
+	u32 pw_buf[TSI721_RIO_PW_MSG_SIZE/sizeof(u32)];
+
+
+	pw_stat = ioread32(priv->regs + TSI721_RIO_PW_RX_STAT);
+
+	if (pw_stat & TSI721_RIO_PW_RX_STAT_PW_VAL) {
+		pw_buf[0] = ioread32(priv->regs + TSI721_RIO_PW_RX_CAPT(0));
+		pw_buf[1] = ioread32(priv->regs + TSI721_RIO_PW_RX_CAPT(1));
+		pw_buf[2] = ioread32(priv->regs + TSI721_RIO_PW_RX_CAPT(2));
+		pw_buf[3] = ioread32(priv->regs + TSI721_RIO_PW_RX_CAPT(3));
+
+		/* Queue PW message (if there is room in FIFO),
+		 * otherwise discard it.
+		 */
+		spin_lock(&priv->pw_fifo_lock);
+		if (kfifo_avail(&priv->pw_fifo) >= TSI721_RIO_PW_MSG_SIZE)
+			kfifo_in(&priv->pw_fifo, pw_buf,
+						TSI721_RIO_PW_MSG_SIZE);
+		else
+			priv->pw_discard_count++;
+		spin_unlock(&priv->pw_fifo_lock);
+	}
+
+	/* Clear pending PW interrupts */
+	iowrite32(TSI721_RIO_PW_RX_STAT_PW_DISC | TSI721_RIO_PW_RX_STAT_PW_VAL,
+		  priv->regs + TSI721_RIO_PW_RX_STAT);
+
+	schedule_work(&priv->pw_work);
+
+	return 0;
+}
+
+static void tsi721_pw_dpc(struct work_struct *work)
+{
+	struct tsi721_device *priv = container_of(work, struct tsi721_device,
+						    pw_work);
+	u32 msg_buffer[RIO_PW_MSG_SIZE/sizeof(u32)]; /* Use full size PW message
+							buffer for RIO layer */
+
+	/*
+	 * Process port-write messages
+	 */
+	while (kfifo_out_spinlocked(&priv->pw_fifo, (unsigned char *)msg_buffer,
+			 TSI721_RIO_PW_MSG_SIZE, &priv->pw_fifo_lock)) {
+		/* Process one message */
+#ifdef DEBUG_PW
+		{
+		u32 i;
+		pr_debug("%s : Port-Write Message:", __func__);
+		for (i = 0; i < RIO_PW_MSG_SIZE/sizeof(u32); ) {
+			pr_debug("0x%02x: %08x %08x %08x %08x", i*4,
+				msg_buffer[i], msg_buffer[i + 1],
+				msg_buffer[i + 2], msg_buffer[i + 3]);
+			i += 4;
+		}
+		pr_debug("\n");
+		}
+#endif
+		/* Pass the port-write message to RIO core for processing */
+		rio_inb_pwrite_handler((union rio_pw_msg *)msg_buffer);
+	}
+}
+
+/**
+ * tsi721_pw_enable - enable/disable port-write interface init
+ * @mport: Master port implementing the port write unit
+ * @enable:    1=enable; 0=disable port-write message handling
+ */
+static int tsi721_pw_enable(struct rio_mport *mport, int enable)
+{
+	struct tsi721_device *priv = mport->priv;
+	u32 rval;
+
+	rval = ioread32(priv->regs + TSI721_RIO_EM_INT_ENABLE);
+
+	if (enable)
+		rval |= TSI721_RIO_EM_INT_ENABLE_PW_RX;
+	else
+		rval &= ~TSI721_RIO_EM_INT_ENABLE_PW_RX;
+
+	/* Clear pending PW interrupts */
+	iowrite32(TSI721_RIO_PW_RX_STAT_PW_DISC | TSI721_RIO_PW_RX_STAT_PW_VAL,
+		  priv->regs + TSI721_RIO_PW_RX_STAT);
+	/* Update enable bits */
+	iowrite32(rval, priv->regs + TSI721_RIO_EM_INT_ENABLE);
+
+	return 0;
+}
+
+/**
+ * tsi721_dsend - Send a RapidIO doorbell
+ * @mport: RapidIO master port info
+ * @index: ID of RapidIO interface
+ * @destid: Destination ID of target device
+ * @data: 16-bit info field of RapidIO doorbell
+ *
+ * Sends a RapidIO doorbell message. Always returns %0.
+ */
+static int tsi721_dsend(struct rio_mport *mport, int index,
+			u16 destid, u16 data)
+{
+	struct tsi721_device *priv = mport->priv;
+	u32 offset;
+
+	offset = (((mport->sys_size) ? RIO_TT_CODE_16 : RIO_TT_CODE_8) << 18) |
+		 (destid << 2);
+
+	dev_dbg(&priv->pdev->dev,
+		"Send Doorbell 0x%04x to destID 0x%x\n", data, destid);
+	iowrite16be(data, priv->odb_base + offset);
+
+	return 0;
+}
+
+/**
+ * tsi721_dbell_handler - Tsi721 doorbell interrupt handler
+ * @mport: RapidIO master port structure
+ *
+ * Handles inbound doorbell interrupts. Copies doorbell entry from an internal
+ * buffer into DB message FIFO and schedules deferred  routine to process
+ * queued DBs.
+ */
+static int
+tsi721_dbell_handler(struct rio_mport *mport)
+{
+	struct tsi721_device *priv = mport->priv;
+	u32 regval;
+
+	/* Disable IDB interrupts */
+	regval = ioread32(priv->regs + TSI721_SR_CHINTE(IDB_QUEUE));
+	regval &= ~TSI721_SR_CHINT_IDBQRCV;
+	iowrite32(regval,
+		priv->regs + TSI721_SR_CHINTE(IDB_QUEUE));
+
+	schedule_work(&priv->idb_work);
+
+	return 0;
+}
+
+static void tsi721_db_dpc(struct work_struct *work)
+{
+	struct tsi721_device *priv = container_of(work, struct tsi721_device,
+						    idb_work);
+	struct rio_mport *mport;
+	struct rio_dbell *dbell;
+	int found = 0;
+	u32 wr_ptr, rd_ptr;
+	u64 *idb_entry;
+	u32 regval;
+	union {
+		u64 msg;
+		u8  bytes[8];
+	} idb;
+
+	/*
+	 * Process queued inbound doorbells
+	 */
+	mport = priv->mport;
+
+	wr_ptr = ioread32(priv->regs + TSI721_IDQ_WP(IDB_QUEUE));
+	rd_ptr = ioread32(priv->regs + TSI721_IDQ_RP(IDB_QUEUE));
+
+	while (wr_ptr != rd_ptr) {
+		idb_entry = (u64 *)(priv->idb_base +
+					(TSI721_IDB_ENTRY_SIZE * rd_ptr));
+		rd_ptr++;
+		idb.msg = *idb_entry;
+		*idb_entry = 0;
+
+		/* Process one doorbell */
+		list_for_each_entry(dbell, &mport->dbells, node) {
+			if ((dbell->res->start <= DBELL_INF(idb.bytes)) &&
+			    (dbell->res->end >= DBELL_INF(idb.bytes))) {
+				found = 1;
+				break;
+			}
+		}
+
+		if (found) {
+			dbell->dinb(mport, dbell->dev_id, DBELL_SID(idb.bytes),
+				    DBELL_TID(idb.bytes), DBELL_INF(idb.bytes));
+		} else {
+			dev_dbg(&priv->pdev->dev,
+				"spurious inb doorbell, sid %2.2x tid %2.2x"
+				" info %4.4x\n", DBELL_SID(idb.bytes),
+				DBELL_TID(idb.bytes), DBELL_INF(idb.bytes));
+		}
+	}
+
+	iowrite32(rd_ptr & (IDB_QSIZE - 1),
+		priv->regs + TSI721_IDQ_RP(IDB_QUEUE));
+
+	/* Re-enable IDB interrupts */
+	regval = ioread32(priv->regs + TSI721_SR_CHINTE(IDB_QUEUE));
+	regval |= TSI721_SR_CHINT_IDBQRCV;
+	iowrite32(regval,
+		priv->regs + TSI721_SR_CHINTE(IDB_QUEUE));
+}
+
+/**
+ * tsi721_irqhandler - Tsi721 interrupt handler
+ * @irq: Linux interrupt number
+ * @ptr: Pointer to interrupt-specific data (mport structure)
+ *
+ * Handles Tsi721 interrupts signaled using MSI and INTA. Checks reported
+ * interrupt events and calls an event-specific handler(s).
+ */
+static irqreturn_t tsi721_irqhandler(int irq, void *ptr)
+{
+	struct rio_mport *mport = (struct rio_mport *)ptr;
+	struct tsi721_device *priv = mport->priv;
+	u32 dev_int;
+	u32 dev_ch_int;
+	u32 intval;
+	u32 ch_inte;
+
+	dev_int = ioread32(priv->regs + TSI721_DEV_INT);
+	if (!dev_int)
+		return IRQ_NONE;
+
+	dev_ch_int = ioread32(priv->regs + TSI721_DEV_CHAN_INT);
+
+	if (dev_int & TSI721_DEV_INT_SR2PC_CH) {
+		/* Service SR2PC Channel interrupts */
+		if (dev_ch_int & TSI721_INT_SR2PC_CHAN(IDB_QUEUE)) {
+			/* Service Inbound Doorbell interrupt */
+			intval = ioread32(priv->regs +
+						TSI721_SR_CHINT(IDB_QUEUE));
+			if (intval & TSI721_SR_CHINT_IDBQRCV)
+				tsi721_dbell_handler(mport);
+			else
+				dev_info(&priv->pdev->dev,
+					"Unsupported SR_CH_INT %x\n", intval);
+
+			/* Clear interrupts */
+			iowrite32(intval,
+				priv->regs + TSI721_SR_CHINT(IDB_QUEUE));
+			ioread32(priv->regs + TSI721_SR_CHINT(IDB_QUEUE));
+		}
+	}
+
+	if (dev_int & TSI721_DEV_INT_SMSG_CH) {
+		int ch;
+
+		/*
+		 * Service channel interrupts from Messaging Engine
+		 */
+
+		if (dev_ch_int & TSI721_INT_IMSG_CHAN_M) { /* Inbound Msg */
+			/* Disable signaled OB MSG Channel interrupts */
+			ch_inte = ioread32(priv->regs + TSI721_DEV_CHAN_INTE);
+			ch_inte &= ~(dev_ch_int & TSI721_INT_IMSG_CHAN_M);
+			iowrite32(ch_inte, priv->regs + TSI721_DEV_CHAN_INTE);
+
+			/*
+			 * Process Inbound Message interrupt for each MBOX
+			 */
+			for (ch = 4; ch < RIO_MAX_MBOX + 4; ch++) {
+				if (!(dev_ch_int & TSI721_INT_IMSG_CHAN(ch)))
+					continue;
+				tsi721_imsg_handler(priv, ch);
+			}
+		}
+
+		if (dev_ch_int & TSI721_INT_OMSG_CHAN_M) { /* Outbound Msg */
+			/* Disable signaled OB MSG Channel interrupts */
+			ch_inte = ioread32(priv->regs + TSI721_DEV_CHAN_INTE);
+			ch_inte &= ~(dev_ch_int & TSI721_INT_OMSG_CHAN_M);
+			iowrite32(ch_inte, priv->regs + TSI721_DEV_CHAN_INTE);
+
+			/*
+			 * Process Outbound Message interrupts for each MBOX
+			 */
+
+			for (ch = 0; ch < RIO_MAX_MBOX; ch++) {
+				if (!(dev_ch_int & TSI721_INT_OMSG_CHAN(ch)))
+					continue;
+				tsi721_omsg_handler(priv, ch);
+			}
+		}
+	}
+
+	if (dev_int & TSI721_DEV_INT_SRIO) {
+		/* Service SRIO MAC interrupts */
+		intval = ioread32(priv->regs + TSI721_RIO_EM_INT_STAT);
+		if (intval & TSI721_RIO_EM_INT_STAT_PW_RX)
+			tsi721_pw_handler(mport);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void tsi721_interrupts_init(struct tsi721_device *priv)
+{
+	u32 intr;
+
+	/* Enable IDB interrupts */
+	iowrite32(TSI721_SR_CHINT_ALL,
+		priv->regs + TSI721_SR_CHINT(IDB_QUEUE));
+	iowrite32(TSI721_SR_CHINT_IDBQRCV,
+		priv->regs + TSI721_SR_CHINTE(IDB_QUEUE));
+	iowrite32(TSI721_INT_SR2PC_CHAN(IDB_QUEUE),
+		priv->regs + TSI721_DEV_CHAN_INTE);
+
+	/* Enable SRIO MAC interrupts */
+	iowrite32(TSI721_RIO_EM_DEV_INT_EN_INT,
+		priv->regs + TSI721_RIO_EM_DEV_INT_EN);
+
+	if (priv->flags & TSI721_USING_MSIX)
+		intr = TSI721_DEV_INT_SRIO;
+	else
+		intr = TSI721_DEV_INT_SR2PC_CH | TSI721_DEV_INT_SRIO |
+			TSI721_DEV_INT_SMSG_CH;
+
+	iowrite32(intr, priv->regs + TSI721_DEV_INTE);
+	ioread32(priv->regs + TSI721_DEV_INTE);
+}
+
+#ifdef CONFIG_PCI_MSI
+/**
+ * tsi721_omsg_msix - MSI-X interrupt handler for outbound messaging
+ * @irq: Linux interrupt number
+ * @ptr: Pointer to interrupt-specific data (mport structure)
+ *
+ * Handles outbound messaging interrupts signaled using MSI-X.
+ */
+static irqreturn_t tsi721_omsg_msix(int irq, void *ptr)
+{
+	struct tsi721_device *priv = ((struct rio_mport *)ptr)->priv;
+	int mbox;
+
+	mbox = (irq - priv->msix[TSI721_VECT_OMB0_DONE].vector) % RIO_MAX_MBOX;
+	tsi721_omsg_handler(priv, mbox);
+	return IRQ_HANDLED;
+}
+
+/**
+ * tsi721_imsg_msix - MSI-X interrupt handler for inbound messaging
+ * @irq: Linux interrupt number
+ * @ptr: Pointer to interrupt-specific data (mport structure)
+ *
+ * Handles inbound messaging interrupts signaled using MSI-X.
+ */
+static irqreturn_t tsi721_imsg_msix(int irq, void *ptr)
+{
+	struct tsi721_device *priv = ((struct rio_mport *)ptr)->priv;
+	int mbox;
+
+	mbox = (irq - priv->msix[TSI721_VECT_IMB0_RCV].vector) % RIO_MAX_MBOX;
+	tsi721_imsg_handler(priv, mbox + 4);
+	return IRQ_HANDLED;
+}
+
+/**
+ * tsi721_srio_msix - Tsi721 MSI-X SRIO MAC interrupt handler
+ * @irq: Linux interrupt number
+ * @ptr: Pointer to interrupt-specific data (mport structure)
+ *
+ * Handles Tsi721 interrupts from SRIO MAC.
+ */
+static irqreturn_t tsi721_srio_msix(int irq, void *ptr)
+{
+	struct tsi721_device *priv = ((struct rio_mport *)ptr)->priv;
+	u32 srio_int;
+
+	/* Service SRIO MAC interrupts */
+	srio_int = ioread32(priv->regs + TSI721_RIO_EM_INT_STAT);
+	if (srio_int & TSI721_RIO_EM_INT_STAT_PW_RX)
+		tsi721_pw_handler((struct rio_mport *)ptr);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * tsi721_sr2pc_ch_msix - Tsi721 MSI-X SR2PC Channel interrupt handler
+ * @irq: Linux interrupt number
+ * @ptr: Pointer to interrupt-specific data (mport structure)
+ *
+ * Handles Tsi721 interrupts from SR2PC Channel.
+ * NOTE: At this moment services only one SR2PC channel associated with inbound
+ * doorbells.
+ */
+static irqreturn_t tsi721_sr2pc_ch_msix(int irq, void *ptr)
+{
+	struct tsi721_device *priv = ((struct rio_mport *)ptr)->priv;
+	u32 sr_ch_int;
+
+	/* Service Inbound DB interrupt from SR2PC channel */
+	sr_ch_int = ioread32(priv->regs + TSI721_SR_CHINT(IDB_QUEUE));
+	if (sr_ch_int & TSI721_SR_CHINT_IDBQRCV)
+		tsi721_dbell_handler((struct rio_mport *)ptr);
+
+	/* Clear interrupts */
+	iowrite32(sr_ch_int, priv->regs + TSI721_SR_CHINT(IDB_QUEUE));
+	/* Read back to ensure that interrupt was cleared */
+	sr_ch_int = ioread32(priv->regs + TSI721_SR_CHINT(IDB_QUEUE));
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * tsi721_request_msix - register interrupt service for MSI-X mode.
+ * @mport: RapidIO master port structure
+ *
+ * Registers MSI-X interrupt service routines for interrupts that are active
+ * immediately after mport initialization. Messaging interrupt service routines
+ * should be registered during corresponding open requests.
+ */
+static int tsi721_request_msix(struct rio_mport *mport)
+{
+	struct tsi721_device *priv = mport->priv;
+	int err = 0;
+
+	err = request_irq(priv->msix[TSI721_VECT_IDB].vector,
+			tsi721_sr2pc_ch_msix, 0,
+			priv->msix[TSI721_VECT_IDB].irq_name, (void *)mport);
+	if (err)
+		goto out;
+
+	err = request_irq(priv->msix[TSI721_VECT_PWRX].vector,
+			tsi721_srio_msix, 0,
+			priv->msix[TSI721_VECT_PWRX].irq_name, (void *)mport);
+	if (err)
+		free_irq(
+			priv->msix[TSI721_VECT_IDB].vector,
+			(void *)mport);
+out:
+	return err;
+}
+
+/**
+ * tsi721_enable_msix - Attempts to enable MSI-X support for Tsi721.
+ * @priv: pointer to tsi721 private data
+ *
+ * Configures MSI-X support for Tsi721. Supports only an exact number
+ * of requested vectors.
+ */
+static int tsi721_enable_msix(struct tsi721_device *priv)
+{
+	struct msix_entry entries[TSI721_VECT_MAX];
+	int err;
+	int i;
+
+	entries[TSI721_VECT_IDB].entry = TSI721_MSIX_SR2PC_IDBQ_RCV(IDB_QUEUE);
+	entries[TSI721_VECT_PWRX].entry = TSI721_MSIX_SRIO_MAC_INT;
+
+	/*
+	 * Initialize MSI-X entries for Messaging Engine:
+	 * this driver supports four RIO mailboxes (inbound and outbound)
+	 * NOTE: Inbound message MBOX 0...4 use IB channels 4...7. Therefore
+	 * offset +4 is added to IB MBOX number.
+	 */
+	for (i = 0; i < RIO_MAX_MBOX; i++) {
+		entries[TSI721_VECT_IMB0_RCV + i].entry =
+					TSI721_MSIX_IMSG_DQ_RCV(i + 4);
+		entries[TSI721_VECT_IMB0_INT + i].entry =
+					TSI721_MSIX_IMSG_INT(i + 4);
+		entries[TSI721_VECT_OMB0_DONE + i].entry =
+					TSI721_MSIX_OMSG_DONE(i);
+		entries[TSI721_VECT_OMB0_INT + i].entry =
+					TSI721_MSIX_OMSG_INT(i);
+	}
+
+	err = pci_enable_msix(priv->pdev, entries, ARRAY_SIZE(entries));
+	if (err) {
+		if (err > 0)
+			dev_info(&priv->pdev->dev,
+				 "Only %d MSI-X vectors available, "
+				 "not using MSI-X\n", err);
+		return err;
+	}
+
+	/*
+	 * Copy MSI-X vector information into tsi721 private structure
+	 */
+	priv->msix[TSI721_VECT_IDB].vector = entries[TSI721_VECT_IDB].vector;
+	snprintf(priv->msix[TSI721_VECT_IDB].irq_name, IRQ_DEVICE_NAME_MAX,
+		 DRV_NAME "-idb@pci:%s", pci_name(priv->pdev));
+	priv->msix[TSI721_VECT_PWRX].vector = entries[TSI721_VECT_PWRX].vector;
+	snprintf(priv->msix[TSI721_VECT_PWRX].irq_name, IRQ_DEVICE_NAME_MAX,
+		 DRV_NAME "-pwrx@pci:%s", pci_name(priv->pdev));
+
+	for (i = 0; i < RIO_MAX_MBOX; i++) {
+		priv->msix[TSI721_VECT_IMB0_RCV + i].vector =
+				entries[TSI721_VECT_IMB0_RCV + i].vector;
+		snprintf(priv->msix[TSI721_VECT_IMB0_RCV + i].irq_name,
+			 IRQ_DEVICE_NAME_MAX, DRV_NAME "-imbr%d@pci:%s",
+			 i, pci_name(priv->pdev));
+
+		priv->msix[TSI721_VECT_IMB0_INT + i].vector =
+				entries[TSI721_VECT_IMB0_INT + i].vector;
+		snprintf(priv->msix[TSI721_VECT_IMB0_INT + i].irq_name,
+			 IRQ_DEVICE_NAME_MAX, DRV_NAME "-imbi%d@pci:%s",
+			 i, pci_name(priv->pdev));
+
+		priv->msix[TSI721_VECT_OMB0_DONE + i].vector =
+				entries[TSI721_VECT_OMB0_DONE + i].vector;
+		snprintf(priv->msix[TSI721_VECT_OMB0_DONE + i].irq_name,
+			 IRQ_DEVICE_NAME_MAX, DRV_NAME "-ombd%d@pci:%s",
+			 i, pci_name(priv->pdev));
+
+		priv->msix[TSI721_VECT_OMB0_INT + i].vector =
+				entries[TSI721_VECT_OMB0_INT + i].vector;
+		snprintf(priv->msix[TSI721_VECT_OMB0_INT + i].irq_name,
+			 IRQ_DEVICE_NAME_MAX, DRV_NAME "-ombi%d@pci:%s",
+			 i, pci_name(priv->pdev));
+	}
+
+	return 0;
+}
+#endif /* CONFIG_PCI_MSI */
+
+static int tsi721_request_irq(struct rio_mport *mport)
+{
+	struct tsi721_device *priv = mport->priv;
+	int err;
+
+#ifdef CONFIG_PCI_MSI
+	if (priv->flags & TSI721_USING_MSIX)
+		err = tsi721_request_msix(mport);
+	else
+#endif
+		err = request_irq(priv->pdev->irq, tsi721_irqhandler,
+			  (priv->flags & TSI721_USING_MSI) ? 0 : IRQF_SHARED,
+			  DRV_NAME, (void *)mport);
+
+	if (err)
+		dev_err(&priv->pdev->dev,
+			"Unable to allocate interrupt, Error: %d\n", err);
+
+	return err;
+}
+
+/**
+ * tsi721_init_pc2sr_mapping - initializes outbound (PCIe->SRIO)
+ * translation regions.
+ * @priv: pointer to tsi721 private data
+ *
+ * Disables SREP translation regions.
+ */
+static void tsi721_init_pc2sr_mapping(struct tsi721_device *priv)
+{
+	int i;
+
+	/* Disable all PC2SR translation windows */
+	for (i = 0; i < TSI721_OBWIN_NUM; i++)
+		iowrite32(0, priv->regs + TSI721_OBWINLB(i));
+}
+
+/**
+ * tsi721_init_sr2pc_mapping - initializes inbound (SRIO->PCIe)
+ * translation regions.
+ * @priv: pointer to tsi721 private data
+ *
+ * Disables inbound windows.
+ */
+static void tsi721_init_sr2pc_mapping(struct tsi721_device *priv)
+{
+	int i;
+
+	/* Disable all SR2PC inbound windows */
+	for (i = 0; i < TSI721_IBWIN_NUM; i++)
+		iowrite32(0, priv->regs + TSI721_IBWINLB(i));
+}
+
+/**
+ * tsi721_port_write_init - Inbound port write interface init
+ * @priv: pointer to tsi721 private data
+ *
+ * Initializes inbound port write handler.
+ * Returns %0 on success or %-ENOMEM on failure.
+ */
+static int tsi721_port_write_init(struct tsi721_device *priv)
+{
+	priv->pw_discard_count = 0;
+	INIT_WORK(&priv->pw_work, tsi721_pw_dpc);
+	spin_lock_init(&priv->pw_fifo_lock);
+	if (kfifo_alloc(&priv->pw_fifo,
+			TSI721_RIO_PW_MSG_SIZE * 32, GFP_KERNEL)) {
+		dev_err(&priv->pdev->dev, "PW FIFO allocation failed\n");
+		return -ENOMEM;
+	}
+
+	/* Use reliable port-write capture mode */
+	iowrite32(TSI721_RIO_PW_CTL_PWC_REL, priv->regs + TSI721_RIO_PW_CTL);
+	return 0;
+}
+
+static int tsi721_doorbell_init(struct tsi721_device *priv)
+{
+	/* Outbound Doorbells do not require any setup.
+	 * Tsi721 uses dedicated PCI BAR1 to generate doorbells.
+	 * That BAR1 was mapped during the probe routine.
+	 */
+
+	/* Initialize Inbound Doorbell processing DPC and queue */
+	priv->db_discard_count = 0;
+	INIT_WORK(&priv->idb_work, tsi721_db_dpc);
+
+	/* Allocate buffer for inbound doorbells queue */
+	priv->idb_base = dma_alloc_coherent(&priv->pdev->dev,
+				IDB_QSIZE * TSI721_IDB_ENTRY_SIZE,
+				&priv->idb_dma, GFP_KERNEL);
+	if (!priv->idb_base)
+		return -ENOMEM;
+
+	memset(priv->idb_base, 0, IDB_QSIZE * TSI721_IDB_ENTRY_SIZE);
+
+	dev_dbg(&priv->pdev->dev, "Allocated IDB buffer @ %p (phys = %llx)\n",
+		priv->idb_base, (unsigned long long)priv->idb_dma);
+
+	iowrite32(TSI721_IDQ_SIZE_VAL(IDB_QSIZE),
+		priv->regs + TSI721_IDQ_SIZE(IDB_QUEUE));
+	iowrite32(((u64)priv->idb_dma >> 32),
+		priv->regs + TSI721_IDQ_BASEU(IDB_QUEUE));
+	iowrite32(((u64)priv->idb_dma & TSI721_IDQ_BASEL_ADDR),
+		priv->regs + TSI721_IDQ_BASEL(IDB_QUEUE));
+	/* Enable accepting all inbound doorbells */
+	iowrite32(0, priv->regs + TSI721_IDQ_MASK(IDB_QUEUE));
+
+	iowrite32(TSI721_IDQ_INIT, priv->regs + TSI721_IDQ_CTL(IDB_QUEUE));
+
+	iowrite32(0, priv->regs + TSI721_IDQ_RP(IDB_QUEUE));
+
+	return 0;
+}
+
+static void tsi721_doorbell_free(struct tsi721_device *priv)
+{
+	if (priv->idb_base == NULL)
+		return;
+
+	/* Free buffer allocated for inbound doorbell queue */
+	dma_free_coherent(&priv->pdev->dev, IDB_QSIZE * TSI721_IDB_ENTRY_SIZE,
+			  priv->idb_base, priv->idb_dma);
+	priv->idb_base = NULL;
+}
+
+static int tsi721_bdma_ch_init(struct tsi721_device *priv, int chnum)
+{
+	struct tsi721_dma_desc *bd_ptr;
+	u64		*sts_ptr;
+	dma_addr_t	bd_phys, sts_phys;
+	int		sts_size;
+	int		bd_num = priv->bdma[chnum].bd_num;
+
+	dev_dbg(&priv->pdev->dev, "Init Block DMA Engine, CH%d\n", chnum);
+
+	/*
+	 * Initialize DMA channel for maintenance requests
+	 */
+
+	/* Allocate space for DMA descriptors */
+	bd_ptr = dma_alloc_coherent(&priv->pdev->dev,
+					bd_num * sizeof(struct tsi721_dma_desc),
+					&bd_phys, GFP_KERNEL);
+	if (!bd_ptr)
+		return -ENOMEM;
+
+	priv->bdma[chnum].bd_phys = bd_phys;
+	priv->bdma[chnum].bd_base = bd_ptr;
+
+	memset(bd_ptr, 0, bd_num * sizeof(struct tsi721_dma_desc));
+
+	dev_dbg(&priv->pdev->dev, "DMA descriptors @ %p (phys = %llx)\n",
+		bd_ptr, (unsigned long long)bd_phys);
+
+	/* Allocate space for descriptor status FIFO */
+	sts_size = (bd_num >= TSI721_DMA_MINSTSSZ) ?
+					bd_num : TSI721_DMA_MINSTSSZ;
+	sts_size = roundup_pow_of_two(sts_size);
+	sts_ptr = dma_alloc_coherent(&priv->pdev->dev,
+				     sts_size * sizeof(struct tsi721_dma_sts),
+				     &sts_phys, GFP_KERNEL);
+	if (!sts_ptr) {
+		/* Free space allocated for DMA descriptors */
+		dma_free_coherent(&priv->pdev->dev,
+				  bd_num * sizeof(struct tsi721_dma_desc),
+				  bd_ptr, bd_phys);
+		priv->bdma[chnum].bd_base = NULL;
+		return -ENOMEM;
+	}
+
+	priv->bdma[chnum].sts_phys = sts_phys;
+	priv->bdma[chnum].sts_base = sts_ptr;
+	priv->bdma[chnum].sts_size = sts_size;
+
+	memset(sts_ptr, 0, sts_size);
+
+	dev_dbg(&priv->pdev->dev,
+		"desc status FIFO @ %p (phys = %llx) size=0x%x\n",
+		sts_ptr, (unsigned long long)sts_phys, sts_size);
+
+	/* Initialize DMA descriptors ring */
+	bd_ptr[bd_num - 1].type_id = cpu_to_le32(DTYPE3 << 29);
+	bd_ptr[bd_num - 1].next_lo = cpu_to_le32((u64)bd_phys &
+						 TSI721_DMAC_DPTRL_MASK);
+	bd_ptr[bd_num - 1].next_hi = cpu_to_le32((u64)bd_phys >> 32);
+
+	/* Setup DMA descriptor pointers */
+	iowrite32(((u64)bd_phys >> 32),
+		priv->regs + TSI721_DMAC_DPTRH(chnum));
+	iowrite32(((u64)bd_phys & TSI721_DMAC_DPTRL_MASK),
+		priv->regs + TSI721_DMAC_DPTRL(chnum));
+
+	/* Setup descriptor status FIFO */
+	iowrite32(((u64)sts_phys >> 32),
+		priv->regs + TSI721_DMAC_DSBH(chnum));
+	iowrite32(((u64)sts_phys & TSI721_DMAC_DSBL_MASK),
+		priv->regs + TSI721_DMAC_DSBL(chnum));
+	iowrite32(TSI721_DMAC_DSSZ_SIZE(sts_size),
+		priv->regs + TSI721_DMAC_DSSZ(chnum));
+
+	/* Clear interrupt bits */
+	iowrite32(TSI721_DMAC_INT_ALL,
+		priv->regs + TSI721_DMAC_INT(chnum));
+
+	ioread32(priv->regs + TSI721_DMAC_INT(chnum));
+
+	/* Toggle DMA channel initialization */
+	iowrite32(TSI721_DMAC_CTL_INIT,	priv->regs + TSI721_DMAC_CTL(chnum));
+	ioread32(priv->regs + TSI721_DMAC_CTL(chnum));
+	udelay(10);
+
+	return 0;
+}
+
+static int tsi721_bdma_ch_free(struct tsi721_device *priv, int chnum)
+{
+	u32 ch_stat;
+
+	if (priv->bdma[chnum].bd_base == NULL)
+		return 0;
+
+	/* Check if DMA channel still running */
+	ch_stat = ioread32(priv->regs +	TSI721_DMAC_STS(chnum));
+	if (ch_stat & TSI721_DMAC_STS_RUN)
+		return -EFAULT;
+
+	/* Put DMA channel into init state */
+	iowrite32(TSI721_DMAC_CTL_INIT,
+		priv->regs + TSI721_DMAC_CTL(chnum));
+
+	/* Free space allocated for DMA descriptors */
+	dma_free_coherent(&priv->pdev->dev,
+		priv->bdma[chnum].bd_num * sizeof(struct tsi721_dma_desc),
+		priv->bdma[chnum].bd_base, priv->bdma[chnum].bd_phys);
+	priv->bdma[chnum].bd_base = NULL;
+
+	/* Free space allocated for status FIFO */
+	dma_free_coherent(&priv->pdev->dev,
+		priv->bdma[chnum].sts_size * sizeof(struct tsi721_dma_sts),
+		priv->bdma[chnum].sts_base, priv->bdma[chnum].sts_phys);
+	priv->bdma[chnum].sts_base = NULL;
+	return 0;
+}
+
+static int tsi721_bdma_init(struct tsi721_device *priv)
+{
+	/* Initialize BDMA channel allocated for RapidIO maintenance read/write
+	 * request generation
+	 */
+	priv->bdma[TSI721_DMACH_MAINT].bd_num = 2;
+	if (tsi721_bdma_ch_init(priv, TSI721_DMACH_MAINT)) {
+		dev_err(&priv->pdev->dev, "Unable to initialize maintenance DMA"
+			" channel %d, aborting\n", TSI721_DMACH_MAINT);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void tsi721_bdma_free(struct tsi721_device *priv)
+{
+	tsi721_bdma_ch_free(priv, TSI721_DMACH_MAINT);
+}
+
+/* Enable Inbound Messaging Interrupts */
+static void
+tsi721_imsg_interrupt_enable(struct tsi721_device *priv, int ch,
+				  u32 inte_mask)
+{
+	u32 rval;
+
+	if (!inte_mask)
+		return;
+
+	/* Clear pending Inbound Messaging interrupts */
+	iowrite32(inte_mask, priv->regs + TSI721_IBDMAC_INT(ch));
+
+	/* Enable Inbound Messaging interrupts */
+	rval = ioread32(priv->regs + TSI721_IBDMAC_INTE(ch));
+	iowrite32(rval | inte_mask, priv->regs + TSI721_IBDMAC_INTE(ch));
+
+	if (priv->flags & TSI721_USING_MSIX)
+		return; /* Finished if we are in MSI-X mode */
+
+	/*
+	 * For MSI and INTA interrupt signalling we need to enable next levels
+	 */
+
+	/* Enable Device Channel Interrupt */
+	rval = ioread32(priv->regs + TSI721_DEV_CHAN_INTE);
+	iowrite32(rval | TSI721_INT_IMSG_CHAN(ch),
+		  priv->regs + TSI721_DEV_CHAN_INTE);
+}
+
+/* Disable Inbound Messaging Interrupts */
+static void
+tsi721_imsg_interrupt_disable(struct tsi721_device *priv, int ch,
+				   u32 inte_mask)
+{
+	u32 rval;
+
+	if (!inte_mask)
+		return;
+
+	/* Clear pending Inbound Messaging interrupts */
+	iowrite32(inte_mask, priv->regs + TSI721_IBDMAC_INT(ch));
+
+	/* Disable Inbound Messaging interrupts */
+	rval = ioread32(priv->regs + TSI721_IBDMAC_INTE(ch));
+	rval &= ~inte_mask;
+	iowrite32(rval, priv->regs + TSI721_IBDMAC_INTE(ch));
+
+	if (priv->flags & TSI721_USING_MSIX)
+		return; /* Finished if we are in MSI-X mode */
+
+	/*
+	 * For MSI and INTA interrupt signalling we need to disable next levels
+	 */
+
+	/* Disable Device Channel Interrupt */
+	rval = ioread32(priv->regs + TSI721_DEV_CHAN_INTE);
+	rval &= ~TSI721_INT_IMSG_CHAN(ch);
+	iowrite32(rval, priv->regs + TSI721_DEV_CHAN_INTE);
+}
+
+/* Enable Outbound Messaging interrupts */
+static void
+tsi721_omsg_interrupt_enable(struct tsi721_device *priv, int ch,
+				  u32 inte_mask)
+{
+	u32 rval;
+
+	if (!inte_mask)
+		return;
+
+	/* Clear pending Outbound Messaging interrupts */
+	iowrite32(inte_mask, priv->regs + TSI721_OBDMAC_INT(ch));
+
+	/* Enable Outbound Messaging channel interrupts */
+	rval = ioread32(priv->regs + TSI721_OBDMAC_INTE(ch));
+	iowrite32(rval | inte_mask, priv->regs + TSI721_OBDMAC_INTE(ch));
+
+	if (priv->flags & TSI721_USING_MSIX)
+		return; /* Finished if we are in MSI-X mode */
+
+	/*
+	 * For MSI and INTA interrupt signalling we need to enable next levels
+	 */
+
+	/* Enable Device Channel Interrupt */
+	rval = ioread32(priv->regs + TSI721_DEV_CHAN_INTE);
+	iowrite32(rval | TSI721_INT_OMSG_CHAN(ch),
+		  priv->regs + TSI721_DEV_CHAN_INTE);
+}
+
+/* Disable Outbound Messaging interrupts */
+static void
+tsi721_omsg_interrupt_disable(struct tsi721_device *priv, int ch,
+				   u32 inte_mask)
+{
+	u32 rval;
+
+	if (!inte_mask)
+		return;
+
+	/* Clear pending Outbound Messaging interrupts */
+	iowrite32(inte_mask, priv->regs + TSI721_OBDMAC_INT(ch));
+
+	/* Disable Outbound Messaging interrupts */
+	rval = ioread32(priv->regs + TSI721_OBDMAC_INTE(ch));
+	rval &= ~inte_mask;
+	iowrite32(rval, priv->regs + TSI721_OBDMAC_INTE(ch));
+
+	if (priv->flags & TSI721_USING_MSIX)
+		return; /* Finished if we are in MSI-X mode */
+
+	/*
+	 * For MSI and INTA interrupt signalling we need to disable next levels
+	 */
+
+	/* Disable Device Channel Interrupt */
+	rval = ioread32(priv->regs + TSI721_DEV_CHAN_INTE);
+	rval &= ~TSI721_INT_OMSG_CHAN(ch);
+	iowrite32(rval, priv->regs + TSI721_DEV_CHAN_INTE);
+}
+
+/**
+ * tsi721_add_outb_message - Add message to the Tsi721 outbound message queue
+ * @mport: Master port with outbound message queue
+ * @rdev: Target of outbound message
+ * @mbox: Outbound mailbox
+ * @buffer: Message to add to outbound queue
+ * @len: Length of message
+ */
+static int
+tsi721_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox,
+			void *buffer, size_t len)
+{
+	struct tsi721_device *priv = mport->priv;
+	struct tsi721_omsg_desc *desc;
+	u32 tx_slot;
+
+	if (!priv->omsg_init[mbox] ||
+	    len > TSI721_MSG_MAX_SIZE || len < 8)
+		return -EINVAL;
+
+	tx_slot = priv->omsg_ring[mbox].tx_slot;
+
+	/* Copy copy message into transfer buffer */
+	memcpy(priv->omsg_ring[mbox].omq_base[tx_slot], buffer, len);
+
+	if (len & 0x7)
+		len += 8;
+
+	/* Build descriptor associated with buffer */
+	desc = priv->omsg_ring[mbox].omd_base;
+	desc[tx_slot].type_id = cpu_to_le32((DTYPE4 << 29) | rdev->destid);
+	if (tx_slot % 4 == 0)
+		desc[tx_slot].type_id |= cpu_to_le32(TSI721_OMD_IOF);
+
+	desc[tx_slot].msg_info =
+		cpu_to_le32((mport->sys_size << 26) | (mbox << 22) |
+			    (0xe << 12) | (len & 0xff8));
+	desc[tx_slot].bufptr_lo =
+		cpu_to_le32((u64)priv->omsg_ring[mbox].omq_phys[tx_slot] &
+			    0xffffffff);
+	desc[tx_slot].bufptr_hi =
+		cpu_to_le32((u64)priv->omsg_ring[mbox].omq_phys[tx_slot] >> 32);
+
+	priv->omsg_ring[mbox].wr_count++;
+
+	/* Go to next descriptor */
+	if (++priv->omsg_ring[mbox].tx_slot == priv->omsg_ring[mbox].size) {
+		priv->omsg_ring[mbox].tx_slot = 0;
+		/* Move through the ring link descriptor at the end */
+		priv->omsg_ring[mbox].wr_count++;
+	}
+
+	mb();
+
+	/* Set new write count value */
+	iowrite32(priv->omsg_ring[mbox].wr_count,
+		priv->regs + TSI721_OBDMAC_DWRCNT(mbox));
+	ioread32(priv->regs + TSI721_OBDMAC_DWRCNT(mbox));
+
+	return 0;
+}
+
+/**
+ * tsi721_omsg_handler - Outbound Message Interrupt Handler
+ * @priv: pointer to tsi721 private data
+ * @ch:   number of OB MSG channel to service
+ *
+ * Services channel interrupts from outbound messaging engine.
+ */
+static void tsi721_omsg_handler(struct tsi721_device *priv, int ch)
+{
+	u32 omsg_int;
+
+	spin_lock(&priv->omsg_ring[ch].lock);
+
+	omsg_int = ioread32(priv->regs + TSI721_OBDMAC_INT(ch));
+
+	if (omsg_int & TSI721_OBDMAC_INT_ST_FULL)
+		dev_info(&priv->pdev->dev,
+			"OB MBOX%d: Status FIFO is full\n", ch);
+
+	if (omsg_int & (TSI721_OBDMAC_INT_DONE | TSI721_OBDMAC_INT_IOF_DONE)) {
+		u32 srd_ptr;
+		u64 *sts_ptr, last_ptr = 0, prev_ptr = 0;
+		int i, j;
+		u32 tx_slot;
+
+		/*
+		 * Find last successfully processed descriptor
+		 */
+
+		/* Check and clear descriptor status FIFO entries */
+		srd_ptr = priv->omsg_ring[ch].sts_rdptr;
+		sts_ptr = priv->omsg_ring[ch].sts_base;
+		j = srd_ptr * 8;
+		while (sts_ptr[j]) {
+			for (i = 0; i < 8 && sts_ptr[j]; i++, j++) {
+				prev_ptr = last_ptr;
+				last_ptr = le64_to_cpu(sts_ptr[j]);
+				sts_ptr[j] = 0;
+			}
+
+			++srd_ptr;
+			srd_ptr %= priv->omsg_ring[ch].sts_size;
+			j = srd_ptr * 8;
+		}
+
+		if (last_ptr == 0)
+			goto no_sts_update;
+
+		priv->omsg_ring[ch].sts_rdptr = srd_ptr;
+		iowrite32(srd_ptr, priv->regs + TSI721_OBDMAC_DSRP(ch));
+
+		if (!priv->mport->outb_msg[ch].mcback)
+			goto no_sts_update;
+
+		/* Inform upper layer about transfer completion */
+
+		tx_slot = (last_ptr - (u64)priv->omsg_ring[ch].omd_phys)/
+						sizeof(struct tsi721_omsg_desc);
+
+		/*
+		 * Check if this is a Link Descriptor (LD).
+		 * If yes, ignore LD and use descriptor processed
+		 * before LD.
+		 */
+		if (tx_slot == priv->omsg_ring[ch].size) {
+			if (prev_ptr)
+				tx_slot = (prev_ptr -
+					(u64)priv->omsg_ring[ch].omd_phys)/
+						sizeof(struct tsi721_omsg_desc);
+			else
+				goto no_sts_update;
+		}
+
+		/* Move slot index to the next message to be sent */
+		++tx_slot;
+		if (tx_slot == priv->omsg_ring[ch].size)
+			tx_slot = 0;
+		BUG_ON(tx_slot >= priv->omsg_ring[ch].size);
+		priv->mport->outb_msg[ch].mcback(priv->mport,
+				priv->omsg_ring[ch].dev_id, ch,
+				tx_slot);
+	}
+
+no_sts_update:
+
+	if (omsg_int & TSI721_OBDMAC_INT_ERROR) {
+		/*
+		* Outbound message operation aborted due to error,
+		* reinitialize OB MSG channel
+		*/
+
+		dev_dbg(&priv->pdev->dev, "OB MSG ABORT ch_stat=%x\n",
+			ioread32(priv->regs + TSI721_OBDMAC_STS(ch)));
+
+		iowrite32(TSI721_OBDMAC_INT_ERROR,
+				priv->regs + TSI721_OBDMAC_INT(ch));
+		iowrite32(TSI721_OBDMAC_CTL_INIT,
+				priv->regs + TSI721_OBDMAC_CTL(ch));
+		ioread32(priv->regs + TSI721_OBDMAC_CTL(ch));
+
+		/* Inform upper level to clear all pending tx slots */
+		if (priv->mport->outb_msg[ch].mcback)
+			priv->mport->outb_msg[ch].mcback(priv->mport,
+					priv->omsg_ring[ch].dev_id, ch,
+					priv->omsg_ring[ch].tx_slot);
+		/* Synch tx_slot tracking */
+		iowrite32(priv->omsg_ring[ch].tx_slot,
+			priv->regs + TSI721_OBDMAC_DRDCNT(ch));
+		ioread32(priv->regs + TSI721_OBDMAC_DRDCNT(ch));
+		priv->omsg_ring[ch].wr_count = priv->omsg_ring[ch].tx_slot;
+		priv->omsg_ring[ch].sts_rdptr = 0;
+	}
+
+	/* Clear channel interrupts */
+	iowrite32(omsg_int, priv->regs + TSI721_OBDMAC_INT(ch));
+
+	if (!(priv->flags & TSI721_USING_MSIX)) {
+		u32 ch_inte;
+
+		/* Re-enable channel interrupts */
+		ch_inte = ioread32(priv->regs + TSI721_DEV_CHAN_INTE);
+		ch_inte |= TSI721_INT_OMSG_CHAN(ch);
+		iowrite32(ch_inte, priv->regs + TSI721_DEV_CHAN_INTE);
+	}
+
+	spin_unlock(&priv->omsg_ring[ch].lock);
+}
+
+/**
+ * tsi721_open_outb_mbox - Initialize Tsi721 outbound mailbox
+ * @mport: Master port implementing Outbound Messaging Engine
+ * @dev_id: Device specific pointer to pass on event
+ * @mbox: Mailbox to open
+ * @entries: Number of entries in the outbound mailbox ring
+ */
+static int tsi721_open_outb_mbox(struct rio_mport *mport, void *dev_id,
+				 int mbox, int entries)
+{
+	struct tsi721_device *priv = mport->priv;
+	struct tsi721_omsg_desc *bd_ptr;
+	int i, rc = 0;
+
+	if ((entries < TSI721_OMSGD_MIN_RING_SIZE) ||
+	    (entries > (TSI721_OMSGD_RING_SIZE)) ||
+	    (!is_power_of_2(entries)) || mbox >= RIO_MAX_MBOX) {
+		rc = -EINVAL;
+		goto out;
+	}
+
+	priv->omsg_ring[mbox].dev_id = dev_id;
+	priv->omsg_ring[mbox].size = entries;
+	priv->omsg_ring[mbox].sts_rdptr = 0;
+	spin_lock_init(&priv->omsg_ring[mbox].lock);
+
+	/* Outbound Msg Buffer allocation based on
+	   the number of maximum descriptor entries */
+	for (i = 0; i < entries; i++) {
+		priv->omsg_ring[mbox].omq_base[i] =
+			dma_alloc_coherent(
+				&priv->pdev->dev, TSI721_MSG_BUFFER_SIZE,
+				&priv->omsg_ring[mbox].omq_phys[i],
+				GFP_KERNEL);
+		if (priv->omsg_ring[mbox].omq_base[i] == NULL) {
+			dev_dbg(&priv->pdev->dev,
+				"Unable to allocate OB MSG data buffer for"
+				" MBOX%d\n", mbox);
+			rc = -ENOMEM;
+			goto out_buf;
+		}
+	}
+
+	/* Outbound message descriptor allocation */
+	priv->omsg_ring[mbox].omd_base = dma_alloc_coherent(
+				&priv->pdev->dev,
+				(entries + 1) * sizeof(struct tsi721_omsg_desc),
+				&priv->omsg_ring[mbox].omd_phys, GFP_KERNEL);
+	if (priv->omsg_ring[mbox].omd_base == NULL) {
+		dev_dbg(&priv->pdev->dev,
+			"Unable to allocate OB MSG descriptor memory "
+			"for MBOX%d\n", mbox);
+		rc = -ENOMEM;
+		goto out_buf;
+	}
+
+	priv->omsg_ring[mbox].tx_slot = 0;
+
+	/* Outbound message descriptor status FIFO allocation */
+	priv->omsg_ring[mbox].sts_size = roundup_pow_of_two(entries + 1);
+	priv->omsg_ring[mbox].sts_base = dma_alloc_coherent(&priv->pdev->dev,
+			priv->omsg_ring[mbox].sts_size *
+						sizeof(struct tsi721_dma_sts),
+			&priv->omsg_ring[mbox].sts_phys, GFP_KERNEL);
+	if (priv->omsg_ring[mbox].sts_base == NULL) {
+		dev_dbg(&priv->pdev->dev,
+			"Unable to allocate OB MSG descriptor status FIFO "
+			"for MBOX%d\n", mbox);
+		rc = -ENOMEM;
+		goto out_desc;
+	}
+
+	memset(priv->omsg_ring[mbox].sts_base, 0,
+		entries * sizeof(struct tsi721_dma_sts));
+
+	/*
+	 * Configure Outbound Messaging Engine
+	 */
+
+	/* Setup Outbound Message descriptor pointer */
+	iowrite32(((u64)priv->omsg_ring[mbox].omd_phys >> 32),
+			priv->regs + TSI721_OBDMAC_DPTRH(mbox));
+	iowrite32(((u64)priv->omsg_ring[mbox].omd_phys &
+					TSI721_OBDMAC_DPTRL_MASK),
+			priv->regs + TSI721_OBDMAC_DPTRL(mbox));
+
+	/* Setup Outbound Message descriptor status FIFO */
+	iowrite32(((u64)priv->omsg_ring[mbox].sts_phys >> 32),
+			priv->regs + TSI721_OBDMAC_DSBH(mbox));
+	iowrite32(((u64)priv->omsg_ring[mbox].sts_phys &
+					TSI721_OBDMAC_DSBL_MASK),
+			priv->regs + TSI721_OBDMAC_DSBL(mbox));
+	iowrite32(TSI721_DMAC_DSSZ_SIZE(priv->omsg_ring[mbox].sts_size),
+		priv->regs + (u32)TSI721_OBDMAC_DSSZ(mbox));
+
+	/* Enable interrupts */
+
+#ifdef CONFIG_PCI_MSI
+	if (priv->flags & TSI721_USING_MSIX) {
+		/* Request interrupt service if we are in MSI-X mode */
+		rc = request_irq(
+			priv->msix[TSI721_VECT_OMB0_DONE + mbox].vector,
+			tsi721_omsg_msix, 0,
+			priv->msix[TSI721_VECT_OMB0_DONE + mbox].irq_name,
+			(void *)mport);
+
+		if (rc) {
+			dev_dbg(&priv->pdev->dev,
+				"Unable to allocate MSI-X interrupt for "
+				"OBOX%d-DONE\n", mbox);
+			goto out_stat;
+		}
+
+		rc = request_irq(priv->msix[TSI721_VECT_OMB0_INT + mbox].vector,
+			tsi721_omsg_msix, 0,
+			priv->msix[TSI721_VECT_OMB0_INT + mbox].irq_name,
+			(void *)mport);
+
+		if (rc)	{
+			dev_dbg(&priv->pdev->dev,
+				"Unable to allocate MSI-X interrupt for "
+				"MBOX%d-INT\n", mbox);
+			free_irq(
+				priv->msix[TSI721_VECT_OMB0_DONE + mbox].vector,
+				(void *)mport);
+			goto out_stat;
+		}
+	}
+#endif /* CONFIG_PCI_MSI */
+
+	tsi721_omsg_interrupt_enable(priv, mbox, TSI721_OBDMAC_INT_ALL);
+
+	/* Initialize Outbound Message descriptors ring */
+	bd_ptr = priv->omsg_ring[mbox].omd_base;
+	bd_ptr[entries].type_id = cpu_to_le32(DTYPE5 << 29);
+	bd_ptr[entries].msg_info = 0;
+	bd_ptr[entries].next_lo =
+		cpu_to_le32((u64)priv->omsg_ring[mbox].omd_phys &
+		TSI721_OBDMAC_DPTRL_MASK);
+	bd_ptr[entries].next_hi =
+		cpu_to_le32((u64)priv->omsg_ring[mbox].omd_phys >> 32);
+	priv->omsg_ring[mbox].wr_count = 0;
+	mb();
+
+	/* Initialize Outbound Message engine */
+	iowrite32(TSI721_OBDMAC_CTL_INIT, priv->regs + TSI721_OBDMAC_CTL(mbox));
+	ioread32(priv->regs + TSI721_OBDMAC_DWRCNT(mbox));
+	udelay(10);
+
+	priv->omsg_init[mbox] = 1;
+
+	return 0;
+
+#ifdef CONFIG_PCI_MSI
+out_stat:
+	dma_free_coherent(&priv->pdev->dev,
+		priv->omsg_ring[mbox].sts_size * sizeof(struct tsi721_dma_sts),
+		priv->omsg_ring[mbox].sts_base,
+		priv->omsg_ring[mbox].sts_phys);
+
+	priv->omsg_ring[mbox].sts_base = NULL;
+#endif /* CONFIG_PCI_MSI */
+
+out_desc:
+	dma_free_coherent(&priv->pdev->dev,
+		(entries + 1) * sizeof(struct tsi721_omsg_desc),
+		priv->omsg_ring[mbox].omd_base,
+		priv->omsg_ring[mbox].omd_phys);
+
+	priv->omsg_ring[mbox].omd_base = NULL;
+
+out_buf:
+	for (i = 0; i < priv->omsg_ring[mbox].size; i++) {
+		if (priv->omsg_ring[mbox].omq_base[i]) {
+			dma_free_coherent(&priv->pdev->dev,
+				TSI721_MSG_BUFFER_SIZE,
+				priv->omsg_ring[mbox].omq_base[i],
+				priv->omsg_ring[mbox].omq_phys[i]);
+
+			priv->omsg_ring[mbox].omq_base[i] = NULL;
+		}
+	}
+
+out:
+	return rc;
+}
+
+/**
+ * tsi721_close_outb_mbox - Close Tsi721 outbound mailbox
+ * @mport: Master port implementing the outbound message unit
+ * @mbox: Mailbox to close
+ */
+static void tsi721_close_outb_mbox(struct rio_mport *mport, int mbox)
+{
+	struct tsi721_device *priv = mport->priv;
+	u32 i;
+
+	if (!priv->omsg_init[mbox])
+		return;
+	priv->omsg_init[mbox] = 0;
+
+	/* Disable Interrupts */
+
+	tsi721_omsg_interrupt_disable(priv, mbox, TSI721_OBDMAC_INT_ALL);
+
+#ifdef CONFIG_PCI_MSI
+	if (priv->flags & TSI721_USING_MSIX) {
+		free_irq(priv->msix[TSI721_VECT_OMB0_DONE + mbox].vector,
+			 (void *)mport);
+		free_irq(priv->msix[TSI721_VECT_OMB0_INT + mbox].vector,
+			 (void *)mport);
+	}
+#endif /* CONFIG_PCI_MSI */
+
+	/* Free OMSG Descriptor Status FIFO */
+	dma_free_coherent(&priv->pdev->dev,
+		priv->omsg_ring[mbox].sts_size * sizeof(struct tsi721_dma_sts),
+		priv->omsg_ring[mbox].sts_base,
+		priv->omsg_ring[mbox].sts_phys);
+
+	priv->omsg_ring[mbox].sts_base = NULL;
+
+	/* Free OMSG descriptors */
+	dma_free_coherent(&priv->pdev->dev,
+		(priv->omsg_ring[mbox].size + 1) *
+			sizeof(struct tsi721_omsg_desc),
+		priv->omsg_ring[mbox].omd_base,
+		priv->omsg_ring[mbox].omd_phys);
+
+	priv->omsg_ring[mbox].omd_base = NULL;
+
+	/* Free message buffers */
+	for (i = 0; i < priv->omsg_ring[mbox].size; i++) {
+		if (priv->omsg_ring[mbox].omq_base[i]) {
+			dma_free_coherent(&priv->pdev->dev,
+				TSI721_MSG_BUFFER_SIZE,
+				priv->omsg_ring[mbox].omq_base[i],
+				priv->omsg_ring[mbox].omq_phys[i]);
+
+			priv->omsg_ring[mbox].omq_base[i] = NULL;
+		}
+	}
+}
+
+/**
+ * tsi721_imsg_handler - Inbound Message Interrupt Handler
+ * @priv: pointer to tsi721 private data
+ * @ch: inbound message channel number to service
+ *
+ * Services channel interrupts from inbound messaging engine.
+ */
+static void tsi721_imsg_handler(struct tsi721_device *priv, int ch)
+{
+	u32 mbox = ch - 4;
+	u32 imsg_int;
+
+	spin_lock(&priv->imsg_ring[mbox].lock);
+
+	imsg_int = ioread32(priv->regs + TSI721_IBDMAC_INT(ch));
+
+	if (imsg_int & TSI721_IBDMAC_INT_SRTO)
+		dev_info(&priv->pdev->dev, "IB MBOX%d SRIO timeout\n",
+			mbox);
+
+	if (imsg_int & TSI721_IBDMAC_INT_PC_ERROR)
+		dev_info(&priv->pdev->dev, "IB MBOX%d PCIe error\n",
+			mbox);
+
+	if (imsg_int & TSI721_IBDMAC_INT_FQ_LOW)
+		dev_info(&priv->pdev->dev,
+			"IB MBOX%d IB free queue low\n", mbox);
+
+	/* Clear IB channel interrupts */
+	iowrite32(imsg_int, priv->regs + TSI721_IBDMAC_INT(ch));
+
+	/* If an IB Msg is received notify the upper layer */
+	if (imsg_int & TSI721_IBDMAC_INT_DQ_RCV &&
+		priv->mport->inb_msg[mbox].mcback)
+		priv->mport->inb_msg[mbox].mcback(priv->mport,
+				priv->imsg_ring[mbox].dev_id, mbox, -1);
+
+	if (!(priv->flags & TSI721_USING_MSIX)) {
+		u32 ch_inte;
+
+		/* Re-enable channel interrupts */
+		ch_inte = ioread32(priv->regs + TSI721_DEV_CHAN_INTE);
+		ch_inte |= TSI721_INT_IMSG_CHAN(ch);
+		iowrite32(ch_inte, priv->regs + TSI721_DEV_CHAN_INTE);
+	}
+
+	spin_unlock(&priv->imsg_ring[mbox].lock);
+}
+
+/**
+ * tsi721_open_inb_mbox - Initialize Tsi721 inbound mailbox
+ * @mport: Master port implementing the Inbound Messaging Engine
+ * @dev_id: Device specific pointer to pass on event
+ * @mbox: Mailbox to open
+ * @entries: Number of entries in the inbound mailbox ring
+ */
+static int tsi721_open_inb_mbox(struct rio_mport *mport, void *dev_id,
+				int mbox, int entries)
+{
+	struct tsi721_device *priv = mport->priv;
+	int ch = mbox + 4;
+	int i;
+	u64 *free_ptr;
+	int rc = 0;
+
+	if ((entries < TSI721_IMSGD_MIN_RING_SIZE) ||
+	    (entries > TSI721_IMSGD_RING_SIZE) ||
+	    (!is_power_of_2(entries)) || mbox >= RIO_MAX_MBOX) {
+		rc = -EINVAL;
+		goto out;
+	}
+
+	/* Initialize IB Messaging Ring */
+	priv->imsg_ring[mbox].dev_id = dev_id;
+	priv->imsg_ring[mbox].size = entries;
+	priv->imsg_ring[mbox].rx_slot = 0;
+	priv->imsg_ring[mbox].desc_rdptr = 0;
+	priv->imsg_ring[mbox].fq_wrptr = 0;
+	for (i = 0; i < priv->imsg_ring[mbox].size; i++)
+		priv->imsg_ring[mbox].imq_base[i] = NULL;
+	spin_lock_init(&priv->imsg_ring[mbox].lock);
+
+	/* Allocate buffers for incoming messages */
+	priv->imsg_ring[mbox].buf_base =
+		dma_alloc_coherent(&priv->pdev->dev,
+				   entries * TSI721_MSG_BUFFER_SIZE,
+				   &priv->imsg_ring[mbox].buf_phys,
+				   GFP_KERNEL);
+
+	if (priv->imsg_ring[mbox].buf_base == NULL) {
+		dev_err(&priv->pdev->dev,
+			"Failed to allocate buffers for IB MBOX%d\n", mbox);
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	/* Allocate memory for circular free list */
+	priv->imsg_ring[mbox].imfq_base =
+		dma_alloc_coherent(&priv->pdev->dev,
+				   entries * 8,
+				   &priv->imsg_ring[mbox].imfq_phys,
+				   GFP_KERNEL);
+
+	if (priv->imsg_ring[mbox].imfq_base == NULL) {
+		dev_err(&priv->pdev->dev,
+			"Failed to allocate free queue for IB MBOX%d\n", mbox);
+		rc = -ENOMEM;
+		goto out_buf;
+	}
+
+	/* Allocate memory for Inbound message descriptors */
+	priv->imsg_ring[mbox].imd_base =
+		dma_alloc_coherent(&priv->pdev->dev,
+				   entries * sizeof(struct tsi721_imsg_desc),
+				   &priv->imsg_ring[mbox].imd_phys, GFP_KERNEL);
+
+	if (priv->imsg_ring[mbox].imd_base == NULL) {
+		dev_err(&priv->pdev->dev,
+			"Failed to allocate descriptor memory for IB MBOX%d\n",
+			mbox);
+		rc = -ENOMEM;
+		goto out_dma;
+	}
+
+	/* Fill free buffer pointer list */
+	free_ptr = priv->imsg_ring[mbox].imfq_base;
+	for (i = 0; i < entries; i++)
+		free_ptr[i] = cpu_to_le64(
+				(u64)(priv->imsg_ring[mbox].buf_phys) +
+				i * 0x1000);
+
+	mb();
+
+	/*
+	 * For mapping of inbound SRIO Messages into appropriate queues we need
+	 * to set Inbound Device ID register in the messaging engine. We do it
+	 * once when first inbound mailbox is requested.
+	 */
+	if (!(priv->flags & TSI721_IMSGID_SET)) {
+		iowrite32((u32)priv->mport->host_deviceid,
+			priv->regs + TSI721_IB_DEVID);
+		priv->flags |= TSI721_IMSGID_SET;
+	}
+
+	/*
+	 * Configure Inbound Messaging channel (ch = mbox + 4)
+	 */
+
+	/* Setup Inbound Message free queue */
+	iowrite32(((u64)priv->imsg_ring[mbox].imfq_phys >> 32),
+		priv->regs + TSI721_IBDMAC_FQBH(ch));
+	iowrite32(((u64)priv->imsg_ring[mbox].imfq_phys &
+			TSI721_IBDMAC_FQBL_MASK),
+		priv->regs+TSI721_IBDMAC_FQBL(ch));
+	iowrite32(TSI721_DMAC_DSSZ_SIZE(entries),
+		priv->regs + TSI721_IBDMAC_FQSZ(ch));
+
+	/* Setup Inbound Message descriptor queue */
+	iowrite32(((u64)priv->imsg_ring[mbox].imd_phys >> 32),
+		priv->regs + TSI721_IBDMAC_DQBH(ch));
+	iowrite32(((u32)priv->imsg_ring[mbox].imd_phys &
+		   (u32)TSI721_IBDMAC_DQBL_MASK),
+		priv->regs+TSI721_IBDMAC_DQBL(ch));
+	iowrite32(TSI721_DMAC_DSSZ_SIZE(entries),
+		priv->regs + TSI721_IBDMAC_DQSZ(ch));
+
+	/* Enable interrupts */
+
+#ifdef CONFIG_PCI_MSI
+	if (priv->flags & TSI721_USING_MSIX) {
+		/* Request interrupt service if we are in MSI-X mode */
+		rc = request_irq(priv->msix[TSI721_VECT_IMB0_RCV + mbox].vector,
+			tsi721_imsg_msix, 0,
+			priv->msix[TSI721_VECT_IMB0_RCV + mbox].irq_name,
+			(void *)mport);
+
+		if (rc) {
+			dev_dbg(&priv->pdev->dev,
+				"Unable to allocate MSI-X interrupt for "
+				"IBOX%d-DONE\n", mbox);
+			goto out_desc;
+		}
+
+		rc = request_irq(priv->msix[TSI721_VECT_IMB0_INT + mbox].vector,
+			tsi721_imsg_msix, 0,
+			priv->msix[TSI721_VECT_IMB0_INT + mbox].irq_name,
+			(void *)mport);
+
+		if (rc)	{
+			dev_dbg(&priv->pdev->dev,
+				"Unable to allocate MSI-X interrupt for "
+				"IBOX%d-INT\n", mbox);
+			free_irq(
+				priv->msix[TSI721_VECT_IMB0_RCV + mbox].vector,
+				(void *)mport);
+			goto out_desc;
+		}
+	}
+#endif /* CONFIG_PCI_MSI */
+
+	tsi721_imsg_interrupt_enable(priv, ch, TSI721_IBDMAC_INT_ALL);
+
+	/* Initialize Inbound Message Engine */
+	iowrite32(TSI721_IBDMAC_CTL_INIT, priv->regs + TSI721_IBDMAC_CTL(ch));
+	ioread32(priv->regs + TSI721_IBDMAC_CTL(ch));
+	udelay(10);
+	priv->imsg_ring[mbox].fq_wrptr = entries - 1;
+	iowrite32(entries - 1, priv->regs + TSI721_IBDMAC_FQWP(ch));
+
+	priv->imsg_init[mbox] = 1;
+	return 0;
+
+#ifdef CONFIG_PCI_MSI
+out_desc:
+	dma_free_coherent(&priv->pdev->dev,
+		priv->imsg_ring[mbox].size * sizeof(struct tsi721_imsg_desc),
+		priv->imsg_ring[mbox].imd_base,
+		priv->imsg_ring[mbox].imd_phys);
+
+	priv->imsg_ring[mbox].imd_base = NULL;
+#endif /* CONFIG_PCI_MSI */
+
+out_dma:
+	dma_free_coherent(&priv->pdev->dev,
+		priv->imsg_ring[mbox].size * 8,
+		priv->imsg_ring[mbox].imfq_base,
+		priv->imsg_ring[mbox].imfq_phys);
+
+	priv->imsg_ring[mbox].imfq_base = NULL;
+
+out_buf:
+	dma_free_coherent(&priv->pdev->dev,
+		priv->imsg_ring[mbox].size * TSI721_MSG_BUFFER_SIZE,
+		priv->imsg_ring[mbox].buf_base,
+		priv->imsg_ring[mbox].buf_phys);
+
+	priv->imsg_ring[mbox].buf_base = NULL;
+
+out:
+	return rc;
+}
+
+/**
+ * tsi721_close_inb_mbox - Shut down Tsi721 inbound mailbox
+ * @mport: Master port implementing the Inbound Messaging Engine
+ * @mbox: Mailbox to close
+ */
+static void tsi721_close_inb_mbox(struct rio_mport *mport, int mbox)
+{
+	struct tsi721_device *priv = mport->priv;
+	u32 rx_slot;
+	int ch = mbox + 4;
+
+	if (!priv->imsg_init[mbox]) /* mbox isn't initialized yet */
+		return;
+	priv->imsg_init[mbox] = 0;
+
+	/* Disable Inbound Messaging Engine */
+
+	/* Disable Interrupts */
+	tsi721_imsg_interrupt_disable(priv, ch, TSI721_OBDMAC_INT_MASK);
+
+#ifdef CONFIG_PCI_MSI
+	if (priv->flags & TSI721_USING_MSIX) {
+		free_irq(priv->msix[TSI721_VECT_IMB0_RCV + mbox].vector,
+				(void *)mport);
+		free_irq(priv->msix[TSI721_VECT_IMB0_INT + mbox].vector,
+				(void *)mport);
+	}
+#endif /* CONFIG_PCI_MSI */
+
+	/* Clear Inbound Buffer Queue */
+	for (rx_slot = 0; rx_slot < priv->imsg_ring[mbox].size; rx_slot++)
+		priv->imsg_ring[mbox].imq_base[rx_slot] = NULL;
+
+	/* Free memory allocated for message buffers */
+	dma_free_coherent(&priv->pdev->dev,
+		priv->imsg_ring[mbox].size * TSI721_MSG_BUFFER_SIZE,
+		priv->imsg_ring[mbox].buf_base,
+		priv->imsg_ring[mbox].buf_phys);
+
+	priv->imsg_ring[mbox].buf_base = NULL;
+
+	/* Free memory allocated for free pointr list */
+	dma_free_coherent(&priv->pdev->dev,
+		priv->imsg_ring[mbox].size * 8,
+		priv->imsg_ring[mbox].imfq_base,
+		priv->imsg_ring[mbox].imfq_phys);
+
+	priv->imsg_ring[mbox].imfq_base = NULL;
+
+	/* Free memory allocated for RX descriptors */
+	dma_free_coherent(&priv->pdev->dev,
+		priv->imsg_ring[mbox].size * sizeof(struct tsi721_imsg_desc),
+		priv->imsg_ring[mbox].imd_base,
+		priv->imsg_ring[mbox].imd_phys);
+
+	priv->imsg_ring[mbox].imd_base = NULL;
+}
+
+/**
+ * tsi721_add_inb_buffer - Add buffer to the Tsi721 inbound message queue
+ * @mport: Master port implementing the Inbound Messaging Engine
+ * @mbox: Inbound mailbox number
+ * @buf: Buffer to add to inbound queue
+ */
+static int tsi721_add_inb_buffer(struct rio_mport *mport, int mbox, void *buf)
+{
+	struct tsi721_device *priv = mport->priv;
+	u32 rx_slot;
+	int rc = 0;
+
+	rx_slot = priv->imsg_ring[mbox].rx_slot;
+	if (priv->imsg_ring[mbox].imq_base[rx_slot]) {
+		dev_err(&priv->pdev->dev,
+			"Error adding inbound buffer %d, buffer exists\n",
+			rx_slot);
+		rc = -EINVAL;
+		goto out;
+	}
+
+	priv->imsg_ring[mbox].imq_base[rx_slot] = buf;
+
+	if (++priv->imsg_ring[mbox].rx_slot == priv->imsg_ring[mbox].size)
+		priv->imsg_ring[mbox].rx_slot = 0;
+
+out:
+	return rc;
+}
+
+/**
+ * tsi721_get_inb_message - Fetch inbound message from the Tsi721 MSG Queue
+ * @mport: Master port implementing the Inbound Messaging Engine
+ * @mbox: Inbound mailbox number
+ *
+ * Returns pointer to the message on success or NULL on failure.
+ */
+static void *tsi721_get_inb_message(struct rio_mport *mport, int mbox)
+{
+	struct tsi721_device *priv = mport->priv;
+	struct tsi721_imsg_desc *desc;
+	u32 rx_slot;
+	void *rx_virt = NULL;
+	u64 rx_phys;
+	void *buf = NULL;
+	u64 *free_ptr;
+	int ch = mbox + 4;
+	int msg_size;
+
+	if (!priv->imsg_init[mbox])
+		return NULL;
+
+	desc = priv->imsg_ring[mbox].imd_base;
+	desc += priv->imsg_ring[mbox].desc_rdptr;
+
+	if (!(le32_to_cpu(desc->msg_info) & TSI721_IMD_HO))
+		goto out;
+
+	rx_slot = priv->imsg_ring[mbox].rx_slot;
+	while (priv->imsg_ring[mbox].imq_base[rx_slot] == NULL) {
+		if (++rx_slot == priv->imsg_ring[mbox].size)
+			rx_slot = 0;
+	}
+
+	rx_phys = ((u64)le32_to_cpu(desc->bufptr_hi) << 32) |
+			le32_to_cpu(desc->bufptr_lo);
+
+	rx_virt = priv->imsg_ring[mbox].buf_base +
+		  (rx_phys - (u64)priv->imsg_ring[mbox].buf_phys);
+
+	buf = priv->imsg_ring[mbox].imq_base[rx_slot];
+	msg_size = le32_to_cpu(desc->msg_info) & TSI721_IMD_BCOUNT;
+	if (msg_size == 0)
+		msg_size = RIO_MAX_MSG_SIZE;
+
+	memcpy(buf, rx_virt, msg_size);
+	priv->imsg_ring[mbox].imq_base[rx_slot] = NULL;
+
+	desc->msg_info &= cpu_to_le32(~TSI721_IMD_HO);
+	if (++priv->imsg_ring[mbox].desc_rdptr == priv->imsg_ring[mbox].size)
+		priv->imsg_ring[mbox].desc_rdptr = 0;
+
+	iowrite32(priv->imsg_ring[mbox].desc_rdptr,
+		priv->regs + TSI721_IBDMAC_DQRP(ch));
+
+	/* Return free buffer into the pointer list */
+	free_ptr = priv->imsg_ring[mbox].imfq_base;
+	free_ptr[priv->imsg_ring[mbox].fq_wrptr] = cpu_to_le64(rx_phys);
+
+	if (++priv->imsg_ring[mbox].fq_wrptr == priv->imsg_ring[mbox].size)
+		priv->imsg_ring[mbox].fq_wrptr = 0;
+
+	iowrite32(priv->imsg_ring[mbox].fq_wrptr,
+		priv->regs + TSI721_IBDMAC_FQWP(ch));
+out:
+	return buf;
+}
+
+/**
+ * tsi721_messages_init - Initialization of Messaging Engine
+ * @priv: pointer to tsi721 private data
+ *
+ * Configures Tsi721 messaging engine.
+ */
+static int tsi721_messages_init(struct tsi721_device *priv)
+{
+	int	ch;
+
+	iowrite32(0, priv->regs + TSI721_SMSG_ECC_LOG);
+	iowrite32(0, priv->regs + TSI721_RETRY_GEN_CNT);
+	iowrite32(0, priv->regs + TSI721_RETRY_RX_CNT);
+
+	/* Set SRIO Message Request/Response Timeout */
+	iowrite32(TSI721_RQRPTO_VAL, priv->regs + TSI721_RQRPTO);
+
+	/* Initialize Inbound Messaging Engine Registers */
+	for (ch = 0; ch < TSI721_IMSG_CHNUM; ch++) {
+		/* Clear interrupt bits */
+		iowrite32(TSI721_IBDMAC_INT_MASK,
+			priv->regs + TSI721_IBDMAC_INT(ch));
+		/* Clear Status */
+		iowrite32(0, priv->regs + TSI721_IBDMAC_STS(ch));
+
+		iowrite32(TSI721_SMSG_ECC_COR_LOG_MASK,
+				priv->regs + TSI721_SMSG_ECC_COR_LOG(ch));
+		iowrite32(TSI721_SMSG_ECC_NCOR_MASK,
+				priv->regs + TSI721_SMSG_ECC_NCOR(ch));
+	}
+
+	return 0;
+}
+
+/**
+ * tsi721_disable_ints - disables all device interrupts
+ * @priv: pointer to tsi721 private data
+ */
+static void tsi721_disable_ints(struct tsi721_device *priv)
+{
+	int ch;
+
+	/* Disable all device level interrupts */
+	iowrite32(0, priv->regs + TSI721_DEV_INTE);
+
+	/* Disable all Device Channel interrupts */
+	iowrite32(0, priv->regs + TSI721_DEV_CHAN_INTE);
+
+	/* Disable all Inbound Msg Channel interrupts */
+	for (ch = 0; ch < TSI721_IMSG_CHNUM; ch++)
+		iowrite32(0, priv->regs + TSI721_IBDMAC_INTE(ch));
+
+	/* Disable all Outbound Msg Channel interrupts */
+	for (ch = 0; ch < TSI721_OMSG_CHNUM; ch++)
+		iowrite32(0, priv->regs + TSI721_OBDMAC_INTE(ch));
+
+	/* Disable all general messaging interrupts */
+	iowrite32(0, priv->regs + TSI721_SMSG_INTE);
+
+	/* Disable all BDMA Channel interrupts */
+	for (ch = 0; ch < TSI721_DMA_MAXCH; ch++)
+		iowrite32(0, priv->regs + TSI721_DMAC_INTE(ch));
+
+	/* Disable all general BDMA interrupts */
+	iowrite32(0, priv->regs + TSI721_BDMA_INTE);
+
+	/* Disable all SRIO Channel interrupts */
+	for (ch = 0; ch < TSI721_SRIO_MAXCH; ch++)
+		iowrite32(0, priv->regs + TSI721_SR_CHINTE(ch));
+
+	/* Disable all general SR2PC interrupts */
+	iowrite32(0, priv->regs + TSI721_SR2PC_GEN_INTE);
+
+	/* Disable all PC2SR interrupts */
+	iowrite32(0, priv->regs + TSI721_PC2SR_INTE);
+
+	/* Disable all I2C interrupts */
+	iowrite32(0, priv->regs + TSI721_I2C_INT_ENABLE);
+
+	/* Disable SRIO MAC interrupts */
+	iowrite32(0, priv->regs + TSI721_RIO_EM_INT_ENABLE);
+	iowrite32(0, priv->regs + TSI721_RIO_EM_DEV_INT_EN);
+}
+
+/**
+ * tsi721_setup_mport - Setup Tsi721 as RapidIO subsystem master port
+ * @priv: pointer to tsi721 private data
+ *
+ * Configures Tsi721 as RapidIO master port.
+ */
+static int __devinit tsi721_setup_mport(struct tsi721_device *priv)
+{
+	struct pci_dev *pdev = priv->pdev;
+	int err = 0;
+	struct rio_ops *ops;
+
+	struct rio_mport *mport;
+
+	ops = kzalloc(sizeof(struct rio_ops), GFP_KERNEL);
+	if (!ops) {
+		dev_dbg(&pdev->dev, "Unable to allocate memory for rio_ops\n");
+		return -ENOMEM;
+	}
+
+	ops->lcread = tsi721_lcread;
+	ops->lcwrite = tsi721_lcwrite;
+	ops->cread = tsi721_cread_dma;
+	ops->cwrite = tsi721_cwrite_dma;
+	ops->dsend = tsi721_dsend;
+	ops->open_inb_mbox = tsi721_open_inb_mbox;
+	ops->close_inb_mbox = tsi721_close_inb_mbox;
+	ops->open_outb_mbox = tsi721_open_outb_mbox;
+	ops->close_outb_mbox = tsi721_close_outb_mbox;
+	ops->add_outb_message = tsi721_add_outb_message;
+	ops->add_inb_buffer = tsi721_add_inb_buffer;
+	ops->get_inb_message = tsi721_get_inb_message;
+
+	mport = kzalloc(sizeof(struct rio_mport), GFP_KERNEL);
+	if (!mport) {
+		kfree(ops);
+		dev_dbg(&pdev->dev, "Unable to allocate memory for mport\n");
+		return -ENOMEM;
+	}
+
+	mport->ops = ops;
+	mport->index = 0;
+	mport->sys_size = 0; /* small system */
+	mport->phy_type = RIO_PHY_SERIAL;
+	mport->priv = (void *)priv;
+	mport->phys_efptr = 0x100;
+
+	INIT_LIST_HEAD(&mport->dbells);
+
+	rio_init_dbell_res(&mport->riores[RIO_DOORBELL_RESOURCE], 0, 0xffff);
+	rio_init_mbox_res(&mport->riores[RIO_INB_MBOX_RESOURCE], 0, 0);
+	rio_init_mbox_res(&mport->riores[RIO_OUTB_MBOX_RESOURCE], 0, 0);
+	strcpy(mport->name, "Tsi721 mport");
+
+	/* Hook up interrupt handler */
+
+#ifdef CONFIG_PCI_MSI
+	if (!tsi721_enable_msix(priv))
+		priv->flags |= TSI721_USING_MSIX;
+	else if (!pci_enable_msi(pdev))
+		priv->flags |= TSI721_USING_MSI;
+	else
+		dev_info(&pdev->dev,
+			 "MSI/MSI-X is not available. Using legacy INTx.\n");
+#endif /* CONFIG_PCI_MSI */
+
+	err = tsi721_request_irq(mport);
+
+	if (!err) {
+		tsi721_interrupts_init(priv);
+		ops->pwenable = tsi721_pw_enable;
+	} else
+		dev_err(&pdev->dev, "Unable to get assigned PCI IRQ "
+			"vector %02X err=0x%x\n", pdev->irq, err);
+
+	/* Enable SRIO link */
+	iowrite32(ioread32(priv->regs + TSI721_DEVCTL) |
+		  TSI721_DEVCTL_SRBOOT_CMPL,
+		  priv->regs + TSI721_DEVCTL);
+
+	rio_register_mport(mport);
+	priv->mport = mport;
+
+	if (mport->host_deviceid >= 0)
+		iowrite32(RIO_PORT_GEN_HOST | RIO_PORT_GEN_MASTER |
+			  RIO_PORT_GEN_DISCOVERED,
+			  priv->regs + (0x100 + RIO_PORT_GEN_CTL_CSR));
+	else
+		iowrite32(0, priv->regs + (0x100 + RIO_PORT_GEN_CTL_CSR));
+
+	return 0;
+}
+
+static int __devinit tsi721_probe(struct pci_dev *pdev,
+				  const struct pci_device_id *id)
+{
+	struct tsi721_device *priv;
+	int i;
+	int err;
+	u32 regval;
+
+	priv = kzalloc(sizeof(struct tsi721_device), GFP_KERNEL);
+	if (priv == NULL) {
+		dev_err(&pdev->dev, "Failed to allocate memory for device\n");
+		err = -ENOMEM;
+		goto err_exit;
+	}
+
+	err = pci_enable_device(pdev);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to enable PCI device\n");
+		goto err_clean;
+	}
+
+	priv->pdev = pdev;
+
+#ifdef DEBUG
+	for (i = 0; i <= PCI_STD_RESOURCE_END; i++) {
+		dev_dbg(&pdev->dev, "res[%d] @ 0x%llx (0x%lx, 0x%lx)\n",
+			i, (unsigned long long)pci_resource_start(pdev, i),
+			(unsigned long)pci_resource_len(pdev, i),
+			pci_resource_flags(pdev, i));
+	}
+#endif
+	/*
+	 * Verify BAR configuration
+	 */
+
+	/* BAR_0 (registers) must be 512KB+ in 32-bit address space */
+	if (!(pci_resource_flags(pdev, BAR_0) & IORESOURCE_MEM) ||
+	    pci_resource_flags(pdev, BAR_0) & IORESOURCE_MEM_64 ||
+	    pci_resource_len(pdev, BAR_0) < TSI721_REG_SPACE_SIZE) {
+		dev_err(&pdev->dev,
+			"Missing or misconfigured CSR BAR0, aborting.\n");
+		err = -ENODEV;
+		goto err_disable_pdev;
+	}
+
+	/* BAR_1 (outbound doorbells) must be 16MB+ in 32-bit address space */
+	if (!(pci_resource_flags(pdev, BAR_1) & IORESOURCE_MEM) ||
+	    pci_resource_flags(pdev, BAR_1) & IORESOURCE_MEM_64 ||
+	    pci_resource_len(pdev, BAR_1) < TSI721_DB_WIN_SIZE) {
+		dev_err(&pdev->dev,
+			"Missing or misconfigured Doorbell BAR1, aborting.\n");
+		err = -ENODEV;
+		goto err_disable_pdev;
+	}
+
+	/*
+	 * BAR_2 and BAR_4 (outbound translation) must be in 64-bit PCIe address
+	 * space.
+	 * NOTE: BAR_2 and BAR_4 are not used by this version of driver.
+	 * It may be a good idea to keep them disabled using HW configuration
+	 * to save PCI memory space.
+	 */
+	if ((pci_resource_flags(pdev, BAR_2) & IORESOURCE_MEM) &&
+	    (pci_resource_flags(pdev, BAR_2) & IORESOURCE_MEM_64)) {
+		dev_info(&pdev->dev, "Outbound BAR2 is not used but enabled.\n");
+	}
+
+	if ((pci_resource_flags(pdev, BAR_4) & IORESOURCE_MEM) &&
+	    (pci_resource_flags(pdev, BAR_4) & IORESOURCE_MEM_64)) {
+		dev_info(&pdev->dev, "Outbound BAR4 is not used but enabled.\n");
+	}
+
+	err = pci_request_regions(pdev, DRV_NAME);
+	if (err) {
+		dev_err(&pdev->dev, "Cannot obtain PCI resources, "
+			"aborting.\n");
+		goto err_disable_pdev;
+	}
+
+	pci_set_master(pdev);
+
+	priv->regs = pci_ioremap_bar(pdev, BAR_0);
+	if (!priv->regs) {
+		dev_err(&pdev->dev,
+			"Unable to map device registers space, aborting\n");
+		err = -ENOMEM;
+		goto err_free_res;
+	}
+
+	priv->odb_base = pci_ioremap_bar(pdev, BAR_1);
+	if (!priv->odb_base) {
+		dev_err(&pdev->dev,
+			"Unable to map outbound doorbells space, aborting\n");
+		err = -ENOMEM;
+		goto err_unmap_bars;
+	}
+
+	/* Configure DMA attributes. */
+	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+		if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
+			dev_info(&pdev->dev, "Unable to set DMA mask\n");
+			goto err_unmap_bars;
+		}
+
+		if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)))
+			dev_info(&pdev->dev, "Unable to set consistent DMA mask\n");
+	} else {
+		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+		if (err)
+			dev_info(&pdev->dev, "Unable to set consistent DMA mask\n");
+	}
+
+	/* Clear "no snoop" and "relaxed ordering" bits. */
+	pci_read_config_dword(pdev, 0x40 + PCI_EXP_DEVCTL, &regval);
+	regval &= ~(PCI_EXP_DEVCTL_RELAX_EN | PCI_EXP_DEVCTL_NOSNOOP_EN);
+	pci_write_config_dword(pdev, 0x40 + PCI_EXP_DEVCTL, regval);
+
+	/*
+	 * FIXUP: correct offsets of MSI-X tables in the MSI-X Capability Block
+	 */
+	pci_write_config_dword(pdev, TSI721_PCIECFG_EPCTL, 0x01);
+	pci_write_config_dword(pdev, TSI721_PCIECFG_MSIXTBL,
+						TSI721_MSIXTBL_OFFSET);
+	pci_write_config_dword(pdev, TSI721_PCIECFG_MSIXPBA,
+						TSI721_MSIXPBA_OFFSET);
+	pci_write_config_dword(pdev, TSI721_PCIECFG_EPCTL, 0);
+	/* End of FIXUP */
+
+	tsi721_disable_ints(priv);
+
+	tsi721_init_pc2sr_mapping(priv);
+	tsi721_init_sr2pc_mapping(priv);
+
+	if (tsi721_bdma_init(priv)) {
+		dev_err(&pdev->dev, "BDMA initialization failed, aborting\n");
+		err = -ENOMEM;
+		goto err_unmap_bars;
+	}
+
+	err = tsi721_doorbell_init(priv);
+	if (err)
+		goto err_free_bdma;
+
+	tsi721_port_write_init(priv);
+
+	err = tsi721_messages_init(priv);
+	if (err)
+		goto err_free_consistent;
+
+	err = tsi721_setup_mport(priv);
+	if (err)
+		goto err_free_consistent;
+
+	return 0;
+
+err_free_consistent:
+	tsi721_doorbell_free(priv);
+err_free_bdma:
+	tsi721_bdma_free(priv);
+err_unmap_bars:
+	if (priv->regs)
+		iounmap(priv->regs);
+	if (priv->odb_base)
+		iounmap(priv->odb_base);
+err_free_res:
+	pci_release_regions(pdev);
+	pci_clear_master(pdev);
+err_disable_pdev:
+	pci_disable_device(pdev);
+err_clean:
+	kfree(priv);
+err_exit:
+	return err;
+}
+
+static DEFINE_PCI_DEVICE_TABLE(tsi721_pci_tbl) = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_IDT, PCI_DEVICE_ID_TSI721) },
+	{ 0, }	/* terminate list */
+};
+
+MODULE_DEVICE_TABLE(pci, tsi721_pci_tbl);
+
+static struct pci_driver tsi721_driver = {
+	.name		= "tsi721",
+	.id_table	= tsi721_pci_tbl,
+	.probe		= tsi721_probe,
+};
+
+static int __init tsi721_init(void)
+{
+	return pci_register_driver(&tsi721_driver);
+}
+
+static void __exit tsi721_exit(void)
+{
+	pci_unregister_driver(&tsi721_driver);
+}
+
+device_initcall(tsi721_init);
diff --git a/drivers/rapidio/devices/tsi721.h b/drivers/rapidio/devices/tsi721.h
new file mode 100644
index 0000000..58be4de
--- /dev/null
+++ b/drivers/rapidio/devices/tsi721.h
@@ -0,0 +1,766 @@
+/*
+ * Tsi721 PCIExpress-to-SRIO bridge definitions
+ *
+ * Copyright 2011, Integrated Device Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef __TSI721_H
+#define __TSI721_H
+
+#define DRV_NAME	"tsi721"
+
+#define DEFAULT_HOPCOUNT	0xff
+#define DEFAULT_DESTID		0xff
+
+/* PCI device ID */
+#define PCI_DEVICE_ID_TSI721		0x80ab
+
+#define BAR_0	0
+#define BAR_1	1
+#define BAR_2	2
+#define BAR_4	4
+
+#define TSI721_PC2SR_BARS	2
+#define TSI721_PC2SR_WINS	8
+#define TSI721_PC2SR_ZONES	8
+#define TSI721_MAINT_WIN	0 /* Window for outbound maintenance requests */
+#define IDB_QUEUE		0 /* Inbound Doorbell Queue to use */
+#define IDB_QSIZE		512 /* Inbound Doorbell Queue size */
+
+/* Memory space sizes */
+#define TSI721_REG_SPACE_SIZE		(512 * 1024) /* 512K */
+#define TSI721_DB_WIN_SIZE		(16 * 1024 * 1024) /* 16MB */
+
+#define  RIO_TT_CODE_8		0x00000000
+#define  RIO_TT_CODE_16		0x00000001
+
+#define TSI721_DMA_MAXCH	8
+#define TSI721_DMA_MINSTSSZ	32
+#define TSI721_DMA_STSBLKSZ	8
+
+#define TSI721_SRIO_MAXCH	8
+
+#define DBELL_SID(buf)		(((u8)buf[2] << 8) | (u8)buf[3])
+#define DBELL_TID(buf)		(((u8)buf[4] << 8) | (u8)buf[5])
+#define DBELL_INF(buf)		(((u8)buf[0] << 8) | (u8)buf[1])
+
+#define TSI721_RIO_PW_MSG_SIZE	16  /* Tsi721 saves only 16 bytes of PW msg */
+
+/* Register definitions */
+
+/*
+ * Registers in PCIe configuration space
+ */
+
+#define TSI721_PCIECFG_MSIXTBL	0x0a4
+#define TSI721_MSIXTBL_OFFSET	0x2c000
+#define TSI721_PCIECFG_MSIXPBA	0x0a8
+#define TSI721_MSIXPBA_OFFSET	0x2a000
+#define TSI721_PCIECFG_EPCTL	0x400
+
+/*
+ * Event Management Registers
+ */
+
+#define TSI721_RIO_EM_INT_STAT		0x10910
+#define TSI721_RIO_EM_INT_STAT_PW_RX	0x00010000
+
+#define TSI721_RIO_EM_INT_ENABLE	0x10914
+#define TSI721_RIO_EM_INT_ENABLE_PW_RX	0x00010000
+
+#define TSI721_RIO_EM_DEV_INT_EN	0x10930
+#define TSI721_RIO_EM_DEV_INT_EN_INT	0x00000001
+
+/*
+ * Port-Write Block Registers
+ */
+
+#define TSI721_RIO_PW_CTL		0x10a04
+#define TSI721_RIO_PW_CTL_PW_TIMER	0xf0000000
+#define TSI721_RIO_PW_CTL_PWT_DIS	(0 << 28)
+#define TSI721_RIO_PW_CTL_PWT_103	(1 << 28)
+#define TSI721_RIO_PW_CTL_PWT_205	(1 << 29)
+#define TSI721_RIO_PW_CTL_PWT_410	(1 << 30)
+#define TSI721_RIO_PW_CTL_PWT_820	(1 << 31)
+#define TSI721_RIO_PW_CTL_PWC_MODE	0x01000000
+#define TSI721_RIO_PW_CTL_PWC_CONT	0x00000000
+#define TSI721_RIO_PW_CTL_PWC_REL	0x01000000
+
+#define TSI721_RIO_PW_RX_STAT		0x10a10
+#define TSI721_RIO_PW_RX_STAT_WR_SIZE	0x0000f000
+#define TSI_RIO_PW_RX_STAT_WDPTR	0x00000100
+#define TSI721_RIO_PW_RX_STAT_PW_SHORT	0x00000008
+#define TSI721_RIO_PW_RX_STAT_PW_TRUNC	0x00000004
+#define TSI721_RIO_PW_RX_STAT_PW_DISC	0x00000002
+#define TSI721_RIO_PW_RX_STAT_PW_VAL	0x00000001
+
+#define TSI721_RIO_PW_RX_CAPT(x)	(0x10a20 + (x)*4)
+
+/*
+ * Inbound Doorbells
+ */
+
+#define TSI721_IDB_ENTRY_SIZE	64
+
+#define TSI721_IDQ_CTL(x)	(0x20000 + (x) * 1000)
+#define TSI721_IDQ_SUSPEND	0x00000002
+#define TSI721_IDQ_INIT		0x00000001
+
+#define TSI721_IDQ_STS(x)	(0x20004 + (x) * 1000)
+#define TSI721_IDQ_RUN		0x00200000
+
+#define TSI721_IDQ_MASK(x)	(0x20008 + (x) * 1000)
+#define TSI721_IDQ_MASK_MASK	0xffff0000
+#define TSI721_IDQ_MASK_PATT	0x0000ffff
+
+#define TSI721_IDQ_RP(x)	(0x2000c + (x) * 1000)
+#define TSI721_IDQ_RP_PTR	0x0007ffff
+
+#define TSI721_IDQ_WP(x)	(0x20010 + (x) * 1000)
+#define TSI721_IDQ_WP_PTR	0x0007ffff
+
+#define TSI721_IDQ_BASEL(x)	(0x20014 + (x) * 1000)
+#define TSI721_IDQ_BASEL_ADDR	0xffffffc0
+#define TSI721_IDQ_BASEU(x)	(0x20018 + (x) * 1000)
+#define TSI721_IDQ_SIZE(x)	(0x2001c + (x) * 1000)
+#define TSI721_IDQ_SIZE_VAL(size)	(__fls(size) - 4)
+#define TSI721_IDQ_SIZE_MIN	512
+#define TSI721_IDQ_SIZE_MAX	(512 * 1024)
+
+#define TSI721_SR_CHINT(x)	(0x20040 + (x) * 1000)
+#define TSI721_SR_CHINTE(x)	(0x20044 + (x) * 1000)
+#define TSI721_SR_CHINTSET(x)	(0x20048 + (x) * 1000)
+#define TSI721_SR_CHINT_ODBOK	0x00000020
+#define TSI721_SR_CHINT_IDBQRCV	0x00000010
+#define TSI721_SR_CHINT_SUSP	0x00000008
+#define TSI721_SR_CHINT_ODBTO	0x00000004
+#define TSI721_SR_CHINT_ODBRTRY	0x00000002
+#define TSI721_SR_CHINT_ODBERR	0x00000001
+#define TSI721_SR_CHINT_ALL	0x0000003f
+
+#define TSI721_IBWIN_NUM	8
+
+#define TSI721_IBWINLB(x)	(0x29000 + (x) * 20)
+#define TSI721_IBWINLB_BA	0xfffff000
+#define TSI721_IBWINLB_WEN	0x00000001
+
+#define TSI721_SR2PC_GEN_INTE	0x29800
+#define TSI721_SR2PC_PWE	0x29804
+#define TSI721_SR2PC_GEN_INT	0x29808
+
+#define TSI721_DEV_INTE		0x29840
+#define TSI721_DEV_INT		0x29844
+#define TSI721_DEV_INTSET	0x29848
+#define TSI721_DEV_INT_SMSG_CH	0x00000800
+#define TSI721_DEV_INT_SMSG_NCH	0x00000400
+#define TSI721_DEV_INT_SR2PC_CH	0x00000200
+#define TSI721_DEV_INT_SRIO	0x00000020
+
+#define TSI721_DEV_CHAN_INTE	0x2984c
+#define TSI721_DEV_CHAN_INT	0x29850
+
+#define TSI721_INT_SR2PC_CHAN_M	0xff000000
+#define TSI721_INT_SR2PC_CHAN(x) (1 << (24 + (x)))
+#define TSI721_INT_IMSG_CHAN_M	0x00ff0000
+#define TSI721_INT_IMSG_CHAN(x)	(1 << (16 + (x)))
+#define TSI721_INT_OMSG_CHAN_M	0x0000ff00
+#define TSI721_INT_OMSG_CHAN(x)	(1 << (8 + (x)))
+
+/*
+ * PC2SR block registers
+ */
+#define TSI721_OBWIN_NUM	TSI721_PC2SR_WINS
+
+#define TSI721_OBWINLB(x)	(0x40000 + (x) * 20)
+#define TSI721_OBWINLB_BA	0xffff8000
+#define TSI721_OBWINLB_WEN	0x00000001
+
+#define TSI721_OBWINUB(x)	(0x40004 + (x) * 20)
+
+#define TSI721_OBWINSZ(x)	(0x40008 + (x) * 20)
+#define TSI721_OBWINSZ_SIZE	0x00001f00
+#define TSI721_OBWIN_SIZE(size)	(__fls(size) - 15)
+
+#define TSI721_ZONE_SEL		0x41300
+#define TSI721_ZONE_SEL_RD_WRB	0x00020000
+#define TSI721_ZONE_SEL_GO	0x00010000
+#define TSI721_ZONE_SEL_WIN	0x00000038
+#define TSI721_ZONE_SEL_ZONE	0x00000007
+
+#define TSI721_LUT_DATA0	0x41304
+#define TSI721_LUT_DATA0_ADD	0xfffff000
+#define TSI721_LUT_DATA0_RDTYPE	0x00000f00
+#define TSI721_LUT_DATA0_NREAD	0x00000100
+#define TSI721_LUT_DATA0_MNTRD	0x00000200
+#define TSI721_LUT_DATA0_RDCRF	0x00000020
+#define TSI721_LUT_DATA0_WRCRF	0x00000010
+#define TSI721_LUT_DATA0_WRTYPE	0x0000000f
+#define TSI721_LUT_DATA0_NWR	0x00000001
+#define TSI721_LUT_DATA0_MNTWR	0x00000002
+#define TSI721_LUT_DATA0_NWR_R	0x00000004
+
+#define TSI721_LUT_DATA1	0x41308
+
+#define TSI721_LUT_DATA2	0x4130c
+#define TSI721_LUT_DATA2_HC	0xff000000
+#define TSI721_LUT_DATA2_ADD65	0x000c0000
+#define TSI721_LUT_DATA2_TT	0x00030000
+#define TSI721_LUT_DATA2_DSTID	0x0000ffff
+
+#define TSI721_PC2SR_INTE	0x41310
+
+#define TSI721_DEVCTL		0x48004
+#define TSI721_DEVCTL_SRBOOT_CMPL	0x00000004
+
+#define TSI721_I2C_INT_ENABLE	0x49120
+
+/*
+ * Block DMA Engine Registers
+ *   x = 0..7
+ */
+
+#define TSI721_DMAC_DWRCNT(x)	(0x51000 + (x) * 0x1000)
+#define TSI721_DMAC_DRDCNT(x)	(0x51004 + (x) * 0x1000)
+
+#define TSI721_DMAC_CTL(x)	(0x51008 + (x) * 0x1000)
+#define TSI721_DMAC_CTL_SUSP	0x00000002
+#define TSI721_DMAC_CTL_INIT	0x00000001
+
+#define TSI721_DMAC_INT(x)	(0x5100c + (x) * 0x1000)
+#define TSI721_DMAC_INT_STFULL	0x00000010
+#define TSI721_DMAC_INT_DONE	0x00000008
+#define TSI721_DMAC_INT_SUSP	0x00000004
+#define TSI721_DMAC_INT_ERR	0x00000002
+#define TSI721_DMAC_INT_IOFDONE	0x00000001
+#define TSI721_DMAC_INT_ALL	0x0000001f
+
+#define TSI721_DMAC_INTSET(x)	(0x51010 + (x) * 0x1000)
+
+#define TSI721_DMAC_STS(x)	(0x51014 + (x) * 0x1000)
+#define TSI721_DMAC_STS_ABORT	0x00400000
+#define TSI721_DMAC_STS_RUN	0x00200000
+#define TSI721_DMAC_STS_CS	0x001f0000
+
+#define TSI721_DMAC_INTE(x)	(0x51018 + (x) * 0x1000)
+
+#define TSI721_DMAC_DPTRL(x)	(0x51024 + (x) * 0x1000)
+#define TSI721_DMAC_DPTRL_MASK	0xffffffe0
+
+#define TSI721_DMAC_DPTRH(x)	(0x51028 + (x) * 0x1000)
+
+#define TSI721_DMAC_DSBL(x)	(0x5102c + (x) * 0x1000)
+#define TSI721_DMAC_DSBL_MASK	0xffffffc0
+
+#define TSI721_DMAC_DSBH(x)	(0x51030 + (x) * 0x1000)
+
+#define TSI721_DMAC_DSSZ(x)	(0x51034 + (x) * 0x1000)
+#define TSI721_DMAC_DSSZ_SIZE_M	0x0000000f
+#define TSI721_DMAC_DSSZ_SIZE(size)	(__fls(size) - 4)
+
+
+#define TSI721_DMAC_DSRP(x)	(0x51038 + (x) * 0x1000)
+#define TSI721_DMAC_DSRP_MASK	0x0007ffff
+
+#define TSI721_DMAC_DSWP(x)	(0x5103c + (x) * 0x1000)
+#define TSI721_DMAC_DSWP_MASK	0x0007ffff
+
+#define TSI721_BDMA_INTE	0x5f000
+
+/*
+ * Messaging definitions
+ */
+#define TSI721_MSG_BUFFER_SIZE		RIO_MAX_MSG_SIZE
+#define TSI721_MSG_MAX_SIZE		RIO_MAX_MSG_SIZE
+#define TSI721_IMSG_MAXCH		8
+#define TSI721_IMSG_CHNUM		TSI721_IMSG_MAXCH
+#define TSI721_IMSGD_MIN_RING_SIZE	32
+#define TSI721_IMSGD_RING_SIZE		512
+
+#define TSI721_OMSG_CHNUM		4 /* One channel per MBOX */
+#define TSI721_OMSGD_MIN_RING_SIZE	32
+#define TSI721_OMSGD_RING_SIZE		512
+
+/*
+ * Outbound Messaging Engine Registers
+ *   x = 0..7
+ */
+
+#define TSI721_OBDMAC_DWRCNT(x)		(0x61000 + (x) * 0x1000)
+
+#define TSI721_OBDMAC_DRDCNT(x)		(0x61004 + (x) * 0x1000)
+
+#define TSI721_OBDMAC_CTL(x)		(0x61008 + (x) * 0x1000)
+#define TSI721_OBDMAC_CTL_MASK		0x00000007
+#define TSI721_OBDMAC_CTL_RETRY_THR	0x00000004
+#define TSI721_OBDMAC_CTL_SUSPEND	0x00000002
+#define TSI721_OBDMAC_CTL_INIT		0x00000001
+
+#define TSI721_OBDMAC_INT(x)		(0x6100c + (x) * 0x1000)
+#define TSI721_OBDMAC_INTSET(x)		(0x61010 + (x) * 0x1000)
+#define TSI721_OBDMAC_INTE(x)		(0x61018 + (x) * 0x1000)
+#define TSI721_OBDMAC_INT_MASK		0x0000001F
+#define TSI721_OBDMAC_INT_ST_FULL	0x00000010
+#define TSI721_OBDMAC_INT_DONE		0x00000008
+#define TSI721_OBDMAC_INT_SUSPENDED	0x00000004
+#define TSI721_OBDMAC_INT_ERROR		0x00000002
+#define TSI721_OBDMAC_INT_IOF_DONE	0x00000001
+#define TSI721_OBDMAC_INT_ALL		TSI721_OBDMAC_INT_MASK
+
+#define TSI721_OBDMAC_STS(x)		(0x61014 + (x) * 0x1000)
+#define TSI721_OBDMAC_STS_MASK		0x007f0000
+#define TSI721_OBDMAC_STS_ABORT		0x00400000
+#define TSI721_OBDMAC_STS_RUN		0x00200000
+#define TSI721_OBDMAC_STS_CS		0x001f0000
+
+#define TSI721_OBDMAC_PWE(x)		(0x6101c + (x) * 0x1000)
+#define TSI721_OBDMAC_PWE_MASK		0x00000002
+#define TSI721_OBDMAC_PWE_ERROR_EN	0x00000002
+
+#define TSI721_OBDMAC_DPTRL(x)		(0x61020 + (x) * 0x1000)
+#define TSI721_OBDMAC_DPTRL_MASK	0xfffffff0
+
+#define TSI721_OBDMAC_DPTRH(x)		(0x61024 + (x) * 0x1000)
+#define TSI721_OBDMAC_DPTRH_MASK	0xffffffff
+
+#define TSI721_OBDMAC_DSBL(x)		(0x61040 + (x) * 0x1000)
+#define TSI721_OBDMAC_DSBL_MASK		0xffffffc0
+
+#define TSI721_OBDMAC_DSBH(x)		(0x61044 + (x) * 0x1000)
+#define TSI721_OBDMAC_DSBH_MASK		0xffffffff
+
+#define TSI721_OBDMAC_DSSZ(x)		(0x61048 + (x) * 0x1000)
+#define TSI721_OBDMAC_DSSZ_MASK		0x0000000f
+
+#define TSI721_OBDMAC_DSRP(x)		(0x6104c + (x) * 0x1000)
+#define TSI721_OBDMAC_DSRP_MASK		0x0007ffff
+
+#define TSI721_OBDMAC_DSWP(x)		(0x61050 + (x) * 0x1000)
+#define TSI721_OBDMAC_DSWP_MASK		0x0007ffff
+
+#define TSI721_RQRPTO			0x60010
+#define TSI721_RQRPTO_MASK		0x00ffffff
+#define TSI721_RQRPTO_VAL		400	/* Response TO value */
+
+/*
+ * Inbound Messaging Engine Registers
+ *   x = 0..7
+ */
+
+#define TSI721_IB_DEVID_GLOBAL		0xffff
+#define TSI721_IBDMAC_FQBL(x)		(0x61200 + (x) * 0x1000)
+#define TSI721_IBDMAC_FQBL_MASK		0xffffffc0
+
+#define TSI721_IBDMAC_FQBH(x)		(0x61204 + (x) * 0x1000)
+#define TSI721_IBDMAC_FQBH_MASK		0xffffffff
+
+#define TSI721_IBDMAC_FQSZ_ENTRY_INX	TSI721_IMSGD_RING_SIZE
+#define TSI721_IBDMAC_FQSZ(x)		(0x61208 + (x) * 0x1000)
+#define TSI721_IBDMAC_FQSZ_MASK		0x0000000f
+
+#define TSI721_IBDMAC_FQRP(x)		(0x6120c + (x) * 0x1000)
+#define TSI721_IBDMAC_FQRP_MASK		0x0007ffff
+
+#define TSI721_IBDMAC_FQWP(x)		(0x61210 + (x) * 0x1000)
+#define TSI721_IBDMAC_FQWP_MASK		0x0007ffff
+
+#define TSI721_IBDMAC_FQTH(x)		(0x61214 + (x) * 0x1000)
+#define TSI721_IBDMAC_FQTH_MASK		0x0007ffff
+
+#define TSI721_IB_DEVID			0x60020
+#define TSI721_IB_DEVID_MASK		0x0000ffff
+
+#define TSI721_IBDMAC_CTL(x)		(0x61240 + (x) * 0x1000)
+#define TSI721_IBDMAC_CTL_MASK		0x00000003
+#define TSI721_IBDMAC_CTL_SUSPEND	0x00000002
+#define TSI721_IBDMAC_CTL_INIT		0x00000001
+
+#define TSI721_IBDMAC_STS(x)		(0x61244 + (x) * 0x1000)
+#define TSI721_IBDMAC_STS_MASK		0x007f0000
+#define TSI721_IBSMAC_STS_ABORT		0x00400000
+#define TSI721_IBSMAC_STS_RUN		0x00200000
+#define TSI721_IBSMAC_STS_CS		0x001f0000
+
+#define TSI721_IBDMAC_INT(x)		(0x61248 + (x) * 0x1000)
+#define TSI721_IBDMAC_INTSET(x)		(0x6124c + (x) * 0x1000)
+#define TSI721_IBDMAC_INTE(x)		(0x61250 + (x) * 0x1000)
+#define TSI721_IBDMAC_INT_MASK		0x0000100f
+#define TSI721_IBDMAC_INT_SRTO		0x00001000
+#define TSI721_IBDMAC_INT_SUSPENDED	0x00000008
+#define TSI721_IBDMAC_INT_PC_ERROR	0x00000004
+#define TSI721_IBDMAC_INT_FQ_LOW	0x00000002
+#define TSI721_IBDMAC_INT_DQ_RCV	0x00000001
+#define TSI721_IBDMAC_INT_ALL		TSI721_IBDMAC_INT_MASK
+
+#define TSI721_IBDMAC_PWE(x)		(0x61254 + (x) * 0x1000)
+#define TSI721_IBDMAC_PWE_MASK		0x00001700
+#define TSI721_IBDMAC_PWE_SRTO		0x00001000
+#define TSI721_IBDMAC_PWE_ILL_FMT	0x00000400
+#define TSI721_IBDMAC_PWE_ILL_DEC	0x00000200
+#define TSI721_IBDMAC_PWE_IMP_SP	0x00000100
+
+#define TSI721_IBDMAC_DQBL(x)		(0x61300 + (x) * 0x1000)
+#define TSI721_IBDMAC_DQBL_MASK		0xffffffc0
+#define TSI721_IBDMAC_DQBL_ADDR		0xffffffc0
+
+#define TSI721_IBDMAC_DQBH(x)		(0x61304 + (x) * 0x1000)
+#define TSI721_IBDMAC_DQBH_MASK		0xffffffff
+
+#define TSI721_IBDMAC_DQRP(x)		(0x61308 + (x) * 0x1000)
+#define TSI721_IBDMAC_DQRP_MASK		0x0007ffff
+
+#define TSI721_IBDMAC_DQWR(x)		(0x6130c + (x) * 0x1000)
+#define TSI721_IBDMAC_DQWR_MASK		0x0007ffff
+
+#define TSI721_IBDMAC_DQSZ(x)		(0x61314 + (x) * 0x1000)
+#define TSI721_IBDMAC_DQSZ_MASK		0x0000000f
+
+/*
+ * Messaging Engine Interrupts
+ */
+
+#define TSI721_SMSG_PWE			0x6a004
+
+#define TSI721_SMSG_INTE		0x6a000
+#define TSI721_SMSG_INT			0x6a008
+#define TSI721_SMSG_INTSET		0x6a010
+#define TSI721_SMSG_INT_MASK		0x0086ffff
+#define TSI721_SMSG_INT_UNS_RSP		0x00800000
+#define TSI721_SMSG_INT_ECC_NCOR	0x00040000
+#define TSI721_SMSG_INT_ECC_COR		0x00020000
+#define TSI721_SMSG_INT_ECC_NCOR_CH	0x0000ff00
+#define TSI721_SMSG_INT_ECC_COR_CH	0x000000ff
+
+#define TSI721_SMSG_ECC_LOG		0x6a014
+#define TSI721_SMSG_ECC_LOG_MASK	0x00070007
+#define TSI721_SMSG_ECC_LOG_ECC_NCOR_M	0x00070000
+#define TSI721_SMSG_ECC_LOG_ECC_COR_M	0x00000007
+
+#define TSI721_RETRY_GEN_CNT		0x6a100
+#define TSI721_RETRY_GEN_CNT_MASK	0xffffffff
+
+#define TSI721_RETRY_RX_CNT		0x6a104
+#define TSI721_RETRY_RX_CNT_MASK	0xffffffff
+
+#define TSI721_SMSG_ECC_COR_LOG(x)	(0x6a300 + (x) * 4)
+#define TSI721_SMSG_ECC_COR_LOG_MASK	0x000000ff
+
+#define TSI721_SMSG_ECC_NCOR(x)		(0x6a340 + (x) * 4)
+#define TSI721_SMSG_ECC_NCOR_MASK	0x000000ff
+
+/*
+ * Block DMA Descriptors
+ */
+
+struct tsi721_dma_desc {
+	__le32 type_id;
+
+#define TSI721_DMAD_DEVID	0x0000ffff
+#define TSI721_DMAD_CRF		0x00010000
+#define TSI721_DMAD_PRIO	0x00060000
+#define TSI721_DMAD_RTYPE	0x00780000
+#define TSI721_DMAD_IOF		0x08000000
+#define TSI721_DMAD_DTYPE	0xe0000000
+
+	__le32 bcount;
+
+#define TSI721_DMAD_BCOUNT1	0x03ffffff /* if DTYPE == 1 */
+#define TSI721_DMAD_BCOUNT2	0x0000000f /* if DTYPE == 2 */
+#define TSI721_DMAD_TT		0x0c000000
+#define TSI721_DMAD_RADDR0	0xc0000000
+
+	union {
+		__le32 raddr_lo;	   /* if DTYPE == (1 || 2) */
+		__le32 next_lo;		   /* if DTYPE == 3 */
+	};
+
+#define TSI721_DMAD_CFGOFF	0x00ffffff
+#define TSI721_DMAD_HOPCNT	0xff000000
+
+	union {
+		__le32 raddr_hi;	   /* if DTYPE == (1 || 2) */
+		__le32 next_hi;		   /* if DTYPE == 3 */
+	};
+
+	union {
+		struct {		   /* if DTYPE == 1 */
+			__le32 bufptr_lo;
+			__le32 bufptr_hi;
+			__le32 s_dist;
+			__le32 s_size;
+		} t1;
+		__le32 data[4];		   /* if DTYPE == 2 */
+		u32    reserved[4];	   /* if DTYPE == 3 */
+	};
+} __aligned(32);
+
+/*
+ * Inbound Messaging Descriptor
+ */
+struct tsi721_imsg_desc {
+	__le32 type_id;
+
+#define TSI721_IMD_DEVID	0x0000ffff
+#define TSI721_IMD_CRF		0x00010000
+#define TSI721_IMD_PRIO		0x00060000
+#define TSI721_IMD_TT		0x00180000
+#define TSI721_IMD_DTYPE	0xe0000000
+
+	__le32 msg_info;
+
+#define TSI721_IMD_BCOUNT	0x00000ff8
+#define TSI721_IMD_SSIZE	0x0000f000
+#define TSI721_IMD_LETER	0x00030000
+#define TSI721_IMD_XMBOX	0x003c0000
+#define TSI721_IMD_MBOX		0x00c00000
+#define TSI721_IMD_CS		0x78000000
+#define TSI721_IMD_HO		0x80000000
+
+	__le32 bufptr_lo;
+	__le32 bufptr_hi;
+	u32    reserved[12];
+
+} __aligned(64);
+
+/*
+ * Outbound Messaging Descriptor
+ */
+struct tsi721_omsg_desc {
+	__le32 type_id;
+
+#define TSI721_OMD_DEVID	0x0000ffff
+#define TSI721_OMD_CRF		0x00010000
+#define TSI721_OMD_PRIO		0x00060000
+#define TSI721_OMD_IOF		0x08000000
+#define TSI721_OMD_DTYPE	0xe0000000
+#define TSI721_OMD_RSRVD	0x17f80000
+
+	__le32 msg_info;
+
+#define TSI721_OMD_BCOUNT	0x00000ff8
+#define TSI721_OMD_SSIZE	0x0000f000
+#define TSI721_OMD_LETER	0x00030000
+#define TSI721_OMD_XMBOX	0x003c0000
+#define TSI721_OMD_MBOX		0x00c00000
+#define TSI721_OMD_TT		0x0c000000
+
+	union {
+		__le32 bufptr_lo;	/* if DTYPE == 4 */
+		__le32 next_lo;		/* if DTYPE == 5 */
+	};
+
+	union {
+		__le32 bufptr_hi;	/* if DTYPE == 4 */
+		__le32 next_hi;		/* if DTYPE == 5 */
+	};
+
+} __aligned(16);
+
+struct tsi721_dma_sts {
+	__le64	desc_sts[8];
+} __aligned(64);
+
+struct tsi721_desc_sts_fifo {
+	union {
+		__le64	da64;
+		struct {
+			__le32	lo;
+			__le32	hi;
+		} da32;
+	} stat[8];
+} __aligned(64);
+
+/* Descriptor types for BDMA and Messaging blocks */
+enum dma_dtype {
+	DTYPE1 = 1, /* Data Transfer DMA Descriptor */
+	DTYPE2 = 2, /* Immediate Data Transfer DMA Descriptor */
+	DTYPE3 = 3, /* Block Pointer DMA Descriptor */
+	DTYPE4 = 4, /* Outbound Msg DMA Descriptor */
+	DTYPE5 = 5, /* OB Messaging Block Pointer Descriptor */
+	DTYPE6 = 6  /* Inbound Messaging Descriptor */
+};
+
+enum dma_rtype {
+	NREAD = 0,
+	LAST_NWRITE_R = 1,
+	ALL_NWRITE = 2,
+	ALL_NWRITE_R = 3,
+	MAINT_RD = 4,
+	MAINT_WR = 5
+};
+
+/*
+ * mport Driver Definitions
+ */
+#define TSI721_DMA_CHNUM	TSI721_DMA_MAXCH
+
+#define TSI721_DMACH_MAINT	0	/* DMA channel for maint requests */
+#define TSI721_DMACH_MAINT_NBD	32	/* Number of BDs for maint requests */
+
+#define MSG_DMA_ENTRY_INX_TO_SIZE(x)	((0x10 << (x)) & 0xFFFF0)
+
+enum tsi721_smsg_int_flag {
+	SMSG_INT_NONE		= 0x00000000,
+	SMSG_INT_ECC_COR_CH	= 0x000000ff,
+	SMSG_INT_ECC_NCOR_CH	= 0x0000ff00,
+	SMSG_INT_ECC_COR	= 0x00020000,
+	SMSG_INT_ECC_NCOR	= 0x00040000,
+	SMSG_INT_UNS_RSP	= 0x00800000,
+	SMSG_INT_ALL		= 0x0006ffff
+};
+
+/* Structures */
+
+struct tsi721_bdma_chan {
+	int		bd_num;		/* number of buffer descriptors */
+	void		*bd_base;	/* start of DMA descriptors */
+	dma_addr_t	bd_phys;
+	void		*sts_base;	/* start of DMA BD status FIFO */
+	dma_addr_t	sts_phys;
+	int		sts_size;
+};
+
+struct tsi721_imsg_ring {
+	u32		size;
+	/* VA/PA of data buffers for incoming messages */
+	void		*buf_base;
+	dma_addr_t	buf_phys;
+	/* VA/PA of circular free buffer list */
+	void		*imfq_base;
+	dma_addr_t	imfq_phys;
+	/* VA/PA of Inbound message descriptors */
+	void		*imd_base;
+	dma_addr_t	imd_phys;
+	 /* Inbound Queue buffer pointers */
+	void		*imq_base[TSI721_IMSGD_RING_SIZE];
+
+	u32		rx_slot;
+	void		*dev_id;
+	u32		fq_wrptr;
+	u32		desc_rdptr;
+	spinlock_t	lock;
+};
+
+struct tsi721_omsg_ring {
+	u32		size;
+	/* VA/PA of OB Msg descriptors */
+	void		*omd_base;
+	dma_addr_t	omd_phys;
+	/* VA/PA of OB Msg data buffers */
+	void		*omq_base[TSI721_OMSGD_RING_SIZE];
+	dma_addr_t	omq_phys[TSI721_OMSGD_RING_SIZE];
+	/* VA/PA of OB Msg descriptor status FIFO */
+	void		*sts_base;
+	dma_addr_t	sts_phys;
+	u32		sts_size; /* # of allocated status entries */
+	u32		sts_rdptr;
+
+	u32		tx_slot;
+	void		*dev_id;
+	u32		wr_count;
+	spinlock_t	lock;
+};
+
+enum tsi721_flags {
+	TSI721_USING_MSI	= (1 << 0),
+	TSI721_USING_MSIX	= (1 << 1),
+	TSI721_IMSGID_SET	= (1 << 2),
+};
+
+#ifdef CONFIG_PCI_MSI
+/*
+ * MSI-X Table Entries (0 ... 69)
+ */
+#define TSI721_MSIX_DMACH_DONE(x)	(0 + (x))
+#define TSI721_MSIX_DMACH_INT(x)	(8 + (x))
+#define TSI721_MSIX_BDMA_INT		16
+#define TSI721_MSIX_OMSG_DONE(x)	(17 + (x))
+#define TSI721_MSIX_OMSG_INT(x)		(25 + (x))
+#define TSI721_MSIX_IMSG_DQ_RCV(x)	(33 + (x))
+#define TSI721_MSIX_IMSG_INT(x)		(41 + (x))
+#define TSI721_MSIX_MSG_INT		49
+#define TSI721_MSIX_SR2PC_IDBQ_RCV(x)	(50 + (x))
+#define TSI721_MSIX_SR2PC_CH_INT(x)	(58 + (x))
+#define TSI721_MSIX_SR2PC_INT		66
+#define TSI721_MSIX_PC2SR_INT		67
+#define TSI721_MSIX_SRIO_MAC_INT	68
+#define TSI721_MSIX_I2C_INT		69
+
+/* MSI-X vector and init table entry indexes */
+enum tsi721_msix_vect {
+	TSI721_VECT_IDB,
+	TSI721_VECT_PWRX, /* PW_RX is part of SRIO MAC Interrupt reporting */
+	TSI721_VECT_OMB0_DONE,
+	TSI721_VECT_OMB1_DONE,
+	TSI721_VECT_OMB2_DONE,
+	TSI721_VECT_OMB3_DONE,
+	TSI721_VECT_OMB0_INT,
+	TSI721_VECT_OMB1_INT,
+	TSI721_VECT_OMB2_INT,
+	TSI721_VECT_OMB3_INT,
+	TSI721_VECT_IMB0_RCV,
+	TSI721_VECT_IMB1_RCV,
+	TSI721_VECT_IMB2_RCV,
+	TSI721_VECT_IMB3_RCV,
+	TSI721_VECT_IMB0_INT,
+	TSI721_VECT_IMB1_INT,
+	TSI721_VECT_IMB2_INT,
+	TSI721_VECT_IMB3_INT,
+	TSI721_VECT_MAX
+};
+
+#define IRQ_DEVICE_NAME_MAX	64
+
+struct msix_irq {
+	u16	vector;
+	char	irq_name[IRQ_DEVICE_NAME_MAX];
+};
+#endif /* CONFIG_PCI_MSI */
+
+struct tsi721_device {
+	struct pci_dev	*pdev;
+	struct rio_mport *mport;
+	u32		flags;
+	void __iomem	*regs;
+#ifdef CONFIG_PCI_MSI
+	struct msix_irq	msix[TSI721_VECT_MAX];
+#endif
+	/* Doorbells */
+	void __iomem	*odb_base;
+	void		*idb_base;
+	dma_addr_t	idb_dma;
+	struct work_struct idb_work;
+	u32		db_discard_count;
+
+	/* Inbound Port-Write */
+	struct work_struct pw_work;
+	struct kfifo	pw_fifo;
+	spinlock_t	pw_fifo_lock;
+	u32		pw_discard_count;
+
+	/* BDMA Engine */
+	struct tsi721_bdma_chan bdma[TSI721_DMA_CHNUM];
+
+	/* Inbound Messaging */
+	int		imsg_init[TSI721_IMSG_CHNUM];
+	struct tsi721_imsg_ring imsg_ring[TSI721_IMSG_CHNUM];
+
+	/* Outbound Messaging */
+	int		omsg_init[TSI721_OMSG_CHNUM];
+	struct tsi721_omsg_ring	omsg_ring[TSI721_OMSG_CHNUM];
+};
+
+#endif
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c
index ebe77dd..2bebd79 100644
--- a/drivers/rapidio/rio-scan.c
+++ b/drivers/rapidio/rio-scan.c
@@ -516,7 +516,7 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
 	return rdev;
 
 cleanup:
-	if (rio_is_switch(rdev))
+	if (rswitch)
 		kfree(rswitch->route_table);
 
 	kfree(rdev);
@@ -923,7 +923,7 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
  * rio_enum_complete- Tests if enumeration of a network is complete
  * @port: Master port to send transaction
  *
- * Tests the Component Tag CSR for non-zero value (enumeration
+ * Tests the PGCCSR discovered bit for non-zero value (enumeration
  * complete flag). Return %1 if enumeration is complete or %0 if
  * enumeration is incomplete.
  */
@@ -933,7 +933,7 @@ static int rio_enum_complete(struct rio_mport *port)
 
 	rio_local_read_config_32(port, port->phys_efptr + RIO_PORT_GEN_CTL_CSR,
 				 &regval);
-	return (regval & RIO_PORT_GEN_MASTER) ? 1 : 0;
+	return (regval & RIO_PORT_GEN_DISCOVERED) ? 1 : 0;
 }
 
 /**
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c
index d63fddb..e821b21 100644
--- a/drivers/regulator/88pm8607.c
+++ b/drivers/regulator/88pm8607.c
@@ -412,7 +412,7 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
 		if (info->desc.id == res->start)
 			break;
 	}
-	if ((i < 0) || (i > PM8607_ID_RG_MAX)) {
+	if (i == ARRAY_SIZE(pm8607_regulator_info)) {
 		dev_err(&pdev->dev, "Failed to find regulator %llu\n",
 			(unsigned long long)res->start);
 		return -EINVAL;
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index c7fd2c0..9713b1b 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -64,6 +64,16 @@ config REGULATOR_USERSPACE_CONSUMER
 
           If unsure, say no.
 
+config REGULATOR_GPIO
+	tristate "GPIO regulator support"
+	depends on GENERIC_GPIO
+	help
+	  This driver provides support for regulators that can be
+	  controlled via gpios.
+	  It is capable of supporting current and voltage regulators
+	  and the platform has to provide a mapping of GPIO-states
+	  to target volts/amps.
+
 config REGULATOR_BQ24022
 	tristate "TI bq24022 Dual Input 1-Cell Li-Ion Charger IC"
 	help
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 040d5aa..93a6318 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o
 obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o
 obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o
 
+obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o
 obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o
 obj-$(CONFIG_REGULATOR_BQ24022) += bq24022.o
 obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o
diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c
index cd41045..5abeb3a 100644
--- a/drivers/regulator/aat2870-regulator.c
+++ b/drivers/regulator/aat2870-regulator.c
@@ -22,6 +22,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/err.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/platform_device.h>
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 9e4c123..67fa2a3 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1425,7 +1425,7 @@ int regulator_enable(struct regulator *regulator)
 	ret = _regulator_enable(rdev);
 	mutex_unlock(&rdev->mutex);
 
-	if (ret != 0)
+	if (ret != 0 && rdev->supply)
 		regulator_disable(rdev->supply);
 
 	return ret;
@@ -2971,6 +2971,43 @@ void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data)
 }
 EXPORT_SYMBOL_GPL(regulator_get_init_drvdata);
 
+#ifdef CONFIG_DEBUG_FS
+static ssize_t supply_map_read_file(struct file *file, char __user *user_buf,
+				    size_t count, loff_t *ppos)
+{
+	char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	ssize_t len, ret = 0;
+	struct regulator_map *map;
+
+	if (!buf)
+		return -ENOMEM;
+
+	list_for_each_entry(map, &regulator_map_list, list) {
+		len = snprintf(buf + ret, PAGE_SIZE - ret,
+			       "%s -> %s.%s\n",
+			       rdev_get_name(map->regulator), map->dev_name,
+			       map->supply);
+		if (len >= 0)
+			ret += len;
+		if (ret > PAGE_SIZE) {
+			ret = PAGE_SIZE;
+			break;
+		}
+	}
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
+
+	kfree(buf);
+
+	return ret;
+}
+
+static const struct file_operations supply_map_fops = {
+	.read = supply_map_read_file,
+	.llseek = default_llseek,
+};
+#endif
+
 static int __init regulator_init(void)
 {
 	int ret;
@@ -2983,6 +3020,10 @@ static int __init regulator_init(void)
 		pr_warn("regulator: Failed to create debugfs directory\n");
 		debugfs_root = NULL;
 	}
+
+	if (IS_ERR(debugfs_create_file("supply_map", 0444, debugfs_root,
+				       NULL, &supply_map_fops)))
+		pr_warn("regulator: Failed to create supplies debugfs\n");
 #endif
 
 	regulator_dummy_init();
diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c
new file mode 100644
index 0000000..f0acf52
--- /dev/null
+++ b/drivers/regulator/gpio-regulator.c
@@ -0,0 +1,358 @@
+/*
+ * gpio-regulator.c
+ *
+ * Copyright 2011 Heiko Stuebner <heiko@sntech.de>
+ *
+ * based on fixed.c
+ *
+ * Copyright 2008 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * Copyright (c) 2009 Nokia Corporation
+ * Roger Quadros <ext-roger.quadros@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU 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/mutex.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/gpio-regulator.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+
+struct gpio_regulator_data {
+	struct regulator_desc desc;
+	struct regulator_dev *dev;
+
+	int enable_gpio;
+	bool enable_high;
+	bool is_enabled;
+	unsigned startup_delay;
+
+	struct gpio *gpios;
+	int nr_gpios;
+
+	struct gpio_regulator_state *states;
+	int nr_states;
+
+	int state;
+};
+
+static int gpio_regulator_is_enabled(struct regulator_dev *dev)
+{
+	struct gpio_regulator_data *data = rdev_get_drvdata(dev);
+
+	return data->is_enabled;
+}
+
+static int gpio_regulator_enable(struct regulator_dev *dev)
+{
+	struct gpio_regulator_data *data = rdev_get_drvdata(dev);
+
+	if (gpio_is_valid(data->enable_gpio)) {
+		gpio_set_value_cansleep(data->enable_gpio, data->enable_high);
+		data->is_enabled = true;
+	}
+
+	return 0;
+}
+
+static int gpio_regulator_disable(struct regulator_dev *dev)
+{
+	struct gpio_regulator_data *data = rdev_get_drvdata(dev);
+
+	if (gpio_is_valid(data->enable_gpio)) {
+		gpio_set_value_cansleep(data->enable_gpio, !data->enable_high);
+		data->is_enabled = false;
+	}
+
+	return 0;
+}
+
+static int gpio_regulator_enable_time(struct regulator_dev *dev)
+{
+	struct gpio_regulator_data *data = rdev_get_drvdata(dev);
+
+	return data->startup_delay;
+}
+
+static int gpio_regulator_get_value(struct regulator_dev *dev)
+{
+	struct gpio_regulator_data *data = rdev_get_drvdata(dev);
+	int ptr;
+
+	for (ptr = 0; ptr < data->nr_states; ptr++)
+		if (data->states[ptr].gpios == data->state)
+			return data->states[ptr].value;
+
+	return -EINVAL;
+}
+
+static int gpio_regulator_set_value(struct regulator_dev *dev,
+					int min, int max)
+{
+	struct gpio_regulator_data *data = rdev_get_drvdata(dev);
+	int ptr, target, state;
+
+	target = -1;
+	for (ptr = 0; ptr < data->nr_states; ptr++)
+		if (data->states[ptr].value >= min &&
+		    data->states[ptr].value <= max)
+			target = data->states[ptr].gpios;
+
+	if (target < 0)
+		return -EINVAL;
+
+	for (ptr = 0; ptr < data->nr_gpios; ptr++) {
+		state = (target & (1 << ptr)) >> ptr;
+		gpio_set_value(data->gpios[ptr].gpio, state);
+	}
+	data->state = target;
+
+	return 0;
+}
+
+static int gpio_regulator_set_voltage(struct regulator_dev *dev,
+					int min_uV, int max_uV,
+					unsigned *selector)
+{
+	return gpio_regulator_set_value(dev, min_uV, max_uV);
+}
+
+static int gpio_regulator_list_voltage(struct regulator_dev *dev,
+				      unsigned selector)
+{
+	struct gpio_regulator_data *data = rdev_get_drvdata(dev);
+
+	if (selector >= data->nr_states)
+		return -EINVAL;
+
+	return data->states[selector].value;
+}
+
+static int gpio_regulator_set_current_limit(struct regulator_dev *dev,
+					int min_uA, int max_uA)
+{
+	return gpio_regulator_set_value(dev, min_uA, max_uA);
+}
+
+static struct regulator_ops gpio_regulator_voltage_ops = {
+	.is_enabled = gpio_regulator_is_enabled,
+	.enable = gpio_regulator_enable,
+	.disable = gpio_regulator_disable,
+	.enable_time = gpio_regulator_enable_time,
+	.get_voltage = gpio_regulator_get_value,
+	.set_voltage = gpio_regulator_set_voltage,
+	.list_voltage = gpio_regulator_list_voltage,
+};
+
+static struct regulator_ops gpio_regulator_current_ops = {
+	.is_enabled = gpio_regulator_is_enabled,
+	.enable = gpio_regulator_enable,
+	.disable = gpio_regulator_disable,
+	.enable_time = gpio_regulator_enable_time,
+	.get_current_limit = gpio_regulator_get_value,
+	.set_current_limit = gpio_regulator_set_current_limit,
+};
+
+static int __devinit gpio_regulator_probe(struct platform_device *pdev)
+{
+	struct gpio_regulator_config *config = pdev->dev.platform_data;
+	struct gpio_regulator_data *drvdata;
+	int ptr, ret, state;
+
+	drvdata = kzalloc(sizeof(struct gpio_regulator_data), GFP_KERNEL);
+	if (drvdata == NULL) {
+		dev_err(&pdev->dev, "Failed to allocate device data\n");
+		return -ENOMEM;
+	}
+
+	drvdata->desc.name = kstrdup(config->supply_name, GFP_KERNEL);
+	if (drvdata->desc.name == NULL) {
+		dev_err(&pdev->dev, "Failed to allocate supply name\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	drvdata->gpios = kmemdup(config->gpios,
+				 config->nr_gpios * sizeof(struct gpio),
+				 GFP_KERNEL);
+	if (drvdata->gpios == NULL) {
+		dev_err(&pdev->dev, "Failed to allocate gpio data\n");
+		ret = -ENOMEM;
+		goto err_name;
+	}
+
+	drvdata->states = kmemdup(config->states,
+				  config->nr_states *
+					 sizeof(struct gpio_regulator_state),
+				  GFP_KERNEL);
+	if (drvdata->states == NULL) {
+		dev_err(&pdev->dev, "Failed to allocate state data\n");
+		ret = -ENOMEM;
+		goto err_memgpio;
+	}
+	drvdata->nr_states = config->nr_states;
+
+	drvdata->desc.owner = THIS_MODULE;
+
+	/* handle regulator type*/
+	switch (config->type) {
+	case REGULATOR_VOLTAGE:
+		drvdata->desc.type = REGULATOR_VOLTAGE;
+		drvdata->desc.ops = &gpio_regulator_voltage_ops;
+		drvdata->desc.n_voltages = config->nr_states;
+		break;
+	case REGULATOR_CURRENT:
+		drvdata->desc.type = REGULATOR_CURRENT;
+		drvdata->desc.ops = &gpio_regulator_current_ops;
+		break;
+	default:
+		dev_err(&pdev->dev, "No regulator type set\n");
+		ret = -EINVAL;
+		goto err_memgpio;
+		break;
+	}
+
+	drvdata->enable_gpio = config->enable_gpio;
+	drvdata->startup_delay = config->startup_delay;
+
+	if (gpio_is_valid(config->enable_gpio)) {
+		drvdata->enable_high = config->enable_high;
+
+		ret = gpio_request(config->enable_gpio, config->supply_name);
+		if (ret) {
+			dev_err(&pdev->dev,
+			   "Could not obtain regulator enable GPIO %d: %d\n",
+						config->enable_gpio, ret);
+			goto err_memstate;
+		}
+
+		/* set output direction without changing state
+		 * to prevent glitch
+		 */
+		if (config->enabled_at_boot) {
+			drvdata->is_enabled = true;
+			ret = gpio_direction_output(config->enable_gpio,
+						    config->enable_high);
+		} else {
+			drvdata->is_enabled = false;
+			ret = gpio_direction_output(config->enable_gpio,
+						    !config->enable_high);
+		}
+
+		if (ret) {
+			dev_err(&pdev->dev,
+			   "Could not configure regulator enable GPIO %d direction: %d\n",
+						config->enable_gpio, ret);
+			goto err_enablegpio;
+		}
+	} else {
+		/* Regulator without GPIO control is considered
+		 * always enabled
+		 */
+		drvdata->is_enabled = true;
+	}
+
+	drvdata->nr_gpios = config->nr_gpios;
+	ret = gpio_request_array(drvdata->gpios, drvdata->nr_gpios);
+	if (ret) {
+		dev_err(&pdev->dev,
+		   "Could not obtain regulator setting GPIOs: %d\n", ret);
+		goto err_enablegpio;
+	}
+
+	/* build initial state from gpio init data. */
+	state = 0;
+	for (ptr = 0; ptr < drvdata->nr_gpios; ptr++) {
+		if (config->gpios[ptr].flags & GPIOF_OUT_INIT_HIGH)
+			state |= (1 << ptr);
+	}
+	drvdata->state = state;
+
+	drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev,
+					  config->init_data, drvdata);
+	if (IS_ERR(drvdata->dev)) {
+		ret = PTR_ERR(drvdata->dev);
+		dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret);
+		goto err_stategpio;
+	}
+
+	platform_set_drvdata(pdev, drvdata);
+
+	return 0;
+
+err_stategpio:
+	gpio_free_array(drvdata->gpios, drvdata->nr_gpios);
+err_enablegpio:
+	if (gpio_is_valid(config->enable_gpio))
+		gpio_free(config->enable_gpio);
+err_memstate:
+	kfree(drvdata->states);
+err_memgpio:
+	kfree(drvdata->gpios);
+err_name:
+	kfree(drvdata->desc.name);
+err:
+	kfree(drvdata);
+	return ret;
+}
+
+static int __devexit gpio_regulator_remove(struct platform_device *pdev)
+{
+	struct gpio_regulator_data *drvdata = platform_get_drvdata(pdev);
+
+	regulator_unregister(drvdata->dev);
+
+	gpio_free_array(drvdata->gpios, drvdata->nr_gpios);
+
+	kfree(drvdata->states);
+	kfree(drvdata->gpios);
+
+	if (gpio_is_valid(drvdata->enable_gpio))
+		gpio_free(drvdata->enable_gpio);
+
+	kfree(drvdata->desc.name);
+	kfree(drvdata);
+
+	return 0;
+}
+
+static struct platform_driver gpio_regulator_driver = {
+	.probe		= gpio_regulator_probe,
+	.remove		= __devexit_p(gpio_regulator_remove),
+	.driver		= {
+		.name		= "gpio-regulator",
+		.owner		= THIS_MODULE,
+	},
+};
+
+static int __init gpio_regulator_init(void)
+{
+	return platform_driver_register(&gpio_regulator_driver);
+}
+subsys_initcall(gpio_regulator_init);
+
+static void __exit gpio_regulator_exit(void)
+{
+	platform_driver_unregister(&gpio_regulator_driver);
+}
+module_exit(gpio_regulator_exit);
+
+MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
+MODULE_DESCRIPTION("gpio voltage regulator");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:gpio-regulator");
diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c
index 30eb9e5..1062cf9 100644
--- a/drivers/regulator/max8649.c
+++ b/drivers/regulator/max8649.c
@@ -221,7 +221,7 @@ static int max8649_enable_time(struct regulator_dev *rdev)
 	ret = (ret & MAX8649_RAMP_MASK) >> 5;
 	rate = (32 * 1000) >> ret;	/* uV/uS */
 
-	return (voltage / rate);
+	return DIV_ROUND_UP(voltage, rate);
 }
 
 static int max8649_set_mode(struct regulator_dev *rdev, unsigned int mode)
diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c
index 486ed81..3883d85 100644
--- a/drivers/regulator/max8952.c
+++ b/drivers/regulator/max8952.c
@@ -26,7 +26,6 @@
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/max8952.h>
-#include <linux/mutex.h>
 #include <linux/gpio.h>
 #include <linux/io.h>
 #include <linux/slab.h>
@@ -47,7 +46,6 @@ enum {
 struct max8952_data {
 	struct i2c_client	*client;
 	struct device		*dev;
-	struct mutex		mutex;
 	struct max8952_platform_data *pdata;
 	struct regulator_dev	*rdev;
 
@@ -208,7 +206,6 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client,
 	max8952->client = client;
 	max8952->dev = &client->dev;
 	max8952->pdata = pdata;
-	mutex_init(&max8952->mutex);
 
 	max8952->rdev = regulator_register(&regulator, max8952->dev,
 			&pdata->reg_data, max8952);
diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c
index 701a590..9fb4c7b 100644
--- a/drivers/regulator/tps65023-regulator.c
+++ b/drivers/regulator/tps65023-regulator.c
@@ -63,6 +63,13 @@
 #define TPS65023_REG_CTRL_LDO2_EN	BIT(2)
 #define TPS65023_REG_CTRL_LDO1_EN	BIT(1)
 
+/* REG_CTRL2 bitfields */
+#define TPS65023_REG_CTRL2_GO		BIT(7)
+#define TPS65023_REG_CTRL2_CORE_ADJ	BIT(6)
+#define TPS65023_REG_CTRL2_DCDC2	BIT(2)
+#define TPS65023_REG_CTRL2_DCDC1	BIT(1)
+#define TPS65023_REG_CTRL2_DCDC3	BIT(0)
+
 /* LDO_CTRL bitfields */
 #define TPS65023_LDO_CTRL_LDOx_SHIFT(ldo_id)	((ldo_id)*4)
 #define TPS65023_LDO_CTRL_LDOx_MASK(ldo_id)	(0xF0 >> ((ldo_id)*4))
@@ -85,7 +92,7 @@
 #define TPS65023_MAX_REG_ID		TPS65023_LDO_2
 
 /* Supported voltage values for regulators */
-static const u16 VDCDC1_VSEL_table[] = {
+static const u16 VCORE_VSEL_table[] = {
 	800, 825, 850, 875,
 	900, 925, 950, 975,
 	1000, 1025, 1050, 1075,
@@ -96,20 +103,29 @@ static const u16 VDCDC1_VSEL_table[] = {
 	1500, 1525, 1550, 1600,
 };
 
-static const u16 LDO1_VSEL_table[] = {
+/* Supported voltage values for LDO regulators for tps65020 */
+static const u16 TPS65020_LDO1_VSEL_table[] = {
+	1000, 1050, 1100, 1300,
+	1800, 2500, 3000, 3300,
+};
+
+static const u16 TPS65020_LDO2_VSEL_table[] = {
+	1000, 1050, 1100, 1300,
+	1800, 2500, 3000, 3300,
+};
+
+/* Supported voltage values for LDO regulators
+ * for tps65021 and tps65023 */
+static const u16 TPS65023_LDO1_VSEL_table[] = {
 	1000, 1100, 1300, 1800,
 	2200, 2600, 2800, 3150,
 };
 
-static const u16 LDO2_VSEL_table[] = {
+static const u16 TPS65023_LDO2_VSEL_table[] = {
 	1050, 1200, 1300, 1800,
 	2500, 2800, 3000, 3300,
 };
 
-static unsigned int num_voltages[] = {ARRAY_SIZE(VDCDC1_VSEL_table),
-				0, 0, ARRAY_SIZE(LDO1_VSEL_table),
-				ARRAY_SIZE(LDO2_VSEL_table)};
-
 /* Regulator specific details */
 struct tps_info {
 	const char *name;
@@ -127,6 +143,13 @@ struct tps_pmic {
 	struct regulator_dev *rdev[TPS65023_NUM_REGULATOR];
 	const struct tps_info *info[TPS65023_NUM_REGULATOR];
 	struct regmap *regmap;
+	u8 core_regulator;
+};
+
+/* Struct passed as driver data */
+struct tps_driver_data {
+	const struct tps_info *info;
+	u8 core_regulator;
 };
 
 static int tps_65023_set_bits(struct tps_pmic *tps, u8 reg, u8 mask)
@@ -253,7 +276,7 @@ static int tps65023_dcdc_get_voltage(struct regulator_dev *dev)
 	if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3)
 		return -EINVAL;
 
-	if (dcdc == TPS65023_DCDC_1) {
+	if (dcdc == tps->core_regulator) {
 		data = tps_65023_reg_read(tps, TPS65023_REG_DEF_CORE);
 		if (data < 0)
 			return data;
@@ -270,10 +293,10 @@ static int tps65023_dcdc_set_voltage(struct regulator_dev *dev,
 	struct tps_pmic *tps = rdev_get_drvdata(dev);
 	int dcdc = rdev_get_id(dev);
 	int vsel;
+	int ret;
 
-	if (dcdc != TPS65023_DCDC_1)
+	if (dcdc != tps->core_regulator)
 		return -EINVAL;
-
 	if (min_uV < tps->info[dcdc]->min_uV
 			|| min_uV > tps->info[dcdc]->max_uV)
 		return -EINVAL;
@@ -292,11 +315,21 @@ static int tps65023_dcdc_set_voltage(struct regulator_dev *dev,
 
 	*selector = vsel;
 
-	/* write to the register in case we found a match */
 	if (vsel == tps->info[dcdc]->table_len)
-		return -EINVAL;
-	else
-		return tps_65023_reg_write(tps, TPS65023_REG_DEF_CORE, vsel);
+		goto failed;
+
+	ret = tps_65023_reg_write(tps, TPS65023_REG_DEF_CORE, vsel);
+
+	/* Tell the chip that we have changed the value in DEFCORE
+	 * and its time to update the core voltage
+	 */
+	tps_65023_set_bits(tps, TPS65023_REG_CON_CTRL2,
+						TPS65023_REG_CTRL2_GO);
+
+	return ret;
+
+failed:
+	return -EINVAL;
 }
 
 static int tps65023_ldo_get_voltage(struct regulator_dev *dev)
@@ -362,7 +395,7 @@ static int tps65023_dcdc_list_voltage(struct regulator_dev *dev,
 	if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3)
 		return -EINVAL;
 
-	if (dcdc == TPS65023_DCDC_1) {
+	if (dcdc == tps->core_regulator) {
 		if (selector >= tps->info[dcdc]->table_len)
 			return -EINVAL;
 		else
@@ -414,7 +447,8 @@ static struct regmap_config tps65023_regmap_config = {
 static int __devinit tps_65023_probe(struct i2c_client *client,
 				     const struct i2c_device_id *id)
 {
-	const struct tps_info *info = (void *)id->driver_data;
+	const struct tps_driver_data *drv_data = (void *)id->driver_data;
+	const struct tps_info *info = drv_data->info;
 	struct regulator_init_data *init_data;
 	struct regulator_dev *rdev;
 	struct tps_pmic *tps;
@@ -446,6 +480,7 @@ static int __devinit tps_65023_probe(struct i2c_client *client,
 
 	/* common for all regulators */
 	tps->client = client;
+	tps->core_regulator = drv_data->core_regulator;
 
 	for (i = 0; i < TPS65023_NUM_REGULATOR; i++, info++, init_data++) {
 		/* Store regulator specific information */
@@ -453,7 +488,7 @@ static int __devinit tps_65023_probe(struct i2c_client *client,
 
 		tps->desc[i].name = info->name;
 		tps->desc[i].id = i;
-		tps->desc[i].n_voltages = num_voltages[i];
+		tps->desc[i].n_voltages = info->table_len;
 		tps->desc[i].ops = (i > TPS65023_DCDC_3 ?
 					&tps65023_ldo_ops : &tps65023_dcdc_ops);
 		tps->desc[i].type = REGULATOR_VOLTAGE;
@@ -475,6 +510,14 @@ static int __devinit tps_65023_probe(struct i2c_client *client,
 
 	i2c_set_clientdata(client, tps);
 
+	/* Enable setting output voltage by I2C */
+	tps_65023_clear_bits(tps, TPS65023_REG_CON_CTRL2,
+						TPS65023_REG_CTRL2_CORE_ADJ);
+
+	/* Enable setting output voltage by I2C */
+	tps_65023_clear_bits(tps, TPS65023_REG_CON_CTRL2,
+						TPS65023_REG_CTRL2_CORE_ADJ);
+
 	return 0;
 
  fail:
@@ -507,13 +550,86 @@ static int __devexit tps_65023_remove(struct i2c_client *client)
 	return 0;
 }
 
+static const struct tps_info tps65020_regs[] = {
+	{
+		.name = "VDCDC1",
+		.min_uV = 3300000,
+		.max_uV = 3300000,
+		.fixed	= 1,
+	},
+	{
+		.name = "VDCDC2",
+		.min_uV =  1800000,
+		.max_uV = 1800000,
+		.fixed = 1,
+	},
+	{
+		.name = "VDCDC3",
+		.min_uV =  800000,
+		.max_uV = 1600000,
+		.table_len = ARRAY_SIZE(VCORE_VSEL_table),
+		.table = VCORE_VSEL_table,
+	},
+
+	{
+		.name = "LDO1",
+		.min_uV = 1000000,
+		.max_uV = 3150000,
+		.table_len = ARRAY_SIZE(TPS65020_LDO1_VSEL_table),
+		.table = TPS65020_LDO1_VSEL_table,
+	},
+	{
+		.name = "LDO2",
+		.min_uV = 1050000,
+		.max_uV = 3300000,
+		.table_len = ARRAY_SIZE(TPS65020_LDO2_VSEL_table),
+		.table = TPS65020_LDO2_VSEL_table,
+	},
+};
+
+static const struct tps_info tps65021_regs[] = {
+	{
+		.name = "VDCDC1",
+		.min_uV =  3300000,
+		.max_uV = 3300000,
+		.fixed = 1,
+	},
+	{
+		.name = "VDCDC2",
+		.min_uV =  1800000,
+		.max_uV = 1800000,
+		.fixed = 1,
+	},
+	{
+		.name = "VDCDC3",
+		.min_uV =  800000,
+		.max_uV = 1600000,
+		.table_len = ARRAY_SIZE(VCORE_VSEL_table),
+		.table = VCORE_VSEL_table,
+	},
+	{
+		.name = "LDO1",
+		.min_uV = 1000000,
+		.max_uV = 3150000,
+		.table_len = ARRAY_SIZE(TPS65023_LDO1_VSEL_table),
+		.table = TPS65023_LDO1_VSEL_table,
+	},
+	{
+		.name = "LDO2",
+		.min_uV = 1050000,
+		.max_uV = 3300000,
+		.table_len = ARRAY_SIZE(TPS65023_LDO2_VSEL_table),
+		.table = TPS65023_LDO2_VSEL_table,
+	},
+};
+
 static const struct tps_info tps65023_regs[] = {
 	{
 		.name = "VDCDC1",
 		.min_uV =  800000,
 		.max_uV = 1600000,
-		.table_len = ARRAY_SIZE(VDCDC1_VSEL_table),
-		.table = VDCDC1_VSEL_table,
+		.table_len = ARRAY_SIZE(VCORE_VSEL_table),
+		.table = VCORE_VSEL_table,
 	},
 	{
 		.name = "VDCDC2",
@@ -531,23 +647,40 @@ static const struct tps_info tps65023_regs[] = {
 		.name = "LDO1",
 		.min_uV = 1000000,
 		.max_uV = 3150000,
-		.table_len = ARRAY_SIZE(LDO1_VSEL_table),
-		.table = LDO1_VSEL_table,
+		.table_len = ARRAY_SIZE(TPS65023_LDO1_VSEL_table),
+		.table = TPS65023_LDO1_VSEL_table,
 	},
 	{
 		.name = "LDO2",
 		.min_uV = 1050000,
 		.max_uV = 3300000,
-		.table_len = ARRAY_SIZE(LDO2_VSEL_table),
-		.table = LDO2_VSEL_table,
+		.table_len = ARRAY_SIZE(TPS65023_LDO2_VSEL_table),
+		.table = TPS65023_LDO2_VSEL_table,
 	},
 };
 
+static struct tps_driver_data tps65020_drv_data = {
+	.info = tps65020_regs,
+	.core_regulator = TPS65023_DCDC_3,
+};
+
+static struct tps_driver_data tps65021_drv_data = {
+		.info = tps65021_regs,
+		.core_regulator = TPS65023_DCDC_3,
+};
+
+static struct tps_driver_data tps65023_drv_data = {
+		.info = tps65023_regs,
+		.core_regulator = TPS65023_DCDC_1,
+};
+
 static const struct i2c_device_id tps_65023_id[] = {
 	{.name = "tps65023",
-	.driver_data = (unsigned long) tps65023_regs,},
+	.driver_data = (unsigned long) &tps65023_drv_data},
 	{.name = "tps65021",
-	.driver_data = (unsigned long) tps65023_regs,},
+	.driver_data = (unsigned long) &tps65021_drv_data,},
+	{.name = "tps65020",
+	.driver_data = (unsigned long) &tps65020_drv_data},
 	{ },
 };
 
diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c
index bfffabc..bdef703 100644
--- a/drivers/regulator/tps6507x-regulator.c
+++ b/drivers/regulator/tps6507x-regulator.c
@@ -90,12 +90,6 @@ static const u16 LDO2_VSEL_table[] = {
 	3000, 3100, 3200, 3300,
 };
 
-static unsigned int num_voltages[] = {ARRAY_SIZE(VDCDCx_VSEL_table),
-				ARRAY_SIZE(VDCDCx_VSEL_table),
-				ARRAY_SIZE(VDCDCx_VSEL_table),
-				ARRAY_SIZE(LDO1_VSEL_table),
-				ARRAY_SIZE(LDO2_VSEL_table)};
-
 struct tps_info {
 	const char *name;
 	unsigned min_uV;
@@ -598,7 +592,7 @@ int tps6507x_pmic_probe(struct platform_device *pdev)
 
 		tps->desc[i].name = info->name;
 		tps->desc[i].id = i;
-		tps->desc[i].n_voltages = num_voltages[i];
+		tps->desc[i].n_voltages = info->table_len;
 		tps->desc[i].ops = (i > TPS6507X_DCDC_3 ?
 		&tps6507x_pmic_ldo_ops : &tps6507x_pmic_dcdc_ops);
 		tps->desc[i].type = REGULATOR_VOLTAGE;
diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c
index bb04a75..dbcf09d 100644
--- a/drivers/regulator/tps6586x-regulator.c
+++ b/drivers/regulator/tps6586x-regulator.c
@@ -332,6 +332,36 @@ static inline int tps6586x_regulator_preinit(struct device *parent,
 				 1 << ri->enable_bit[1]);
 }
 
+static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev)
+{
+	struct device *parent = pdev->dev.parent;
+	struct regulator_init_data *p = pdev->dev.platform_data;
+	struct tps6586x_settings *setting = p->driver_data;
+	uint8_t reg;
+
+	if (setting == NULL)
+		return 0;
+
+	if (!(setting->slew_rate & TPS6586X_SLEW_RATE_SET))
+		return 0;
+
+	/* only SM0 and SM1 can have the slew rate settings */
+	switch (pdev->id) {
+	case TPS6586X_ID_SM_0:
+		reg = TPS6586X_SM0SL;
+		break;
+	case TPS6586X_ID_SM_1:
+		reg = TPS6586X_SM1SL;
+		break;
+	default:
+		dev_warn(&pdev->dev, "Only SM0/SM1 can set slew rate\n");
+		return -EINVAL;
+	}
+
+	return tps6586x_write(parent, reg,
+			setting->slew_rate & TPS6586X_SLEW_RATE_MASK);
+}
+
 static inline struct tps6586x_regulator *find_regulator_info(int id)
 {
 	struct tps6586x_regulator *ri;
@@ -374,7 +404,7 @@ static int __devinit tps6586x_regulator_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, rdev);
 
-	return 0;
+	return tps6586x_regulator_set_slew_rate(pdev);
 }
 
 static int __devexit tps6586x_regulator_remove(struct platform_device *pdev)
diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c
index 3a9313e..39d4a17 100644
--- a/drivers/regulator/tps65912-regulator.c
+++ b/drivers/regulator/tps65912-regulator.c
@@ -43,8 +43,6 @@
 #define TPS65912_REG_LDO9	12
 #define TPS65912_REG_LDO10	13
 
-#define TPS65912_MAX_REG_ID	TPS65912_REG_LDO_10
-
 /* Number of step-down converters available */
 #define TPS65912_NUM_DCDC	4
 
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 5a538fc..53eb4e5 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -8,7 +8,7 @@ config RTC_LIB
 menuconfig RTC_CLASS
 	bool "Real Time Clock"
 	default n
-	depends on !S390
+	depends on !S390 && !UML
 	select RTC_LIB
 	help
 	  Generic RTC class support. If you say yes here, you will
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index 01a7df5..e8326f2 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -21,16 +21,13 @@
 #include "rtc-core.h"
 
 
-static DEFINE_IDR(rtc_idr);
-static DEFINE_MUTEX(idr_lock);
+static DEFINE_IDA(rtc_ida);
 struct class *rtc_class;
 
 static void rtc_device_release(struct device *dev)
 {
 	struct rtc_device *rtc = to_rtc_device(dev);
-	mutex_lock(&idr_lock);
-	idr_remove(&rtc_idr, rtc->id);
-	mutex_unlock(&idr_lock);
+	ida_simple_remove(&rtc_ida, rtc->id);
 	kfree(rtc);
 }
 
@@ -146,25 +143,16 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
 	struct rtc_wkalrm alrm;
 	int id, err;
 
-	if (idr_pre_get(&rtc_idr, GFP_KERNEL) == 0) {
-		err = -ENOMEM;
+	id = ida_simple_get(&rtc_ida, 0, 0, GFP_KERNEL);
+	if (id < 0) {
+		err = id;
 		goto exit;
 	}
 
-
-	mutex_lock(&idr_lock);
-	err = idr_get_new(&rtc_idr, NULL, &id);
-	mutex_unlock(&idr_lock);
-
-	if (err < 0)
-		goto exit;
-
-	id = id & MAX_ID_MASK;
-
 	rtc = kzalloc(sizeof(struct rtc_device), GFP_KERNEL);
 	if (rtc == NULL) {
 		err = -ENOMEM;
-		goto exit_idr;
+		goto exit_ida;
 	}
 
 	rtc->id = id;
@@ -222,10 +210,8 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
 exit_kfree:
 	kfree(rtc);
 
-exit_idr:
-	mutex_lock(&idr_lock);
-	idr_remove(&rtc_idr, id);
-	mutex_unlock(&idr_lock);
+exit_ida:
+	ida_simple_remove(&rtc_ida, id);
 
 exit:
 	dev_err(dev, "rtc core: unable to register %s, err = %d\n",
@@ -276,7 +262,7 @@ static void __exit rtc_exit(void)
 {
 	rtc_dev_exit();
 	class_destroy(rtc_class);
-	idr_destroy(&rtc_idr);
+	ida_destroy(&rtc_ida);
 }
 
 subsys_initcall(rtc_init);
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index b2005b4..62b0763 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -34,6 +34,7 @@ enum ds_type {
 	ds_1388,
 	ds_3231,
 	m41t00,
+	mcp7941x,
 	rx_8025,
 	// rs5c372 too?  different address...
 };
@@ -43,6 +44,7 @@ enum ds_type {
 #define DS1307_REG_SECS		0x00	/* 00-59 */
 #	define DS1307_BIT_CH		0x80
 #	define DS1340_BIT_nEOSC		0x80
+#	define MCP7941X_BIT_ST		0x80
 #define DS1307_REG_MIN		0x01	/* 00-59 */
 #define DS1307_REG_HOUR		0x02	/* 00-23, or 1-12{am,pm} */
 #	define DS1307_BIT_12HR		0x40	/* in REG_HOUR */
@@ -50,6 +52,7 @@ enum ds_type {
 #	define DS1340_BIT_CENTURY_EN	0x80	/* in REG_HOUR */
 #	define DS1340_BIT_CENTURY	0x40	/* in REG_HOUR */
 #define DS1307_REG_WDAY		0x03	/* 01-07 */
+#	define MCP7941X_BIT_VBATEN	0x08
 #define DS1307_REG_MDAY		0x04	/* 01-31 */
 #define DS1307_REG_MONTH	0x05	/* 01-12 */
 #	define DS1337_BIT_CENTURY	0x80	/* in REG_MONTH */
@@ -137,6 +140,8 @@ static const struct chip_desc chips[] = {
 },
 [m41t00] = {
 },
+[mcp7941x] = {
+},
 [rx_8025] = {
 }, };
 
@@ -149,6 +154,7 @@ static const struct i2c_device_id ds1307_id[] = {
 	{ "ds1340", ds_1340 },
 	{ "ds3231", ds_3231 },
 	{ "m41t00", m41t00 },
+	{ "mcp7941x", mcp7941x },
 	{ "pt7c4338", ds_1307 },
 	{ "rx8025", rx_8025 },
 	{ }
@@ -365,6 +371,10 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
 		buf[DS1307_REG_HOUR] |= DS1340_BIT_CENTURY_EN
 				| DS1340_BIT_CENTURY;
 		break;
+	case mcp7941x:
+		buf[DS1307_REG_SECS] |= MCP7941X_BIT_ST;
+		buf[DS1307_REG_WDAY] |= MCP7941X_BIT_VBATEN;
+		break;
 	default:
 		break;
 	}
@@ -809,6 +819,23 @@ read_rtc:
 			dev_warn(&client->dev, "SET TIME!\n");
 		}
 		break;
+	case mcp7941x:
+		/* make sure that the backup battery is enabled */
+		if (!(ds1307->regs[DS1307_REG_WDAY] & MCP7941X_BIT_VBATEN)) {
+			i2c_smbus_write_byte_data(client, DS1307_REG_WDAY,
+					ds1307->regs[DS1307_REG_WDAY]
+					| MCP7941X_BIT_VBATEN);
+		}
+
+		/* clock halted?  turn it on, so clock can tick. */
+		if (!(tmp & MCP7941X_BIT_ST)) {
+			i2c_smbus_write_byte_data(client, DS1307_REG_SECS,
+					MCP7941X_BIT_ST);
+			dev_warn(&client->dev, "SET TIME!\n");
+			goto read_rtc;
+		}
+
+		break;
 	case rx_8025:
 	case ds_1337:
 	case ds_1339:
diff --git a/drivers/rtc/rtc-mc13xxx.c b/drivers/rtc/rtc-mc13xxx.c
index a1a278b..9d0c3b4 100644
--- a/drivers/rtc/rtc-mc13xxx.c
+++ b/drivers/rtc/rtc-mc13xxx.c
@@ -309,7 +309,7 @@ static irqreturn_t mc13xxx_rtc_reset_handler(int irq, void *dev)
 	return IRQ_HANDLED;
 }
 
-static int __devinit mc13xxx_rtc_probe(struct platform_device *pdev)
+static int __init mc13xxx_rtc_probe(struct platform_device *pdev)
 {
 	int ret;
 	struct mc13xxx_rtc *priv;
@@ -378,7 +378,7 @@ err_reset_irq_request:
 	return ret;
 }
 
-static int __devexit mc13xxx_rtc_remove(struct platform_device *pdev)
+static int __exit mc13xxx_rtc_remove(struct platform_device *pdev)
 {
 	struct mc13xxx_rtc *priv = platform_get_drvdata(pdev);
 
@@ -410,7 +410,7 @@ const struct platform_device_id mc13xxx_rtc_idtable[] = {
 
 static struct platform_driver mc13xxx_rtc_driver = {
 	.id_table = mc13xxx_rtc_idtable,
-	.remove = __devexit_p(mc13xxx_rtc_remove),
+	.remove = __exit_p(mc13xxx_rtc_remove),
 	.driver = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
diff --git a/drivers/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c
index f3c6060..7a19555 100644
--- a/drivers/staging/pohmelfs/inode.c
+++ b/drivers/staging/pohmelfs/inode.c
@@ -1197,7 +1197,7 @@ const struct inode_operations pohmelfs_file_inode_operations = {
 void pohmelfs_fill_inode(struct inode *inode, struct netfs_inode_info *info)
 {
 	inode->i_mode = info->mode;
-	inode->i_nlink = info->nlink;
+	set_nlink(inode, info->nlink);
 	inode->i_uid = info->uid;
 	inode->i_gid = info->gid;
 	inode->i_blocks = info->blocks;
diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig
index 8816f53..b3d1741 100644
--- a/drivers/tty/Kconfig
+++ b/drivers/tty/Kconfig
@@ -1,6 +1,6 @@
 config VT
 	bool "Virtual terminal" if EXPERT
-	depends on !S390
+	depends on !S390 && !UML
 	select INPUT
 	default y
 	---help---
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index 29cbfd8..8131e2c 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -19,6 +19,7 @@
 # define SUPPORT_SYSRQ
 #endif
 
+#include <linux/atomic.h>
 #include <linux/hrtimer.h>
 #include <linux/module.h>
 #include <linux/io.h>
@@ -33,6 +34,8 @@
 #include <linux/clk.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include "msm_serial.h"
 
@@ -589,9 +592,8 @@ static void msm_release_port(struct uart_port *port)
 		iowrite32(GSBI_PROTOCOL_IDLE, msm_port->gsbi_base +
 			  GSBI_CONTROL);
 
-		gsbi_resource = platform_get_resource_byname(pdev,
-							     IORESOURCE_MEM,
-							     "gsbi_resource");
+		gsbi_resource = platform_get_resource(pdev,
+							IORESOURCE_MEM, 1);
 
 		if (unlikely(!gsbi_resource))
 			return;
@@ -612,8 +614,7 @@ static int msm_request_port(struct uart_port *port)
 	resource_size_t size;
 	int ret;
 
-	uart_resource = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-						     "uart_resource");
+	uart_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (unlikely(!uart_resource))
 		return -ENXIO;
 
@@ -628,8 +629,7 @@ static int msm_request_port(struct uart_port *port)
 		goto fail_release_port;
 	}
 
-	gsbi_resource = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-						     "gsbi_resource");
+	gsbi_resource = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 	/* Is this a GSBI-based port? */
 	if (gsbi_resource) {
 		size = resource_size(gsbi_resource);
@@ -857,6 +857,8 @@ static struct uart_driver msm_uart_driver = {
 	.cons = MSM_CONSOLE,
 };
 
+static atomic_t msm_uart_next_id = ATOMIC_INIT(0);
+
 static int __init msm_serial_probe(struct platform_device *pdev)
 {
 	struct msm_port *msm_port;
@@ -864,6 +866,9 @@ static int __init msm_serial_probe(struct platform_device *pdev)
 	struct uart_port *port;
 	int irq;
 
+	if (pdev->id == -1)
+		pdev->id = atomic_inc_return(&msm_uart_next_id) - 1;
+
 	if (unlikely(pdev->id < 0 || pdev->id >= UART_NR))
 		return -ENXIO;
 
@@ -873,7 +878,7 @@ static int __init msm_serial_probe(struct platform_device *pdev)
 	port->dev = &pdev->dev;
 	msm_port = UART_TO_MSM(port);
 
-	if (platform_get_resource_byname(pdev, IORESOURCE_MEM, "gsbi_resource"))
+	if (platform_get_resource(pdev, IORESOURCE_MEM, 1))
 		msm_port->is_uartdm = 1;
 	else
 		msm_port->is_uartdm = 0;
@@ -897,8 +902,7 @@ static int __init msm_serial_probe(struct platform_device *pdev)
 	printk(KERN_INFO "uartclk = %d\n", port->uartclk);
 
 
-	resource = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-						     "uart_resource");
+	resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (unlikely(!resource))
 		return -ENXIO;
 	port->mapbase = resource->start;
@@ -922,11 +926,17 @@ static int __devexit msm_serial_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static struct of_device_id msm_match_table[] = {
+	{ .compatible = "qcom,msm-uart" },
+	{}
+};
+
 static struct platform_driver msm_platform_driver = {
 	.remove = msm_serial_remove,
 	.driver = {
 		.name = "msm_serial",
 		.owner = THIS_MODULE,
+		.of_match_table = msm_match_table,
 	},
 };
 
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index 944291e..ba3a46b 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -35,8 +35,7 @@ extern int usb_disabled(void);
 
 static void at91_start_clock(void)
 {
-	if (cpu_is_at91sam9261() || cpu_is_at91sam9g10())
-		clk_enable(hclk);
+	clk_enable(hclk);
 	clk_enable(iclk);
 	clk_enable(fclk);
 	clocked = 1;
@@ -46,8 +45,7 @@ static void at91_stop_clock(void)
 {
 	clk_disable(fclk);
 	clk_disable(iclk);
-	if (cpu_is_at91sam9261() || cpu_is_at91sam9g10())
-		clk_disable(hclk);
+	clk_disable(hclk);
 	clocked = 0;
 }
 
@@ -142,8 +140,7 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
 
 	iclk = clk_get(&pdev->dev, "ohci_clk");
 	fclk = clk_get(&pdev->dev, "uhpck");
-	if (cpu_is_at91sam9261() || cpu_is_at91sam9g10())
-		hclk = clk_get(&pdev->dev, "hck0");
+	hclk = clk_get(&pdev->dev, "hclk");
 
 	at91_start_hc(pdev);
 	ohci_hcd_init(hcd_to_ohci(hcd));
@@ -155,8 +152,7 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
 	/* Error handling */
 	at91_stop_hc(pdev);
 
-	if (cpu_is_at91sam9261() || cpu_is_at91sam9g10())
-		clk_put(hclk);
+	clk_put(hclk);
 	clk_put(fclk);
 	clk_put(iclk);
 
@@ -192,8 +188,7 @@ static void usb_hcd_at91_remove(struct usb_hcd *hcd,
 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 	usb_put_hcd(hcd);
 
-	if (cpu_is_at91sam9261() || cpu_is_at91sam9g10())
-		clk_put(hclk);
+	clk_put(hclk);
 	clk_put(fclk);
 	clk_put(iclk);
 	fclk = iclk = hclk = NULL;
@@ -223,6 +218,156 @@ ohci_at91_start (struct usb_hcd *hcd)
 	return 0;
 }
 
+static void ohci_at91_usb_set_power(struct at91_usbh_data *pdata, int port, int enable)
+{
+	if (port < 0 || port >= 2)
+		return;
+
+	gpio_set_value(pdata->vbus_pin[port], !pdata->vbus_pin_inverted ^ enable);
+}
+
+static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port)
+{
+	if (port < 0 || port >= 2)
+		return -EINVAL;
+
+	return gpio_get_value(pdata->vbus_pin[port]) ^ !pdata->vbus_pin_inverted;
+}
+
+/*
+ * Update the status data from the hub with the over-current indicator change.
+ */
+static int ohci_at91_hub_status_data(struct usb_hcd *hcd, char *buf)
+{
+	struct at91_usbh_data *pdata = hcd->self.controller->platform_data;
+	int length = ohci_hub_status_data(hcd, buf);
+	int port;
+
+	for (port = 0; port < ARRAY_SIZE(pdata->overcurrent_pin); port++) {
+		if (pdata->overcurrent_changed[port]) {
+			if (! length)
+				length = 1;
+			buf[0] |= 1 << (port + 1);
+		}
+	}
+
+	return length;
+}
+
+/*
+ * Look at the control requests to the root hub and see if we need to override.
+ */
+static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+				 u16 wIndex, char *buf, u16 wLength)
+{
+	struct at91_usbh_data *pdata = hcd->self.controller->platform_data;
+	struct usb_hub_descriptor *desc;
+	int ret = -EINVAL;
+	u32 *data = (u32 *)buf;
+
+	dev_dbg(hcd->self.controller,
+		"ohci_at91_hub_control(%p,0x%04x,0x%04x,0x%04x,%p,%04x)\n",
+		hcd, typeReq, wValue, wIndex, buf, wLength);
+
+	switch (typeReq) {
+	case SetPortFeature:
+		if (wValue == USB_PORT_FEAT_POWER) {
+			dev_dbg(hcd->self.controller, "SetPortFeat: POWER\n");
+			ohci_at91_usb_set_power(pdata, wIndex - 1, 1);
+			goto out;
+		}
+		break;
+
+	case ClearPortFeature:
+		switch (wValue) {
+		case USB_PORT_FEAT_C_OVER_CURRENT:
+			dev_dbg(hcd->self.controller,
+				"ClearPortFeature: C_OVER_CURRENT\n");
+
+			if (wIndex == 1 || wIndex == 2) {
+				pdata->overcurrent_changed[wIndex-1] = 0;
+				pdata->overcurrent_status[wIndex-1] = 0;
+			}
+
+			goto out;
+
+		case USB_PORT_FEAT_OVER_CURRENT:
+			dev_dbg(hcd->self.controller,
+				"ClearPortFeature: OVER_CURRENT\n");
+
+			if (wIndex == 1 || wIndex == 2) {
+				pdata->overcurrent_status[wIndex-1] = 0;
+			}
+
+			goto out;
+
+		case USB_PORT_FEAT_POWER:
+			dev_dbg(hcd->self.controller,
+				"ClearPortFeature: POWER\n");
+
+			if (wIndex == 1 || wIndex == 2) {
+				ohci_at91_usb_set_power(pdata, wIndex - 1, 0);
+				return 0;
+			}
+		}
+		break;
+	}
+
+	ret = ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
+	if (ret)
+		goto out;
+
+	switch (typeReq) {
+	case GetHubDescriptor:
+
+		/* update the hub's descriptor */
+
+		desc = (struct usb_hub_descriptor *)buf;
+
+		dev_dbg(hcd->self.controller, "wHubCharacteristics 0x%04x\n",
+			desc->wHubCharacteristics);
+
+		/* remove the old configurations for power-switching, and
+		 * over-current protection, and insert our new configuration
+		 */
+
+		desc->wHubCharacteristics &= ~cpu_to_le16(HUB_CHAR_LPSM);
+		desc->wHubCharacteristics |= cpu_to_le16(0x0001);
+
+		if (pdata->overcurrent_supported) {
+			desc->wHubCharacteristics &= ~cpu_to_le16(HUB_CHAR_OCPM);
+			desc->wHubCharacteristics |=  cpu_to_le16(0x0008|0x0001);
+		}
+
+		dev_dbg(hcd->self.controller, "wHubCharacteristics after 0x%04x\n",
+			desc->wHubCharacteristics);
+
+		return ret;
+
+	case GetPortStatus:
+		/* check port status */
+
+		dev_dbg(hcd->self.controller, "GetPortStatus(%d)\n", wIndex);
+
+		if (wIndex == 1 || wIndex == 2) {
+			if (! ohci_at91_usb_get_power(pdata, wIndex-1)) {
+				*data &= ~cpu_to_le32(RH_PS_PPS);
+			}
+
+			if (pdata->overcurrent_changed[wIndex-1]) {
+				*data |= cpu_to_le32(RH_PS_OCIC);
+			}
+
+			if (pdata->overcurrent_status[wIndex-1]) {
+				*data |= cpu_to_le32(RH_PS_POCI);
+			}
+		}
+	}
+
+ out:
+	return ret;
+}
+
 /*-------------------------------------------------------------------------*/
 
 static const struct hc_driver ohci_at91_hc_driver = {
@@ -258,8 +403,8 @@ static const struct hc_driver ohci_at91_hc_driver = {
 	/*
 	 * root hub support
 	 */
-	.hub_status_data =	ohci_hub_status_data,
-	.hub_control =		ohci_hub_control,
+	.hub_status_data =	ohci_at91_hub_status_data,
+	.hub_control =		ohci_at91_hub_control,
 #ifdef CONFIG_PM
 	.bus_suspend =		ohci_bus_suspend,
 	.bus_resume =		ohci_bus_resume,
@@ -269,22 +414,71 @@ static const struct hc_driver ohci_at91_hc_driver = {
 
 /*-------------------------------------------------------------------------*/
 
+static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data)
+{
+	struct platform_device *pdev = data;
+	struct at91_usbh_data *pdata = pdev->dev.platform_data;
+	int val, gpio, port;
+
+	/* From the GPIO notifying the over-current situation, find
+	 * out the corresponding port */
+	gpio = irq_to_gpio(irq);
+	for (port = 0; port < ARRAY_SIZE(pdata->overcurrent_pin); port++) {
+		if (pdata->overcurrent_pin[port] == gpio)
+			break;
+	}
+
+	if (port == ARRAY_SIZE(pdata->overcurrent_pin)) {
+		dev_err(& pdev->dev, "overcurrent interrupt from unknown GPIO\n");
+		return IRQ_HANDLED;
+	}
+
+	val = gpio_get_value(gpio);
+
+	/* When notified of an over-current situation, disable power
+	   on the corresponding port, and mark this port in
+	   over-current. */
+	if (! val) {
+		ohci_at91_usb_set_power(pdata, port, 0);
+		pdata->overcurrent_status[port]  = 1;
+		pdata->overcurrent_changed[port] = 1;
+	}
+
+	dev_dbg(& pdev->dev, "overcurrent situation %s\n",
+		val ? "exited" : "notified");
+
+	return IRQ_HANDLED;
+}
+
+/*-------------------------------------------------------------------------*/
+
 static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
 {
 	struct at91_usbh_data	*pdata = pdev->dev.platform_data;
 	int			i;
 
 	if (pdata) {
-		/* REVISIT make the driver support per-port power switching,
-		 * and also overcurrent detection.  Here we assume the ports
-		 * are always powered while this driver is active, and use
-		 * active-low power switches.
-		 */
 		for (i = 0; i < ARRAY_SIZE(pdata->vbus_pin); i++) {
 			if (pdata->vbus_pin[i] <= 0)
 				continue;
 			gpio_request(pdata->vbus_pin[i], "ohci_vbus");
-			gpio_direction_output(pdata->vbus_pin[i], 0);
+			ohci_at91_usb_set_power(pdata, i, 1);
+		}
+
+		for (i = 0; i < ARRAY_SIZE(pdata->overcurrent_pin); i++) {
+			int ret;
+
+			if (pdata->overcurrent_pin[i] <= 0)
+				continue;
+			gpio_request(pdata->overcurrent_pin[i], "ohci_overcurrent");
+
+			ret = request_irq(gpio_to_irq(pdata->overcurrent_pin[i]),
+					  ohci_hcd_at91_overcurrent_irq,
+					  IRQF_SHARED, "ohci_overcurrent", pdev);
+			if (ret) {
+				gpio_free(pdata->overcurrent_pin[i]);
+				dev_warn(& pdev->dev, "cannot get GPIO IRQ for overcurrent\n");
+			}
 		}
 	}
 
@@ -301,9 +495,16 @@ static int ohci_hcd_at91_drv_remove(struct platform_device *pdev)
 		for (i = 0; i < ARRAY_SIZE(pdata->vbus_pin); i++) {
 			if (pdata->vbus_pin[i] <= 0)
 				continue;
-			gpio_direction_output(pdata->vbus_pin[i], 1);
+			ohci_at91_usb_set_power(pdata, i, 0);
 			gpio_free(pdata->vbus_pin[i]);
 		}
+
+		for (i = 0; i < ARRAY_SIZE(pdata->overcurrent_pin); i++) {
+			if (pdata->overcurrent_pin[i] <= 0)
+				continue;
+			free_irq(gpio_to_irq(pdata->overcurrent_pin[i]), pdev);
+			gpio_free(pdata->overcurrent_pin[i]);
+		}
 	}
 
 	device_init_wakeup(&pdev->dev, 0);
diff --git a/drivers/video/mbx/mbxfb.c b/drivers/video/mbx/mbxfb.c
index afea9ab..6ce3416 100644
--- a/drivers/video/mbx/mbxfb.c
+++ b/drivers/video/mbx/mbxfb.c
@@ -34,7 +34,7 @@
 #include "regs.h"
 #include "reg_bits.h"
 
-static unsigned long virt_base_2700;
+static void __iomem *virt_base_2700;
 
 #define write_reg(val, reg) do { writel((val), (reg)); } while(0)
 
@@ -850,7 +850,7 @@ static int mbxfb_suspend(struct platform_device *dev, pm_message_t state)
 {
 	/* make frame buffer memory enter self-refresh mode */
 	write_reg_dly(LMPWR_MC_PWR_SRM, LMPWR);
-	while (LMPWRSTAT != LMPWRSTAT_MC_PWR_SRM)
+	while (readl(LMPWRSTAT) != LMPWRSTAT_MC_PWR_SRM)
 		; /* empty statement */
 
 	/* reset the device, since it's initial state is 'mostly sleeping' */
@@ -946,7 +946,7 @@ static int __devinit mbxfb_probe(struct platform_device *dev)
 		ret = -EINVAL;
 		goto err3;
 	}
-	virt_base_2700 = (unsigned long)mfbi->reg_virt_addr;
+	virt_base_2700 = mfbi->reg_virt_addr;
 
 	mfbi->fb_virt_addr = ioremap_nocache(mfbi->fb_phys_addr,
 					     res_size(mfbi->fb_req));
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index e89778f..1d1e4f1 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -1309,16 +1309,6 @@ static int pxafb_smart_init(struct pxafb_info *fbi)
 	return 0;
 }
 #else
-int pxafb_smart_queue(struct fb_info *info, uint16_t *cmds, int n_cmds)
-{
-	return 0;
-}
-
-int pxafb_smart_flush(struct fb_info *info)
-{
-	return 0;
-}
-
 static inline int pxafb_smart_init(struct pxafb_info *fbi) { return 0; }
 #endif /* CONFIG_FB_PXA_SMARTPANEL */
 
diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
index 57e493b..816ed08 100644
--- a/drivers/virtio/Kconfig
+++ b/drivers/virtio/Kconfig
@@ -35,4 +35,15 @@ config VIRTIO_BALLOON
 
 	 If unsure, say M.
 
+ config VIRTIO_MMIO
+ 	tristate "Platform bus driver for memory mapped virtio devices (EXPERIMENTAL)"
+ 	depends on EXPERIMENTAL
+ 	select VIRTIO
+ 	select VIRTIO_RING
+ 	---help---
+ 	 This drivers provides support for memory mapped virtio
+	 platform device driver.
+
+ 	 If unsure, say N.
+
 endmenu
diff --git a/drivers/virtio/Makefile b/drivers/virtio/Makefile
index 6738c44..5a4c63c 100644
--- a/drivers/virtio/Makefile
+++ b/drivers/virtio/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_VIRTIO) += virtio.o
 obj-$(CONFIG_VIRTIO_RING) += virtio_ring.o
+obj-$(CONFIG_VIRTIO_MMIO) += virtio_mmio.o
 obj-$(CONFIG_VIRTIO_PCI) += virtio_pci.o
 obj-$(CONFIG_VIRTIO_BALLOON) += virtio_balloon.o
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
new file mode 100644
index 0000000..acc5e43
--- /dev/null
+++ b/drivers/virtio/virtio_mmio.c
@@ -0,0 +1,479 @@
+/*
+ * Virtio memory mapped device driver
+ *
+ * Copyright 2011, ARM Ltd.
+ *
+ * This module allows virtio devices to be used over a virtual, memory mapped
+ * platform device.
+ *
+ * Registers layout (all 32-bit wide):
+ *
+ * offset d. name             description
+ * ------ -- ---------------- -----------------
+ *
+ * 0x000  R  MagicValue       Magic value "virt"
+ * 0x004  R  Version          Device version (current max. 1)
+ * 0x008  R  DeviceID         Virtio device ID
+ * 0x00c  R  VendorID         Virtio vendor ID
+ *
+ * 0x010  R  HostFeatures     Features supported by the host
+ * 0x014  W  HostFeaturesSel  Set of host features to access via HostFeatures
+ *
+ * 0x020  W  GuestFeatures    Features activated by the guest
+ * 0x024  W  GuestFeaturesSel Set of activated features to set via GuestFeatures
+ * 0x028  W  GuestPageSize    Size of guest's memory page in bytes
+ *
+ * 0x030  W  QueueSel         Queue selector
+ * 0x034  R  QueueNumMax      Maximum size of the currently selected queue
+ * 0x038  W  QueueNum         Queue size for the currently selected queue
+ * 0x03c  W  QueueAlign       Used Ring alignment for the current queue
+ * 0x040  RW QueuePFN         PFN for the currently selected queue
+ *
+ * 0x050  W  QueueNotify      Queue notifier
+ * 0x060  R  InterruptStatus  Interrupt status register
+ * 0x060  W  InterruptACK     Interrupt acknowledge register
+ * 0x070  RW Status           Device status register
+ *
+ * 0x100+ RW                  Device-specific configuration space
+ *
+ * Based on Virtio PCI driver by Anthony Liguori, copyright IBM Corp. 2007
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <linux/highmem.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/virtio.h>
+#include <linux/virtio_config.h>
+#include <linux/virtio_mmio.h>
+#include <linux/virtio_ring.h>
+
+
+
+/* The alignment to use between consumer and producer parts of vring.
+ * Currently hardcoded to the page size. */
+#define VIRTIO_MMIO_VRING_ALIGN		PAGE_SIZE
+
+
+
+#define to_virtio_mmio_device(_plat_dev) \
+	container_of(_plat_dev, struct virtio_mmio_device, vdev)
+
+struct virtio_mmio_device {
+	struct virtio_device vdev;
+	struct platform_device *pdev;
+
+	void __iomem *base;
+	unsigned long version;
+
+	/* a list of queues so we can dispatch IRQs */
+	spinlock_t lock;
+	struct list_head virtqueues;
+};
+
+struct virtio_mmio_vq_info {
+	/* the actual virtqueue */
+	struct virtqueue *vq;
+
+	/* the number of entries in the queue */
+	unsigned int num;
+
+	/* the index of the queue */
+	int queue_index;
+
+	/* the virtual address of the ring queue */
+	void *queue;
+
+	/* the list node for the virtqueues list */
+	struct list_head node;
+};
+
+
+
+/* Configuration interface */
+
+static u32 vm_get_features(struct virtio_device *vdev)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+
+	/* TODO: Features > 32 bits */
+	writel(0, vm_dev->base + VIRTIO_MMIO_HOST_FEATURES_SEL);
+
+	return readl(vm_dev->base + VIRTIO_MMIO_HOST_FEATURES);
+}
+
+static void vm_finalize_features(struct virtio_device *vdev)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+	int i;
+
+	/* Give virtio_ring a chance to accept features. */
+	vring_transport_features(vdev);
+
+	for (i = 0; i < ARRAY_SIZE(vdev->features); i++) {
+		writel(i, vm_dev->base + VIRTIO_MMIO_GUEST_FEATURES_SET);
+		writel(vdev->features[i],
+				vm_dev->base + VIRTIO_MMIO_GUEST_FEATURES);
+	}
+}
+
+static void vm_get(struct virtio_device *vdev, unsigned offset,
+		   void *buf, unsigned len)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+	u8 *ptr = buf;
+	int i;
+
+	for (i = 0; i < len; i++)
+		ptr[i] = readb(vm_dev->base + VIRTIO_MMIO_CONFIG + offset + i);
+}
+
+static void vm_set(struct virtio_device *vdev, unsigned offset,
+		   const void *buf, unsigned len)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+	const u8 *ptr = buf;
+	int i;
+
+	for (i = 0; i < len; i++)
+		writeb(ptr[i], vm_dev->base + VIRTIO_MMIO_CONFIG + offset + i);
+}
+
+static u8 vm_get_status(struct virtio_device *vdev)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+
+	return readl(vm_dev->base + VIRTIO_MMIO_STATUS) & 0xff;
+}
+
+static void vm_set_status(struct virtio_device *vdev, u8 status)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+
+	/* We should never be setting status to 0. */
+	BUG_ON(status == 0);
+
+	writel(status, vm_dev->base + VIRTIO_MMIO_STATUS);
+}
+
+static void vm_reset(struct virtio_device *vdev)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+
+	/* 0 status means a reset. */
+	writel(0, vm_dev->base + VIRTIO_MMIO_STATUS);
+}
+
+
+
+/* Transport interface */
+
+/* the notify function used when creating a virt queue */
+static void vm_notify(struct virtqueue *vq)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vq->vdev);
+	struct virtio_mmio_vq_info *info = vq->priv;
+
+	/* We write the queue's selector into the notification register to
+	 * signal the other end */
+	writel(info->queue_index, vm_dev->base + VIRTIO_MMIO_QUEUE_NOTIFY);
+}
+
+/* Notify all virtqueues on an interrupt. */
+static irqreturn_t vm_interrupt(int irq, void *opaque)
+{
+	struct virtio_mmio_device *vm_dev = opaque;
+	struct virtio_mmio_vq_info *info;
+	struct virtio_driver *vdrv = container_of(vm_dev->vdev.dev.driver,
+			struct virtio_driver, driver);
+	unsigned long status;
+	unsigned long flags;
+	irqreturn_t ret = IRQ_NONE;
+
+	/* Read and acknowledge interrupts */
+	status = readl(vm_dev->base + VIRTIO_MMIO_INTERRUPT_STATUS);
+	writel(status, vm_dev->base + VIRTIO_MMIO_INTERRUPT_ACK);
+
+	if (unlikely(status & VIRTIO_MMIO_INT_CONFIG)
+			&& vdrv && vdrv->config_changed) {
+		vdrv->config_changed(&vm_dev->vdev);
+		ret = IRQ_HANDLED;
+	}
+
+	if (likely(status & VIRTIO_MMIO_INT_VRING)) {
+		spin_lock_irqsave(&vm_dev->lock, flags);
+		list_for_each_entry(info, &vm_dev->virtqueues, node)
+			ret |= vring_interrupt(irq, info->vq);
+		spin_unlock_irqrestore(&vm_dev->lock, flags);
+	}
+
+	return ret;
+}
+
+
+
+static void vm_del_vq(struct virtqueue *vq)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vq->vdev);
+	struct virtio_mmio_vq_info *info = vq->priv;
+	unsigned long flags, size;
+
+	spin_lock_irqsave(&vm_dev->lock, flags);
+	list_del(&info->node);
+	spin_unlock_irqrestore(&vm_dev->lock, flags);
+
+	vring_del_virtqueue(vq);
+
+	/* Select and deactivate the queue */
+	writel(info->queue_index, vm_dev->base + VIRTIO_MMIO_QUEUE_SEL);
+	writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN);
+
+	size = PAGE_ALIGN(vring_size(info->num, VIRTIO_MMIO_VRING_ALIGN));
+	free_pages_exact(info->queue, size);
+	kfree(info);
+}
+
+static void vm_del_vqs(struct virtio_device *vdev)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+	struct virtqueue *vq, *n;
+
+	list_for_each_entry_safe(vq, n, &vdev->vqs, list)
+		vm_del_vq(vq);
+
+	free_irq(platform_get_irq(vm_dev->pdev, 0), vm_dev);
+}
+
+
+
+static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
+				  void (*callback)(struct virtqueue *vq),
+				  const char *name)
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+	struct virtio_mmio_vq_info *info;
+	struct virtqueue *vq;
+	unsigned long flags, size;
+	int err;
+
+	/* Select the queue we're interested in */
+	writel(index, vm_dev->base + VIRTIO_MMIO_QUEUE_SEL);
+
+	/* Queue shouldn't already be set up. */
+	if (readl(vm_dev->base + VIRTIO_MMIO_QUEUE_PFN)) {
+		err = -ENOENT;
+		goto error_available;
+	}
+
+	/* Allocate and fill out our active queue description */
+	info = kmalloc(sizeof(*info), GFP_KERNEL);
+	if (!info) {
+		err = -ENOMEM;
+		goto error_kmalloc;
+	}
+	info->queue_index = index;
+
+	/* Allocate pages for the queue - start with a queue as big as
+	 * possible (limited by maximum size allowed by device), drop down
+	 * to a minimal size, just big enough to fit descriptor table
+	 * and two rings (which makes it "alignment_size * 2")
+	 */
+	info->num = readl(vm_dev->base + VIRTIO_MMIO_QUEUE_NUM_MAX);
+	while (1) {
+		size = PAGE_ALIGN(vring_size(info->num,
+				VIRTIO_MMIO_VRING_ALIGN));
+		/* Already smallest possible allocation? */
+		if (size <= VIRTIO_MMIO_VRING_ALIGN * 2) {
+			err = -ENOMEM;
+			goto error_alloc_pages;
+		}
+
+		info->queue = alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO);
+		if (info->queue)
+			break;
+
+		info->num /= 2;
+	}
+
+	/* Activate the queue */
+	writel(info->num, vm_dev->base + VIRTIO_MMIO_QUEUE_NUM);
+	writel(VIRTIO_MMIO_VRING_ALIGN,
+			vm_dev->base + VIRTIO_MMIO_QUEUE_ALIGN);
+	writel(virt_to_phys(info->queue) >> PAGE_SHIFT,
+			vm_dev->base + VIRTIO_MMIO_QUEUE_PFN);
+
+	/* Create the vring */
+	vq = vring_new_virtqueue(info->num, VIRTIO_MMIO_VRING_ALIGN,
+				 vdev, info->queue, vm_notify, callback, name);
+	if (!vq) {
+		err = -ENOMEM;
+		goto error_new_virtqueue;
+	}
+
+	vq->priv = info;
+	info->vq = vq;
+
+	spin_lock_irqsave(&vm_dev->lock, flags);
+	list_add(&info->node, &vm_dev->virtqueues);
+	spin_unlock_irqrestore(&vm_dev->lock, flags);
+
+	return vq;
+
+error_new_virtqueue:
+	writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN);
+	free_pages_exact(info->queue, size);
+error_alloc_pages:
+	kfree(info);
+error_kmalloc:
+error_available:
+	return ERR_PTR(err);
+}
+
+static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
+		       struct virtqueue *vqs[],
+		       vq_callback_t *callbacks[],
+		       const char *names[])
+{
+	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+	unsigned int irq = platform_get_irq(vm_dev->pdev, 0);
+	int i, err;
+
+	err = request_irq(irq, vm_interrupt, IRQF_SHARED,
+			dev_name(&vdev->dev), vm_dev);
+	if (err)
+		return err;
+
+	for (i = 0; i < nvqs; ++i) {
+		vqs[i] = vm_setup_vq(vdev, i, callbacks[i], names[i]);
+		if (IS_ERR(vqs[i])) {
+			vm_del_vqs(vdev);
+			return PTR_ERR(vqs[i]);
+		}
+	}
+
+	return 0;
+}
+
+
+
+static struct virtio_config_ops virtio_mmio_config_ops = {
+	.get		= vm_get,
+	.set		= vm_set,
+	.get_status	= vm_get_status,
+	.set_status	= vm_set_status,
+	.reset		= vm_reset,
+	.find_vqs	= vm_find_vqs,
+	.del_vqs	= vm_del_vqs,
+	.get_features	= vm_get_features,
+	.finalize_features = vm_finalize_features,
+};
+
+
+
+/* Platform device */
+
+static int __devinit virtio_mmio_probe(struct platform_device *pdev)
+{
+	struct virtio_mmio_device *vm_dev;
+	struct resource *mem;
+	unsigned long magic;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem)
+		return -EINVAL;
+
+	if (!devm_request_mem_region(&pdev->dev, mem->start,
+			resource_size(mem), pdev->name))
+		return -EBUSY;
+
+	vm_dev = devm_kzalloc(&pdev->dev, sizeof(*vm_dev), GFP_KERNEL);
+	if (!vm_dev)
+		return  -ENOMEM;
+
+	vm_dev->vdev.dev.parent = &pdev->dev;
+	vm_dev->vdev.config = &virtio_mmio_config_ops;
+	vm_dev->pdev = pdev;
+	INIT_LIST_HEAD(&vm_dev->virtqueues);
+	spin_lock_init(&vm_dev->lock);
+
+	vm_dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
+	if (vm_dev->base == NULL)
+		return -EFAULT;
+
+	/* Check magic value */
+	magic = readl(vm_dev->base + VIRTIO_MMIO_MAGIC_VALUE);
+	if (memcmp(&magic, "virt", 4) != 0) {
+		dev_warn(&pdev->dev, "Wrong magic value 0x%08lx!\n", magic);
+		return -ENODEV;
+	}
+
+	/* Check device version */
+	vm_dev->version = readl(vm_dev->base + VIRTIO_MMIO_VERSION);
+	if (vm_dev->version != 1) {
+		dev_err(&pdev->dev, "Version %ld not supported!\n",
+				vm_dev->version);
+		return -ENXIO;
+	}
+
+	vm_dev->vdev.id.device = readl(vm_dev->base + VIRTIO_MMIO_DEVICE_ID);
+	vm_dev->vdev.id.vendor = readl(vm_dev->base + VIRTIO_MMIO_VENDOR_ID);
+
+	writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_GUEST_PAGE_SIZE);
+
+	platform_set_drvdata(pdev, vm_dev);
+
+	return register_virtio_device(&vm_dev->vdev);
+}
+
+static int __devexit virtio_mmio_remove(struct platform_device *pdev)
+{
+	struct virtio_mmio_device *vm_dev = platform_get_drvdata(pdev);
+
+	unregister_virtio_device(&vm_dev->vdev);
+
+	return 0;
+}
+
+
+
+/* Platform driver */
+
+static struct of_device_id virtio_mmio_match[] = {
+	{ .compatible = "virtio,mmio", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, virtio_mmio_match);
+
+static struct platform_driver virtio_mmio_driver = {
+	.probe		= virtio_mmio_probe,
+	.remove		= __devexit_p(virtio_mmio_remove),
+	.driver		= {
+		.name	= "virtio-mmio",
+		.owner	= THIS_MODULE,
+		.of_match_table	= virtio_mmio_match,
+	},
+};
+
+static int __init virtio_mmio_init(void)
+{
+	return platform_driver_register(&virtio_mmio_driver);
+}
+
+static void __exit virtio_mmio_exit(void)
+{
+	platform_driver_unregister(&virtio_mmio_driver);
+}
+
+module_init(virtio_mmio_init);
+module_exit(virtio_mmio_exit);
+
+MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>");
+MODULE_DESCRIPTION("Platform bus driver for memory mapped virtio devices");
+MODULE_LICENSE("GPL");
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
index 4bcc8b8..79a31e5 100644
--- a/drivers/virtio/virtio_pci.c
+++ b/drivers/virtio/virtio_pci.c
@@ -415,9 +415,13 @@ static struct virtqueue *setup_vq(struct virtio_device *vdev, unsigned index,
 		}
 	}
 
-	spin_lock_irqsave(&vp_dev->lock, flags);
-	list_add(&info->node, &vp_dev->virtqueues);
-	spin_unlock_irqrestore(&vp_dev->lock, flags);
+	if (callback) {
+		spin_lock_irqsave(&vp_dev->lock, flags);
+		list_add(&info->node, &vp_dev->virtqueues);
+		spin_unlock_irqrestore(&vp_dev->lock, flags);
+	} else {
+		INIT_LIST_HEAD(&info->node);
+	}
 
 	return vq;
 
diff --git a/drivers/w1/slaves/w1_ds2760.c b/drivers/w1/slaves/w1_ds2760.c
index 483d451..5754c9a 100644
--- a/drivers/w1/slaves/w1_ds2760.c
+++ b/drivers/w1/slaves/w1_ds2760.c
@@ -114,43 +114,7 @@ static struct bin_attribute w1_ds2760_bin_attr = {
 	.read = w1_ds2760_read_bin,
 };
 
-static DEFINE_IDR(bat_idr);
-static DEFINE_MUTEX(bat_idr_lock);
-
-static int new_bat_id(void)
-{
-	int ret;
-
-	while (1) {
-		int id;
-
-		ret = idr_pre_get(&bat_idr, GFP_KERNEL);
-		if (ret == 0)
-			return -ENOMEM;
-
-		mutex_lock(&bat_idr_lock);
-		ret = idr_get_new(&bat_idr, NULL, &id);
-		mutex_unlock(&bat_idr_lock);
-
-		if (ret == 0) {
-			ret = id & MAX_ID_MASK;
-			break;
-		} else if (ret == -EAGAIN) {
-			continue;
-		} else {
-			break;
-		}
-	}
-
-	return ret;
-}
-
-static void release_bat_id(int id)
-{
-	mutex_lock(&bat_idr_lock);
-	idr_remove(&bat_idr, id);
-	mutex_unlock(&bat_idr_lock);
-}
+static DEFINE_IDA(bat_ida);
 
 static int w1_ds2760_add_slave(struct w1_slave *sl)
 {
@@ -158,7 +122,7 @@ static int w1_ds2760_add_slave(struct w1_slave *sl)
 	int id;
 	struct platform_device *pdev;
 
-	id = new_bat_id();
+	id = ida_simple_get(&bat_ida, 0, 0, GFP_KERNEL);
 	if (id < 0) {
 		ret = id;
 		goto noid;
@@ -187,7 +151,7 @@ bin_attr_failed:
 pdev_add_failed:
 	platform_device_unregister(pdev);
 pdev_alloc_failed:
-	release_bat_id(id);
+	ida_simple_remove(&bat_ida, id);
 noid:
 success:
 	return ret;
@@ -199,7 +163,7 @@ static void w1_ds2760_remove_slave(struct w1_slave *sl)
 	int id = pdev->id;
 
 	platform_device_unregister(pdev);
-	release_bat_id(id);
+	ida_simple_remove(&bat_ida, id);
 	sysfs_remove_bin_file(&sl->dev.kobj, &w1_ds2760_bin_attr);
 }
 
@@ -217,14 +181,14 @@ static int __init w1_ds2760_init(void)
 {
 	printk(KERN_INFO "1-Wire driver for the DS2760 battery monitor "
 	       " chip  - (c) 2004-2005, Szabolcs Gyurko\n");
-	idr_init(&bat_idr);
+	ida_init(&bat_ida);
 	return w1_register_family(&w1_ds2760_family);
 }
 
 static void __exit w1_ds2760_exit(void)
 {
 	w1_unregister_family(&w1_ds2760_family);
-	idr_destroy(&bat_idr);
+	ida_destroy(&bat_ida);
 }
 
 EXPORT_SYMBOL(w1_ds2760_read);
diff --git a/drivers/w1/slaves/w1_ds2780.c b/drivers/w1/slaves/w1_ds2780.c
index 274c8f3..39f78c0 100644
--- a/drivers/w1/slaves/w1_ds2780.c
+++ b/drivers/w1/slaves/w1_ds2780.c
@@ -26,20 +26,14 @@
 #include "../w1_family.h"
 #include "w1_ds2780.h"
 
-int w1_ds2780_io(struct device *dev, char *buf, int addr, size_t count,
-			int io)
+static int w1_ds2780_do_io(struct device *dev, char *buf, int addr,
+			size_t count, int io)
 {
 	struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
 
-	if (!dev)
-		return -ENODEV;
+	if (addr > DS2780_DATA_SIZE || addr < 0)
+		return 0;
 
-	mutex_lock(&sl->master->mutex);
-
-	if (addr > DS2780_DATA_SIZE || addr < 0) {
-		count = 0;
-		goto out;
-	}
 	count = min_t(int, count, DS2780_DATA_SIZE - addr);
 
 	if (w1_reset_select_slave(sl) == 0) {
@@ -47,7 +41,6 @@ int w1_ds2780_io(struct device *dev, char *buf, int addr, size_t count,
 			w1_write_8(sl->master, W1_DS2780_WRITE_DATA);
 			w1_write_8(sl->master, addr);
 			w1_write_block(sl->master, buf, count);
-			/* XXX w1_write_block returns void, not n_written */
 		} else {
 			w1_write_8(sl->master, W1_DS2780_READ_DATA);
 			w1_write_8(sl->master, addr);
@@ -55,13 +48,42 @@ int w1_ds2780_io(struct device *dev, char *buf, int addr, size_t count,
 		}
 	}
 
-out:
+	return count;
+}
+
+int w1_ds2780_io(struct device *dev, char *buf, int addr, size_t count,
+			int io)
+{
+	struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
+	int ret;
+
+	if (!dev)
+		return -ENODEV;
+
+	mutex_lock(&sl->master->mutex);
+
+	ret = w1_ds2780_do_io(dev, buf, addr, count, io);
+
 	mutex_unlock(&sl->master->mutex);
 
-	return count;
+	return ret;
 }
 EXPORT_SYMBOL(w1_ds2780_io);
 
+int w1_ds2780_io_nolock(struct device *dev, char *buf, int addr, size_t count,
+			int io)
+{
+	int ret;
+
+	if (!dev)
+		return -ENODEV;
+
+	ret = w1_ds2780_do_io(dev, buf, addr, count, io);
+
+	return ret;
+}
+EXPORT_SYMBOL(w1_ds2780_io_nolock);
+
 int w1_ds2780_eeprom_cmd(struct device *dev, int addr, int cmd)
 {
 	struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
@@ -99,43 +121,7 @@ static struct bin_attribute w1_ds2780_bin_attr = {
 	.read = w1_ds2780_read_bin,
 };
 
-static DEFINE_IDR(bat_idr);
-static DEFINE_MUTEX(bat_idr_lock);
-
-static int new_bat_id(void)
-{
-	int ret;
-
-	while (1) {
-		int id;
-
-		ret = idr_pre_get(&bat_idr, GFP_KERNEL);
-		if (ret == 0)
-			return -ENOMEM;
-
-		mutex_lock(&bat_idr_lock);
-		ret = idr_get_new(&bat_idr, NULL, &id);
-		mutex_unlock(&bat_idr_lock);
-
-		if (ret == 0) {
-			ret = id & MAX_ID_MASK;
-			break;
-		} else if (ret == -EAGAIN) {
-			continue;
-		} else {
-			break;
-		}
-	}
-
-	return ret;
-}
-
-static void release_bat_id(int id)
-{
-	mutex_lock(&bat_idr_lock);
-	idr_remove(&bat_idr, id);
-	mutex_unlock(&bat_idr_lock);
-}
+static DEFINE_IDA(bat_ida);
 
 static int w1_ds2780_add_slave(struct w1_slave *sl)
 {
@@ -143,7 +129,7 @@ static int w1_ds2780_add_slave(struct w1_slave *sl)
 	int id;
 	struct platform_device *pdev;
 
-	id = new_bat_id();
+	id = ida_simple_get(&bat_ida, 0, 0, GFP_KERNEL);
 	if (id < 0) {
 		ret = id;
 		goto noid;
@@ -172,7 +158,7 @@ bin_attr_failed:
 pdev_add_failed:
 	platform_device_unregister(pdev);
 pdev_alloc_failed:
-	release_bat_id(id);
+	ida_simple_remove(&bat_ida, id);
 noid:
 	return ret;
 }
@@ -183,7 +169,7 @@ static void w1_ds2780_remove_slave(struct w1_slave *sl)
 	int id = pdev->id;
 
 	platform_device_unregister(pdev);
-	release_bat_id(id);
+	ida_simple_remove(&bat_ida, id);
 	sysfs_remove_bin_file(&sl->dev.kobj, &w1_ds2780_bin_attr);
 }
 
@@ -199,14 +185,14 @@ static struct w1_family w1_ds2780_family = {
 
 static int __init w1_ds2780_init(void)
 {
-	idr_init(&bat_idr);
+	ida_init(&bat_ida);
 	return w1_register_family(&w1_ds2780_family);
 }
 
 static void __exit w1_ds2780_exit(void)
 {
 	w1_unregister_family(&w1_ds2780_family);
-	idr_destroy(&bat_idr);
+	ida_destroy(&bat_ida);
 }
 
 module_init(w1_ds2780_init);
diff --git a/drivers/w1/slaves/w1_ds2780.h b/drivers/w1/slaves/w1_ds2780.h
index a1fba79..7373793 100644
--- a/drivers/w1/slaves/w1_ds2780.h
+++ b/drivers/w1/slaves/w1_ds2780.h
@@ -124,6 +124,8 @@
 
 extern int w1_ds2780_io(struct device *dev, char *buf, int addr, size_t count,
 			int io);
+extern int w1_ds2780_io_nolock(struct device *dev, char *buf, int addr,
+			size_t count, int io);
 extern int w1_ds2780_eeprom_cmd(struct device *dev, int addr, int cmd);
 
 #endif /* !_W1_DS2780_H */
diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c
index d220bce..f79e62e 100644
--- a/drivers/w1/w1_int.c
+++ b/drivers/w1/w1_int.c
@@ -78,6 +78,7 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
 	memcpy(&dev->dev, device, sizeof(struct device));
 	dev_set_name(&dev->dev, "w1_bus_master%u", dev->id);
 	snprintf(dev->name, sizeof(dev->name), "w1_bus_master%u", dev->id);
+	dev->dev.init_name = dev->name;
 
 	dev->driver = driver;
 
diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c
index 765b37b..3135b2c 100644
--- a/drivers/w1/w1_io.c
+++ b/drivers/w1/w1_io.c
@@ -158,13 +158,18 @@ EXPORT_SYMBOL_GPL(w1_write_8);
 static u8 w1_read_bit(struct w1_master *dev)
 {
 	int result;
+	unsigned long flags;
 
+	/* sample timing is critical here */
+	local_irq_save(flags);
 	dev->bus_master->write_bit(dev->bus_master->data, 0);
 	w1_delay(6);
 	dev->bus_master->write_bit(dev->bus_master->data, 1);
 	w1_delay(9);
 
 	result = dev->bus_master->read_bit(dev->bus_master->data);
+	local_irq_restore(flags);
+
 	w1_delay(55);
 
 	return result & 0x1;
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 86b0735..64c6752 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -726,7 +726,7 @@ config SBC8360_WDT
 
 config SBC7240_WDT
 	tristate "SBC Nano 7240 Watchdog Timer"
-	depends on X86_32
+	depends on X86_32 && !UML
 	---help---
 	  This is the driver for the hardware watchdog found on the IEI
 	  single board computers EPIC Nano 7240 (and likely others). This
@@ -1174,6 +1174,10 @@ config XEN_WDT
 	  by Xen 4.0 and newer.  The watchdog timeout period is normally one
 	  minute but can be changed with a boot-time parameter.
 
+config UML_WATCHDOG
+	tristate "UML watchdog"
+	depends on UML
+
 #
 # ISA-based Watchdog Cards
 #
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index b5a1076..879ed88 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -1138,7 +1138,7 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
 	struct v9fs_session_info *v9ses = sb->s_fs_info;
 	struct v9fs_inode *v9inode = V9FS_I(inode);
 
-	inode->i_nlink = 1;
+	set_nlink(inode, 1);
 
 	inode->i_atime.tv_sec = stat->atime;
 	inode->i_mtime.tv_sec = stat->mtime;
@@ -1164,7 +1164,7 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
 			/* HARDLINKCOUNT %u */
 			sscanf(ext, "%13s %u", tag_name, &i_nlink);
 			if (!strncmp(tag_name, "HARDLINKCOUNT", 13))
-				inode->i_nlink = i_nlink;
+				set_nlink(inode, i_nlink);
 		}
 	}
 	mode = stat->mode & S_IALLUGO;
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index aded79f..0b5745e 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -606,7 +606,7 @@ v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode)
 		inode->i_ctime.tv_nsec = stat->st_ctime_nsec;
 		inode->i_uid = stat->st_uid;
 		inode->i_gid = stat->st_gid;
-		inode->i_nlink = stat->st_nlink;
+		set_nlink(inode, stat->st_nlink);
 
 		mode = stat->st_mode & S_IALLUGO;
 		mode |= inode->i_mode & ~S_IALLUGO;
@@ -632,7 +632,7 @@ v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode)
 		if (stat->st_result_mask & P9_STATS_GID)
 			inode->i_gid = stat->st_gid;
 		if (stat->st_result_mask & P9_STATS_NLINK)
-			inode->i_nlink = stat->st_nlink;
+			set_nlink(inode, stat->st_nlink);
 		if (stat->st_result_mask & P9_STATS_MODE) {
 			inode->i_mode = stat->st_mode;
 			if ((S_ISBLK(inode->i_mode)) ||
diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c
index d5250c5..1dab6a1 100644
--- a/fs/adfs/inode.c
+++ b/fs/adfs/inode.c
@@ -247,7 +247,7 @@ adfs_iget(struct super_block *sb, struct object_info *obj)
 	inode->i_gid	 = ADFS_SB(sb)->s_gid;
 	inode->i_ino	 = obj->file_id;
 	inode->i_size	 = obj->size;
-	inode->i_nlink	 = 2;
+	set_nlink(inode, 2);
 	inode->i_blocks	 = (inode->i_size + sb->s_blocksize - 1) >>
 			    sb->s_blocksize_bits;
 
diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c
index 3a4557e..de37ec8 100644
--- a/fs/affs/amigaffs.c
+++ b/fs/affs/amigaffs.c
@@ -215,7 +215,7 @@ affs_remove_link(struct dentry *dentry)
 				break;
 			default:
 				if (!AFFS_TAIL(sb, bh)->link_chain)
-					inode->i_nlink = 1;
+					set_nlink(inode, 1);
 			}
 			affs_free_block(sb, link_ino);
 			goto done;
@@ -316,7 +316,7 @@ affs_remove_header(struct dentry *dentry)
 	if (inode->i_nlink > 1)
 		retval = affs_remove_link(dentry);
 	else
-		inode->i_nlink = 0;
+		clear_nlink(inode);
 	affs_unlock_link(inode);
 	inode->i_ctime = CURRENT_TIME_SEC;
 	mark_inode_dirty(inode);
diff --git a/fs/affs/inode.c b/fs/affs/inode.c
index 5d82890..88a4b0b 100644
--- a/fs/affs/inode.c
+++ b/fs/affs/inode.c
@@ -54,7 +54,7 @@ struct inode *affs_iget(struct super_block *sb, unsigned long ino)
 	prot = be32_to_cpu(tail->protect);
 
 	inode->i_size = 0;
-	inode->i_nlink = 1;
+	set_nlink(inode, 1);
 	inode->i_mode = 0;
 	AFFS_I(inode)->i_extcnt = 1;
 	AFFS_I(inode)->i_ext_last = ~1;
@@ -137,7 +137,7 @@ struct inode *affs_iget(struct super_block *sb, unsigned long ino)
 					       sbi->s_hashsize + 1;
 		}
 		if (tail->link_chain)
-			inode->i_nlink = 2;
+			set_nlink(inode, 2);
 		inode->i_mapping->a_ops = (sbi->s_flags & SF_OFS) ? &affs_aops_ofs : &affs_aops;
 		inode->i_op = &affs_file_inode_operations;
 		inode->i_fop = &affs_file_operations;
@@ -304,7 +304,7 @@ affs_new_inode(struct inode *dir)
 	inode->i_uid     = current_fsuid();
 	inode->i_gid     = current_fsgid();
 	inode->i_ino     = block;
-	inode->i_nlink   = 1;
+	set_nlink(inode, 1);
 	inode->i_mtime   = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
 	atomic_set(&AFFS_I(inode)->i_opencnt, 0);
 	AFFS_I(inode)->i_blkcnt = 0;
@@ -387,7 +387,7 @@ affs_add_entry(struct inode *dir, struct inode *inode, struct dentry *dentry, s3
 		AFFS_TAIL(sb, inode_bh)->link_chain = cpu_to_be32(block);
 		affs_adjust_checksum(inode_bh, block - be32_to_cpu(chain));
 		mark_buffer_dirty_inode(inode_bh, inode);
-		inode->i_nlink = 2;
+		set_nlink(inode, 2);
 		ihold(inode);
 	}
 	affs_fix_checksum(sb, bh);
diff --git a/fs/affs/namei.c b/fs/affs/namei.c
index e3e9efc..780a11d 100644
--- a/fs/affs/namei.c
+++ b/fs/affs/namei.c
@@ -277,7 +277,7 @@ affs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata
 	inode->i_mapping->a_ops = (AFFS_SB(sb)->s_flags & SF_OFS) ? &affs_aops_ofs : &affs_aops;
 	error = affs_add_entry(dir, inode, dentry, ST_FILE);
 	if (error) {
-		inode->i_nlink = 0;
+		clear_nlink(inode);
 		iput(inode);
 		return error;
 	}
@@ -305,7 +305,7 @@ affs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 
 	error = affs_add_entry(dir, inode, dentry, ST_USERDIR);
 	if (error) {
-		inode->i_nlink = 0;
+		clear_nlink(inode);
 		mark_inode_dirty(inode);
 		iput(inode);
 		return error;
@@ -392,7 +392,7 @@ affs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
 	return 0;
 
 err:
-	inode->i_nlink = 0;
+	clear_nlink(inode);
 	mark_inode_dirty(inode);
 	iput(inode);
 	return error;
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c
index 346e328..2f213d1 100644
--- a/fs/afs/fsclient.c
+++ b/fs/afs/fsclient.c
@@ -90,7 +90,7 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
 			vnode->vfs_inode.i_uid = status->owner;
 			vnode->vfs_inode.i_gid = status->group;
 			vnode->vfs_inode.i_generation = vnode->fid.unique;
-			vnode->vfs_inode.i_nlink = status->nlink;
+			set_nlink(&vnode->vfs_inode, status->nlink);
 
 			mode = vnode->vfs_inode.i_mode;
 			mode &= ~S_IALLUGO;
diff --git a/fs/afs/inode.c b/fs/afs/inode.c
index 0fdab6e..d890ae3 100644
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -67,7 +67,7 @@ static int afs_inode_map_status(struct afs_vnode *vnode, struct key *key)
 		fscache_attr_changed(vnode->cache);
 #endif
 
-	inode->i_nlink		= vnode->status.nlink;
+	set_nlink(inode, vnode->status.nlink);
 	inode->i_uid		= vnode->status.owner;
 	inode->i_gid		= 0;
 	inode->i_size		= vnode->status.size;
@@ -174,7 +174,7 @@ struct inode *afs_iget_autocell(struct inode *dir, const char *dev_name,
 	inode->i_size		= 0;
 	inode->i_mode		= S_IFDIR | S_IRUGO | S_IXUGO;
 	inode->i_op		= &afs_autocell_inode_operations;
-	inode->i_nlink		= 2;
+	set_nlink(inode, 2);
 	inode->i_uid		= 0;
 	inode->i_gid		= 0;
 	inode->i_ctime.tv_sec	= get_seconds();
diff --git a/fs/aio.c b/fs/aio.c
index 632b235..78c514c 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -440,8 +440,6 @@ void exit_aio(struct mm_struct *mm)
 static struct kiocb *__aio_get_req(struct kioctx *ctx)
 {
 	struct kiocb *req = NULL;
-	struct aio_ring *ring;
-	int okay = 0;
 
 	req = kmem_cache_alloc(kiocb_cachep, GFP_KERNEL);
 	if (unlikely(!req))
@@ -459,39 +457,114 @@ static struct kiocb *__aio_get_req(struct kioctx *ctx)
 	INIT_LIST_HEAD(&req->ki_run_list);
 	req->ki_eventfd = NULL;
 
-	/* Check if the completion queue has enough free space to
-	 * accept an event from this io.
-	 */
+	return req;
+}
+
+/*
+ * struct kiocb's are allocated in batches to reduce the number of
+ * times the ctx lock is acquired and released.
+ */
+#define KIOCB_BATCH_SIZE	32L
+struct kiocb_batch {
+	struct list_head head;
+	long count; /* number of requests left to allocate */
+};
+
+static void kiocb_batch_init(struct kiocb_batch *batch, long total)
+{
+	INIT_LIST_HEAD(&batch->head);
+	batch->count = total;
+}
+
+static void kiocb_batch_free(struct kiocb_batch *batch)
+{
+	struct kiocb *req, *n;
+
+	list_for_each_entry_safe(req, n, &batch->head, ki_batch) {
+		list_del(&req->ki_batch);
+		kmem_cache_free(kiocb_cachep, req);
+	}
+}
+
+/*
+ * Allocate a batch of kiocbs.  This avoids taking and dropping the
+ * context lock a lot during setup.
+ */
+static int kiocb_batch_refill(struct kioctx *ctx, struct kiocb_batch *batch)
+{
+	unsigned short allocated, to_alloc;
+	long avail;
+	bool called_fput = false;
+	struct kiocb *req, *n;
+	struct aio_ring *ring;
+
+	to_alloc = min(batch->count, KIOCB_BATCH_SIZE);
+	for (allocated = 0; allocated < to_alloc; allocated++) {
+		req = __aio_get_req(ctx);
+		if (!req)
+			/* allocation failed, go with what we've got */
+			break;
+		list_add(&req->ki_batch, &batch->head);
+	}
+
+	if (allocated == 0)
+		goto out;
+
+retry:
 	spin_lock_irq(&ctx->ctx_lock);
-	ring = kmap_atomic(ctx->ring_info.ring_pages[0], KM_USER0);
-	if (ctx->reqs_active < aio_ring_avail(&ctx->ring_info, ring)) {
+	ring = kmap_atomic(ctx->ring_info.ring_pages[0]);
+
+	avail = aio_ring_avail(&ctx->ring_info, ring) - ctx->reqs_active;
+	BUG_ON(avail < 0);
+	if (avail == 0 && !called_fput) {
+		/*
+		 * Handle a potential starvation case.  It is possible that
+		 * we hold the last reference on a struct file, causing us
+		 * to delay the final fput to non-irq context.  In this case,
+		 * ctx->reqs_active is artificially high.  Calling the fput
+		 * routine here may free up a slot in the event completion
+		 * ring, allowing this allocation to succeed.
+		 */
+		kunmap_atomic(ring);
+		spin_unlock_irq(&ctx->ctx_lock);
+		aio_fput_routine(NULL);
+		called_fput = true;
+		goto retry;
+	}
+
+	if (avail < allocated) {
+		/* Trim back the number of requests. */
+		list_for_each_entry_safe(req, n, &batch->head, ki_batch) {
+			list_del(&req->ki_batch);
+			kmem_cache_free(kiocb_cachep, req);
+			if (--allocated <= avail)
+				break;
+		}
+	}
+
+	batch->count -= allocated;
+	list_for_each_entry(req, &batch->head, ki_batch) {
 		list_add(&req->ki_list, &ctx->active_reqs);
 		ctx->reqs_active++;
-		okay = 1;
 	}
-	kunmap_atomic(ring, KM_USER0);
-	spin_unlock_irq(&ctx->ctx_lock);
 
-	if (!okay) {
-		kmem_cache_free(kiocb_cachep, req);
-		req = NULL;
-	}
+	kunmap_atomic(ring);
+	spin_unlock_irq(&ctx->ctx_lock);
 
-	return req;
+out:
+	return allocated;
 }
 
-static inline struct kiocb *aio_get_req(struct kioctx *ctx)
+static inline struct kiocb *aio_get_req(struct kioctx *ctx,
+					struct kiocb_batch *batch)
 {
 	struct kiocb *req;
-	/* Handle a potential starvation case -- should be exceedingly rare as 
-	 * requests will be stuck on fput_head only if the aio_fput_routine is 
-	 * delayed and the requests were the last user of the struct file.
-	 */
-	req = __aio_get_req(ctx);
-	if (unlikely(NULL == req)) {
-		aio_fput_routine(NULL);
-		req = __aio_get_req(ctx);
-	}
+
+	if (list_empty(&batch->head))
+		if (kiocb_batch_refill(ctx, batch) == 0)
+			return NULL;
+	req = list_first_entry(&batch->head, struct kiocb, ki_batch);
+	list_del(&req->ki_batch);
 	return req;
 }
 
@@ -1515,7 +1588,8 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat)
 }
 
 static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
-			 struct iocb *iocb, bool compat)
+			 struct iocb *iocb, struct kiocb_batch *batch,
+			 bool compat)
 {
 	struct kiocb *req;
 	struct file *file;
@@ -1541,7 +1615,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
 	if (unlikely(!file))
 		return -EBADF;
 
-	req = aio_get_req(ctx);		/* returns with 2 references to req */
+	req = aio_get_req(ctx, batch);  /* returns with 2 references to req */
 	if (unlikely(!req)) {
 		fput(file);
 		return -EAGAIN;
@@ -1621,8 +1695,9 @@ long do_io_submit(aio_context_t ctx_id, long nr,
 {
 	struct kioctx *ctx;
 	long ret = 0;
-	int i;
+	int i = 0;
 	struct blk_plug plug;
+	struct kiocb_batch batch;
 
 	if (unlikely(nr < 0))
 		return -EINVAL;
@@ -1639,6 +1714,8 @@ long do_io_submit(aio_context_t ctx_id, long nr,
 		return -EINVAL;
 	}
 
+	kiocb_batch_init(&batch, nr);
+
 	blk_start_plug(&plug);
 
 	/*
@@ -1659,12 +1736,13 @@ long do_io_submit(aio_context_t ctx_id, long nr,
 			break;
 		}
 
-		ret = io_submit_one(ctx, user_iocb, &tmp, compat);
+		ret = io_submit_one(ctx, user_iocb, &tmp, &batch, compat);
 		if (ret)
 			break;
 	}
 	blk_finish_plug(&plug);
 
+	kiocb_batch_free(&batch);
 	put_ioctx(ctx);
 	return i ? i : ret;
 }
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index 180fa24..8179f1a 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -342,7 +342,7 @@ struct inode *autofs4_get_inode(struct super_block *sb, mode_t mode)
 	inode->i_ino = get_next_ino();
 
 	if (S_ISDIR(mode)) {
-		inode->i_nlink = 2;
+		set_nlink(inode, 2);
 		inode->i_op = &autofs4_dir_inode_operations;
 		inode->i_fop = &autofs4_dir_operations;
 	} else if (S_ISLNK(mode)) {
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
index 720d885..8342ca6 100644
--- a/fs/befs/linuxvfs.c
+++ b/fs/befs/linuxvfs.c
@@ -357,7 +357,7 @@ static struct inode *befs_iget(struct super_block *sb, unsigned long ino)
 	inode->i_gid = befs_sb->mount_opts.use_gid ?
 	    befs_sb->mount_opts.gid : (gid_t) fs32_to_cpu(sb, raw_inode->gid);
 
-	inode->i_nlink = 1;
+	set_nlink(inode, 1);
 
 	/*
 	 * BEFS's time is 64 bits, but current VFS is 32 bits...
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c
index b14cebf..9cc0740 100644
--- a/fs/bfs/dir.c
+++ b/fs/bfs/dir.c
@@ -199,7 +199,7 @@ static int bfs_unlink(struct inode *dir, struct dentry *dentry)
 		printf("unlinking non-existent file %s:%lu (nlink=%d)\n",
 					inode->i_sb->s_id, inode->i_ino,
 					inode->i_nlink);
-		inode->i_nlink = 1;
+		set_nlink(inode, 1);
 	}
 	de->ino = 0;
 	mark_buffer_dirty_inode(bh, dir);
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c
index a8e37f8..697af5b 100644
--- a/fs/bfs/inode.c
+++ b/fs/bfs/inode.c
@@ -78,7 +78,7 @@ struct inode *bfs_iget(struct super_block *sb, unsigned long ino)
 	BFS_I(inode)->i_dsk_ino = le16_to_cpu(di->i_ino);
 	inode->i_uid =  le32_to_cpu(di->i_uid);
 	inode->i_gid =  le32_to_cpu(di->i_gid);
-	inode->i_nlink =  le32_to_cpu(di->i_nlink);
+	set_nlink(inode, le32_to_cpu(di->i_nlink));
 	inode->i_size = BFS_FILESIZE(di);
 	inode->i_blocks = BFS_FILEBLOCKS(di);
 	inode->i_atime.tv_sec =  le32_to_cpu(di->i_atime);
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index dd0fdfc..21ac5ee 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -795,7 +795,16 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
 			 * might try to exec.  This is because the brk will
 			 * follow the loader, and is not movable.  */
 #if defined(CONFIG_X86) || defined(CONFIG_ARM)
-			load_bias = 0;
+			/* Memory randomization might have been switched off
+			 * in runtime via sysctl.
+			 * If that is the case, retain the original non-zero
+			 * load_bias value in order to establish proper
+			 * non-randomized mappings.
+			 */
+			if (current->flags & PF_RANDOMIZE)
+				load_bias = 0;
+			else
+				load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
 #else
 			load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
 #endif
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index ba1a1ae..1e9edbd 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -521,7 +521,7 @@ static void kill_node(Node *e)
 	write_unlock(&entries_lock);
 
 	if (dentry) {
-		dentry->d_inode->i_nlink--;
+		drop_nlink(dentry->d_inode);
 		d_drop(dentry);
 		dput(dentry);
 		simple_release_fs(&bm_mnt, &entry_count);
diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c
index b52c672..ae4d9cd 100644
--- a/fs/btrfs/delayed-inode.c
+++ b/fs/btrfs/delayed-inode.c
@@ -1641,7 +1641,7 @@ int btrfs_fill_inode(struct inode *inode, u32 *rdev)
 	inode->i_gid = btrfs_stack_inode_gid(inode_item);
 	btrfs_i_size_write(inode, btrfs_stack_inode_size(inode_item));
 	inode->i_mode = btrfs_stack_inode_mode(inode_item);
-	inode->i_nlink = btrfs_stack_inode_nlink(inode_item);
+	set_nlink(inode, btrfs_stack_inode_nlink(inode_item));
 	inode_set_bytes(inode, btrfs_stack_inode_nbytes(inode_item));
 	BTRFS_I(inode)->generation = btrfs_stack_inode_generation(inode_item);
 	BTRFS_I(inode)->sequence = btrfs_stack_inode_sequence(inode_item);
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 07b3ac6..07ea918 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1705,7 +1705,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
 	sb->s_bdi = &fs_info->bdi;
 
 	fs_info->btree_inode->i_ino = BTRFS_BTREE_INODE_OBJECTID;
-	fs_info->btree_inode->i_nlink = 1;
+	set_nlink(fs_info->btree_inode, 1);
 	/*
 	 * we set the i_size on the btree inode to the max possible int.
 	 * the real end of the address space is determined by all of
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index b2d004a..75686a6 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -2534,7 +2534,7 @@ static void btrfs_read_locked_inode(struct inode *inode)
 	inode_item = btrfs_item_ptr(leaf, path->slots[0],
 				    struct btrfs_inode_item);
 	inode->i_mode = btrfs_inode_mode(leaf, inode_item);
-	inode->i_nlink = btrfs_inode_nlink(leaf, inode_item);
+	set_nlink(inode, btrfs_inode_nlink(leaf, inode_item));
 	inode->i_uid = btrfs_inode_uid(leaf, inode_item);
 	inode->i_gid = btrfs_inode_gid(leaf, inode_item);
 	btrfs_i_size_write(inode, btrfs_inode_size(leaf, inode_item));
@@ -6728,7 +6728,7 @@ int btrfs_create_subvol_root(struct btrfs_trans_handle *trans,
 	inode->i_op = &btrfs_dir_inode_operations;
 	inode->i_fop = &btrfs_dir_file_operations;
 
-	inode->i_nlink = 1;
+	set_nlink(inode, 1);
 	btrfs_i_size_write(inode, 0);
 
 	err = btrfs_update_inode(trans, new_root, inode);
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 786639f..0618aa3 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -1030,7 +1030,7 @@ static noinline int fixup_inode_link_count(struct btrfs_trans_handle *trans,
 	}
 	btrfs_release_path(path);
 	if (nlink != inode->i_nlink) {
-		inode->i_nlink = nlink;
+		set_nlink(inode, nlink);
 		btrfs_update_inode(trans, root, inode);
 	}
 	BTRFS_I(inode)->index_cnt = (u64)-1;
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index b8731bf..15b21e3 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -2363,7 +2363,7 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
 	}
 
 	if ((issued & CEPH_CAP_LINK_EXCL) == 0)
-		inode->i_nlink = le32_to_cpu(grant->nlink);
+		set_nlink(inode, le32_to_cpu(grant->nlink));
 
 	if ((issued & CEPH_CAP_XATTR_EXCL) == 0 && grant->xattr_len) {
 		int len = le32_to_cpu(grant->xattr_len);
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 5dde7d51..1616a0d 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -618,7 +618,7 @@ static int fill_inode(struct inode *inode,
 	}
 
 	if ((issued & CEPH_CAP_LINK_EXCL) == 0)
-		inode->i_nlink = le32_to_cpu(info->nlink);
+		set_nlink(inode, le32_to_cpu(info->nlink));
 
 	/* be careful with mtime, atime, size */
 	ceph_decode_timespec(&atime, &info->atime);
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 2c50bd2..e851d5b 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -132,7 +132,7 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
 	inode->i_mtime = fattr->cf_mtime;
 	inode->i_ctime = fattr->cf_ctime;
 	inode->i_rdev = fattr->cf_rdev;
-	inode->i_nlink = fattr->cf_nlink;
+	set_nlink(inode, fattr->cf_nlink);
 	inode->i_uid = fattr->cf_uid;
 	inode->i_gid = fattr->cf_gid;
 
@@ -905,7 +905,7 @@ struct inode *cifs_root_iget(struct super_block *sb)
 	if (rc && tcon->ipc) {
 		cFYI(1, "ipc connection - fake read inode");
 		inode->i_mode |= S_IFDIR;
-		inode->i_nlink = 2;
+		set_nlink(inode, 2);
 		inode->i_op = &cifs_ipc_inode_ops;
 		inode->i_fop = &simple_dir_operations;
 		inode->i_uid = cifs_sb->mnt_uid;
@@ -1367,7 +1367,7 @@ mkdir_get_info:
 		 /* setting nlink not necessary except in cases where we
 		  * failed to get it from the server or was set bogus */
 		if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
-				direntry->d_inode->i_nlink = 2;
+			set_nlink(direntry->d_inode, 2);
 
 		mode &= ~current_umask();
 		/* must turn on setgid bit if parent dir has it */
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 8693b5d..6b0e064 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -433,7 +433,7 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
 	if (old_file->d_inode) {
 		cifsInode = CIFS_I(old_file->d_inode);
 		if (rc == 0) {
-			old_file->d_inode->i_nlink++;
+			inc_nlink(old_file->d_inode);
 /* BB should we make this contingent on superblock flag NOATIME? */
 /*			old_file->d_inode->i_ctime = CURRENT_TIME;*/
 			/* parent dir timestamps will update from srv
diff --git a/fs/coda/coda_linux.c b/fs/coda/coda_linux.c
index 2bdbcc1..854ace7 100644
--- a/fs/coda/coda_linux.c
+++ b/fs/coda/coda_linux.c
@@ -104,7 +104,7 @@ void coda_vattr_to_iattr(struct inode *inode, struct coda_vattr *attr)
         if (attr->va_gid != -1)
 	        inode->i_gid = (gid_t) attr->va_gid;
 	if (attr->va_nlink != -1)
-	        inode->i_nlink = attr->va_nlink;
+		set_nlink(inode, attr->va_nlink);
 	if (attr->va_size != -1)
 	        inode->i_size = attr->va_size;
 	if (attr->va_size != -1)
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index 0239433..28e7e13 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -340,7 +340,7 @@ static int coda_rmdir(struct inode *dir, struct dentry *de)
 	if (!error) {
 		/* VFS may delete the child */
 		if (de->d_inode)
-		    de->d_inode->i_nlink = 0;
+			clear_nlink(de->d_inode);
 
 		/* fix the link count of the parent */
 		coda_dir_drop_nlink(dir);
diff --git a/fs/dcache.c b/fs/dcache.c
index a88948b..274f13e 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -225,7 +225,7 @@ static void dentry_unlink_inode(struct dentry * dentry)
 }
 
 /*
- * dentry_lru_(add|del|move_tail) must be called with d_lock held.
+ * dentry_lru_(add|del|prune|move_tail) must be called with d_lock held.
  */
 static void dentry_lru_add(struct dentry *dentry)
 {
@@ -245,6 +245,9 @@ static void __dentry_lru_del(struct dentry *dentry)
 	dentry_stat.nr_unused--;
 }
 
+/*
+ * Remove a dentry with references from the LRU.
+ */
 static void dentry_lru_del(struct dentry *dentry)
 {
 	if (!list_empty(&dentry->d_lru)) {
@@ -254,6 +257,23 @@ static void dentry_lru_del(struct dentry *dentry)
 	}
 }
 
+/*
+ * Remove a dentry that is unreferenced and about to be pruned
+ * (unhashed and destroyed) from the LRU, and inform the file system.
+ * This wrapper should be called _prior_ to unhashing a victim dentry.
+ */
+static void dentry_lru_prune(struct dentry *dentry)
+{
+	if (!list_empty(&dentry->d_lru)) {
+		if (dentry->d_flags & DCACHE_OP_PRUNE)
+			dentry->d_op->d_prune(dentry);
+
+		spin_lock(&dcache_lru_lock);
+		__dentry_lru_del(dentry);
+		spin_unlock(&dcache_lru_lock);
+	}
+}
+
 static void dentry_lru_move_tail(struct dentry *dentry)
 {
 	spin_lock(&dcache_lru_lock);
@@ -403,8 +423,12 @@ relock:
 
 	if (ref)
 		dentry->d_count--;
-	/* if dentry was on the d_lru list delete it from there */
-	dentry_lru_del(dentry);
+	/*
+	 * if dentry was on the d_lru list delete it from there.
+	 * inform the fs via d_prune that this dentry is about to be
+	 * unhashed and destroyed.
+	 */
+	dentry_lru_prune(dentry);
 	/* if it was on the hash then remove it */
 	__d_drop(dentry);
 	return d_kill(dentry, parent);
@@ -854,8 +878,12 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
 		do {
 			struct inode *inode;
 
-			/* detach from the system */
-			dentry_lru_del(dentry);
+			/*
+			 * remove the dentry from the lru, and inform
+			 * the fs that this dentry is about to be
+			 * unhashed and destroyed.
+			 */
+			dentry_lru_prune(dentry);
 			__d_shrink(dentry);
 
 			if (dentry->d_count != 0) {
@@ -1283,6 +1311,8 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
 		dentry->d_flags |= DCACHE_OP_REVALIDATE;
 	if (op->d_delete)
 		dentry->d_flags |= DCACHE_OP_DELETE;
+	if (op->d_prune)
+		dentry->d_flags |= DCACHE_OP_PRUNE;
 
 }
 EXPORT_SYMBOL(d_set_d_op);
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 2f27e57..d5d5297 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -307,7 +307,7 @@ devpts_fill_super(struct super_block *s, void *data, int silent)
 	inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
 	inode->i_op = &simple_dir_inode_operations;
 	inode->i_fop = &simple_dir_operations;
-	inode->i_nlink = 2;
+	set_nlink(inode, 2);
 
 	s->s_root = d_alloc_root(inode);
 	if (s->s_root)
@@ -549,7 +549,7 @@ void devpts_pty_kill(struct tty_struct *tty)
 
 	dentry = d_find_alias(inode);
 
-	inode->i_nlink--;
+	drop_nlink(inode);
 	d_delete(dentry);
 	dput(dentry);	/* d_alloc_name() in devpts_pty_new() */
 	dput(dentry);		/* d_find_alias above */
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 11f8582..a36d327 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -474,8 +474,8 @@ static int ecryptfs_link(struct dentry *old_dentry, struct inode *dir,
 		goto out_lock;
 	fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
 	fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
-	old_dentry->d_inode->i_nlink =
-		ecryptfs_inode_to_lower(old_dentry->d_inode)->i_nlink;
+	set_nlink(old_dentry->d_inode,
+		  ecryptfs_inode_to_lower(old_dentry->d_inode)->i_nlink);
 	i_size_write(new_dentry->d_inode, file_size_save);
 out_lock:
 	unlock_dir(lower_dir_dentry);
@@ -499,8 +499,8 @@ static int ecryptfs_unlink(struct inode *dir, struct dentry *dentry)
 		goto out_unlock;
 	}
 	fsstack_copy_attr_times(dir, lower_dir_inode);
-	dentry->d_inode->i_nlink =
-		ecryptfs_inode_to_lower(dentry->d_inode)->i_nlink;
+	set_nlink(dentry->d_inode,
+		  ecryptfs_inode_to_lower(dentry->d_inode)->i_nlink);
 	dentry->d_inode->i_ctime = dir->i_ctime;
 	d_drop(dentry);
 out_unlock:
@@ -565,7 +565,7 @@ static int ecryptfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 		goto out;
 	fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
 	fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
-	dir->i_nlink = lower_dir_dentry->d_inode->i_nlink;
+	set_nlink(dir, lower_dir_dentry->d_inode->i_nlink);
 out:
 	unlock_dir(lower_dir_dentry);
 	if (!dentry->d_inode)
@@ -588,7 +588,7 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)
 	if (!rc && dentry->d_inode)
 		clear_nlink(dentry->d_inode);
 	fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
-	dir->i_nlink = lower_dir_dentry->d_inode->i_nlink;
+	set_nlink(dir, lower_dir_dentry->d_inode->i_nlink);
 	unlock_dir(lower_dir_dentry);
 	if (!rc)
 		d_drop(dentry);
diff --git a/fs/efs/inode.c b/fs/efs/inode.c
index 9c13412..bc84f36 100644
--- a/fs/efs/inode.c
+++ b/fs/efs/inode.c
@@ -96,7 +96,7 @@ struct inode *efs_iget(struct super_block *super, unsigned long ino)
 	efs_inode = (struct efs_dinode *) (bh->b_data + offset);
     
 	inode->i_mode  = be16_to_cpu(efs_inode->di_mode);
-	inode->i_nlink = be16_to_cpu(efs_inode->di_nlink);
+	set_nlink(inode, be16_to_cpu(efs_inode->di_nlink));
 	inode->i_uid   = (uid_t)be16_to_cpu(efs_inode->di_uid);
 	inode->i_gid   = (gid_t)be16_to_cpu(efs_inode->di_gid);
 	inode->i_size  = be32_to_cpu(efs_inode->di_size);
diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c
index 3e5f3a6..f6dbf77 100644
--- a/fs/exofs/inode.c
+++ b/fs/exofs/inode.c
@@ -1165,7 +1165,7 @@ struct inode *exofs_iget(struct super_block *sb, unsigned long ino)
 	inode->i_mode = le16_to_cpu(fcb.i_mode);
 	inode->i_uid = le32_to_cpu(fcb.i_uid);
 	inode->i_gid = le32_to_cpu(fcb.i_gid);
-	inode->i_nlink = le16_to_cpu(fcb.i_links_count);
+	set_nlink(inode, le16_to_cpu(fcb.i_links_count));
 	inode->i_ctime.tv_sec = (signed)le32_to_cpu(fcb.i_ctime);
 	inode->i_atime.tv_sec = (signed)le32_to_cpu(fcb.i_atime);
 	inode->i_mtime.tv_sec = (signed)le32_to_cpu(fcb.i_mtime);
diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c
index 8f44cef..a8cbe1b 100644
--- a/fs/ext2/balloc.c
+++ b/fs/ext2/balloc.c
@@ -421,7 +421,7 @@ static inline int rsv_is_empty(struct ext2_reserve_window *rsv)
 void ext2_init_block_alloc_info(struct inode *inode)
 {
 	struct ext2_inode_info *ei = EXT2_I(inode);
-	struct ext2_block_alloc_info *block_i = ei->i_block_alloc_info;
+	struct ext2_block_alloc_info *block_i;
 	struct super_block *sb = inode->i_sb;
 
 	block_i = kmalloc(sizeof(*block_i), GFP_NOFS);
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
index ee9ed31..c4e81df 100644
--- a/fs/ext2/ialloc.c
+++ b/fs/ext2/ialloc.c
@@ -601,7 +601,7 @@ fail_free_drop:
 fail_drop:
 	dquot_drop(inode);
 	inode->i_flags |= S_NOQUOTA;
-	inode->i_nlink = 0;
+	clear_nlink(inode);
 	unlock_new_inode(inode);
 	iput(inode);
 	return ERR_PTR(err);
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index a8a58f6..91a6945 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -1321,7 +1321,7 @@ struct inode *ext2_iget (struct super_block *sb, unsigned long ino)
 		inode->i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16;
 		inode->i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16;
 	}
-	inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
+	set_nlink(inode, le16_to_cpu(raw_inode->i_links_count));
 	inode->i_size = le32_to_cpu(raw_inode->i_size);
 	inode->i_atime.tv_sec = (signed)le32_to_cpu(raw_inode->i_atime);
 	inode->i_ctime.tv_sec = (signed)le32_to_cpu(raw_inode->i_ctime);
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 1dd62ed..bd8ac16 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -327,10 +327,10 @@ static struct inode *ext2_nfs_get_inode(struct super_block *sb,
 	if (ino > le32_to_cpu(EXT2_SB(sb)->s_es->s_inodes_count))
 		return ERR_PTR(-ESTALE);
 
-	/* iget isn't really right if the inode is currently unallocated!!
-	 * ext2_read_inode currently does appropriate checks, but
-	 * it might be "neater" to call ext2_get_inode first and check
-	 * if the inode is valid.....
+	/*
+	 * ext2_iget isn't quite right if the inode is currently unallocated!
+	 * However ext2_iget currently does appropriate checks to handle stale
+	 * inodes so everything is OK.
 	 */
 	inode = ext2_iget(sb, ino);
 	if (IS_ERR(inode))
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index 6386d76..a203892 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -427,7 +427,7 @@ static inline int rsv_is_empty(struct ext3_reserve_window *rsv)
 void ext3_init_block_alloc_info(struct inode *inode)
 {
 	struct ext3_inode_info *ei = EXT3_I(inode);
-	struct ext3_block_alloc_info *block_i = ei->i_block_alloc_info;
+	struct ext3_block_alloc_info *block_i;
 	struct super_block *sb = inode->i_sb;
 
 	block_i = kmalloc(sizeof(*block_i), GFP_NOFS);
@@ -1440,14 +1440,14 @@ out:
  *
  * Check if filesystem has at least 1 free block available for allocation.
  */
-static int ext3_has_free_blocks(struct ext3_sb_info *sbi)
+static int ext3_has_free_blocks(struct ext3_sb_info *sbi, int use_reservation)
 {
 	ext3_fsblk_t free_blocks, root_blocks;
 
 	free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
 	root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count);
 	if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&
-		sbi->s_resuid != current_fsuid() &&
+		!use_reservation && sbi->s_resuid != current_fsuid() &&
 		(sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
 		return 0;
 	}
@@ -1468,7 +1468,7 @@ static int ext3_has_free_blocks(struct ext3_sb_info *sbi)
  */
 int ext3_should_retry_alloc(struct super_block *sb, int *retries)
 {
-	if (!ext3_has_free_blocks(EXT3_SB(sb)) || (*retries)++ > 3)
+	if (!ext3_has_free_blocks(EXT3_SB(sb), 0) || (*retries)++ > 3)
 		return 0;
 
 	jbd_debug(1, "%s: retrying operation after ENOSPC\n", sb->s_id);
@@ -1546,7 +1546,7 @@ ext3_fsblk_t ext3_new_blocks(handle_t *handle, struct inode *inode,
 	if (block_i && ((windowsz = block_i->rsv_window_node.rsv_goal_size) > 0))
 		my_rsv = &block_i->rsv_window_node;
 
-	if (!ext3_has_free_blocks(sbi)) {
+	if (!ext3_has_free_blocks(sbi, IS_NOQUOTA(inode))) {
 		*errp = -ENOSPC;
 		goto out;
 	}
@@ -1924,9 +1924,10 @@ unsigned long ext3_bg_num_gdb(struct super_block *sb, int group)
  * reaches any used block. Then issue a TRIM command on this extent and free
  * the extent in the block bitmap. This is done until whole group is scanned.
  */
-ext3_grpblk_t ext3_trim_all_free(struct super_block *sb, unsigned int group,
-				ext3_grpblk_t start, ext3_grpblk_t max,
-				ext3_grpblk_t minblocks)
+static ext3_grpblk_t ext3_trim_all_free(struct super_block *sb,
+					unsigned int group,
+					ext3_grpblk_t start, ext3_grpblk_t max,
+					ext3_grpblk_t minblocks)
 {
 	handle_t *handle;
 	ext3_grpblk_t next, free_blocks, bit, freed, count = 0;
diff --git a/fs/ext3/fsync.c b/fs/ext3/fsync.c
index d494c55..1860ed3 100644
--- a/fs/ext3/fsync.c
+++ b/fs/ext3/fsync.c
@@ -61,13 +61,6 @@ int ext3_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 	if (ret)
 		goto out;
 
-	/*
-	 * Taking the mutex here just to keep consistent with how fsync was
-	 * called previously, however it looks like we don't need to take
-	 * i_mutex at all.
-	 */
-	mutex_lock(&inode->i_mutex);
-
 	J_ASSERT(ext3_journal_current_handle() == NULL);
 
 	/*
@@ -85,7 +78,6 @@ int ext3_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 	 *  safe in-journal, which is all fsync() needs to ensure.
 	 */
 	if (ext3_should_journal_data(inode)) {
-		mutex_unlock(&inode->i_mutex);
 		ret = ext3_force_commit(inode->i_sb);
 		goto out;
 	}
@@ -108,8 +100,6 @@ int ext3_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 	 */
 	if (needs_barrier)
 		blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
-
-	mutex_unlock(&inode->i_mutex);
 out:
 	trace_ext3_sync_file_exit(inode, ret);
 	return ret;
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
index bf09cbf..5c866e0 100644
--- a/fs/ext3/ialloc.c
+++ b/fs/ext3/ialloc.c
@@ -178,42 +178,6 @@ error_return:
 }
 
 /*
- * There are two policies for allocating an inode.  If the new inode is
- * a directory, then a forward search is made for a block group with both
- * free space and a low directory-to-inode ratio; if that fails, then of
- * the groups with above-average free space, that group with the fewest
- * directories already is chosen.
- *
- * For other inodes, search forward from the parent directory\'s block
- * group to find a free inode.
- */
-static int find_group_dir(struct super_block *sb, struct inode *parent)
-{
-	int ngroups = EXT3_SB(sb)->s_groups_count;
-	unsigned int freei, avefreei;
-	struct ext3_group_desc *desc, *best_desc = NULL;
-	int group, best_group = -1;
-
-	freei = percpu_counter_read_positive(&EXT3_SB(sb)->s_freeinodes_counter);
-	avefreei = freei / ngroups;
-
-	for (group = 0; group < ngroups; group++) {
-		desc = ext3_get_group_desc (sb, group, NULL);
-		if (!desc || !desc->bg_free_inodes_count)
-			continue;
-		if (le16_to_cpu(desc->bg_free_inodes_count) < avefreei)
-			continue;
-		if (!best_desc ||
-		    (le16_to_cpu(desc->bg_free_blocks_count) >
-		     le16_to_cpu(best_desc->bg_free_blocks_count))) {
-			best_group = group;
-			best_desc = desc;
-		}
-	}
-	return best_group;
-}
-
-/*
  * Orlov's allocator for directories.
  *
  * We always try to spread first-level directories.
@@ -436,12 +400,9 @@ struct inode *ext3_new_inode(handle_t *handle, struct inode * dir,
 
 	sbi = EXT3_SB(sb);
 	es = sbi->s_es;
-	if (S_ISDIR(mode)) {
-		if (test_opt (sb, OLDALLOC))
-			group = find_group_dir(sb, dir);
-		else
-			group = find_group_orlov(sb, dir);
-	} else
+	if (S_ISDIR(mode))
+		group = find_group_orlov(sb, dir);
+	else
 		group = find_group_other(sb, dir);
 
 	err = -ENOSPC;
@@ -621,7 +582,7 @@ fail_free_drop:
 fail_drop:
 	dquot_drop(inode);
 	inode->i_flags |= S_NOQUOTA;
-	inode->i_nlink = 0;
+	clear_nlink(inode);
 	unlock_new_inode(inode);
 	iput(inode);
 	brelse(bitmap_bh);
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 12661e1..85fe655 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -2899,7 +2899,7 @@ struct inode *ext3_iget(struct super_block *sb, unsigned long ino)
 		inode->i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16;
 		inode->i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16;
 	}
-	inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
+	set_nlink(inode, le16_to_cpu(raw_inode->i_links_count));
 	inode->i_size = le32_to_cpu(raw_inode->i_size);
 	inode->i_atime.tv_sec = (signed)le32_to_cpu(raw_inode->i_atime);
 	inode->i_ctime.tv_sec = (signed)le32_to_cpu(raw_inode->i_ctime);
diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c
index c7f4394..ba1b54e 100644
--- a/fs/ext3/ioctl.c
+++ b/fs/ext3/ioctl.c
@@ -150,30 +150,6 @@ setversion_out:
 		mnt_drop_write(filp->f_path.mnt);
 		return err;
 	}
-#ifdef CONFIG_JBD_DEBUG
-	case EXT3_IOC_WAIT_FOR_READONLY:
-		/*
-		 * This is racy - by the time we're woken up and running,
-		 * the superblock could be released.  And the module could
-		 * have been unloaded.  So sue me.
-		 *
-		 * Returns 1 if it slept, else zero.
-		 */
-		{
-			struct super_block *sb = inode->i_sb;
-			DECLARE_WAITQUEUE(wait, current);
-			int ret = 0;
-
-			set_current_state(TASK_INTERRUPTIBLE);
-			add_wait_queue(&EXT3_SB(sb)->ro_wait_queue, &wait);
-			if (timer_pending(&EXT3_SB(sb)->turn_ro_timer)) {
-				schedule();
-				ret = 1;
-			}
-			remove_wait_queue(&EXT3_SB(sb)->ro_wait_queue, &wait);
-			return ret;
-		}
-#endif
 	case EXT3_IOC_GETRSVSZ:
 		if (test_opt(inode->i_sb, RESERVATION)
 			&& S_ISREG(inode->i_mode)
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 0629e09..642dc6d 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -1821,7 +1821,7 @@ retry:
 	de->name_len = 2;
 	strcpy (de->name, "..");
 	ext3_set_de_type(dir->i_sb, de, S_IFDIR);
-	inode->i_nlink = 2;
+	set_nlink(inode, 2);
 	BUFFER_TRACE(dir_block, "call ext3_journal_dirty_metadata");
 	err = ext3_journal_dirty_metadata(handle, dir_block);
 	if (err)
@@ -1833,7 +1833,7 @@ retry:
 
 	if (err) {
 out_clear_inode:
-		inode->i_nlink = 0;
+		clear_nlink(inode);
 		unlock_new_inode(inode);
 		ext3_mark_inode_dirty(handle, inode);
 		iput (inode);
@@ -2170,7 +2170,7 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry)
 		ext3_warning (inode->i_sb, "ext3_unlink",
 			      "Deleting nonexistent file (%lu), %d",
 			      inode->i_ino, inode->i_nlink);
-		inode->i_nlink = 1;
+		set_nlink(inode, 1);
 	}
 	retval = ext3_delete_entry(handle, dir, de, bh);
 	if (retval)
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 7beb69a..922d289 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -652,8 +652,6 @@ static int ext3_show_options(struct seq_file *seq, struct vfsmount *vfs)
 		seq_puts(seq, ",nouid32");
 	if (test_opt(sb, DEBUG))
 		seq_puts(seq, ",debug");
-	if (test_opt(sb, OLDALLOC))
-		seq_puts(seq, ",oldalloc");
 #ifdef CONFIG_EXT3_FS_XATTR
 	if (test_opt(sb, XATTR_USER))
 		seq_puts(seq, ",user_xattr");
@@ -1049,10 +1047,12 @@ static int parse_options (char *options, struct super_block *sb,
 			set_opt (sbi->s_mount_opt, DEBUG);
 			break;
 		case Opt_oldalloc:
-			set_opt (sbi->s_mount_opt, OLDALLOC);
+			ext3_msg(sb, KERN_WARNING,
+				"Ignoring deprecated oldalloc option");
 			break;
 		case Opt_orlov:
-			clear_opt (sbi->s_mount_opt, OLDALLOC);
+			ext3_msg(sb, KERN_WARNING,
+				"Ignoring deprecated orlov option");
 			break;
 #ifdef CONFIG_EXT3_FS_XATTR
 		case Opt_user_xattr:
@@ -2669,13 +2669,13 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
 			/*
 			 * If we have an unprocessed orphan list hanging
 			 * around from a previously readonly bdev mount,
-			 * require a full umount/remount for now.
+			 * require a full umount & mount for now.
 			 */
 			if (es->s_last_orphan) {
 				ext3_msg(sb, KERN_WARNING, "warning: couldn't "
 				       "remount RDWR because of unprocessed "
 				       "orphan inode list.  Please "
-				       "umount/remount instead.");
+				       "umount & mount instead.");
 				err = -EINVAL;
 				goto restore_opts;
 			}
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index f8224ad..f6dba45 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -28,7 +28,8 @@
  */
 
 /*
- * Calculate the block group number and offset, given a block number
+ * Calculate the block group number and offset into the block/cluster
+ * allocation bitmap, given a block number
  */
 void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
 		ext4_group_t *blockgrpp, ext4_grpblk_t *offsetp)
@@ -37,7 +38,8 @@ void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
 	ext4_grpblk_t offset;
 
 	blocknr = blocknr - le32_to_cpu(es->s_first_data_block);
-	offset = do_div(blocknr, EXT4_BLOCKS_PER_GROUP(sb));
+	offset = do_div(blocknr, EXT4_BLOCKS_PER_GROUP(sb)) >>
+		EXT4_SB(sb)->s_cluster_bits;
 	if (offsetp)
 		*offsetp = offset;
 	if (blockgrpp)
@@ -55,130 +57,169 @@ static int ext4_block_in_group(struct super_block *sb, ext4_fsblk_t block,
 	return 0;
 }
 
-static int ext4_group_used_meta_blocks(struct super_block *sb,
-				       ext4_group_t block_group,
-				       struct ext4_group_desc *gdp)
+/* Return the number of clusters used for file system metadata; this
+ * represents the overhead needed by the file system.
+ */
+unsigned ext4_num_overhead_clusters(struct super_block *sb,
+				    ext4_group_t block_group,
+				    struct ext4_group_desc *gdp)
 {
-	ext4_fsblk_t tmp;
+	unsigned num_clusters;
+	int block_cluster = -1, inode_cluster = -1, itbl_cluster = -1, i, c;
+	ext4_fsblk_t start = ext4_group_first_block_no(sb, block_group);
+	ext4_fsblk_t itbl_blk;
 	struct ext4_sb_info *sbi = EXT4_SB(sb);
-	/* block bitmap, inode bitmap, and inode table blocks */
-	int used_blocks = sbi->s_itb_per_group + 2;
 
-	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
-		if (!ext4_block_in_group(sb, ext4_block_bitmap(sb, gdp),
-					block_group))
-			used_blocks--;
-
-		if (!ext4_block_in_group(sb, ext4_inode_bitmap(sb, gdp),
-					block_group))
-			used_blocks--;
-
-		tmp = ext4_inode_table(sb, gdp);
-		for (; tmp < ext4_inode_table(sb, gdp) +
-				sbi->s_itb_per_group; tmp++) {
-			if (!ext4_block_in_group(sb, tmp, block_group))
-				used_blocks -= 1;
+	/* This is the number of clusters used by the superblock,
+	 * block group descriptors, and reserved block group
+	 * descriptor blocks */
+	num_clusters = ext4_num_base_meta_clusters(sb, block_group);
+
+	/*
+	 * For the allocation bitmaps and inode table, we first need
+	 * to check to see if the block is in the block group.  If it
+	 * is, then check to see if the cluster is already accounted
+	 * for in the clusters used for the base metadata cluster, or
+	 * if we can increment the base metadata cluster to include
+	 * that block.  Otherwise, we will have to track the cluster
+	 * used for the allocation bitmap or inode table explicitly.
+	 * Normally all of these blocks are contiguous, so the special
+	 * case handling shouldn't be necessary except for *very*
+	 * unusual file system layouts.
+	 */
+	if (ext4_block_in_group(sb, ext4_block_bitmap(sb, gdp), block_group)) {
+		block_cluster = EXT4_B2C(sbi, (start -
+					       ext4_block_bitmap(sb, gdp)));
+		if (block_cluster < num_clusters)
+			block_cluster = -1;
+		else if (block_cluster == num_clusters) {
+			num_clusters++;
+			block_cluster = -1;
 		}
 	}
-	return used_blocks;
-}
 
-/* Initializes an uninitialized block bitmap if given, and returns the
- * number of blocks free in the group. */
-unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
-		 ext4_group_t block_group, struct ext4_group_desc *gdp)
-{
-	int bit, bit_max;
-	ext4_group_t ngroups = ext4_get_groups_count(sb);
-	unsigned free_blocks, group_blocks;
-	struct ext4_sb_info *sbi = EXT4_SB(sb);
-
-	if (bh) {
-		J_ASSERT_BH(bh, buffer_locked(bh));
-
-		/* 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, "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);
-			memset(bh->b_data, 0xff, sb->s_blocksize);
-			return 0;
+	if (ext4_block_in_group(sb, ext4_inode_bitmap(sb, gdp), block_group)) {
+		inode_cluster = EXT4_B2C(sbi,
+					 start - ext4_inode_bitmap(sb, gdp));
+		if (inode_cluster < num_clusters)
+			inode_cluster = -1;
+		else if (inode_cluster == num_clusters) {
+			num_clusters++;
+			inode_cluster = -1;
 		}
-		memset(bh->b_data, 0, sb->s_blocksize);
 	}
 
-	/* Check for superblock and gdt backups in this group */
-	bit_max = ext4_bg_has_super(sb, block_group);
-
-	if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG) ||
-	    block_group < le32_to_cpu(sbi->s_es->s_first_meta_bg) *
-			  sbi->s_desc_per_block) {
-		if (bit_max) {
-			bit_max += ext4_bg_num_gdb(sb, block_group);
-			bit_max +=
-				le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks);
+	itbl_blk = ext4_inode_table(sb, gdp);
+	for (i = 0; i < sbi->s_itb_per_group; i++) {
+		if (ext4_block_in_group(sb, itbl_blk + i, block_group)) {
+			c = EXT4_B2C(sbi, start - itbl_blk + i);
+			if ((c < num_clusters) || (c == inode_cluster) ||
+			    (c == block_cluster) || (c == itbl_cluster))
+				continue;
+			if (c == num_clusters) {
+				num_clusters++;
+				continue;
+			}
+			num_clusters++;
+			itbl_cluster = c;
 		}
-	} else { /* For META_BG_BLOCK_GROUPS */
-		bit_max += ext4_bg_num_gdb(sb, block_group);
 	}
 
-	if (block_group == ngroups - 1) {
+	if (block_cluster != -1)
+		num_clusters++;
+	if (inode_cluster != -1)
+		num_clusters++;
+
+	return num_clusters;
+}
+
+static unsigned int num_clusters_in_group(struct super_block *sb,
+					  ext4_group_t block_group)
+{
+	unsigned int blocks;
+
+	if (block_group == ext4_get_groups_count(sb) - 1) {
 		/*
-		 * Even though mke2fs always initialize first and last group
-		 * if some other tool enabled the EXT4_BG_BLOCK_UNINIT we need
-		 * to make sure we calculate the right free blocks
+		 * Even though mke2fs always initializes the first and
+		 * last group, just in case some other tool was used,
+		 * we need to make sure we calculate the right free
+		 * blocks.
 		 */
-		group_blocks = ext4_blocks_count(sbi->s_es) -
-			ext4_group_first_block_no(sb, ngroups - 1);
-	} else {
-		group_blocks = EXT4_BLOCKS_PER_GROUP(sb);
-	}
+		blocks = ext4_blocks_count(EXT4_SB(sb)->s_es) -
+			ext4_group_first_block_no(sb, block_group);
+	} else
+		blocks = EXT4_BLOCKS_PER_GROUP(sb);
+	return EXT4_NUM_B2C(EXT4_SB(sb), blocks);
+}
 
-	free_blocks = group_blocks - bit_max;
+/* Initializes an uninitialized block bitmap */
+void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
+			    ext4_group_t block_group,
+			    struct ext4_group_desc *gdp)
+{
+	unsigned int bit, bit_max;
+	struct ext4_sb_info *sbi = EXT4_SB(sb);
+	ext4_fsblk_t start, tmp;
+	int flex_bg = 0;
+
+	J_ASSERT_BH(bh, buffer_locked(bh));
+
+	/* 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, "Checksum bad for group %u", block_group);
+		ext4_free_group_clusters_set(sb, gdp, 0);
+		ext4_free_inodes_set(sb, gdp, 0);
+		ext4_itable_unused_set(sb, gdp, 0);
+		memset(bh->b_data, 0xff, sb->s_blocksize);
+		return;
+	}
+	memset(bh->b_data, 0, sb->s_blocksize);
 
-	if (bh) {
-		ext4_fsblk_t start, tmp;
-		int flex_bg = 0;
+	bit_max = ext4_num_base_meta_clusters(sb, block_group);
+	for (bit = 0; bit < bit_max; bit++)
+		ext4_set_bit(bit, bh->b_data);
 
-		for (bit = 0; bit < bit_max; bit++)
-			ext4_set_bit(bit, bh->b_data);
+	start = ext4_group_first_block_no(sb, block_group);
 
-		start = ext4_group_first_block_no(sb, block_group);
+	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG))
+		flex_bg = 1;
 
-		if (EXT4_HAS_INCOMPAT_FEATURE(sb,
-					      EXT4_FEATURE_INCOMPAT_FLEX_BG))
-			flex_bg = 1;
+	/* Set bits for block and inode bitmaps, and inode table */
+	tmp = ext4_block_bitmap(sb, gdp);
+	if (!flex_bg || ext4_block_in_group(sb, tmp, block_group))
+		ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data);
 
-		/* Set bits for block and inode bitmaps, and inode table */
-		tmp = ext4_block_bitmap(sb, gdp);
-		if (!flex_bg || ext4_block_in_group(sb, tmp, block_group))
-			ext4_set_bit(tmp - start, bh->b_data);
+	tmp = ext4_inode_bitmap(sb, gdp);
+	if (!flex_bg || ext4_block_in_group(sb, tmp, block_group))
+		ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data);
 
-		tmp = ext4_inode_bitmap(sb, gdp);
+	tmp = ext4_inode_table(sb, gdp);
+	for (; tmp < ext4_inode_table(sb, gdp) +
+		     sbi->s_itb_per_group; tmp++) {
 		if (!flex_bg || ext4_block_in_group(sb, tmp, block_group))
-			ext4_set_bit(tmp - start, bh->b_data);
-
-		tmp = ext4_inode_table(sb, gdp);
-		for (; tmp < ext4_inode_table(sb, gdp) +
-				sbi->s_itb_per_group; tmp++) {
-			if (!flex_bg ||
-				ext4_block_in_group(sb, tmp, block_group))
-				ext4_set_bit(tmp - start, bh->b_data);
-		}
-		/*
-		 * Also if the number of blocks within the group is
-		 * less than the blocksize * 8 ( which is the size
-		 * of bitmap ), set rest of the block bitmap to 1
-		 */
-		ext4_mark_bitmap_end(group_blocks, sb->s_blocksize * 8,
-				     bh->b_data);
+			ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data);
 	}
-	return free_blocks - ext4_group_used_meta_blocks(sb, block_group, gdp);
+
+	/*
+	 * Also if the number of blocks within the group is less than
+	 * the blocksize * 8 ( which is the size of bitmap ), set rest
+	 * of the block bitmap to 1
+	 */
+	ext4_mark_bitmap_end(num_clusters_in_group(sb, block_group),
+			     sb->s_blocksize * 8, bh->b_data);
 }
 
+/* Return the number of free blocks in a block group.  It is used when
+ * the block bitmap is uninitialized, so we can't just count the bits
+ * in the bitmap. */
+unsigned ext4_free_clusters_after_init(struct super_block *sb,
+				       ext4_group_t block_group,
+				       struct ext4_group_desc *gdp)
+{
+	return num_clusters_in_group(sb, block_group) - 
+		ext4_num_overhead_clusters(sb, block_group, gdp);
+}
 
 /*
  * The free blocks are managed by bitmaps.  A file system contains several
@@ -362,53 +403,54 @@ ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
 }
 
 /**
- * ext4_has_free_blocks()
+ * ext4_has_free_clusters()
  * @sbi:	in-core super block structure.
- * @nblocks:	number of needed blocks
+ * @nclusters:	number of needed blocks
+ * @flags:	flags from ext4_mb_new_blocks()
  *
- * Check if filesystem has nblocks free & available for allocation.
+ * Check if filesystem has nclusters free & available for allocation.
  * On success return 1, return 0 on failure.
  */
-static int ext4_has_free_blocks(struct ext4_sb_info *sbi,
-				s64 nblocks, unsigned int flags)
+static int ext4_has_free_clusters(struct ext4_sb_info *sbi,
+				  s64 nclusters, unsigned int flags)
 {
-	s64 free_blocks, dirty_blocks, root_blocks;
-	struct percpu_counter *fbc = &sbi->s_freeblocks_counter;
-	struct percpu_counter *dbc = &sbi->s_dirtyblocks_counter;
-
-	free_blocks  = percpu_counter_read_positive(fbc);
-	dirty_blocks = percpu_counter_read_positive(dbc);
-	root_blocks = ext4_r_blocks_count(sbi->s_es);
-
-	if (free_blocks - (nblocks + root_blocks + dirty_blocks) <
-						EXT4_FREEBLOCKS_WATERMARK) {
-		free_blocks  = percpu_counter_sum_positive(fbc);
-		dirty_blocks = percpu_counter_sum_positive(dbc);
+	s64 free_clusters, dirty_clusters, root_clusters;
+	struct percpu_counter *fcc = &sbi->s_freeclusters_counter;
+	struct percpu_counter *dcc = &sbi->s_dirtyclusters_counter;
+
+	free_clusters  = percpu_counter_read_positive(fcc);
+	dirty_clusters = percpu_counter_read_positive(dcc);
+	root_clusters = EXT4_B2C(sbi, ext4_r_blocks_count(sbi->s_es));
+
+	if (free_clusters - (nclusters + root_clusters + dirty_clusters) <
+					EXT4_FREECLUSTERS_WATERMARK) {
+		free_clusters  = EXT4_C2B(sbi, percpu_counter_sum_positive(fcc));
+		dirty_clusters = percpu_counter_sum_positive(dcc);
 	}
-	/* Check whether we have space after
-	 * accounting for current dirty blocks & root reserved blocks.
+	/* Check whether we have space after accounting for current
+	 * dirty clusters & root reserved clusters.
 	 */
-	if (free_blocks >= ((root_blocks + nblocks) + dirty_blocks))
+	if (free_clusters >= ((root_clusters + nclusters) + dirty_clusters))
 		return 1;
 
-	/* Hm, nope.  Are (enough) root reserved blocks available? */
+	/* Hm, nope.  Are (enough) root reserved clusters available? */
 	if (sbi->s_resuid == current_fsuid() ||
 	    ((sbi->s_resgid != 0) && in_group_p(sbi->s_resgid)) ||
 	    capable(CAP_SYS_RESOURCE) ||
 		(flags & EXT4_MB_USE_ROOT_BLOCKS)) {
 
-		if (free_blocks >= (nblocks + dirty_blocks))
+		if (free_clusters >= (nclusters + dirty_clusters))
 			return 1;
 	}
 
 	return 0;
 }
 
-int ext4_claim_free_blocks(struct ext4_sb_info *sbi,
-			   s64 nblocks, unsigned int flags)
+int ext4_claim_free_clusters(struct ext4_sb_info *sbi,
+			     s64 nclusters, unsigned int flags)
 {
-	if (ext4_has_free_blocks(sbi, nblocks, flags)) {
-		percpu_counter_add(&sbi->s_dirtyblocks_counter, nblocks);
+	if (ext4_has_free_clusters(sbi, nclusters, flags)) {
+		percpu_counter_add(&sbi->s_dirtyclusters_counter, nclusters);
 		return 0;
 	} else
 		return -ENOSPC;
@@ -428,7 +470,7 @@ int ext4_claim_free_blocks(struct ext4_sb_info *sbi,
  */
 int ext4_should_retry_alloc(struct super_block *sb, int *retries)
 {
-	if (!ext4_has_free_blocks(EXT4_SB(sb), 1, 0) ||
+	if (!ext4_has_free_clusters(EXT4_SB(sb), 1, 0) ||
 	    (*retries)++ > 3 ||
 	    !EXT4_SB(sb)->s_journal)
 		return 0;
@@ -444,7 +486,7 @@ int ext4_should_retry_alloc(struct super_block *sb, int *retries)
  * @handle:             handle to this transaction
  * @inode:              file inode
  * @goal:               given target block(filesystem wide)
- * @count:		pointer to total number of blocks needed
+ * @count:		pointer to total number of clusters needed
  * @errp:               error code
  *
  * Return 1st allocated block number on success, *count stores total account
@@ -476,18 +518,19 @@ ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode,
 		spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
 		EXT4_I(inode)->i_allocated_meta_blocks += ar.len;
 		spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
-		dquot_alloc_block_nofail(inode, ar.len);
+		dquot_alloc_block_nofail(inode,
+				EXT4_C2B(EXT4_SB(inode->i_sb), ar.len));
 	}
 	return ret;
 }
 
 /**
- * ext4_count_free_blocks() -- count filesystem free blocks
+ * ext4_count_free_clusters() -- count filesystem free clusters
  * @sb:		superblock
  *
- * Adds up the number of free blocks from each block group.
+ * Adds up the number of free clusters from each block group.
  */
-ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
+ext4_fsblk_t ext4_count_free_clusters(struct super_block *sb)
 {
 	ext4_fsblk_t desc_count;
 	struct ext4_group_desc *gdp;
@@ -508,7 +551,7 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
 		gdp = ext4_get_group_desc(sb, i, NULL);
 		if (!gdp)
 			continue;
-		desc_count += ext4_free_blks_count(sb, gdp);
+		desc_count += ext4_free_group_clusters(sb, gdp);
 		brelse(bitmap_bh);
 		bitmap_bh = ext4_read_block_bitmap(sb, i);
 		if (bitmap_bh == NULL)
@@ -516,12 +559,13 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
 
 		x = ext4_count_free(bitmap_bh, sb->s_blocksize);
 		printk(KERN_DEBUG "group %u: stored = %d, counted = %u\n",
-			i, ext4_free_blks_count(sb, gdp), x);
+			i, ext4_free_group_clusters(sb, gdp), x);
 		bitmap_count += x;
 	}
 	brelse(bitmap_bh);
-	printk(KERN_DEBUG "ext4_count_free_blocks: stored = %llu"
-		", computed = %llu, %llu\n", ext4_free_blocks_count(es),
+	printk(KERN_DEBUG "ext4_count_free_clusters: stored = %llu"
+	       ", computed = %llu, %llu\n",
+	       EXT4_B2C(sbi, ext4_free_blocks_count(es)),
 	       desc_count, bitmap_count);
 	return bitmap_count;
 #else
@@ -530,7 +574,7 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
 		gdp = ext4_get_group_desc(sb, i, NULL);
 		if (!gdp)
 			continue;
-		desc_count += ext4_free_blks_count(sb, gdp);
+		desc_count += ext4_free_group_clusters(sb, gdp);
 	}
 
 	return desc_count;
@@ -620,6 +664,31 @@ unsigned long ext4_bg_num_gdb(struct super_block *sb, ext4_group_t group)
 
 }
 
+/*
+ * This function returns the number of file system metadata clusters at
+ * the beginning of a block group, including the reserved gdt blocks.
+ */
+unsigned ext4_num_base_meta_clusters(struct super_block *sb,
+				     ext4_group_t block_group)
+{
+	struct ext4_sb_info *sbi = EXT4_SB(sb);
+	unsigned num;
+
+	/* Check for superblock and gdt backups in this group */
+	num = ext4_bg_has_super(sb, block_group);
+
+	if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG) ||
+	    block_group < le32_to_cpu(sbi->s_es->s_first_meta_bg) *
+			  sbi->s_desc_per_block) {
+		if (num) {
+			num += ext4_bg_num_gdb(sb, block_group);
+			num += le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks);
+		}
+	} else { /* For META_BG_BLOCK_GROUPS */
+		num += ext4_bg_num_gdb(sb, block_group);
+	}
+	return EXT4_NUM_B2C(sbi, num);
+}
 /**
  *	ext4_inode_to_goal_block - return a hint for block allocation
  *	@inode: inode for block allocation
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index cec3145..5b0e26a 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -144,9 +144,17 @@ struct ext4_allocation_request {
 #define EXT4_MAP_UNWRITTEN	(1 << BH_Unwritten)
 #define EXT4_MAP_BOUNDARY	(1 << BH_Boundary)
 #define EXT4_MAP_UNINIT		(1 << BH_Uninit)
+/* Sometimes (in the bigalloc case, from ext4_da_get_block_prep) the caller of
+ * ext4_map_blocks wants to know whether or not the underlying cluster has
+ * already been accounted for. EXT4_MAP_FROM_CLUSTER conveys to the caller that
+ * the requested mapping was from previously mapped (or delayed allocated)
+ * cluster. We use BH_AllocFromCluster only for this flag. BH_AllocFromCluster
+ * should never appear on buffer_head's state flags.
+ */
+#define EXT4_MAP_FROM_CLUSTER	(1 << BH_AllocFromCluster)
 #define EXT4_MAP_FLAGS		(EXT4_MAP_NEW | EXT4_MAP_MAPPED |\
 				 EXT4_MAP_UNWRITTEN | EXT4_MAP_BOUNDARY |\
-				 EXT4_MAP_UNINIT)
+				 EXT4_MAP_UNINIT | EXT4_MAP_FROM_CLUSTER)
 
 struct ext4_map_blocks {
 	ext4_fsblk_t m_pblk;
@@ -239,8 +247,11 @@ struct ext4_io_submit {
 # define EXT4_BLOCK_SIZE(s)		(EXT4_MIN_BLOCK_SIZE << (s)->s_log_block_size)
 #endif
 #define	EXT4_ADDR_PER_BLOCK(s)		(EXT4_BLOCK_SIZE(s) / sizeof(__u32))
+#define EXT4_CLUSTER_SIZE(s)		(EXT4_BLOCK_SIZE(s) << \
+					 EXT4_SB(s)->s_cluster_bits)
 #ifdef __KERNEL__
 # define EXT4_BLOCK_SIZE_BITS(s)	((s)->s_blocksize_bits)
+# define EXT4_CLUSTER_BITS(s)		(EXT4_SB(s)->s_cluster_bits)
 #else
 # define EXT4_BLOCK_SIZE_BITS(s)	((s)->s_log_block_size + 10)
 #endif
@@ -258,6 +269,14 @@ struct ext4_io_submit {
 #endif
 #define EXT4_BLOCK_ALIGN(size, blkbits)		ALIGN((size), (1 << (blkbits)))
 
+/* Translate a block number to a cluster number */
+#define EXT4_B2C(sbi, blk)	((blk) >> (sbi)->s_cluster_bits)
+/* Translate a cluster number to a block number */
+#define EXT4_C2B(sbi, cluster)	((cluster) << (sbi)->s_cluster_bits)
+/* Translate # of blks to # of clusters */
+#define EXT4_NUM_B2C(sbi, blks)	(((blks) + (sbi)->s_cluster_ratio - 1) >> \
+				 (sbi)->s_cluster_bits)
+
 /*
  * Structure of a blocks group descriptor
  */
@@ -289,7 +308,7 @@ struct ext4_group_desc
 
 struct flex_groups {
 	atomic_t free_inodes;
-	atomic_t free_blocks;
+	atomic_t free_clusters;
 	atomic_t used_dirs;
 };
 
@@ -306,6 +325,7 @@ struct flex_groups {
 #define EXT4_DESC_SIZE(s)		(EXT4_SB(s)->s_desc_size)
 #ifdef __KERNEL__
 # define EXT4_BLOCKS_PER_GROUP(s)	(EXT4_SB(s)->s_blocks_per_group)
+# define EXT4_CLUSTERS_PER_GROUP(s)	(EXT4_SB(s)->s_clusters_per_group)
 # define EXT4_DESC_PER_BLOCK(s)		(EXT4_SB(s)->s_desc_per_block)
 # define EXT4_INODES_PER_GROUP(s)	(EXT4_SB(s)->s_inodes_per_group)
 # define EXT4_DESC_PER_BLOCK_BITS(s)	(EXT4_SB(s)->s_desc_per_block_bits)
@@ -358,8 +378,7 @@ struct flex_groups {
 
 /* Flags that should be inherited by new inodes from their parent. */
 #define EXT4_FL_INHERITED (EXT4_SECRM_FL | EXT4_UNRM_FL | EXT4_COMPR_FL |\
-			   EXT4_SYNC_FL | EXT4_IMMUTABLE_FL | EXT4_APPEND_FL |\
-			   EXT4_NODUMP_FL | EXT4_NOATIME_FL |\
+			   EXT4_SYNC_FL | EXT4_NODUMP_FL | EXT4_NOATIME_FL |\
 			   EXT4_NOCOMPR_FL | EXT4_JOURNAL_DATA_FL |\
 			   EXT4_NOTAIL_FL | EXT4_DIRSYNC_FL)
 
@@ -520,6 +539,8 @@ struct ext4_new_group_data {
 #define EXT4_GET_BLOCKS_PUNCH_OUT_EXT		0x0020
 	/* Don't normalize allocation size (used for fallocate) */
 #define EXT4_GET_BLOCKS_NO_NORMALIZE		0x0040
+	/* Request will not result in inode size update (user for fallocate) */
+#define EXT4_GET_BLOCKS_KEEP_SIZE		0x0080
 
 /*
  * Flags used by ext4_free_blocks
@@ -528,6 +549,13 @@ struct ext4_new_group_data {
 #define EXT4_FREE_BLOCKS_FORGET		0x0002
 #define EXT4_FREE_BLOCKS_VALIDATED	0x0004
 #define EXT4_FREE_BLOCKS_NO_QUOT_UPDATE	0x0008
+#define EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER	0x0010
+#define EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER	0x0020
+
+/*
+ * Flags used by ext4_discard_partial_page_buffers
+ */
+#define EXT4_DISCARD_PARTIAL_PG_ZERO_UNMAPPED	0x0001
 
 /*
  * ioctl commands
@@ -538,9 +566,6 @@ struct ext4_new_group_data {
 #define	EXT4_IOC_SETVERSION		_IOW('f', 4, long)
 #define	EXT4_IOC_GETVERSION_OLD		FS_IOC_GETVERSION
 #define	EXT4_IOC_SETVERSION_OLD		FS_IOC_SETVERSION
-#ifdef CONFIG_JBD2_DEBUG
-#define EXT4_IOC_WAIT_FOR_READONLY	_IOR('f', 99, long)
-#endif
 #define EXT4_IOC_GETRSVSZ		_IOR('f', 5, long)
 #define EXT4_IOC_SETRSVSZ		_IOW('f', 6, long)
 #define EXT4_IOC_GROUP_EXTEND		_IOW('f', 7, unsigned long)
@@ -563,9 +588,6 @@ struct ext4_new_group_data {
 #define EXT4_IOC32_SETRSVSZ		_IOW('f', 6, int)
 #define EXT4_IOC32_GROUP_EXTEND		_IOW('f', 7, unsigned int)
 #define EXT4_IOC32_GROUP_ADD		_IOW('f', 8, struct compat_ext4_new_group_input)
-#ifdef CONFIG_JBD2_DEBUG
-#define EXT4_IOC32_WAIT_FOR_READONLY	_IOR('f', 99, int)
-#endif
 #define EXT4_IOC32_GETVERSION_OLD	FS_IOC32_GETVERSION
 #define EXT4_IOC32_SETVERSION_OLD	FS_IOC32_SETVERSION
 #endif
@@ -837,6 +859,7 @@ struct ext4_inode_info {
 	ext4_group_t	i_last_alloc_group;
 
 	/* allocation reservation info for delalloc */
+	/* In case of bigalloc, these refer to clusters rather than blocks */
 	unsigned int i_reserved_data_blocks;
 	unsigned int i_reserved_meta_blocks;
 	unsigned int i_allocated_meta_blocks;
@@ -886,7 +909,6 @@ struct ext4_inode_info {
 /*
  * Mount flags
  */
-#define EXT4_MOUNT_OLDALLOC		0x00002  /* Don't use the new Orlov allocator */
 #define EXT4_MOUNT_GRPID		0x00004	/* Create files with directory's group */
 #define EXT4_MOUNT_DEBUG		0x00008	/* Some debugging messages */
 #define EXT4_MOUNT_ERRORS_CONT		0x00010	/* Continue on errors */
@@ -918,6 +940,9 @@ struct ext4_inode_info {
 #define EXT4_MOUNT_DISCARD		0x40000000 /* Issue DISCARD requests */
 #define EXT4_MOUNT_INIT_INODE_TABLE	0x80000000 /* Initialize uninitialized itables */
 
+#define EXT4_MOUNT2_EXPLICIT_DELALLOC	0x00000001 /* User explicitly
+						      specified delalloc */
+
 #define clear_opt(sb, opt)		EXT4_SB(sb)->s_mount_opt &= \
 						~EXT4_MOUNT_##opt
 #define set_opt(sb, opt)		EXT4_SB(sb)->s_mount_opt |= \
@@ -968,9 +993,9 @@ struct ext4_super_block {
 /*10*/	__le32	s_free_inodes_count;	/* Free inodes count */
 	__le32	s_first_data_block;	/* First Data Block */
 	__le32	s_log_block_size;	/* Block size */
-	__le32	s_obso_log_frag_size;	/* Obsoleted fragment size */
+	__le32	s_log_cluster_size;	/* Allocation cluster size */
 /*20*/	__le32	s_blocks_per_group;	/* # Blocks per group */
-	__le32	s_obso_frags_per_group;	/* Obsoleted fragments per group */
+	__le32	s_clusters_per_group;	/* # Clusters per group */
 	__le32	s_inodes_per_group;	/* # Inodes per group */
 	__le32	s_mtime;		/* Mount time */
 /*30*/	__le32	s_wtime;		/* Write time */
@@ -1066,7 +1091,10 @@ struct ext4_super_block {
 	__u8	s_last_error_func[32];	/* function where the error happened */
 #define EXT4_S_ERR_END offsetof(struct ext4_super_block, s_mount_opts)
 	__u8	s_mount_opts[64];
-	__le32	s_reserved[112];        /* Padding to the end of the block */
+	__le32	s_usr_quota_inum;	/* inode for tracking user quota */
+	__le32	s_grp_quota_inum;	/* inode for tracking group quota */
+	__le32	s_overhead_clusters;	/* overhead blocks/clusters in fs */
+	__le32  s_reserved[109];        /* Padding to the end of the block */
 };
 
 #define EXT4_S_ERR_LEN (EXT4_S_ERR_END - EXT4_S_ERR_START)
@@ -1086,6 +1114,7 @@ struct ext4_sb_info {
 	unsigned long s_desc_size;	/* Size of a group descriptor in bytes */
 	unsigned long s_inodes_per_block;/* Number of inodes per block */
 	unsigned long s_blocks_per_group;/* Number of blocks in a group */
+	unsigned long s_clusters_per_group; /* Number of clusters in a group */
 	unsigned long s_inodes_per_group;/* Number of inodes in a group */
 	unsigned long s_itb_per_group;	/* Number of inode table blocks per group */
 	unsigned long s_gdb_count;	/* Number of group descriptor blocks */
@@ -1094,6 +1123,8 @@ struct ext4_sb_info {
 	ext4_group_t s_blockfile_groups;/* Groups acceptable for non-extent files */
 	unsigned long s_overhead_last;  /* Last calculated overhead */
 	unsigned long s_blocks_last;    /* Last seen block count */
+	unsigned int s_cluster_ratio;	/* Number of blocks per cluster */
+	unsigned int s_cluster_bits;	/* log2 of s_cluster_ratio */
 	loff_t s_bitmap_maxbytes;	/* max bytes for bitmap files */
 	struct buffer_head * s_sbh;	/* Buffer containing the super block */
 	struct ext4_super_block *s_es;	/* Pointer to the super block in the buffer */
@@ -1117,10 +1148,10 @@ struct ext4_sb_info {
 	u32 s_hash_seed[4];
 	int s_def_hash_version;
 	int s_hash_unsigned;	/* 3 if hash should be signed, 0 if not */
-	struct percpu_counter s_freeblocks_counter;
+	struct percpu_counter s_freeclusters_counter;
 	struct percpu_counter s_freeinodes_counter;
 	struct percpu_counter s_dirs_counter;
-	struct percpu_counter s_dirtyblocks_counter;
+	struct percpu_counter s_dirtyclusters_counter;
 	struct blockgroup_lock *s_blockgroup_lock;
 	struct proc_dir_entry *s_proc;
 	struct kobject s_kobj;
@@ -1136,10 +1167,6 @@ struct ext4_sb_info {
 	u32 s_max_batch_time;
 	u32 s_min_batch_time;
 	struct block_device *journal_bdev;
-#ifdef CONFIG_JBD2_DEBUG
-	struct timer_list turn_ro_timer;	/* For turning read-only (crash simulation) */
-	wait_queue_head_t ro_wait_queue;	/* For people waiting for the fs to go read-only */
-#endif
 #ifdef CONFIG_QUOTA
 	char *s_qf_names[MAXQUOTAS];		/* Names of quota files with journalled quota */
 	int s_jquota_fmt;			/* Format of quota to use */
@@ -1248,6 +1275,15 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
 		 ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count));
 }
 
+static inline void ext4_set_io_unwritten_flag(struct inode *inode,
+					      struct ext4_io_end *io_end)
+{
+	if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) {
+		io_end->flag |= EXT4_IO_END_UNWRITTEN;
+		atomic_inc(&EXT4_I(inode)->i_aiodio_unwritten);
+	}
+}
+
 /*
  * Inode dynamic state flags
  */
@@ -1360,6 +1396,7 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei)
 #define EXT4_FEATURE_RO_COMPAT_DIR_NLINK	0x0020
 #define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE	0x0040
 #define EXT4_FEATURE_RO_COMPAT_QUOTA		0x0100
+#define EXT4_FEATURE_RO_COMPAT_BIGALLOC		0x0200
 
 #define EXT4_FEATURE_INCOMPAT_COMPRESSION	0x0001
 #define EXT4_FEATURE_INCOMPAT_FILETYPE		0x0002
@@ -1402,7 +1439,8 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei)
 					 EXT4_FEATURE_RO_COMPAT_DIR_NLINK | \
 					 EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE | \
 					 EXT4_FEATURE_RO_COMPAT_BTREE_DIR |\
-					 EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
+					 EXT4_FEATURE_RO_COMPAT_HUGE_FILE |\
+					 EXT4_FEATURE_RO_COMPAT_BIGALLOC)
 
 /*
  * Default values for user and/or group using reserved blocks
@@ -1735,9 +1773,9 @@ extern ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode,
 					 unsigned int flags,
 					 unsigned long *count,
 					 int *errp);
-extern int ext4_claim_free_blocks(struct ext4_sb_info *sbi,
-				  s64 nblocks, unsigned int flags);
-extern ext4_fsblk_t ext4_count_free_blocks(struct super_block *);
+extern int ext4_claim_free_clusters(struct ext4_sb_info *sbi,
+				    s64 nclusters, unsigned int flags);
+extern ext4_fsblk_t ext4_count_free_clusters(struct super_block *);
 extern void ext4_check_blocks_bitmap(struct super_block *);
 extern struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
 						    ext4_group_t block_group,
@@ -1745,12 +1783,18 @@ extern struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
 extern int ext4_should_retry_alloc(struct super_block *sb, int *retries);
 struct buffer_head *ext4_read_block_bitmap(struct super_block *sb,
 				      ext4_group_t block_group);
-extern unsigned ext4_init_block_bitmap(struct super_block *sb,
-				       struct buffer_head *bh,
-				       ext4_group_t group,
-				       struct ext4_group_desc *desc);
-#define ext4_free_blocks_after_init(sb, group, desc)			\
-		ext4_init_block_bitmap(sb, NULL, group, desc)
+extern void ext4_init_block_bitmap(struct super_block *sb,
+				   struct buffer_head *bh,
+				   ext4_group_t group,
+				   struct ext4_group_desc *desc);
+extern unsigned ext4_free_clusters_after_init(struct super_block *sb,
+					      ext4_group_t block_group,
+					      struct ext4_group_desc *gdp);
+extern unsigned ext4_num_base_meta_clusters(struct super_block *sb,
+					    ext4_group_t block_group);
+extern unsigned ext4_num_overhead_clusters(struct super_block *sb,
+					   ext4_group_t block_group,
+					   struct ext4_group_desc *gdp);
 ext4_fsblk_t ext4_inode_to_goal_block(struct inode *);
 
 /* dir.c */
@@ -1776,7 +1820,8 @@ extern int ext4fs_dirhash(const char *name, int len, struct
 
 /* ialloc.c */
 extern struct inode *ext4_new_inode(handle_t *, struct inode *, int,
-				    const struct qstr *qstr, __u32 goal);
+				    const struct qstr *qstr, __u32 goal,
+				    uid_t *owner);
 extern void ext4_free_inode(handle_t *, struct inode *);
 extern struct inode * ext4_orphan_get(struct super_block *, unsigned long);
 extern unsigned long ext4_count_free_inodes(struct super_block *);
@@ -1839,6 +1884,12 @@ extern int ext4_block_truncate_page(handle_t *handle,
 		struct address_space *mapping, loff_t from);
 extern int ext4_block_zero_page_range(handle_t *handle,
 		struct address_space *mapping, loff_t from, loff_t length);
+extern int ext4_discard_partial_page_buffers(handle_t *handle,
+		struct address_space *mapping, loff_t from,
+		loff_t length, int flags);
+extern int ext4_discard_partial_page_buffers_no_lock(handle_t *handle,
+		struct inode *inode, struct page *page, loff_t from,
+		loff_t length, int flags);
 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 void ext4_da_update_reserve_space(struct inode *inode,
@@ -1927,8 +1978,8 @@ extern ext4_fsblk_t ext4_inode_bitmap(struct super_block *sb,
 				      struct ext4_group_desc *bg);
 extern ext4_fsblk_t ext4_inode_table(struct super_block *sb,
 				     struct ext4_group_desc *bg);
-extern __u32 ext4_free_blks_count(struct super_block *sb,
-				struct ext4_group_desc *bg);
+extern __u32 ext4_free_group_clusters(struct super_block *sb,
+				      struct ext4_group_desc *bg);
 extern __u32 ext4_free_inodes_count(struct super_block *sb,
 				 struct ext4_group_desc *bg);
 extern __u32 ext4_used_dirs_count(struct super_block *sb,
@@ -1941,8 +1992,9 @@ extern void ext4_inode_bitmap_set(struct super_block *sb,
 				  struct ext4_group_desc *bg, ext4_fsblk_t blk);
 extern void ext4_inode_table_set(struct super_block *sb,
 				 struct ext4_group_desc *bg, ext4_fsblk_t blk);
-extern void ext4_free_blks_set(struct super_block *sb,
-			       struct ext4_group_desc *bg, __u32 count);
+extern void ext4_free_group_clusters_set(struct super_block *sb,
+					 struct ext4_group_desc *bg,
+					 __u32 count);
 extern void ext4_free_inodes_set(struct super_block *sb,
 				struct ext4_group_desc *bg, __u32 count);
 extern void ext4_used_dirs_set(struct super_block *sb,
@@ -2051,13 +2103,13 @@ do {								\
 } while (0)
 
 #ifdef CONFIG_SMP
-/* Each CPU can accumulate percpu_counter_batch blocks in their local
- * counters. So we need to make sure we have free blocks more
+/* Each CPU can accumulate percpu_counter_batch clusters in their local
+ * counters. So we need to make sure we have free clusters more
  * than percpu_counter_batch  * nr_cpu_ids. Also add a window of 4 times.
  */
-#define EXT4_FREEBLOCKS_WATERMARK (4 * (percpu_counter_batch * nr_cpu_ids))
+#define EXT4_FREECLUSTERS_WATERMARK (4 * (percpu_counter_batch * nr_cpu_ids))
 #else
-#define EXT4_FREEBLOCKS_WATERMARK 0
+#define EXT4_FREECLUSTERS_WATERMARK 0
 #endif
 
 static inline void ext4_update_i_disksize(struct inode *inode, loff_t newsize)
@@ -2243,10 +2295,19 @@ extern int ext4_multi_mount_protect(struct super_block *, ext4_fsblk_t);
 enum ext4_state_bits {
 	BH_Uninit	/* blocks are allocated but uninitialized on disk */
 	  = BH_JBDPrivateStart,
+	BH_AllocFromCluster,	/* allocated blocks were part of already
+				 * allocated cluster. Note that this flag will
+				 * never, ever appear in a buffer_head's state
+				 * flag. See EXT4_MAP_FROM_CLUSTER to see where
+				 * this is used. */
+	BH_Da_Mapped,	/* Delayed allocated block that now has a mapping. This
+			 * flag is set when ext4_map_blocks is called on a
+			 * delayed allocated block to get its real mapping. */
 };
 
 BUFFER_FNS(Uninit, uninit)
 TAS_BUFFER_FNS(Uninit, uninit)
+BUFFER_FNS(Da_Mapped, da_mapped)
 
 /*
  * Add new method to test wether block and inode bitmaps are properly
@@ -2282,4 +2343,6 @@ extern void ext4_resize_end(struct super_block *sb);
 
 #endif	/* __KERNEL__ */
 
+#include "ext4_extents.h"
+
 #endif	/* _EXT4_H */
diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h
index 095c36f..a52db3a 100644
--- a/fs/ext4/ext4_extents.h
+++ b/fs/ext4/ext4_extents.h
@@ -290,5 +290,7 @@ extern struct ext4_ext_path *ext4_ext_find_extent(struct inode *, ext4_lblk_t,
 							struct ext4_ext_path *);
 extern void ext4_ext_drop_refs(struct ext4_ext_path *);
 extern int ext4_ext_check_inode(struct inode *inode);
+extern int ext4_find_delalloc_cluster(struct inode *inode, ext4_lblk_t lblk,
+				      int search_hint_reverse);
 #endif /* _EXT4_EXTENTS */
 
diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
index f5240aa..aca1790 100644
--- a/fs/ext4/ext4_jbd2.c
+++ b/fs/ext4/ext4_jbd2.c
@@ -109,9 +109,11 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
 
 	if (ext4_handle_valid(handle)) {
 		err = jbd2_journal_dirty_metadata(handle, bh);
-		if (err)
-			ext4_journal_abort_handle(where, line, __func__,
-						  bh, handle, err);
+		if (err) {
+			/* Errors can only happen if there is a bug */
+			handle->h_err = err;
+			__ext4_journal_stop(where, line, handle);
+		}
 	} else {
 		if (inode)
 			mark_buffer_dirty_inode(bh, inode);
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 57cf568..61fa9e1 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -42,7 +42,6 @@
 #include <asm/uaccess.h>
 #include <linux/fiemap.h>
 #include "ext4_jbd2.h"
-#include "ext4_extents.h"
 
 #include <trace/events/ext4.h>
 
@@ -96,13 +95,17 @@ static int ext4_ext_get_access(handle_t *handle, struct inode *inode,
  *  - ENOMEM
  *  - EIO
  */
-static int ext4_ext_dirty(handle_t *handle, struct inode *inode,
-				struct ext4_ext_path *path)
+#define ext4_ext_dirty(handle, inode, path) \
+		__ext4_ext_dirty(__func__, __LINE__, (handle), (inode), (path))
+static int __ext4_ext_dirty(const char *where, unsigned int line,
+			    handle_t *handle, struct inode *inode,
+			    struct ext4_ext_path *path)
 {
 	int err;
 	if (path->p_bh) {
 		/* path points to block */
-		err = ext4_handle_dirty_metadata(handle, inode, path->p_bh);
+		err = __ext4_handle_dirty_metadata(where, line, handle,
+						   inode, path->p_bh);
 	} else {
 		/* path points to leaf/index in inode body */
 		err = ext4_mark_inode_dirty(handle, inode);
@@ -114,11 +117,9 @@ static ext4_fsblk_t ext4_ext_find_goal(struct inode *inode,
 			      struct ext4_ext_path *path,
 			      ext4_lblk_t block)
 {
-	int depth;
-
 	if (path) {
+		int depth = path->p_depth;
 		struct ext4_extent *ex;
-		depth = path->p_depth;
 
 		/*
 		 * Try to predict block placement assuming that we are
@@ -180,12 +181,10 @@ static inline int ext4_ext_space_block(struct inode *inode, int check)
 
 	size = (inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header))
 			/ sizeof(struct ext4_extent);
-	if (!check) {
 #ifdef AGGRESSIVE_TEST
-		if (size > 6)
-			size = 6;
+	if (!check && size > 6)
+		size = 6;
 #endif
-	}
 	return size;
 }
 
@@ -195,12 +194,10 @@ static inline int ext4_ext_space_block_idx(struct inode *inode, int check)
 
 	size = (inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header))
 			/ sizeof(struct ext4_extent_idx);
-	if (!check) {
 #ifdef AGGRESSIVE_TEST
-		if (size > 5)
-			size = 5;
+	if (!check && size > 5)
+		size = 5;
 #endif
-	}
 	return size;
 }
 
@@ -211,12 +208,10 @@ static inline int ext4_ext_space_root(struct inode *inode, int check)
 	size = sizeof(EXT4_I(inode)->i_data);
 	size -= sizeof(struct ext4_extent_header);
 	size /= sizeof(struct ext4_extent);
-	if (!check) {
 #ifdef AGGRESSIVE_TEST
-		if (size > 3)
-			size = 3;
+	if (!check && size > 3)
+		size = 3;
 #endif
-	}
 	return size;
 }
 
@@ -227,12 +222,10 @@ static inline int ext4_ext_space_root_idx(struct inode *inode, int check)
 	size = sizeof(EXT4_I(inode)->i_data);
 	size -= sizeof(struct ext4_extent_header);
 	size /= sizeof(struct ext4_extent_idx);
-	if (!check) {
 #ifdef AGGRESSIVE_TEST
-		if (size > 4)
-			size = 4;
+	if (!check && size > 4)
+		size = 4;
 #endif
-	}
 	return size;
 }
 
@@ -244,7 +237,7 @@ static inline int ext4_ext_space_root_idx(struct inode *inode, int check)
 int ext4_ext_calc_metadata_amount(struct inode *inode, ext4_lblk_t lblock)
 {
 	struct ext4_inode_info *ei = EXT4_I(inode);
-	int idxs, num = 0;
+	int idxs;
 
 	idxs = ((inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header))
 		/ sizeof(struct ext4_extent_idx));
@@ -259,6 +252,8 @@ int ext4_ext_calc_metadata_amount(struct inode *inode, ext4_lblk_t lblock)
 	 */
 	if (ei->i_da_metadata_calc_len &&
 	    ei->i_da_metadata_calc_last_lblock+1 == lblock) {
+		int num = 0;
+
 		if ((ei->i_da_metadata_calc_len % idxs) == 0)
 			num++;
 		if ((ei->i_da_metadata_calc_len % (idxs*idxs)) == 0)
@@ -321,8 +316,6 @@ static int ext4_valid_extent_entries(struct inode *inode,
 				struct ext4_extent_header *eh,
 				int depth)
 {
-	struct ext4_extent *ext;
-	struct ext4_extent_idx *ext_idx;
 	unsigned short entries;
 	if (eh->eh_entries == 0)
 		return 1;
@@ -331,7 +324,7 @@ static int ext4_valid_extent_entries(struct inode *inode,
 
 	if (depth == 0) {
 		/* leaf entries */
-		ext = EXT_FIRST_EXTENT(eh);
+		struct ext4_extent *ext = EXT_FIRST_EXTENT(eh);
 		while (entries) {
 			if (!ext4_valid_extent(inode, ext))
 				return 0;
@@ -339,7 +332,7 @@ static int ext4_valid_extent_entries(struct inode *inode,
 			entries--;
 		}
 	} else {
-		ext_idx = EXT_FIRST_INDEX(eh);
+		struct ext4_extent_idx *ext_idx = EXT_FIRST_INDEX(eh);
 		while (entries) {
 			if (!ext4_valid_extent_idx(inode, ext_idx))
 				return 0;
@@ -751,31 +744,30 @@ static int ext4_ext_insert_index(handle_t *handle, struct inode *inode,
 		return -EIO;
 	}
 
-	len = EXT_MAX_INDEX(curp->p_hdr) - curp->p_idx;
 	if (logical > le32_to_cpu(curp->p_idx->ei_block)) {
 		/* insert after */
-		if (curp->p_idx != EXT_LAST_INDEX(curp->p_hdr)) {
-			len = (len - 1) * sizeof(struct ext4_extent_idx);
-			len = len < 0 ? 0 : len;
-			ext_debug("insert new index %d after: %llu. "
-					"move %d from 0x%p to 0x%p\n",
-					logical, ptr, len,
-					(curp->p_idx + 1), (curp->p_idx + 2));
-			memmove(curp->p_idx + 2, curp->p_idx + 1, len);
-		}
+		ext_debug("insert new index %d after: %llu\n", logical, ptr);
 		ix = curp->p_idx + 1;
 	} else {
 		/* insert before */
-		len = len * sizeof(struct ext4_extent_idx);
-		len = len < 0 ? 0 : len;
-		ext_debug("insert new index %d before: %llu. "
-				"move %d from 0x%p to 0x%p\n",
-				logical, ptr, len,
-				curp->p_idx, (curp->p_idx + 1));
-		memmove(curp->p_idx + 1, curp->p_idx, len);
+		ext_debug("insert new index %d before: %llu\n", logical, ptr);
 		ix = curp->p_idx;
 	}
 
+	len = EXT_LAST_INDEX(curp->p_hdr) - ix + 1;
+	BUG_ON(len < 0);
+	if (len > 0) {
+		ext_debug("insert new index %d: "
+				"move %d indices from 0x%p to 0x%p\n",
+				logical, len, ix, ix + 1);
+		memmove(ix + 1, ix, len * sizeof(struct ext4_extent_idx));
+	}
+
+	if (unlikely(ix > EXT_MAX_INDEX(curp->p_hdr))) {
+		EXT4_ERROR_INODE(inode, "ix > EXT_MAX_INDEX!");
+		return -EIO;
+	}
+
 	ix->ei_block = cpu_to_le32(logical);
 	ext4_idx_store_pblock(ix, ptr);
 	le16_add_cpu(&curp->p_hdr->eh_entries, 1);
@@ -1042,16 +1034,14 @@ cleanup:
  */
 static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
 				 unsigned int flags,
-				 struct ext4_ext_path *path,
 				 struct ext4_extent *newext)
 {
-	struct ext4_ext_path *curp = path;
 	struct ext4_extent_header *neh;
 	struct buffer_head *bh;
 	ext4_fsblk_t newblock;
 	int err = 0;
 
-	newblock = ext4_ext_new_meta_block(handle, inode, path,
+	newblock = ext4_ext_new_meta_block(handle, inode, NULL,
 		newext, &err, flags);
 	if (newblock == 0)
 		return err;
@@ -1071,7 +1061,8 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
 	}
 
 	/* move top-level index/leaf into new block */
-	memmove(bh->b_data, curp->p_hdr, sizeof(EXT4_I(inode)->i_data));
+	memmove(bh->b_data, EXT4_I(inode)->i_data,
+		sizeof(EXT4_I(inode)->i_data));
 
 	/* set size of new block */
 	neh = ext_block_hdr(bh);
@@ -1089,32 +1080,23 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
 	if (err)
 		goto out;
 
-	/* create index in new top-level index: num,max,pointer */
-	err = ext4_ext_get_access(handle, inode, curp);
-	if (err)
-		goto out;
-
-	curp->p_hdr->eh_magic = EXT4_EXT_MAGIC;
-	curp->p_hdr->eh_max = cpu_to_le16(ext4_ext_space_root_idx(inode, 0));
-	curp->p_hdr->eh_entries = cpu_to_le16(1);
-	curp->p_idx = EXT_FIRST_INDEX(curp->p_hdr);
-
-	if (path[0].p_hdr->eh_depth)
-		curp->p_idx->ei_block =
-			EXT_FIRST_INDEX(path[0].p_hdr)->ei_block;
-	else
-		curp->p_idx->ei_block =
-			EXT_FIRST_EXTENT(path[0].p_hdr)->ee_block;
-	ext4_idx_store_pblock(curp->p_idx, newblock);
-
+	/* Update top-level index: num,max,pointer */
 	neh = ext_inode_hdr(inode);
+	neh->eh_entries = cpu_to_le16(1);
+	ext4_idx_store_pblock(EXT_FIRST_INDEX(neh), newblock);
+	if (neh->eh_depth == 0) {
+		/* Root extent block becomes index block */
+		neh->eh_max = cpu_to_le16(ext4_ext_space_root_idx(inode, 0));
+		EXT_FIRST_INDEX(neh)->ei_block =
+			EXT_FIRST_EXTENT(neh)->ee_block;
+	}
 	ext_debug("new root: num %d(%d), lblock %d, ptr %llu\n",
 		  le16_to_cpu(neh->eh_entries), le16_to_cpu(neh->eh_max),
 		  le32_to_cpu(EXT_FIRST_INDEX(neh)->ei_block),
 		  ext4_idx_pblock(EXT_FIRST_INDEX(neh)));
 
-	neh->eh_depth = cpu_to_le16(path->p_depth + 1);
-	err = ext4_ext_dirty(handle, inode, curp);
+	neh->eh_depth = cpu_to_le16(neh->eh_depth + 1);
+	ext4_mark_inode_dirty(handle, inode);
 out:
 	brelse(bh);
 
@@ -1162,8 +1144,7 @@ repeat:
 			err = PTR_ERR(path);
 	} else {
 		/* tree is full, time to grow in depth */
-		err = ext4_ext_grow_indepth(handle, inode, flags,
-					    path, newext);
+		err = ext4_ext_grow_indepth(handle, inode, flags, newext);
 		if (err)
 			goto out;
 
@@ -1235,9 +1216,9 @@ static int ext4_ext_search_left(struct inode *inode,
 			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,
+				  ix != NULL ? le32_to_cpu(ix->ei_block) : 0,
 				  EXT_FIRST_INDEX(path[depth].p_hdr) != NULL ?
-				    EXT_FIRST_INDEX(path[depth].p_hdr)->ei_block : 0,
+		le32_to_cpu(EXT_FIRST_INDEX(path[depth].p_hdr)->ei_block) : 0,
 				  depth);
 				return -EIO;
 			}
@@ -1260,13 +1241,14 @@ static int ext4_ext_search_left(struct inode *inode,
 /*
  * search the closest allocated block to the right for *logical
  * and returns it at @logical + it's physical address at @phys
- * if *logical is the smallest allocated block, the function
+ * if *logical is the largest allocated block, the function
  * returns 0 at @phys
  * return value contains 0 (success) or error code
  */
 static int ext4_ext_search_right(struct inode *inode,
 				 struct ext4_ext_path *path,
-				 ext4_lblk_t *logical, ext4_fsblk_t *phys)
+				 ext4_lblk_t *logical, ext4_fsblk_t *phys,
+				 struct ext4_extent **ret_ex)
 {
 	struct buffer_head *bh = NULL;
 	struct ext4_extent_header *eh;
@@ -1308,9 +1290,7 @@ static int ext4_ext_search_right(struct inode *inode,
 				return -EIO;
 			}
 		}
-		*logical = le32_to_cpu(ex->ee_block);
-		*phys = ext4_ext_pblock(ex);
-		return 0;
+		goto found_extent;
 	}
 
 	if (unlikely(*logical < (le32_to_cpu(ex->ee_block) + ee_len))) {
@@ -1323,9 +1303,7 @@ static int ext4_ext_search_right(struct inode *inode,
 	if (ex != EXT_LAST_EXTENT(path[depth].p_hdr)) {
 		/* next allocated block in this leaf */
 		ex++;
-		*logical = le32_to_cpu(ex->ee_block);
-		*phys = ext4_ext_pblock(ex);
-		return 0;
+		goto found_extent;
 	}
 
 	/* go up and search for index to the right */
@@ -1368,9 +1346,12 @@ got_index:
 		return -EIO;
 	}
 	ex = EXT_FIRST_EXTENT(eh);
+found_extent:
 	*logical = le32_to_cpu(ex->ee_block);
 	*phys = ext4_ext_pblock(ex);
-	put_bh(bh);
+	*ret_ex = ex;
+	if (bh)
+		put_bh(bh);
 	return 0;
 }
 
@@ -1395,7 +1376,8 @@ ext4_ext_next_allocated_block(struct ext4_ext_path *path)
 	while (depth >= 0) {
 		if (depth == path->p_depth) {
 			/* leaf */
-			if (path[depth].p_ext !=
+			if (path[depth].p_ext &&
+				path[depth].p_ext !=
 					EXT_LAST_EXTENT(path[depth].p_hdr))
 			  return le32_to_cpu(path[depth].p_ext[1].ee_block);
 		} else {
@@ -1623,7 +1605,8 @@ static int ext4_ext_try_to_merge(struct inode *inode,
  * such that there will be no overlap, and then returns 1.
  * If there is no overlap found, it returns 0.
  */
-static unsigned int ext4_ext_check_overlap(struct inode *inode,
+static unsigned int ext4_ext_check_overlap(struct ext4_sb_info *sbi,
+					   struct inode *inode,
 					   struct ext4_extent *newext,
 					   struct ext4_ext_path *path)
 {
@@ -1637,6 +1620,7 @@ static unsigned int ext4_ext_check_overlap(struct inode *inode,
 	if (!path[depth].p_ext)
 		goto out;
 	b2 = le32_to_cpu(path[depth].p_ext->ee_block);
+	b2 &= ~(sbi->s_cluster_ratio - 1);
 
 	/*
 	 * get the next allocated block if the extent in the path
@@ -1646,6 +1630,7 @@ static unsigned int ext4_ext_check_overlap(struct inode *inode,
 		b2 = ext4_ext_next_allocated_block(path);
 		if (b2 == EXT_MAX_BLOCKS)
 			goto out;
+		b2 &= ~(sbi->s_cluster_ratio - 1);
 	}
 
 	/* check for wrap through zero on extent logical start block*/
@@ -1697,7 +1682,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
 	/* try to insert block into found extent and return */
 	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",
+		ext_debug("append [%d]%d block to %u:[%d]%d (from %llu)\n",
 			  ext4_ext_is_uninitialized(newext),
 			  ext4_ext_get_actual_len(newext),
 			  le32_to_cpu(ex->ee_block),
@@ -1735,7 +1720,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
 	if (le32_to_cpu(newext->ee_block) > le32_to_cpu(fex->ee_block))
 		next = ext4_ext_next_leaf_block(path);
 	if (next != EXT_MAX_BLOCKS) {
-		ext_debug("next leaf block - %d\n", next);
+		ext_debug("next leaf block - %u\n", next);
 		BUG_ON(npath != NULL);
 		npath = ext4_ext_find_extent(inode, next, NULL);
 		if (IS_ERR(npath))
@@ -1773,46 +1758,51 @@ has_space:
 
 	if (!nearex) {
 		/* there is no extent in this leaf, create first one */
-		ext_debug("first extent in the leaf: %d:%llu:[%d]%d\n",
+		ext_debug("first extent in the leaf: %u:%llu:[%d]%d\n",
 				le32_to_cpu(newext->ee_block),
 				ext4_ext_pblock(newext),
 				ext4_ext_is_uninitialized(newext),
 				ext4_ext_get_actual_len(newext));
-		path[depth].p_ext = EXT_FIRST_EXTENT(eh);
-	} else if (le32_to_cpu(newext->ee_block)
+		nearex = EXT_FIRST_EXTENT(eh);
+	} else {
+		if (le32_to_cpu(newext->ee_block)
 			   > le32_to_cpu(nearex->ee_block)) {
-/*		BUG_ON(newext->ee_block == nearex->ee_block); */
-		if (nearex != EXT_LAST_EXTENT(eh)) {
-			len = EXT_MAX_EXTENT(eh) - nearex;
-			len = (len - 1) * sizeof(struct ext4_extent);
-			len = len < 0 ? 0 : len;
-			ext_debug("insert %d:%llu:[%d]%d after: nearest 0x%p, "
-					"move %d from 0x%p to 0x%p\n",
+			/* Insert after */
+			ext_debug("insert %u:%llu:[%d]%d before: "
+					"nearest %p\n",
 					le32_to_cpu(newext->ee_block),
 					ext4_ext_pblock(newext),
 					ext4_ext_is_uninitialized(newext),
 					ext4_ext_get_actual_len(newext),
-					nearex, len, nearex + 1, nearex + 2);
-			memmove(nearex + 2, nearex + 1, len);
+					nearex);
+			nearex++;
+		} else {
+			/* Insert before */
+			BUG_ON(newext->ee_block == nearex->ee_block);
+			ext_debug("insert %u:%llu:[%d]%d after: "
+					"nearest %p\n",
+					le32_to_cpu(newext->ee_block),
+					ext4_ext_pblock(newext),
+					ext4_ext_is_uninitialized(newext),
+					ext4_ext_get_actual_len(newext),
+					nearex);
+		}
+		len = EXT_LAST_EXTENT(eh) - nearex + 1;
+		if (len > 0) {
+			ext_debug("insert %u:%llu:[%d]%d: "
+					"move %d extents from 0x%p to 0x%p\n",
+					le32_to_cpu(newext->ee_block),
+					ext4_ext_pblock(newext),
+					ext4_ext_is_uninitialized(newext),
+					ext4_ext_get_actual_len(newext),
+					len, nearex, nearex + 1);
+			memmove(nearex + 1, nearex,
+				len * sizeof(struct ext4_extent));
 		}
-		path[depth].p_ext = nearex + 1;
-	} else {
-		BUG_ON(newext->ee_block == nearex->ee_block);
-		len = (EXT_MAX_EXTENT(eh) - nearex) * sizeof(struct ext4_extent);
-		len = len < 0 ? 0 : len;
-		ext_debug("insert %d:%llu:[%d]%d before: nearest 0x%p, "
-				"move %d from 0x%p to 0x%p\n",
-				le32_to_cpu(newext->ee_block),
-				ext4_ext_pblock(newext),
-				ext4_ext_is_uninitialized(newext),
-				ext4_ext_get_actual_len(newext),
-				nearex, len, nearex, nearex + 1);
-		memmove(nearex + 1, nearex, len);
-		path[depth].p_ext = nearex;
 	}
 
 	le16_add_cpu(&eh->eh_entries, 1);
-	nearex = path[depth].p_ext;
+	path[depth].p_ext = nearex;
 	nearex->ee_block = newext->ee_block;
 	ext4_ext_store_pblock(nearex, ext4_ext_pblock(newext));
 	nearex->ee_len = newext->ee_len;
@@ -1962,6 +1952,7 @@ ext4_ext_put_in_cache(struct inode *inode, ext4_lblk_t block,
 	struct ext4_ext_cache *cex;
 	BUG_ON(len == 0);
 	spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
+	trace_ext4_ext_put_in_cache(inode, block, len, start);
 	cex = &EXT4_I(inode)->i_cached_extent;
 	cex->ec_block = block;
 	cex->ec_len = len;
@@ -2063,6 +2054,7 @@ errout:
 		sbi->extent_cache_misses++;
 	else
 		sbi->extent_cache_hits++;
+	trace_ext4_ext_in_cache(inode, block, ret);
 	spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
 	return ret;
 }
@@ -2130,6 +2122,8 @@ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode,
 	if (err)
 		return err;
 	ext_debug("index is empty, remove it, free block %llu\n", leaf);
+	trace_ext4_ext_rm_idx(inode, leaf);
+
 	ext4_free_blocks(handle, inode, NULL, leaf, 1,
 			 EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET);
 	return err;
@@ -2158,7 +2152,7 @@ int ext4_ext_calc_credits_for_single_extent(struct inode *inode, int nrblocks,
 			 *  need to account for leaf block credit
 			 *
 			 *  bitmaps and block group descriptor blocks
-			 *  and other metadat blocks still need to be
+			 *  and other metadata blocks still need to be
 			 *  accounted.
 			 */
 			/* 1 bitmap, 1 block group descriptor */
@@ -2195,14 +2189,40 @@ int ext4_ext_index_trans_blocks(struct inode *inode, int nrblocks, int chunk)
 }
 
 static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
-				struct ext4_extent *ex,
-				ext4_lblk_t from, ext4_lblk_t to)
+			      struct ext4_extent *ex,
+			      ext4_fsblk_t *partial_cluster,
+			      ext4_lblk_t from, ext4_lblk_t to)
 {
+	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
 	unsigned short ee_len =  ext4_ext_get_actual_len(ex);
+	ext4_fsblk_t pblk;
 	int flags = EXT4_FREE_BLOCKS_FORGET;
 
 	if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
 		flags |= EXT4_FREE_BLOCKS_METADATA;
+	/*
+	 * For bigalloc file systems, we never free a partial cluster
+	 * at the beginning of the extent.  Instead, we make a note
+	 * that we tried freeing the cluster, and check to see if we
+	 * need to free it on a subsequent call to ext4_remove_blocks,
+	 * or at the end of the ext4_truncate() operation.
+	 */
+	flags |= EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER;
+
+	trace_ext4_remove_blocks(inode, ex, from, to, *partial_cluster);
+	/*
+	 * If we have a partial cluster, and it's different from the
+	 * cluster of the last block, we need to explicitly free the
+	 * partial cluster here.
+	 */
+	pblk = ext4_ext_pblock(ex) + ee_len - 1;
+	if (*partial_cluster && (EXT4_B2C(sbi, pblk) != *partial_cluster)) {
+		ext4_free_blocks(handle, inode, NULL,
+				 EXT4_C2B(sbi, *partial_cluster),
+				 sbi->s_cluster_ratio, flags);
+		*partial_cluster = 0;
+	}
+
 #ifdef EXTENTS_STATS
 	{
 		struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
@@ -2222,12 +2242,24 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
 	    && to == le32_to_cpu(ex->ee_block) + ee_len - 1) {
 		/* tail removal */
 		ext4_lblk_t num;
-		ext4_fsblk_t start;
 
 		num = le32_to_cpu(ex->ee_block) + ee_len - from;
-		start = ext4_ext_pblock(ex) + ee_len - num;
-		ext_debug("free last %u blocks starting %llu\n", num, start);
-		ext4_free_blocks(handle, inode, NULL, start, num, flags);
+		pblk = ext4_ext_pblock(ex) + ee_len - num;
+		ext_debug("free last %u blocks starting %llu\n", num, pblk);
+		ext4_free_blocks(handle, inode, NULL, pblk, num, flags);
+		/*
+		 * If the block range to be freed didn't start at the
+		 * beginning of a cluster, and we removed the entire
+		 * extent, save the partial cluster here, since we
+		 * might need to delete if we determine that the
+		 * truncate operation has removed all of the blocks in
+		 * the cluster.
+		 */
+		if (pblk & (sbi->s_cluster_ratio - 1) &&
+		    (ee_len == num))
+			*partial_cluster = EXT4_B2C(sbi, pblk);
+		else
+			*partial_cluster = 0;
 	} else if (from == le32_to_cpu(ex->ee_block)
 		   && to <= le32_to_cpu(ex->ee_block) + ee_len - 1) {
 		/* head removal */
@@ -2238,7 +2270,7 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
 		start = ext4_ext_pblock(ex);
 
 		ext_debug("free first %u blocks starting %llu\n", num, start);
-		ext4_free_blocks(handle, inode, 0, start, num, flags);
+		ext4_free_blocks(handle, inode, NULL, start, num, flags);
 
 	} else {
 		printk(KERN_INFO "strange request: removal(2) "
@@ -2262,19 +2294,19 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
  */
 static int
 ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
-		struct ext4_ext_path *path, ext4_lblk_t start,
-		ext4_lblk_t end)
+		 struct ext4_ext_path *path, ext4_fsblk_t *partial_cluster,
+		 ext4_lblk_t start, ext4_lblk_t end)
 {
+	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
 	int err = 0, correct_index = 0;
 	int depth = ext_depth(inode), credits;
 	struct ext4_extent_header *eh;
-	ext4_lblk_t a, b, block;
+	ext4_lblk_t a, b;
 	unsigned num;
 	ext4_lblk_t ex_ee_block;
 	unsigned short ex_ee_len;
 	unsigned uninitialized = 0;
 	struct ext4_extent *ex;
-	struct ext4_map_blocks map;
 
 	/* the header must be checked already in ext4_ext_remove_space() */
 	ext_debug("truncate since %u in leaf\n", start);
@@ -2291,6 +2323,8 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
 	ex_ee_block = le32_to_cpu(ex->ee_block);
 	ex_ee_len = ext4_ext_get_actual_len(ex);
 
+	trace_ext4_ext_rm_leaf(inode, start, ex, *partial_cluster);
+
 	while (ex >= EXT_FIRST_EXTENT(eh) &&
 			ex_ee_block + ex_ee_len > start) {
 
@@ -2315,86 +2349,18 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
 			ex_ee_block = le32_to_cpu(ex->ee_block);
 			ex_ee_len = ext4_ext_get_actual_len(ex);
 			continue;
-		} else if (a != ex_ee_block &&
-			b != ex_ee_block + ex_ee_len - 1) {
-			/*
-			 * If this is a truncate, then this condition should
-			 * never happen because at least one of the end points
-			 * needs to be on the edge of the extent.
-			 */
-			if (end == EXT_MAX_BLOCKS - 1) {
-				ext_debug("  bad truncate %u:%u\n",
-						start, end);
-				block = 0;
-				num = 0;
-				err = -EIO;
-				goto out;
-			}
-			/*
-			 * else this is a hole punch, so the extent needs to
-			 * be split since neither edge of the hole is on the
-			 * extent edge
-			 */
-			else{
-				map.m_pblk = ext4_ext_pblock(ex);
-				map.m_lblk = ex_ee_block;
-				map.m_len = b - ex_ee_block;
-
-				err = ext4_split_extent(handle,
-					inode, path, &map, 0,
-					EXT4_GET_BLOCKS_PUNCH_OUT_EXT |
-					EXT4_GET_BLOCKS_PRE_IO);
-
-				if (err < 0)
-					goto out;
-
-				ex_ee_len = ext4_ext_get_actual_len(ex);
-
-				b = ex_ee_block+ex_ee_len - 1 < end ?
-					ex_ee_block+ex_ee_len - 1 : end;
-
-				/* Then remove tail of this extent */
-				block = ex_ee_block;
-				num = a - block;
-			}
+		} else if (b != ex_ee_block + ex_ee_len - 1) {
+			EXT4_ERROR_INODE(inode,"  bad truncate %u:%u\n",
+					 start, end);
+			err = -EIO;
+			goto out;
 		} else if (a != ex_ee_block) {
 			/* remove tail of the extent */
-			block = ex_ee_block;
-			num = a - block;
-		} else if (b != ex_ee_block + ex_ee_len - 1) {
-			/* remove head of the extent */
-			block = b;
-			num =  ex_ee_block + ex_ee_len - b;
-
-			/*
-			 * If this is a truncate, this condition
-			 * should never happen
-			 */
-			if (end == EXT_MAX_BLOCKS - 1) {
-				ext_debug("  bad truncate %u:%u\n",
-					start, end);
-				err = -EIO;
-				goto out;
-			}
+			num = a - ex_ee_block;
 		} else {
 			/* remove whole extent: excellent! */
-			block = ex_ee_block;
 			num = 0;
-			if (a != ex_ee_block) {
-				ext_debug("  bad truncate %u:%u\n",
-					start, end);
-				err = -EIO;
-				goto out;
-			}
-
-			if (b != ex_ee_block + ex_ee_len - 1) {
-				ext_debug("  bad truncate %u:%u\n",
-					start, end);
-				err = -EIO;
-				goto out;
-			}
 		}
-
 		/*
 		 * 3 for leaf, sb, and inode plus 2 (bmap and group
 		 * descriptor) for each block group; assume two block
@@ -2416,23 +2382,15 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
 		if (err)
 			goto out;
 
-		err = ext4_remove_blocks(handle, inode, ex, a, b);
+		err = ext4_remove_blocks(handle, inode, ex, partial_cluster,
+					 a, b);
 		if (err)
 			goto out;
 
-		if (num == 0) {
+		if (num == 0)
 			/* this extent is removed; mark slot entirely unused */
 			ext4_ext_store_pblock(ex, 0);
-		} else if (block != ex_ee_block) {
-			/*
-			 * If this was a head removal, then we need to update
-			 * the physical block since it is now at a different
-			 * location
-			 */
-			ext4_ext_store_pblock(ex, ext4_ext_pblock(ex) + (b-a));
-		}
 
-		ex->ee_block = cpu_to_le32(block);
 		ex->ee_len = cpu_to_le16(num);
 		/*
 		 * Do not mark uninitialized if all the blocks in the
@@ -2440,11 +2398,6 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
 		 */
 		if (uninitialized && num)
 			ext4_ext_mark_uninitialized(ex);
-
-		err = ext4_ext_dirty(handle, inode, path + depth);
-		if (err)
-			goto out;
-
 		/*
 		 * If the extent was completely released,
 		 * we need to remove it from the leaf
@@ -2464,9 +2417,14 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
 					sizeof(struct ext4_extent));
 			}
 			le16_add_cpu(&eh->eh_entries, -1);
-		}
+		} else
+			*partial_cluster = 0;
 
-		ext_debug("new extent: %u:%u:%llu\n", block, num,
+		err = ext4_ext_dirty(handle, inode, path + depth);
+		if (err)
+			goto out;
+
+		ext_debug("new extent: %u:%u:%llu\n", ex_ee_block, num,
 				ext4_ext_pblock(ex));
 		ex--;
 		ex_ee_block = le32_to_cpu(ex->ee_block);
@@ -2476,6 +2434,25 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
 	if (correct_index && eh->eh_entries)
 		err = ext4_ext_correct_indexes(handle, inode, path);
 
+	/*
+	 * If there is still a entry in the leaf node, check to see if
+	 * it references the partial cluster.  This is the only place
+	 * where it could; if it doesn't, we can free the cluster.
+	 */
+	if (*partial_cluster && ex >= EXT_FIRST_EXTENT(eh) &&
+	    (EXT4_B2C(sbi, ext4_ext_pblock(ex) + ex_ee_len - 1) !=
+	     *partial_cluster)) {
+		int flags = EXT4_FREE_BLOCKS_FORGET;
+
+		if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+			flags |= EXT4_FREE_BLOCKS_METADATA;
+
+		ext4_free_blocks(handle, inode, NULL,
+				 EXT4_C2B(sbi, *partial_cluster),
+				 sbi->s_cluster_ratio, flags);
+		*partial_cluster = 0;
+	}
+
 	/* if this leaf is free, then we should
 	 * remove it from index block above */
 	if (err == 0 && eh->eh_entries == 0 && path[depth].p_bh != NULL)
@@ -2511,6 +2488,7 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start)
 	struct super_block *sb = inode->i_sb;
 	int depth = ext_depth(inode);
 	struct ext4_ext_path *path;
+	ext4_fsblk_t partial_cluster = 0;
 	handle_t *handle;
 	int i, err;
 
@@ -2524,6 +2502,8 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start)
 again:
 	ext4_ext_invalidate_cache(inode);
 
+	trace_ext4_ext_remove_space(inode, start, depth);
+
 	/*
 	 * We start scanning from right side, freeing all the blocks
 	 * after i_size and walking into the tree depth-wise.
@@ -2546,7 +2526,8 @@ again:
 		if (i == depth) {
 			/* this is leaf block */
 			err = ext4_ext_rm_leaf(handle, inode, path,
-					start, EXT_MAX_BLOCKS - 1);
+					       &partial_cluster, start,
+					       EXT_MAX_BLOCKS - 1);
 			/* root level has p_bh == NULL, brelse() eats this */
 			brelse(path[i].p_bh);
 			path[i].p_bh = NULL;
@@ -2618,6 +2599,24 @@ again:
 		}
 	}
 
+	trace_ext4_ext_remove_space_done(inode, start, depth, partial_cluster,
+			path->p_hdr->eh_entries);
+
+	/* If we still have something in the partial cluster and we have removed
+	 * even the first extent, then we should free the blocks in the partial
+	 * cluster as well. */
+	if (partial_cluster && path->p_hdr->eh_entries == 0) {
+		int flags = EXT4_FREE_BLOCKS_FORGET;
+
+		if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+			flags |= EXT4_FREE_BLOCKS_METADATA;
+
+		ext4_free_blocks(handle, inode, NULL,
+				 EXT4_C2B(EXT4_SB(sb), partial_cluster),
+				 EXT4_SB(sb)->s_cluster_ratio, flags);
+		partial_cluster = 0;
+	}
+
 	/* TODO: flexible tree reduction should be here */
 	if (path->p_hdr->eh_entries == 0) {
 		/*
@@ -2909,17 +2908,29 @@ out:
  *   a> There is no split required: Entire extent should be initialized
  *   b> Splits in two extents: Write is happening at either end of the extent
  *   c> Splits in three extents: Somone is writing in middle of the extent
+ *
+ * Pre-conditions:
+ *  - The extent pointed to by 'path' is uninitialized.
+ *  - The extent pointed to by 'path' contains a superset
+ *    of the logical span [map->m_lblk, map->m_lblk + map->m_len).
+ *
+ * Post-conditions on success:
+ *  - the returned value is the number of blocks beyond map->l_lblk
+ *    that are allocated and initialized.
+ *    It is guaranteed to be >= map->m_len.
  */
 static int ext4_ext_convert_to_initialized(handle_t *handle,
 					   struct inode *inode,
 					   struct ext4_map_blocks *map,
 					   struct ext4_ext_path *path)
 {
+	struct ext4_extent_header *eh;
 	struct ext4_map_blocks split_map;
 	struct ext4_extent zero_ex;
 	struct ext4_extent *ex;
 	ext4_lblk_t ee_block, eof_block;
-	unsigned int allocated, ee_len, depth;
+	unsigned int ee_len, depth;
+	int allocated;
 	int err = 0;
 	int split_flag = 0;
 
@@ -2933,11 +2944,93 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
 		eof_block = map->m_lblk + map->m_len;
 
 	depth = ext_depth(inode);
+	eh = path[depth].p_hdr;
 	ex = path[depth].p_ext;
 	ee_block = le32_to_cpu(ex->ee_block);
 	ee_len = ext4_ext_get_actual_len(ex);
 	allocated = ee_len - (map->m_lblk - ee_block);
 
+	trace_ext4_ext_convert_to_initialized_enter(inode, map, ex);
+
+	/* Pre-conditions */
+	BUG_ON(!ext4_ext_is_uninitialized(ex));
+	BUG_ON(!in_range(map->m_lblk, ee_block, ee_len));
+	BUG_ON(map->m_lblk + map->m_len > ee_block + ee_len);
+
+	/*
+	 * Attempt to transfer newly initialized blocks from the currently
+	 * uninitialized extent to its left neighbor. This is much cheaper
+	 * than an insertion followed by a merge as those involve costly
+	 * memmove() calls. This is the common case in steady state for
+	 * workloads doing fallocate(FALLOC_FL_KEEP_SIZE) followed by append
+	 * writes.
+	 *
+	 * Limitations of the current logic:
+	 *  - L1: we only deal with writes at the start of the extent.
+	 *    The approach could be extended to writes at the end
+	 *    of the extent but this scenario was deemed less common.
+	 *  - L2: we do not deal with writes covering the whole extent.
+	 *    This would require removing the extent if the transfer
+	 *    is possible.
+	 *  - L3: we only attempt to merge with an extent stored in the
+	 *    same extent tree node.
+	 */
+	if ((map->m_lblk == ee_block) &&	/*L1*/
+		(map->m_len < ee_len) &&	/*L2*/
+		(ex > EXT_FIRST_EXTENT(eh))) {	/*L3*/
+		struct ext4_extent *prev_ex;
+		ext4_lblk_t prev_lblk;
+		ext4_fsblk_t prev_pblk, ee_pblk;
+		unsigned int prev_len, write_len;
+
+		prev_ex = ex - 1;
+		prev_lblk = le32_to_cpu(prev_ex->ee_block);
+		prev_len = ext4_ext_get_actual_len(prev_ex);
+		prev_pblk = ext4_ext_pblock(prev_ex);
+		ee_pblk = ext4_ext_pblock(ex);
+		write_len = map->m_len;
+
+		/*
+		 * A transfer of blocks from 'ex' to 'prev_ex' is allowed
+		 * upon those conditions:
+		 * - C1: prev_ex is initialized,
+		 * - C2: prev_ex is logically abutting ex,
+		 * - C3: prev_ex is physically abutting ex,
+		 * - C4: prev_ex can receive the additional blocks without
+		 *   overflowing the (initialized) length limit.
+		 */
+		if ((!ext4_ext_is_uninitialized(prev_ex)) &&		/*C1*/
+			((prev_lblk + prev_len) == ee_block) &&		/*C2*/
+			((prev_pblk + prev_len) == ee_pblk) &&		/*C3*/
+			(prev_len < (EXT_INIT_MAX_LEN - write_len))) {	/*C4*/
+			err = ext4_ext_get_access(handle, inode, path + depth);
+			if (err)
+				goto out;
+
+			trace_ext4_ext_convert_to_initialized_fastpath(inode,
+				map, ex, prev_ex);
+
+			/* Shift the start of ex by 'write_len' blocks */
+			ex->ee_block = cpu_to_le32(ee_block + write_len);
+			ext4_ext_store_pblock(ex, ee_pblk + write_len);
+			ex->ee_len = cpu_to_le16(ee_len - write_len);
+			ext4_ext_mark_uninitialized(ex); /* Restore the flag */
+
+			/* Extend prev_ex by 'write_len' blocks */
+			prev_ex->ee_len = cpu_to_le16(prev_len + write_len);
+
+			/* Mark the block containing both extents as dirty */
+			ext4_ext_dirty(handle, inode, path + depth);
+
+			/* Update path to point to the right extent */
+			path[depth].p_ext = prev_ex;
+
+			/* Result: number of initialized blocks past m_lblk */
+			allocated = write_len;
+			goto out;
+		}
+	}
+
 	WARN_ON(map->m_lblk < ee_block);
 	/*
 	 * It is safe to convert extent to initialized via explicit
@@ -3165,6 +3258,192 @@ static int check_eofblocks_fl(handle_t *handle, struct inode *inode,
 	return ext4_mark_inode_dirty(handle, inode);
 }
 
+/**
+ * ext4_find_delalloc_range: find delayed allocated block in the given range.
+ *
+ * Goes through the buffer heads in the range [lblk_start, lblk_end] and returns
+ * whether there are any buffers marked for delayed allocation. It returns '1'
+ * on the first delalloc'ed buffer head found. If no buffer head in the given
+ * range is marked for delalloc, it returns 0.
+ * lblk_start should always be <= lblk_end.
+ * search_hint_reverse is to indicate that searching in reverse from lblk_end to
+ * lblk_start might be more efficient (i.e., we will likely hit the delalloc'ed
+ * block sooner). This is useful when blocks are truncated sequentially from
+ * lblk_start towards lblk_end.
+ */
+static int ext4_find_delalloc_range(struct inode *inode,
+				    ext4_lblk_t lblk_start,
+				    ext4_lblk_t lblk_end,
+				    int search_hint_reverse)
+{
+	struct address_space *mapping = inode->i_mapping;
+	struct buffer_head *head, *bh = NULL;
+	struct page *page;
+	ext4_lblk_t i, pg_lblk;
+	pgoff_t index;
+
+	/* reverse search wont work if fs block size is less than page size */
+	if (inode->i_blkbits < PAGE_CACHE_SHIFT)
+		search_hint_reverse = 0;
+
+	if (search_hint_reverse)
+		i = lblk_end;
+	else
+		i = lblk_start;
+
+	index = i >> (PAGE_CACHE_SHIFT - inode->i_blkbits);
+
+	while ((i >= lblk_start) && (i <= lblk_end)) {
+		page = find_get_page(mapping, index);
+		if (!page)
+			goto nextpage;
+
+		if (!page_has_buffers(page))
+			goto nextpage;
+
+		head = page_buffers(page);
+		if (!head)
+			goto nextpage;
+
+		bh = head;
+		pg_lblk = index << (PAGE_CACHE_SHIFT -
+						inode->i_blkbits);
+		do {
+			if (unlikely(pg_lblk < lblk_start)) {
+				/*
+				 * This is possible when fs block size is less
+				 * than page size and our cluster starts/ends in
+				 * middle of the page. So we need to skip the
+				 * initial few blocks till we reach the 'lblk'
+				 */
+				pg_lblk++;
+				continue;
+			}
+
+			/* Check if the buffer is delayed allocated and that it
+			 * is not yet mapped. (when da-buffers are mapped during
+			 * their writeout, their da_mapped bit is set.)
+			 */
+			if (buffer_delay(bh) && !buffer_da_mapped(bh)) {
+				page_cache_release(page);
+				trace_ext4_find_delalloc_range(inode,
+						lblk_start, lblk_end,
+						search_hint_reverse,
+						1, i);
+				return 1;
+			}
+			if (search_hint_reverse)
+				i--;
+			else
+				i++;
+		} while ((i >= lblk_start) && (i <= lblk_end) &&
+				((bh = bh->b_this_page) != head));
+nextpage:
+		if (page)
+			page_cache_release(page);
+		/*
+		 * Move to next page. 'i' will be the first lblk in the next
+		 * page.
+		 */
+		if (search_hint_reverse)
+			index--;
+		else
+			index++;
+		i = index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
+	}
+
+	trace_ext4_find_delalloc_range(inode, lblk_start, lblk_end,
+					search_hint_reverse, 0, 0);
+	return 0;
+}
+
+int ext4_find_delalloc_cluster(struct inode *inode, ext4_lblk_t lblk,
+			       int search_hint_reverse)
+{
+	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+	ext4_lblk_t lblk_start, lblk_end;
+	lblk_start = lblk & (~(sbi->s_cluster_ratio - 1));
+	lblk_end = lblk_start + sbi->s_cluster_ratio - 1;
+
+	return ext4_find_delalloc_range(inode, lblk_start, lblk_end,
+					search_hint_reverse);
+}
+
+/**
+ * Determines how many complete clusters (out of those specified by the 'map')
+ * are under delalloc and were reserved quota for.
+ * This function is called when we are writing out the blocks that were
+ * originally written with their allocation delayed, but then the space was
+ * allocated using fallocate() before the delayed allocation could be resolved.
+ * The cases to look for are:
+ * ('=' indicated delayed allocated blocks
+ *  '-' indicates non-delayed allocated blocks)
+ * (a) partial clusters towards beginning and/or end outside of allocated range
+ *     are not delalloc'ed.
+ *	Ex:
+ *	|----c---=|====c====|====c====|===-c----|
+ *	         |++++++ allocated ++++++|
+ *	==> 4 complete clusters in above example
+ *
+ * (b) partial cluster (outside of allocated range) towards either end is
+ *     marked for delayed allocation. In this case, we will exclude that
+ *     cluster.
+ *	Ex:
+ *	|----====c========|========c========|
+ *	     |++++++ allocated ++++++|
+ *	==> 1 complete clusters in above example
+ *
+ *	Ex:
+ *	|================c================|
+ *            |++++++ allocated ++++++|
+ *	==> 0 complete clusters in above example
+ *
+ * The ext4_da_update_reserve_space will be called only if we
+ * determine here that there were some "entire" clusters that span
+ * this 'allocated' range.
+ * In the non-bigalloc case, this function will just end up returning num_blks
+ * without ever calling ext4_find_delalloc_range.
+ */
+static unsigned int
+get_reserved_cluster_alloc(struct inode *inode, ext4_lblk_t lblk_start,
+			   unsigned int num_blks)
+{
+	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+	ext4_lblk_t alloc_cluster_start, alloc_cluster_end;
+	ext4_lblk_t lblk_from, lblk_to, c_offset;
+	unsigned int allocated_clusters = 0;
+
+	alloc_cluster_start = EXT4_B2C(sbi, lblk_start);
+	alloc_cluster_end = EXT4_B2C(sbi, lblk_start + num_blks - 1);
+
+	/* max possible clusters for this allocation */
+	allocated_clusters = alloc_cluster_end - alloc_cluster_start + 1;
+
+	trace_ext4_get_reserved_cluster_alloc(inode, lblk_start, num_blks);
+
+	/* Check towards left side */
+	c_offset = lblk_start & (sbi->s_cluster_ratio - 1);
+	if (c_offset) {
+		lblk_from = lblk_start & (~(sbi->s_cluster_ratio - 1));
+		lblk_to = lblk_from + c_offset - 1;
+
+		if (ext4_find_delalloc_range(inode, lblk_from, lblk_to, 0))
+			allocated_clusters--;
+	}
+
+	/* Now check towards right. */
+	c_offset = (lblk_start + num_blks) & (sbi->s_cluster_ratio - 1);
+	if (allocated_clusters && c_offset) {
+		lblk_from = lblk_start + num_blks;
+		lblk_to = lblk_from + (sbi->s_cluster_ratio - c_offset) - 1;
+
+		if (ext4_find_delalloc_range(inode, lblk_from, lblk_to, 0))
+			allocated_clusters--;
+	}
+
+	return allocated_clusters;
+}
+
 static int
 ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
 			struct ext4_map_blocks *map,
@@ -3181,6 +3460,9 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
 		  flags, allocated);
 	ext4_ext_show_leaf(inode, path);
 
+	trace_ext4_ext_handle_uninitialized_extents(inode, map, allocated,
+						    newblock);
+
 	/* get_block() before submit the IO, split the extent */
 	if ((flags & EXT4_GET_BLOCKS_PRE_IO)) {
 		ret = ext4_split_unwritten_extents(handle, inode, map,
@@ -3190,10 +3472,9 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
 		 * that this IO needs to conversion to written when IO is
 		 * completed
 		 */
-		if (io && !(io->flag & EXT4_IO_END_UNWRITTEN)) {
-			io->flag = EXT4_IO_END_UNWRITTEN;
-			atomic_inc(&EXT4_I(inode)->i_aiodio_unwritten);
-		} else
+		if (io)
+			ext4_set_io_unwritten_flag(inode, io);
+		else
 			ext4_set_inode_state(inode, EXT4_STATE_DIO_UNWRITTEN);
 		if (ext4_should_dioread_nolock(inode))
 			map->m_flags |= EXT4_MAP_UNINIT;
@@ -3234,14 +3515,8 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
 
 	/* buffered write, writepage time, convert*/
 	ret = ext4_ext_convert_to_initialized(handle, inode, map, path);
-	if (ret >= 0) {
+	if (ret >= 0)
 		ext4_update_inode_fsync_trans(handle, inode, 1);
-		err = check_eofblocks_fl(handle, inode, map->m_lblk, path,
-					 map->m_len);
-		if (err < 0)
-			goto out2;
-	}
-
 out:
 	if (ret <= 0) {
 		err = ret;
@@ -3270,11 +3545,24 @@ out:
 	 * But fallocate would have already updated quota and block
 	 * count for this offset. So cancel these reservation
 	 */
-	if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
-		ext4_da_update_reserve_space(inode, allocated, 0);
+	if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) {
+		unsigned int reserved_clusters;
+		reserved_clusters = get_reserved_cluster_alloc(inode,
+				map->m_lblk, map->m_len);
+		if (reserved_clusters)
+			ext4_da_update_reserve_space(inode,
+						     reserved_clusters,
+						     0);
+	}
 
 map_out:
 	map->m_flags |= EXT4_MAP_MAPPED;
+	if ((flags & EXT4_GET_BLOCKS_KEEP_SIZE) == 0) {
+		err = check_eofblocks_fl(handle, inode, map->m_lblk, path,
+					 map->m_len);
+		if (err < 0)
+			goto out2;
+	}
 out1:
 	if (allocated > map->m_len)
 		allocated = map->m_len;
@@ -3290,6 +3578,111 @@ out2:
 }
 
 /*
+ * get_implied_cluster_alloc - check to see if the requested
+ * allocation (in the map structure) overlaps with a cluster already
+ * allocated in an extent.
+ *	@sb	The filesystem superblock structure
+ *	@map	The requested lblk->pblk mapping
+ *	@ex	The extent structure which might contain an implied
+ *			cluster allocation
+ *
+ * This function is called by ext4_ext_map_blocks() after we failed to
+ * find blocks that were already in the inode's extent tree.  Hence,
+ * we know that the beginning of the requested region cannot overlap
+ * the extent from the inode's extent tree.  There are three cases we
+ * want to catch.  The first is this case:
+ *
+ *		 |--- cluster # N--|
+ *    |--- extent ---|	|---- requested region ---|
+ *			|==========|
+ *
+ * The second case that we need to test for is this one:
+ *
+ *   |--------- cluster # N ----------------|
+ *	   |--- requested region --|   |------- extent ----|
+ *	   |=======================|
+ *
+ * The third case is when the requested region lies between two extents
+ * within the same cluster:
+ *          |------------- cluster # N-------------|
+ * |----- ex -----|                  |---- ex_right ----|
+ *                  |------ requested region ------|
+ *                  |================|
+ *
+ * In each of the above cases, we need to set the map->m_pblk and
+ * map->m_len so it corresponds to the return the extent labelled as
+ * "|====|" from cluster #N, since it is already in use for data in
+ * cluster EXT4_B2C(sbi, map->m_lblk).	We will then return 1 to
+ * signal to ext4_ext_map_blocks() that map->m_pblk should be treated
+ * as a new "allocated" block region.  Otherwise, we will return 0 and
+ * ext4_ext_map_blocks() will then allocate one or more new clusters
+ * by calling ext4_mb_new_blocks().
+ */
+static int get_implied_cluster_alloc(struct super_block *sb,
+				     struct ext4_map_blocks *map,
+				     struct ext4_extent *ex,
+				     struct ext4_ext_path *path)
+{
+	struct ext4_sb_info *sbi = EXT4_SB(sb);
+	ext4_lblk_t c_offset = map->m_lblk & (sbi->s_cluster_ratio-1);
+	ext4_lblk_t ex_cluster_start, ex_cluster_end;
+	ext4_lblk_t rr_cluster_start, rr_cluster_end;
+	ext4_lblk_t ee_block = le32_to_cpu(ex->ee_block);
+	ext4_fsblk_t ee_start = ext4_ext_pblock(ex);
+	unsigned short ee_len = ext4_ext_get_actual_len(ex);
+
+	/* The extent passed in that we are trying to match */
+	ex_cluster_start = EXT4_B2C(sbi, ee_block);
+	ex_cluster_end = EXT4_B2C(sbi, ee_block + ee_len - 1);
+
+	/* The requested region passed into ext4_map_blocks() */
+	rr_cluster_start = EXT4_B2C(sbi, map->m_lblk);
+	rr_cluster_end = EXT4_B2C(sbi, map->m_lblk + map->m_len - 1);
+
+	if ((rr_cluster_start == ex_cluster_end) ||
+	    (rr_cluster_start == ex_cluster_start)) {
+		if (rr_cluster_start == ex_cluster_end)
+			ee_start += ee_len - 1;
+		map->m_pblk = (ee_start & ~(sbi->s_cluster_ratio - 1)) +
+			c_offset;
+		map->m_len = min(map->m_len,
+				 (unsigned) sbi->s_cluster_ratio - c_offset);
+		/*
+		 * Check for and handle this case:
+		 *
+		 *   |--------- cluster # N-------------|
+		 *		       |------- extent ----|
+		 *	   |--- requested region ---|
+		 *	   |===========|
+		 */
+
+		if (map->m_lblk < ee_block)
+			map->m_len = min(map->m_len, ee_block - map->m_lblk);
+
+		/*
+		 * Check for the case where there is already another allocated
+		 * block to the right of 'ex' but before the end of the cluster.
+		 *
+		 *          |------------- cluster # N-------------|
+		 * |----- ex -----|                  |---- ex_right ----|
+		 *                  |------ requested region ------|
+		 *                  |================|
+		 */
+		if (map->m_lblk > ee_block) {
+			ext4_lblk_t next = ext4_ext_next_allocated_block(path);
+			map->m_len = min(map->m_len, next - map->m_lblk);
+		}
+
+		trace_ext4_get_implied_cluster_alloc_exit(sb, map, 1);
+		return 1;
+	}
+
+	trace_ext4_get_implied_cluster_alloc_exit(sb, map, 0);
+	return 0;
+}
+
+
+/*
  * Block allocation/map/preallocation routine for extents based files
  *
  *
@@ -3311,15 +3704,17 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 			struct ext4_map_blocks *map, int flags)
 {
 	struct ext4_ext_path *path = NULL;
-	struct ext4_extent newex, *ex;
+	struct ext4_extent newex, *ex, *ex2;
+	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
 	ext4_fsblk_t newblock = 0;
-	int err = 0, depth, ret;
-	unsigned int allocated = 0;
+	int free_on_err = 0, err = 0, depth, ret;
+	unsigned int allocated = 0, offset = 0;
+	unsigned int allocated_clusters = 0;
 	unsigned int punched_out = 0;
 	unsigned int result = 0;
 	struct ext4_allocation_request ar;
 	ext4_io_end_t *io = EXT4_I(inode)->cur_aio_dio;
-	struct ext4_map_blocks punch_map;
+	ext4_lblk_t cluster_offset;
 
 	ext_debug("blocks %u/%u requested for inode %lu\n",
 		  map->m_lblk, map->m_len, inode->i_ino);
@@ -3329,6 +3724,10 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 	if (!(flags & EXT4_GET_BLOCKS_PUNCH_OUT_EXT) &&
 		ext4_ext_in_cache(inode, map->m_lblk, &newex)) {
 		if (!newex.ee_start_lo && !newex.ee_start_hi) {
+			if ((sbi->s_cluster_ratio > 1) &&
+			    ext4_find_delalloc_cluster(inode, map->m_lblk, 0))
+				map->m_flags |= EXT4_MAP_FROM_CLUSTER;
+
 			if ((flags & EXT4_GET_BLOCKS_CREATE) == 0) {
 				/*
 				 * block isn't allocated yet and
@@ -3339,6 +3738,8 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 			/* we should allocate requested block */
 		} else {
 			/* block is already allocated */
+			if (sbi->s_cluster_ratio > 1)
+				map->m_flags |= EXT4_MAP_FROM_CLUSTER;
 			newblock = map->m_lblk
 				   - le32_to_cpu(newex.ee_block)
 				   + ext4_ext_pblock(&newex);
@@ -3384,8 +3785,14 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 		 * we split out initialized portions during a write.
 		 */
 		ee_len = ext4_ext_get_actual_len(ex);
+
+		trace_ext4_ext_show_extent(inode, ee_block, ee_start, ee_len);
+
 		/* if found extent covers block, simply return it */
 		if (in_range(map->m_lblk, ee_block, ee_len)) {
+			struct ext4_map_blocks punch_map;
+			ext4_fsblk_t partial_cluster = 0;
+
 			newblock = map->m_lblk - ee_block + ee_start;
 			/* number of remaining blocks in the extent */
 			allocated = ee_len - (map->m_lblk - ee_block);
@@ -3469,7 +3876,8 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 			ext4_ext_invalidate_cache(inode);
 
 			err = ext4_ext_rm_leaf(handle, inode, path,
-				map->m_lblk, map->m_lblk + punched_out);
+					       &partial_cluster, map->m_lblk,
+					       map->m_lblk + punched_out);
 
 			if (!err && path->p_hdr->eh_entries == 0) {
 				/*
@@ -3492,6 +3900,10 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 		}
 	}
 
+	if ((sbi->s_cluster_ratio > 1) &&
+	    ext4_find_delalloc_cluster(inode, map->m_lblk, 0))
+		map->m_flags |= EXT4_MAP_FROM_CLUSTER;
+
 	/*
 	 * requested block isn't allocated yet;
 	 * we couldn't try to create block if create flag is zero
@@ -3504,9 +3916,25 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 		ext4_ext_put_gap_in_cache(inode, path, map->m_lblk);
 		goto out2;
 	}
+
 	/*
 	 * Okay, we need to do block allocation.
 	 */
+	map->m_flags &= ~EXT4_MAP_FROM_CLUSTER;
+	newex.ee_block = cpu_to_le32(map->m_lblk);
+	cluster_offset = map->m_lblk & (sbi->s_cluster_ratio-1);
+
+	/*
+	 * If we are doing bigalloc, check to see if the extent returned
+	 * by ext4_ext_find_extent() implies a cluster we can use.
+	 */
+	if (cluster_offset && ex &&
+	    get_implied_cluster_alloc(inode->i_sb, map, ex, path)) {
+		ar.len = allocated = map->m_len;
+		newblock = map->m_pblk;
+		map->m_flags |= EXT4_MAP_FROM_CLUSTER;
+		goto got_allocated_blocks;
+	}
 
 	/* find neighbour allocated blocks */
 	ar.lleft = map->m_lblk;
@@ -3514,10 +3942,21 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 	if (err)
 		goto out2;
 	ar.lright = map->m_lblk;
-	err = ext4_ext_search_right(inode, path, &ar.lright, &ar.pright);
+	ex2 = NULL;
+	err = ext4_ext_search_right(inode, path, &ar.lright, &ar.pright, &ex2);
 	if (err)
 		goto out2;
 
+	/* Check if the extent after searching to the right implies a
+	 * cluster we can use. */
+	if ((sbi->s_cluster_ratio > 1) && ex2 &&
+	    get_implied_cluster_alloc(inode->i_sb, map, ex2, path)) {
+		ar.len = allocated = map->m_len;
+		newblock = map->m_pblk;
+		map->m_flags |= EXT4_MAP_FROM_CLUSTER;
+		goto got_allocated_blocks;
+	}
+
 	/*
 	 * See if request is beyond maximum number of blocks we can have in
 	 * a single extent. For an initialized extent this limit is
@@ -3532,9 +3971,8 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 		map->m_len = EXT_UNINIT_MAX_LEN;
 
 	/* Check if we can really insert (m_lblk)::(m_lblk + m_len) extent */
-	newex.ee_block = cpu_to_le32(map->m_lblk);
 	newex.ee_len = cpu_to_le16(map->m_len);
-	err = ext4_ext_check_overlap(inode, &newex, path);
+	err = ext4_ext_check_overlap(sbi, inode, &newex, path);
 	if (err)
 		allocated = ext4_ext_get_actual_len(&newex);
 	else
@@ -3544,7 +3982,18 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 	ar.inode = inode;
 	ar.goal = ext4_ext_find_goal(inode, path, map->m_lblk);
 	ar.logical = map->m_lblk;
-	ar.len = allocated;
+	/*
+	 * We calculate the offset from the beginning of the cluster
+	 * for the logical block number, since when we allocate a
+	 * physical cluster, the physical block should start at the
+	 * same offset from the beginning of the cluster.  This is
+	 * needed so that future calls to get_implied_cluster_alloc()
+	 * work correctly.
+	 */
+	offset = map->m_lblk & (sbi->s_cluster_ratio - 1);
+	ar.len = EXT4_NUM_B2C(sbi, offset+allocated);
+	ar.goal -= offset;
+	ar.logical -= offset;
 	if (S_ISREG(inode->i_mode))
 		ar.flags = EXT4_MB_HINT_DATA;
 	else
@@ -3557,9 +4006,15 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 		goto out2;
 	ext_debug("allocate new block: goal %llu, found %llu/%u\n",
 		  ar.goal, newblock, allocated);
+	free_on_err = 1;
+	allocated_clusters = ar.len;
+	ar.len = EXT4_C2B(sbi, ar.len) - offset;
+	if (ar.len > allocated)
+		ar.len = allocated;
 
+got_allocated_blocks:
 	/* try to insert new extent into found leaf and return */
-	ext4_ext_store_pblock(&newex, newblock);
+	ext4_ext_store_pblock(&newex, newblock + offset);
 	newex.ee_len = cpu_to_le16(ar.len);
 	/* Mark uninitialized */
 	if (flags & EXT4_GET_BLOCKS_UNINIT_EXT){
@@ -3572,10 +4027,9 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 		 * that we need to perform conversion when IO is done.
 		 */
 		if ((flags & EXT4_GET_BLOCKS_PRE_IO)) {
-			if (io && !(io->flag & EXT4_IO_END_UNWRITTEN)) {
-				io->flag = EXT4_IO_END_UNWRITTEN;
-				atomic_inc(&EXT4_I(inode)->i_aiodio_unwritten);
-			} else
+			if (io)
+				ext4_set_io_unwritten_flag(inode, io);
+			else
 				ext4_set_inode_state(inode,
 						     EXT4_STATE_DIO_UNWRITTEN);
 		}
@@ -3583,11 +4037,14 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 			map->m_flags |= EXT4_MAP_UNINIT;
 	}
 
-	err = check_eofblocks_fl(handle, inode, map->m_lblk, path, ar.len);
+	err = 0;
+	if ((flags & EXT4_GET_BLOCKS_KEEP_SIZE) == 0)
+		err = check_eofblocks_fl(handle, inode, map->m_lblk,
+					 path, ar.len);
 	if (!err)
 		err = ext4_ext_insert_extent(handle, inode, path,
 					     &newex, flags);
-	if (err) {
+	if (err && free_on_err) {
 		int fb_flags = flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE ?
 			EXT4_FREE_BLOCKS_NO_QUOT_UPDATE : 0;
 		/* free data blocks we just allocated */
@@ -3610,8 +4067,82 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 	 * Update reserved blocks/metadata blocks after successful
 	 * block allocation which had been deferred till now.
 	 */
-	if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
-		ext4_da_update_reserve_space(inode, allocated, 1);
+	if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) {
+		unsigned int reserved_clusters;
+		/*
+		 * Check how many clusters we had reserved this allocated range
+		 */
+		reserved_clusters = get_reserved_cluster_alloc(inode,
+						map->m_lblk, allocated);
+		if (map->m_flags & EXT4_MAP_FROM_CLUSTER) {
+			if (reserved_clusters) {
+				/*
+				 * We have clusters reserved for this range.
+				 * But since we are not doing actual allocation
+				 * and are simply using blocks from previously
+				 * allocated cluster, we should release the
+				 * reservation and not claim quota.
+				 */
+				ext4_da_update_reserve_space(inode,
+						reserved_clusters, 0);
+			}
+		} else {
+			BUG_ON(allocated_clusters < reserved_clusters);
+			/* We will claim quota for all newly allocated blocks.*/
+			ext4_da_update_reserve_space(inode, allocated_clusters,
+							1);
+			if (reserved_clusters < allocated_clusters) {
+				struct ext4_inode_info *ei = EXT4_I(inode);
+				int reservation = allocated_clusters -
+						  reserved_clusters;
+				/*
+				 * It seems we claimed few clusters outside of
+				 * the range of this allocation. We should give
+				 * it back to the reservation pool. This can
+				 * happen in the following case:
+				 *
+				 * * Suppose s_cluster_ratio is 4 (i.e., each
+				 *   cluster has 4 blocks. Thus, the clusters
+				 *   are [0-3],[4-7],[8-11]...
+				 * * First comes delayed allocation write for
+				 *   logical blocks 10 & 11. Since there were no
+				 *   previous delayed allocated blocks in the
+				 *   range [8-11], we would reserve 1 cluster
+				 *   for this write.
+				 * * Next comes write for logical blocks 3 to 8.
+				 *   In this case, we will reserve 2 clusters
+				 *   (for [0-3] and [4-7]; and not for [8-11] as
+				 *   that range has a delayed allocated blocks.
+				 *   Thus total reserved clusters now becomes 3.
+				 * * Now, during the delayed allocation writeout
+				 *   time, we will first write blocks [3-8] and
+				 *   allocate 3 clusters for writing these
+				 *   blocks. Also, we would claim all these
+				 *   three clusters above.
+				 * * Now when we come here to writeout the
+				 *   blocks [10-11], we would expect to claim
+				 *   the reservation of 1 cluster we had made
+				 *   (and we would claim it since there are no
+				 *   more delayed allocated blocks in the range
+				 *   [8-11]. But our reserved cluster count had
+				 *   already gone to 0.
+				 *
+				 *   Thus, at the step 4 above when we determine
+				 *   that there are still some unwritten delayed
+				 *   allocated blocks outside of our current
+				 *   block range, we should increment the
+				 *   reserved clusters count so that when the
+				 *   remaining blocks finally gets written, we
+				 *   could claim them.
+				 */
+				dquot_reserve_block(inode,
+						EXT4_C2B(sbi, reservation));
+				spin_lock(&ei->i_block_reservation_lock);
+				ei->i_reserved_data_blocks += reservation;
+				spin_unlock(&ei->i_block_reservation_lock);
+			}
+		}
+	}
 
 	/*
 	 * Cache the extent and update transaction to commit on fdatasync only
@@ -3634,12 +4165,12 @@ out2:
 		ext4_ext_drop_refs(path);
 		kfree(path);
 	}
-	trace_ext4_ext_map_blocks_exit(inode, map->m_lblk,
-		newblock, map->m_len, err ? err : allocated);
-
 	result = (flags & EXT4_GET_BLOCKS_PUNCH_OUT_EXT) ?
 			punched_out : allocated;
 
+	trace_ext4_ext_map_blocks_exit(inode, map->m_lblk,
+		newblock, map->m_len, err ? err : result);
+
 	return err ? err : result;
 }
 
@@ -3649,6 +4180,7 @@ void ext4_ext_truncate(struct inode *inode)
 	struct super_block *sb = inode->i_sb;
 	ext4_lblk_t last_block;
 	handle_t *handle;
+	loff_t page_len;
 	int err = 0;
 
 	/*
@@ -3665,8 +4197,16 @@ void ext4_ext_truncate(struct inode *inode)
 	if (IS_ERR(handle))
 		return;
 
-	if (inode->i_size & (sb->s_blocksize - 1))
-		ext4_block_truncate_page(handle, mapping, inode->i_size);
+	if (inode->i_size % PAGE_CACHE_SIZE != 0) {
+		page_len = PAGE_CACHE_SIZE -
+			(inode->i_size & (PAGE_CACHE_SIZE - 1));
+
+		err = ext4_discard_partial_page_buffers(handle,
+			mapping, inode->i_size, page_len, 0);
+
+		if (err)
+			goto out_stop;
+	}
 
 	if (ext4_orphan_add(handle, inode))
 		goto out_stop;
@@ -3760,6 +4300,7 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
 	int ret = 0;
 	int ret2 = 0;
 	int retries = 0;
+	int flags;
 	struct ext4_map_blocks map;
 	unsigned int credits, blkbits = inode->i_blkbits;
 
@@ -3796,6 +4337,16 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
 		trace_ext4_fallocate_exit(inode, offset, max_blocks, ret);
 		return ret;
 	}
+	flags = EXT4_GET_BLOCKS_CREATE_UNINIT_EXT;
+	if (mode & FALLOC_FL_KEEP_SIZE)
+		flags |= EXT4_GET_BLOCKS_KEEP_SIZE;
+	/*
+	 * Don't normalize the request if it can fit in one extent so
+	 * that it doesn't get unnecessarily split into multiple
+	 * extents.
+	 */
+	if (len <= EXT_UNINIT_MAX_LEN << blkbits)
+		flags |= EXT4_GET_BLOCKS_NO_NORMALIZE;
 retry:
 	while (ret >= 0 && ret < max_blocks) {
 		map.m_lblk = map.m_lblk + ret;
@@ -3805,9 +4356,7 @@ retry:
 			ret = PTR_ERR(handle);
 			break;
 		}
-		ret = ext4_map_blocks(handle, inode, &map,
-				      EXT4_GET_BLOCKS_CREATE_UNINIT_EXT |
-				      EXT4_GET_BLOCKS_NO_NORMALIZE);
+		ret = ext4_map_blocks(handle, inode, &map, flags);
 		if (ret <= 0) {
 #ifdef EXT4FS_DEBUG
 			WARN_ON(ret <= 0);
@@ -4102,7 +4651,6 @@ found_delayed_extent:
 		return EXT_BREAK;
 	return EXT_CONTINUE;
 }
-
 /* fiemap flags we can handle specified here */
 #define EXT4_FIEMAP_FLAGS	(FIEMAP_FLAG_SYNC|FIEMAP_FLAG_XATTR)
 
@@ -4162,17 +4710,28 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length)
 	struct address_space *mapping = inode->i_mapping;
 	struct ext4_map_blocks map;
 	handle_t *handle;
-	loff_t first_block_offset, last_block_offset, block_len;
-	loff_t first_page, last_page, first_page_offset, last_page_offset;
+	loff_t first_page, last_page, page_len;
+	loff_t first_page_offset, last_page_offset;
 	int ret, credits, blocks_released, err = 0;
 
+	/* No need to punch hole beyond i_size */
+	if (offset >= inode->i_size)
+		return 0;
+
+	/*
+	 * If the hole extends beyond i_size, set the hole
+	 * to end after the page that contains i_size
+	 */
+	if (offset + length > inode->i_size) {
+		length = inode->i_size +
+		   PAGE_CACHE_SIZE - (inode->i_size & (PAGE_CACHE_SIZE - 1)) -
+		   offset;
+	}
+
 	first_block = (offset + sb->s_blocksize - 1) >>
 		EXT4_BLOCK_SIZE_BITS(sb);
 	last_block = (offset + length) >> EXT4_BLOCK_SIZE_BITS(sb);
 
-	first_block_offset = first_block << EXT4_BLOCK_SIZE_BITS(sb);
-	last_block_offset = last_block << EXT4_BLOCK_SIZE_BITS(sb);
-
 	first_page = (offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 	last_page = (offset + length) >> PAGE_CACHE_SHIFT;
 
@@ -4185,11 +4744,10 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length)
 	 */
 	if (mapping->nrpages && mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {
 		err = filemap_write_and_wait_range(mapping,
-			first_page_offset == 0 ? 0 : first_page_offset-1,
-			last_page_offset);
+			offset, offset + length - 1);
 
-			if (err)
-				return err;
+		if (err)
+			return err;
 	}
 
 	/* Now release the pages */
@@ -4211,24 +4769,64 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length)
 		goto out;
 
 	/*
-	 * Now we need to zero out the un block aligned data.
-	 * If the file is smaller than a block, just
-	 * zero out the middle
+	 * Now we need to zero out the non-page-aligned data in the
+	 * pages at the start and tail of the hole, and unmap the buffer
+	 * heads for the block aligned regions of the page that were
+	 * completely zeroed.
 	 */
-	if (first_block > last_block)
-		ext4_block_zero_page_range(handle, mapping, offset, length);
-	else {
-		/* zero out the head of the hole before the first block */
-		block_len  = first_block_offset - offset;
-		if (block_len > 0)
-			ext4_block_zero_page_range(handle, mapping,
-						   offset, block_len);
-
-		/* zero out the tail of the hole after the last block */
-		block_len = offset + length - last_block_offset;
-		if (block_len > 0) {
-			ext4_block_zero_page_range(handle, mapping,
-					last_block_offset, block_len);
+	if (first_page > last_page) {
+		/*
+		 * If the file space being truncated is contained within a page
+		 * just zero out and unmap the middle of that page
+		 */
+		err = ext4_discard_partial_page_buffers(handle,
+			mapping, offset, length, 0);
+
+		if (err)
+			goto out;
+	} else {
+		/*
+		 * zero out and unmap the partial page that contains
+		 * the start of the hole
+		 */
+		page_len  = first_page_offset - offset;
+		if (page_len > 0) {
+			err = ext4_discard_partial_page_buffers(handle, mapping,
+						   offset, page_len, 0);
+			if (err)
+				goto out;
+		}
+
+		/*
+		 * zero out and unmap the partial page that contains
+		 * the end of the hole
+		 */
+		page_len = offset + length - last_page_offset;
+		if (page_len > 0) {
+			err = ext4_discard_partial_page_buffers(handle, mapping,
+					last_page_offset, page_len, 0);
+			if (err)
+				goto out;
+		}
+	}
+
+
+	/*
+	 * If i_size is contained in the last page, we need to
+	 * unmap and zero the partial page after i_size
+	 */
+	if (inode->i_size >> PAGE_CACHE_SHIFT == last_page &&
+	   inode->i_size % PAGE_CACHE_SIZE != 0) {
+
+		page_len = PAGE_CACHE_SIZE -
+			(inode->i_size & (PAGE_CACHE_SIZE - 1));
+
+		if (page_len > 0) {
+			err = ext4_discard_partial_page_buffers(handle,
+			  mapping, inode->i_size, page_len, 0);
+
+			if (err)
+				goto out;
 		}
 	}
 
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index b9548f4..cb70f18 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -181,8 +181,8 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
 		path.dentry = mnt->mnt_root;
 		cp = d_path(&path, buf, sizeof(buf));
 		if (!IS_ERR(cp)) {
-			memcpy(sbi->s_es->s_last_mounted, cp,
-			       sizeof(sbi->s_es->s_last_mounted));
+			strlcpy(sbi->s_es->s_last_mounted, cp,
+				sizeof(sbi->s_es->s_last_mounted));
 			ext4_mark_super_dirty(sb);
 		}
 	}
diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c
index 036f78f..00a2cb7 100644
--- a/fs/ext4/fsync.c
+++ b/fs/ext4/fsync.c
@@ -75,7 +75,7 @@ static void dump_completed_IO(struct inode * inode)
  * to written.
  * The function return the number of pending IOs on success.
  */
-extern int ext4_flush_completed_IO(struct inode *inode)
+int ext4_flush_completed_IO(struct inode *inode)
 {
 	ext4_io_end_t *io;
 	struct ext4_inode_info *ei = EXT4_I(inode);
@@ -83,14 +83,12 @@ extern int ext4_flush_completed_IO(struct inode *inode)
 	int ret = 0;
 	int ret2 = 0;
 
-	if (list_empty(&ei->i_completed_io_list))
-		return ret;
-
 	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);
+		list_del_init(&io->list);
 		/*
 		 * Calling ext4_end_io_nolock() to convert completed
 		 * IO to written.
@@ -107,11 +105,9 @@ extern int ext4_flush_completed_IO(struct inode *inode)
 		 */
 		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_lock_irqsave(&ei->i_completed_io_lock, flags);
 	}
 	spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
 	return (ret2 < 0) ? ret2 : 0;
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 9c63f27..00beb4f 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -78,7 +78,7 @@ static unsigned ext4_init_inode_bitmap(struct super_block *sb,
 	 * allocation, essentially implementing a per-group read-only flag. */
 	if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
 		ext4_error(sb, "Checksum bad for group %u", block_group);
-		ext4_free_blks_set(sb, gdp, 0);
+		ext4_free_group_clusters_set(sb, gdp, 0);
 		ext4_free_inodes_set(sb, gdp, 0);
 		ext4_itable_unused_set(sb, gdp, 0);
 		memset(bh->b_data, 0xff, sb->s_blocksize);
@@ -293,121 +293,9 @@ error_return:
 	ext4_std_error(sb, fatal);
 }
 
-/*
- * There are two policies for allocating an inode.  If the new inode is
- * a directory, then a forward search is made for a block group with both
- * free space and a low directory-to-inode ratio; if that fails, then of
- * the groups with above-average free space, that group with the fewest
- * directories already is chosen.
- *
- * For other inodes, search forward from the parent directory\'s block
- * group to find a free inode.
- */
-static int find_group_dir(struct super_block *sb, struct inode *parent,
-				ext4_group_t *best_group)
-{
-	ext4_group_t ngroups = ext4_get_groups_count(sb);
-	unsigned int freei, avefreei;
-	struct ext4_group_desc *desc, *best_desc = NULL;
-	ext4_group_t group;
-	int ret = -1;
-
-	freei = percpu_counter_read_positive(&EXT4_SB(sb)->s_freeinodes_counter);
-	avefreei = freei / ngroups;
-
-	for (group = 0; group < ngroups; group++) {
-		desc = ext4_get_group_desc(sb, group, NULL);
-		if (!desc || !ext4_free_inodes_count(sb, desc))
-			continue;
-		if (ext4_free_inodes_count(sb, desc) < avefreei)
-			continue;
-		if (!best_desc ||
-		    (ext4_free_blks_count(sb, desc) >
-		     ext4_free_blks_count(sb, best_desc))) {
-			*best_group = group;
-			best_desc = desc;
-			ret = 0;
-		}
-	}
-	return ret;
-}
-
-#define free_block_ratio 10
-
-static int find_group_flex(struct super_block *sb, struct inode *parent,
-			   ext4_group_t *best_group)
-{
-	struct ext4_sb_info *sbi = EXT4_SB(sb);
-	struct ext4_group_desc *desc;
-	struct flex_groups *flex_group = sbi->s_flex_groups;
-	ext4_group_t parent_group = EXT4_I(parent)->i_block_group;
-	ext4_group_t parent_fbg_group = ext4_flex_group(sbi, parent_group);
-	ext4_group_t ngroups = ext4_get_groups_count(sb);
-	int flex_size = ext4_flex_bg_size(sbi);
-	ext4_group_t best_flex = parent_fbg_group;
-	int blocks_per_flex = sbi->s_blocks_per_group * flex_size;
-	int flexbg_free_blocks;
-	int flex_freeb_ratio;
-	ext4_group_t n_fbg_groups;
-	ext4_group_t i;
-
-	n_fbg_groups = (ngroups + flex_size - 1) >>
-		sbi->s_log_groups_per_flex;
-
-find_close_to_parent:
-	flexbg_free_blocks = atomic_read(&flex_group[best_flex].free_blocks);
-	flex_freeb_ratio = flexbg_free_blocks * 100 / blocks_per_flex;
-	if (atomic_read(&flex_group[best_flex].free_inodes) &&
-	    flex_freeb_ratio > free_block_ratio)
-		goto found_flexbg;
-
-	if (best_flex && best_flex == parent_fbg_group) {
-		best_flex--;
-		goto find_close_to_parent;
-	}
-
-	for (i = 0; i < n_fbg_groups; i++) {
-		if (i == parent_fbg_group || i == parent_fbg_group - 1)
-			continue;
-
-		flexbg_free_blocks = atomic_read(&flex_group[i].free_blocks);
-		flex_freeb_ratio = flexbg_free_blocks * 100 / blocks_per_flex;
-
-		if (flex_freeb_ratio > free_block_ratio &&
-		    (atomic_read(&flex_group[i].free_inodes))) {
-			best_flex = i;
-			goto found_flexbg;
-		}
-
-		if ((atomic_read(&flex_group[best_flex].free_inodes) == 0) ||
-		    ((atomic_read(&flex_group[i].free_blocks) >
-		      atomic_read(&flex_group[best_flex].free_blocks)) &&
-		     atomic_read(&flex_group[i].free_inodes)))
-			best_flex = i;
-	}
-
-	if (!atomic_read(&flex_group[best_flex].free_inodes) ||
-	    !atomic_read(&flex_group[best_flex].free_blocks))
-		return -1;
-
-found_flexbg:
-	for (i = best_flex * flex_size; i < ngroups &&
-		     i < (best_flex + 1) * flex_size; i++) {
-		desc = ext4_get_group_desc(sb, i, NULL);
-		if (ext4_free_inodes_count(sb, desc)) {
-			*best_group = i;
-			goto out;
-		}
-	}
-
-	return -1;
-out:
-	return 0;
-}
-
 struct orlov_stats {
 	__u32 free_inodes;
-	__u32 free_blocks;
+	__u32 free_clusters;
 	__u32 used_dirs;
 };
 
@@ -424,7 +312,7 @@ static void get_orlov_stats(struct super_block *sb, ext4_group_t g,
 
 	if (flex_size > 1) {
 		stats->free_inodes = atomic_read(&flex_group[g].free_inodes);
-		stats->free_blocks = atomic_read(&flex_group[g].free_blocks);
+		stats->free_clusters = atomic_read(&flex_group[g].free_clusters);
 		stats->used_dirs = atomic_read(&flex_group[g].used_dirs);
 		return;
 	}
@@ -432,11 +320,11 @@ static void get_orlov_stats(struct super_block *sb, ext4_group_t g,
 	desc = ext4_get_group_desc(sb, g, NULL);
 	if (desc) {
 		stats->free_inodes = ext4_free_inodes_count(sb, desc);
-		stats->free_blocks = ext4_free_blks_count(sb, desc);
+		stats->free_clusters = ext4_free_group_clusters(sb, desc);
 		stats->used_dirs = ext4_used_dirs_count(sb, desc);
 	} else {
 		stats->free_inodes = 0;
-		stats->free_blocks = 0;
+		stats->free_clusters = 0;
 		stats->used_dirs = 0;
 	}
 }
@@ -471,10 +359,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
 	ext4_group_t real_ngroups = ext4_get_groups_count(sb);
 	int inodes_per_group = EXT4_INODES_PER_GROUP(sb);
 	unsigned int freei, avefreei;
-	ext4_fsblk_t freeb, avefreeb;
+	ext4_fsblk_t freeb, avefreec;
 	unsigned int ndirs;
 	int max_dirs, min_inodes;
-	ext4_grpblk_t min_blocks;
+	ext4_grpblk_t min_clusters;
 	ext4_group_t i, grp, g, ngroups;
 	struct ext4_group_desc *desc;
 	struct orlov_stats stats;
@@ -490,9 +378,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
 
 	freei = percpu_counter_read_positive(&sbi->s_freeinodes_counter);
 	avefreei = freei / ngroups;
-	freeb = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
-	avefreeb = freeb;
-	do_div(avefreeb, ngroups);
+	freeb = EXT4_C2B(sbi,
+		percpu_counter_read_positive(&sbi->s_freeclusters_counter));
+	avefreec = freeb;
+	do_div(avefreec, ngroups);
 	ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter);
 
 	if (S_ISDIR(mode) &&
@@ -518,7 +407,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
 				continue;
 			if (stats.free_inodes < avefreei)
 				continue;
-			if (stats.free_blocks < avefreeb)
+			if (stats.free_clusters < avefreec)
 				continue;
 			grp = g;
 			ret = 0;
@@ -556,7 +445,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
 	min_inodes = avefreei - inodes_per_group*flex_size / 4;
 	if (min_inodes < 1)
 		min_inodes = 1;
-	min_blocks = avefreeb - EXT4_BLOCKS_PER_GROUP(sb)*flex_size / 4;
+	min_clusters = avefreec - EXT4_CLUSTERS_PER_GROUP(sb)*flex_size / 4;
 
 	/*
 	 * Start looking in the flex group where we last allocated an
@@ -575,7 +464,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
 			continue;
 		if (stats.free_inodes < min_inodes)
 			continue;
-		if (stats.free_blocks < min_blocks)
+		if (stats.free_clusters < min_clusters)
 			continue;
 		goto found_flex_bg;
 	}
@@ -659,7 +548,7 @@ static int find_group_other(struct super_block *sb, struct inode *parent,
 	*group = parent_group;
 	desc = ext4_get_group_desc(sb, *group, NULL);
 	if (desc && ext4_free_inodes_count(sb, desc) &&
-			ext4_free_blks_count(sb, desc))
+	    ext4_free_group_clusters(sb, desc))
 		return 0;
 
 	/*
@@ -683,7 +572,7 @@ static int find_group_other(struct super_block *sb, struct inode *parent,
 			*group -= ngroups;
 		desc = ext4_get_group_desc(sb, *group, NULL);
 		if (desc && ext4_free_inodes_count(sb, desc) &&
-				ext4_free_blks_count(sb, desc))
+		    ext4_free_group_clusters(sb, desc))
 			return 0;
 	}
 
@@ -802,7 +691,7 @@ err_ret:
  * group to find a free inode.
  */
 struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode,
-			     const struct qstr *qstr, __u32 goal)
+			     const struct qstr *qstr, __u32 goal, uid_t *owner)
 {
 	struct super_block *sb;
 	struct buffer_head *inode_bitmap_bh = NULL;
@@ -816,8 +705,6 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode,
 	int ret2, err = 0;
 	struct inode *ret;
 	ext4_group_t i;
-	int free = 0;
-	static int once = 1;
 	ext4_group_t flex_group;
 
 	/* Cannot create files in a deleted directory */
@@ -843,26 +730,9 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode,
 		goto got_group;
 	}
 
-	if (sbi->s_log_groups_per_flex && test_opt(sb, OLDALLOC)) {
-		ret2 = find_group_flex(sb, dir, &group);
-		if (ret2 == -1) {
-			ret2 = find_group_other(sb, dir, &group, mode);
-			if (ret2 == 0 && once) {
-				once = 0;
-				printk(KERN_NOTICE "ext4: find_group_flex "
-				       "failed, fallback succeeded dir %lu\n",
-				       dir->i_ino);
-			}
-		}
-		goto got_group;
-	}
-
-	if (S_ISDIR(mode)) {
-		if (test_opt(sb, OLDALLOC))
-			ret2 = find_group_dir(sb, dir, &group);
-		else
-			ret2 = find_group_orlov(sb, dir, &group, mode, qstr);
-	} else
+	if (S_ISDIR(mode))
+		ret2 = find_group_orlov(sb, dir, &group, mode, qstr);
+	else
 		ret2 = find_group_other(sb, dir, &group, mode);
 
 got_group:
@@ -950,26 +820,21 @@ got:
 			goto fail;
 		}
 
-		free = 0;
-		ext4_lock_group(sb, group);
+		BUFFER_TRACE(block_bitmap_bh, "dirty block bitmap");
+		err = ext4_handle_dirty_metadata(handle, NULL, block_bitmap_bh);
+		brelse(block_bitmap_bh);
+
 		/* recheck and clear flag under lock if we still need to */
+		ext4_lock_group(sb, group);
 		if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
-			free = ext4_free_blocks_after_init(sb, group, gdp);
 			gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
-			ext4_free_blks_set(sb, gdp, free);
+			ext4_free_group_clusters_set(sb, gdp,
+				ext4_free_clusters_after_init(sb, group, gdp));
 			gdp->bg_checksum = ext4_group_desc_csum(sbi, group,
 								gdp);
 		}
 		ext4_unlock_group(sb, group);
 
-		/* Don't need to dirty bitmap block if we didn't change it */
-		if (free) {
-			BUFFER_TRACE(block_bitmap_bh, "dirty block bitmap");
-			err = ext4_handle_dirty_metadata(handle,
-							NULL, block_bitmap_bh);
-		}
-
-		brelse(block_bitmap_bh);
 		if (err)
 			goto fail;
 	}
@@ -987,8 +852,11 @@ got:
 		flex_group = ext4_flex_group(sbi, group);
 		atomic_dec(&sbi->s_flex_groups[flex_group].free_inodes);
 	}
-
-	if (test_opt(sb, GRPID)) {
+	if (owner) {
+		inode->i_mode = mode;
+		inode->i_uid = owner[0];
+		inode->i_gid = owner[1];
+	} else if (test_opt(sb, GRPID)) {
 		inode->i_mode = mode;
 		inode->i_uid = current_fsuid();
 		inode->i_gid = dir->i_gid;
@@ -1005,11 +873,7 @@ got:
 	ei->i_dir_start_lookup = 0;
 	ei->i_disksize = 0;
 
-	/*
-	 * Don't inherit extent flag from directory, amongst others. We set
-	 * extent flag on newly created directory and file only if -o extent
-	 * mount option is specified
-	 */
+	/* Don't inherit extent flag from directory, amongst others. */
 	ei->i_flags =
 		ext4_mask_flags(mode, EXT4_I(dir)->i_flags & EXT4_FL_INHERITED);
 	ei->i_file_acl = 0;
@@ -1084,7 +948,7 @@ fail_free_drop:
 fail_drop:
 	dquot_drop(inode);
 	inode->i_flags |= S_NOQUOTA;
-	inode->i_nlink = 0;
+	clear_nlink(inode);
 	unlock_new_inode(inode);
 	iput(inode);
 	brelse(inode_bitmap_bh);
@@ -1235,7 +1099,7 @@ unsigned long ext4_count_dirs(struct super_block * sb)
  * inode allocation from the current group, so we take alloc_sem lock, to
  * block ext4_claim_inode until we are finished.
  */
-extern int ext4_init_inode_table(struct super_block *sb, ext4_group_t group,
+int ext4_init_inode_table(struct super_block *sb, ext4_group_t group,
 				 int barrier)
 {
 	struct ext4_group_info *grp = ext4_get_group_info(sb, group);
diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
index 0962642..3cfc73f 100644
--- a/fs/ext4/indirect.c
+++ b/fs/ext4/indirect.c
@@ -699,6 +699,13 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
 	/*
 	 * Okay, we need to do block allocation.
 	*/
+	if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
+				       EXT4_FEATURE_RO_COMPAT_BIGALLOC)) {
+		EXT4_ERROR_INODE(inode, "Can't allocate blocks for "
+				 "non-extent mapped inodes with bigalloc");
+		return -ENOSPC;
+	}
+
 	goal = ext4_find_goal(inode, map->m_lblk, partial);
 
 	/* the number of blocks need to allocate for [d,t]indirect blocks */
@@ -1343,7 +1350,9 @@ void ext4_ind_truncate(struct inode *inode)
 	__le32 nr = 0;
 	int n = 0;
 	ext4_lblk_t last_block, max_block;
+	loff_t page_len;
 	unsigned blocksize = inode->i_sb->s_blocksize;
+	int err;
 
 	handle = start_transaction(inode);
 	if (IS_ERR(handle))
@@ -1354,9 +1363,16 @@ void ext4_ind_truncate(struct inode *inode)
 	max_block = (EXT4_SB(inode->i_sb)->s_bitmap_maxbytes + blocksize-1)
 					>> EXT4_BLOCK_SIZE_BITS(inode->i_sb);
 
-	if (inode->i_size & (blocksize - 1))
-		if (ext4_block_truncate_page(handle, mapping, inode->i_size))
+	if (inode->i_size % PAGE_CACHE_SIZE != 0) {
+		page_len = PAGE_CACHE_SIZE -
+			(inode->i_size & (PAGE_CACHE_SIZE - 1));
+
+		err = ext4_discard_partial_page_buffers(handle,
+			mapping, inode->i_size, page_len, 0);
+
+		if (err)
 			goto out_stop;
+	}
 
 	if (last_block != max_block) {
 		n = ext4_block_to_path(inode, last_block, offsets, NULL);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 0defe0b..cc5a6da 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -42,7 +42,6 @@
 #include "ext4_jbd2.h"
 #include "xattr.h"
 #include "acl.h"
-#include "ext4_extents.h"
 #include "truncate.h"
 
 #include <trace/events/ext4.h>
@@ -268,7 +267,7 @@ void ext4_da_update_reserve_space(struct inode *inode,
 	struct ext4_inode_info *ei = EXT4_I(inode);
 
 	spin_lock(&ei->i_block_reservation_lock);
-	trace_ext4_da_update_reserve_space(inode, used);
+	trace_ext4_da_update_reserve_space(inode, used, quota_claim);
 	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",
@@ -281,7 +280,7 @@ void ext4_da_update_reserve_space(struct inode *inode,
 	/* Update per-inode reservations */
 	ei->i_reserved_data_blocks -= used;
 	ei->i_reserved_meta_blocks -= ei->i_allocated_meta_blocks;
-	percpu_counter_sub(&sbi->s_dirtyblocks_counter,
+	percpu_counter_sub(&sbi->s_dirtyclusters_counter,
 			   used + ei->i_allocated_meta_blocks);
 	ei->i_allocated_meta_blocks = 0;
 
@@ -291,7 +290,7 @@ void ext4_da_update_reserve_space(struct inode *inode,
 		 * only when we have written all of the delayed
 		 * allocation blocks.
 		 */
-		percpu_counter_sub(&sbi->s_dirtyblocks_counter,
+		percpu_counter_sub(&sbi->s_dirtyclusters_counter,
 				   ei->i_reserved_meta_blocks);
 		ei->i_reserved_meta_blocks = 0;
 		ei->i_da_metadata_calc_len = 0;
@@ -300,14 +299,14 @@ void ext4_da_update_reserve_space(struct inode *inode,
 
 	/* Update quota subsystem for data blocks */
 	if (quota_claim)
-		dquot_claim_block(inode, used);
+		dquot_claim_block(inode, EXT4_C2B(sbi, used));
 	else {
 		/*
 		 * We did fallocate with an offset that is already delayed
 		 * allocated. So on delayed allocated writeback we should
 		 * not re-claim the quota for fallocated blocks.
 		 */
-		dquot_release_reservation_block(inode, used);
+		dquot_release_reservation_block(inode, EXT4_C2B(sbi, used));
 	}
 
 	/*
@@ -399,6 +398,49 @@ static pgoff_t ext4_num_dirty_pages(struct inode *inode, pgoff_t idx,
 }
 
 /*
+ * Sets the BH_Da_Mapped bit on the buffer heads corresponding to the given map.
+ */
+static void set_buffers_da_mapped(struct inode *inode,
+				   struct ext4_map_blocks *map)
+{
+	struct address_space *mapping = inode->i_mapping;
+	struct pagevec pvec;
+	int i, nr_pages;
+	pgoff_t index, end;
+
+	index = map->m_lblk >> (PAGE_CACHE_SHIFT - inode->i_blkbits);
+	end = (map->m_lblk + map->m_len - 1) >>
+		(PAGE_CACHE_SHIFT - inode->i_blkbits);
+
+	pagevec_init(&pvec, 0);
+	while (index <= end) {
+		nr_pages = pagevec_lookup(&pvec, mapping, index,
+					  min(end - index + 1,
+					      (pgoff_t)PAGEVEC_SIZE));
+		if (nr_pages == 0)
+			break;
+		for (i = 0; i < nr_pages; i++) {
+			struct page *page = pvec.pages[i];
+			struct buffer_head *bh, *head;
+
+			if (unlikely(page->mapping != mapping) ||
+			    !PageDirty(page))
+				break;
+
+			if (page_has_buffers(page)) {
+				bh = head = page_buffers(page);
+				do {
+					set_buffer_da_mapped(bh);
+					bh = bh->b_this_page;
+				} while (bh != head);
+			}
+			index++;
+		}
+		pagevec_release(&pvec);
+	}
+}
+
+/*
  * The ext4_map_blocks() function tries to look up the requested blocks,
  * and returns if the blocks are already mapped.
  *
@@ -416,7 +458,7 @@ static pgoff_t ext4_num_dirty_pages(struct inode *inode, pgoff_t idx,
  * the buffer head is mapped.
  *
  * It returns 0 if plain look up failed (blocks have not been allocated), in
- * that casem, buffer head is unmapped
+ * that case, buffer head is unmapped
  *
  * It returns the error in case of allocation failure.
  */
@@ -435,9 +477,11 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
 	 */
 	down_read((&EXT4_I(inode)->i_data_sem));
 	if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) {
-		retval = ext4_ext_map_blocks(handle, inode, map, 0);
+		retval = ext4_ext_map_blocks(handle, inode, map, flags &
+					     EXT4_GET_BLOCKS_KEEP_SIZE);
 	} else {
-		retval = ext4_ind_map_blocks(handle, inode, map, 0);
+		retval = ext4_ind_map_blocks(handle, inode, map, flags &
+					     EXT4_GET_BLOCKS_KEEP_SIZE);
 	}
 	up_read((&EXT4_I(inode)->i_data_sem));
 
@@ -455,7 +499,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
 	 * Returns if the blocks have already allocated
 	 *
 	 * Note that if blocks have been preallocated
-	 * ext4_ext_get_block() returns th create = 0
+	 * ext4_ext_get_block() returns the create = 0
 	 * with buffer head unmapped.
 	 */
 	if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED)
@@ -517,9 +561,17 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
 			(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE))
 			ext4_da_update_reserve_space(inode, retval, 1);
 	}
-	if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
+	if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) {
 		ext4_clear_inode_state(inode, EXT4_STATE_DELALLOC_RESERVED);
 
+		/* If we have successfully mapped the delayed allocated blocks,
+		 * set the BH_Da_Mapped bit on them. Its important to do this
+		 * under the protection of i_data_sem.
+		 */
+		if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED)
+			set_buffers_da_mapped(inode, map);
+	}
+
 	up_write((&EXT4_I(inode)->i_data_sem));
 	if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) {
 		int ret = check_block_validity(inode, map);
@@ -909,7 +961,11 @@ static int ext4_ordered_write_end(struct file *file,
 			ext4_orphan_add(handle, inode);
 		if (ret2 < 0)
 			ret = ret2;
+	} else {
+		unlock_page(page);
+		page_cache_release(page);
 	}
+
 	ret2 = ext4_journal_stop(handle);
 	if (!ret)
 		ret = ret2;
@@ -1037,14 +1093,14 @@ static int ext4_journalled_write_end(struct file *file,
 }
 
 /*
- * Reserve a single block located at lblock
+ * Reserve a single cluster located at lblock
  */
 static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock)
 {
 	int retries = 0;
 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
 	struct ext4_inode_info *ei = EXT4_I(inode);
-	unsigned long md_needed;
+	unsigned int md_needed;
 	int ret;
 
 	/*
@@ -1054,7 +1110,8 @@ static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock)
 	 */
 repeat:
 	spin_lock(&ei->i_block_reservation_lock);
-	md_needed = ext4_calc_metadata_amount(inode, lblock);
+	md_needed = EXT4_NUM_B2C(sbi,
+				 ext4_calc_metadata_amount(inode, lblock));
 	trace_ext4_da_reserve_space(inode, md_needed);
 	spin_unlock(&ei->i_block_reservation_lock);
 
@@ -1063,15 +1120,15 @@ repeat:
 	 * us from metadata over-estimation, though we may go over by
 	 * a small amount in the end.  Here we just reserve for data.
 	 */
-	ret = dquot_reserve_block(inode, 1);
+	ret = dquot_reserve_block(inode, EXT4_C2B(sbi, 1));
 	if (ret)
 		return ret;
 	/*
 	 * We do still charge estimated metadata to the sb though;
 	 * we cannot afford to run out of free blocks.
 	 */
-	if (ext4_claim_free_blocks(sbi, md_needed + 1, 0)) {
-		dquot_release_reservation_block(inode, 1);
+	if (ext4_claim_free_clusters(sbi, md_needed + 1, 0)) {
+		dquot_release_reservation_block(inode, EXT4_C2B(sbi, 1));
 		if (ext4_should_retry_alloc(inode->i_sb, &retries)) {
 			yield();
 			goto repeat;
@@ -1118,19 +1175,21 @@ static void ext4_da_release_space(struct inode *inode, int to_free)
 		 * We can release all of the reserved metadata blocks
 		 * only when we have written all of the delayed
 		 * allocation blocks.
+		 * Note that in case of bigalloc, i_reserved_meta_blocks,
+		 * i_reserved_data_blocks, etc. refer to number of clusters.
 		 */
-		percpu_counter_sub(&sbi->s_dirtyblocks_counter,
+		percpu_counter_sub(&sbi->s_dirtyclusters_counter,
 				   ei->i_reserved_meta_blocks);
 		ei->i_reserved_meta_blocks = 0;
 		ei->i_da_metadata_calc_len = 0;
 	}
 
 	/* update fs dirty data blocks counter */
-	percpu_counter_sub(&sbi->s_dirtyblocks_counter, to_free);
+	percpu_counter_sub(&sbi->s_dirtyclusters_counter, to_free);
 
 	spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
 
-	dquot_release_reservation_block(inode, to_free);
+	dquot_release_reservation_block(inode, EXT4_C2B(sbi, to_free));
 }
 
 static void ext4_da_page_release_reservation(struct page *page,
@@ -1139,6 +1198,9 @@ static void ext4_da_page_release_reservation(struct page *page,
 	int to_release = 0;
 	struct buffer_head *head, *bh;
 	unsigned int curr_off = 0;
+	struct inode *inode = page->mapping->host;
+	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+	int num_clusters;
 
 	head = page_buffers(page);
 	bh = head;
@@ -1148,10 +1210,24 @@ static void ext4_da_page_release_reservation(struct page *page,
 		if ((offset <= curr_off) && (buffer_delay(bh))) {
 			to_release++;
 			clear_buffer_delay(bh);
+			clear_buffer_da_mapped(bh);
 		}
 		curr_off = next_off;
 	} while ((bh = bh->b_this_page) != head);
-	ext4_da_release_space(page->mapping->host, to_release);
+
+	/* If we have released all the blocks belonging to a cluster, then we
+	 * need to release the reserved space for that cluster. */
+	num_clusters = EXT4_NUM_B2C(sbi, to_release);
+	while (num_clusters > 0) {
+		ext4_fsblk_t lblk;
+		lblk = (page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits)) +
+			((num_clusters - 1) << sbi->s_cluster_bits);
+		if (sbi->s_cluster_ratio == 1 ||
+		    !ext4_find_delalloc_cluster(inode, lblk, 1))
+			ext4_da_release_space(inode, 1);
+
+		num_clusters--;
+	}
 }
 
 /*
@@ -1253,6 +1329,8 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd,
 						clear_buffer_delay(bh);
 						bh->b_blocknr = pblock;
 					}
+					if (buffer_da_mapped(bh))
+						clear_buffer_da_mapped(bh);
 					if (buffer_unwritten(bh) ||
 					    buffer_mapped(bh))
 						BUG_ON(bh->b_blocknr != pblock);
@@ -1346,12 +1424,15 @@ static void ext4_print_free_blocks(struct inode *inode)
 {
 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
 	printk(KERN_CRIT "Total free blocks count %lld\n",
-	       ext4_count_free_blocks(inode->i_sb));
+	       EXT4_C2B(EXT4_SB(inode->i_sb),
+			ext4_count_free_clusters(inode->i_sb)));
 	printk(KERN_CRIT "Free/Dirty block details\n");
 	printk(KERN_CRIT "free_blocks=%lld\n",
-	       (long long) percpu_counter_sum(&sbi->s_freeblocks_counter));
+	       (long long) EXT4_C2B(EXT4_SB(inode->i_sb),
+		percpu_counter_sum(&sbi->s_freeclusters_counter)));
 	printk(KERN_CRIT "dirty_blocks=%lld\n",
-	       (long long) percpu_counter_sum(&sbi->s_dirtyblocks_counter));
+	       (long long) EXT4_C2B(EXT4_SB(inode->i_sb),
+		percpu_counter_sum(&sbi->s_dirtyclusters_counter)));
 	printk(KERN_CRIT "Block reservation details\n");
 	printk(KERN_CRIT "i_reserved_data_blocks=%u\n",
 	       EXT4_I(inode)->i_reserved_data_blocks);
@@ -1430,8 +1511,7 @@ static void mpage_da_map_and_submit(struct mpage_da_data *mpd)
 		if (err == -EAGAIN)
 			goto submit_io;
 
-		if (err == -ENOSPC &&
-		    ext4_count_free_blocks(sb)) {
+		if (err == -ENOSPC && ext4_count_free_clusters(sb)) {
 			mpd->retval = err;
 			goto submit_io;
 		}
@@ -1471,13 +1551,15 @@ static void mpage_da_map_and_submit(struct mpage_da_data *mpd)
 
 		for (i = 0; i < map.m_len; i++)
 			unmap_underlying_metadata(bdev, map.m_pblk + i);
-	}
 
-	if (ext4_should_order_data(mpd->inode)) {
-		err = ext4_jbd2_file_inode(handle, mpd->inode);
-		if (err)
-			/* This only happens if the journal is aborted */
-			return;
+		if (ext4_should_order_data(mpd->inode)) {
+			err = ext4_jbd2_file_inode(handle, mpd->inode);
+			if (err) {
+				/* Only if the journal is aborted */
+				mpd->retval = err;
+				goto submit_io;
+			}
+		}
 	}
 
 	/*
@@ -1584,6 +1666,66 @@ static int ext4_bh_delay_or_unwritten(handle_t *handle, struct buffer_head *bh)
 }
 
 /*
+ * This function is grabs code from the very beginning of
+ * ext4_map_blocks, but assumes that the caller is from delayed write
+ * time. This function looks up the requested blocks and sets the
+ * buffer delay bit under the protection of i_data_sem.
+ */
+static int ext4_da_map_blocks(struct inode *inode, sector_t iblock,
+			      struct ext4_map_blocks *map,
+			      struct buffer_head *bh)
+{
+	int retval;
+	sector_t invalid_block = ~((sector_t) 0xffff);
+
+	if (invalid_block < ext4_blocks_count(EXT4_SB(inode->i_sb)->s_es))
+		invalid_block = ~0;
+
+	map->m_flags = 0;
+	ext_debug("ext4_da_map_blocks(): inode %lu, max_blocks %u,"
+		  "logical block %lu\n", inode->i_ino, map->m_len,
+		  (unsigned long) map->m_lblk);
+	/*
+	 * Try to see if we can get the block without requesting a new
+	 * file system block.
+	 */
+	down_read((&EXT4_I(inode)->i_data_sem));
+	if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
+		retval = ext4_ext_map_blocks(NULL, inode, map, 0);
+	else
+		retval = ext4_ind_map_blocks(NULL, inode, map, 0);
+
+	if (retval == 0) {
+		/*
+		 * XXX: __block_prepare_write() unmaps passed block,
+		 * is it OK?
+		 */
+		/* If the block was allocated from previously allocated cluster,
+		 * then we dont need to reserve it again. */
+		if (!(map->m_flags & EXT4_MAP_FROM_CLUSTER)) {
+			retval = ext4_da_reserve_space(inode, iblock);
+			if (retval)
+				/* not enough space to reserve */
+				goto out_unlock;
+		}
+
+		/* Clear EXT4_MAP_FROM_CLUSTER flag since its purpose is served
+		 * and it should not appear on the bh->b_state.
+		 */
+		map->m_flags &= ~EXT4_MAP_FROM_CLUSTER;
+
+		map_bh(bh, inode->i_sb, invalid_block);
+		set_buffer_new(bh);
+		set_buffer_delay(bh);
+	}
+
+out_unlock:
+	up_read((&EXT4_I(inode)->i_data_sem));
+
+	return retval;
+}
+
+/*
  * This is a special get_blocks_t callback which is used by
  * ext4_da_write_begin().  It will either return mapped block or
  * reserve space for a single block.
@@ -1600,10 +1742,6 @@ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock,
 {
 	struct ext4_map_blocks map;
 	int ret = 0;
-	sector_t invalid_block = ~((sector_t) 0xffff);
-
-	if (invalid_block < ext4_blocks_count(EXT4_SB(inode->i_sb)->s_es))
-		invalid_block = ~0;
 
 	BUG_ON(create == 0);
 	BUG_ON(bh->b_size != inode->i_sb->s_blocksize);
@@ -1616,25 +1754,9 @@ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock,
 	 * preallocated blocks are unmapped but should treated
 	 * the same as allocated blocks.
 	 */
-	ret = ext4_map_blocks(NULL, inode, &map, 0);
-	if (ret < 0)
+	ret = ext4_da_map_blocks(inode, iblock, &map, bh);
+	if (ret <= 0)
 		return ret;
-	if (ret == 0) {
-		if (buffer_delay(bh))
-			return 0; /* Not sure this could or should happen */
-		/*
-		 * XXX: __block_write_begin() unmaps passed block, is it OK?
-		 */
-		ret = ext4_da_reserve_space(inode, iblock);
-		if (ret)
-			/* not enough space to reserve */
-			return ret;
-
-		map_bh(bh, inode->i_sb, invalid_block);
-		set_buffer_new(bh);
-		set_buffer_delay(bh);
-		return 0;
-	}
 
 	map_bh(bh, inode->i_sb, map.m_pblk);
 	bh->b_state = (bh->b_state & ~EXT4_MAP_FLAGS) | map.m_flags;
@@ -2050,6 +2172,7 @@ static int ext4_da_writepages(struct address_space *mapping,
 	struct ext4_sb_info *sbi = EXT4_SB(mapping->host->i_sb);
 	pgoff_t done_index = 0;
 	pgoff_t end;
+	struct blk_plug plug;
 
 	trace_ext4_da_writepages(inode, wbc);
 
@@ -2128,6 +2251,7 @@ retry:
 	if (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages)
 		tag_pages_for_writeback(mapping, index, end);
 
+	blk_start_plug(&plug);
 	while (!ret && wbc->nr_to_write > 0) {
 
 		/*
@@ -2178,11 +2302,12 @@ retry:
 			ret = 0;
 		} else if (ret == MPAGE_DA_EXTENT_TAIL) {
 			/*
-			 * got one extent now try with
-			 * rest of the pages
+			 * Got one extent now try with rest of the pages.
+			 * If mpd.retval is set -EIO, journal is aborted.
+			 * So we don't need to write any more.
 			 */
 			pages_written += mpd.pages_written;
-			ret = 0;
+			ret = mpd.retval;
 			io_done = 1;
 		} else if (wbc->nr_to_write)
 			/*
@@ -2192,6 +2317,7 @@ retry:
 			 */
 			break;
 	}
+	blk_finish_plug(&plug);
 	if (!io_done && !cycled) {
 		cycled = 1;
 		index = 0;
@@ -2230,10 +2356,11 @@ static int ext4_nonda_switch(struct super_block *sb)
 	 * Delalloc need an accurate free block accounting. So switch
 	 * to non delalloc when we are near to error range.
 	 */
-	free_blocks  = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
-	dirty_blocks = percpu_counter_read_positive(&sbi->s_dirtyblocks_counter);
+	free_blocks  = EXT4_C2B(sbi,
+		percpu_counter_read_positive(&sbi->s_freeclusters_counter));
+	dirty_blocks = percpu_counter_read_positive(&sbi->s_dirtyclusters_counter);
 	if (2 * free_blocks < 3 * dirty_blocks ||
-		free_blocks < (dirty_blocks + EXT4_FREEBLOCKS_WATERMARK)) {
+		free_blocks < (dirty_blocks + EXT4_FREECLUSTERS_WATERMARK)) {
 		/*
 		 * free block count is less than 150% of dirty blocks
 		 * or free blocks is less than watermark
@@ -2259,6 +2386,7 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
 	pgoff_t index;
 	struct inode *inode = mapping->host;
 	handle_t *handle;
+	loff_t page_len;
 
 	index = pos >> PAGE_CACHE_SHIFT;
 
@@ -2305,6 +2433,13 @@ retry:
 		 */
 		if (pos + len > inode->i_size)
 			ext4_truncate_failed_write(inode);
+	} else {
+		page_len = pos & (PAGE_CACHE_SIZE - 1);
+		if (page_len > 0) {
+			ret = ext4_discard_partial_page_buffers_no_lock(handle,
+				inode, page, pos - page_len, page_len,
+				EXT4_DISCARD_PARTIAL_PG_ZERO_UNMAPPED);
+		}
 	}
 
 	if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
@@ -2347,6 +2482,7 @@ static int ext4_da_write_end(struct file *file,
 	loff_t new_i_size;
 	unsigned long start, end;
 	int write_mode = (int)(unsigned long)fsdata;
+	loff_t page_len;
 
 	if (write_mode == FALL_BACK_TO_NONDELALLOC) {
 		if (ext4_should_order_data(inode)) {
@@ -2395,6 +2531,16 @@ static int ext4_da_write_end(struct file *file,
 	}
 	ret2 = generic_write_end(file, mapping, pos, len, copied,
 							page, fsdata);
+
+	page_len = PAGE_CACHE_SIZE -
+			((pos + copied - 1) & (PAGE_CACHE_SIZE - 1));
+
+	if (page_len > 0) {
+		ret = ext4_discard_partial_page_buffers_no_lock(handle,
+			inode, page, pos + copied - 1, page_len,
+			EXT4_DISCARD_PARTIAL_PG_ZERO_UNMAPPED);
+	}
+
 	copied = ret2;
 	if (ret2 < 0)
 		ret = ret2;
@@ -2689,10 +2835,7 @@ static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate)
 	 * but being more careful is always safe for the future change.
 	 */
 	inode = io_end->inode;
-	if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) {
-		io_end->flag |= EXT4_IO_END_UNWRITTEN;
-		atomic_inc(&EXT4_I(inode)->i_aiodio_unwritten);
-	}
+	ext4_set_io_unwritten_flag(inode, io_end);
 
 	/* Add the io_end to per-inode completed io list*/
 	spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags);
@@ -2858,6 +3001,12 @@ static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb,
 	struct inode *inode = file->f_mapping->host;
 	ssize_t ret;
 
+	/*
+	 * If we are doing data journalling we don't support O_DIRECT
+	 */
+	if (ext4_should_journal_data(inode))
+		return 0;
+
 	trace_ext4_direct_IO_enter(inode, offset, iov_length(iov, nr_segs), rw);
 	if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
 		ret = ext4_ext_direct_IO(rw, iocb, iov, offset, nr_segs);
@@ -2927,6 +3076,7 @@ static const struct address_space_operations ext4_journalled_aops = {
 	.bmap			= ext4_bmap,
 	.invalidatepage		= ext4_invalidatepage,
 	.releasepage		= ext4_releasepage,
+	.direct_IO		= ext4_direct_IO,
 	.is_partially_uptodate  = block_is_partially_uptodate,
 	.error_remove_page	= generic_error_remove_page,
 };
@@ -2963,6 +3113,227 @@ void ext4_set_aops(struct inode *inode)
 		inode->i_mapping->a_ops = &ext4_journalled_aops;
 }
 
+
+/*
+ * ext4_discard_partial_page_buffers()
+ * Wrapper function for ext4_discard_partial_page_buffers_no_lock.
+ * This function finds and locks the page containing the offset
+ * "from" and passes it to ext4_discard_partial_page_buffers_no_lock.
+ * Calling functions that already have the page locked should call
+ * ext4_discard_partial_page_buffers_no_lock directly.
+ */
+int ext4_discard_partial_page_buffers(handle_t *handle,
+		struct address_space *mapping, loff_t from,
+		loff_t length, int flags)
+{
+	struct inode *inode = mapping->host;
+	struct page *page;
+	int err = 0;
+
+	page = find_or_create_page(mapping, from >> PAGE_CACHE_SHIFT,
+				   mapping_gfp_mask(mapping) & ~__GFP_FS);
+	if (!page)
+		return -ENOMEM;
+
+	err = ext4_discard_partial_page_buffers_no_lock(handle, inode, page,
+		from, length, flags);
+
+	unlock_page(page);
+	page_cache_release(page);
+	return err;
+}
+
+/*
+ * ext4_discard_partial_page_buffers_no_lock()
+ * Zeros a page range of length 'length' starting from offset 'from'.
+ * Buffer heads that correspond to the block aligned regions of the
+ * zeroed range will be unmapped.  Unblock aligned regions
+ * will have the corresponding buffer head mapped if needed so that
+ * that region of the page can be updated with the partial zero out.
+ *
+ * This function assumes that the page has already been  locked.  The
+ * The range to be discarded must be contained with in the given page.
+ * If the specified range exceeds the end of the page it will be shortened
+ * to the end of the page that corresponds to 'from'.  This function is
+ * appropriate for updating a page and it buffer heads to be unmapped and
+ * zeroed for blocks that have been either released, or are going to be
+ * released.
+ *
+ * handle: The journal handle
+ * inode:  The files inode
+ * page:   A locked page that contains the offset "from"
+ * from:   The starting byte offset (from the begining of the file)
+ *         to begin discarding
+ * len:    The length of bytes to discard
+ * flags:  Optional flags that may be used:
+ *
+ *         EXT4_DISCARD_PARTIAL_PG_ZERO_UNMAPPED
+ *         Only zero the regions of the page whose buffer heads
+ *         have already been unmapped.  This flag is appropriate
+ *         for updateing the contents of a page whose blocks may
+ *         have already been released, and we only want to zero
+ *         out the regions that correspond to those released blocks.
+ *
+ * Returns zero on sucess or negative on failure.
+ */
+int ext4_discard_partial_page_buffers_no_lock(handle_t *handle,
+		struct inode *inode, struct page *page, loff_t from,
+		loff_t length, int flags)
+{
+	ext4_fsblk_t index = from >> PAGE_CACHE_SHIFT;
+	unsigned int offset = from & (PAGE_CACHE_SIZE-1);
+	unsigned int blocksize, max, pos;
+	ext4_lblk_t iblock;
+	struct buffer_head *bh;
+	int err = 0;
+
+	blocksize = inode->i_sb->s_blocksize;
+	max = PAGE_CACHE_SIZE - offset;
+
+	if (index != page->index)
+		return -EINVAL;
+
+	/*
+	 * correct length if it does not fall between
+	 * 'from' and the end of the page
+	 */
+	if (length > max || length < 0)
+		length = max;
+
+	iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
+
+	if (!page_has_buffers(page)) {
+		/*
+		 * If the range to be discarded covers a partial block
+		 * we need to get the page buffers.  This is because
+		 * partial blocks cannot be released and the page needs
+		 * to be updated with the contents of the block before
+		 * we write the zeros on top of it.
+		 */
+		if ((from & (blocksize - 1)) ||
+		    ((from + length) & (blocksize - 1))) {
+			create_empty_buffers(page, blocksize, 0);
+		} else {
+			/*
+			 * If there are no partial blocks,
+			 * there is nothing to update,
+			 * so we can return now
+			 */
+			return 0;
+		}
+	}
+
+	/* Find the buffer that contains "offset" */
+	bh = page_buffers(page);
+	pos = blocksize;
+	while (offset >= pos) {
+		bh = bh->b_this_page;
+		iblock++;
+		pos += blocksize;
+	}
+
+	pos = offset;
+	while (pos < offset + length) {
+		unsigned int end_of_block, range_to_discard;
+
+		err = 0;
+
+		/* The length of space left to zero and unmap */
+		range_to_discard = offset + length - pos;
+
+		/* The length of space until the end of the block */
+		end_of_block = blocksize - (pos & (blocksize-1));
+
+		/*
+		 * Do not unmap or zero past end of block
+		 * for this buffer head
+		 */
+		if (range_to_discard > end_of_block)
+			range_to_discard = end_of_block;
+
+
+		/*
+		 * Skip this buffer head if we are only zeroing unampped
+		 * regions of the page
+		 */
+		if (flags & EXT4_DISCARD_PARTIAL_PG_ZERO_UNMAPPED &&
+			buffer_mapped(bh))
+				goto next;
+
+		/* If the range is block aligned, unmap */
+		if (range_to_discard == blocksize) {
+			clear_buffer_dirty(bh);
+			bh->b_bdev = NULL;
+			clear_buffer_mapped(bh);
+			clear_buffer_req(bh);
+			clear_buffer_new(bh);
+			clear_buffer_delay(bh);
+			clear_buffer_unwritten(bh);
+			clear_buffer_uptodate(bh);
+			zero_user(page, pos, range_to_discard);
+			BUFFER_TRACE(bh, "Buffer discarded");
+			goto next;
+		}
+
+		/*
+		 * If this block is not completely contained in the range
+		 * to be discarded, then it is not going to be released. Because
+		 * we need to keep this block, we need to make sure this part
+		 * of the page is uptodate before we modify it by writeing
+		 * partial zeros on it.
+		 */
+		if (!buffer_mapped(bh)) {
+			/*
+			 * Buffer head must be mapped before we can read
+			 * from the block
+			 */
+			BUFFER_TRACE(bh, "unmapped");
+			ext4_get_block(inode, iblock, bh, 0);
+			/* unmapped? It's a hole - nothing to do */
+			if (!buffer_mapped(bh)) {
+				BUFFER_TRACE(bh, "still unmapped");
+				goto next;
+			}
+		}
+
+		/* Ok, it's mapped. Make sure it's up-to-date */
+		if (PageUptodate(page))
+			set_buffer_uptodate(bh);
+
+		if (!buffer_uptodate(bh)) {
+			err = -EIO;
+			ll_rw_block(READ, 1, &bh);
+			wait_on_buffer(bh);
+			/* Uhhuh. Read error. Complain and punt.*/
+			if (!buffer_uptodate(bh))
+				goto next;
+		}
+
+		if (ext4_should_journal_data(inode)) {
+			BUFFER_TRACE(bh, "get write access");
+			err = ext4_journal_get_write_access(handle, bh);
+			if (err)
+				goto next;
+		}
+
+		zero_user(page, pos, range_to_discard);
+
+		err = 0;
+		if (ext4_should_journal_data(inode)) {
+			err = ext4_handle_dirty_metadata(handle, inode, bh);
+		} else
+			mark_buffer_dirty(bh);
+
+		BUFFER_TRACE(bh, "Partial buffer zeroed");
+next:
+		bh = bh->b_this_page;
+		iblock++;
+		pos += range_to_discard;
+	}
+
+	return err;
+}
+
 /*
  * ext4_block_truncate_page() zeroes out a mapping from file offset `from'
  * up to the end of the block which corresponds to `from'.
@@ -3005,7 +3376,7 @@ int ext4_block_zero_page_range(handle_t *handle,
 	page = find_or_create_page(mapping, from >> PAGE_CACHE_SHIFT,
 				   mapping_gfp_mask(mapping) & ~__GFP_FS);
 	if (!page)
-		return -EINVAL;
+		return -ENOMEM;
 
 	blocksize = inode->i_sb->s_blocksize;
 	max = blocksize - (offset & (blocksize - 1));
@@ -3074,11 +3445,8 @@ int ext4_block_zero_page_range(handle_t *handle,
 	err = 0;
 	if (ext4_should_journal_data(inode)) {
 		err = ext4_handle_dirty_metadata(handle, inode, bh);
-	} else {
-		if (ext4_should_order_data(inode) && EXT4_I(inode)->jinode)
-			err = ext4_jbd2_file_inode(handle, inode);
+	} else
 		mark_buffer_dirty(bh);
-	}
 
 unlock:
 	unlock_page(page);
@@ -3119,6 +3487,11 @@ int ext4_punch_hole(struct file *file, loff_t offset, loff_t length)
 		return -ENOTSUPP;
 	}
 
+	if (EXT4_SB(inode->i_sb)->s_cluster_ratio > 1) {
+		/* TODO: Add support for bigalloc file systems */
+		return -ENOTSUPP;
+	}
+
 	return ext4_ext_punch_hole(file, offset, length);
 }
 
@@ -3418,7 +3791,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
 		inode->i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16;
 		inode->i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16;
 	}
-	inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
+	set_nlink(inode, le16_to_cpu(raw_inode->i_links_count));
 
 	ext4_clear_state_flags(ei);	/* Only relevant on 32-bit archs */
 	ei->i_dir_start_lookup = 0;
@@ -4420,6 +4793,7 @@ retry_alloc:
 			  PAGE_CACHE_SIZE, NULL, do_journal_get_write_access)) {
 			unlock_page(page);
 			ret = VM_FAULT_SIGBUS;
+			ext4_journal_stop(handle);
 			goto out;
 		}
 		ext4_set_inode_state(inode, EXT4_STATE_JDATA);
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index f18bfe3..a567968 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -21,6 +21,7 @@
 long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
 	struct inode *inode = filp->f_dentry->d_inode;
+	struct super_block *sb = inode->i_sb;
 	struct ext4_inode_info *ei = EXT4_I(inode);
 	unsigned int flags;
 
@@ -173,33 +174,8 @@ setversion_out:
 		mnt_drop_write(filp->f_path.mnt);
 		return err;
 	}
-#ifdef CONFIG_JBD2_DEBUG
-	case EXT4_IOC_WAIT_FOR_READONLY:
-		/*
-		 * This is racy - by the time we're woken up and running,
-		 * the superblock could be released.  And the module could
-		 * have been unloaded.  So sue me.
-		 *
-		 * Returns 1 if it slept, else zero.
-		 */
-		{
-			struct super_block *sb = inode->i_sb;
-			DECLARE_WAITQUEUE(wait, current);
-			int ret = 0;
-
-			set_current_state(TASK_INTERRUPTIBLE);
-			add_wait_queue(&EXT4_SB(sb)->ro_wait_queue, &wait);
-			if (timer_pending(&EXT4_SB(sb)->turn_ro_timer)) {
-				schedule();
-				ret = 1;
-			}
-			remove_wait_queue(&EXT4_SB(sb)->ro_wait_queue, &wait);
-			return ret;
-		}
-#endif
 	case EXT4_IOC_GROUP_EXTEND: {
 		ext4_fsblk_t n_blocks_count;
-		struct super_block *sb = inode->i_sb;
 		int err, err2=0;
 
 		err = ext4_resize_begin(sb);
@@ -209,6 +185,13 @@ setversion_out:
 		if (get_user(n_blocks_count, (__u32 __user *)arg))
 			return -EFAULT;
 
+		if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
+			       EXT4_FEATURE_RO_COMPAT_BIGALLOC)) {
+			ext4_msg(sb, KERN_ERR,
+				 "Online resizing not supported with bigalloc");
+			return -EOPNOTSUPP;
+		}
+
 		err = mnt_want_write(filp->f_path.mnt);
 		if (err)
 			return err;
@@ -250,6 +233,13 @@ setversion_out:
 			goto mext_out;
 		}
 
+		if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
+			       EXT4_FEATURE_RO_COMPAT_BIGALLOC)) {
+			ext4_msg(sb, KERN_ERR,
+				 "Online defrag not supported with bigalloc");
+			return -EOPNOTSUPP;
+		}
+
 		err = mnt_want_write(filp->f_path.mnt);
 		if (err)
 			goto mext_out;
@@ -270,7 +260,6 @@ mext_out:
 
 	case EXT4_IOC_GROUP_ADD: {
 		struct ext4_new_group_data input;
-		struct super_block *sb = inode->i_sb;
 		int err, err2=0;
 
 		err = ext4_resize_begin(sb);
@@ -281,6 +270,13 @@ mext_out:
 				sizeof(input)))
 			return -EFAULT;
 
+		if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
+			       EXT4_FEATURE_RO_COMPAT_BIGALLOC)) {
+			ext4_msg(sb, KERN_ERR,
+				 "Online resizing not supported with bigalloc");
+			return -EOPNOTSUPP;
+		}
+
 		err = mnt_want_write(filp->f_path.mnt);
 		if (err)
 			return err;
@@ -337,7 +333,6 @@ mext_out:
 
 	case FITRIM:
 	{
-		struct super_block *sb = inode->i_sb;
 		struct request_queue *q = bdev_get_queue(sb->s_bdev);
 		struct fstrim_range range;
 		int ret = 0;
@@ -348,7 +343,14 @@ mext_out:
 		if (!blk_queue_discard(q))
 			return -EOPNOTSUPP;
 
-		if (copy_from_user(&range, (struct fstrim_range *)arg,
+		if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
+			       EXT4_FEATURE_RO_COMPAT_BIGALLOC)) {
+			ext4_msg(sb, KERN_ERR,
+				 "FITRIM not supported with bigalloc");
+			return -EOPNOTSUPP;
+		}
+
+		if (copy_from_user(&range, (struct fstrim_range __user *)arg,
 		    sizeof(range)))
 			return -EFAULT;
 
@@ -358,7 +360,7 @@ mext_out:
 		if (ret < 0)
 			return ret;
 
-		if (copy_to_user((struct fstrim_range *)arg, &range,
+		if (copy_to_user((struct fstrim_range __user *)arg, &range,
 		    sizeof(range)))
 			return -EFAULT;
 
@@ -396,11 +398,6 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	case EXT4_IOC32_SETVERSION_OLD:
 		cmd = EXT4_IOC_SETVERSION_OLD;
 		break;
-#ifdef CONFIG_JBD2_DEBUG
-	case EXT4_IOC32_WAIT_FOR_READONLY:
-		cmd = EXT4_IOC_WAIT_FOR_READONLY;
-		break;
-#endif
 	case EXT4_IOC32_GETRSVSZ:
 		cmd = EXT4_IOC_GETRSVSZ;
 		break;
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 17a5a57..e2d8be8 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -70,8 +70,8 @@
  *
  * pa_lstart -> the logical start block for this prealloc space
  * pa_pstart -> the physical start block for this prealloc space
- * pa_len    -> length for this prealloc space
- * pa_free   ->  free space available in this prealloc space
+ * pa_len    -> length for this prealloc space (in clusters)
+ * pa_free   ->  free space available in this prealloc space (in clusters)
  *
  * The inode preallocation space is used looking at the _logical_ start
  * block. If only the logical file block falls within the range of prealloc
@@ -126,7 +126,8 @@
  * list. In case of inode preallocation we follow a list of heuristics
  * based on file size. This can be found in ext4_mb_normalize_request. If
  * we are doing a group prealloc we try to normalize the request to
- * sbi->s_mb_group_prealloc. Default value of s_mb_group_prealloc is
+ * sbi->s_mb_group_prealloc.  The default value of s_mb_group_prealloc is
+ * dependent on the cluster size; for non-bigalloc file systems, it is
  * 512 blocks. This can be tuned via
  * /sys/fs/ext4/<partition>/mb_group_prealloc. The value is represented in
  * terms of number of blocks. If we have mounted the file system with -O
@@ -459,7 +460,7 @@ static void mb_free_blocks_double(struct inode *inode, struct ext4_buddy *e4b,
 			ext4_fsblk_t blocknr;
 
 			blocknr = ext4_group_first_block_no(sb, e4b->bd_group);
-			blocknr += first + i;
+			blocknr += EXT4_C2B(EXT4_SB(sb), first + i);
 			ext4_grp_locked_error(sb, e4b->bd_group,
 					      inode ? inode->i_ino : 0,
 					      blocknr,
@@ -580,7 +581,7 @@ static int __mb_check_buddy(struct ext4_buddy *e4b, char *file,
 				continue;
 			}
 
-			/* both bits in buddy2 must be 0 */
+			/* both bits in buddy2 must be 1 */
 			MB_CHECK_ASSERT(mb_test_bit(i << 1, buddy2));
 			MB_CHECK_ASSERT(mb_test_bit((i << 1) + 1, buddy2));
 
@@ -653,7 +654,7 @@ static void ext4_mb_mark_free_simple(struct super_block *sb,
 	ext4_grpblk_t chunk;
 	unsigned short border;
 
-	BUG_ON(len > EXT4_BLOCKS_PER_GROUP(sb));
+	BUG_ON(len > EXT4_CLUSTERS_PER_GROUP(sb));
 
 	border = 2 << sb->s_blocksize_bits;
 
@@ -705,7 +706,7 @@ void ext4_mb_generate_buddy(struct super_block *sb,
 				void *buddy, void *bitmap, ext4_group_t group)
 {
 	struct ext4_group_info *grp = ext4_get_group_info(sb, group);
-	ext4_grpblk_t max = EXT4_BLOCKS_PER_GROUP(sb);
+	ext4_grpblk_t max = EXT4_CLUSTERS_PER_GROUP(sb);
 	ext4_grpblk_t i = 0;
 	ext4_grpblk_t first;
 	ext4_grpblk_t len;
@@ -734,7 +735,7 @@ void ext4_mb_generate_buddy(struct super_block *sb,
 
 	if (free != grp->bb_free) {
 		ext4_grp_locked_error(sb, group, 0, 0,
-				      "%u blocks in bitmap, %u in gd",
+				      "%u clusters in bitmap, %u in gd",
 				      free, grp->bb_free);
 		/*
 		 * If we intent to continue, we consider group descritor
@@ -1339,7 +1340,7 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b,
 			ext4_fsblk_t blocknr;
 
 			blocknr = ext4_group_first_block_no(sb, e4b->bd_group);
-			blocknr += block;
+			blocknr += EXT4_C2B(EXT4_SB(sb), block);
 			ext4_grp_locked_error(sb, e4b->bd_group,
 					      inode ? inode->i_ino : 0,
 					      blocknr,
@@ -1390,7 +1391,6 @@ static int mb_find_extent(struct ext4_buddy *e4b, int order, int block,
 {
 	int next = block;
 	int max;
-	int ord;
 	void *buddy;
 
 	assert_spin_locked(ext4_group_lock_ptr(e4b->bd_sb, e4b->bd_group));
@@ -1432,9 +1432,8 @@ static int mb_find_extent(struct ext4_buddy *e4b, int order, int block,
 		if (mb_test_bit(next, EXT4_MB_BITMAP(e4b)))
 			break;
 
-		ord = mb_find_order_for_block(e4b, next);
+		order = mb_find_order_for_block(e4b, next);
 
-		order = ord;
 		block = next >> order;
 		ex->fe_len += 1 << order;
 	}
@@ -1624,8 +1623,8 @@ static void ext4_mb_measure_extent(struct ext4_allocation_context *ac,
 	struct ext4_free_extent *gex = &ac->ac_g_ex;
 
 	BUG_ON(ex->fe_len <= 0);
-	BUG_ON(ex->fe_len > EXT4_BLOCKS_PER_GROUP(ac->ac_sb));
-	BUG_ON(ex->fe_start >= EXT4_BLOCKS_PER_GROUP(ac->ac_sb));
+	BUG_ON(ex->fe_len > EXT4_CLUSTERS_PER_GROUP(ac->ac_sb));
+	BUG_ON(ex->fe_start >= EXT4_CLUSTERS_PER_GROUP(ac->ac_sb));
 	BUG_ON(ac->ac_status != AC_STATUS_CONTINUE);
 
 	ac->ac_found++;
@@ -1823,15 +1822,15 @@ void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
 
 	while (free && ac->ac_status == AC_STATUS_CONTINUE) {
 		i = mb_find_next_zero_bit(bitmap,
-						EXT4_BLOCKS_PER_GROUP(sb), i);
-		if (i >= EXT4_BLOCKS_PER_GROUP(sb)) {
+						EXT4_CLUSTERS_PER_GROUP(sb), i);
+		if (i >= EXT4_CLUSTERS_PER_GROUP(sb)) {
 			/*
 			 * IF we have corrupt bitmap, we won't find any
 			 * free blocks even though group info says we
 			 * we have free blocks
 			 */
 			ext4_grp_locked_error(sb, e4b->bd_group, 0, 0,
-					"%d free blocks as per "
+					"%d free clusters as per "
 					"group info. But bitmap says 0",
 					free);
 			break;
@@ -1841,7 +1840,7 @@ void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
 		BUG_ON(ex.fe_len <= 0);
 		if (free < ex.fe_len) {
 			ext4_grp_locked_error(sb, e4b->bd_group, 0, 0,
-					"%d free blocks as per "
+					"%d free clusters as per "
 					"group info. But got %d blocks",
 					free, ex.fe_len);
 			/*
@@ -1887,7 +1886,7 @@ void ext4_mb_scan_aligned(struct ext4_allocation_context *ac,
 	do_div(a, sbi->s_stripe);
 	i = (a * sbi->s_stripe) - first_group_block;
 
-	while (i < EXT4_BLOCKS_PER_GROUP(sb)) {
+	while (i < EXT4_CLUSTERS_PER_GROUP(sb)) {
 		if (!mb_test_bit(i, bitmap)) {
 			max = mb_find_extent(e4b, 0, i, sbi->s_stripe, &ex);
 			if (max >= sbi->s_stripe) {
@@ -2252,10 +2251,10 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group,
 	 */
 	if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
 		meta_group_info[i]->bb_free =
-			ext4_free_blocks_after_init(sb, group, desc);
+			ext4_free_clusters_after_init(sb, group, desc);
 	} else {
 		meta_group_info[i]->bb_free =
-			ext4_free_blks_count(sb, desc);
+			ext4_free_group_clusters(sb, desc);
 	}
 
 	INIT_LIST_HEAD(&meta_group_info[i]->bb_prealloc_list);
@@ -2473,7 +2472,20 @@ int ext4_mb_init(struct super_block *sb, int needs_recovery)
 	sbi->s_mb_stats = MB_DEFAULT_STATS;
 	sbi->s_mb_stream_request = MB_DEFAULT_STREAM_THRESHOLD;
 	sbi->s_mb_order2_reqs = MB_DEFAULT_ORDER2_REQS;
-	sbi->s_mb_group_prealloc = MB_DEFAULT_GROUP_PREALLOC;
+	/*
+	 * The default group preallocation is 512, which for 4k block
+	 * sizes translates to 2 megabytes.  However for bigalloc file
+	 * systems, this is probably too big (i.e, if the cluster size
+	 * is 1 megabyte, then group preallocation size becomes half a
+	 * gigabyte!).  As a default, we will keep a two megabyte
+	 * group pralloc size for cluster sizes up to 64k, and after
+	 * that, we will force a minimum group preallocation size of
+	 * 32 clusters.  This translates to 8 megs when the cluster
+	 * size is 256k, and 32 megs when the cluster size is 1 meg,
+	 * which seems reasonable as a default.
+	 */
+	sbi->s_mb_group_prealloc = max(MB_DEFAULT_GROUP_PREALLOC >>
+				       sbi->s_cluster_bits, 32);
 	/*
 	 * If there is a s_stripe > 1, then we set the s_mb_group_prealloc
 	 * to the lowest multiple of s_stripe which is bigger than
@@ -2490,7 +2502,7 @@ int ext4_mb_init(struct super_block *sb, int needs_recovery)
 	sbi->s_locality_groups = alloc_percpu(struct ext4_locality_group);
 	if (sbi->s_locality_groups == NULL) {
 		ret = -ENOMEM;
-		goto out;
+		goto out_free_groupinfo_slab;
 	}
 	for_each_possible_cpu(i) {
 		struct ext4_locality_group *lg;
@@ -2503,9 +2515,8 @@ int ext4_mb_init(struct super_block *sb, int needs_recovery)
 
 	/* init file for buddy data */
 	ret = ext4_mb_init_backend(sb);
-	if (ret != 0) {
-		goto out;
-	}
+	if (ret != 0)
+		goto out_free_locality_groups;
 
 	if (sbi->s_proc)
 		proc_create_data("mb_groups", S_IRUGO, sbi->s_proc,
@@ -2513,11 +2524,19 @@ int ext4_mb_init(struct super_block *sb, int needs_recovery)
 
 	if (sbi->s_journal)
 		sbi->s_journal->j_commit_callback = release_blocks_on_commit;
+
+	return 0;
+
+out_free_locality_groups:
+	free_percpu(sbi->s_locality_groups);
+	sbi->s_locality_groups = NULL;
+out_free_groupinfo_slab:
+	ext4_groupinfo_destroy_slabs();
 out:
-	if (ret) {
-		kfree(sbi->s_mb_offsets);
-		kfree(sbi->s_mb_maxs);
-	}
+	kfree(sbi->s_mb_offsets);
+	sbi->s_mb_offsets = NULL;
+	kfree(sbi->s_mb_maxs);
+	sbi->s_mb_maxs = NULL;
 	return ret;
 }
 
@@ -2602,11 +2621,13 @@ int ext4_mb_release(struct super_block *sb)
 }
 
 static inline int ext4_issue_discard(struct super_block *sb,
-		ext4_group_t block_group, ext4_grpblk_t block, int count)
+		ext4_group_t block_group, ext4_grpblk_t cluster, int count)
 {
 	ext4_fsblk_t discard_block;
 
-	discard_block = block + ext4_group_first_block_no(sb, block_group);
+	discard_block = (EXT4_C2B(EXT4_SB(sb), cluster) +
+			 ext4_group_first_block_no(sb, block_group));
+	count = EXT4_C2B(EXT4_SB(sb), count);
 	trace_ext4_discard_blocks(sb,
 			(unsigned long long) discard_block, count);
 	return sb_issue_discard(sb, discard_block, count, GFP_NOFS, 0);
@@ -2633,7 +2654,7 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn)
 
 		if (test_opt(sb, DISCARD))
 			ext4_issue_discard(sb, entry->group,
-					   entry->start_blk, entry->count);
+					   entry->start_cluster, entry->count);
 
 		err = ext4_mb_load_buddy(sb, entry->group, &e4b);
 		/* we expect to find existing buddy because it's pinned */
@@ -2646,7 +2667,7 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn)
 		ext4_lock_group(sb, entry->group);
 		/* Take it out of per group rb tree */
 		rb_erase(&entry->node, &(db->bb_free_root));
-		mb_free_blocks(NULL, &e4b, entry->start_blk, entry->count);
+		mb_free_blocks(NULL, &e4b, entry->start_cluster, entry->count);
 
 		/*
 		 * Clear the trimmed flag for the group so that the next
@@ -2752,7 +2773,7 @@ void ext4_exit_mballoc(void)
  */
 static noinline_for_stack int
 ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
-				handle_t *handle, unsigned int reserv_blks)
+				handle_t *handle, unsigned int reserv_clstrs)
 {
 	struct buffer_head *bitmap_bh = NULL;
 	struct ext4_group_desc *gdp;
@@ -2783,7 +2804,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
 		goto out_err;
 
 	ext4_debug("using block group %u(%d)\n", ac->ac_b_ex.fe_group,
-			ext4_free_blks_count(sb, gdp));
+			ext4_free_group_clusters(sb, gdp));
 
 	err = ext4_journal_get_write_access(handle, gdp_bh);
 	if (err)
@@ -2791,7 +2812,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
 
 	block = ext4_grp_offs_to_block(sb, &ac->ac_b_ex);
 
-	len = ac->ac_b_ex.fe_len;
+	len = EXT4_C2B(sbi, ac->ac_b_ex.fe_len);
 	if (!ext4_data_block_valid(sbi, block, len)) {
 		ext4_error(sb, "Allocating blocks %llu-%llu which overlap "
 			   "fs metadata\n", block, block+len);
@@ -2823,28 +2844,29 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
 		      ac->ac_b_ex.fe_len);
 	if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
 		gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
-		ext4_free_blks_set(sb, gdp,
-					ext4_free_blocks_after_init(sb,
-					ac->ac_b_ex.fe_group, gdp));
+		ext4_free_group_clusters_set(sb, gdp,
+					     ext4_free_clusters_after_init(sb,
+						ac->ac_b_ex.fe_group, gdp));
 	}
-	len = ext4_free_blks_count(sb, gdp) - ac->ac_b_ex.fe_len;
-	ext4_free_blks_set(sb, gdp, len);
+	len = ext4_free_group_clusters(sb, gdp) - ac->ac_b_ex.fe_len;
+	ext4_free_group_clusters_set(sb, gdp, len);
 	gdp->bg_checksum = ext4_group_desc_csum(sbi, ac->ac_b_ex.fe_group, gdp);
 
 	ext4_unlock_group(sb, ac->ac_b_ex.fe_group);
-	percpu_counter_sub(&sbi->s_freeblocks_counter, ac->ac_b_ex.fe_len);
+	percpu_counter_sub(&sbi->s_freeclusters_counter, ac->ac_b_ex.fe_len);
 	/*
 	 * Now reduce the dirty block count also. Should not go negative
 	 */
 	if (!(ac->ac_flags & EXT4_MB_DELALLOC_RESERVED))
 		/* release all the reserved blocks if non delalloc */
-		percpu_counter_sub(&sbi->s_dirtyblocks_counter, reserv_blks);
+		percpu_counter_sub(&sbi->s_dirtyclusters_counter,
+				   reserv_clstrs);
 
 	if (sbi->s_log_groups_per_flex) {
 		ext4_group_t flex_group = ext4_flex_group(sbi,
 							  ac->ac_b_ex.fe_group);
 		atomic_sub(ac->ac_b_ex.fe_len,
-			   &sbi->s_flex_groups[flex_group].free_blocks);
+			   &sbi->s_flex_groups[flex_group].free_clusters);
 	}
 
 	err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
@@ -2886,6 +2908,7 @@ static noinline_for_stack void
 ext4_mb_normalize_request(struct ext4_allocation_context *ac,
 				struct ext4_allocation_request *ar)
 {
+	struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb);
 	int bsbits, max;
 	ext4_lblk_t end;
 	loff_t size, orig_size, start_off;
@@ -2916,7 +2939,7 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
 
 	/* first, let's learn actual file size
 	 * given current request is allocated */
-	size = ac->ac_o_ex.fe_logical + ac->ac_o_ex.fe_len;
+	size = ac->ac_o_ex.fe_logical + EXT4_C2B(sbi, ac->ac_o_ex.fe_len);
 	size = size << bsbits;
 	if (size < i_size_read(ac->ac_inode))
 		size = i_size_read(ac->ac_inode);
@@ -2988,7 +3011,8 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
 			continue;
 		}
 
-		pa_end = pa->pa_lstart + pa->pa_len;
+		pa_end = pa->pa_lstart + EXT4_C2B(EXT4_SB(ac->ac_sb),
+						  pa->pa_len);
 
 		/* PA must not overlap original request */
 		BUG_ON(!(ac->ac_o_ex.fe_logical >= pa_end ||
@@ -3018,9 +3042,11 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
 	rcu_read_lock();
 	list_for_each_entry_rcu(pa, &ei->i_prealloc_list, pa_inode_list) {
 		ext4_lblk_t pa_end;
+
 		spin_lock(&pa->pa_lock);
 		if (pa->pa_deleted == 0) {
-			pa_end = pa->pa_lstart + pa->pa_len;
+			pa_end = pa->pa_lstart + EXT4_C2B(EXT4_SB(ac->ac_sb),
+							  pa->pa_len);
 			BUG_ON(!(start >= pa_end || end <= pa->pa_lstart));
 		}
 		spin_unlock(&pa->pa_lock);
@@ -3036,14 +3062,14 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
 	}
 	BUG_ON(start + size <= ac->ac_o_ex.fe_logical &&
 			start > ac->ac_o_ex.fe_logical);
-	BUG_ON(size <= 0 || size > EXT4_BLOCKS_PER_GROUP(ac->ac_sb));
+	BUG_ON(size <= 0 || size > EXT4_CLUSTERS_PER_GROUP(ac->ac_sb));
 
 	/* now prepare goal request */
 
 	/* XXX: is it better to align blocks WRT to logical
 	 * placement or satisfy big request as is */
 	ac->ac_g_ex.fe_logical = start;
-	ac->ac_g_ex.fe_len = size;
+	ac->ac_g_ex.fe_len = EXT4_NUM_B2C(sbi, size);
 
 	/* define goal start in order to merge */
 	if (ar->pright && (ar->lright == (start + size))) {
@@ -3112,14 +3138,16 @@ static void ext4_discard_allocated_blocks(struct ext4_allocation_context *ac)
 static void ext4_mb_use_inode_pa(struct ext4_allocation_context *ac,
 				struct ext4_prealloc_space *pa)
 {
+	struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb);
 	ext4_fsblk_t start;
 	ext4_fsblk_t end;
 	int len;
 
 	/* found preallocated blocks, use them */
 	start = pa->pa_pstart + (ac->ac_o_ex.fe_logical - pa->pa_lstart);
-	end = min(pa->pa_pstart + pa->pa_len, start + ac->ac_o_ex.fe_len);
-	len = end - start;
+	end = min(pa->pa_pstart + EXT4_C2B(sbi, pa->pa_len),
+		  start + EXT4_C2B(sbi, ac->ac_o_ex.fe_len));
+	len = EXT4_NUM_B2C(sbi, end - start);
 	ext4_get_group_no_and_offset(ac->ac_sb, start, &ac->ac_b_ex.fe_group,
 					&ac->ac_b_ex.fe_start);
 	ac->ac_b_ex.fe_len = len;
@@ -3127,7 +3155,7 @@ static void ext4_mb_use_inode_pa(struct ext4_allocation_context *ac,
 	ac->ac_pa = pa;
 
 	BUG_ON(start < pa->pa_pstart);
-	BUG_ON(start + len > pa->pa_pstart + pa->pa_len);
+	BUG_ON(end > pa->pa_pstart + EXT4_C2B(sbi, pa->pa_len));
 	BUG_ON(pa->pa_free < len);
 	pa->pa_free -= len;
 
@@ -3193,6 +3221,7 @@ ext4_mb_check_group_pa(ext4_fsblk_t goal_block,
 static noinline_for_stack int
 ext4_mb_use_preallocated(struct ext4_allocation_context *ac)
 {
+	struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb);
 	int order, i;
 	struct ext4_inode_info *ei = EXT4_I(ac->ac_inode);
 	struct ext4_locality_group *lg;
@@ -3210,12 +3239,14 @@ ext4_mb_use_preallocated(struct ext4_allocation_context *ac)
 		/* all fields in this condition don't change,
 		 * so we can skip locking for them */
 		if (ac->ac_o_ex.fe_logical < pa->pa_lstart ||
-			ac->ac_o_ex.fe_logical >= pa->pa_lstart + pa->pa_len)
+		    ac->ac_o_ex.fe_logical >= (pa->pa_lstart +
+					       EXT4_C2B(sbi, pa->pa_len)))
 			continue;
 
 		/* non-extent files can't have physical blocks past 2^32 */
 		if (!(ext4_test_inode_flag(ac->ac_inode, EXT4_INODE_EXTENTS)) &&
-			pa->pa_pstart + pa->pa_len > EXT4_MAX_BLOCK_FILE_PHYS)
+		    (pa->pa_pstart + EXT4_C2B(sbi, pa->pa_len) >
+		     EXT4_MAX_BLOCK_FILE_PHYS))
 			continue;
 
 		/* found preallocated blocks, use them */
@@ -3291,7 +3322,7 @@ static void ext4_mb_generate_from_freelist(struct super_block *sb, void *bitmap,
 
 	while (n) {
 		entry = rb_entry(n, struct ext4_free_data, node);
-		ext4_set_bits(bitmap, entry->start_blk, entry->count);
+		ext4_set_bits(bitmap, entry->start_cluster, entry->count);
 		n = rb_next(n);
 	}
 	return;
@@ -3312,7 +3343,6 @@ void ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap,
 	ext4_group_t groupnr;
 	ext4_grpblk_t start;
 	int preallocated = 0;
-	int count = 0;
 	int len;
 
 	/* all form of preallocation discards first load group,
@@ -3335,7 +3365,6 @@ void ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap,
 		BUG_ON(groupnr != group);
 		ext4_set_bits(bitmap, start, len);
 		preallocated += len;
-		count++;
 	}
 	mb_debug(1, "prellocated %u for group %u\n", preallocated, group);
 }
@@ -3412,6 +3441,7 @@ static noinline_for_stack int
 ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
 {
 	struct super_block *sb = ac->ac_sb;
+	struct ext4_sb_info *sbi = EXT4_SB(sb);
 	struct ext4_prealloc_space *pa;
 	struct ext4_group_info *grp;
 	struct ext4_inode_info *ei;
@@ -3443,16 +3473,18 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
 		winl = ac->ac_o_ex.fe_logical - ac->ac_g_ex.fe_logical;
 
 		/* also, we should cover whole original request */
-		wins = ac->ac_b_ex.fe_len - ac->ac_o_ex.fe_len;
+		wins = EXT4_C2B(sbi, ac->ac_b_ex.fe_len - ac->ac_o_ex.fe_len);
 
 		/* the smallest one defines real window */
 		win = min(winl, wins);
 
-		offs = ac->ac_o_ex.fe_logical % ac->ac_b_ex.fe_len;
+		offs = ac->ac_o_ex.fe_logical %
+			EXT4_C2B(sbi, ac->ac_b_ex.fe_len);
 		if (offs && offs < win)
 			win = offs;
 
-		ac->ac_b_ex.fe_logical = ac->ac_o_ex.fe_logical - win;
+		ac->ac_b_ex.fe_logical = ac->ac_o_ex.fe_logical -
+			EXT4_B2C(sbi, win);
 		BUG_ON(ac->ac_o_ex.fe_logical < ac->ac_b_ex.fe_logical);
 		BUG_ON(ac->ac_o_ex.fe_len > ac->ac_b_ex.fe_len);
 	}
@@ -3477,7 +3509,7 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
 	trace_ext4_mb_new_inode_pa(ac, pa);
 
 	ext4_mb_use_inode_pa(ac, pa);
-	atomic_add(pa->pa_free, &EXT4_SB(sb)->s_mb_preallocated);
+	atomic_add(pa->pa_free, &sbi->s_mb_preallocated);
 
 	ei = EXT4_I(ac->ac_inode);
 	grp = ext4_get_group_info(sb, ac->ac_b_ex.fe_group);
@@ -3592,7 +3624,7 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh,
 
 	BUG_ON(pa->pa_deleted == 0);
 	ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, &bit);
-	grp_blk_start = pa->pa_pstart - bit;
+	grp_blk_start = pa->pa_pstart - EXT4_C2B(sbi, bit);
 	BUG_ON(group != e4b->bd_group && pa->pa_len != 0);
 	end = bit + pa->pa_len;
 
@@ -3607,7 +3639,8 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh,
 		free += next - bit;
 
 		trace_ext4_mballoc_discard(sb, NULL, group, bit, next - bit);
-		trace_ext4_mb_release_inode_pa(pa, grp_blk_start + bit,
+		trace_ext4_mb_release_inode_pa(pa, (grp_blk_start +
+						    EXT4_C2B(sbi, bit)),
 					       next - bit);
 		mb_free_blocks(pa->pa_inode, e4b, bit, next - bit);
 		bit = next + 1;
@@ -3690,7 +3723,7 @@ ext4_mb_discard_group_preallocations(struct super_block *sb,
 	}
 
 	if (needed == 0)
-		needed = EXT4_BLOCKS_PER_GROUP(sb) + 1;
+		needed = EXT4_CLUSTERS_PER_GROUP(sb) + 1;
 
 	INIT_LIST_HEAD(&list);
 repeat:
@@ -3958,7 +3991,7 @@ static void ext4_mb_group_or_file(struct ext4_allocation_context *ac)
 	if (unlikely(ac->ac_flags & EXT4_MB_HINT_GOAL_ONLY))
 		return;
 
-	size = ac->ac_o_ex.fe_logical + ac->ac_o_ex.fe_len;
+	size = ac->ac_o_ex.fe_logical + EXT4_C2B(sbi, ac->ac_o_ex.fe_len);
 	isize = (i_size_read(ac->ac_inode) + ac->ac_sb->s_blocksize - 1)
 		>> bsbits;
 
@@ -3969,6 +4002,11 @@ static void ext4_mb_group_or_file(struct ext4_allocation_context *ac)
 		return;
 	}
 
+	if (sbi->s_mb_group_prealloc <= 0) {
+		ac->ac_flags |= EXT4_MB_STREAM_ALLOC;
+		return;
+	}
+
 	/* don't use group allocation for large files */
 	size = max(size, isize);
 	if (size > sbi->s_mb_stream_request) {
@@ -4007,8 +4045,8 @@ ext4_mb_initialize_context(struct ext4_allocation_context *ac,
 	len = ar->len;
 
 	/* just a dirty hack to filter too big requests  */
-	if (len >= EXT4_BLOCKS_PER_GROUP(sb) - 10)
-		len = EXT4_BLOCKS_PER_GROUP(sb) - 10;
+	if (len >= EXT4_CLUSTERS_PER_GROUP(sb) - 10)
+		len = EXT4_CLUSTERS_PER_GROUP(sb) - 10;
 
 	/* start searching from the goal */
 	goal = ar->goal;
@@ -4019,18 +4057,15 @@ ext4_mb_initialize_context(struct ext4_allocation_context *ac,
 
 	/* set up allocation goals */
 	memset(ac, 0, sizeof(struct ext4_allocation_context));
-	ac->ac_b_ex.fe_logical = ar->logical;
+	ac->ac_b_ex.fe_logical = ar->logical & ~(sbi->s_cluster_ratio - 1);
 	ac->ac_status = AC_STATUS_CONTINUE;
 	ac->ac_sb = sb;
 	ac->ac_inode = ar->inode;
-	ac->ac_o_ex.fe_logical = ar->logical;
+	ac->ac_o_ex.fe_logical = ac->ac_b_ex.fe_logical;
 	ac->ac_o_ex.fe_group = group;
 	ac->ac_o_ex.fe_start = block;
 	ac->ac_o_ex.fe_len = len;
-	ac->ac_g_ex.fe_logical = ar->logical;
-	ac->ac_g_ex.fe_group = group;
-	ac->ac_g_ex.fe_start = block;
-	ac->ac_g_ex.fe_len = len;
+	ac->ac_g_ex = ac->ac_o_ex;
 	ac->ac_flags = ar->flags;
 
 	/* we have to define context: we'll we work with a file or
@@ -4182,13 +4217,14 @@ static void ext4_mb_add_n_trim(struct ext4_allocation_context *ac)
  */
 static int ext4_mb_release_context(struct ext4_allocation_context *ac)
 {
+	struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb);
 	struct ext4_prealloc_space *pa = ac->ac_pa;
 	if (pa) {
 		if (pa->pa_type == MB_GROUP_PA) {
 			/* see comment in ext4_mb_use_group_pa() */
 			spin_lock(&pa->pa_lock);
-			pa->pa_pstart += ac->ac_b_ex.fe_len;
-			pa->pa_lstart += ac->ac_b_ex.fe_len;
+			pa->pa_pstart += EXT4_C2B(sbi, ac->ac_b_ex.fe_len);
+			pa->pa_lstart += EXT4_C2B(sbi, ac->ac_b_ex.fe_len);
 			pa->pa_free -= ac->ac_b_ex.fe_len;
 			pa->pa_len -= ac->ac_b_ex.fe_len;
 			spin_unlock(&pa->pa_lock);
@@ -4249,13 +4285,17 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
 	struct super_block *sb;
 	ext4_fsblk_t block = 0;
 	unsigned int inquota = 0;
-	unsigned int reserv_blks = 0;
+	unsigned int reserv_clstrs = 0;
 
 	sb = ar->inode->i_sb;
 	sbi = EXT4_SB(sb);
 
 	trace_ext4_request_blocks(ar);
 
+	/* Allow to use superuser reservation for quota file */
+	if (IS_NOQUOTA(ar->inode))
+		ar->flags |= EXT4_MB_USE_ROOT_BLOCKS;
+
 	/*
 	 * For delayed allocation, we could skip the ENOSPC and
 	 * EDQUOT check, as blocks and quotas have been already
@@ -4269,7 +4309,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
 		 * and verify allocation doesn't exceed the quota limits.
 		 */
 		while (ar->len &&
-			ext4_claim_free_blocks(sbi, ar->len, ar->flags)) {
+			ext4_claim_free_clusters(sbi, ar->len, ar->flags)) {
 
 			/* let others to free the space */
 			yield();
@@ -4279,12 +4319,14 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
 			*errp = -ENOSPC;
 			return 0;
 		}
-		reserv_blks = ar->len;
+		reserv_clstrs = ar->len;
 		if (ar->flags & EXT4_MB_USE_ROOT_BLOCKS) {
-			dquot_alloc_block_nofail(ar->inode, ar->len);
+			dquot_alloc_block_nofail(ar->inode,
+						 EXT4_C2B(sbi, ar->len));
 		} else {
 			while (ar->len &&
-				dquot_alloc_block(ar->inode, ar->len)) {
+				dquot_alloc_block(ar->inode,
+						  EXT4_C2B(sbi, ar->len))) {
 
 				ar->flags |= EXT4_MB_HINT_NOPREALLOC;
 				ar->len--;
@@ -4328,7 +4370,7 @@ repeat:
 			ext4_mb_new_preallocation(ac);
 	}
 	if (likely(ac->ac_status == AC_STATUS_FOUND)) {
-		*errp = ext4_mb_mark_diskspace_used(ac, handle, reserv_blks);
+		*errp = ext4_mb_mark_diskspace_used(ac, handle, reserv_clstrs);
 		if (*errp == -EAGAIN) {
 			/*
 			 * drop the reference that we took
@@ -4364,13 +4406,13 @@ out:
 	if (ac)
 		kmem_cache_free(ext4_ac_cachep, ac);
 	if (inquota && ar->len < inquota)
-		dquot_free_block(ar->inode, inquota - ar->len);
+		dquot_free_block(ar->inode, EXT4_C2B(sbi, inquota - ar->len));
 	if (!ar->len) {
 		if (!ext4_test_inode_state(ar->inode,
 					   EXT4_STATE_DELALLOC_RESERVED))
 			/* release all the reserved blocks if non delalloc */
-			percpu_counter_sub(&sbi->s_dirtyblocks_counter,
-						reserv_blks);
+			percpu_counter_sub(&sbi->s_dirtyclusters_counter,
+						reserv_clstrs);
 	}
 
 	trace_ext4_allocate_blocks(ar, (unsigned long long)block);
@@ -4388,7 +4430,7 @@ static int can_merge(struct ext4_free_data *entry1,
 {
 	if ((entry1->t_tid == entry2->t_tid) &&
 	    (entry1->group == entry2->group) &&
-	    ((entry1->start_blk + entry1->count) == entry2->start_blk))
+	    ((entry1->start_cluster + entry1->count) == entry2->start_cluster))
 		return 1;
 	return 0;
 }
@@ -4398,7 +4440,7 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
 		      struct ext4_free_data *new_entry)
 {
 	ext4_group_t group = e4b->bd_group;
-	ext4_grpblk_t block;
+	ext4_grpblk_t cluster;
 	struct ext4_free_data *entry;
 	struct ext4_group_info *db = e4b->bd_info;
 	struct super_block *sb = e4b->bd_sb;
@@ -4411,7 +4453,7 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
 	BUG_ON(e4b->bd_buddy_page == NULL);
 
 	new_node = &new_entry->node;
-	block = new_entry->start_blk;
+	cluster = new_entry->start_cluster;
 
 	if (!*n) {
 		/* first free block exent. We need to
@@ -4425,13 +4467,14 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
 	while (*n) {
 		parent = *n;
 		entry = rb_entry(parent, struct ext4_free_data, node);
-		if (block < entry->start_blk)
+		if (cluster < entry->start_cluster)
 			n = &(*n)->rb_left;
-		else if (block >= (entry->start_blk + entry->count))
+		else if (cluster >= (entry->start_cluster + entry->count))
 			n = &(*n)->rb_right;
 		else {
 			ext4_grp_locked_error(sb, group, 0,
-				ext4_group_first_block_no(sb, group) + block,
+				ext4_group_first_block_no(sb, group) +
+				EXT4_C2B(sbi, cluster),
 				"Block already on to-be-freed list");
 			return 0;
 		}
@@ -4445,7 +4488,7 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
 	if (node) {
 		entry = rb_entry(node, struct ext4_free_data, node);
 		if (can_merge(entry, new_entry)) {
-			new_entry->start_blk = entry->start_blk;
+			new_entry->start_cluster = entry->start_cluster;
 			new_entry->count += entry->count;
 			rb_erase(node, &(db->bb_free_root));
 			spin_lock(&sbi->s_md_lock);
@@ -4496,6 +4539,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
 	ext4_group_t block_group;
 	struct ext4_sb_info *sbi;
 	struct ext4_buddy e4b;
+	unsigned int count_clusters;
 	int err = 0;
 	int ret;
 
@@ -4544,6 +4588,38 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
 	if (!ext4_should_writeback_data(inode))
 		flags |= EXT4_FREE_BLOCKS_METADATA;
 
+	/*
+	 * If the extent to be freed does not begin on a cluster
+	 * boundary, we need to deal with partial clusters at the
+	 * beginning and end of the extent.  Normally we will free
+	 * blocks at the beginning or the end unless we are explicitly
+	 * requested to avoid doing so.
+	 */
+	overflow = block & (sbi->s_cluster_ratio - 1);
+	if (overflow) {
+		if (flags & EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER) {
+			overflow = sbi->s_cluster_ratio - overflow;
+			block += overflow;
+			if (count > overflow)
+				count -= overflow;
+			else
+				return;
+		} else {
+			block -= overflow;
+			count += overflow;
+		}
+	}
+	overflow = count & (sbi->s_cluster_ratio - 1);
+	if (overflow) {
+		if (flags & EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER) {
+			if (count > overflow)
+				count -= overflow;
+			else
+				return;
+		} else
+			count += sbi->s_cluster_ratio - overflow;
+	}
+
 do_more:
 	overflow = 0;
 	ext4_get_group_no_and_offset(sb, block, &block_group, &bit);
@@ -4552,10 +4628,12 @@ do_more:
 	 * Check to see if we are freeing blocks across a group
 	 * boundary.
 	 */
-	if (bit + count > EXT4_BLOCKS_PER_GROUP(sb)) {
-		overflow = bit + count - EXT4_BLOCKS_PER_GROUP(sb);
+	if (EXT4_C2B(sbi, bit) + count > EXT4_BLOCKS_PER_GROUP(sb)) {
+		overflow = EXT4_C2B(sbi, bit) + count -
+			EXT4_BLOCKS_PER_GROUP(sb);
 		count -= overflow;
 	}
+	count_clusters = EXT4_B2C(sbi, count);
 	bitmap_bh = ext4_read_block_bitmap(sb, block_group);
 	if (!bitmap_bh) {
 		err = -EIO;
@@ -4570,9 +4648,9 @@ do_more:
 	if (in_range(ext4_block_bitmap(sb, gdp), block, count) ||
 	    in_range(ext4_inode_bitmap(sb, gdp), block, count) ||
 	    in_range(block, ext4_inode_table(sb, gdp),
-		      EXT4_SB(sb)->s_itb_per_group) ||
+		     EXT4_SB(sb)->s_itb_per_group) ||
 	    in_range(block + count - 1, ext4_inode_table(sb, gdp),
-		      EXT4_SB(sb)->s_itb_per_group)) {
+		     EXT4_SB(sb)->s_itb_per_group)) {
 
 		ext4_error(sb, "Freeing blocks in system zone - "
 			   "Block = %llu, count = %lu", block, count);
@@ -4597,11 +4675,11 @@ do_more:
 #ifdef AGGRESSIVE_CHECK
 	{
 		int i;
-		for (i = 0; i < count; i++)
+		for (i = 0; i < count_clusters; i++)
 			BUG_ON(!mb_test_bit(bit + i, bitmap_bh->b_data));
 	}
 #endif
-	trace_ext4_mballoc_free(sb, inode, block_group, bit, count);
+	trace_ext4_mballoc_free(sb, inode, block_group, bit, count_clusters);
 
 	err = ext4_mb_load_buddy(sb, block_group, &e4b);
 	if (err)
@@ -4618,13 +4696,13 @@ do_more:
 			err = -ENOMEM;
 			goto error_return;
 		}
-		new_entry->start_blk = bit;
+		new_entry->start_cluster = bit;
 		new_entry->group  = block_group;
-		new_entry->count = count;
+		new_entry->count = count_clusters;
 		new_entry->t_tid = handle->h_transaction->t_tid;
 
 		ext4_lock_group(sb, block_group);
-		mb_clear_bits(bitmap_bh->b_data, bit, count);
+		mb_clear_bits(bitmap_bh->b_data, bit, count_clusters);
 		ext4_mb_free_metadata(handle, &e4b, new_entry);
 	} else {
 		/* need to update group_info->bb_free and bitmap
@@ -4632,25 +4710,29 @@ do_more:
 		 * them with group lock_held
 		 */
 		ext4_lock_group(sb, block_group);
-		mb_clear_bits(bitmap_bh->b_data, bit, count);
-		mb_free_blocks(inode, &e4b, bit, count);
+		mb_clear_bits(bitmap_bh->b_data, bit, count_clusters);
+		mb_free_blocks(inode, &e4b, bit, count_clusters);
 	}
 
-	ret = ext4_free_blks_count(sb, gdp) + count;
-	ext4_free_blks_set(sb, gdp, ret);
+	ret = ext4_free_group_clusters(sb, gdp) + count_clusters;
+	ext4_free_group_clusters_set(sb, gdp, ret);
 	gdp->bg_checksum = ext4_group_desc_csum(sbi, block_group, gdp);
 	ext4_unlock_group(sb, block_group);
-	percpu_counter_add(&sbi->s_freeblocks_counter, count);
+	percpu_counter_add(&sbi->s_freeclusters_counter, count_clusters);
 
 	if (sbi->s_log_groups_per_flex) {
 		ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
-		atomic_add(count, &sbi->s_flex_groups[flex_group].free_blocks);
+		atomic_add(count_clusters,
+			   &sbi->s_flex_groups[flex_group].free_clusters);
 	}
 
 	ext4_mb_unload_buddy(&e4b);
 
 	freed += count;
 
+	if (!(flags & EXT4_FREE_BLOCKS_NO_QUOT_UPDATE))
+		dquot_free_block(inode, EXT4_C2B(sbi, count_clusters));
+
 	/* We dirtied the bitmap block */
 	BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
 	err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
@@ -4669,8 +4751,6 @@ do_more:
 	}
 	ext4_mark_super_dirty(sb);
 error_return:
-	if (freed && !(flags & EXT4_FREE_BLOCKS_NO_QUOT_UPDATE))
-		dquot_free_block(inode, freed);
 	brelse(bitmap_bh);
 	ext4_std_error(sb, err);
 	return;
@@ -4778,16 +4858,17 @@ int ext4_group_add_blocks(handle_t *handle, struct super_block *sb,
 	ext4_lock_group(sb, block_group);
 	mb_clear_bits(bitmap_bh->b_data, bit, count);
 	mb_free_blocks(NULL, &e4b, bit, count);
-	blk_free_count = blocks_freed + ext4_free_blks_count(sb, desc);
-	ext4_free_blks_set(sb, desc, blk_free_count);
+	blk_free_count = blocks_freed + ext4_free_group_clusters(sb, desc);
+	ext4_free_group_clusters_set(sb, desc, blk_free_count);
 	desc->bg_checksum = ext4_group_desc_csum(sbi, block_group, desc);
 	ext4_unlock_group(sb, block_group);
-	percpu_counter_add(&sbi->s_freeblocks_counter, blocks_freed);
+	percpu_counter_add(&sbi->s_freeclusters_counter,
+			   EXT4_B2C(sbi, blocks_freed));
 
 	if (sbi->s_log_groups_per_flex) {
 		ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
-		atomic_add(blocks_freed,
-			   &sbi->s_flex_groups[flex_group].free_blocks);
+		atomic_add(EXT4_B2C(sbi, blocks_freed),
+			   &sbi->s_flex_groups[flex_group].free_clusters);
 	}
 
 	ext4_mb_unload_buddy(&e4b);
@@ -4948,7 +5029,7 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
 	struct ext4_group_info *grp;
 	ext4_group_t first_group, last_group;
 	ext4_group_t group, ngroups = ext4_get_groups_count(sb);
-	ext4_grpblk_t cnt = 0, first_block, last_block;
+	ext4_grpblk_t cnt = 0, first_cluster, last_cluster;
 	uint64_t start, len, minlen, trimmed = 0;
 	ext4_fsblk_t first_data_blk =
 			le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
@@ -4958,7 +5039,7 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
 	len = range->len >> sb->s_blocksize_bits;
 	minlen = range->minlen >> sb->s_blocksize_bits;
 
-	if (unlikely(minlen > EXT4_BLOCKS_PER_GROUP(sb)))
+	if (unlikely(minlen > EXT4_CLUSTERS_PER_GROUP(sb)))
 		return -EINVAL;
 	if (start + len <= first_data_blk)
 		goto out;
@@ -4969,11 +5050,11 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
 
 	/* Determine first and last group to examine based on start and len */
 	ext4_get_group_no_and_offset(sb, (ext4_fsblk_t) start,
-				     &first_group, &first_block);
+				     &first_group, &first_cluster);
 	ext4_get_group_no_and_offset(sb, (ext4_fsblk_t) (start + len),
-				     &last_group, &last_block);
+				     &last_group, &last_cluster);
 	last_group = (last_group > ngroups - 1) ? ngroups - 1 : last_group;
-	last_block = EXT4_BLOCKS_PER_GROUP(sb);
+	last_cluster = EXT4_CLUSTERS_PER_GROUP(sb);
 
 	if (first_group > last_group)
 		return -EINVAL;
@@ -4993,20 +5074,20 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
 		 * change it for the last group in which case start +
 		 * len < EXT4_BLOCKS_PER_GROUP(sb).
 		 */
-		if (first_block + len < EXT4_BLOCKS_PER_GROUP(sb))
-			last_block = first_block + len;
-		len -= last_block - first_block;
+		if (first_cluster + len < EXT4_CLUSTERS_PER_GROUP(sb))
+			last_cluster = first_cluster + len;
+		len -= last_cluster - first_cluster;
 
 		if (grp->bb_free >= minlen) {
-			cnt = ext4_trim_all_free(sb, group, first_block,
-						last_block, minlen);
+			cnt = ext4_trim_all_free(sb, group, first_cluster,
+						last_cluster, minlen);
 			if (cnt < 0) {
 				ret = cnt;
 				break;
 			}
 		}
 		trimmed += cnt;
-		first_block = 0;
+		first_cluster = 0;
 	}
 	range->len = trimmed * sb->s_blocksize;
 
diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h
index 9d4a636..47705f3 100644
--- a/fs/ext4/mballoc.h
+++ b/fs/ext4/mballoc.h
@@ -106,7 +106,7 @@ struct ext4_free_data {
 	ext4_group_t group;
 
 	/* free block extent */
-	ext4_grpblk_t start_blk;
+	ext4_grpblk_t start_cluster;
 	ext4_grpblk_t count;
 
 	/* transaction which freed this extent */
@@ -139,9 +139,9 @@ enum {
 
 struct ext4_free_extent {
 	ext4_lblk_t fe_logical;
-	ext4_grpblk_t fe_start;
+	ext4_grpblk_t fe_start;	/* In cluster units */
 	ext4_group_t fe_group;
-	ext4_grpblk_t fe_len;
+	ext4_grpblk_t fe_len;	/* In cluster units */
 };
 
 /*
@@ -175,7 +175,7 @@ struct ext4_allocation_context {
 	/* the best found extent */
 	struct ext4_free_extent ac_b_ex;
 
-	/* copy of the bext found extent taken before preallocation efforts */
+	/* copy of the best found extent taken before preallocation efforts */
 	struct ext4_free_extent ac_f_ex;
 
 	/* number of iterations done. we have to track to limit searching */
@@ -216,6 +216,7 @@ struct ext4_buddy {
 static inline ext4_fsblk_t ext4_grp_offs_to_block(struct super_block *sb,
 					struct ext4_free_extent *fex)
 {
-	return ext4_group_first_block_no(sb, fex->fe_group) + fex->fe_start;
+	return ext4_group_first_block_no(sb, fex->fe_group) +
+		(fex->fe_start << EXT4_SB(sb)->s_cluster_bits);
 }
 #endif
diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
index b57b98f..16ac228 100644
--- a/fs/ext4/migrate.c
+++ b/fs/ext4/migrate.c
@@ -15,19 +15,18 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include "ext4_jbd2.h"
-#include "ext4_extents.h"
 
 /*
  * The contiguous blocks details which can be
  * represented by a single extent
  */
-struct list_blocks_struct {
-	ext4_lblk_t first_block, last_block;
+struct migrate_struct {
+	ext4_lblk_t first_block, last_block, curr_block;
 	ext4_fsblk_t first_pblock, last_pblock;
 };
 
 static int finish_range(handle_t *handle, struct inode *inode,
-				struct list_blocks_struct *lb)
+				struct migrate_struct *lb)
 
 {
 	int retval = 0, needed;
@@ -87,8 +86,7 @@ err_out:
 }
 
 static int update_extent_range(handle_t *handle, struct inode *inode,
-				ext4_fsblk_t pblock, ext4_lblk_t blk_num,
-				struct list_blocks_struct *lb)
+			       ext4_fsblk_t pblock, struct migrate_struct *lb)
 {
 	int retval;
 	/*
@@ -96,9 +94,10 @@ static int update_extent_range(handle_t *handle, struct inode *inode,
 	 */
 	if (lb->first_pblock &&
 		(lb->last_pblock+1 == pblock) &&
-		(lb->last_block+1 == blk_num)) {
+		(lb->last_block+1 == lb->curr_block)) {
 		lb->last_pblock = pblock;
-		lb->last_block = blk_num;
+		lb->last_block = lb->curr_block;
+		lb->curr_block++;
 		return 0;
 	}
 	/*
@@ -106,64 +105,49 @@ static int update_extent_range(handle_t *handle, struct inode *inode,
 	 */
 	retval = finish_range(handle, inode, lb);
 	lb->first_pblock = lb->last_pblock = pblock;
-	lb->first_block = lb->last_block = blk_num;
-
+	lb->first_block = lb->last_block = lb->curr_block;
+	lb->curr_block++;
 	return retval;
 }
 
 static int update_ind_extent_range(handle_t *handle, struct inode *inode,
-				   ext4_fsblk_t pblock, ext4_lblk_t *blk_nump,
-				   struct list_blocks_struct *lb)
+				   ext4_fsblk_t pblock,
+				   struct migrate_struct *lb)
 {
 	struct buffer_head *bh;
 	__le32 *i_data;
 	int i, retval = 0;
-	ext4_lblk_t blk_count = *blk_nump;
 	unsigned long max_entries = inode->i_sb->s_blocksize >> 2;
 
-	if (!pblock) {
-		/* Only update the file block number */
-		*blk_nump += max_entries;
-		return 0;
-	}
-
 	bh = sb_bread(inode->i_sb, pblock);
 	if (!bh)
 		return -EIO;
 
 	i_data = (__le32 *)bh->b_data;
-	for (i = 0; i < max_entries; i++, blk_count++) {
+	for (i = 0; i < max_entries; i++) {
 		if (i_data[i]) {
 			retval = update_extent_range(handle, inode,
-						le32_to_cpu(i_data[i]),
-						blk_count, lb);
+						le32_to_cpu(i_data[i]), lb);
 			if (retval)
 				break;
+		} else {
+			lb->curr_block++;
 		}
 	}
-
-	/* Update the file block number */
-	*blk_nump = blk_count;
 	put_bh(bh);
 	return retval;
 
 }
 
 static int update_dind_extent_range(handle_t *handle, struct inode *inode,
-				    ext4_fsblk_t pblock, ext4_lblk_t *blk_nump,
-				    struct list_blocks_struct *lb)
+				    ext4_fsblk_t pblock,
+				    struct migrate_struct *lb)
 {
 	struct buffer_head *bh;
 	__le32 *i_data;
 	int i, retval = 0;
-	ext4_lblk_t blk_count = *blk_nump;
 	unsigned long max_entries = inode->i_sb->s_blocksize >> 2;
 
-	if (!pblock) {
-		/* Only update the file block number */
-		*blk_nump += max_entries * max_entries;
-		return 0;
-	}
 	bh = sb_bread(inode->i_sb, pblock);
 	if (!bh)
 		return -EIO;
@@ -172,38 +156,28 @@ static int update_dind_extent_range(handle_t *handle, struct inode *inode,
 	for (i = 0; i < max_entries; i++) {
 		if (i_data[i]) {
 			retval = update_ind_extent_range(handle, inode,
-						le32_to_cpu(i_data[i]),
-						&blk_count, lb);
+						le32_to_cpu(i_data[i]), lb);
 			if (retval)
 				break;
 		} else {
 			/* Only update the file block number */
-			blk_count += max_entries;
+			lb->curr_block += max_entries;
 		}
 	}
-
-	/* Update the file block number */
-	*blk_nump = blk_count;
 	put_bh(bh);
 	return retval;
 
 }
 
 static int update_tind_extent_range(handle_t *handle, struct inode *inode,
-				     ext4_fsblk_t pblock, ext4_lblk_t *blk_nump,
-				     struct list_blocks_struct *lb)
+				    ext4_fsblk_t pblock,
+				    struct migrate_struct *lb)
 {
 	struct buffer_head *bh;
 	__le32 *i_data;
 	int i, retval = 0;
-	ext4_lblk_t blk_count = *blk_nump;
 	unsigned long max_entries = inode->i_sb->s_blocksize >> 2;
 
-	if (!pblock) {
-		/* Only update the file block number */
-		*blk_nump += max_entries * max_entries * max_entries;
-		return 0;
-	}
 	bh = sb_bread(inode->i_sb, pblock);
 	if (!bh)
 		return -EIO;
@@ -212,16 +186,14 @@ static int update_tind_extent_range(handle_t *handle, struct inode *inode,
 	for (i = 0; i < max_entries; i++) {
 		if (i_data[i]) {
 			retval = update_dind_extent_range(handle, inode,
-						le32_to_cpu(i_data[i]),
-						&blk_count, lb);
+						le32_to_cpu(i_data[i]), lb);
 			if (retval)
 				break;
-		} else
+		} else {
 			/* Only update the file block number */
-			blk_count += max_entries * max_entries;
+			lb->curr_block += max_entries * max_entries;
+		}
 	}
-	/* Update the file block number */
-	*blk_nump = blk_count;
 	put_bh(bh);
 	return retval;
 
@@ -462,12 +434,12 @@ int ext4_ext_migrate(struct inode *inode)
 	handle_t *handle;
 	int retval = 0, i;
 	__le32 *i_data;
-	ext4_lblk_t blk_count = 0;
 	struct ext4_inode_info *ei;
 	struct inode *tmp_inode = NULL;
-	struct list_blocks_struct lb;
+	struct migrate_struct lb;
 	unsigned long max_entries;
 	__u32 goal;
+	uid_t owner[2];
 
 	/*
 	 * If the filesystem does not support extents, or the inode
@@ -495,10 +467,12 @@ int ext4_ext_migrate(struct inode *inode)
 	}
 	goal = (((inode->i_ino - 1) / EXT4_INODES_PER_GROUP(inode->i_sb)) *
 		EXT4_INODES_PER_GROUP(inode->i_sb)) + 1;
+	owner[0] = inode->i_uid;
+	owner[1] = inode->i_gid;
 	tmp_inode = ext4_new_inode(handle, inode->i_sb->s_root->d_inode,
-				   S_IFREG, NULL, goal);
+				   S_IFREG, NULL, goal, owner);
 	if (IS_ERR(tmp_inode)) {
-		retval = -ENOMEM;
+		retval = PTR_ERR(inode);
 		ext4_journal_stop(handle);
 		return retval;
 	}
@@ -507,7 +481,7 @@ int ext4_ext_migrate(struct inode *inode)
 	 * Set the i_nlink to zero so it will be deleted later
 	 * when we drop inode reference.
 	 */
-	tmp_inode->i_nlink = 0;
+	clear_nlink(tmp_inode);
 
 	ext4_ext_tree_init(handle, tmp_inode);
 	ext4_orphan_add(handle, tmp_inode);
@@ -551,35 +525,32 @@ int ext4_ext_migrate(struct inode *inode)
 
 	/* 32 bit block address 4 bytes */
 	max_entries = inode->i_sb->s_blocksize >> 2;
-	for (i = 0; i < EXT4_NDIR_BLOCKS; i++, blk_count++) {
+	for (i = 0; i < EXT4_NDIR_BLOCKS; i++) {
 		if (i_data[i]) {
 			retval = update_extent_range(handle, tmp_inode,
-						le32_to_cpu(i_data[i]),
-						blk_count, &lb);
+						le32_to_cpu(i_data[i]), &lb);
 			if (retval)
 				goto err_out;
-		}
+		} else
+			lb.curr_block++;
 	}
 	if (i_data[EXT4_IND_BLOCK]) {
 		retval = update_ind_extent_range(handle, tmp_inode,
-					le32_to_cpu(i_data[EXT4_IND_BLOCK]),
-					&blk_count, &lb);
+				le32_to_cpu(i_data[EXT4_IND_BLOCK]), &lb);
 			if (retval)
 				goto err_out;
 	} else
-		blk_count +=  max_entries;
+		lb.curr_block += max_entries;
 	if (i_data[EXT4_DIND_BLOCK]) {
 		retval = update_dind_extent_range(handle, tmp_inode,
-					le32_to_cpu(i_data[EXT4_DIND_BLOCK]),
-					&blk_count, &lb);
+				le32_to_cpu(i_data[EXT4_DIND_BLOCK]), &lb);
 			if (retval)
 				goto err_out;
 	} else
-		blk_count += max_entries * max_entries;
+		lb.curr_block += max_entries * max_entries;
 	if (i_data[EXT4_TIND_BLOCK]) {
 		retval = update_tind_extent_range(handle, tmp_inode,
-					le32_to_cpu(i_data[EXT4_TIND_BLOCK]),
-					&blk_count, &lb);
+				le32_to_cpu(i_data[EXT4_TIND_BLOCK]), &lb);
 			if (retval)
 				goto err_out;
 	}
diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c
index 9bdef3f..7ea4ba4 100644
--- a/fs/ext4/mmp.c
+++ b/fs/ext4/mmp.c
@@ -109,7 +109,7 @@ static int kmmpd(void *data)
 	mmp->mmp_check_interval = cpu_to_le16(mmp_check_interval);
 	bdevname(bh->b_bdev, mmp->mmp_bdevname);
 
-	memcpy(mmp->mmp_nodename, init_utsname()->sysname,
+	memcpy(mmp->mmp_nodename, init_utsname()->nodename,
 	       sizeof(mmp->mmp_nodename));
 
 	while (!kthread_should_stop()) {
@@ -125,8 +125,9 @@ static int kmmpd(void *data)
 		 * Don't spew too many error messages. Print one every
 		 * (s_mmp_update_interval * 60) seconds.
 		 */
-		if (retval && (failed_writes % 60) == 0) {
-			ext4_error(sb, "Error writing to MMP block");
+		if (retval) {
+			if ((failed_writes % 60) == 0)
+				ext4_error(sb, "Error writing to MMP block");
 			failed_writes++;
 		}
 
@@ -295,7 +296,8 @@ skip:
 	/*
 	 * write a new random sequence number.
 	 */
-	mmp->mmp_seq = seq = cpu_to_le32(mmp_new_seq());
+	seq = mmp_new_seq();
+	mmp->mmp_seq = cpu_to_le32(seq);
 
 	retval = write_mmp_block(bh);
 	if (retval)
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
index f57455a..c5826c6 100644
--- a/fs/ext4/move_extent.c
+++ b/fs/ext4/move_extent.c
@@ -17,7 +17,6 @@
 #include <linux/quotaops.h>
 #include <linux/slab.h>
 #include "ext4_jbd2.h"
-#include "ext4_extents.h"
 #include "ext4.h"
 
 /**
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 1c924fa..aa4c782 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -1586,7 +1586,7 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
 			dxtrace(dx_show_index("node", frames[1].entries));
 			dxtrace(dx_show_index("node",
 			       ((struct dx_node *) bh2->b_data)->entries));
-			err = ext4_handle_dirty_metadata(handle, inode, bh2);
+			err = ext4_handle_dirty_metadata(handle, dir, bh2);
 			if (err)
 				goto journal_error;
 			brelse (bh2);
@@ -1612,7 +1612,7 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
 			if (err)
 				goto journal_error;
 		}
-		err = ext4_handle_dirty_metadata(handle, inode, frames[0].bh);
+		err = ext4_handle_dirty_metadata(handle, dir, frames[0].bh);
 		if (err) {
 			ext4_std_error(inode->i_sb, err);
 			goto cleanup;
@@ -1694,7 +1694,7 @@ static void ext4_inc_count(handle_t *handle, struct inode *inode)
 	if (is_dx(inode) && inode->i_nlink > 1) {
 		/* limit is 16-bit i_links_count */
 		if (inode->i_nlink >= EXT4_LINK_MAX || inode->i_nlink == 2) {
-			inode->i_nlink = 1;
+			set_nlink(inode, 1);
 			EXT4_SET_RO_COMPAT_FEATURE(inode->i_sb,
 					      EXT4_FEATURE_RO_COMPAT_DIR_NLINK);
 		}
@@ -1707,9 +1707,8 @@ static void ext4_inc_count(handle_t *handle, struct inode *inode)
  */
 static void ext4_dec_count(handle_t *handle, struct inode *inode)
 {
-	drop_nlink(inode);
-	if (S_ISDIR(inode->i_mode) && inode->i_nlink == 0)
-		inc_nlink(inode);
+	if (!S_ISDIR(inode->i_mode) || inode->i_nlink > 2)
+		drop_nlink(inode);
 }
 
 
@@ -1756,7 +1755,7 @@ retry:
 	if (IS_DIRSYNC(dir))
 		ext4_handle_sync(handle);
 
-	inode = ext4_new_inode(handle, dir, mode, &dentry->d_name, 0);
+	inode = ext4_new_inode(handle, dir, mode, &dentry->d_name, 0, NULL);
 	err = PTR_ERR(inode);
 	if (!IS_ERR(inode)) {
 		inode->i_op = &ext4_file_inode_operations;
@@ -1792,7 +1791,7 @@ retry:
 	if (IS_DIRSYNC(dir))
 		ext4_handle_sync(handle);
 
-	inode = ext4_new_inode(handle, dir, mode, &dentry->d_name, 0);
+	inode = ext4_new_inode(handle, dir, mode, &dentry->d_name, 0, NULL);
 	err = PTR_ERR(inode);
 	if (!IS_ERR(inode)) {
 		init_special_inode(inode, inode->i_mode, rdev);
@@ -1832,7 +1831,7 @@ retry:
 		ext4_handle_sync(handle);
 
 	inode = ext4_new_inode(handle, dir, S_IFDIR | mode,
-			       &dentry->d_name, 0);
+			       &dentry->d_name, 0, NULL);
 	err = PTR_ERR(inode);
 	if (IS_ERR(inode))
 		goto out_stop;
@@ -1861,9 +1860,9 @@ retry:
 	de->name_len = 2;
 	strcpy(de->name, "..");
 	ext4_set_de_type(dir->i_sb, de, S_IFDIR);
-	inode->i_nlink = 2;
+	set_nlink(inode, 2);
 	BUFFER_TRACE(dir_block, "call ext4_handle_dirty_metadata");
-	err = ext4_handle_dirty_metadata(handle, dir, dir_block);
+	err = ext4_handle_dirty_metadata(handle, inode, dir_block);
 	if (err)
 		goto out_clear_inode;
 	err = ext4_mark_inode_dirty(handle, inode);
@@ -2214,7 +2213,7 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
 		ext4_warning(inode->i_sb,
 			     "Deleting nonexistent file (%lu), %d",
 			     inode->i_ino, inode->i_nlink);
-		inode->i_nlink = 1;
+		set_nlink(inode, 1);
 	}
 	retval = ext4_delete_entry(handle, dir, de, bh);
 	if (retval)
@@ -2279,7 +2278,7 @@ retry:
 		ext4_handle_sync(handle);
 
 	inode = ext4_new_inode(handle, dir, S_IFLNK|S_IRWXUGO,
-			       &dentry->d_name, 0);
+			       &dentry->d_name, 0, NULL);
 	err = PTR_ERR(inode);
 	if (IS_ERR(inode))
 		goto out_stop;
@@ -2530,7 +2529,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
 		PARENT_INO(dir_bh->b_data, new_dir->i_sb->s_blocksize) =
 						cpu_to_le32(new_dir->i_ino);
 		BUFFER_TRACE(dir_bh, "call ext4_handle_dirty_metadata");
-		retval = ext4_handle_dirty_metadata(handle, old_dir, dir_bh);
+		retval = ext4_handle_dirty_metadata(handle, old_inode, dir_bh);
 		if (retval) {
 			ext4_std_error(old_dir->i_sb, retval);
 			goto end_rename;
@@ -2539,7 +2538,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
 		if (new_inode) {
 			/* checked empty_dir above, can't have another parent,
 			 * ext4_dec_count() won't work for many-linked dirs */
-			new_inode->i_nlink = 0;
+			clear_nlink(new_inode);
 		} else {
 			ext4_inc_count(handle, new_dir);
 			ext4_update_dx_flag(new_dir);
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
index 92f38ee..7ce1d0b 100644
--- a/fs/ext4/page-io.c
+++ b/fs/ext4/page-io.c
@@ -70,7 +70,6 @@ static void put_io_page(struct ext4_io_page *io_page)
 void ext4_free_io_end(ext4_io_end_t *io)
 {
 	int i;
-	wait_queue_head_t *wq;
 
 	BUG_ON(!io);
 	if (io->page)
@@ -78,56 +77,43 @@ void ext4_free_io_end(ext4_io_end_t *io)
 	for (i = 0; i < io->num_io_pages; i++)
 		put_io_page(io->pages[i]);
 	io->num_io_pages = 0;
-	wq = ext4_ioend_wq(io->inode);
-	if (atomic_dec_and_test(&EXT4_I(io->inode)->i_ioend_count) &&
-	    waitqueue_active(wq))
-		wake_up_all(wq);
+	if (atomic_dec_and_test(&EXT4_I(io->inode)->i_ioend_count))
+		wake_up_all(ext4_ioend_wq(io->inode));
 	kmem_cache_free(io_end_cachep, io);
 }
 
 /*
  * check a range of space and convert unwritten extents to written.
+ *
+ * Called with inode->i_mutex; we depend on this when we manipulate
+ * io->flag, since we could otherwise race with ext4_flush_completed_IO()
  */
 int ext4_end_io_nolock(ext4_io_end_t *io)
 {
 	struct inode *inode = io->inode;
 	loff_t offset = io->offset;
 	ssize_t size = io->size;
-	wait_queue_head_t *wq;
 	int ret = 0;
 
 	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 & EXT4_IO_END_UNWRITTEN))
-		return ret;
-
 	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 "
-			"io is still on inode %lu aio dio list\n",
-		       __func__, ret, inode->i_ino);
-		return ret;
+		ext4_msg(inode->i_sb, KERN_EMERG,
+			 "failed to convert unwritten extents to written "
+			 "extents -- potential data loss!  "
+			 "(inode %lu, offset %llu, size %zd, error %d)",
+			 inode->i_ino, offset, size, ret);
 	}
 
 	if (io->iocb)
 		aio_complete(io->iocb, io->result, 0);
-	/* clear the DIO AIO unwritten flag */
-	if (io->flag & EXT4_IO_END_UNWRITTEN) {
-		io->flag &= ~EXT4_IO_END_UNWRITTEN;
-		/* Wake up anyone waiting on unwritten extent conversion */
-		wq = ext4_ioend_wq(io->inode);
-		if (atomic_dec_and_test(&EXT4_I(inode)->i_aiodio_unwritten) &&
-		    waitqueue_active(wq)) {
-			wake_up_all(wq);
-		}
-	}
 
+	/* Wake up anyone waiting on unwritten extent conversion */
+	if (atomic_dec_and_test(&EXT4_I(inode)->i_aiodio_unwritten))
+		wake_up_all(ext4_ioend_wq(io->inode));
 	return ret;
 }
 
@@ -140,9 +126,15 @@ static void ext4_end_io_work(struct work_struct *work)
 	struct inode		*inode = io->inode;
 	struct ext4_inode_info	*ei = EXT4_I(inode);
 	unsigned long		flags;
-	int			ret;
+
+	spin_lock_irqsave(&ei->i_completed_io_lock, flags);
+	if (list_empty(&io->list)) {
+		spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
+		goto free;
+	}
 
 	if (!mutex_trylock(&inode->i_mutex)) {
+		spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
 		/*
 		 * Requeue the work instead of waiting so that the work
 		 * items queued after this can be processed.
@@ -159,17 +151,11 @@ static void ext4_end_io_work(struct work_struct *work)
 		io->flag |= EXT4_IO_END_QUEUED;
 		return;
 	}
-	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);
+	list_del_init(&io->list);
 	spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
+	(void) ext4_end_io_nolock(io);
 	mutex_unlock(&inode->i_mutex);
+free:
 	ext4_free_io_end(io);
 }
 
@@ -350,10 +336,8 @@ submit_and_retry:
 	if ((io_end->num_io_pages >= MAX_IO_PAGES) &&
 	    (io_end->pages[io_end->num_io_pages-1] != io_page))
 		goto submit_and_retry;
-	if (buffer_uninit(bh) && !(io_end->flag & EXT4_IO_END_UNWRITTEN)) {
-		io_end->flag |= EXT4_IO_END_UNWRITTEN;
-		atomic_inc(&EXT4_I(inode)->i_aiodio_unwritten);
-	}
+	if (buffer_uninit(bh))
+		ext4_set_io_unwritten_flag(inode, io_end);
 	io->io_end->size += bh->b_size;
 	io->io_next_block++;
 	ret = bio_add_page(io->io_bio, bh->b_page, bh->b_size, bh_offset(bh));
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
index 707d3f1..996780a 100644
--- a/fs/ext4/resize.c
+++ b/fs/ext4/resize.c
@@ -875,7 +875,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
 	ext4_block_bitmap_set(sb, gdp, input->block_bitmap); /* LV FIXME */
 	ext4_inode_bitmap_set(sb, gdp, input->inode_bitmap); /* LV FIXME */
 	ext4_inode_table_set(sb, gdp, input->inode_table); /* LV FIXME */
-	ext4_free_blks_set(sb, gdp, input->free_blocks_count);
+	ext4_free_group_clusters_set(sb, gdp, input->free_blocks_count);
 	ext4_free_inodes_set(sb, gdp, EXT4_INODES_PER_GROUP(sb));
 	gdp->bg_flags = cpu_to_le16(EXT4_BG_INODE_ZEROED);
 	gdp->bg_checksum = ext4_group_desc_csum(sbi, input->group, gdp);
@@ -937,8 +937,8 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
 		input->reserved_blocks);
 
 	/* Update the free space counts */
-	percpu_counter_add(&sbi->s_freeblocks_counter,
-			   input->free_blocks_count);
+	percpu_counter_add(&sbi->s_freeclusters_counter,
+			   EXT4_B2C(sbi, input->free_blocks_count));
 	percpu_counter_add(&sbi->s_freeinodes_counter,
 			   EXT4_INODES_PER_GROUP(sb));
 
@@ -946,8 +946,8 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
 	    sbi->s_log_groups_per_flex) {
 		ext4_group_t flex_group;
 		flex_group = ext4_flex_group(sbi, input->group);
-		atomic_add(input->free_blocks_count,
-			   &sbi->s_flex_groups[flex_group].free_blocks);
+		atomic_add(EXT4_B2C(sbi, input->free_blocks_count),
+			   &sbi->s_flex_groups[flex_group].free_clusters);
 		atomic_add(EXT4_INODES_PER_GROUP(sb),
 			   &sbi->s_flex_groups[flex_group].free_inodes);
 	}
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 44d0c8d..9953d80 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -45,6 +45,7 @@
 #include <linux/freezer.h>
 
 #include "ext4.h"
+#include "ext4_extents.h"
 #include "ext4_jbd2.h"
 #include "xattr.h"
 #include "acl.h"
@@ -163,8 +164,8 @@ ext4_fsblk_t ext4_inode_table(struct super_block *sb,
 		 (ext4_fsblk_t)le32_to_cpu(bg->bg_inode_table_hi) << 32 : 0);
 }
 
-__u32 ext4_free_blks_count(struct super_block *sb,
-			      struct ext4_group_desc *bg)
+__u32 ext4_free_group_clusters(struct super_block *sb,
+			       struct ext4_group_desc *bg)
 {
 	return le16_to_cpu(bg->bg_free_blocks_count_lo) |
 		(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
@@ -219,8 +220,8 @@ void ext4_inode_table_set(struct super_block *sb,
 		bg->bg_inode_table_hi = cpu_to_le32(blk >> 32);
 }
 
-void ext4_free_blks_set(struct super_block *sb,
-			  struct ext4_group_desc *bg, __u32 count)
+void ext4_free_group_clusters_set(struct super_block *sb,
+				  struct ext4_group_desc *bg, __u32 count)
 {
 	bg->bg_free_blocks_count_lo = cpu_to_le16((__u16)count);
 	if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
@@ -414,6 +415,22 @@ static void save_error_info(struct super_block *sb, const char *func,
 	ext4_commit_super(sb, 1);
 }
 
+/*
+ * The del_gendisk() function uninitializes the disk-specific data
+ * structures, including the bdi structure, without telling anyone
+ * else.  Once this happens, any attempt to call mark_buffer_dirty()
+ * (for example, by ext4_commit_super), will cause a kernel OOPS.
+ * This is a kludge to prevent these oops until we can put in a proper
+ * hook in del_gendisk() to inform the VFS and file system layers.
+ */
+static int block_device_ejected(struct super_block *sb)
+{
+	struct inode *bd_inode = sb->s_bdev->bd_inode;
+	struct backing_dev_info *bdi = bd_inode->i_mapping->backing_dev_info;
+
+	return bdi->dev == NULL;
+}
+
 
 /* Deal with the reporting of failure conditions on a filesystem such as
  * inconsistencies detected or read IO failures.
@@ -821,10 +838,10 @@ static void ext4_put_super(struct super_block *sb)
 		brelse(sbi->s_group_desc[i]);
 	ext4_kvfree(sbi->s_group_desc);
 	ext4_kvfree(sbi->s_flex_groups);
-	percpu_counter_destroy(&sbi->s_freeblocks_counter);
+	percpu_counter_destroy(&sbi->s_freeclusters_counter);
 	percpu_counter_destroy(&sbi->s_freeinodes_counter);
 	percpu_counter_destroy(&sbi->s_dirs_counter);
-	percpu_counter_destroy(&sbi->s_dirtyblocks_counter);
+	percpu_counter_destroy(&sbi->s_dirtyclusters_counter);
 	brelse(sbi->s_sbh);
 #ifdef CONFIG_QUOTA
 	for (i = 0; i < MAXQUOTAS; i++)
@@ -1057,8 +1074,6 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
 		seq_puts(seq, ",nouid32");
 	if (test_opt(sb, DEBUG) && !(def_mount_opts & EXT4_DEFM_DEBUG))
 		seq_puts(seq, ",debug");
-	if (test_opt(sb, OLDALLOC))
-		seq_puts(seq, ",oldalloc");
 #ifdef CONFIG_EXT4_FS_XATTR
 	if (test_opt(sb, XATTR_USER))
 		seq_puts(seq, ",user_xattr");
@@ -1567,10 +1582,12 @@ static int parse_options(char *options, struct super_block *sb,
 			set_opt(sb, DEBUG);
 			break;
 		case Opt_oldalloc:
-			set_opt(sb, OLDALLOC);
+			ext4_msg(sb, KERN_WARNING,
+				 "Ignoring deprecated oldalloc option");
 			break;
 		case Opt_orlov:
-			clear_opt(sb, OLDALLOC);
+			ext4_msg(sb, KERN_WARNING,
+				 "Ignoring deprecated orlov option");
 			break;
 #ifdef CONFIG_EXT4_FS_XATTR
 		case Opt_user_xattr:
@@ -1801,6 +1818,7 @@ set_qf_format:
 			break;
 		case Opt_nodelalloc:
 			clear_opt(sb, DELALLOC);
+			clear_opt2(sb, EXPLICIT_DELALLOC);
 			break;
 		case Opt_mblk_io_submit:
 			set_opt(sb, MBLK_IO_SUBMIT);
@@ -1817,6 +1835,7 @@ set_qf_format:
 			break;
 		case Opt_delalloc:
 			set_opt(sb, DELALLOC);
+			set_opt2(sb, EXPLICIT_DELALLOC);
 			break;
 		case Opt_block_validity:
 			set_opt(sb, BLOCK_VALIDITY);
@@ -1935,7 +1954,7 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
 		res = MS_RDONLY;
 	}
 	if (read_only)
-		return res;
+		goto done;
 	if (!(sbi->s_mount_state & EXT4_VALID_FS))
 		ext4_msg(sb, KERN_WARNING, "warning: mounting unchecked fs, "
 			 "running e2fsck is recommended");
@@ -1966,6 +1985,7 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
 		EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
 
 	ext4_commit_super(sb, 1);
+done:
 	if (test_opt(sb, DEBUG))
 		printk(KERN_INFO "[EXT4 FS bs=%lu, gc=%u, "
 				"bpg=%lu, ipg=%lu, mo=%04x, mo2=%04x]\n",
@@ -2015,8 +2035,8 @@ static int ext4_fill_flex_info(struct super_block *sb)
 		flex_group = ext4_flex_group(sbi, i);
 		atomic_add(ext4_free_inodes_count(sb, gdp),
 			   &sbi->s_flex_groups[flex_group].free_inodes);
-		atomic_add(ext4_free_blks_count(sb, gdp),
-			   &sbi->s_flex_groups[flex_group].free_blocks);
+		atomic_add(ext4_free_group_clusters(sb, gdp),
+			   &sbi->s_flex_groups[flex_group].free_clusters);
 		atomic_add(ext4_used_dirs_count(sb, gdp),
 			   &sbi->s_flex_groups[flex_group].used_dirs);
 	}
@@ -2134,7 +2154,8 @@ static int ext4_check_descriptors(struct super_block *sb,
 	if (NULL != first_not_zeroed)
 		*first_not_zeroed = grp;
 
-	ext4_free_blocks_count_set(sbi->s_es, ext4_count_free_blocks(sb));
+	ext4_free_blocks_count_set(sbi->s_es,
+				   EXT4_C2B(sbi, ext4_count_free_clusters(sb)));
 	sbi->s_es->s_free_inodes_count =cpu_to_le32(ext4_count_free_inodes(sb));
 	return 1;
 }
@@ -2454,7 +2475,8 @@ static ssize_t delayed_allocation_blocks_show(struct ext4_attr *a,
 					      char *buf)
 {
 	return snprintf(buf, PAGE_SIZE, "%llu\n",
-			(s64) percpu_counter_sum(&sbi->s_dirtyblocks_counter));
+		(s64) EXT4_C2B(sbi,
+			percpu_counter_sum(&sbi->s_dirtyclusters_counter)));
 }
 
 static ssize_t session_write_kbytes_show(struct ext4_attr *a,
@@ -2682,6 +2704,13 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly)
 			return 0;
 		}
 	}
+	if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_BIGALLOC) &&
+	    !EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
+		ext4_msg(sb, KERN_ERR,
+			 "Can't support bigalloc feature without "
+			 "extents feature\n");
+		return 0;
+	}
 	return 1;
 }
 
@@ -3087,10 +3116,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 	char *cp;
 	const char *descr;
 	int ret = -ENOMEM;
-	int blocksize;
+	int blocksize, clustersize;
 	unsigned int db_count;
 	unsigned int i;
-	int needs_recovery, has_huge_files;
+	int needs_recovery, has_huge_files, has_bigalloc;
 	__u64 blocks_count;
 	int err;
 	unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO;
@@ -3224,6 +3253,33 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 			   &journal_ioprio, NULL, 0))
 		goto failed_mount;
 
+	if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
+		printk_once(KERN_WARNING "EXT4-fs: Warning: mounting "
+			    "with data=journal disables delayed "
+			    "allocation and O_DIRECT support!\n");
+		if (test_opt2(sb, EXPLICIT_DELALLOC)) {
+			ext4_msg(sb, KERN_ERR, "can't mount with "
+				 "both data=journal and delalloc");
+			goto failed_mount;
+		}
+		if (test_opt(sb, DIOREAD_NOLOCK)) {
+			ext4_msg(sb, KERN_ERR, "can't mount with "
+				 "both data=journal and delalloc");
+			goto failed_mount;
+		}
+		if (test_opt(sb, DELALLOC))
+			clear_opt(sb, DELALLOC);
+	}
+
+	blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size);
+	if (test_opt(sb, DIOREAD_NOLOCK)) {
+		if (blocksize < PAGE_SIZE) {
+			ext4_msg(sb, KERN_ERR, "can't mount with "
+				 "dioread_nolock if block size != PAGE_SIZE");
+			goto failed_mount;
+		}
+	}
+
 	sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
 		(test_opt(sb, POSIX_ACL) ? MS_POSIXACL : 0);
 
@@ -3265,8 +3321,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 	if (!ext4_feature_set_ok(sb, (sb->s_flags & MS_RDONLY)))
 		goto failed_mount;
 
-	blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size);
-
 	if (blocksize < EXT4_MIN_BLOCK_SIZE ||
 	    blocksize > EXT4_MAX_BLOCK_SIZE) {
 		ext4_msg(sb, KERN_ERR,
@@ -3369,12 +3423,53 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 		sb->s_dirt = 1;
 	}
 
-	if (sbi->s_blocks_per_group > blocksize * 8) {
-		ext4_msg(sb, KERN_ERR,
-		       "#blocks per group too big: %lu",
-		       sbi->s_blocks_per_group);
-		goto failed_mount;
+	/* Handle clustersize */
+	clustersize = BLOCK_SIZE << le32_to_cpu(es->s_log_cluster_size);
+	has_bigalloc = EXT4_HAS_RO_COMPAT_FEATURE(sb,
+				EXT4_FEATURE_RO_COMPAT_BIGALLOC);
+	if (has_bigalloc) {
+		if (clustersize < blocksize) {
+			ext4_msg(sb, KERN_ERR,
+				 "cluster size (%d) smaller than "
+				 "block size (%d)", clustersize, blocksize);
+			goto failed_mount;
+		}
+		sbi->s_cluster_bits = le32_to_cpu(es->s_log_cluster_size) -
+			le32_to_cpu(es->s_log_block_size);
+		sbi->s_clusters_per_group =
+			le32_to_cpu(es->s_clusters_per_group);
+		if (sbi->s_clusters_per_group > blocksize * 8) {
+			ext4_msg(sb, KERN_ERR,
+				 "#clusters per group too big: %lu",
+				 sbi->s_clusters_per_group);
+			goto failed_mount;
+		}
+		if (sbi->s_blocks_per_group !=
+		    (sbi->s_clusters_per_group * (clustersize / blocksize))) {
+			ext4_msg(sb, KERN_ERR, "blocks per group (%lu) and "
+				 "clusters per group (%lu) inconsistent",
+				 sbi->s_blocks_per_group,
+				 sbi->s_clusters_per_group);
+			goto failed_mount;
+		}
+	} else {
+		if (clustersize != blocksize) {
+			ext4_warning(sb, "fragment/cluster size (%d) != "
+				     "block size (%d)", clustersize,
+				     blocksize);
+			clustersize = blocksize;
+		}
+		if (sbi->s_blocks_per_group > blocksize * 8) {
+			ext4_msg(sb, KERN_ERR,
+				 "#blocks per group too big: %lu",
+				 sbi->s_blocks_per_group);
+			goto failed_mount;
+		}
+		sbi->s_clusters_per_group = sbi->s_blocks_per_group;
+		sbi->s_cluster_bits = 0;
 	}
+	sbi->s_cluster_ratio = clustersize / blocksize;
+
 	if (sbi->s_inodes_per_group > blocksize * 8) {
 		ext4_msg(sb, KERN_ERR,
 		       "#inodes per group too big: %lu",
@@ -3446,10 +3541,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 		goto failed_mount;
 	}
 
-#ifdef CONFIG_PROC_FS
 	if (ext4_proc_root)
 		sbi->s_proc = proc_mkdir(sb->s_id, ext4_proc_root);
-#endif
 
 	bgl_lock_init(sbi->s_blockgroup_lock);
 
@@ -3483,8 +3576,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 	sbi->s_err_report.function = print_daily_error_info;
 	sbi->s_err_report.data = (unsigned long) sb;
 
-	err = percpu_counter_init(&sbi->s_freeblocks_counter,
-			ext4_count_free_blocks(sb));
+	err = percpu_counter_init(&sbi->s_freeclusters_counter,
+			ext4_count_free_clusters(sb));
 	if (!err) {
 		err = percpu_counter_init(&sbi->s_freeinodes_counter,
 				ext4_count_free_inodes(sb));
@@ -3494,7 +3587,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 				ext4_count_dirs(sb));
 	}
 	if (!err) {
-		err = percpu_counter_init(&sbi->s_dirtyblocks_counter, 0);
+		err = percpu_counter_init(&sbi->s_dirtyclusters_counter, 0);
 	}
 	if (err) {
 		ext4_msg(sb, KERN_ERR, "insufficient memory");
@@ -3609,13 +3702,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 	 * The journal may have updated the bg summary counts, so we
 	 * need to update the global counters.
 	 */
-	percpu_counter_set(&sbi->s_freeblocks_counter,
-			   ext4_count_free_blocks(sb));
+	percpu_counter_set(&sbi->s_freeclusters_counter,
+			   ext4_count_free_clusters(sb));
 	percpu_counter_set(&sbi->s_freeinodes_counter,
 			   ext4_count_free_inodes(sb));
 	percpu_counter_set(&sbi->s_dirs_counter,
 			   ext4_count_dirs(sb));
-	percpu_counter_set(&sbi->s_dirtyblocks_counter, 0);
+	percpu_counter_set(&sbi->s_dirtyclusters_counter, 0);
 
 no_journal:
 	/*
@@ -3679,25 +3772,6 @@ no_journal:
 			 "available");
 	}
 
-	if (test_opt(sb, DELALLOC) &&
-	    (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)) {
-		ext4_msg(sb, KERN_WARNING, "Ignoring delalloc option - "
-			 "requested data journaling mode");
-		clear_opt(sb, 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(sb, DIOREAD_NOLOCK);
-		}
-		if (sb->s_blocksize < PAGE_SIZE) {
-			ext4_msg(sb, KERN_WARNING, "Ignoring dioread_nolock "
-				"option - block size is too small");
-			clear_opt(sb, DIOREAD_NOLOCK);
-		}
-	}
-
 	err = ext4_setup_system_zone(sb);
 	if (err) {
 		ext4_msg(sb, KERN_ERR, "failed to initialize system "
@@ -3710,22 +3784,19 @@ no_journal:
 	if (err) {
 		ext4_msg(sb, KERN_ERR, "failed to initialize mballoc (%d)",
 			 err);
-		goto failed_mount4;
+		goto failed_mount5;
 	}
 
 	err = ext4_register_li_request(sb, first_not_zeroed);
 	if (err)
-		goto failed_mount4;
+		goto failed_mount6;
 
 	sbi->s_kobj.kset = ext4_kset;
 	init_completion(&sbi->s_kobj_unregister);
 	err = kobject_init_and_add(&sbi->s_kobj, &ext4_ktype, NULL,
 				   "%s", sb->s_id);
-	if (err) {
-		ext4_mb_release(sb);
-		ext4_ext_release(sb);
-		goto failed_mount4;
-	};
+	if (err)
+		goto failed_mount7;
 
 	EXT4_SB(sb)->s_mount_state |= EXT4_ORPHAN_FS;
 	ext4_orphan_cleanup(sb, es);
@@ -3759,13 +3830,19 @@ cantfind_ext4:
 		ext4_msg(sb, KERN_ERR, "VFS: Can't find ext4 filesystem");
 	goto failed_mount;
 
+failed_mount7:
+	ext4_unregister_li_request(sb);
+failed_mount6:
+	ext4_ext_release(sb);
+failed_mount5:
+	ext4_mb_release(sb);
+	ext4_release_system_zone(sb);
 failed_mount4:
 	iput(root);
 	sb->s_root = NULL;
 	ext4_msg(sb, KERN_ERR, "mount failed");
 	destroy_workqueue(EXT4_SB(sb)->dio_unwritten_wq);
 failed_mount_wq:
-	ext4_release_system_zone(sb);
 	if (sbi->s_journal) {
 		jbd2_journal_destroy(sbi->s_journal);
 		sbi->s_journal = NULL;
@@ -3774,10 +3851,10 @@ failed_mount3:
 	del_timer(&sbi->s_err_report);
 	if (sbi->s_flex_groups)
 		ext4_kvfree(sbi->s_flex_groups);
-	percpu_counter_destroy(&sbi->s_freeblocks_counter);
+	percpu_counter_destroy(&sbi->s_freeclusters_counter);
 	percpu_counter_destroy(&sbi->s_freeinodes_counter);
 	percpu_counter_destroy(&sbi->s_dirs_counter);
-	percpu_counter_destroy(&sbi->s_dirtyblocks_counter);
+	percpu_counter_destroy(&sbi->s_dirtyclusters_counter);
 	if (sbi->s_mmp_tsk)
 		kthread_stop(sbi->s_mmp_tsk);
 failed_mount2:
@@ -4064,7 +4141,7 @@ static int ext4_commit_super(struct super_block *sb, int sync)
 	struct buffer_head *sbh = EXT4_SB(sb)->s_sbh;
 	int error = 0;
 
-	if (!sbh)
+	if (!sbh || block_device_ejected(sb))
 		return error;
 	if (buffer_write_io_error(sbh)) {
 		/*
@@ -4100,8 +4177,9 @@ static int ext4_commit_super(struct super_block *sb, int sync)
 	else
 		es->s_kbytes_written =
 			cpu_to_le64(EXT4_SB(sb)->s_kbytes_written);
-	ext4_free_blocks_count_set(es, percpu_counter_sum_positive(
-					   &EXT4_SB(sb)->s_freeblocks_counter));
+	ext4_free_blocks_count_set(es,
+			EXT4_C2B(EXT4_SB(sb), percpu_counter_sum_positive(
+				&EXT4_SB(sb)->s_freeclusters_counter)));
 	es->s_free_inodes_count =
 		cpu_to_le32(percpu_counter_sum_positive(
 				&EXT4_SB(sb)->s_freeinodes_counter));
@@ -4506,16 +4584,34 @@ restore_opts:
 	return err;
 }
 
+/*
+ * Note: calculating the overhead so we can be compatible with
+ * historical BSD practice is quite difficult in the face of
+ * clusters/bigalloc.  This is because multiple metadata blocks from
+ * different block group can end up in the same allocation cluster.
+ * Calculating the exact overhead in the face of clustered allocation
+ * requires either O(all block bitmaps) in memory or O(number of block
+ * groups**2) in time.  We will still calculate the superblock for
+ * older file systems --- and if we come across with a bigalloc file
+ * system with zero in s_overhead_clusters the estimate will be close to
+ * correct especially for very large cluster sizes --- but for newer
+ * file systems, it's better to calculate this figure once at mkfs
+ * time, and store it in the superblock.  If the superblock value is
+ * present (even for non-bigalloc file systems), we will use it.
+ */
 static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
 	struct super_block *sb = dentry->d_sb;
 	struct ext4_sb_info *sbi = EXT4_SB(sb);
 	struct ext4_super_block *es = sbi->s_es;
+	struct ext4_group_desc *gdp;
 	u64 fsid;
 	s64 bfree;
 
 	if (test_opt(sb, MINIX_DF)) {
 		sbi->s_overhead_last = 0;
+	} else if (es->s_overhead_clusters) {
+		sbi->s_overhead_last = le32_to_cpu(es->s_overhead_clusters);
 	} else if (sbi->s_blocks_last != ext4_blocks_count(es)) {
 		ext4_group_t i, ngroups = ext4_get_groups_count(sb);
 		ext4_fsblk_t overhead = 0;
@@ -4530,24 +4626,16 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)
 		 * All of the blocks before first_data_block are
 		 * overhead
 		 */
-		overhead = le32_to_cpu(es->s_first_data_block);
+		overhead = EXT4_B2C(sbi, le32_to_cpu(es->s_first_data_block));
 
 		/*
-		 * Add the overhead attributed to the superblock and
-		 * block group descriptors.  If the sparse superblocks
-		 * feature is turned on, then not all groups have this.
+		 * Add the overhead found in each block group
 		 */
 		for (i = 0; i < ngroups; i++) {
-			overhead += ext4_bg_has_super(sb, i) +
-				ext4_bg_num_gdb(sb, i);
+			gdp = ext4_get_group_desc(sb, i, NULL);
+			overhead += ext4_num_overhead_clusters(sb, i, gdp);
 			cond_resched();
 		}
-
-		/*
-		 * Every block group has an inode bitmap, a block
-		 * bitmap, and an inode table.
-		 */
-		overhead += ngroups * (2 + sbi->s_itb_per_group);
 		sbi->s_overhead_last = overhead;
 		smp_wmb();
 		sbi->s_blocks_last = ext4_blocks_count(es);
@@ -4555,11 +4643,12 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)
 
 	buf->f_type = EXT4_SUPER_MAGIC;
 	buf->f_bsize = sb->s_blocksize;
-	buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last;
-	bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter) -
-		       percpu_counter_sum_positive(&sbi->s_dirtyblocks_counter);
+	buf->f_blocks = (ext4_blocks_count(es) -
+			 EXT4_C2B(sbi, sbi->s_overhead_last));
+	bfree = percpu_counter_sum_positive(&sbi->s_freeclusters_counter) -
+		percpu_counter_sum_positive(&sbi->s_dirtyclusters_counter);
 	/* prevent underflow in case that few free space is available */
-	buf->f_bfree = max_t(s64, bfree, 0);
+	buf->f_bfree = EXT4_C2B(sbi, max_t(s64, bfree, 0));
 	buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es);
 	if (buf->f_bfree < ext4_r_blocks_count(es))
 		buf->f_bavail = 0;
@@ -4980,13 +5069,11 @@ static int __init ext4_init_fs(void)
 		return err;
 	err = ext4_init_system_zone();
 	if (err)
-		goto out7;
+		goto out6;
 	ext4_kset = kset_create_and_add("ext4", NULL, fs_kobj);
 	if (!ext4_kset)
-		goto out6;
-	ext4_proc_root = proc_mkdir("fs/ext4", NULL);
-	if (!ext4_proc_root)
 		goto out5;
+	ext4_proc_root = proc_mkdir("fs/ext4", NULL);
 
 	err = ext4_init_feat_adverts();
 	if (err)
@@ -5022,12 +5109,12 @@ out2:
 out3:
 	ext4_exit_feat_adverts();
 out4:
-	remove_proc_entry("fs/ext4", NULL);
-out5:
+	if (ext4_proc_root)
+		remove_proc_entry("fs/ext4", NULL);
 	kset_unregister(ext4_kset);
-out6:
+out5:
 	ext4_exit_system_zone();
-out7:
+out6:
 	ext4_exit_pageio();
 	return err;
 }
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index c757adc..93a00d8 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -820,8 +820,14 @@ inserted:
 			if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
 				goal = goal & EXT4_MAX_BLOCK_FILE_PHYS;
 
+			/*
+			 * take i_data_sem because we will test
+			 * i_delalloc_reserved_flag in ext4_mb_new_blocks
+			 */
+			down_read((&EXT4_I(inode)->i_data_sem));
 			block = ext4_new_meta_blocks(handle, inode, goal, 0,
 						     NULL, &error);
+			up_read((&EXT4_I(inode)->i_data_sem));
 			if (error)
 				goto cleanup;
 
@@ -985,11 +991,7 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
 	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)
-		goto cleanup;
-
-	error = ext4_journal_get_write_access(handle, is.iloc.bh);
+	error = ext4_reserve_inode_write(handle, inode, &is.iloc);
 	if (error)
 		goto cleanup;
 
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 1726d73..808cac7 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -379,7 +379,7 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
 			return error;
 		MSDOS_I(inode)->mmu_private = inode->i_size;
 
-		inode->i_nlink = fat_subdirs(inode);
+		set_nlink(inode, fat_subdirs(inode));
 	} else { /* not a directory */
 		inode->i_generation |= 1;
 		inode->i_mode = fat_make_mode(sbi, de->attr,
@@ -1233,7 +1233,7 @@ static int fat_read_root(struct inode *inode)
 	fat_save_attrs(inode, ATTR_DIR);
 	inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec = 0;
 	inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = 0;
-	inode->i_nlink = fat_subdirs(inode)+2;
+	set_nlink(inode, fat_subdirs(inode)+2);
 
 	return 0;
 }
diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c
index 66e83b8..216b419 100644
--- a/fs/fat/namei_msdos.c
+++ b/fs/fat/namei_msdos.c
@@ -387,7 +387,7 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 		/* the directory was completed, just return a error */
 		goto out;
 	}
-	inode->i_nlink = 2;
+	set_nlink(inode, 2);
 	inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
 	/* timestamp is already written, so mark_inode_dirty() is unneeded. */
 
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
index bb3f29c..a87a656 100644
--- a/fs/fat/namei_vfat.c
+++ b/fs/fat/namei_vfat.c
@@ -900,7 +900,7 @@ static int vfat_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 		goto out;
 	}
 	inode->i_version++;
-	inode->i_nlink = 2;
+	set_nlink(inode, 2);
 	inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
 	/* timestamp is already written, so mark_inode_dirty() is unneeded. */
 
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
index 1a43114..7b2af5a 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -227,7 +227,7 @@ vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip)
 	ip->i_uid = (uid_t)vip->vii_uid;
 	ip->i_gid = (gid_t)vip->vii_gid;
 
-	ip->i_nlink = vip->vii_nlink;
+	set_nlink(ip, vip->vii_nlink);
 	ip->i_size = vip->vii_size;
 
 	ip->i_atime.tv_sec = vip->vii_atime;
diff --git a/fs/fuse/control.c b/fs/fuse/control.c
index 85542a7..42593c5 100644
--- a/fs/fuse/control.c
+++ b/fs/fuse/control.c
@@ -231,7 +231,7 @@ static struct dentry *fuse_ctl_add_dentry(struct dentry *parent,
 	if (iop)
 		inode->i_op = iop;
 	inode->i_fop = fop;
-	inode->i_nlink = nlink;
+	set_nlink(inode, nlink);
 	inode->i_private = fc;
 	d_add(dentry, inode);
 	return dentry;
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index add96f6..3e6d727 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -151,7 +151,7 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
 
 	inode->i_ino     = attr->ino;
 	inode->i_mode    = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
-	inode->i_nlink   = attr->nlink;
+	set_nlink(inode, attr->nlink);
 	inode->i_uid     = attr->uid;
 	inode->i_gid     = attr->gid;
 	inode->i_blocks  = attr->blocks;
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 78418b4..1656df7 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -299,7 +299,7 @@ static void gfs2_set_nlink(struct inode *inode, u32 nlink)
 		if (nlink == 0)
 			clear_nlink(inode);
 		else
-			inode->i_nlink = nlink;
+			set_nlink(inode, nlink);
 	}
 }
 
diff --git a/fs/hfs/btree.c b/fs/hfs/btree.c
index 3ebc437..1cbdeea 100644
--- a/fs/hfs/btree.c
+++ b/fs/hfs/btree.c
@@ -46,11 +46,26 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp ke
 	case HFS_EXT_CNID:
 		hfs_inode_read_fork(tree->inode, mdb->drXTExtRec, mdb->drXTFlSize,
 				    mdb->drXTFlSize, be32_to_cpu(mdb->drXTClpSiz));
+		if (HFS_I(tree->inode)->alloc_blocks >
+					HFS_I(tree->inode)->first_blocks) {
+			printk(KERN_ERR "hfs: invalid btree extent records\n");
+			unlock_new_inode(tree->inode);
+			goto free_inode;
+		}
+
 		tree->inode->i_mapping->a_ops = &hfs_btree_aops;
 		break;
 	case HFS_CAT_CNID:
 		hfs_inode_read_fork(tree->inode, mdb->drCTExtRec, mdb->drCTFlSize,
 				    mdb->drCTFlSize, be32_to_cpu(mdb->drCTClpSiz));
+
+		if (!HFS_I(tree->inode)->first_blocks) {
+			printk(KERN_ERR "hfs: invalid btree extent records "
+								"(0 size).\n");
+			unlock_new_inode(tree->inode);
+			goto free_inode;
+		}
+
 		tree->inode->i_mapping->a_ops = &hfs_btree_aops;
 		break;
 	default:
@@ -59,11 +74,6 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp ke
 	}
 	unlock_new_inode(tree->inode);
 
-	if (!HFS_I(tree->inode)->first_blocks) {
-		printk(KERN_ERR "hfs: invalid btree extent records (0 size).\n");
-		goto free_inode;
-	}
-
 	mapping = tree->inode->i_mapping;
 	page = read_mapping_page(mapping, 0, NULL);
 	if (IS_ERR(page))
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c
index b4d70b1..bce4eef 100644
--- a/fs/hfs/dir.c
+++ b/fs/hfs/dir.c
@@ -198,7 +198,7 @@ static int hfs_create(struct inode *dir, struct dentry *dentry, int mode,
 
 	res = hfs_cat_create(inode->i_ino, dir, &dentry->d_name, inode);
 	if (res) {
-		inode->i_nlink = 0;
+		clear_nlink(inode);
 		hfs_delete_inode(inode);
 		iput(inode);
 		return res;
@@ -227,7 +227,7 @@ static int hfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 
 	res = hfs_cat_create(inode->i_ino, dir, &dentry->d_name, inode);
 	if (res) {
-		inode->i_nlink = 0;
+		clear_nlink(inode);
 		hfs_delete_inode(inode);
 		iput(inode);
 		return res;
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 96a1b62..a1a9fdc 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -183,7 +183,7 @@ struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, int mode)
 	inode->i_mode = mode;
 	inode->i_uid = current_fsuid();
 	inode->i_gid = current_fsgid();
-	inode->i_nlink = 1;
+	set_nlink(inode, 1);
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
 	HFS_I(inode)->flags = 0;
 	HFS_I(inode)->rsrc_inode = NULL;
@@ -313,7 +313,7 @@ static int hfs_read_inode(struct inode *inode, void *data)
 	/* Initialize the inode */
 	inode->i_uid = hsb->s_uid;
 	inode->i_gid = hsb->s_gid;
-	inode->i_nlink = 1;
+	set_nlink(inode, 1);
 
 	if (idata->key)
 		HFS_I(inode)->cat_key = *idata->key;
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index 25b2443..4536cd3 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -415,7 +415,7 @@ static int hfsplus_symlink(struct inode *dir, struct dentry *dentry,
 	goto out;
 
 out_err:
-	inode->i_nlink = 0;
+	clear_nlink(inode);
 	hfsplus_delete_inode(inode);
 	iput(inode);
 out:
@@ -440,7 +440,7 @@ static int hfsplus_mknod(struct inode *dir, struct dentry *dentry,
 
 	res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode);
 	if (res) {
-		inode->i_nlink = 0;
+		clear_nlink(inode);
 		hfsplus_delete_inode(inode);
 		iput(inode);
 		goto out;
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 4cc1e3a..40e1413 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -391,7 +391,7 @@ struct inode *hfsplus_new_inode(struct super_block *sb, int mode)
 	inode->i_mode = mode;
 	inode->i_uid = current_fsuid();
 	inode->i_gid = current_fsgid();
-	inode->i_nlink = 1;
+	set_nlink(inode, 1);
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
 
 	hip = HFSPLUS_I(inode);
@@ -512,7 +512,7 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
 		hfs_bnode_read(fd->bnode, &entry, fd->entryoffset,
 					sizeof(struct hfsplus_cat_folder));
 		hfsplus_get_perms(inode, &folder->permissions, 1);
-		inode->i_nlink = 1;
+		set_nlink(inode, 1);
 		inode->i_size = 2 + be32_to_cpu(folder->valence);
 		inode->i_atime = hfsp_mt2ut(folder->access_date);
 		inode->i_mtime = hfsp_mt2ut(folder->content_mod_date);
@@ -532,11 +532,11 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
 		hfsplus_inode_read_fork(inode, HFSPLUS_IS_RSRC(inode) ?
 					&file->rsrc_fork : &file->data_fork);
 		hfsplus_get_perms(inode, &file->permissions, 0);
-		inode->i_nlink = 1;
+		set_nlink(inode, 1);
 		if (S_ISREG(inode->i_mode)) {
 			if (file->permissions.dev)
-				inode->i_nlink =
-					be32_to_cpu(file->permissions.dev);
+				set_nlink(inode,
+					  be32_to_cpu(file->permissions.dev));
 			inode->i_op = &hfsplus_file_inode_operations;
 			inode->i_fop = &hfsplus_file_operations;
 			inode->i_mapping->a_ops = &hfsplus_aops;
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 0d22afd..2f72da5 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -541,7 +541,7 @@ static int read_name(struct inode *ino, char *name)
 
 	ino->i_ino = st.ino;
 	ino->i_mode = st.mode;
-	ino->i_nlink = st.nlink;
+	set_nlink(ino, st.nlink);
 	ino->i_uid = st.uid;
 	ino->i_gid = st.gid;
 	ino->i_atime = st.atime;
diff --git a/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c
index d51a983..dd7bc38 100644
--- a/fs/hostfs/hostfs_user.c
+++ b/fs/hostfs/hostfs_user.c
@@ -16,7 +16,6 @@
 #include <sys/vfs.h>
 #include "hostfs.h"
 #include "os.h"
-#include "user.h"
 #include <utime.h>
 
 static void stat64_to_hostfs(const struct stat64 *buf, struct hostfs_stat *p)
diff --git a/fs/hpfs/dir.c b/fs/hpfs/dir.c
index 96a8ed9..2fa0089 100644
--- a/fs/hpfs/dir.c
+++ b/fs/hpfs/dir.c
@@ -247,7 +247,7 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name
 			result->i_mode &= ~0111;
 			result->i_op = &hpfs_file_iops;
 			result->i_fop = &hpfs_file_ops;
-			result->i_nlink = 1;
+			set_nlink(result, 1);
 		}
 		unlock_new_inode(result);
 	}
diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c
index 338cd83..3b2cec2 100644
--- a/fs/hpfs/inode.c
+++ b/fs/hpfs/inode.c
@@ -53,7 +53,7 @@ void hpfs_read_inode(struct inode *i)
 		i->i_mode &= ~0111;
 		i->i_op = &hpfs_file_iops;
 		i->i_fop = &hpfs_file_ops;
-		i->i_nlink = 0;*/
+		clear_nlink(i);*/
 		make_bad_inode(i);
 		return;
 	}
@@ -77,7 +77,7 @@ void hpfs_read_inode(struct inode *i)
 			i->i_mode = S_IFLNK | 0777;
 			i->i_op = &page_symlink_inode_operations;
 			i->i_data.a_ops = &hpfs_symlink_aops;
-			i->i_nlink = 1;
+			set_nlink(i, 1);
 			i->i_size = ea_size;
 			i->i_blocks = 1;
 			brelse(bh);
@@ -101,7 +101,7 @@ void hpfs_read_inode(struct inode *i)
 			}
 			if (S_ISBLK(mode) || S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) {
 				brelse(bh);
-				i->i_nlink = 1;
+				set_nlink(i, 1);
 				i->i_size = 0;
 				i->i_blocks = 1;
 				init_special_inode(i, mode,
@@ -125,13 +125,13 @@ void hpfs_read_inode(struct inode *i)
 		hpfs_count_dnodes(i->i_sb, hpfs_inode->i_dno, &n_dnodes, &n_subdirs, NULL);
 		i->i_blocks = 4 * n_dnodes;
 		i->i_size = 2048 * n_dnodes;
-		i->i_nlink = 2 + n_subdirs;
+		set_nlink(i, 2 + n_subdirs);
 	} else {
 		i->i_mode |= S_IFREG;
 		if (!hpfs_inode->i_ea_mode) i->i_mode &= ~0111;
 		i->i_op = &hpfs_file_iops;
 		i->i_fop = &hpfs_file_ops;
-		i->i_nlink = 1;
+		set_nlink(i, 1);
 		i->i_size = le32_to_cpu(fnode->file_size);
 		i->i_blocks = ((i->i_size + 511) >> 9) + 1;
 		i->i_data.a_ops = &hpfs_aops;
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c
index 2df69e2..ea91fcb 100644
--- a/fs/hpfs/namei.c
+++ b/fs/hpfs/namei.c
@@ -56,7 +56,7 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 	result->i_fop = &hpfs_dir_ops;
 	result->i_blocks = 4;
 	result->i_size = 2048;
-	result->i_nlink = 2;
+	set_nlink(result, 2);
 	if (dee.read_only)
 		result->i_mode &= ~0222;
 
@@ -150,7 +150,7 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc
 	result->i_mode &= ~0111;
 	result->i_op = &hpfs_file_iops;
 	result->i_fop = &hpfs_file_ops;
-	result->i_nlink = 1;
+	set_nlink(result, 1);
 	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, le32_to_cpu(dee.creation_date));
 	result->i_ctime.tv_nsec = 0;
@@ -242,7 +242,7 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t
 	hpfs_i(result)->i_ea_size = 0;
 	result->i_uid = current_fsuid();
 	result->i_gid = current_fsgid();
-	result->i_nlink = 1;
+	set_nlink(result, 1);
 	result->i_size = 0;
 	result->i_blocks = 1;
 	init_special_inode(result, mode, rdev);
@@ -318,7 +318,7 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy
 	result->i_uid = current_fsuid();
 	result->i_gid = current_fsgid();
 	result->i_blocks = 1;
-	result->i_nlink = 1;
+	set_nlink(result, 1);
 	result->i_size = strlen(symlink);
 	result->i_op = &page_symlink_inode_operations;
 	result->i_data.a_ops = &hpfs_symlink_aops;
diff --git a/fs/hppfs/hppfs.c b/fs/hppfs/hppfs.c
index 970ea98..f590b11 100644
--- a/fs/hppfs/hppfs.c
+++ b/fs/hppfs/hppfs.c
@@ -702,7 +702,7 @@ static struct inode *get_inode(struct super_block *sb, struct dentry *dentry)
 	inode->i_ctime = proc_ino->i_ctime;
 	inode->i_ino = proc_ino->i_ino;
 	inode->i_mode = proc_ino->i_mode;
-	inode->i_nlink = proc_ino->i_nlink;
+	set_nlink(inode, proc_ino->i_nlink);
 	inode->i_size = proc_ino->i_size;
 	inode->i_blocks = proc_ino->i_blocks;
 
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index ec88953..0be5a78 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -970,7 +970,7 @@ struct file *hugetlb_file_setup(const char *name, size_t size,
 
 	d_instantiate(path.dentry, inode);
 	inode->i_size = size;
-	inode->i_nlink = 0;
+	clear_nlink(inode);
 
 	error = -ENFILE;
 	file = alloc_file(&path, FMODE_WRITE | FMODE_READ,
diff --git a/fs/inode.c b/fs/inode.c
index ecbb68d..ee4e66b 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -142,7 +142,7 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
 	atomic_set(&inode->i_count, 1);
 	inode->i_op = &empty_iops;
 	inode->i_fop = &empty_fops;
-	inode->i_nlink = 1;
+	inode->__i_nlink = 1;
 	inode->i_opflags = 0;
 	inode->i_uid = 0;
 	inode->i_gid = 0;
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index a5d0367..f950059 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -20,6 +20,7 @@
 #include <linux/statfs.h>
 #include <linux/cdrom.h>
 #include <linux/parser.h>
+#include <linux/mpage.h>
 
 #include "isofs.h"
 #include "zisofs.h"
@@ -1148,7 +1149,13 @@ struct buffer_head *isofs_bread(struct inode *inode, sector_t block)
 
 static int isofs_readpage(struct file *file, struct page *page)
 {
-	return block_read_full_page(page,isofs_get_block);
+	return mpage_readpage(page, isofs_get_block);
+}
+
+static int isofs_readpages(struct file *file, struct address_space *mapping,
+			struct list_head *pages, unsigned nr_pages)
+{
+	return mpage_readpages(mapping, pages, nr_pages, isofs_get_block);
 }
 
 static sector_t _isofs_bmap(struct address_space *mapping, sector_t block)
@@ -1158,6 +1165,7 @@ static sector_t _isofs_bmap(struct address_space *mapping, sector_t block)
 
 static const struct address_space_operations isofs_aops = {
 	.readpage = isofs_readpage,
+	.readpages = isofs_readpages,
 	.bmap = _isofs_bmap
 };
 
@@ -1319,7 +1327,7 @@ static int isofs_read_inode(struct inode *inode)
 			inode->i_mode = S_IFDIR | sbi->s_dmode;
 		else
 			inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
-		inode->i_nlink = 1;	/*
+		set_nlink(inode, 1);	/*
 					 * Set to 1.  We know there are 2, but
 					 * the find utility tries to optimize
 					 * if it is 2, and it screws up.  It is
@@ -1337,7 +1345,7 @@ static int isofs_read_inode(struct inode *inode)
 			 */
 			inode->i_mode = S_IFREG | S_IRUGO | S_IXUGO;
 		}
-		inode->i_nlink = 1;
+		set_nlink(inode, 1);
 	}
 	inode->i_uid = sbi->s_uid;
 	inode->i_gid = sbi->s_gid;
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
index 1fbc7de..70e79d0 100644
--- a/fs/isofs/rock.c
+++ b/fs/isofs/rock.c
@@ -363,7 +363,7 @@ repeat:
 			break;
 		case SIG('P', 'X'):
 			inode->i_mode = isonum_733(rr->u.PX.mode);
-			inode->i_nlink = isonum_733(rr->u.PX.n_links);
+			set_nlink(inode, isonum_733(rr->u.PX.n_links));
 			inode->i_uid = isonum_733(rr->u.PX.uid);
 			inode->i_gid = isonum_733(rr->u.PX.gid);
 			break;
@@ -496,7 +496,7 @@ repeat:
 				goto out;
 			}
 			inode->i_mode = reloc->i_mode;
-			inode->i_nlink = reloc->i_nlink;
+			set_nlink(inode, reloc->i_nlink);
 			inode->i_uid = reloc->i_uid;
 			inode->i_gid = reloc->i_gid;
 			inode->i_rdev = reloc->i_rdev;
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index 9fe061f..fea8dd6 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -1135,6 +1135,14 @@ static int journal_get_superblock(journal_t *journal)
 		goto out;
 	}
 
+	if (be32_to_cpu(sb->s_first) == 0 ||
+	    be32_to_cpu(sb->s_first) >= journal->j_maxlen) {
+		printk(KERN_WARNING
+			"JBD: Invalid start block of journal: %u\n",
+			be32_to_cpu(sb->s_first));
+		goto out;
+	}
+
 	return 0;
 
 out:
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index eef6979..68d704d 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -352,7 +352,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
 	J_ASSERT(commit_transaction->t_state == T_RUNNING);
 
 	trace_jbd2_start_commit(journal, commit_transaction);
-	jbd_debug(1, "JBD: starting commit of transaction %d\n",
+	jbd_debug(1, "JBD2: starting commit of transaction %d\n",
 			commit_transaction->t_tid);
 
 	write_lock(&journal->j_state_lock);
@@ -427,7 +427,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
 	__jbd2_journal_clean_checkpoint_list(journal);
 	spin_unlock(&journal->j_list_lock);
 
-	jbd_debug (3, "JBD: commit phase 1\n");
+	jbd_debug(3, "JBD2: commit phase 1\n");
 
 	/*
 	 * Switch to a new revoke table.
@@ -447,7 +447,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
 	wake_up(&journal->j_wait_transaction_locked);
 	write_unlock(&journal->j_state_lock);
 
-	jbd_debug (3, "JBD: commit phase 2\n");
+	jbd_debug(3, "JBD2: commit phase 2\n");
 
 	/*
 	 * Now start flushing things to disk, in the order they appear
@@ -462,7 +462,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
 					  WRITE_SYNC);
 	blk_finish_plug(&plug);
 
-	jbd_debug(3, "JBD: commit phase 2\n");
+	jbd_debug(3, "JBD2: commit phase 2\n");
 
 	/*
 	 * Way to go: we have now written out all of the data for a
@@ -522,7 +522,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
 
 			J_ASSERT (bufs == 0);
 
-			jbd_debug(4, "JBD: get descriptor\n");
+			jbd_debug(4, "JBD2: get descriptor\n");
 
 			descriptor = jbd2_journal_get_descriptor_buffer(journal);
 			if (!descriptor) {
@@ -531,7 +531,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
 			}
 
 			bh = jh2bh(descriptor);
-			jbd_debug(4, "JBD: got buffer %llu (%p)\n",
+			jbd_debug(4, "JBD2: got buffer %llu (%p)\n",
 				(unsigned long long)bh->b_blocknr, bh->b_data);
 			header = (journal_header_t *)&bh->b_data[0];
 			header->h_magic     = cpu_to_be32(JBD2_MAGIC_NUMBER);
@@ -625,7 +625,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
 		    commit_transaction->t_buffers == NULL ||
 		    space_left < tag_bytes + 16) {
 
-			jbd_debug(4, "JBD: Submit %d IOs\n", bufs);
+			jbd_debug(4, "JBD2: Submit %d IOs\n", bufs);
 
 			/* Write an end-of-descriptor marker before
                            submitting the IOs.  "tag" still points to
@@ -707,7 +707,7 @@ start_journal_io:
 	   so we incur less scheduling load.
 	*/
 
-	jbd_debug(3, "JBD: commit phase 3\n");
+	jbd_debug(3, "JBD2: commit phase 3\n");
 
 	/*
 	 * akpm: these are BJ_IO, and j_list_lock is not needed.
@@ -771,7 +771,7 @@ wait_for_iobuf:
 
 	J_ASSERT (commit_transaction->t_shadow_list == NULL);
 
-	jbd_debug(3, "JBD: commit phase 4\n");
+	jbd_debug(3, "JBD2: commit phase 4\n");
 
 	/* Here we wait for the revoke record and descriptor record buffers */
  wait_for_ctlbuf:
@@ -801,7 +801,7 @@ wait_for_iobuf:
 	if (err)
 		jbd2_journal_abort(journal, err);
 
-	jbd_debug(3, "JBD: commit phase 5\n");
+	jbd_debug(3, "JBD2: commit phase 5\n");
 	write_lock(&journal->j_state_lock);
 	J_ASSERT(commit_transaction->t_state == T_COMMIT_DFLUSH);
 	commit_transaction->t_state = T_COMMIT_JFLUSH;
@@ -830,7 +830,7 @@ wait_for_iobuf:
            transaction can be removed from any checkpoint list it was on
            before. */
 
-	jbd_debug(3, "JBD: commit phase 6\n");
+	jbd_debug(3, "JBD2: commit phase 6\n");
 
 	J_ASSERT(list_empty(&commit_transaction->t_inode_list));
 	J_ASSERT(commit_transaction->t_buffers == NULL);
@@ -964,7 +964,7 @@ restart_loop:
 
 	/* Done with this transaction! */
 
-	jbd_debug(3, "JBD: commit phase 7\n");
+	jbd_debug(3, "JBD2: commit phase 7\n");
 
 	J_ASSERT(commit_transaction->t_state == T_COMMIT_JFLUSH);
 
@@ -1039,7 +1039,7 @@ restart_loop:
 		journal->j_commit_callback(journal, commit_transaction);
 
 	trace_jbd2_end_commit(journal, commit_transaction);
-	jbd_debug(1, "JBD: commit %d complete, head %d\n",
+	jbd_debug(1, "JBD2: commit %d complete, head %d\n",
 		  journal->j_commit_sequence, journal->j_tail_sequence);
 	if (to_free)
 		kfree(commit_transaction);
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index f24df13..0fa0123 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -491,7 +491,7 @@ int __jbd2_log_start_commit(journal_t *journal, tid_t target)
 		 */
 
 		journal->j_commit_request = target;
-		jbd_debug(1, "JBD: requesting commit %d/%d\n",
+		jbd_debug(1, "JBD2: requesting commit %d/%d\n",
 			  journal->j_commit_request,
 			  journal->j_commit_sequence);
 		wake_up(&journal->j_wait_commit);
@@ -500,7 +500,7 @@ int __jbd2_log_start_commit(journal_t *journal, tid_t target)
 		/* This should never happen, but if it does, preserve
 		   the evidence before kjournald goes into a loop and
 		   increments j_commit_sequence beyond all recognition. */
-		WARN_ONCE(1, "jbd: bad log_start_commit: %u %u %u %u\n",
+		WARN_ONCE(1, "JBD2: bad log_start_commit: %u %u %u %u\n",
 			  journal->j_commit_request,
 			  journal->j_commit_sequence,
 			  target, journal->j_running_transaction ? 
@@ -645,7 +645,7 @@ int jbd2_log_wait_commit(journal_t *journal, tid_t tid)
 	}
 #endif
 	while (tid_gt(tid, journal->j_commit_sequence)) {
-		jbd_debug(1, "JBD: want %d, j_commit_sequence=%d\n",
+		jbd_debug(1, "JBD2: want %d, j_commit_sequence=%d\n",
 				  tid, journal->j_commit_sequence);
 		wake_up(&journal->j_wait_commit);
 		read_unlock(&journal->j_state_lock);
@@ -1093,7 +1093,7 @@ static int journal_reset(journal_t *journal)
 	first = be32_to_cpu(sb->s_first);
 	last = be32_to_cpu(sb->s_maxlen);
 	if (first + JBD2_MIN_JOURNAL_BLOCKS > last + 1) {
-		printk(KERN_ERR "JBD: Journal too short (blocks %llu-%llu).\n",
+		printk(KERN_ERR "JBD2: Journal too short (blocks %llu-%llu).\n",
 		       first, last);
 		journal_fail_superblock(journal);
 		return -EINVAL;
@@ -1139,7 +1139,7 @@ void jbd2_journal_update_superblock(journal_t *journal, int wait)
 	 */
 	if (sb->s_start == 0 && journal->j_tail_sequence ==
 				journal->j_transaction_sequence) {
-		jbd_debug(1,"JBD: Skipping superblock update on recovered sb "
+		jbd_debug(1, "JBD2: Skipping superblock update on recovered sb "
 			"(start %ld, seq %d, errno %d)\n",
 			journal->j_tail, journal->j_tail_sequence,
 			journal->j_errno);
@@ -1163,7 +1163,7 @@ void jbd2_journal_update_superblock(journal_t *journal, int wait)
 	}
 
 	read_lock(&journal->j_state_lock);
-	jbd_debug(1,"JBD: updating superblock (start %ld, seq %d, errno %d)\n",
+	jbd_debug(1, "JBD2: updating superblock (start %ld, seq %d, errno %d)\n",
 		  journal->j_tail, journal->j_tail_sequence, journal->j_errno);
 
 	sb->s_sequence = cpu_to_be32(journal->j_tail_sequence);
@@ -1216,8 +1216,8 @@ static int journal_get_superblock(journal_t *journal)
 		ll_rw_block(READ, 1, &bh);
 		wait_on_buffer(bh);
 		if (!buffer_uptodate(bh)) {
-			printk (KERN_ERR
-				"JBD: IO error reading journal superblock\n");
+			printk(KERN_ERR
+				"JBD2: IO error reading journal superblock\n");
 			goto out;
 		}
 	}
@@ -1228,7 +1228,7 @@ static int journal_get_superblock(journal_t *journal)
 
 	if (sb->s_header.h_magic != cpu_to_be32(JBD2_MAGIC_NUMBER) ||
 	    sb->s_blocksize != cpu_to_be32(journal->j_blocksize)) {
-		printk(KERN_WARNING "JBD: no valid journal superblock found\n");
+		printk(KERN_WARNING "JBD2: no valid journal superblock found\n");
 		goto out;
 	}
 
@@ -1240,14 +1240,22 @@ static int journal_get_superblock(journal_t *journal)
 		journal->j_format_version = 2;
 		break;
 	default:
-		printk(KERN_WARNING "JBD: unrecognised superblock format ID\n");
+		printk(KERN_WARNING "JBD2: unrecognised superblock format ID\n");
 		goto out;
 	}
 
 	if (be32_to_cpu(sb->s_maxlen) < journal->j_maxlen)
 		journal->j_maxlen = be32_to_cpu(sb->s_maxlen);
 	else if (be32_to_cpu(sb->s_maxlen) > journal->j_maxlen) {
-		printk (KERN_WARNING "JBD: journal file too short\n");
+		printk(KERN_WARNING "JBD2: journal file too short\n");
+		goto out;
+	}
+
+	if (be32_to_cpu(sb->s_first) == 0 ||
+	    be32_to_cpu(sb->s_first) >= journal->j_maxlen) {
+		printk(KERN_WARNING
+			"JBD2: Invalid start block of journal: %u\n",
+			be32_to_cpu(sb->s_first));
 		goto out;
 	}
 
@@ -1310,8 +1318,8 @@ int jbd2_journal_load(journal_t *journal)
 		     ~cpu_to_be32(JBD2_KNOWN_ROCOMPAT_FEATURES)) ||
 		    (sb->s_feature_incompat &
 		     ~cpu_to_be32(JBD2_KNOWN_INCOMPAT_FEATURES))) {
-			printk (KERN_WARNING
-				"JBD: Unrecognised features on journal\n");
+			printk(KERN_WARNING
+				"JBD2: Unrecognised features on journal\n");
 			return -EINVAL;
 		}
 	}
@@ -1346,7 +1354,7 @@ int jbd2_journal_load(journal_t *journal)
 	return 0;
 
 recovery_error:
-	printk (KERN_WARNING "JBD: recovery failed\n");
+	printk(KERN_WARNING "JBD2: recovery failed\n");
 	return -EIO;
 }
 
@@ -1577,7 +1585,7 @@ static int journal_convert_superblock_v1(journal_t *journal,
 	struct buffer_head *bh;
 
 	printk(KERN_WARNING
-		"JBD: Converting superblock from version 1 to 2.\n");
+		"JBD2: Converting superblock from version 1 to 2.\n");
 
 	/* Pre-initialise new fields to zero */
 	offset = ((char *) &(sb->s_feature_compat)) - ((char *) sb);
@@ -1694,7 +1702,7 @@ int jbd2_journal_wipe(journal_t *journal, int write)
 	if (!journal->j_tail)
 		goto no_recovery;
 
-	printk (KERN_WARNING "JBD: %s recovery information on journal\n",
+	printk(KERN_WARNING "JBD2: %s recovery information on journal\n",
 		write ? "Clearing" : "Ignoring");
 
 	err = jbd2_journal_skip_recovery(journal);
@@ -2020,7 +2028,7 @@ static int journal_init_jbd2_journal_head_cache(void)
 	retval = 0;
 	if (!jbd2_journal_head_cache) {
 		retval = -ENOMEM;
-		printk(KERN_EMERG "JBD: no memory for journal_head cache\n");
+		printk(KERN_EMERG "JBD2: no memory for journal_head cache\n");
 	}
 	return retval;
 }
@@ -2383,7 +2391,7 @@ static void __exit journal_exit(void)
 #ifdef CONFIG_JBD2_DEBUG
 	int n = atomic_read(&nr_journal_heads);
 	if (n)
-		printk(KERN_EMERG "JBD: leaked %d journal_heads!\n", n);
+		printk(KERN_EMERG "JBD2: leaked %d journal_heads!\n", n);
 #endif
 	jbd2_remove_debugfs_entry();
 	jbd2_remove_jbd_stats_proc_entry();
diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c
index 1cad869..da6d7ba 100644
--- a/fs/jbd2/recovery.c
+++ b/fs/jbd2/recovery.c
@@ -89,7 +89,7 @@ static int do_readahead(journal_t *journal, unsigned int start)
 		err = jbd2_journal_bmap(journal, next, &blocknr);
 
 		if (err) {
-			printk (KERN_ERR "JBD: bad block at offset %u\n",
+			printk(KERN_ERR "JBD2: bad block at offset %u\n",
 				next);
 			goto failed;
 		}
@@ -138,14 +138,14 @@ static int jread(struct buffer_head **bhp, journal_t *journal,
 	*bhp = NULL;
 
 	if (offset >= journal->j_maxlen) {
-		printk(KERN_ERR "JBD: corrupted journal superblock\n");
+		printk(KERN_ERR "JBD2: corrupted journal superblock\n");
 		return -EIO;
 	}
 
 	err = jbd2_journal_bmap(journal, offset, &blocknr);
 
 	if (err) {
-		printk (KERN_ERR "JBD: bad block at offset %u\n",
+		printk(KERN_ERR "JBD2: bad block at offset %u\n",
 			offset);
 		return err;
 	}
@@ -163,7 +163,7 @@ static int jread(struct buffer_head **bhp, journal_t *journal,
 	}
 
 	if (!buffer_uptodate(bh)) {
-		printk (KERN_ERR "JBD: Failed to read block at offset %u\n",
+		printk(KERN_ERR "JBD2: Failed to read block at offset %u\n",
 			offset);
 		brelse(bh);
 		return -EIO;
@@ -251,10 +251,10 @@ int jbd2_journal_recover(journal_t *journal)
 	if (!err)
 		err = do_one_pass(journal, &info, PASS_REPLAY);
 
-	jbd_debug(1, "JBD: recovery, exit status %d, "
+	jbd_debug(1, "JBD2: recovery, exit status %d, "
 		  "recovered transactions %u to %u\n",
 		  err, info.start_transaction, info.end_transaction);
-	jbd_debug(1, "JBD: Replayed %d and revoked %d/%d blocks\n",
+	jbd_debug(1, "JBD2: Replayed %d and revoked %d/%d blocks\n",
 		  info.nr_replays, info.nr_revoke_hits, info.nr_revokes);
 
 	/* Restart the log at the next transaction ID, thus invalidating
@@ -293,14 +293,14 @@ int jbd2_journal_skip_recovery(journal_t *journal)
 	err = do_one_pass(journal, &info, PASS_SCAN);
 
 	if (err) {
-		printk(KERN_ERR "JBD: error %d scanning journal\n", err);
+		printk(KERN_ERR "JBD2: error %d scanning journal\n", err);
 		++journal->j_transaction_sequence;
 	} else {
 #ifdef CONFIG_JBD2_DEBUG
 		int dropped = info.end_transaction - 
 			be32_to_cpu(journal->j_superblock->s_sequence);
 		jbd_debug(1,
-			  "JBD: ignoring %d transaction%s from the journal.\n",
+			  "JBD2: ignoring %d transaction%s from the journal.\n",
 			  dropped, (dropped == 1) ? "" : "s");
 #endif
 		journal->j_transaction_sequence = ++info.end_transaction;
@@ -338,7 +338,7 @@ static int calc_chksums(journal_t *journal, struct buffer_head *bh,
 		wrap(journal, *next_log_block);
 		err = jread(&obh, journal, io_block);
 		if (err) {
-			printk(KERN_ERR "JBD: IO error %d recovering block "
+			printk(KERN_ERR "JBD2: IO error %d recovering block "
 				"%lu in log\n", err, io_block);
 			return 1;
 		} else {
@@ -411,7 +411,7 @@ static int do_one_pass(journal_t *journal,
 		 * either the next descriptor block or the final commit
 		 * record. */
 
-		jbd_debug(3, "JBD: checking block %ld\n", next_log_block);
+		jbd_debug(3, "JBD2: checking block %ld\n", next_log_block);
 		err = jread(&bh, journal, next_log_block);
 		if (err)
 			goto failed;
@@ -491,8 +491,8 @@ static int do_one_pass(journal_t *journal,
 					/* Recover what we can, but
 					 * report failure at the end. */
 					success = err;
-					printk (KERN_ERR
-						"JBD: IO error %d recovering "
+					printk(KERN_ERR
+						"JBD2: IO error %d recovering "
 						"block %ld in log\n",
 						err, io_block);
 				} else {
@@ -520,7 +520,7 @@ static int do_one_pass(journal_t *journal,
 							journal->j_blocksize);
 					if (nbh == NULL) {
 						printk(KERN_ERR
-						       "JBD: Out of memory "
+						       "JBD2: Out of memory "
 						       "during recovery.\n");
 						err = -ENOMEM;
 						brelse(bh);
@@ -689,7 +689,7 @@ static int do_one_pass(journal_t *journal,
 		/* It's really bad news if different passes end up at
 		 * different places (but possible due to IO errors). */
 		if (info->end_transaction != next_commit_ID) {
-			printk (KERN_ERR "JBD: recovery pass %d ended at "
+			printk(KERN_ERR "JBD2: recovery pass %d ended at "
 				"transaction %u, expected %u\n",
 				pass, next_commit_ID, info->end_transaction);
 			if (!success)
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
index 2d71094..a0e41a4 100644
--- a/fs/jbd2/transaction.c
+++ b/fs/jbd2/transaction.c
@@ -27,6 +27,7 @@
 #include <linux/highmem.h>
 #include <linux/hrtimer.h>
 #include <linux/backing-dev.h>
+#include <linux/bug.h>
 #include <linux/module.h>
 
 static void __jbd2_journal_temp_unlink_buffer(struct journal_head *jh);
@@ -115,7 +116,7 @@ static inline void update_t_max_wait(transaction_t *transaction,
  */
 
 static int start_this_handle(journal_t *journal, handle_t *handle,
-			     int gfp_mask)
+			     gfp_t gfp_mask)
 {
 	transaction_t	*transaction, *new_transaction = NULL;
 	tid_t		tid;
@@ -124,7 +125,7 @@ static int start_this_handle(journal_t *journal, handle_t *handle,
 	unsigned long ts = jiffies;
 
 	if (nblocks > journal->j_max_transaction_buffers) {
-		printk(KERN_ERR "JBD: %s wants too many credits (%d > %d)\n",
+		printk(KERN_ERR "JBD2: %s wants too many credits (%d > %d)\n",
 		       current->comm, nblocks,
 		       journal->j_max_transaction_buffers);
 		return -ENOSPC;
@@ -320,7 +321,7 @@ static handle_t *new_handle(int nblocks)
  * Return a pointer to a newly allocated handle, or an ERR_PTR() value
  * on failure.
  */
-handle_t *jbd2__journal_start(journal_t *journal, int nblocks, int gfp_mask)
+handle_t *jbd2__journal_start(journal_t *journal, int nblocks, gfp_t gfp_mask)
 {
 	handle_t *handle = journal_current_handle();
 	int err;
@@ -443,7 +444,7 @@ out:
  * transaction capabable of guaranteeing the requested number of
  * credits.
  */
-int jbd2__journal_restart(handle_t *handle, int nblocks, int gfp_mask)
+int jbd2__journal_restart(handle_t *handle, int nblocks, gfp_t gfp_mask)
 {
 	transaction_t *transaction = handle->h_transaction;
 	journal_t *journal = transaction->t_journal;
@@ -563,7 +564,7 @@ static void warn_dirty_buffer(struct buffer_head *bh)
 	char b[BDEVNAME_SIZE];
 
 	printk(KERN_WARNING
-	       "JBD: Spotted dirty metadata buffer (dev = %s, blocknr = %llu). "
+	       "JBD2: Spotted dirty metadata buffer (dev = %s, blocknr = %llu). "
 	       "There's a risk of filesystem corruption in case of system "
 	       "crash.\n",
 	       bdevname(bh->b_bdev, b), (unsigned long long)bh->b_blocknr);
@@ -1049,6 +1050,10 @@ void jbd2_buffer_abort_trigger(struct journal_head *jh,
  * mark dirty metadata which needs to be journaled as part of the current
  * transaction.
  *
+ * The buffer must have previously had jbd2_journal_get_write_access()
+ * called so that it has a valid journal_head attached to the buffer
+ * head.
+ *
  * The buffer is placed on the transaction's metadata list and is marked
  * as belonging to the transaction.
  *
@@ -1065,11 +1070,16 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
 	transaction_t *transaction = handle->h_transaction;
 	journal_t *journal = transaction->t_journal;
 	struct journal_head *jh = bh2jh(bh);
+	int ret = 0;
 
 	jbd_debug(5, "journal_head %p\n", jh);
 	JBUFFER_TRACE(jh, "entry");
 	if (is_handle_aborted(handle))
 		goto out;
+	if (!buffer_jbd(bh)) {
+		ret = -EUCLEAN;
+		goto out;
+	}
 
 	jbd_lock_bh_state(bh);
 
@@ -1093,8 +1103,20 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
 	 */
 	if (jh->b_transaction == transaction && jh->b_jlist == BJ_Metadata) {
 		JBUFFER_TRACE(jh, "fastpath");
-		J_ASSERT_JH(jh, jh->b_transaction ==
-					journal->j_running_transaction);
+		if (unlikely(jh->b_transaction !=
+			     journal->j_running_transaction)) {
+			printk(KERN_EMERG "JBD: %s: "
+			       "jh->b_transaction (%llu, %p, %u) != "
+			       "journal->j_running_transaction (%p, %u)",
+			       journal->j_devname,
+			       (unsigned long long) bh->b_blocknr,
+			       jh->b_transaction,
+			       jh->b_transaction ? jh->b_transaction->t_tid : 0,
+			       journal->j_running_transaction,
+			       journal->j_running_transaction ?
+			       journal->j_running_transaction->t_tid : 0);
+			ret = -EINVAL;
+		}
 		goto out_unlock_bh;
 	}
 
@@ -1108,9 +1130,32 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
 	 */
 	if (jh->b_transaction != transaction) {
 		JBUFFER_TRACE(jh, "already on other transaction");
-		J_ASSERT_JH(jh, jh->b_transaction ==
-					journal->j_committing_transaction);
-		J_ASSERT_JH(jh, jh->b_next_transaction == transaction);
+		if (unlikely(jh->b_transaction !=
+			     journal->j_committing_transaction)) {
+			printk(KERN_EMERG "JBD: %s: "
+			       "jh->b_transaction (%llu, %p, %u) != "
+			       "journal->j_committing_transaction (%p, %u)",
+			       journal->j_devname,
+			       (unsigned long long) bh->b_blocknr,
+			       jh->b_transaction,
+			       jh->b_transaction ? jh->b_transaction->t_tid : 0,
+			       journal->j_committing_transaction,
+			       journal->j_committing_transaction ?
+			       journal->j_committing_transaction->t_tid : 0);
+			ret = -EINVAL;
+		}
+		if (unlikely(jh->b_next_transaction != transaction)) {
+			printk(KERN_EMERG "JBD: %s: "
+			       "jh->b_next_transaction (%llu, %p, %u) != "
+			       "transaction (%p, %u)",
+			       journal->j_devname,
+			       (unsigned long long) bh->b_blocknr,
+			       jh->b_next_transaction,
+			       jh->b_next_transaction ?
+			       jh->b_next_transaction->t_tid : 0,
+			       transaction, transaction->t_tid);
+			ret = -EINVAL;
+		}
 		/* And this case is illegal: we can't reuse another
 		 * transaction's data buffer, ever. */
 		goto out_unlock_bh;
@@ -1127,7 +1172,8 @@ out_unlock_bh:
 	jbd_unlock_bh_state(bh);
 out:
 	JBUFFER_TRACE(jh, "exit");
-	return 0;
+	WARN_ON(ret);	/* All errors are bugs, so dump the stack */
+	return ret;
 }
 
 /*
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index 9659b7c..be6169b 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -245,7 +245,7 @@ static int jffs2_unlink(struct inode *dir_i, struct dentry *dentry)
 	ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name,
 			      dentry->d_name.len, dead_f, now);
 	if (dead_f->inocache)
-		dentry->d_inode->i_nlink = dead_f->inocache->pino_nlink;
+		set_nlink(dentry->d_inode, dead_f->inocache->pino_nlink);
 	if (!ret)
 		dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
 	return ret;
@@ -278,7 +278,7 @@ static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct de
 
 	if (!ret) {
 		mutex_lock(&f->sem);
-		old_dentry->d_inode->i_nlink = ++f->inocache->pino_nlink;
+		set_nlink(old_dentry->d_inode, ++f->inocache->pino_nlink);
 		mutex_unlock(&f->sem);
 		d_instantiate(dentry, old_dentry->d_inode);
 		dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
@@ -497,7 +497,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
 	f = JFFS2_INODE_INFO(inode);
 
 	/* Directories get nlink 2 at start */
-	inode->i_nlink = 2;
+	set_nlink(inode, 2);
 	/* but ic->pino_nlink is the parent ino# */
 	f->inocache->pino_nlink = dir_i->i_ino;
 
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index bbcb975..7286e44 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -278,7 +278,7 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
 	inode->i_mtime = ITIME(je32_to_cpu(latest_node.mtime));
 	inode->i_ctime = ITIME(je32_to_cpu(latest_node.ctime));
 
-	inode->i_nlink = f->inocache->pino_nlink;
+	set_nlink(inode, f->inocache->pino_nlink);
 
 	inode->i_blocks = (inode->i_size + 511) >> 9;
 
@@ -291,7 +291,7 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
 	case S_IFDIR:
 	{
 		struct jffs2_full_dirent *fd;
-		inode->i_nlink = 2; /* parent and '.' */
+		set_nlink(inode, 2); /* parent and '.' */
 
 		for (fd=f->dents; fd; fd = fd->next) {
 			if (fd->type == DT_DIR && fd->ino)
@@ -453,7 +453,7 @@ struct inode *jffs2_new_inode (struct inode *dir_i, umode_t mode, struct jffs2_r
 		iput(inode);
 		return ERR_PTR(ret);
 	}
-	inode->i_nlink = 1;
+	set_nlink(inode, 1);
 	inode->i_ino = je32_to_cpu(ri->ino);
 	inode->i_mode = jemode_to_cpu(ri->mode);
 	inode->i_gid = je16_to_cpu(ri->gid);
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
index b78b2f9..1b6f15f 100644
--- a/fs/jfs/jfs_imap.c
+++ b/fs/jfs/jfs_imap.c
@@ -457,7 +457,7 @@ struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary)
 	/* read the page of fixed disk inode (AIT) in raw mode */
 	mp = read_metapage(ip, address << sbi->l2nbperpage, PSIZE, 1);
 	if (mp == NULL) {
-		ip->i_nlink = 1;	/* Don't want iput() deleting it */
+		set_nlink(ip, 1);	/* Don't want iput() deleting it */
 		iput(ip);
 		return (NULL);
 	}
@@ -469,7 +469,7 @@ struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary)
 	/* copy on-disk inode to in-memory inode */
 	if ((copy_from_dinode(dp, ip)) != 0) {
 		/* handle bad return by returning NULL for ip */
-		ip->i_nlink = 1;	/* Don't want iput() deleting it */
+		set_nlink(ip, 1);	/* Don't want iput() deleting it */
 		iput(ip);
 		/* release the page */
 		release_metapage(mp);
@@ -3076,7 +3076,7 @@ static int copy_from_dinode(struct dinode * dip, struct inode *ip)
 				ip->i_mode |= 0001;
 		}
 	}
-	ip->i_nlink = le32_to_cpu(dip->di_nlink);
+	set_nlink(ip, le32_to_cpu(dip->di_nlink));
 
 	jfs_ip->saved_uid = le32_to_cpu(dip->di_uid);
 	if (sbi->uid == -1)
diff --git a/fs/jfs/jfs_inode.c b/fs/jfs/jfs_inode.c
index 2686531..c1a3e60 100644
--- a/fs/jfs/jfs_inode.c
+++ b/fs/jfs/jfs_inode.c
@@ -157,7 +157,7 @@ fail_drop:
 	dquot_drop(inode);
 	inode->i_flags |= S_NOQUOTA;
 fail_unlock:
-	inode->i_nlink = 0;
+	clear_nlink(inode);
 	unlock_new_inode(inode);
 fail_put:
 	iput(inode);
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index e17545e..a112ad9 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -172,7 +172,7 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode,
 	mutex_unlock(&JFS_IP(dip)->commit_mutex);
 	if (rc) {
 		free_ea_wmap(ip);
-		ip->i_nlink = 0;
+		clear_nlink(ip);
 		unlock_new_inode(ip);
 		iput(ip);
 	} else {
@@ -292,7 +292,7 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
 		goto out3;
 	}
 
-	ip->i_nlink = 2;	/* for '.' */
+	set_nlink(ip, 2);	/* for '.' */
 	ip->i_op = &jfs_dir_inode_operations;
 	ip->i_fop = &jfs_dir_operations;
 
@@ -311,7 +311,7 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
 	mutex_unlock(&JFS_IP(dip)->commit_mutex);
 	if (rc) {
 		free_ea_wmap(ip);
-		ip->i_nlink = 0;
+		clear_nlink(ip);
 		unlock_new_inode(ip);
 		iput(ip);
 	} else {
@@ -844,7 +844,7 @@ static int jfs_link(struct dentry *old_dentry,
 	rc = txCommit(tid, 2, &iplist[0], 0);
 
 	if (rc) {
-		ip->i_nlink--; /* never instantiated */
+		drop_nlink(ip); /* never instantiated */
 		iput(ip);
 	} else
 		d_instantiate(dentry, ip);
@@ -1048,7 +1048,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
 	mutex_unlock(&JFS_IP(dip)->commit_mutex);
 	if (rc) {
 		free_ea_wmap(ip);
-		ip->i_nlink = 0;
+		clear_nlink(ip);
 		unlock_new_inode(ip);
 		iput(ip);
 	} else {
@@ -1433,7 +1433,7 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,
 	mutex_unlock(&JFS_IP(dir)->commit_mutex);
 	if (rc) {
 		free_ea_wmap(ip);
-		ip->i_nlink = 0;
+		clear_nlink(ip);
 		unlock_new_inode(ip);
 		iput(ip);
 	} else {
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 06c8a67..a44eff0 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -485,7 +485,6 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent)
 		goto out_unload;
 	}
 	inode->i_ino = 0;
-	inode->i_nlink = 1;
 	inode->i_size = sb->s_bdev->bd_inode->i_size;
 	inode->i_mapping->a_ops = &jfs_metapage_aops;
 	insert_inode_hash(inode);
diff --git a/fs/libfs.c b/fs/libfs.c
index c18e9a1..f6d411e 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -490,7 +490,7 @@ int simple_fill_super(struct super_block *s, unsigned long magic,
 	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 	inode->i_op = &simple_dir_inode_operations;
 	inode->i_fop = &simple_dir_operations;
-	inode->i_nlink = 2;
+	set_nlink(inode, 2);
 	root = d_alloc_root(inode);
 	if (!root) {
 		iput(inode);
@@ -510,8 +510,10 @@ int simple_fill_super(struct super_block *s, unsigned long magic,
 		if (!dentry)
 			goto out;
 		inode = new_inode(s);
-		if (!inode)
+		if (!inode) {
+			dput(dentry);
 			goto out;
+		}
 		inode->i_mode = S_IFREG | files->mode;
 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 		inode->i_fop = files->ops;
diff --git a/fs/logfs/dir.c b/fs/logfs/dir.c
index b3ff3d8..b7d7f67 100644
--- a/fs/logfs/dir.c
+++ b/fs/logfs/dir.c
@@ -197,7 +197,7 @@ static int logfs_remove_inode(struct inode *inode)
 {
 	int ret;
 
-	inode->i_nlink--;
+	drop_nlink(inode);
 	ret = write_inode(inode);
 	LOGFS_BUG_ON(ret, inode->i_sb);
 	return ret;
@@ -433,7 +433,7 @@ static int __logfs_create(struct inode *dir, struct dentry *dentry,
 
 	ta = kzalloc(sizeof(*ta), GFP_KERNEL);
 	if (!ta) {
-		inode->i_nlink--;
+		drop_nlink(inode);
 		iput(inode);
 		return -ENOMEM;
 	}
@@ -456,7 +456,7 @@ static int __logfs_create(struct inode *dir, struct dentry *dentry,
 		abort_transaction(inode, ta);
 		li->li_flags |= LOGFS_IF_STILLBORN;
 		/* FIXME: truncate symlink */
-		inode->i_nlink--;
+		drop_nlink(inode);
 		iput(inode);
 		goto out;
 	}
@@ -563,7 +563,7 @@ static int logfs_link(struct dentry *old_dentry, struct inode *dir,
 
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 	ihold(inode);
-	inode->i_nlink++;
+	inc_nlink(inode);
 	mark_inode_dirty_sync(inode);
 
 	return __logfs_create(dir, dentry, inode, NULL, 0);
diff --git a/fs/logfs/inode.c b/fs/logfs/inode.c
index edfea7a..7e441ad 100644
--- a/fs/logfs/inode.c
+++ b/fs/logfs/inode.c
@@ -93,7 +93,7 @@ static struct inode *__logfs_iget(struct super_block *sb, ino_t ino)
 		/* inode->i_nlink == 0 can be true when called from
 		 * block validator */
 		/* set i_nlink to 0 to prevent caching */
-		inode->i_nlink = 0;
+		clear_nlink(inode);
 		logfs_inode(inode)->li_flags |= LOGFS_IF_ZOMBIE;
 		iget_failed(inode);
 		if (!err)
@@ -199,7 +199,6 @@ static void logfs_init_inode(struct super_block *sb, struct inode *inode)
 	inode->i_blocks	= 0;
 	inode->i_ctime	= CURRENT_TIME;
 	inode->i_mtime	= CURRENT_TIME;
-	inode->i_nlink	= 1;
 	li->li_refcount = 1;
 	INIT_LIST_HEAD(&li->li_freeing_list);
 
diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c
index d8d0938..2ac4217 100644
--- a/fs/logfs/readwrite.c
+++ b/fs/logfs/readwrite.c
@@ -126,7 +126,7 @@ static void logfs_disk_to_inode(struct logfs_disk_inode *di, struct inode*inode)
 	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);
+	set_nlink(inode, be32_to_cpu(di->di_refcount));
 	inode->i_generation = be32_to_cpu(di->di_generation);
 
 	switch (inode->i_mode & S_IFMT) {
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index e7d23e2..64cdcd6 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -446,7 +446,7 @@ static struct inode *V1_minix_iget(struct inode *inode)
 	inode->i_mode = raw_inode->i_mode;
 	inode->i_uid = (uid_t)raw_inode->i_uid;
 	inode->i_gid = (gid_t)raw_inode->i_gid;
-	inode->i_nlink = raw_inode->i_nlinks;
+	set_nlink(inode, raw_inode->i_nlinks);
 	inode->i_size = raw_inode->i_size;
 	inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec = raw_inode->i_time;
 	inode->i_mtime.tv_nsec = 0;
@@ -479,7 +479,7 @@ static struct inode *V2_minix_iget(struct inode *inode)
 	inode->i_mode = raw_inode->i_mode;
 	inode->i_uid = (uid_t)raw_inode->i_uid;
 	inode->i_gid = (gid_t)raw_inode->i_gid;
-	inode->i_nlink = raw_inode->i_nlinks;
+	set_nlink(inode, raw_inode->i_nlinks);
 	inode->i_size = raw_inode->i_size;
 	inode->i_mtime.tv_sec = raw_inode->i_mtime;
 	inode->i_atime.tv_sec = raw_inode->i_atime;
diff --git a/fs/namei.c b/fs/namei.c
index 7657be4..ac6d214 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -137,7 +137,7 @@ static int do_getname(const char __user *filename, char *page)
 	return retval;
 }
 
-static char *getname_flags(const char __user * filename, int flags)
+static char *getname_flags(const char __user *filename, int flags, int *empty)
 {
 	char *tmp, *result;
 
@@ -148,6 +148,8 @@ static char *getname_flags(const char __user * filename, int flags)
 
 		result = tmp;
 		if (retval < 0) {
+			if (retval == -ENOENT && empty)
+				*empty = 1;
 			if (retval != -ENOENT || !(flags & LOOKUP_EMPTY)) {
 				__putname(tmp);
 				result = ERR_PTR(retval);
@@ -160,7 +162,7 @@ static char *getname_flags(const char __user * filename, int flags)
 
 char *getname(const char __user * filename)
 {
-	return getname_flags(filename, 0);
+	return getname_flags(filename, 0, 0);
 }
 
 #ifdef CONFIG_AUDITSYSCALL
@@ -1798,11 +1800,11 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
 	return __lookup_hash(&this, base, NULL);
 }
 
-int user_path_at(int dfd, const char __user *name, unsigned flags,
-		 struct path *path)
+int user_path_at_empty(int dfd, const char __user *name, unsigned flags,
+		 struct path *path, int *empty)
 {
 	struct nameidata nd;
-	char *tmp = getname_flags(name, flags);
+	char *tmp = getname_flags(name, flags, empty);
 	int err = PTR_ERR(tmp);
 	if (!IS_ERR(tmp)) {
 
@@ -1816,6 +1818,12 @@ int user_path_at(int dfd, const char __user *name, unsigned flags,
 	return err;
 }
 
+int user_path_at(int dfd, const char __user *name, unsigned flags,
+		 struct path *path)
+{
+	return user_path_at_empty(dfd, name, flags, path, 0);
+}
+
 static int user_path_parent(int dfd, const char __user *path,
 			struct nameidata *nd, char **name)
 {
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index 202f370..5b5fa33 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -228,7 +228,7 @@ static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
 
 	DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
 
-	inode->i_nlink = 1;
+	set_nlink(inode, 1);
 	inode->i_uid = server->m.uid;
 	inode->i_gid = server->m.gid;
 
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 4dc6d07..c07a55a 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -320,7 +320,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
 		memset(&inode->i_ctime, 0, sizeof(inode->i_ctime));
 		inode->i_version = 0;
 		inode->i_size = 0;
-		inode->i_nlink = 0;
+		clear_nlink(inode);
 		inode->i_uid = -2;
 		inode->i_gid = -2;
 		inode->i_blocks = 0;
@@ -355,7 +355,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
 				| NFS_INO_INVALID_DATA
 				| NFS_INO_REVAL_PAGECACHE;
 		if (fattr->valid & NFS_ATTR_FATTR_NLINK)
-			inode->i_nlink = fattr->nlink;
+			set_nlink(inode, fattr->nlink);
 		else if (nfs_server_capable(inode, NFS_CAP_NLINK))
 			nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
 		if (fattr->valid & NFS_ATTR_FATTR_OWNER)
@@ -1361,7 +1361,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
 			invalid |= NFS_INO_INVALID_ATTR;
 			if (S_ISDIR(inode->i_mode))
 				invalid |= NFS_INO_INVALID_DATA;
-			inode->i_nlink = fattr->nlink;
+			set_nlink(inode, fattr->nlink);
 		}
 	} else if (server->caps & NFS_CAP_NLINK)
 		invalid |= save_cache_validity & (NFS_INO_INVALID_ATTR
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 66d095d..b6fa792 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -655,7 +655,7 @@ static __be32 nfsd4_decode_share_access(struct nfsd4_compoundargs *argp, u32 *x)
 	default:
 		return nfserr_bad_xdr;
 	}
-	w &= !NFS4_SHARE_ACCESS_MASK;
+	w &= ~NFS4_SHARE_ACCESS_MASK;
 	if (!w)
 		return nfs_ok;
 	if (!argp->minorversion)
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index 666628b..b50ffb7 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -354,7 +354,7 @@ struct inode *nilfs_new_inode(struct inode *dir, int mode)
 
  failed_acl:
  failed_bmap:
-	inode->i_nlink = 0;
+	clear_nlink(inode);
 	iput(inode);  /* raw_inode will be deleted through
 			 generic_delete_inode() */
 	goto failed;
@@ -396,7 +396,7 @@ int nilfs_read_inode_common(struct inode *inode,
 	inode->i_mode = le16_to_cpu(raw_inode->i_mode);
 	inode->i_uid = (uid_t)le32_to_cpu(raw_inode->i_uid);
 	inode->i_gid = (gid_t)le32_to_cpu(raw_inode->i_gid);
-	inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
+	set_nlink(inode, le16_to_cpu(raw_inode->i_links_count));
 	inode->i_size = le64_to_cpu(raw_inode->i_size);
 	inode->i_atime.tv_sec = le64_to_cpu(raw_inode->i_mtime);
 	inode->i_ctime.tv_sec = le64_to_cpu(raw_inode->i_ctime);
diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c
index a314199..768982d 100644
--- a/fs/nilfs2/namei.c
+++ b/fs/nilfs2/namei.c
@@ -289,7 +289,7 @@ static int nilfs_do_unlink(struct inode *dir, struct dentry *dentry)
 		nilfs_warning(inode->i_sb, __func__,
 			      "deleting nonexistent file (%lu), %d\n",
 			      inode->i_ino, inode->i_nlink);
-		inode->i_nlink = 1;
+		set_nlink(inode, 1);
 	}
 	err = nilfs_delete_entry(de, page);
 	if (err)
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index 1371487..97e2dac 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -612,7 +612,7 @@ static int ntfs_read_locked_inode(struct inode *vi)
 	 * might be tricky due to vfs interactions. Need to think about this
 	 * some more when implementing the unlink command.
 	 */
-	vi->i_nlink = le16_to_cpu(m->link_count);
+	set_nlink(vi, le16_to_cpu(m->link_count));
 	/*
 	 * FIXME: Reparse points can have the directory bit set even though
 	 * they would be S_IFLNK. Need to deal with this further below when we
@@ -634,7 +634,7 @@ static int ntfs_read_locked_inode(struct inode *vi)
 		vi->i_mode &= ~vol->dmask;
 		/* Things break without this kludge! */
 		if (vi->i_nlink > 1)
-			vi->i_nlink = 1;
+			set_nlink(vi, 1);
 	} else {
 		vi->i_mode |= S_IFREG;
 		/* Apply the file permissions mask set in the mount options. */
@@ -1242,7 +1242,7 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
 	vi->i_version	= base_vi->i_version;
 	vi->i_uid	= base_vi->i_uid;
 	vi->i_gid	= base_vi->i_gid;
-	vi->i_nlink	= base_vi->i_nlink;
+	set_nlink(vi, base_vi->i_nlink);
 	vi->i_mtime	= base_vi->i_mtime;
 	vi->i_ctime	= base_vi->i_ctime;
 	vi->i_atime	= base_vi->i_atime;
@@ -1508,7 +1508,7 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi)
 	vi->i_version	= base_vi->i_version;
 	vi->i_uid	= base_vi->i_uid;
 	vi->i_gid	= base_vi->i_gid;
-	vi->i_nlink	= base_vi->i_nlink;
+	set_nlink(vi, base_vi->i_nlink);
 	vi->i_mtime	= base_vi->i_mtime;
 	vi->i_ctime	= base_vi->i_ctime;
 	vi->i_atime	= base_vi->i_atime;
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
index 8582e3f..e2878b5 100644
--- a/fs/ocfs2/dir.c
+++ b/fs/ocfs2/dir.c
@@ -2292,7 +2292,7 @@ static int ocfs2_fill_new_dir_id(struct ocfs2_super *osb,
 	ocfs2_journal_dirty(handle, di_bh);
 
 	i_size_write(inode, size);
-	inode->i_nlink = 2;
+	set_nlink(inode, 2);
 	inode->i_blocks = ocfs2_inode_sector_count(inode);
 
 	ret = ocfs2_mark_inode_dirty(handle, inode, di_bh);
@@ -2354,7 +2354,7 @@ static int ocfs2_fill_new_dir_el(struct ocfs2_super *osb,
 	ocfs2_journal_dirty(handle, new_bh);
 
 	i_size_write(inode, inode->i_sb->s_blocksize);
-	inode->i_nlink = 2;
+	set_nlink(inode, 2);
 	inode->i_blocks = ocfs2_inode_sector_count(inode);
 	status = ocfs2_mark_inode_dirty(handle, inode, fe_bh);
 	if (status < 0) {
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index 7642d7c..e1ed5e5 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -2092,7 +2092,7 @@ static void ocfs2_refresh_inode_from_lvb(struct inode *inode)
 	inode->i_uid     = be32_to_cpu(lvb->lvb_iuid);
 	inode->i_gid     = be32_to_cpu(lvb->lvb_igid);
 	inode->i_mode    = be16_to_cpu(lvb->lvb_imode);
-	inode->i_nlink   = be16_to_cpu(lvb->lvb_inlink);
+	set_nlink(inode, be16_to_cpu(lvb->lvb_inlink));
 	ocfs2_unpack_timespec(&inode->i_atime,
 			      be64_to_cpu(lvb->lvb_iatime_packed));
 	ocfs2_unpack_timespec(&inode->i_mtime,
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
index b4c8bb6..a22d2c0 100644
--- a/fs/ocfs2/inode.c
+++ b/fs/ocfs2/inode.c
@@ -291,7 +291,7 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
 		     (unsigned long long)OCFS2_I(inode)->ip_blkno,
 		     (unsigned long long)le64_to_cpu(fe->i_blkno));
 
-	inode->i_nlink = ocfs2_read_links_count(fe);
+	set_nlink(inode, ocfs2_read_links_count(fe));
 
 	trace_ocfs2_populate_inode(OCFS2_I(inode)->ip_blkno,
 				   le32_to_cpu(fe->i_flags));
@@ -1290,7 +1290,7 @@ void ocfs2_refresh_inode(struct inode *inode,
 	OCFS2_I(inode)->ip_dyn_features = le16_to_cpu(fe->i_dyn_features);
 	ocfs2_set_inode_flags(inode);
 	i_size_write(inode, le64_to_cpu(fe->i_size));
-	inode->i_nlink = ocfs2_read_links_count(fe);
+	set_nlink(inode, ocfs2_read_links_count(fe));
 	inode->i_uid = le32_to_cpu(fe->i_uid);
 	inode->i_gid = le32_to_cpu(fe->i_gid);
 	inode->i_mode = le16_to_cpu(fe->i_mode);
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 53aa41e..a8b2bfe 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -199,9 +199,7 @@ static struct inode *ocfs2_get_init_inode(struct inode *dir, int mode)
 	 * these are used by the support functions here and in
 	 * callers. */
 	if (S_ISDIR(mode))
-		inode->i_nlink = 2;
-	else
-		inode->i_nlink = 1;
+		set_nlink(inode, 2);
 	inode_init_owner(inode, dir, mode);
 	dquot_initialize(inode);
 	return inode;
@@ -1379,7 +1377,7 @@ static int ocfs2_rename(struct inode *old_dir,
 	}
 
 	if (new_inode) {
-		new_inode->i_nlink--;
+		drop_nlink(new_inode);
 		new_inode->i_ctime = CURRENT_TIME;
 	}
 	old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
@@ -1387,9 +1385,9 @@ static int ocfs2_rename(struct inode *old_dir,
 	if (update_dot_dot) {
 		status = ocfs2_update_entry(old_inode, handle,
 					    &old_inode_dot_dot_res, new_dir);
-		old_dir->i_nlink--;
+		drop_nlink(old_dir);
 		if (new_inode) {
-			new_inode->i_nlink--;
+			drop_nlink(new_inode);
 		} else {
 			inc_nlink(new_dir);
 			mark_inode_dirty(new_dir);
@@ -2018,7 +2016,7 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
 	orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data;
 	if (S_ISDIR(inode->i_mode))
 		ocfs2_add_links_count(orphan_fe, 1);
-	orphan_dir_inode->i_nlink = ocfs2_read_links_count(orphan_fe);
+	set_nlink(orphan_dir_inode, ocfs2_read_links_count(orphan_fe));
 	ocfs2_journal_dirty(handle, orphan_dir_bh);
 
 	status = __ocfs2_add_entry(handle, orphan_dir_inode, name,
@@ -2116,7 +2114,7 @@ int ocfs2_orphan_del(struct ocfs2_super *osb,
 	orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data;
 	if (S_ISDIR(inode->i_mode))
 		ocfs2_add_links_count(orphan_fe, -1);
-	orphan_dir_inode->i_nlink = ocfs2_read_links_count(orphan_fe);
+	set_nlink(orphan_dir_inode, ocfs2_read_links_count(orphan_fe));
 	ocfs2_journal_dirty(handle, orphan_dir_bh);
 
 leave:
@@ -2282,7 +2280,7 @@ int ocfs2_create_inode_in_orphan(struct inode *dir,
 		goto leave;
 	}
 
-	inode->i_nlink = 0;
+	clear_nlink(inode);
 	/* do the real work now. */
 	status = __ocfs2_mknod_locked(dir, inode,
 				      0, &new_di_bh, parent_di_bh, handle,
@@ -2437,7 +2435,7 @@ int ocfs2_mv_orphaned_inode_to_new(struct inode *dir,
 	di = (struct ocfs2_dinode *)di_bh->b_data;
 	le32_add_cpu(&di->i_flags, -OCFS2_ORPHANED_FL);
 	di->i_orphaned_slot = 0;
-	inode->i_nlink = 1;
+	set_nlink(inode, 1);
 	ocfs2_set_links_count(di, inode->i_nlink);
 	ocfs2_journal_dirty(handle, di_bh);
 
diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c
index a2a5bff..e4e0ff7 100644
--- a/fs/openpromfs/inode.c
+++ b/fs/openpromfs/inode.c
@@ -242,7 +242,7 @@ found:
 		inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
 		inode->i_op = &openprom_inode_operations;
 		inode->i_fop = &openprom_operations;
-		inode->i_nlink = 2;
+		set_nlink(inode, 2);
 		break;
 	case op_inode_prop:
 		if (!strcmp(dp->name, "options") && (len == 17) &&
@@ -251,7 +251,7 @@ found:
 		else
 			inode->i_mode = S_IFREG | S_IRUGO;
 		inode->i_fop = &openpromfs_prop_ops;
-		inode->i_nlink = 1;
+		set_nlink(inode, 1);
 		inode->i_size = ent_oi->u.prop->length;
 		break;
 	}
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 8f0087e..2db1bd3 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1652,12 +1652,46 @@ out:
 	return error;
 }
 
+static int proc_pid_fd_link_getattr(struct vfsmount *mnt, struct dentry *dentry,
+		struct kstat *stat)
+{
+	struct inode *inode = dentry->d_inode;
+	struct task_struct *task = get_proc_task(inode);
+	int rc;
+
+	if (task == NULL)
+		return -ESRCH;
+
+	rc = -EACCES;
+	if (lock_trace(task))
+		goto out_task;
+
+	generic_fillattr(inode, stat);
+	unlock_trace(task);
+	rc = 0;
+out_task:
+	put_task_struct(task);
+	return rc;
+}
+
 static const struct inode_operations proc_pid_link_inode_operations = {
 	.readlink	= proc_pid_readlink,
 	.follow_link	= proc_pid_follow_link,
 	.setattr	= proc_setattr,
 };
 
+static const struct inode_operations proc_fdinfo_link_inode_operations = {
+	.setattr	= proc_setattr,
+	.getattr	= proc_pid_fd_link_getattr,
+};
+
+static const struct inode_operations proc_fd_link_inode_operations = {
+	.readlink	= proc_pid_readlink,
+	.follow_link	= proc_pid_follow_link,
+	.setattr	= proc_setattr,
+	.getattr	= proc_pid_fd_link_getattr,
+};
+
 
 /* building an inode */
 
@@ -1889,49 +1923,61 @@ out:
 
 static int proc_fd_info(struct inode *inode, struct path *path, char *info)
 {
-	struct task_struct *task = get_proc_task(inode);
-	struct files_struct *files = NULL;
+	struct task_struct *task;
+	struct files_struct *files;
 	struct file *file;
 	int fd = proc_fd(inode);
+	int rc;
 
-	if (task) {
-		files = get_files_struct(task);
-		put_task_struct(task);
-	}
-	if (files) {
-		/*
-		 * We are not taking a ref to the file structure, so we must
-		 * hold ->file_lock.
-		 */
-		spin_lock(&files->file_lock);
-		file = fcheck_files(files, fd);
-		if (file) {
-			unsigned int f_flags;
-			struct fdtable *fdt;
-
-			fdt = files_fdtable(files);
-			f_flags = file->f_flags & ~O_CLOEXEC;
-			if (FD_ISSET(fd, fdt->close_on_exec))
-				f_flags |= O_CLOEXEC;
-
-			if (path) {
-				*path = file->f_path;
-				path_get(&file->f_path);
-			}
-			if (info)
-				snprintf(info, PROC_FDINFO_MAX,
-					 "pos:\t%lli\n"
-					 "flags:\t0%o\n",
-					 (long long) file->f_pos,
-					 f_flags);
-			spin_unlock(&files->file_lock);
-			put_files_struct(files);
-			return 0;
+	task = get_proc_task(inode);
+	if (!task)
+		return -ENOENT;
+
+	rc = -EACCES;
+	if (lock_trace(task))
+		goto out_task;
+
+	rc = -ENOENT;
+	files = get_files_struct(task);
+	if (files == NULL)
+		goto out_unlock;
+
+	/*
+	 * We are not taking a ref to the file structure, so we must
+	 * hold ->file_lock.
+	 */
+	spin_lock(&files->file_lock);
+	file = fcheck_files(files, fd);
+	if (file) {
+		unsigned int f_flags;
+		struct fdtable *fdt;
+
+		fdt = files_fdtable(files);
+		f_flags = file->f_flags & ~O_CLOEXEC;
+		if (FD_ISSET(fd, fdt->close_on_exec))
+			f_flags |= O_CLOEXEC;
+
+		if (path) {
+			*path = file->f_path;
+			path_get(&file->f_path);
 		}
-		spin_unlock(&files->file_lock);
-		put_files_struct(files);
-	}
-	return -ENOENT;
+		if (info)
+			snprintf(info, PROC_FDINFO_MAX,
+				 "pos:\t%lli\n"
+				 "flags:\t0%o\n",
+				 (long long) file->f_pos,
+				 f_flags);
+		rc = 0;
+	} else
+		rc = -ENOENT;
+	spin_unlock(&files->file_lock);
+	put_files_struct(files);
+
+out_unlock:
+	unlock_trace(task);
+out_task:
+	put_task_struct(task);
+	return rc;
 }
 
 static int proc_fd_link(struct inode *inode, struct path *path)
@@ -2026,7 +2072,7 @@ static struct dentry *proc_fd_instantiate(struct inode *dir,
 	spin_unlock(&files->file_lock);
 	put_files_struct(files);
 
-	inode->i_op = &proc_pid_link_inode_operations;
+	inode->i_op = &proc_fd_link_inode_operations;
 	inode->i_size = 64;
 	ei->op.proc_get_link = proc_fd_link;
 	d_set_d_op(dentry, &tid_fd_dentry_operations);
@@ -2058,7 +2104,12 @@ static struct dentry *proc_lookupfd_common(struct inode *dir,
 	if (fd == ~0U)
 		goto out;
 
+	result = ERR_PTR(-EACCES);
+	if (lock_trace(task))
+		goto out;
+
 	result = instantiate(dir, dentry, task, &fd);
+	unlock_trace(task);
 out:
 	put_task_struct(task);
 out_no_task:
@@ -2078,23 +2129,28 @@ static int proc_readfd_common(struct file * filp, void * dirent,
 	retval = -ENOENT;
 	if (!p)
 		goto out_no_task;
+
+	retval = -EACCES;
+	if (lock_trace(p))
+		goto out;
+
 	retval = 0;
 
 	fd = filp->f_pos;
 	switch (fd) {
 		case 0:
 			if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0)
-				goto out;
+				goto out_unlock;
 			filp->f_pos++;
 		case 1:
 			ino = parent_ino(dentry);
 			if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0)
-				goto out;
+				goto out_unlock;
 			filp->f_pos++;
 		default:
 			files = get_files_struct(p);
 			if (!files)
-				goto out;
+				goto out_unlock;
 			rcu_read_lock();
 			for (fd = filp->f_pos-2;
 			     fd < files_fdtable(files)->max_fds;
@@ -2118,6 +2174,9 @@ static int proc_readfd_common(struct file * filp, void * dirent,
 			rcu_read_unlock();
 			put_files_struct(files);
 	}
+
+out_unlock:
+	unlock_trace(p);
 out:
 	put_task_struct(p);
 out_no_task:
@@ -2195,6 +2254,7 @@ static struct dentry *proc_fdinfo_instantiate(struct inode *dir,
 	ei->fd = fd;
 	inode->i_mode = S_IFREG | S_IRUSR;
 	inode->i_fop = &proc_fdinfo_file_operations;
+	inode->i_op = &proc_fdinfo_link_inode_operations;
 	d_set_d_op(dentry, &tid_fd_dentry_operations);
 	d_add(dentry, inode);
 	/* Close the race of the process dying before we return the dentry */
@@ -2248,7 +2308,7 @@ static struct dentry *proc_pident_instantiate(struct inode *dir,
 	ei = PROC_I(inode);
 	inode->i_mode = p->mode;
 	if (S_ISDIR(inode->i_mode))
-		inode->i_nlink = 2;	/* Use getattr to fix if necessary */
+		set_nlink(inode, 2);	/* Use getattr to fix if necessary */
 	if (p->iop)
 		inode->i_op = p->iop;
 	if (p->fop)
@@ -2642,7 +2702,7 @@ static struct dentry *proc_base_instantiate(struct inode *dir,
 
 	inode->i_mode = p->mode;
 	if (S_ISDIR(inode->i_mode))
-		inode->i_nlink = 2;
+		set_nlink(inode, 2);
 	if (S_ISLNK(inode->i_mode))
 		inode->i_size = 64;
 	if (p->iop)
@@ -2981,8 +3041,8 @@ static struct dentry *proc_pid_instantiate(struct inode *dir,
 	inode->i_fop = &proc_tgid_base_operations;
 	inode->i_flags|=S_IMMUTABLE;
 
-	inode->i_nlink = 2 + pid_entry_count_dirs(tgid_base_stuff,
-		ARRAY_SIZE(tgid_base_stuff));
+	set_nlink(inode, 2 + pid_entry_count_dirs(tgid_base_stuff,
+						  ARRAY_SIZE(tgid_base_stuff)));
 
 	d_set_d_op(dentry, &pid_dentry_operations);
 
@@ -3233,8 +3293,8 @@ static struct dentry *proc_task_instantiate(struct inode *dir,
 	inode->i_fop = &proc_tid_base_operations;
 	inode->i_flags|=S_IMMUTABLE;
 
-	inode->i_nlink = 2 + pid_entry_count_dirs(tid_base_stuff,
-		ARRAY_SIZE(tid_base_stuff));
+	set_nlink(inode, 2 + pid_entry_count_dirs(tid_base_stuff,
+						  ARRAY_SIZE(tid_base_stuff)));
 
 	d_set_d_op(dentry, &pid_dentry_operations);
 
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 9d99131..10090d9 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -283,7 +283,7 @@ static int proc_getattr(struct vfsmount *mnt, struct dentry *dentry,
 	struct inode *inode = dentry->d_inode;
 	struct proc_dir_entry *de = PROC_I(inode)->pde;
 	if (de && de->nlink)
-		inode->i_nlink = de->nlink;
+		set_nlink(inode, de->nlink);
 
 	generic_fillattr(inode, stat);
 	return 0;
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 7ed72d6..7737c54 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -445,7 +445,7 @@ struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de)
 		if (de->size)
 			inode->i_size = de->size;
 		if (de->nlink)
-			inode->i_nlink = de->nlink;
+			set_nlink(inode, de->nlink);
 		if (de->proc_iops)
 			inode->i_op = de->proc_iops;
 		if (de->proc_fops) {
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index 1a77dbe..a6b6217 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -3,6 +3,7 @@
  */
 #include <linux/init.h>
 #include <linux/sysctl.h>
+#include <linux/poll.h>
 #include <linux/proc_fs.h>
 #include <linux/security.h>
 #include <linux/namei.h>
@@ -14,6 +15,15 @@ static const struct inode_operations proc_sys_inode_operations;
 static const struct file_operations proc_sys_dir_file_operations;
 static const struct inode_operations proc_sys_dir_operations;
 
+void proc_sys_poll_notify(struct ctl_table_poll *poll)
+{
+	if (!poll)
+		return;
+
+	atomic_inc(&poll->event);
+	wake_up_interruptible(&poll->wait);
+}
+
 static struct inode *proc_sys_make_inode(struct super_block *sb,
 		struct ctl_table_header *head, struct ctl_table *table)
 {
@@ -39,7 +49,7 @@ static struct inode *proc_sys_make_inode(struct super_block *sb,
 		inode->i_fop = &proc_sys_file_operations;
 	} else {
 		inode->i_mode |= S_IFDIR;
-		inode->i_nlink = 0;
+		clear_nlink(inode);
 		inode->i_op = &proc_sys_dir_operations;
 		inode->i_fop = &proc_sys_dir_file_operations;
 	}
@@ -176,6 +186,39 @@ static ssize_t proc_sys_write(struct file *filp, const char __user *buf,
 	return proc_sys_call_handler(filp, (void __user *)buf, count, ppos, 1);
 }
 
+static int proc_sys_open(struct inode *inode, struct file *filp)
+{
+	struct ctl_table *table = PROC_I(inode)->sysctl_entry;
+
+	if (table->poll)
+		filp->private_data = proc_sys_poll_event(table->poll);
+
+	return 0;
+}
+
+static unsigned int proc_sys_poll(struct file *filp, poll_table *wait)
+{
+	struct inode *inode = filp->f_path.dentry->d_inode;
+	struct ctl_table *table = PROC_I(inode)->sysctl_entry;
+	unsigned long event = (unsigned long)filp->private_data;
+	unsigned int ret = DEFAULT_POLLMASK;
+
+	if (!table->proc_handler)
+		goto out;
+
+	if (!table->poll)
+		goto out;
+
+	poll_wait(filp, &table->poll->wait, wait);
+
+	if (event != atomic_read(&table->poll->event)) {
+		filp->private_data = proc_sys_poll_event(table->poll);
+		ret = POLLIN | POLLRDNORM | POLLERR | POLLPRI;
+	}
+
+out:
+	return ret;
+}
 
 static int proc_sys_fill_cache(struct file *filp, void *dirent,
 				filldir_t filldir,
@@ -364,12 +407,15 @@ static int proc_sys_getattr(struct vfsmount *mnt, struct dentry *dentry, struct
 }
 
 static const struct file_operations proc_sys_file_operations = {
+	.open		= proc_sys_open,
+	.poll		= proc_sys_poll,
 	.read		= proc_sys_read,
 	.write		= proc_sys_write,
 	.llseek		= default_llseek,
 };
 
 static const struct file_operations proc_sys_dir_file_operations = {
+	.read		= generic_read_dir,
 	.readdir	= proc_sys_readdir,
 	.llseek		= generic_file_llseek,
 };
diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
index 893b961..379a02d 100644
--- a/fs/pstore/inode.c
+++ b/fs/pstore/inode.c
@@ -24,6 +24,7 @@
 #include <linux/highmem.h>
 #include <linux/time.h>
 #include <linux/init.h>
+#include <linux/list.h>
 #include <linux/string.h>
 #include <linux/mount.h>
 #include <linux/ramfs.h>
@@ -32,13 +33,18 @@
 #include <linux/magic.h>
 #include <linux/pstore.h>
 #include <linux/slab.h>
+#include <linux/spinlock.h>
 #include <linux/uaccess.h>
 
 #include "internal.h"
 
 #define	PSTORE_NAMELEN	64
 
+static DEFINE_SPINLOCK(allpstore_lock);
+static LIST_HEAD(allpstore);
+
 struct pstore_private {
+	struct list_head list;
 	struct pstore_info *psi;
 	enum pstore_type_id type;
 	u64	id;
@@ -81,8 +87,16 @@ static int pstore_unlink(struct inode *dir, struct dentry *dentry)
 
 static void pstore_evict_inode(struct inode *inode)
 {
+	struct pstore_private	*p = inode->i_private;
+	unsigned long		flags;
+
 	end_writeback(inode);
-	kfree(inode->i_private);
+	if (p) {
+		spin_lock_irqsave(&allpstore_lock, flags);
+		list_del(&p->list);
+		spin_unlock_irqrestore(&allpstore_lock, flags);
+		kfree(p);
+	}
 }
 
 static const struct inode_operations pstore_dir_inode_operations = {
@@ -182,9 +196,23 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id,
 	struct dentry		*root = pstore_sb->s_root;
 	struct dentry		*dentry;
 	struct inode		*inode;
-	int			rc;
+	int			rc = 0;
 	char			name[PSTORE_NAMELEN];
-	struct pstore_private	*private;
+	struct pstore_private	*private, *pos;
+	unsigned long		flags;
+
+	spin_lock_irqsave(&allpstore_lock, flags);
+	list_for_each_entry(pos, &allpstore, list) {
+		if (pos->type == type &&
+		    pos->id == id &&
+		    pos->psi == psi) {
+			rc = -EEXIST;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&allpstore_lock, flags);
+	if (rc)
+		return rc;
 
 	rc = -ENOMEM;
 	inode = pstore_get_inode(pstore_sb, root->d_inode, S_IFREG | 0444, 0);
@@ -229,6 +257,10 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id,
 
 	d_add(dentry, inode);
 
+	spin_lock_irqsave(&allpstore_lock, flags);
+	list_add(&private->list, &allpstore);
+	spin_unlock_irqrestore(&allpstore_lock, flags);
+
 	mutex_unlock(&root->d_inode->i_mutex);
 
 	return 0;
@@ -277,7 +309,7 @@ int pstore_fill_super(struct super_block *sb, void *data, int silent)
 		goto fail;
 	}
 
-	pstore_get_records();
+	pstore_get_records(0);
 
 	return 0;
 fail:
diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h
index 611c1b3..3bde461 100644
--- a/fs/pstore/internal.h
+++ b/fs/pstore/internal.h
@@ -1,5 +1,5 @@
 extern void	pstore_set_kmsg_bytes(int);
-extern void	pstore_get_records(void);
+extern void	pstore_get_records(int);
 extern int	pstore_mkfile(enum pstore_type_id, char *psname, u64 id,
 			      char *data, size_t size,
 			      struct timespec time, struct pstore_info *psi);
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index c5300ec..2bd620f 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -25,12 +25,30 @@
 #include <linux/module.h>
 #include <linux/pstore.h>
 #include <linux/string.h>
+#include <linux/timer.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
+#include <linux/hardirq.h>
+#include <linux/workqueue.h>
 
 #include "internal.h"
 
 /*
+ * We defer making "oops" entries appear in pstore - see
+ * whether the system is actually still running well enough
+ * to let someone see the entry
+ */
+#define	PSTORE_INTERVAL	(60 * HZ)
+
+static int pstore_new_entry;
+
+static void pstore_timefunc(unsigned long);
+static DEFINE_TIMER(pstore_timer, pstore_timefunc, 0, 0);
+
+static void pstore_dowork(struct work_struct *);
+static DECLARE_WORK(pstore_work, pstore_dowork);
+
+/*
  * pstore_lock just protects "psinfo" during
  * calls to pstore_register()
  */
@@ -69,15 +87,22 @@ static void pstore_dump(struct kmsg_dumper *dumper,
 	unsigned long	size, total = 0;
 	char		*dst, *why;
 	u64		id;
-	int		hsize;
+	int		hsize, ret;
 	unsigned int	part = 1;
+	unsigned long	flags = 0;
+	int		is_locked = 0;
 
 	if (reason < ARRAY_SIZE(reason_str))
 		why = reason_str[reason];
 	else
 		why = "Unknown";
 
-	mutex_lock(&psinfo->buf_mutex);
+	if (in_nmi()) {
+		is_locked = spin_trylock(&psinfo->buf_lock);
+		if (!is_locked)
+			pr_err("pstore dump routine blocked in NMI, may corrupt error record\n");
+	} else
+		spin_lock_irqsave(&psinfo->buf_lock, flags);
 	oopscount++;
 	while (total < kmsg_bytes) {
 		dst = psinfo->buf;
@@ -97,18 +122,20 @@ static void pstore_dump(struct kmsg_dumper *dumper,
 		memcpy(dst, s1 + s1_start, l1_cpy);
 		memcpy(dst + l1_cpy, s2 + s2_start, l2_cpy);
 
-		id = psinfo->write(PSTORE_TYPE_DMESG, part,
+		ret = psinfo->write(PSTORE_TYPE_DMESG, &id, part,
 				   hsize + l1_cpy + l2_cpy, psinfo);
-		if (reason == KMSG_DUMP_OOPS && pstore_is_mounted())
-			pstore_mkfile(PSTORE_TYPE_DMESG, psinfo->name, id,
-				      psinfo->buf, hsize + l1_cpy + l2_cpy,
-				      CURRENT_TIME, psinfo);
+		if (ret == 0 && reason == KMSG_DUMP_OOPS && pstore_is_mounted())
+			pstore_new_entry = 1;
 		l1 -= l1_cpy;
 		l2 -= l2_cpy;
 		total += l1_cpy + l2_cpy;
 		part++;
 	}
-	mutex_unlock(&psinfo->buf_mutex);
+	if (in_nmi()) {
+		if (is_locked)
+			spin_unlock(&psinfo->buf_lock);
+	} else
+		spin_unlock_irqrestore(&psinfo->buf_lock, flags);
 }
 
 static struct kmsg_dumper pstore_dumper = {
@@ -148,19 +175,24 @@ int pstore_register(struct pstore_info *psi)
 	}
 
 	if (pstore_is_mounted())
-		pstore_get_records();
+		pstore_get_records(0);
 
 	kmsg_dump_register(&pstore_dumper);
 
+	pstore_timer.expires = jiffies + PSTORE_INTERVAL;
+	add_timer(&pstore_timer);
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(pstore_register);
 
 /*
- * Read all the records from the persistent store. Create and
- * file files in our filesystem.
+ * Read all the records from the persistent store. Create
+ * files in our filesystem.  Don't warn about -EEXIST errors
+ * when we are re-scanning the backing store looking to add new
+ * error records.
  */
-void pstore_get_records(void)
+void pstore_get_records(int quiet)
 {
 	struct pstore_info *psi = psinfo;
 	ssize_t			size;
@@ -168,36 +200,55 @@ void pstore_get_records(void)
 	enum pstore_type_id	type;
 	struct timespec		time;
 	int			failed = 0, rc;
+	unsigned long		flags;
 
 	if (!psi)
 		return;
 
-	mutex_lock(&psinfo->buf_mutex);
+	spin_lock_irqsave(&psinfo->buf_lock, flags);
 	rc = psi->open(psi);
 	if (rc)
 		goto out;
 
 	while ((size = psi->read(&id, &type, &time, psi)) > 0) {
-		if (pstore_mkfile(type, psi->name, id, psi->buf, (size_t)size,
-				  time, psi))
+		rc = pstore_mkfile(type, psi->name, id, psi->buf, (size_t)size,
+				  time, psi);
+		if (rc && (rc != -EEXIST || !quiet))
 			failed++;
 	}
 	psi->close(psi);
 out:
-	mutex_unlock(&psinfo->buf_mutex);
+	spin_unlock_irqrestore(&psinfo->buf_lock, flags);
 
 	if (failed)
 		printk(KERN_WARNING "pstore: failed to load %d record(s) from '%s'\n",
 		       failed, psi->name);
 }
 
+static void pstore_dowork(struct work_struct *work)
+{
+	pstore_get_records(1);
+}
+
+static void pstore_timefunc(unsigned long dummy)
+{
+	if (pstore_new_entry) {
+		pstore_new_entry = 0;
+		schedule_work(&pstore_work);
+	}
+
+	mod_timer(&pstore_timer, jiffies + PSTORE_INTERVAL);
+}
+
 /*
  * Call platform driver to write a record to the
  * persistent store.
  */
 int pstore_write(enum pstore_type_id type, char *buf, size_t size)
 {
-	u64	id;
+	u64		id;
+	int		ret;
+	unsigned long	flags;
 
 	if (!psinfo)
 		return -ENODEV;
@@ -205,13 +256,13 @@ int pstore_write(enum pstore_type_id type, char *buf, size_t size)
 	if (size > psinfo->bufsize)
 		return -EFBIG;
 
-	mutex_lock(&psinfo->buf_mutex);
+	spin_lock_irqsave(&psinfo->buf_lock, flags);
 	memcpy(psinfo->buf, buf, size);
-	id = psinfo->write(type, 0, size, psinfo);
-	if (pstore_is_mounted())
+	ret = psinfo->write(type, &id, 0, size, psinfo);
+	if (ret == 0 && pstore_is_mounted())
 		pstore_mkfile(PSTORE_TYPE_DMESG, psinfo->name, id, psinfo->buf,
 			      size, CURRENT_TIME, psinfo);
-	mutex_unlock(&psinfo->buf_mutex);
+	spin_unlock_irqrestore(&psinfo->buf_lock, flags);
 
 	return 0;
 }
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
index 2b06466..3bdd214 100644
--- a/fs/qnx4/inode.c
+++ b/fs/qnx4/inode.c
@@ -379,7 +379,7 @@ struct inode *qnx4_iget(struct super_block *sb, unsigned long ino)
 	inode->i_mode    = le16_to_cpu(raw_inode->di_mode);
 	inode->i_uid     = (uid_t)le16_to_cpu(raw_inode->di_uid);
 	inode->i_gid     = (gid_t)le16_to_cpu(raw_inode->di_gid);
-	inode->i_nlink   = le16_to_cpu(raw_inode->di_nlink);
+	set_nlink(inode, le16_to_cpu(raw_inode->di_nlink));
 	inode->i_size    = le32_to_cpu(raw_inode->di_size);
 	inode->i_mtime.tv_sec   = le32_to_cpu(raw_inode->di_mtime);
 	inode->i_mtime.tv_nsec = 0;
diff --git a/fs/quota/quota.c b/fs/quota/quota.c
index 10b6be3..aae0edb 100644
--- a/fs/quota/quota.c
+++ b/fs/quota/quota.c
@@ -363,12 +363,15 @@ SYSCALL_DEFINE4(quotactl, unsigned int, cmd, const char __user *, special,
 	}
 
 	sb = quotactl_block(special);
-	if (IS_ERR(sb))
-		return PTR_ERR(sb);
+	if (IS_ERR(sb)) {
+		ret = PTR_ERR(sb);
+		goto out;
+	}
 
 	ret = do_quotactl(sb, type, cmds, id, addr, pathp);
 
 	drop_super(sb);
+out:
 	if (pathp && !IS_ERR(pathp))
 		path_put(pathp);
 	return ret;
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index eacb166..462ceb3 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -23,7 +23,6 @@
  * caches is sufficient.
  */
 
-#include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
 #include <linux/highmem.h>
@@ -288,14 +287,7 @@ static int __init init_ramfs_fs(void)
 {
 	return register_filesystem(&ramfs_fs_type);
 }
-
-static void __exit exit_ramfs_fs(void)
-{
-	unregister_filesystem(&ramfs_fs_type);
-}
-
 module_init(init_ramfs_fs)
-module_exit(exit_ramfs_fs)
 
 int __init init_rootfs(void)
 {
@@ -311,5 +303,3 @@ int __init init_rootfs(void)
 
 	return err;
 }
-
-MODULE_LICENSE("GPL");
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 9b0d4b7..950f13a 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -1154,7 +1154,7 @@ static void init_inode(struct inode *inode, struct treepath *path)
 		set_inode_item_key_version(inode, KEY_FORMAT_3_5);
 		set_inode_sd_version(inode, STAT_DATA_V1);
 		inode->i_mode = sd_v1_mode(sd);
-		inode->i_nlink = sd_v1_nlink(sd);
+		set_nlink(inode, sd_v1_nlink(sd));
 		inode->i_uid = sd_v1_uid(sd);
 		inode->i_gid = sd_v1_gid(sd);
 		inode->i_size = sd_v1_size(sd);
@@ -1199,7 +1199,7 @@ static void init_inode(struct inode *inode, struct treepath *path)
 		struct stat_data *sd = (struct stat_data *)B_I_PITEM(bh, ih);
 
 		inode->i_mode = sd_v2_mode(sd);
-		inode->i_nlink = sd_v2_nlink(sd);
+		set_nlink(inode, sd_v2_nlink(sd));
 		inode->i_uid = sd_v2_uid(sd);
 		inode->i_size = sd_v2_size(sd);
 		inode->i_gid = sd_v2_gid(sd);
@@ -1444,7 +1444,7 @@ void reiserfs_read_locked_inode(struct inode *inode,
 		/* a stale NFS handle can trigger this without it being an error */
 		pathrelse(&path_to_sd);
 		reiserfs_make_bad_inode(inode);
-		inode->i_nlink = 0;
+		clear_nlink(inode);
 		return;
 	}
 
@@ -1832,7 +1832,7 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
 #endif
 
 	/* fill stat data */
-	inode->i_nlink = (S_ISDIR(mode) ? 2 : 1);
+	set_nlink(inode, (S_ISDIR(mode) ? 2 : 1));
 
 	/* uid and gid must already be set by the caller for quota init */
 
@@ -1987,7 +1987,7 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
 	make_bad_inode(inode);
 
       out_inserted_sd:
-	inode->i_nlink = 0;
+	clear_nlink(inode);
 	th->t_trans_id = 0;	/* so the caller can't use this handle later */
 	unlock_new_inode(inode); /* OK to do even if we hadn't locked it */
 	iput(inode);
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index ef39232..80058e8 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -19,7 +19,7 @@
 #include <linux/reiserfs_xattr.h>
 #include <linux/quotaops.h>
 
-#define INC_DIR_INODE_NLINK(i) if (i->i_nlink != 1) { inc_nlink(i); if (i->i_nlink >= REISERFS_LINK_MAX) i->i_nlink=1; }
+#define INC_DIR_INODE_NLINK(i) if (i->i_nlink != 1) { inc_nlink(i); if (i->i_nlink >= REISERFS_LINK_MAX) set_nlink(i, 1); }
 #define DEC_DIR_INODE_NLINK(i) if (i->i_nlink != 1) drop_nlink(i);
 
 // directory item contains array of entry headers. This performs
@@ -622,7 +622,7 @@ static int reiserfs_create(struct inode *dir, struct dentry *dentry, int mode,
 			       dentry->d_name.len, inode, 1 /*visible */ );
 	if (retval) {
 		int err;
-		inode->i_nlink--;
+		drop_nlink(inode);
 		reiserfs_update_sd(&th, inode);
 		err = journal_end(&th, dir->i_sb, jbegin_count);
 		if (err)
@@ -702,7 +702,7 @@ static int reiserfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
 			       dentry->d_name.len, inode, 1 /*visible */ );
 	if (retval) {
 		int err;
-		inode->i_nlink--;
+		drop_nlink(inode);
 		reiserfs_update_sd(&th, inode);
 		err = journal_end(&th, dir->i_sb, jbegin_count);
 		if (err)
@@ -787,7 +787,7 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 			       dentry->d_name.len, inode, 1 /*visible */ );
 	if (retval) {
 		int err;
-		inode->i_nlink = 0;
+		clear_nlink(inode);
 		DEC_DIR_INODE_NLINK(dir);
 		reiserfs_update_sd(&th, inode);
 		err = journal_end(&th, dir->i_sb, jbegin_count);
@@ -964,7 +964,7 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry)
 		reiserfs_warning(inode->i_sb, "reiserfs-7042",
 				 "deleting nonexistent file (%lu), %d",
 				 inode->i_ino, inode->i_nlink);
-		inode->i_nlink = 1;
+		set_nlink(inode, 1);
 	}
 
 	drop_nlink(inode);
@@ -1086,7 +1086,7 @@ static int reiserfs_symlink(struct inode *parent_dir,
 				    dentry->d_name.len, inode, 1 /*visible */ );
 	if (retval) {
 		int err;
-		inode->i_nlink--;
+		drop_nlink(inode);
 		reiserfs_update_sd(&th, inode);
 		err = journal_end(&th, parent_dir->i_sb, jbegin_count);
 		if (err)
@@ -1129,7 +1129,7 @@ static int reiserfs_link(struct dentry *old_dentry, struct inode *dir,
 
 	retval = journal_begin(&th, dir->i_sb, jbegin_count);
 	if (retval) {
-		inode->i_nlink--;
+		drop_nlink(inode);
 		reiserfs_write_unlock(dir->i_sb);
 		return retval;
 	}
@@ -1144,7 +1144,7 @@ static int reiserfs_link(struct dentry *old_dentry, struct inode *dir,
 
 	if (retval) {
 		int err;
-		inode->i_nlink--;
+		drop_nlink(inode);
 		err = journal_end(&th, dir->i_sb, jbegin_count);
 		reiserfs_write_unlock(dir->i_sb);
 		return err ? err : retval;
diff --git a/fs/romfs/super.c b/fs/romfs/super.c
index 2305e31..8b4089f 100644
--- a/fs/romfs/super.c
+++ b/fs/romfs/super.c
@@ -337,7 +337,7 @@ static struct inode *romfs_iget(struct super_block *sb, unsigned long pos)
 	inode->i_metasize = (ROMFH_SIZE + nlen + 1 + ROMFH_PAD) & ROMFH_MASK;
 	inode->i_dataoffset = pos + inode->i_metasize;
 
-	i->i_nlink = 1;		/* Hard to decide.. */
+	set_nlink(i, 1);		/* Hard to decide.. */
 	i->i_size = be32_to_cpu(ri.size);
 	i->i_mtime.tv_sec = i->i_atime.tv_sec = i->i_ctime.tv_sec = 0;
 	i->i_mtime.tv_nsec = i->i_atime.tv_nsec = i->i_ctime.tv_nsec = 0;
diff --git a/fs/squashfs/inode.c b/fs/squashfs/inode.c
index 04bebca..fd7b3b3 100644
--- a/fs/squashfs/inode.c
+++ b/fs/squashfs/inode.c
@@ -159,7 +159,7 @@ int squashfs_read_inode(struct inode *inode, long long ino)
 			frag_offset = 0;
 		}
 
-		inode->i_nlink = 1;
+		set_nlink(inode, 1);
 		inode->i_size = le32_to_cpu(sqsh_ino->file_size);
 		inode->i_fop = &generic_ro_fops;
 		inode->i_mode |= S_IFREG;
@@ -203,7 +203,7 @@ int squashfs_read_inode(struct inode *inode, long long ino)
 		}
 
 		xattr_id = le32_to_cpu(sqsh_ino->xattr);
-		inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
+		set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
 		inode->i_size = le64_to_cpu(sqsh_ino->file_size);
 		inode->i_op = &squashfs_inode_ops;
 		inode->i_fop = &generic_ro_fops;
@@ -232,7 +232,7 @@ int squashfs_read_inode(struct inode *inode, long long ino)
 		if (err < 0)
 			goto failed_read;
 
-		inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
+		set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
 		inode->i_size = le16_to_cpu(sqsh_ino->file_size);
 		inode->i_op = &squashfs_dir_inode_ops;
 		inode->i_fop = &squashfs_dir_ops;
@@ -257,7 +257,7 @@ int squashfs_read_inode(struct inode *inode, long long ino)
 			goto failed_read;
 
 		xattr_id = le32_to_cpu(sqsh_ino->xattr);
-		inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
+		set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
 		inode->i_size = le32_to_cpu(sqsh_ino->file_size);
 		inode->i_op = &squashfs_dir_inode_ops;
 		inode->i_fop = &squashfs_dir_ops;
@@ -284,7 +284,7 @@ int squashfs_read_inode(struct inode *inode, long long ino)
 		if (err < 0)
 			goto failed_read;
 
-		inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
+		set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
 		inode->i_size = le32_to_cpu(sqsh_ino->symlink_size);
 		inode->i_op = &squashfs_symlink_inode_ops;
 		inode->i_data.a_ops = &squashfs_symlink_aops;
@@ -325,7 +325,7 @@ int squashfs_read_inode(struct inode *inode, long long ino)
 			inode->i_mode |= S_IFCHR;
 		else
 			inode->i_mode |= S_IFBLK;
-		inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
+		set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
 		rdev = le32_to_cpu(sqsh_ino->rdev);
 		init_special_inode(inode, inode->i_mode, new_decode_dev(rdev));
 
@@ -349,7 +349,7 @@ int squashfs_read_inode(struct inode *inode, long long ino)
 			inode->i_mode |= S_IFBLK;
 		xattr_id = le32_to_cpu(sqsh_ino->xattr);
 		inode->i_op = &squashfs_inode_ops;
-		inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
+		set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
 		rdev = le32_to_cpu(sqsh_ino->rdev);
 		init_special_inode(inode, inode->i_mode, new_decode_dev(rdev));
 
@@ -370,7 +370,7 @@ int squashfs_read_inode(struct inode *inode, long long ino)
 			inode->i_mode |= S_IFIFO;
 		else
 			inode->i_mode |= S_IFSOCK;
-		inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
+		set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
 		init_special_inode(inode, inode->i_mode, 0);
 		break;
 	}
@@ -389,7 +389,7 @@ int squashfs_read_inode(struct inode *inode, long long ino)
 			inode->i_mode |= S_IFSOCK;
 		xattr_id = le32_to_cpu(sqsh_ino->xattr);
 		inode->i_op = &squashfs_inode_ops;
-		inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
+		set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
 		init_special_inode(inode, inode->i_mode, 0);
 		break;
 	}
diff --git a/fs/stack.c b/fs/stack.c
index b4f2ab4..9c11519 100644
--- a/fs/stack.c
+++ b/fs/stack.c
@@ -71,6 +71,6 @@ void fsstack_copy_attr_all(struct inode *dest, const struct inode *src)
 	dest->i_ctime = src->i_ctime;
 	dest->i_blkbits = src->i_blkbits;
 	dest->i_flags = src->i_flags;
-	dest->i_nlink = src->i_nlink;
+	set_nlink(dest, src->i_nlink);
 }
 EXPORT_SYMBOL_GPL(fsstack_copy_attr_all);
diff --git a/fs/stat.c b/fs/stat.c
index 78a3aa8..8806b89 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -294,15 +294,16 @@ SYSCALL_DEFINE4(readlinkat, int, dfd, const char __user *, pathname,
 {
 	struct path path;
 	int error;
+	int empty = 0;
 
 	if (bufsiz <= 0)
 		return -EINVAL;
 
-	error = user_path_at(dfd, pathname, LOOKUP_EMPTY, &path);
+	error = user_path_at_empty(dfd, pathname, LOOKUP_EMPTY, &path, &empty);
 	if (!error) {
 		struct inode *inode = path.dentry->d_inode;
 
-		error = -EINVAL;
+		error = empty ? -ENOENT : -EINVAL;
 		if (inode->i_op->readlink) {
 			error = security_inode_readlink(path.dentry);
 			if (!error) {
diff --git a/fs/super.c b/fs/super.c
index 32a81f3..afd0f1a 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -727,8 +727,13 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
 
 	if (sb->s_op->remount_fs) {
 		retval = sb->s_op->remount_fs(sb, &flags, data);
-		if (retval)
-			return retval;
+		if (retval) {
+			if (!force)
+				return retval;
+			/* If forced remount, go ahead despite any errors */
+			WARN(1, "forced remount of a %s fs returned %i\n",
+			     sb->s_type->name, retval);
+		}
 	}
 	sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK);
 
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 48ffbdf..7fdf6a7 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -865,15 +865,13 @@ int sysfs_rename(struct sysfs_dirent *sd,
 		sd->s_name = new_name;
 	}
 
-	/* Remove from old parent's list and insert into new parent's list. */
-	if (sd->s_parent != new_parent_sd) {
-		sysfs_unlink_sibling(sd);
-		sysfs_get(new_parent_sd);
-		sysfs_put(sd->s_parent);
-		sd->s_parent = new_parent_sd;
-		sysfs_link_sibling(sd);
-	}
+	/* Move to the appropriate place in the appropriate directories rbtree. */
+	sysfs_unlink_sibling(sd);
+	sysfs_get(new_parent_sd);
+	sysfs_put(sd->s_parent);
 	sd->s_ns = new_ns;
+	sd->s_parent = new_parent_sd;
+	sysfs_link_sibling(sd);
 
 	error = 0;
  out:
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index e23f288..c81b22f 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -218,7 +218,7 @@ static void sysfs_refresh_inode(struct sysfs_dirent *sd, struct inode *inode)
 	}
 
 	if (sysfs_type(sd) == SYSFS_DIR)
-		inode->i_nlink = sd->s_dir.subdirs + 2;
+		set_nlink(inode, sd->s_dir.subdirs + 2);
 }
 
 int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c
index 0630eb9..25ffb3e 100644
--- a/fs/sysv/inode.c
+++ b/fs/sysv/inode.c
@@ -219,7 +219,7 @@ struct inode *sysv_iget(struct super_block *sb, unsigned int ino)
 	inode->i_mode = fs16_to_cpu(sbi, raw_inode->i_mode);
 	inode->i_uid = (uid_t)fs16_to_cpu(sbi, raw_inode->i_uid);
 	inode->i_gid = (gid_t)fs16_to_cpu(sbi, raw_inode->i_gid);
-	inode->i_nlink = fs16_to_cpu(sbi, raw_inode->i_nlink);
+	set_nlink(inode, fs16_to_cpu(sbi, raw_inode->i_nlink));
 	inode->i_size = fs32_to_cpu(sbi, raw_inode->i_size);
 	inode->i_atime.tv_sec = fs32_to_cpu(sbi, raw_inode->i_atime);
 	inode->i_mtime.tv_sec = fs32_to_cpu(sbi, raw_inode->i_mtime);
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index b281212..20403dc 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -129,7 +129,7 @@ struct inode *ubifs_iget(struct super_block *sb, unsigned long inum)
 		goto out_ino;
 
 	inode->i_flags |= (S_NOCMTIME | S_NOATIME);
-	inode->i_nlink = le32_to_cpu(ino->nlink);
+	set_nlink(inode, le32_to_cpu(ino->nlink));
 	inode->i_uid   = le32_to_cpu(ino->uid);
 	inode->i_gid   = le32_to_cpu(ino->gid);
 	inode->i_atime.tv_sec  = (int64_t)le64_to_cpu(ino->atime_sec);
diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c
index 16f19f5..bf18f7a 100644
--- a/fs/ubifs/xattr.c
+++ b/fs/ubifs/xattr.c
@@ -558,10 +558,10 @@ int ubifs_removexattr(struct dentry *dentry, const char *name)
 	}
 
 	ubifs_assert(inode->i_nlink == 1);
-	inode->i_nlink = 0;
+	clear_nlink(inode);
 	err = remove_xattr(c, host, inode, &nm);
 	if (err)
-		inode->i_nlink = 1;
+		set_nlink(inode, 1);
 
 	/* If @i_nlink is 0, 'iput()' will delete the inode */
 	iput(inode);
diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c
index 95518a9..987585b 100644
--- a/fs/udf/balloc.c
+++ b/fs/udf/balloc.c
@@ -59,8 +59,8 @@ static int __load_block_bitmap(struct super_block *sb,
 	int nr_groups = bitmap->s_nr_groups;
 
 	if (block_group >= nr_groups) {
-		udf_debug("block_group (%d) > nr_groups (%d)\n", block_group,
-			  nr_groups);
+		udf_debug("block_group (%d) > nr_groups (%d)\n",
+			  block_group, nr_groups);
 	}
 
 	if (bitmap->s_block_bitmap[block_group]) {
@@ -126,8 +126,9 @@ static void udf_bitmap_free_blocks(struct super_block *sb,
 	if (bloc->logicalBlockNum + count < count ||
 	    (bloc->logicalBlockNum + count) > partmap->s_partition_len) {
 		udf_debug("%d < %d || %d + %d > %d\n",
-			  bloc->logicalBlockNum, 0, bloc->logicalBlockNum,
-			  count, partmap->s_partition_len);
+			  bloc->logicalBlockNum, 0,
+			  bloc->logicalBlockNum, count,
+			  partmap->s_partition_len);
 		goto error_return;
 	}
 
@@ -155,7 +156,7 @@ static void udf_bitmap_free_blocks(struct super_block *sb,
 			if (udf_set_bit(bit + i, bh->b_data)) {
 				udf_debug("bit %ld already set\n", bit + i);
 				udf_debug("byte=%2x\n",
-					((char *)bh->b_data)[(bit + i) >> 3]);
+					  ((char *)bh->b_data)[(bit + i) >> 3]);
 			}
 		}
 		udf_add_free_space(sb, sbi->s_partition, count);
@@ -369,7 +370,8 @@ static void udf_table_free_blocks(struct super_block *sb,
 	if (bloc->logicalBlockNum + count < count ||
 	    (bloc->logicalBlockNum + count) > partmap->s_partition_len) {
 		udf_debug("%d < %d || %d + %d > %d\n",
-			  bloc->logicalBlockNum, 0, bloc->logicalBlockNum, count,
+			  bloc->logicalBlockNum, 0,
+			  bloc->logicalBlockNum, count,
 			  partmap->s_partition_len);
 		goto error_return;
 	}
diff --git a/fs/udf/directory.c b/fs/udf/directory.c
index 2ffdb67..3e44f57 100644
--- a/fs/udf/directory.c
+++ b/fs/udf/directory.c
@@ -162,8 +162,8 @@ struct fileIdentDesc *udf_get_fileident(void *buffer, int bufsize, int *offset)
 	int padlen;
 
 	if ((!buffer) || (!offset)) {
-		udf_debug("invalidparms\n, buffer=%p, offset=%p\n", buffer,
-			  offset);
+		udf_debug("invalidparms, buffer=%p, offset=%p\n",
+			  buffer, offset);
 		return NULL;
 	}
 
@@ -201,7 +201,7 @@ struct short_ad *udf_get_fileshortad(uint8_t *ptr, int maxoffset, uint32_t *offs
 	struct short_ad *sa;
 
 	if ((!ptr) || (!offset)) {
-		printk(KERN_ERR "udf: udf_get_fileshortad() invalidparms\n");
+		pr_err("%s: invalidparms\n", __func__);
 		return NULL;
 	}
 
@@ -223,7 +223,7 @@ struct long_ad *udf_get_filelongad(uint8_t *ptr, int maxoffset, uint32_t *offset
 	struct long_ad *la;
 
 	if ((!ptr) || (!offset)) {
-		printk(KERN_ERR "udf: udf_get_filelongad() invalidparms\n");
+		pr_err("%s: invalidparms\n", __func__);
 		return NULL;
 	}
 
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 1d1358e..4fd1d80 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -37,6 +37,7 @@
 #include <linux/writeback.h>
 #include <linux/slab.h>
 #include <linux/crc-itu-t.h>
+#include <linux/mpage.h>
 
 #include "udf_i.h"
 #include "udf_sb.h"
@@ -83,12 +84,10 @@ void udf_evict_inode(struct inode *inode)
 	end_writeback(inode);
 	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 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);
+		udf_warn(inode->i_sb, "Inode %lu (mode %o) has inode size %llu different from extent length %llu. Filesystem need not be standards compliant.\n",
+			 inode->i_ino, inode->i_mode,
+			 (unsigned long long)inode->i_size,
+			 (unsigned long long)iinfo->i_lenExtents);
 	}
 	kfree(iinfo->i_ext.i_data);
 	iinfo->i_ext.i_data = NULL;
@@ -104,7 +103,13 @@ static int udf_writepage(struct page *page, struct writeback_control *wbc)
 
 static int udf_readpage(struct file *file, struct page *page)
 {
-	return block_read_full_page(page, udf_get_block);
+	return mpage_readpage(page, udf_get_block);
+}
+
+static int udf_readpages(struct file *file, struct address_space *mapping,
+			struct list_head *pages, unsigned nr_pages)
+{
+	return mpage_readpages(mapping, pages, nr_pages, udf_get_block);
 }
 
 static int udf_write_begin(struct file *file, struct address_space *mapping,
@@ -139,6 +144,7 @@ static sector_t udf_bmap(struct address_space *mapping, sector_t block)
 
 const struct address_space_operations udf_aops = {
 	.readpage	= udf_readpage,
+	.readpages	= udf_readpages,
 	.writepage	= udf_writepage,
 	.write_begin		= udf_write_begin,
 	.write_end		= generic_write_end,
@@ -1169,16 +1175,15 @@ static void __udf_read_inode(struct inode *inode)
 	 */
 	bh = udf_read_ptagged(inode->i_sb, &iinfo->i_location, 0, &ident);
 	if (!bh) {
-		printk(KERN_ERR "udf: udf_read_inode(ino %ld) failed !bh\n",
-		       inode->i_ino);
+		udf_err(inode->i_sb, "(ino %ld) failed !bh\n", inode->i_ino);
 		make_bad_inode(inode);
 		return;
 	}
 
 	if (ident != TAG_IDENT_FE && ident != TAG_IDENT_EFE &&
 	    ident != TAG_IDENT_USE) {
-		printk(KERN_ERR "udf: udf_read_inode(ino %ld) "
-				"failed ident=%d\n", inode->i_ino, ident);
+		udf_err(inode->i_sb, "(ino %ld) failed ident=%d\n",
+			inode->i_ino, ident);
 		brelse(bh);
 		make_bad_inode(inode);
 		return;
@@ -1218,8 +1223,8 @@ static void __udf_read_inode(struct inode *inode)
 		}
 		brelse(ibh);
 	} else if (fe->icbTag.strategyType != cpu_to_le16(4)) {
-		printk(KERN_ERR "udf: unsupported strategy type: %d\n",
-		       le16_to_cpu(fe->icbTag.strategyType));
+		udf_err(inode->i_sb, "unsupported strategy type: %d\n",
+			le16_to_cpu(fe->icbTag.strategyType));
 		brelse(bh);
 		make_bad_inode(inode);
 		return;
@@ -1236,6 +1241,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
 	int offset;
 	struct udf_sb_info *sbi = UDF_SB(inode->i_sb);
 	struct udf_inode_info *iinfo = UDF_I(inode);
+	unsigned int link_count;
 
 	fe = (struct fileEntry *)bh->b_data;
 	efe = (struct extendedFileEntry *)bh->b_data;
@@ -1318,9 +1324,10 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
 	inode->i_mode &= ~sbi->s_umask;
 	read_unlock(&sbi->s_cred_lock);
 
-	inode->i_nlink = le16_to_cpu(fe->fileLinkCount);
-	if (!inode->i_nlink)
-		inode->i_nlink = 1;
+	link_count = le16_to_cpu(fe->fileLinkCount);
+	if (!link_count)
+		link_count = 1;
+	set_nlink(inode, link_count);
 
 	inode->i_size = le64_to_cpu(fe->informationLength);
 	iinfo->i_lenExtents = inode->i_size;
@@ -1413,9 +1420,8 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
 		udf_debug("METADATA BITMAP FILE-----\n");
 		break;
 	default:
-		printk(KERN_ERR "udf: udf_fill_inode(ino %ld) failed unknown "
-				"file type=%d\n", inode->i_ino,
-				fe->icbTag.fileType);
+		udf_err(inode->i_sb, "(ino %ld) failed unknown file type=%d\n",
+			inode->i_ino, fe->icbTag.fileType);
 		make_bad_inode(inode);
 		return;
 	}
@@ -1438,8 +1444,8 @@ static int udf_alloc_i_data(struct inode *inode, size_t size)
 	iinfo->i_ext.i_data = kmalloc(size, GFP_KERNEL);
 
 	if (!iinfo->i_ext.i_data) {
-		printk(KERN_ERR "udf:udf_alloc_i_data (ino %ld) "
-				"no free memory\n", inode->i_ino);
+		udf_err(inode->i_sb, "(ino %ld) no free memory\n",
+			inode->i_ino);
 		return -ENOMEM;
 	}
 
@@ -1689,9 +1695,8 @@ out:
 	if (do_sync) {
 		sync_dirty_buffer(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);
+			udf_warn(inode->i_sb, "IO error syncing udf inode [%08lx]\n",
+				 inode->i_ino);
 			err = -EIO;
 		}
 	}
@@ -1982,8 +1987,7 @@ int8_t udf_current_aext(struct inode *inode, struct extent_position *epos,
 		*elen = le32_to_cpu(lad->extLength) & UDF_EXTENT_LENGTH_MASK;
 		break;
 	default:
-		udf_debug("alloc_type = %d unsupported\n",
-				iinfo->i_alloc_type);
+		udf_debug("alloc_type = %d unsupported\n", iinfo->i_alloc_type);
 		return -1;
 	}
 
diff --git a/fs/udf/lowlevel.c b/fs/udf/lowlevel.c
index 43e24a3..6583fe9 100644
--- a/fs/udf/lowlevel.c
+++ b/fs/udf/lowlevel.c
@@ -38,7 +38,7 @@ unsigned int udf_get_last_session(struct super_block *sb)
 
 	if (i == 0) {
 		udf_debug("XA disk: %s, vol_desc_start=%d\n",
-			  (ms_info.xa_flag ? "yes" : "no"), ms_info.addr.lba);
+			  ms_info.xa_flag ? "yes" : "no", ms_info.addr.lba);
 		if (ms_info.xa_flag) /* necessary for a valid ms_info.addr */
 			vol_desc_start = ms_info.addr.lba;
 	} else {
diff --git a/fs/udf/misc.c b/fs/udf/misc.c
index 9215700..c175b4d 100644
--- a/fs/udf/misc.c
+++ b/fs/udf/misc.c
@@ -204,6 +204,7 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,
 {
 	struct tag *tag_p;
 	struct buffer_head *bh = NULL;
+	u8 checksum;
 
 	/* Read the block */
 	if (block == 0xFFFFFFFF)
@@ -211,8 +212,8 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,
 
 	bh = udf_tread(sb, block);
 	if (!bh) {
-		udf_debug("block=%d, location=%d: read failed\n",
-			  block, location);
+		udf_err(sb, "read failed, block=%u, location=%d\n",
+			block, location);
 		return NULL;
 	}
 
@@ -227,16 +228,18 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,
 	}
 
 	/* Verify the tag checksum */
-	if (udf_tag_checksum(tag_p) != tag_p->tagChecksum) {
-		printk(KERN_ERR "udf: tag checksum failed block %d\n", block);
+	checksum = udf_tag_checksum(tag_p);
+	if (checksum != tag_p->tagChecksum) {
+		udf_err(sb, "tag checksum failed, block %u: 0x%02x != 0x%02x\n",
+			block, checksum, tag_p->tagChecksum);
 		goto error_out;
 	}
 
 	/* Verify the tag version */
 	if (tag_p->descVersion != cpu_to_le16(0x0002U) &&
 	    tag_p->descVersion != cpu_to_le16(0x0003U)) {
-		udf_debug("tag version 0x%04x != 0x0002 || 0x0003 block %d\n",
-			  le16_to_cpu(tag_p->descVersion), block);
+		udf_err(sb, "tag version 0x%04x != 0x0002 || 0x0003, block %u\n",
+			le16_to_cpu(tag_p->descVersion), block);
 		goto error_out;
 	}
 
@@ -248,8 +251,8 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,
 		return bh;
 
 	udf_debug("Crc failure block %d: crc = %d, crclen = %d\n", block,
-	    le16_to_cpu(tag_p->descCRC), le16_to_cpu(tag_p->descCRCLength));
-
+		  le16_to_cpu(tag_p->descCRC),
+		  le16_to_cpu(tag_p->descCRCLength));
 error_out:
 	brelse(bh);
 	return NULL;
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index f1dce84..4639e13 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -577,8 +577,7 @@ static int udf_create(struct inode *dir, struct dentry *dentry, int mode,
 
 	fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
 	if (!fi) {
-		inode->i_nlink--;
-		mark_inode_dirty(inode);
+		inode_dec_link_count(inode);
 		iput(inode);
 		return err;
 	}
@@ -618,8 +617,7 @@ static int udf_mknod(struct inode *dir, struct dentry *dentry, int mode,
 	init_special_inode(inode, mode, rdev);
 	fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
 	if (!fi) {
-		inode->i_nlink--;
-		mark_inode_dirty(inode);
+		inode_dec_link_count(inode);
 		iput(inode);
 		return err;
 	}
@@ -665,12 +663,11 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 	inode->i_fop = &udf_dir_operations;
 	fi = udf_add_entry(inode, NULL, &fibh, &cfi, &err);
 	if (!fi) {
-		inode->i_nlink--;
-		mark_inode_dirty(inode);
+		inode_dec_link_count(inode);
 		iput(inode);
 		goto out;
 	}
-	inode->i_nlink = 2;
+	set_nlink(inode, 2);
 	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
 	cfi.icb.extLocation = cpu_to_lelb(dinfo->i_location);
 	*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
@@ -683,7 +680,7 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 
 	fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
 	if (!fi) {
-		inode->i_nlink = 0;
+		clear_nlink(inode);
 		mark_inode_dirty(inode);
 		iput(inode);
 		goto out;
@@ -799,9 +796,8 @@ static int udf_rmdir(struct inode *dir, struct dentry *dentry)
 	if (retval)
 		goto end_rmdir;
 	if (inode->i_nlink != 2)
-		udf_warning(inode->i_sb, "udf_rmdir",
-			    "empty directory has nlink != 2 (%d)",
-			    inode->i_nlink);
+		udf_warn(inode->i_sb, "empty directory has nlink != 2 (%d)\n",
+			 inode->i_nlink);
 	clear_nlink(inode);
 	inode->i_size = 0;
 	inode_dec_link_count(dir);
@@ -840,7 +836,7 @@ static int udf_unlink(struct inode *dir, struct dentry *dentry)
 	if (!inode->i_nlink) {
 		udf_debug("Deleting nonexistent file (%lu), %d\n",
 			  inode->i_ino, inode->i_nlink);
-		inode->i_nlink = 1;
+		set_nlink(inode, 1);
 	}
 	retval = udf_delete_entry(dir, fi, &fibh, &cfi);
 	if (retval)
diff --git a/fs/udf/partition.c b/fs/udf/partition.c
index a71090e..d6caf01 100644
--- a/fs/udf/partition.c
+++ b/fs/udf/partition.c
@@ -33,8 +33,8 @@ uint32_t udf_get_pblock(struct super_block *sb, uint32_t block,
 	struct udf_sb_info *sbi = UDF_SB(sb);
 	struct udf_part_map *map;
 	if (partition >= sbi->s_partitions) {
-		udf_debug("block=%d, partition=%d, offset=%d: "
-			  "invalid partition\n", block, partition, offset);
+		udf_debug("block=%d, partition=%d, offset=%d: invalid partition\n",
+			  block, partition, offset);
 		return 0xFFFFFFFF;
 	}
 	map = &sbi->s_partmaps[partition];
@@ -60,8 +60,8 @@ uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block,
 	vdata = &map->s_type_specific.s_virtual;
 
 	if (block > vdata->s_num_entries) {
-		udf_debug("Trying to access block beyond end of VAT "
-			  "(%d max %d)\n", block, vdata->s_num_entries);
+		udf_debug("Trying to access block beyond end of VAT (%d max %d)\n",
+			  block, vdata->s_num_entries);
 		return 0xFFFFFFFF;
 	}
 
@@ -321,9 +321,14 @@ uint32_t udf_get_pblock_meta25(struct super_block *sb, uint32_t block,
 	/* We shouldn't mount such media... */
 	BUG_ON(!inode);
 	retblk = udf_try_read_meta(inode, block, partition, offset);
-	if (retblk == 0xFFFFFFFF) {
-		udf_warning(sb, __func__, "error reading from METADATA, "
-			"trying to read from MIRROR");
+	if (retblk == 0xFFFFFFFF && mdata->s_metadata_fe) {
+		udf_warn(sb, "error reading from METADATA, trying to read from MIRROR\n");
+		if (!(mdata->s_flags & MF_MIRROR_FE_LOADED)) {
+			mdata->s_mirror_fe = udf_find_metadata_inode_efe(sb,
+				mdata->s_mirror_file_loc, map->s_partition_num);
+			mdata->s_flags |= MF_MIRROR_FE_LOADED;
+		}
+
 		inode = mdata->s_mirror_fe;
 		if (!inode)
 			return 0xFFFFFFFF;
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 7b27b06..e185253 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -75,8 +75,6 @@
 
 #define UDF_DEFAULT_BLOCKSIZE 2048
 
-static char error_buf[1024];
-
 /* These are the "meat" - everything else is stuffing */
 static int udf_fill_super(struct super_block *, void *, int);
 static void udf_put_super(struct super_block *);
@@ -92,8 +90,6 @@ static void udf_close_lvid(struct super_block *);
 static unsigned int udf_count_free(struct super_block *);
 static int udf_statfs(struct dentry *, struct kstatfs *);
 static int udf_show_options(struct seq_file *, struct vfsmount *);
-static void udf_error(struct super_block *sb, const char *function,
-		      const char *fmt, ...);
 
 struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct udf_sb_info *sbi)
 {
@@ -244,9 +240,8 @@ static int udf_sb_alloc_partition_maps(struct super_block *sb, u32 count)
 	sbi->s_partmaps = kcalloc(count, sizeof(struct udf_part_map),
 				  GFP_KERNEL);
 	if (!sbi->s_partmaps) {
-		udf_error(sb, __func__,
-			  "Unable to allocate space for %d partition maps",
-			  count);
+		udf_err(sb, "Unable to allocate space for %d partition maps\n",
+			count);
 		sbi->s_partitions = 0;
 		return -ENOMEM;
 	}
@@ -550,8 +545,7 @@ static int udf_parse_options(char *options, struct udf_options *uopt,
 			uopt->dmode = option & 0777;
 			break;
 		default:
-			printk(KERN_ERR "udf: bad mount option \"%s\" "
-			       "or missing value\n", p);
+			pr_err("bad mount option \"%s\" or missing value\n", p);
 			return 0;
 		}
 	}
@@ -645,20 +639,16 @@ static loff_t udf_check_vsd(struct super_block *sb)
 				udf_debug("ISO9660 Boot Record found\n");
 				break;
 			case 1:
-				udf_debug("ISO9660 Primary Volume Descriptor "
-					  "found\n");
+				udf_debug("ISO9660 Primary Volume Descriptor found\n");
 				break;
 			case 2:
-				udf_debug("ISO9660 Supplementary Volume "
-					  "Descriptor found\n");
+				udf_debug("ISO9660 Supplementary Volume Descriptor found\n");
 				break;
 			case 3:
-				udf_debug("ISO9660 Volume Partition Descriptor "
-					  "found\n");
+				udf_debug("ISO9660 Volume Partition Descriptor found\n");
 				break;
 			case 255:
-				udf_debug("ISO9660 Volume Descriptor Set "
-					  "Terminator found\n");
+				udf_debug("ISO9660 Volume Descriptor Set Terminator found\n");
 				break;
 			default:
 				udf_debug("ISO9660 VRS (%u) found\n",
@@ -809,8 +799,7 @@ static int udf_load_pvoldesc(struct super_block *sb, sector_t block)
 			      pvoldesc->recordingDateAndTime)) {
 #ifdef UDFFS_DEBUG
 		struct timestamp *ts = &pvoldesc->recordingDateAndTime;
-		udf_debug("recording time %04u/%02u/%02u"
-			  " %02u:%02u (%x)\n",
+		udf_debug("recording time %04u/%02u/%02u %02u:%02u (%x)\n",
 			  le16_to_cpu(ts->year), ts->month, ts->day, ts->hour,
 			  ts->minute, le16_to_cpu(ts->typeAndTimezone));
 #endif
@@ -821,7 +810,7 @@ static int udf_load_pvoldesc(struct super_block *sb, sector_t block)
 			strncpy(UDF_SB(sb)->s_volume_ident, outstr->u_name,
 				outstr->u_len > 31 ? 31 : outstr->u_len);
 			udf_debug("volIdent[] = '%s'\n",
-					UDF_SB(sb)->s_volume_ident);
+				  UDF_SB(sb)->s_volume_ident);
 		}
 
 	if (!udf_build_ustr(instr, pvoldesc->volSetIdent, 128))
@@ -837,64 +826,57 @@ out1:
 	return ret;
 }
 
+struct inode *udf_find_metadata_inode_efe(struct super_block *sb,
+					u32 meta_file_loc, u32 partition_num)
+{
+	struct kernel_lb_addr addr;
+	struct inode *metadata_fe;
+
+	addr.logicalBlockNum = meta_file_loc;
+	addr.partitionReferenceNum = partition_num;
+
+	metadata_fe = udf_iget(sb, &addr);
+
+	if (metadata_fe == NULL)
+		udf_warn(sb, "metadata inode efe not found\n");
+	else if (UDF_I(metadata_fe)->i_alloc_type != ICBTAG_FLAG_AD_SHORT) {
+		udf_warn(sb, "metadata inode efe does not have short allocation descriptors!\n");
+		iput(metadata_fe);
+		metadata_fe = NULL;
+	}
+
+	return metadata_fe;
+}
+
 static int udf_load_metadata_files(struct super_block *sb, int partition)
 {
 	struct udf_sb_info *sbi = UDF_SB(sb);
 	struct udf_part_map *map;
 	struct udf_meta_data *mdata;
 	struct kernel_lb_addr addr;
-	int fe_error = 0;
 
 	map = &sbi->s_partmaps[partition];
 	mdata = &map->s_type_specific.s_metadata;
 
 	/* metadata address */
-	addr.logicalBlockNum =  mdata->s_meta_file_loc;
-	addr.partitionReferenceNum = map->s_partition_num;
-
 	udf_debug("Metadata file location: block = %d part = %d\n",
-			  addr.logicalBlockNum, addr.partitionReferenceNum);
+		  mdata->s_meta_file_loc, map->s_partition_num);
 
-	mdata->s_metadata_fe = udf_iget(sb, &addr);
+	mdata->s_metadata_fe = udf_find_metadata_inode_efe(sb,
+		mdata->s_meta_file_loc, map->s_partition_num);
 
 	if (mdata->s_metadata_fe == NULL) {
-		udf_warning(sb, __func__, "metadata inode efe not found, "
-				"will try mirror inode.");
-		fe_error = 1;
-	} else if (UDF_I(mdata->s_metadata_fe)->i_alloc_type !=
-		 ICBTAG_FLAG_AD_SHORT) {
-		udf_warning(sb, __func__, "metadata inode efe does not have "
-			"short allocation descriptors!");
-		fe_error = 1;
-		iput(mdata->s_metadata_fe);
-		mdata->s_metadata_fe = NULL;
-	}
+		/* mirror file entry */
+		udf_debug("Mirror metadata file location: block = %d part = %d\n",
+			  mdata->s_mirror_file_loc, map->s_partition_num);
 
-	/* mirror file entry */
-	addr.logicalBlockNum = mdata->s_mirror_file_loc;
-	addr.partitionReferenceNum = map->s_partition_num;
-
-	udf_debug("Mirror metadata file location: block = %d part = %d\n",
-			  addr.logicalBlockNum, addr.partitionReferenceNum);
+		mdata->s_mirror_fe = udf_find_metadata_inode_efe(sb,
+			mdata->s_mirror_file_loc, map->s_partition_num);
 
-	mdata->s_mirror_fe = udf_iget(sb, &addr);
-
-	if (mdata->s_mirror_fe == NULL) {
-		if (fe_error) {
-			udf_error(sb, __func__, "mirror inode efe not found "
-			"and metadata inode is missing too, exiting...");
-			goto error_exit;
-		} else
-			udf_warning(sb, __func__, "mirror inode efe not found,"
-					" but metadata inode is OK");
-	} else if (UDF_I(mdata->s_mirror_fe)->i_alloc_type !=
-		 ICBTAG_FLAG_AD_SHORT) {
-		udf_warning(sb, __func__, "mirror inode efe does not have "
-			"short allocation descriptors!");
-		iput(mdata->s_mirror_fe);
-		mdata->s_mirror_fe = NULL;
-		if (fe_error)
+		if (mdata->s_mirror_fe == NULL) {
+			udf_err(sb, "Both metadata and mirror metadata inode efe can not found\n");
 			goto error_exit;
+		}
 	}
 
 	/*
@@ -907,18 +889,15 @@ static int udf_load_metadata_files(struct super_block *sb, int partition)
 		addr.partitionReferenceNum = map->s_partition_num;
 
 		udf_debug("Bitmap file location: block = %d part = %d\n",
-			addr.logicalBlockNum, addr.partitionReferenceNum);
+			  addr.logicalBlockNum, addr.partitionReferenceNum);
 
 		mdata->s_bitmap_fe = udf_iget(sb, &addr);
 
 		if (mdata->s_bitmap_fe == NULL) {
 			if (sb->s_flags & MS_RDONLY)
-				udf_warning(sb, __func__, "bitmap inode efe "
-					"not found but it's ok since the disc"
-					" is mounted read-only");
+				udf_warn(sb, "bitmap inode efe not found but it's ok since the disc is mounted read-only\n");
 			else {
-				udf_error(sb, __func__, "bitmap inode efe not "
-					"found and attempted read-write mount");
+				udf_err(sb, "bitmap inode efe not found and attempted read-write mount\n");
 				goto error_exit;
 			}
 		}
@@ -971,9 +950,8 @@ static struct udf_bitmap *udf_sb_alloc_bitmap(struct super_block *sb, u32 index)
 		bitmap = vzalloc(size); /* TODO: get rid of vzalloc */
 
 	if (bitmap == NULL) {
-		udf_error(sb, __func__,
-			  "Unable to allocate space for bitmap "
-			  "and %d buffer_head pointers", nr_groups);
+		udf_err(sb, "Unable to allocate space for bitmap and %d buffer_head pointers\n",
+			nr_groups);
 		return NULL;
 	}
 
@@ -1003,10 +981,9 @@ static int udf_fill_partdesc_info(struct super_block *sb,
 	if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_OVERWRITABLE))
 		map->s_partition_flags |= UDF_PART_FLAG_OVERWRITABLE;
 
-	udf_debug("Partition (%d type %x) starts at physical %d, "
-		  "block length %d\n", p_index,
-		  map->s_partition_type, map->s_partition_root,
-		  map->s_partition_len);
+	udf_debug("Partition (%d type %x) starts at physical %d, block length %d\n",
+		  p_index, map->s_partition_type,
+		  map->s_partition_root, map->s_partition_len);
 
 	if (strcmp(p->partitionContents.ident, PD_PARTITION_CONTENTS_NSR02) &&
 	    strcmp(p->partitionContents.ident, PD_PARTITION_CONTENTS_NSR03))
@@ -1023,12 +1000,12 @@ static int udf_fill_partdesc_info(struct super_block *sb,
 		map->s_uspace.s_table = udf_iget(sb, &loc);
 		if (!map->s_uspace.s_table) {
 			udf_debug("cannot load unallocSpaceTable (part %d)\n",
-					p_index);
+				  p_index);
 			return 1;
 		}
 		map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_TABLE;
 		udf_debug("unallocSpaceTable (part %d) @ %ld\n",
-				p_index, map->s_uspace.s_table->i_ino);
+			  p_index, map->s_uspace.s_table->i_ino);
 	}
 
 	if (phd->unallocSpaceBitmap.extLength) {
@@ -1041,8 +1018,8 @@ static int udf_fill_partdesc_info(struct super_block *sb,
 		bitmap->s_extPosition = le32_to_cpu(
 				phd->unallocSpaceBitmap.extPosition);
 		map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_BITMAP;
-		udf_debug("unallocSpaceBitmap (part %d) @ %d\n", p_index,
-						bitmap->s_extPosition);
+		udf_debug("unallocSpaceBitmap (part %d) @ %d\n",
+			  p_index, bitmap->s_extPosition);
 	}
 
 	if (phd->partitionIntegrityTable.extLength)
@@ -1058,13 +1035,13 @@ static int udf_fill_partdesc_info(struct super_block *sb,
 		map->s_fspace.s_table = udf_iget(sb, &loc);
 		if (!map->s_fspace.s_table) {
 			udf_debug("cannot load freedSpaceTable (part %d)\n",
-				p_index);
+				  p_index);
 			return 1;
 		}
 
 		map->s_partition_flags |= UDF_PART_FLAG_FREED_TABLE;
 		udf_debug("freedSpaceTable (part %d) @ %ld\n",
-				p_index, map->s_fspace.s_table->i_ino);
+			  p_index, map->s_fspace.s_table->i_ino);
 	}
 
 	if (phd->freedSpaceBitmap.extLength) {
@@ -1077,8 +1054,8 @@ static int udf_fill_partdesc_info(struct super_block *sb,
 		bitmap->s_extPosition = le32_to_cpu(
 				phd->freedSpaceBitmap.extPosition);
 		map->s_partition_flags |= UDF_PART_FLAG_FREED_BITMAP;
-		udf_debug("freedSpaceBitmap (part %d) @ %d\n", p_index,
-					bitmap->s_extPosition);
+		udf_debug("freedSpaceBitmap (part %d) @ %d\n",
+			  p_index, bitmap->s_extPosition);
 	}
 	return 0;
 }
@@ -1118,11 +1095,9 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index)
 	udf_find_vat_block(sb, p_index, type1_index, sbi->s_last_block);
 	if (!sbi->s_vat_inode &&
 	    sbi->s_last_block != blocks - 1) {
-		printk(KERN_NOTICE "UDF-fs: Failed to read VAT inode from the"
-		       " last recorded block (%lu), retrying with the last "
-		       "block of the device (%lu).\n",
-		       (unsigned long)sbi->s_last_block,
-		       (unsigned long)blocks - 1);
+		pr_notice("Failed to read VAT inode from the last recorded block (%lu), retrying with the last block of the device (%lu).\n",
+			  (unsigned long)sbi->s_last_block,
+			  (unsigned long)blocks - 1);
 		udf_find_vat_block(sb, p_index, type1_index, blocks - 1);
 	}
 	if (!sbi->s_vat_inode)
@@ -1220,8 +1195,8 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block)
 	if (map->s_partition_type == UDF_METADATA_MAP25) {
 		ret = udf_load_metadata_files(sb, i);
 		if (ret) {
-			printk(KERN_ERR "UDF-fs: error loading MetaData "
-			"partition map %d\n", i);
+			udf_err(sb, "error loading MetaData partition map %d\n",
+				i);
 			goto out_bh;
 		}
 	} else {
@@ -1234,9 +1209,7 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block)
 		 * overwrite blocks instead of relocating them).
 		 */
 		sb->s_flags |= MS_RDONLY;
-		printk(KERN_NOTICE "UDF-fs: Filesystem marked read-only "
-			"because writing to pseudooverwrite partition is "
-			"not implemented.\n");
+		pr_notice("Filesystem marked read-only because writing to pseudooverwrite partition is not implemented\n");
 	}
 out_bh:
 	/* In case loading failed, we handle cleanup in udf_fill_super */
@@ -1344,9 +1317,8 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block,
 				struct metadataPartitionMap *mdm =
 						(struct metadataPartitionMap *)
 						&(lvd->partitionMaps[offset]);
-				udf_debug("Parsing Logical vol part %d "
-					"type %d  id=%s\n", i, type,
-					UDF_ID_METADATA);
+				udf_debug("Parsing Logical vol part %d type %d  id=%s\n",
+					  i, type, UDF_ID_METADATA);
 
 				map->s_partition_type = UDF_METADATA_MAP25;
 				map->s_partition_func = udf_get_pblock_meta25;
@@ -1361,25 +1333,24 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block,
 					le32_to_cpu(mdm->allocUnitSize);
 				mdata->s_align_unit_size =
 					le16_to_cpu(mdm->alignUnitSize);
-				mdata->s_dup_md_flag 	 =
-					mdm->flags & 0x01;
+				if (mdm->flags & 0x01)
+					mdata->s_flags |= MF_DUPLICATE_MD;
 
 				udf_debug("Metadata Ident suffix=0x%x\n",
-					(le16_to_cpu(
-					 ((__le16 *)
-					      mdm->partIdent.identSuffix)[0])));
+					  le16_to_cpu(*(__le16 *)
+						      mdm->partIdent.identSuffix));
 				udf_debug("Metadata part num=%d\n",
-					le16_to_cpu(mdm->partitionNum));
+					  le16_to_cpu(mdm->partitionNum));
 				udf_debug("Metadata part alloc unit size=%d\n",
-					le32_to_cpu(mdm->allocUnitSize));
+					  le32_to_cpu(mdm->allocUnitSize));
 				udf_debug("Metadata file loc=%d\n",
-					le32_to_cpu(mdm->metadataFileLoc));
+					  le32_to_cpu(mdm->metadataFileLoc));
 				udf_debug("Mirror file loc=%d\n",
-				       le32_to_cpu(mdm->metadataMirrorFileLoc));
+					  le32_to_cpu(mdm->metadataMirrorFileLoc));
 				udf_debug("Bitmap file loc=%d\n",
-				       le32_to_cpu(mdm->metadataBitmapFileLoc));
-				udf_debug("Duplicate Flag: %d %d\n",
-					mdata->s_dup_md_flag, mdm->flags);
+					  le32_to_cpu(mdm->metadataBitmapFileLoc));
+				udf_debug("Flags: %d %d\n",
+					  mdata->s_flags, mdm->flags);
 			} else {
 				udf_debug("Unknown ident: %s\n",
 					  upm2->partIdent.ident);
@@ -1389,16 +1360,15 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block,
 			map->s_partition_num = le16_to_cpu(upm2->partitionNum);
 		}
 		udf_debug("Partition (%d:%d) type %d on volume %d\n",
-			  i, map->s_partition_num, type,
-			  map->s_volumeseqnum);
+			  i, map->s_partition_num, type, map->s_volumeseqnum);
 	}
 
 	if (fileset) {
 		struct long_ad *la = (struct long_ad *)&(lvd->logicalVolContentsUse[0]);
 
 		*fileset = lelb_to_cpu(la->extLocation);
-		udf_debug("FileSet found in LogicalVolDesc at block=%d, "
-			  "partition=%d\n", fileset->logicalBlockNum,
+		udf_debug("FileSet found in LogicalVolDesc at block=%d, partition=%d\n",
+			  fileset->logicalBlockNum,
 			  fileset->partitionReferenceNum);
 	}
 	if (lvd->integritySeqExt.extLength)
@@ -1478,9 +1448,9 @@ static noinline int udf_process_sequence(struct super_block *sb, long block,
 
 		bh = udf_read_tagged(sb, block, block, &ident);
 		if (!bh) {
-			printk(KERN_ERR "udf: Block %Lu of volume descriptor "
-			       "sequence is corrupted or we could not read "
-			       "it.\n", (unsigned long long)block);
+			udf_err(sb,
+				"Block %llu of volume descriptor sequence is corrupted or we could not read it\n",
+				(unsigned long long)block);
 			return 1;
 		}
 
@@ -1553,7 +1523,7 @@ static noinline int udf_process_sequence(struct super_block *sb, long block,
 	 * in a suitable order
 	 */
 	if (!vds[VDS_POS_PRIMARY_VOL_DESC].block) {
-		printk(KERN_ERR "udf: Primary Volume Descriptor not found!\n");
+		udf_err(sb, "Primary Volume Descriptor not found!\n");
 		return 1;
 	}
 	if (udf_load_pvoldesc(sb, vds[VDS_POS_PRIMARY_VOL_DESC].block))
@@ -1740,7 +1710,7 @@ static int udf_load_vrs(struct super_block *sb, struct udf_options *uopt,
 
 	if (!sb_set_blocksize(sb, uopt->blocksize)) {
 		if (!silent)
-			printk(KERN_WARNING "UDF-fs: Bad block size\n");
+			udf_warn(sb, "Bad block size\n");
 		return 0;
 	}
 	sbi->s_last_block = uopt->lastblock;
@@ -1749,12 +1719,11 @@ static int udf_load_vrs(struct super_block *sb, struct udf_options *uopt,
 		nsr_off = udf_check_vsd(sb);
 		if (!nsr_off) {
 			if (!silent)
-				printk(KERN_WARNING "UDF-fs: No VRS found\n");
+				udf_warn(sb, "No VRS found\n");
 			return 0;
 		}
 		if (nsr_off == -1)
-			udf_debug("Failed to read byte 32768. Assuming open "
-				  "disc. Skipping validity check\n");
+			udf_debug("Failed to read byte 32768. Assuming open disc. Skipping validity check\n");
 		if (!sbi->s_last_block)
 			sbi->s_last_block = udf_get_last_block(sb);
 	} else {
@@ -1765,7 +1734,7 @@ static int udf_load_vrs(struct super_block *sb, struct udf_options *uopt,
 	sbi->s_anchor = uopt->anchor;
 	if (!udf_find_anchor(sb, fileset)) {
 		if (!silent)
-			printk(KERN_WARNING "UDF-fs: No anchor found\n");
+			udf_warn(sb, "No anchor found\n");
 		return 0;
 	}
 	return 1;
@@ -1937,8 +1906,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
 
 	if (uopt.flags & (1 << UDF_FLAG_UTF8) &&
 	    uopt.flags & (1 << UDF_FLAG_NLS_MAP)) {
-		udf_error(sb, "udf_read_super",
-			  "utf8 cannot be combined with iocharset\n");
+		udf_err(sb, "utf8 cannot be combined with iocharset\n");
 		goto error_out;
 	}
 #ifdef CONFIG_UDF_NLS
@@ -1987,15 +1955,14 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
 		ret = udf_load_vrs(sb, &uopt, silent, &fileset);
 		if (!ret && uopt.blocksize != UDF_DEFAULT_BLOCKSIZE) {
 			if (!silent)
-				printk(KERN_NOTICE
-				       "UDF-fs: Rescanning with blocksize "
-				       "%d\n", UDF_DEFAULT_BLOCKSIZE);
+				pr_notice("Rescanning with blocksize %d\n",
+					  UDF_DEFAULT_BLOCKSIZE);
 			uopt.blocksize = UDF_DEFAULT_BLOCKSIZE;
 			ret = udf_load_vrs(sb, &uopt, silent, &fileset);
 		}
 	}
 	if (!ret) {
-		printk(KERN_WARNING "UDF-fs: No partition found (1)\n");
+		udf_warn(sb, "No partition found (1)\n");
 		goto error_out;
 	}
 
@@ -2010,10 +1977,9 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
 				le16_to_cpu(lvidiu->maxUDFWriteRev); */
 
 		if (minUDFReadRev > UDF_MAX_READ_VERSION) {
-			printk(KERN_ERR "UDF-fs: minUDFReadRev=%x "
-					"(max is %x)\n",
-			       le16_to_cpu(lvidiu->minUDFReadRev),
-			       UDF_MAX_READ_VERSION);
+			udf_err(sb, "minUDFReadRev=%x (max is %x)\n",
+				le16_to_cpu(lvidiu->minUDFReadRev),
+				UDF_MAX_READ_VERSION);
 			goto error_out;
 		} else if (minUDFWriteRev > UDF_MAX_WRITE_VERSION)
 			sb->s_flags |= MS_RDONLY;
@@ -2027,28 +1993,27 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
 	}
 
 	if (!sbi->s_partitions) {
-		printk(KERN_WARNING "UDF-fs: No partition found (2)\n");
+		udf_warn(sb, "No partition found (2)\n");
 		goto error_out;
 	}
 
 	if (sbi->s_partmaps[sbi->s_partition].s_partition_flags &
 			UDF_PART_FLAG_READ_ONLY) {
-		printk(KERN_NOTICE "UDF-fs: Partition marked readonly; "
-				   "forcing readonly mount\n");
+		pr_notice("Partition marked readonly; forcing readonly mount\n");
 		sb->s_flags |= MS_RDONLY;
 	}
 
 	if (udf_find_fileset(sb, &fileset, &rootdir)) {
-		printk(KERN_WARNING "UDF-fs: No fileset found\n");
+		udf_warn(sb, "No fileset found\n");
 		goto error_out;
 	}
 
 	if (!silent) {
 		struct timestamp ts;
 		udf_time_to_disk_stamp(&ts, sbi->s_record_time);
-		udf_info("UDF: Mounting volume '%s', "
-			 "timestamp %04u/%02u/%02u %02u:%02u (%x)\n",
-			 sbi->s_volume_ident, le16_to_cpu(ts.year), ts.month, ts.day,
+		udf_info("Mounting volume '%s', timestamp %04u/%02u/%02u %02u:%02u (%x)\n",
+			 sbi->s_volume_ident,
+			 le16_to_cpu(ts.year), ts.month, ts.day,
 			 ts.hour, ts.minute, le16_to_cpu(ts.typeAndTimezone));
 	}
 	if (!(sb->s_flags & MS_RDONLY))
@@ -2059,8 +2024,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
 	/* perhaps it's not extensible enough, but for now ... */
 	inode = udf_iget(sb, &rootdir);
 	if (!inode) {
-		printk(KERN_ERR "UDF-fs: Error in udf_iget, block=%d, "
-				"partition=%d\n",
+		udf_err(sb, "Error in udf_iget, block=%d, partition=%d\n",
 		       rootdir.logicalBlockNum, rootdir.partitionReferenceNum);
 		goto error_out;
 	}
@@ -2068,7 +2032,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
 	/* Allocate a dentry for the root inode */
 	sb->s_root = d_alloc_root(inode);
 	if (!sb->s_root) {
-		printk(KERN_ERR "UDF-fs: Couldn't allocate root dentry\n");
+		udf_err(sb, "Couldn't allocate root dentry\n");
 		iput(inode);
 		goto error_out;
 	}
@@ -2096,32 +2060,40 @@ error_out:
 	return -EINVAL;
 }
 
-static void udf_error(struct super_block *sb, const char *function,
-		      const char *fmt, ...)
+void _udf_err(struct super_block *sb, const char *function,
+	      const char *fmt, ...)
 {
+	struct va_format vaf;
 	va_list args;
 
-	if (!(sb->s_flags & MS_RDONLY)) {
-		/* mark sb error */
+	/* mark sb error */
+	if (!(sb->s_flags & MS_RDONLY))
 		sb->s_dirt = 1;
-	}
+
 	va_start(args, fmt);
-	vsnprintf(error_buf, sizeof(error_buf), fmt, args);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	pr_err("error (device %s): %s: %pV", sb->s_id, function, &vaf);
+
 	va_end(args);
-	printk(KERN_CRIT "UDF-fs error (device %s): %s: %s\n",
-		sb->s_id, function, error_buf);
 }
 
-void udf_warning(struct super_block *sb, const char *function,
-		 const char *fmt, ...)
+void _udf_warn(struct super_block *sb, const char *function,
+	       const char *fmt, ...)
 {
+	struct va_format vaf;
 	va_list args;
 
 	va_start(args, fmt);
-	vsnprintf(error_buf, sizeof(error_buf), fmt, args);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	pr_warn("warning (device %s): %s: %pV", sb->s_id, function, &vaf);
+
 	va_end(args);
-	printk(KERN_WARNING "UDF-fs warning (device %s): %s: %s\n",
-	       sb->s_id, function, error_buf);
 }
 
 static void udf_put_super(struct super_block *sb)
@@ -2213,11 +2185,11 @@ static unsigned int udf_count_free_bitmap(struct super_block *sb,
 	bh = udf_read_ptagged(sb, &loc, 0, &ident);
 
 	if (!bh) {
-		printk(KERN_ERR "udf: udf_count_free failed\n");
+		udf_err(sb, "udf_count_free failed\n");
 		goto out;
 	} else if (ident != TAG_IDENT_SBD) {
 		brelse(bh);
-		printk(KERN_ERR "udf: udf_count_free failed\n");
+		udf_err(sb, "udf_count_free failed\n");
 		goto out;
 	}
 
diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c
index 8424308..4b98fee 100644
--- a/fs/udf/truncate.c
+++ b/fs/udf/truncate.c
@@ -95,23 +95,21 @@ void udf_truncate_tail_extent(struct inode *inode)
 		lbcount += elen;
 		if (lbcount > inode->i_size) {
 			if (lbcount - inode->i_size >= inode->i_sb->s_blocksize)
-				printk(KERN_WARNING
-				       "udf_truncate_tail_extent(): Too long "
-				       "extent after EOF in inode %u: i_size: "
-				       "%Ld lbcount: %Ld extent %u+%u\n",
-				       (unsigned)inode->i_ino,
-				       (long long)inode->i_size,
-				       (long long)lbcount,
-				       (unsigned)eloc.logicalBlockNum,
-				       (unsigned)elen);
+				udf_warn(inode->i_sb,
+					 "Too long extent after EOF in inode %u: i_size: %lld lbcount: %lld extent %u+%u\n",
+					 (unsigned)inode->i_ino,
+					 (long long)inode->i_size,
+					 (long long)lbcount,
+					 (unsigned)eloc.logicalBlockNum,
+					 (unsigned)elen);
 			nelen = elen - (lbcount - inode->i_size);
 			epos.offset -= adsize;
 			extent_trunc(inode, &epos, &eloc, etype, elen, nelen);
 			epos.offset += adsize;
 			if (udf_next_aext(inode, &epos, &eloc, &elen, 1) != -1)
-				printk(KERN_ERR "udf_truncate_tail_extent(): "
-				       "Extent after EOF in inode %u.\n",
-				       (unsigned)inode->i_ino);
+				udf_err(inode->i_sb,
+					"Extent after EOF in inode %u\n",
+					(unsigned)inode->i_ino);
 			break;
 		}
 	}
diff --git a/fs/udf/udf_sb.h b/fs/udf/udf_sb.h
index 4858c19..5142a82 100644
--- a/fs/udf/udf_sb.h
+++ b/fs/udf/udf_sb.h
@@ -54,13 +54,16 @@
 
 #pragma pack(1) /* XXX(hch): Why?  This file just defines in-core structures */
 
+#define MF_DUPLICATE_MD		0x01
+#define MF_MIRROR_FE_LOADED	0x02
+
 struct udf_meta_data {
 	__u32	s_meta_file_loc;
 	__u32	s_mirror_file_loc;
 	__u32	s_bitmap_file_loc;
 	__u32	s_alloc_unit_size;
 	__u16	s_align_unit_size;
-	__u8 	s_dup_md_flag;
+	int	s_flags;
 	struct inode *s_metadata_fe;
 	struct inode *s_mirror_fe;
 	struct inode *s_bitmap_fe;
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
index dc8a8dc..f34e6fc 100644
--- a/fs/udf/udfdecl.h
+++ b/fs/udf/udfdecl.h
@@ -1,6 +1,8 @@
 #ifndef __UDF_DECL_H
 #define __UDF_DECL_H
 
+#define pr_fmt(fmt) "UDF-fs: " fmt
+
 #include "ecma_167.h"
 #include "osta_udf.h"
 
@@ -16,23 +18,30 @@
 #define UDF_PREALLOCATE
 #define UDF_DEFAULT_PREALLOC_BLOCKS	8
 
+extern __printf(3, 4) void _udf_err(struct super_block *sb,
+		const char *function, const char *fmt, ...);
+#define udf_err(sb, fmt, ...)					\
+	_udf_err(sb, __func__, fmt, ##__VA_ARGS__)
+
+extern __printf(3, 4) void _udf_warn(struct super_block *sb,
+		const char *function, const char *fmt, ...);
+#define udf_warn(sb, fmt, ...)					\
+	_udf_warn(sb, __func__, fmt, ##__VA_ARGS__)
+
+#define udf_info(fmt, ...)					\
+	pr_info("INFO " fmt, ##__VA_ARGS__)
+
 #undef UDFFS_DEBUG
 
 #ifdef UDFFS_DEBUG
-#define udf_debug(f, a...) \
-do { \
-	printk(KERN_DEBUG "UDF-fs DEBUG %s:%d:%s: ", \
-		__FILE__, __LINE__, __func__); \
-	printk(f, ##a); \
-} while (0)
+#define udf_debug(fmt, ...)					\
+	printk(KERN_DEBUG pr_fmt("%s:%d:%s: " fmt),		\
+	       __FILE__, __LINE__, __func__, ##__VA_ARGS__)
 #else
-#define udf_debug(f, a...) /**/
+#define udf_debug(fmt, ...)					\
+	no_printk(fmt, ##__VA_ARGS__)
 #endif
 
-#define udf_info(f, a...) \
-	printk(KERN_INFO "UDF-fs INFO " f, ##a);
-
-
 #define udf_fixed_to_variable(x) ( ( ( (x) >> 5 ) * 39 ) + ( (x) & 0x0000001F ) )
 #define udf_variable_to_fixed(x) ( ( ( (x) / 39 ) << 5 ) + ( (x) % 39 ) )
 
@@ -112,8 +121,6 @@ struct extent_position {
 
 /* super.c */
 
-extern __printf(3, 4) void udf_warning(struct super_block *, const char *,
-					const char *, ...);
 static inline void udf_updated_lvid(struct super_block *sb)
 {
 	struct buffer_head *bh = UDF_SB(sb)->s_lvid_bh;
@@ -126,6 +133,8 @@ static inline void udf_updated_lvid(struct super_block *sb)
 	UDF_SB(sb)->s_lvid_dirty = 1;
 }
 extern u64 lvid_get_unique_id(struct super_block *sb);
+struct inode *udf_find_metadata_inode_efe(struct super_block *sb,
+					u32 meta_file_loc, u32 partition_num);
 
 /* namei.c */
 extern int udf_write_fi(struct inode *inode, struct fileIdentDesc *,
diff --git a/fs/udf/udftime.c b/fs/udf/udftime.c
index b8c828c..1f11483 100644
--- a/fs/udf/udftime.c
+++ b/fs/udf/udftime.c
@@ -34,9 +34,10 @@
  * http://www.boulder.nist.gov/timefreq/pubs/bulletin/leapsecond.htm
  */
 
+#include "udfdecl.h"
+
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include "udfdecl.h"
 
 #define EPOCH_YEAR 1970
 
diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c
index d03a90b..44b815e 100644
--- a/fs/udf/unicode.c
+++ b/fs/udf/unicode.c
@@ -114,7 +114,7 @@ int udf_CS0toUTF8(struct ustr *utf_o, const struct ustr *ocu_i)
 	cmp_id = ocu_i->u_cmpID;
 	if (cmp_id != 8 && cmp_id != 16) {
 		memset(utf_o, 0, sizeof(struct ustr));
-		printk(KERN_ERR "udf: unknown compression code (%d) stri=%s\n",
+		pr_err("unknown compression code (%d) stri=%s\n",
 		       cmp_id, ocu_i->u_name);
 		return 0;
 	}
@@ -242,7 +242,7 @@ try_again:
 	if (utf_cnt) {
 error_out:
 		ocu[++u_len] = '?';
-		printk(KERN_DEBUG "udf: bad UTF-8 character\n");
+		printk(KERN_DEBUG pr_fmt("bad UTF-8 character\n"));
 	}
 
 	ocu[length - 1] = (uint8_t)u_len + 1;
@@ -267,7 +267,7 @@ static int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o,
 	cmp_id = ocu_i->u_cmpID;
 	if (cmp_id != 8 && cmp_id != 16) {
 		memset(utf_o, 0, sizeof(struct ustr));
-		printk(KERN_ERR "udf: unknown compression code (%d) stri=%s\n",
+		pr_err("unknown compression code (%d) stri=%s\n",
 		       cmp_id, ocu_i->u_name);
 		return 0;
 	}
diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c
index 2eabf04..78a4c70 100644
--- a/fs/ufs/ialloc.c
+++ b/fs/ufs/ialloc.c
@@ -341,7 +341,7 @@ cg_found:
 
 fail_remove_inode:
 	unlock_super(sb);
-	inode->i_nlink = 0;
+	clear_nlink(inode);
 	iput(inode);
 	UFSD("EXIT (FAILED): err %d\n", err);
 	return ERR_PTR(err);
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index b4d791a..879b134 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -589,7 +589,7 @@ static int ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode)
 	 * Copy data to the in-core inode.
 	 */
 	inode->i_mode = mode = fs16_to_cpu(sb, ufs_inode->ui_mode);
-	inode->i_nlink = fs16_to_cpu(sb, ufs_inode->ui_nlink);
+	set_nlink(inode, fs16_to_cpu(sb, ufs_inode->ui_nlink));
 	if (inode->i_nlink == 0) {
 		ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino);
 		return -1;
@@ -637,7 +637,7 @@ static int ufs2_read_inode(struct inode *inode, struct ufs2_inode *ufs2_inode)
 	 * Copy data to the in-core inode.
 	 */
 	inode->i_mode = mode = fs16_to_cpu(sb, ufs2_inode->ui_mode);
-	inode->i_nlink = fs16_to_cpu(sb, ufs2_inode->ui_nlink);
+	set_nlink(inode, fs16_to_cpu(sb, ufs2_inode->ui_nlink));
 	if (inode->i_nlink == 0) {
 		ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino);
 		return -1;
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 9ba2a07..23ce927 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -1153,7 +1153,7 @@ xfs_setup_inode(
 	hlist_add_fake(&inode->i_hash);
 
 	inode->i_mode	= ip->i_d.di_mode;
-	inode->i_nlink	= ip->i_d.di_nlink;
+	set_nlink(inode, ip->i_d.di_nlink);
 	inode->i_uid	= ip->i_d.di_uid;
 	inode->i_gid	= ip->i_d.di_gid;
 
diff --git a/include/asm-generic/checksum.h b/include/asm-generic/checksum.h
index 4647c76..c084767 100644
--- a/include/asm-generic/checksum.h
+++ b/include/asm-generic/checksum.h
@@ -33,8 +33,10 @@ extern __wsum csum_partial_copy(const void *src, void *dst, int len, __wsum sum)
 extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst,
 					int len, __wsum sum, int *csum_err);
 
+#ifndef csum_partial_copy_nocheck
 #define csum_partial_copy_nocheck(src, dst, len, sum)	\
 	csum_partial_copy((src), (dst), (len), (sum))
+#endif
 
 /*
  * This is a version of ip_compute_csum() optimized for IP headers,
@@ -63,12 +65,14 @@ csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
 		unsigned short proto, __wsum sum);
 #endif
 
+#ifndef csum_tcpudp_magic
 static inline __sum16
 csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len,
 		  unsigned short proto, __wsum sum)
 {
 	return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
 }
+#endif
 
 /*
  * this routine is used for miscellaneous IP-like checksums, mainly
diff --git a/include/asm-generic/rwsem.h b/include/asm-generic/rwsem.h
new file mode 100644
index 0000000..bb1e2cd
--- /dev/null
+++ b/include/asm-generic/rwsem.h
@@ -0,0 +1,132 @@
+#ifndef _ASM_POWERPC_RWSEM_H
+#define _ASM_POWERPC_RWSEM_H
+
+#ifndef _LINUX_RWSEM_H
+#error "Please don't include <asm/rwsem.h> directly, use <linux/rwsem.h> instead."
+#endif
+
+#ifdef __KERNEL__
+
+/*
+ * R/W semaphores for PPC using the stuff in lib/rwsem.c.
+ * Adapted largely from include/asm-i386/rwsem.h
+ * by Paul Mackerras <paulus@samba.org>.
+ */
+
+/*
+ * the semaphore definition
+ */
+#ifdef CONFIG_PPC64
+# define RWSEM_ACTIVE_MASK		0xffffffffL
+#else
+# define RWSEM_ACTIVE_MASK		0x0000ffffL
+#endif
+
+#define RWSEM_UNLOCKED_VALUE		0x00000000L
+#define RWSEM_ACTIVE_BIAS		0x00000001L
+#define RWSEM_WAITING_BIAS		(-RWSEM_ACTIVE_MASK-1)
+#define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS
+#define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
+
+/*
+ * lock for reading
+ */
+static inline void __down_read(struct rw_semaphore *sem)
+{
+	if (unlikely(atomic_long_inc_return((atomic_long_t *)&sem->count) <= 0))
+		rwsem_down_read_failed(sem);
+}
+
+static inline int __down_read_trylock(struct rw_semaphore *sem)
+{
+	long tmp;
+
+	while ((tmp = sem->count) >= 0) {
+		if (tmp == cmpxchg(&sem->count, tmp,
+				   tmp + RWSEM_ACTIVE_READ_BIAS)) {
+			return 1;
+		}
+	}
+	return 0;
+}
+
+/*
+ * lock for writing
+ */
+static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
+{
+	long tmp;
+
+	tmp = atomic_long_add_return(RWSEM_ACTIVE_WRITE_BIAS,
+				     (atomic_long_t *)&sem->count);
+	if (unlikely(tmp != RWSEM_ACTIVE_WRITE_BIAS))
+		rwsem_down_write_failed(sem);
+}
+
+static inline void __down_write(struct rw_semaphore *sem)
+{
+	__down_write_nested(sem, 0);
+}
+
+static inline int __down_write_trylock(struct rw_semaphore *sem)
+{
+	long tmp;
+
+	tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE,
+		      RWSEM_ACTIVE_WRITE_BIAS);
+	return tmp == RWSEM_UNLOCKED_VALUE;
+}
+
+/*
+ * unlock after reading
+ */
+static inline void __up_read(struct rw_semaphore *sem)
+{
+	long tmp;
+
+	tmp = atomic_long_dec_return((atomic_long_t *)&sem->count);
+	if (unlikely(tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0))
+		rwsem_wake(sem);
+}
+
+/*
+ * unlock after writing
+ */
+static inline void __up_write(struct rw_semaphore *sem)
+{
+	if (unlikely(atomic_long_sub_return(RWSEM_ACTIVE_WRITE_BIAS,
+				 (atomic_long_t *)&sem->count) < 0))
+		rwsem_wake(sem);
+}
+
+/*
+ * implement atomic add functionality
+ */
+static inline void rwsem_atomic_add(long delta, struct rw_semaphore *sem)
+{
+	atomic_long_add(delta, (atomic_long_t *)&sem->count);
+}
+
+/*
+ * downgrade write lock to read lock
+ */
+static inline void __downgrade_write(struct rw_semaphore *sem)
+{
+	long tmp;
+
+	tmp = atomic_long_add_return(-RWSEM_WAITING_BIAS,
+				     (atomic_long_t *)&sem->count);
+	if (tmp < 0)
+		rwsem_downgrade_wake(sem);
+}
+
+/*
+ * implement exchange and add functionality
+ */
+static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem)
+{
+	return atomic_long_add_return(delta, (atomic_long_t *)&sem->count);
+}
+
+#endif	/* __KERNEL__ */
+#endif	/* _ASM_POWERPC_RWSEM_H */
diff --git a/include/crypto/algapi.h b/include/crypto/algapi.h
index 59c3e5b..ecc721d 100644
--- a/include/crypto/algapi.h
+++ b/include/crypto/algapi.h
@@ -15,6 +15,7 @@
 #include <linux/crypto.h>
 #include <linux/list.h>
 #include <linux/kernel.h>
+#include <linux/skbuff.h>
 
 struct module;
 struct rtattr;
@@ -26,6 +27,7 @@ struct crypto_type {
 	int (*init)(struct crypto_tfm *tfm, u32 type, u32 mask);
 	int (*init_tfm)(struct crypto_tfm *tfm);
 	void (*show)(struct seq_file *m, struct crypto_alg *alg);
+	int (*report)(struct sk_buff *skb, struct crypto_alg *alg);
 	struct crypto_alg *(*lookup)(const char *name, u32 type, u32 mask);
 
 	unsigned int type;
diff --git a/include/crypto/blowfish.h b/include/crypto/blowfish.h
new file mode 100644
index 0000000..1450d4a
--- /dev/null
+++ b/include/crypto/blowfish.h
@@ -0,0 +1,23 @@
+/*
+ * Common values for blowfish algorithms
+ */
+
+#ifndef _CRYPTO_BLOWFISH_H
+#define _CRYPTO_BLOWFISH_H
+
+#include <linux/types.h>
+#include <linux/crypto.h>
+
+#define BF_BLOCK_SIZE 8
+#define BF_MIN_KEY_SIZE 4
+#define BF_MAX_KEY_SIZE 56
+
+struct bf_ctx {
+	u32 p[18];
+	u32 s[1024];
+};
+
+int blowfish_setkey(struct crypto_tfm *tfm, const u8 *key,
+		    unsigned int key_len);
+
+#endif
diff --git a/include/crypto/sha.h b/include/crypto/sha.h
index 069e85b..c6c9c1f 100644
--- a/include/crypto/sha.h
+++ b/include/crypto/sha.h
@@ -82,4 +82,9 @@ struct sha512_state {
 	u8 buf[SHA512_BLOCK_SIZE];
 };
 
+struct shash_desc;
+
+extern int crypto_sha1_update(struct shash_desc *desc, const u8 *data,
+			      unsigned int len);
+
 #endif
diff --git a/include/linux/aio.h b/include/linux/aio.h
index 2dcb72b..2314ad8 100644
--- a/include/linux/aio.h
+++ b/include/linux/aio.h
@@ -117,6 +117,7 @@ struct kiocb {
 
 	struct list_head	ki_list;	/* the aio core uses this
 						 * for cancellation */
+	struct list_head	ki_batch;	/* batch allocation */
 
 	/*
 	 * If the aio_resfd field of the userspace iocb is not zero,
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index da7e4bc..1b7f9d5 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -516,7 +516,7 @@ struct cgroup_subsys {
 	struct list_head sibling;
 	/* used when use_id == true */
 	struct idr idr;
-	spinlock_t id_lock;
+	rwlock_t id_lock;
 
 	/* should be defined only by modular subsystems */
 	struct module *module;
diff --git a/include/linux/clksrc-dbx500-prcmu.h b/include/linux/clksrc-dbx500-prcmu.h
new file mode 100644
index 0000000..4fb8119
--- /dev/null
+++ b/include/linux/clksrc-dbx500-prcmu.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Mattias Wallin <mattias.wallin@stericsson.com>
+ *
+ */
+#ifndef __CLKSRC_DBX500_PRCMU_H
+#define __CLKSRC_DBX500_PRCMU_H
+
+#include <linux/init.h>
+#include <linux/io.h>
+
+#ifdef CONFIG_CLKSRC_DBX500_PRCMU
+void __init clksrc_dbx500_prcmu_init(void __iomem *base);
+#else
+static inline void __init clksrc_dbx500_prcmu_init(void __iomem *base) {}
+#endif
+
+#endif
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index e5e468e..de9adec 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -72,6 +72,11 @@
 #define CRYPTO_ALG_TESTED		0x00000400
 
 /*
+ * Set if the algorithm is an instance that is build from templates.
+ */
+#define CRYPTO_ALG_INSTANCE		0x00000800
+
+/*
  * Transform masks and values (for crt_flags).
  */
 #define CRYPTO_TFM_REQ_MASK		0x000fff00
diff --git a/include/linux/cryptouser.h b/include/linux/cryptouser.h
new file mode 100644
index 0000000..532fb58
--- /dev/null
+++ b/include/linux/cryptouser.h
@@ -0,0 +1,102 @@
+/*
+ * Crypto user configuration API.
+ *
+ * Copyright (C) 2011 secunet Security Networks AG
+ * Copyright (C) 2011 Steffen Klassert <steffen.klassert@secunet.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/* Netlink configuration messages.  */
+enum {
+	CRYPTO_MSG_BASE = 0x10,
+	CRYPTO_MSG_NEWALG = 0x10,
+	CRYPTO_MSG_DELALG,
+	CRYPTO_MSG_UPDATEALG,
+	CRYPTO_MSG_GETALG,
+	__CRYPTO_MSG_MAX
+};
+#define CRYPTO_MSG_MAX (__CRYPTO_MSG_MAX - 1)
+#define CRYPTO_NR_MSGTYPES (CRYPTO_MSG_MAX + 1 - CRYPTO_MSG_BASE)
+
+#define CRYPTO_MAX_NAME CRYPTO_MAX_ALG_NAME
+
+/* Netlink message attributes.  */
+enum crypto_attr_type_t {
+	CRYPTOCFGA_UNSPEC,
+	CRYPTOCFGA_PRIORITY_VAL,	/* __u32 */
+	CRYPTOCFGA_REPORT_LARVAL,	/* struct crypto_report_larval */
+	CRYPTOCFGA_REPORT_HASH,		/* struct crypto_report_hash */
+	CRYPTOCFGA_REPORT_BLKCIPHER,	/* struct crypto_report_blkcipher */
+	CRYPTOCFGA_REPORT_AEAD,		/* struct crypto_report_aead */
+	CRYPTOCFGA_REPORT_COMPRESS,	/* struct crypto_report_comp */
+	CRYPTOCFGA_REPORT_RNG,		/* struct crypto_report_rng */
+	CRYPTOCFGA_REPORT_CIPHER,	/* struct crypto_report_cipher */
+	__CRYPTOCFGA_MAX
+
+#define CRYPTOCFGA_MAX (__CRYPTOCFGA_MAX - 1)
+};
+
+struct crypto_user_alg {
+	char cru_name[CRYPTO_MAX_ALG_NAME];
+	char cru_driver_name[CRYPTO_MAX_ALG_NAME];
+	char cru_module_name[CRYPTO_MAX_ALG_NAME];
+	__u32 cru_type;
+	__u32 cru_mask;
+	__u32 cru_refcnt;
+	__u32 cru_flags;
+};
+
+struct crypto_report_larval {
+	char type[CRYPTO_MAX_NAME];
+};
+
+struct crypto_report_hash {
+	char type[CRYPTO_MAX_NAME];
+	unsigned int blocksize;
+	unsigned int digestsize;
+};
+
+struct crypto_report_cipher {
+	char type[CRYPTO_MAX_ALG_NAME];
+	unsigned int blocksize;
+	unsigned int min_keysize;
+	unsigned int max_keysize;
+};
+
+struct crypto_report_blkcipher {
+	char type[CRYPTO_MAX_NAME];
+	char geniv[CRYPTO_MAX_NAME];
+	unsigned int blocksize;
+	unsigned int min_keysize;
+	unsigned int max_keysize;
+	unsigned int ivsize;
+};
+
+struct crypto_report_aead {
+	char type[CRYPTO_MAX_NAME];
+	char geniv[CRYPTO_MAX_NAME];
+	unsigned int blocksize;
+	unsigned int maxauthsize;
+	unsigned int ivsize;
+};
+
+struct crypto_report_comp {
+	char type[CRYPTO_MAX_NAME];
+};
+
+struct crypto_report_rng {
+	char type[CRYPTO_MAX_NAME];
+	unsigned int seedsize;
+};
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 62157c0..4df9261 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -165,6 +165,7 @@ struct dentry_operations {
 			unsigned int, const char *, const struct qstr *);
 	int (*d_delete)(const struct dentry *);
 	void (*d_release)(struct dentry *);
+	void (*d_prune)(struct dentry *);
 	void (*d_iput)(struct dentry *, struct inode *);
 	char *(*d_dname)(struct dentry *, char *, int);
 	struct vfsmount *(*d_automount)(struct path *);
@@ -184,8 +185,9 @@ struct dentry_operations {
 #define DCACHE_OP_COMPARE	0x0002
 #define DCACHE_OP_REVALIDATE	0x0004
 #define DCACHE_OP_DELETE	0x0008
+#define DCACHE_OP_PRUNE         0x0010
 
-#define	DCACHE_DISCONNECTED	0x0010
+#define	DCACHE_DISCONNECTED	0x0020
      /* This dentry is possibly not currently connected to the dcache tree, in
       * which case its parent will either be itself, or will have this flag as
       * well.  nfsd will not use a dentry with this bit set, but will first
@@ -196,8 +198,8 @@ struct dentry_operations {
       * dentry into place and return that dentry rather than the passed one,
       * typically using d_splice_alias. */
 
-#define DCACHE_REFERENCED	0x0020  /* Recently used, don't discard. */
-#define DCACHE_RCUACCESS	0x0040	/* Entry has ever been RCU-visible */
+#define DCACHE_REFERENCED	0x0040  /* Recently used, don't discard. */
+#define DCACHE_RCUACCESS	0x0080	/* Entry has ever been RCU-visible */
 
 #define DCACHE_CANT_MOUNT	0x0100
 #define DCACHE_GENOCIDE		0x0200
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index 99e3e50..98f34b8 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -10,6 +10,7 @@
 
 #include <linux/bio.h>
 #include <linux/blkdev.h>
+#include <linux/ratelimit.h>
 
 struct dm_dev;
 struct dm_target;
@@ -127,10 +128,6 @@ void dm_put_device(struct dm_target *ti, struct dm_dev *d);
  * Information about a target type
  */
 
-/*
- * Target features
- */
-
 struct target_type {
 	uint64_t features;
 	const char *name;
@@ -159,6 +156,30 @@ struct target_type {
 	struct list_head list;
 };
 
+/*
+ * Target features
+ */
+
+/*
+ * Any table that contains an instance of this target must have only one.
+ */
+#define DM_TARGET_SINGLETON		0x00000001
+#define dm_target_needs_singleton(type)	((type)->features & DM_TARGET_SINGLETON)
+
+/*
+ * Indicates that a target does not support read-only devices.
+ */
+#define DM_TARGET_ALWAYS_WRITEABLE	0x00000002
+#define dm_target_always_writeable(type) \
+		((type)->features & DM_TARGET_ALWAYS_WRITEABLE)
+
+/*
+ * Any device that contains a table with an instance of this target may never
+ * have tables containing any different target type.
+ */
+#define DM_TARGET_IMMUTABLE		0x00000004
+#define dm_target_is_immutable(type)	((type)->features & DM_TARGET_IMMUTABLE)
+
 struct dm_target {
 	struct dm_table *table;
 	struct target_type *type;
@@ -375,6 +396,14 @@ void *dm_vcalloc(unsigned long nmemb, unsigned long elem_size);
  *---------------------------------------------------------------*/
 #define DM_NAME "device-mapper"
 
+#ifdef CONFIG_PRINTK
+extern struct ratelimit_state dm_ratelimit_state;
+
+#define dm_ratelimit()	__ratelimit(&dm_ratelimit_state)
+#else
+#define dm_ratelimit()	0
+#endif
+
 #define DMCRIT(f, arg...) \
 	printk(KERN_CRIT DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
 
@@ -382,7 +411,7 @@ void *dm_vcalloc(unsigned long nmemb, unsigned long elem_size);
 	printk(KERN_ERR DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
 #define DMERR_LIMIT(f, arg...) \
 	do { \
-		if (printk_ratelimit())	\
+		if (dm_ratelimit())	\
 			printk(KERN_ERR DM_NAME ": " DM_MSG_PREFIX ": " \
 			       f "\n", ## arg); \
 	} while (0)
@@ -391,7 +420,7 @@ void *dm_vcalloc(unsigned long nmemb, unsigned long elem_size);
 	printk(KERN_WARNING DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
 #define DMWARN_LIMIT(f, arg...) \
 	do { \
-		if (printk_ratelimit())	\
+		if (dm_ratelimit())	\
 			printk(KERN_WARNING DM_NAME ": " DM_MSG_PREFIX ": " \
 			       f "\n", ## arg); \
 	} while (0)
@@ -400,7 +429,7 @@ void *dm_vcalloc(unsigned long nmemb, unsigned long elem_size);
 	printk(KERN_INFO DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
 #define DMINFO_LIMIT(f, arg...) \
 	do { \
-		if (printk_ratelimit())	\
+		if (dm_ratelimit())	\
 			printk(KERN_INFO DM_NAME ": " DM_MSG_PREFIX ": " f \
 			       "\n", ## arg); \
 	} while (0)
@@ -410,7 +439,7 @@ void *dm_vcalloc(unsigned long nmemb, unsigned long elem_size);
 	printk(KERN_DEBUG DM_NAME ": " DM_MSG_PREFIX " DEBUG: " f "\n", ## arg)
 #  define DMDEBUG_LIMIT(f, arg...) \
 	do { \
-		if (printk_ratelimit())	\
+		if (dm_ratelimit())	\
 			printk(KERN_DEBUG DM_NAME ": " DM_MSG_PREFIX ": " f \
 			       "\n", ## arg); \
 	} while (0)
diff --git a/include/linux/dm-ioctl.h b/include/linux/dm-ioctl.h
index 0cb8eff..75fd557 100644
--- a/include/linux/dm-ioctl.h
+++ b/include/linux/dm-ioctl.h
@@ -267,9 +267,9 @@ enum {
 #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	21
+#define DM_VERSION_MINOR	22
 #define DM_VERSION_PATCHLEVEL	0
-#define DM_VERSION_EXTRA	"-ioctl (2011-07-06)"
+#define DM_VERSION_EXTRA	"-ioctl (2011-10-19)"
 
 /* Status bits */
 #define DM_READONLY_FLAG	(1 << 0) /* In/Out */
diff --git a/include/linux/dm-kcopyd.h b/include/linux/dm-kcopyd.h
index 5e54458..47d9d37 100644
--- a/include/linux/dm-kcopyd.h
+++ b/include/linux/dm-kcopyd.h
@@ -57,5 +57,9 @@ void *dm_kcopyd_prepare_callback(struct dm_kcopyd_client *kc,
 				 dm_kcopyd_notify_fn fn, void *context);
 void dm_kcopyd_do_callback(void *job, int read_err, unsigned long write_err);
 
+int dm_kcopyd_zero(struct dm_kcopyd_client *kc,
+		   unsigned num_dests, struct dm_io_region *dests,
+		   unsigned flags, dm_kcopyd_notify_fn fn, void *context);
+
 #endif	/* __KERNEL__ */
 #endif	/* _LINUX_DM_KCOPYD_H */
diff --git a/include/linux/dm-log-userspace.h b/include/linux/dm-log-userspace.h
index eeace7d..0678c2a 100644
--- a/include/linux/dm-log-userspace.h
+++ b/include/linux/dm-log-userspace.h
@@ -52,15 +52,20 @@
  * Payload-to-userspace:
  *	A single string containing all the argv arguments separated by ' 's
  * Payload-to-kernel:
- *	None.  ('data_size' in the dm_ulog_request struct should be 0.)
+ *	A NUL-terminated string that is the name of the device that is used
+ *	as the backing store for the log data.  'dm_get_device' will be called
+ *	on this device.  ('dm_put_device' will be called on this device
+ *	automatically after calling DM_ULOG_DTR.)  If there is no device needed
+ *	for log data, 'data_size' in the dm_ulog_request struct should be 0.
  *
  * The UUID contained in the dm_ulog_request structure is the reference that
  * will be used by all request types to a specific log.  The constructor must
- * record this assotiation with instance created.
+ * record this association with the instance created.
  *
  * When the request has been processed, user-space must return the
- * dm_ulog_request to the kernel - setting the 'error' field and
- * 'data_size' appropriately.
+ * dm_ulog_request to the kernel - setting the 'error' field, filling the
+ * data field with the log device if necessary, and setting 'data_size'
+ * appropriately.
  */
 #define DM_ULOG_CTR                    1
 
@@ -377,8 +382,11 @@
  * dm_ulog_request or a change in the way requests are
  * issued/handled.  Changes are outlined here:
  *	version 1:  Initial implementation
+ *	version 2:  DM_ULOG_CTR allowed to return a string containing a
+ *	            device name that is to be registered with DM via
+ *	            'dm_get_device'.
  */
-#define DM_ULOG_REQUEST_VERSION 1
+#define DM_ULOG_REQUEST_VERSION 2
 
 struct dm_ulog_request {
 	/*
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 347fdc3..be86ae1 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -1,6 +1,7 @@
 #ifndef _LINUX_DMA_MAPPING_H
 #define _LINUX_DMA_MAPPING_H
 
+#include <linux/string.h>
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/dma-attrs.h>
@@ -117,6 +118,15 @@ static inline int dma_set_seg_boundary(struct device *dev, unsigned long mask)
 		return -EIO;
 }
 
+static inline void *dma_zalloc_coherent(struct device *dev, size_t size,
+					dma_addr_t *dma_handle, gfp_t flag)
+{
+	void *ret = dma_alloc_coherent(dev, size, dma_handle, flag);
+	if (ret)
+		memset(ret, 0, size);
+	return ret;
+}
+
 #ifdef CONFIG_HAS_DMA
 static inline int dma_get_cache_alignment(void)
 {
diff --git a/include/linux/edac.h b/include/linux/edac.h
index 4a73257..055b248 100644
--- a/include/linux/edac.h
+++ b/include/linux/edac.h
@@ -42,4 +42,354 @@ static inline void opstate_init(void)
 	return;
 }
 
+#define EDAC_MC_LABEL_LEN	31
+#define MC_PROC_NAME_MAX_LEN	7
+
+/* memory devices */
+enum dev_type {
+	DEV_UNKNOWN = 0,
+	DEV_X1,
+	DEV_X2,
+	DEV_X4,
+	DEV_X8,
+	DEV_X16,
+	DEV_X32,		/* Do these parts exist? */
+	DEV_X64			/* Do these parts exist? */
+};
+
+#define DEV_FLAG_UNKNOWN	BIT(DEV_UNKNOWN)
+#define DEV_FLAG_X1		BIT(DEV_X1)
+#define DEV_FLAG_X2		BIT(DEV_X2)
+#define DEV_FLAG_X4		BIT(DEV_X4)
+#define DEV_FLAG_X8		BIT(DEV_X8)
+#define DEV_FLAG_X16		BIT(DEV_X16)
+#define DEV_FLAG_X32		BIT(DEV_X32)
+#define DEV_FLAG_X64		BIT(DEV_X64)
+
+/* memory types */
+enum mem_type {
+	MEM_EMPTY = 0,		/* Empty csrow */
+	MEM_RESERVED,		/* Reserved csrow type */
+	MEM_UNKNOWN,		/* Unknown csrow type */
+	MEM_FPM,		/* Fast page mode */
+	MEM_EDO,		/* Extended data out */
+	MEM_BEDO,		/* Burst Extended data out */
+	MEM_SDR,		/* Single data rate SDRAM */
+	MEM_RDR,		/* Registered single data rate SDRAM */
+	MEM_DDR,		/* Double data rate SDRAM */
+	MEM_RDDR,		/* Registered Double data rate SDRAM */
+	MEM_RMBS,		/* Rambus DRAM */
+	MEM_DDR2,		/* DDR2 RAM */
+	MEM_FB_DDR2,		/* fully buffered DDR2 */
+	MEM_RDDR2,		/* Registered DDR2 RAM */
+	MEM_XDR,		/* Rambus XDR */
+	MEM_DDR3,		/* DDR3 RAM */
+	MEM_RDDR3,		/* Registered DDR3 RAM */
+};
+
+#define MEM_FLAG_EMPTY		BIT(MEM_EMPTY)
+#define MEM_FLAG_RESERVED	BIT(MEM_RESERVED)
+#define MEM_FLAG_UNKNOWN	BIT(MEM_UNKNOWN)
+#define MEM_FLAG_FPM		BIT(MEM_FPM)
+#define MEM_FLAG_EDO		BIT(MEM_EDO)
+#define MEM_FLAG_BEDO		BIT(MEM_BEDO)
+#define MEM_FLAG_SDR		BIT(MEM_SDR)
+#define MEM_FLAG_RDR		BIT(MEM_RDR)
+#define MEM_FLAG_DDR		BIT(MEM_DDR)
+#define MEM_FLAG_RDDR		BIT(MEM_RDDR)
+#define MEM_FLAG_RMBS		BIT(MEM_RMBS)
+#define MEM_FLAG_DDR2           BIT(MEM_DDR2)
+#define MEM_FLAG_FB_DDR2        BIT(MEM_FB_DDR2)
+#define MEM_FLAG_RDDR2          BIT(MEM_RDDR2)
+#define MEM_FLAG_XDR            BIT(MEM_XDR)
+#define MEM_FLAG_DDR3		 BIT(MEM_DDR3)
+#define MEM_FLAG_RDDR3		 BIT(MEM_RDDR3)
+
+/* chipset Error Detection and Correction capabilities and mode */
+enum edac_type {
+	EDAC_UNKNOWN = 0,	/* Unknown if ECC is available */
+	EDAC_NONE,		/* Doesn't support ECC */
+	EDAC_RESERVED,		/* Reserved ECC type */
+	EDAC_PARITY,		/* Detects parity errors */
+	EDAC_EC,		/* Error Checking - no correction */
+	EDAC_SECDED,		/* Single bit error correction, Double detection */
+	EDAC_S2ECD2ED,		/* Chipkill x2 devices - do these exist? */
+	EDAC_S4ECD4ED,		/* Chipkill x4 devices */
+	EDAC_S8ECD8ED,		/* Chipkill x8 devices */
+	EDAC_S16ECD16ED,	/* Chipkill x16 devices */
+};
+
+#define EDAC_FLAG_UNKNOWN	BIT(EDAC_UNKNOWN)
+#define EDAC_FLAG_NONE		BIT(EDAC_NONE)
+#define EDAC_FLAG_PARITY	BIT(EDAC_PARITY)
+#define EDAC_FLAG_EC		BIT(EDAC_EC)
+#define EDAC_FLAG_SECDED	BIT(EDAC_SECDED)
+#define EDAC_FLAG_S2ECD2ED	BIT(EDAC_S2ECD2ED)
+#define EDAC_FLAG_S4ECD4ED	BIT(EDAC_S4ECD4ED)
+#define EDAC_FLAG_S8ECD8ED	BIT(EDAC_S8ECD8ED)
+#define EDAC_FLAG_S16ECD16ED	BIT(EDAC_S16ECD16ED)
+
+/* scrubbing capabilities */
+enum scrub_type {
+	SCRUB_UNKNOWN = 0,	/* Unknown if scrubber is available */
+	SCRUB_NONE,		/* No scrubber */
+	SCRUB_SW_PROG,		/* SW progressive (sequential) scrubbing */
+	SCRUB_SW_SRC,		/* Software scrub only errors */
+	SCRUB_SW_PROG_SRC,	/* Progressive software scrub from an error */
+	SCRUB_SW_TUNABLE,	/* Software scrub frequency is tunable */
+	SCRUB_HW_PROG,		/* HW progressive (sequential) scrubbing */
+	SCRUB_HW_SRC,		/* Hardware scrub only errors */
+	SCRUB_HW_PROG_SRC,	/* Progressive hardware scrub from an error */
+	SCRUB_HW_TUNABLE	/* Hardware scrub frequency is tunable */
+};
+
+#define SCRUB_FLAG_SW_PROG	BIT(SCRUB_SW_PROG)
+#define SCRUB_FLAG_SW_SRC	BIT(SCRUB_SW_SRC)
+#define SCRUB_FLAG_SW_PROG_SRC	BIT(SCRUB_SW_PROG_SRC)
+#define SCRUB_FLAG_SW_TUN	BIT(SCRUB_SW_SCRUB_TUNABLE)
+#define SCRUB_FLAG_HW_PROG	BIT(SCRUB_HW_PROG)
+#define SCRUB_FLAG_HW_SRC	BIT(SCRUB_HW_SRC)
+#define SCRUB_FLAG_HW_PROG_SRC	BIT(SCRUB_HW_PROG_SRC)
+#define SCRUB_FLAG_HW_TUN	BIT(SCRUB_HW_TUNABLE)
+
+/* FIXME - should have notify capabilities: NMI, LOG, PROC, etc */
+
+/* EDAC internal operation states */
+#define	OP_ALLOC		0x100
+#define OP_RUNNING_POLL		0x201
+#define OP_RUNNING_INTERRUPT	0x202
+#define OP_RUNNING_POLL_INTR	0x203
+#define OP_OFFLINE		0x300
+
+/*
+ * There are several things to be aware of that aren't at all obvious:
+ *
+ *
+ * SOCKETS, SOCKET SETS, BANKS, ROWS, CHIP-SELECT ROWS, CHANNELS, etc..
+ *
+ * These are some of the many terms that are thrown about that don't always
+ * mean what people think they mean (Inconceivable!).  In the interest of
+ * creating a common ground for discussion, terms and their definitions
+ * will be established.
+ *
+ * Memory devices:	The individual chip on a memory stick.  These devices
+ *			commonly output 4 and 8 bits each.  Grouping several
+ *			of these in parallel provides 64 bits which is common
+ *			for a memory stick.
+ *
+ * Memory Stick:	A printed circuit board that aggregates multiple
+ *			memory devices in parallel.  This is the atomic
+ *			memory component that is purchaseable by Joe consumer
+ *			and loaded into a memory socket.
+ *
+ * Socket:		A physical connector on the motherboard that accepts
+ *			a single memory stick.
+ *
+ * Channel:		Set of memory devices on a memory stick that must be
+ *			grouped in parallel with one or more additional
+ *			channels from other memory sticks.  This parallel
+ *			grouping of the output from multiple channels are
+ *			necessary for the smallest granularity of memory access.
+ *			Some memory controllers are capable of single channel -
+ *			which means that memory sticks can be loaded
+ *			individually.  Other memory controllers are only
+ *			capable of dual channel - which means that memory
+ *			sticks must be loaded as pairs (see "socket set").
+ *
+ * Chip-select row:	All of the memory devices that are selected together.
+ *			for a single, minimum grain of memory access.
+ *			This selects all of the parallel memory devices across
+ *			all of the parallel channels.  Common chip-select rows
+ *			for single channel are 64 bits, for dual channel 128
+ *			bits.
+ *
+ * Single-Ranked stick:	A Single-ranked stick has 1 chip-select row of memory.
+ *			Motherboards commonly drive two chip-select pins to
+ *			a memory stick. A single-ranked stick, will occupy
+ *			only one of those rows. The other will be unused.
+ *
+ * Double-Ranked stick:	A double-ranked stick has two chip-select rows which
+ *			access different sets of memory devices.  The two
+ *			rows cannot be accessed concurrently.
+ *
+ * Double-sided stick:	DEPRECATED TERM, see Double-Ranked stick.
+ *			A double-sided stick has two chip-select rows which
+ *			access different sets of memory devices.  The two
+ *			rows cannot be accessed concurrently.  "Double-sided"
+ *			is irrespective of the memory devices being mounted
+ *			on both sides of the memory stick.
+ *
+ * Socket set:		All of the memory sticks that are required for
+ *			a single memory access or all of the memory sticks
+ *			spanned by a chip-select row.  A single socket set
+ *			has two chip-select rows and if double-sided sticks
+ *			are used these will occupy those chip-select rows.
+ *
+ * Bank:		This term is avoided because it is unclear when
+ *			needing to distinguish between chip-select rows and
+ *			socket sets.
+ *
+ * Controller pages:
+ *
+ * Physical pages:
+ *
+ * Virtual pages:
+ *
+ *
+ * STRUCTURE ORGANIZATION AND CHOICES
+ *
+ *
+ *
+ * PS - I enjoyed writing all that about as much as you enjoyed reading it.
+ */
+
+struct channel_info {
+	int chan_idx;		/* channel index */
+	u32 ce_count;		/* Correctable Errors for this CHANNEL */
+	char label[EDAC_MC_LABEL_LEN + 1];	/* DIMM label on motherboard */
+	struct csrow_info *csrow;	/* the parent */
+};
+
+struct csrow_info {
+	unsigned long first_page;	/* first page number in dimm */
+	unsigned long last_page;	/* last page number in dimm */
+	unsigned long page_mask;	/* used for interleaving -
+					 * 0UL for non intlv
+					 */
+	u32 nr_pages;		/* number of pages in csrow */
+	u32 grain;		/* granularity of reported error in bytes */
+	int csrow_idx;		/* the chip-select row */
+	enum dev_type dtype;	/* memory device type */
+	u32 ue_count;		/* Uncorrectable Errors for this csrow */
+	u32 ce_count;		/* Correctable Errors for this csrow */
+	enum mem_type mtype;	/* memory csrow type */
+	enum edac_type edac_mode;	/* EDAC mode for this csrow */
+	struct mem_ctl_info *mci;	/* the parent */
+
+	struct kobject kobj;	/* sysfs kobject for this csrow */
+
+	/* channel information for this csrow */
+	u32 nr_channels;
+	struct channel_info *channels;
+};
+
+struct mcidev_sysfs_group {
+	const char *name;				/* group name */
+	const struct mcidev_sysfs_attribute *mcidev_attr; /* group attributes */
+};
+
+struct mcidev_sysfs_group_kobj {
+	struct list_head list;		/* list for all instances within a mc */
+
+	struct kobject kobj;		/* kobj for the group */
+
+	const struct mcidev_sysfs_group *grp;	/* group description table */
+	struct mem_ctl_info *mci;	/* the parent */
+};
+
+/* mcidev_sysfs_attribute structure
+ *	used for driver sysfs attributes and in mem_ctl_info
+ * 	sysfs top level entries
+ */
+struct mcidev_sysfs_attribute {
+	/* It should use either attr or grp */
+	struct attribute attr;
+	const struct mcidev_sysfs_group *grp;	/* Points to a group of attributes */
+
+	/* Ops for show/store values at the attribute - not used on group */
+        ssize_t (*show)(struct mem_ctl_info *,char *);
+        ssize_t (*store)(struct mem_ctl_info *, const char *,size_t);
+};
+
+/* MEMORY controller information structure
+ */
+struct mem_ctl_info {
+	struct list_head link;	/* for global list of mem_ctl_info structs */
+
+	struct module *owner;	/* Module owner of this control struct */
+
+	unsigned long mtype_cap;	/* memory types supported by mc */
+	unsigned long edac_ctl_cap;	/* Mem controller EDAC capabilities */
+	unsigned long edac_cap;	/* configuration capabilities - this is
+				 * closely related to edac_ctl_cap.  The
+				 * difference is that the controller may be
+				 * capable of s4ecd4ed which would be listed
+				 * in edac_ctl_cap, but if channels aren't
+				 * capable of s4ecd4ed then the edac_cap would
+				 * not have that capability.
+				 */
+	unsigned long scrub_cap;	/* chipset scrub capabilities */
+	enum scrub_type scrub_mode;	/* current scrub mode */
+
+	/* Translates sdram memory scrub rate given in bytes/sec to the
+	   internal representation and configures whatever else needs
+	   to be configured.
+	 */
+	int (*set_sdram_scrub_rate) (struct mem_ctl_info * mci, u32 bw);
+
+	/* Get the current sdram memory scrub rate from the internal
+	   representation and converts it to the closest matching
+	   bandwidth in bytes/sec.
+	 */
+	int (*get_sdram_scrub_rate) (struct mem_ctl_info * mci);
+
+
+	/* pointer to edac checking routine */
+	void (*edac_check) (struct mem_ctl_info * mci);
+
+	/*
+	 * Remaps memory pages: controller pages to physical pages.
+	 * For most MC's, this will be NULL.
+	 */
+	/* FIXME - why not send the phys page to begin with? */
+	unsigned long (*ctl_page_to_phys) (struct mem_ctl_info * mci,
+					   unsigned long page);
+	int mc_idx;
+	int nr_csrows;
+	struct csrow_info *csrows;
+	/*
+	 * FIXME - what about controllers on other busses? - IDs must be
+	 * unique.  dev pointer should be sufficiently unique, but
+	 * BUS:SLOT.FUNC numbers may not be unique.
+	 */
+	struct device *dev;
+	const char *mod_name;
+	const char *mod_ver;
+	const char *ctl_name;
+	const char *dev_name;
+	char proc_name[MC_PROC_NAME_MAX_LEN + 1];
+	void *pvt_info;
+	u32 ue_noinfo_count;	/* Uncorrectable Errors w/o info */
+	u32 ce_noinfo_count;	/* Correctable Errors w/o info */
+	u32 ue_count;		/* Total Uncorrectable Errors for this MC */
+	u32 ce_count;		/* Total Correctable Errors for this MC */
+	unsigned long start_time;	/* mci load start time (in jiffies) */
+
+	struct completion complete;
+
+	/* edac sysfs device control */
+	struct kobject edac_mci_kobj;
+
+	/* list for all grp instances within a mc */
+	struct list_head grp_kobj_list;
+
+	/* Additional top controller level attributes, but specified
+	 * by the low level driver.
+	 *
+	 * Set by the low level driver to provide attributes at the
+	 * controller level, same level as 'ue_count' and 'ce_count' above.
+	 * An array of structures, NULL terminated
+	 *
+	 * If attributes are desired, then set to array of attributes
+	 * If no attributes are desired, leave NULL
+	 */
+	const struct mcidev_sysfs_attribute *mc_driver_sysfs_attributes;
+
+	/* work struct for this MC */
+	struct delayed_work work;
+
+	/* the internal state of this controller instance */
+	int op_state;
+};
+
 #endif
diff --git a/include/linux/edac_mce.h b/include/linux/edac_mce.h
deleted file mode 100644
index f974fc0..0000000
--- a/include/linux/edac_mce.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Provides edac interface to mcelog events
- *
- * This file may be distributed under the terms of the
- * GNU General Public License version 2.
- *
- * Copyright (c) 2009 by:
- *	 Mauro Carvalho Chehab <mchehab@redhat.com>
- *
- * Red Hat Inc. http://www.redhat.com
- */
-
-#if defined(CONFIG_EDAC_MCE) || \
-			(defined(CONFIG_EDAC_MCE_MODULE) && defined(MODULE))
-
-#include <asm/mce.h>
-#include <linux/list.h>
-
-struct edac_mce {
-	struct list_head list;
-
-	void *priv;
-	int (*check_error)(void *priv, struct mce *mce);
-};
-
-int edac_mce_register(struct edac_mce *edac_mce);
-void edac_mce_unregister(struct edac_mce *edac_mce);
-int edac_mce_parse(struct mce *mce);
-
-#else
-#define edac_mce_parse(mce) (0)
-#endif
diff --git a/include/linux/ext2_fs.h b/include/linux/ext2_fs.h
index 53792bf..ce1b719 100644
--- a/include/linux/ext2_fs.h
+++ b/include/linux/ext2_fs.h
@@ -197,8 +197,8 @@ struct ext2_group_desc
 
 /* Flags that should be inherited by new inodes from their parent. */
 #define EXT2_FL_INHERITED (EXT2_SECRM_FL | EXT2_UNRM_FL | EXT2_COMPR_FL |\
-			   EXT2_SYNC_FL | EXT2_IMMUTABLE_FL | EXT2_APPEND_FL |\
-			   EXT2_NODUMP_FL | EXT2_NOATIME_FL | EXT2_COMPRBLK_FL|\
+			   EXT2_SYNC_FL | EXT2_NODUMP_FL |\
+			   EXT2_NOATIME_FL | EXT2_COMPRBLK_FL |\
 			   EXT2_NOCOMP_FL | EXT2_JOURNAL_DATA_FL |\
 			   EXT2_NOTAIL_FL | EXT2_DIRSYNC_FL)
 
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
index 81965cc..dec9911 100644
--- a/include/linux/ext3_fs.h
+++ b/include/linux/ext3_fs.h
@@ -180,8 +180,8 @@ struct ext3_group_desc
 
 /* Flags that should be inherited by new inodes from their parent. */
 #define EXT3_FL_INHERITED (EXT3_SECRM_FL | EXT3_UNRM_FL | EXT3_COMPR_FL |\
-			   EXT3_SYNC_FL | EXT3_IMMUTABLE_FL | EXT3_APPEND_FL |\
-			   EXT3_NODUMP_FL | EXT3_NOATIME_FL | EXT3_COMPRBLK_FL|\
+			   EXT3_SYNC_FL | EXT3_NODUMP_FL |\
+			   EXT3_NOATIME_FL | EXT3_COMPRBLK_FL |\
 			   EXT3_NOCOMPR_FL | EXT3_JOURNAL_DATA_FL |\
 			   EXT3_NOTAIL_FL | EXT3_DIRSYNC_FL)
 
@@ -381,7 +381,7 @@ struct ext3_inode {
  * Mount flags
  */
 #define EXT3_MOUNT_CHECK		0x00001	/* Do mount-time checks */
-#define EXT3_MOUNT_OLDALLOC		0x00002  /* Don't use the new Orlov allocator */
+/* EXT3_MOUNT_OLDALLOC was there */
 #define EXT3_MOUNT_GRPID		0x00004	/* Create files with directory's group */
 #define EXT3_MOUNT_DEBUG		0x00008	/* Some debugging messages */
 #define EXT3_MOUNT_ERRORS_CONT		0x00010	/* Continue on errors */
diff --git a/include/linux/ext3_fs_sb.h b/include/linux/ext3_fs_sb.h
index 258088a..6436525 100644
--- a/include/linux/ext3_fs_sb.h
+++ b/include/linux/ext3_fs_sb.h
@@ -76,10 +76,6 @@ struct ext3_sb_info {
 	struct mutex s_resize_lock;
 	unsigned long s_commit_interval;
 	struct block_device *journal_bdev;
-#ifdef CONFIG_JBD_DEBUG
-	struct timer_list turn_ro_timer;	/* For turning read-only (crash simulation) */
-	wait_queue_head_t ro_wait_queue;	/* For people waiting for the fs to go read-only */
-#endif
 #ifdef CONFIG_QUOTA
 	char *s_qf_names[MAXQUOTAS];		/* Names of quota files with journalled quota */
 	int s_jquota_fmt;			/* Format of quota to use */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 7a049fd..0c4df26 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -768,14 +768,25 @@ struct inode {
 
 	/* Stat data, not accessed from path walking */
 	unsigned long		i_ino;
-	unsigned int		i_nlink;
+	/*
+	 * Filesystems may only read i_nlink directly.  They shall use the
+	 * following functions for modification:
+	 *
+	 *    (set|clear|inc|drop)_nlink
+	 *    inode_(inc|dec)_link_count
+	 */
+	union {
+		const unsigned int i_nlink;
+		unsigned int __i_nlink;
+	};
 	dev_t			i_rdev;
-	loff_t			i_size;
 	struct timespec		i_atime;
 	struct timespec		i_mtime;
 	struct timespec		i_ctime;
-	unsigned int		i_blkbits;
+	spinlock_t		i_lock;	/* i_blocks, i_bytes, maybe i_size */
+	unsigned short          i_bytes;
 	blkcnt_t		i_blocks;
+	loff_t			i_size;
 
 #ifdef __NEED_I_SIZE_ORDERED
 	seqcount_t		i_size_seqcount;
@@ -783,7 +794,6 @@ struct inode {
 
 	/* Misc */
 	unsigned long		i_state;
-	spinlock_t		i_lock;	/* i_blocks, i_bytes, maybe i_size */
 	struct mutex		i_mutex;
 
 	unsigned long		dirtied_when;	/* jiffies of first dirtying */
@@ -797,9 +807,10 @@ struct inode {
 		struct rcu_head		i_rcu;
 	};
 	atomic_t		i_count;
+	unsigned int		i_blkbits;
 	u64			i_version;
-	unsigned short          i_bytes;
 	atomic_t		i_dio_count;
+	atomic_t		i_writecount;
 	const struct file_operations	*i_fop;	/* former ->i_op->default_file_ops */
 	struct file_lock	*i_flock;
 	struct address_space	i_data;
@@ -823,7 +834,6 @@ struct inode {
 #ifdef CONFIG_IMA
 	atomic_t		i_readcount; /* struct files open RO */
 #endif
-	atomic_t		i_writecount;
 	void			*i_private; /* fs or device private pointer */
 };
 
@@ -1755,6 +1765,19 @@ static inline void mark_inode_dirty_sync(struct inode *inode)
 }
 
 /**
+ * set_nlink - directly set an inode's link count
+ * @inode: inode
+ * @nlink: new nlink (should be non-zero)
+ *
+ * This is a low-level filesystem helper to replace any
+ * direct filesystem manipulation of i_nlink.
+ */
+static inline void set_nlink(struct inode *inode, unsigned int nlink)
+{
+	inode->__i_nlink = nlink;
+}
+
+/**
  * inc_nlink - directly increment an inode's link count
  * @inode: inode
  *
@@ -1764,7 +1787,7 @@ static inline void mark_inode_dirty_sync(struct inode *inode)
  */
 static inline void inc_nlink(struct inode *inode)
 {
-	inode->i_nlink++;
+	inode->__i_nlink++;
 }
 
 static inline void inode_inc_link_count(struct inode *inode)
@@ -1786,7 +1809,7 @@ static inline void inode_inc_link_count(struct inode *inode)
  */
 static inline void drop_nlink(struct inode *inode)
 {
-	inode->i_nlink--;
+	inode->__i_nlink--;
 }
 
 /**
@@ -1799,7 +1822,7 @@ static inline void drop_nlink(struct inode *inode)
  */
 static inline void clear_nlink(struct inode *inode)
 {
-	inode->i_nlink = 0;
+	inode->__i_nlink = 0;
 }
 
 static inline void inode_dec_link_count(struct inode *inode)
diff --git a/include/linux/i2c-omap.h b/include/linux/i2c-omap.h
index 0aa0cbd..92a0dc7 100644
--- a/include/linux/i2c-omap.h
+++ b/include/linux/i2c-omap.h
@@ -32,10 +32,9 @@
 
 struct omap_i2c_bus_platform_data {
 	u32		clkrate;
+	u32		rev;
+	u32		flags;
 	void		(*set_mpu_wkup_lat)(struct device *dev, long set);
-	int		(*device_enable) (struct platform_device *pdev);
-	int		(*device_shutdown) (struct platform_device *pdev);
-	int		(*device_idle) (struct platform_device *pdev);
 };
 
 #endif
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 3ad553e..99834e58 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -47,6 +47,7 @@ struct irq_domain_ops {
  *            of the irq_domain is responsible for allocating the array of
  *            irq_desc structures.
  * @nr_irq: Number of irqs managed by the irq domain
+ * @hwirq_base: Starting number for hwirqs managed by the irq domain
  * @ops: pointer to irq_domain methods
  * @priv: private data pointer for use by owner.  Not touched by irq_domain
  *        core code.
@@ -57,6 +58,7 @@ struct irq_domain {
 	struct list_head list;
 	unsigned int irq_base;
 	unsigned int nr_irq;
+	unsigned int hwirq_base;
 	const struct irq_domain_ops *ops;
 	void *priv;
 	struct device_node *of_node;
@@ -72,9 +74,21 @@ struct irq_domain {
 static inline unsigned int irq_domain_to_irq(struct irq_domain *d,
 					     unsigned long hwirq)
 {
-	return d->ops->to_irq ? d->ops->to_irq(d, hwirq) : d->irq_base + hwirq;
+	if (d->ops->to_irq)
+		return d->ops->to_irq(d, hwirq);
+	if (WARN_ON(hwirq < d->hwirq_base))
+		return 0;
+	return d->irq_base + hwirq - d->hwirq_base;
 }
 
+#define irq_domain_for_each_hwirq(d, hw) \
+	for (hw = d->hwirq_base; hw < d->hwirq_base + d->nr_irq; hw++)
+
+#define irq_domain_for_each_irq(d, hw, irq) \
+	for (hw = d->hwirq_base, irq = irq_domain_to_irq(d, hw); \
+	     hw < d->hwirq_base + d->nr_irq; \
+	     hw++, irq = irq_domain_to_irq(d, hw))
+
 extern void irq_domain_add(struct irq_domain *domain);
 extern void irq_domain_del(struct irq_domain *domain);
 #endif /* CONFIG_IRQ_DOMAIN */
diff --git a/include/linux/jbd.h b/include/linux/jbd.h
index e6a5e34..c7acdde 100644
--- a/include/linux/jbd.h
+++ b/include/linux/jbd.h
@@ -244,6 +244,7 @@ typedef struct journal_superblock_s
 
 #include <linux/fs.h>
 #include <linux/sched.h>
+#include <linux/jbd_common.h>
 
 #define J_ASSERT(assert)	BUG_ON(!(assert))
 
@@ -270,69 +271,6 @@ typedef struct journal_superblock_s
 #define J_EXPECT_JH(jh, expr, why...)	__journal_expect(expr, ## why)
 #endif
 
-enum jbd_state_bits {
-	BH_JBD			/* Has an attached ext3 journal_head */
-	  = BH_PrivateStart,
-	BH_JWrite,		/* Being written to log (@@@ DEBUGGING) */
-	BH_Freed,		/* Has been freed (truncated) */
-	BH_Revoked,		/* Has been revoked from the log */
-	BH_RevokeValid,		/* Revoked flag is valid */
-	BH_JBDDirty,		/* Is dirty but journaled */
-	BH_State,		/* Pins most journal_head state */
-	BH_JournalHead,		/* Pins bh->b_private and jh->b_bh */
-	BH_Unshadow,		/* Dummy bit, for BJ_Shadow wakeup filtering */
-};
-
-BUFFER_FNS(JBD, jbd)
-BUFFER_FNS(JWrite, jwrite)
-BUFFER_FNS(JBDDirty, jbddirty)
-TAS_BUFFER_FNS(JBDDirty, jbddirty)
-BUFFER_FNS(Revoked, revoked)
-TAS_BUFFER_FNS(Revoked, revoked)
-BUFFER_FNS(RevokeValid, revokevalid)
-TAS_BUFFER_FNS(RevokeValid, revokevalid)
-BUFFER_FNS(Freed, freed)
-
-static inline struct buffer_head *jh2bh(struct journal_head *jh)
-{
-	return jh->b_bh;
-}
-
-static inline struct journal_head *bh2jh(struct buffer_head *bh)
-{
-	return bh->b_private;
-}
-
-static inline void jbd_lock_bh_state(struct buffer_head *bh)
-{
-	bit_spin_lock(BH_State, &bh->b_state);
-}
-
-static inline int jbd_trylock_bh_state(struct buffer_head *bh)
-{
-	return bit_spin_trylock(BH_State, &bh->b_state);
-}
-
-static inline int jbd_is_locked_bh_state(struct buffer_head *bh)
-{
-	return bit_spin_is_locked(BH_State, &bh->b_state);
-}
-
-static inline void jbd_unlock_bh_state(struct buffer_head *bh)
-{
-	bit_spin_unlock(BH_State, &bh->b_state);
-}
-
-static inline void jbd_lock_bh_journal_head(struct buffer_head *bh)
-{
-	bit_spin_lock(BH_JournalHead, &bh->b_state);
-}
-
-static inline void jbd_unlock_bh_journal_head(struct buffer_head *bh)
-{
-	bit_spin_unlock(BH_JournalHead, &bh->b_state);
-}
-
 struct jbd_revoke_table_s;
 
 /**
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
index 38f307b..2092ea2 100644
--- a/include/linux/jbd2.h
+++ b/include/linux/jbd2.h
@@ -275,6 +275,7 @@ typedef struct journal_superblock_s
 
 #include <linux/fs.h>
 #include <linux/sched.h>
+#include <linux/jbd_common.h>
 
 #define J_ASSERT(assert)	BUG_ON(!(assert))
 
@@ -302,70 +303,6 @@ typedef struct journal_superblock_s
 #define J_EXPECT_JH(jh, expr, why...)	__journal_expect(expr, ## why)
 #endif
 
-enum jbd_state_bits {
-	BH_JBD			/* Has an attached ext3 journal_head */
-	  = BH_PrivateStart,
-	BH_JWrite,		/* Being written to log (@@@ DEBUGGING) */
-	BH_Freed,		/* Has been freed (truncated) */
-	BH_Revoked,		/* Has been revoked from the log */
-	BH_RevokeValid,		/* Revoked flag is valid */
-	BH_JBDDirty,		/* Is dirty but journaled */
-	BH_State,		/* Pins most journal_head state */
-	BH_JournalHead,		/* Pins bh->b_private and jh->b_bh */
-	BH_Unshadow,		/* Dummy bit, for BJ_Shadow wakeup filtering */
-	BH_JBDPrivateStart,	/* First bit available for private use by FS */
-};
-
-BUFFER_FNS(JBD, jbd)
-BUFFER_FNS(JWrite, jwrite)
-BUFFER_FNS(JBDDirty, jbddirty)
-TAS_BUFFER_FNS(JBDDirty, jbddirty)
-BUFFER_FNS(Revoked, revoked)
-TAS_BUFFER_FNS(Revoked, revoked)
-BUFFER_FNS(RevokeValid, revokevalid)
-TAS_BUFFER_FNS(RevokeValid, revokevalid)
-BUFFER_FNS(Freed, freed)
-
-static inline struct buffer_head *jh2bh(struct journal_head *jh)
-{
-	return jh->b_bh;
-}
-
-static inline struct journal_head *bh2jh(struct buffer_head *bh)
-{
-	return bh->b_private;
-}
-
-static inline void jbd_lock_bh_state(struct buffer_head *bh)
-{
-	bit_spin_lock(BH_State, &bh->b_state);
-}
-
-static inline int jbd_trylock_bh_state(struct buffer_head *bh)
-{
-	return bit_spin_trylock(BH_State, &bh->b_state);
-}
-
-static inline int jbd_is_locked_bh_state(struct buffer_head *bh)
-{
-	return bit_spin_is_locked(BH_State, &bh->b_state);
-}
-
-static inline void jbd_unlock_bh_state(struct buffer_head *bh)
-{
-	bit_spin_unlock(BH_State, &bh->b_state);
-}
-
-static inline void jbd_lock_bh_journal_head(struct buffer_head *bh)
-{
-	bit_spin_lock(BH_JournalHead, &bh->b_state);
-}
-
-static inline void jbd_unlock_bh_journal_head(struct buffer_head *bh)
-{
-	bit_spin_unlock(BH_JournalHead, &bh->b_state);
-}
-
 /* Flags in jbd_inode->i_flags */
 #define __JI_COMMIT_RUNNING 0
 /* Commit of the inode data in progress. We use this flag to protect us from
@@ -1106,9 +1043,9 @@ static inline handle_t *journal_current_handle(void)
  */
 
 extern handle_t *jbd2_journal_start(journal_t *, int nblocks);
-extern handle_t *jbd2__journal_start(journal_t *, int nblocks, int gfp_mask);
+extern handle_t *jbd2__journal_start(journal_t *, int nblocks, gfp_t gfp_mask);
 extern int	 jbd2_journal_restart(handle_t *, int nblocks);
-extern int	 jbd2__journal_restart(handle_t *, int nblocks, int gfp_mask);
+extern int	 jbd2__journal_restart(handle_t *, int nblocks, gfp_t gfp_mask);
 extern int	 jbd2_journal_extend (handle_t *, int nblocks);
 extern int	 jbd2_journal_get_write_access(handle_t *, struct buffer_head *);
 extern int	 jbd2_journal_get_create_access (handle_t *, struct buffer_head *);
diff --git a/include/linux/jbd_common.h b/include/linux/jbd_common.h
new file mode 100644
index 0000000..6230f85
--- /dev/null
+++ b/include/linux/jbd_common.h
@@ -0,0 +1,68 @@
+#ifndef _LINUX_JBD_STATE_H
+#define _LINUX_JBD_STATE_H
+
+enum jbd_state_bits {
+	BH_JBD			/* Has an attached ext3 journal_head */
+	  = BH_PrivateStart,
+	BH_JWrite,		/* Being written to log (@@@ DEBUGGING) */
+	BH_Freed,		/* Has been freed (truncated) */
+	BH_Revoked,		/* Has been revoked from the log */
+	BH_RevokeValid,		/* Revoked flag is valid */
+	BH_JBDDirty,		/* Is dirty but journaled */
+	BH_State,		/* Pins most journal_head state */
+	BH_JournalHead,		/* Pins bh->b_private and jh->b_bh */
+	BH_Unshadow,		/* Dummy bit, for BJ_Shadow wakeup filtering */
+	BH_JBDPrivateStart,	/* First bit available for private use by FS */
+};
+
+BUFFER_FNS(JBD, jbd)
+BUFFER_FNS(JWrite, jwrite)
+BUFFER_FNS(JBDDirty, jbddirty)
+TAS_BUFFER_FNS(JBDDirty, jbddirty)
+BUFFER_FNS(Revoked, revoked)
+TAS_BUFFER_FNS(Revoked, revoked)
+BUFFER_FNS(RevokeValid, revokevalid)
+TAS_BUFFER_FNS(RevokeValid, revokevalid)
+BUFFER_FNS(Freed, freed)
+
+static inline struct buffer_head *jh2bh(struct journal_head *jh)
+{
+	return jh->b_bh;
+}
+
+static inline struct journal_head *bh2jh(struct buffer_head *bh)
+{
+	return bh->b_private;
+}
+
+static inline void jbd_lock_bh_state(struct buffer_head *bh)
+{
+	bit_spin_lock(BH_State, &bh->b_state);
+}
+
+static inline int jbd_trylock_bh_state(struct buffer_head *bh)
+{
+	return bit_spin_trylock(BH_State, &bh->b_state);
+}
+
+static inline int jbd_is_locked_bh_state(struct buffer_head *bh)
+{
+	return bit_spin_is_locked(BH_State, &bh->b_state);
+}
+
+static inline void jbd_unlock_bh_state(struct buffer_head *bh)
+{
+	bit_spin_unlock(BH_State, &bh->b_state);
+}
+
+static inline void jbd_lock_bh_journal_head(struct buffer_head *bh)
+{
+	bit_spin_lock(BH_JournalHead, &bh->b_state);
+}
+
+static inline void jbd_unlock_bh_journal_head(struct buffer_head *bh)
+{
+	bit_spin_unlock(BH_JournalHead, &bh->b_state);
+}
+
+#endif
diff --git a/include/linux/magic.h b/include/linux/magic.h
index 1e5df2a..2d4beab 100644
--- a/include/linux/magic.h
+++ b/include/linux/magic.h
@@ -30,11 +30,11 @@
 #define ANON_INODE_FS_MAGIC	0x09041934
 #define PSTOREFS_MAGIC		0x6165676C
 
-#define MINIX_SUPER_MAGIC	0x137F		/* original minix fs */
-#define MINIX_SUPER_MAGIC2	0x138F		/* minix fs, 30 char names */
-#define MINIX2_SUPER_MAGIC	0x2468		/* minix V2 fs */
-#define MINIX2_SUPER_MAGIC2	0x2478		/* minix V2 fs, 30 char names */
-#define MINIX3_SUPER_MAGIC	0x4d5a		/* minix V3 fs */
+#define MINIX_SUPER_MAGIC	0x137F		/* minix v1 fs, 14 char names */
+#define MINIX_SUPER_MAGIC2	0x138F		/* minix v1 fs, 30 char names */
+#define MINIX2_SUPER_MAGIC	0x2468		/* minix v2 fs, 14 char names */
+#define MINIX2_SUPER_MAGIC2	0x2478		/* minix v2 fs, 30 char names */
+#define MINIX3_SUPER_MAGIC	0x4d5a		/* minix v3 fs, 60 char names */
 
 #define MSDOS_SUPER_MAGIC	0x4d44		/* MD */
 #define NCP_SUPER_MAGIC		0x564c		/* Guess, what 0x564c is :-) */
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index ac797fa..b87068a 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -78,8 +78,8 @@ extern void mem_cgroup_uncharge_end(void);
 extern void mem_cgroup_uncharge_page(struct page *page);
 extern void mem_cgroup_uncharge_cache_page(struct page *page);
 
-extern void mem_cgroup_out_of_memory(struct mem_cgroup *mem, gfp_t gfp_mask);
-int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *mem);
+extern void mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask);
+int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *memcg);
 
 extern struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page);
 extern struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p);
@@ -88,26 +88,28 @@ extern struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm);
 static inline
 int mm_match_cgroup(const struct mm_struct *mm, const struct mem_cgroup *cgroup)
 {
-	struct mem_cgroup *mem;
+	struct mem_cgroup *memcg;
 	rcu_read_lock();
-	mem = mem_cgroup_from_task(rcu_dereference((mm)->owner));
+	memcg = mem_cgroup_from_task(rcu_dereference((mm)->owner));
 	rcu_read_unlock();
-	return cgroup == mem;
+	return cgroup == memcg;
 }
 
-extern struct cgroup_subsys_state *mem_cgroup_css(struct mem_cgroup *mem);
+extern struct cgroup_subsys_state *mem_cgroup_css(struct mem_cgroup *memcg);
 
 extern int
 mem_cgroup_prepare_migration(struct page *page,
 	struct page *newpage, struct mem_cgroup **ptr, gfp_t gfp_mask);
-extern void mem_cgroup_end_migration(struct mem_cgroup *mem,
+extern void mem_cgroup_end_migration(struct mem_cgroup *memcg,
 	struct page *oldpage, struct page *newpage, bool migration_ok);
 
 /*
  * For memory reclaim.
  */
-int mem_cgroup_inactive_anon_is_low(struct mem_cgroup *memcg);
-int mem_cgroup_inactive_file_is_low(struct mem_cgroup *memcg);
+int mem_cgroup_inactive_anon_is_low(struct mem_cgroup *memcg,
+				    struct zone *zone);
+int mem_cgroup_inactive_file_is_low(struct mem_cgroup *memcg,
+				    struct zone *zone);
 int mem_cgroup_select_victim_node(struct mem_cgroup *memcg);
 unsigned long mem_cgroup_zone_nr_lru_pages(struct mem_cgroup *memcg,
 					int nid, int zid, unsigned int lrumask);
@@ -148,7 +150,7 @@ static inline void mem_cgroup_dec_page_stat(struct page *page,
 unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
 						gfp_t gfp_mask,
 						unsigned long *total_scanned);
-u64 mem_cgroup_get_limit(struct mem_cgroup *mem);
+u64 mem_cgroup_get_limit(struct mem_cgroup *memcg);
 
 void mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx);
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
@@ -244,18 +246,20 @@ static inline struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm
 	return NULL;
 }
 
-static inline int mm_match_cgroup(struct mm_struct *mm, struct mem_cgroup *mem)
+static inline int mm_match_cgroup(struct mm_struct *mm,
+		struct mem_cgroup *memcg)
 {
 	return 1;
 }
 
 static inline int task_in_mem_cgroup(struct task_struct *task,
-				     const struct mem_cgroup *mem)
+				     const struct mem_cgroup *memcg)
 {
 	return 1;
 }
 
-static inline struct cgroup_subsys_state *mem_cgroup_css(struct mem_cgroup *mem)
+static inline struct cgroup_subsys_state
+		*mem_cgroup_css(struct mem_cgroup *memcg)
 {
 	return NULL;
 }
@@ -267,22 +271,22 @@ mem_cgroup_prepare_migration(struct page *page, struct page *newpage,
 	return 0;
 }
 
-static inline void mem_cgroup_end_migration(struct mem_cgroup *mem,
+static inline void mem_cgroup_end_migration(struct mem_cgroup *memcg,
 		struct page *oldpage, struct page *newpage, bool migration_ok)
 {
 }
 
-static inline int mem_cgroup_get_reclaim_priority(struct mem_cgroup *mem)
+static inline int mem_cgroup_get_reclaim_priority(struct mem_cgroup *memcg)
 {
 	return 0;
 }
 
-static inline void mem_cgroup_note_reclaim_priority(struct mem_cgroup *mem,
+static inline void mem_cgroup_note_reclaim_priority(struct mem_cgroup *memcg,
 						int priority)
 {
 }
 
-static inline void mem_cgroup_record_reclaim_priority(struct mem_cgroup *mem,
+static inline void mem_cgroup_record_reclaim_priority(struct mem_cgroup *memcg,
 						int priority)
 {
 }
@@ -293,13 +297,13 @@ static inline bool mem_cgroup_disabled(void)
 }
 
 static inline int
-mem_cgroup_inactive_anon_is_low(struct mem_cgroup *memcg)
+mem_cgroup_inactive_anon_is_low(struct mem_cgroup *memcg, struct zone *zone)
 {
 	return 1;
 }
 
 static inline int
-mem_cgroup_inactive_file_is_low(struct mem_cgroup *memcg)
+mem_cgroup_inactive_file_is_low(struct mem_cgroup *memcg, struct zone *zone)
 {
 	return 1;
 }
@@ -348,7 +352,7 @@ unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
 }
 
 static inline
-u64 mem_cgroup_get_limit(struct mem_cgroup *mem)
+u64 mem_cgroup_get_limit(struct mem_cgroup *memcg)
 {
 	return 0;
 }
diff --git a/include/linux/mfd/tps6586x.h b/include/linux/mfd/tps6586x.h
index b6bab1b..b19176e 100644
--- a/include/linux/mfd/tps6586x.h
+++ b/include/linux/mfd/tps6586x.h
@@ -1,6 +1,18 @@
 #ifndef __LINUX_MFD_TPS6586X_H
 #define __LINUX_MFD_TPS6586X_H
 
+#define TPS6586X_SLEW_RATE_INSTANTLY	0x00
+#define TPS6586X_SLEW_RATE_110UV	0x01
+#define TPS6586X_SLEW_RATE_220UV	0x02
+#define TPS6586X_SLEW_RATE_440UV	0x03
+#define TPS6586X_SLEW_RATE_880UV	0x04
+#define TPS6586X_SLEW_RATE_1760UV	0x05
+#define TPS6586X_SLEW_RATE_3520UV	0x06
+#define TPS6586X_SLEW_RATE_7040UV	0x07
+
+#define TPS6586X_SLEW_RATE_SET		0x08
+#define TPS6586X_SLEW_RATE_MASK         0x07
+
 enum {
 	TPS6586X_ID_SM_0,
 	TPS6586X_ID_SM_1,
@@ -48,6 +60,10 @@ enum {
 	TPS6586X_INT_RTC_ALM2,
 };
 
+struct tps6586x_settings {
+	int slew_rate;
+};
+
 struct tps6586x_subdev_info {
 	int		id;
 	const char	*name;
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 2366f94..84b0b18 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -61,6 +61,7 @@ enum {
 	MLX4_DEV_CAP_FLAG_RC		= 1LL <<  0,
 	MLX4_DEV_CAP_FLAG_UC		= 1LL <<  1,
 	MLX4_DEV_CAP_FLAG_UD		= 1LL <<  2,
+	MLX4_DEV_CAP_FLAG_XRC		= 1LL <<  3,
 	MLX4_DEV_CAP_FLAG_SRQ		= 1LL <<  6,
 	MLX4_DEV_CAP_FLAG_IPOIB_CSUM	= 1LL <<  7,
 	MLX4_DEV_CAP_FLAG_BAD_PKEY_CNTR	= 1LL <<  8,
@@ -83,6 +84,12 @@ enum {
 	MLX4_DEV_CAP_FLAG_COUNTERS	= 1LL << 48
 };
 
+#define MLX4_ATTR_EXTENDED_PORT_INFO	cpu_to_be16(0xff90)
+
+enum {
+	MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO	= 1 <<  0
+};
+
 enum {
 	MLX4_BMME_FLAG_LOCAL_INV	= 1 <<  6,
 	MLX4_BMME_FLAG_REMOTE_INV	= 1 <<  7,
@@ -257,6 +264,8 @@ struct mlx4_caps {
 	int			num_qp_per_mgm;
 	int			num_pds;
 	int			reserved_pds;
+	int			max_xrcds;
+	int			reserved_xrcds;
 	int			mtt_entry_sz;
 	u32			max_msg_sz;
 	u32			page_size_cap;
@@ -277,6 +286,7 @@ struct mlx4_caps {
 	u32			port_mask;
 	enum mlx4_port_type	possible_type[MLX4_MAX_PORTS + 1];
 	u32			max_counters;
+	u8			ext_port_cap[MLX4_MAX_PORTS + 1];
 };
 
 struct mlx4_buf_list {
@@ -500,6 +510,8 @@ static inline void *mlx4_buf_offset(struct mlx4_buf *buf, int offset)
 
 int mlx4_pd_alloc(struct mlx4_dev *dev, u32 *pdn);
 void mlx4_pd_free(struct mlx4_dev *dev, u32 pdn);
+int mlx4_xrcd_alloc(struct mlx4_dev *dev, u32 *xrcdn);
+void mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn);
 
 int mlx4_uar_alloc(struct mlx4_dev *dev, struct mlx4_uar *uar);
 void mlx4_uar_free(struct mlx4_dev *dev, struct mlx4_uar *uar);
@@ -539,8 +551,8 @@ void mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt);
 int mlx4_qp_alloc(struct mlx4_dev *dev, int qpn, struct mlx4_qp *qp);
 void mlx4_qp_free(struct mlx4_dev *dev, struct mlx4_qp *qp);
 
-int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, struct mlx4_mtt *mtt,
-		   u64 db_rec, struct mlx4_srq *srq);
+int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, u32 cqn, u16 xrcdn,
+		   struct mlx4_mtt *mtt, u64 db_rec, struct mlx4_srq *srq);
 void mlx4_srq_free(struct mlx4_dev *dev, struct mlx4_srq *srq);
 int mlx4_srq_arm(struct mlx4_dev *dev, struct mlx4_srq *srq, int limit_watermark);
 int mlx4_srq_query(struct mlx4_dev *dev, struct mlx4_srq *srq, int *limit_watermark);
diff --git a/include/linux/mlx4/qp.h b/include/linux/mlx4/qp.h
index 4001c82..48cc4cb 100644
--- a/include/linux/mlx4/qp.h
+++ b/include/linux/mlx4/qp.h
@@ -75,6 +75,7 @@ enum {
 	MLX4_QP_ST_UC				= 0x1,
 	MLX4_QP_ST_RD				= 0x2,
 	MLX4_QP_ST_UD				= 0x3,
+	MLX4_QP_ST_XRC				= 0x6,
 	MLX4_QP_ST_MLX				= 0x7
 };
 
@@ -137,7 +138,7 @@ struct mlx4_qp_context {
 	__be32			ssn;
 	__be32			params2;
 	__be32			rnr_nextrecvpsn;
-	__be32			srcd;
+	__be32			xrcd;
 	__be32			cqn_recv;
 	__be64			db_rec_addr;
 	__be32			qkey;
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 3b3e3b8..3dc3a8c 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -356,36 +356,50 @@ static inline struct page *compound_head(struct page *page)
 	return page;
 }
 
+/*
+ * The atomic page->_mapcount, starts from -1: so that transitions
+ * both from it and to it can be tracked, using atomic_inc_and_test
+ * and atomic_add_negative(-1).
+ */
+static inline void reset_page_mapcount(struct page *page)
+{
+	atomic_set(&(page)->_mapcount, -1);
+}
+
+static inline int page_mapcount(struct page *page)
+{
+	return atomic_read(&(page)->_mapcount) + 1;
+}
+
 static inline int page_count(struct page *page)
 {
 	return atomic_read(&compound_head(page)->_count);
 }
 
+static inline void get_huge_page_tail(struct page *page)
+{
+	/*
+	 * __split_huge_page_refcount() cannot run
+	 * from under us.
+	 */
+	VM_BUG_ON(page_mapcount(page) < 0);
+	VM_BUG_ON(atomic_read(&page->_count) != 0);
+	atomic_inc(&page->_mapcount);
+}
+
+extern bool __get_page_tail(struct page *page);
+
 static inline void get_page(struct page *page)
 {
+	if (unlikely(PageTail(page)))
+		if (likely(__get_page_tail(page)))
+			return;
 	/*
 	 * Getting a normal page or the head of a compound page
-	 * requires to already have an elevated page->_count. Only if
-	 * we're getting a tail page, the elevated page->_count is
-	 * required only in the head page, so for tail pages the
-	 * bugcheck only verifies that the page->_count isn't
-	 * negative.
+	 * requires to already have an elevated page->_count.
 	 */
-	VM_BUG_ON(atomic_read(&page->_count) < !PageTail(page));
+	VM_BUG_ON(atomic_read(&page->_count) <= 0);
 	atomic_inc(&page->_count);
-	/*
-	 * Getting a tail page will elevate both the head and tail
-	 * page->_count(s).
-	 */
-	if (unlikely(PageTail(page))) {
-		/*
-		 * This is safe only because
-		 * __split_huge_page_refcount can't run under
-		 * get_page().
-		 */
-		VM_BUG_ON(atomic_read(&page->first_page->_count) <= 0);
-		atomic_inc(&page->first_page->_count);
-	}
 }
 
 static inline struct page *virt_to_head_page(const void *x)
@@ -804,21 +818,6 @@ static inline pgoff_t page_index(struct page *page)
 }
 
 /*
- * The atomic page->_mapcount, like _count, starts from -1:
- * so that transitions both from it and to it can be tracked,
- * using atomic_inc_and_test and atomic_add_negative(-1).
- */
-static inline void reset_page_mapcount(struct page *page)
-{
-	atomic_set(&(page)->_mapcount, -1);
-}
-
-static inline int page_mapcount(struct page *page)
-{
-	return atomic_read(&(page)->_mapcount) + 1;
-}
-
-/*
  * Return true if this page is mapped into pagetables.
  */
 static inline int page_mapped(struct page *page)
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 3e01a19..5b42f1b 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -62,10 +62,23 @@ struct page {
 			struct {
 
 				union {
-					atomic_t _mapcount;	/* Count of ptes mapped in mms,
-							 * to show when page is mapped
-							 * & limit reverse map searches.
-							 */
+					/*
+					 * Count of ptes mapped in
+					 * mms, to show when page is
+					 * mapped & limit reverse map
+					 * searches.
+					 *
+					 * Used also for tail pages
+					 * refcounting instead of
+					 * _count. Tail pages cannot
+					 * be mapped and keeping the
+					 * tail page _count zero at
+					 * all times guarantees
+					 * get_page_unless_zero() will
+					 * never succeed on tail
+					 * pages.
+					 */
+					atomic_t _mapcount;
 
 					struct {
 						unsigned inuse:16;
diff --git a/include/linux/namei.h b/include/linux/namei.h
index 409328d..ffc0213 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -67,6 +67,7 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
 #define LOOKUP_EMPTY		0x4000
 
 extern int user_path_at(int, const char __user *, unsigned, struct path *);
+extern int user_path_at_empty(int, const char __user *, unsigned, struct path *, int *empty);
 
 #define user_path(name, path) user_path_at(AT_FDCWD, name, LOOKUP_FOLLOW, path)
 #define user_lpath(name, path) user_path_at(AT_FDCWD, name, 0, path)
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index 8180cd9..8374d29 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -25,6 +25,7 @@
 #define NETLINK_SCSITRANSPORT	18	/* SCSI Transports */
 #define NETLINK_ECRYPTFS	19
 #define NETLINK_RDMA		20
+#define NETLINK_CRYPTO		21	/* Crypto layer */
 
 #define MAX_LINKS 32		
 
diff --git a/include/linux/of.h b/include/linux/of.h
index 5dbe263..f01ba8a 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -207,6 +207,11 @@ extern int of_property_read_u64(const struct device_node *np,
 extern int of_property_read_string(struct device_node *np,
 				   const char *propname,
 				   const char **out_string);
+extern int of_property_read_string_index(struct device_node *np,
+					 const char *propname,
+					 int index, const char **output);
+extern int of_property_count_strings(struct device_node *np,
+				     const char *propname);
 extern int of_device_is_compatible(const struct device_node *device,
 				   const char *);
 extern int of_device_is_available(const struct device_node *device);
@@ -283,6 +288,19 @@ static inline int of_property_read_string(struct device_node *np,
 	return -ENOSYS;
 }
 
+static inline int of_property_read_string_index(struct device_node *np,
+						const char *propname, int index,
+						const char **out_string)
+{
+	return -ENOSYS;
+}
+
+static inline int of_property_count_strings(struct device_node *np,
+					    const char *propname)
+{
+	return -ENOSYS;
+}
+
 static inline const void *of_get_property(const struct device_node *node,
 				const char *name,
 				int *lenp)
diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h
index cd2e61c..d0307ee 100644
--- a/include/linux/of_irq.h
+++ b/include/linux/of_irq.h
@@ -33,6 +33,8 @@ struct of_irq {
 	u32 specifier[OF_MAX_IRQ_SPEC]; /* Specifier copy */
 };
 
+typedef int (*of_irq_init_cb_t)(struct device_node *, struct device_node *);
+
 /*
  * Workarounds only applied to 32bit powermac machines
  */
@@ -73,6 +75,7 @@ extern int of_irq_to_resource_table(struct device_node *dev,
 		struct resource *res, int nr_irqs);
 extern struct device_node *of_irq_find_parent(struct device_node *child);
 
+extern void of_irq_init(const struct of_device_id *matches);
 
 #endif /* CONFIG_OF_IRQ */
 #endif /* CONFIG_OF */
diff --git a/include/linux/pps-gpio.h b/include/linux/pps-gpio.h
new file mode 100644
index 0000000..0035abe
--- /dev/null
+++ b/include/linux/pps-gpio.h
@@ -0,0 +1,32 @@
+/*
+ * pps-gpio.h -- PPS client for GPIOs
+ *
+ *
+ * Copyright (C) 2011 James Nuss <jamesnuss@nanometrics.ca>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You 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 _PPS_GPIO_H
+#define _PPS_GPIO_H
+
+struct pps_gpio_platform_data {
+	bool assert_falling_edge;
+	bool capture_clear;
+	unsigned int gpio_pin;
+	const char *gpio_label;
+};
+
+#endif
diff --git a/include/linux/pstore.h b/include/linux/pstore.h
index cc03bbf..ea56732 100644
--- a/include/linux/pstore.h
+++ b/include/linux/pstore.h
@@ -32,15 +32,15 @@ enum pstore_type_id {
 struct pstore_info {
 	struct module	*owner;
 	char		*name;
-	struct mutex	buf_mutex;	/* serialize access to 'buf' */
+	spinlock_t	buf_lock;	/* serialize access to 'buf' */
 	char		*buf;
 	size_t		bufsize;
 	int		(*open)(struct pstore_info *psi);
 	int		(*close)(struct pstore_info *psi);
 	ssize_t		(*read)(u64 *id, enum pstore_type_id *type,
 			struct timespec *time, struct pstore_info *psi);
-	u64		(*write)(enum pstore_type_id type, unsigned int part,
-			size_t size, struct pstore_info *psi);
+	int		(*write)(enum pstore_type_id type, u64 *id,
+			unsigned int part, size_t size, struct pstore_info *psi);
 	int		(*erase)(enum pstore_type_id type, u64 id,
 			struct pstore_info *psi);
 	void		*data;
diff --git a/include/linux/regulator/gpio-regulator.h b/include/linux/regulator/gpio-regulator.h
new file mode 100644
index 0000000..19fbd26
--- /dev/null
+++ b/include/linux/regulator/gpio-regulator.h
@@ -0,0 +1,87 @@
+/*
+ * gpio-regulator.h
+ *
+ * Copyright 2011 Heiko Stuebner <heiko@sntech.de>
+ *
+ * based on fixed.h
+ *
+ * Copyright 2008 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * Copyright (c) 2009 Nokia Corporation
+ * Roger Quadros <ext-roger.quadros@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 __REGULATOR_GPIO_H
+#define __REGULATOR_GPIO_H
+
+struct regulator_init_data;
+
+enum regulator_type;
+
+/**
+ * struct gpio_regulator_state - state description
+ * @value:		microvolts or microamps
+ * @gpios:		bitfield of gpio target-states for the value
+ *
+ * This structure describes a supported setting of the regulator
+ * and the necessary gpio-state to achieve it.
+ *
+ * The n-th bit in the bitfield describes the state of the n-th GPIO
+ * from the gpios-array defined in gpio_regulator_config below.
+ */
+struct gpio_regulator_state {
+	int value;
+	int gpios;
+};
+
+/**
+ * struct gpio_regulator_config - config structure
+ * @supply_name:	Name of the regulator supply
+ * @enable_gpio:	GPIO to use for enable control
+ *			set to -EINVAL if not used
+ * @enable_high:	Polarity of enable GPIO
+ *			1 = Active high, 0 = Active low
+ * @enabled_at_boot:	Whether regulator has been enabled at
+ *			boot or not. 1 = Yes, 0 = No
+ *			This is used to keep the regulator at
+ *			the default state
+ * @startup_delay:	Start-up time in microseconds
+ * @gpios:		Array containing the gpios needed to control
+ *			the setting of the regulator
+ * @nr_gpios:		Number of gpios
+ * @states:		Array of gpio_regulator_state entries describing
+ *			the gpio state for specific voltages
+ * @nr_states:		Number of states available
+ * @regulator_type:	either REGULATOR_CURRENT or REGULATOR_VOLTAGE
+ * @init_data:		regulator_init_data
+ *
+ * This structure contains gpio-voltage regulator configuration
+ * information that must be passed by platform code to the
+ * gpio-voltage regulator driver.
+ */
+struct gpio_regulator_config {
+	const char *supply_name;
+
+	int enable_gpio;
+	unsigned enable_high:1;
+	unsigned enabled_at_boot:1;
+	unsigned startup_delay;
+
+	struct gpio *gpios;
+	int nr_gpios;
+
+	struct gpio_regulator_state *states;
+	int nr_states;
+
+	enum regulator_type type;
+	struct regulator_init_data *init_data;
+};
+
+#endif
diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h
index ce3127a..f3f13fd 100644
--- a/include/linux/regulator/machine.h
+++ b/include/linux/regulator/machine.h
@@ -95,7 +95,7 @@ struct regulator_state {
  */
 struct regulation_constraints {
 
-	char *name;
+	const char *name;
 
 	/* voltage output range (inclusive) - for voltage control */
 	int min_uV;
diff --git a/include/linux/rio_ids.h b/include/linux/rio_ids.h
index 0cee015..b66d13d 100644
--- a/include/linux/rio_ids.h
+++ b/include/linux/rio_ids.h
@@ -39,5 +39,6 @@
 #define RIO_DID_IDTCPS1616		0x0379
 #define RIO_DID_IDTVPS1616		0x0377
 #define RIO_DID_IDTSPS1616		0x0378
+#define RIO_DID_TSI721			0x80ab
 
 #endif				/* LINUX_RIO_IDS_H */
diff --git a/include/linux/rtc/sirfsoc_rtciobrg.h b/include/linux/rtc/sirfsoc_rtciobrg.h
new file mode 100644
index 0000000..2c92e1c
--- /dev/null
+++ b/include/linux/rtc/sirfsoc_rtciobrg.h
@@ -0,0 +1,18 @@
+/*
+ * RTC I/O Bridge interfaces for CSR SiRFprimaII
+ * ARM access the registers of SYSRTC, GPSRTC and PWRC through this module
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+#ifndef _SIRFSOC_RTC_IOBRG_H_
+#define _SIRFSOC_RTC_IOBRG_H_
+
+extern void sirfsoc_rtc_iobrg_besyncing(void);
+
+extern u32 sirfsoc_rtc_iobrg_readl(u32 addr);
+
+extern void sirfsoc_rtc_iobrg_writel(u32 val, u32 addr);
+
+#endif
diff --git a/include/linux/sem.h b/include/linux/sem.h
index 1feb2de..10d6b22 100644
--- a/include/linux/sem.h
+++ b/include/linux/sem.h
@@ -83,13 +83,6 @@ struct  seminfo {
 
 struct task_struct;
 
-/* One semaphore structure for each semaphore in the system. */
-struct sem {
-	int	semval;		/* current value */
-	int	sempid;		/* pid of last operation */
-	struct list_head sem_pending; /* pending single-sop operations */
-};
-
 /* One sem_array data structure for each set of semaphores in the system. */
 struct sem_array {
 	struct kern_ipc_perm	____cacheline_aligned_in_smp
@@ -103,51 +96,21 @@ struct sem_array {
 	int			complex_count;	/* pending complex operations */
 };
 
-/* One queue for each sleeping process in the system. */
-struct sem_queue {
-	struct list_head	simple_list; /* queue of pending operations */
-	struct list_head	list;	 /* queue of pending operations */
-	struct task_struct	*sleeper; /* this process */
-	struct sem_undo		*undo;	 /* undo structure */
-	int    			pid;	 /* process id of requesting process */
-	int    			status;	 /* completion status of operation */
-	struct sembuf		*sops;	 /* array of pending operations */
-	int			nsops;	 /* number of operations */
-	int			alter;   /* does the operation alter the array? */
-};
-
-/* Each task has a list of undo requests. They are executed automatically
- * when the process exits.
- */
-struct sem_undo {
-	struct list_head	list_proc;	/* per-process list: all undos from one process. */
-						/* rcu protected */
-	struct rcu_head		rcu;		/* rcu struct for sem_undo() */
-	struct sem_undo_list	*ulp;		/* sem_undo_list for the process */
-	struct list_head	list_id;	/* per semaphore array list: all undos for one array */
-	int			semid;		/* semaphore set identifier */
-	short *			semadj;		/* array of adjustments, one per semaphore */
-};
-
-/* sem_undo_list controls shared access to the list of sem_undo structures
- * that may be shared among all a CLONE_SYSVSEM task group.
- */ 
-struct sem_undo_list {
-	atomic_t		refcnt;
-	spinlock_t		lock;
-	struct list_head	list_proc;
-};
+#ifdef CONFIG_SYSVIPC
 
 struct sysv_sem {
 	struct sem_undo_list *undo_list;
 };
 
-#ifdef CONFIG_SYSVIPC
-
 extern int copy_semundo(unsigned long clone_flags, struct task_struct *tsk);
 extern void exit_sem(struct task_struct *tsk);
 
 #else
+
+struct sysv_sem {
+	/* empty */
+};
+
 static inline int copy_semundo(unsigned long clone_flags, struct task_struct *tsk)
 {
 	return 0;
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 9a1ec10..703cfa3 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -931,6 +931,7 @@ enum
 #ifdef __KERNEL__
 #include <linux/list.h>
 #include <linux/rcupdate.h>
+#include <linux/wait.h>
 
 /* For the /proc/sys support */
 struct ctl_table;
@@ -1011,6 +1012,26 @@ extern int proc_do_large_bitmap(struct ctl_table *, int,
  * cover common cases.
  */
 
+/* Support for userspace poll() to watch for changes */
+struct ctl_table_poll {
+	atomic_t event;
+	wait_queue_head_t wait;
+};
+
+static inline void *proc_sys_poll_event(struct ctl_table_poll *poll)
+{
+	return (void *)(unsigned long)atomic_read(&poll->event);
+}
+
+void proc_sys_poll_notify(struct ctl_table_poll *poll);
+
+#define __CTL_TABLE_POLL_INITIALIZER(name) {				\
+	.event = ATOMIC_INIT(0),					\
+	.wait = __WAIT_QUEUE_HEAD_INITIALIZER(name.wait) }
+
+#define DEFINE_CTL_TABLE_POLL(name)					\
+	struct ctl_table_poll name = __CTL_TABLE_POLL_INITIALIZER(name)
+
 /* A sysctl table is an array of struct ctl_table: */
 struct ctl_table 
 {
@@ -1021,6 +1042,7 @@ struct ctl_table
 	struct ctl_table *child;
 	struct ctl_table *parent;	/* Automatically set */
 	proc_handler *proc_handler;	/* Callback for text formatting */
+	struct ctl_table_poll *poll;
 	void *extra1;
 	void *extra2;
 };
diff --git a/include/linux/utsname.h b/include/linux/utsname.h
index 4e5b021..c714ed7 100644
--- a/include/linux/utsname.h
+++ b/include/linux/utsname.h
@@ -37,6 +37,14 @@ struct new_utsname {
 #include <linux/nsproxy.h>
 #include <linux/err.h>
 
+enum uts_proc {
+	UTS_PROC_OSTYPE,
+	UTS_PROC_OSRELEASE,
+	UTS_PROC_VERSION,
+	UTS_PROC_HOSTNAME,
+	UTS_PROC_DOMAINNAME,
+};
+
 struct user_namespace;
 extern struct user_namespace init_user_ns;
 
@@ -80,6 +88,14 @@ static inline struct uts_namespace *copy_utsname(unsigned long flags,
 }
 #endif
 
+#ifdef CONFIG_PROC_SYSCTL
+extern void uts_proc_notify(enum uts_proc proc);
+#else
+static inline void uts_proc_notify(enum uts_proc proc)
+{
+}
+#endif
+
 static inline struct new_utsname *utsname(void)
 {
 	return &current->nsproxy->uts_ns->name;
diff --git a/include/linux/virtio.h b/include/linux/virtio.h
index 851ebf1..4c069d8 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -131,10 +131,10 @@ void unregister_virtio_device(struct virtio_device *dev);
  * virtio_driver - operations for a virtio I/O driver
  * @driver: underlying device driver (populate name and owner).
  * @id_table: the ids serviced by this driver.
- * @feature_table: an array of feature numbers supported by this device.
+ * @feature_table: an array of feature numbers supported by this driver.
  * @feature_table_size: number of entries in the feature table array.
  * @probe: the function to call when a device is found.  Returns 0 or -errno.
- * @remove: the function when a device is removed.
+ * @remove: the function to call when a device is removed.
  * @config_changed: optional function to call when the device configuration
  *    changes; may be called in interrupt context.
  */
diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
index 39c88c5..add4790 100644
--- a/include/linux/virtio_config.h
+++ b/include/linux/virtio_config.h
@@ -155,6 +155,9 @@ static inline bool virtio_has_feature(const struct virtio_device *vdev,
 #define virtio_config_val(vdev, fbit, offset, v) \
 	virtio_config_buf((vdev), (fbit), (offset), (v), sizeof(*v))
 
+#define virtio_config_val_len(vdev, fbit, offset, v, len) \
+	virtio_config_buf((vdev), (fbit), (offset), (v), (len))
+
 static inline int virtio_config_buf(struct virtio_device *vdev,
 				    unsigned int fbit,
 				    unsigned int offset,
diff --git a/include/linux/virtio_mmio.h b/include/linux/virtio_mmio.h
new file mode 100644
index 0000000..27c7ede
--- /dev/null
+++ b/include/linux/virtio_mmio.h
@@ -0,0 +1,111 @@
+/*
+ * Virtio platform device driver
+ *
+ * Copyright 2011, ARM Ltd.
+ *
+ * Based on Virtio PCI driver by Anthony Liguori, copyright IBM Corp. 2007
+ *
+ * This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of IBM nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _LINUX_VIRTIO_MMIO_H
+#define _LINUX_VIRTIO_MMIO_H
+
+/*
+ * Control registers
+ */
+
+/* Magic value ("virt" string) - Read Only */
+#define VIRTIO_MMIO_MAGIC_VALUE		0x000
+
+/* Virtio device version - Read Only */
+#define VIRTIO_MMIO_VERSION		0x004
+
+/* Virtio device ID - Read Only */
+#define VIRTIO_MMIO_DEVICE_ID		0x008
+
+/* Virtio vendor ID - Read Only */
+#define VIRTIO_MMIO_VENDOR_ID		0x00c
+
+/* Bitmask of the features supported by the host
+ * (32 bits per set) - Read Only */
+#define VIRTIO_MMIO_HOST_FEATURES	0x010
+
+/* Host features set selector - Write Only */
+#define VIRTIO_MMIO_HOST_FEATURES_SEL	0x014
+
+/* Bitmask of features activated by the guest
+ * (32 bits per set) - Write Only */
+#define VIRTIO_MMIO_GUEST_FEATURES	0x020
+
+/* Activated features set selector - Write Only */
+#define VIRTIO_MMIO_GUEST_FEATURES_SET	0x024
+
+/* Guest's memory page size in bytes - Write Only */
+#define VIRTIO_MMIO_GUEST_PAGE_SIZE	0x028
+
+/* Queue selector - Write Only */
+#define VIRTIO_MMIO_QUEUE_SEL		0x030
+
+/* Maximum size of the currently selected queue - Read Only */
+#define VIRTIO_MMIO_QUEUE_NUM_MAX	0x034
+
+/* Queue size for the currently selected queue - Write Only */
+#define VIRTIO_MMIO_QUEUE_NUM		0x038
+
+/* Used Ring alignment for the currently selected queue - Write Only */
+#define VIRTIO_MMIO_QUEUE_ALIGN		0x03c
+
+/* Guest's PFN for the currently selected queue - Read Write */
+#define VIRTIO_MMIO_QUEUE_PFN		0x040
+
+/* Queue notifier - Write Only */
+#define VIRTIO_MMIO_QUEUE_NOTIFY	0x050
+
+/* Interrupt status - Read Only */
+#define VIRTIO_MMIO_INTERRUPT_STATUS	0x060
+
+/* Interrupt acknowledge - Write Only */
+#define VIRTIO_MMIO_INTERRUPT_ACK	0x064
+
+/* Device status register - Read Write */
+#define VIRTIO_MMIO_STATUS		0x070
+
+/* The config space is defined by each driver as
+ * the per-driver configuration space - Read Write */
+#define VIRTIO_MMIO_CONFIG		0x100
+
+
+
+/*
+ * Interrupt flags (re: interrupt status & acknowledge registers)
+ */
+
+#define VIRTIO_MMIO_INT_VRING		(1 << 0)
+#define VIRTIO_MMIO_INT_CONFIG		(1 << 1)
+
+#endif
diff --git a/include/linux/virtio_ring.h b/include/linux/virtio_ring.h
index 4a32cb6..36be0f6 100644
--- a/include/linux/virtio_ring.h
+++ b/include/linux/virtio_ring.h
@@ -135,13 +135,13 @@ static inline void vring_init(struct vring *vr, unsigned int num, void *p,
 	vr->num = num;
 	vr->desc = p;
 	vr->avail = p + num*sizeof(struct vring_desc);
-	vr->used = (void *)(((unsigned long)&vr->avail->ring[num] + align-1)
-			    & ~(align - 1));
+	vr->used = (void *)(((unsigned long)&vr->avail->ring[num] + sizeof(__u16)
+		+ align-1) & ~(align - 1));
 }
 
 static inline unsigned vring_size(unsigned int num, unsigned long align)
 {
-	return ((sizeof(struct vring_desc) * num + sizeof(__u16) * (2 + num)
+	return ((sizeof(struct vring_desc) * num + sizeof(__u16) * (3 + num)
 		 + align - 1) & ~(align - 1))
 		+ sizeof(__u16) * 3 + sizeof(struct vring_used_elem) * num;
 }
diff --git a/include/rdma/ib_user_verbs.h b/include/rdma/ib_user_verbs.h
index fe5b051..81aba3a 100644
--- a/include/rdma/ib_user_verbs.h
+++ b/include/rdma/ib_user_verbs.h
@@ -81,7 +81,11 @@ enum {
 	IB_USER_VERBS_CMD_MODIFY_SRQ,
 	IB_USER_VERBS_CMD_QUERY_SRQ,
 	IB_USER_VERBS_CMD_DESTROY_SRQ,
-	IB_USER_VERBS_CMD_POST_SRQ_RECV
+	IB_USER_VERBS_CMD_POST_SRQ_RECV,
+	IB_USER_VERBS_CMD_OPEN_XRCD,
+	IB_USER_VERBS_CMD_CLOSE_XRCD,
+	IB_USER_VERBS_CMD_CREATE_XSRQ,
+	IB_USER_VERBS_CMD_OPEN_QP
 };
 
 /*
@@ -222,6 +226,21 @@ struct ib_uverbs_dealloc_pd {
 	__u32 pd_handle;
 };
 
+struct ib_uverbs_open_xrcd {
+	__u64 response;
+	__u32 fd;
+	__u32 oflags;
+	__u64 driver_data[0];
+};
+
+struct ib_uverbs_open_xrcd_resp {
+	__u32 xrcd_handle;
+};
+
+struct ib_uverbs_close_xrcd {
+	__u32 xrcd_handle;
+};
+
 struct ib_uverbs_reg_mr {
 	__u64 response;
 	__u64 start;
@@ -404,6 +423,17 @@ struct ib_uverbs_create_qp {
 	__u64 driver_data[0];
 };
 
+struct ib_uverbs_open_qp {
+	__u64 response;
+	__u64 user_handle;
+	__u32 pd_handle;
+	__u32 qpn;
+	__u8  qp_type;
+	__u8  reserved[7];
+	__u64 driver_data[0];
+};
+
+/* also used for open response */
 struct ib_uverbs_create_qp_resp {
 	__u32 qp_handle;
 	__u32 qpn;
@@ -648,11 +678,25 @@ struct ib_uverbs_create_srq {
 	__u64 driver_data[0];
 };
 
+struct ib_uverbs_create_xsrq {
+	__u64 response;
+	__u64 user_handle;
+	__u32 srq_type;
+	__u32 pd_handle;
+	__u32 max_wr;
+	__u32 max_sge;
+	__u32 srq_limit;
+	__u32 reserved;
+	__u32 xrcd_handle;
+	__u32 cq_handle;
+	__u64 driver_data[0];
+};
+
 struct ib_uverbs_create_srq_resp {
 	__u32 srq_handle;
 	__u32 max_wr;
 	__u32 max_sge;
-	__u32 reserved;
+	__u32 srqn;
 };
 
 struct ib_uverbs_modify_srq {
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 228be3e..bf5daaf 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -112,6 +112,7 @@ enum ib_device_cap_flags {
 	 */
 	IB_DEVICE_UD_IP_CSUM		= (1<<18),
 	IB_DEVICE_UD_TSO		= (1<<19),
+	IB_DEVICE_XRC			= (1<<20),
 	IB_DEVICE_MEM_MGT_EXTENSIONS	= (1<<21),
 	IB_DEVICE_BLOCK_MULTICAST_LOOPBACK = (1<<22),
 };
@@ -207,6 +208,7 @@ enum ib_port_cap_flags {
 	IB_PORT_SM_DISABLED			= 1 << 10,
 	IB_PORT_SYS_IMAGE_GUID_SUP		= 1 << 11,
 	IB_PORT_PKEY_SW_EXT_PORT_TRAP_SUP	= 1 << 12,
+	IB_PORT_EXTENDED_SPEEDS_SUP             = 1 << 14,
 	IB_PORT_CM_SUP				= 1 << 16,
 	IB_PORT_SNMP_TUNNEL_SUP			= 1 << 17,
 	IB_PORT_REINIT_SUP			= 1 << 18,
@@ -415,7 +417,15 @@ enum ib_rate {
 	IB_RATE_40_GBPS  = 7,
 	IB_RATE_60_GBPS  = 8,
 	IB_RATE_80_GBPS  = 9,
-	IB_RATE_120_GBPS = 10
+	IB_RATE_120_GBPS = 10,
+	IB_RATE_14_GBPS  = 11,
+	IB_RATE_56_GBPS  = 12,
+	IB_RATE_112_GBPS = 13,
+	IB_RATE_168_GBPS = 14,
+	IB_RATE_25_GBPS  = 15,
+	IB_RATE_100_GBPS = 16,
+	IB_RATE_200_GBPS = 17,
+	IB_RATE_300_GBPS = 18
 };
 
 /**
@@ -427,6 +437,13 @@ enum ib_rate {
 int ib_rate_to_mult(enum ib_rate rate) __attribute_const__;
 
 /**
+ * ib_rate_to_mbps - Convert the IB rate enum to Mbps.
+ * For example, IB_RATE_2_5_GBPS will be converted to 2500.
+ * @rate: rate to convert.
+ */
+int ib_rate_to_mbps(enum ib_rate rate) __attribute_const__;
+
+/**
  * mult_to_ib_rate - Convert a multiple of 2.5 Gbit/sec to an IB rate
  * enum.
  * @mult: multiple to convert.
@@ -522,6 +539,11 @@ enum ib_cq_notify_flags {
 	IB_CQ_REPORT_MISSED_EVENTS	= 1 << 2,
 };
 
+enum ib_srq_type {
+	IB_SRQT_BASIC,
+	IB_SRQT_XRC
+};
+
 enum ib_srq_attr_mask {
 	IB_SRQ_MAX_WR	= 1 << 0,
 	IB_SRQ_LIMIT	= 1 << 1,
@@ -537,6 +559,14 @@ struct ib_srq_init_attr {
 	void		      (*event_handler)(struct ib_event *, void *);
 	void		       *srq_context;
 	struct ib_srq_attr	attr;
+	enum ib_srq_type	srq_type;
+
+	union {
+		struct {
+			struct ib_xrcd *xrcd;
+			struct ib_cq   *cq;
+		} xrc;
+	} ext;
 };
 
 struct ib_qp_cap {
@@ -565,7 +595,11 @@ enum ib_qp_type {
 	IB_QPT_UC,
 	IB_QPT_UD,
 	IB_QPT_RAW_IPV6,
-	IB_QPT_RAW_ETHERTYPE
+	IB_QPT_RAW_ETHERTYPE,
+	/* Save 8 for RAW_PACKET */
+	IB_QPT_XRC_INI = 9,
+	IB_QPT_XRC_TGT,
+	IB_QPT_MAX
 };
 
 enum ib_qp_create_flags {
@@ -579,6 +613,7 @@ struct ib_qp_init_attr {
 	struct ib_cq	       *send_cq;
 	struct ib_cq	       *recv_cq;
 	struct ib_srq	       *srq;
+	struct ib_xrcd	       *xrcd;     /* XRC TGT QPs only */
 	struct ib_qp_cap	cap;
 	enum ib_sig_type	sq_sig_type;
 	enum ib_qp_type		qp_type;
@@ -586,6 +621,13 @@ struct ib_qp_init_attr {
 	u8			port_num; /* special QP types only */
 };
 
+struct ib_qp_open_attr {
+	void                  (*event_handler)(struct ib_event *, void *);
+	void		       *qp_context;
+	u32			qp_num;
+	enum ib_qp_type		qp_type;
+};
+
 enum ib_rnr_timeout {
 	IB_RNR_TIMER_655_36 =  0,
 	IB_RNR_TIMER_000_01 =  1,
@@ -770,6 +812,7 @@ struct ib_send_wr {
 			u32				rkey;
 		} fast_reg;
 	} wr;
+	u32			xrc_remote_srq_num;	/* XRC TGT QPs only */
 };
 
 struct ib_recv_wr {
@@ -831,6 +874,7 @@ struct ib_ucontext {
 	struct list_head	qp_list;
 	struct list_head	srq_list;
 	struct list_head	ah_list;
+	struct list_head	xrcd_list;
 	int			closing;
 };
 
@@ -858,6 +902,15 @@ struct ib_pd {
 	atomic_t          	usecnt; /* count all resources */
 };
 
+struct ib_xrcd {
+	struct ib_device       *device;
+	atomic_t		usecnt; /* count all exposed resources */
+	struct inode	       *inode;
+
+	struct mutex		tgt_qp_mutex;
+	struct list_head	tgt_qp_list;
+};
+
 struct ib_ah {
 	struct ib_device	*device;
 	struct ib_pd		*pd;
@@ -882,7 +935,16 @@ struct ib_srq {
 	struct ib_uobject      *uobject;
 	void		      (*event_handler)(struct ib_event *, void *);
 	void		       *srq_context;
+	enum ib_srq_type	srq_type;
 	atomic_t		usecnt;
+
+	union {
+		struct {
+			struct ib_xrcd *xrcd;
+			struct ib_cq   *cq;
+			u32		srq_num;
+		} xrc;
+	} ext;
 };
 
 struct ib_qp {
@@ -891,6 +953,11 @@ struct ib_qp {
 	struct ib_cq	       *send_cq;
 	struct ib_cq	       *recv_cq;
 	struct ib_srq	       *srq;
+	struct ib_xrcd	       *xrcd; /* XRC TGT QPs only */
+	struct list_head	xrcd_list;
+	atomic_t		usecnt; /* count times opened */
+	struct list_head	open_list;
+	struct ib_qp           *real_qp;
 	struct ib_uobject      *uobject;
 	void                  (*event_handler)(struct ib_event *, void *);
 	void		       *qp_context;
@@ -1149,6 +1216,10 @@ struct ib_device {
 						  struct ib_grh *in_grh,
 						  struct ib_mad *in_mad,
 						  struct ib_mad *out_mad);
+	struct ib_xrcd *	   (*alloc_xrcd)(struct ib_device *device,
+						 struct ib_ucontext *ucontext,
+						 struct ib_udata *udata);
+	int			   (*dealloc_xrcd)(struct ib_xrcd *xrcd);
 
 	struct ib_dma_mapping_ops   *dma_ops;
 
@@ -1443,6 +1514,25 @@ int ib_query_qp(struct ib_qp *qp,
 int ib_destroy_qp(struct ib_qp *qp);
 
 /**
+ * ib_open_qp - Obtain a reference to an existing sharable QP.
+ * @xrcd - XRC domain
+ * @qp_open_attr: Attributes identifying the QP to open.
+ *
+ * Returns a reference to a sharable QP.
+ */
+struct ib_qp *ib_open_qp(struct ib_xrcd *xrcd,
+			 struct ib_qp_open_attr *qp_open_attr);
+
+/**
+ * ib_close_qp - Release an external reference to a QP.
+ * @qp: The QP handle to release
+ *
+ * The opened QP handle is released by the caller.  The underlying
+ * shared QP is not destroyed until all internal references are released.
+ */
+int ib_close_qp(struct ib_qp *qp);
+
+/**
  * ib_post_send - Posts a list of work requests to the send queue of
  *   the specified QP.
  * @qp: The QP to post the work request on.
@@ -2060,4 +2150,16 @@ int ib_attach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid);
  */
 int ib_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid);
 
+/**
+ * ib_alloc_xrcd - Allocates an XRC domain.
+ * @device: The device on which to allocate the XRC domain.
+ */
+struct ib_xrcd *ib_alloc_xrcd(struct ib_device *device);
+
+/**
+ * ib_dealloc_xrcd - Deallocates an XRC domain.
+ * @xrcd: The XRC domain to deallocate.
+ */
+int ib_dealloc_xrcd(struct ib_xrcd *xrcd);
+
 #endif /* IB_VERBS_H */
diff --git a/include/rdma/iw_cm.h b/include/rdma/iw_cm.h
index 2d0191c..1a046b1 100644
--- a/include/rdma/iw_cm.h
+++ b/include/rdma/iw_cm.h
@@ -52,8 +52,10 @@ struct iw_cm_event {
 	struct sockaddr_in local_addr;
 	struct sockaddr_in remote_addr;
 	void *private_data;
-	u8 private_data_len;
 	void *provider_data;
+	u8 private_data_len;
+	u8 ord;
+	u8 ird;
 };
 
 /**
diff --git a/include/rdma/rdma_cm.h b/include/rdma/rdma_cm.h
index 26977c1..51988f8 100644
--- a/include/rdma/rdma_cm.h
+++ b/include/rdma/rdma_cm.h
@@ -65,6 +65,7 @@ enum rdma_cm_event_type {
 enum rdma_port_space {
 	RDMA_PS_SDP   = 0x0001,
 	RDMA_PS_IPOIB = 0x0002,
+	RDMA_PS_IB    = 0x013F,
 	RDMA_PS_TCP   = 0x0106,
 	RDMA_PS_UDP   = 0x0111,
 };
diff --git a/include/rdma/rdma_user_cm.h b/include/rdma/rdma_user_cm.h
index fc82c18..5348a00 100644
--- a/include/rdma/rdma_user_cm.h
+++ b/include/rdma/rdma_user_cm.h
@@ -77,7 +77,8 @@ struct rdma_ucm_create_id {
 	__u64 uid;
 	__u64 response;
 	__u16 ps;
-	__u8  reserved[6];
+	__u8  qp_type;
+	__u8  reserved[5];
 };
 
 struct rdma_ucm_create_id_resp {
diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
index b50a547..748ff7c 100644
--- a/include/trace/events/ext4.h
+++ b/include/trace/events/ext4.h
@@ -9,9 +9,12 @@
 
 struct ext4_allocation_context;
 struct ext4_allocation_request;
+struct ext4_extent;
 struct ext4_prealloc_space;
 struct ext4_inode_info;
 struct mpage_da_data;
+struct ext4_map_blocks;
+struct ext4_extent;
 
 #define EXT4_I(inode) (container_of(inode, struct ext4_inode_info, vfs_inode))
 
@@ -1032,9 +1035,9 @@ TRACE_EVENT(ext4_forget,
 );
 
 TRACE_EVENT(ext4_da_update_reserve_space,
-	TP_PROTO(struct inode *inode, int used_blocks),
+	TP_PROTO(struct inode *inode, int used_blocks, int quota_claim),
 
-	TP_ARGS(inode, used_blocks),
+	TP_ARGS(inode, used_blocks, quota_claim),
 
 	TP_STRUCT__entry(
 		__field(	dev_t,	dev			)
@@ -1045,6 +1048,7 @@ TRACE_EVENT(ext4_da_update_reserve_space,
 		__field(	int,	reserved_data_blocks	)
 		__field(	int,	reserved_meta_blocks	)
 		__field(	int,	allocated_meta_blocks	)
+		__field(	int,	quota_claim		)
 	),
 
 	TP_fast_assign(
@@ -1053,19 +1057,24 @@ TRACE_EVENT(ext4_da_update_reserve_space,
 		__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;
+		__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;
+		__entry->quota_claim = quota_claim;
 	),
 
 	TP_printk("dev %d,%d ino %lu mode 0%o i_blocks %llu used_blocks %d "
 		  "reserved_data_blocks %d reserved_meta_blocks %d "
-		  "allocated_meta_blocks %d",
+		  "allocated_meta_blocks %d quota_claim %d",
 		  MAJOR(__entry->dev), MINOR(__entry->dev),
 		  (unsigned long) __entry->ino,
 		  __entry->mode, __entry->i_blocks,
 		  __entry->used_blocks, __entry->reserved_data_blocks,
-		  __entry->reserved_meta_blocks, __entry->allocated_meta_blocks)
+		  __entry->reserved_meta_blocks, __entry->allocated_meta_blocks,
+		  __entry->quota_claim)
 );
 
 TRACE_EVENT(ext4_da_reserve_space,
@@ -1386,6 +1395,87 @@ DEFINE_EVENT(ext4__truncate, ext4_truncate_exit,
 	TP_ARGS(inode)
 );
 
+/* 'ux' is the uninitialized extent. */
+TRACE_EVENT(ext4_ext_convert_to_initialized_enter,
+	TP_PROTO(struct inode *inode, struct ext4_map_blocks *map,
+		 struct ext4_extent *ux),
+
+	TP_ARGS(inode, map, ux),
+
+	TP_STRUCT__entry(
+		__field(	ino_t,		ino	)
+		__field(	dev_t,		dev	)
+		__field(	ext4_lblk_t,	m_lblk	)
+		__field(	unsigned,	m_len	)
+		__field(	ext4_lblk_t,	u_lblk	)
+		__field(	unsigned,	u_len	)
+		__field(	ext4_fsblk_t,	u_pblk	)
+	),
+
+	TP_fast_assign(
+		__entry->ino		= inode->i_ino;
+		__entry->dev		= inode->i_sb->s_dev;
+		__entry->m_lblk		= map->m_lblk;
+		__entry->m_len		= map->m_len;
+		__entry->u_lblk		= le32_to_cpu(ux->ee_block);
+		__entry->u_len		= ext4_ext_get_actual_len(ux);
+		__entry->u_pblk		= ext4_ext_pblock(ux);
+	),
+
+	TP_printk("dev %d,%d ino %lu m_lblk %u m_len %u u_lblk %u u_len %u "
+		  "u_pblk %llu",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  __entry->m_lblk, __entry->m_len,
+		  __entry->u_lblk, __entry->u_len, __entry->u_pblk)
+);
+
+/*
+ * 'ux' is the uninitialized extent.
+ * 'ix' is the initialized extent to which blocks are transferred.
+ */
+TRACE_EVENT(ext4_ext_convert_to_initialized_fastpath,
+	TP_PROTO(struct inode *inode, struct ext4_map_blocks *map,
+		 struct ext4_extent *ux, struct ext4_extent *ix),
+
+	TP_ARGS(inode, map, ux, ix),
+
+	TP_STRUCT__entry(
+		__field(	ino_t,		ino	)
+		__field(	dev_t,		dev	)
+		__field(	ext4_lblk_t,	m_lblk	)
+		__field(	unsigned,	m_len	)
+		__field(	ext4_lblk_t,	u_lblk	)
+		__field(	unsigned,	u_len	)
+		__field(	ext4_fsblk_t,	u_pblk	)
+		__field(	ext4_lblk_t,	i_lblk	)
+		__field(	unsigned,	i_len	)
+		__field(	ext4_fsblk_t,	i_pblk	)
+	),
+
+	TP_fast_assign(
+		__entry->ino		= inode->i_ino;
+		__entry->dev		= inode->i_sb->s_dev;
+		__entry->m_lblk		= map->m_lblk;
+		__entry->m_len		= map->m_len;
+		__entry->u_lblk		= le32_to_cpu(ux->ee_block);
+		__entry->u_len		= ext4_ext_get_actual_len(ux);
+		__entry->u_pblk		= ext4_ext_pblock(ux);
+		__entry->i_lblk		= le32_to_cpu(ix->ee_block);
+		__entry->i_len		= ext4_ext_get_actual_len(ix);
+		__entry->i_pblk		= ext4_ext_pblock(ix);
+	),
+
+	TP_printk("dev %d,%d ino %lu m_lblk %u m_len %u "
+		  "u_lblk %u u_len %u u_pblk %llu "
+		  "i_lblk %u i_len %u i_pblk %llu ",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  __entry->m_lblk, __entry->m_len,
+		  __entry->u_lblk, __entry->u_len, __entry->u_pblk,
+		  __entry->i_lblk, __entry->i_len, __entry->i_pblk)
+);
+
 DECLARE_EVENT_CLASS(ext4__map_blocks_enter,
 	TP_PROTO(struct inode *inode, ext4_lblk_t lblk,
 		 unsigned int len, unsigned int flags),
@@ -1589,6 +1679,382 @@ DEFINE_EVENT(ext4__trim, ext4_trim_all_free,
 	TP_ARGS(sb, group, start, len)
 );
 
+TRACE_EVENT(ext4_ext_handle_uninitialized_extents,
+	TP_PROTO(struct inode *inode, struct ext4_map_blocks *map,
+		 unsigned int allocated, ext4_fsblk_t newblock),
+
+	TP_ARGS(inode, map, allocated, newblock),
+
+	TP_STRUCT__entry(
+		__field(	ino_t,		ino		)
+		__field(	dev_t,		dev		)
+		__field(	ext4_lblk_t,	lblk		)
+		__field(	ext4_fsblk_t,	pblk		)
+		__field(	unsigned int,	len		)
+		__field(	int,		flags		)
+		__field(	unsigned int,	allocated	)
+		__field(	ext4_fsblk_t,	newblk		)
+	),
+
+	TP_fast_assign(
+		__entry->ino		= inode->i_ino;
+		__entry->dev		= inode->i_sb->s_dev;
+		__entry->lblk		= map->m_lblk;
+		__entry->pblk		= map->m_pblk;
+		__entry->len		= map->m_len;
+		__entry->flags		= map->m_flags;
+		__entry->allocated	= allocated;
+		__entry->newblk		= newblock;
+	),
+
+	TP_printk("dev %d,%d ino %lu m_lblk %u m_pblk %llu m_len %u flags %d"
+		  "allocated %d newblock %llu",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  (unsigned) __entry->lblk, (unsigned long long) __entry->pblk,
+		  __entry->len, __entry->flags,
+		  (unsigned int) __entry->allocated,
+		  (unsigned long long) __entry->newblk)
+);
+
+TRACE_EVENT(ext4_get_implied_cluster_alloc_exit,
+	TP_PROTO(struct super_block *sb, struct ext4_map_blocks *map, int ret),
+
+	TP_ARGS(sb, map, ret),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,		dev	)
+		__field(	ext4_lblk_t,	lblk	)
+		__field(	ext4_fsblk_t,	pblk	)
+		__field(	unsigned int,	len	)
+		__field(	unsigned int,	flags	)
+		__field(	int,		ret	)
+	),
+
+	TP_fast_assign(
+		__entry->dev	= sb->s_dev;
+		__entry->lblk	= map->m_lblk;
+		__entry->pblk	= map->m_pblk;
+		__entry->len	= map->m_len;
+		__entry->flags	= map->m_flags;
+		__entry->ret	= ret;
+	),
+
+	TP_printk("dev %d,%d m_lblk %u m_pblk %llu m_len %u m_flags %u ret %d",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  __entry->lblk, (unsigned long long) __entry->pblk,
+		  __entry->len, __entry->flags, __entry->ret)
+);
+
+TRACE_EVENT(ext4_ext_put_in_cache,
+	TP_PROTO(struct inode *inode, ext4_lblk_t lblk, unsigned int len,
+		 ext4_fsblk_t start),
+
+	TP_ARGS(inode, lblk, len, start),
+
+	TP_STRUCT__entry(
+		__field(	ino_t,		ino	)
+		__field(	dev_t,		dev	)
+		__field(	ext4_lblk_t,	lblk	)
+		__field(	unsigned int,	len	)
+		__field(	ext4_fsblk_t,	start	)
+	),
+
+	TP_fast_assign(
+		__entry->ino	= inode->i_ino;
+		__entry->dev	= inode->i_sb->s_dev;
+		__entry->lblk	= lblk;
+		__entry->len	= len;
+		__entry->start	= start;
+	),
+
+	TP_printk("dev %d,%d ino %lu lblk %u len %u start %llu",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  (unsigned) __entry->lblk,
+		  __entry->len,
+		  (unsigned long long) __entry->start)
+);
+
+TRACE_EVENT(ext4_ext_in_cache,
+	TP_PROTO(struct inode *inode, ext4_lblk_t lblk, int ret),
+
+	TP_ARGS(inode, lblk, ret),
+
+	TP_STRUCT__entry(
+		__field(	ino_t,		ino	)
+		__field(	dev_t,		dev	)
+		__field(	ext4_lblk_t,	lblk	)
+		__field(	int,		ret	)
+	),
+
+	TP_fast_assign(
+		__entry->ino	= inode->i_ino;
+		__entry->dev	= inode->i_sb->s_dev;
+		__entry->lblk	= lblk;
+		__entry->ret	= ret;
+	),
+
+	TP_printk("dev %d,%d ino %lu lblk %u ret %d",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  (unsigned) __entry->lblk,
+		  __entry->ret)
+
+);
+
+TRACE_EVENT(ext4_find_delalloc_range,
+	TP_PROTO(struct inode *inode, ext4_lblk_t from, ext4_lblk_t to,
+		int reverse, int found, ext4_lblk_t found_blk),
+
+	TP_ARGS(inode, from, to, reverse, found, found_blk),
+
+	TP_STRUCT__entry(
+		__field(	ino_t,		ino		)
+		__field(	dev_t,		dev		)
+		__field(	ext4_lblk_t,	from		)
+		__field(	ext4_lblk_t,	to		)
+		__field(	int,		reverse		)
+		__field(	int,		found		)
+		__field(	ext4_lblk_t,	found_blk	)
+	),
+
+	TP_fast_assign(
+		__entry->ino		= inode->i_ino;
+		__entry->dev		= inode->i_sb->s_dev;
+		__entry->from		= from;
+		__entry->to		= to;
+		__entry->reverse	= reverse;
+		__entry->found		= found;
+		__entry->found_blk	= found_blk;
+	),
+
+	TP_printk("dev %d,%d ino %lu from %u to %u reverse %d found %d "
+		  "(blk = %u)",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  (unsigned) __entry->from, (unsigned) __entry->to,
+		  __entry->reverse, __entry->found,
+		  (unsigned) __entry->found_blk)
+);
+
+TRACE_EVENT(ext4_get_reserved_cluster_alloc,
+	TP_PROTO(struct inode *inode, ext4_lblk_t lblk, unsigned int len),
+
+	TP_ARGS(inode, lblk, len),
+
+	TP_STRUCT__entry(
+		__field(	ino_t,		ino	)
+		__field(	dev_t,		dev	)
+		__field(	ext4_lblk_t,	lblk	)
+		__field(	unsigned int,	len	)
+	),
+
+	TP_fast_assign(
+		__entry->ino	= inode->i_ino;
+		__entry->dev	= inode->i_sb->s_dev;
+		__entry->lblk	= lblk;
+		__entry->len	= len;
+	),
+
+	TP_printk("dev %d,%d ino %lu lblk %u len %u",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  (unsigned) __entry->lblk,
+		  __entry->len)
+);
+
+TRACE_EVENT(ext4_ext_show_extent,
+	TP_PROTO(struct inode *inode, ext4_lblk_t lblk, ext4_fsblk_t pblk,
+		 unsigned short len),
+
+	TP_ARGS(inode, lblk, pblk, len),
+
+	TP_STRUCT__entry(
+		__field(	ino_t,		ino	)
+		__field(	dev_t,		dev	)
+		__field(	ext4_lblk_t,	lblk	)
+		__field(	ext4_fsblk_t,	pblk	)
+		__field(	unsigned short,	len	)
+	),
+
+	TP_fast_assign(
+		__entry->ino	= inode->i_ino;
+		__entry->dev	= inode->i_sb->s_dev;
+		__entry->lblk	= lblk;
+		__entry->pblk	= pblk;
+		__entry->len	= len;
+	),
+
+	TP_printk("dev %d,%d ino %lu lblk %u pblk %llu len %u",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  (unsigned) __entry->lblk,
+		  (unsigned long long) __entry->pblk,
+		  (unsigned short) __entry->len)
+);
+
+TRACE_EVENT(ext4_remove_blocks,
+	    TP_PROTO(struct inode *inode, struct ext4_extent *ex,
+		ext4_lblk_t from, ext4_fsblk_t to,
+		ext4_fsblk_t partial_cluster),
+
+	TP_ARGS(inode, ex, from, to, partial_cluster),
+
+	TP_STRUCT__entry(
+		__field(	ino_t,		ino	)
+		__field(	dev_t,		dev	)
+		__field(	ext4_lblk_t,	ee_lblk	)
+		__field(	ext4_fsblk_t,	ee_pblk	)
+		__field(	unsigned short,	ee_len	)
+		__field(	ext4_lblk_t,	from	)
+		__field(	ext4_lblk_t,	to	)
+		__field(	ext4_fsblk_t,	partial	)
+	),
+
+	TP_fast_assign(
+		__entry->ino		= inode->i_ino;
+		__entry->dev		= inode->i_sb->s_dev;
+		__entry->ee_lblk	= cpu_to_le32(ex->ee_block);
+		__entry->ee_pblk	= ext4_ext_pblock(ex);
+		__entry->ee_len		= ext4_ext_get_actual_len(ex);
+		__entry->from		= from;
+		__entry->to		= to;
+		__entry->partial	= partial_cluster;
+	),
+
+	TP_printk("dev %d,%d ino %lu extent [%u(%llu), %u]"
+		  "from %u to %u partial_cluster %u",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  (unsigned) __entry->ee_lblk,
+		  (unsigned long long) __entry->ee_pblk,
+		  (unsigned short) __entry->ee_len,
+		  (unsigned) __entry->from,
+		  (unsigned) __entry->to,
+		  (unsigned) __entry->partial)
+);
+
+TRACE_EVENT(ext4_ext_rm_leaf,
+	TP_PROTO(struct inode *inode, ext4_lblk_t start,
+		 struct ext4_extent *ex, ext4_fsblk_t partial_cluster),
+
+	TP_ARGS(inode, start, ex, partial_cluster),
+
+	TP_STRUCT__entry(
+		__field(	ino_t,		ino	)
+		__field(	dev_t,		dev	)
+		__field(	ext4_lblk_t,	start	)
+		__field(	ext4_lblk_t,	ee_lblk	)
+		__field(	ext4_fsblk_t,	ee_pblk	)
+		__field(	short,		ee_len	)
+		__field(	ext4_fsblk_t,	partial	)
+	),
+
+	TP_fast_assign(
+		__entry->ino		= inode->i_ino;
+		__entry->dev		= inode->i_sb->s_dev;
+		__entry->start		= start;
+		__entry->ee_lblk	= le32_to_cpu(ex->ee_block);
+		__entry->ee_pblk	= ext4_ext_pblock(ex);
+		__entry->ee_len		= ext4_ext_get_actual_len(ex);
+		__entry->partial	= partial_cluster;
+	),
+
+	TP_printk("dev %d,%d ino %lu start_lblk %u last_extent [%u(%llu), %u]"
+		  "partial_cluster %u",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  (unsigned) __entry->start,
+		  (unsigned) __entry->ee_lblk,
+		  (unsigned long long) __entry->ee_pblk,
+		  (unsigned short) __entry->ee_len,
+		  (unsigned) __entry->partial)
+);
+
+TRACE_EVENT(ext4_ext_rm_idx,
+	TP_PROTO(struct inode *inode, ext4_fsblk_t pblk),
+
+	TP_ARGS(inode, pblk),
+
+	TP_STRUCT__entry(
+		__field(	ino_t,		ino	)
+		__field(	dev_t,		dev	)
+		__field(	ext4_fsblk_t,	pblk	)
+	),
+
+	TP_fast_assign(
+		__entry->ino	= inode->i_ino;
+		__entry->dev	= inode->i_sb->s_dev;
+		__entry->pblk	= pblk;
+	),
+
+	TP_printk("dev %d,%d ino %lu index_pblk %llu",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  (unsigned long long) __entry->pblk)
+);
+
+TRACE_EVENT(ext4_ext_remove_space,
+	TP_PROTO(struct inode *inode, ext4_lblk_t start, int depth),
+
+	TP_ARGS(inode, start, depth),
+
+	TP_STRUCT__entry(
+		__field(	ino_t,		ino	)
+		__field(	dev_t,		dev	)
+		__field(	ext4_lblk_t,	start	)
+		__field(	int,		depth	)
+	),
+
+	TP_fast_assign(
+		__entry->ino	= inode->i_ino;
+		__entry->dev	= inode->i_sb->s_dev;
+		__entry->start	= start;
+		__entry->depth	= depth;
+	),
+
+	TP_printk("dev %d,%d ino %lu since %u depth %d",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  (unsigned) __entry->start,
+		  __entry->depth)
+);
+
+TRACE_EVENT(ext4_ext_remove_space_done,
+	TP_PROTO(struct inode *inode, ext4_lblk_t start, int depth,
+		ext4_lblk_t partial, unsigned short eh_entries),
+
+	TP_ARGS(inode, start, depth, partial, eh_entries),
+
+	TP_STRUCT__entry(
+		__field(	ino_t,		ino		)
+		__field(	dev_t,		dev		)
+		__field(	ext4_lblk_t,	start		)
+		__field(	int,		depth		)
+		__field(	ext4_lblk_t,	partial		)
+		__field(	unsigned short,	eh_entries	)
+	),
+
+	TP_fast_assign(
+		__entry->ino		= inode->i_ino;
+		__entry->dev		= inode->i_sb->s_dev;
+		__entry->start		= start;
+		__entry->depth		= depth;
+		__entry->partial	= partial;
+		__entry->eh_entries	= eh_entries;
+	),
+
+	TP_printk("dev %d,%d ino %lu since %u depth %d partial %u "
+		  "remaining_entries %u",
+		  MAJOR(__entry->dev), MINOR(__entry->dev),
+		  (unsigned long) __entry->ino,
+		  (unsigned) __entry->start,
+		  __entry->depth,
+		  (unsigned) __entry->partial,
+		  (unsigned short) __entry->eh_entries)
+);
+
 #endif /* _TRACE_EXT4_H */
 
 /* This part must be outside protection */
diff --git a/init/Kconfig b/init/Kconfig
index 31ba0fd..43298f9 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -947,7 +947,7 @@ config UID16
 config SYSCTL_SYSCALL
 	bool "Sysctl syscall support" if EXPERT
 	depends on PROC_SYSCTL
-	default y
+	default n
 	select SYSCTL
 	---help---
 	  sys_sysctl uses binary paths that have been found challenging
@@ -959,7 +959,7 @@ config SYSCTL_SYSCALL
 	  trying to save some space it is probably safe to disable this,
 	  making your kernel marginally smaller.
 
-	  If unsure say Y here.
+	  If unsure say N here.
 
 config KALLSYMS
 	 bool "Load all symbols for debugging/ksymoops" if EXPERT
diff --git a/init/do_mounts.c b/init/do_mounts.c
index c0851a8..0f6e1d9 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -28,7 +28,7 @@ int __initdata rd_doload;	/* 1 = load RAM disk, 0 = don't load */
 int root_mountflags = MS_RDONLY | MS_SILENT;
 static char * __initdata root_device_name;
 static char __initdata saved_root_name[64];
-static int __initdata root_wait;
+static int root_wait;
 
 dev_t ROOT_DEV;
 
@@ -85,12 +85,15 @@ no_match:
 
 /**
  * devt_from_partuuid - looks up the dev_t of a partition by its UUID
- * @uuid:	36 byte char array containing a hex ascii UUID
+ * @uuid:	min 36 byte char array containing a hex ascii UUID
  *
  * The function will return the first partition which contains a matching
  * UUID value in its partition_meta_info struct.  This does not search
  * by filesystem UUIDs.
  *
+ * If @uuid is followed by a "/PARTNROFF=%d", then the number will be
+ * extracted and used as an offset from the partition identified by the UUID.
+ *
  * Returns the matching dev_t on success or 0 on failure.
  */
 static dev_t devt_from_partuuid(char *uuid_str)
@@ -98,6 +101,28 @@ static dev_t devt_from_partuuid(char *uuid_str)
 	dev_t res = 0;
 	struct device *dev = NULL;
 	u8 uuid[16];
+	struct gendisk *disk;
+	struct hd_struct *part;
+	int offset = 0;
+
+	if (strlen(uuid_str) < 36)
+		goto done;
+
+	/* Check for optional partition number offset attributes. */
+	if (uuid_str[36]) {
+		char c = 0;
+		/* Explicitly fail on poor PARTUUID syntax. */
+		if (sscanf(&uuid_str[36],
+			   "/PARTNROFF=%d%c", &offset, &c) != 1) {
+			printk(KERN_ERR "VFS: PARTUUID= is invalid.\n"
+			 "Expected PARTUUID=<valid-uuid-id>[/PARTNROFF=%%d]\n");
+			if (root_wait)
+				printk(KERN_ERR
+				     "Disabling rootwait; root= is invalid.\n");
+			root_wait = 0;
+			goto done;
+		}
+	}
 
 	/* Pack the requested UUID in the expected format. */
 	part_pack_uuid(uuid_str, uuid);
@@ -107,8 +132,21 @@ static dev_t devt_from_partuuid(char *uuid_str)
 		goto done;
 
 	res = dev->devt;
-	put_device(dev);
 
+	/* Attempt to find the partition by offset. */
+	if (!offset)
+		goto no_offset;
+
+	res = 0;
+	disk = part_to_disk(dev_to_part(dev));
+	part = disk_get_part(disk, dev_to_part(dev)->partno + offset);
+	if (part) {
+		res = part_devt(part);
+		put_device(part_to_dev(part));
+	}
+
+no_offset:
+	put_device(dev);
 done:
 	return res;
 }
@@ -126,6 +164,8 @@ done:
  *	   used when disk name of partitioned disk ends on a digit.
  *	6) PARTUUID=00112233-4455-6677-8899-AABBCCDDEEFF representing the
  *	   unique id of a partition if the partition table provides it.
+ *	7) PARTUUID=<UUID>/PARTNROFF=<int> to select a partition in relation to
+ *	   a partition with a known unique id.
  *
  *	If name doesn't have fall into the categories above, we return (0,0).
  *	block_class is used to check if something is a disk name. If the disk
@@ -143,8 +183,6 @@ dev_t name_to_dev_t(char *name)
 #ifdef CONFIG_BLOCK
 	if (strncmp(name, "PARTUUID=", 9) == 0) {
 		name += 9;
-		if (strlen(name) != 36)
-			goto fail;
 		res = devt_from_partuuid(name);
 		if (!res)
 			goto fail;
diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c
index fe9acb0..887629e 100644
--- a/init/do_mounts_rd.c
+++ b/init/do_mounts_rd.c
@@ -120,6 +120,20 @@ identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor)
 	}
 
 	/*
+	 * Read 512 bytes further to check if cramfs is padded
+	 */
+	sys_lseek(fd, start_block * BLOCK_SIZE + 0x200, 0);
+	sys_read(fd, buf, size);
+
+	if (cramfsb->magic == CRAMFS_MAGIC) {
+		printk(KERN_NOTICE
+		       "RAMDISK: cramfs filesystem found at block %d\n",
+		       start_block);
+		nblocks = (cramfsb->size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
+		goto done;
+	}
+
+	/*
 	 * Read block 1 to test for minix and ext2 superblock
 	 */
 	sys_lseek(fd, (start_block+1) * BLOCK_SIZE, 0);
diff --git a/ipc/sem.c b/ipc/sem.c
index c8e00f8..5215a81 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -90,6 +90,52 @@
 #include <asm/uaccess.h>
 #include "util.h"
 
+/* One semaphore structure for each semaphore in the system. */
+struct sem {
+	int	semval;		/* current value */
+	int	sempid;		/* pid of last operation */
+	struct list_head sem_pending; /* pending single-sop operations */
+};
+
+/* One queue for each sleeping process in the system. */
+struct sem_queue {
+	struct list_head	simple_list; /* queue of pending operations */
+	struct list_head	list;	 /* queue of pending operations */
+	struct task_struct	*sleeper; /* this process */
+	struct sem_undo		*undo;	 /* undo structure */
+	int			pid;	 /* process id of requesting process */
+	int			status;	 /* completion status of operation */
+	struct sembuf		*sops;	 /* array of pending operations */
+	int			nsops;	 /* number of operations */
+	int			alter;	 /* does *sops alter the array? */
+};
+
+/* Each task has a list of undo requests. They are executed automatically
+ * when the process exits.
+ */
+struct sem_undo {
+	struct list_head	list_proc;	/* per-process list: *
+						 * all undos from one process
+						 * rcu protected */
+	struct rcu_head		rcu;		/* rcu struct for sem_undo */
+	struct sem_undo_list	*ulp;		/* back ptr to sem_undo_list */
+	struct list_head	list_id;	/* per semaphore array list:
+						 * all undos for one array */
+	int			semid;		/* semaphore set identifier */
+	short			*semadj;	/* array of adjustments */
+						/* one per semaphore */
+};
+
+/* sem_undo_list controls shared access to the list of sem_undo structures
+ * that may be shared among all a CLONE_SYSVSEM task group.
+ */
+struct sem_undo_list {
+	atomic_t		refcnt;
+	spinlock_t		lock;
+	struct list_head	list_proc;
+};
+
+
 #define sem_ids(ns)	((ns)->ids[IPC_SEM_IDS])
 
 #define sem_unlock(sma)		ipc_unlock(&(sma)->sem_perm)
@@ -1426,6 +1472,8 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
 
 	queue.status = -EINTR;
 	queue.sleeper = current;
+
+sleep_again:
 	current->state = TASK_INTERRUPTIBLE;
 	sem_unlock(sma);
 
@@ -1460,7 +1508,6 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
 	 * Array removed? If yes, leave without sem_unlock().
 	 */
 	if (IS_ERR(sma)) {
-		error = -EIDRM;
 		goto out_free;
 	}
 
@@ -1479,6 +1526,13 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
 	 */
 	if (timeout && jiffies_left == 0)
 		error = -EAGAIN;
+
+	/*
+	 * If the wakeup was spurious, just retry
+	 */
+	if (error == -EINTR && !signal_pending(current))
+		goto sleep_again;
+
 	unlink_queue(sma, &queue);
 
 out_unlock_free:
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 453100a..d9d5648 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -2027,7 +2027,7 @@ int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
 		goto out_free_group_list;
 
 	/* prevent changes to the threadgroup list while we take a snapshot. */
-	rcu_read_lock();
+	read_lock(&tasklist_lock);
 	if (!thread_group_leader(leader)) {
 		/*
 		 * a race with de_thread from another thread's exec() may strip
@@ -2036,7 +2036,7 @@ int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
 		 * throw this task away and try again (from cgroup_procs_write);
 		 * this is "double-double-toil-and-trouble-check locking".
 		 */
-		rcu_read_unlock();
+		read_unlock(&tasklist_lock);
 		retval = -EAGAIN;
 		goto out_free_group_list;
 	}
@@ -2057,7 +2057,7 @@ int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
 	} while_each_thread(leader, tsk);
 	/* remember the number of threads in the array for later. */
 	group_size = i;
-	rcu_read_unlock();
+	read_unlock(&tasklist_lock);
 
 	/*
 	 * step 1: check that we can legitimately attach to the cgroup.
@@ -2135,14 +2135,17 @@ int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
 		oldcgrp = task_cgroup_from_root(tsk, root);
 		if (cgrp == oldcgrp)
 			continue;
-		/* attach each task to each subsystem */
-		for_each_subsys(root, ss) {
-			if (ss->attach_task)
-				ss->attach_task(cgrp, tsk);
-		}
 		/* if the thread is PF_EXITING, it can just get skipped. */
 		retval = cgroup_task_migrate(cgrp, oldcgrp, tsk, true);
-		BUG_ON(retval != 0 && retval != -ESRCH);
+		if (retval == 0) {
+			/* attach each task to each subsystem */
+			for_each_subsys(root, ss) {
+				if (ss->attach_task)
+					ss->attach_task(cgrp, tsk);
+			}
+		} else {
+			BUG_ON(retval != -ESRCH);
+		}
 	}
 	/* nothing is sensitive to fork() after this point. */
 
@@ -4880,9 +4883,9 @@ void free_css_id(struct cgroup_subsys *ss, struct cgroup_subsys_state *css)
 
 	rcu_assign_pointer(id->css, NULL);
 	rcu_assign_pointer(css->id, NULL);
-	spin_lock(&ss->id_lock);
+	write_lock(&ss->id_lock);
 	idr_remove(&ss->idr, id->id);
-	spin_unlock(&ss->id_lock);
+	write_unlock(&ss->id_lock);
 	kfree_rcu(id, rcu_head);
 }
 EXPORT_SYMBOL_GPL(free_css_id);
@@ -4908,10 +4911,10 @@ static struct css_id *get_new_cssid(struct cgroup_subsys *ss, int depth)
 		error = -ENOMEM;
 		goto err_out;
 	}
-	spin_lock(&ss->id_lock);
+	write_lock(&ss->id_lock);
 	/* Don't use 0. allocates an ID of 1-65535 */
 	error = idr_get_new_above(&ss->idr, newid, 1, &myid);
-	spin_unlock(&ss->id_lock);
+	write_unlock(&ss->id_lock);
 
 	/* Returns error when there are no free spaces for new ID.*/
 	if (error) {
@@ -4926,9 +4929,9 @@ static struct css_id *get_new_cssid(struct cgroup_subsys *ss, int depth)
 	return newid;
 remove_idr:
 	error = -ENOSPC;
-	spin_lock(&ss->id_lock);
+	write_lock(&ss->id_lock);
 	idr_remove(&ss->idr, myid);
-	spin_unlock(&ss->id_lock);
+	write_unlock(&ss->id_lock);
 err_out:
 	kfree(newid);
 	return ERR_PTR(error);
@@ -4940,7 +4943,7 @@ static int __init_or_module cgroup_init_idr(struct cgroup_subsys *ss,
 {
 	struct css_id *newid;
 
-	spin_lock_init(&ss->id_lock);
+	rwlock_init(&ss->id_lock);
 	idr_init(&ss->idr);
 
 	newid = get_new_cssid(ss, 0);
@@ -5035,9 +5038,9 @@ css_get_next(struct cgroup_subsys *ss, int id,
 		 * scan next entry from bitmap(tree), tmpid is updated after
 		 * idr_get_next().
 		 */
-		spin_lock(&ss->id_lock);
+		read_lock(&ss->id_lock);
 		tmp = idr_get_next(&ss->idr, &tmpid);
-		spin_unlock(&ss->id_lock);
+		read_unlock(&ss->id_lock);
 
 		if (!tmp)
 			break;
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 10131fd..ed0ff44 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -949,6 +949,8 @@ static void cpuset_migrate_mm(struct mm_struct *mm, const nodemask_t *from,
 static void cpuset_change_task_nodemask(struct task_struct *tsk,
 					nodemask_t *newmems)
 {
+	bool masks_disjoint = !nodes_intersects(*newmems, tsk->mems_allowed);
+
 repeat:
 	/*
 	 * Allow tasks that have access to memory reserves because they have
@@ -963,7 +965,6 @@ repeat:
 	nodes_or(tsk->mems_allowed, tsk->mems_allowed, *newmems);
 	mpol_rebind_task(tsk, newmems, MPOL_REBIND_STEP1);
 
-
 	/*
 	 * ensure checking ->mems_allowed_change_disable after setting all new
 	 * allowed nodes.
@@ -980,9 +981,11 @@ repeat:
 
 	/*
 	 * Allocation of memory is very fast, we needn't sleep when waiting
-	 * for the read-side.
+	 * for the read-side.  No wait is necessary, however, if at least one
+	 * node remains unchanged.
 	 */
-	while (ACCESS_ONCE(tsk->mems_allowed_change_disable)) {
+	while (masks_disjoint &&
+			ACCESS_ONCE(tsk->mems_allowed_change_disable)) {
 		task_unlock(tsk);
 		if (!task_curr(tsk))
 			yield();
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index b57a377..200ce83 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -20,15 +20,15 @@ static DEFINE_MUTEX(irq_domain_mutex);
 void irq_domain_add(struct irq_domain *domain)
 {
 	struct irq_data *d;
-	int hwirq;
+	int hwirq, irq;
 
 	/*
 	 * This assumes that the irq_domain owner has already allocated
 	 * the irq_descs.  This block will be removed when support for dynamic
 	 * allocation of irq_descs is added to irq_domain.
 	 */
-	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
-		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
+	irq_domain_for_each_irq(domain, hwirq, irq) {
+		d = irq_get_irq_data(irq);
 		if (!d) {
 			WARN(1, "error: assigning domain to non existant irq_desc");
 			return;
@@ -54,15 +54,15 @@ void irq_domain_add(struct irq_domain *domain)
 void irq_domain_del(struct irq_domain *domain)
 {
 	struct irq_data *d;
-	int hwirq;
+	int hwirq, irq;
 
 	mutex_lock(&irq_domain_mutex);
 	list_del(&domain->list);
 	mutex_unlock(&irq_domain_mutex);
 
 	/* Clear the irq_domain assignments */
-	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
-		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
+	irq_domain_for_each_irq(domain, hwirq, irq) {
+		d = irq_get_irq_data(irq);
 		d->domain = NULL;
 	}
 }
diff --git a/kernel/sys.c b/kernel/sys.c
index 5845950..d06c091 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1286,6 +1286,7 @@ SYSCALL_DEFINE2(sethostname, char __user *, name, int, len)
 		memset(u->nodename + len, 0, sizeof(u->nodename) - len);
 		errno = 0;
 	}
+	uts_proc_notify(UTS_PROC_HOSTNAME);
 	up_write(&uts_sem);
 	return errno;
 }
@@ -1336,6 +1337,7 @@ SYSCALL_DEFINE2(setdomainname, char __user *, name, int, len)
 		memset(u->domainname + len, 0, sizeof(u->domainname) - len);
 		errno = 0;
 	}
+	uts_proc_notify(UTS_PROC_DOMAINNAME);
 	up_write(&uts_sem);
 	return errno;
 }
diff --git a/kernel/utsname_sysctl.c b/kernel/utsname_sysctl.c
index a2cd77e..3b0d48e 100644
--- a/kernel/utsname_sysctl.c
+++ b/kernel/utsname_sysctl.c
@@ -13,6 +13,7 @@
 #include <linux/uts.h>
 #include <linux/utsname.h>
 #include <linux/sysctl.h>
+#include <linux/wait.h>
 
 static void *get_uts(ctl_table *table, int write)
 {
@@ -51,12 +52,19 @@ static int proc_do_uts_string(ctl_table *table, int write,
 	uts_table.data = get_uts(table, write);
 	r = proc_dostring(&uts_table,write,buffer,lenp, ppos);
 	put_uts(table, write, uts_table.data);
+
+	if (write)
+		proc_sys_poll_notify(table->poll);
+
 	return r;
 }
 #else
 #define proc_do_uts_string NULL
 #endif
 
+static DEFINE_CTL_TABLE_POLL(hostname_poll);
+static DEFINE_CTL_TABLE_POLL(domainname_poll);
+
 static struct ctl_table uts_kern_table[] = {
 	{
 		.procname	= "ostype",
@@ -85,6 +93,7 @@ static struct ctl_table uts_kern_table[] = {
 		.maxlen		= sizeof(init_uts_ns.name.nodename),
 		.mode		= 0644,
 		.proc_handler	= proc_do_uts_string,
+		.poll		= &hostname_poll,
 	},
 	{
 		.procname	= "domainname",
@@ -92,6 +101,7 @@ static struct ctl_table uts_kern_table[] = {
 		.maxlen		= sizeof(init_uts_ns.name.domainname),
 		.mode		= 0644,
 		.proc_handler	= proc_do_uts_string,
+		.poll		= &domainname_poll,
 	},
 	{}
 };
@@ -105,6 +115,19 @@ static struct ctl_table uts_root_table[] = {
 	{}
 };
 
+#ifdef CONFIG_PROC_SYSCTL
+/*
+ * Notify userspace about a change in a certain entry of uts_kern_table,
+ * identified by the parameter proc.
+ */
+void uts_proc_notify(enum uts_proc proc)
+{
+	struct ctl_table *table = &uts_kern_table[proc];
+
+	proc_sys_poll_notify(table->poll);
+}
+#endif
+
 static int __init utsname_sysctl_init(void)
 {
 	register_sysctl_table(uts_root_table);
diff --git a/lib/idr.c b/lib/idr.c
index bbf211a..ed055b2 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -944,6 +944,7 @@ int ida_simple_get(struct ida *ida, unsigned int start, unsigned int end,
 {
 	int ret, id;
 	unsigned int max;
+	unsigned long flags;
 
 	BUG_ON((int)start < 0);
 	BUG_ON((int)end < 0);
@@ -959,7 +960,7 @@ again:
 	if (!ida_pre_get(ida, gfp_mask))
 		return -ENOMEM;
 
-	spin_lock(&simple_ida_lock);
+	spin_lock_irqsave(&simple_ida_lock, flags);
 	ret = ida_get_new_above(ida, start, &id);
 	if (!ret) {
 		if (id > max) {
@@ -969,7 +970,7 @@ again:
 			ret = id;
 		}
 	}
-	spin_unlock(&simple_ida_lock);
+	spin_unlock_irqrestore(&simple_ida_lock, flags);
 
 	if (unlikely(ret == -EAGAIN))
 		goto again;
@@ -985,10 +986,12 @@ EXPORT_SYMBOL(ida_simple_get);
  */
 void ida_simple_remove(struct ida *ida, unsigned int id)
 {
+	unsigned long flags;
+
 	BUG_ON((int)id < 0);
-	spin_lock(&simple_ida_lock);
+	spin_lock_irqsave(&simple_ida_lock, flags);
 	ida_remove(ida, id);
-	spin_unlock(&simple_ida_lock);
+	spin_unlock_irqrestore(&simple_ida_lock, flags);
 }
 EXPORT_SYMBOL(ida_simple_remove);
 
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 860ec21..4298aba 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -990,7 +990,7 @@ struct page *follow_trans_huge_pmd(struct mm_struct *mm,
 	page += (addr & ~HPAGE_PMD_MASK) >> PAGE_SHIFT;
 	VM_BUG_ON(!PageCompound(page));
 	if (flags & FOLL_GET)
-		get_page(page);
+		get_page_foll(page);
 
 out:
 	return page;
@@ -1202,6 +1202,7 @@ static void __split_huge_page_refcount(struct page *page)
 	unsigned long head_index = page->index;
 	struct zone *zone = page_zone(page);
 	int zonestat;
+	int tail_count = 0;
 
 	/* prevent PageLRU to go away from under us, and freeze lru stats */
 	spin_lock_irq(&zone->lru_lock);
@@ -1210,11 +1211,27 @@ static void __split_huge_page_refcount(struct page *page)
 	for (i = 1; i < HPAGE_PMD_NR; i++) {
 		struct page *page_tail = page + i;
 
-		/* tail_page->_count cannot change */
-		atomic_sub(atomic_read(&page_tail->_count), &page->_count);
-		BUG_ON(page_count(page) <= 0);
-		atomic_add(page_mapcount(page) + 1, &page_tail->_count);
-		BUG_ON(atomic_read(&page_tail->_count) <= 0);
+		/* tail_page->_mapcount cannot change */
+		BUG_ON(page_mapcount(page_tail) < 0);
+		tail_count += page_mapcount(page_tail);
+		/* check for overflow */
+		BUG_ON(tail_count < 0);
+		BUG_ON(atomic_read(&page_tail->_count) != 0);
+		/*
+		 * tail_page->_count is zero and not changing from
+		 * under us. But get_page_unless_zero() may be running
+		 * from under us on the tail_page. If we used
+		 * atomic_set() below instead of atomic_add(), we
+		 * would then run atomic_set() concurrently with
+		 * get_page_unless_zero(), and atomic_set() is
+		 * implemented in C not using locked ops. spin_unlock
+		 * on x86 sometime uses locked ops because of PPro
+		 * errata 66, 92, so unless somebody can guarantee
+		 * atomic_set() here would be safe on all archs (and
+		 * not only on x86), it's safer to use atomic_add().
+		 */
+		atomic_add(page_mapcount(page) + page_mapcount(page_tail) + 1,
+			   &page_tail->_count);
 
 		/* after clearing PageTail the gup refcount can be released */
 		smp_mb();
@@ -1232,10 +1249,7 @@ static void __split_huge_page_refcount(struct page *page)
 				      (1L << PG_uptodate)));
 		page_tail->flags |= (1L << PG_dirty);
 
-		/*
-		 * 1) clear PageTail before overwriting first_page
-		 * 2) clear PageTail before clearing PageHead for VM_BUG_ON
-		 */
+		/* clear PageTail before overwriting first_page */
 		smp_wmb();
 
 		/*
@@ -1252,7 +1266,6 @@ static void __split_huge_page_refcount(struct page *page)
 		 * status is achieved setting a reserved bit in the
 		 * pmd, not by clearing the present bit.
 		*/
-		BUG_ON(page_mapcount(page_tail));
 		page_tail->_mapcount = page->_mapcount;
 
 		BUG_ON(page_tail->mapping);
@@ -1269,6 +1282,8 @@ static void __split_huge_page_refcount(struct page *page)
 
 		lru_add_page_tail(zone, page, page_tail);
 	}
+	atomic_sub(tail_count, &page->_count);
+	BUG_ON(atomic_read(&page->_count) <= 0);
 
 	__dec_zone_page_state(page, NR_ANON_TRANSPARENT_HUGEPAGES);
 	__mod_zone_page_state(zone, NR_ANON_PAGES, HPAGE_PMD_NR);
diff --git a/mm/internal.h b/mm/internal.h
index d071d38..2189af4 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -37,6 +37,52 @@ static inline void __put_page(struct page *page)
 	atomic_dec(&page->_count);
 }
 
+static inline void __get_page_tail_foll(struct page *page,
+					bool get_page_head)
+{
+	/*
+	 * If we're getting a tail page, the elevated page->_count is
+	 * required only in the head page and we will elevate the head
+	 * page->_count and tail page->_mapcount.
+	 *
+	 * We elevate page_tail->_mapcount for tail pages to force
+	 * page_tail->_count to be zero at all times to avoid getting
+	 * false positives from get_page_unless_zero() with
+	 * speculative page access (like in
+	 * page_cache_get_speculative()) on tail pages.
+	 */
+	VM_BUG_ON(atomic_read(&page->first_page->_count) <= 0);
+	VM_BUG_ON(atomic_read(&page->_count) != 0);
+	VM_BUG_ON(page_mapcount(page) < 0);
+	if (get_page_head)
+		atomic_inc(&page->first_page->_count);
+	atomic_inc(&page->_mapcount);
+}
+
+/*
+ * This is meant to be called as the FOLL_GET operation of
+ * follow_page() and it must be called while holding the proper PT
+ * lock while the pte (or pmd_trans_huge) is still mapping the page.
+ */
+static inline void get_page_foll(struct page *page)
+{
+	if (unlikely(PageTail(page)))
+		/*
+		 * This is safe only because
+		 * __split_huge_page_refcount() can't run under
+		 * get_page_foll() because we hold the proper PT lock.
+		 */
+		__get_page_tail_foll(page, true);
+	else {
+		/*
+		 * Getting a normal page or the head of a compound page
+		 * requires to already have an elevated page->_count.
+		 */
+		VM_BUG_ON(atomic_read(&page->_count) <= 0);
+		atomic_inc(&page->_count);
+	}
+}
+
 extern unsigned long highest_memmap_pfn;
 
 /*
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 2d57555..7af1d5e 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -201,8 +201,8 @@ struct mem_cgroup_eventfd_list {
 	struct eventfd_ctx *eventfd;
 };
 
-static void mem_cgroup_threshold(struct mem_cgroup *mem);
-static void mem_cgroup_oom_notify(struct mem_cgroup *mem);
+static void mem_cgroup_threshold(struct mem_cgroup *memcg);
+static void mem_cgroup_oom_notify(struct mem_cgroup *memcg);
 
 /*
  * The memory controller data structure. The memory controller controls both
@@ -362,29 +362,29 @@ enum charge_type {
 #define MEM_CGROUP_RECLAIM_SOFT_BIT	0x2
 #define MEM_CGROUP_RECLAIM_SOFT		(1 << MEM_CGROUP_RECLAIM_SOFT_BIT)
 
-static void mem_cgroup_get(struct mem_cgroup *mem);
-static void mem_cgroup_put(struct mem_cgroup *mem);
-static struct mem_cgroup *parent_mem_cgroup(struct mem_cgroup *mem);
-static void drain_all_stock_async(struct mem_cgroup *mem);
+static void mem_cgroup_get(struct mem_cgroup *memcg);
+static void mem_cgroup_put(struct mem_cgroup *memcg);
+static struct mem_cgroup *parent_mem_cgroup(struct mem_cgroup *memcg);
+static void drain_all_stock_async(struct mem_cgroup *memcg);
 
 static struct mem_cgroup_per_zone *
-mem_cgroup_zoneinfo(struct mem_cgroup *mem, int nid, int zid)
+mem_cgroup_zoneinfo(struct mem_cgroup *memcg, int nid, int zid)
 {
-	return &mem->info.nodeinfo[nid]->zoneinfo[zid];
+	return &memcg->info.nodeinfo[nid]->zoneinfo[zid];
 }
 
-struct cgroup_subsys_state *mem_cgroup_css(struct mem_cgroup *mem)
+struct cgroup_subsys_state *mem_cgroup_css(struct mem_cgroup *memcg)
 {
-	return &mem->css;
+	return &memcg->css;
 }
 
 static struct mem_cgroup_per_zone *
-page_cgroup_zoneinfo(struct mem_cgroup *mem, struct page *page)
+page_cgroup_zoneinfo(struct mem_cgroup *memcg, struct page *page)
 {
 	int nid = page_to_nid(page);
 	int zid = page_zonenum(page);
 
-	return mem_cgroup_zoneinfo(mem, nid, zid);
+	return mem_cgroup_zoneinfo(memcg, nid, zid);
 }
 
 static struct mem_cgroup_tree_per_zone *
@@ -403,7 +403,7 @@ soft_limit_tree_from_page(struct page *page)
 }
 
 static void
-__mem_cgroup_insert_exceeded(struct mem_cgroup *mem,
+__mem_cgroup_insert_exceeded(struct mem_cgroup *memcg,
 				struct mem_cgroup_per_zone *mz,
 				struct mem_cgroup_tree_per_zone *mctz,
 				unsigned long long new_usage_in_excess)
@@ -437,7 +437,7 @@ __mem_cgroup_insert_exceeded(struct mem_cgroup *mem,
 }
 
 static void
-__mem_cgroup_remove_exceeded(struct mem_cgroup *mem,
+__mem_cgroup_remove_exceeded(struct mem_cgroup *memcg,
 				struct mem_cgroup_per_zone *mz,
 				struct mem_cgroup_tree_per_zone *mctz)
 {
@@ -448,17 +448,17 @@ __mem_cgroup_remove_exceeded(struct mem_cgroup *mem,
 }
 
 static void
-mem_cgroup_remove_exceeded(struct mem_cgroup *mem,
+mem_cgroup_remove_exceeded(struct mem_cgroup *memcg,
 				struct mem_cgroup_per_zone *mz,
 				struct mem_cgroup_tree_per_zone *mctz)
 {
 	spin_lock(&mctz->lock);
-	__mem_cgroup_remove_exceeded(mem, mz, mctz);
+	__mem_cgroup_remove_exceeded(memcg, mz, mctz);
 	spin_unlock(&mctz->lock);
 }
 
 
-static void mem_cgroup_update_tree(struct mem_cgroup *mem, struct page *page)
+static void mem_cgroup_update_tree(struct mem_cgroup *memcg, struct page *page)
 {
 	unsigned long long excess;
 	struct mem_cgroup_per_zone *mz;
@@ -471,9 +471,9 @@ static void mem_cgroup_update_tree(struct mem_cgroup *mem, struct page *page)
 	 * Necessary to update all ancestors when hierarchy is used.
 	 * because their event counter is not touched.
 	 */
-	for (; mem; mem = parent_mem_cgroup(mem)) {
-		mz = mem_cgroup_zoneinfo(mem, nid, zid);
-		excess = res_counter_soft_limit_excess(&mem->res);
+	for (; memcg; memcg = parent_mem_cgroup(memcg)) {
+		mz = mem_cgroup_zoneinfo(memcg, nid, zid);
+		excess = res_counter_soft_limit_excess(&memcg->res);
 		/*
 		 * We have to update the tree if mz is on RB-tree or
 		 * mem is over its softlimit.
@@ -482,18 +482,18 @@ static void mem_cgroup_update_tree(struct mem_cgroup *mem, struct page *page)
 			spin_lock(&mctz->lock);
 			/* if on-tree, remove it */
 			if (mz->on_tree)
-				__mem_cgroup_remove_exceeded(mem, mz, mctz);
+				__mem_cgroup_remove_exceeded(memcg, mz, mctz);
 			/*
 			 * Insert again. mz->usage_in_excess will be updated.
 			 * If excess is 0, no tree ops.
 			 */
-			__mem_cgroup_insert_exceeded(mem, mz, mctz, excess);
+			__mem_cgroup_insert_exceeded(memcg, mz, mctz, excess);
 			spin_unlock(&mctz->lock);
 		}
 	}
 }
 
-static void mem_cgroup_remove_from_trees(struct mem_cgroup *mem)
+static void mem_cgroup_remove_from_trees(struct mem_cgroup *memcg)
 {
 	int node, zone;
 	struct mem_cgroup_per_zone *mz;
@@ -501,9 +501,9 @@ static void mem_cgroup_remove_from_trees(struct mem_cgroup *mem)
 
 	for_each_node_state(node, N_POSSIBLE) {
 		for (zone = 0; zone < MAX_NR_ZONES; zone++) {
-			mz = mem_cgroup_zoneinfo(mem, node, zone);
+			mz = mem_cgroup_zoneinfo(memcg, node, zone);
 			mctz = soft_limit_tree_node_zone(node, zone);
-			mem_cgroup_remove_exceeded(mem, mz, mctz);
+			mem_cgroup_remove_exceeded(memcg, mz, mctz);
 		}
 	}
 }
@@ -564,7 +564,7 @@ mem_cgroup_largest_soft_limit_node(struct mem_cgroup_tree_per_zone *mctz)
  * common workload, threashold and synchonization as vmstat[] should be
  * implemented.
  */
-static long mem_cgroup_read_stat(struct mem_cgroup *mem,
+static long mem_cgroup_read_stat(struct mem_cgroup *memcg,
 				 enum mem_cgroup_stat_index idx)
 {
 	long val = 0;
@@ -572,81 +572,83 @@ static long mem_cgroup_read_stat(struct mem_cgroup *mem,
 
 	get_online_cpus();
 	for_each_online_cpu(cpu)
-		val += per_cpu(mem->stat->count[idx], cpu);
+		val += per_cpu(memcg->stat->count[idx], cpu);
 #ifdef CONFIG_HOTPLUG_CPU
-	spin_lock(&mem->pcp_counter_lock);
-	val += mem->nocpu_base.count[idx];
-	spin_unlock(&mem->pcp_counter_lock);
+	spin_lock(&memcg->pcp_counter_lock);
+	val += memcg->nocpu_base.count[idx];
+	spin_unlock(&memcg->pcp_counter_lock);
 #endif
 	put_online_cpus();
 	return val;
 }
 
-static void mem_cgroup_swap_statistics(struct mem_cgroup *mem,
+static void mem_cgroup_swap_statistics(struct mem_cgroup *memcg,
 					 bool charge)
 {
 	int val = (charge) ? 1 : -1;
-	this_cpu_add(mem->stat->count[MEM_CGROUP_STAT_SWAPOUT], val);
+	this_cpu_add(memcg->stat->count[MEM_CGROUP_STAT_SWAPOUT], val);
 }
 
-void mem_cgroup_pgfault(struct mem_cgroup *mem, int val)
+void mem_cgroup_pgfault(struct mem_cgroup *memcg, int val)
 {
-	this_cpu_add(mem->stat->events[MEM_CGROUP_EVENTS_PGFAULT], val);
+	this_cpu_add(memcg->stat->events[MEM_CGROUP_EVENTS_PGFAULT], val);
 }
 
-void mem_cgroup_pgmajfault(struct mem_cgroup *mem, int val)
+void mem_cgroup_pgmajfault(struct mem_cgroup *memcg, int val)
 {
-	this_cpu_add(mem->stat->events[MEM_CGROUP_EVENTS_PGMAJFAULT], val);
+	this_cpu_add(memcg->stat->events[MEM_CGROUP_EVENTS_PGMAJFAULT], val);
 }
 
-static unsigned long mem_cgroup_read_events(struct mem_cgroup *mem,
+static unsigned long mem_cgroup_read_events(struct mem_cgroup *memcg,
 					    enum mem_cgroup_events_index idx)
 {
 	unsigned long val = 0;
 	int cpu;
 
 	for_each_online_cpu(cpu)
-		val += per_cpu(mem->stat->events[idx], cpu);
+		val += per_cpu(memcg->stat->events[idx], cpu);
 #ifdef CONFIG_HOTPLUG_CPU
-	spin_lock(&mem->pcp_counter_lock);
-	val += mem->nocpu_base.events[idx];
-	spin_unlock(&mem->pcp_counter_lock);
+	spin_lock(&memcg->pcp_counter_lock);
+	val += memcg->nocpu_base.events[idx];
+	spin_unlock(&memcg->pcp_counter_lock);
 #endif
 	return val;
 }
 
-static void mem_cgroup_charge_statistics(struct mem_cgroup *mem,
+static void mem_cgroup_charge_statistics(struct mem_cgroup *memcg,
 					 bool file, int nr_pages)
 {
 	preempt_disable();
 
 	if (file)
-		__this_cpu_add(mem->stat->count[MEM_CGROUP_STAT_CACHE], nr_pages);
+		__this_cpu_add(memcg->stat->count[MEM_CGROUP_STAT_CACHE],
+				nr_pages);
 	else
-		__this_cpu_add(mem->stat->count[MEM_CGROUP_STAT_RSS], nr_pages);
+		__this_cpu_add(memcg->stat->count[MEM_CGROUP_STAT_RSS],
+				nr_pages);
 
 	/* pagein of a big page is an event. So, ignore page size */
 	if (nr_pages > 0)
-		__this_cpu_inc(mem->stat->events[MEM_CGROUP_EVENTS_PGPGIN]);
+		__this_cpu_inc(memcg->stat->events[MEM_CGROUP_EVENTS_PGPGIN]);
 	else {
-		__this_cpu_inc(mem->stat->events[MEM_CGROUP_EVENTS_PGPGOUT]);
+		__this_cpu_inc(memcg->stat->events[MEM_CGROUP_EVENTS_PGPGOUT]);
 		nr_pages = -nr_pages; /* for event */
 	}
 
-	__this_cpu_add(mem->stat->events[MEM_CGROUP_EVENTS_COUNT], nr_pages);
+	__this_cpu_add(memcg->stat->events[MEM_CGROUP_EVENTS_COUNT], nr_pages);
 
 	preempt_enable();
 }
 
 unsigned long
-mem_cgroup_zone_nr_lru_pages(struct mem_cgroup *mem, int nid, int zid,
+mem_cgroup_zone_nr_lru_pages(struct mem_cgroup *memcg, int nid, int zid,
 			unsigned int lru_mask)
 {
 	struct mem_cgroup_per_zone *mz;
 	enum lru_list l;
 	unsigned long ret = 0;
 
-	mz = mem_cgroup_zoneinfo(mem, nid, zid);
+	mz = mem_cgroup_zoneinfo(memcg, nid, zid);
 
 	for_each_lru(l) {
 		if (BIT(l) & lru_mask)
@@ -656,44 +658,45 @@ mem_cgroup_zone_nr_lru_pages(struct mem_cgroup *mem, int nid, int zid,
 }
 
 static unsigned long
-mem_cgroup_node_nr_lru_pages(struct mem_cgroup *mem,
+mem_cgroup_node_nr_lru_pages(struct mem_cgroup *memcg,
 			int nid, unsigned int lru_mask)
 {
 	u64 total = 0;
 	int zid;
 
 	for (zid = 0; zid < MAX_NR_ZONES; zid++)
-		total += mem_cgroup_zone_nr_lru_pages(mem, nid, zid, lru_mask);
+		total += mem_cgroup_zone_nr_lru_pages(memcg,
+						nid, zid, lru_mask);
 
 	return total;
 }
 
-static unsigned long mem_cgroup_nr_lru_pages(struct mem_cgroup *mem,
+static unsigned long mem_cgroup_nr_lru_pages(struct mem_cgroup *memcg,
 			unsigned int lru_mask)
 {
 	int nid;
 	u64 total = 0;
 
 	for_each_node_state(nid, N_HIGH_MEMORY)
-		total += mem_cgroup_node_nr_lru_pages(mem, nid, lru_mask);
+		total += mem_cgroup_node_nr_lru_pages(memcg, nid, lru_mask);
 	return total;
 }
 
-static bool __memcg_event_check(struct mem_cgroup *mem, int target)
+static bool __memcg_event_check(struct mem_cgroup *memcg, int target)
 {
 	unsigned long val, next;
 
-	val = this_cpu_read(mem->stat->events[MEM_CGROUP_EVENTS_COUNT]);
-	next = this_cpu_read(mem->stat->targets[target]);
+	val = __this_cpu_read(memcg->stat->events[MEM_CGROUP_EVENTS_COUNT]);
+	next = __this_cpu_read(memcg->stat->targets[target]);
 	/* from time_after() in jiffies.h */
 	return ((long)next - (long)val < 0);
 }
 
-static void __mem_cgroup_target_update(struct mem_cgroup *mem, int target)
+static void __mem_cgroup_target_update(struct mem_cgroup *memcg, int target)
 {
 	unsigned long val, next;
 
-	val = this_cpu_read(mem->stat->events[MEM_CGROUP_EVENTS_COUNT]);
+	val = __this_cpu_read(memcg->stat->events[MEM_CGROUP_EVENTS_COUNT]);
 
 	switch (target) {
 	case MEM_CGROUP_TARGET_THRESH:
@@ -709,34 +712,36 @@ static void __mem_cgroup_target_update(struct mem_cgroup *mem, int target)
 		return;
 	}
 
-	this_cpu_write(mem->stat->targets[target], next);
+	__this_cpu_write(memcg->stat->targets[target], next);
 }
 
 /*
  * Check events in order.
  *
  */
-static void memcg_check_events(struct mem_cgroup *mem, struct page *page)
+static void memcg_check_events(struct mem_cgroup *memcg, struct page *page)
 {
+	preempt_disable();
 	/* threshold event is triggered in finer grain than soft limit */
-	if (unlikely(__memcg_event_check(mem, MEM_CGROUP_TARGET_THRESH))) {
-		mem_cgroup_threshold(mem);
-		__mem_cgroup_target_update(mem, MEM_CGROUP_TARGET_THRESH);
-		if (unlikely(__memcg_event_check(mem,
+	if (unlikely(__memcg_event_check(memcg, MEM_CGROUP_TARGET_THRESH))) {
+		mem_cgroup_threshold(memcg);
+		__mem_cgroup_target_update(memcg, MEM_CGROUP_TARGET_THRESH);
+		if (unlikely(__memcg_event_check(memcg,
 			     MEM_CGROUP_TARGET_SOFTLIMIT))) {
-			mem_cgroup_update_tree(mem, page);
-			__mem_cgroup_target_update(mem,
+			mem_cgroup_update_tree(memcg, page);
+			__mem_cgroup_target_update(memcg,
 						   MEM_CGROUP_TARGET_SOFTLIMIT);
 		}
 #if MAX_NUMNODES > 1
-		if (unlikely(__memcg_event_check(mem,
+		if (unlikely(__memcg_event_check(memcg,
 			MEM_CGROUP_TARGET_NUMAINFO))) {
-			atomic_inc(&mem->numainfo_events);
-			__mem_cgroup_target_update(mem,
+			atomic_inc(&memcg->numainfo_events);
+			__mem_cgroup_target_update(memcg,
 				MEM_CGROUP_TARGET_NUMAINFO);
 		}
 #endif
 	}
+	preempt_enable();
 }
 
 static struct mem_cgroup *mem_cgroup_from_cont(struct cgroup *cont)
@@ -762,7 +767,7 @@ struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p)
 
 struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm)
 {
-	struct mem_cgroup *mem = NULL;
+	struct mem_cgroup *memcg = NULL;
 
 	if (!mm)
 		return NULL;
@@ -773,25 +778,25 @@ struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm)
 	 */
 	rcu_read_lock();
 	do {
-		mem = mem_cgroup_from_task(rcu_dereference(mm->owner));
-		if (unlikely(!mem))
+		memcg = mem_cgroup_from_task(rcu_dereference(mm->owner));
+		if (unlikely(!memcg))
 			break;
-	} while (!css_tryget(&mem->css));
+	} while (!css_tryget(&memcg->css));
 	rcu_read_unlock();
-	return mem;
+	return memcg;
 }
 
 /* The caller has to guarantee "mem" exists before calling this */
-static struct mem_cgroup *mem_cgroup_start_loop(struct mem_cgroup *mem)
+static struct mem_cgroup *mem_cgroup_start_loop(struct mem_cgroup *memcg)
 {
 	struct cgroup_subsys_state *css;
 	int found;
 
-	if (!mem) /* ROOT cgroup has the smallest ID */
+	if (!memcg) /* ROOT cgroup has the smallest ID */
 		return root_mem_cgroup; /*css_put/get against root is ignored*/
-	if (!mem->use_hierarchy) {
-		if (css_tryget(&mem->css))
-			return mem;
+	if (!memcg->use_hierarchy) {
+		if (css_tryget(&memcg->css))
+			return memcg;
 		return NULL;
 	}
 	rcu_read_lock();
@@ -799,13 +804,13 @@ static struct mem_cgroup *mem_cgroup_start_loop(struct mem_cgroup *mem)
 	 * searching a memory cgroup which has the smallest ID under given
 	 * ROOT cgroup. (ID >= 1)
 	 */
-	css = css_get_next(&mem_cgroup_subsys, 1, &mem->css, &found);
+	css = css_get_next(&mem_cgroup_subsys, 1, &memcg->css, &found);
 	if (css && css_tryget(css))
-		mem = container_of(css, struct mem_cgroup, css);
+		memcg = container_of(css, struct mem_cgroup, css);
 	else
-		mem = NULL;
+		memcg = NULL;
 	rcu_read_unlock();
-	return mem;
+	return memcg;
 }
 
 static struct mem_cgroup *mem_cgroup_get_next(struct mem_cgroup *iter,
@@ -859,29 +864,29 @@ static struct mem_cgroup *mem_cgroup_get_next(struct mem_cgroup *iter,
 	for_each_mem_cgroup_tree_cond(iter, NULL, true)
 
 
-static inline bool mem_cgroup_is_root(struct mem_cgroup *mem)
+static inline bool mem_cgroup_is_root(struct mem_cgroup *memcg)
 {
-	return (mem == root_mem_cgroup);
+	return (memcg == root_mem_cgroup);
 }
 
 void mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx)
 {
-	struct mem_cgroup *mem;
+	struct mem_cgroup *memcg;
 
 	if (!mm)
 		return;
 
 	rcu_read_lock();
-	mem = mem_cgroup_from_task(rcu_dereference(mm->owner));
-	if (unlikely(!mem))
+	memcg = mem_cgroup_from_task(rcu_dereference(mm->owner));
+	if (unlikely(!memcg))
 		goto out;
 
 	switch (idx) {
 	case PGMAJFAULT:
-		mem_cgroup_pgmajfault(mem, 1);
+		mem_cgroup_pgmajfault(memcg, 1);
 		break;
 	case PGFAULT:
-		mem_cgroup_pgfault(mem, 1);
+		mem_cgroup_pgfault(memcg, 1);
 		break;
 	default:
 		BUG();
@@ -990,6 +995,16 @@ void mem_cgroup_add_lru_list(struct page *page, enum lru_list lru)
 		return;
 	pc = lookup_page_cgroup(page);
 	VM_BUG_ON(PageCgroupAcctLRU(pc));
+	/*
+	 * putback:				charge:
+	 * SetPageLRU				SetPageCgroupUsed
+	 * smp_mb				smp_mb
+	 * PageCgroupUsed && add to memcg LRU	PageLRU && add to memcg LRU
+	 *
+	 * Ensure that one of the two sides adds the page to the memcg
+	 * LRU during a race.
+	 */
+	smp_mb();
 	if (!PageCgroupUsed(pc))
 		return;
 	/* Ensure pc->mem_cgroup is visible after reading PCG_USED. */
@@ -1041,7 +1056,16 @@ static void mem_cgroup_lru_add_after_commit(struct page *page)
 	unsigned long flags;
 	struct zone *zone = page_zone(page);
 	struct page_cgroup *pc = lookup_page_cgroup(page);
-
+	/*
+	 * putback:				charge:
+	 * SetPageLRU				SetPageCgroupUsed
+	 * smp_mb				smp_mb
+	 * PageCgroupUsed && add to memcg LRU	PageLRU && add to memcg LRU
+	 *
+	 * Ensure that one of the two sides adds the page to the memcg
+	 * LRU during a race.
+	 */
+	smp_mb();
 	/* taking care of that the page is added to LRU while we commit it */
 	if (likely(!PageLRU(page)))
 		return;
@@ -1063,21 +1087,21 @@ void mem_cgroup_move_lists(struct page *page,
 }
 
 /*
- * Checks whether given mem is same or in the root_mem's
+ * Checks whether given mem is same or in the root_mem_cgroup's
  * hierarchy subtree
  */
-static bool mem_cgroup_same_or_subtree(const struct mem_cgroup *root_mem,
-		struct mem_cgroup *mem)
+static bool mem_cgroup_same_or_subtree(const struct mem_cgroup *root_memcg,
+		struct mem_cgroup *memcg)
 {
-	if (root_mem != mem) {
-		return (root_mem->use_hierarchy &&
-			css_is_ancestor(&mem->css, &root_mem->css));
+	if (root_memcg != memcg) {
+		return (root_memcg->use_hierarchy &&
+			css_is_ancestor(&memcg->css, &root_memcg->css));
 	}
 
 	return true;
 }
 
-int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *mem)
+int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *memcg)
 {
 	int ret;
 	struct mem_cgroup *curr = NULL;
@@ -1091,25 +1115,29 @@ int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *mem)
 	if (!curr)
 		return 0;
 	/*
-	 * We should check use_hierarchy of "mem" not "curr". Because checking
+	 * We should check use_hierarchy of "memcg" not "curr". Because checking
 	 * use_hierarchy of "curr" here make this function true if hierarchy is
-	 * enabled in "curr" and "curr" is a child of "mem" in *cgroup*
-	 * hierarchy(even if use_hierarchy is disabled in "mem").
+	 * enabled in "curr" and "curr" is a child of "memcg" in *cgroup*
+	 * hierarchy(even if use_hierarchy is disabled in "memcg").
 	 */
-	ret = mem_cgroup_same_or_subtree(mem, curr);
+	ret = mem_cgroup_same_or_subtree(memcg, curr);
 	css_put(&curr->css);
 	return ret;
 }
 
-static int calc_inactive_ratio(struct mem_cgroup *memcg, unsigned long *present_pages)
+int mem_cgroup_inactive_anon_is_low(struct mem_cgroup *memcg, struct zone *zone)
 {
-	unsigned long active;
+	unsigned long inactive_ratio;
+	int nid = zone_to_nid(zone);
+	int zid = zone_idx(zone);
 	unsigned long inactive;
+	unsigned long active;
 	unsigned long gb;
-	unsigned long inactive_ratio;
 
-	inactive = mem_cgroup_nr_lru_pages(memcg, BIT(LRU_INACTIVE_ANON));
-	active = mem_cgroup_nr_lru_pages(memcg, BIT(LRU_ACTIVE_ANON));
+	inactive = mem_cgroup_zone_nr_lru_pages(memcg, nid, zid,
+						BIT(LRU_INACTIVE_ANON));
+	active = mem_cgroup_zone_nr_lru_pages(memcg, nid, zid,
+					      BIT(LRU_ACTIVE_ANON));
 
 	gb = (inactive + active) >> (30 - PAGE_SHIFT);
 	if (gb)
@@ -1117,39 +1145,20 @@ static int calc_inactive_ratio(struct mem_cgroup *memcg, unsigned long *present_
 	else
 		inactive_ratio = 1;
 
-	if (present_pages) {
-		present_pages[0] = inactive;
-		present_pages[1] = active;
-	}
-
-	return inactive_ratio;
+	return inactive * inactive_ratio < active;
 }
 
-int mem_cgroup_inactive_anon_is_low(struct mem_cgroup *memcg)
-{
-	unsigned long active;
-	unsigned long inactive;
-	unsigned long present_pages[2];
-	unsigned long inactive_ratio;
-
-	inactive_ratio = calc_inactive_ratio(memcg, present_pages);
-
-	inactive = present_pages[0];
-	active = present_pages[1];
-
-	if (inactive * inactive_ratio < active)
-		return 1;
-
-	return 0;
-}
-
-int mem_cgroup_inactive_file_is_low(struct mem_cgroup *memcg)
+int mem_cgroup_inactive_file_is_low(struct mem_cgroup *memcg, struct zone *zone)
 {
 	unsigned long active;
 	unsigned long inactive;
+	int zid = zone_idx(zone);
+	int nid = zone_to_nid(zone);
 
-	inactive = mem_cgroup_nr_lru_pages(memcg, BIT(LRU_INACTIVE_FILE));
-	active = mem_cgroup_nr_lru_pages(memcg, BIT(LRU_ACTIVE_FILE));
+	inactive = mem_cgroup_zone_nr_lru_pages(memcg, nid, zid,
+						BIT(LRU_INACTIVE_FILE));
+	active = mem_cgroup_zone_nr_lru_pages(memcg, nid, zid,
+					      BIT(LRU_ACTIVE_FILE));
 
 	return (active > inactive);
 }
@@ -1254,13 +1263,13 @@ unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan,
  * Returns the maximum amount of memory @mem can be charged with, in
  * pages.
  */
-static unsigned long mem_cgroup_margin(struct mem_cgroup *mem)
+static unsigned long mem_cgroup_margin(struct mem_cgroup *memcg)
 {
 	unsigned long long margin;
 
-	margin = res_counter_margin(&mem->res);
+	margin = res_counter_margin(&memcg->res);
 	if (do_swap_account)
-		margin = min(margin, res_counter_margin(&mem->memsw));
+		margin = min(margin, res_counter_margin(&memcg->memsw));
 	return margin >> PAGE_SHIFT;
 }
 
@@ -1275,33 +1284,33 @@ int mem_cgroup_swappiness(struct mem_cgroup *memcg)
 	return memcg->swappiness;
 }
 
-static void mem_cgroup_start_move(struct mem_cgroup *mem)
+static void mem_cgroup_start_move(struct mem_cgroup *memcg)
 {
 	int cpu;
 
 	get_online_cpus();
-	spin_lock(&mem->pcp_counter_lock);
+	spin_lock(&memcg->pcp_counter_lock);
 	for_each_online_cpu(cpu)
-		per_cpu(mem->stat->count[MEM_CGROUP_ON_MOVE], cpu) += 1;
-	mem->nocpu_base.count[MEM_CGROUP_ON_MOVE] += 1;
-	spin_unlock(&mem->pcp_counter_lock);
+		per_cpu(memcg->stat->count[MEM_CGROUP_ON_MOVE], cpu) += 1;
+	memcg->nocpu_base.count[MEM_CGROUP_ON_MOVE] += 1;
+	spin_unlock(&memcg->pcp_counter_lock);
 	put_online_cpus();
 
 	synchronize_rcu();
 }
 
-static void mem_cgroup_end_move(struct mem_cgroup *mem)
+static void mem_cgroup_end_move(struct mem_cgroup *memcg)
 {
 	int cpu;
 
-	if (!mem)
+	if (!memcg)
 		return;
 	get_online_cpus();
-	spin_lock(&mem->pcp_counter_lock);
+	spin_lock(&memcg->pcp_counter_lock);
 	for_each_online_cpu(cpu)
-		per_cpu(mem->stat->count[MEM_CGROUP_ON_MOVE], cpu) -= 1;
-	mem->nocpu_base.count[MEM_CGROUP_ON_MOVE] -= 1;
-	spin_unlock(&mem->pcp_counter_lock);
+		per_cpu(memcg->stat->count[MEM_CGROUP_ON_MOVE], cpu) -= 1;
+	memcg->nocpu_base.count[MEM_CGROUP_ON_MOVE] -= 1;
+	spin_unlock(&memcg->pcp_counter_lock);
 	put_online_cpus();
 }
 /*
@@ -1316,13 +1325,13 @@ static void mem_cgroup_end_move(struct mem_cgroup *mem)
  *			  waiting at hith-memory prressure caused by "move".
  */
 
-static bool mem_cgroup_stealed(struct mem_cgroup *mem)
+static bool mem_cgroup_stealed(struct mem_cgroup *memcg)
 {
 	VM_BUG_ON(!rcu_read_lock_held());
-	return this_cpu_read(mem->stat->count[MEM_CGROUP_ON_MOVE]) > 0;
+	return this_cpu_read(memcg->stat->count[MEM_CGROUP_ON_MOVE]) > 0;
 }
 
-static bool mem_cgroup_under_move(struct mem_cgroup *mem)
+static bool mem_cgroup_under_move(struct mem_cgroup *memcg)
 {
 	struct mem_cgroup *from;
 	struct mem_cgroup *to;
@@ -1337,17 +1346,17 @@ static bool mem_cgroup_under_move(struct mem_cgroup *mem)
 	if (!from)
 		goto unlock;
 
-	ret = mem_cgroup_same_or_subtree(mem, from)
-		|| mem_cgroup_same_or_subtree(mem, to);
+	ret = mem_cgroup_same_or_subtree(memcg, from)
+		|| mem_cgroup_same_or_subtree(memcg, to);
 unlock:
 	spin_unlock(&mc.lock);
 	return ret;
 }
 
-static bool mem_cgroup_wait_acct_move(struct mem_cgroup *mem)
+static bool mem_cgroup_wait_acct_move(struct mem_cgroup *memcg)
 {
 	if (mc.moving_task && current != mc.moving_task) {
-		if (mem_cgroup_under_move(mem)) {
+		if (mem_cgroup_under_move(memcg)) {
 			DEFINE_WAIT(wait);
 			prepare_to_wait(&mc.waitq, &wait, TASK_INTERRUPTIBLE);
 			/* moving charge context might have finished. */
@@ -1431,12 +1440,12 @@ done:
  * This function returns the number of memcg under hierarchy tree. Returns
  * 1(self count) if no children.
  */
-static int mem_cgroup_count_children(struct mem_cgroup *mem)
+static int mem_cgroup_count_children(struct mem_cgroup *memcg)
 {
 	int num = 0;
 	struct mem_cgroup *iter;
 
-	for_each_mem_cgroup_tree(iter, mem)
+	for_each_mem_cgroup_tree(iter, memcg)
 		num++;
 	return num;
 }
@@ -1466,21 +1475,21 @@ u64 mem_cgroup_get_limit(struct mem_cgroup *memcg)
  * that to reclaim free pages from.
  */
 static struct mem_cgroup *
-mem_cgroup_select_victim(struct mem_cgroup *root_mem)
+mem_cgroup_select_victim(struct mem_cgroup *root_memcg)
 {
 	struct mem_cgroup *ret = NULL;
 	struct cgroup_subsys_state *css;
 	int nextid, found;
 
-	if (!root_mem->use_hierarchy) {
-		css_get(&root_mem->css);
-		ret = root_mem;
+	if (!root_memcg->use_hierarchy) {
+		css_get(&root_memcg->css);
+		ret = root_memcg;
 	}
 
 	while (!ret) {
 		rcu_read_lock();
-		nextid = root_mem->last_scanned_child + 1;
-		css = css_get_next(&mem_cgroup_subsys, nextid, &root_mem->css,
+		nextid = root_memcg->last_scanned_child + 1;
+		css = css_get_next(&mem_cgroup_subsys, nextid, &root_memcg->css,
 				   &found);
 		if (css && css_tryget(css))
 			ret = container_of(css, struct mem_cgroup, css);
@@ -1489,9 +1498,9 @@ mem_cgroup_select_victim(struct mem_cgroup *root_mem)
 		/* Updates scanning parameter */
 		if (!css) {
 			/* this means start scan from ID:1 */
-			root_mem->last_scanned_child = 0;
+			root_memcg->last_scanned_child = 0;
 		} else
-			root_mem->last_scanned_child = found;
+			root_memcg->last_scanned_child = found;
 	}
 
 	return ret;
@@ -1507,14 +1516,14 @@ mem_cgroup_select_victim(struct mem_cgroup *root_mem)
  * reclaimable pages on a node. Returns true if there are any reclaimable
  * pages in the node.
  */
-static bool test_mem_cgroup_node_reclaimable(struct mem_cgroup *mem,
+static bool test_mem_cgroup_node_reclaimable(struct mem_cgroup *memcg,
 		int nid, bool noswap)
 {
-	if (mem_cgroup_node_nr_lru_pages(mem, nid, LRU_ALL_FILE))
+	if (mem_cgroup_node_nr_lru_pages(memcg, nid, LRU_ALL_FILE))
 		return true;
 	if (noswap || !total_swap_pages)
 		return false;
-	if (mem_cgroup_node_nr_lru_pages(mem, nid, LRU_ALL_ANON))
+	if (mem_cgroup_node_nr_lru_pages(memcg, nid, LRU_ALL_ANON))
 		return true;
 	return false;
 
@@ -1527,29 +1536,29 @@ static bool test_mem_cgroup_node_reclaimable(struct mem_cgroup *mem,
  * nodes based on the zonelist. So update the list loosely once per 10 secs.
  *
  */
-static void mem_cgroup_may_update_nodemask(struct mem_cgroup *mem)
+static void mem_cgroup_may_update_nodemask(struct mem_cgroup *memcg)
 {
 	int nid;
 	/*
 	 * numainfo_events > 0 means there was at least NUMAINFO_EVENTS_TARGET
 	 * pagein/pageout changes since the last update.
 	 */
-	if (!atomic_read(&mem->numainfo_events))
+	if (!atomic_read(&memcg->numainfo_events))
 		return;
-	if (atomic_inc_return(&mem->numainfo_updating) > 1)
+	if (atomic_inc_return(&memcg->numainfo_updating) > 1)
 		return;
 
 	/* make a nodemask where this memcg uses memory from */
-	mem->scan_nodes = node_states[N_HIGH_MEMORY];
+	memcg->scan_nodes = node_states[N_HIGH_MEMORY];
 
 	for_each_node_mask(nid, node_states[N_HIGH_MEMORY]) {
 
-		if (!test_mem_cgroup_node_reclaimable(mem, nid, false))
-			node_clear(nid, mem->scan_nodes);
+		if (!test_mem_cgroup_node_reclaimable(memcg, nid, false))
+			node_clear(nid, memcg->scan_nodes);
 	}
 
-	atomic_set(&mem->numainfo_events, 0);
-	atomic_set(&mem->numainfo_updating, 0);
+	atomic_set(&memcg->numainfo_events, 0);
+	atomic_set(&memcg->numainfo_updating, 0);
 }
 
 /*
@@ -1564,16 +1573,16 @@ static void mem_cgroup_may_update_nodemask(struct mem_cgroup *mem)
  *
  * Now, we use round-robin. Better algorithm is welcomed.
  */
-int mem_cgroup_select_victim_node(struct mem_cgroup *mem)
+int mem_cgroup_select_victim_node(struct mem_cgroup *memcg)
 {
 	int node;
 
-	mem_cgroup_may_update_nodemask(mem);
-	node = mem->last_scanned_node;
+	mem_cgroup_may_update_nodemask(memcg);
+	node = memcg->last_scanned_node;
 
-	node = next_node(node, mem->scan_nodes);
+	node = next_node(node, memcg->scan_nodes);
 	if (node == MAX_NUMNODES)
-		node = first_node(mem->scan_nodes);
+		node = first_node(memcg->scan_nodes);
 	/*
 	 * We call this when we hit limit, not when pages are added to LRU.
 	 * No LRU may hold pages because all pages are UNEVICTABLE or
@@ -1583,7 +1592,7 @@ int mem_cgroup_select_victim_node(struct mem_cgroup *mem)
 	if (unlikely(node == MAX_NUMNODES))
 		node = numa_node_id();
 
-	mem->last_scanned_node = node;
+	memcg->last_scanned_node = node;
 	return node;
 }
 
@@ -1593,7 +1602,7 @@ int mem_cgroup_select_victim_node(struct mem_cgroup *mem)
  * unused nodes. But scan_nodes is lazily updated and may not cotain
  * enough new information. We need to do double check.
  */
-bool mem_cgroup_reclaimable(struct mem_cgroup *mem, bool noswap)
+bool mem_cgroup_reclaimable(struct mem_cgroup *memcg, bool noswap)
 {
 	int nid;
 
@@ -1601,12 +1610,12 @@ bool mem_cgroup_reclaimable(struct mem_cgroup *mem, bool noswap)
 	 * quick check...making use of scan_node.
 	 * We can skip unused nodes.
 	 */
-	if (!nodes_empty(mem->scan_nodes)) {
-		for (nid = first_node(mem->scan_nodes);
+	if (!nodes_empty(memcg->scan_nodes)) {
+		for (nid = first_node(memcg->scan_nodes);
 		     nid < MAX_NUMNODES;
-		     nid = next_node(nid, mem->scan_nodes)) {
+		     nid = next_node(nid, memcg->scan_nodes)) {
 
-			if (test_mem_cgroup_node_reclaimable(mem, nid, noswap))
+			if (test_mem_cgroup_node_reclaimable(memcg, nid, noswap))
 				return true;
 		}
 	}
@@ -1614,23 +1623,23 @@ bool mem_cgroup_reclaimable(struct mem_cgroup *mem, bool noswap)
 	 * Check rest of nodes.
 	 */
 	for_each_node_state(nid, N_HIGH_MEMORY) {
-		if (node_isset(nid, mem->scan_nodes))
+		if (node_isset(nid, memcg->scan_nodes))
 			continue;
-		if (test_mem_cgroup_node_reclaimable(mem, nid, noswap))
+		if (test_mem_cgroup_node_reclaimable(memcg, nid, noswap))
 			return true;
 	}
 	return false;
 }
 
 #else
-int mem_cgroup_select_victim_node(struct mem_cgroup *mem)
+int mem_cgroup_select_victim_node(struct mem_cgroup *memcg)
 {
 	return 0;
 }
 
-bool mem_cgroup_reclaimable(struct mem_cgroup *mem, bool noswap)
+bool mem_cgroup_reclaimable(struct mem_cgroup *memcg, bool noswap)
 {
-	return test_mem_cgroup_node_reclaimable(mem, 0, noswap);
+	return test_mem_cgroup_node_reclaimable(memcg, 0, noswap);
 }
 #endif
 
@@ -1639,14 +1648,14 @@ bool mem_cgroup_reclaimable(struct mem_cgroup *mem, bool noswap)
  * we reclaimed from, so that we don't end up penalizing one child extensively
  * based on its position in the children list.
  *
- * root_mem is the original ancestor that we've been reclaim from.
+ * root_memcg is the original ancestor that we've been reclaim from.
  *
- * We give up and return to the caller when we visit root_mem twice.
+ * We give up and return to the caller when we visit root_memcg twice.
  * (other groups can be removed while we're walking....)
  *
  * If shrink==true, for avoiding to free too much, this returns immedieately.
  */
-static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem,
+static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_memcg,
 						struct zone *zone,
 						gfp_t gfp_mask,
 						unsigned long reclaim_options,
@@ -1661,15 +1670,15 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem,
 	unsigned long excess;
 	unsigned long nr_scanned;
 
-	excess = res_counter_soft_limit_excess(&root_mem->res) >> PAGE_SHIFT;
+	excess = res_counter_soft_limit_excess(&root_memcg->res) >> PAGE_SHIFT;
 
 	/* If memsw_is_minimum==1, swap-out is of-no-use. */
-	if (!check_soft && !shrink && root_mem->memsw_is_minimum)
+	if (!check_soft && !shrink && root_memcg->memsw_is_minimum)
 		noswap = true;
 
 	while (1) {
-		victim = mem_cgroup_select_victim(root_mem);
-		if (victim == root_mem) {
+		victim = mem_cgroup_select_victim(root_memcg);
+		if (victim == root_memcg) {
 			loop++;
 			/*
 			 * We are not draining per cpu cached charges during
@@ -1678,7 +1687,7 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem,
 			 * charges will not give any.
 			 */
 			if (!check_soft && loop >= 1)
-				drain_all_stock_async(root_mem);
+				drain_all_stock_async(root_memcg);
 			if (loop >= 2) {
 				/*
 				 * If we have not been able to reclaim
@@ -1725,9 +1734,9 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem,
 			return ret;
 		total += ret;
 		if (check_soft) {
-			if (!res_counter_soft_limit_excess(&root_mem->res))
+			if (!res_counter_soft_limit_excess(&root_memcg->res))
 				return total;
-		} else if (mem_cgroup_margin(root_mem))
+		} else if (mem_cgroup_margin(root_memcg))
 			return total;
 	}
 	return total;
@@ -1738,12 +1747,12 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem,
  * If someone is running, return false.
  * Has to be called with memcg_oom_lock
  */
-static bool mem_cgroup_oom_lock(struct mem_cgroup *mem)
+static bool mem_cgroup_oom_lock(struct mem_cgroup *memcg)
 {
 	struct mem_cgroup *iter, *failed = NULL;
 	bool cond = true;
 
-	for_each_mem_cgroup_tree_cond(iter, mem, cond) {
+	for_each_mem_cgroup_tree_cond(iter, memcg, cond) {
 		if (iter->oom_lock) {
 			/*
 			 * this subtree of our hierarchy is already locked
@@ -1763,7 +1772,7 @@ static bool mem_cgroup_oom_lock(struct mem_cgroup *mem)
 	 * what we set up to the failing subtree
 	 */
 	cond = true;
-	for_each_mem_cgroup_tree_cond(iter, mem, cond) {
+	for_each_mem_cgroup_tree_cond(iter, memcg, cond) {
 		if (iter == failed) {
 			cond = false;
 			continue;
@@ -1776,24 +1785,24 @@ static bool mem_cgroup_oom_lock(struct mem_cgroup *mem)
 /*
  * Has to be called with memcg_oom_lock
  */
-static int mem_cgroup_oom_unlock(struct mem_cgroup *mem)
+static int mem_cgroup_oom_unlock(struct mem_cgroup *memcg)
 {
 	struct mem_cgroup *iter;
 
-	for_each_mem_cgroup_tree(iter, mem)
+	for_each_mem_cgroup_tree(iter, memcg)
 		iter->oom_lock = false;
 	return 0;
 }
 
-static void mem_cgroup_mark_under_oom(struct mem_cgroup *mem)
+static void mem_cgroup_mark_under_oom(struct mem_cgroup *memcg)
 {
 	struct mem_cgroup *iter;
 
-	for_each_mem_cgroup_tree(iter, mem)
+	for_each_mem_cgroup_tree(iter, memcg)
 		atomic_inc(&iter->under_oom);
 }
 
-static void mem_cgroup_unmark_under_oom(struct mem_cgroup *mem)
+static void mem_cgroup_unmark_under_oom(struct mem_cgroup *memcg)
 {
 	struct mem_cgroup *iter;
 
@@ -1802,7 +1811,7 @@ static void mem_cgroup_unmark_under_oom(struct mem_cgroup *mem)
 	 * mem_cgroup_oom_lock() may not be called. We have to use
 	 * atomic_add_unless() here.
 	 */
-	for_each_mem_cgroup_tree(iter, mem)
+	for_each_mem_cgroup_tree(iter, memcg)
 		atomic_add_unless(&iter->under_oom, -1, 0);
 }
 
@@ -1817,85 +1826,85 @@ struct oom_wait_info {
 static int memcg_oom_wake_function(wait_queue_t *wait,
 	unsigned mode, int sync, void *arg)
 {
-	struct mem_cgroup *wake_mem = (struct mem_cgroup *)arg,
-			  *oom_wait_mem;
+	struct mem_cgroup *wake_memcg = (struct mem_cgroup *)arg,
+			  *oom_wait_memcg;
 	struct oom_wait_info *oom_wait_info;
 
 	oom_wait_info = container_of(wait, struct oom_wait_info, wait);
-	oom_wait_mem = oom_wait_info->mem;
+	oom_wait_memcg = oom_wait_info->mem;
 
 	/*
 	 * Both of oom_wait_info->mem and wake_mem are stable under us.
 	 * Then we can use css_is_ancestor without taking care of RCU.
 	 */
-	if (!mem_cgroup_same_or_subtree(oom_wait_mem, wake_mem)
-			&& !mem_cgroup_same_or_subtree(wake_mem, oom_wait_mem))
+	if (!mem_cgroup_same_or_subtree(oom_wait_memcg, wake_memcg)
+		&& !mem_cgroup_same_or_subtree(wake_memcg, oom_wait_memcg))
 		return 0;
 	return autoremove_wake_function(wait, mode, sync, arg);
 }
 
-static void memcg_wakeup_oom(struct mem_cgroup *mem)
+static void memcg_wakeup_oom(struct mem_cgroup *memcg)
 {
-	/* for filtering, pass "mem" as argument. */
-	__wake_up(&memcg_oom_waitq, TASK_NORMAL, 0, mem);
+	/* for filtering, pass "memcg" as argument. */
+	__wake_up(&memcg_oom_waitq, TASK_NORMAL, 0, memcg);
 }
 
-static void memcg_oom_recover(struct mem_cgroup *mem)
+static void memcg_oom_recover(struct mem_cgroup *memcg)
 {
-	if (mem && atomic_read(&mem->under_oom))
-		memcg_wakeup_oom(mem);
+	if (memcg && atomic_read(&memcg->under_oom))
+		memcg_wakeup_oom(memcg);
 }
 
 /*
  * 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)
+bool mem_cgroup_handle_oom(struct mem_cgroup *memcg, gfp_t mask)
 {
 	struct oom_wait_info owait;
 	bool locked, need_to_kill;
 
-	owait.mem = mem;
+	owait.mem = memcg;
 	owait.wait.flags = 0;
 	owait.wait.func = memcg_oom_wake_function;
 	owait.wait.private = current;
 	INIT_LIST_HEAD(&owait.wait.task_list);
 	need_to_kill = true;
-	mem_cgroup_mark_under_oom(mem);
+	mem_cgroup_mark_under_oom(memcg);
 
-	/* At first, try to OOM lock hierarchy under mem.*/
+	/* At first, try to OOM lock hierarchy under memcg.*/
 	spin_lock(&memcg_oom_lock);
-	locked = mem_cgroup_oom_lock(mem);
+	locked = mem_cgroup_oom_lock(memcg);
 	/*
 	 * 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.
 	 */
 	prepare_to_wait(&memcg_oom_waitq, &owait.wait, TASK_KILLABLE);
-	if (!locked || mem->oom_kill_disable)
+	if (!locked || memcg->oom_kill_disable)
 		need_to_kill = false;
 	if (locked)
-		mem_cgroup_oom_notify(mem);
+		mem_cgroup_oom_notify(memcg);
 	spin_unlock(&memcg_oom_lock);
 
 	if (need_to_kill) {
 		finish_wait(&memcg_oom_waitq, &owait.wait);
-		mem_cgroup_out_of_memory(mem, mask);
+		mem_cgroup_out_of_memory(memcg, mask);
 	} else {
 		schedule();
 		finish_wait(&memcg_oom_waitq, &owait.wait);
 	}
 	spin_lock(&memcg_oom_lock);
 	if (locked)
-		mem_cgroup_oom_unlock(mem);
-	memcg_wakeup_oom(mem);
+		mem_cgroup_oom_unlock(memcg);
+	memcg_wakeup_oom(memcg);
 	spin_unlock(&memcg_oom_lock);
 
-	mem_cgroup_unmark_under_oom(mem);
+	mem_cgroup_unmark_under_oom(memcg);
 
 	if (test_thread_flag(TIF_MEMDIE) || fatal_signal_pending(current))
 		return false;
 	/* Give chance to dying process */
-	schedule_timeout(1);
+	schedule_timeout_uninterruptible(1);
 	return true;
 }
 
@@ -1926,7 +1935,7 @@ bool mem_cgroup_handle_oom(struct mem_cgroup *mem, gfp_t mask)
 void mem_cgroup_update_page_stat(struct page *page,
 				 enum mem_cgroup_page_stat_item idx, int val)
 {
-	struct mem_cgroup *mem;
+	struct mem_cgroup *memcg;
 	struct page_cgroup *pc = lookup_page_cgroup(page);
 	bool need_unlock = false;
 	unsigned long uninitialized_var(flags);
@@ -1935,16 +1944,16 @@ void mem_cgroup_update_page_stat(struct page *page,
 		return;
 
 	rcu_read_lock();
-	mem = pc->mem_cgroup;
-	if (unlikely(!mem || !PageCgroupUsed(pc)))
+	memcg = pc->mem_cgroup;
+	if (unlikely(!memcg || !PageCgroupUsed(pc)))
 		goto out;
 	/* pc->mem_cgroup is unstable ? */
-	if (unlikely(mem_cgroup_stealed(mem)) || PageTransHuge(page)) {
+	if (unlikely(mem_cgroup_stealed(memcg)) || PageTransHuge(page)) {
 		/* take a lock against to access pc->mem_cgroup */
 		move_lock_page_cgroup(pc, &flags);
 		need_unlock = true;
-		mem = pc->mem_cgroup;
-		if (!mem || !PageCgroupUsed(pc))
+		memcg = pc->mem_cgroup;
+		if (!memcg || !PageCgroupUsed(pc))
 			goto out;
 	}
 
@@ -1960,7 +1969,7 @@ void mem_cgroup_update_page_stat(struct page *page,
 		BUG();
 	}
 
-	this_cpu_add(mem->stat->count[idx], val);
+	this_cpu_add(memcg->stat->count[idx], val);
 
 out:
 	if (unlikely(need_unlock))
@@ -1991,13 +2000,13 @@ static DEFINE_MUTEX(percpu_charge_mutex);
  * cgroup which is not current target, returns false. This stock will be
  * refilled.
  */
-static bool consume_stock(struct mem_cgroup *mem)
+static bool consume_stock(struct mem_cgroup *memcg)
 {
 	struct memcg_stock_pcp *stock;
 	bool ret = true;
 
 	stock = &get_cpu_var(memcg_stock);
-	if (mem == stock->cached && stock->nr_pages)
+	if (memcg == stock->cached && stock->nr_pages)
 		stock->nr_pages--;
 	else /* need to call res_counter_charge */
 		ret = false;
@@ -2038,24 +2047,24 @@ static void drain_local_stock(struct work_struct *dummy)
  * Cache charges(val) which is from res_counter, to local per_cpu area.
  * This will be consumed by consume_stock() function, later.
  */
-static void refill_stock(struct mem_cgroup *mem, unsigned int nr_pages)
+static void refill_stock(struct mem_cgroup *memcg, unsigned int nr_pages)
 {
 	struct memcg_stock_pcp *stock = &get_cpu_var(memcg_stock);
 
-	if (stock->cached != mem) { /* reset if necessary */
+	if (stock->cached != memcg) { /* reset if necessary */
 		drain_stock(stock);
-		stock->cached = mem;
+		stock->cached = memcg;
 	}
 	stock->nr_pages += nr_pages;
 	put_cpu_var(memcg_stock);
 }
 
 /*
- * Drains all per-CPU charge caches for given root_mem resp. subtree
+ * Drains all per-CPU charge caches for given root_memcg resp. subtree
  * of the hierarchy under it. sync flag says whether we should block
  * until the work is done.
  */
-static void drain_all_stock(struct mem_cgroup *root_mem, bool sync)
+static void drain_all_stock(struct mem_cgroup *root_memcg, bool sync)
 {
 	int cpu, curcpu;
 
@@ -2064,12 +2073,12 @@ static void drain_all_stock(struct mem_cgroup *root_mem, bool sync)
 	curcpu = get_cpu();
 	for_each_online_cpu(cpu) {
 		struct memcg_stock_pcp *stock = &per_cpu(memcg_stock, cpu);
-		struct mem_cgroup *mem;
+		struct mem_cgroup *memcg;
 
-		mem = stock->cached;
-		if (!mem || !stock->nr_pages)
+		memcg = stock->cached;
+		if (!memcg || !stock->nr_pages)
 			continue;
-		if (!mem_cgroup_same_or_subtree(root_mem, mem))
+		if (!mem_cgroup_same_or_subtree(root_memcg, memcg))
 			continue;
 		if (!test_and_set_bit(FLUSHING_CACHED_CHARGE, &stock->flags)) {
 			if (cpu == curcpu)
@@ -2098,23 +2107,23 @@ out:
  * expects some charges will be back to res_counter later but cannot wait for
  * it.
  */
-static void drain_all_stock_async(struct mem_cgroup *root_mem)
+static void drain_all_stock_async(struct mem_cgroup *root_memcg)
 {
 	/*
 	 * If someone calls draining, avoid adding more kworker runs.
 	 */
 	if (!mutex_trylock(&percpu_charge_mutex))
 		return;
-	drain_all_stock(root_mem, false);
+	drain_all_stock(root_memcg, false);
 	mutex_unlock(&percpu_charge_mutex);
 }
 
 /* This is a synchronous drain interface. */
-static void drain_all_stock_sync(struct mem_cgroup *root_mem)
+static void drain_all_stock_sync(struct mem_cgroup *root_memcg)
 {
 	/* called when force_empty is called */
 	mutex_lock(&percpu_charge_mutex);
-	drain_all_stock(root_mem, true);
+	drain_all_stock(root_memcg, true);
 	mutex_unlock(&percpu_charge_mutex);
 }
 
@@ -2122,35 +2131,35 @@ static void drain_all_stock_sync(struct mem_cgroup *root_mem)
  * This function drains percpu counter value from DEAD cpu and
  * move it to local cpu. Note that this function can be preempted.
  */
-static void mem_cgroup_drain_pcp_counter(struct mem_cgroup *mem, int cpu)
+static void mem_cgroup_drain_pcp_counter(struct mem_cgroup *memcg, int cpu)
 {
 	int i;
 
-	spin_lock(&mem->pcp_counter_lock);
+	spin_lock(&memcg->pcp_counter_lock);
 	for (i = 0; i < MEM_CGROUP_STAT_DATA; i++) {
-		long x = per_cpu(mem->stat->count[i], cpu);
+		long x = per_cpu(memcg->stat->count[i], cpu);
 
-		per_cpu(mem->stat->count[i], cpu) = 0;
-		mem->nocpu_base.count[i] += x;
+		per_cpu(memcg->stat->count[i], cpu) = 0;
+		memcg->nocpu_base.count[i] += x;
 	}
 	for (i = 0; i < MEM_CGROUP_EVENTS_NSTATS; i++) {
-		unsigned long x = per_cpu(mem->stat->events[i], cpu);
+		unsigned long x = per_cpu(memcg->stat->events[i], cpu);
 
-		per_cpu(mem->stat->events[i], cpu) = 0;
-		mem->nocpu_base.events[i] += x;
+		per_cpu(memcg->stat->events[i], cpu) = 0;
+		memcg->nocpu_base.events[i] += x;
 	}
 	/* need to clear ON_MOVE value, works as a kind of lock. */
-	per_cpu(mem->stat->count[MEM_CGROUP_ON_MOVE], cpu) = 0;
-	spin_unlock(&mem->pcp_counter_lock);
+	per_cpu(memcg->stat->count[MEM_CGROUP_ON_MOVE], cpu) = 0;
+	spin_unlock(&memcg->pcp_counter_lock);
 }
 
-static void synchronize_mem_cgroup_on_move(struct mem_cgroup *mem, int cpu)
+static void synchronize_mem_cgroup_on_move(struct mem_cgroup *memcg, int cpu)
 {
 	int idx = MEM_CGROUP_ON_MOVE;
 
-	spin_lock(&mem->pcp_counter_lock);
-	per_cpu(mem->stat->count[idx], cpu) = mem->nocpu_base.count[idx];
-	spin_unlock(&mem->pcp_counter_lock);
+	spin_lock(&memcg->pcp_counter_lock);
+	per_cpu(memcg->stat->count[idx], cpu) = memcg->nocpu_base.count[idx];
+	spin_unlock(&memcg->pcp_counter_lock);
 }
 
 static int __cpuinit memcg_cpu_hotplug_callback(struct notifier_block *nb,
@@ -2188,7 +2197,7 @@ enum {
 	CHARGE_OOM_DIE,		/* the current is killed because of OOM */
 };
 
-static int mem_cgroup_do_charge(struct mem_cgroup *mem, gfp_t gfp_mask,
+static int mem_cgroup_do_charge(struct mem_cgroup *memcg, gfp_t gfp_mask,
 				unsigned int nr_pages, bool oom_check)
 {
 	unsigned long csize = nr_pages * PAGE_SIZE;
@@ -2197,16 +2206,16 @@ static int mem_cgroup_do_charge(struct mem_cgroup *mem, gfp_t gfp_mask,
 	unsigned long flags = 0;
 	int ret;
 
-	ret = res_counter_charge(&mem->res, csize, &fail_res);
+	ret = res_counter_charge(&memcg->res, csize, &fail_res);
 
 	if (likely(!ret)) {
 		if (!do_swap_account)
 			return CHARGE_OK;
-		ret = res_counter_charge(&mem->memsw, csize, &fail_res);
+		ret = res_counter_charge(&memcg->memsw, csize, &fail_res);
 		if (likely(!ret))
 			return CHARGE_OK;
 
-		res_counter_uncharge(&mem->res, csize);
+		res_counter_uncharge(&memcg->res, csize);
 		mem_over_limit = mem_cgroup_from_res_counter(fail_res, memsw);
 		flags |= MEM_CGROUP_RECLAIM_NOSWAP;
 	} else
@@ -2264,12 +2273,12 @@ static int mem_cgroup_do_charge(struct mem_cgroup *mem, gfp_t gfp_mask,
 static int __mem_cgroup_try_charge(struct mm_struct *mm,
 				   gfp_t gfp_mask,
 				   unsigned int nr_pages,
-				   struct mem_cgroup **memcg,
+				   struct mem_cgroup **ptr,
 				   bool oom)
 {
 	unsigned int batch = max(CHARGE_BATCH, nr_pages);
 	int nr_oom_retries = MEM_CGROUP_RECLAIM_RETRIES;
-	struct mem_cgroup *mem = NULL;
+	struct mem_cgroup *memcg = NULL;
 	int ret;
 
 	/*
@@ -2287,17 +2296,17 @@ static int __mem_cgroup_try_charge(struct mm_struct *mm,
 	 * thread group leader migrates. It's possible that mm is not
 	 * set, if so charge the init_mm (happens for pagecache usage).
 	 */
-	if (!*memcg && !mm)
+	if (!*ptr && !mm)
 		goto bypass;
 again:
-	if (*memcg) { /* css should be a valid one */
-		mem = *memcg;
-		VM_BUG_ON(css_is_removed(&mem->css));
-		if (mem_cgroup_is_root(mem))
+	if (*ptr) { /* css should be a valid one */
+		memcg = *ptr;
+		VM_BUG_ON(css_is_removed(&memcg->css));
+		if (mem_cgroup_is_root(memcg))
 			goto done;
-		if (nr_pages == 1 && consume_stock(mem))
+		if (nr_pages == 1 && consume_stock(memcg))
 			goto done;
-		css_get(&mem->css);
+		css_get(&memcg->css);
 	} else {
 		struct task_struct *p;
 
@@ -2305,7 +2314,7 @@ again:
 		p = rcu_dereference(mm->owner);
 		/*
 		 * Because we don't have task_lock(), "p" can exit.
-		 * In that case, "mem" can point to root or p can be NULL with
+		 * In that case, "memcg" can point to root or p can be NULL with
 		 * race with swapoff. Then, we have small risk of mis-accouning.
 		 * But such kind of mis-account by race always happens because
 		 * we don't have cgroup_mutex(). It's overkill and we allo that
@@ -2313,12 +2322,12 @@ again:
 		 * (*) swapoff at el will charge against mm-struct not against
 		 * task-struct. So, mm->owner can be NULL.
 		 */
-		mem = mem_cgroup_from_task(p);
-		if (!mem || mem_cgroup_is_root(mem)) {
+		memcg = mem_cgroup_from_task(p);
+		if (!memcg || mem_cgroup_is_root(memcg)) {
 			rcu_read_unlock();
 			goto done;
 		}
-		if (nr_pages == 1 && consume_stock(mem)) {
+		if (nr_pages == 1 && consume_stock(memcg)) {
 			/*
 			 * It seems dagerous to access memcg without css_get().
 			 * But considering how consume_stok works, it's not
@@ -2331,7 +2340,7 @@ again:
 			goto done;
 		}
 		/* after here, we may be blocked. we need to get refcnt */
-		if (!css_tryget(&mem->css)) {
+		if (!css_tryget(&memcg->css)) {
 			rcu_read_unlock();
 			goto again;
 		}
@@ -2343,7 +2352,7 @@ again:
 
 		/* If killed, bypass charge */
 		if (fatal_signal_pending(current)) {
-			css_put(&mem->css);
+			css_put(&memcg->css);
 			goto bypass;
 		}
 
@@ -2353,43 +2362,43 @@ again:
 			nr_oom_retries = MEM_CGROUP_RECLAIM_RETRIES;
 		}
 
-		ret = mem_cgroup_do_charge(mem, gfp_mask, batch, oom_check);
+		ret = mem_cgroup_do_charge(memcg, gfp_mask, batch, oom_check);
 		switch (ret) {
 		case CHARGE_OK:
 			break;
 		case CHARGE_RETRY: /* not in OOM situation but retry */
 			batch = nr_pages;
-			css_put(&mem->css);
-			mem = NULL;
+			css_put(&memcg->css);
+			memcg = NULL;
 			goto again;
 		case CHARGE_WOULDBLOCK: /* !__GFP_WAIT */
-			css_put(&mem->css);
+			css_put(&memcg->css);
 			goto nomem;
 		case CHARGE_NOMEM: /* OOM routine works */
 			if (!oom) {
-				css_put(&mem->css);
+				css_put(&memcg->css);
 				goto nomem;
 			}
 			/* If oom, we never return -ENOMEM */
 			nr_oom_retries--;
 			break;
 		case CHARGE_OOM_DIE: /* Killed by OOM Killer */
-			css_put(&mem->css);
+			css_put(&memcg->css);
 			goto bypass;
 		}
 	} while (ret != CHARGE_OK);
 
 	if (batch > nr_pages)
-		refill_stock(mem, batch - nr_pages);
-	css_put(&mem->css);
+		refill_stock(memcg, batch - nr_pages);
+	css_put(&memcg->css);
 done:
-	*memcg = mem;
+	*ptr = memcg;
 	return 0;
 nomem:
-	*memcg = NULL;
+	*ptr = NULL;
 	return -ENOMEM;
 bypass:
-	*memcg = NULL;
+	*ptr = NULL;
 	return 0;
 }
 
@@ -2398,15 +2407,15 @@ bypass:
  * 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 *memcg,
 				       unsigned int nr_pages)
 {
-	if (!mem_cgroup_is_root(mem)) {
+	if (!mem_cgroup_is_root(memcg)) {
 		unsigned long bytes = nr_pages * PAGE_SIZE;
 
-		res_counter_uncharge(&mem->res, bytes);
+		res_counter_uncharge(&memcg->res, bytes);
 		if (do_swap_account)
-			res_counter_uncharge(&mem->memsw, bytes);
+			res_counter_uncharge(&memcg->memsw, bytes);
 	}
 }
 
@@ -2431,7 +2440,7 @@ static struct mem_cgroup *mem_cgroup_lookup(unsigned short id)
 
 struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page)
 {
-	struct mem_cgroup *mem = NULL;
+	struct mem_cgroup *memcg = NULL;
 	struct page_cgroup *pc;
 	unsigned short id;
 	swp_entry_t ent;
@@ -2441,23 +2450,23 @@ struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page)
 	pc = lookup_page_cgroup(page);
 	lock_page_cgroup(pc);
 	if (PageCgroupUsed(pc)) {
-		mem = pc->mem_cgroup;
-		if (mem && !css_tryget(&mem->css))
-			mem = NULL;
+		memcg = pc->mem_cgroup;
+		if (memcg && !css_tryget(&memcg->css))
+			memcg = NULL;
 	} else if (PageSwapCache(page)) {
 		ent.val = page_private(page);
 		id = lookup_swap_cgroup(ent);
 		rcu_read_lock();
-		mem = mem_cgroup_lookup(id);
-		if (mem && !css_tryget(&mem->css))
-			mem = NULL;
+		memcg = mem_cgroup_lookup(id);
+		if (memcg && !css_tryget(&memcg->css))
+			memcg = NULL;
 		rcu_read_unlock();
 	}
 	unlock_page_cgroup(pc);
-	return mem;
+	return memcg;
 }
 
-static void __mem_cgroup_commit_charge(struct mem_cgroup *mem,
+static void __mem_cgroup_commit_charge(struct mem_cgroup *memcg,
 				       struct page *page,
 				       unsigned int nr_pages,
 				       struct page_cgroup *pc,
@@ -2466,14 +2475,14 @@ static void __mem_cgroup_commit_charge(struct mem_cgroup *mem,
 	lock_page_cgroup(pc);
 	if (unlikely(PageCgroupUsed(pc))) {
 		unlock_page_cgroup(pc);
-		__mem_cgroup_cancel_charge(mem, nr_pages);
+		__mem_cgroup_cancel_charge(memcg, nr_pages);
 		return;
 	}
 	/*
 	 * we don't need page_cgroup_lock about tail pages, becase they are not
 	 * accessed by any other context at this point.
 	 */
-	pc->mem_cgroup = mem;
+	pc->mem_cgroup = memcg;
 	/*
 	 * We access a page_cgroup asynchronously without lock_page_cgroup().
 	 * Especially when a page_cgroup is taken from a page, pc->mem_cgroup
@@ -2496,14 +2505,14 @@ static void __mem_cgroup_commit_charge(struct mem_cgroup *mem,
 		break;
 	}
 
-	mem_cgroup_charge_statistics(mem, PageCgroupCache(pc), nr_pages);
+	mem_cgroup_charge_statistics(memcg, PageCgroupCache(pc), nr_pages);
 	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, page);
+	memcg_check_events(memcg, page);
 }
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
@@ -2690,7 +2699,7 @@ out:
 static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm,
 				gfp_t gfp_mask, enum charge_type ctype)
 {
-	struct mem_cgroup *mem = NULL;
+	struct mem_cgroup *memcg = NULL;
 	unsigned int nr_pages = 1;
 	struct page_cgroup *pc;
 	bool oom = true;
@@ -2709,11 +2718,11 @@ static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm,
 	pc = lookup_page_cgroup(page);
 	BUG_ON(!pc); /* XXX: remove this and move pc lookup into commit */
 
-	ret = __mem_cgroup_try_charge(mm, gfp_mask, nr_pages, &mem, oom);
-	if (ret || !mem)
+	ret = __mem_cgroup_try_charge(mm, gfp_mask, nr_pages, &memcg, oom);
+	if (ret || !memcg)
 		return ret;
 
-	__mem_cgroup_commit_charge(mem, page, nr_pages, pc, ctype);
+	__mem_cgroup_commit_charge(memcg, page, nr_pages, pc, ctype);
 	return 0;
 }
 
@@ -2742,7 +2751,7 @@ __mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *ptr,
 					enum charge_type ctype);
 
 static void
-__mem_cgroup_commit_charge_lrucare(struct page *page, struct mem_cgroup *mem,
+__mem_cgroup_commit_charge_lrucare(struct page *page, struct mem_cgroup *memcg,
 					enum charge_type ctype)
 {
 	struct page_cgroup *pc = lookup_page_cgroup(page);
@@ -2752,7 +2761,7 @@ __mem_cgroup_commit_charge_lrucare(struct page *page, struct mem_cgroup *mem,
 	 * LRU. Take care of it.
 	 */
 	mem_cgroup_lru_del_before_commit(page);
-	__mem_cgroup_commit_charge(mem, page, 1, pc, ctype);
+	__mem_cgroup_commit_charge(memcg, page, 1, pc, ctype);
 	mem_cgroup_lru_add_after_commit(page);
 	return;
 }
@@ -2760,7 +2769,7 @@ __mem_cgroup_commit_charge_lrucare(struct page *page, struct mem_cgroup *mem,
 int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
 				gfp_t gfp_mask)
 {
-	struct mem_cgroup *mem = NULL;
+	struct mem_cgroup *memcg = NULL;
 	int ret;
 
 	if (mem_cgroup_disabled())
@@ -2772,8 +2781,8 @@ int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
 		mm = &init_mm;
 
 	if (page_is_file_cache(page)) {
-		ret = __mem_cgroup_try_charge(mm, gfp_mask, 1, &mem, true);
-		if (ret || !mem)
+		ret = __mem_cgroup_try_charge(mm, gfp_mask, 1, &memcg, true);
+		if (ret || !memcg)
 			return ret;
 
 		/*
@@ -2781,15 +2790,15 @@ int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
 		 * put that would remove them from the LRU list, make
 		 * sure that they get relinked properly.
 		 */
-		__mem_cgroup_commit_charge_lrucare(page, mem,
+		__mem_cgroup_commit_charge_lrucare(page, memcg,
 					MEM_CGROUP_CHARGE_TYPE_CACHE);
 		return ret;
 	}
 	/* shmem */
 	if (PageSwapCache(page)) {
-		ret = mem_cgroup_try_charge_swapin(mm, page, gfp_mask, &mem);
+		ret = mem_cgroup_try_charge_swapin(mm, page, gfp_mask, &memcg);
 		if (!ret)
-			__mem_cgroup_commit_charge_swapin(page, mem,
+			__mem_cgroup_commit_charge_swapin(page, memcg,
 					MEM_CGROUP_CHARGE_TYPE_SHMEM);
 	} else
 		ret = mem_cgroup_charge_common(page, mm, gfp_mask,
@@ -2808,7 +2817,7 @@ int mem_cgroup_try_charge_swapin(struct mm_struct *mm,
 				 struct page *page,
 				 gfp_t mask, struct mem_cgroup **ptr)
 {
-	struct mem_cgroup *mem;
+	struct mem_cgroup *memcg;
 	int ret;
 
 	*ptr = NULL;
@@ -2826,12 +2835,12 @@ int mem_cgroup_try_charge_swapin(struct mm_struct *mm,
 	 */
 	if (!PageSwapCache(page))
 		goto charge_cur_mm;
-	mem = try_get_mem_cgroup_from_page(page);
-	if (!mem)
+	memcg = try_get_mem_cgroup_from_page(page);
+	if (!memcg)
 		goto charge_cur_mm;
-	*ptr = mem;
+	*ptr = memcg;
 	ret = __mem_cgroup_try_charge(NULL, mask, 1, ptr, true);
-	css_put(&mem->css);
+	css_put(&memcg->css);
 	return ret;
 charge_cur_mm:
 	if (unlikely(!mm))
@@ -2891,16 +2900,16 @@ void mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *ptr)
 					MEM_CGROUP_CHARGE_TYPE_MAPPED);
 }
 
-void mem_cgroup_cancel_charge_swapin(struct mem_cgroup *mem)
+void mem_cgroup_cancel_charge_swapin(struct mem_cgroup *memcg)
 {
 	if (mem_cgroup_disabled())
 		return;
-	if (!mem)
+	if (!memcg)
 		return;
-	__mem_cgroup_cancel_charge(mem, 1);
+	__mem_cgroup_cancel_charge(memcg, 1);
 }
 
-static void mem_cgroup_do_uncharge(struct mem_cgroup *mem,
+static void mem_cgroup_do_uncharge(struct mem_cgroup *memcg,
 				   unsigned int nr_pages,
 				   const enum charge_type ctype)
 {
@@ -2918,7 +2927,7 @@ static void mem_cgroup_do_uncharge(struct mem_cgroup *mem,
 	 * uncharges. Then, it's ok to ignore memcg's refcnt.
 	 */
 	if (!batch->memcg)
-		batch->memcg = mem;
+		batch->memcg = memcg;
 	/*
 	 * do_batch > 0 when unmapping pages or inode invalidate/truncate.
 	 * In those cases, all pages freed continuously can be expected to be in
@@ -2938,7 +2947,7 @@ static void mem_cgroup_do_uncharge(struct mem_cgroup *mem,
 	 * merge a series of uncharges to an uncharge of res_counter.
 	 * If not, we uncharge res_counter ony by one.
 	 */
-	if (batch->memcg != mem)
+	if (batch->memcg != memcg)
 		goto direct_uncharge;
 	/* remember freed charge and uncharge it later */
 	batch->nr_pages++;
@@ -2946,11 +2955,11 @@ static void mem_cgroup_do_uncharge(struct mem_cgroup *mem,
 		batch->memsw_nr_pages++;
 	return;
 direct_uncharge:
-	res_counter_uncharge(&mem->res, nr_pages * PAGE_SIZE);
+	res_counter_uncharge(&memcg->res, nr_pages * PAGE_SIZE);
 	if (uncharge_memsw)
-		res_counter_uncharge(&mem->memsw, nr_pages * PAGE_SIZE);
-	if (unlikely(batch->memcg != mem))
-		memcg_oom_recover(mem);
+		res_counter_uncharge(&memcg->memsw, nr_pages * PAGE_SIZE);
+	if (unlikely(batch->memcg != memcg))
+		memcg_oom_recover(memcg);
 	return;
 }
 
@@ -2960,7 +2969,7 @@ direct_uncharge:
 static struct mem_cgroup *
 __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype)
 {
-	struct mem_cgroup *mem = NULL;
+	struct mem_cgroup *memcg = NULL;
 	unsigned int nr_pages = 1;
 	struct page_cgroup *pc;
 
@@ -2983,7 +2992,7 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype)
 
 	lock_page_cgroup(pc);
 
-	mem = pc->mem_cgroup;
+	memcg = pc->mem_cgroup;
 
 	if (!PageCgroupUsed(pc))
 		goto unlock_out;
@@ -3006,7 +3015,7 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype)
 		break;
 	}
 
-	mem_cgroup_charge_statistics(mem, PageCgroupCache(pc), -nr_pages);
+	mem_cgroup_charge_statistics(memcg, PageCgroupCache(pc), -nr_pages);
 
 	ClearPageCgroupUsed(pc);
 	/*
@@ -3018,18 +3027,18 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype)
 
 	unlock_page_cgroup(pc);
 	/*
-	 * even after unlock, we have mem->res.usage here and this memcg
+	 * even after unlock, we have memcg->res.usage here and this memcg
 	 * will never be freed.
 	 */
-	memcg_check_events(mem, page);
+	memcg_check_events(memcg, page);
 	if (do_swap_account && ctype == MEM_CGROUP_CHARGE_TYPE_SWAPOUT) {
-		mem_cgroup_swap_statistics(mem, true);
-		mem_cgroup_get(mem);
+		mem_cgroup_swap_statistics(memcg, true);
+		mem_cgroup_get(memcg);
 	}
-	if (!mem_cgroup_is_root(mem))
-		mem_cgroup_do_uncharge(mem, nr_pages, ctype);
+	if (!mem_cgroup_is_root(memcg))
+		mem_cgroup_do_uncharge(memcg, nr_pages, ctype);
 
-	return mem;
+	return memcg;
 
 unlock_out:
 	unlock_page_cgroup(pc);
@@ -3219,7 +3228,7 @@ static inline int mem_cgroup_move_swap_account(swp_entry_t entry,
 int mem_cgroup_prepare_migration(struct page *page,
 	struct page *newpage, struct mem_cgroup **ptr, gfp_t gfp_mask)
 {
-	struct mem_cgroup *mem = NULL;
+	struct mem_cgroup *memcg = NULL;
 	struct page_cgroup *pc;
 	enum charge_type ctype;
 	int ret = 0;
@@ -3233,8 +3242,8 @@ int mem_cgroup_prepare_migration(struct page *page,
 	pc = lookup_page_cgroup(page);
 	lock_page_cgroup(pc);
 	if (PageCgroupUsed(pc)) {
-		mem = pc->mem_cgroup;
-		css_get(&mem->css);
+		memcg = pc->mem_cgroup;
+		css_get(&memcg->css);
 		/*
 		 * At migrating an anonymous page, its mapcount goes down
 		 * to 0 and uncharge() will be called. But, even if it's fully
@@ -3272,12 +3281,12 @@ int mem_cgroup_prepare_migration(struct page *page,
 	 * If the page is not charged at this point,
 	 * we return here.
 	 */
-	if (!mem)
+	if (!memcg)
 		return 0;
 
-	*ptr = mem;
+	*ptr = memcg;
 	ret = __mem_cgroup_try_charge(NULL, gfp_mask, 1, ptr, false);
-	css_put(&mem->css);/* drop extra refcnt */
+	css_put(&memcg->css);/* drop extra refcnt */
 	if (ret || *ptr == NULL) {
 		if (PageAnon(page)) {
 			lock_page_cgroup(pc);
@@ -3303,21 +3312,21 @@ int mem_cgroup_prepare_migration(struct page *page,
 		ctype = MEM_CGROUP_CHARGE_TYPE_CACHE;
 	else
 		ctype = MEM_CGROUP_CHARGE_TYPE_SHMEM;
-	__mem_cgroup_commit_charge(mem, page, 1, pc, ctype);
+	__mem_cgroup_commit_charge(memcg, page, 1, pc, ctype);
 	return ret;
 }
 
 /* remove redundant charge if migration failed*/
-void mem_cgroup_end_migration(struct mem_cgroup *mem,
+void mem_cgroup_end_migration(struct mem_cgroup *memcg,
 	struct page *oldpage, struct page *newpage, bool migration_ok)
 {
 	struct page *used, *unused;
 	struct page_cgroup *pc;
 
-	if (!mem)
+	if (!memcg)
 		return;
 	/* blocks rmdir() */
-	cgroup_exclude_rmdir(&mem->css);
+	cgroup_exclude_rmdir(&memcg->css);
 	if (!migration_ok) {
 		used = oldpage;
 		unused = newpage;
@@ -3353,7 +3362,7 @@ void mem_cgroup_end_migration(struct mem_cgroup *mem,
 	 * So, rmdir()->pre_destroy() can be called while we do this charge.
 	 * In that case, we need to call pre_destroy() again. check it here.
 	 */
-	cgroup_release_and_wakeup_rmdir(&mem->css);
+	cgroup_release_and_wakeup_rmdir(&memcg->css);
 }
 
 #ifdef CONFIG_DEBUG_VM
@@ -3432,7 +3441,7 @@ static int mem_cgroup_resize_limit(struct mem_cgroup *memcg,
 		/*
 		 * Rather than hide all in some function, I do this in
 		 * open coded manner. You see what this really does.
-		 * We have to guarantee mem->res.limit < mem->memsw.limit.
+		 * We have to guarantee memcg->res.limit < memcg->memsw.limit.
 		 */
 		mutex_lock(&set_limit_mutex);
 		memswlimit = res_counter_read_u64(&memcg->memsw, RES_LIMIT);
@@ -3494,7 +3503,7 @@ static int mem_cgroup_resize_memsw_limit(struct mem_cgroup *memcg,
 		/*
 		 * Rather than hide all in some function, I do this in
 		 * open coded manner. You see what this really does.
-		 * We have to guarantee mem->res.limit < mem->memsw.limit.
+		 * We have to guarantee memcg->res.limit < memcg->memsw.limit.
 		 */
 		mutex_lock(&set_limit_mutex);
 		memlimit = res_counter_read_u64(&memcg->res, RES_LIMIT);
@@ -3632,7 +3641,7 @@ unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
  * This routine traverse page_cgroup in given list and drop them all.
  * *And* this routine doesn't reclaim page itself, just removes page_cgroup.
  */
-static int mem_cgroup_force_empty_list(struct mem_cgroup *mem,
+static int mem_cgroup_force_empty_list(struct mem_cgroup *memcg,
 				int node, int zid, enum lru_list lru)
 {
 	struct zone *zone;
@@ -3643,7 +3652,7 @@ static int mem_cgroup_force_empty_list(struct mem_cgroup *mem,
 	int ret = 0;
 
 	zone = &NODE_DATA(node)->node_zones[zid];
-	mz = mem_cgroup_zoneinfo(mem, node, zid);
+	mz = mem_cgroup_zoneinfo(memcg, node, zid);
 	list = &mz->lists[lru];
 
 	loop = MEM_CGROUP_ZSTAT(mz, lru);
@@ -3670,7 +3679,7 @@ static int mem_cgroup_force_empty_list(struct mem_cgroup *mem,
 
 		page = lookup_cgroup_page(pc);
 
-		ret = mem_cgroup_move_parent(page, pc, mem, GFP_KERNEL);
+		ret = mem_cgroup_move_parent(page, pc, memcg, GFP_KERNEL);
 		if (ret == -ENOMEM)
 			break;
 
@@ -3691,14 +3700,14 @@ static int mem_cgroup_force_empty_list(struct mem_cgroup *mem,
  * make mem_cgroup's charge to be 0 if there is no task.
  * This enables deleting this mem_cgroup.
  */
-static int mem_cgroup_force_empty(struct mem_cgroup *mem, bool free_all)
+static int mem_cgroup_force_empty(struct mem_cgroup *memcg, bool free_all)
 {
 	int ret;
 	int node, zid, shrink;
 	int nr_retries = MEM_CGROUP_RECLAIM_RETRIES;
-	struct cgroup *cgrp = mem->css.cgroup;
+	struct cgroup *cgrp = memcg->css.cgroup;
 
-	css_get(&mem->css);
+	css_get(&memcg->css);
 
 	shrink = 0;
 	/* should free all ? */
@@ -3714,14 +3723,14 @@ move_account:
 			goto out;
 		/* This is for making all *used* pages to be on LRU. */
 		lru_add_drain_all();
-		drain_all_stock_sync(mem);
+		drain_all_stock_sync(memcg);
 		ret = 0;
-		mem_cgroup_start_move(mem);
+		mem_cgroup_start_move(memcg);
 		for_each_node_state(node, N_HIGH_MEMORY) {
 			for (zid = 0; !ret && zid < MAX_NR_ZONES; zid++) {
 				enum lru_list l;
 				for_each_lru(l) {
-					ret = mem_cgroup_force_empty_list(mem,
+					ret = mem_cgroup_force_empty_list(memcg,
 							node, zid, l);
 					if (ret)
 						break;
@@ -3730,16 +3739,16 @@ move_account:
 			if (ret)
 				break;
 		}
-		mem_cgroup_end_move(mem);
-		memcg_oom_recover(mem);
+		mem_cgroup_end_move(memcg);
+		memcg_oom_recover(memcg);
 		/* it seems parent cgroup doesn't have enough mem */
 		if (ret == -ENOMEM)
 			goto try_to_free;
 		cond_resched();
 	/* "ret" should also be checked to ensure all lists are empty. */
-	} while (mem->res.usage > 0 || ret);
+	} while (memcg->res.usage > 0 || ret);
 out:
-	css_put(&mem->css);
+	css_put(&memcg->css);
 	return ret;
 
 try_to_free:
@@ -3752,14 +3761,14 @@ try_to_free:
 	lru_add_drain_all();
 	/* try to free all pages in this cgroup */
 	shrink = 1;
-	while (nr_retries && mem->res.usage > 0) {
+	while (nr_retries && memcg->res.usage > 0) {
 		int progress;
 
 		if (signal_pending(current)) {
 			ret = -EINTR;
 			goto out;
 		}
-		progress = try_to_free_mem_cgroup_pages(mem, GFP_KERNEL,
+		progress = try_to_free_mem_cgroup_pages(memcg, GFP_KERNEL,
 						false);
 		if (!progress) {
 			nr_retries--;
@@ -3788,12 +3797,12 @@ static int mem_cgroup_hierarchy_write(struct cgroup *cont, struct cftype *cft,
 					u64 val)
 {
 	int retval = 0;
-	struct mem_cgroup *mem = mem_cgroup_from_cont(cont);
+	struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
 	struct cgroup *parent = cont->parent;
-	struct mem_cgroup *parent_mem = NULL;
+	struct mem_cgroup *parent_memcg = NULL;
 
 	if (parent)
-		parent_mem = mem_cgroup_from_cont(parent);
+		parent_memcg = mem_cgroup_from_cont(parent);
 
 	cgroup_lock();
 	/*
@@ -3804,10 +3813,10 @@ static int mem_cgroup_hierarchy_write(struct cgroup *cont, struct cftype *cft,
 	 * For the root cgroup, parent_mem is NULL, we allow value to be
 	 * set if there are no children.
 	 */
-	if ((!parent_mem || !parent_mem->use_hierarchy) &&
+	if ((!parent_memcg || !parent_memcg->use_hierarchy) &&
 				(val == 1 || val == 0)) {
 		if (list_empty(&cont->children))
-			mem->use_hierarchy = val;
+			memcg->use_hierarchy = val;
 		else
 			retval = -EBUSY;
 	} else
@@ -3818,14 +3827,14 @@ static int mem_cgroup_hierarchy_write(struct cgroup *cont, struct cftype *cft,
 }
 
 
-static unsigned long mem_cgroup_recursive_stat(struct mem_cgroup *mem,
+static unsigned long mem_cgroup_recursive_stat(struct mem_cgroup *memcg,
 					       enum mem_cgroup_stat_index idx)
 {
 	struct mem_cgroup *iter;
 	long val = 0;
 
 	/* Per-cpu values can be negative, use a signed accumulator */
-	for_each_mem_cgroup_tree(iter, mem)
+	for_each_mem_cgroup_tree(iter, memcg)
 		val += mem_cgroup_read_stat(iter, idx);
 
 	if (val < 0) /* race ? */
@@ -3833,29 +3842,29 @@ static unsigned long mem_cgroup_recursive_stat(struct mem_cgroup *mem,
 	return val;
 }
 
-static inline u64 mem_cgroup_usage(struct mem_cgroup *mem, bool swap)
+static inline u64 mem_cgroup_usage(struct mem_cgroup *memcg, bool swap)
 {
 	u64 val;
 
-	if (!mem_cgroup_is_root(mem)) {
+	if (!mem_cgroup_is_root(memcg)) {
 		if (!swap)
-			return res_counter_read_u64(&mem->res, RES_USAGE);
+			return res_counter_read_u64(&memcg->res, RES_USAGE);
 		else
-			return res_counter_read_u64(&mem->memsw, RES_USAGE);
+			return res_counter_read_u64(&memcg->memsw, RES_USAGE);
 	}
 
-	val = mem_cgroup_recursive_stat(mem, MEM_CGROUP_STAT_CACHE);
-	val += mem_cgroup_recursive_stat(mem, MEM_CGROUP_STAT_RSS);
+	val = mem_cgroup_recursive_stat(memcg, MEM_CGROUP_STAT_CACHE);
+	val += mem_cgroup_recursive_stat(memcg, MEM_CGROUP_STAT_RSS);
 
 	if (swap)
-		val += mem_cgroup_recursive_stat(mem, MEM_CGROUP_STAT_SWAPOUT);
+		val += mem_cgroup_recursive_stat(memcg, MEM_CGROUP_STAT_SWAPOUT);
 
 	return val << PAGE_SHIFT;
 }
 
 static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft)
 {
-	struct mem_cgroup *mem = mem_cgroup_from_cont(cont);
+	struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
 	u64 val;
 	int type, name;
 
@@ -3864,15 +3873,15 @@ static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft)
 	switch (type) {
 	case _MEM:
 		if (name == RES_USAGE)
-			val = mem_cgroup_usage(mem, false);
+			val = mem_cgroup_usage(memcg, false);
 		else
-			val = res_counter_read_u64(&mem->res, name);
+			val = res_counter_read_u64(&memcg->res, name);
 		break;
 	case _MEMSWAP:
 		if (name == RES_USAGE)
-			val = mem_cgroup_usage(mem, true);
+			val = mem_cgroup_usage(memcg, true);
 		else
-			val = res_counter_read_u64(&mem->memsw, name);
+			val = res_counter_read_u64(&memcg->memsw, name);
 		break;
 	default:
 		BUG();
@@ -3960,24 +3969,24 @@ out:
 
 static int mem_cgroup_reset(struct cgroup *cont, unsigned int event)
 {
-	struct mem_cgroup *mem;
+	struct mem_cgroup *memcg;
 	int type, name;
 
-	mem = mem_cgroup_from_cont(cont);
+	memcg = mem_cgroup_from_cont(cont);
 	type = MEMFILE_TYPE(event);
 	name = MEMFILE_ATTR(event);
 	switch (name) {
 	case RES_MAX_USAGE:
 		if (type == _MEM)
-			res_counter_reset_max(&mem->res);
+			res_counter_reset_max(&memcg->res);
 		else
-			res_counter_reset_max(&mem->memsw);
+			res_counter_reset_max(&memcg->memsw);
 		break;
 	case RES_FAILCNT:
 		if (type == _MEM)
-			res_counter_reset_failcnt(&mem->res);
+			res_counter_reset_failcnt(&memcg->res);
 		else
-			res_counter_reset_failcnt(&mem->memsw);
+			res_counter_reset_failcnt(&memcg->memsw);
 		break;
 	}
 
@@ -3994,7 +4003,7 @@ static u64 mem_cgroup_move_charge_read(struct cgroup *cgrp,
 static int mem_cgroup_move_charge_write(struct cgroup *cgrp,
 					struct cftype *cft, u64 val)
 {
-	struct mem_cgroup *mem = mem_cgroup_from_cont(cgrp);
+	struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp);
 
 	if (val >= (1 << NR_MOVE_TYPE))
 		return -EINVAL;
@@ -4004,7 +4013,7 @@ static int mem_cgroup_move_charge_write(struct cgroup *cgrp,
 	 * inconsistent.
 	 */
 	cgroup_lock();
-	mem->move_charge_at_immigrate = val;
+	memcg->move_charge_at_immigrate = val;
 	cgroup_unlock();
 
 	return 0;
@@ -4061,49 +4070,49 @@ struct {
 
 
 static void
-mem_cgroup_get_local_stat(struct mem_cgroup *mem, struct mcs_total_stat *s)
+mem_cgroup_get_local_stat(struct mem_cgroup *memcg, struct mcs_total_stat *s)
 {
 	s64 val;
 
 	/* per cpu stat */
-	val = mem_cgroup_read_stat(mem, MEM_CGROUP_STAT_CACHE);
+	val = mem_cgroup_read_stat(memcg, MEM_CGROUP_STAT_CACHE);
 	s->stat[MCS_CACHE] += val * PAGE_SIZE;
-	val = mem_cgroup_read_stat(mem, MEM_CGROUP_STAT_RSS);
+	val = mem_cgroup_read_stat(memcg, MEM_CGROUP_STAT_RSS);
 	s->stat[MCS_RSS] += val * PAGE_SIZE;
-	val = mem_cgroup_read_stat(mem, MEM_CGROUP_STAT_FILE_MAPPED);
+	val = mem_cgroup_read_stat(memcg, MEM_CGROUP_STAT_FILE_MAPPED);
 	s->stat[MCS_FILE_MAPPED] += val * PAGE_SIZE;
-	val = mem_cgroup_read_events(mem, MEM_CGROUP_EVENTS_PGPGIN);
+	val = mem_cgroup_read_events(memcg, MEM_CGROUP_EVENTS_PGPGIN);
 	s->stat[MCS_PGPGIN] += val;
-	val = mem_cgroup_read_events(mem, MEM_CGROUP_EVENTS_PGPGOUT);
+	val = mem_cgroup_read_events(memcg, MEM_CGROUP_EVENTS_PGPGOUT);
 	s->stat[MCS_PGPGOUT] += val;
 	if (do_swap_account) {
-		val = mem_cgroup_read_stat(mem, MEM_CGROUP_STAT_SWAPOUT);
+		val = mem_cgroup_read_stat(memcg, MEM_CGROUP_STAT_SWAPOUT);
 		s->stat[MCS_SWAP] += val * PAGE_SIZE;
 	}
-	val = mem_cgroup_read_events(mem, MEM_CGROUP_EVENTS_PGFAULT);
+	val = mem_cgroup_read_events(memcg, MEM_CGROUP_EVENTS_PGFAULT);
 	s->stat[MCS_PGFAULT] += val;
-	val = mem_cgroup_read_events(mem, MEM_CGROUP_EVENTS_PGMAJFAULT);
+	val = mem_cgroup_read_events(memcg, MEM_CGROUP_EVENTS_PGMAJFAULT);
 	s->stat[MCS_PGMAJFAULT] += val;
 
 	/* per zone stat */
-	val = mem_cgroup_nr_lru_pages(mem, BIT(LRU_INACTIVE_ANON));
+	val = mem_cgroup_nr_lru_pages(memcg, BIT(LRU_INACTIVE_ANON));
 	s->stat[MCS_INACTIVE_ANON] += val * PAGE_SIZE;
-	val = mem_cgroup_nr_lru_pages(mem, BIT(LRU_ACTIVE_ANON));
+	val = mem_cgroup_nr_lru_pages(memcg, BIT(LRU_ACTIVE_ANON));
 	s->stat[MCS_ACTIVE_ANON] += val * PAGE_SIZE;
-	val = mem_cgroup_nr_lru_pages(mem, BIT(LRU_INACTIVE_FILE));
+	val = mem_cgroup_nr_lru_pages(memcg, BIT(LRU_INACTIVE_FILE));
 	s->stat[MCS_INACTIVE_FILE] += val * PAGE_SIZE;
-	val = mem_cgroup_nr_lru_pages(mem, BIT(LRU_ACTIVE_FILE));
+	val = mem_cgroup_nr_lru_pages(memcg, BIT(LRU_ACTIVE_FILE));
 	s->stat[MCS_ACTIVE_FILE] += val * PAGE_SIZE;
-	val = mem_cgroup_nr_lru_pages(mem, BIT(LRU_UNEVICTABLE));
+	val = mem_cgroup_nr_lru_pages(memcg, BIT(LRU_UNEVICTABLE));
 	s->stat[MCS_UNEVICTABLE] += val * PAGE_SIZE;
 }
 
 static void
-mem_cgroup_get_total_stat(struct mem_cgroup *mem, struct mcs_total_stat *s)
+mem_cgroup_get_total_stat(struct mem_cgroup *memcg, struct mcs_total_stat *s)
 {
 	struct mem_cgroup *iter;
 
-	for_each_mem_cgroup_tree(iter, mem)
+	for_each_mem_cgroup_tree(iter, memcg)
 		mem_cgroup_get_local_stat(iter, s);
 }
 
@@ -4189,8 +4198,6 @@ static int mem_control_stat_show(struct cgroup *cont, struct cftype *cft,
 	}
 
 #ifdef CONFIG_DEBUG_VM
-	cb->fill(cb, "inactive_ratio", calc_inactive_ratio(mem_cont, NULL));
-
 	{
 		int nid, zid;
 		struct mem_cgroup_per_zone *mz;
@@ -4327,20 +4334,20 @@ static int compare_thresholds(const void *a, const void *b)
 	return _a->threshold - _b->threshold;
 }
 
-static int mem_cgroup_oom_notify_cb(struct mem_cgroup *mem)
+static int mem_cgroup_oom_notify_cb(struct mem_cgroup *memcg)
 {
 	struct mem_cgroup_eventfd_list *ev;
 
-	list_for_each_entry(ev, &mem->oom_notify, list)
+	list_for_each_entry(ev, &memcg->oom_notify, list)
 		eventfd_signal(ev->eventfd, 1);
 	return 0;
 }
 
-static void mem_cgroup_oom_notify(struct mem_cgroup *mem)
+static void mem_cgroup_oom_notify(struct mem_cgroup *memcg)
 {
 	struct mem_cgroup *iter;
 
-	for_each_mem_cgroup_tree(iter, mem)
+	for_each_mem_cgroup_tree(iter, memcg)
 		mem_cgroup_oom_notify_cb(iter);
 }
 
@@ -4530,7 +4537,7 @@ static int mem_cgroup_oom_register_event(struct cgroup *cgrp,
 static void mem_cgroup_oom_unregister_event(struct cgroup *cgrp,
 	struct cftype *cft, struct eventfd_ctx *eventfd)
 {
-	struct mem_cgroup *mem = mem_cgroup_from_cont(cgrp);
+	struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp);
 	struct mem_cgroup_eventfd_list *ev, *tmp;
 	int type = MEMFILE_TYPE(cft->private);
 
@@ -4538,7 +4545,7 @@ static void mem_cgroup_oom_unregister_event(struct cgroup *cgrp,
 
 	spin_lock(&memcg_oom_lock);
 
-	list_for_each_entry_safe(ev, tmp, &mem->oom_notify, list) {
+	list_for_each_entry_safe(ev, tmp, &memcg->oom_notify, list) {
 		if (ev->eventfd == eventfd) {
 			list_del(&ev->list);
 			kfree(ev);
@@ -4551,11 +4558,11 @@ static void mem_cgroup_oom_unregister_event(struct cgroup *cgrp,
 static int mem_cgroup_oom_control_read(struct cgroup *cgrp,
 	struct cftype *cft,  struct cgroup_map_cb *cb)
 {
-	struct mem_cgroup *mem = mem_cgroup_from_cont(cgrp);
+	struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp);
 
-	cb->fill(cb, "oom_kill_disable", mem->oom_kill_disable);
+	cb->fill(cb, "oom_kill_disable", memcg->oom_kill_disable);
 
-	if (atomic_read(&mem->under_oom))
+	if (atomic_read(&memcg->under_oom))
 		cb->fill(cb, "under_oom", 1);
 	else
 		cb->fill(cb, "under_oom", 0);
@@ -4565,7 +4572,7 @@ static int mem_cgroup_oom_control_read(struct cgroup *cgrp,
 static int mem_cgroup_oom_control_write(struct cgroup *cgrp,
 	struct cftype *cft, u64 val)
 {
-	struct mem_cgroup *mem = mem_cgroup_from_cont(cgrp);
+	struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp);
 	struct mem_cgroup *parent;
 
 	/* cannot set to root cgroup and only 0 and 1 are allowed */
@@ -4577,13 +4584,13 @@ static int mem_cgroup_oom_control_write(struct cgroup *cgrp,
 	cgroup_lock();
 	/* oom-kill-disable is a flag for subhierarchy. */
 	if ((parent->use_hierarchy) ||
-	    (mem->use_hierarchy && !list_empty(&cgrp->children))) {
+	    (memcg->use_hierarchy && !list_empty(&cgrp->children))) {
 		cgroup_unlock();
 		return -EINVAL;
 	}
-	mem->oom_kill_disable = val;
+	memcg->oom_kill_disable = val;
 	if (!val)
-		memcg_oom_recover(mem);
+		memcg_oom_recover(memcg);
 	cgroup_unlock();
 	return 0;
 }
@@ -4719,7 +4726,7 @@ static int register_memsw_files(struct cgroup *cont, struct cgroup_subsys *ss)
 }
 #endif
 
-static int alloc_mem_cgroup_per_zone_info(struct mem_cgroup *mem, int node)
+static int alloc_mem_cgroup_per_zone_info(struct mem_cgroup *memcg, int node)
 {
 	struct mem_cgroup_per_node *pn;
 	struct mem_cgroup_per_zone *mz;
@@ -4739,21 +4746,21 @@ static int alloc_mem_cgroup_per_zone_info(struct mem_cgroup *mem, int node)
 	if (!pn)
 		return 1;
 
-	mem->info.nodeinfo[node] = pn;
 	for (zone = 0; zone < MAX_NR_ZONES; zone++) {
 		mz = &pn->zoneinfo[zone];
 		for_each_lru(l)
 			INIT_LIST_HEAD(&mz->lists[l]);
 		mz->usage_in_excess = 0;
 		mz->on_tree = false;
-		mz->mem = mem;
+		mz->mem = memcg;
 	}
+	memcg->info.nodeinfo[node] = pn;
 	return 0;
 }
 
-static void free_mem_cgroup_per_zone_info(struct mem_cgroup *mem, int node)
+static void free_mem_cgroup_per_zone_info(struct mem_cgroup *memcg, int node)
 {
-	kfree(mem->info.nodeinfo[node]);
+	kfree(memcg->info.nodeinfo[node]);
 }
 
 static struct mem_cgroup *mem_cgroup_alloc(void)
@@ -4795,51 +4802,51 @@ out_free:
  * Removal of cgroup itself succeeds regardless of refs from swap.
  */
 
-static void __mem_cgroup_free(struct mem_cgroup *mem)
+static void __mem_cgroup_free(struct mem_cgroup *memcg)
 {
 	int node;
 
-	mem_cgroup_remove_from_trees(mem);
-	free_css_id(&mem_cgroup_subsys, &mem->css);
+	mem_cgroup_remove_from_trees(memcg);
+	free_css_id(&mem_cgroup_subsys, &memcg->css);
 
 	for_each_node_state(node, N_POSSIBLE)
-		free_mem_cgroup_per_zone_info(mem, node);
+		free_mem_cgroup_per_zone_info(memcg, node);
 
-	free_percpu(mem->stat);
+	free_percpu(memcg->stat);
 	if (sizeof(struct mem_cgroup) < PAGE_SIZE)
-		kfree(mem);
+		kfree(memcg);
 	else
-		vfree(mem);
+		vfree(memcg);
 }
 
-static void mem_cgroup_get(struct mem_cgroup *mem)
+static void mem_cgroup_get(struct mem_cgroup *memcg)
 {
-	atomic_inc(&mem->refcnt);
+	atomic_inc(&memcg->refcnt);
 }
 
-static void __mem_cgroup_put(struct mem_cgroup *mem, int count)
+static void __mem_cgroup_put(struct mem_cgroup *memcg, int count)
 {
-	if (atomic_sub_and_test(count, &mem->refcnt)) {
-		struct mem_cgroup *parent = parent_mem_cgroup(mem);
-		__mem_cgroup_free(mem);
+	if (atomic_sub_and_test(count, &memcg->refcnt)) {
+		struct mem_cgroup *parent = parent_mem_cgroup(memcg);
+		__mem_cgroup_free(memcg);
 		if (parent)
 			mem_cgroup_put(parent);
 	}
 }
 
-static void mem_cgroup_put(struct mem_cgroup *mem)
+static void mem_cgroup_put(struct mem_cgroup *memcg)
 {
-	__mem_cgroup_put(mem, 1);
+	__mem_cgroup_put(memcg, 1);
 }
 
 /*
  * Returns the parent mem_cgroup in memcgroup hierarchy with hierarchy enabled.
  */
-static struct mem_cgroup *parent_mem_cgroup(struct mem_cgroup *mem)
+static struct mem_cgroup *parent_mem_cgroup(struct mem_cgroup *memcg)
 {
-	if (!mem->res.parent)
+	if (!memcg->res.parent)
 		return NULL;
-	return mem_cgroup_from_res_counter(mem->res.parent, res);
+	return mem_cgroup_from_res_counter(memcg->res.parent, res);
 }
 
 #ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP
@@ -4882,16 +4889,16 @@ static int mem_cgroup_soft_limit_tree_init(void)
 static struct cgroup_subsys_state * __ref
 mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont)
 {
-	struct mem_cgroup *mem, *parent;
+	struct mem_cgroup *memcg, *parent;
 	long error = -ENOMEM;
 	int node;
 
-	mem = mem_cgroup_alloc();
-	if (!mem)
+	memcg = mem_cgroup_alloc();
+	if (!memcg)
 		return ERR_PTR(error);
 
 	for_each_node_state(node, N_POSSIBLE)
-		if (alloc_mem_cgroup_per_zone_info(mem, node))
+		if (alloc_mem_cgroup_per_zone_info(memcg, node))
 			goto free_out;
 
 	/* root ? */
@@ -4899,7 +4906,7 @@ mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont)
 		int cpu;
 		enable_swap_cgroup();
 		parent = NULL;
-		root_mem_cgroup = mem;
+		root_mem_cgroup = memcg;
 		if (mem_cgroup_soft_limit_tree_init())
 			goto free_out;
 		for_each_possible_cpu(cpu) {
@@ -4910,13 +4917,13 @@ mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont)
 		hotcpu_notifier(memcg_cpu_hotplug_callback, 0);
 	} else {
 		parent = mem_cgroup_from_cont(cont->parent);
-		mem->use_hierarchy = parent->use_hierarchy;
-		mem->oom_kill_disable = parent->oom_kill_disable;
+		memcg->use_hierarchy = parent->use_hierarchy;
+		memcg->oom_kill_disable = parent->oom_kill_disable;
 	}
 
 	if (parent && parent->use_hierarchy) {
-		res_counter_init(&mem->res, &parent->res);
-		res_counter_init(&mem->memsw, &parent->memsw);
+		res_counter_init(&memcg->res, &parent->res);
+		res_counter_init(&memcg->memsw, &parent->memsw);
 		/*
 		 * We increment refcnt of the parent to ensure that we can
 		 * safely access it on res_counter_charge/uncharge.
@@ -4925,21 +4932,21 @@ mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont)
 		 */
 		mem_cgroup_get(parent);
 	} else {
-		res_counter_init(&mem->res, NULL);
-		res_counter_init(&mem->memsw, NULL);
+		res_counter_init(&memcg->res, NULL);
+		res_counter_init(&memcg->memsw, NULL);
 	}
-	mem->last_scanned_child = 0;
-	mem->last_scanned_node = MAX_NUMNODES;
-	INIT_LIST_HEAD(&mem->oom_notify);
+	memcg->last_scanned_child = 0;
+	memcg->last_scanned_node = MAX_NUMNODES;
+	INIT_LIST_HEAD(&memcg->oom_notify);
 
 	if (parent)
-		mem->swappiness = mem_cgroup_swappiness(parent);
-	atomic_set(&mem->refcnt, 1);
-	mem->move_charge_at_immigrate = 0;
-	mutex_init(&mem->thresholds_lock);
-	return &mem->css;
+		memcg->swappiness = mem_cgroup_swappiness(parent);
+	atomic_set(&memcg->refcnt, 1);
+	memcg->move_charge_at_immigrate = 0;
+	mutex_init(&memcg->thresholds_lock);
+	return &memcg->css;
 free_out:
-	__mem_cgroup_free(mem);
+	__mem_cgroup_free(memcg);
 	root_mem_cgroup = NULL;
 	return ERR_PTR(error);
 }
@@ -4947,17 +4954,17 @@ free_out:
 static int mem_cgroup_pre_destroy(struct cgroup_subsys *ss,
 					struct cgroup *cont)
 {
-	struct mem_cgroup *mem = mem_cgroup_from_cont(cont);
+	struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
 
-	return mem_cgroup_force_empty(mem, false);
+	return mem_cgroup_force_empty(memcg, false);
 }
 
 static void mem_cgroup_destroy(struct cgroup_subsys *ss,
 				struct cgroup *cont)
 {
-	struct mem_cgroup *mem = mem_cgroup_from_cont(cont);
+	struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
 
-	mem_cgroup_put(mem);
+	mem_cgroup_put(memcg);
 }
 
 static int mem_cgroup_populate(struct cgroup_subsys *ss,
@@ -4980,9 +4987,9 @@ 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;
+	struct mem_cgroup *memcg = mc.to;
 
-	if (mem_cgroup_is_root(mem)) {
+	if (mem_cgroup_is_root(memcg)) {
 		mc.precharge += count;
 		/* we don't need css_get for root */
 		return ret;
@@ -4991,16 +4998,16 @@ static int mem_cgroup_do_precharge(unsigned long count)
 	if (count > 1) {
 		struct res_counter *dummy;
 		/*
-		 * "mem" cannot be under rmdir() because we've already checked
+		 * "memcg" 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))
+		if (res_counter_charge(&memcg->res, PAGE_SIZE * count, &dummy))
 			goto one_by_one;
-		if (do_swap_account && res_counter_charge(&mem->memsw,
+		if (do_swap_account && res_counter_charge(&memcg->memsw,
 						PAGE_SIZE * count, &dummy)) {
-			res_counter_uncharge(&mem->res, PAGE_SIZE * count);
+			res_counter_uncharge(&memcg->res, PAGE_SIZE * count);
 			goto one_by_one;
 		}
 		mc.precharge += count;
@@ -5017,8 +5024,9 @@ one_by_one:
 			batch_count = PRECHARGE_COUNT_AT_ONCE;
 			cond_resched();
 		}
-		ret = __mem_cgroup_try_charge(NULL, GFP_KERNEL, 1, &mem, false);
-		if (ret || !mem)
+		ret = __mem_cgroup_try_charge(NULL,
+					GFP_KERNEL, 1, &memcg, false);
+		if (ret || !memcg)
 			/* mem_cgroup_clear_mc() will do uncharge later */
 			return -ENOMEM;
 		mc.precharge++;
@@ -5292,13 +5300,13 @@ static int mem_cgroup_can_attach(struct cgroup_subsys *ss,
 				struct task_struct *p)
 {
 	int ret = 0;
-	struct mem_cgroup *mem = mem_cgroup_from_cont(cgroup);
+	struct mem_cgroup *memcg = mem_cgroup_from_cont(cgroup);
 
-	if (mem->move_charge_at_immigrate) {
+	if (memcg->move_charge_at_immigrate) {
 		struct mm_struct *mm;
 		struct mem_cgroup *from = mem_cgroup_from_task(p);
 
-		VM_BUG_ON(from == mem);
+		VM_BUG_ON(from == memcg);
 
 		mm = get_task_mm(p);
 		if (!mm)
@@ -5313,7 +5321,7 @@ static int mem_cgroup_can_attach(struct cgroup_subsys *ss,
 			mem_cgroup_start_move(from);
 			spin_lock(&mc.lock);
 			mc.from = from;
-			mc.to = mem;
+			mc.to = memcg;
 			spin_unlock(&mc.lock);
 			/* We set mc.moving_task later */
 
diff --git a/mm/memory.c b/mm/memory.c
index a56e3ba..b2b8731 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1503,7 +1503,7 @@ split_fallthrough:
 	}
 
 	if (flags & FOLL_GET)
-		get_page(page);
+		get_page_foll(page);
 	if (flags & FOLL_TOUCH) {
 		if ((flags & FOLL_WRITE) &&
 		    !pte_dirty(pte) && !PageDirty(page))
diff --git a/mm/page_cgroup.c b/mm/page_cgroup.c
index 6bdc67d..2d123f9 100644
--- a/mm/page_cgroup.c
+++ b/mm/page_cgroup.c
@@ -133,10 +133,13 @@ struct page *lookup_cgroup_page(struct page_cgroup *pc)
 static void *__meminit alloc_page_cgroup(size_t size, int nid)
 {
 	void *addr = NULL;
+	gfp_t flags = GFP_KERNEL | __GFP_NOWARN;
 
-	addr = alloc_pages_exact_nid(nid, size, GFP_KERNEL | __GFP_NOWARN);
-	if (addr)
+	addr = alloc_pages_exact_nid(nid, size, flags);
+	if (addr) {
+		kmemleak_alloc(addr, size, 1, flags);
 		return addr;
+	}
 
 	if (node_state(nid, N_HIGH_MEMORY))
 		addr = vmalloc_node(size, nid);
@@ -357,7 +360,7 @@ struct swap_cgroup_ctrl {
 	spinlock_t	lock;
 };
 
-struct swap_cgroup_ctrl swap_cgroup_ctrl[MAX_SWAPFILES];
+static struct swap_cgroup_ctrl swap_cgroup_ctrl[MAX_SWAPFILES];
 
 struct swap_cgroup {
 	unsigned short		id;
diff --git a/mm/shmem.c b/mm/shmem.c
index fa4fa6c..45b9acb 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -2503,7 +2503,7 @@ struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags
 
 	d_instantiate(path.dentry, inode);
 	inode->i_size = size;
-	inode->i_nlink = 0;	/* It is unlinked */
+	clear_nlink(inode);	/* It is unlinked */
 #ifndef CONFIG_MMU
 	error = ramfs_nommu_expand_for_mapping(inode, size);
 	if (error)
diff --git a/mm/swap.c b/mm/swap.c
index 3a442f1..87627f1 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -78,39 +78,22 @@ static void put_compound_page(struct page *page)
 {
 	if (unlikely(PageTail(page))) {
 		/* __split_huge_page_refcount can run under us */
-		struct page *page_head = page->first_page;
-		smp_rmb();
-		/*
-		 * If PageTail is still set after smp_rmb() we can be sure
-		 * that the page->first_page we read wasn't a dangling pointer.
-		 * See __split_huge_page_refcount() smp_wmb().
-		 */
-		if (likely(PageTail(page) && get_page_unless_zero(page_head))) {
+		struct page *page_head = compound_trans_head(page);
+
+		if (likely(page != page_head &&
+			   get_page_unless_zero(page_head))) {
 			unsigned long flags;
 			/*
-			 * Verify that our page_head wasn't converted
-			 * to a a regular page before we got a
-			 * reference on it.
+			 * page_head wasn't a dangling pointer but it
+			 * may not be a head page anymore by the time
+			 * we obtain the lock. That is ok as long as it
+			 * can't be freed from under us.
 			 */
-			if (unlikely(!PageHead(page_head))) {
-				/* PageHead is cleared after PageTail */
-				smp_rmb();
-				VM_BUG_ON(PageTail(page));
-				goto out_put_head;
-			}
-			/*
-			 * Only run compound_lock on a valid PageHead,
-			 * after having it pinned with
-			 * get_page_unless_zero() above.
-			 */
-			smp_mb();
-			/* page_head wasn't a dangling pointer */
 			flags = compound_lock_irqsave(page_head);
 			if (unlikely(!PageTail(page))) {
 				/* __split_huge_page_refcount run before us */
 				compound_unlock_irqrestore(page_head, flags);
 				VM_BUG_ON(PageHead(page_head));
-			out_put_head:
 				if (put_page_testzero(page_head))
 					__put_single_page(page_head);
 			out_put_single:
@@ -121,16 +104,17 @@ static void put_compound_page(struct page *page)
 			VM_BUG_ON(page_head != page->first_page);
 			/*
 			 * We can release the refcount taken by
-			 * get_page_unless_zero now that
-			 * split_huge_page_refcount is blocked on the
-			 * compound_lock.
+			 * get_page_unless_zero() now that
+			 * __split_huge_page_refcount() is blocked on
+			 * the compound_lock.
 			 */
 			if (put_page_testzero(page_head))
 				VM_BUG_ON(1);
 			/* __split_huge_page_refcount will wait now */
-			VM_BUG_ON(atomic_read(&page->_count) <= 0);
-			atomic_dec(&page->_count);
+			VM_BUG_ON(page_mapcount(page) <= 0);
+			atomic_dec(&page->_mapcount);
 			VM_BUG_ON(atomic_read(&page_head->_count) <= 0);
+			VM_BUG_ON(atomic_read(&page->_count) != 0);
 			compound_unlock_irqrestore(page_head, flags);
 			if (put_page_testzero(page_head)) {
 				if (PageHead(page_head))
@@ -160,6 +144,45 @@ void put_page(struct page *page)
 }
 EXPORT_SYMBOL(put_page);
 
+/*
+ * This function is exported but must not be called by anything other
+ * than get_page(). It implements the slow path of get_page().
+ */
+bool __get_page_tail(struct page *page)
+{
+	/*
+	 * This takes care of get_page() if run on a tail page
+	 * returned by one of the get_user_pages/follow_page variants.
+	 * get_user_pages/follow_page itself doesn't need the compound
+	 * lock because it runs __get_page_tail_foll() under the
+	 * proper PT lock that already serializes against
+	 * split_huge_page().
+	 */
+	unsigned long flags;
+	bool got = false;
+	struct page *page_head = compound_trans_head(page);
+
+	if (likely(page != page_head && get_page_unless_zero(page_head))) {
+		/*
+		 * page_head wasn't a dangling pointer but it
+		 * may not be a head page anymore by the time
+		 * we obtain the lock. That is ok as long as it
+		 * can't be freed from under us.
+		 */
+		flags = compound_lock_irqsave(page_head);
+		/* here __split_huge_page_refcount won't run anymore */
+		if (likely(PageTail(page))) {
+			__get_page_tail_foll(page, false);
+			got = true;
+		}
+		compound_unlock_irqrestore(page_head, flags);
+		if (unlikely(!got))
+			put_page(page_head);
+	}
+	return got;
+}
+EXPORT_SYMBOL(__get_page_tail);
+
 /**
  * put_pages_list() - release a list of pages
  * @pages: list of pages threaded on page->lru
diff --git a/mm/vmscan.c b/mm/vmscan.c
index a90c603..132d1dd 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1767,7 +1767,7 @@ static int inactive_anon_is_low(struct zone *zone, struct scan_control *sc)
 	if (scanning_global_lru(sc))
 		low = inactive_anon_is_low_global(zone);
 	else
-		low = mem_cgroup_inactive_anon_is_low(sc->mem_cgroup);
+		low = mem_cgroup_inactive_anon_is_low(sc->mem_cgroup, zone);
 	return low;
 }
 #else
@@ -1810,7 +1810,7 @@ static int inactive_file_is_low(struct zone *zone, struct scan_control *sc)
 	if (scanning_global_lru(sc))
 		low = inactive_file_is_low_global(zone);
 	else
-		low = mem_cgroup_inactive_file_is_low(sc->mem_cgroup);
+		low = mem_cgroup_inactive_file_is_low(sc->mem_cgroup, zone);
 	return low;
 }
 
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 19c053b..4f554f2 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -9,7 +9,7 @@ config IMA
 	select CRYPTO_HMAC
 	select CRYPTO_MD5
 	select CRYPTO_SHA1
-	select TCG_TPM if !S390
+	select TCG_TPM if !S390 && !UML
 	select TCG_TIS if TCG_TPM
 	help
 	  The Trusted Computing Group(TCG) runtime Integrity
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index 150911c..c47d3ce 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -966,6 +966,9 @@ static bool tomoyo_manager(void)
 	return found;
 }
 
+static struct tomoyo_domain_info *tomoyo_find_domain_by_qid
+(unsigned int serial);
+
 /**
  * tomoyo_select_domain - Parse select command.
  *
@@ -999,6 +1002,8 @@ static bool tomoyo_select_domain(struct tomoyo_io_buffer *head,
 	} else if (!strncmp(data, "domain=", 7)) {
 		if (tomoyo_domain_def(data + 7))
 			domain = tomoyo_find_domain(data + 7);
+	} else if (sscanf(data, "Q=%u", &pid) == 1) {
+		domain = tomoyo_find_domain_by_qid(pid);
 	} else
 		return false;
 	head->w.domain = domain;
@@ -1894,6 +1899,7 @@ static DECLARE_WAIT_QUEUE_HEAD(tomoyo_answer_wait);
 /* Structure for query. */
 struct tomoyo_query {
 	struct list_head list;
+	struct tomoyo_domain_info *domain;
 	char *query;
 	size_t query_len;
 	unsigned int serial;
@@ -2044,6 +2050,7 @@ int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...)
 		goto out;
 	}
 	len = tomoyo_round2(entry.query_len);
+	entry.domain = r->domain;
 	spin_lock(&tomoyo_query_list_lock);
 	if (tomoyo_memory_quota[TOMOYO_MEMORY_QUERY] &&
 	    tomoyo_memory_used[TOMOYO_MEMORY_QUERY] + len
@@ -2091,6 +2098,29 @@ out:
 }
 
 /**
+ * tomoyo_find_domain_by_qid - Get domain by query id.
+ *
+ * @serial: Query ID assigned by tomoyo_supervisor().
+ *
+ * Returns pointer to "struct tomoyo_domain_info" if found, NULL otherwise.
+ */
+static struct tomoyo_domain_info *tomoyo_find_domain_by_qid
+(unsigned int serial)
+{
+	struct tomoyo_query *ptr;
+	struct tomoyo_domain_info *domain = NULL;
+	spin_lock(&tomoyo_query_list_lock);
+	list_for_each_entry(ptr, &tomoyo_query_list, list) {
+		if (ptr->serial != serial || ptr->answer)
+			continue;
+		domain = ptr->domain;
+		break;
+	}
+	spin_unlock(&tomoyo_query_list_lock);
+	return domain;
+}
+
+/**
  * tomoyo_poll_query - poll() for /sys/kernel/security/tomoyo/query.
  *
  * @file: Pointer to "struct file".
diff --git a/sound/Kconfig b/sound/Kconfig
index 1fef141..261a03c 100644
--- a/sound/Kconfig
+++ b/sound/Kconfig
@@ -59,7 +59,7 @@ config SOUND_OSS_CORE_PRECLAIM
 
 source "sound/oss/dmasound/Kconfig"
 
-if !M68K
+if !M68K && !UML
 
 menuconfig SND
 	tristate "Advanced Linux Sound Architecture"
