Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: (52 commits)
  split invalidate_inodes()
  fs: skip I_FREEING inodes in writeback_sb_inodes
  fs: fold invalidate_list into invalidate_inodes
  fs: do not drop inode_lock in dispose_list
  fs: inode split IO and LRU lists
  fs: switch bdev inode bdi's correctly
  fs: fix buffer invalidation in invalidate_list
  fsnotify: use dget_parent
  smbfs: use dget_parent
  exportfs: use dget_parent
  fs: use RCU read side protection in d_validate
  fs: clean up dentry lru modification
  fs: split __shrink_dcache_sb
  fs: improve DCACHE_REFERENCED usage
  fs: use percpu counter for nr_dentry and nr_dentry_unused
  fs: simplify __d_free
  fs: take dcache_lock inside __d_path
  fs: do not assign default i_ino in new_inode
  fs: introduce a per-cpu last_ino allocator
  new helper: ihold()
  ...
diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl
index feca075..22edcbb 100644
--- a/Documentation/DocBook/device-drivers.tmpl
+++ b/Documentation/DocBook/device-drivers.tmpl
@@ -51,8 +51,13 @@
      <sect1><title>Delaying, scheduling, and timer routines</title>
 !Iinclude/linux/sched.h
 !Ekernel/sched.c
+!Iinclude/linux/completion.h
 !Ekernel/timer.c
      </sect1>
+     <sect1><title>Wait queues and Wake events</title>
+!Iinclude/linux/wait.h
+!Ekernel/wait.c
+     </sect1>
      <sect1><title>High-resolution timers</title>
 !Iinclude/linux/ktime.h
 !Iinclude/linux/hrtimer.h
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index 6b4e07f..7160652 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -93,6 +93,12 @@
 !Elib/crc32.c
 !Elib/crc-ccitt.c
      </sect1>
+
+     <sect1 id="idr"><title>idr/ida Functions</title>
+!Pinclude/linux/idr.h idr sync
+!Plib/idr.c IDA description
+!Elib/idr.c
+     </sect1>
   </chapter>
 
   <chapter id="mm">
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index e833c8c..d2af87b 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -535,3 +535,13 @@
 Who:	Wey-Yi Guy <wey-yi.w.guy@intel.com>
 
 ----------------------------
+
+What:   access to nfsd auth cache through sys_nfsservctl or '.' files
+        in the 'nfsd' filesystem.
+When:   2.6.40
+Why:    This is a legacy interface which have been replaced by a more
+        dynamic cache.  Continuing to maintain this interface is an
+        unnecessary burden.
+Who:    NeilBrown <neilb@suse.de>
+
+----------------------------
diff --git a/Documentation/filesystems/nfs/00-INDEX b/Documentation/filesystems/nfs/00-INDEX
index 2f68cd6..a57e124 100644
--- a/Documentation/filesystems/nfs/00-INDEX
+++ b/Documentation/filesystems/nfs/00-INDEX
@@ -12,5 +12,9 @@
 	- how to install and setup the Linux NFS/RDMA client and server software
 nfsroot.txt
 	- short guide on setting up a diskless box with NFS root filesystem.
+pnfs.txt
+	- short explanation of some of the internals of the pnfs client code
 rpc-cache.txt
 	- introduction to the caching mechanisms in the sunrpc layer.
+idmapper.txt
+	- information for configuring request-keys to be used by idmapper
diff --git a/Documentation/filesystems/nfs/idmapper.txt b/Documentation/filesystems/nfs/idmapper.txt
new file mode 100644
index 0000000..b9b4192
--- /dev/null
+++ b/Documentation/filesystems/nfs/idmapper.txt
@@ -0,0 +1,67 @@
+
+=========
+ID Mapper
+=========
+Id mapper is used by NFS to translate user and group ids into names, and to
+translate user and group names into ids.  Part of this translation involves
+performing an upcall to userspace to request the information.  Id mapper will
+user request-key to perform this upcall and cache the result.  The program
+/usr/sbin/nfs.idmap should be called by request-key, and will perform the
+translation and initialize a key with the resulting information.
+
+ NFS_USE_NEW_IDMAPPER must be selected when configuring the kernel to use this
+ feature.
+
+===========
+Configuring
+===========
+The file /etc/request-key.conf will need to be modified so /sbin/request-key can
+direct the upcall.  The following line should be added:
+
+#OP	TYPE	DESCRIPTION	CALLOUT INFO	PROGRAM ARG1 ARG2 ARG3 ...
+#======	=======	===============	===============	===============================
+create	id_resolver	*	*		/usr/sbin/nfs.idmap %k %d 600
+
+This will direct all id_resolver requests to the program /usr/sbin/nfs.idmap.
+The last parameter, 600, defines how many seconds into the future the key will
+expire.  This parameter is optional for /usr/sbin/nfs.idmap.  When the timeout
+is not specified, nfs.idmap will default to 600 seconds.
+
+id mapper uses for key descriptions:
+	  uid:  Find the UID for the given user
+	  gid:  Find the GID for the given group
+	 user:  Find the user  name for the given UID
+	group:  Find the group name for the given GID
+
+You can handle any of these individually, rather than using the generic upcall
+program.  If you would like to use your own program for a uid lookup then you
+would edit your request-key.conf so it look similar to this:
+
+#OP	TYPE	DESCRIPTION	CALLOUT INFO	PROGRAM ARG1 ARG2 ARG3 ...
+#======	=======	===============	===============	===============================
+create	id_resolver	uid:*	*		/some/other/program %k %d 600
+create	id_resolver	*	*		/usr/sbin/nfs.idmap %k %d 600
+
+Notice that the new line was added above the line for the generic program.
+request-key will find the first matching line and corresponding program.  In
+this case, /some/other/program will handle all uid lookups and
+/usr/sbin/nfs.idmap will handle gid, user, and group lookups.
+
+See <file:Documentation/keys-request-keys.txt> for more information about the
+request-key function.
+
+
+=========
+nfs.idmap
+=========
+nfs.idmap is designed to be called by request-key, and should not be run "by
+hand".  This program takes two arguments, a serialized key and a key
+description.  The serialized key is first converted into a key_serial_t, and
+then passed as an argument to keyctl_instantiate (both are part of keyutils.h).
+
+The actual lookups are performed by functions found in nfsidmap.h.  nfs.idmap
+determines the correct function to call by looking at the first part of the
+description string.  For example, a uid lookup description will appear as
+"uid:user@domain".
+
+nfs.idmap will return 0 if the key was instantiated, and non-zero otherwise.
diff --git a/Documentation/filesystems/nfs/nfsroot.txt b/Documentation/filesystems/nfs/nfsroot.txt
index f2430a7..90c71c6 100644
--- a/Documentation/filesystems/nfs/nfsroot.txt
+++ b/Documentation/filesystems/nfs/nfsroot.txt
@@ -159,6 +159,28 @@
                 Default: any
 
 
+nfsrootdebug
+
+  This parameter enables debugging messages to appear in the kernel
+  log at boot time so that administrators can verify that the correct
+  NFS mount options, server address, and root path are passed to the
+  NFS client.
+
+
+rdinit=<executable file>
+
+  To specify which file contains the program that starts system
+  initialization, administrators can use this command line parameter.
+  The default value of this parameter is "/init".  If the specified
+  file exists and the kernel can execute it, root filesystem related
+  kernel command line parameters, including `nfsroot=', are ignored.
+
+  A description of the process of mounting the root file system can be
+  found in:
+
+    Documentation/early-userspace/README
+
+
 
 
 3.) Boot Loader
diff --git a/Documentation/filesystems/nfs/pnfs.txt b/Documentation/filesystems/nfs/pnfs.txt
new file mode 100644
index 0000000..bc0b9cf
--- /dev/null
+++ b/Documentation/filesystems/nfs/pnfs.txt
@@ -0,0 +1,48 @@
+Reference counting in pnfs:
+==========================
+
+The are several inter-related caches.  We have layouts which can
+reference multiple devices, each of which can reference multiple data servers.
+Each data server can be referenced by multiple devices.  Each device
+can be referenced by multiple layouts.  To keep all of this straight,
+we need to reference count.
+
+
+struct pnfs_layout_hdr
+----------------------
+The on-the-wire command LAYOUTGET corresponds to struct
+pnfs_layout_segment, usually referred to by the variable name lseg.
+Each nfs_inode may hold a pointer to a cache of of these layout
+segments in nfsi->layout, of type struct pnfs_layout_hdr.
+
+We reference the header for the inode pointing to it, across each
+outstanding RPC call that references it (LAYOUTGET, LAYOUTRETURN,
+LAYOUTCOMMIT), and for each lseg held within.
+
+Each header is also (when non-empty) put on a list associated with
+struct nfs_client (cl_layouts).  Being put on this list does not bump
+the reference count, as the layout is kept around by the lseg that
+keeps it in the list.
+
+deviceid_cache
+--------------
+lsegs reference device ids, which are resolved per nfs_client and
+layout driver type.  The device ids are held in a RCU cache (struct
+nfs4_deviceid_cache).  The cache itself is referenced across each
+mount.  The entries (struct nfs4_deviceid) themselves are held across
+the lifetime of each lseg referencing them.
+
+RCU is used because the deviceid is basically a write once, read many
+data structure.  The hlist size of 32 buckets needs better
+justification, but seems reasonable given that we can have multiple
+deviceid's per filesystem, and multiple filesystems per nfs_client.
+
+The hash code is copied from the nfsd code base.  A discussion of
+hashing and variations of this algorithm can be found at:
+http://groups.google.com/group/comp.lang.c/browse_thread/thread/9522965e2b8d3809
+
+data server cache
+-----------------
+file driver devices refer to data servers, which are kept in a module
+level cache.  Its reference is held over the lifetime of the deviceid
+pointing to it.
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index a6aca87..a563b74 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -374,13 +374,13 @@
 KernelPageSize:        4 kB
 MMUPageSize:           4 kB
 
-The first  of these lines shows  the same information  as is displayed for the
-mapping in /proc/PID/maps.  The remaining lines show  the size of the mapping,
-the amount of the mapping that is currently resident in RAM, the "proportional
-set size” (divide each shared page by the number of processes sharing it), the
-number of clean and dirty shared pages in the mapping, and the number of clean
-and dirty private pages in the mapping.  The "Referenced" indicates the amount
-of memory currently marked as referenced or accessed.
+The first of these lines shows the same information as is displayed for the
+mapping in /proc/PID/maps.  The remaining lines show the size of the mapping
+(size), the amount of the mapping that is currently resident in RAM (RSS), the
+process' proportional share of this mapping (PSS), the number of clean and
+dirty shared pages in the mapping, and the number of clean and dirty private
+pages in the mapping.  The "Referenced" indicates the amount of memory
+currently marked as referenced or accessed.
 
 This file is only present if the CONFIG_MMU kernel configuration option is
 enabled.
diff --git a/Documentation/hwmon/ltc4261 b/Documentation/hwmon/ltc4261
new file mode 100644
index 0000000..eba2e2c
--- /dev/null
+++ b/Documentation/hwmon/ltc4261
@@ -0,0 +1,63 @@
+Kernel driver ltc4261
+=====================
+
+Supported chips:
+  * Linear Technology LTC4261
+    Prefix: 'ltc4261'
+    Addresses scanned: -
+    Datasheet:
+        http://cds.linear.com/docs/Datasheet/42612fb.pdf
+
+Author: Guenter Roeck <guenter.roeck@ericsson.com>
+
+
+Description
+-----------
+
+The LTC4261/LTC4261-2 negative voltage Hot Swap controllers allow a board
+to be safely inserted and removed from a live backplane.
+
+
+Usage Notes
+-----------
+
+This driver does not probe for LTC4261 devices, since there is no register
+which can be safely used to identify the chip. You will have to instantiate
+the devices explicitly.
+
+Example: the following will load the driver for an LTC4261 at address 0x10
+on I2C bus #1:
+$ modprobe ltc4261
+$ echo ltc4261 0x10 > /sys/bus/i2c/devices/i2c-1/new_device
+
+
+Sysfs entries
+-------------
+
+Voltage readings provided by this driver are reported as obtained from the ADC
+registers. If a set of voltage divider resistors is installed, calculate the
+real voltage by multiplying the reported value with (R1+R2)/R2, where R1 is the
+value of the divider resistor against the measured voltage and R2 is the value
+of the divider resistor against Ground.
+
+Current reading provided by this driver is reported as obtained from the ADC
+Current Sense register. The reported value assumes that a 1 mOhm sense resistor
+is installed. If a different sense resistor is installed, calculate the real
+current by dividing the reported value by the sense resistor value in mOhm.
+
+The chip has two voltage sensors, but only one set of voltage alarm status bits.
+In many many designs, those alarms are associated with the ADIN2 sensor, due to
+the proximity of the ADIN2 pin to the OV pin. ADIN2 is, however, not available
+on all chip variants. To ensure that the alarm condition is reported to the user,
+report it with both voltage sensors.
+
+in1_input		ADIN2 voltage (mV)
+in1_min_alarm		ADIN/ADIN2 Undervoltage alarm
+in1_max_alarm		ADIN/ADIN2 Overvoltage alarm
+
+in2_input		ADIN voltage (mV)
+in2_min_alarm		ADIN/ADIN2 Undervoltage alarm
+in2_max_alarm		ADIN/ADIN2 Overvoltage alarm
+
+curr1_input		SENSE current (mA)
+curr1_alarm		SENSE overcurrent alarm
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index b660085..4bc2f3c 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1541,12 +1541,15 @@
 			1 to enable accounting
 			Default value is 0.
 
-	nfsaddrs=	[NFS]
+	nfsaddrs=	[NFS] Deprecated.  Use ip= instead.
 			See Documentation/filesystems/nfs/nfsroot.txt.
 
 	nfsroot=	[NFS] nfs root filesystem for disk-less boxes.
 			See Documentation/filesystems/nfs/nfsroot.txt.
 
+	nfsrootdebug	[NFS] enable nfsroot debugging messages.
+			See Documentation/filesystems/nfs/nfsroot.txt.
+
 	nfs.callback_tcpport=
 			[NFS] set the TCP port on which the NFSv4 callback
 			channel should listen.
diff --git a/Documentation/misc-devices/apds990x.txt b/Documentation/misc-devices/apds990x.txt
new file mode 100644
index 0000000..d5408ca
--- /dev/null
+++ b/Documentation/misc-devices/apds990x.txt
@@ -0,0 +1,111 @@
+Kernel driver apds990x
+======================
+
+Supported chips:
+Avago APDS990X
+
+Data sheet:
+Not freely available
+
+Author:
+Samu Onkalo <samu.p.onkalo@nokia.com>
+
+Description
+-----------
+
+APDS990x is a combined ambient light and proximity sensor. ALS and proximity
+functionality are highly connected. ALS measurement path must be running
+while the proximity functionality is enabled.
+
+ALS produces raw measurement values for two channels: Clear channel
+(infrared + visible light) and IR only. However, threshold comparisons happen
+using clear channel only. Lux value and the threshold level on the HW
+might vary quite much depending the spectrum of the light source.
+
+Driver makes necessary conversions to both directions so that user handles
+only lux values. Lux value is calculated using information from the both
+channels. HW threshold level is calculated from the given lux value to match
+with current type of the lightning. Sometimes inaccuracy of the estimations
+lead to false interrupt, but that doesn't harm.
+
+ALS contains 4 different gain steps. Driver automatically
+selects suitable gain step. After each measurement, reliability of the results
+is estimated and new measurement is trigged if necessary.
+
+Platform data can provide tuned values to the conversion formulas if
+values are known. Otherwise plain sensor default values are used.
+
+Proximity side is little bit simpler. There is no need for complex conversions.
+It produces directly usable values.
+
+Driver controls chip operational state using pm_runtime framework.
+Voltage regulators are controlled based on chip operational state.
+
+SYSFS
+-----
+
+
+chip_id
+	RO - shows detected chip type and version
+
+power_state
+	RW - enable / disable chip. Uses counting logic
+	     1 enables the chip
+	     0 disables the chip
+lux0_input
+	RO - measured lux value
+	     sysfs_notify called when threshold interrupt occurs
+
+lux0_sensor_range
+	RO - lux0_input max value. Actually never reaches since sensor tends
+	     to saturate much before that. Real max value varies depending
+	     on the light spectrum etc.
+
+lux0_rate
+	RW - measurement rate in Hz
+
+lux0_rate_avail
+	RO - supported measurement rates
+
+lux0_calibscale
+	RW - calibration value. Set to neutral value by default.
+	     Output results are multiplied with calibscale / calibscale_default
+	     value.
+
+lux0_calibscale_default
+	RO - neutral calibration value
+
+lux0_thresh_above_value
+	RW - HI level threshold value. All results above the value
+	     trigs an interrupt. 65535 (i.e. sensor_range) disables the above
+	     interrupt.
+
+lux0_thresh_below_value
+	RW - LO level threshold value. All results below the value
+	     trigs an interrupt. 0 disables the below interrupt.
+
+prox0_raw
+	RO - measured proximity value
+	     sysfs_notify called when threshold interrupt occurs
+
+prox0_sensor_range
+	RO - prox0_raw max value (1023)
+
+prox0_raw_en
+	RW - enable / disable proximity - uses counting logic
+	     1 enables the proximity
+	     0 disables the proximity
+
+prox0_reporting_mode
+	RW - trigger / periodic. In "trigger" mode the driver tells two possible
+	     values: 0 or prox0_sensor_range value. 0 means no proximity,
+	     1023 means proximity. This causes minimal number of interrupts.
+	     In "periodic" mode the driver reports all values above
+	     prox0_thresh_above. This causes more interrupts, but it can give
+	     _rough_ estimate about the distance.
+
+prox0_reporting_mode_avail
+	RO - accepted values to prox0_reporting_mode (trigger, periodic)
+
+prox0_thresh_above_value
+	RW - threshold level which trigs proximity events.
diff --git a/Documentation/misc-devices/bh1770glc.txt b/Documentation/misc-devices/bh1770glc.txt
new file mode 100644
index 0000000..7d64c01
--- /dev/null
+++ b/Documentation/misc-devices/bh1770glc.txt
@@ -0,0 +1,116 @@
+Kernel driver bh1770glc
+=======================
+
+Supported chips:
+ROHM BH1770GLC
+OSRAM SFH7770
+
+Data sheet:
+Not freely available
+
+Author:
+Samu Onkalo <samu.p.onkalo@nokia.com>
+
+Description
+-----------
+BH1770GLC and SFH7770 are combined ambient light and proximity sensors.
+ALS and proximity parts operates on their own, but they shares common I2C
+interface and interrupt logic. In principle they can run on their own,
+but ALS side results are used to estimate reliability of the proximity sensor.
+
+ALS produces 16 bit lux values. The chip contains interrupt logic to produce
+low and high threshold interrupts.
+
+Proximity part contains IR-led driver up to 3 IR leds. The chip measures
+amount of reflected IR light and produces proximity result. Resolution is
+8 bit. Driver supports only one channel. Driver uses ALS results to estimate
+reliability of the proximity results. Thus ALS is always running while
+proximity detection is needed.
+
+Driver uses threshold interrupts to avoid need for polling the values.
+Proximity low interrupt doesn't exists in the chip. This is simulated
+by using a delayed work. As long as there is proximity threshold above
+interrupts the delayed work is pushed forward. So, when proximity level goes
+below the threshold value, there is no interrupt and the delayed work will
+finally run. This is handled as no proximity indication.
+
+Chip state is controlled via runtime pm framework when enabled in config.
+
+Calibscale factor is used to hide differences between the chips. By default
+value set to neutral state meaning factor of 1.00. To get proper values,
+calibrated source of light is needed as a reference. Calibscale factor is set
+so that measurement produces about the expected lux value.
+
+SYSFS
+-----
+
+chip_id
+	RO - shows detected chip type and version
+
+power_state
+	RW - enable / disable chip. Uses counting logic
+	     1 enables the chip
+	     0 disables the chip
+
+lux0_input
+	RO - measured lux value
+	     sysfs_notify called when threshold interrupt occurs
+
+lux0_sensor_range
+	RO - lux0_input max value
+
+lux0_rate
+	RW - measurement rate in Hz
+
+lux0_rate_avail
+	RO - supported measurement rates
+
+lux0_thresh_above_value
+	RW - HI level threshold value. All results above the value
+	     trigs an interrupt. 65535 (i.e. sensor_range) disables the above
+	     interrupt.
+
+lux0_thresh_below_value
+	RW - LO level threshold value. All results below the value
+	     trigs an interrupt. 0 disables the below interrupt.
+
+lux0_calibscale
+	RW - calibration value. Set to neutral value by default.
+	     Output results are multiplied with calibscale / calibscale_default
+	     value.
+
+lux0_calibscale_default
+	RO - neutral calibration value
+
+prox0_raw
+	RO - measured proximity value
+	     sysfs_notify called when threshold interrupt occurs
+
+prox0_sensor_range
+	RO - prox0_raw max value
+
+prox0_raw_en
+	RW - enable / disable proximity - uses counting logic
+	     1 enables the proximity
+	     0 disables the proximity
+
+prox0_thresh_above_count
+	RW - number of proximity interrupts needed before triggering the event
+
+prox0_rate_above
+	RW - Measurement rate (in Hz) when the level is above threshold
+	     i.e. when proximity on has been reported.
+
+prox0_rate_below
+	RW - Measurement rate (in Hz) when the level is below threshold
+	     i.e. when proximity off has been reported.
+
+prox0_rate_avail
+	RO - Supported proximity measurement rates in Hz
+
+prox0_thresh_above0_value
+	RW - threshold level which trigs proximity events.
+	     Filtered by persistence filter (prox0_thresh_above_count)
+
+prox0_thresh_above1_value
+	RW - threshold level which trigs event immediately
diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt
index 5c17196..312e375 100644
--- a/Documentation/sysrq.txt
+++ b/Documentation/sysrq.txt
@@ -75,7 +75,7 @@
 
 'f'	- Will call oom_kill to kill a memory hog process.
 
-'g'	- Used by kgdb on ppc and sh platforms.
+'g'	- Used by kgdb (kernel debugger)
 
 'h'     - Will display help (actually any other key than those listed
           here will display help. but 'h' is easy to remember :-)
@@ -110,12 +110,15 @@
 
 'u'     - Will attempt to remount all mounted filesystems read-only.
 
-'v'	- Dumps Voyager SMP processor info to your console.
+'v'	- Forcefully restores framebuffer console
+'v'	- Causes ETM buffer dump [ARM-specific]
 
 'w'	- Dumps tasks that are in uninterruptable (blocked) state.
 
 'x'	- Used by xmon interface on ppc/powerpc platforms.
 
+'y'	- Show global CPU Registers [SPARC-64 specific]
+
 'z'	- Dump the ftrace buffer
 
 '0'-'9' - Sets the console log level, controlling which kernel messages
diff --git a/Documentation/timers/hpet_example.c b/Documentation/timers/hpet_example.c
index 4bfafb7..9a3e701 100644
--- a/Documentation/timers/hpet_example.c
+++ b/Documentation/timers/hpet_example.c
@@ -97,6 +97,33 @@
 void
 hpet_info(int argc, const char **argv)
 {
+	struct hpet_info	info;
+	int			fd;
+
+	if (argc != 1) {
+		fprintf(stderr, "hpet_info: device-name\n");
+		return;
+	}
+
+	fd = open(argv[0], O_RDONLY);
+	if (fd < 0) {
+		fprintf(stderr, "hpet_info: open of %s failed\n", argv[0]);
+		return;
+	}
+
+	if (ioctl(fd, HPET_INFO, &info) < 0) {
+		fprintf(stderr, "hpet_info: failed to get info\n");
+		goto out;
+	}
+
+	fprintf(stderr, "hpet_info: hi_irqfreq 0x%lx hi_flags 0x%lx ",
+		info.hi_ireqfreq, info.hi_flags);
+	fprintf(stderr, "hi_hpet %d hi_timer %d\n",
+		info.hi_hpet, info.hi_timer);
+
+out:
+	close(fd);
+	return;
 }
 
 void
diff --git a/Documentation/trace/postprocess/trace-vmscan-postprocess.pl b/Documentation/trace/postprocess/trace-vmscan-postprocess.pl
index 1b55146..b3e73dd 100644
--- a/Documentation/trace/postprocess/trace-vmscan-postprocess.pl
+++ b/Documentation/trace/postprocess/trace-vmscan-postprocess.pl
@@ -46,7 +46,7 @@
 use constant HIGH_KSWAPD_REWAKEUP		=> 21;
 use constant HIGH_NR_SCANNED			=> 22;
 use constant HIGH_NR_TAKEN			=> 23;
-use constant HIGH_NR_RECLAIM			=> 24;
+use constant HIGH_NR_RECLAIMED			=> 24;
 use constant HIGH_NR_CONTIG_DIRTY		=> 25;
 
 my %perprocesspid;
@@ -58,11 +58,13 @@
 my $total_wakeup_kswapd;
 my ($total_direct_reclaim, $total_direct_nr_scanned);
 my ($total_direct_latency, $total_kswapd_latency);
+my ($total_direct_nr_reclaimed);
 my ($total_direct_writepage_file_sync, $total_direct_writepage_file_async);
 my ($total_direct_writepage_anon_sync, $total_direct_writepage_anon_async);
 my ($total_kswapd_nr_scanned, $total_kswapd_wake);
 my ($total_kswapd_writepage_file_sync, $total_kswapd_writepage_file_async);
 my ($total_kswapd_writepage_anon_sync, $total_kswapd_writepage_anon_async);
+my ($total_kswapd_nr_reclaimed);
 
 # Catch sigint and exit on request
 my $sigint_report = 0;
@@ -104,7 +106,7 @@
 my $regex_kswapd_sleep_default = 'nid=([0-9]*)';
 my $regex_wakeup_kswapd_default = 'nid=([0-9]*) zid=([0-9]*) order=([0-9]*)';
 my $regex_lru_isolate_default = 'isolate_mode=([0-9]*) order=([0-9]*) nr_requested=([0-9]*) nr_scanned=([0-9]*) nr_taken=([0-9]*) contig_taken=([0-9]*) contig_dirty=([0-9]*) contig_failed=([0-9]*)';
-my $regex_lru_shrink_inactive_default = 'lru=([A-Z_]*) nr_scanned=([0-9]*) nr_reclaimed=([0-9]*) priority=([0-9]*)';
+my $regex_lru_shrink_inactive_default = 'nid=([0-9]*) zid=([0-9]*) nr_scanned=([0-9]*) nr_reclaimed=([0-9]*) priority=([0-9]*) flags=([A-Z_|]*)';
 my $regex_lru_shrink_active_default = 'lru=([A-Z_]*) nr_scanned=([0-9]*) nr_rotated=([0-9]*) priority=([0-9]*)';
 my $regex_writepage_default = 'page=([0-9a-f]*) pfn=([0-9]*) flags=([A-Z_|]*)';
 
@@ -203,8 +205,8 @@
 			"vmscan/mm_vmscan_lru_shrink_inactive",
 			$regex_lru_shrink_inactive_default,
 			"nid", "zid",
-			"lru",
-			"nr_scanned", "nr_reclaimed", "priority");
+			"nr_scanned", "nr_reclaimed", "priority",
+			"flags");
 $regex_lru_shrink_active = generate_traceevent_regex(
 			"vmscan/mm_vmscan_lru_shrink_active",
 			$regex_lru_shrink_active_default,
@@ -375,6 +377,16 @@
 			my $nr_contig_dirty = $7;
 			$perprocesspid{$process_pid}->{HIGH_NR_SCANNED} += $nr_scanned;
 			$perprocesspid{$process_pid}->{HIGH_NR_CONTIG_DIRTY} += $nr_contig_dirty;
+		} elsif ($tracepoint eq "mm_vmscan_lru_shrink_inactive") {
+			$details = $5;
+			if ($details !~ /$regex_lru_shrink_inactive/o) {
+				print "WARNING: Failed to parse mm_vmscan_lru_shrink_inactive as expected\n";
+				print "         $details\n";
+				print "         $regex_lru_shrink_inactive/o\n";
+				next;
+			}
+			my $nr_reclaimed = $4;
+			$perprocesspid{$process_pid}->{HIGH_NR_RECLAIMED} += $nr_reclaimed;
 		} elsif ($tracepoint eq "mm_vmscan_writepage") {
 			$details = $5;
 			if ($details !~ /$regex_writepage/o) {
@@ -464,8 +476,8 @@
 
 	# Print out process activity
 	printf("\n");
-	printf("%-" . $max_strlen . "s %8s %10s   %8s   %8s %8s %8s %8s\n", "Process", "Direct",  "Wokeup", "Pages",   "Pages",   "Pages",     "Time");
-	printf("%-" . $max_strlen . "s %8s %10s   %8s   %8s %8s %8s %8s\n", "details", "Rclms",   "Kswapd", "Scanned", "Sync-IO", "ASync-IO",  "Stalled");
+	printf("%-" . $max_strlen . "s %8s %10s   %8s %8s  %8s %8s %8s %8s\n", "Process", "Direct",  "Wokeup", "Pages",   "Pages",   "Pages",   "Pages",     "Time");
+	printf("%-" . $max_strlen . "s %8s %10s   %8s %8s  %8s %8s %8s %8s\n", "details", "Rclms",   "Kswapd", "Scanned", "Rclmed",  "Sync-IO", "ASync-IO",  "Stalled");
 	foreach $process_pid (keys %stats) {
 
 		if (!$stats{$process_pid}->{MM_VMSCAN_DIRECT_RECLAIM_BEGIN}) {
@@ -475,6 +487,7 @@
 		$total_direct_reclaim += $stats{$process_pid}->{MM_VMSCAN_DIRECT_RECLAIM_BEGIN};
 		$total_wakeup_kswapd += $stats{$process_pid}->{MM_VMSCAN_WAKEUP_KSWAPD};
 		$total_direct_nr_scanned += $stats{$process_pid}->{HIGH_NR_SCANNED};
+		$total_direct_nr_reclaimed += $stats{$process_pid}->{HIGH_NR_RECLAIMED};
 		$total_direct_writepage_file_sync += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC};
 		$total_direct_writepage_anon_sync += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC};
 		$total_direct_writepage_file_async += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC};
@@ -489,11 +502,12 @@
 			$index++;
 		}
 
-		printf("%-" . $max_strlen . "s %8d %10d   %8u   %8u %8u %8.3f",
+		printf("%-" . $max_strlen . "s %8d %10d   %8u %8u  %8u %8u %8.3f",
 			$process_pid,
 			$stats{$process_pid}->{MM_VMSCAN_DIRECT_RECLAIM_BEGIN},
 			$stats{$process_pid}->{MM_VMSCAN_WAKEUP_KSWAPD},
 			$stats{$process_pid}->{HIGH_NR_SCANNED},
+			$stats{$process_pid}->{HIGH_NR_RECLAIMED},
 			$stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC} + $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC},
 			$stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC} + $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_ASYNC},
 			$this_reclaim_delay / 1000);
@@ -529,8 +543,8 @@
 
 	# Print out kswapd activity
 	printf("\n");
-	printf("%-" . $max_strlen . "s %8s %10s   %8s   %8s %8s %8s\n", "Kswapd",   "Kswapd",  "Order",     "Pages",   "Pages",  "Pages");
-	printf("%-" . $max_strlen . "s %8s %10s   %8s   %8s %8s %8s\n", "Instance", "Wakeups", "Re-wakeup", "Scanned", "Sync-IO", "ASync-IO");
+	printf("%-" . $max_strlen . "s %8s %10s   %8s   %8s %8s %8s\n", "Kswapd",   "Kswapd",  "Order",     "Pages",   "Pages",   "Pages",  "Pages");
+	printf("%-" . $max_strlen . "s %8s %10s   %8s   %8s %8s %8s\n", "Instance", "Wakeups", "Re-wakeup", "Scanned", "Rclmed",  "Sync-IO", "ASync-IO");
 	foreach $process_pid (keys %stats) {
 
 		if (!$stats{$process_pid}->{MM_VMSCAN_KSWAPD_WAKE}) {
@@ -539,16 +553,18 @@
 
 		$total_kswapd_wake += $stats{$process_pid}->{MM_VMSCAN_KSWAPD_WAKE};
 		$total_kswapd_nr_scanned += $stats{$process_pid}->{HIGH_NR_SCANNED};
+		$total_kswapd_nr_reclaimed += $stats{$process_pid}->{HIGH_NR_RECLAIMED};
 		$total_kswapd_writepage_file_sync += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC};
 		$total_kswapd_writepage_anon_sync += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC};
 		$total_kswapd_writepage_file_async += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC};
 		$total_kswapd_writepage_anon_async += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_ASYNC};
 
-		printf("%-" . $max_strlen . "s %8d %10d   %8u   %8i %8u",
+		printf("%-" . $max_strlen . "s %8d %10d   %8u %8u  %8i %8u",
 			$process_pid,
 			$stats{$process_pid}->{MM_VMSCAN_KSWAPD_WAKE},
 			$stats{$process_pid}->{HIGH_KSWAPD_REWAKEUP},
 			$stats{$process_pid}->{HIGH_NR_SCANNED},
+			$stats{$process_pid}->{HIGH_NR_RECLAIMED},
 			$stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC} + $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC},
 			$stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC} + $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_ASYNC});
 
@@ -579,6 +595,7 @@
 	print "\nSummary\n";
 	print "Direct reclaims:     			$total_direct_reclaim\n";
 	print "Direct reclaim pages scanned:		$total_direct_nr_scanned\n";
+	print "Direct reclaim pages reclaimed:		$total_direct_nr_reclaimed\n";
 	print "Direct reclaim write file sync I/O:	$total_direct_writepage_file_sync\n";
 	print "Direct reclaim write anon sync I/O:	$total_direct_writepage_anon_sync\n";
 	print "Direct reclaim write file async I/O:	$total_direct_writepage_file_async\n";
@@ -588,6 +605,7 @@
 	print "\n";
 	print "Kswapd wakeups:				$total_kswapd_wake\n";
 	print "Kswapd pages scanned:			$total_kswapd_nr_scanned\n";
+	print "Kswapd pages reclaimed:			$total_kswapd_nr_reclaimed\n";
 	print "Kswapd reclaim write file sync I/O:	$total_kswapd_writepage_file_sync\n";
 	print "Kswapd reclaim write anon sync I/O:	$total_kswapd_writepage_anon_sync\n";
 	print "Kswapd reclaim write file async I/O:	$total_kswapd_writepage_file_async\n";
@@ -612,6 +630,7 @@
 		$perprocess{$process}->{MM_VMSCAN_WAKEUP_KSWAPD} += $perprocesspid{$process_pid}->{MM_VMSCAN_WAKEUP_KSWAPD};
 		$perprocess{$process}->{HIGH_KSWAPD_REWAKEUP} += $perprocesspid{$process_pid}->{HIGH_KSWAPD_REWAKEUP};
 		$perprocess{$process}->{HIGH_NR_SCANNED} += $perprocesspid{$process_pid}->{HIGH_NR_SCANNED};
+		$perprocess{$process}->{HIGH_NR_RECLAIMED} += $perprocesspid{$process_pid}->{HIGH_NR_RECLAIMED};
 		$perprocess{$process}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC} += $perprocesspid{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC};
 		$perprocess{$process}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC} += $perprocesspid{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC};
 		$perprocess{$process}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC} += $perprocesspid{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC};
diff --git a/Documentation/vm/highmem.txt b/Documentation/vm/highmem.txt
new file mode 100644
index 0000000..4324d24
--- /dev/null
+++ b/Documentation/vm/highmem.txt
@@ -0,0 +1,162 @@
+
+			     ====================
+			     HIGH MEMORY HANDLING
+			     ====================
+
+By: Peter Zijlstra <a.p.zijlstra@chello.nl>
+
+Contents:
+
+ (*) What is high memory?
+
+ (*) Temporary virtual mappings.
+
+ (*) Using kmap_atomic.
+
+ (*) Cost of temporary mappings.
+
+ (*) i386 PAE.
+
+
+====================
+WHAT IS HIGH MEMORY?
+====================
+
+High memory (highmem) is used when the size of physical memory approaches or
+exceeds the maximum size of virtual memory.  At that point it becomes
+impossible for the kernel to keep all of the available physical memory mapped
+at all times.  This means the kernel needs to start using temporary mappings of
+the pieces of physical memory that it wants to access.
+
+The part of (physical) memory not covered by a permanent mapping is what we
+refer to as 'highmem'.  There are various architecture dependent constraints on
+where exactly that border lies.
+
+In the i386 arch, for example, we choose to map the kernel into every process's
+VM space so that we don't have to pay the full TLB invalidation costs for
+kernel entry/exit.  This means the available virtual memory space (4GiB on
+i386) has to be divided between user and kernel space.
+
+The traditional split for architectures using this approach is 3:1, 3GiB for
+userspace and the top 1GiB for kernel space:
+
+		+--------+ 0xffffffff
+		| Kernel |
+		+--------+ 0xc0000000
+		|        |
+		| User   |
+		|        |
+		+--------+ 0x00000000
+
+This means that the kernel can at most map 1GiB of physical memory at any one
+time, but because we need virtual address space for other things - including
+temporary maps to access the rest of the physical memory - the actual direct
+map will typically be less (usually around ~896MiB).
+
+Other architectures that have mm context tagged TLBs can have separate kernel
+and user maps.  Some hardware (like some ARMs), however, have limited virtual
+space when they use mm context tags.
+
+
+==========================
+TEMPORARY VIRTUAL MAPPINGS
+==========================
+
+The kernel contains several ways of creating temporary mappings:
+
+ (*) vmap().  This can be used to make a long duration mapping of multiple
+     physical pages into a contiguous virtual space.  It needs global
+     synchronization to unmap.
+
+ (*) kmap().  This permits a short duration mapping of a single page.  It needs
+     global synchronization, but is amortized somewhat.  It is also prone to
+     deadlocks when using in a nested fashion, and so it is not recommended for
+     new code.
+
+ (*) kmap_atomic().  This permits a very short duration mapping of a single
+     page.  Since the mapping is restricted to the CPU that issued it, it
+     performs well, but the issuing task is therefore required to stay on that
+     CPU until it has finished, lest some other task displace its mappings.
+
+     kmap_atomic() may also be used by interrupt contexts, since it is does not
+     sleep and the caller may not sleep until after kunmap_atomic() is called.
+
+     It may be assumed that k[un]map_atomic() won't fail.
+
+
+=================
+USING KMAP_ATOMIC
+=================
+
+When and where to use kmap_atomic() is straightforward.  It is used when code
+wants to access the contents of a page that might be allocated from high memory
+(see __GFP_HIGHMEM), for example a page in the pagecache.  The API has two
+functions, and they can be used in a manner similar to the following:
+
+	/* Find the page of interest. */
+	struct page *page = find_get_page(mapping, offset);
+
+	/* Gain access to the contents of that page. */
+	void *vaddr = kmap_atomic(page);
+
+	/* Do something to the contents of that page. */
+	memset(vaddr, 0, PAGE_SIZE);
+
+	/* Unmap that page. */
+	kunmap_atomic(vaddr);
+
+Note that the kunmap_atomic() call takes the result of the kmap_atomic() call
+not the argument.
+
+If you need to map two pages because you want to copy from one page to
+another you need to keep the kmap_atomic calls strictly nested, like:
+
+	vaddr1 = kmap_atomic(page1);
+	vaddr2 = kmap_atomic(page2);
+
+	memcpy(vaddr1, vaddr2, PAGE_SIZE);
+
+	kunmap_atomic(vaddr2);
+	kunmap_atomic(vaddr1);
+
+
+==========================
+COST OF TEMPORARY MAPPINGS
+==========================
+
+The cost of creating temporary mappings can be quite high.  The arch has to
+manipulate the kernel's page tables, the data TLB and/or the MMU's registers.
+
+If CONFIG_HIGHMEM is not set, then the kernel will try and create a mapping
+simply with a bit of arithmetic that will convert the page struct address into
+a pointer to the page contents rather than juggling mappings about.  In such a
+case, the unmap operation may be a null operation.
+
+If CONFIG_MMU is not set, then there can be no temporary mappings and no
+highmem.  In such a case, the arithmetic approach will also be used.
+
+
+========
+i386 PAE
+========
+
+The i386 arch, under some circumstances, will permit you to stick up to 64GiB
+of RAM into your 32-bit machine.  This has a number of consequences:
+
+ (*) Linux needs a page-frame structure for each page in the system and the
+     pageframes need to live in the permanent mapping, which means:
+
+ (*) you can have 896M/sizeof(struct page) page-frames at most; with struct
+     page being 32-bytes that would end up being something in the order of 112G
+     worth of pages; the kernel, however, needs to store more than just
+     page-frames in that memory...
+
+ (*) PAE makes your page tables larger - which slows the system down as more
+     data has to be accessed to traverse in TLB fills and the like.  One
+     advantage is that PAE has more PTE bits and can provide advanced features
+     like NX and PAT.
+
+The general recommendation is that you don't use more than 8GiB on a 32-bit
+machine - although more might work for you and your workload, you're pretty
+much on your own - don't expect kernel developers to really care much if things
+come apart.
diff --git a/MAINTAINERS b/MAINTAINERS
index 5414510..bbcaf31 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -243,21 +243,6 @@
 F:	include/linux/acpi.h
 F:	include/acpi/
 
-ACPI BATTERY DRIVERS
-M:	Alexey Starikovskiy <astarikovskiy@suse.de>
-L:	linux-acpi@vger.kernel.org
-W:	http://www.lesswatts.org/projects/acpi/
-S:	Supported
-F:	drivers/acpi/battery.c
-F:	drivers/acpi/*sbs*
-
-ACPI EC DRIVER
-M:	Alexey Starikovskiy <astarikovskiy@suse.de>
-L:	linux-acpi@vger.kernel.org
-W:	http://www.lesswatts.org/projects/acpi/
-S:	Supported
-F:	drivers/acpi/ec.c
-
 ACPI FAN DRIVER
 M:	Zhang Rui <rui.zhang@intel.com>
 L:	linux-acpi@vger.kernel.org
@@ -657,7 +642,7 @@
 M:	Hans Ulli Kroll <ulli.kroll@googlemail.com>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
-T:	git://git.berlios.de/gemini-board
+T:	git git://git.berlios.de/gemini-board
 F:	arch/arm/mm/*-fa*
 
 ARM/FOOTBRIDGE ARCHITECTURE
@@ -672,7 +657,7 @@
 M:	Sascha Hauer <kernel@pengutronix.de>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
-T:	git://git.pengutronix.de/git/imx/linux-2.6.git
+T:	git git://git.pengutronix.de/git/imx/linux-2.6.git
 F:	arch/arm/mach-mx*/
 F:	arch/arm/plat-mxc/
 
@@ -710,8 +695,7 @@
 M:	Marek Vasut <marek.vasut@gmail.com>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
-F:	arch/arm/mach-pxa/income.c
-F:	arch/arm/mach-pxa/include/mach-pxa/income.h
+F:	arch/arm/mach-pxa/colibri-pxa270-income.c
 
 ARM/INTEL IOP32X ARM ARCHITECTURE
 M:	Lennert Buytenhek <kernel@wantstofly.org>
@@ -758,13 +742,7 @@
 S:	Maintained
 F:	arch/arm/mach-ixp4xx/
 
-ARM/INTEL RESEARCH IMOTE 2 MACHINE SUPPORT
-M:	Jonathan Cameron <jic23@cam.ac.uk>
-L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S:	Maintained
-F:	arch/arm/mach-pxa/imote2.c
-
-ARM/INTEL RESEARCH STARGATE 2 MACHINE SUPPORT
+ARM/INTEL RESEARCH IMOTE/STARGATE 2 MACHINE SUPPORT
 M:	Jonathan Cameron <jic23@cam.ac.uk>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
@@ -929,40 +907,20 @@
 S:	Maintained
 F:	arch/arm/mach-s3c2410/
 
-ARM/S3C2440 ARM ARCHITECTURE
+ARM/S3C244x ARM ARCHITECTURE
 M:	Ben Dooks <ben-linux@fluff.org>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 W:	http://www.fluff.org/ben/linux/
 S:	Maintained
 F:	arch/arm/mach-s3c2440/
-
-ARM/S3C2442 ARM ARCHITECTURE
-M:	Ben Dooks <ben-linux@fluff.org>
-L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-W:	http://www.fluff.org/ben/linux/
-S:	Maintained
-F:	arch/arm/mach-s3c2442/
-
-ARM/S3C2443 ARM ARCHITECTURE
-M:	Ben Dooks <ben-linux@fluff.org>
-L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-W:	http://www.fluff.org/ben/linux/
-S:	Maintained
 F:	arch/arm/mach-s3c2443/
 
-ARM/S3C6400 ARM ARCHITECTURE
+ARM/S3C64xx ARM ARCHITECTURE
 M:	Ben Dooks <ben-linux@fluff.org>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 W:	http://www.fluff.org/ben/linux/
 S:	Maintained
-F:	arch/arm/mach-s3c6400/
-
-ARM/S3C6410 ARM ARCHITECTURE
-M:	Ben Dooks <ben-linux@fluff.org>
-L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-W:	http://www.fluff.org/ben/linux/
-S:	Maintained
-F:	arch/arm/mach-s3c6410/
+F:	arch/arm/mach-s3c64xx/
 
 ARM/S5P ARM ARCHITECTURES
 M:	Kukjin Kim <kgene.kim@samsung.com>
@@ -3015,7 +2973,7 @@
 M:	Sean Hefty <sean.hefty@intel.com>
 M:	Hal Rosenstock <hal.rosenstock@gmail.com>
 L:	linux-rdma@vger.kernel.org
-W:	http://www.openib.org/
+W:	http://www.openfabrics.org/
 Q:	http://patchwork.kernel.org/project/linux-rdma/list/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband.git
 S:	Supported
@@ -3765,6 +3723,13 @@
 S:	Maintained
 F:	drivers/scsi/sym53c8xx_2/
 
+LTC4261 HARDWARE MONITOR DRIVER
+M:	Guenter Roeck <linux@roeck-us.net>
+L:	lm-sensors@lm-sensors.org
+S:	Maintained
+F:	Documentation/hwmon/ltc4261
+F:	drivers/hwmon/ltc4261.c
+
 LTP (Linux Test Project)
 M:	Rishikesh K Rajak <risrajak@linux.vnet.ibm.com>
 M:	Garrett Cooper <yanegomi@gmail.com>
@@ -3860,7 +3825,7 @@
 MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER
 M:	Nicolas Pitre <nico@fluxnic.net>
 S:	Odd Fixes
-F: drivers/mmc/host/mvsdio.*
+F:	drivers/mmc/host/mvsdio.*
 
 MARVELL YUKON / SYSKONNECT DRIVER
 M:	Mirko Lindner <mlindner@syskonnect.de>
@@ -4951,7 +4916,7 @@
 M:	Josh Triplett <josh@freedesktop.org>
 M:	"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
 S:	Supported
-T:	git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-2.6-rcu.git
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-2.6-rcu.git
 F:	Documentation/RCU/torture.txt
 F:	kernel/rcutorture.c
 
@@ -4976,7 +4941,7 @@
 M:	"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
 W:	http://www.rdrop.com/users/paulmck/rclock/
 S:	Supported
-T:	git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-2.6-rcu.git
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-2.6-rcu.git
 F:	Documentation/RCU/
 F:	include/linux/rcu*
 F:	include/linux/srcu*
@@ -5166,6 +5131,16 @@
 S:	Maintained
 F:	drivers/scsi/sr*
 
+SCSI RDMA PROTOCOL (SRP) INITIATOR
+M:	David Dillow <dillowda@ornl.gov>
+L:	linux-rdma@vger.kernel.org
+S:	Supported
+W:	http://www.openfabrics.org
+Q:	http://patchwork.kernel.org/project/linux-rdma/list/
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/dad/srp-initiator.git
+F:	drivers/infiniband/ulp/srp/
+F:	include/scsi/srp.h
+
 SCSI SG DRIVER
 M:	Doug Gilbert <dgilbert@interlog.com>
 L:	linux-scsi@vger.kernel.org
@@ -6134,13 +6109,6 @@
 S:	Maintained
 F:	drivers/usb/serial/option.c
 
-USB OV511 DRIVER
-M:	Mark McClelland <mmcclell@bigfoot.com>
-L:	linux-usb@vger.kernel.org
-W:	http://alpha.dyndns.org/ov511/
-S:	Maintained
-F:	drivers/media/video/ov511.*
-
 USB PEGASUS DRIVER
 M:	Petko Manolov <petkan@users.sourceforge.net>
 L:	linux-usb@vger.kernel.org
@@ -6301,16 +6269,6 @@
 F:	drivers/usb/host/xhci*
 F:	drivers/usb/host/pci-quirks*
 
-USB ZC0301 DRIVER
-M:	Luca Risolia <luca.risolia@studio.unibo.it>
-L:	linux-usb@vger.kernel.org
-L:	linux-media@vger.kernel.org
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
-W:	http://www.linux-projects.org
-S:	Maintained
-F:	Documentation/video4linux/zc0301.txt
-F:	drivers/media/video/zc0301/
-
 USB ZD1201 DRIVER
 L:	linux-wireless@vger.kernel.org
 W:	http://linux-lc100020.sourceforge.net
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index d04ccd7..28f93a6 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -55,6 +55,9 @@
 	bool
 	default y
 
+config ARCH_DMA_ADDR_T_64BIT
+	def_bool y
+
 config NEED_DMA_MAP_STATE
        def_bool y
 
diff --git a/arch/alpha/include/asm/core_mcpcia.h b/arch/alpha/include/asm/core_mcpcia.h
index 21ac533..9f67a05 100644
--- a/arch/alpha/include/asm/core_mcpcia.h
+++ b/arch/alpha/include/asm/core_mcpcia.h
@@ -247,7 +247,7 @@
 #define vip	volatile int __force *
 #define vuip	volatile unsigned int __force *
 
-#ifdef MCPCIA_ONE_HAE_WINDOW
+#ifndef MCPCIA_ONE_HAE_WINDOW
 #define MCPCIA_FROB_MMIO						\
 	if (__mcpcia_is_mmio(hose)) {					\
 		set_hae(hose & 0xffffffff);				\
diff --git a/arch/alpha/include/asm/core_t2.h b/arch/alpha/include/asm/core_t2.h
index 471c072..91b4680 100644
--- a/arch/alpha/include/asm/core_t2.h
+++ b/arch/alpha/include/asm/core_t2.h
@@ -1,6 +1,9 @@
 #ifndef __ALPHA_T2__H__
 #define __ALPHA_T2__H__
 
+/* Fit everything into one 128MB HAE window. */
+#define T2_ONE_HAE_WINDOW 1
+
 #include <linux/types.h>
 #include <linux/spinlock.h>
 #include <asm/compiler.h>
@@ -19,7 +22,7 @@
  *
  */
 
-#define T2_MEM_R1_MASK 0x07ffffff  /* Mem sparse region 1 mask is 26 bits */
+#define T2_MEM_R1_MASK 0x07ffffff  /* Mem sparse region 1 mask is 27 bits */
 
 /* GAMMA-SABLE is a SABLE with EV5-based CPUs */
 /* All LYNX machines, EV4 or EV5, use the GAMMA bias also */
@@ -85,7 +88,9 @@
 #define T2_DIR			(IDENT_ADDR + GAMMA_BIAS + 0x38e0004a0UL)
 #define T2_ICE			(IDENT_ADDR + GAMMA_BIAS + 0x38e0004c0UL)
 
+#ifndef T2_ONE_HAE_WINDOW
 #define T2_HAE_ADDRESS		T2_HAE_1
+#endif
 
 /*  T2 CSRs are in the non-cachable primary IO space from 3.8000.0000 to
  3.8fff.ffff
@@ -429,13 +434,15 @@
  *
  */
 
+#ifdef T2_ONE_HAE_WINDOW
+#define t2_set_hae
+#else
 #define t2_set_hae { \
-	msb = addr  >> 27; \
+	unsigned long msb = addr >> 27; \
 	addr &= T2_MEM_R1_MASK; \
 	set_hae(msb); \
 }
-
-extern raw_spinlock_t t2_hae_lock;
+#endif
 
 /*
  * NOTE: take T2_DENSE_MEM off in each readX/writeX routine, since
@@ -446,28 +453,22 @@
 __EXTERN_INLINE u8 t2_readb(const volatile void __iomem *xaddr)
 {
 	unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
-	unsigned long result, msb;
-	unsigned long flags;
-	raw_spin_lock_irqsave(&t2_hae_lock, flags);
+	unsigned long result;
 
 	t2_set_hae;
 
 	result = *(vip) ((addr << 5) + T2_SPARSE_MEM + 0x00);
-	raw_spin_unlock_irqrestore(&t2_hae_lock, flags);
 	return __kernel_extbl(result, addr & 3);
 }
 
 __EXTERN_INLINE u16 t2_readw(const volatile void __iomem *xaddr)
 {
 	unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
-	unsigned long result, msb;
-	unsigned long flags;
-	raw_spin_lock_irqsave(&t2_hae_lock, flags);
+	unsigned long result;
 
 	t2_set_hae;
 
 	result = *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x08);
-	raw_spin_unlock_irqrestore(&t2_hae_lock, flags);
 	return __kernel_extwl(result, addr & 3);
 }
 
@@ -478,59 +479,47 @@
 __EXTERN_INLINE u32 t2_readl(const volatile void __iomem *xaddr)
 {
 	unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
-	unsigned long result, msb;
-	unsigned long flags;
-	raw_spin_lock_irqsave(&t2_hae_lock, flags);
+	unsigned long result;
 
 	t2_set_hae;
 
 	result = *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x18);
-	raw_spin_unlock_irqrestore(&t2_hae_lock, flags);
 	return result & 0xffffffffUL;
 }
 
 __EXTERN_INLINE u64 t2_readq(const volatile void __iomem *xaddr)
 {
 	unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
-	unsigned long r0, r1, work, msb;
-	unsigned long flags;
-	raw_spin_lock_irqsave(&t2_hae_lock, flags);
+	unsigned long r0, r1, work;
 
 	t2_set_hae;
 
 	work = (addr << 5) + T2_SPARSE_MEM + 0x18;
 	r0 = *(vuip)(work);
 	r1 = *(vuip)(work + (4 << 5));
-	raw_spin_unlock_irqrestore(&t2_hae_lock, flags);
 	return r1 << 32 | r0;
 }
 
 __EXTERN_INLINE void t2_writeb(u8 b, volatile void __iomem *xaddr)
 {
 	unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
-	unsigned long msb, w;
-	unsigned long flags;
-	raw_spin_lock_irqsave(&t2_hae_lock, flags);
+	unsigned long w;
 
 	t2_set_hae;
 
 	w = __kernel_insbl(b, addr & 3);
 	*(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x00) = w;
-	raw_spin_unlock_irqrestore(&t2_hae_lock, flags);
 }
 
 __EXTERN_INLINE void t2_writew(u16 b, volatile void __iomem *xaddr)
 {
 	unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
-	unsigned long msb, w;
-	unsigned long flags;
-	raw_spin_lock_irqsave(&t2_hae_lock, flags);
+	unsigned long w;
 
 	t2_set_hae;
 
 	w = __kernel_inswl(b, addr & 3);
 	*(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x08) = w;
-	raw_spin_unlock_irqrestore(&t2_hae_lock, flags);
 }
 
 /*
@@ -540,29 +529,22 @@
 __EXTERN_INLINE void t2_writel(u32 b, volatile void __iomem *xaddr)
 {
 	unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
-	unsigned long msb;
-	unsigned long flags;
-	raw_spin_lock_irqsave(&t2_hae_lock, flags);
 
 	t2_set_hae;
 
 	*(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x18) = b;
-	raw_spin_unlock_irqrestore(&t2_hae_lock, flags);
 }
 
 __EXTERN_INLINE void t2_writeq(u64 b, volatile void __iomem *xaddr)
 {
 	unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
-	unsigned long msb, work;
-	unsigned long flags;
-	raw_spin_lock_irqsave(&t2_hae_lock, flags);
+	unsigned long work;
 
 	t2_set_hae;
 
 	work = (addr << 5) + T2_SPARSE_MEM + 0x18;
 	*(vuip)work = b;
 	*(vuip)(work + (4 << 5)) = b >> 32;
-	raw_spin_unlock_irqrestore(&t2_hae_lock, flags);
 }
 
 __EXTERN_INLINE void __iomem *t2_ioportmap(unsigned long addr)
diff --git a/arch/alpha/include/asm/pgtable.h b/arch/alpha/include/asm/pgtable.h
index 71a2432..de98a73 100644
--- a/arch/alpha/include/asm/pgtable.h
+++ b/arch/alpha/include/asm/pgtable.h
@@ -318,9 +318,7 @@
 }
 
 #define pte_offset_map(dir,addr)	pte_offset_kernel((dir),(addr))
-#define pte_offset_map_nested(dir,addr)	pte_offset_kernel((dir),(addr))
 #define pte_unmap(pte)			do { } while (0)
-#define pte_unmap_nested(pte)		do { } while (0)
 
 extern pgd_t swapper_pg_dir[1024];
 
diff --git a/arch/alpha/kernel/core_t2.c b/arch/alpha/kernel/core_t2.c
index e6d9056..2f770e9 100644
--- a/arch/alpha/kernel/core_t2.c
+++ b/arch/alpha/kernel/core_t2.c
@@ -74,8 +74,6 @@
 # define DBG(args)
 #endif
 
-DEFINE_RAW_SPINLOCK(t2_hae_lock);
-
 static volatile unsigned int t2_mcheck_any_expected;
 static volatile unsigned int t2_mcheck_last_taken;
 
@@ -406,6 +404,7 @@
 t2_init_arch(void)
 {
 	struct pci_controller *hose;
+	struct resource *hae_mem;
 	unsigned long temp;
 	unsigned int i;
 
@@ -433,7 +432,13 @@
 	 */
 	pci_isa_hose = hose = alloc_pci_controller();
 	hose->io_space = &ioport_resource;
-	hose->mem_space = &iomem_resource;
+	hae_mem = alloc_resource();
+	hae_mem->start = 0;
+	hae_mem->end = T2_MEM_R1_MASK;
+	hae_mem->name = pci_hae0_name;
+	if (request_resource(&iomem_resource, hae_mem) < 0)
+		printk(KERN_ERR "Failed to request HAE_MEM\n");
+	hose->mem_space = hae_mem;
 	hose->index = 0;
 
 	hose->sparse_mem_base = T2_SPARSE_MEM - IDENT_ADDR;
diff --git a/arch/alpha/kernel/machvec_impl.h b/arch/alpha/kernel/machvec_impl.h
index 512685f..7fa6248 100644
--- a/arch/alpha/kernel/machvec_impl.h
+++ b/arch/alpha/kernel/machvec_impl.h
@@ -25,6 +25,9 @@
 #ifdef MCPCIA_ONE_HAE_WINDOW
 #define MCPCIA_HAE_ADDRESS	(&alpha_mv.hae_cache)
 #endif
+#ifdef T2_ONE_HAE_WINDOW
+#define T2_HAE_ADDRESS		(&alpha_mv.hae_cache)
+#endif
 
 /* Only a few systems don't define IACK_SC, handling all interrupts through
    the SRM console.  But splitting out that one case from IO() below
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index b64e465..bf7273f 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -573,6 +573,7 @@
 	select HAVE_CLK
 	select COMMON_CLKDEV
 	select ARCH_HAS_BARRIERS if CACHE_L2X0
+	select ARCH_HAS_CPUFREQ
 	help
 	  This enables support for NVIDIA Tegra based systems (Tegra APX,
 	  Tegra 6xx and Tegra 2 series).
@@ -831,7 +832,7 @@
 	select GENERIC_CLOCKEVENTS
 	select ARCH_HAS_HOLES_MEMORYMODEL
 	help
-	  Support for TI's OMAP platform (OMAP1 and OMAP2).
+	  Support for TI's OMAP platform (OMAP1/2/3/4).
 
 config PLAT_SPEAR
 	bool "ST SPEAr"
diff --git a/arch/arm/configs/n8x0_defconfig b/arch/arm/configs/n8x0_defconfig
deleted file mode 100644
index 56aebb6..0000000
--- a/arch/arm/configs/n8x0_defconfig
+++ /dev/null
@@ -1,94 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_LBDAF is not set
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-CONFIG_ARCH_OMAP=y
-CONFIG_ARCH_OMAP2=y
-CONFIG_OMAP_RESET_CLOCKS=y
-# CONFIG_OMAP_MUX is not set
-# CONFIG_OMAP_MCBSP is not set
-CONFIG_OMAP_MBOX_FWK=y
-CONFIG_OMAP_32K_TIMER=y
-CONFIG_ARCH_OMAP2420=y
-CONFIG_MACH_NOKIA_N8X0=y
-CONFIG_AEABI=y
-CONFIG_LEDS=y
-CONFIG_ZBOOT_ROM_TEXT=0x10C08000
-CONFIG_ZBOOT_ROM_BSS=0x10200000
-CONFIG_CMDLINE="root=/dev/mmcblk0p2 console=ttyS2,115200n8 debug earlyprintk rootwait"
-CONFIG_FPE_NWFPE=y
-CONFIG_VFP=y
-CONFIG_PM=y
-CONFIG_PM_RUNTIME=y
-CONFIG_NET=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_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_ONENAND=y
-CONFIG_MTD_ONENAND_OMAP2=y
-CONFIG_MTD_ONENAND_OTP=y
-CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-# CONFIG_I2C_COMPAT is not set
-# CONFIG_I2C_HELPER_AUTO is not set
-CONFIG_I2C_OMAP=y
-CONFIG_SPI=y
-CONFIG_SPI_OMAP24XX=y
-# CONFIG_HWMON is not set
-CONFIG_MENELAUS=y
-CONFIG_REGULATOR=y
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_HID_SUPPORT is not set
-CONFIG_USB=y
-CONFIG_USB_DEBUG=y
-CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_SUSPEND=y
-# CONFIG_USB_OTG_WHITELIST is not set
-CONFIG_USB_MUSB_HDRC=y
-CONFIG_USB_MUSB_OTG=y
-CONFIG_USB_GADGET_MUSB_HDRC=y
-# CONFIG_MUSB_PIO_ONLY is not set
-CONFIG_USB_MUSB_DEBUG=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DEBUG=y
-CONFIG_USB_GADGET_DEBUG_FILES=y
-CONFIG_USB_ETH=m
-CONFIG_USB_ETH_EEM=y
-CONFIG_MMC=y
-CONFIG_MMC_OMAP=y
-CONFIG_EXT3_FS=y
-CONFIG_INOTIFY=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_SUMMARY=y
-CONFIG_JFFS2_COMPRESSION_OPTIONS=y
-CONFIG_JFFS2_LZO=y
-CONFIG_PRINTK_TIME=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
-CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/omap3_defconfig b/arch/arm/configs/omap2plus_defconfig
similarity index 90%
rename from arch/arm/configs/omap3_defconfig
rename to arch/arm/configs/omap2plus_defconfig
index 5db9a6b..ccedde1 100644
--- a/arch/arm/configs/omap3_defconfig
+++ b/arch/arm/configs/omap2plus_defconfig
@@ -53,18 +53,18 @@
 CONFIG_MACH_OMAP_3630SDP=y
 CONFIG_MACH_OMAP_4430SDP=y
 CONFIG_ARM_THUMBEE=y
+CONFIG_ARM_L1_CACHE_SHIFT=5
+CONFIG_ARM_ERRATA_411920=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+# CONFIG_LOCAL_TIMERS is not set
 CONFIG_AEABI=y
 CONFIG_LEDS=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="root=/dev/mmcblk0p2 rootwait console=ttyS2,115200"
+CONFIG_CMDLINE="root=/dev/mmcblk0p2 rootwait console=ttyO2,115200"
 CONFIG_KEXEC=y
-CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_STAT_DETAILS=y
-CONFIG_CPU_FREQ_GOV_USERSPACE=y
-CONFIG_CPU_FREQ_GOV_ONDEMAND=y
 CONFIG_FPE_NWFPE=y
 CONFIG_VFP=y
 CONFIG_NEON=y
@@ -87,23 +87,23 @@
 # CONFIG_INET_LRO is not set
 # CONFIG_IPV6 is not set
 CONFIG_NETFILTER=y
-CONFIG_BT=y
-CONFIG_BT_L2CAP=y
-CONFIG_BT_SCO=y
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
 CONFIG_BT_RFCOMM=y
 CONFIG_BT_RFCOMM_TTY=y
-CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP=m
 CONFIG_BT_BNEP_MC_FILTER=y
 CONFIG_BT_BNEP_PROTO_FILTER=y
-CONFIG_BT_HIDP=y
-CONFIG_BT_HCIUART=y
+CONFIG_BT_HIDP=m
+CONFIG_BT_HCIUART=m
 CONFIG_BT_HCIUART_H4=y
 CONFIG_BT_HCIUART_BCSP=y
 CONFIG_BT_HCIUART_LL=y
-CONFIG_BT_HCIBCM203X=y
-CONFIG_BT_HCIBPA10X=y
-CONFIG_CFG80211=y
-CONFIG_MAC80211=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_CFG80211=m
+CONFIG_MAC80211=m
 CONFIG_MAC80211_RC_PID=y
 CONFIG_MAC80211_RC_DEFAULT_PID=y
 CONFIG_MAC80211_LEDS=y
@@ -137,9 +137,11 @@
 CONFIG_NET_ETHERNET=y
 CONFIG_SMC91X=y
 CONFIG_SMSC911X=y
-CONFIG_LIBERTAS=y
-CONFIG_LIBERTAS_USB=y
-CONFIG_LIBERTAS_SDIO=y
+CONFIG_KS8851=y
+CONFIG_KS8851_MLL=y
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+CONFIG_LIBERTAS_SDIO=m
 CONFIG_LIBERTAS_DEBUG=y
 CONFIG_USB_USBNET=y
 CONFIG_USB_ALI_M5632=y
@@ -201,8 +203,8 @@
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
 CONFIG_LOGO=y
-CONFIG_SOUND=y
-CONFIG_SND=y
+CONFIG_SOUND=m
+CONFIG_SND=m
 CONFIG_SND_MIXER_OSS=y
 CONFIG_SND_PCM_OSS=y
 CONFIG_SND_VERBOSE_PRINTK=y
@@ -218,9 +220,9 @@
 CONFIG_USB_SUSPEND=y
 # CONFIG_USB_OTG_WHITELIST is not set
 CONFIG_USB_MON=y
-CONFIG_USB_MUSB_HDRC=y
-CONFIG_USB_MUSB_OTG=y
-CONFIG_USB_GADGET_MUSB_HDRC=y
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_MUSB_OTG is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
 CONFIG_USB_MUSB_DEBUG=y
 CONFIG_USB_WDM=y
 CONFIG_USB_STORAGE=y
@@ -276,12 +278,11 @@
 CONFIG_SCHEDSTATS=y
 CONFIG_TIMER_STATS=y
 CONFIG_PROVE_LOCKING=y
-CONFIG_LOCK_STAT=y
+# CONFIG_LOCK_STAT is not set
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
 # CONFIG_DEBUG_BUGVERBOSE is not set
 CONFIG_DEBUG_INFO=y
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_DEBUG_LL=y
 CONFIG_SECURITY=y
 CONFIG_CRYPTO_MICHAEL_MIC=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/arm/configs/omap_4430sdp_defconfig b/arch/arm/configs/omap_4430sdp_defconfig
deleted file mode 100644
index 14c1e18..0000000
--- a/arch/arm/configs/omap_4430sdp_defconfig
+++ /dev/null
@@ -1,125 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
-# CONFIG_SYSCTL_SYSCALL is not set
-# CONFIG_ELF_CORE is not set
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_OMAP=y
-CONFIG_ARCH_OMAP4=y
-# CONFIG_ARCH_OMAP2PLUS_TYPICAL is not set
-# CONFIG_ARCH_OMAP2 is not set
-# CONFIG_ARCH_OMAP3 is not set
-# CONFIG_OMAP_MUX is not set
-CONFIG_OMAP_32K_TIMER=y
-CONFIG_OMAP_DM_TIMER=y
-CONFIG_MACH_OMAP_4430SDP=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_PL310_ERRATA_588369=y
-CONFIG_SMP=y
-CONFIG_NR_CPUS=2
-# CONFIG_LOCAL_TIMERS is not set
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="root=/dev/ram0 rw mem=128M console=ttyS2,115200n8 initrd=0x81600000,20M ramdisk_size=20480"
-CONFIG_VFP=y
-CONFIG_NEON=y
-CONFIG_BINFMT_MISC=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-# CONFIG_IPV6 is not set
-# CONFIG_WIRELESS is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_FW_LOADER is not set
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=16384
-# CONFIG_MISC_DEVICES is not set
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_KS8851=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_WLAN is not set
-# CONFIG_INPUT_MOUSEDEV is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=32
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_MANY_PORTS=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-CONFIG_SERIAL_8250_DETECT_IRQ=y
-CONFIG_SERIAL_8250_RSA=y
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_HW_RANDOM=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_OMAP=y
-CONFIG_SPI=y
-CONFIG_SPI_OMAP24XX=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_OMAP_WATCHDOG=y
-CONFIG_TWL4030_CORE=y
-CONFIG_REGULATOR=y
-CONFIG_REGULATOR_TWL4030=y
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
-CONFIG_MMC=y
-CONFIG_MMC_OMAP_HS=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_TWL4030=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_FS_XATTR is not set
-CONFIG_INOTIFY=y
-CONFIG_QUOTA=y
-CONFIG_QFMT_V2=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V3_ACL=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ISO8859_1=y
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-# CONFIG_ENABLE_MUST_CHECK is not set
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_DETECT_SOFTLOCKUP is not set
-CONFIG_DETECT_HUNG_TASK=y
-# CONFIG_SCHED_DEBUG is not set
-# CONFIG_DEBUG_PREEMPT is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
-CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-# CONFIG_FTRACE is not set
-# CONFIG_ARM_UNWIND is not set
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_PCBC=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRC_CCITT=y
-CONFIG_CRC_T10DIF=y
-CONFIG_LIBCRC32C=y
diff --git a/arch/arm/configs/omap_generic_2420_defconfig b/arch/arm/configs/omap_generic_2420_defconfig
deleted file mode 100644
index ac08e51..0000000
--- a/arch/arm/configs/omap_generic_2420_defconfig
+++ /dev/null
@@ -1,37 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_OMAP=y
-CONFIG_ARCH_OMAP2=y
-# CONFIG_OMAP_MUX is not set
-CONFIG_MACH_OMAP_GENERIC=y
-CONFIG_ARCH_OMAP2420=y
-CONFIG_LEDS=y
-CONFIG_ZBOOT_ROM_TEXT=0x10C08000
-CONFIG_ZBOOT_ROM_BSS=0x10200000
-CONFIG_FPE_NWFPE=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_VIDEO_OUTPUT_CONTROL=m
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_INOTIFY=y
-CONFIG_ROMFS_FS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
-CONFIG_DEBUG_LL=y
-CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/pcontrol_g20_defconfig b/arch/arm/configs/pcontrol_g20_defconfig
new file mode 100644
index 0000000..b42ee62
--- /dev/null
+++ b/arch/arm/configs/pcontrol_g20_defconfig
@@ -0,0 +1,175 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_CROSS_COMPILE="/opt/arm-2010q1/bin/arm-none-linux-gnueabi-"
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_NAMESPACES=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EMBEDDED=y
+# CONFIG_SYSCTL_SYSCALL is not set
+# CONFIG_KALLSYMS is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_DEFAULT_DEADLINE=y
+CONFIG_ARCH_AT91=y
+CONFIG_ARCH_AT91SAM9G20=y
+CONFIG_MACH_PCONTROL_G20=y
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,115200 mem=128M mtdparts=atmel_nand:128k(bootstrap)ro,256k(uboot)ro,128k(env1)ro,128k(env2)ro,2M(linux),-(root) root=/dev/mmcblk0p1 rootwait rw"
+CONFIG_VFP=y
+CONFIG_BINFMT_MISC=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+CONFIG_VLAN_8021Q=y
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHRAM=m
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ATMEL=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_ATMEL_TCLIB=y
+CONFIG_EEPROM_AT24=m
+CONFIG_SCSI=m
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=m
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_MACVLAN=m
+CONFIG_TUN=m
+CONFIG_SMSC_PHY=m
+CONFIG_BROADCOM_PHY=m
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_MACB=y
+CONFIG_SMSC911X=m
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
+CONFIG_PPP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_MPPE=m
+CONFIG_INPUT_POLLDEV=y
+CONFIG_INPUT_SPARSEKMAP=y
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=m
+CONFIG_INPUT_EVBUG=m
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=m
+CONFIG_KEYBOARD_MATRIX=m
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=m
+CONFIG_INPUT_GPIO_ROTARY_ENCODER=m
+# CONFIG_SERIO is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+CONFIG_SERIAL_MAX3100=m
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_R3964=m
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_GPIO=m
+CONFIG_SPI=y
+CONFIG_SPI_ATMEL=m
+CONFIG_SPI_SPIDEV=m
+CONFIG_GPIO_SYSFS=y
+CONFIG_W1=m
+CONFIG_W1_MASTER_GPIO=m
+CONFIG_W1_SLAVE_DS2431=m
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_AT91SAM9X_WATCHDOG=y
+# CONFIG_MFD_SUPPORT is not set
+# CONFIG_HID_SUPPORT is not set
+CONFIG_USB=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=m
+CONFIG_USB_LIBUSUAL=y
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_GADGET=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_G_HID=m
+CONFIG_MMC=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_ATMELMCI=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91SAM9=y
+CONFIG_AUXDISPLAY=y
+CONFIG_UIO=y
+CONFIG_UIO_PDRV=y
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+CONFIG_IIO=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=y
+CONFIG_NLS_UTF8=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ANSI_CPRNG=y
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_CCITT=y
diff --git a/arch/arm/include/asm/highmem.h b/arch/arm/include/asm/highmem.h
index 5aff581..1fc684e 100644
--- a/arch/arm/include/asm/highmem.h
+++ b/arch/arm/include/asm/highmem.h
@@ -35,9 +35,9 @@
 #ifdef CONFIG_HIGHMEM
 extern void *kmap(struct page *page);
 extern void kunmap(struct page *page);
-extern void *kmap_atomic(struct page *page, enum km_type type);
-extern void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type);
-extern void *kmap_atomic_pfn(unsigned long pfn, enum km_type type);
+extern void *__kmap_atomic(struct page *page);
+extern void __kunmap_atomic(void *kvaddr);
+extern void *kmap_atomic_pfn(unsigned long pfn);
 extern struct page *kmap_atomic_to_page(const void *ptr);
 #endif
 
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index a9672e8..b155414 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -263,17 +263,15 @@
 #define pte_page(pte)		(pfn_to_page(pte_pfn(pte)))
 #define pte_offset_kernel(dir,addr)	(pmd_page_vaddr(*(dir)) + __pte_index(addr))
 
-#define pte_offset_map(dir,addr)	(__pte_map(dir, KM_PTE0) + __pte_index(addr))
-#define pte_offset_map_nested(dir,addr)	(__pte_map(dir, KM_PTE1) + __pte_index(addr))
-#define pte_unmap(pte)			__pte_unmap(pte, KM_PTE0)
-#define pte_unmap_nested(pte)		__pte_unmap(pte, KM_PTE1)
+#define pte_offset_map(dir,addr)	(__pte_map(dir) + __pte_index(addr))
+#define pte_unmap(pte)			__pte_unmap(pte)
 
 #ifndef CONFIG_HIGHPTE
-#define __pte_map(dir,km)	pmd_page_vaddr(*(dir))
-#define __pte_unmap(pte,km)	do { } while (0)
+#define __pte_map(dir)		pmd_page_vaddr(*(dir))
+#define __pte_unmap(pte)	do { } while (0)
 #else
-#define __pte_map(dir,km)	((pte_t *)kmap_atomic(pmd_page(*(dir)), km) + PTRS_PER_PTE)
-#define __pte_unmap(pte,km)	kunmap_atomic((pte - PTRS_PER_PTE), km)
+#define __pte_map(dir)		((pte_t *)kmap_atomic(pmd_page(*(dir))) + PTRS_PER_PTE)
+#define __pte_unmap(pte)	kunmap_atomic((pte - PTRS_PER_PTE))
 #endif
 
 #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext)
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index abed4d1..c015b68 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -375,6 +375,12 @@
 	  evaluation board.
 	  <http://www.taskit.de/en/>
 
+config MACH_PCONTROL_G20
+	bool "PControl G20 CPU module"
+	help
+	  Select this if you are using taskit's Stamp9G20 CPU module on this
+	  carrier board, beeing the decentralized unit of a building automation
+	  system; featuring nvram, eth-switch, iso-rs485, display, io
 endif
 
 if (ARCH_AT91SAM9260 || ARCH_AT91SAM9G20)
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index 412b3a4..821eb84 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -11,12 +11,12 @@
 
 # CPU-specific support
 obj-$(CONFIG_ARCH_AT91RM9200)	+= at91rm9200.o at91rm9200_time.o at91rm9200_devices.o
-obj-$(CONFIG_ARCH_AT91SAM9260)	+= at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o
-obj-$(CONFIG_ARCH_AT91SAM9261)	+= at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o
-obj-$(CONFIG_ARCH_AT91SAM9G10)	+= at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o
-obj-$(CONFIG_ARCH_AT91SAM9263)	+= at91sam9263.o at91sam926x_time.o at91sam9263_devices.o sam9_smc.o
-obj-$(CONFIG_ARCH_AT91SAM9RL)	+= at91sam9rl.o at91sam926x_time.o at91sam9rl_devices.o sam9_smc.o
-obj-$(CONFIG_ARCH_AT91SAM9G20)	+= at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o
+obj-$(CONFIG_ARCH_AT91SAM9260)	+= at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o at91sam9_alt_reset.o
+obj-$(CONFIG_ARCH_AT91SAM9261)	+= at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o at91sam9_alt_reset.o
+obj-$(CONFIG_ARCH_AT91SAM9G10)	+= at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o at91sam9_alt_reset.o
+obj-$(CONFIG_ARCH_AT91SAM9263)	+= at91sam9263.o at91sam926x_time.o at91sam9263_devices.o sam9_smc.o at91sam9_alt_reset.o
+obj-$(CONFIG_ARCH_AT91SAM9RL)	+= at91sam9rl.o at91sam926x_time.o at91sam9rl_devices.o sam9_smc.o at91sam9_alt_reset.o
+obj-$(CONFIG_ARCH_AT91SAM9G20)	+= at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o at91sam9_alt_reset.o
 obj-$(CONFIG_ARCH_AT91SAM9G45)	+= at91sam9g45.o at91sam926x_time.o at91sam9g45_devices.o sam9_smc.o
 obj-$(CONFIG_ARCH_AT91CAP9)	+= at91cap9.o at91sam926x_time.o at91cap9_devices.o sam9_smc.o
 obj-$(CONFIG_ARCH_AT572D940HF)  += at572d940hf.o at91sam926x_time.o at572d940hf_devices.o sam9_smc.o
@@ -65,6 +65,7 @@
 obj-$(CONFIG_MACH_CPU9G20)	+= board-cpu9krea.o
 obj-$(CONFIG_MACH_STAMP9G20)	+= board-stamp9g20.o
 obj-$(CONFIG_MACH_PORTUXG20)	+= board-stamp9g20.o
+obj-$(CONFIG_MACH_PCONTROL_G20)	+= board-pcontrol-g20.o
 
 # AT91SAM9260/AT91SAM9G20 board-specific support
 obj-$(CONFIG_MACH_SNAPPER_9260)	+= board-snapper9260.o
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index 0894f10..195208b 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -279,11 +279,6 @@
 	}
 };
 
-static void at91sam9260_reset(void)
-{
-	at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
-}
-
 static void at91sam9260_poweroff(void)
 {
 	at91_sys_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);
@@ -327,7 +322,7 @@
 	else
 		iotable_init(at91sam9260_sram_desc, ARRAY_SIZE(at91sam9260_sram_desc));
 
-	at91_arch_reset = at91sam9260_reset;
+	at91_arch_reset = at91sam9_alt_reset;
 	pm_power_off = at91sam9260_poweroff;
 	at91_extern_irq = (1 << AT91SAM9260_ID_IRQ0) | (1 << AT91SAM9260_ID_IRQ1)
 			| (1 << AT91SAM9260_ID_IRQ2);
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index 4ecf379..fcad886 100644
--- a/arch/arm/mach-at91/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -257,11 +257,6 @@
 	}
 };
 
-static void at91sam9261_reset(void)
-{
-	at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
-}
-
 static void at91sam9261_poweroff(void)
 {
 	at91_sys_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);
@@ -283,7 +278,7 @@
 		iotable_init(at91sam9261_sram_desc, ARRAY_SIZE(at91sam9261_sram_desc));
 
 
-	at91_arch_reset = at91sam9261_reset;
+	at91_arch_reset = at91sam9_alt_reset;
 	pm_power_off = at91sam9261_poweroff;
 	at91_extern_irq = (1 << AT91SAM9261_ID_IRQ0) | (1 << AT91SAM9261_ID_IRQ1)
 			| (1 << AT91SAM9261_ID_IRQ2);
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
index 942792d..249f900 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -269,11 +269,6 @@
 	}
 };
 
-static void at91sam9263_reset(void)
-{
-	at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
-}
-
 static void at91sam9263_poweroff(void)
 {
 	at91_sys_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);
@@ -289,7 +284,7 @@
 	/* Map peripherals */
 	iotable_init(at91sam9263_io_desc, ARRAY_SIZE(at91sam9263_io_desc));
 
-	at91_arch_reset = at91sam9263_reset;
+	at91_arch_reset = at91sam9_alt_reset;
 	pm_power_off = at91sam9263_poweroff;
 	at91_extern_irq = (1 << AT91SAM9263_ID_IRQ0) | (1 << AT91SAM9263_ID_IRQ1);
 
diff --git a/arch/arm/mach-at91/at91sam9_alt_reset.S b/arch/arm/mach-at91/at91sam9_alt_reset.S
new file mode 100644
index 0000000..e0256de
--- /dev/null
+++ b/arch/arm/mach-at91/at91sam9_alt_reset.S
@@ -0,0 +1,48 @@
+/*
+ * reset AT91SAM9G20 as per errata
+ *
+ * (C) BitBox Ltd 2010
+ *
+ * unless the SDRAM is cleanly shutdown before we hit the
+ * reset register it can be left driving the data bus and
+ * killing the chance of a subsequent boot from NAND
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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/system.h>
+#include <mach/hardware.h>
+#include <mach/at91sam9_sdramc.h>
+#include <mach/at91_rstc.h>
+
+			.arm
+
+			.globl	at91sam9_alt_reset
+
+at91sam9_alt_reset:	mrc	p15, 0, r0, c1, c0, 0
+			orr	r0, r0, #CR_I
+			mcr	p15, 0, r0, c1, c0, 0		@ enable I-cache
+
+			ldr	r0, .at91_va_base_sdramc	@ preload constants
+			ldr	r1, .at91_va_base_rstc_cr
+
+			mov	r2, #1
+			mov	r3, #AT91_SDRAMC_LPCB_POWER_DOWN
+			ldr	r4, =AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST
+
+			.balign	32				@ align to cache line
+
+			str	r2, [r0, #AT91_SDRAMC_TR]	@ disable SDRAM access
+			str	r3, [r0, #AT91_SDRAMC_LPR]	@ power down SDRAM
+			str	r4, [r1]			@ reset processor
+
+			b	.
+
+.at91_va_base_sdramc:
+	.word AT91_VA_BASE_SYS + AT91_SDRAMC0
+.at91_va_base_rstc_cr:
+	.word AT91_VA_BASE_SYS + AT91_RSTC_CR
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 1276bab..1e8f275 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -15,6 +15,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
 #include <linux/i2c-gpio.h>
+#include <linux/atmel-mci.h>
 
 #include <linux/fb.h>
 #include <video/atmel_lcdc.h>
@@ -25,6 +26,7 @@
 #include <mach/at91sam9g45_matrix.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at_hdmac.h>
+#include <mach/atmel-mci.h>
 
 #include "generic.h"
 
@@ -350,6 +352,169 @@
 
 
 /* --------------------------------------------------------------------
+ *  MMC / SD
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
+static u64 mmc_dmamask = DMA_BIT_MASK(32);
+static struct mci_platform_data mmc0_data, mmc1_data;
+
+static struct resource mmc0_resources[] = {
+	[0] = {
+		.start	= AT91SAM9G45_BASE_MCI0,
+		.end	= AT91SAM9G45_BASE_MCI0 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9G45_ID_MCI0,
+		.end	= AT91SAM9G45_ID_MCI0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91sam9g45_mmc0_device = {
+	.name		= "atmel_mci",
+	.id		= 0,
+	.dev		= {
+				.dma_mask		= &mmc_dmamask,
+				.coherent_dma_mask	= DMA_BIT_MASK(32),
+				.platform_data		= &mmc0_data,
+	},
+	.resource	= mmc0_resources,
+	.num_resources	= ARRAY_SIZE(mmc0_resources),
+};
+
+static struct resource mmc1_resources[] = {
+	[0] = {
+		.start	= AT91SAM9G45_BASE_MCI1,
+		.end	= AT91SAM9G45_BASE_MCI1 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9G45_ID_MCI1,
+		.end	= AT91SAM9G45_ID_MCI1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91sam9g45_mmc1_device = {
+	.name		= "atmel_mci",
+	.id		= 1,
+	.dev		= {
+				.dma_mask		= &mmc_dmamask,
+				.coherent_dma_mask	= DMA_BIT_MASK(32),
+				.platform_data		= &mmc1_data,
+	},
+	.resource	= mmc1_resources,
+	.num_resources	= ARRAY_SIZE(mmc1_resources),
+};
+
+/* Consider only one slot : slot 0 */
+void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
+{
+
+	if (!data)
+		return;
+
+	/* Must have at least one usable slot */
+	if (!data->slot[0].bus_width)
+		return;
+
+#if defined(CONFIG_AT_HDMAC) || defined(CONFIG_AT_HDMAC_MODULE)
+	{
+	struct at_dma_slave	*atslave;
+	struct mci_dma_data	*alt_atslave;
+
+	alt_atslave = kzalloc(sizeof(struct mci_dma_data), GFP_KERNEL);
+	atslave = &alt_atslave->sdata;
+
+	/* DMA slave channel configuration */
+	atslave->dma_dev = &at_hdmac_device.dev;
+	atslave->reg_width = AT_DMA_SLAVE_WIDTH_32BIT;
+	atslave->cfg = ATC_FIFOCFG_HALFFIFO
+			| ATC_SRC_H2SEL_HW | ATC_DST_H2SEL_HW;
+	atslave->ctrla = ATC_SCSIZE_16 | ATC_DCSIZE_16;
+	if (mmc_id == 0)	/* MCI0 */
+		atslave->cfg |= ATC_SRC_PER(AT_DMA_ID_MCI0)
+			      | ATC_DST_PER(AT_DMA_ID_MCI0);
+
+	else			/* MCI1 */
+		atslave->cfg |= ATC_SRC_PER(AT_DMA_ID_MCI1)
+			      | ATC_DST_PER(AT_DMA_ID_MCI1);
+
+	data->dma_slave = alt_atslave;
+	}
+#endif
+
+
+	/* input/irq */
+	if (data->slot[0].detect_pin) {
+		at91_set_gpio_input(data->slot[0].detect_pin, 1);
+		at91_set_deglitch(data->slot[0].detect_pin, 1);
+	}
+	if (data->slot[0].wp_pin)
+		at91_set_gpio_input(data->slot[0].wp_pin, 1);
+
+	if (mmc_id == 0) {		/* MCI0 */
+
+		/* CLK */
+		at91_set_A_periph(AT91_PIN_PA0, 0);
+
+		/* CMD */
+		at91_set_A_periph(AT91_PIN_PA1, 1);
+
+		/* DAT0, maybe DAT1..DAT3 and maybe DAT4..DAT7 */
+		at91_set_A_periph(AT91_PIN_PA2, 1);
+		if (data->slot[0].bus_width == 4) {
+			at91_set_A_periph(AT91_PIN_PA3, 1);
+			at91_set_A_periph(AT91_PIN_PA4, 1);
+			at91_set_A_periph(AT91_PIN_PA5, 1);
+			if (data->slot[0].bus_width == 8) {
+				at91_set_A_periph(AT91_PIN_PA6, 1);
+				at91_set_A_periph(AT91_PIN_PA7, 1);
+				at91_set_A_periph(AT91_PIN_PA8, 1);
+				at91_set_A_periph(AT91_PIN_PA9, 1);
+			}
+		}
+
+		mmc0_data = *data;
+		at91_clock_associate("mci0_clk", &at91sam9g45_mmc0_device.dev, "mci_clk");
+		platform_device_register(&at91sam9g45_mmc0_device);
+
+	} else {			/* MCI1 */
+
+		/* CLK */
+		at91_set_A_periph(AT91_PIN_PA31, 0);
+
+		/* CMD */
+		at91_set_A_periph(AT91_PIN_PA22, 1);
+
+		/* DAT0, maybe DAT1..DAT3 and maybe DAT4..DAT7 */
+		at91_set_A_periph(AT91_PIN_PA23, 1);
+		if (data->slot[0].bus_width == 4) {
+			at91_set_A_periph(AT91_PIN_PA24, 1);
+			at91_set_A_periph(AT91_PIN_PA25, 1);
+			at91_set_A_periph(AT91_PIN_PA26, 1);
+			if (data->slot[0].bus_width == 8) {
+				at91_set_A_periph(AT91_PIN_PA27, 1);
+				at91_set_A_periph(AT91_PIN_PA28, 1);
+				at91_set_A_periph(AT91_PIN_PA29, 1);
+				at91_set_A_periph(AT91_PIN_PA30, 1);
+			}
+		}
+
+		mmc1_data = *data;
+		at91_clock_associate("mci1_clk", &at91sam9g45_mmc1_device.dev, "mci_clk");
+		platform_device_register(&at91sam9g45_mmc1_device);
+
+	}
+}
+#else
+void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
  *  NAND / SmartMedia
  * -------------------------------------------------------------------- */
 
diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
index 211c5c1..6a9d24e 100644
--- a/arch/arm/mach-at91/at91sam9rl.c
+++ b/arch/arm/mach-at91/at91sam9rl.c
@@ -242,11 +242,6 @@
 	}
 };
 
-static void at91sam9rl_reset(void)
-{
-	at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
-}
-
 static void at91sam9rl_poweroff(void)
 {
 	at91_sys_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);
@@ -281,7 +276,7 @@
 	/* Map SRAM */
 	iotable_init(at91sam9rl_sram_desc, ARRAY_SIZE(at91sam9rl_sram_desc));
 
-	at91_arch_reset = at91sam9rl_reset;
+	at91_arch_reset = at91sam9_alt_reset;
 	pm_power_off = at91sam9rl_poweroff;
 	at91_extern_irq = (1 << AT91SAM9RL_ID_IRQ0);
 
diff --git a/arch/arm/mach-at91/board-pcontrol-g20.c b/arch/arm/mach-at91/board-pcontrol-g20.c
new file mode 100644
index 0000000..bba5a56
--- /dev/null
+++ b/arch/arm/mach-at91/board-pcontrol-g20.c
@@ -0,0 +1,322 @@
+/*
+ *  Copyright (C) 2010 Christian Glindkamp <christian.glindkamp@taskit.de>
+ *                     taskit GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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
+ */
+/*
+ * copied and adjusted from board-stamp9g20.c
+ * by Peter Gsellmann <pgsellmann@portner-elektronik.at>
+ */
+
+#include <linux/mm.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/w1-gpio.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/board.h>
+#include <mach/at91sam9_smc.h>
+
+#include "sam9_smc.h"
+#include "generic.h"
+
+
+static void __init pcontrol_g20_map_io(void)
+{
+	/* Initialize processor: 18.432 MHz crystal */
+	at91sam9260_initialize(18432000);
+
+	/* DGBU on ttyS0. (Rx, Tx) only TTL -> JTAG connector X7 17,19 ) */
+	at91_register_uart(0, 0, 0);
+
+	/* USART0 on ttyS1. (Rx, Tx, CTS, RTS) piggyback  A2 */
+	at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS
+						| ATMEL_UART_RTS);
+
+	/* USART1 on ttyS2. (Rx, Tx, CTS, RTS) isolated RS485  X5 */
+	at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS
+						| ATMEL_UART_RTS);
+
+	/* USART2 on ttyS3. (Rx, Tx)  9bit-Bus  Multidrop-mode  X4 */
+	at91_register_uart(AT91SAM9260_ID_US4, 3, 0);
+
+	/* set serial console to ttyS0 (ie, DBGU) */
+	at91_set_serial_console(0);
+}
+
+
+static void __init init_irq(void)
+{
+	at91sam9260_init_interrupts(NULL);
+}
+
+
+/*
+ * NAND flash 512MiB 1,8V 8-bit, sector size 128 KiB
+ */
+static struct atmel_nand_data __initdata nand_data = {
+	.ale		= 21,
+	.cle		= 22,
+	.rdy_pin	= AT91_PIN_PC13,
+	.enable_pin	= AT91_PIN_PC14,
+};
+
+/*
+ * Bus timings; unit = 7.57ns
+ */
+static struct sam9_smc_config __initdata 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 struct sam9_smc_config __initdata pcontrol_smc_config[2] = { {
+	.ncs_read_setup		= 16,
+	.nrd_setup		= 18,
+	.ncs_write_setup	= 16,
+	.nwe_setup		= 18,
+
+	.ncs_read_pulse		= 63,
+	.nrd_pulse		= 55,
+	.ncs_write_pulse	= 63,
+	.nwe_pulse		= 55,
+
+	.read_cycle		= 127,
+	.write_cycle		= 127,
+
+	.mode			= AT91_SMC_READMODE | AT91_SMC_WRITEMODE
+			| AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_BAT_SELECT
+			| AT91_SMC_DBW_8 | AT91_SMC_PS_4
+			| AT91_SMC_TDFMODE,
+	.tdf_cycles		= 3,
+}, {
+	.ncs_read_setup		= 0,
+	.nrd_setup		= 0,
+	.ncs_write_setup	= 0,
+	.nwe_setup		= 1,
+
+	.ncs_read_pulse		= 8,
+	.nrd_pulse		= 8,
+	.ncs_write_pulse	= 5,
+	.nwe_pulse		= 4,
+
+	.read_cycle		= 8,
+	.write_cycle		= 7,
+
+	.mode			= AT91_SMC_READMODE | AT91_SMC_WRITEMODE
+			| AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_BAT_SELECT
+			| AT91_SMC_DBW_16 | AT91_SMC_PS_8
+			| AT91_SMC_TDFMODE,
+	.tdf_cycles		= 1,
+} };
+
+static void __init add_device_nand(void)
+{
+	/* configure chip-select 3 (NAND) */
+	sam9_smc_configure(3, &nand_smc_config);
+	at91_add_device_nand(&nand_data);
+}
+
+
+static void __init add_device_pcontrol(void)
+{
+	/* configure chip-select 4 (IO compatible to 8051  X4 ) */
+	sam9_smc_configure(4, &pcontrol_smc_config[0]);
+	/* configure chip-select 7 (FerroRAM 256KiBx16bit MR2A16A  D4 ) */
+	sam9_smc_configure(7, &pcontrol_smc_config[1]);
+}
+
+
+/*
+ * MCI (SD/MMC)
+ * det_pin, wp_pin and vcc_pin are not connected
+ */
+#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
+static struct mci_platform_data __initdata mmc_data = {
+	.slot[0] = {
+		.bus_width	= 4,
+	},
+};
+#else
+static struct at91_mmc_data __initdata mmc_data = {
+	.wire4		= 1,
+};
+#endif
+
+
+/*
+ * USB Host port
+ */
+static struct at91_usbh_data __initdata usbh_data = {
+	.ports		= 2,
+};
+
+
+/*
+ * USB Device port
+ */
+static struct at91_udc_data __initdata pcontrol_g20_udc_data = {
+	.vbus_pin	= AT91_PIN_PA22,	/* Detect +5V bus voltage */
+	.pullup_pin	= AT91_PIN_PA4,		/* K-state, active low */
+};
+
+
+/*
+ * MACB Ethernet device
+ */
+static struct at91_eth_data __initdata macb_data = {
+	.phy_irq_pin	= AT91_PIN_PA28,
+	.is_rmii	= 1,
+};
+
+
+/*
+ * I2C devices: eeprom and phy/switch
+ */
+static struct i2c_board_info __initdata pcontrol_g20_i2c_devices[] = {
+{		/* D7  address width=2, 8KiB */
+	I2C_BOARD_INFO("24c64", 0x50)
+}, {		/* D8  address width=1, 1 byte has 32 bits! */
+	I2C_BOARD_INFO("lan9303", 0x0a)
+}, };
+
+
+/*
+ * LEDs
+ */
+static struct gpio_led pcontrol_g20_leds[] = {
+	{
+		.name			= "LED1",	/* red  H5 */
+		.gpio			= AT91_PIN_PB18,
+		.active_low		= 1,
+		.default_trigger	= "none",	/* supervisor */
+	}, {
+		.name			= "LED2",	/* yellow  H7 */
+		.gpio			= AT91_PIN_PB19,
+		.active_low		= 1,
+		.default_trigger	= "mmc0",	/* SD-card activity */
+	}, {
+		.name			= "LED3",	/* green  H2 */
+		.gpio			= AT91_PIN_PB20,
+		.active_low		= 1,
+		.default_trigger	= "heartbeat",	/* blinky */
+	}, {
+		.name			= "LED4",	/* red  H3 */
+		.gpio			= AT91_PIN_PC6,
+		.active_low		= 1,
+		.default_trigger	= "none",	/* connection lost */
+	}, {
+		.name			= "LED5",	/* yellow  H6 */
+		.gpio			= AT91_PIN_PC7,
+		.active_low		= 1,
+		.default_trigger	= "none",	/* unsent data */
+	}, {
+		.name			= "LED6",	/* green  H1 */
+		.gpio			= AT91_PIN_PC9,
+		.active_low		= 1,
+		.default_trigger	= "none",	/* snafu */
+	}
+};
+
+
+/*
+ * SPI devices
+ */
+static struct spi_board_info pcontrol_g20_spi_devices[] = {
+	{
+		.modalias	= "spidev",	/* HMI port  X4 */
+		.chip_select	= 1,
+		.max_speed_hz	= 50 * 1000 * 1000,
+		.bus_num	= 0,
+	}, {
+		.modalias	= "spidev",	/* piggyback  A2 */
+		.chip_select	= 0,
+		.max_speed_hz	= 50 * 1000 * 1000,
+		.bus_num	= 1,
+	},
+};
+
+
+/*
+ * Dallas 1-Wire  DS2431
+ */
+static struct w1_gpio_platform_data w1_gpio_pdata = {
+	.pin		= AT91_PIN_PA29,
+	.is_open_drain	= 1,
+};
+
+static struct platform_device w1_device = {
+	.name			= "w1-gpio",
+	.id			= -1,
+	.dev.platform_data	= &w1_gpio_pdata,
+};
+
+static void add_wire1(void)
+{
+	at91_set_GPIO_periph(w1_gpio_pdata.pin, 1);
+	at91_set_multi_drive(w1_gpio_pdata.pin, 1);
+	platform_device_register(&w1_device);
+}
+
+
+static void __init pcontrol_g20_board_init(void)
+{
+	at91_add_device_serial();
+	add_device_nand();
+#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
+	at91_add_device_mci(0, &mmc_data);
+#else
+	at91_add_device_mmc(0, &mmc_data);
+#endif
+	at91_add_device_usbh(&usbh_data);
+	at91_add_device_eth(&macb_data);
+	at91_add_device_i2c(pcontrol_g20_i2c_devices,
+		ARRAY_SIZE(pcontrol_g20_i2c_devices));
+	add_wire1();
+	add_device_pcontrol();
+	at91_add_device_spi(pcontrol_g20_spi_devices,
+		ARRAY_SIZE(pcontrol_g20_spi_devices));
+	at91_add_device_udc(&pcontrol_g20_udc_data);
+	at91_gpio_leds(pcontrol_g20_leds,
+		ARRAY_SIZE(pcontrol_g20_leds));
+	/* piggyback  A2 */
+	at91_set_gpio_output(AT91_PIN_PB31, 1);
+}
+
+
+MACHINE_START(PCONTROL_G20, "PControl G20")
+	/* Maintainer: pgsellmann@portner-elektronik.at */
+	.boot_params	= AT91_SDRAM_BASE + 0x100,
+	.timer		= &at91sam926x_timer,
+	.map_io		= pcontrol_g20_map_io,
+	.init_irq	= init_irq,
+	.init_machine	= pcontrol_g20_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c
index 7913984..86ff4b5 100644
--- a/arch/arm/mach-at91/board-sam9m10g45ek.c
+++ b/arch/arm/mach-at91/board-sam9m10g45ek.c
@@ -24,7 +24,9 @@
 #include <linux/input.h>
 #include <linux/leds.h>
 #include <linux/clk.h>
+#include <linux/atmel-mci.h>
 
+#include <mach/hardware.h>
 #include <video/atmel_lcdc.h>
 
 #include <asm/setup.h>
@@ -98,6 +100,25 @@
 
 
 /*
+ * MCI (SD/MMC)
+ */
+static struct mci_platform_data __initdata mci0_data = {
+	.slot[0] = {
+		.bus_width	= 4,
+		.detect_pin	= AT91_PIN_PD10,
+	},
+};
+
+static struct mci_platform_data __initdata mci1_data = {
+	.slot[0] = {
+		.bus_width	= 4,
+		.detect_pin	= AT91_PIN_PD11,
+		.wp_pin		= AT91_PIN_PD29,
+	},
+};
+
+
+/*
  * MACB Ethernet device
  */
 static struct at91_eth_data __initdata ek_macb_data = {
@@ -380,6 +401,9 @@
 	at91_add_device_usba(&ek_usba_udc_data);
 	/* SPI */
 	at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
+	/* MMC */
+	at91_add_device_mci(0, &mci0_data);
+	at91_add_device_mci(1, &mci1_data);
 	/* Ethernet */
 	at91_add_device_eth(&ek_macb_data);
 	/* NAND */
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
index 65c3dc5..0c66deb 100644
--- a/arch/arm/mach-at91/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -46,6 +46,9 @@
 extern void at91_irq_suspend(void);
 extern void at91_irq_resume(void);
 
+/* reset */
+extern void at91sam9_alt_reset(void);
+
  /* GPIO */
 #define AT91RM9200_PQFP		3	/* AT91RM9200 PQFP package has 3 banks */
 #define AT91RM9200_BGA		4	/* AT91RM9200 BGA package has 4 banks */
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 6156689..dafbacc 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -258,16 +258,23 @@
 			 * NOTE: the Wait-for-Interrupt instruction needs to be
 			 * in icache so no SDRAM accesses are needed until the
 			 * wakeup IRQ occurs and self-refresh is terminated.
+			 * For ARM 926 based chips, this requirement is weaker
+			 * as at91sam9 can access a RAM in self-refresh mode.
 			 */
-			asm("b 1f; .align 5; 1:");
-			asm("mcr p15, 0, r0, c7, c10, 4");	/* drain write buffer */
+			asm volatile (	"mov r0, #0\n\t"
+					"b 1f\n\t"
+					".align 5\n\t"
+					"1: mcr p15, 0, r0, c7, c10, 4\n\t"
+					: /* no output */
+					: /* no input */
+					: "r0");
 			saved_lpr = sdram_selfrefresh_enable();
-			asm("mcr p15, 0, r0, c7, c0, 4");	/* wait for interrupt */
+			wait_for_interrupt_enable();
 			sdram_selfrefresh_disable(saved_lpr);
 			break;
 
 		case PM_SUSPEND_ON:
-			asm("mcr p15, 0, r0, c7, c0, 4");	/* wait for interrupt */
+			cpu_do_idle();
 			break;
 
 		default:
diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h
index 8c87d0c..ce9a206 100644
--- a/arch/arm/mach-at91/pm.h
+++ b/arch/arm/mach-at91/pm.h
@@ -21,6 +21,8 @@
 }
 
 #define sdram_selfrefresh_disable(saved_lpr)	at91_sys_write(AT91_SDRAMC_LPR, saved_lpr)
+#define wait_for_interrupt_enable()		asm volatile ("mcr p15, 0, %0, c7, c0, 4" \
+								: : "r" (0))
 
 #elif defined(CONFIG_ARCH_AT91CAP9)
 #include <mach/at91cap9_ddrsdr.h>
@@ -38,6 +40,7 @@
 }
 
 #define sdram_selfrefresh_disable(saved_lpr)	at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr)
+#define wait_for_interrupt_enable()		cpu_do_idle()
 
 #elif defined(CONFIG_ARCH_AT91SAM9G45)
 #include <mach/at91sam9_ddrsdr.h>
@@ -74,6 +77,7 @@
 		at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr0); \
 		at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1); \
 	} while (0)
+#define wait_for_interrupt_enable()		cpu_do_idle()
 
 #else
 #include <mach/at91sam9_sdramc.h>
@@ -98,5 +102,6 @@
 }
 
 #define sdram_selfrefresh_disable(saved_lpr)	at91_ramc_write(0, AT91_SDRAMC_LPR, saved_lpr)
+#define wait_for_interrupt_enable()		cpu_do_idle()
 
 #endif
diff --git a/arch/arm/mach-at91/pm_slowclock.S b/arch/arm/mach-at91/pm_slowclock.S
index b6b00a1..f7922a4 100644
--- a/arch/arm/mach-at91/pm_slowclock.S
+++ b/arch/arm/mach-at91/pm_slowclock.S
@@ -124,6 +124,7 @@
 	ldr	r5, .at91_va_base_ramc1
 
 	/* Drain write buffer */
+	mov	r0, #0
 	mcr	p15, 0, r0, c7, c10, 4
 
 #ifdef CONFIG_ARCH_AT91RM9200
diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c
index 4566bd1..ef06c66 100644
--- a/arch/arm/mach-ep93xx/clock.c
+++ b/arch/arm/mach-ep93xx/clock.c
@@ -358,8 +358,7 @@
 	int i, found = 0, __div = 0, __pdiv = 0;
 
 	/* Don't exceed the maximum rate */
-	max_rate = max(max(clk_pll1.rate / 4, clk_pll2.rate / 4),
-		       clk_xtali.rate / 4);
+	max_rate = max3(clk_pll1.rate / 4, clk_pll2.rate / 4, clk_xtali.rate / 4);
 	rate = min(rate, max_rate);
 
 	/*
diff --git a/arch/arm/mach-kirkwood/netspace_v2-setup.c b/arch/arm/mach-kirkwood/netspace_v2-setup.c
index 5e28644..5ea66f1 100644
--- a/arch/arm/mach-kirkwood/netspace_v2-setup.c
+++ b/arch/arm/mach-kirkwood/netspace_v2-setup.c
@@ -30,6 +30,7 @@
 #include <linux/gpio.h>
 #include <linux/gpio_keys.h>
 #include <linux/leds.h>
+#include <linux/gpio-fan.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/kirkwood.h>
@@ -137,6 +138,46 @@
 };
 
 /*****************************************************************************
+ * GPIO fan
+ ****************************************************************************/
+
+/* Designed for fan 40x40x16: ADDA AD0412LB-D50 6000rpm@12v */
+static struct gpio_fan_speed netspace_max_v2_fan_speed[] = {
+	{    0,  0 },
+	{ 1500,	15 },
+	{ 1700,	14 },
+	{ 1800,	13 },
+	{ 2100,	12 },
+	{ 3100,	11 },
+	{ 3300,	10 },
+	{ 4300,	 9 },
+	{ 5500,	 8 },
+};
+
+static unsigned netspace_max_v2_fan_ctrl[] = { 22, 7, 33, 23 };
+
+static struct gpio_fan_alarm netspace_max_v2_fan_alarm = {
+	.gpio		= 25,
+	.active_low	= 1,
+};
+
+static struct gpio_fan_platform_data netspace_max_v2_fan_data = {
+	.num_ctrl	= ARRAY_SIZE(netspace_max_v2_fan_ctrl),
+	.ctrl		= netspace_max_v2_fan_ctrl,
+	.alarm		= &netspace_max_v2_fan_alarm,
+	.num_speed	= ARRAY_SIZE(netspace_max_v2_fan_speed),
+	.speed		= netspace_max_v2_fan_speed,
+};
+
+static struct platform_device netspace_max_v2_gpio_fan = {
+	.name	= "gpio-fan",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &netspace_max_v2_fan_data,
+	},
+};
+
+/*****************************************************************************
  * General Setup
  ****************************************************************************/
 
@@ -205,6 +246,8 @@
 	platform_device_register(&netspace_v2_leds);
 	platform_device_register(&netspace_v2_gpio_leds);
 	platform_device_register(&netspace_v2_gpio_buttons);
+	if (machine_is_netspace_max_v2())
+		platform_device_register(&netspace_max_v2_gpio_fan);
 
 	if (gpio_request(NETSPACE_V2_GPIO_POWER_OFF, "power-off") == 0 &&
 	    gpio_direction_output(NETSPACE_V2_GPIO_POWER_OFF, 0) == 0)
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
index facfaeb..9a304d8 100644
--- a/arch/arm/mach-omap1/Makefile
+++ b/arch/arm/mach-omap1/Makefile
@@ -12,7 +12,7 @@
 obj-$(CONFIG_OMAP_32K_TIMER)	+= timer32k.o
 
 # Power Management
-obj-$(CONFIG_PM) += pm.o sleep.o
+obj-$(CONFIG_PM) += pm.o sleep.o pm_bus.o
 
 # DSP
 obj-$(CONFIG_OMAP_MBOX_FWK)	+= mailbox_mach.o
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index 73c8639..1d4163b 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -16,9 +16,12 @@
 #include <linux/init.h>
 #include <linux/input.h>
 #include <linux/interrupt.h>
+#include <linux/leds.h>
 #include <linux/platform_device.h>
 #include <linux/serial_8250.h>
 
+#include <media/soc_camera.h>
+
 #include <asm/serial.h>
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -32,6 +35,7 @@
 #include <plat/usb.h>
 #include <plat/board.h>
 #include <plat/common.h>
+#include <mach/camera.h>
 
 #include <mach/ams-delta-fiq.h>
 
@@ -213,10 +217,56 @@
 	.id	= -1
 };
 
+static struct i2c_board_info ams_delta_camera_board_info[] = {
+	{
+		I2C_BOARD_INFO("ov6650", 0x60),
+	},
+};
+
+#ifdef CONFIG_LEDS_TRIGGERS
+DEFINE_LED_TRIGGER(ams_delta_camera_led_trigger);
+
+static int ams_delta_camera_power(struct device *dev, int power)
+{
+	/*
+	 * turn on camera LED
+	 */
+	if (power)
+		led_trigger_event(ams_delta_camera_led_trigger, LED_FULL);
+	else
+		led_trigger_event(ams_delta_camera_led_trigger, LED_OFF);
+	return 0;
+}
+#else
+#define ams_delta_camera_power	NULL
+#endif
+
+static struct soc_camera_link __initdata ams_delta_iclink = {
+	.bus_id         = 0,	/* OMAP1 SoC camera bus */
+	.i2c_adapter_id = 1,
+	.board_info     = &ams_delta_camera_board_info[0],
+	.module_name    = "ov6650",
+	.power		= ams_delta_camera_power,
+};
+
+static struct platform_device ams_delta_camera_device = {
+	.name   = "soc-camera-pdrv",
+	.id     = 0,
+	.dev    = {
+		.platform_data = &ams_delta_iclink,
+	},
+};
+
+static struct omap1_cam_platform_data ams_delta_camera_platform_data = {
+	.camexclk_khz	= 12000,	/* default 12MHz clock, no extra DPLL */
+	.lclk_khz_max	= 1334,		/* results in 5fps CIF, 10fps QCIF */
+};
+
 static struct platform_device *ams_delta_devices[] __initdata = {
 	&ams_delta_kp_device,
 	&ams_delta_lcd_device,
 	&ams_delta_led_device,
+	&ams_delta_camera_device,
 };
 
 static void __init ams_delta_init(void)
@@ -225,6 +275,20 @@
 	omap_cfg_reg(UART1_TX);
 	omap_cfg_reg(UART1_RTS);
 
+	/* parallel camera interface */
+	omap_cfg_reg(H19_1610_CAM_EXCLK);
+	omap_cfg_reg(J15_1610_CAM_LCLK);
+	omap_cfg_reg(L18_1610_CAM_VS);
+	omap_cfg_reg(L15_1610_CAM_HS);
+	omap_cfg_reg(L19_1610_CAM_D0);
+	omap_cfg_reg(K14_1610_CAM_D1);
+	omap_cfg_reg(K15_1610_CAM_D2);
+	omap_cfg_reg(K19_1610_CAM_D3);
+	omap_cfg_reg(K18_1610_CAM_D4);
+	omap_cfg_reg(J14_1610_CAM_D5);
+	omap_cfg_reg(J19_1610_CAM_D6);
+	omap_cfg_reg(J18_1610_CAM_D7);
+
 	iotable_init(ams_delta_io_desc, ARRAY_SIZE(ams_delta_io_desc));
 
 	omap_board_config = ams_delta_config;
@@ -236,6 +300,11 @@
 	ams_delta_latch2_write(~0, 0);
 
 	omap1_usb_init(&ams_delta_usb_config);
+	omap1_set_camera_info(&ams_delta_camera_platform_data);
+#ifdef CONFIG_LEDS_TRIGGERS
+	led_trigger_register_simple("ams_delta_camera",
+			&ams_delta_camera_led_trigger);
+#endif
 	platform_add_devices(ams_delta_devices, ARRAY_SIZE(ams_delta_devices));
 
 #ifdef CONFIG_AMS_DELTA_FIQ
diff --git a/arch/arm/mach-omap1/board-h2-mmc.c b/arch/arm/mach-omap1/board-h2-mmc.c
index b30c499..f2fc43d 100644
--- a/arch/arm/mach-omap1/board-h2-mmc.c
+++ b/arch/arm/mach-omap1/board-h2-mmc.c
@@ -58,8 +58,7 @@
 	.dma_mask			= 0xffffffff,
 	.slots[0]       = {
 		.set_power              = mmc_set_power,
-		.ocr_mask               = MMC_VDD_28_29 | MMC_VDD_30_31 |
-					  MMC_VDD_32_33 | MMC_VDD_33_34,
+		.ocr_mask               = MMC_VDD_32_33 | MMC_VDD_33_34,
 		.name                   = "mmcblk",
 	},
 };
diff --git a/arch/arm/mach-omap1/board-h3-mmc.c b/arch/arm/mach-omap1/board-h3-mmc.c
index 54b0f06..2098525 100644
--- a/arch/arm/mach-omap1/board-h3-mmc.c
+++ b/arch/arm/mach-omap1/board-h3-mmc.c
@@ -40,8 +40,7 @@
 	.dma_mask			= 0xffffffff,
 	.slots[0]       = {
 		.set_power              = mmc_set_power,
-		.ocr_mask               = MMC_VDD_28_29 | MMC_VDD_30_31 |
-					  MMC_VDD_32_33 | MMC_VDD_33_34,
+		.ocr_mask               = MMC_VDD_32_33 | MMC_VDD_33_34,
 		.name                   = "mmcblk",
 	},
 };
diff --git a/arch/arm/mach-omap1/board-htcherald.c b/arch/arm/mach-omap1/board-htcherald.c
index 86afb29..071af3e 100644
--- a/arch/arm/mach-omap1/board-htcherald.c
+++ b/arch/arm/mach-omap1/board-htcherald.c
@@ -30,6 +30,13 @@
 #include <linux/input.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+#include <linux/htcpld.h>
+#include <linux/leds.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -39,6 +46,7 @@
 #include <plat/board.h>
 #include <plat/keypad.h>
 #include <plat/usb.h>
+#include <plat/mmc.h>
 
 #include <mach/irqs.h>
 
@@ -52,13 +60,123 @@
 #define       OMAP_LCDC_CTRL_LCD_EN           (1 << 0)
 #define       OMAP_LCDC_STAT_DONE             (1 << 0)
 
-static struct omap_lcd_config htcherald_lcd_config __initdata = {
-	.ctrl_name	= "internal",
-};
+/* GPIO definitions for the power button and keyboard slide switch */
+#define HTCHERALD_GPIO_POWER 139
+#define HTCHERALD_GPIO_SLIDE 174
+#define HTCHERALD_GIRQ_BTNS 141
 
-static struct omap_board_config_kernel htcherald_config[] __initdata = {
-	{ OMAP_TAG_LCD, &htcherald_lcd_config },
-};
+/* GPIO definitions for the touchscreen */
+#define HTCHERALD_GPIO_TS 76
+
+/* HTCPLD definitions */
+
+/*
+ * CPLD Logic
+ *
+ * Chip 3 - 0x03
+ *
+ * Function            7 6 5 4  3 2 1 0
+ * ------------------------------------
+ * DPAD light          x x x x  x x x 1
+ * SoundDev            x x x x  1 x x x
+ * Screen white        1 x x x  x x x x
+ * MMC power on        x x x x  x 1 x x
+ * Happy times (n)     0 x x x  x 1 x x
+ *
+ * Chip 4 - 0x04
+ *
+ * Function            7 6 5 4  3 2 1 0
+ * ------------------------------------
+ * Keyboard light      x x x x  x x x 1
+ * LCD Bright (4)      x x x x  x 1 1 x
+ * LCD Bright (3)      x x x x  x 0 1 x
+ * LCD Bright (2)      x x x x  x 1 0 x
+ * LCD Bright (1)      x x x x  x 0 0 x
+ * LCD Off             x x x x  0 x x x
+ * LCD image (fb)      1 x x x  x x x x
+ * LCD image (white)   0 x x x  x x x x
+ * Caps lock LED       x x 1 x  x x x x
+ *
+ * Chip 5 - 0x05
+ *
+ * Function            7 6 5 4  3 2 1 0
+ * ------------------------------------
+ * Red (solid)         x x x x  x 1 x x
+ * Red (flash)         x x x x  x x 1 x
+ * Green (GSM flash)   x x x x  1 x x x
+ * Green (GSM solid)   x x x 1  x x x x
+ * Green (wifi flash)  x x 1 x  x x x x
+ * Blue (bt flash)     x 1 x x  x x x x
+ * DPAD Int Enable     1 x x x  x x x 0
+ *
+ * (Combinations of the above can be made for different colors.)
+ * The direction pad interrupt enable must be set each time the
+ * interrupt is handled.
+ *
+ * Chip 6 - 0x06
+ *
+ * Function            7 6 5 4  3 2 1 0
+ * ------------------------------------
+ * Vibrator            x x x x  1 x x x
+ * Alt LED             x x x 1  x x x x
+ * Screen white        1 x x x  x x x x
+ * Screen white        x x 1 x  x x x x
+ * Screen white        x 0 x x  x x x x
+ * Enable kbd dpad     x x x x  x x 0 x
+ * Happy Times         0 1 0 x  x x 0 x
+ */
+
+/*
+ * HTCPLD GPIO lines start 16 after OMAP_MAX_GPIO_LINES to account
+ * for the 16 MPUIO lines.
+ */
+#define HTCPLD_GPIO_START_OFFSET	(OMAP_MAX_GPIO_LINES + 16)
+#define HTCPLD_IRQ(chip, offset)	(OMAP_IRQ_END + 8 * (chip) + (offset))
+#define HTCPLD_BASE(chip, offset)	\
+	(HTCPLD_GPIO_START_OFFSET + 8 * (chip) + (offset))
+
+#define HTCPLD_GPIO_LED_DPAD		HTCPLD_BASE(0, 0)
+#define HTCPLD_GPIO_LED_KBD		HTCPLD_BASE(1, 0)
+#define HTCPLD_GPIO_LED_CAPS		HTCPLD_BASE(1, 5)
+#define HTCPLD_GPIO_LED_RED_FLASH	HTCPLD_BASE(2, 1)
+#define HTCPLD_GPIO_LED_RED_SOLID	HTCPLD_BASE(2, 2)
+#define HTCPLD_GPIO_LED_GREEN_FLASH	HTCPLD_BASE(2, 3)
+#define HTCPLD_GPIO_LED_GREEN_SOLID	HTCPLD_BASE(2, 4)
+#define HTCPLD_GPIO_LED_WIFI		HTCPLD_BASE(2, 5)
+#define HTCPLD_GPIO_LED_BT		HTCPLD_BASE(2, 6)
+#define HTCPLD_GPIO_LED_VIBRATE		HTCPLD_BASE(3, 3)
+#define HTCPLD_GPIO_LED_ALT		HTCPLD_BASE(3, 4)
+
+#define HTCPLD_GPIO_RIGHT_KBD		HTCPLD_BASE(6, 7)
+#define HTCPLD_GPIO_UP_KBD		HTCPLD_BASE(6, 6)
+#define HTCPLD_GPIO_LEFT_KBD		HTCPLD_BASE(6, 5)
+#define HTCPLD_GPIO_DOWN_KBD		HTCPLD_BASE(6, 4)
+
+#define HTCPLD_GPIO_RIGHT_DPAD		HTCPLD_BASE(7, 7)
+#define HTCPLD_GPIO_UP_DPAD		HTCPLD_BASE(7, 6)
+#define HTCPLD_GPIO_LEFT_DPAD		HTCPLD_BASE(7, 5)
+#define HTCPLD_GPIO_DOWN_DPAD		HTCPLD_BASE(7, 4)
+#define HTCPLD_GPIO_ENTER_DPAD		HTCPLD_BASE(7, 3)
+
+/*
+ * The htcpld chip requires a gpio write to a specific line
+ * to re-enable interrupts after one has occurred.
+ */
+#define HTCPLD_GPIO_INT_RESET_HI	HTCPLD_BASE(2, 7)
+#define HTCPLD_GPIO_INT_RESET_LO	HTCPLD_BASE(2, 0)
+
+/* Chip 5 */
+#define HTCPLD_IRQ_RIGHT_KBD		HTCPLD_IRQ(0, 7)
+#define HTCPLD_IRQ_UP_KBD		HTCPLD_IRQ(0, 6)
+#define HTCPLD_IRQ_LEFT_KBD		HTCPLD_IRQ(0, 5)
+#define HTCPLD_IRQ_DOWN_KBD		HTCPLD_IRQ(0, 4)
+
+/* Chip 6 */
+#define HTCPLD_IRQ_RIGHT_DPAD		HTCPLD_IRQ(1, 7)
+#define HTCPLD_IRQ_UP_DPAD		HTCPLD_IRQ(1, 6)
+#define HTCPLD_IRQ_LEFT_DPAD		HTCPLD_IRQ(1, 5)
+#define HTCPLD_IRQ_DOWN_DPAD		HTCPLD_IRQ(1, 4)
+#define HTCPLD_IRQ_ENTER_DPAD		HTCPLD_IRQ(1, 3)
 
 /* Keyboard definition */
 
@@ -140,6 +258,129 @@
 	.resource	= kp_resources,
 };
 
+/* GPIO buttons for keyboard slide and power button */
+static struct gpio_keys_button herald_gpio_keys_table[] = {
+	{BTN_0,  HTCHERALD_GPIO_POWER, 1, "POWER", EV_KEY, 1, 20},
+	{SW_LID, HTCHERALD_GPIO_SLIDE, 0, "SLIDE", EV_SW,  1, 20},
+
+	{KEY_LEFT,  HTCPLD_GPIO_LEFT_KBD,  1, "LEFT",  EV_KEY, 1, 20},
+	{KEY_RIGHT, HTCPLD_GPIO_RIGHT_KBD, 1, "RIGHT", EV_KEY, 1, 20},
+	{KEY_UP,    HTCPLD_GPIO_UP_KBD,    1, "UP",    EV_KEY, 1, 20},
+	{KEY_DOWN,  HTCPLD_GPIO_DOWN_KBD,  1, "DOWN",  EV_KEY, 1, 20},
+
+	{KEY_LEFT,  HTCPLD_GPIO_LEFT_DPAD,   1, "DLEFT",  EV_KEY, 1, 20},
+	{KEY_RIGHT, HTCPLD_GPIO_RIGHT_DPAD,  1, "DRIGHT", EV_KEY, 1, 20},
+	{KEY_UP,    HTCPLD_GPIO_UP_DPAD,     1, "DUP",    EV_KEY, 1, 20},
+	{KEY_DOWN,  HTCPLD_GPIO_DOWN_DPAD,   1, "DDOWN",  EV_KEY, 1, 20},
+	{KEY_ENTER, HTCPLD_GPIO_ENTER_DPAD,  1, "DENTER", EV_KEY, 1, 20},
+};
+
+static struct gpio_keys_platform_data herald_gpio_keys_data = {
+	.buttons	= herald_gpio_keys_table,
+	.nbuttons	= ARRAY_SIZE(herald_gpio_keys_table),
+	.rep		= 1,
+};
+
+static struct platform_device herald_gpiokeys_device = {
+	.name      = "gpio-keys",
+	.id		= -1,
+	.dev = {
+		.platform_data = &herald_gpio_keys_data,
+	},
+};
+
+/* LEDs for the Herald.  These connect to the HTCPLD GPIO device. */
+static struct gpio_led gpio_leds[] = {
+	{"dpad",        NULL, HTCPLD_GPIO_LED_DPAD,        0, 0, LEDS_GPIO_DEFSTATE_OFF},
+	{"kbd",         NULL, HTCPLD_GPIO_LED_KBD,         0, 0, LEDS_GPIO_DEFSTATE_OFF},
+	{"vibrate",     NULL, HTCPLD_GPIO_LED_VIBRATE,     0, 0, LEDS_GPIO_DEFSTATE_OFF},
+	{"green_solid", NULL, HTCPLD_GPIO_LED_GREEN_SOLID, 0, 0, LEDS_GPIO_DEFSTATE_OFF},
+	{"green_flash", NULL, HTCPLD_GPIO_LED_GREEN_FLASH, 0, 0, LEDS_GPIO_DEFSTATE_OFF},
+	{"red_solid",   "mmc0", HTCPLD_GPIO_LED_RED_SOLID, 0, 0, LEDS_GPIO_DEFSTATE_OFF},
+	{"red_flash",   NULL, HTCPLD_GPIO_LED_RED_FLASH,   0, 0, LEDS_GPIO_DEFSTATE_OFF},
+	{"wifi",        NULL, HTCPLD_GPIO_LED_WIFI,        0, 0, LEDS_GPIO_DEFSTATE_OFF},
+	{"bt",          NULL, HTCPLD_GPIO_LED_BT,          0, 0, LEDS_GPIO_DEFSTATE_OFF},
+	{"caps",        NULL, HTCPLD_GPIO_LED_CAPS,        0, 0, LEDS_GPIO_DEFSTATE_OFF},
+	{"alt",         NULL, HTCPLD_GPIO_LED_ALT,         0, 0, LEDS_GPIO_DEFSTATE_OFF},
+};
+
+static struct gpio_led_platform_data gpio_leds_data = {
+	.leds		= gpio_leds,
+	.num_leds	= ARRAY_SIZE(gpio_leds),
+};
+
+static struct platform_device gpio_leds_device = {
+	.name		= "leds-gpio",
+	.id		= 0,
+	.dev	= {
+		.platform_data	= &gpio_leds_data,
+	},
+};
+
+/* HTC PLD chips */
+
+static struct resource htcpld_resources[] = {
+	[0] = {
+		.start  = OMAP_GPIO_IRQ(HTCHERALD_GIRQ_BTNS),
+		.end    = OMAP_GPIO_IRQ(HTCHERALD_GIRQ_BTNS),
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+struct htcpld_chip_platform_data htcpld_chips[] = {
+	[0] = {
+		.addr		= 0x03,
+		.reset		= 0x04,
+		.num_gpios	= 8,
+		.gpio_out_base	= HTCPLD_BASE(0, 0),
+		.gpio_in_base	= HTCPLD_BASE(4, 0),
+	},
+	[1] = {
+		.addr		= 0x04,
+		.reset		= 0x8e,
+		.num_gpios	= 8,
+		.gpio_out_base	= HTCPLD_BASE(1, 0),
+		.gpio_in_base	= HTCPLD_BASE(5, 0),
+	},
+	[2] = {
+		.addr		= 0x05,
+		.reset		= 0x80,
+		.num_gpios	= 8,
+		.gpio_out_base	= HTCPLD_BASE(2, 0),
+		.gpio_in_base	= HTCPLD_BASE(6, 0),
+		.irq_base	= HTCPLD_IRQ(0, 0),
+		.num_irqs	= 8,
+	},
+	[3] = {
+		.addr		= 0x06,
+		.reset		= 0x40,
+		.num_gpios	= 8,
+		.gpio_out_base	= HTCPLD_BASE(3, 0),
+		.gpio_in_base	= HTCPLD_BASE(7, 0),
+		.irq_base	= HTCPLD_IRQ(1, 0),
+		.num_irqs	= 8,
+	},
+};
+
+struct htcpld_core_platform_data htcpld_pfdata = {
+	.int_reset_gpio_hi = HTCPLD_GPIO_INT_RESET_HI,
+	.int_reset_gpio_lo = HTCPLD_GPIO_INT_RESET_LO,
+	.i2c_adapter_id	   = 1,
+
+	.chip		   = htcpld_chips,
+	.num_chip	   = ARRAY_SIZE(htcpld_chips),
+};
+
+static struct platform_device htcpld_device = {
+	.name		= "i2c-htcpld",
+	.id		= -1,
+	.resource	= htcpld_resources,
+	.num_resources	= ARRAY_SIZE(htcpld_resources),
+	.dev	= {
+		.platform_data	= &htcpld_pfdata,
+	},
+};
+
 /* USB Device */
 static struct omap_usb_config htcherald_usb_config __initdata = {
 	.otg = 0,
@@ -150,14 +391,71 @@
 };
 
 /* LCD Device resources */
+static struct omap_lcd_config htcherald_lcd_config __initdata = {
+	.ctrl_name	= "internal",
+};
+
+static struct omap_board_config_kernel htcherald_config[] __initdata = {
+	{ OMAP_TAG_LCD, &htcherald_lcd_config },
+};
+
 static struct platform_device lcd_device = {
 	.name           = "lcd_htcherald",
 	.id             = -1,
 };
 
+/* MMC Card */
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
+static struct omap_mmc_platform_data htc_mmc1_data = {
+	.nr_slots                       = 1,
+	.switch_slot                    = NULL,
+	.slots[0]       = {
+		.ocr_mask               = MMC_VDD_32_33 | MMC_VDD_33_34,
+		.name                   = "mmcblk",
+		.nomux                  = 1,
+		.wires                  = 4,
+		.switch_pin             = -1,
+	},
+};
+
+static struct omap_mmc_platform_data *htc_mmc_data[1];
+#endif
+
+
+/* Platform devices for the Herald */
 static struct platform_device *devices[] __initdata = {
 	&kp_device,
 	&lcd_device,
+	&htcpld_device,
+	&gpio_leds_device,
+	&herald_gpiokeys_device,
+};
+
+/*
+ * Touchscreen
+ */
+static const struct ads7846_platform_data htcherald_ts_platform_data = {
+	.model			= 7846,
+	.keep_vref_on		= 1,
+	.x_plate_ohms		= 496,
+	.gpio_pendown		= HTCHERALD_GPIO_TS,
+	.pressure_max		= 100000,
+	.pressure_min		= 5000,
+	.x_min			= 528,
+	.x_max			= 3760,
+	.y_min			= 624,
+	.y_max			= 3760,
+};
+
+static struct spi_board_info __initdata htcherald_spi_board_info[] = {
+	{
+		.modalias		= "ads7846",
+		.platform_data		= &htcherald_ts_platform_data,
+		.irq			= OMAP_GPIO_IRQ(HTCHERALD_GPIO_TS),
+		.max_speed_hz		= 2500000,
+		.bus_num		= 2,
+		.chip_select		= 1,
+	}
 };
 
 /*
@@ -278,6 +576,7 @@
 {
 	printk(KERN_INFO "HTC Herald init.\n");
 
+	/* Do board initialization before we register all the devices */
 	omap_gpio_init();
 
 	omap_board_config = htcherald_config;
@@ -288,6 +587,16 @@
 
 	htcherald_usb_enable();
 	omap1_usb_init(&htcherald_usb_config);
+
+	spi_register_board_info(htcherald_spi_board_info,
+		ARRAY_SIZE(htcherald_spi_board_info));
+
+	omap_register_i2c_bus(1, 100, NULL, 0);
+
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
+	htc_mmc_data[0] = &htc_mmc1_data;
+	omap1_init_mmc(htc_mmc_data, 1);
+#endif
 }
 
 static void __init htcherald_init_irq(void)
diff --git a/arch/arm/mach-omap1/board-sx1-mmc.c b/arch/arm/mach-omap1/board-sx1-mmc.c
index 5b33ae8..e8ddd86 100644
--- a/arch/arm/mach-omap1/board-sx1-mmc.c
+++ b/arch/arm/mach-omap1/board-sx1-mmc.c
@@ -44,8 +44,7 @@
 	.nr_slots                       = 1,
 	.slots[0]       = {
 		.set_power              = mmc_set_power,
-		.ocr_mask               = MMC_VDD_28_29 | MMC_VDD_30_31 |
-					  MMC_VDD_32_33 | MMC_VDD_33_34,
+		.ocr_mask               = MMC_VDD_32_33 | MMC_VDD_33_34,
 		.name                   = "mmcblk",
 	},
 };
diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c
index b583121..ea0d80a 100644
--- a/arch/arm/mach-omap1/devices.c
+++ b/arch/arm/mach-omap1/devices.c
@@ -9,6 +9,7 @@
  * (at your option) any later version.
  */
 
+#include <linux/dma-mapping.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -192,6 +193,48 @@
 }
 #endif
 
+
+#define OMAP1_CAMERA_BASE	0xfffb6800
+#define OMAP1_CAMERA_IOSIZE	0x1c
+
+static struct resource omap1_camera_resources[] = {
+	[0] = {
+		.start	= OMAP1_CAMERA_BASE,
+		.end	= OMAP1_CAMERA_BASE + OMAP1_CAMERA_IOSIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= INT_CAMERA,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static u64 omap1_camera_dma_mask = DMA_BIT_MASK(32);
+
+static struct platform_device omap1_camera_device = {
+	.name		= "omap1-camera",
+	.id		= 0, /* This is used to put cameras on this interface */
+	.dev		= {
+		.dma_mask		= &omap1_camera_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+	.num_resources	= ARRAY_SIZE(omap1_camera_resources),
+	.resource	= omap1_camera_resources,
+};
+
+void __init omap1_camera_init(void *info)
+{
+	struct platform_device *dev = &omap1_camera_device;
+	int ret;
+
+	dev->dev.platform_data = info;
+
+	ret = platform_device_register(dev);
+	if (ret)
+		dev_err(&dev->dev, "unable to register device: %d\n", ret);
+}
+
+
 /*-------------------------------------------------------------------------*/
 
 static inline void omap_init_sti(void) {}
@@ -258,3 +301,30 @@
 }
 arch_initcall(omap1_init_devices);
 
+#if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE)
+
+static struct resource wdt_resources[] = {
+	{
+		.start		= 0xfffeb000,
+		.end		= 0xfffeb07F,
+		.flags		= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device omap_wdt_device = {
+	.name	   = "omap_wdt",
+	.id	     = -1,
+	.num_resources	= ARRAY_SIZE(wdt_resources),
+	.resource	= wdt_resources,
+};
+
+static int __init omap_init_wdt(void)
+{
+	if (!cpu_is_omap16xx())
+		return;
+
+	platform_device_register(&omap_wdt_device);
+	return 0;
+}
+subsys_initcall(omap_init_wdt);
+#endif
diff --git a/arch/arm/mach-omap1/include/mach/camera.h b/arch/arm/mach-omap1/include/mach/camera.h
new file mode 100644
index 0000000..fd54b45
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/camera.h
@@ -0,0 +1,11 @@
+#ifndef __ASM_ARCH_CAMERA_H_
+#define __ASM_ARCH_CAMERA_H_
+
+void omap1_camera_init(void *);
+
+static inline void omap1_set_camera_info(struct omap1_cam_platform_data *info)
+{
+	omap1_camera_init(info);
+}
+
+#endif /* __ASM_ARCH_CAMERA_H_ */
diff --git a/arch/arm/mach-omap1/pm_bus.c b/arch/arm/mach-omap1/pm_bus.c
new file mode 100644
index 0000000..8b66392
--- /dev/null
+++ b/arch/arm/mach-omap1/pm_bus.c
@@ -0,0 +1,98 @@
+/*
+ * Runtime PM support code for OMAP1
+ *
+ * Author: Kevin Hilman, Deep Root Systems, LLC
+ *
+ * Copyright (C) 2010 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/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/pm_runtime.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+
+#include <plat/omap_device.h>
+#include <plat/omap-pm.h>
+
+#ifdef CONFIG_PM_RUNTIME
+static int omap1_pm_runtime_suspend(struct device *dev)
+{
+	struct clk *iclk, *fclk;
+	int ret = 0;
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	ret = pm_generic_runtime_suspend(dev);
+
+	fclk = clk_get(dev, "fck");
+	if (!IS_ERR(fclk)) {
+		clk_disable(fclk);
+		clk_put(fclk);
+	}
+
+	iclk = clk_get(dev, "ick");
+	if (!IS_ERR(iclk)) {
+		clk_disable(iclk);
+		clk_put(iclk);
+	}
+
+	return 0;
+};
+
+static int omap1_pm_runtime_resume(struct device *dev)
+{
+	int ret = 0;
+	struct clk *iclk, *fclk;
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	iclk = clk_get(dev, "ick");
+	if (!IS_ERR(iclk)) {
+		clk_enable(iclk);
+		clk_put(iclk);
+	}
+
+	fclk = clk_get(dev, "fck");
+	if (!IS_ERR(fclk)) {
+		clk_enable(fclk);
+		clk_put(fclk);
+	}
+
+	return pm_generic_runtime_resume(dev);
+};
+
+static int __init omap1_pm_runtime_init(void)
+{
+	const struct dev_pm_ops *pm;
+	struct dev_pm_ops *omap_pm;
+
+	pm = platform_bus_get_pm_ops();
+	if (!pm) {
+		pr_err("%s: unable to get dev_pm_ops from platform_bus\n",
+			__func__);
+		return -ENODEV;
+	}
+
+	omap_pm = kmemdup(pm, sizeof(struct dev_pm_ops), GFP_KERNEL);
+	if (!omap_pm) {
+		pr_err("%s: unable to alloc memory for new dev_pm_ops\n",
+			__func__);
+		return -ENOMEM;
+	}
+
+	omap_pm->runtime_suspend = omap1_pm_runtime_suspend;
+	omap_pm->runtime_resume = omap1_pm_runtime_resume;
+
+	platform_bus_set_pm_ops(omap_pm);
+
+	return 0;
+}
+core_initcall(omap1_pm_runtime_init);
+#endif /* CONFIG_PM_RUNTIME */
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index b48bacf..ab784bf 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -11,9 +11,8 @@
 	select PM_RUNTIME
 	select VFP
 	select NEON if ARCH_OMAP3 || ARCH_OMAP4
-	select SERIAL_8250
-	select SERIAL_CORE_CONSOLE
-	select SERIAL_8250_CONSOLE
+	select SERIAL_OMAP
+	select SERIAL_OMAP_CONSOLE
 	select I2C
 	select I2C_OMAP
 	select MFD
@@ -35,7 +34,7 @@
 	default y
 	select CPU_V7
 	select USB_ARCH_HAS_EHCI
-	select ARM_L1_CACHE_SHIFT_6
+	select ARM_L1_CACHE_SHIFT_6 if !ARCH_OMAP4
 
 config ARCH_OMAP4
 	bool "TI OMAP4"
@@ -43,6 +42,8 @@
 	depends on ARCH_OMAP2PLUS
 	select CPU_V7
 	select ARM_GIC
+	select PL310_ERRATA_588369
+	select ARM_ERRATA_720789
 
 comment "OMAP Core Type"
 	depends on ARCH_OMAP2
@@ -99,20 +100,20 @@
 
 config MACH_OMAP_H4
 	bool "OMAP 2420 H4 board"
-	depends on ARCH_OMAP2
+	depends on ARCH_OMAP2420
 	default y
 	select OMAP_PACKAGE_ZAF
 	select OMAP_DEBUG_DEVICES
 
 config MACH_OMAP_APOLLON
 	bool "OMAP 2420 Apollon board"
-	depends on ARCH_OMAP2
+	depends on ARCH_OMAP2420
 	default y
 	select OMAP_PACKAGE_ZAC
 
 config MACH_OMAP_2430SDP
 	bool "OMAP 2430 SDP board"
-	depends on ARCH_OMAP2
+	depends on ARCH_OMAP2430
 	default y
 	select OMAP_PACKAGE_ZAC
 
@@ -135,6 +136,26 @@
 	default y
 	select OMAP_PACKAGE_CBB
 
+config MACH_OMAP3530_LV_SOM
+	bool "OMAP3 Logic 3530 LV SOM board"
+	depends on ARCH_OMAP3
+	select OMAP_PACKAGE_CBB
+	default y
+	help
+	 Support for the LogicPD OMAP3530 SOM Development kit
+	 for full description please see the products webpage at
+	 http://www.logicpd.com/products/development-kits/texas-instruments-zoom%E2%84%A2-omap35x-development-kit
+
+config MACH_OMAP3_TORPEDO
+	bool "OMAP3 Logic 35x Torpedo board"
+	depends on ARCH_OMAP3
+	select OMAP_PACKAGE_CBB
+	default y
+	help
+	 Support for the LogicPD OMAP35x Torpedo Development kit
+	 for full description please see the products webpage at
+	 http://www.logicpd.com/products/development-kits/zoom-omap35x-torpedo-development-kit
+
 config MACH_OVERO
 	bool "Gumstix Overo board"
 	depends on ARCH_OMAP3
@@ -200,12 +221,18 @@
 	depends on ARCH_OMAP3
 	default y
 	select OMAP_PACKAGE_CBB
+	select SERIAL_8250
+	select SERIAL_CORE_CONSOLE
+	select SERIAL_8250_CONSOLE
 
 config MACH_OMAP_ZOOM3
 	bool "OMAP3630 Zoom3 board"
 	depends on ARCH_OMAP3
 	default y
 	select OMAP_PACKAGE_CBP
+	select SERIAL_8250
+	select SERIAL_CORE_CONSOLE
+	select SERIAL_8250_CONSOLE
 
 config MACH_CM_T35
 	bool "CompuLab CM-T35 module"
@@ -214,12 +241,25 @@
 	select OMAP_PACKAGE_CUS
 	select OMAP_MUX
 
+config MACH_CM_T3517
+	bool "CompuLab CM-T3517 module"
+	depends on ARCH_OMAP3
+	default y
+	select OMAP_PACKAGE_CBB
+	select OMAP_MUX
+
 config MACH_IGEP0020
 	bool "IGEP v2 board"
 	depends on ARCH_OMAP3
 	default y
 	select OMAP_PACKAGE_CBB
 
+config MACH_IGEP0030
+	bool "IGEP OMAP3 module"
+	depends on ARCH_OMAP3
+	default y
+	select OMAP_PACKAGE_CBB
+
 config MACH_SBC3530
 	bool "OMAP3 SBC STALKER board"
 	depends on ARCH_OMAP3
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 88d3a1e..7352412 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -3,9 +3,10 @@
 #
 
 # Common support
-obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o pm.o
+obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o pm.o \
+	 common.o
 
-omap-2-3-common				= irq.o sdrc.o
+omap-2-3-common				= irq.o sdrc.o prm2xxx_3xxx.o
 hwmod-common				= omap_hwmod.o \
 					  omap_hwmod_common_data.o
 prcm-common				= prcm.o powerdomain.o
@@ -15,7 +16,7 @@
 
 obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(prcm-common) $(hwmod-common)
 obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(prcm-common) $(hwmod-common)
-obj-$(CONFIG_ARCH_OMAP4) += $(prcm-common) $(hwmod-common)
+obj-$(CONFIG_ARCH_OMAP4) += $(prcm-common) prm44xx.o $(hwmod-common)
 
 obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
 
@@ -49,14 +50,18 @@
 # Power Management
 ifeq ($(CONFIG_PM),y)
 obj-$(CONFIG_ARCH_OMAP2)		+= pm24xx.o
-obj-$(CONFIG_ARCH_OMAP2)		+= sleep24xx.o
-obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o cpuidle34xx.o
-obj-$(CONFIG_ARCH_OMAP4)		+= pm44xx.o
+obj-$(CONFIG_ARCH_OMAP2)		+= sleep24xx.o pm_bus.o
+obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o cpuidle34xx.o pm_bus.o
+obj-$(CONFIG_ARCH_OMAP4)		+= pm44xx.o pm_bus.o
 obj-$(CONFIG_PM_DEBUG)			+= pm-debug.o
 
 AFLAGS_sleep24xx.o			:=-Wa,-march=armv6
 AFLAGS_sleep34xx.o			:=-Wa,-march=armv7-a
 
+ifeq ($(CONFIG_PM_VERBOSE),y)
+CFLAGS_pm_bus.o				+= -DDEBUG
+endif
+
 endif
 
 # PRCM
@@ -87,6 +92,7 @@
 obj-$(CONFIG_ARCH_OMAP2420)		+= omap_hwmod_2420_data.o
 obj-$(CONFIG_ARCH_OMAP2430)		+= omap_hwmod_2430_data.o
 obj-$(CONFIG_ARCH_OMAP3)		+= omap_hwmod_3xxx_data.o
+obj-$(CONFIG_ARCH_OMAP4)		+= omap_hwmod_44xx_data.o
 
 # EMU peripherals
 obj-$(CONFIG_OMAP3_EMU)			+= emu.o
@@ -115,6 +121,10 @@
 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 \
@@ -146,8 +156,11 @@
 					   hsmmc.o
 obj-$(CONFIG_MACH_CM_T35)		+= board-cm-t35.o \
 					   hsmmc.o
+obj-$(CONFIG_MACH_CM_T3517)		+= board-cm-t3517.o
 obj-$(CONFIG_MACH_IGEP0020)		+= board-igep0020.o \
 					   hsmmc.o
+obj-$(CONFIG_MACH_IGEP0030)		+= board-igep0030.o \
+					   hsmmc.o
 obj-$(CONFIG_MACH_OMAP3_TOUCHBOOK)	+= board-omap3touchbook.o \
 					   hsmmc.o
 obj-$(CONFIG_MACH_OMAP_4430SDP)		+= board-4430sdp.o \
@@ -174,3 +187,6 @@
 
 smc91x-$(CONFIG_SMC91X)			:= gpmc-smc91x.o
 obj-y					+= $(smc91x-m) $(smc91x-y)
+
+smsc911x-$(CONFIG_SMSC911X)		:= gpmc-smsc911x.o
+obj-y					+= $(smsc911x-m) $(smsc911x-y)
diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index b857ce4..b527f8d 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -19,6 +19,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
+#include <linux/mmc/host.h>
 #include <linux/delay.h>
 #include <linux/i2c/twl.h>
 #include <linux/err.h>
@@ -190,7 +191,7 @@
 static struct omap2_hsmmc_info mmc[] __initdata = {
 	{
 		.mmc		= 1,
-		.wires		= 4,
+		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
 		.ext_clock	= 1,
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index a5b095c..4e3742c 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -24,6 +24,7 @@
 #include <linux/regulator/machine.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
+#include <linux/mmc/host.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -38,15 +39,14 @@
 #include <plat/gpmc.h>
 #include <plat/display.h>
 
-#include <plat/control.h>
 #include <plat/gpmc-smc91x.h>
 
-#include <mach/board-flash.h>
-
+#include "board-flash.h"
 #include "mux.h"
 #include "sdram-qimonda-hyb18m512160af-6.h"
 #include "hsmmc.h"
 #include "pm.h"
+#include "control.h"
 
 #define CONFIG_DISABLE_HFCLK 1
 
@@ -76,7 +76,7 @@
 	{1, 10000, 30000, 300000},
 };
 
-static int board_keymap[] = {
+static uint32_t board_keymap[] = {
 	KEY(0, 0, KEY_LEFT),
 	KEY(0, 1, KEY_RIGHT),
 	KEY(0, 2, KEY_A),
@@ -353,12 +353,12 @@
 		/* 8 bits (default) requires S6.3 == ON,
 		 * so the SIM card isn't used; else 4 bits.
 		 */
-		.wires		= 8,
+		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= 4,
 	},
 	{
 		.mmc		= 2,
-		.wires		= 8,
+		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= 7,
 	},
 	{}	/* Terminator */
diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c
index fd27ac0..bbcf580 100644
--- a/arch/arm/mach-omap2/board-3630sdp.c
+++ b/arch/arm/mach-omap2/board-3630sdp.c
@@ -21,8 +21,8 @@
 #include <plat/usb.h>
 
 #include <mach/board-zoom.h>
-#include <mach/board-flash.h>
 
+#include "board-flash.h"
 #include "mux.h"
 #include "sdram-hynix-h8mbx00u0mer-0em.h"
 
@@ -208,7 +208,6 @@
 static void __init omap_sdp_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBP);
-	omap_serial_init();
 	zoom_peripherals_init();
 	board_smc91x_init();
 	board_flash_init(sdp_flash_partitions, chip_sel_sdp);
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 0b6a65f..69a4ae9 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -20,6 +20,7 @@
 #include <linux/usb/otg.h>
 #include <linux/spi/spi.h>
 #include <linux/i2c/twl.h>
+#include <linux/gpio_keys.h>
 #include <linux/regulator/machine.h>
 #include <linux/leds.h>
 
@@ -31,15 +32,18 @@
 
 #include <plat/board.h>
 #include <plat/common.h>
-#include <plat/control.h>
-#include <plat/timer-gp.h>
 #include <plat/usb.h>
 #include <plat/mmc.h>
+
 #include "hsmmc.h"
+#include "timer-gp.h"
+#include "control.h"
 
 #define ETH_KS8851_IRQ			34
 #define ETH_KS8851_POWER_ON		48
 #define ETH_KS8851_QUART		138
+#define OMAP4_SFH7741_SENSOR_OUTPUT_GPIO	184
+#define OMAP4_SFH7741_ENABLE_GPIO		188
 
 static struct gpio_led sdp4430_gpio_leds[] = {
 	{
@@ -77,11 +81,47 @@
 
 };
 
+static struct gpio_keys_button sdp4430_gpio_keys[] = {
+	{
+		.desc			= "Proximity Sensor",
+		.type			= EV_SW,
+		.code			= SW_FRONT_PROXIMITY,
+		.gpio			= OMAP4_SFH7741_SENSOR_OUTPUT_GPIO,
+		.active_low		= 0,
+	}
+};
+
 static struct gpio_led_platform_data sdp4430_led_data = {
 	.leds	= sdp4430_gpio_leds,
 	.num_leds	= ARRAY_SIZE(sdp4430_gpio_leds),
 };
 
+static int omap_prox_activate(struct device *dev)
+{
+	gpio_set_value(OMAP4_SFH7741_ENABLE_GPIO , 1);
+	return 0;
+}
+
+static void omap_prox_deactivate(struct device *dev)
+{
+	gpio_set_value(OMAP4_SFH7741_ENABLE_GPIO , 0);
+}
+
+static struct gpio_keys_platform_data sdp4430_gpio_keys_data = {
+	.buttons	= sdp4430_gpio_keys,
+	.nbuttons	= ARRAY_SIZE(sdp4430_gpio_keys),
+	.enable		= omap_prox_activate,
+	.disable	= omap_prox_deactivate,
+};
+
+static struct platform_device sdp4430_gpio_keys_device = {
+	.name	= "gpio-keys",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &sdp4430_gpio_keys_data,
+	},
+};
+
 static struct platform_device sdp4430_leds_gpio = {
 	.name	= "leds-gpio",
 	.id	= -1,
@@ -161,6 +201,7 @@
 
 static struct platform_device *sdp4430_devices[] __initdata = {
 	&sdp4430_lcd_device,
+	&sdp4430_gpio_keys_device,
 	&sdp4430_leds_gpio,
 };
 
@@ -193,15 +234,16 @@
 static struct omap2_hsmmc_info mmc[] = {
 	{
 		.mmc		= 1,
-		.wires		= 8,
+		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= -EINVAL,
 	},
 	{
 		.mmc		= 2,
-		.wires		= 8,
+		.caps		=  MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
 		.nonremovable   = true,
+		.ocr_mask	= MMC_VDD_29_30,
 	},
 	{}	/* Terminator */
 };
@@ -235,8 +277,14 @@
 
 static __init void omap4_twl6030_hsmmc_set_late_init(struct device *dev)
 {
-	struct omap_mmc_platform_data *pdata = dev->platform_data;
+	struct omap_mmc_platform_data *pdata;
 
+	/* dev can be null if CONFIG_MMC_OMAP_HS is not set */
+	if (!dev) {
+		pr_err("Failed %s\n", __func__);
+		return;
+	}
+	pdata = dev->platform_data;
 	pdata->init =	omap4_twl6030_hsmmc_late_init;
 }
 
@@ -412,6 +460,11 @@
 		I2C_BOARD_INFO("tmp105", 0x48),
 	},
 };
+static struct i2c_board_info __initdata sdp4430_i2c_4_boardinfo[] = {
+	{
+		I2C_BOARD_INFO("hmc5843", 0x1e),
+	},
+};
 static int __init omap4_i2c_init(void)
 {
 	/*
@@ -423,14 +476,36 @@
 	omap_register_i2c_bus(2, 400, NULL, 0);
 	omap_register_i2c_bus(3, 400, sdp4430_i2c_3_boardinfo,
 				ARRAY_SIZE(sdp4430_i2c_3_boardinfo));
-	omap_register_i2c_bus(4, 400, NULL, 0);
+	omap_register_i2c_bus(4, 400, sdp4430_i2c_4_boardinfo,
+				ARRAY_SIZE(sdp4430_i2c_4_boardinfo));
 	return 0;
 }
+
+static void __init omap_sfh7741prox_init(void)
+{
+	int  error;
+
+	error = gpio_request(OMAP4_SFH7741_ENABLE_GPIO, "sfh7741");
+	if (error < 0) {
+		pr_err("%s:failed to request GPIO %d, error %d\n",
+			__func__, OMAP4_SFH7741_ENABLE_GPIO, error);
+		return;
+	}
+
+	error = gpio_direction_output(OMAP4_SFH7741_ENABLE_GPIO , 0);
+	if (error < 0) {
+		pr_err("%s: GPIO configuration failed: GPIO %d,error %d\n",
+			 __func__, OMAP4_SFH7741_ENABLE_GPIO, error);
+		gpio_free(OMAP4_SFH7741_ENABLE_GPIO);
+	}
+}
+
 static void __init omap_4430sdp_init(void)
 {
 	int status;
 
 	omap4_i2c_init();
+	omap_sfh7741prox_init();
 	platform_add_devices(sdp4430_devices, ARRAY_SIZE(sdp4430_devices));
 	omap_serial_init();
 	omap4_twl6030_hsmmc_init(mmc);
diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c
index e1f8dda..0739950 100644
--- a/arch/arm/mach-omap2/board-am3517evm.c
+++ b/arch/arm/mach-omap2/board-am3517evm.c
@@ -33,11 +33,11 @@
 
 #include <plat/board.h>
 #include <plat/common.h>
-#include <plat/control.h>
 #include <plat/usb.h>
 #include <plat/display.h>
 
 #include "mux.h"
+#include "control.h"
 
 #define AM35XX_EVM_MDIO_FREQUENCY	(1000000)
 
@@ -125,7 +125,7 @@
 	regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
 }
 
-void am3517_evm_ethernet_init(struct emac_platform_data *pdata)
+static void am3517_evm_ethernet_init(struct emac_platform_data *pdata)
 {
 	unsigned int regval;
 
@@ -160,7 +160,6 @@
 static struct i2c_board_info __initdata am3517evm_i2c1_boardinfo[] = {
 	{
 		I2C_BOARD_INFO("s35390a", 0x30),
-		.type		= "s35390a",
 	},
 };
 
@@ -368,7 +367,7 @@
 	.default_device	= &am3517_evm_lcd_device,
 };
 
-struct platform_device am3517_evm_dss_device = {
+static struct platform_device am3517_evm_dss_device = {
 	.name		= "omapdss",
 	.id		= -1,
 	.dev		= {
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
index 68f07f5..2c6db1a 100644
--- a/arch/arm/mach-omap2/board-apollon.c
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -39,9 +39,9 @@
 #include <plat/board.h>
 #include <plat/common.h>
 #include <plat/gpmc.h>
-#include <plat/control.h>
 
 #include "mux.h"
+#include "control.h"
 
 /* LED & Switch macros */
 #define LED0_GPIO13		13
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index 934d938..63f764e 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -31,6 +31,7 @@
 #include <linux/i2c/at24.h>
 #include <linux/i2c/twl.h>
 #include <linux/regulator/machine.h>
+#include <linux/mmc/host.h>
 
 #include <linux/spi/spi.h>
 #include <linux/spi/tdo24m.h>
@@ -237,8 +238,6 @@
 	defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
 #include <linux/spi/ads7846.h>
 
-#include <plat/mcspi.h>
-
 static struct omap2_mcspi_device_config ads7846_mcspi_config = {
 	.turbo_mode	= 0,
 	.single_channel	= 1,	/* 0: slave, 1: master */
@@ -558,7 +557,7 @@
 	.usb_mode	= T2_USB_MODE_ULPI,
 };
 
-static int cm_t35_keymap[] = {
+static uint32_t cm_t35_keymap[] = {
 	KEY(0, 0, KEY_A),	KEY(0, 1, KEY_B),	KEY(0, 2, KEY_LEFT),
 	KEY(1, 0, KEY_UP),	KEY(1, 1, KEY_ENTER),	KEY(1, 2, KEY_DOWN),
 	KEY(2, 0, KEY_RIGHT),	KEY(2, 1, KEY_C),	KEY(2, 2, KEY_D),
@@ -579,14 +578,14 @@
 static struct omap2_hsmmc_info mmc[] = {
 	{
 		.mmc		= 1,
-		.wires		= 4,
+		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
 
 	},
 	{
 		.mmc		= 2,
-		.wires		= 4,
+		.caps		= MMC_CAP_4_BIT_DATA,
 		.transceiver	= 1,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
diff --git a/arch/arm/mach-omap2/board-cm-t3517.c b/arch/arm/mach-omap2/board-cm-t3517.c
new file mode 100644
index 0000000..1dd303e
--- /dev/null
+++ b/arch/arm/mach-omap2/board-cm-t3517.c
@@ -0,0 +1,292 @@
+/*
+ * linux/arch/arm/mach-omap2/board-cm-t3517.c
+ *
+ * Support for the CompuLab CM-T3517 modules
+ *
+ * Copyright (C) 2010 CompuLab, Ltd.
+ * Author: Igor Grinberg <grinberg@compulab.co.il>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/rtc-v3020.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/can/platform/ti_hecc.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <plat/board.h>
+#include <plat/common.h>
+#include <plat/usb.h>
+#include <plat/nand.h>
+#include <plat/gpmc.h>
+
+#include <mach/am35xx.h>
+
+#include "mux.h"
+#include "control.h"
+
+#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+static struct gpio_led cm_t3517_leds[] = {
+	[0] = {
+		.gpio			= 186,
+		.name			= "cm-t3517:green",
+		.default_trigger	= "heartbeat",
+		.active_low		= 0,
+	},
+};
+
+static struct gpio_led_platform_data cm_t3517_led_pdata = {
+	.num_leds	= ARRAY_SIZE(cm_t3517_leds),
+	.leds		= cm_t3517_leds,
+};
+
+static struct platform_device cm_t3517_led_device = {
+	.name		= "leds-gpio",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &cm_t3517_led_pdata,
+	},
+};
+
+static void __init cm_t3517_init_leds(void)
+{
+	platform_device_register(&cm_t3517_led_device);
+}
+#else
+static inline void cm_t3517_init_leds(void) {}
+#endif
+
+#if defined(CONFIG_CAN_TI_HECC) || defined(CONFIG_CAN_TI_HECC_MODULE)
+static struct resource cm_t3517_hecc_resources[] = {
+	{
+		.start	= AM35XX_IPSS_HECC_BASE,
+		.end	= AM35XX_IPSS_HECC_BASE + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_35XX_HECC0_IRQ,
+		.end	= INT_35XX_HECC0_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct ti_hecc_platform_data cm_t3517_hecc_pdata = {
+	.scc_hecc_offset	= AM35XX_HECC_SCC_HECC_OFFSET,
+	.scc_ram_offset		= AM35XX_HECC_SCC_RAM_OFFSET,
+	.hecc_ram_offset	= AM35XX_HECC_RAM_OFFSET,
+	.mbx_offset		= AM35XX_HECC_MBOX_OFFSET,
+	.int_line		= AM35XX_HECC_INT_LINE,
+	.version		= AM35XX_HECC_VERSION,
+};
+
+static struct platform_device cm_t3517_hecc_device = {
+	.name		= "ti_hecc",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(cm_t3517_hecc_resources),
+	.resource	= cm_t3517_hecc_resources,
+	.dev		= {
+		.platform_data	= &cm_t3517_hecc_pdata,
+	},
+};
+
+static void cm_t3517_init_hecc(void)
+{
+	platform_device_register(&cm_t3517_hecc_device);
+}
+#else
+static inline void cm_t3517_init_hecc(void) {}
+#endif
+
+#if defined(CONFIG_RTC_DRV_V3020) || defined(CONFIG_RTC_DRV_V3020_MODULE)
+#define RTC_IO_GPIO		(153)
+#define RTC_WR_GPIO		(154)
+#define RTC_RD_GPIO		(160)
+#define RTC_CS_GPIO		(163)
+
+struct v3020_platform_data cm_t3517_v3020_pdata = {
+	.use_gpio	= 1,
+	.gpio_cs	= RTC_CS_GPIO,
+	.gpio_wr	= RTC_WR_GPIO,
+	.gpio_rd	= RTC_RD_GPIO,
+	.gpio_io	= RTC_IO_GPIO,
+};
+
+static struct platform_device cm_t3517_rtc_device = {
+	.name		= "v3020",
+	.id		= -1,
+	.dev		= {
+		.platform_data = &cm_t3517_v3020_pdata,
+	}
+};
+
+static void __init cm_t3517_init_rtc(void)
+{
+	platform_device_register(&cm_t3517_rtc_device);
+}
+#else
+static inline void cm_t3517_init_rtc(void) {}
+#endif
+
+#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_EHCI_HCD_MODULE)
+#define HSUSB1_RESET_GPIO	(146)
+#define HSUSB2_RESET_GPIO	(147)
+#define USB_HUB_RESET_GPIO	(152)
+
+static struct ehci_hcd_omap_platform_data cm_t3517_ehci_pdata __initdata = {
+	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
+	.port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
+	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+
+	.phy_reset  = true,
+	.reset_gpio_port[0]  = HSUSB1_RESET_GPIO,
+	.reset_gpio_port[1]  = HSUSB2_RESET_GPIO,
+	.reset_gpio_port[2]  = -EINVAL,
+};
+
+static int cm_t3517_init_usbh(void)
+{
+	int err;
+
+	err = gpio_request(USB_HUB_RESET_GPIO, "usb hub rst");
+	if (err) {
+		pr_err("CM-T3517: usb hub rst gpio request failed: %d\n", err);
+	} else {
+		gpio_direction_output(USB_HUB_RESET_GPIO, 0);
+		udelay(10);
+		gpio_set_value(USB_HUB_RESET_GPIO, 1);
+		msleep(1);
+	}
+
+	usb_ehci_init(&cm_t3517_ehci_pdata);
+
+	return 0;
+}
+#else
+static inline int cm_t3517_init_usbh(void)
+{
+	return 0;
+}
+#endif
+
+#if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE)
+#define NAND_BLOCK_SIZE		SZ_128K
+
+static struct mtd_partition cm_t3517_nand_partitions[] = {
+	{
+		.name           = "xloader",
+		.offset         = 0,			/* Offset = 0x00000 */
+		.size           = 4 * NAND_BLOCK_SIZE,
+		.mask_flags     = MTD_WRITEABLE
+	},
+	{
+		.name           = "uboot",
+		.offset         = MTDPART_OFS_APPEND,	/* Offset = 0x80000 */
+		.size           = 15 * NAND_BLOCK_SIZE,
+	},
+	{
+		.name           = "uboot environment",
+		.offset         = MTDPART_OFS_APPEND,	/* Offset = 0x260000 */
+		.size           = 2 * NAND_BLOCK_SIZE,
+	},
+	{
+		.name           = "linux",
+		.offset         = MTDPART_OFS_APPEND,	/* Offset = 0x280000 */
+		.size           = 32 * NAND_BLOCK_SIZE,
+	},
+	{
+		.name           = "rootfs",
+		.offset         = MTDPART_OFS_APPEND,	/* Offset = 0x680000 */
+		.size           = MTDPART_SIZ_FULL,
+	},
+};
+
+static struct omap_nand_platform_data cm_t3517_nand_data = {
+	.parts			= cm_t3517_nand_partitions,
+	.nr_parts		= ARRAY_SIZE(cm_t3517_nand_partitions),
+	.dma_channel		= -1,	/* disable DMA in OMAP NAND driver */
+	.cs			= 0,
+};
+
+static void __init cm_t3517_init_nand(void)
+{
+	if (gpmc_nand_init(&cm_t3517_nand_data) < 0)
+		pr_err("CM-T3517: NAND initialization failed\n");
+}
+#else
+static inline void cm_t3517_init_nand(void) {}
+#endif
+
+static struct omap_board_config_kernel cm_t3517_config[] __initdata = {
+};
+
+static void __init cm_t3517_init_irq(void)
+{
+	omap_board_config = cm_t3517_config;
+	omap_board_config_size = ARRAY_SIZE(cm_t3517_config);
+
+	omap2_init_common_hw(NULL, NULL);
+	omap_init_irq();
+	omap_gpio_init();
+}
+
+static struct omap_board_mux board_mux[] __initdata = {
+	/* GPIO186 - Green LED */
+	OMAP3_MUX(SYS_CLKOUT2, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
+	/* RTC GPIOs: IO, WR#, RD#, CS# */
+	OMAP3_MUX(MCBSP4_DR, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
+	OMAP3_MUX(MCBSP4_DX, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
+	OMAP3_MUX(MCBSP_CLKS, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
+	OMAP3_MUX(UART3_CTS_RCTX, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
+	/* HSUSB1 RESET */
+	OMAP3_MUX(UART2_TX, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
+	/* HSUSB2 RESET */
+	OMAP3_MUX(UART2_RX, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
+	/* CM-T3517 USB HUB nRESET */
+	OMAP3_MUX(MCBSP4_CLKX, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
+
+	{ .reg_offset = OMAP_MUX_TERMINATOR },
+};
+
+static void __init cm_t3517_init(void)
+{
+	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+	omap_serial_init();
+	cm_t3517_init_leds();
+	cm_t3517_init_nand();
+	cm_t3517_init_rtc();
+	cm_t3517_init_usbh();
+	cm_t3517_init_hecc();
+}
+
+MACHINE_START(CM_T3517, "Compulab CM-T3517")
+	.boot_params	= 0x80000100,
+	.map_io		= omap3_map_io,
+	.reserve        = omap_reserve,
+	.init_irq	= cm_t3517_init_irq,
+	.init_machine	= cm_t3517_init,
+	.timer		= &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index 2205c20..067f437 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -28,6 +28,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/nand.h>
+#include <linux/mmc/host.h>
 
 #include <linux/regulator/machine.h>
 #include <linux/i2c/twl.h>
@@ -44,7 +45,6 @@
 #include <plat/gpmc.h>
 #include <plat/nand.h>
 #include <plat/usb.h>
-#include <plat/timer-gp.h>
 #include <plat/display.h>
 
 #include <plat/mcspi.h>
@@ -58,6 +58,7 @@
 
 #include "mux.h"
 #include "hsmmc.h"
+#include "timer-gp.h"
 
 #define NAND_BLOCK_SIZE		SZ_128K
 
@@ -105,7 +106,7 @@
 static struct omap2_hsmmc_info mmc[] = {
 	{
 		.mmc		= 1,
-		.wires		= 8,
+		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= 29,
 	},
 	{}	/* Terminator */
@@ -198,7 +199,7 @@
 static struct regulator_consumer_supply devkit8000_vdda_dac_supply =
 	REGULATOR_SUPPLY("vdda_dac", "omapdss");
 
-static int board_keymap[] = {
+static uint32_t board_keymap[] = {
 	KEY(0, 0, KEY_1),
 	KEY(1, 0, KEY_2),
 	KEY(2, 0, KEY_3),
diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index ac834aa..fd38c05 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -21,7 +21,8 @@
 #include <plat/nand.h>
 #include <plat/onenand.h>
 #include <plat/tc.h>
-#include <mach/board-flash.h>
+
+#include "board-flash.h"
 
 #define REG_FPGA_REV			0x10
 #define REG_FPGA_DIP_SWITCH_INPUT2	0x60
diff --git a/arch/arm/mach-omap2/include/mach/board-flash.h b/arch/arm/mach-omap2/board-flash.h
similarity index 88%
rename from arch/arm/mach-omap2/include/mach/board-flash.h
rename to arch/arm/mach-omap2/board-flash.h
index b2242ae..69befe0 100644
--- a/arch/arm/mach-omap2/include/mach/board-flash.h
+++ b/arch/arm/mach-omap2/board-flash.h
@@ -26,3 +26,5 @@
 
 extern void board_flash_init(struct flash_partitions [],
 				char chip_sel[][GPMC_CS_NUM]);
+extern void board_nand_init(struct mtd_partition *nand_parts,
+					u8 nr_parts, u8 cs);
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index 69064b1..b1c2c9a 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -48,10 +48,22 @@
 
 static void __init omap_generic_map_io(void)
 {
-	omap2_set_globals_242x(); /* should be 242x, 243x, or 343x */
-	omap242x_map_common_io();
+	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();
+	}
 }
 
+/* XXX This machine entry name should be updated */
 MACHINE_START(OMAP_GENERIC, "Generic OMAP24xx")
 	/* Maintainer: Paul Mundt <paul.mundt@nokia.com> */
 	.boot_params	= 0x80000100,
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index cc39fc8..929993b 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -31,7 +31,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/control.h>
 #include <mach/gpio.h>
 #include <plat/usb.h>
 #include <plat/board.h>
@@ -42,6 +41,7 @@
 #include <plat/gpmc.h>
 
 #include "mux.h"
+#include "control.h"
 
 #define H4_FLASH_CS	0
 #define H4_SMC91X_CS	1
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index b62a68b..5e035a5 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -20,6 +20,7 @@
 
 #include <linux/regulator/machine.h>
 #include <linux/i2c/twl.h>
+#include <linux/mmc/host.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -38,12 +39,61 @@
 #define IGEP2_SMSC911X_CS       5
 #define IGEP2_SMSC911X_GPIO     176
 #define IGEP2_GPIO_USBH_NRESET  24
-#define IGEP2_GPIO_LED0_GREEN 	26
-#define IGEP2_GPIO_LED0_RED 	27
-#define IGEP2_GPIO_LED1_RED   	28
-#define IGEP2_GPIO_DVI_PUP	170
-#define IGEP2_GPIO_WIFI_NPD 	94
-#define IGEP2_GPIO_WIFI_NRESET 	95
+#define IGEP2_GPIO_LED0_GREEN   26
+#define IGEP2_GPIO_LED0_RED     27
+#define IGEP2_GPIO_LED1_RED     28
+#define IGEP2_GPIO_DVI_PUP      170
+
+#define IGEP2_RB_GPIO_WIFI_NPD     94
+#define IGEP2_RB_GPIO_WIFI_NRESET  95
+#define IGEP2_RB_GPIO_BT_NRESET    137
+#define IGEP2_RC_GPIO_WIFI_NPD     138
+#define IGEP2_RC_GPIO_WIFI_NRESET  139
+#define IGEP2_RC_GPIO_BT_NRESET    137
+
+/*
+ * IGEP2 Hardware Revision Table
+ *
+ *  --------------------------------------------------------------------------
+ * | Id. | Hw Rev.            | HW0 (28) | WIFI_NPD | WIFI_NRESET | BT_NRESET |
+ *  --------------------------------------------------------------------------
+ * |  0  | B                  |   high   |  gpio94  |   gpio95    |     -     |
+ * |  0  | B/C (B-compatible) |   high   |  gpio94  |   gpio95    |  gpio137  |
+ * |  1  | C                  |   low    |  gpio138 |   gpio139   |  gpio137  |
+ *  --------------------------------------------------------------------------
+ */
+
+#define IGEP2_BOARD_HWREV_B	0
+#define IGEP2_BOARD_HWREV_C	1
+
+static u8 hwrev;
+
+static void __init igep2_get_revision(void)
+{
+	u8 ret;
+
+	omap_mux_init_gpio(IGEP2_GPIO_LED1_RED, OMAP_PIN_INPUT);
+
+	if ((gpio_request(IGEP2_GPIO_LED1_RED, "GPIO_HW0_REV") == 0) &&
+	    (gpio_direction_input(IGEP2_GPIO_LED1_RED) == 0)) {
+		ret = gpio_get_value(IGEP2_GPIO_LED1_RED);
+		if (ret == 0) {
+			pr_info("IGEP2: Hardware Revision C (B-NON compatible)\n");
+			hwrev = IGEP2_BOARD_HWREV_C;
+		} else if (ret ==  1) {
+			pr_info("IGEP2: Hardware Revision B/C (B compatible)\n");
+			hwrev = IGEP2_BOARD_HWREV_B;
+		} else {
+			pr_err("IGEP2: Unknown Hardware Revision\n");
+			hwrev = -1;
+		}
+	} else {
+		pr_warning("IGEP2: Could not obtain gpio GPIO_HW0_REV\n");
+		pr_err("IGEP2: Unknown Hardware Revision\n");
+	}
+
+	gpio_free(IGEP2_GPIO_LED1_RED);
+}
 
 #if defined(CONFIG_MTD_ONENAND_OMAP2) || \
 	defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
@@ -107,7 +157,7 @@
 	},
 };
 
-void __init igep2_flash_init(void)
+static void __init igep2_flash_init(void)
 {
 	u8		cs = 0;
 	u8		onenandcs = GPMC_CS_NUM + 1;
@@ -141,7 +191,7 @@
 }
 
 #else
-void __init igep2_flash_init(void) {}
+static void __init igep2_flash_init(void) {}
 #endif
 
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
@@ -211,10 +261,6 @@
 	.supply		= "vmmc",
 };
 
-static struct regulator_consumer_supply igep2_vmmc2_supply = {
-	.supply		= "vmmc",
-};
-
 /* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
 static struct regulator_init_data igep2_vmmc1 = {
 	.constraints = {
@@ -230,37 +276,95 @@
 	.consumer_supplies      = &igep2_vmmc1_supply,
 };
 
-/* VMMC2 for OMAP VDD_MMC2 (i/o) and MMC2 WIFI */
-static struct regulator_init_data igep2_vmmc2 = {
-	.constraints = {
-		.min_uV			= 1850000,
-		.max_uV			= 3150000,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
-					| REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies  = 1,
-	.consumer_supplies      = &igep2_vmmc2_supply,
-};
-
 static struct omap2_hsmmc_info mmc[] = {
 	{
 		.mmc		= 1,
-		.wires		= 4,
+		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
 	},
+#if defined(CONFIG_LIBERTAS_SDIO) || defined(CONFIG_LIBERTAS_SDIO_MODULE)
 	{
 		.mmc		= 2,
-		.wires		= 4,
+		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
 	},
+#endif
 	{}      /* Terminator */
 };
 
+#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+#include <linux/leds.h>
+
+static struct gpio_led igep2_gpio_leds[] = {
+	[0] = {
+		.name			= "gpio-led:red:d0",
+		.gpio			= IGEP2_GPIO_LED0_RED,
+		.default_trigger	= "default-off"
+	},
+	[1] = {
+		.name			= "gpio-led:green:d0",
+		.gpio			= IGEP2_GPIO_LED0_GREEN,
+		.default_trigger	= "default-off",
+	},
+	[2] = {
+		.name			= "gpio-led:red:d1",
+		.gpio			= IGEP2_GPIO_LED1_RED,
+		.default_trigger	= "default-off",
+	},
+	[3] = {
+		.name			= "gpio-led:green:d1",
+		.default_trigger	= "heartbeat",
+		.gpio			= -EINVAL, /* gets replaced */
+	},
+};
+
+static struct gpio_led_platform_data igep2_led_pdata = {
+	.leds           = igep2_gpio_leds,
+	.num_leds       = ARRAY_SIZE(igep2_gpio_leds),
+};
+
+static struct platform_device igep2_led_device = {
+	 .name   = "leds-gpio",
+	 .id     = -1,
+	 .dev    = {
+		 .platform_data  =  &igep2_led_pdata,
+	},
+};
+
+static void __init igep2_leds_init(void)
+{
+	platform_device_register(&igep2_led_device);
+}
+
+#else
+static inline void igep2_leds_init(void)
+{
+	if ((gpio_request(IGEP2_GPIO_LED0_RED, "gpio-led:red:d0") == 0) &&
+	    (gpio_direction_output(IGEP2_GPIO_LED0_RED, 1) == 0)) {
+		gpio_export(IGEP2_GPIO_LED0_RED, 0);
+		gpio_set_value(IGEP2_GPIO_LED0_RED, 0);
+	} else
+		pr_warning("IGEP v2: Could not obtain gpio GPIO_LED0_RED\n");
+
+	if ((gpio_request(IGEP2_GPIO_LED0_GREEN, "gpio-led:green:d0") == 0) &&
+	    (gpio_direction_output(IGEP2_GPIO_LED0_GREEN, 1) == 0)) {
+		gpio_export(IGEP2_GPIO_LED0_GREEN, 0);
+		gpio_set_value(IGEP2_GPIO_LED0_GREEN, 0);
+	} else
+		pr_warning("IGEP v2: Could not obtain gpio GPIO_LED0_GREEN\n");
+
+	if ((gpio_request(IGEP2_GPIO_LED1_RED, "gpio-led:red:d1") == 0) &&
+	    (gpio_direction_output(IGEP2_GPIO_LED1_RED, 1) == 0)) {
+		gpio_export(IGEP2_GPIO_LED1_RED, 0);
+		gpio_set_value(IGEP2_GPIO_LED1_RED, 0);
+	} else
+		pr_warning("IGEP v2: Could not obtain gpio GPIO_LED1_RED\n");
+
+}
+#endif
+
 static int igep2_twl_gpio_setup(struct device *dev,
 		unsigned gpio, unsigned ngpio)
 {
@@ -268,20 +372,48 @@
 	mmc[0].gpio_cd = gpio + 0;
 	omap2_hsmmc_init(mmc);
 
-	/* link regulators to MMC adapters ... we "know" the
+	/*
+	 * link regulators to MMC adapters ... we "know" the
 	 * regulators will be set up only *after* we return.
-	*/
+	 */
 	igep2_vmmc1_supply.dev = mmc[0].dev;
-	igep2_vmmc2_supply.dev = mmc[1].dev;
+
+	/*
+	 * REVISIT: need ehci-omap hooks for external VBUS
+	 * power switch and overcurrent detect
+	 */
+	if ((gpio_request(gpio + 1, "GPIO_EHCI_NOC") < 0) ||
+	    (gpio_direction_input(gpio + 1) < 0))
+		pr_err("IGEP2: Could not obtain gpio for EHCI NOC");
+
+	/*
+	 * TWL4030_GPIO_MAX + 0 == ledA, GPIO_USBH_CPEN
+	 * (out, active low)
+	 */
+	if ((gpio_request(gpio + TWL4030_GPIO_MAX, "GPIO_USBH_CPEN") < 0) ||
+	    (gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0) < 0))
+		pr_err("IGEP2: Could not obtain gpio for USBH_CPEN");
+
+	/* TWL4030_GPIO_MAX + 1 == ledB (out, active low LED) */
+#if !defined(CONFIG_LEDS_GPIO) && !defined(CONFIG_LEDS_GPIO_MODULE)
+	if ((gpio_request(gpio+TWL4030_GPIO_MAX+1, "gpio-led:green:d1") == 0)
+	    && (gpio_direction_output(gpio + TWL4030_GPIO_MAX + 1, 1) == 0)) {
+		gpio_export(gpio + TWL4030_GPIO_MAX + 1, 0);
+		gpio_set_value(gpio + TWL4030_GPIO_MAX + 1, 0);
+	} else
+		pr_warning("IGEP v2: Could not obtain gpio GPIO_LED1_GREEN\n");
+#else
+	igep2_gpio_leds[3].gpio = gpio + TWL4030_GPIO_MAX + 1;
+#endif
 
 	return 0;
 };
 
-static struct twl4030_gpio_platform_data igep2_gpio_data = {
+static struct twl4030_gpio_platform_data igep2_twl4030_gpio_pdata = {
 	.gpio_base	= OMAP_MAX_GPIO_LINES,
 	.irq_base	= TWL4030_GPIO_IRQ_BASE,
 	.irq_end	= TWL4030_GPIO_IRQ_END,
-	.use_leds	= false,
+	.use_leds	= true,
 	.setup		= igep2_twl_gpio_setup,
 };
 
@@ -355,47 +487,6 @@
 		pr_err("IGEP v2: Could not obtain gpio GPIO_DVI_PUP\n");
 }
 
-#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
-#include <linux/leds.h>
-
-static struct gpio_led igep2_gpio_leds[] = {
-	{
-		.name = "led0:red",
-		.gpio = IGEP2_GPIO_LED0_RED,
-	},
-	{
-		.name = "led0:green",
-		.default_trigger = "heartbeat",
-		.gpio = IGEP2_GPIO_LED0_GREEN,
-	},
-	{
-		.name = "led1:red",
-		.gpio = IGEP2_GPIO_LED1_RED,
-	},
-};
-
-static struct gpio_led_platform_data igep2_led_pdata = {
-	.leds           = igep2_gpio_leds,
-	.num_leds       = ARRAY_SIZE(igep2_gpio_leds),
-};
-
-static struct platform_device igep2_led_device = {
-	 .name   = "leds-gpio",
-	 .id     = -1,
-	 .dev    = {
-		 .platform_data  =  &igep2_led_pdata,
-	},
-};
-
-static void __init igep2_init_led(void)
-{
-	platform_device_register(&igep2_led_device);
-}
-
-#else
-static inline void igep2_init_led(void) {}
-#endif
-
 static struct platform_device *igep2_devices[] __initdata = {
 	&igep2_dss_device,
 };
@@ -425,14 +516,13 @@
 	/* platform_data for children goes here */
 	.usb		= &igep2_usb_data,
 	.codec		= &igep2_codec_data,
-	.gpio		= &igep2_gpio_data,
+	.gpio		= &igep2_twl4030_gpio_pdata,
 	.vmmc1          = &igep2_vmmc1,
-	.vmmc2		= &igep2_vmmc2,
 	.vpll2		= &igep2_vpll2,
 
 };
 
-static struct i2c_board_info __initdata igep2_i2c_boardinfo[] = {
+static struct i2c_board_info __initdata igep2_i2c1_boardinfo[] = {
 	{
 		I2C_BOARD_INFO("twl4030", 0x48),
 		.flags		= I2C_CLIENT_WAKE,
@@ -441,14 +531,29 @@
 	},
 };
 
-static int __init igep2_i2c_init(void)
+static struct i2c_board_info __initdata igep2_i2c3_boardinfo[] = {
+	{
+		I2C_BOARD_INFO("eeprom", 0x50),
+	},
+};
+
+static void __init igep2_i2c_init(void)
 {
-	omap_register_i2c_bus(1, 2600, igep2_i2c_boardinfo,
-			ARRAY_SIZE(igep2_i2c_boardinfo));
-	/* Bus 3 is attached to the DVI port where devices like the pico DLP
-	 * projector don't work reliably with 400kHz */
-	omap_register_i2c_bus(3, 100, NULL, 0);
-	return 0;
+	int ret;
+
+	ret = omap_register_i2c_bus(1, 2600, igep2_i2c1_boardinfo,
+		ARRAY_SIZE(igep2_i2c1_boardinfo));
+	if (ret)
+		pr_warning("IGEP2: Could not register I2C1 bus (%d)\n", ret);
+
+	/*
+	 * Bus 3 is attached to the DVI port where devices like the pico DLP
+	 * projector don't work reliably with 400kHz
+	 */
+	ret = omap_register_i2c_bus(3, 100, igep2_i2c3_boardinfo,
+		ARRAY_SIZE(igep2_i2c3_boardinfo));
+	if (ret)
+		pr_warning("IGEP2: Could not register I2C3 bus (%d)\n", ret);
 }
 
 static struct omap_musb_board_data musb_board_data = {
@@ -476,9 +581,57 @@
 #define board_mux	NULL
 #endif
 
+#if defined(CONFIG_LIBERTAS_SDIO) || defined(CONFIG_LIBERTAS_SDIO_MODULE)
+
+static void __init igep2_wlan_bt_init(void)
+{
+	unsigned npd, wreset, btreset;
+
+	/* GPIO's for WLAN-BT combo depends on hardware revision */
+	if (hwrev == IGEP2_BOARD_HWREV_B) {
+		npd = IGEP2_RB_GPIO_WIFI_NPD;
+		wreset = IGEP2_RB_GPIO_WIFI_NRESET;
+		btreset = IGEP2_RB_GPIO_BT_NRESET;
+	} else if (hwrev == IGEP2_BOARD_HWREV_C) {
+		npd = IGEP2_RC_GPIO_WIFI_NPD;
+		wreset = IGEP2_RC_GPIO_WIFI_NRESET;
+		btreset = IGEP2_RC_GPIO_BT_NRESET;
+	} else
+		return;
+
+	/* Set GPIO's for  WLAN-BT combo module */
+	if ((gpio_request(npd, "GPIO_WIFI_NPD") == 0) &&
+	    (gpio_direction_output(npd, 1) == 0)) {
+		gpio_export(npd, 0);
+	} else
+		pr_warning("IGEP2: Could not obtain gpio GPIO_WIFI_NPD\n");
+
+	if ((gpio_request(wreset, "GPIO_WIFI_NRESET") == 0) &&
+	    (gpio_direction_output(wreset, 1) == 0)) {
+		gpio_export(wreset, 0);
+		gpio_set_value(wreset, 0);
+		udelay(10);
+		gpio_set_value(wreset, 1);
+	} else
+		pr_warning("IGEP2: Could not obtain gpio GPIO_WIFI_NRESET\n");
+
+	if ((gpio_request(btreset, "GPIO_BT_NRESET") == 0) &&
+	    (gpio_direction_output(btreset, 1) == 0)) {
+		gpio_export(btreset, 0);
+	} else
+		pr_warning("IGEP2: Could not obtain gpio GPIO_BT_NRESET\n");
+}
+#else
+static inline void __init igep2_wlan_bt_init(void) { }
+#endif
+
 static void __init igep2_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+
+	/* Get IGEP2 hardware revision */
+	igep2_get_revision();
+	/* Register I2C busses and drivers */
 	igep2_i2c_init();
 	platform_add_devices(igep2_devices, ARRAY_SIZE(igep2_devices));
 	omap_serial_init();
@@ -486,50 +639,16 @@
 	usb_ehci_init(&ehci_pdata);
 
 	igep2_flash_init();
-	igep2_init_led();
+	igep2_leds_init();
 	igep2_display_init();
 	igep2_init_smsc911x();
 
-	/* GPIO userspace leds */
-#if !defined(CONFIG_LEDS_GPIO) && !defined(CONFIG_LEDS_GPIO_MODULE)
-	if ((gpio_request(IGEP2_GPIO_LED0_RED, "led0:red") == 0) &&
-	    (gpio_direction_output(IGEP2_GPIO_LED0_RED, 1) == 0)) {
-		gpio_export(IGEP2_GPIO_LED0_RED, 0);
-		gpio_set_value(IGEP2_GPIO_LED0_RED, 0);
-	} else
-		pr_warning("IGEP v2: Could not obtain gpio GPIO_LED0_RED\n");
+	/*
+	 * WLAN-BT combo module from MuRata wich has a Marvell WLAN
+	 * (88W8686) + CSR Bluetooth chipset. Uses SDIO interface.
+	 */
+	igep2_wlan_bt_init();
 
-	if ((gpio_request(IGEP2_GPIO_LED0_GREEN, "led0:green") == 0) &&
-	    (gpio_direction_output(IGEP2_GPIO_LED0_GREEN, 1) == 0)) {
-		gpio_export(IGEP2_GPIO_LED0_GREEN, 0);
-		gpio_set_value(IGEP2_GPIO_LED0_GREEN, 0);
-	} else
-		pr_warning("IGEP v2: Could not obtain gpio GPIO_LED0_GREEN\n");
-
-	if ((gpio_request(IGEP2_GPIO_LED1_RED, "led1:red") == 0) &&
-	    (gpio_direction_output(IGEP2_GPIO_LED1_RED, 1) == 0)) {
-		gpio_export(IGEP2_GPIO_LED1_RED, 0);
-		gpio_set_value(IGEP2_GPIO_LED1_RED, 0);
-	} else
-		pr_warning("IGEP v2: Could not obtain gpio GPIO_LED1_RED\n");
-#endif
-
-	/* GPIO W-LAN + Bluetooth combo module */
-	if ((gpio_request(IGEP2_GPIO_WIFI_NPD, "GPIO_WIFI_NPD") == 0) &&
-	    (gpio_direction_output(IGEP2_GPIO_WIFI_NPD, 1) == 0)) {
-		gpio_export(IGEP2_GPIO_WIFI_NPD, 0);
-/* 		gpio_set_value(IGEP2_GPIO_WIFI_NPD, 0); */
-	} else
-		pr_warning("IGEP v2: Could not obtain gpio GPIO_WIFI_NPD\n");
-
-	if ((gpio_request(IGEP2_GPIO_WIFI_NRESET, "GPIO_WIFI_NRESET") == 0) &&
-	    (gpio_direction_output(IGEP2_GPIO_WIFI_NRESET, 1) == 0)) {
-		gpio_export(IGEP2_GPIO_WIFI_NRESET, 0);
-		gpio_set_value(IGEP2_GPIO_WIFI_NRESET, 0);
-		udelay(10);
-		gpio_set_value(IGEP2_GPIO_WIFI_NRESET, 1);
-	} else
-		pr_warning("IGEP v2: Could not obtain gpio GPIO_WIFI_NRESET\n");
 }
 
 MACHINE_START(IGEP0020, "IGEP v2 board")
diff --git a/arch/arm/mach-omap2/board-igep0030.c b/arch/arm/mach-omap2/board-igep0030.c
new file mode 100644
index 0000000..22b0b25
--- /dev/null
+++ b/arch/arm/mach-omap2/board-igep0030.c
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) 2010 - ISEE 2007 SL
+ *
+ * Modified from mach-omap2/board-generic.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+
+#include <linux/regulator/machine.h>
+#include <linux/i2c/twl.h>
+#include <linux/mmc/host.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <plat/board.h>
+#include <plat/common.h>
+#include <plat/gpmc.h>
+#include <plat/usb.h>
+#include <plat/onenand.h>
+
+#include "mux.h"
+#include "hsmmc.h"
+#include "sdram-numonyx-m65kxxxxam.h"
+
+#define IGEP3_GPIO_LED0_GREEN	54
+#define IGEP3_GPIO_LED0_RED	53
+#define IGEP3_GPIO_LED1_RED	16
+
+#define IGEP3_GPIO_WIFI_NPD	138
+#define IGEP3_GPIO_WIFI_NRESET	139
+#define IGEP3_GPIO_BT_NRESET	137
+
+#define IGEP3_GPIO_USBH_NRESET  115
+
+
+#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
+	defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
+
+#define ONENAND_MAP             0x20000000
+
+/*
+ * x2 Flash built-in COMBO POP MEMORY
+ * Since the device is equipped with two DataRAMs, and two-plane NAND
+ * Flash memory array, these two component enables simultaneous program
+ * of 4KiB. Plane1 has only even blocks such as block0, block2, block4
+ * while Plane2 has only odd blocks such as block1, block3, block5.
+ * So MTD regards it as 4KiB page size and 256KiB block size 64*(2*2048)
+ */
+
+static struct mtd_partition igep3_onenand_partitions[] = {
+	{
+		.name           = "X-Loader",
+		.offset         = 0,
+		.size           = 2 * (64*(2*2048))
+	},
+	{
+		.name           = "U-Boot",
+		.offset         = MTDPART_OFS_APPEND,
+		.size           = 6 * (64*(2*2048)),
+	},
+	{
+		.name           = "Environment",
+		.offset         = MTDPART_OFS_APPEND,
+		.size           = 2 * (64*(2*2048)),
+	},
+	{
+		.name           = "Kernel",
+		.offset         = MTDPART_OFS_APPEND,
+		.size           = 12 * (64*(2*2048)),
+	},
+	{
+		.name           = "File System",
+		.offset         = MTDPART_OFS_APPEND,
+		.size           = MTDPART_SIZ_FULL,
+	},
+};
+
+static struct omap_onenand_platform_data igep3_onenand_pdata = {
+	.parts = igep3_onenand_partitions,
+	.nr_parts = ARRAY_SIZE(igep3_onenand_partitions),
+	.onenand_setup = NULL,
+	.dma_channel	= -1,	/* disable DMA in OMAP OneNAND driver */
+};
+
+static struct platform_device igep3_onenand_device = {
+	.name		= "omap2-onenand",
+	.id		= -1,
+	.dev = {
+		.platform_data = &igep3_onenand_pdata,
+	},
+};
+
+void __init igep3_flash_init(void)
+{
+	u8 cs = 0;
+	u8 onenandcs = GPMC_CS_NUM + 1;
+
+	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
+		u32 ret;
+		ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+
+		/* Check if NAND/oneNAND is configured */
+		if ((ret & 0xC00) == 0x800)
+			/* NAND found */
+			pr_err("IGEP3: Unsupported NAND found\n");
+		else {
+			ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
+
+			if ((ret & 0x3F) == (ONENAND_MAP >> 24))
+				/* OneNAND found */
+				onenandcs = cs;
+		}
+	}
+
+	if (onenandcs > GPMC_CS_NUM) {
+		pr_err("IGEP3: Unable to find configuration in GPMC\n");
+		return;
+	}
+
+	igep3_onenand_pdata.cs = onenandcs;
+
+	if (platform_device_register(&igep3_onenand_device) < 0)
+		pr_err("IGEP3: Unable to register OneNAND device\n");
+}
+
+#else
+void __init igep3_flash_init(void) {}
+#endif
+
+static struct regulator_consumer_supply igep3_vmmc1_supply = {
+	.supply		= "vmmc",
+};
+
+/* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
+static struct regulator_init_data igep3_vmmc1 = {
+	.constraints = {
+		.min_uV			= 1850000,
+		.max_uV			= 3150000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
+					| REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies  = 1,
+	.consumer_supplies      = &igep3_vmmc1_supply,
+};
+
+static struct omap2_hsmmc_info mmc[] = {
+	[0] = {
+		.mmc		= 1,
+		.caps		= MMC_CAP_4_BIT_DATA,
+		.gpio_cd	= -EINVAL,
+		.gpio_wp	= -EINVAL,
+	},
+#if defined(CONFIG_LIBERTAS_SDIO) || defined(CONFIG_LIBERTAS_SDIO_MODULE)
+	[1] = {
+		.mmc		= 2,
+		.caps		= MMC_CAP_4_BIT_DATA,
+		.gpio_cd	= -EINVAL,
+		.gpio_wp	= -EINVAL,
+	},
+#endif
+	{}      /* Terminator */
+};
+
+#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+#include <linux/leds.h>
+
+static struct gpio_led igep3_gpio_leds[] = {
+	[0] = {
+		.name			= "gpio-led:red:d0",
+		.gpio			= IGEP3_GPIO_LED0_RED,
+		.default_trigger	= "default-off"
+	},
+	[1] = {
+		.name			= "gpio-led:green:d0",
+		.gpio			= IGEP3_GPIO_LED0_GREEN,
+		.default_trigger	= "default-off",
+	},
+	[2] = {
+		.name			= "gpio-led:red:d1",
+		.gpio			= IGEP3_GPIO_LED1_RED,
+		.default_trigger	= "default-off",
+	},
+	[3] = {
+		.name			= "gpio-led:green:d1",
+		.default_trigger	= "heartbeat",
+		.gpio			= -EINVAL, /* gets replaced */
+	},
+};
+
+static struct gpio_led_platform_data igep3_led_pdata = {
+	.leds           = igep3_gpio_leds,
+	.num_leds       = ARRAY_SIZE(igep3_gpio_leds),
+};
+
+static struct platform_device igep3_led_device = {
+	 .name   = "leds-gpio",
+	 .id     = -1,
+	 .dev    = {
+		 .platform_data = &igep3_led_pdata,
+	},
+};
+
+static void __init igep3_leds_init(void)
+{
+	platform_device_register(&igep3_led_device);
+}
+
+#else
+static inline void igep3_leds_init(void)
+{
+	if ((gpio_request(IGEP3_GPIO_LED0_RED, "gpio-led:red:d0") == 0) &&
+	    (gpio_direction_output(IGEP3_GPIO_LED0_RED, 1) == 0)) {
+		gpio_export(IGEP3_GPIO_LED0_RED, 0);
+		gpio_set_value(IGEP3_GPIO_LED0_RED, 1);
+	} else
+		pr_warning("IGEP3: Could not obtain gpio GPIO_LED0_RED\n");
+
+	if ((gpio_request(IGEP3_GPIO_LED0_GREEN, "gpio-led:green:d0") == 0) &&
+	    (gpio_direction_output(IGEP3_GPIO_LED0_GREEN, 1) == 0)) {
+		gpio_export(IGEP3_GPIO_LED0_GREEN, 0);
+		gpio_set_value(IGEP3_GPIO_LED0_GREEN, 1);
+	} else
+		pr_warning("IGEP3: Could not obtain gpio GPIO_LED0_GREEN\n");
+
+	if ((gpio_request(IGEP3_GPIO_LED1_RED, "gpio-led:red:d1") == 0) &&
+		(gpio_direction_output(IGEP3_GPIO_LED1_RED, 1) == 0)) {
+		gpio_export(IGEP3_GPIO_LED1_RED, 0);
+		gpio_set_value(IGEP3_GPIO_LED1_RED, 1);
+	} else
+		pr_warning("IGEP3: Could not obtain gpio GPIO_LED1_RED\n");
+}
+#endif
+
+static int igep3_twl4030_gpio_setup(struct device *dev,
+		unsigned gpio, unsigned ngpio)
+{
+	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
+	mmc[0].gpio_cd = gpio + 0;
+	omap2_hsmmc_init(mmc);
+
+	/*
+	 * link regulators to MMC adapters ... we "know" the
+	 * regulators will be set up only *after* we return.
+	 */
+	igep3_vmmc1_supply.dev = mmc[0].dev;
+
+	/* TWL4030_GPIO_MAX + 1 == ledB (out, active low LED) */
+#if !defined(CONFIG_LEDS_GPIO) && !defined(CONFIG_LEDS_GPIO_MODULE)
+	if ((gpio_request(gpio+TWL4030_GPIO_MAX+1, "gpio-led:green:d1") == 0)
+	    && (gpio_direction_output(gpio + TWL4030_GPIO_MAX + 1, 1) == 0)) {
+		gpio_export(gpio + TWL4030_GPIO_MAX + 1, 0);
+		gpio_set_value(gpio + TWL4030_GPIO_MAX + 1, 0);
+	} else
+		pr_warning("IGEP3: Could not obtain gpio GPIO_LED1_GREEN\n");
+#else
+	igep3_gpio_leds[3].gpio = gpio + TWL4030_GPIO_MAX + 1;
+#endif
+
+	return 0;
+};
+
+static struct twl4030_gpio_platform_data igep3_twl4030_gpio_pdata = {
+	.gpio_base	= OMAP_MAX_GPIO_LINES,
+	.irq_base	= TWL4030_GPIO_IRQ_BASE,
+	.irq_end	= TWL4030_GPIO_IRQ_END,
+	.use_leds	= true,
+	.setup		= igep3_twl4030_gpio_setup,
+};
+
+static struct twl4030_usb_data igep3_twl4030_usb_data = {
+	.usb_mode	= T2_USB_MODE_ULPI,
+};
+
+static void __init igep3_init_irq(void)
+{
+	omap2_init_common_hw(m65kxxxxam_sdrc_params, m65kxxxxam_sdrc_params);
+	omap_init_irq();
+	omap_gpio_init();
+}
+
+static struct twl4030_platform_data igep3_twl4030_pdata = {
+	.irq_base	= TWL4030_IRQ_BASE,
+	.irq_end	= TWL4030_IRQ_END,
+
+	/* platform_data for children goes here */
+	.usb		= &igep3_twl4030_usb_data,
+	.gpio		= &igep3_twl4030_gpio_pdata,
+	.vmmc1		= &igep3_vmmc1,
+};
+
+static struct i2c_board_info __initdata igep3_i2c_boardinfo[] = {
+	{
+		I2C_BOARD_INFO("twl4030", 0x48),
+		.flags		= I2C_CLIENT_WAKE,
+		.irq		= INT_34XX_SYS_NIRQ,
+		.platform_data	= &igep3_twl4030_pdata,
+	},
+};
+
+static int __init igep3_i2c_init(void)
+{
+	omap_register_i2c_bus(1, 2600, igep3_i2c_boardinfo,
+			ARRAY_SIZE(igep3_i2c_boardinfo));
+
+	return 0;
+}
+
+static struct omap_musb_board_data musb_board_data = {
+	.interface_type	= MUSB_INTERFACE_ULPI,
+	.mode		= MUSB_OTG,
+	.power		= 100,
+};
+
+#if defined(CONFIG_LIBERTAS_SDIO) || defined(CONFIG_LIBERTAS_SDIO_MODULE)
+
+static void __init igep3_wifi_bt_init(void)
+{
+	/* Configure MUX values for W-LAN + Bluetooth GPIO's */
+	omap_mux_init_gpio(IGEP3_GPIO_WIFI_NPD, OMAP_PIN_OUTPUT);
+	omap_mux_init_gpio(IGEP3_GPIO_WIFI_NRESET, OMAP_PIN_OUTPUT);
+	omap_mux_init_gpio(IGEP3_GPIO_BT_NRESET, OMAP_PIN_OUTPUT);
+
+	/* Set GPIO's for  W-LAN + Bluetooth combo module */
+	if ((gpio_request(IGEP3_GPIO_WIFI_NPD, "GPIO_WIFI_NPD") == 0) &&
+	    (gpio_direction_output(IGEP3_GPIO_WIFI_NPD, 1) == 0)) {
+		gpio_export(IGEP3_GPIO_WIFI_NPD, 0);
+	} else
+		pr_warning("IGEP3: Could not obtain gpio GPIO_WIFI_NPD\n");
+
+	if ((gpio_request(IGEP3_GPIO_WIFI_NRESET, "GPIO_WIFI_NRESET") == 0) &&
+	    (gpio_direction_output(IGEP3_GPIO_WIFI_NRESET, 1) == 0)) {
+		gpio_export(IGEP3_GPIO_WIFI_NRESET, 0);
+		gpio_set_value(IGEP3_GPIO_WIFI_NRESET, 0);
+		udelay(10);
+		gpio_set_value(IGEP3_GPIO_WIFI_NRESET, 1);
+	} else
+		pr_warning("IGEP3: Could not obtain gpio GPIO_WIFI_NRESET\n");
+
+	if ((gpio_request(IGEP3_GPIO_BT_NRESET, "GPIO_BT_NRESET") == 0) &&
+	    (gpio_direction_output(IGEP3_GPIO_BT_NRESET, 1) == 0)) {
+		gpio_export(IGEP3_GPIO_BT_NRESET, 0);
+	} else
+		pr_warning("IGEP3: Could not obtain gpio GPIO_BT_NRESET\n");
+}
+#else
+void __init igep3_wifi_bt_init(void) {}
+#endif
+
+#ifdef CONFIG_OMAP_MUX
+static struct omap_board_mux board_mux[] __initdata = {
+	{ .reg_offset = OMAP_MUX_TERMINATOR },
+};
+#else
+#define board_mux	NULL
+#endif
+
+static void __init igep3_init(void)
+{
+	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+
+	/* Register I2C busses and drivers */
+	igep3_i2c_init();
+
+	omap_serial_init();
+	usb_musb_init(&musb_board_data);
+
+	igep3_flash_init();
+	igep3_leds_init();
+
+	/*
+	 * WLAN-BT combo module from MuRata wich has a Marvell WLAN
+	 * (88W8686) + CSR Bluetooth chipset. Uses SDIO interface.
+	 */
+	igep3_wifi_bt_init();
+
+}
+
+MACHINE_START(IGEP0030, "IGEP OMAP3 module")
+	.boot_params	= 0x80000100,
+	.map_io		= omap3_map_io,
+	.init_irq	= igep3_init_irq,
+	.init_machine	= igep3_init,
+	.timer		= &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index f28fd77..001fd97 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -27,6 +27,7 @@
 #include <linux/i2c/twl.h>
 #include <linux/io.h>
 #include <linux/smsc911x.h>
+#include <linux/mmc/host.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -41,11 +42,12 @@
 #include <mach/board-zoom.h>
 
 #include <asm/delay.h>
-#include <plat/control.h>
 #include <plat/usb.h>
 
+#include "board-flash.h"
 #include "mux.h"
 #include "hsmmc.h"
+#include "control.h"
 
 #define LDP_SMSC911X_CS		1
 #define LDP_SMSC911X_GPIO	152
@@ -82,7 +84,7 @@
 	},
 };
 
-static int board_keymap[] = {
+static uint32_t board_keymap[] = {
 	KEY(0, 0, KEY_1),
 	KEY(1, 0, KEY_2),
 	KEY(2, 0, KEY_3),
@@ -362,7 +364,7 @@
 static struct omap2_hsmmc_info mmc[] __initdata = {
 	{
 		.mmc		= 1,
-		.wires		= 4,
+		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
 	},
diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
index 3f79668..e823c70 100644
--- a/arch/arm/mach-omap2/board-n8x0.c
+++ b/arch/arm/mach-omap2/board-n8x0.c
@@ -20,6 +20,7 @@
 #include <linux/i2c.h>
 #include <linux/spi/spi.h>
 #include <linux/usb/musb.h>
+#include <sound/tlv320aic3x.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
@@ -383,15 +384,6 @@
 	omap_mmc_notify_cover_event(mmc_device, index, *openp);
 }
 
-void n8x0_mmc_slot1_cover_handler(void *arg, int closed_state)
-{
-	if (mmc_device == NULL)
-		return;
-
-	slot1_cover_open = !closed_state;
-	omap_mmc_notify_cover_event(mmc_device, 0, closed_state);
-}
-
 static int n8x0_mmc_late_init(struct device *dev)
 {
 	int r, bit, *openp;
@@ -511,7 +503,7 @@
 
 static struct omap_mmc_platform_data *mmc_data[OMAP24XX_NR_MMC];
 
-void __init n8x0_mmc_init(void)
+static void __init n8x0_mmc_init(void)
 
 {
 	int err;
@@ -560,11 +552,6 @@
 void __init n8x0_mmc_init(void)
 {
 }
-
-void n8x0_mmc_slot1_cover_handler(void *arg, int state)
-{
-}
-
 #endif	/* CONFIG_MMC_OMAP */
 
 #ifdef CONFIG_MENELAUS
@@ -614,29 +601,35 @@
 	return 0;
 }
 
-static struct i2c_board_info __initdata n8x0_i2c_board_info_1[] = {
-	{
-		I2C_BOARD_INFO("menelaus", 0x72),
-		.irq = INT_24XX_SYS_NIRQ,
-	},
-};
+#else
+static int n8x0_menelaus_late_init(struct device *dev)
+{
+	return 0;
+}
+#endif
 
-static struct menelaus_platform_data n8x0_menelaus_platform_data = {
+static struct menelaus_platform_data n8x0_menelaus_platform_data __initdata = {
 	.late_init = n8x0_menelaus_late_init,
 };
 
-static void __init n8x0_menelaus_init(void)
-{
-	n8x0_i2c_board_info_1[0].platform_data = &n8x0_menelaus_platform_data;
-	omap_register_i2c_bus(1, 400, n8x0_i2c_board_info_1,
-			      ARRAY_SIZE(n8x0_i2c_board_info_1));
-}
+static struct i2c_board_info __initdata n8x0_i2c_board_info_1[] __initdata = {
+	{
+		I2C_BOARD_INFO("menelaus", 0x72),
+		.irq = INT_24XX_SYS_NIRQ,
+		.platform_data = &n8x0_menelaus_platform_data,
+	},
+};
 
-#else
-static inline void __init n8x0_menelaus_init(void)
-{
-}
-#endif
+static struct aic3x_pdata n810_aic33_data __initdata = {
+	.gpio_reset = 118,
+};
+
+static struct i2c_board_info n810_i2c_board_info_2[] __initdata = {
+	{
+		I2C_BOARD_INFO("tlv320aic3x", 0x18),
+		.platform_data = &n810_aic33_data,
+	},
+};
 
 static void __init n8x0_map_io(void)
 {
@@ -653,6 +646,11 @@
 
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
+	/* I2S codec port pins for McBSP block */
+	OMAP2420_MUX(EAC_AC_SCLK, OMAP_MUX_MODE1 | OMAP_PIN_INPUT),
+	OMAP2420_MUX(EAC_AC_FS, OMAP_MUX_MODE1 | OMAP_PIN_INPUT),
+	OMAP2420_MUX(EAC_AC_DIN, OMAP_MUX_MODE1 | OMAP_PIN_INPUT),
+	OMAP2420_MUX(EAC_AC_DOUT, OMAP_MUX_MODE1 | OMAP_PIN_OUTPUT),
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
 #else
@@ -665,9 +663,14 @@
 	/* FIXME: add n810 spi devices */
 	spi_register_board_info(n800_spi_board_info,
 				ARRAY_SIZE(n800_spi_board_info));
+	omap_register_i2c_bus(1, 400, n8x0_i2c_board_info_1,
+			      ARRAY_SIZE(n8x0_i2c_board_info_1));
+	omap_register_i2c_bus(2, 400, NULL, 0);
+	if (machine_is_nokia_n810())
+		i2c_register_board_info(2, n810_i2c_board_info_2,
+					ARRAY_SIZE(n810_i2c_board_info_2));
 
 	omap_serial_init();
-	n8x0_menelaus_init();
 	n8x0_onenand_init();
 	n8x0_mmc_init();
 	n8x0_usb_init();
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 9d9f5b8..14f4224 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -27,6 +27,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/nand.h>
+#include <linux/mmc/host.h>
 
 #include <linux/regulator/machine.h>
 #include <linux/i2c/twl.h>
@@ -43,13 +44,100 @@
 #include <plat/gpmc.h>
 #include <plat/nand.h>
 #include <plat/usb.h>
-#include <plat/timer-gp.h>
 
 #include "mux.h"
 #include "hsmmc.h"
+#include "timer-gp.h"
 
 #define NAND_BLOCK_SIZE		SZ_128K
 
+/*
+ * OMAP3 Beagle revision
+ * Run time detection of Beagle revision is done by reading GPIO.
+ * GPIO ID -
+ *	AXBX	= GPIO173, GPIO172, GPIO171: 1 1 1
+ *	C1_3	= GPIO173, GPIO172, GPIO171: 1 1 0
+ *	C4	= GPIO173, GPIO172, GPIO171: 1 0 1
+ *	XM	= GPIO173, GPIO172, GPIO171: 0 0 0
+ */
+enum {
+	OMAP3BEAGLE_BOARD_UNKN = 0,
+	OMAP3BEAGLE_BOARD_AXBX,
+	OMAP3BEAGLE_BOARD_C1_3,
+	OMAP3BEAGLE_BOARD_C4,
+	OMAP3BEAGLE_BOARD_XM,
+};
+
+static u8 omap3_beagle_version;
+
+static u8 omap3_beagle_get_rev(void)
+{
+	return omap3_beagle_version;
+}
+
+static void __init omap3_beagle_init_rev(void)
+{
+	int ret;
+	u16 beagle_rev = 0;
+
+	omap_mux_init_gpio(171, OMAP_PIN_INPUT_PULLUP);
+	omap_mux_init_gpio(172, OMAP_PIN_INPUT_PULLUP);
+	omap_mux_init_gpio(173, OMAP_PIN_INPUT_PULLUP);
+
+	ret = gpio_request(171, "rev_id_0");
+	if (ret < 0)
+		goto fail0;
+
+	ret = gpio_request(172, "rev_id_1");
+	if (ret < 0)
+		goto fail1;
+
+	ret = gpio_request(173, "rev_id_2");
+	if (ret < 0)
+		goto fail2;
+
+	gpio_direction_input(171);
+	gpio_direction_input(172);
+	gpio_direction_input(173);
+
+	beagle_rev = gpio_get_value(171) | (gpio_get_value(172) << 1)
+			| (gpio_get_value(173) << 2);
+
+	switch (beagle_rev) {
+	case 7:
+		printk(KERN_INFO "OMAP3 Beagle Rev: Ax/Bx\n");
+		omap3_beagle_version = OMAP3BEAGLE_BOARD_AXBX;
+		break;
+	case 6:
+		printk(KERN_INFO "OMAP3 Beagle Rev: C1/C2/C3\n");
+		omap3_beagle_version = OMAP3BEAGLE_BOARD_C1_3;
+		break;
+	case 5:
+		printk(KERN_INFO "OMAP3 Beagle Rev: C4\n");
+		omap3_beagle_version = OMAP3BEAGLE_BOARD_C4;
+		break;
+	case 0:
+		printk(KERN_INFO "OMAP3 Beagle Rev: xM\n");
+		omap3_beagle_version = OMAP3BEAGLE_BOARD_XM;
+		break;
+	default:
+		printk(KERN_INFO "OMAP3 Beagle Rev: unknown %hd\n", beagle_rev);
+		omap3_beagle_version = OMAP3BEAGLE_BOARD_UNKN;
+	}
+
+	return;
+
+fail2:
+	gpio_free(172);
+fail1:
+	gpio_free(171);
+fail0:
+	printk(KERN_ERR "Unable to get revision detection GPIO pins\n");
+	omap3_beagle_version = OMAP3BEAGLE_BOARD_UNKN;
+
+	return;
+}
+
 static struct mtd_partition omap3beagle_nand_partitions[] = {
 	/* All the partition sizes are listed in terms of NAND block size */
 	{
@@ -166,7 +254,7 @@
 static struct omap2_hsmmc_info mmc[] = {
 	{
 		.mmc		= 1,
-		.wires		= 8,
+		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= 29,
 	},
 	{}	/* Terminator */
@@ -185,7 +273,10 @@
 static int beagle_twl_gpio_setup(struct device *dev,
 		unsigned gpio, unsigned ngpio)
 {
-	if (system_rev >= 0x20 && system_rev <= 0x34301000) {
+	if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
+		mmc[0].gpio_wp = -EINVAL;
+	} else if ((omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C1_3) ||
+		(omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C4)) {
 		omap_mux_init_gpio(23, OMAP_PIN_INPUT);
 		mmc[0].gpio_wp = 23;
 	} else {
@@ -322,13 +413,19 @@
 	},
 };
 
+static struct i2c_board_info __initdata beagle_i2c_eeprom[] = {
+       {
+               I2C_BOARD_INFO("eeprom", 0x50),
+       },
+};
+
 static int __init omap3_beagle_i2c_init(void)
 {
 	omap_register_i2c_bus(1, 2600, beagle_i2c_boardinfo,
 			ARRAY_SIZE(beagle_i2c_boardinfo));
 	/* Bus 3 is attached to the DVI port where devices like the pico DLP
 	 * projector don't work reliably with 400kHz */
-	omap_register_i2c_bus(3, 100, NULL, 0);
+	omap_register_i2c_bus(3, 100, beagle_i2c_eeprom, ARRAY_SIZE(beagle_i2c_eeprom));
 	return 0;
 }
 
@@ -464,6 +561,7 @@
 static void __init omap3_beagle_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+	omap3_beagle_init_rev();
 	omap3_beagle_i2c_init();
 	platform_add_devices(omap3_beagle_devices,
 			ARRAY_SIZE(omap3_beagle_devices));
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index 8936e4f..b04365c 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -31,6 +31,7 @@
 #include <linux/smsc911x.h>
 
 #include <linux/regulator/machine.h>
+#include <linux/mmc/host.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -370,7 +371,7 @@
 static struct omap2_hsmmc_info mmc[] = {
 	{
 		.mmc		= 1,
-		.wires		= 4,
+		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= 63,
 	},
@@ -446,7 +447,7 @@
 	.usb_mode	= T2_USB_MODE_ULPI,
 };
 
-static int board_keymap[] = {
+static uint32_t board_keymap[] = {
 	KEY(0, 0, KEY_LEFT),
 	KEY(0, 1, KEY_DOWN),
 	KEY(0, 2, KEY_ENTER),
@@ -584,7 +585,7 @@
 	return !gpio_get_value(OMAP3_EVM_TS_GPIO);
 }
 
-struct ads7846_platform_data ads7846_config = {
+static struct ads7846_platform_data ads7846_config = {
 	.x_max			= 0x0fff,
 	.y_max			= 0x0fff,
 	.x_plate_ohms		= 180,
@@ -603,7 +604,7 @@
 	.single_channel	= 1,	/* 0: slave, 1: master */
 };
 
-struct spi_board_info omap3evm_spi_board_info[] = {
+static struct spi_board_info omap3evm_spi_board_info[] = {
 	[0] = {
 		.modalias		= "ads7846",
 		.bus_num		= 1,
diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c
new file mode 100644
index 0000000..5f7d2c1
--- /dev/null
+++ b/arch/arm/mach-omap2/board-omap3logic.c
@@ -0,0 +1,241 @@
+/*
+ * linux/arch/arm/mach-omap2/board-omap3logic.c
+ *
+ * Copyright (C) 2010 Li-Pro.Net
+ * Stephan Linz <linz@li-pro.net>
+ *
+ * Copyright (C) 2010 Logic Product Development, Inc.
+ * Peter Barada <peter.barada@logicpd.com>
+ *
+ * Modified from Beagle, EVM, and RX51
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+
+#include <linux/regulator/machine.h>
+
+#include <linux/i2c/twl.h>
+#include <linux/mmc/host.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include "mux.h"
+#include "hsmmc.h"
+#include "timer-gp.h"
+#include "control.h"
+
+#include <plat/mux.h>
+#include <plat/board.h>
+#include <plat/common.h>
+#include <plat/gpmc-smsc911x.h>
+#include <plat/gpmc.h>
+#include <plat/sdrc.h>
+
+#define OMAP3LOGIC_SMSC911X_CS			1
+
+#define OMAP3530_LV_SOM_MMC_GPIO_CD		110
+#define OMAP3530_LV_SOM_MMC_GPIO_WP		126
+#define OMAP3530_LV_SOM_SMSC911X_GPIO_IRQ	152
+
+#define OMAP3_TORPEDO_MMC_GPIO_CD		127
+#define OMAP3_TORPEDO_SMSC911X_GPIO_IRQ		129
+
+static struct regulator_consumer_supply omap3logic_vmmc1_supply = {
+	.supply			= "vmmc",
+};
+
+/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
+static struct regulator_init_data omap3logic_vmmc1 = {
+	.constraints = {
+		.name			= "VMMC1",
+		.min_uV			= 1850000,
+		.max_uV			= 3150000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
+					| REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies  = 1,
+	.consumer_supplies      = &omap3logic_vmmc1_supply,
+};
+
+static struct twl4030_gpio_platform_data omap3logic_gpio_data = {
+	.gpio_base	= OMAP_MAX_GPIO_LINES,
+	.irq_base	= TWL4030_GPIO_IRQ_BASE,
+	.irq_end	= TWL4030_GPIO_IRQ_END,
+	.use_leds	= true,
+	.pullups	= BIT(1),
+	.pulldowns	= BIT(2)  | BIT(6)  | BIT(7)  | BIT(8)
+			| BIT(13) | BIT(15) | BIT(16) | BIT(17),
+};
+
+static struct twl4030_platform_data omap3logic_twldata = {
+	.irq_base	= TWL4030_IRQ_BASE,
+	.irq_end	= TWL4030_IRQ_END,
+
+	/* platform_data for children goes here */
+	.gpio		= &omap3logic_gpio_data,
+	.vmmc1		= &omap3logic_vmmc1,
+};
+
+static struct i2c_board_info __initdata omap3logic_i2c_boardinfo[] = {
+	{
+		I2C_BOARD_INFO("twl4030", 0x48),
+		.flags = I2C_CLIENT_WAKE,
+		.irq = INT_34XX_SYS_NIRQ,
+		.platform_data = &omap3logic_twldata,
+	},
+};
+
+static int __init omap3logic_i2c_init(void)
+{
+	omap_register_i2c_bus(1, 2600, omap3logic_i2c_boardinfo,
+				ARRAY_SIZE(omap3logic_i2c_boardinfo));
+	return 0;
+}
+
+static struct omap2_hsmmc_info __initdata board_mmc_info[] = {
+	{
+		.name		= "external",
+		.mmc		= 1,
+		.caps		= MMC_CAP_4_BIT_DATA,
+		.gpio_cd	= -EINVAL,
+		.gpio_wp	= -EINVAL,
+	},
+	{}      /* Terminator */
+};
+
+static void __init board_mmc_init(void)
+{
+	if (machine_is_omap3530_lv_som()) {
+		/* OMAP3530 LV SOM board */
+		board_mmc_info[0].gpio_cd = OMAP3530_LV_SOM_MMC_GPIO_CD;
+		board_mmc_info[0].gpio_wp = OMAP3530_LV_SOM_MMC_GPIO_WP;
+		omap_mux_init_signal("gpio_110", OMAP_PIN_OUTPUT);
+		omap_mux_init_signal("gpio_126", OMAP_PIN_OUTPUT);
+	} else if (machine_is_omap3_torpedo()) {
+		/* OMAP3 Torpedo board */
+		board_mmc_info[0].gpio_cd = OMAP3_TORPEDO_MMC_GPIO_CD;
+		omap_mux_init_signal("gpio_127", OMAP_PIN_OUTPUT);
+	} else {
+		/* unsupported board */
+		printk(KERN_ERR "%s(): unknown machine type\n", __func__);
+		return;
+	}
+
+	omap2_hsmmc_init(board_mmc_info);
+	/* link regulators to MMC adapters */
+	omap3logic_vmmc1_supply.dev = board_mmc_info[0].dev;
+}
+
+static struct omap_smsc911x_platform_data __initdata board_smsc911x_data = {
+	.cs             = OMAP3LOGIC_SMSC911X_CS,
+	.gpio_irq       = -EINVAL,
+	.gpio_reset     = -EINVAL,
+	.flags          = IORESOURCE_IRQ_LOWLEVEL,
+};
+
+/* TODO/FIXME (comment by Peter Barada, LogicPD):
+ * Fix the PBIAS voltage for Torpedo MMC1 pins that
+ * are used for other needs (IRQs, etc).            */
+static void omap3torpedo_fix_pbias_voltage(void)
+{
+	u16 control_pbias_offset = OMAP343X_CONTROL_PBIAS_LITE;
+	u32 reg;
+
+	if (machine_is_omap3_torpedo())
+	{
+		/* Set the bias for the pin */
+		reg = omap_ctrl_readl(control_pbias_offset);
+
+		reg &= ~OMAP343X_PBIASLITEPWRDNZ1;
+		omap_ctrl_writel(reg, control_pbias_offset);
+
+		/* 100ms delay required for PBIAS configuration */
+		msleep(100);
+
+		reg |= OMAP343X_PBIASLITEVMODE1;
+		reg |= OMAP343X_PBIASLITEPWRDNZ1;
+		omap_ctrl_writel(reg | 0x300, control_pbias_offset);
+	}
+}
+
+static inline void __init board_smsc911x_init(void)
+{
+	if (machine_is_omap3530_lv_som()) {
+		/* OMAP3530 LV SOM board */
+		board_smsc911x_data.gpio_irq =
+					OMAP3530_LV_SOM_SMSC911X_GPIO_IRQ;
+		omap_mux_init_signal("gpio_152", OMAP_PIN_INPUT);
+	} else if (machine_is_omap3_torpedo()) {
+		/* OMAP3 Torpedo board */
+		board_smsc911x_data.gpio_irq = OMAP3_TORPEDO_SMSC911X_GPIO_IRQ;
+		omap_mux_init_signal("gpio_129", OMAP_PIN_INPUT);
+	} else {
+		/* unsupported board */
+		printk(KERN_ERR "%s(): unknown machine type\n", __func__);
+		return;
+	}
+
+	gpmc_smsc911x_init(&board_smsc911x_data);
+}
+
+static void __init omap3logic_init_irq(void)
+{
+	omap2_init_common_hw(NULL, NULL);
+	omap_init_irq();
+	omap_gpio_init();
+}
+
+#ifdef CONFIG_OMAP_MUX
+static struct omap_board_mux board_mux[] __initdata = {
+	{ .reg_offset = OMAP_MUX_TERMINATOR },
+};
+#else
+#define board_mux       NULL
+#endif
+
+static void __init omap3logic_init(void)
+{
+	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+	omap3torpedo_fix_pbias_voltage();
+	omap3logic_i2c_init();
+	omap_serial_init();
+	board_mmc_init();
+	board_smsc911x_init();
+
+	/* Ensure SDRC pins are mux'd for self-refresh */
+	omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
+	omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
+}
+
+MACHINE_START(OMAP3_TORPEDO, "Logic OMAP3 Torpedo board")
+	.boot_params	= 0x80000100,
+	.map_io		= omap3_map_io,
+	.init_irq	= omap3logic_init_irq,
+	.init_machine	= omap3logic_init,
+	.timer		= &omap_timer,
+MACHINE_END
+
+MACHINE_START(OMAP3530_LV_SOM, "OMAP Logic 3530 LV SOM board")
+	.boot_params	= 0x80000100,
+	.map_io		= omap3_map_io,
+	.init_irq	= omap3logic_init_irq,
+	.init_machine	= omap3logic_init,
+	.timer		= &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index 41d6f54..89ed1be 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -32,7 +32,9 @@
 #include <linux/input.h>
 #include <linux/input/matrix_keypad.h>
 #include <linux/gpio_keys.h>
+#include <linux/mmc/host.h>
 #include <linux/mmc/card.h>
+#include <linux/regulator/fixed.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -276,14 +278,14 @@
 static struct omap2_hsmmc_info omap3pandora_mmc[] = {
 	{
 		.mmc		= 1,
-		.wires		= 4,
+		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= 126,
 		.ext_clock	= 0,
 	},
 	{
 		.mmc		= 2,
-		.wires		= 4,
+		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= 127,
 		.ext_clock	= 1,
@@ -291,7 +293,7 @@
 	},
 	{
 		.mmc		= 3,
-		.wires		= 4,
+		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
 		.init_card	= pandora_wl1251_init_card,
@@ -344,6 +346,9 @@
 static struct regulator_consumer_supply pandora_vmmc2_supply =
 	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.1");
 
+static struct regulator_consumer_supply pandora_vmmc3_supply =
+	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.2");
+
 static struct regulator_consumer_supply pandora_vdda_dac_supply =
 	REGULATOR_SUPPLY("vdda_dac", "omapdss");
 
@@ -488,6 +493,33 @@
 	.consumer_supplies	= &pandora_adac_supply,
 };
 
+/* Fixed regulator internal to Wifi module */
+static struct regulator_init_data pandora_vmmc3 = {
+	.constraints = {
+		.valid_ops_mask		= REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &pandora_vmmc3_supply,
+};
+
+static struct fixed_voltage_config pandora_vwlan = {
+	.supply_name		= "vwlan",
+	.microvolts		= 1800000, /* 1.8V */
+	.gpio			= PANDORA_WIFI_NRESET_GPIO,
+	.startup_delay		= 50000, /* 50ms */
+	.enable_high		= 1,
+	.enabled_at_boot	= 0,
+	.init_data		= &pandora_vmmc3,
+};
+
+static struct platform_device pandora_vwlan_device = {
+	.name		= "reg-fixed-voltage",
+	.id		= 1,
+	.dev = {
+		.platform_data = &pandora_vwlan,
+	},
+};
+
 static struct twl4030_usb_data omap3pandora_usb_data = {
 	.usb_mode	= T2_USB_MODE_ULPI,
 };
@@ -501,6 +533,8 @@
 	.audio = &omap3pandora_audio_data,
 };
 
+static struct twl4030_bci_platform_data pandora_bci_data;
+
 static struct twl4030_platform_data omap3pandora_twldata = {
 	.irq_base	= TWL4030_IRQ_BASE,
 	.irq_end	= TWL4030_IRQ_END,
@@ -516,6 +550,7 @@
 	.vaux4		= &pandora_vaux4,
 	.vsim		= &pandora_vsim,
 	.keypad		= &pandora_kp_data,
+	.bci		= &pandora_bci_data,
 };
 
 static struct i2c_board_info __initdata omap3pandora_i2c_boardinfo[] = {
@@ -644,19 +679,8 @@
 	if (pandora_wl1251_pdata.irq < 0)
 		goto fail_irq;
 
-	ret = gpio_request(PANDORA_WIFI_NRESET_GPIO, "wl1251 nreset");
-	if (ret < 0)
-		goto fail_irq;
-
-	/* start powered so that it probes with MMC subsystem */
-	ret = gpio_direction_output(PANDORA_WIFI_NRESET_GPIO, 1);
-	if (ret < 0)
-		goto fail_nreset;
-
 	return;
 
-fail_nreset:
-	gpio_free(PANDORA_WIFI_NRESET_GPIO);
 fail_irq:
 	gpio_free(PANDORA_WIFI_IRQ_GPIO);
 fail:
@@ -668,6 +692,7 @@
 	&pandora_keys_gpio,
 	&pandora_dss_device,
 	&pandora_wl1251_data,
+	&pandora_vwlan_device,
 };
 
 static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index bc5ac83..f252721 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -26,6 +26,7 @@
 
 #include <linux/regulator/machine.h>
 #include <linux/i2c/twl.h>
+#include <linux/mmc/host.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -38,7 +39,6 @@
 #include <plat/gpmc.h>
 #include <plat/nand.h>
 #include <plat/usb.h>
-#include <plat/timer-gp.h>
 #include <plat/display.h>
 
 #include <plat/mcspi.h>
@@ -52,6 +52,7 @@
 #include "sdram-micron-mt46h32m32lf-6.h"
 #include "mux.h"
 #include "hsmmc.h"
+#include "timer-gp.h"
 
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
 #define OMAP3STALKER_ETHR_START	0x2c000000
@@ -275,7 +276,7 @@
 static struct omap2_hsmmc_info mmc[] = {
 	{
 	 .mmc		= 1,
-	 .wires		= 4,
+	 .caps		= MMC_CAP_4_BIT_DATA,
 	 .gpio_cd	= -EINVAL,
 	 .gpio_wp	= 23,
 	 },
@@ -389,7 +390,7 @@
 	.usb_mode	= T2_USB_MODE_ULPI,
 };
 
-static int board_keymap[] = {
+static uint32_t board_keymap[] = {
 	KEY(0, 0, KEY_LEFT),
 	KEY(0, 1, KEY_DOWN),
 	KEY(0, 2, KEY_ENTER),
@@ -564,7 +565,7 @@
 	.single_channel		= 1,	/* 0: slave, 1: master */
 };
 
-struct spi_board_info omap3stalker_spi_board_info[] = {
+static struct spi_board_info omap3stalker_spi_board_info[] = {
 	[0] = {
 	       .modalias	= "ads7846",
 	       .bus_num		= 1,
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index 0e99ce5..41104bb 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -27,6 +27,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/nand.h>
+#include <linux/mmc/host.h>
 
 #include <plat/mcspi.h>
 #include <linux/spi/spi.h>
@@ -47,10 +48,10 @@
 #include <plat/gpmc.h>
 #include <plat/nand.h>
 #include <plat/usb.h>
-#include <plat/timer-gp.h>
 
 #include "mux.h"
 #include "hsmmc.h"
+#include "timer-gp.h"
 
 #include <asm/setup.h>
 
@@ -61,7 +62,7 @@
 #define TB_BL_PWM_TIMER		9
 #define TB_KILL_POWER_GPIO	168
 
-unsigned long touchbook_revision;
+static unsigned long touchbook_revision;
 
 static struct mtd_partition omap3touchbook_nand_partitions[] = {
 	/* All the partition sizes are listed in terms of NAND block size */
@@ -108,7 +109,7 @@
 static struct omap2_hsmmc_info mmc[] = {
 	{
 		.mmc		= 1,
-		.wires		= 8,
+		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= 29,
 	},
 	{}	/* Terminator */
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index db69bca..702f2a6 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -20,6 +20,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/leds.h>
 #include <linux/gpio.h>
 #include <linux/usb/otg.h>
 #include <linux/i2c/twl.h>
@@ -33,12 +34,45 @@
 
 #include <plat/board.h>
 #include <plat/common.h>
-#include <plat/control.h>
-#include <plat/timer-gp.h>
 #include <plat/usb.h>
 #include <plat/mmc.h>
-#include "hsmmc.h"
+#include "timer-gp.h"
 
+#include "hsmmc.h"
+#include "control.h"
+
+#define GPIO_HUB_POWER		1
+#define GPIO_HUB_NRESET		62
+
+static struct gpio_led gpio_leds[] = {
+	{
+		.name			= "pandaboard::status1",
+		.default_trigger	= "heartbeat",
+		.gpio			= 7,
+	},
+	{
+		.name			= "pandaboard::status2",
+		.default_trigger	= "mmc0",
+		.gpio			= 8,
+	},
+};
+
+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 *panda_devices[] __initdata = {
+	&leds_gpio,
+};
 
 static void __init omap4_panda_init_irq(void)
 {
@@ -47,6 +81,56 @@
 	omap_gpio_init();
 }
 
+static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
+	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
+	.port_mode[1] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+	.phy_reset  = false,
+	.reset_gpio_port[0]  = -EINVAL,
+	.reset_gpio_port[1]  = -EINVAL,
+	.reset_gpio_port[2]  = -EINVAL
+};
+
+static void __init omap4_ehci_init(void)
+{
+	int ret;
+
+
+	/* disable the power to the usb hub prior to init */
+	ret = gpio_request(GPIO_HUB_POWER, "hub_power");
+	if (ret) {
+		pr_err("Cannot request GPIO %d\n", GPIO_HUB_POWER);
+		goto error1;
+	}
+	gpio_export(GPIO_HUB_POWER, 0);
+	gpio_direction_output(GPIO_HUB_POWER, 0);
+	gpio_set_value(GPIO_HUB_POWER, 0);
+
+	/* reset phy+hub */
+	ret = gpio_request(GPIO_HUB_NRESET, "hub_nreset");
+	if (ret) {
+		pr_err("Cannot request GPIO %d\n", GPIO_HUB_NRESET);
+		goto error2;
+	}
+	gpio_export(GPIO_HUB_NRESET, 0);
+	gpio_direction_output(GPIO_HUB_NRESET, 0);
+	gpio_set_value(GPIO_HUB_NRESET, 0);
+	gpio_set_value(GPIO_HUB_NRESET, 1);
+
+	usb_ehci_init(&ehci_pdata);
+
+	/* enable power to hub */
+	gpio_set_value(GPIO_HUB_POWER, 1);
+	return;
+
+error2:
+	gpio_free(GPIO_HUB_POWER);
+error1:
+	pr_err("Unable to initialize EHCI power/reset\n");
+	return;
+
+}
+
 static struct omap_musb_board_data musb_board_data = {
 	.interface_type		= MUSB_INTERFACE_UTMI,
 	.mode			= MUSB_PERIPHERAL,
@@ -56,7 +140,7 @@
 static struct omap2_hsmmc_info mmc[] = {
 	{
 		.mmc		= 1,
-		.wires		= 8,
+		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= -EINVAL,
 	},
 	{}	/* Terminator */
@@ -67,10 +151,6 @@
 		.supply = "vmmc",
 		.dev_name = "mmci-omap-hs.0",
 	},
-	{
-		.supply = "vmmc",
-		.dev_name = "mmci-omap-hs.1",
-	},
 };
 
 static int omap4_twl6030_hsmmc_late_init(struct device *dev)
@@ -89,7 +169,14 @@
 
 static __init void omap4_twl6030_hsmmc_set_late_init(struct device *dev)
 {
-	struct omap_mmc_platform_data *pdata = dev->platform_data;
+	struct omap_mmc_platform_data *pdata;
+
+	/* dev can be null if CONFIG_MMC_OMAP_HS is not set */
+	if (!dev) {
+		pr_err("Failed omap4_twl6030_hsmmc_set_late_init\n");
+		return;
+	}
+	pdata = dev->platform_data;
 
 	pdata->init =	omap4_twl6030_hsmmc_late_init;
 }
@@ -156,7 +243,7 @@
 					| REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies  = 2,
+	.num_consumer_supplies  = 1,
 	.consumer_supplies      = omap4_panda_vmmc_supply,
 };
 
@@ -274,13 +361,13 @@
 }
 static void __init omap4_panda_init(void)
 {
-	int status;
-
 	omap4_panda_i2c_init();
+	platform_add_devices(panda_devices, ARRAY_SIZE(panda_devices));
 	omap_serial_init();
 	omap4_twl6030_hsmmc_init(mmc);
 	/* OMAP4 Panda uses internal transceiver so register nop transceiver */
 	usb_nop_xceiv_register();
+	omap4_ehci_init();
 	/* FIXME: allow multi-omap to boot until musb is updated for omap4 */
 	if (!cpu_is_omap44xx())
 		usb_musb_init(&musb_board_data);
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index 5e528ca..7053bc0 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -32,6 +32,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
+#include <linux/mmc/host.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -303,13 +304,13 @@
 static struct omap2_hsmmc_info mmc[] = {
 	{
 		.mmc		= 1,
-		.wires		= 4,
+		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
 	},
 	{
 		.mmc		= 2,
-		.wires		= 4,
+		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
 		.transceiver	= true,
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index 63d786b..3fec4d6 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -33,6 +33,8 @@
 #include <plat/onenand.h>
 #include <plat/gpmc-smc91x.h>
 
+#include <mach/board-rx51.h>
+
 #include <sound/tlv320aic3x.h>
 #include <sound/tpa6130a2-plat.h>
 
@@ -105,6 +107,10 @@
 	},
 };
 
+static struct platform_device rx51_charger_device = {
+	.name = "isp1704_charger",
+};
+
 #if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
 
 #define RX51_GPIO_CAMERA_LENS_COVER	110
@@ -185,7 +191,7 @@
 }
 #endif /* CONFIG_KEYBOARD_GPIO || CONFIG_KEYBOARD_GPIO_MODULE */
 
-static int board_keymap[] = {
+static uint32_t board_keymap[] = {
 	/*
 	 * Note that KEY(x, 8, KEY_XXX) entries represent "entrire row
 	 * connected to the ground" matrix state.
@@ -303,7 +309,7 @@
 	{
 		.name		= "external",
 		.mmc		= 1,
-		.wires		= 4,
+		.caps		= MMC_CAP_4_BIT_DATA,
 		.cover_only	= true,
 		.gpio_cd	= 160,
 		.gpio_wp	= -EINVAL,
@@ -312,7 +318,8 @@
 	{
 		.name		= "internal",
 		.mmc		= 2,
-		.wires		= 8, /* See also rx51_mmc2_remux */
+		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
+						/* See also rx51_mmc2_remux */
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
 		.nonremovable	= true,
@@ -916,5 +923,6 @@
 	spi_register_board_info(rx51_peripherals_spi_board_info,
 				ARRAY_SIZE(rx51_peripherals_spi_board_info));
 	omap2_hsmmc_init(mmc);
+	platform_device_register(&rx51_charger_device);
 }
 
diff --git a/arch/arm/mach-omap2/board-rx51-sdram.c b/arch/arm/mach-omap2/board-rx51-sdram.c
index f392844..a43b2c5 100644
--- a/arch/arm/mach-omap2/board-rx51-sdram.c
+++ b/arch/arm/mach-omap2/board-rx51-sdram.c
@@ -43,7 +43,7 @@
 	u32 tWTR;
 };
 
-struct omap_sdrc_params rx51_sdrc_params[4];
+static struct omap_sdrc_params rx51_sdrc_params[4];
 
 static const struct sdram_timings rx51_timings[] = {
 	{
diff --git a/arch/arm/mach-omap2/board-rx51-video.c b/arch/arm/mach-omap2/board-rx51-video.c
index 5a1005b..85503fe 100644
--- a/arch/arm/mach-omap2/board-rx51-video.c
+++ b/arch/arm/mach-omap2/board-rx51-video.c
@@ -20,6 +20,8 @@
 #include <plat/vram.h>
 #include <plat/mcspi.h>
 
+#include <mach/board-rx51.h>
+
 #include "mux.h"
 
 #define RX51_LCD_RESET_GPIO	90
diff --git a/arch/arm/mach-omap2/board-zoom-debugboard.c b/arch/arm/mach-omap2/board-zoom-debugboard.c
index 1d7f827..007ebdc 100644
--- a/arch/arm/mach-omap2/board-zoom-debugboard.c
+++ b/arch/arm/mach-omap2/board-zoom-debugboard.c
@@ -16,6 +16,8 @@
 
 #include <plat/gpmc.h>
 
+#include <mach/board-zoom.h>
+
 #define ZOOM_SMSC911X_CS	7
 #define ZOOM_SMSC911X_GPIO	158
 #define ZOOM_QUADUART_CS	3
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
index bc82328..86c9b21 100644
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -18,6 +18,7 @@
 #include <linux/regulator/machine.h>
 #include <linux/regulator/fixed.h>
 #include <linux/wl12xx.h>
+#include <linux/mmc/host.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -35,7 +36,7 @@
 #define OMAP_ZOOM_WLAN_IRQ_GPIO		(162)
 
 /* Zoom2 has Qwerty keyboard*/
-static int board_keymap[] = {
+static uint32_t board_keymap[] = {
 	KEY(0, 0, KEY_E),
 	KEY(0, 1, KEY_R),
 	KEY(0, 2, KEY_T),
@@ -199,14 +200,14 @@
 	{
 		.name		= "external",
 		.mmc		= 1,
-		.wires		= 4,
+		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_wp	= -EINVAL,
 		.power_saving	= true,
 	},
 	{
 		.name		= "internal",
 		.mmc		= 2,
-		.wires		= 8,
+		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
 		.nonremovable	= true,
@@ -348,4 +349,5 @@
 	platform_device_register(&omap_vwlan_device);
 	usb_musb_init(&musb_board_data);
 	enable_board_wakeup_source();
+	omap_serial_init();
 }
diff --git a/arch/arm/mach-omap2/board-zoom2.c b/arch/arm/mach-omap2/board-zoom2.c
index 4ccbc32..2992a9f 100644
--- a/arch/arm/mach-omap2/board-zoom2.c
+++ b/arch/arm/mach-omap2/board-zoom2.c
@@ -24,6 +24,7 @@
 
 #include <mach/board-zoom.h>
 
+#include "board-flash.h"
 #include "mux.h"
 #include "sdram-micron-mt46h32m32lf-6.h"
 
diff --git a/arch/arm/mach-omap2/board-zoom3.c b/arch/arm/mach-omap2/board-zoom3.c
index b2bb3ff..5adde12 100644
--- a/arch/arm/mach-omap2/board-zoom3.c
+++ b/arch/arm/mach-omap2/board-zoom3.c
@@ -22,6 +22,7 @@
 #include <plat/board.h>
 #include <plat/usb.h>
 
+#include "board-flash.h"
 #include "mux.h"
 #include "sdram-hynix-h8mbx00u0mer-0em.h"
 
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 605f531..b5babf5 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -395,7 +395,7 @@
 	if ((regval32 & (1 << clk->enable_bit)) == v)
 		return;
 
-	printk(KERN_DEBUG "Disabling unused clock \"%s\"\n", clk->name);
+	pr_debug("Disabling unused clock \"%s\"\n", clk->name);
 	if (cpu_is_omap34xx()) {
 		omap2_clk_enable(clk);
 		omap2_clk_disable(clk);
diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c
index 5f2066a..21f8562 100644
--- a/arch/arm/mach-omap2/clock2420_data.c
+++ b/arch/arm/mach-omap2/clock2420_data.c
@@ -27,6 +27,7 @@
 #include "prm-regbits-24xx.h"
 #include "cm-regbits-24xx.h"
 #include "sdrc.h"
+#include "control.h"
 
 #define OMAP_CM_REGADDR                 OMAP2420_CM_REGADDR
 
@@ -89,6 +90,12 @@
 	.clkdm_name	= "wkup_clkdm",
 };
 
+/* Optional external clock input for McBSP CLKS */
+static struct clk mcbsp_clks = {
+	.name		= "mcbsp_clks",
+	.ops		= &clkops_null,
+};
+
 /*
  * Analog domain root source clocks
  */
@@ -1135,14 +1142,34 @@
 	.recalc		= &followparent_recalc,
 };
 
+static const struct clksel_rate common_mcbsp_96m_rates[] = {
+	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate common_mcbsp_mcbsp_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel mcbsp_fck_clksel[] = {
+	{ .parent = &func_96m_ck,  .rates = common_mcbsp_96m_rates },
+	{ .parent = &mcbsp_clks,   .rates = common_mcbsp_mcbsp_rates },
+	{ .parent = NULL }
+};
+
 static struct clk mcbsp1_fck = {
 	.name		= "mcbsp1_fck",
 	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_96m_ck,
+	.init		= &omap2_init_clksel_parent,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_MCBSP1_SHIFT,
-	.recalc		= &followparent_recalc,
+	.clksel_reg	= OMAP242X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
+	.clksel_mask	= OMAP2_MCBSP1_CLKS_MASK,
+	.clksel		= mcbsp_fck_clksel,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk mcbsp2_ick = {
@@ -1159,10 +1186,14 @@
 	.name		= "mcbsp2_fck",
 	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_96m_ck,
+	.init		= &omap2_init_clksel_parent,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_MCBSP2_SHIFT,
-	.recalc		= &followparent_recalc,
+	.clksel_reg	= OMAP242X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
+	.clksel_mask	= OMAP2_MCBSP2_CLKS_MASK,
+	.clksel		= mcbsp_fck_clksel,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk mcspi1_ick = {
@@ -1721,6 +1752,9 @@
 	CLK(NULL,	"osc_ck",	&osc_ck,	CK_242X),
 	CLK(NULL,	"sys_ck",	&sys_ck,	CK_242X),
 	CLK(NULL,	"alt_ck",	&alt_ck,	CK_242X),
+	CLK("omap-mcbsp.1",	"pad_fck",	&mcbsp_clks,	CK_242X),
+	CLK("omap-mcbsp.2",	"pad_fck",	&mcbsp_clks,	CK_242X),
+	CLK(NULL,	"mcbsp_clks",	&mcbsp_clks,	CK_242X),
 	/* internal analog sources */
 	CLK(NULL,	"dpll_ck",	&dpll_ck,	CK_242X),
 	CLK(NULL,	"apll96_ck",	&apll96_ck,	CK_242X),
@@ -1728,6 +1762,8 @@
 	/* internal prcm root sources */
 	CLK(NULL,	"func_54m_ck",	&func_54m_ck,	CK_242X),
 	CLK(NULL,	"core_ck",	&core_ck,	CK_242X),
+	CLK("omap-mcbsp.1",	"prcm_fck",	&func_96m_ck,	CK_242X),
+	CLK("omap-mcbsp.2",	"prcm_fck",	&func_96m_ck,	CK_242X),
 	CLK(NULL,	"func_96m_ck",	&func_96m_ck,	CK_242X),
 	CLK(NULL,	"func_48m_ck",	&func_48m_ck,	CK_242X),
 	CLK(NULL,	"func_12m_ck",	&func_12m_ck,	CK_242X),
diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c
index 701a171..e32afcb 100644
--- a/arch/arm/mach-omap2/clock2430_data.c
+++ b/arch/arm/mach-omap2/clock2430_data.c
@@ -27,6 +27,7 @@
 #include "prm-regbits-24xx.h"
 #include "cm-regbits-24xx.h"
 #include "sdrc.h"
+#include "control.h"
 
 #define OMAP_CM_REGADDR			OMAP2430_CM_REGADDR
 
@@ -89,6 +90,12 @@
 	.clkdm_name	= "wkup_clkdm",
 };
 
+/* Optional external clock input for McBSP CLKS */
+static struct clk mcbsp_clks = {
+	.name		= "mcbsp_clks",
+	.ops		= &clkops_null,
+};
+
 /*
  * Analog domain root source clocks
  */
@@ -1123,14 +1130,34 @@
 	.recalc		= &followparent_recalc,
 };
 
+static const struct clksel_rate common_mcbsp_96m_rates[] = {
+	{ .div = 1, .val = 0, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate common_mcbsp_mcbsp_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
+	{ .div = 0 }
+};
+
+static const struct clksel mcbsp_fck_clksel[] = {
+	{ .parent = &func_96m_ck,  .rates = common_mcbsp_96m_rates },
+	{ .parent = &mcbsp_clks,   .rates = common_mcbsp_mcbsp_rates },
+	{ .parent = NULL }
+};
+
 static struct clk mcbsp1_fck = {
 	.name		= "mcbsp1_fck",
 	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_96m_ck,
+	.init		= &omap2_init_clksel_parent,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_MCBSP1_SHIFT,
-	.recalc		= &followparent_recalc,
+	.clksel_reg	= OMAP243X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
+	.clksel_mask	= OMAP2_MCBSP1_CLKS_MASK,
+	.clksel		= mcbsp_fck_clksel,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk mcbsp2_ick = {
@@ -1147,10 +1174,14 @@
 	.name		= "mcbsp2_fck",
 	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_96m_ck,
+	.init		= &omap2_init_clksel_parent,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_MCBSP2_SHIFT,
-	.recalc		= &followparent_recalc,
+	.clksel_reg	= OMAP243X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
+	.clksel_mask	= OMAP2_MCBSP2_CLKS_MASK,
+	.clksel		= mcbsp_fck_clksel,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk mcbsp3_ick = {
@@ -1167,10 +1198,14 @@
 	.name		= "mcbsp3_fck",
 	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_96m_ck,
+	.init		= &omap2_init_clksel_parent,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
 	.enable_bit	= OMAP2430_EN_MCBSP3_SHIFT,
-	.recalc		= &followparent_recalc,
+	.clksel_reg	= OMAP243X_CTRL_REGADDR(OMAP243X_CONTROL_DEVCONF1),
+	.clksel_mask	= OMAP2_MCBSP3_CLKS_MASK,
+	.clksel		= mcbsp_fck_clksel,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk mcbsp4_ick = {
@@ -1187,10 +1222,14 @@
 	.name		= "mcbsp4_fck",
 	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_96m_ck,
+	.init		= &omap2_init_clksel_parent,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
 	.enable_bit	= OMAP2430_EN_MCBSP4_SHIFT,
-	.recalc		= &followparent_recalc,
+	.clksel_reg	= OMAP243X_CTRL_REGADDR(OMAP243X_CONTROL_DEVCONF1),
+	.clksel_mask	= OMAP2_MCBSP4_CLKS_MASK,
+	.clksel		= mcbsp_fck_clksel,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk mcbsp5_ick = {
@@ -1207,10 +1246,14 @@
 	.name		= "mcbsp5_fck",
 	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_96m_ck,
+	.init		= &omap2_init_clksel_parent,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
 	.enable_bit	= OMAP2430_EN_MCBSP5_SHIFT,
-	.recalc		= &followparent_recalc,
+	.clksel_reg	= OMAP243X_CTRL_REGADDR(OMAP243X_CONTROL_DEVCONF1),
+	.clksel_mask	= OMAP2_MCBSP5_CLKS_MASK,
+	.clksel		= mcbsp_fck_clksel,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk mcspi1_ick = {
@@ -1808,6 +1851,12 @@
 	CLK(NULL,	"osc_ck",	&osc_ck,	CK_243X),
 	CLK(NULL,	"sys_ck",	&sys_ck,	CK_243X),
 	CLK(NULL,	"alt_ck",	&alt_ck,	CK_243X),
+	CLK("omap-mcbsp.1",	"pad_fck",	&mcbsp_clks,	CK_243X),
+	CLK("omap-mcbsp.2",	"pad_fck",	&mcbsp_clks,	CK_243X),
+	CLK("omap-mcbsp.3",	"pad_fck",	&mcbsp_clks,	CK_243X),
+	CLK("omap-mcbsp.4",	"pad_fck",	&mcbsp_clks,	CK_243X),
+	CLK("omap-mcbsp.5",	"pad_fck",	&mcbsp_clks,	CK_243X),
+	CLK(NULL,	"mcbsp_clks",	&mcbsp_clks,	CK_243X),
 	/* internal analog sources */
 	CLK(NULL,	"dpll_ck",	&dpll_ck,	CK_243X),
 	CLK(NULL,	"apll96_ck",	&apll96_ck,	CK_243X),
@@ -1815,6 +1864,11 @@
 	/* internal prcm root sources */
 	CLK(NULL,	"func_54m_ck",	&func_54m_ck,	CK_243X),
 	CLK(NULL,	"core_ck",	&core_ck,	CK_243X),
+	CLK("omap-mcbsp.1",	"prcm_fck",	&func_96m_ck,	CK_243X),
+	CLK("omap-mcbsp.2",	"prcm_fck",	&func_96m_ck,	CK_243X),
+	CLK("omap-mcbsp.3",	"prcm_fck",	&func_96m_ck,	CK_243X),
+	CLK("omap-mcbsp.4",	"prcm_fck",	&func_96m_ck,	CK_243X),
+	CLK("omap-mcbsp.5",	"prcm_fck",	&func_96m_ck,	CK_243X),
 	CLK(NULL,	"func_96m_ck",	&func_96m_ck,	CK_243X),
 	CLK(NULL,	"func_48m_ck",	&func_48m_ck,	CK_243X),
 	CLK(NULL,	"func_12m_ck",	&func_12m_ck,	CK_243X),
diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
index c73906d..d85ecd5 100644
--- a/arch/arm/mach-omap2/clock3xxx_data.c
+++ b/arch/arm/mach-omap2/clock3xxx_data.c
@@ -20,7 +20,6 @@
 #include <linux/clk.h>
 #include <linux/list.h>
 
-#include <plat/control.h>
 #include <plat/clkdev_omap.h>
 
 #include "clock.h"
@@ -33,6 +32,7 @@
 #include "cm-regbits-34xx.h"
 #include "prm.h"
 #include "prm-regbits-34xx.h"
+#include "control.h"
 
 /*
  * clocks
@@ -2465,6 +2465,16 @@
 	.recalc		= &followparent_recalc,
 };
 
+static struct clk uart4_fck = {
+	.name		= "uart4_fck",
+	.ops		= &clkops_omap2_dflt_wait,
+	.parent		= &per_48m_fck,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP3630_EN_UART4_SHIFT,
+	.clkdm_name	= "per_clkdm",
+	.recalc		= &followparent_recalc,
+};
+
 static struct clk gpt2_fck = {
 	.name		= "gpt2_fck",
 	.ops		= &clkops_omap2_dflt_wait,
@@ -2715,6 +2725,16 @@
 	.recalc		= &followparent_recalc,
 };
 
+static struct clk uart4_ick = {
+	.name		= "uart4_ick",
+	.ops		= &clkops_omap2_dflt_wait,
+	.parent		= &per_l4_ick,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+	.enable_bit	= OMAP3630_EN_UART4_SHIFT,
+	.clkdm_name	= "per_clkdm",
+	.recalc		= &followparent_recalc,
+};
+
 static struct clk gpt9_ick = {
 	.name		= "gpt9_ick",
 	.ops		= &clkops_omap2_dflt_wait,
@@ -3188,6 +3208,11 @@
 	CLK(NULL,	"osc_sys_ck",	&osc_sys_ck,	CK_3XXX),
 	CLK(NULL,	"sys_ck",	&sys_ck,	CK_3XXX),
 	CLK(NULL,	"sys_altclk",	&sys_altclk,	CK_3XXX),
+	CLK("omap-mcbsp.1",	"pad_fck",	&mcbsp_clks,	CK_3XXX),
+	CLK("omap-mcbsp.2",	"pad_fck",	&mcbsp_clks,	CK_3XXX),
+	CLK("omap-mcbsp.3",	"pad_fck",	&mcbsp_clks,	CK_3XXX),
+	CLK("omap-mcbsp.4",	"pad_fck",	&mcbsp_clks,	CK_3XXX),
+	CLK("omap-mcbsp.5",	"pad_fck",	&mcbsp_clks,	CK_3XXX),
 	CLK(NULL,	"mcbsp_clks",	&mcbsp_clks,	CK_3XXX),
 	CLK(NULL,	"sys_clkout1",	&sys_clkout1,	CK_3XXX),
 	CLK(NULL,	"dpll1_ck",	&dpll1_ck,	CK_3XXX),
@@ -3253,6 +3278,8 @@
 	CLK(NULL,	"cpefuse_fck",	&cpefuse_fck,	CK_3430ES2 | CK_AM35XX),
 	CLK(NULL,	"ts_fck",	&ts_fck,	CK_3430ES2 | CK_AM35XX),
 	CLK(NULL,	"usbtll_fck",	&usbtll_fck,	CK_3430ES2 | CK_AM35XX),
+	CLK("omap-mcbsp.1",	"prcm_fck",	&core_96m_fck,	CK_3XXX),
+	CLK("omap-mcbsp.5",	"prcm_fck",	&core_96m_fck,	CK_3XXX),
 	CLK(NULL,	"core_96m_fck",	&core_96m_fck,	CK_3XXX),
 	CLK("mmci-omap-hs.2",	"fck",	&mmchs3_fck,	CK_3430ES2 | CK_AM35XX),
 	CLK("mmci-omap-hs.1",	"fck",	&mmchs2_fck,	CK_3XXX),
@@ -3346,9 +3373,13 @@
 	CLK(NULL,	"omap_32ksync_ick", &omap_32ksync_ick, CK_3XXX),
 	CLK(NULL,	"gpt12_ick",	&gpt12_ick,	CK_3XXX),
 	CLK(NULL,	"gpt1_ick",	&gpt1_ick,	CK_3XXX),
+	CLK("omap-mcbsp.2",	"prcm_fck",	&per_96m_fck,	CK_3XXX),
+	CLK("omap-mcbsp.3",	"prcm_fck",	&per_96m_fck,	CK_3XXX),
+	CLK("omap-mcbsp.4",	"prcm_fck",	&per_96m_fck,	CK_3XXX),
 	CLK(NULL,	"per_96m_fck",	&per_96m_fck,	CK_3XXX),
 	CLK(NULL,	"per_48m_fck",	&per_48m_fck,	CK_3XXX),
 	CLK(NULL,	"uart3_fck",	&uart3_fck,	CK_3XXX),
+	CLK(NULL,	"uart4_fck",	&uart4_fck,	CK_36XX),
 	CLK(NULL,	"gpt2_fck",	&gpt2_fck,	CK_3XXX),
 	CLK(NULL,	"gpt3_fck",	&gpt3_fck,	CK_3XXX),
 	CLK(NULL,	"gpt4_fck",	&gpt4_fck,	CK_3XXX),
@@ -3372,6 +3403,7 @@
 	CLK(NULL,	"gpio2_ick",	&gpio2_ick,	CK_3XXX),
 	CLK(NULL,	"wdt3_ick",	&wdt3_ick,	CK_3XXX),
 	CLK(NULL,	"uart3_ick",	&uart3_ick,	CK_3XXX),
+	CLK(NULL,	"uart4_ick",	&uart4_ick,	CK_36XX),
 	CLK(NULL,	"gpt9_ick",	&gpt9_ick,	CK_3XXX),
 	CLK(NULL,	"gpt8_ick",	&gpt8_ick,	CK_3XXX),
 	CLK(NULL,	"gpt7_ick",	&gpt7_ick,	CK_3XXX),
diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index e10db7a..1599836 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -17,13 +17,15 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
+ *
+ * XXX Some of the ES1 clocks have been removed/changed; once support
+ * is added for discriminating clocks by ES level, these should be added back
+ * in.
  */
 
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/clk.h>
-
-#include <plat/control.h>
 #include <plat/clkdev_omap.h>
 
 #include "clock.h"
@@ -32,6 +34,7 @@
 #include "cm-regbits-44xx.h"
 #include "prm.h"
 #include "prm-regbits-44xx.h"
+#include "control.h"
 
 /* Root clocks */
 
@@ -175,21 +178,27 @@
 	.recalc		= &omap2_clksel_recalc,
 };
 
+static struct clk tie_low_clock_ck = {
+	.name		= "tie_low_clock_ck",
+	.rate		= 0,
+	.ops		= &clkops_null,
+};
+
 static struct clk utmi_phy_clkout_ck = {
 	.name		= "utmi_phy_clkout_ck",
-	.rate		= 12000000,
+	.rate		= 60000000,
 	.ops		= &clkops_null,
 };
 
 static struct clk xclk60mhsp1_ck = {
 	.name		= "xclk60mhsp1_ck",
-	.rate		= 12000000,
+	.rate		= 60000000,
 	.ops		= &clkops_null,
 };
 
 static struct clk xclk60mhsp2_ck = {
 	.name		= "xclk60mhsp2_ck",
-	.rate		= 12000000,
+	.rate		= 60000000,
 	.ops		= &clkops_null,
 };
 
@@ -201,39 +210,23 @@
 
 /* Module clocks and DPLL outputs */
 
-static const struct clksel_rate div2_1to2_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_4430 },
-	{ .div = 2, .val = 1, .flags = RATE_IN_4430 },
-	{ .div = 0 },
-};
-
-static const struct clksel dpll_sys_ref_clk_div[] = {
-	{ .parent = &sys_clkin_ck, .rates = div2_1to2_rates },
-	{ .parent = NULL },
-};
-
-static struct clk dpll_sys_ref_clk = {
-	.name		= "dpll_sys_ref_clk",
-	.parent		= &sys_clkin_ck,
-	.clksel		= dpll_sys_ref_clk_div,
-	.clksel_reg	= OMAP4430_CM_DPLL_SYS_REF_CLKSEL,
-	.clksel_mask	= OMAP4430_CLKSEL_0_0_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static const struct clksel abe_dpll_refclk_mux_sel[] = {
-	{ .parent = &dpll_sys_ref_clk, .rates = div_1_0_rates },
+static const struct clksel abe_dpll_bypass_clk_mux_sel[] = {
+	{ .parent = &sys_clkin_ck, .rates = div_1_0_rates },
 	{ .parent = &sys_32k_ck, .rates = div_1_1_rates },
 	{ .parent = NULL },
 };
 
+static struct clk abe_dpll_bypass_clk_mux_ck = {
+	.name		= "abe_dpll_bypass_clk_mux_ck",
+	.parent		= &sys_clkin_ck,
+	.ops		= &clkops_null,
+	.recalc		= &followparent_recalc,
+};
+
 static struct clk abe_dpll_refclk_mux_ck = {
 	.name		= "abe_dpll_refclk_mux_ck",
-	.parent		= &dpll_sys_ref_clk,
-	.clksel		= abe_dpll_refclk_mux_sel,
+	.parent		= &sys_clkin_ck,
+	.clksel		= abe_dpll_bypass_clk_mux_sel,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP4430_CM_ABE_PLL_REF_CLKSEL,
 	.clksel_mask	= OMAP4430_CLKSEL_0_0_MASK,
@@ -244,7 +237,7 @@
 /* DPLL_ABE */
 static struct dpll_data dpll_abe_dd = {
 	.mult_div1_reg	= OMAP4430_CM_CLKSEL_DPLL_ABE,
-	.clk_bypass	= &sys_clkin_ck,
+	.clk_bypass	= &abe_dpll_bypass_clk_mux_ck,
 	.clk_ref	= &abe_dpll_refclk_mux_ck,
 	.control_reg	= OMAP4430_CM_CLKMODE_DPLL_ABE,
 	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
@@ -310,6 +303,12 @@
 	.set_rate	= &omap2_clksel_set_rate,
 };
 
+static const struct clksel_rate div2_1to2_rates[] = {
+	{ .div = 1, .val = 0, .flags = RATE_IN_4430 },
+	{ .div = 2, .val = 1, .flags = RATE_IN_4430 },
+	{ .div = 0 },
+};
+
 static const struct clksel aess_fclk_div[] = {
 	{ .parent = &abe_clk, .rates = div2_1to2_rates },
 	{ .parent = NULL },
@@ -380,14 +379,14 @@
 };
 
 static const struct clksel core_hsd_byp_clk_mux_sel[] = {
-	{ .parent = &dpll_sys_ref_clk, .rates = div_1_0_rates },
+	{ .parent = &sys_clkin_ck, .rates = div_1_0_rates },
 	{ .parent = &dpll_abe_m3_ck, .rates = div_1_1_rates },
 	{ .parent = NULL },
 };
 
 static struct clk core_hsd_byp_clk_mux_ck = {
 	.name		= "core_hsd_byp_clk_mux_ck",
-	.parent		= &dpll_sys_ref_clk,
+	.parent		= &sys_clkin_ck,
 	.clksel		= core_hsd_byp_clk_mux_sel,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP4430_CM_CLKSEL_DPLL_CORE,
@@ -400,7 +399,7 @@
 static struct dpll_data dpll_core_dd = {
 	.mult_div1_reg	= OMAP4430_CM_CLKSEL_DPLL_CORE,
 	.clk_bypass	= &core_hsd_byp_clk_mux_ck,
-	.clk_ref	= &dpll_sys_ref_clk,
+	.clk_ref	= &sys_clkin_ck,
 	.control_reg	= OMAP4430_CM_CLKMODE_DPLL_CORE,
 	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
 	.autoidle_reg	= OMAP4430_CM_AUTOIDLE_DPLL_CORE,
@@ -418,7 +417,7 @@
 
 static struct clk dpll_core_ck = {
 	.name		= "dpll_core_ck",
-	.parent		= &dpll_sys_ref_clk,
+	.parent		= &sys_clkin_ck,
 	.dpll_data	= &dpll_core_dd,
 	.init		= &omap2_init_dpll_parent,
 	.ops		= &clkops_null,
@@ -596,14 +595,14 @@
 };
 
 static const struct clksel iva_hsd_byp_clk_mux_sel[] = {
-	{ .parent = &dpll_sys_ref_clk, .rates = div_1_0_rates },
+	{ .parent = &sys_clkin_ck, .rates = div_1_0_rates },
 	{ .parent = &div_iva_hs_clk, .rates = div_1_1_rates },
 	{ .parent = NULL },
 };
 
 static struct clk iva_hsd_byp_clk_mux_ck = {
 	.name		= "iva_hsd_byp_clk_mux_ck",
-	.parent		= &dpll_sys_ref_clk,
+	.parent		= &sys_clkin_ck,
 	.ops		= &clkops_null,
 	.recalc		= &followparent_recalc,
 };
@@ -612,7 +611,7 @@
 static struct dpll_data dpll_iva_dd = {
 	.mult_div1_reg	= OMAP4430_CM_CLKSEL_DPLL_IVA,
 	.clk_bypass	= &iva_hsd_byp_clk_mux_ck,
-	.clk_ref	= &dpll_sys_ref_clk,
+	.clk_ref	= &sys_clkin_ck,
 	.control_reg	= OMAP4430_CM_CLKMODE_DPLL_IVA,
 	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
 	.autoidle_reg	= OMAP4430_CM_AUTOIDLE_DPLL_IVA,
@@ -630,7 +629,7 @@
 
 static struct clk dpll_iva_ck = {
 	.name		= "dpll_iva_ck",
-	.parent		= &dpll_sys_ref_clk,
+	.parent		= &sys_clkin_ck,
 	.dpll_data	= &dpll_iva_dd,
 	.init		= &omap2_init_dpll_parent,
 	.ops		= &clkops_omap3_noncore_dpll_ops,
@@ -672,7 +671,7 @@
 static struct dpll_data dpll_mpu_dd = {
 	.mult_div1_reg	= OMAP4430_CM_CLKSEL_DPLL_MPU,
 	.clk_bypass	= &div_mpu_hs_clk,
-	.clk_ref	= &dpll_sys_ref_clk,
+	.clk_ref	= &sys_clkin_ck,
 	.control_reg	= OMAP4430_CM_CLKMODE_DPLL_MPU,
 	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
 	.autoidle_reg	= OMAP4430_CM_AUTOIDLE_DPLL_MPU,
@@ -690,7 +689,7 @@
 
 static struct clk dpll_mpu_ck = {
 	.name		= "dpll_mpu_ck",
-	.parent		= &dpll_sys_ref_clk,
+	.parent		= &sys_clkin_ck,
 	.dpll_data	= &dpll_mpu_dd,
 	.init		= &omap2_init_dpll_parent,
 	.ops		= &clkops_omap3_noncore_dpll_ops,
@@ -724,14 +723,14 @@
 };
 
 static const struct clksel per_hsd_byp_clk_mux_sel[] = {
-	{ .parent = &dpll_sys_ref_clk, .rates = div_1_0_rates },
+	{ .parent = &sys_clkin_ck, .rates = div_1_0_rates },
 	{ .parent = &per_hs_clk_div_ck, .rates = div_1_1_rates },
 	{ .parent = NULL },
 };
 
 static struct clk per_hsd_byp_clk_mux_ck = {
 	.name		= "per_hsd_byp_clk_mux_ck",
-	.parent		= &dpll_sys_ref_clk,
+	.parent		= &sys_clkin_ck,
 	.clksel		= per_hsd_byp_clk_mux_sel,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP4430_CM_CLKSEL_DPLL_PER,
@@ -744,7 +743,7 @@
 static struct dpll_data dpll_per_dd = {
 	.mult_div1_reg	= OMAP4430_CM_CLKSEL_DPLL_PER,
 	.clk_bypass	= &per_hsd_byp_clk_mux_ck,
-	.clk_ref	= &dpll_sys_ref_clk,
+	.clk_ref	= &sys_clkin_ck,
 	.control_reg	= OMAP4430_CM_CLKMODE_DPLL_PER,
 	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
 	.autoidle_reg	= OMAP4430_CM_AUTOIDLE_DPLL_PER,
@@ -762,7 +761,7 @@
 
 static struct clk dpll_per_ck = {
 	.name		= "dpll_per_ck",
-	.parent		= &dpll_sys_ref_clk,
+	.parent		= &sys_clkin_ck,
 	.dpll_data	= &dpll_per_dd,
 	.init		= &omap2_init_dpll_parent,
 	.ops		= &clkops_omap3_noncore_dpll_ops,
@@ -858,8 +857,8 @@
 /* DPLL_UNIPRO */
 static struct dpll_data dpll_unipro_dd = {
 	.mult_div1_reg	= OMAP4430_CM_CLKSEL_DPLL_UNIPRO,
-	.clk_bypass	= &dpll_sys_ref_clk,
-	.clk_ref	= &dpll_sys_ref_clk,
+	.clk_bypass	= &sys_clkin_ck,
+	.clk_ref	= &sys_clkin_ck,
 	.control_reg	= OMAP4430_CM_CLKMODE_DPLL_UNIPRO,
 	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
 	.autoidle_reg	= OMAP4430_CM_AUTOIDLE_DPLL_UNIPRO,
@@ -877,7 +876,7 @@
 
 static struct clk dpll_unipro_ck = {
 	.name		= "dpll_unipro_ck",
-	.parent		= &dpll_sys_ref_clk,
+	.parent		= &sys_clkin_ck,
 	.dpll_data	= &dpll_unipro_dd,
 	.init		= &omap2_init_dpll_parent,
 	.ops		= &clkops_omap3_noncore_dpll_ops,
@@ -914,7 +913,8 @@
 static struct dpll_data dpll_usb_dd = {
 	.mult_div1_reg	= OMAP4430_CM_CLKSEL_DPLL_USB,
 	.clk_bypass	= &usb_hs_clk_div_ck,
-	.clk_ref	= &dpll_sys_ref_clk,
+	.flags		= DPLL_J_TYPE | DPLL_NO_DCO_SEL,
+	.clk_ref	= &sys_clkin_ck,
 	.control_reg	= OMAP4430_CM_CLKMODE_DPLL_USB,
 	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
 	.autoidle_reg	= OMAP4430_CM_AUTOIDLE_DPLL_USB,
@@ -927,13 +927,12 @@
 	.max_multiplier	= OMAP4430_MAX_DPLL_MULT,
 	.max_divider	= OMAP4430_MAX_DPLL_DIV,
 	.min_divider	= 1,
-	.flags		= DPLL_J_TYPE | DPLL_NO_DCO_SEL
 };
 
 
 static struct clk dpll_usb_ck = {
 	.name		= "dpll_usb_ck",
-	.parent		= &dpll_sys_ref_clk,
+	.parent		= &sys_clkin_ck,
 	.dpll_data	= &dpll_usb_dd,
 	.init		= &omap2_init_dpll_parent,
 	.ops		= &clkops_omap3_noncore_dpll_ops,
@@ -1222,7 +1221,7 @@
 static const struct clksel pmd_stm_clock_mux_sel[] = {
 	{ .parent = &sys_clkin_ck, .rates = div_1_0_rates },
 	{ .parent = &dpll_core_m6_ck, .rates = div_1_1_rates },
-	{ .parent = &dpll_per_m7_ck, .rates = div_1_2_rates },
+	{ .parent = &tie_low_clock_ck, .rates = div_1_2_rates },
 	{ .parent = NULL },
 };
 
@@ -1240,10 +1239,15 @@
 	.recalc		= &followparent_recalc,
 };
 
+static const struct clksel syc_clk_div_div[] = {
+	{ .parent = &sys_clkin_ck, .rates = div2_1to2_rates },
+	{ .parent = NULL },
+};
+
 static struct clk syc_clk_div_ck = {
 	.name		= "syc_clk_div_ck",
 	.parent		= &sys_clkin_ck,
-	.clksel		= dpll_sys_ref_clk_div,
+	.clksel		= syc_clk_div_div,
 	.clksel_reg	= OMAP4430_CM_ABE_DSS_SYS_CLKSEL,
 	.clksel_mask	= OMAP4430_CLKSEL_0_0_MASK,
 	.ops		= &clkops_null,
@@ -1284,13 +1288,13 @@
 	.recalc		= &followparent_recalc,
 };
 
-static struct clk cust_efuse_fck = {
-	.name		= "cust_efuse_fck",
+static struct clk bandgap_fclk = {
+	.name		= "bandgap_fclk",
 	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_CEFUSE_CEFUSE_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_cefuse_clkdm",
-	.parent		= &sys_clkin_ck,
+	.enable_reg	= OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_BGAP_32K_SHIFT,
+	.clkdm_name	= "l4_wkup_clkdm",
+	.parent		= &sys_32k_ck,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1344,6 +1348,56 @@
 	.clkdm_name	= "abe_clkdm",
 };
 
+static struct clk dsp_fck = {
+	.name		= "dsp_fck",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_TESLA_TESLA_CLKCTRL,
+	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
+	.clkdm_name	= "tesla_clkdm",
+	.parent		= &dpll_iva_m4_ck,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk dss_sys_clk = {
+	.name		= "dss_sys_clk",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_DSS_DSS_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_SYS_CLK_SHIFT,
+	.clkdm_name	= "l3_dss_clkdm",
+	.parent		= &syc_clk_div_ck,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk dss_tv_clk = {
+	.name		= "dss_tv_clk",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_DSS_DSS_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_TV_CLK_SHIFT,
+	.clkdm_name	= "l3_dss_clkdm",
+	.parent		= &extalt_clkin_ck,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk dss_dss_clk = {
+	.name		= "dss_dss_clk",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_DSS_DSS_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_DSSCLK_SHIFT,
+	.clkdm_name	= "l3_dss_clkdm",
+	.parent		= &dpll_per_m5_ck,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk dss_48mhz_clk = {
+	.name		= "dss_48mhz_clk",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_DSS_DSS_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_48MHZ_CLK_SHIFT,
+	.clkdm_name	= "l3_dss_clkdm",
+	.parent		= &func_48mc_fclk,
+	.recalc		= &followparent_recalc,
+};
+
 static struct clk dss_fck = {
 	.name		= "dss_fck",
 	.ops		= &clkops_omap2_dflt,
@@ -1354,18 +1408,18 @@
 	.recalc		= &followparent_recalc,
 };
 
-static struct clk ducati_ick = {
-	.name		= "ducati_ick",
+static struct clk efuse_ctrl_cust_fck = {
+	.name		= "efuse_ctrl_cust_fck",
 	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_DUCATI_DUCATI_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
-	.clkdm_name	= "ducati_clkdm",
-	.parent		= &ducati_clk_mux_ck,
+	.enable_reg	= OMAP4430_CM_CEFUSE_CEFUSE_CLKCTRL,
+	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
+	.clkdm_name	= "l4_cefuse_clkdm",
+	.parent		= &sys_clkin_ck,
 	.recalc		= &followparent_recalc,
 };
 
-static struct clk emif1_ick = {
-	.name		= "emif1_ick",
+static struct clk emif1_fck = {
+	.name		= "emif1_fck",
 	.ops		= &clkops_omap2_dflt,
 	.enable_reg	= OMAP4430_CM_MEMIF_EMIF_1_CLKCTRL,
 	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
@@ -1375,8 +1429,8 @@
 	.recalc		= &followparent_recalc,
 };
 
-static struct clk emif2_ick = {
-	.name		= "emif2_ick",
+static struct clk emif2_fck = {
+	.name		= "emif2_fck",
 	.ops		= &clkops_omap2_dflt,
 	.enable_reg	= OMAP4430_CM_MEMIF_EMIF_2_CLKCTRL,
 	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
@@ -1407,42 +1461,24 @@
 	.clkdm_name	= "iss_clkdm",
 };
 
-static const struct clksel per_sgx_fclk_div[] = {
-	{ .parent = &dpll_per_m2x2_ck, .rates = div3_1to4_rates },
-	{ .parent = NULL },
-};
-
-static struct clk per_sgx_fclk = {
-	.name		= "per_sgx_fclk",
-	.parent		= &dpll_per_m2x2_ck,
-	.clksel		= per_sgx_fclk_div,
-	.clksel_reg	= OMAP4430_CM_GFX_GFX_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_PER_192M_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static const struct clksel sgx_clk_mux_sel[] = {
-	{ .parent = &dpll_core_m7_ck, .rates = div_1_0_rates },
-	{ .parent = &per_sgx_fclk, .rates = div_1_1_rates },
-	{ .parent = NULL },
-};
-
-/* Merged sgx_clk_mux into gfx */
-static struct clk gfx_fck = {
-	.name		= "gfx_fck",
-	.parent		= &dpll_core_m7_ck,
-	.clksel		= sgx_clk_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_GFX_GFX_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_SGX_FCLK_MASK,
+static struct clk fpka_fck = {
+	.name		= "fpka_fck",
 	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM_GFX_GFX_CLKCTRL,
+	.enable_reg	= OMAP4430_CM_L4SEC_PKAEIP29_CLKCTRL,
 	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l3_gfx_clkdm",
+	.clkdm_name	= "l4_secure_clkdm",
+	.parent		= &l4_div_ck,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk gpio1_dbclk = {
+	.name		= "gpio1_dbclk",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_WKUP_GPIO1_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
+	.clkdm_name	= "l4_wkup_clkdm",
+	.parent		= &sys_32k_ck,
+	.recalc		= &followparent_recalc,
 };
 
 static struct clk gpio1_ick = {
@@ -1455,6 +1491,16 @@
 	.recalc		= &followparent_recalc,
 };
 
+static struct clk gpio2_dbclk = {
+	.name		= "gpio2_dbclk",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_L4PER_GPIO2_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
+	.clkdm_name	= "l4_per_clkdm",
+	.parent		= &sys_32k_ck,
+	.recalc		= &followparent_recalc,
+};
+
 static struct clk gpio2_ick = {
 	.name		= "gpio2_ick",
 	.ops		= &clkops_omap2_dflt,
@@ -1465,6 +1511,16 @@
 	.recalc		= &followparent_recalc,
 };
 
+static struct clk gpio3_dbclk = {
+	.name		= "gpio3_dbclk",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_L4PER_GPIO3_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
+	.clkdm_name	= "l4_per_clkdm",
+	.parent		= &sys_32k_ck,
+	.recalc		= &followparent_recalc,
+};
+
 static struct clk gpio3_ick = {
 	.name		= "gpio3_ick",
 	.ops		= &clkops_omap2_dflt,
@@ -1475,6 +1531,16 @@
 	.recalc		= &followparent_recalc,
 };
 
+static struct clk gpio4_dbclk = {
+	.name		= "gpio4_dbclk",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_L4PER_GPIO4_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
+	.clkdm_name	= "l4_per_clkdm",
+	.parent		= &sys_32k_ck,
+	.recalc		= &followparent_recalc,
+};
+
 static struct clk gpio4_ick = {
 	.name		= "gpio4_ick",
 	.ops		= &clkops_omap2_dflt,
@@ -1485,6 +1551,16 @@
 	.recalc		= &followparent_recalc,
 };
 
+static struct clk gpio5_dbclk = {
+	.name		= "gpio5_dbclk",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_L4PER_GPIO5_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
+	.clkdm_name	= "l4_per_clkdm",
+	.parent		= &sys_32k_ck,
+	.recalc		= &followparent_recalc,
+};
+
 static struct clk gpio5_ick = {
 	.name		= "gpio5_ick",
 	.ops		= &clkops_omap2_dflt,
@@ -1495,6 +1571,16 @@
 	.recalc		= &followparent_recalc,
 };
 
+static struct clk gpio6_dbclk = {
+	.name		= "gpio6_dbclk",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_L4PER_GPIO6_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
+	.clkdm_name	= "l4_per_clkdm",
+	.parent		= &sys_32k_ck,
+	.recalc		= &followparent_recalc,
+};
+
 static struct clk gpio6_ick = {
 	.name		= "gpio6_ick",
 	.ops		= &clkops_omap2_dflt,
@@ -1515,214 +1601,25 @@
 	.recalc		= &followparent_recalc,
 };
 
-static const struct clksel dmt1_clk_mux_sel[] = {
-	{ .parent = &sys_clkin_ck, .rates = div_1_0_rates },
-	{ .parent = &sys_32k_ck, .rates = div_1_1_rates },
+static const struct clksel sgx_clk_mux_sel[] = {
+	{ .parent = &dpll_core_m7_ck, .rates = div_1_0_rates },
+	{ .parent = &dpll_per_m7_ck, .rates = div_1_1_rates },
 	{ .parent = NULL },
 };
 
-/*
- * Merged dmt1_clk_mux into gptimer1
- * gptimer1 renamed temporarily into gpt1 to match OMAP3 convention
- */
-static struct clk gpt1_fck = {
-	.name		= "gpt1_fck",
-	.parent		= &sys_clkin_ck,
-	.clksel		= dmt1_clk_mux_sel,
+/* Merged sgx_clk_mux into gpu */
+static struct clk gpu_fck = {
+	.name		= "gpu_fck",
+	.parent		= &dpll_core_m7_ck,
+	.clksel		= sgx_clk_mux_sel,
 	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_WKUP_TIMER1_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_MASK,
+	.clksel_reg	= OMAP4430_CM_GFX_GFX_CLKCTRL,
+	.clksel_mask	= OMAP4430_CLKSEL_SGX_FCLK_MASK,
 	.ops		= &clkops_omap2_dflt,
 	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM_WKUP_TIMER1_CLKCTRL,
+	.enable_reg	= OMAP4430_CM_GFX_GFX_CLKCTRL,
 	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_wkup_clkdm",
-};
-
-/*
- * Merged cm2_dm10_mux into gptimer10
- * gptimer10 renamed temporarily into gpt10 to match OMAP3 convention
- */
-static struct clk gpt10_fck = {
-	.name		= "gpt10_fck",
-	.parent		= &sys_clkin_ck,
-	.clksel		= dmt1_clk_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-};
-
-/*
- * Merged cm2_dm11_mux into gptimer11
- * gptimer11 renamed temporarily into gpt11 to match OMAP3 convention
- */
-static struct clk gpt11_fck = {
-	.name		= "gpt11_fck",
-	.parent		= &sys_clkin_ck,
-	.clksel		= dmt1_clk_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-};
-
-/*
- * Merged cm2_dm2_mux into gptimer2
- * gptimer2 renamed temporarily into gpt2 to match OMAP3 convention
- */
-static struct clk gpt2_fck = {
-	.name		= "gpt2_fck",
-	.parent		= &sys_clkin_ck,
-	.clksel		= dmt1_clk_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-};
-
-/*
- * Merged cm2_dm3_mux into gptimer3
- * gptimer3 renamed temporarily into gpt3 to match OMAP3 convention
- */
-static struct clk gpt3_fck = {
-	.name		= "gpt3_fck",
-	.parent		= &sys_clkin_ck,
-	.clksel		= dmt1_clk_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-};
-
-/*
- * Merged cm2_dm4_mux into gptimer4
- * gptimer4 renamed temporarily into gpt4 to match OMAP3 convention
- */
-static struct clk gpt4_fck = {
-	.name		= "gpt4_fck",
-	.parent		= &sys_clkin_ck,
-	.clksel		= dmt1_clk_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
-};
-
-static const struct clksel timer5_sync_mux_sel[] = {
-	{ .parent = &syc_clk_div_ck, .rates = div_1_0_rates },
-	{ .parent = &sys_32k_ck, .rates = div_1_1_rates },
-	{ .parent = NULL },
-};
-
-/*
- * Merged timer5_sync_mux into gptimer5
- * gptimer5 renamed temporarily into gpt5 to match OMAP3 convention
- */
-static struct clk gpt5_fck = {
-	.name		= "gpt5_fck",
-	.parent		= &syc_clk_div_ck,
-	.clksel		= timer5_sync_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "abe_clkdm",
-};
-
-/*
- * Merged timer6_sync_mux into gptimer6
- * gptimer6 renamed temporarily into gpt6 to match OMAP3 convention
- */
-static struct clk gpt6_fck = {
-	.name		= "gpt6_fck",
-	.parent		= &syc_clk_div_ck,
-	.clksel		= timer5_sync_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "abe_clkdm",
-};
-
-/*
- * Merged timer7_sync_mux into gptimer7
- * gptimer7 renamed temporarily into gpt7 to match OMAP3 convention
- */
-static struct clk gpt7_fck = {
-	.name		= "gpt7_fck",
-	.parent		= &syc_clk_div_ck,
-	.clksel		= timer5_sync_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "abe_clkdm",
-};
-
-/*
- * Merged timer8_sync_mux into gptimer8
- * gptimer8 renamed temporarily into gpt8 to match OMAP3 convention
- */
-static struct clk gpt8_fck = {
-	.name		= "gpt8_fck",
-	.parent		= &syc_clk_div_ck,
-	.clksel		= timer5_sync_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "abe_clkdm",
-};
-
-/*
- * Merged cm2_dm9_mux into gptimer9
- * gptimer9 renamed temporarily into gpt9 to match OMAP3 convention
- */
-static struct clk gpt9_fck = {
-	.name		= "gpt9_fck",
-	.parent		= &sys_clkin_ck,
-	.clksel		= dmt1_clk_mux_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_MASK,
-	.ops		= &clkops_omap2_dflt,
-	.recalc		= &omap2_clksel_recalc,
-	.enable_reg	= OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_per_clkdm",
+	.clkdm_name	= "l3_gfx_clkdm",
 };
 
 static struct clk hdq1w_fck = {
@@ -1735,11 +1632,16 @@
 	.recalc		= &followparent_recalc,
 };
 
+static const struct clksel hsi_fclk_div[] = {
+	{ .parent = &dpll_per_m2x2_ck, .rates = div3_1to4_rates },
+	{ .parent = NULL },
+};
+
 /* Merged hsi_fclk into hsi */
-static struct clk hsi_ick = {
-	.name		= "hsi_ick",
+static struct clk hsi_fck = {
+	.name		= "hsi_fck",
 	.parent		= &dpll_per_m2x2_ck,
-	.clksel		= per_sgx_fclk_div,
+	.clksel		= hsi_fclk_div,
 	.clksel_reg	= OMAP4430_CM_L3INIT_HSI_CLKCTRL,
 	.clksel_mask	= OMAP4430_CLKSEL_24_25_MASK,
 	.ops		= &clkops_omap2_dflt,
@@ -1791,6 +1693,26 @@
 	.recalc		= &followparent_recalc,
 };
 
+static struct clk ipu_fck = {
+	.name		= "ipu_fck",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_DUCATI_DUCATI_CLKCTRL,
+	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
+	.clkdm_name	= "ducati_clkdm",
+	.parent		= &ducati_clk_mux_ck,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk iss_ctrlclk = {
+	.name		= "iss_ctrlclk",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_CAM_ISS_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_CTRLCLK_SHIFT,
+	.clkdm_name	= "iss_clkdm",
+	.parent		= &func_96m_fclk,
+	.recalc		= &followparent_recalc,
+};
+
 static struct clk iss_fck = {
 	.name		= "iss_fck",
 	.ops		= &clkops_omap2_dflt,
@@ -1801,8 +1723,8 @@
 	.recalc		= &followparent_recalc,
 };
 
-static struct clk ivahd_ick = {
-	.name		= "ivahd_ick",
+static struct clk iva_fck = {
+	.name		= "iva_fck",
 	.ops		= &clkops_omap2_dflt,
 	.enable_reg	= OMAP4430_CM_IVAHD_IVAHD_CLKCTRL,
 	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
@@ -1811,8 +1733,8 @@
 	.recalc		= &followparent_recalc,
 };
 
-static struct clk keyboard_fck = {
-	.name		= "keyboard_fck",
+static struct clk kbd_fck = {
+	.name		= "kbd_fck",
 	.ops		= &clkops_omap2_dflt,
 	.enable_reg	= OMAP4430_CM_WKUP_KEYBOARD_CLKCTRL,
 	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
@@ -1821,8 +1743,8 @@
 	.recalc		= &followparent_recalc,
 };
 
-static struct clk l3_instr_interconnect_ick = {
-	.name		= "l3_instr_interconnect_ick",
+static struct clk l3_instr_ick = {
+	.name		= "l3_instr_ick",
 	.ops		= &clkops_omap2_dflt,
 	.enable_reg	= OMAP4430_CM_L3INSTR_L3_INSTR_CLKCTRL,
 	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
@@ -1831,8 +1753,8 @@
 	.recalc		= &followparent_recalc,
 };
 
-static struct clk l3_interconnect_3_ick = {
-	.name		= "l3_interconnect_3_ick",
+static struct clk l3_main_3_ick = {
+	.name		= "l3_main_3_ick",
 	.ops		= &clkops_omap2_dflt,
 	.enable_reg	= OMAP4430_CM_L3INSTR_L3_3_CLKCTRL,
 	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
@@ -2005,6 +1927,16 @@
 	.clkdm_name	= "l4_per_clkdm",
 };
 
+static struct clk mcpdm_fck = {
+	.name		= "mcpdm_fck",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM1_ABE_PDM_CLKCTRL,
+	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
+	.clkdm_name	= "abe_clkdm",
+	.parent		= &pad_clks_ck,
+	.recalc		= &followparent_recalc,
+};
+
 static struct clk mcspi1_fck = {
 	.name		= "mcspi1_fck",
 	.ops		= &clkops_omap2_dflt,
@@ -2105,8 +2037,28 @@
 	.recalc		= &followparent_recalc,
 };
 
-static struct clk ocp_wp1_ick = {
-	.name		= "ocp_wp1_ick",
+static struct clk ocp2scp_usb_phy_phy_48m = {
+	.name		= "ocp2scp_usb_phy_phy_48m",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_PHY_48M_SHIFT,
+	.clkdm_name	= "l3_init_clkdm",
+	.parent		= &func_48m_fclk,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk ocp2scp_usb_phy_ick = {
+	.name		= "ocp2scp_usb_phy_ick",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL,
+	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
+	.clkdm_name	= "l3_init_clkdm",
+	.parent		= &l4_div_ck,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk ocp_wp_noc_ick = {
+	.name		= "ocp_wp_noc_ick",
 	.ops		= &clkops_omap2_dflt,
 	.enable_reg	= OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL,
 	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
@@ -2115,26 +2067,6 @@
 	.recalc		= &followparent_recalc,
 };
 
-static struct clk pdm_fck = {
-	.name		= "pdm_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM1_ABE_PDM_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "abe_clkdm",
-	.parent		= &pad_clks_ck,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk pkaeip29_fck = {
-	.name		= "pkaeip29_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L4SEC_PKAEIP29_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_secure_clkdm",
-	.parent		= &l4_div_ck,
-	.recalc		= &followparent_recalc,
-};
-
 static struct clk rng_ick = {
 	.name		= "rng_ick",
 	.ops		= &clkops_omap2_dflt,
@@ -2145,8 +2077,8 @@
 	.recalc		= &followparent_recalc,
 };
 
-static struct clk sha2md51_fck = {
-	.name		= "sha2md51_fck",
+static struct clk sha2md5_fck = {
+	.name		= "sha2md5_fck",
 	.ops		= &clkops_omap2_dflt,
 	.enable_reg	= OMAP4430_CM_L4SEC_SHA2MD51_CLKCTRL,
 	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
@@ -2155,8 +2087,8 @@
 	.recalc		= &followparent_recalc,
 };
 
-static struct clk sl2_ick = {
-	.name		= "sl2_ick",
+static struct clk sl2if_ick = {
+	.name		= "sl2if_ick",
 	.ops		= &clkops_omap2_dflt,
 	.enable_reg	= OMAP4430_CM_IVAHD_SL2_CLKCTRL,
 	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
@@ -2165,6 +2097,46 @@
 	.recalc		= &followparent_recalc,
 };
 
+static struct clk slimbus1_fclk_1 = {
+	.name		= "slimbus1_fclk_1",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_FCLK1_SHIFT,
+	.clkdm_name	= "abe_clkdm",
+	.parent		= &func_24m_clk,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk slimbus1_fclk_0 = {
+	.name		= "slimbus1_fclk_0",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_FCLK0_SHIFT,
+	.clkdm_name	= "abe_clkdm",
+	.parent		= &abe_24m_fclk,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk slimbus1_fclk_2 = {
+	.name		= "slimbus1_fclk_2",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_FCLK2_SHIFT,
+	.clkdm_name	= "abe_clkdm",
+	.parent		= &pad_clks_ck,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk slimbus1_slimbus_clk = {
+	.name		= "slimbus1_slimbus_clk",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_SLIMBUS_CLK_11_11_SHIFT,
+	.clkdm_name	= "abe_clkdm",
+	.parent		= &slimbus_clk,
+	.recalc		= &followparent_recalc,
+};
+
 static struct clk slimbus1_fck = {
 	.name		= "slimbus1_fck",
 	.ops		= &clkops_omap2_dflt,
@@ -2175,6 +2147,36 @@
 	.recalc		= &followparent_recalc,
 };
 
+static struct clk slimbus2_fclk_1 = {
+	.name		= "slimbus2_fclk_1",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_PERABE24M_GFCLK_SHIFT,
+	.clkdm_name	= "l4_per_clkdm",
+	.parent		= &per_abe_24m_fclk,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk slimbus2_fclk_0 = {
+	.name		= "slimbus2_fclk_0",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_PER24MC_GFCLK_SHIFT,
+	.clkdm_name	= "l4_per_clkdm",
+	.parent		= &func_24mc_fclk,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk slimbus2_slimbus_clk = {
+	.name		= "slimbus2_slimbus_clk",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_SLIMBUS_CLK_SHIFT,
+	.clkdm_name	= "l4_per_clkdm",
+	.parent		= &pad_slimbus_core_clks_ck,
+	.recalc		= &followparent_recalc,
+};
+
 static struct clk slimbus2_fck = {
 	.name		= "slimbus2_fck",
 	.ops		= &clkops_omap2_dflt,
@@ -2185,8 +2187,8 @@
 	.recalc		= &followparent_recalc,
 };
 
-static struct clk sr_core_fck = {
-	.name		= "sr_core_fck",
+static struct clk smartreflex_core_fck = {
+	.name		= "smartreflex_core_fck",
 	.ops		= &clkops_omap2_dflt,
 	.enable_reg	= OMAP4430_CM_ALWON_SR_CORE_CLKCTRL,
 	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
@@ -2195,8 +2197,8 @@
 	.recalc		= &followparent_recalc,
 };
 
-static struct clk sr_iva_fck = {
-	.name		= "sr_iva_fck",
+static struct clk smartreflex_iva_fck = {
+	.name		= "smartreflex_iva_fck",
 	.ops		= &clkops_omap2_dflt,
 	.enable_reg	= OMAP4430_CM_ALWON_SR_IVA_CLKCTRL,
 	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
@@ -2205,8 +2207,8 @@
 	.recalc		= &followparent_recalc,
 };
 
-static struct clk sr_mpu_fck = {
-	.name		= "sr_mpu_fck",
+static struct clk smartreflex_mpu_fck = {
+	.name		= "smartreflex_mpu_fck",
 	.ops		= &clkops_omap2_dflt,
 	.enable_reg	= OMAP4430_CM_ALWON_SR_MPU_CLKCTRL,
 	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
@@ -2215,14 +2217,175 @@
 	.recalc		= &followparent_recalc,
 };
 
-static struct clk tesla_ick = {
-	.name		= "tesla_ick",
+/* Merged dmt1_clk_mux into timer1 */
+static struct clk timer1_fck = {
+	.name		= "timer1_fck",
+	.parent		= &sys_clkin_ck,
+	.clksel		= abe_dpll_bypass_clk_mux_sel,
+	.init		= &omap2_init_clksel_parent,
+	.clksel_reg	= OMAP4430_CM_WKUP_TIMER1_CLKCTRL,
+	.clksel_mask	= OMAP4430_CLKSEL_MASK,
 	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_TESLA_TESLA_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
-	.clkdm_name	= "tesla_clkdm",
-	.parent		= &dpll_iva_m4_ck,
-	.recalc		= &followparent_recalc,
+	.recalc		= &omap2_clksel_recalc,
+	.enable_reg	= OMAP4430_CM_WKUP_TIMER1_CLKCTRL,
+	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
+	.clkdm_name	= "l4_wkup_clkdm",
+};
+
+/* Merged cm2_dm10_mux into timer10 */
+static struct clk timer10_fck = {
+	.name		= "timer10_fck",
+	.parent		= &sys_clkin_ck,
+	.clksel		= abe_dpll_bypass_clk_mux_sel,
+	.init		= &omap2_init_clksel_parent,
+	.clksel_reg	= OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
+	.clksel_mask	= OMAP4430_CLKSEL_MASK,
+	.ops		= &clkops_omap2_dflt,
+	.recalc		= &omap2_clksel_recalc,
+	.enable_reg	= OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
+	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
+	.clkdm_name	= "l4_per_clkdm",
+};
+
+/* Merged cm2_dm11_mux into timer11 */
+static struct clk timer11_fck = {
+	.name		= "timer11_fck",
+	.parent		= &sys_clkin_ck,
+	.clksel		= abe_dpll_bypass_clk_mux_sel,
+	.init		= &omap2_init_clksel_parent,
+	.clksel_reg	= OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
+	.clksel_mask	= OMAP4430_CLKSEL_MASK,
+	.ops		= &clkops_omap2_dflt,
+	.recalc		= &omap2_clksel_recalc,
+	.enable_reg	= OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
+	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
+	.clkdm_name	= "l4_per_clkdm",
+};
+
+/* Merged cm2_dm2_mux into timer2 */
+static struct clk timer2_fck = {
+	.name		= "timer2_fck",
+	.parent		= &sys_clkin_ck,
+	.clksel		= abe_dpll_bypass_clk_mux_sel,
+	.init		= &omap2_init_clksel_parent,
+	.clksel_reg	= OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
+	.clksel_mask	= OMAP4430_CLKSEL_MASK,
+	.ops		= &clkops_omap2_dflt,
+	.recalc		= &omap2_clksel_recalc,
+	.enable_reg	= OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
+	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
+	.clkdm_name	= "l4_per_clkdm",
+};
+
+/* Merged cm2_dm3_mux into timer3 */
+static struct clk timer3_fck = {
+	.name		= "timer3_fck",
+	.parent		= &sys_clkin_ck,
+	.clksel		= abe_dpll_bypass_clk_mux_sel,
+	.init		= &omap2_init_clksel_parent,
+	.clksel_reg	= OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
+	.clksel_mask	= OMAP4430_CLKSEL_MASK,
+	.ops		= &clkops_omap2_dflt,
+	.recalc		= &omap2_clksel_recalc,
+	.enable_reg	= OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
+	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
+	.clkdm_name	= "l4_per_clkdm",
+};
+
+/* Merged cm2_dm4_mux into timer4 */
+static struct clk timer4_fck = {
+	.name		= "timer4_fck",
+	.parent		= &sys_clkin_ck,
+	.clksel		= abe_dpll_bypass_clk_mux_sel,
+	.init		= &omap2_init_clksel_parent,
+	.clksel_reg	= OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
+	.clksel_mask	= OMAP4430_CLKSEL_MASK,
+	.ops		= &clkops_omap2_dflt,
+	.recalc		= &omap2_clksel_recalc,
+	.enable_reg	= OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
+	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
+	.clkdm_name	= "l4_per_clkdm",
+};
+
+static const struct clksel timer5_sync_mux_sel[] = {
+	{ .parent = &syc_clk_div_ck, .rates = div_1_0_rates },
+	{ .parent = &sys_32k_ck, .rates = div_1_1_rates },
+	{ .parent = NULL },
+};
+
+/* Merged timer5_sync_mux into timer5 */
+static struct clk timer5_fck = {
+	.name		= "timer5_fck",
+	.parent		= &syc_clk_div_ck,
+	.clksel		= timer5_sync_mux_sel,
+	.init		= &omap2_init_clksel_parent,
+	.clksel_reg	= OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
+	.clksel_mask	= OMAP4430_CLKSEL_MASK,
+	.ops		= &clkops_omap2_dflt,
+	.recalc		= &omap2_clksel_recalc,
+	.enable_reg	= OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
+	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
+	.clkdm_name	= "abe_clkdm",
+};
+
+/* Merged timer6_sync_mux into timer6 */
+static struct clk timer6_fck = {
+	.name		= "timer6_fck",
+	.parent		= &syc_clk_div_ck,
+	.clksel		= timer5_sync_mux_sel,
+	.init		= &omap2_init_clksel_parent,
+	.clksel_reg	= OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
+	.clksel_mask	= OMAP4430_CLKSEL_MASK,
+	.ops		= &clkops_omap2_dflt,
+	.recalc		= &omap2_clksel_recalc,
+	.enable_reg	= OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
+	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
+	.clkdm_name	= "abe_clkdm",
+};
+
+/* Merged timer7_sync_mux into timer7 */
+static struct clk timer7_fck = {
+	.name		= "timer7_fck",
+	.parent		= &syc_clk_div_ck,
+	.clksel		= timer5_sync_mux_sel,
+	.init		= &omap2_init_clksel_parent,
+	.clksel_reg	= OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
+	.clksel_mask	= OMAP4430_CLKSEL_MASK,
+	.ops		= &clkops_omap2_dflt,
+	.recalc		= &omap2_clksel_recalc,
+	.enable_reg	= OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
+	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
+	.clkdm_name	= "abe_clkdm",
+};
+
+/* Merged timer8_sync_mux into timer8 */
+static struct clk timer8_fck = {
+	.name		= "timer8_fck",
+	.parent		= &syc_clk_div_ck,
+	.clksel		= timer5_sync_mux_sel,
+	.init		= &omap2_init_clksel_parent,
+	.clksel_reg	= OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
+	.clksel_mask	= OMAP4430_CLKSEL_MASK,
+	.ops		= &clkops_omap2_dflt,
+	.recalc		= &omap2_clksel_recalc,
+	.enable_reg	= OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
+	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
+	.clkdm_name	= "abe_clkdm",
+};
+
+/* Merged cm2_dm9_mux into timer9 */
+static struct clk timer9_fck = {
+	.name		= "timer9_fck",
+	.parent		= &sys_clkin_ck,
+	.clksel		= abe_dpll_bypass_clk_mux_sel,
+	.init		= &omap2_init_clksel_parent,
+	.clksel_reg	= OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
+	.clksel_mask	= OMAP4430_CLKSEL_MASK,
+	.ops		= &clkops_omap2_dflt,
+	.recalc		= &omap2_clksel_recalc,
+	.enable_reg	= OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
+	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
+	.clkdm_name	= "l4_per_clkdm",
 };
 
 static struct clk uart1_fck = {
@@ -2265,26 +2428,6 @@
 	.recalc		= &followparent_recalc,
 };
 
-static struct clk unipro1_fck = {
-	.name		= "unipro1_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L3INIT_UNIPRO1_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l3_init_clkdm",
-	.parent		= &func_96m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk usb_host_fck = {
-	.name		= "usb_host_fck",
-	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l3_init_clkdm",
-	.parent		= &init_60m_fclk,
-	.recalc		= &followparent_recalc,
-};
-
 static struct clk usb_host_fs_fck = {
 	.name		= "usb_host_fs_fck",
 	.ops		= &clkops_omap2_dflt,
@@ -2295,75 +2438,138 @@
 	.recalc		= &followparent_recalc,
 };
 
-static struct clk usb_otg_ick = {
-	.name		= "usb_otg_ick",
+static struct clk usb_host_hs_utmi_p3_clk = {
+	.name		= "usb_host_hs_utmi_p3_clk",
 	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
+	.enable_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_UTMI_P3_CLK_SHIFT,
 	.clkdm_name	= "l3_init_clkdm",
-	.parent		= &l3_div_ck,
+	.parent		= &init_60m_fclk,
 	.recalc		= &followparent_recalc,
 };
 
-static struct clk usb_tll_ick = {
-	.name		= "usb_tll_ick",
+static struct clk usb_host_hs_hsic60m_p1_clk = {
+	.name		= "usb_host_hs_hsic60m_p1_clk",
 	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
+	.enable_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK_SHIFT,
 	.clkdm_name	= "l3_init_clkdm",
-	.parent		= &l4_div_ck,
+	.parent		= &init_60m_fclk,
 	.recalc		= &followparent_recalc,
 };
 
-static struct clk usbphyocp2scp_ick = {
-	.name		= "usbphyocp2scp_ick",
+static struct clk usb_host_hs_hsic60m_p2_clk = {
+	.name		= "usb_host_hs_hsic60m_p2_clk",
 	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
+	.enable_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK_SHIFT,
 	.clkdm_name	= "l3_init_clkdm",
-	.parent		= &l4_div_ck,
+	.parent		= &init_60m_fclk,
 	.recalc		= &followparent_recalc,
 };
 
-static struct clk usim_fck = {
-	.name		= "usim_fck",
+static const struct clksel utmi_p1_gfclk_sel[] = {
+	{ .parent = &init_60m_fclk, .rates = div_1_0_rates },
+	{ .parent = &xclk60mhsp1_ck, .rates = div_1_1_rates },
+	{ .parent = NULL },
+};
+
+static struct clk utmi_p1_gfclk = {
+	.name		= "utmi_p1_gfclk",
+	.parent		= &init_60m_fclk,
+	.clksel		= utmi_p1_gfclk_sel,
+	.init		= &omap2_init_clksel_parent,
+	.clksel_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+	.clksel_mask	= OMAP4430_CLKSEL_UTMI_P1_MASK,
+	.ops		= &clkops_null,
+	.recalc		= &omap2_clksel_recalc,
+};
+
+static struct clk usb_host_hs_utmi_p1_clk = {
+	.name		= "usb_host_hs_utmi_p1_clk",
 	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_WKUP_USIM_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_wkup_clkdm",
-	.parent		= &sys_32k_ck,
+	.enable_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_UTMI_P1_CLK_SHIFT,
+	.clkdm_name	= "l3_init_clkdm",
+	.parent		= &utmi_p1_gfclk,
 	.recalc		= &followparent_recalc,
 };
 
-static struct clk wdt2_fck = {
-	.name		= "wdt2_fck",
+static const struct clksel utmi_p2_gfclk_sel[] = {
+	{ .parent = &init_60m_fclk, .rates = div_1_0_rates },
+	{ .parent = &xclk60mhsp2_ck, .rates = div_1_1_rates },
+	{ .parent = NULL },
+};
+
+static struct clk utmi_p2_gfclk = {
+	.name		= "utmi_p2_gfclk",
+	.parent		= &init_60m_fclk,
+	.clksel		= utmi_p2_gfclk_sel,
+	.init		= &omap2_init_clksel_parent,
+	.clksel_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+	.clksel_mask	= OMAP4430_CLKSEL_UTMI_P2_MASK,
+	.ops		= &clkops_null,
+	.recalc		= &omap2_clksel_recalc,
+};
+
+static struct clk usb_host_hs_utmi_p2_clk = {
+	.name		= "usb_host_hs_utmi_p2_clk",
 	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM_WKUP_WDT2_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "l4_wkup_clkdm",
-	.parent		= &sys_32k_ck,
+	.enable_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_UTMI_P2_CLK_SHIFT,
+	.clkdm_name	= "l3_init_clkdm",
+	.parent		= &utmi_p2_gfclk,
 	.recalc		= &followparent_recalc,
 };
 
-static struct clk wdt3_fck = {
-	.name		= "wdt3_fck",
+static struct clk usb_host_hs_hsic480m_p1_clk = {
+	.name		= "usb_host_hs_hsic480m_p1_clk",
 	.ops		= &clkops_omap2_dflt,
-	.enable_reg	= OMAP4430_CM1_ABE_WDT3_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
-	.clkdm_name	= "abe_clkdm",
-	.parent		= &sys_32k_ck,
+	.enable_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_HSIC480M_P1_CLK_SHIFT,
+	.clkdm_name	= "l3_init_clkdm",
+	.parent		= &dpll_usb_m2_ck,
 	.recalc		= &followparent_recalc,
 };
 
-/* Remaining optional clocks */
+static struct clk usb_host_hs_hsic480m_p2_clk = {
+	.name		= "usb_host_hs_hsic480m_p2_clk",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_HSIC480M_P2_CLK_SHIFT,
+	.clkdm_name	= "l3_init_clkdm",
+	.parent		= &dpll_usb_m2_ck,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk usb_host_hs_func48mclk = {
+	.name		= "usb_host_hs_func48mclk",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_FUNC48MCLK_SHIFT,
+	.clkdm_name	= "l3_init_clkdm",
+	.parent		= &func_48mc_fclk,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk usb_host_hs_fck = {
+	.name		= "usb_host_hs_fck",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
+	.clkdm_name	= "l3_init_clkdm",
+	.parent		= &init_60m_fclk,
+	.recalc		= &followparent_recalc,
+};
+
 static const struct clksel otg_60m_gfclk_sel[] = {
 	{ .parent = &utmi_phy_clkout_ck, .rates = div_1_0_rates },
 	{ .parent = &xclk60motg_ck, .rates = div_1_1_rates },
 	{ .parent = NULL },
 };
 
-static struct clk otg_60m_gfclk_ck = {
-	.name		= "otg_60m_gfclk_ck",
+static struct clk otg_60m_gfclk = {
+	.name		= "otg_60m_gfclk",
 	.parent		= &utmi_phy_clkout_ck,
 	.clksel		= otg_60m_gfclk_sel,
 	.init		= &omap2_init_clksel_parent,
@@ -2373,6 +2579,140 @@
 	.recalc		= &omap2_clksel_recalc,
 };
 
+static struct clk usb_otg_hs_xclk = {
+	.name		= "usb_otg_hs_xclk",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_XCLK_SHIFT,
+	.clkdm_name	= "l3_init_clkdm",
+	.parent		= &otg_60m_gfclk,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk usb_otg_hs_ick = {
+	.name		= "usb_otg_hs_ick",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL,
+	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
+	.clkdm_name	= "l3_init_clkdm",
+	.parent		= &l3_div_ck,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk usb_phy_cm_clk32k = {
+	.name		= "usb_phy_cm_clk32k",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_ALWON_USBPHY_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_CLK32K_SHIFT,
+	.clkdm_name	= "l4_ao_clkdm",
+	.parent		= &sys_32k_ck,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk usb_tll_hs_usb_ch2_clk = {
+	.name		= "usb_tll_hs_usb_ch2_clk",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_USB_CH2_CLK_SHIFT,
+	.clkdm_name	= "l3_init_clkdm",
+	.parent		= &init_60m_fclk,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk usb_tll_hs_usb_ch0_clk = {
+	.name		= "usb_tll_hs_usb_ch0_clk",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_USB_CH0_CLK_SHIFT,
+	.clkdm_name	= "l3_init_clkdm",
+	.parent		= &init_60m_fclk,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk usb_tll_hs_usb_ch1_clk = {
+	.name		= "usb_tll_hs_usb_ch1_clk",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_USB_CH1_CLK_SHIFT,
+	.clkdm_name	= "l3_init_clkdm",
+	.parent		= &init_60m_fclk,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk usb_tll_hs_ick = {
+	.name		= "usb_tll_hs_ick",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
+	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
+	.clkdm_name	= "l3_init_clkdm",
+	.parent		= &l4_div_ck,
+	.recalc		= &followparent_recalc,
+};
+
+static const struct clksel_rate div2_14to18_rates[] = {
+	{ .div = 14, .val = 0, .flags = RATE_IN_4430 },
+	{ .div = 18, .val = 1, .flags = RATE_IN_4430 },
+	{ .div = 0 },
+};
+
+static const struct clksel usim_fclk_div[] = {
+	{ .parent = &dpll_per_m4_ck, .rates = div2_14to18_rates },
+	{ .parent = NULL },
+};
+
+static struct clk usim_ck = {
+	.name		= "usim_ck",
+	.parent		= &dpll_per_m4_ck,
+	.clksel		= usim_fclk_div,
+	.clksel_reg	= OMAP4430_CM_WKUP_USIM_CLKCTRL,
+	.clksel_mask	= OMAP4430_CLKSEL_DIV_MASK,
+	.ops		= &clkops_null,
+	.recalc		= &omap2_clksel_recalc,
+	.round_rate	= &omap2_clksel_round_rate,
+	.set_rate	= &omap2_clksel_set_rate,
+};
+
+static struct clk usim_fclk = {
+	.name		= "usim_fclk",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_WKUP_USIM_CLKCTRL,
+	.enable_bit	= OMAP4430_OPTFCLKEN_FCLK_SHIFT,
+	.clkdm_name	= "l4_wkup_clkdm",
+	.parent		= &usim_ck,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk usim_fck = {
+	.name		= "usim_fck",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_WKUP_USIM_CLKCTRL,
+	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL,
+	.clkdm_name	= "l4_wkup_clkdm",
+	.parent		= &sys_32k_ck,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk wd_timer2_fck = {
+	.name		= "wd_timer2_fck",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM_WKUP_WDT2_CLKCTRL,
+	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
+	.clkdm_name	= "l4_wkup_clkdm",
+	.parent		= &sys_32k_ck,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk wd_timer3_fck = {
+	.name		= "wd_timer3_fck",
+	.ops		= &clkops_omap2_dflt,
+	.enable_reg	= OMAP4430_CM1_ABE_WDT3_CLKCTRL,
+	.enable_bit	= OMAP4430_MODULEMODE_SWCTRL,
+	.clkdm_name	= "abe_clkdm",
+	.parent		= &sys_32k_ck,
+	.recalc		= &followparent_recalc,
+};
+
+/* Remaining optional clocks */
 static const struct clksel stm_clk_div_div[] = {
 	{ .parent = &pmd_stm_clock_mux_ck, .rates = div3_1to4_rates },
 	{ .parent = NULL },
@@ -2407,63 +2747,6 @@
 	.set_rate	= &omap2_clksel_set_rate,
 };
 
-static const struct clksel_rate div2_14to18_rates[] = {
-	{ .div = 14, .val = 0, .flags = RATE_IN_4430 },
-	{ .div = 18, .val = 1, .flags = RATE_IN_4430 },
-	{ .div = 0 },
-};
-
-static const struct clksel usim_fclk_div[] = {
-	{ .parent = &dpll_per_m4_ck, .rates = div2_14to18_rates },
-	{ .parent = NULL },
-};
-
-static struct clk usim_fclk = {
-	.name		= "usim_fclk",
-	.parent		= &dpll_per_m4_ck,
-	.clksel		= usim_fclk_div,
-	.clksel_reg	= OMAP4430_CM_WKUP_USIM_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_DIV_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-	.round_rate	= &omap2_clksel_round_rate,
-	.set_rate	= &omap2_clksel_set_rate,
-};
-
-static const struct clksel utmi_p1_gfclk_sel[] = {
-	{ .parent = &init_60m_fclk, .rates = div_1_0_rates },
-	{ .parent = &xclk60mhsp1_ck, .rates = div_1_1_rates },
-	{ .parent = NULL },
-};
-
-static struct clk utmi_p1_gfclk_ck = {
-	.name		= "utmi_p1_gfclk_ck",
-	.parent		= &init_60m_fclk,
-	.clksel		= utmi_p1_gfclk_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_UTMI_P1_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static const struct clksel utmi_p2_gfclk_sel[] = {
-	{ .parent = &init_60m_fclk, .rates = div_1_0_rates },
-	{ .parent = &xclk60mhsp2_ck, .rates = div_1_1_rates },
-	{ .parent = NULL },
-};
-
-static struct clk utmi_p2_gfclk_ck = {
-	.name		= "utmi_p2_gfclk_ck",
-	.parent		= &init_60m_fclk,
-	.clksel		= utmi_p2_gfclk_sel,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-	.clksel_mask	= OMAP4430_CLKSEL_UTMI_P2_MASK,
-	.ops		= &clkops_null,
-	.recalc		= &omap2_clksel_recalc,
-};
-
 /*
  * clkdev
  */
@@ -2483,11 +2766,12 @@
 	CLK(NULL,	"virt_27000000_ck",		&virt_27000000_ck,	CK_443X),
 	CLK(NULL,	"virt_38400000_ck",		&virt_38400000_ck,	CK_443X),
 	CLK(NULL,	"sys_clkin_ck",			&sys_clkin_ck,	CK_443X),
+	CLK(NULL,	"tie_low_clock_ck",		&tie_low_clock_ck,	CK_443X),
 	CLK(NULL,	"utmi_phy_clkout_ck",		&utmi_phy_clkout_ck,	CK_443X),
 	CLK(NULL,	"xclk60mhsp1_ck",		&xclk60mhsp1_ck,	CK_443X),
 	CLK(NULL,	"xclk60mhsp2_ck",		&xclk60mhsp2_ck,	CK_443X),
 	CLK(NULL,	"xclk60motg_ck",		&xclk60motg_ck,	CK_443X),
-	CLK(NULL,	"dpll_sys_ref_clk",		&dpll_sys_ref_clk,	CK_443X),
+	CLK(NULL,	"abe_dpll_bypass_clk_mux_ck",	&abe_dpll_bypass_clk_mux_ck,	CK_443X),
 	CLK(NULL,	"abe_dpll_refclk_mux_ck",	&abe_dpll_refclk_mux_ck,	CK_443X),
 	CLK(NULL,	"dpll_abe_ck",			&dpll_abe_ck,	CK_443X),
 	CLK(NULL,	"dpll_abe_m2x2_ck",		&dpll_abe_m2x2_ck,	CK_443X),
@@ -2557,46 +2841,48 @@
 	CLK(NULL,	"aes1_fck",			&aes1_fck,	CK_443X),
 	CLK(NULL,	"aes2_fck",			&aes2_fck,	CK_443X),
 	CLK(NULL,	"aess_fck",			&aess_fck,	CK_443X),
-	CLK(NULL,	"cust_efuse_fck",		&cust_efuse_fck,	CK_443X),
+	CLK(NULL,	"bandgap_fclk",			&bandgap_fclk,	CK_443X),
 	CLK(NULL,	"des3des_fck",			&des3des_fck,	CK_443X),
 	CLK(NULL,	"dmic_sync_mux_ck",		&dmic_sync_mux_ck,	CK_443X),
 	CLK(NULL,	"dmic_fck",			&dmic_fck,	CK_443X),
+	CLK(NULL,	"dsp_fck",			&dsp_fck,	CK_443X),
+	CLK(NULL,	"dss_sys_clk",			&dss_sys_clk,	CK_443X),
+	CLK(NULL,	"dss_tv_clk",			&dss_tv_clk,	CK_443X),
+	CLK(NULL,	"dss_dss_clk",			&dss_dss_clk,	CK_443X),
+	CLK(NULL,	"dss_48mhz_clk",		&dss_48mhz_clk,	CK_443X),
 	CLK(NULL,	"dss_fck",			&dss_fck,	CK_443X),
-	CLK(NULL,	"ducati_ick",			&ducati_ick,	CK_443X),
-	CLK(NULL,	"emif1_ick",			&emif1_ick,	CK_443X),
-	CLK(NULL,	"emif2_ick",			&emif2_ick,	CK_443X),
+	CLK(NULL,	"efuse_ctrl_cust_fck",		&efuse_ctrl_cust_fck,	CK_443X),
+	CLK(NULL,	"emif1_fck",			&emif1_fck,	CK_443X),
+	CLK(NULL,	"emif2_fck",			&emif2_fck,	CK_443X),
 	CLK(NULL,	"fdif_fck",			&fdif_fck,	CK_443X),
-	CLK(NULL,	"per_sgx_fclk",			&per_sgx_fclk,	CK_443X),
-	CLK(NULL,	"gfx_fck",			&gfx_fck,	CK_443X),
+	CLK(NULL,	"fpka_fck",			&fpka_fck,	CK_443X),
+	CLK(NULL,	"gpio1_dbck",			&gpio1_dbclk,	CK_443X),
 	CLK(NULL,	"gpio1_ick",			&gpio1_ick,	CK_443X),
+	CLK(NULL,	"gpio2_dbck",			&gpio2_dbclk,	CK_443X),
 	CLK(NULL,	"gpio2_ick",			&gpio2_ick,	CK_443X),
+	CLK(NULL,	"gpio3_dbck",			&gpio3_dbclk,	CK_443X),
 	CLK(NULL,	"gpio3_ick",			&gpio3_ick,	CK_443X),
+	CLK(NULL,	"gpio4_dbck",			&gpio4_dbclk,	CK_443X),
 	CLK(NULL,	"gpio4_ick",			&gpio4_ick,	CK_443X),
+	CLK(NULL,	"gpio5_dbck",			&gpio5_dbclk,	CK_443X),
 	CLK(NULL,	"gpio5_ick",			&gpio5_ick,	CK_443X),
+	CLK(NULL,	"gpio6_dbck",			&gpio6_dbclk,	CK_443X),
 	CLK(NULL,	"gpio6_ick",			&gpio6_ick,	CK_443X),
 	CLK(NULL,	"gpmc_ick",			&gpmc_ick,	CK_443X),
-	CLK(NULL,	"gpt1_fck",			&gpt1_fck,	CK_443X),
-	CLK(NULL,	"gpt10_fck",			&gpt10_fck,	CK_443X),
-	CLK(NULL,	"gpt11_fck",			&gpt11_fck,	CK_443X),
-	CLK(NULL,	"gpt2_fck",			&gpt2_fck,	CK_443X),
-	CLK(NULL,	"gpt3_fck",			&gpt3_fck,	CK_443X),
-	CLK(NULL,	"gpt4_fck",			&gpt4_fck,	CK_443X),
-	CLK(NULL,	"gpt5_fck",			&gpt5_fck,	CK_443X),
-	CLK(NULL,	"gpt6_fck",			&gpt6_fck,	CK_443X),
-	CLK(NULL,	"gpt7_fck",			&gpt7_fck,	CK_443X),
-	CLK(NULL,	"gpt8_fck",			&gpt8_fck,	CK_443X),
-	CLK(NULL,	"gpt9_fck",			&gpt9_fck,	CK_443X),
+	CLK(NULL,	"gpu_fck",			&gpu_fck,	CK_443X),
 	CLK("omap2_hdq.0",	"fck",				&hdq1w_fck,	CK_443X),
-	CLK(NULL,	"hsi_ick",			&hsi_ick,	CK_443X),
+	CLK(NULL,	"hsi_fck",			&hsi_fck,	CK_443X),
 	CLK("i2c_omap.1",	"fck",				&i2c1_fck,	CK_443X),
 	CLK("i2c_omap.2",	"fck",				&i2c2_fck,	CK_443X),
 	CLK("i2c_omap.3",	"fck",				&i2c3_fck,	CK_443X),
 	CLK("i2c_omap.4",	"fck",				&i2c4_fck,	CK_443X),
+	CLK(NULL,	"ipu_fck",			&ipu_fck,	CK_443X),
+	CLK(NULL,	"iss_ctrlclk",			&iss_ctrlclk,	CK_443X),
 	CLK(NULL,	"iss_fck",			&iss_fck,	CK_443X),
-	CLK(NULL,	"ivahd_ick",			&ivahd_ick,	CK_443X),
-	CLK(NULL,	"keyboard_fck",			&keyboard_fck,	CK_443X),
-	CLK(NULL,	"l3_instr_interconnect_ick",	&l3_instr_interconnect_ick,	CK_443X),
-	CLK(NULL,	"l3_interconnect_3_ick",	&l3_interconnect_3_ick,	CK_443X),
+	CLK(NULL,	"iva_fck",			&iva_fck,	CK_443X),
+	CLK(NULL,	"kbd_fck",			&kbd_fck,	CK_443X),
+	CLK(NULL,	"l3_instr_ick",			&l3_instr_ick,	CK_443X),
+	CLK(NULL,	"l3_main_3_ick",		&l3_main_3_ick,	CK_443X),
 	CLK(NULL,	"mcasp_sync_mux_ck",		&mcasp_sync_mux_ck,	CK_443X),
 	CLK(NULL,	"mcasp_fck",			&mcasp_fck,	CK_443X),
 	CLK(NULL,	"mcbsp1_sync_mux_ck",		&mcbsp1_sync_mux_ck,	CK_443X),
@@ -2607,6 +2893,7 @@
 	CLK("omap-mcbsp.3",	"fck",				&mcbsp3_fck,	CK_443X),
 	CLK(NULL,	"mcbsp4_sync_mux_ck",		&mcbsp4_sync_mux_ck,	CK_443X),
 	CLK("omap-mcbsp.4",	"fck",				&mcbsp4_fck,	CK_443X),
+	CLK(NULL,	"mcpdm_fck",			&mcpdm_fck,	CK_443X),
 	CLK("omap2_mcspi.1",	"fck",				&mcspi1_fck,	CK_443X),
 	CLK("omap2_mcspi.2",	"fck",				&mcspi2_fck,	CK_443X),
 	CLK("omap2_mcspi.3",	"fck",				&mcspi3_fck,	CK_443X),
@@ -2616,43 +2903,66 @@
 	CLK("mmci-omap-hs.2",	"fck",				&mmc3_fck,	CK_443X),
 	CLK("mmci-omap-hs.3",	"fck",				&mmc4_fck,	CK_443X),
 	CLK("mmci-omap-hs.4",	"fck",				&mmc5_fck,	CK_443X),
-	CLK(NULL,	"ocp_wp1_ick",			&ocp_wp1_ick,	CK_443X),
-	CLK(NULL,	"pdm_fck",			&pdm_fck,	CK_443X),
-	CLK(NULL,	"pkaeip29_fck",			&pkaeip29_fck,	CK_443X),
+	CLK(NULL,	"ocp2scp_usb_phy_phy_48m",	&ocp2scp_usb_phy_phy_48m,	CK_443X),
+	CLK(NULL,	"ocp2scp_usb_phy_ick",		&ocp2scp_usb_phy_ick,	CK_443X),
+	CLK(NULL,	"ocp_wp_noc_ick",		&ocp_wp_noc_ick,	CK_443X),
 	CLK("omap_rng",	"ick",				&rng_ick,	CK_443X),
-	CLK(NULL,	"sha2md51_fck",			&sha2md51_fck,	CK_443X),
-	CLK(NULL,	"sl2_ick",			&sl2_ick,	CK_443X),
+	CLK(NULL,	"sha2md5_fck",			&sha2md5_fck,	CK_443X),
+	CLK(NULL,	"sl2if_ick",			&sl2if_ick,	CK_443X),
+	CLK(NULL,	"slimbus1_fclk_1",		&slimbus1_fclk_1,	CK_443X),
+	CLK(NULL,	"slimbus1_fclk_0",		&slimbus1_fclk_0,	CK_443X),
+	CLK(NULL,	"slimbus1_fclk_2",		&slimbus1_fclk_2,	CK_443X),
+	CLK(NULL,	"slimbus1_slimbus_clk",		&slimbus1_slimbus_clk,	CK_443X),
 	CLK(NULL,	"slimbus1_fck",			&slimbus1_fck,	CK_443X),
+	CLK(NULL,	"slimbus2_fclk_1",		&slimbus2_fclk_1,	CK_443X),
+	CLK(NULL,	"slimbus2_fclk_0",		&slimbus2_fclk_0,	CK_443X),
+	CLK(NULL,	"slimbus2_slimbus_clk",		&slimbus2_slimbus_clk,	CK_443X),
 	CLK(NULL,	"slimbus2_fck",			&slimbus2_fck,	CK_443X),
-	CLK(NULL,	"sr_core_fck",			&sr_core_fck,	CK_443X),
-	CLK(NULL,	"sr_iva_fck",			&sr_iva_fck,	CK_443X),
-	CLK(NULL,	"sr_mpu_fck",			&sr_mpu_fck,	CK_443X),
-	CLK(NULL,	"tesla_ick",			&tesla_ick,	CK_443X),
+	CLK(NULL,	"smartreflex_core_fck",		&smartreflex_core_fck,	CK_443X),
+	CLK(NULL,	"smartreflex_iva_fck",		&smartreflex_iva_fck,	CK_443X),
+	CLK(NULL,	"smartreflex_mpu_fck",		&smartreflex_mpu_fck,	CK_443X),
+	CLK(NULL,	"gpt1_fck",			&timer1_fck,	CK_443X),
+	CLK(NULL,	"gpt10_fck",			&timer10_fck,	CK_443X),
+	CLK(NULL,	"gpt11_fck",			&timer11_fck,	CK_443X),
+	CLK(NULL,	"gpt2_fck",			&timer2_fck,	CK_443X),
+	CLK(NULL,	"gpt3_fck",			&timer3_fck,	CK_443X),
+	CLK(NULL,	"gpt4_fck",			&timer4_fck,	CK_443X),
+	CLK(NULL,	"gpt5_fck",			&timer5_fck,	CK_443X),
+	CLK(NULL,	"gpt6_fck",			&timer6_fck,	CK_443X),
+	CLK(NULL,	"gpt7_fck",			&timer7_fck,	CK_443X),
+	CLK(NULL,	"gpt8_fck",			&timer8_fck,	CK_443X),
+	CLK(NULL,	"gpt9_fck",			&timer9_fck,	CK_443X),
 	CLK(NULL,	"uart1_fck",			&uart1_fck,	CK_443X),
 	CLK(NULL,	"uart2_fck",			&uart2_fck,	CK_443X),
 	CLK(NULL,	"uart3_fck",			&uart3_fck,	CK_443X),
 	CLK(NULL,	"uart4_fck",			&uart4_fck,	CK_443X),
-	CLK(NULL,	"unipro1_fck",			&unipro1_fck,	CK_443X),
-	CLK(NULL,	"usb_host_fck",			&usb_host_fck,	CK_443X),
 	CLK(NULL,	"usb_host_fs_fck",		&usb_host_fs_fck,	CK_443X),
-	CLK("musb_hdrc",	"ick",				&usb_otg_ick,	CK_443X),
-	CLK(NULL,	"usb_tll_ick",			&usb_tll_ick,	CK_443X),
-	CLK(NULL,	"usbphyocp2scp_ick",		&usbphyocp2scp_ick,	CK_443X),
+	CLK(NULL,	"usb_host_hs_utmi_p3_clk",	&usb_host_hs_utmi_p3_clk,	CK_443X),
+	CLK(NULL,	"usb_host_hs_hsic60m_p1_clk",	&usb_host_hs_hsic60m_p1_clk,	CK_443X),
+	CLK(NULL,	"usb_host_hs_hsic60m_p2_clk",	&usb_host_hs_hsic60m_p2_clk,	CK_443X),
+	CLK(NULL,	"utmi_p1_gfclk",		&utmi_p1_gfclk,	CK_443X),
+	CLK(NULL,	"usb_host_hs_utmi_p1_clk",	&usb_host_hs_utmi_p1_clk,	CK_443X),
+	CLK(NULL,	"utmi_p2_gfclk",		&utmi_p2_gfclk,	CK_443X),
+	CLK(NULL,	"usb_host_hs_utmi_p2_clk",	&usb_host_hs_utmi_p2_clk,	CK_443X),
+	CLK(NULL,	"usb_host_hs_hsic480m_p1_clk",	&usb_host_hs_hsic480m_p1_clk,	CK_443X),
+	CLK(NULL,	"usb_host_hs_hsic480m_p2_clk",	&usb_host_hs_hsic480m_p2_clk,	CK_443X),
+	CLK(NULL,	"usb_host_hs_func48mclk",	&usb_host_hs_func48mclk,	CK_443X),
+	CLK(NULL,	"usb_host_hs_fck",		&usb_host_hs_fck,	CK_443X),
+	CLK(NULL,	"otg_60m_gfclk",		&otg_60m_gfclk,	CK_443X),
+	CLK(NULL,	"usb_otg_hs_xclk",		&usb_otg_hs_xclk,	CK_443X),
+	CLK("musb_hdrc",	"ick",				&usb_otg_hs_ick,	CK_443X),
+	CLK(NULL,	"usb_phy_cm_clk32k",		&usb_phy_cm_clk32k,	CK_443X),
+	CLK(NULL,	"usb_tll_hs_usb_ch2_clk",	&usb_tll_hs_usb_ch2_clk,	CK_443X),
+	CLK(NULL,	"usb_tll_hs_usb_ch0_clk",	&usb_tll_hs_usb_ch0_clk,	CK_443X),
+	CLK(NULL,	"usb_tll_hs_usb_ch1_clk",	&usb_tll_hs_usb_ch1_clk,	CK_443X),
+	CLK(NULL,	"usb_tll_hs_ick",		&usb_tll_hs_ick,	CK_443X),
+	CLK(NULL,	"usim_ck",			&usim_ck,	CK_443X),
+	CLK(NULL,	"usim_fclk",			&usim_fclk,	CK_443X),
 	CLK(NULL,	"usim_fck",			&usim_fck,	CK_443X),
-	CLK("omap_wdt",	"fck",				&wdt2_fck,	CK_443X),
-	CLK(NULL,	"wdt3_fck",			&wdt3_fck,	CK_443X),
-	CLK(NULL,	"otg_60m_gfclk_ck",		&otg_60m_gfclk_ck,	CK_443X),
+	CLK("omap_wdt",	"fck",				&wd_timer2_fck,	CK_443X),
+	CLK(NULL,	"wd_timer3_fck",		&wd_timer3_fck,	CK_443X),
 	CLK(NULL,	"stm_clk_div_ck",		&stm_clk_div_ck,	CK_443X),
 	CLK(NULL,	"trace_clk_div_ck",		&trace_clk_div_ck,	CK_443X),
-	CLK(NULL,	"usim_fclk",			&usim_fclk,	CK_443X),
-	CLK(NULL,	"utmi_p1_gfclk_ck",		&utmi_p1_gfclk_ck,	CK_443X),
-	CLK(NULL,	"utmi_p2_gfclk_ck",		&utmi_p2_gfclk_ck,	CK_443X),
-	CLK(NULL,	"gpio1_dbck",			&dummy_ck,	CK_443X),
-	CLK(NULL,	"gpio2_dbck",			&dummy_ck,	CK_443X),
-	CLK(NULL,	"gpio3_dbck",			&dummy_ck,	CK_443X),
-	CLK(NULL,	"gpio4_dbck",			&dummy_ck,	CK_443X),
-	CLK(NULL,	"gpio5_dbck",			&dummy_ck,	CK_443X),
-	CLK(NULL,	"gpio6_dbck",			&dummy_ck,	CK_443X),
 	CLK(NULL,	"gpmc_ck",			&dummy_ck,	CK_443X),
 	CLK(NULL,	"gpt1_ick",			&dummy_ck,	CK_443X),
 	CLK(NULL,	"gpt2_ick",			&dummy_ck,	CK_443X),
@@ -2669,19 +2979,19 @@
 	CLK("i2c_omap.2",	"ick",				&dummy_ck,	CK_443X),
 	CLK("i2c_omap.3",	"ick",				&dummy_ck,	CK_443X),
 	CLK("i2c_omap.4",	"ick",				&dummy_ck,	CK_443X),
+	CLK("mmci-omap-hs.0",	"ick",				&dummy_ck,	CK_443X),
+	CLK("mmci-omap-hs.1",	"ick",				&dummy_ck,	CK_443X),
+	CLK("mmci-omap-hs.2",	"ick",				&dummy_ck,	CK_443X),
+	CLK("mmci-omap-hs.3",	"ick",				&dummy_ck,	CK_443X),
+	CLK("mmci-omap-hs.4",	"ick",				&dummy_ck,	CK_443X),
 	CLK("omap-mcbsp.1",	"ick",				&dummy_ck,	CK_443X),
 	CLK("omap-mcbsp.2",	"ick",				&dummy_ck,	CK_443X),
 	CLK("omap-mcbsp.3",	"ick",				&dummy_ck,	CK_443X),
 	CLK("omap-mcbsp.4",	"ick",				&dummy_ck,	CK_443X),
-	CLK("omap2_mcspi.1",	"ick",			&dummy_ck,	CK_443X),
-	CLK("omap2_mcspi.2",	"ick",			&dummy_ck,	CK_443X),
-	CLK("omap2_mcspi.3",	"ick",			&dummy_ck,	CK_443X),
-	CLK("omap2_mcspi.4",	"ick",			&dummy_ck,	CK_443X),
-	CLK("mmci-omap-hs.0",	"ick",		&dummy_ck,	CK_443X),
-	CLK("mmci-omap-hs.1",	"ick",		&dummy_ck,	CK_443X),
-	CLK("mmci-omap-hs.2",	"ick",		&dummy_ck,	CK_443X),
-	CLK("mmci-omap-hs.3",	"ick",		&dummy_ck,	CK_443X),
-	CLK("mmci-omap-hs.4",	"ick",		&dummy_ck,	CK_443X),
+	CLK("omap2_mcspi.1",	"ick",				&dummy_ck,	CK_443X),
+	CLK("omap2_mcspi.2",	"ick",				&dummy_ck,	CK_443X),
+	CLK("omap2_mcspi.3",	"ick",				&dummy_ck,	CK_443X),
+	CLK("omap2_mcspi.4",	"ick",				&dummy_ck,	CK_443X),
 	CLK(NULL,	"uart1_ick",			&dummy_ck,	CK_443X),
 	CLK(NULL,	"uart2_ick",			&dummy_ck,	CK_443X),
 	CLK(NULL,	"uart3_ick",			&dummy_ck,	CK_443X),
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 5d80cb8..6fb61b1 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -258,97 +258,6 @@
 
 }
 
-/**
- * _init_wkdep_usecount - initialize wkdep usecounts to match hardware
- * @clkdm: clockdomain to initialize wkdep usecounts
- *
- * Initialize the wakeup dependency usecount variables for clockdomain @clkdm.
- * If a wakeup dependency is present in the hardware, the usecount will be
- * set to 1; otherwise, it will be set to 0.  Software should clear all
- * software wakeup dependencies prior to calling this function if it wishes
- * to ensure that all usecounts start at 0.  No return value.
- */
-static void _init_wkdep_usecount(struct clockdomain *clkdm)
-{
-	u32 v;
-	struct clkdm_dep *cd;
-
-	if (!clkdm->wkdep_srcs)
-		return;
-
-	for (cd = clkdm->wkdep_srcs; 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);
-
-		if (!cd->clkdm) {
-			WARN(!cd->clkdm, "clockdomain: %s: wkdep clkdm %s not "
-			     "found\n", clkdm->name, cd->clkdm_name);
-			continue;
-		}
-
-		v = prm_read_mod_bits_shift(clkdm->pwrdm.ptr->prcm_offs,
-					    PM_WKDEP,
-					    (1 << cd->clkdm->dep_bit));
-
-		if (v)
-			pr_debug("clockdomain: %s: wakeup dependency already "
-				 "set to wake up when %s wakes\n",
-				 clkdm->name, cd->clkdm->name);
-
-		atomic_set(&cd->wkdep_usecount, (v) ? 1 : 0);
-	}
-}
-
-/**
- * _init_sleepdep_usecount - initialize sleepdep usecounts to match hardware
- * @clkdm: clockdomain to initialize sleepdep usecounts
- *
- * Initialize the sleep dependency usecount variables for clockdomain @clkdm.
- * If a sleep dependency is present in the hardware, the usecount will be
- * set to 1; otherwise, it will be set to 0.  Software should clear all
- * software sleep dependencies prior to calling this function if it wishes
- * to ensure that all usecounts start at 0.  No return value.
- */
-static void _init_sleepdep_usecount(struct clockdomain *clkdm)
-{
-	u32 v;
-	struct clkdm_dep *cd;
-
-	if (!cpu_is_omap34xx())
-		return;
-
-	if (!clkdm->sleepdep_srcs)
-		return;
-
-	for (cd = clkdm->sleepdep_srcs; 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);
-
-		if (!cd->clkdm) {
-			WARN(!cd->clkdm, "clockdomain: %s: sleepdep clkdm %s "
-			     "not found\n", clkdm->name, cd->clkdm_name);
-			continue;
-		}
-
-		v = prm_read_mod_bits_shift(clkdm->pwrdm.ptr->prcm_offs,
-					    OMAP3430_CM_SLEEPDEP,
-					    (1 << cd->clkdm->dep_bit));
-
-		if (v)
-			pr_debug("clockdomain: %s: sleep dependency already "
-				 "set to prevent from idling until %s "
-				 "idles\n", clkdm->name, cd->clkdm->name);
-
-		atomic_set(&cd->sleepdep_usecount, (v) ? 1 : 0);
-	}
-};
-
 /* Public functions */
 
 /**
@@ -379,12 +288,17 @@
 			_autodep_lookup(autodep);
 
 	/*
-	 * Ensure that the *dep_usecount registers reflect the current
-	 * state of the PRCM.
+	 * 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) {
-		_init_wkdep_usecount(clkdm);
-		_init_sleepdep_usecount(clkdm);
+		if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
+			omap2_clkdm_wakeup(clkdm);
+		else if (clkdm->flags & CLKDM_CAN_DISABLE_AUTO)
+			omap2_clkdm_deny_idle(clkdm);
+
+		clkdm_clear_all_wkdeps(clkdm);
+		clkdm_clear_all_sleepdeps(clkdm);
 	}
 }
 
@@ -592,6 +506,9 @@
 		if (!omap_chip_is(cd->omap_chip))
 			continue;
 
+		if (!cd->clkdm && cd->clkdm_name)
+			cd->clkdm = _clkdm_lookup(cd->clkdm_name);
+
 		/* PRM accesses are slow, so minimize them */
 		mask |= 1 << cd->clkdm->dep_bit;
 		atomic_set(&cd->wkdep_usecount, 0);
@@ -752,6 +669,9 @@
 		if (!omap_chip_is(cd->omap_chip))
 			continue;
 
+		if (!cd->clkdm && cd->clkdm_name)
+			cd->clkdm = _clkdm_lookup(cd->clkdm_name);
+
 		/* PRM accesses are slow, so minimize them */
 		mask |= 1 << cd->clkdm->dep_bit;
 		atomic_set(&cd->sleepdep_usecount, 0);
diff --git a/arch/arm/mach-omap2/cm-regbits-34xx.h b/arch/arm/mach-omap2/cm-regbits-34xx.h
index fe82b79..4f959a7 100644
--- a/arch/arm/mach-omap2/cm-regbits-34xx.h
+++ b/arch/arm/mach-omap2/cm-regbits-34xx.h
@@ -649,6 +649,8 @@
 #define OMAP3430_ST_MCBSP2_MASK				(1 << 0)
 
 /* CM_AUTOIDLE_PER */
+#define OMAP3630_AUTO_UART4_MASK			(1 << 18)
+#define OMAP3630_AUTO_UART4_SHIFT			18
 #define OMAP3430_AUTO_GPIO6_MASK			(1 << 17)
 #define OMAP3430_AUTO_GPIO6_SHIFT			17
 #define OMAP3430_AUTO_GPIO5_MASK			(1 << 16)
diff --git a/arch/arm/mach-omap2/cm-regbits-44xx.h b/arch/arm/mach-omap2/cm-regbits-44xx.h
index ac8458e..0b72be4 100644
--- a/arch/arm/mach-omap2/cm-regbits-44xx.h
+++ b/arch/arm/mach-omap2/cm-regbits-44xx.h
@@ -1,8 +1,8 @@
 /*
  * OMAP44xx Clock Management register bits
  *
- * Copyright (C) 2009 Texas Instruments, Inc.
- * Copyright (C) 2009 Nokia Corporation
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2009-2010 Nokia Corporation
  *
  * Paul Walmsley (paul@pwsan.com)
  * Rajendra Nayak (rnayak@ti.com)
@@ -25,453 +25,459 @@
 #include "cm.h"
 
 
-/* Used by CM_L3_1_DYNAMICDEP, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP */
+/*
+ * Used by CM_L3_1_DYNAMICDEP, CM_L3_1_DYNAMICDEP_RESTORE, CM_MPU_DYNAMICDEP,
+ * CM_TESLA_DYNAMICDEP
+ */
 #define OMAP4430_ABE_DYNDEP_SHIFT				3
-#define OMAP4430_ABE_DYNDEP_MASK				BITFIELD(3, 3)
+#define OMAP4430_ABE_DYNDEP_MASK				(1 << 3)
 
 /*
- * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP,
- * CM_L3INIT_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_MPU_STATICDEP,
- * CM_TESLA_STATICDEP
+ * Used by CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE, CM_DUCATI_STATICDEP,
+ * CM_L3INIT_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP,
+ * CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
  */
 #define OMAP4430_ABE_STATDEP_SHIFT				3
-#define OMAP4430_ABE_STATDEP_MASK				BITFIELD(3, 3)
+#define OMAP4430_ABE_STATDEP_MASK				(1 << 3)
 
-/* Used by CM_L4CFG_DYNAMICDEP */
+/* Used by CM_L4CFG_DYNAMICDEP, CM_L4CFG_DYNAMICDEP_RESTORE */
 #define OMAP4430_ALWONCORE_DYNDEP_SHIFT				16
-#define OMAP4430_ALWONCORE_DYNDEP_MASK				BITFIELD(16, 16)
+#define OMAP4430_ALWONCORE_DYNDEP_MASK				(1 << 16)
 
 /* Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP, CM_TESLA_STATICDEP */
 #define OMAP4430_ALWONCORE_STATDEP_SHIFT			16
-#define OMAP4430_ALWONCORE_STATDEP_MASK				BITFIELD(16, 16)
+#define OMAP4430_ALWONCORE_STATDEP_MASK				(1 << 16)
 
 /*
- * Used by CM_AUTOIDLE_DPLL_PER, CM_AUTOIDLE_DPLL_UNIPRO, CM_AUTOIDLE_DPLL_USB,
- * CM_AUTOIDLE_DPLL_CORE_RESTORE, CM_AUTOIDLE_DPLL_ABE, CM_AUTOIDLE_DPLL_CORE,
- * CM_AUTOIDLE_DPLL_DDRPHY, CM_AUTOIDLE_DPLL_IVA, CM_AUTOIDLE_DPLL_MPU
+ * Used by CM_AUTOIDLE_DPLL_ABE, CM_AUTOIDLE_DPLL_CORE,
+ * CM_AUTOIDLE_DPLL_CORE_RESTORE, CM_AUTOIDLE_DPLL_DDRPHY,
+ * CM_AUTOIDLE_DPLL_IVA, CM_AUTOIDLE_DPLL_MPU, CM_AUTOIDLE_DPLL_PER,
+ * CM_AUTOIDLE_DPLL_UNIPRO, CM_AUTOIDLE_DPLL_USB
  */
 #define OMAP4430_AUTO_DPLL_MODE_SHIFT				0
-#define OMAP4430_AUTO_DPLL_MODE_MASK				BITFIELD(0, 2)
+#define OMAP4430_AUTO_DPLL_MODE_MASK				(0x7 << 0)
 
-/* Used by CM_L4CFG_DYNAMICDEP */
+/* Used by CM_L4CFG_DYNAMICDEP, CM_L4CFG_DYNAMICDEP_RESTORE */
 #define OMAP4430_CEFUSE_DYNDEP_SHIFT				17
-#define OMAP4430_CEFUSE_DYNDEP_MASK				BITFIELD(17, 17)
+#define OMAP4430_CEFUSE_DYNDEP_MASK				(1 << 17)
 
 /* Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP, CM_TESLA_STATICDEP */
 #define OMAP4430_CEFUSE_STATDEP_SHIFT				17
-#define OMAP4430_CEFUSE_STATDEP_MASK				BITFIELD(17, 17)
+#define OMAP4430_CEFUSE_STATDEP_MASK				(1 << 17)
 
 /* Used by CM1_ABE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_ABE_24M_GFCLK_SHIFT		13
-#define OMAP4430_CLKACTIVITY_ABE_24M_GFCLK_MASK			BITFIELD(13, 13)
+#define OMAP4430_CLKACTIVITY_ABE_24M_GFCLK_MASK			(1 << 13)
 
 /* Used by CM1_ABE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_ABE_ALWON_32K_CLK_SHIFT		12
-#define OMAP4430_CLKACTIVITY_ABE_ALWON_32K_CLK_MASK		BITFIELD(12, 12)
+#define OMAP4430_CLKACTIVITY_ABE_ALWON_32K_CLK_MASK		(1 << 12)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_ABE_LP_CLK_SHIFT			9
-#define OMAP4430_CLKACTIVITY_ABE_LP_CLK_MASK			BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_ABE_LP_CLK_MASK			(1 << 9)
 
 /* Used by CM1_ABE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_ABE_SYSCLK_SHIFT			11
-#define OMAP4430_CLKACTIVITY_ABE_SYSCLK_MASK			BITFIELD(11, 11)
+#define OMAP4430_CLKACTIVITY_ABE_SYSCLK_MASK			(1 << 11)
 
 /* Used by CM1_ABE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_ABE_X2_CLK_SHIFT			8
-#define OMAP4430_CLKACTIVITY_ABE_X2_CLK_MASK			BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_ABE_X2_CLK_MASK			(1 << 8)
 
 /* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_ASYNC_DLL_CLK_SHIFT		11
-#define OMAP4430_CLKACTIVITY_ASYNC_DLL_CLK_MASK			BITFIELD(11, 11)
+#define OMAP4430_CLKACTIVITY_ASYNC_DLL_CLK_MASK			(1 << 11)
 
 /* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_ASYNC_PHY1_CLK_SHIFT		12
-#define OMAP4430_CLKACTIVITY_ASYNC_PHY1_CLK_MASK		BITFIELD(12, 12)
+#define OMAP4430_CLKACTIVITY_ASYNC_PHY1_CLK_MASK		(1 << 12)
 
 /* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_ASYNC_PHY2_CLK_SHIFT		13
-#define OMAP4430_CLKACTIVITY_ASYNC_PHY2_CLK_MASK		BITFIELD(13, 13)
+#define OMAP4430_CLKACTIVITY_ASYNC_PHY2_CLK_MASK		(1 << 13)
 
 /* Used by CM_CAM_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_CAM_PHY_CTRL_GCLK_SHIFT		9
-#define OMAP4430_CLKACTIVITY_CAM_PHY_CTRL_GCLK_MASK		BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_CAM_PHY_CTRL_GCLK_MASK		(1 << 9)
+
+/* Used by CM_ALWON_CLKSTCTRL */
+#define OMAP4430_CLKACTIVITY_CORE_ALWON_32K_GFCLK_SHIFT		12
+#define OMAP4430_CLKACTIVITY_CORE_ALWON_32K_GFCLK_MASK		(1 << 12)
 
 /* Used by CM_EMU_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_CORE_DPLL_EMU_CLK_SHIFT		9
-#define OMAP4430_CLKACTIVITY_CORE_DPLL_EMU_CLK_MASK		BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_CORE_DPLL_EMU_CLK_MASK		(1 << 9)
 
 /* Used by CM_CEFUSE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_CUST_EFUSE_SYS_CLK_SHIFT		9
-#define OMAP4430_CLKACTIVITY_CUST_EFUSE_SYS_CLK_MASK		BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_CUST_EFUSE_SYS_CLK_MASK		(1 << 9)
 
 /* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_DLL_CLK_SHIFT			9
-#define OMAP4430_CLKACTIVITY_DLL_CLK_MASK			BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_DLL_CLK_MASK			(1 << 9)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_DMT10_GFCLK_SHIFT			9
-#define OMAP4430_CLKACTIVITY_DMT10_GFCLK_MASK			BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_DMT10_GFCLK_MASK			(1 << 9)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_DMT11_GFCLK_SHIFT			10
-#define OMAP4430_CLKACTIVITY_DMT11_GFCLK_MASK			BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_DMT11_GFCLK_MASK			(1 << 10)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_DMT2_GFCLK_SHIFT			11
-#define OMAP4430_CLKACTIVITY_DMT2_GFCLK_MASK			BITFIELD(11, 11)
+#define OMAP4430_CLKACTIVITY_DMT2_GFCLK_MASK			(1 << 11)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_DMT3_GFCLK_SHIFT			12
-#define OMAP4430_CLKACTIVITY_DMT3_GFCLK_MASK			BITFIELD(12, 12)
+#define OMAP4430_CLKACTIVITY_DMT3_GFCLK_MASK			(1 << 12)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_DMT4_GFCLK_SHIFT			13
-#define OMAP4430_CLKACTIVITY_DMT4_GFCLK_MASK			BITFIELD(13, 13)
+#define OMAP4430_CLKACTIVITY_DMT4_GFCLK_MASK			(1 << 13)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_DMT9_GFCLK_SHIFT			14
-#define OMAP4430_CLKACTIVITY_DMT9_GFCLK_MASK			BITFIELD(14, 14)
+#define OMAP4430_CLKACTIVITY_DMT9_GFCLK_MASK			(1 << 14)
 
 /* Used by CM_DSS_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_DSS_ALWON_SYS_CLK_SHIFT		10
-#define OMAP4430_CLKACTIVITY_DSS_ALWON_SYS_CLK_MASK		BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_DSS_ALWON_SYS_CLK_MASK		(1 << 10)
 
 /* Used by CM_DSS_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_DSS_FCLK_SHIFT			9
-#define OMAP4430_CLKACTIVITY_DSS_FCLK_MASK			BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_DSS_FCLK_MASK			(1 << 9)
 
 /* Used by CM_DUCATI_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_DUCATI_GCLK_SHIFT			8
-#define OMAP4430_CLKACTIVITY_DUCATI_GCLK_MASK			BITFIELD(8, 8)
-
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
-#define OMAP4430_CLKACTIVITY_EMAC_50MHZ_CLK_SHIFT		10
-#define OMAP4430_CLKACTIVITY_EMAC_50MHZ_CLK_MASK		BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_DUCATI_GCLK_MASK			(1 << 8)
 
 /* Used by CM_EMU_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_EMU_SYS_CLK_SHIFT			8
-#define OMAP4430_CLKACTIVITY_EMU_SYS_CLK_MASK			BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_EMU_SYS_CLK_MASK			(1 << 8)
 
 /* Used by CM_CAM_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_FDIF_GFCLK_SHIFT			10
-#define OMAP4430_CLKACTIVITY_FDIF_GFCLK_MASK			BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_FDIF_GFCLK_MASK			(1 << 10)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_FUNC_12M_GFCLK_SHIFT		15
-#define OMAP4430_CLKACTIVITY_FUNC_12M_GFCLK_MASK		BITFIELD(15, 15)
+#define OMAP4430_CLKACTIVITY_FUNC_12M_GFCLK_MASK		(1 << 15)
 
 /* Used by CM1_ABE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_FUNC_24M_GFCLK_SHIFT		10
-#define OMAP4430_CLKACTIVITY_FUNC_24M_GFCLK_MASK		BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_FUNC_24M_GFCLK_MASK		(1 << 10)
 
 /* Used by CM_DSS_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_HDMI_PHY_48MHZ_GFCLK_SHIFT		11
-#define OMAP4430_CLKACTIVITY_HDMI_PHY_48MHZ_GFCLK_MASK		BITFIELD(11, 11)
+#define OMAP4430_CLKACTIVITY_HDMI_PHY_48MHZ_GFCLK_MASK		(1 << 11)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_HSIC_P1_480M_GFCLK_SHIFT		20
-#define OMAP4430_CLKACTIVITY_HSIC_P1_480M_GFCLK_MASK		BITFIELD(20, 20)
+#define OMAP4430_CLKACTIVITY_HSIC_P1_480M_GFCLK_MASK		(1 << 20)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_HSIC_P1_GFCLK_SHIFT		26
-#define OMAP4430_CLKACTIVITY_HSIC_P1_GFCLK_MASK			BITFIELD(26, 26)
+#define OMAP4430_CLKACTIVITY_HSIC_P1_GFCLK_MASK			(1 << 26)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_HSIC_P2_480M_GFCLK_SHIFT		21
-#define OMAP4430_CLKACTIVITY_HSIC_P2_480M_GFCLK_MASK		BITFIELD(21, 21)
+#define OMAP4430_CLKACTIVITY_HSIC_P2_480M_GFCLK_MASK		(1 << 21)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_HSIC_P2_GFCLK_SHIFT		27
-#define OMAP4430_CLKACTIVITY_HSIC_P2_GFCLK_MASK			BITFIELD(27, 27)
-
-/* Used by CM_L3INIT_CLKSTCTRL */
-#define OMAP4430_CLKACTIVITY_INIT_32K_GFCLK_SHIFT		31
-#define OMAP4430_CLKACTIVITY_INIT_32K_GFCLK_MASK		BITFIELD(31, 31)
+#define OMAP4430_CLKACTIVITY_HSIC_P2_GFCLK_MASK			(1 << 27)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_INIT_48MC_GFCLK_SHIFT		13
-#define OMAP4430_CLKACTIVITY_INIT_48MC_GFCLK_MASK		BITFIELD(13, 13)
+#define OMAP4430_CLKACTIVITY_INIT_48MC_GFCLK_MASK		(1 << 13)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_INIT_48M_GFCLK_SHIFT		12
-#define OMAP4430_CLKACTIVITY_INIT_48M_GFCLK_MASK		BITFIELD(12, 12)
+#define OMAP4430_CLKACTIVITY_INIT_48M_GFCLK_MASK		(1 << 12)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_INIT_60M_P1_GFCLK_SHIFT		28
-#define OMAP4430_CLKACTIVITY_INIT_60M_P1_GFCLK_MASK		BITFIELD(28, 28)
+#define OMAP4430_CLKACTIVITY_INIT_60M_P1_GFCLK_MASK		(1 << 28)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_INIT_60M_P2_GFCLK_SHIFT		29
-#define OMAP4430_CLKACTIVITY_INIT_60M_P2_GFCLK_MASK		BITFIELD(29, 29)
+#define OMAP4430_CLKACTIVITY_INIT_60M_P2_GFCLK_MASK		(1 << 29)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_INIT_96M_GFCLK_SHIFT		11
-#define OMAP4430_CLKACTIVITY_INIT_96M_GFCLK_MASK		BITFIELD(11, 11)
+#define OMAP4430_CLKACTIVITY_INIT_96M_GFCLK_MASK		(1 << 11)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_INIT_HSI_GFCLK_SHIFT		16
-#define OMAP4430_CLKACTIVITY_INIT_HSI_GFCLK_MASK		BITFIELD(16, 16)
+#define OMAP4430_CLKACTIVITY_INIT_HSI_GFCLK_MASK		(1 << 16)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_INIT_HSMMC1_GFCLK_SHIFT		17
-#define OMAP4430_CLKACTIVITY_INIT_HSMMC1_GFCLK_MASK		BITFIELD(17, 17)
+#define OMAP4430_CLKACTIVITY_INIT_HSMMC1_GFCLK_MASK		(1 << 17)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_INIT_HSMMC2_GFCLK_SHIFT		18
-#define OMAP4430_CLKACTIVITY_INIT_HSMMC2_GFCLK_MASK		BITFIELD(18, 18)
+#define OMAP4430_CLKACTIVITY_INIT_HSMMC2_GFCLK_MASK		(1 << 18)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_INIT_HSMMC6_GFCLK_SHIFT		19
-#define OMAP4430_CLKACTIVITY_INIT_HSMMC6_GFCLK_MASK		BITFIELD(19, 19)
+#define OMAP4430_CLKACTIVITY_INIT_HSMMC6_GFCLK_MASK		(1 << 19)
 
 /* Used by CM_CAM_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_ISS_GCLK_SHIFT			8
-#define OMAP4430_CLKACTIVITY_ISS_GCLK_MASK			BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_ISS_GCLK_MASK			(1 << 8)
 
 /* Used by CM_IVAHD_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_IVAHD_ROOT_CLK_SHIFT		8
-#define OMAP4430_CLKACTIVITY_IVAHD_ROOT_CLK_MASK		BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_IVAHD_ROOT_CLK_MASK		(1 << 8)
 
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
-#define OMAP4430_CLKACTIVITY_L3INIT_DPLL_ALWON_CLK_SHIFT	14
-#define OMAP4430_CLKACTIVITY_L3INIT_DPLL_ALWON_CLK_MASK		BITFIELD(14, 14)
+/* Used by CM_D2D_CLKSTCTRL */
+#define OMAP4430_CLKACTIVITY_L3X2_D2D_GICLK_SHIFT		10
+#define OMAP4430_CLKACTIVITY_L3X2_D2D_GICLK_MASK		(1 << 10)
 
 /* Used by CM_L3_1_CLKSTCTRL, CM_L3_1_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_L3_1_GICLK_SHIFT			8
-#define OMAP4430_CLKACTIVITY_L3_1_GICLK_MASK			BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L3_1_GICLK_MASK			(1 << 8)
 
 /* Used by CM_L3_2_CLKSTCTRL, CM_L3_2_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_L3_2_GICLK_SHIFT			8
-#define OMAP4430_CLKACTIVITY_L3_2_GICLK_MASK			BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L3_2_GICLK_MASK			(1 << 8)
 
 /* Used by CM_D2D_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_D2D_GICLK_SHIFT			8
-#define OMAP4430_CLKACTIVITY_L3_D2D_GICLK_MASK			BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L3_D2D_GICLK_MASK			(1 << 8)
 
 /* Used by CM_SDMA_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_DMA_GICLK_SHIFT			8
-#define OMAP4430_CLKACTIVITY_L3_DMA_GICLK_MASK			BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L3_DMA_GICLK_MASK			(1 << 8)
 
 /* Used by CM_DSS_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_DSS_GICLK_SHIFT			8
-#define OMAP4430_CLKACTIVITY_L3_DSS_GICLK_MASK			BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L3_DSS_GICLK_MASK			(1 << 8)
 
 /* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_L3_EMIF_GICLK_SHIFT		8
-#define OMAP4430_CLKACTIVITY_L3_EMIF_GICLK_MASK			BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L3_EMIF_GICLK_MASK			(1 << 8)
 
 /* Used by CM_GFX_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_GFX_GICLK_SHIFT			8
-#define OMAP4430_CLKACTIVITY_L3_GFX_GICLK_MASK			BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L3_GFX_GICLK_MASK			(1 << 8)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_L3_INIT_GICLK_SHIFT		8
-#define OMAP4430_CLKACTIVITY_L3_INIT_GICLK_MASK			BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L3_INIT_GICLK_MASK			(1 << 8)
 
 /* Used by CM_L3INSTR_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_INSTR_GICLK_SHIFT		8
-#define OMAP4430_CLKACTIVITY_L3_INSTR_GICLK_MASK		BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L3_INSTR_GICLK_MASK		(1 << 8)
 
 /* Used by CM_L4SEC_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_SECURE_GICLK_SHIFT		8
-#define OMAP4430_CLKACTIVITY_L3_SECURE_GICLK_MASK		BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L3_SECURE_GICLK_MASK		(1 << 8)
 
 /* Used by CM_ALWON_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L4_AO_ICLK_SHIFT			8
-#define OMAP4430_CLKACTIVITY_L4_AO_ICLK_MASK			BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L4_AO_ICLK_MASK			(1 << 8)
 
 /* Used by CM_CEFUSE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L4_CEFUSE_GICLK_SHIFT		8
-#define OMAP4430_CLKACTIVITY_L4_CEFUSE_GICLK_MASK		BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L4_CEFUSE_GICLK_MASK		(1 << 8)
 
 /* Used by CM_L4CFG_CLKSTCTRL, CM_L4CFG_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_L4_CFG_GICLK_SHIFT			8
-#define OMAP4430_CLKACTIVITY_L4_CFG_GICLK_MASK			BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L4_CFG_GICLK_MASK			(1 << 8)
 
 /* Used by CM_D2D_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L4_D2D_GICLK_SHIFT			9
-#define OMAP4430_CLKACTIVITY_L4_D2D_GICLK_MASK			BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_L4_D2D_GICLK_MASK			(1 << 9)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_L4_INIT_GICLK_SHIFT		9
-#define OMAP4430_CLKACTIVITY_L4_INIT_GICLK_MASK			BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_L4_INIT_GICLK_MASK			(1 << 9)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_L4_PER_GICLK_SHIFT			8
-#define OMAP4430_CLKACTIVITY_L4_PER_GICLK_MASK			BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L4_PER_GICLK_MASK			(1 << 8)
 
 /* Used by CM_L4SEC_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L4_SECURE_GICLK_SHIFT		9
-#define OMAP4430_CLKACTIVITY_L4_SECURE_GICLK_MASK		BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_L4_SECURE_GICLK_MASK		(1 << 9)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L4_WKUP_GICLK_SHIFT		12
-#define OMAP4430_CLKACTIVITY_L4_WKUP_GICLK_MASK			BITFIELD(12, 12)
+#define OMAP4430_CLKACTIVITY_L4_WKUP_GICLK_MASK			(1 << 12)
 
 /* Used by CM_MPU_CLKSTCTRL, CM_MPU_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_MPU_DPLL_CLK_SHIFT			8
-#define OMAP4430_CLKACTIVITY_MPU_DPLL_CLK_MASK			BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_MPU_DPLL_CLK_MASK			(1 << 8)
 
 /* Used by CM1_ABE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_OCP_ABE_GICLK_SHIFT		9
-#define OMAP4430_CLKACTIVITY_OCP_ABE_GICLK_MASK			BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_OCP_ABE_GICLK_MASK			(1 << 9)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_PER_24MC_GFCLK_SHIFT		16
-#define OMAP4430_CLKACTIVITY_PER_24MC_GFCLK_MASK		BITFIELD(16, 16)
+#define OMAP4430_CLKACTIVITY_PER_24MC_GFCLK_MASK		(1 << 16)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_PER_32K_GFCLK_SHIFT		17
-#define OMAP4430_CLKACTIVITY_PER_32K_GFCLK_MASK			BITFIELD(17, 17)
+#define OMAP4430_CLKACTIVITY_PER_32K_GFCLK_MASK			(1 << 17)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_PER_48M_GFCLK_SHIFT		18
-#define OMAP4430_CLKACTIVITY_PER_48M_GFCLK_MASK			BITFIELD(18, 18)
+#define OMAP4430_CLKACTIVITY_PER_48M_GFCLK_MASK			(1 << 18)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_PER_96M_GFCLK_SHIFT		19
-#define OMAP4430_CLKACTIVITY_PER_96M_GFCLK_MASK			BITFIELD(19, 19)
+#define OMAP4430_CLKACTIVITY_PER_96M_GFCLK_MASK			(1 << 19)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_PER_ABE_24M_GFCLK_SHIFT		25
-#define OMAP4430_CLKACTIVITY_PER_ABE_24M_GFCLK_MASK		BITFIELD(25, 25)
-
-/* Used by CM_EMU_CLKSTCTRL */
-#define OMAP4430_CLKACTIVITY_PER_DPLL_EMU_CLK_SHIFT		10
-#define OMAP4430_CLKACTIVITY_PER_DPLL_EMU_CLK_MASK		BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_PER_ABE_24M_GFCLK_MASK		(1 << 25)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_PER_MCASP2_GFCLK_SHIFT		20
-#define OMAP4430_CLKACTIVITY_PER_MCASP2_GFCLK_MASK		BITFIELD(20, 20)
+#define OMAP4430_CLKACTIVITY_PER_MCASP2_GFCLK_MASK		(1 << 20)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_PER_MCASP3_GFCLK_SHIFT		21
-#define OMAP4430_CLKACTIVITY_PER_MCASP3_GFCLK_MASK		BITFIELD(21, 21)
+#define OMAP4430_CLKACTIVITY_PER_MCASP3_GFCLK_MASK		(1 << 21)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_PER_MCBSP4_GFCLK_SHIFT		22
-#define OMAP4430_CLKACTIVITY_PER_MCBSP4_GFCLK_MASK		BITFIELD(22, 22)
+#define OMAP4430_CLKACTIVITY_PER_MCBSP4_GFCLK_MASK		(1 << 22)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_PER_SYS_GFCLK_SHIFT		24
-#define OMAP4430_CLKACTIVITY_PER_SYS_GFCLK_MASK			BITFIELD(24, 24)
+#define OMAP4430_CLKACTIVITY_PER_SYS_GFCLK_MASK			(1 << 24)
 
 /* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_PHY_ROOT_CLK_SHIFT			10
-#define OMAP4430_CLKACTIVITY_PHY_ROOT_CLK_MASK			BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_PHY_ROOT_CLK_MASK			(1 << 10)
 
 /* Used by CM_GFX_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_SGX_GFCLK_SHIFT			9
-#define OMAP4430_CLKACTIVITY_SGX_GFCLK_MASK			BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_SGX_GFCLK_MASK			(1 << 9)
 
 /* Used by CM_ALWON_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_SR_CORE_SYSCLK_SHIFT		11
-#define OMAP4430_CLKACTIVITY_SR_CORE_SYSCLK_MASK		BITFIELD(11, 11)
+#define OMAP4430_CLKACTIVITY_SR_CORE_SYSCLK_MASK		(1 << 11)
 
 /* Used by CM_ALWON_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_SR_IVA_SYSCLK_SHIFT		10
-#define OMAP4430_CLKACTIVITY_SR_IVA_SYSCLK_MASK			BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_SR_IVA_SYSCLK_MASK			(1 << 10)
 
 /* Used by CM_ALWON_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_SR_MPU_SYSCLK_SHIFT		9
-#define OMAP4430_CLKACTIVITY_SR_MPU_SYSCLK_MASK			BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_SR_MPU_SYSCLK_MASK			(1 << 9)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_SYS_CLK_SHIFT			8
-#define OMAP4430_CLKACTIVITY_SYS_CLK_MASK			BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_SYS_CLK_MASK			(1 << 8)
 
 /* Used by CM_TESLA_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_TESLA_ROOT_CLK_SHIFT		8
-#define OMAP4430_CLKACTIVITY_TESLA_ROOT_CLK_MASK		BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_TESLA_ROOT_CLK_MASK		(1 << 8)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_TLL_CH0_GFCLK_SHIFT		22
-#define OMAP4430_CLKACTIVITY_TLL_CH0_GFCLK_MASK			BITFIELD(22, 22)
+#define OMAP4430_CLKACTIVITY_TLL_CH0_GFCLK_MASK			(1 << 22)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_TLL_CH1_GFCLK_SHIFT		23
-#define OMAP4430_CLKACTIVITY_TLL_CH1_GFCLK_MASK			BITFIELD(23, 23)
+#define OMAP4430_CLKACTIVITY_TLL_CH1_GFCLK_MASK			(1 << 23)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_TLL_CH2_GFCLK_SHIFT		24
-#define OMAP4430_CLKACTIVITY_TLL_CH2_GFCLK_MASK			BITFIELD(24, 24)
+#define OMAP4430_CLKACTIVITY_TLL_CH2_GFCLK_MASK			(1 << 24)
+
+/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+#define OMAP4430_CLKACTIVITY_UNIPRO_DPLL_CLK_SHIFT		10
+#define OMAP4430_CLKACTIVITY_UNIPRO_DPLL_CLK_MASK		(1 << 10)
+
+/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+#define OMAP4430_CLKACTIVITY_USB_DPLL_CLK_SHIFT			14
+#define OMAP4430_CLKACTIVITY_USB_DPLL_CLK_MASK			(1 << 14)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_USB_DPLL_HS_CLK_SHIFT		15
-#define OMAP4430_CLKACTIVITY_USB_DPLL_HS_CLK_MASK		BITFIELD(15, 15)
+#define OMAP4430_CLKACTIVITY_USB_DPLL_HS_CLK_MASK		(1 << 15)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_USIM_GFCLK_SHIFT			10
-#define OMAP4430_CLKACTIVITY_USIM_GFCLK_MASK			BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_USIM_GFCLK_MASK			(1 << 10)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_UTMI_P3_GFCLK_SHIFT		30
-#define OMAP4430_CLKACTIVITY_UTMI_P3_GFCLK_MASK			BITFIELD(30, 30)
+#define OMAP4430_CLKACTIVITY_UTMI_P3_GFCLK_MASK			(1 << 30)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_UTMI_ROOT_GFCLK_SHIFT		25
-#define OMAP4430_CLKACTIVITY_UTMI_ROOT_GFCLK_MASK		BITFIELD(25, 25)
+#define OMAP4430_CLKACTIVITY_UTMI_ROOT_GFCLK_MASK		(1 << 25)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_WKUP_32K_GFCLK_SHIFT		11
-#define OMAP4430_CLKACTIVITY_WKUP_32K_GFCLK_MASK		BITFIELD(11, 11)
+#define OMAP4430_CLKACTIVITY_WKUP_32K_GFCLK_MASK		(1 << 11)
 
 /*
- * Used by CM_WKUP_TIMER1_CLKCTRL, CM_L4PER_DMTIMER10_CLKCTRL,
+ * Used by CM1_ABE_TIMER5_CLKCTRL, CM1_ABE_TIMER6_CLKCTRL,
+ * CM1_ABE_TIMER7_CLKCTRL, CM1_ABE_TIMER8_CLKCTRL, CM_L3INIT_MMC1_CLKCTRL,
+ * CM_L3INIT_MMC2_CLKCTRL, CM_L3INIT_MMC6_CLKCTRL, CM_L4PER_DMTIMER10_CLKCTRL,
  * CM_L4PER_DMTIMER11_CLKCTRL, CM_L4PER_DMTIMER2_CLKCTRL,
  * CM_L4PER_DMTIMER3_CLKCTRL, CM_L4PER_DMTIMER4_CLKCTRL,
  * CM_L4PER_DMTIMER9_CLKCTRL, CM_L4PER_MCASP2_CLKCTRL, CM_L4PER_MCASP3_CLKCTRL,
- * CM_L3INIT_MMC1_CLKCTRL, CM_L3INIT_MMC2_CLKCTRL, CM_L3INIT_MMC6_CLKCTRL,
- * CM1_ABE_TIMER5_CLKCTRL, CM1_ABE_TIMER6_CLKCTRL, CM1_ABE_TIMER7_CLKCTRL,
- * CM1_ABE_TIMER8_CLKCTRL
+ * CM_WKUP_TIMER1_CLKCTRL
  */
 #define OMAP4430_CLKSEL_SHIFT					24
-#define OMAP4430_CLKSEL_MASK					BITFIELD(24, 24)
+#define OMAP4430_CLKSEL_MASK					(1 << 24)
 
 /*
  * Renamed from CLKSEL Used by CM_ABE_DSS_SYS_CLKSEL, CM_ABE_PLL_REF_CLKSEL,
- * CM_DPLL_SYS_REF_CLKSEL, CM_L4_WKUP_CLKSEL, CM_CLKSEL_DUCATI_ISS_ROOT,
- * CM_CLKSEL_USB_60MHZ
+ * CM_L4_WKUP_CLKSEL, CM_CLKSEL_DUCATI_ISS_ROOT, CM_CLKSEL_USB_60MHZ
  */
 #define OMAP4430_CLKSEL_0_0_SHIFT				0
-#define OMAP4430_CLKSEL_0_0_MASK				BITFIELD(0, 0)
+#define OMAP4430_CLKSEL_0_0_MASK				(1 << 0)
 
 /* Renamed from CLKSEL Used by CM_BYPCLK_DPLL_IVA, CM_BYPCLK_DPLL_MPU */
 #define OMAP4430_CLKSEL_0_1_SHIFT				0
-#define OMAP4430_CLKSEL_0_1_MASK				BITFIELD(0, 1)
+#define OMAP4430_CLKSEL_0_1_MASK				(0x3 << 0)
 
 /* Renamed from CLKSEL Used by CM_L3INIT_HSI_CLKCTRL */
 #define OMAP4430_CLKSEL_24_25_SHIFT				24
-#define OMAP4430_CLKSEL_24_25_MASK				BITFIELD(24, 25)
+#define OMAP4430_CLKSEL_24_25_MASK				(0x3 << 24)
 
 /* Used by CM_L3INIT_USB_OTG_CLKCTRL */
 #define OMAP4430_CLKSEL_60M_SHIFT				24
-#define OMAP4430_CLKSEL_60M_MASK				BITFIELD(24, 24)
+#define OMAP4430_CLKSEL_60M_MASK				(1 << 24)
 
 /* Used by CM1_ABE_AESS_CLKCTRL */
 #define OMAP4430_CLKSEL_AESS_FCLK_SHIFT				24
-#define OMAP4430_CLKSEL_AESS_FCLK_MASK				BITFIELD(24, 24)
+#define OMAP4430_CLKSEL_AESS_FCLK_MASK				(1 << 24)
 
-/* Used by CM_CLKSEL_CORE_RESTORE, CM_CLKSEL_CORE */
+/* Used by CM_CLKSEL_CORE, CM_CLKSEL_CORE_RESTORE */
 #define OMAP4430_CLKSEL_CORE_SHIFT				0
-#define OMAP4430_CLKSEL_CORE_MASK				BITFIELD(0, 0)
+#define OMAP4430_CLKSEL_CORE_MASK				(1 << 0)
 
-/* Renamed from CLKSEL_CORE Used by CM_SHADOW_FREQ_CONFIG2 */
+/*
+ * Renamed from CLKSEL_CORE Used by CM_SHADOW_FREQ_CONFIG2_RESTORE,
+ * CM_SHADOW_FREQ_CONFIG2
+ */
 #define OMAP4430_CLKSEL_CORE_1_1_SHIFT				1
-#define OMAP4430_CLKSEL_CORE_1_1_MASK				BITFIELD(1, 1)
+#define OMAP4430_CLKSEL_CORE_1_1_MASK				(1 << 1)
 
 /* Used by CM_WKUP_USIM_CLKCTRL */
 #define OMAP4430_CLKSEL_DIV_SHIFT				24
-#define OMAP4430_CLKSEL_DIV_MASK				BITFIELD(24, 24)
+#define OMAP4430_CLKSEL_DIV_MASK				(1 << 24)
 
 /* Used by CM_CAM_FDIF_CLKCTRL */
 #define OMAP4430_CLKSEL_FCLK_SHIFT				24
-#define OMAP4430_CLKSEL_FCLK_MASK				BITFIELD(24, 25)
+#define OMAP4430_CLKSEL_FCLK_MASK				(0x3 << 24)
 
 /* Used by CM_L4PER_MCBSP4_CLKCTRL */
 #define OMAP4430_CLKSEL_INTERNAL_SOURCE_SHIFT			25
-#define OMAP4430_CLKSEL_INTERNAL_SOURCE_MASK			BITFIELD(25, 25)
+#define OMAP4430_CLKSEL_INTERNAL_SOURCE_MASK			(1 << 25)
 
 /*
  * Renamed from CLKSEL_INTERNAL_SOURCE Used by CM1_ABE_DMIC_CLKCTRL,
@@ -479,836 +485,869 @@
  * CM1_ABE_MCBSP3_CLKCTRL
  */
 #define OMAP4430_CLKSEL_INTERNAL_SOURCE_CM1_ABE_DMIC_SHIFT	26
-#define OMAP4430_CLKSEL_INTERNAL_SOURCE_CM1_ABE_DMIC_MASK	BITFIELD(26, 27)
+#define OMAP4430_CLKSEL_INTERNAL_SOURCE_CM1_ABE_DMIC_MASK	(0x3 << 26)
 
-/* Used by CM_CLKSEL_CORE_RESTORE, CM_CLKSEL_CORE */
+/* Used by CM_CLKSEL_CORE, CM_CLKSEL_CORE_RESTORE */
 #define OMAP4430_CLKSEL_L3_SHIFT				4
-#define OMAP4430_CLKSEL_L3_MASK					BITFIELD(4, 4)
+#define OMAP4430_CLKSEL_L3_MASK					(1 << 4)
 
-/* Renamed from CLKSEL_L3 Used by CM_SHADOW_FREQ_CONFIG2 */
+/*
+ * Renamed from CLKSEL_L3 Used by CM_SHADOW_FREQ_CONFIG2_RESTORE,
+ * CM_SHADOW_FREQ_CONFIG2
+ */
 #define OMAP4430_CLKSEL_L3_SHADOW_SHIFT				2
-#define OMAP4430_CLKSEL_L3_SHADOW_MASK				BITFIELD(2, 2)
+#define OMAP4430_CLKSEL_L3_SHADOW_MASK				(1 << 2)
 
-/* Used by CM_CLKSEL_CORE_RESTORE, CM_CLKSEL_CORE */
+/* Used by CM_CLKSEL_CORE, CM_CLKSEL_CORE_RESTORE */
 #define OMAP4430_CLKSEL_L4_SHIFT				8
-#define OMAP4430_CLKSEL_L4_MASK					BITFIELD(8, 8)
+#define OMAP4430_CLKSEL_L4_MASK					(1 << 8)
 
 /* Used by CM_CLKSEL_ABE */
 #define OMAP4430_CLKSEL_OPP_SHIFT				0
-#define OMAP4430_CLKSEL_OPP_MASK				BITFIELD(0, 1)
-
-/* Used by CM_GFX_GFX_CLKCTRL */
-#define OMAP4430_CLKSEL_PER_192M_SHIFT				25
-#define OMAP4430_CLKSEL_PER_192M_MASK				BITFIELD(25, 26)
+#define OMAP4430_CLKSEL_OPP_MASK				(0x3 << 0)
 
 /* Used by CM_EMU_DEBUGSS_CLKCTRL */
 #define OMAP4430_CLKSEL_PMD_STM_CLK_SHIFT			27
-#define OMAP4430_CLKSEL_PMD_STM_CLK_MASK			BITFIELD(27, 29)
+#define OMAP4430_CLKSEL_PMD_STM_CLK_MASK			(0x7 << 27)
 
 /* Used by CM_EMU_DEBUGSS_CLKCTRL */
 #define OMAP4430_CLKSEL_PMD_TRACE_CLK_SHIFT			24
-#define OMAP4430_CLKSEL_PMD_TRACE_CLK_MASK			BITFIELD(24, 26)
+#define OMAP4430_CLKSEL_PMD_TRACE_CLK_MASK			(0x7 << 24)
 
 /* Used by CM_GFX_GFX_CLKCTRL */
 #define OMAP4430_CLKSEL_SGX_FCLK_SHIFT				24
-#define OMAP4430_CLKSEL_SGX_FCLK_MASK				BITFIELD(24, 24)
+#define OMAP4430_CLKSEL_SGX_FCLK_MASK				(1 << 24)
 
 /*
  * Used by CM1_ABE_DMIC_CLKCTRL, CM1_ABE_MCASP_CLKCTRL, CM1_ABE_MCBSP1_CLKCTRL,
  * CM1_ABE_MCBSP2_CLKCTRL, CM1_ABE_MCBSP3_CLKCTRL
  */
 #define OMAP4430_CLKSEL_SOURCE_SHIFT				24
-#define OMAP4430_CLKSEL_SOURCE_MASK				BITFIELD(24, 25)
+#define OMAP4430_CLKSEL_SOURCE_MASK				(0x3 << 24)
 
 /* Renamed from CLKSEL_SOURCE Used by CM_L4PER_MCBSP4_CLKCTRL */
 #define OMAP4430_CLKSEL_SOURCE_24_24_SHIFT			24
-#define OMAP4430_CLKSEL_SOURCE_24_24_MASK			BITFIELD(24, 24)
+#define OMAP4430_CLKSEL_SOURCE_24_24_MASK			(1 << 24)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
 #define OMAP4430_CLKSEL_UTMI_P1_SHIFT				24
-#define OMAP4430_CLKSEL_UTMI_P1_MASK				BITFIELD(24, 24)
+#define OMAP4430_CLKSEL_UTMI_P1_MASK				(1 << 24)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
 #define OMAP4430_CLKSEL_UTMI_P2_SHIFT				25
-#define OMAP4430_CLKSEL_UTMI_P2_MASK				BITFIELD(25, 25)
+#define OMAP4430_CLKSEL_UTMI_P2_MASK				(1 << 25)
 
 /*
- * Used by CM_WKUP_CLKSTCTRL, CM_EMU_CLKSTCTRL, CM_D2D_CLKSTCTRL,
- * CM_DUCATI_CLKSTCTRL, CM_L3INSTR_CLKSTCTRL, CM_L3_1_CLKSTCTRL,
- * CM_L3_2_CLKSTCTRL, CM_L4CFG_CLKSTCTRL, CM_MEMIF_CLKSTCTRL,
- * CM_SDMA_CLKSTCTRL, CM_GFX_CLKSTCTRL, CM_L4PER_CLKSTCTRL, CM_L4SEC_CLKSTCTRL,
- * CM_L3INIT_CLKSTCTRL, CM_CAM_CLKSTCTRL, CM_CEFUSE_CLKSTCTRL,
- * CM_L3INIT_CLKSTCTRL_RESTORE, CM_L3_1_CLKSTCTRL_RESTORE,
- * CM_L3_2_CLKSTCTRL_RESTORE, CM_L4CFG_CLKSTCTRL_RESTORE,
- * CM_L4PER_CLKSTCTRL_RESTORE, CM_MEMIF_CLKSTCTRL_RESTORE, CM_ALWON_CLKSTCTRL,
- * CM_IVAHD_CLKSTCTRL, CM_DSS_CLKSTCTRL, CM_MPU_CLKSTCTRL, CM_TESLA_CLKSTCTRL,
- * CM1_ABE_CLKSTCTRL, CM_MPU_CLKSTCTRL_RESTORE
+ * Used by CM1_ABE_CLKSTCTRL, CM_ALWON_CLKSTCTRL, CM_CAM_CLKSTCTRL,
+ * CM_CEFUSE_CLKSTCTRL, CM_D2D_CLKSTCTRL, CM_DSS_CLKSTCTRL,
+ * CM_DUCATI_CLKSTCTRL, CM_EMU_CLKSTCTRL, CM_GFX_CLKSTCTRL, CM_IVAHD_CLKSTCTRL,
+ * CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE, CM_L3INSTR_CLKSTCTRL,
+ * CM_L3_1_CLKSTCTRL, CM_L3_1_CLKSTCTRL_RESTORE, CM_L3_2_CLKSTCTRL,
+ * CM_L3_2_CLKSTCTRL_RESTORE, CM_L4CFG_CLKSTCTRL, CM_L4CFG_CLKSTCTRL_RESTORE,
+ * CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE, CM_L4SEC_CLKSTCTRL,
+ * CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE, CM_MPU_CLKSTCTRL,
+ * CM_MPU_CLKSTCTRL_RESTORE, CM_SDMA_CLKSTCTRL, CM_TESLA_CLKSTCTRL,
+ * CM_WKUP_CLKSTCTRL
  */
 #define OMAP4430_CLKTRCTRL_SHIFT				0
-#define OMAP4430_CLKTRCTRL_MASK					BITFIELD(0, 1)
+#define OMAP4430_CLKTRCTRL_MASK					(0x3 << 0)
 
 /* Used by CM_EMU_OVERRIDE_DPLL_CORE */
 #define OMAP4430_CORE_DPLL_EMU_DIV_SHIFT			0
-#define OMAP4430_CORE_DPLL_EMU_DIV_MASK				BITFIELD(0, 6)
+#define OMAP4430_CORE_DPLL_EMU_DIV_MASK				(0x7f << 0)
 
 /* Used by CM_EMU_OVERRIDE_DPLL_CORE */
 #define OMAP4430_CORE_DPLL_EMU_MULT_SHIFT			8
-#define OMAP4430_CORE_DPLL_EMU_MULT_MASK			BITFIELD(8, 18)
+#define OMAP4430_CORE_DPLL_EMU_MULT_MASK			(0x7ff << 8)
 
-/* Used by CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP */
+/* Used by REVISION_CM1, REVISION_CM2 */
+#define OMAP4430_CUSTOM_SHIFT					6
+#define OMAP4430_CUSTOM_MASK					(0x3 << 6)
+
+/*
+ * Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
+ * CM_L4CFG_DYNAMICDEP_RESTORE
+ */
 #define OMAP4430_D2D_DYNDEP_SHIFT				18
-#define OMAP4430_D2D_DYNDEP_MASK				BITFIELD(18, 18)
+#define OMAP4430_D2D_DYNDEP_MASK				(1 << 18)
 
 /* Used by CM_MPU_STATICDEP */
 #define OMAP4430_D2D_STATDEP_SHIFT				18
-#define OMAP4430_D2D_STATDEP_MASK				BITFIELD(18, 18)
+#define OMAP4430_D2D_STATDEP_MASK				(1 << 18)
 
 /*
- * Used by CM_SSC_DELTAMSTEP_DPLL_PER, CM_SSC_DELTAMSTEP_DPLL_UNIPRO,
- * CM_SSC_DELTAMSTEP_DPLL_USB, CM_SSC_DELTAMSTEP_DPLL_CORE_RESTORE,
- * CM_SSC_DELTAMSTEP_DPLL_ABE, CM_SSC_DELTAMSTEP_DPLL_CORE,
- * CM_SSC_DELTAMSTEP_DPLL_DDRPHY, CM_SSC_DELTAMSTEP_DPLL_IVA,
- * CM_SSC_DELTAMSTEP_DPLL_MPU
+ * Used by CM_SSC_DELTAMSTEP_DPLL_ABE, CM_SSC_DELTAMSTEP_DPLL_CORE,
+ * CM_SSC_DELTAMSTEP_DPLL_CORE_RESTORE, CM_SSC_DELTAMSTEP_DPLL_DDRPHY,
+ * CM_SSC_DELTAMSTEP_DPLL_IVA, CM_SSC_DELTAMSTEP_DPLL_MPU,
+ * CM_SSC_DELTAMSTEP_DPLL_PER, CM_SSC_DELTAMSTEP_DPLL_UNIPRO,
+ * CM_SSC_DELTAMSTEP_DPLL_USB
  */
 #define OMAP4430_DELTAMSTEP_SHIFT				0
-#define OMAP4430_DELTAMSTEP_MASK				BITFIELD(0, 19)
+#define OMAP4430_DELTAMSTEP_MASK				(0xfffff << 0)
 
-/* Used by CM_SHADOW_FREQ_CONFIG1_RESTORE, CM_SHADOW_FREQ_CONFIG1 */
+/* Used by CM_SHADOW_FREQ_CONFIG1, CM_SHADOW_FREQ_CONFIG1_RESTORE */
 #define OMAP4430_DLL_OVERRIDE_SHIFT				2
-#define OMAP4430_DLL_OVERRIDE_MASK				BITFIELD(2, 2)
+#define OMAP4430_DLL_OVERRIDE_MASK				(1 << 2)
 
 /* Renamed from DLL_OVERRIDE Used by CM_DLL_CTRL */
 #define OMAP4430_DLL_OVERRIDE_0_0_SHIFT				0
-#define OMAP4430_DLL_OVERRIDE_0_0_MASK				BITFIELD(0, 0)
+#define OMAP4430_DLL_OVERRIDE_0_0_MASK				(1 << 0)
 
-/* Used by CM_SHADOW_FREQ_CONFIG1_RESTORE, CM_SHADOW_FREQ_CONFIG1 */
+/* Used by CM_SHADOW_FREQ_CONFIG1, CM_SHADOW_FREQ_CONFIG1_RESTORE */
 #define OMAP4430_DLL_RESET_SHIFT				3
-#define OMAP4430_DLL_RESET_MASK					BITFIELD(3, 3)
+#define OMAP4430_DLL_RESET_MASK					(1 << 3)
 
 /*
- * Used by CM_CLKSEL_DPLL_PER, CM_CLKSEL_DPLL_UNIPRO, CM_CLKSEL_DPLL_USB,
- * CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE,
- * CM_CLKSEL_DPLL_DDRPHY, CM_CLKSEL_DPLL_IVA, CM_CLKSEL_DPLL_MPU
+ * Used by CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE,
+ * CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_DDRPHY, CM_CLKSEL_DPLL_IVA,
+ * CM_CLKSEL_DPLL_MPU, CM_CLKSEL_DPLL_PER, CM_CLKSEL_DPLL_UNIPRO,
+ * CM_CLKSEL_DPLL_USB
  */
 #define OMAP4430_DPLL_BYP_CLKSEL_SHIFT				23
-#define OMAP4430_DPLL_BYP_CLKSEL_MASK				BITFIELD(23, 23)
+#define OMAP4430_DPLL_BYP_CLKSEL_MASK				(1 << 23)
 
 /* Used by CM_CLKDCOLDO_DPLL_USB */
 #define OMAP4430_DPLL_CLKDCOLDO_GATE_CTRL_SHIFT			8
-#define OMAP4430_DPLL_CLKDCOLDO_GATE_CTRL_MASK			BITFIELD(8, 8)
+#define OMAP4430_DPLL_CLKDCOLDO_GATE_CTRL_MASK			(1 << 8)
 
-/* Used by CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_CORE */
+/* Used by CM_CLKSEL_DPLL_CORE, CM_CLKSEL_DPLL_CORE_RESTORE */
 #define OMAP4430_DPLL_CLKOUTHIF_CLKSEL_SHIFT			20
-#define OMAP4430_DPLL_CLKOUTHIF_CLKSEL_MASK			BITFIELD(20, 20)
+#define OMAP4430_DPLL_CLKOUTHIF_CLKSEL_MASK			(1 << 20)
 
 /*
- * Used by CM_DIV_M3_DPLL_PER, CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_ABE,
- * CM_DIV_M3_DPLL_CORE
+ * Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE,
+ * CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_PER
  */
 #define OMAP4430_DPLL_CLKOUTHIF_DIV_SHIFT			0
-#define OMAP4430_DPLL_CLKOUTHIF_DIV_MASK			BITFIELD(0, 4)
+#define OMAP4430_DPLL_CLKOUTHIF_DIV_MASK			(0x1f << 0)
 
 /*
- * Used by CM_DIV_M3_DPLL_PER, CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_ABE,
- * CM_DIV_M3_DPLL_CORE
+ * Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE,
+ * CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_PER
  */
 #define OMAP4430_DPLL_CLKOUTHIF_DIVCHACK_SHIFT			5
-#define OMAP4430_DPLL_CLKOUTHIF_DIVCHACK_MASK			BITFIELD(5, 5)
+#define OMAP4430_DPLL_CLKOUTHIF_DIVCHACK_MASK			(1 << 5)
 
 /*
- * Used by CM_DIV_M3_DPLL_PER, CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_ABE,
- * CM_DIV_M3_DPLL_CORE
+ * Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE,
+ * CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_PER
  */
 #define OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT			8
-#define OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_MASK			BITFIELD(8, 8)
+#define OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_MASK			(1 << 8)
 
-/* Used by CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO, CM_DIV_M2_DPLL_ABE */
+/* Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO */
 #define OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_SHIFT			10
-#define OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK			BITFIELD(10, 10)
+#define OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK			(1 << 10)
 
 /*
- * Used by CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO,
- * CM_DIV_M2_DPLL_CORE_RESTORE, CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE,
- * CM_DIV_M2_DPLL_DDRPHY, CM_DIV_M2_DPLL_MPU
+ * Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE,
+ * CM_DIV_M2_DPLL_CORE_RESTORE, CM_DIV_M2_DPLL_DDRPHY, CM_DIV_M2_DPLL_MPU,
+ * CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO
  */
 #define OMAP4430_DPLL_CLKOUT_DIV_SHIFT				0
-#define OMAP4430_DPLL_CLKOUT_DIV_MASK				BITFIELD(0, 4)
+#define OMAP4430_DPLL_CLKOUT_DIV_MASK				(0x1f << 0)
 
 /* Renamed from DPLL_CLKOUT_DIV Used by CM_DIV_M2_DPLL_USB */
 #define OMAP4430_DPLL_CLKOUT_DIV_0_6_SHIFT			0
-#define OMAP4430_DPLL_CLKOUT_DIV_0_6_MASK			BITFIELD(0, 6)
+#define OMAP4430_DPLL_CLKOUT_DIV_0_6_MASK			(0x7f << 0)
 
 /*
- * Used by CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO,
- * CM_DIV_M2_DPLL_CORE_RESTORE, CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE,
- * CM_DIV_M2_DPLL_DDRPHY, CM_DIV_M2_DPLL_MPU
+ * Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE,
+ * CM_DIV_M2_DPLL_CORE_RESTORE, CM_DIV_M2_DPLL_DDRPHY, CM_DIV_M2_DPLL_MPU,
+ * CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO
  */
 #define OMAP4430_DPLL_CLKOUT_DIVCHACK_SHIFT			5
-#define OMAP4430_DPLL_CLKOUT_DIVCHACK_MASK			BITFIELD(5, 5)
+#define OMAP4430_DPLL_CLKOUT_DIVCHACK_MASK			(1 << 5)
 
 /* Renamed from DPLL_CLKOUT_DIVCHACK Used by CM_DIV_M2_DPLL_USB */
 #define OMAP4430_DPLL_CLKOUT_DIVCHACK_M2_USB_SHIFT		7
-#define OMAP4430_DPLL_CLKOUT_DIVCHACK_M2_USB_MASK		BITFIELD(7, 7)
+#define OMAP4430_DPLL_CLKOUT_DIVCHACK_M2_USB_MASK		(1 << 7)
 
 /*
- * Used by CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_USB, CM_DIV_M2_DPLL_CORE_RESTORE,
- * CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE, CM_DIV_M2_DPLL_DDRPHY,
- * CM_DIV_M2_DPLL_MPU
+ * Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE,
+ * CM_DIV_M2_DPLL_CORE_RESTORE, CM_DIV_M2_DPLL_DDRPHY, CM_DIV_M2_DPLL_MPU,
+ * CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_USB
  */
 #define OMAP4430_DPLL_CLKOUT_GATE_CTRL_SHIFT			8
-#define OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK			BITFIELD(8, 8)
+#define OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK			(1 << 8)
 
-/* Used by CM_SHADOW_FREQ_CONFIG1_RESTORE, CM_SHADOW_FREQ_CONFIG1 */
+/* Used by CM_SHADOW_FREQ_CONFIG1, CM_SHADOW_FREQ_CONFIG1_RESTORE */
 #define OMAP4430_DPLL_CORE_DPLL_EN_SHIFT			8
-#define OMAP4430_DPLL_CORE_DPLL_EN_MASK				BITFIELD(8, 10)
+#define OMAP4430_DPLL_CORE_DPLL_EN_MASK				(0x7 << 8)
 
-/* Used by CM_SHADOW_FREQ_CONFIG1_RESTORE, CM_SHADOW_FREQ_CONFIG1 */
+/* Used by CM_SHADOW_FREQ_CONFIG1, CM_SHADOW_FREQ_CONFIG1_RESTORE */
 #define OMAP4430_DPLL_CORE_M2_DIV_SHIFT				11
-#define OMAP4430_DPLL_CORE_M2_DIV_MASK				BITFIELD(11, 15)
+#define OMAP4430_DPLL_CORE_M2_DIV_MASK				(0x1f << 11)
 
-/* Used by CM_SHADOW_FREQ_CONFIG2 */
+/* Used by CM_SHADOW_FREQ_CONFIG2, CM_SHADOW_FREQ_CONFIG2_RESTORE */
 #define OMAP4430_DPLL_CORE_M5_DIV_SHIFT				3
-#define OMAP4430_DPLL_CORE_M5_DIV_MASK				BITFIELD(3, 7)
-
-/* Used by CM_SHADOW_FREQ_CONFIG1_RESTORE, CM_SHADOW_FREQ_CONFIG1 */
-#define OMAP4430_DPLL_CORE_SYS_REF_CLKSEL_SHIFT			1
-#define OMAP4430_DPLL_CORE_SYS_REF_CLKSEL_MASK			BITFIELD(1, 1)
+#define OMAP4430_DPLL_CORE_M5_DIV_MASK				(0x1f << 3)
 
 /*
- * Used by CM_CLKSEL_DPLL_PER, CM_CLKSEL_DPLL_UNIPRO,
- * CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE,
- * CM_CLKSEL_DPLL_DDRPHY, CM_CLKSEL_DPLL_IVA, CM_CLKSEL_DPLL_MPU
+ * Used by CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE,
+ * CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_DDRPHY, CM_CLKSEL_DPLL_IVA,
+ * CM_CLKSEL_DPLL_MPU, CM_CLKSEL_DPLL_PER, CM_CLKSEL_DPLL_UNIPRO
  */
 #define OMAP4430_DPLL_DIV_SHIFT					0
-#define OMAP4430_DPLL_DIV_MASK					BITFIELD(0, 6)
+#define OMAP4430_DPLL_DIV_MASK					(0x7f << 0)
 
 /* Renamed from DPLL_DIV Used by CM_CLKSEL_DPLL_USB */
 #define OMAP4430_DPLL_DIV_0_7_SHIFT				0
-#define OMAP4430_DPLL_DIV_0_7_MASK				BITFIELD(0, 7)
+#define OMAP4430_DPLL_DIV_0_7_MASK				(0xff << 0)
 
 /*
- * Used by CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_USB,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
+ * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
+ * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER
  */
 #define OMAP4430_DPLL_DRIFTGUARD_EN_SHIFT			8
-#define OMAP4430_DPLL_DRIFTGUARD_EN_MASK			BITFIELD(8, 8)
+#define OMAP4430_DPLL_DRIFTGUARD_EN_MASK			(1 << 8)
 
 /* Renamed from DPLL_DRIFTGUARD_EN Used by CM_CLKMODE_DPLL_UNIPRO */
 #define OMAP4430_DPLL_DRIFTGUARD_EN_3_3_SHIFT			3
-#define OMAP4430_DPLL_DRIFTGUARD_EN_3_3_MASK			BITFIELD(3, 3)
+#define OMAP4430_DPLL_DRIFTGUARD_EN_3_3_MASK			(1 << 3)
 
 /*
- * Used by CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO, CM_CLKMODE_DPLL_USB,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
+ * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
+ * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO,
+ * CM_CLKMODE_DPLL_USB
  */
 #define OMAP4430_DPLL_EN_SHIFT					0
-#define OMAP4430_DPLL_EN_MASK					BITFIELD(0, 2)
+#define OMAP4430_DPLL_EN_MASK					(0x7 << 0)
 
 /*
- * Used by CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
+ * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
+ * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO
  */
 #define OMAP4430_DPLL_LPMODE_EN_SHIFT				10
-#define OMAP4430_DPLL_LPMODE_EN_MASK				BITFIELD(10, 10)
+#define OMAP4430_DPLL_LPMODE_EN_MASK				(1 << 10)
 
 /*
- * Used by CM_CLKSEL_DPLL_PER, CM_CLKSEL_DPLL_UNIPRO,
- * CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE,
- * CM_CLKSEL_DPLL_DDRPHY, CM_CLKSEL_DPLL_IVA, CM_CLKSEL_DPLL_MPU
+ * Used by CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE,
+ * CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_DDRPHY, CM_CLKSEL_DPLL_IVA,
+ * CM_CLKSEL_DPLL_MPU, CM_CLKSEL_DPLL_PER, CM_CLKSEL_DPLL_UNIPRO
  */
 #define OMAP4430_DPLL_MULT_SHIFT				8
-#define OMAP4430_DPLL_MULT_MASK					BITFIELD(8, 18)
+#define OMAP4430_DPLL_MULT_MASK					(0x7ff << 8)
 
 /* Renamed from DPLL_MULT Used by CM_CLKSEL_DPLL_USB */
 #define OMAP4430_DPLL_MULT_USB_SHIFT				8
-#define OMAP4430_DPLL_MULT_USB_MASK				BITFIELD(8, 19)
+#define OMAP4430_DPLL_MULT_USB_MASK				(0xfff << 8)
 
 /*
- * Used by CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
+ * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
+ * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO
  */
 #define OMAP4430_DPLL_REGM4XEN_SHIFT				11
-#define OMAP4430_DPLL_REGM4XEN_MASK				BITFIELD(11, 11)
+#define OMAP4430_DPLL_REGM4XEN_MASK				(1 << 11)
 
 /* Used by CM_CLKSEL_DPLL_USB */
 #define OMAP4430_DPLL_SD_DIV_SHIFT				24
-#define OMAP4430_DPLL_SD_DIV_MASK				BITFIELD(24, 31)
+#define OMAP4430_DPLL_SD_DIV_MASK				(0xff << 24)
 
 /*
- * Used by CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO, CM_CLKMODE_DPLL_USB,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
+ * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
+ * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO,
+ * CM_CLKMODE_DPLL_USB
  */
 #define OMAP4430_DPLL_SSC_ACK_SHIFT				13
-#define OMAP4430_DPLL_SSC_ACK_MASK				BITFIELD(13, 13)
+#define OMAP4430_DPLL_SSC_ACK_MASK				(1 << 13)
 
 /*
- * Used by CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO, CM_CLKMODE_DPLL_USB,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
+ * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
+ * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO,
+ * CM_CLKMODE_DPLL_USB
  */
 #define OMAP4430_DPLL_SSC_DOWNSPREAD_SHIFT			14
-#define OMAP4430_DPLL_SSC_DOWNSPREAD_MASK			BITFIELD(14, 14)
+#define OMAP4430_DPLL_SSC_DOWNSPREAD_MASK			(1 << 14)
 
 /*
- * Used by CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO, CM_CLKMODE_DPLL_USB,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
+ * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
+ * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO,
+ * CM_CLKMODE_DPLL_USB
  */
 #define OMAP4430_DPLL_SSC_EN_SHIFT				12
-#define OMAP4430_DPLL_SSC_EN_MASK				BITFIELD(12, 12)
-
-/* Used by CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP, CM_L4PER_DYNAMICDEP */
-#define OMAP4430_DSS_DYNDEP_SHIFT				8
-#define OMAP4430_DSS_DYNDEP_MASK				BITFIELD(8, 8)
+#define OMAP4430_DPLL_SSC_EN_MASK				(1 << 12)
 
 /*
- * Used by CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE,
- * CM_MPU_STATICDEP
+ * Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
+ * CM_L4CFG_DYNAMICDEP_RESTORE, CM_L4PER_DYNAMICDEP, CM_L4PER_DYNAMICDEP_RESTORE
+ */
+#define OMAP4430_DSS_DYNDEP_SHIFT				8
+#define OMAP4430_DSS_DYNDEP_MASK				(1 << 8)
+
+/*
+ * Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP,
+ * CM_SDMA_STATICDEP_RESTORE
  */
 #define OMAP4430_DSS_STATDEP_SHIFT				8
-#define OMAP4430_DSS_STATDEP_MASK				BITFIELD(8, 8)
+#define OMAP4430_DSS_STATDEP_MASK				(1 << 8)
 
-/* Used by CM_L3_2_DYNAMICDEP */
+/* Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE */
 #define OMAP4430_DUCATI_DYNDEP_SHIFT				0
-#define OMAP4430_DUCATI_DYNDEP_MASK				BITFIELD(0, 0)
+#define OMAP4430_DUCATI_DYNDEP_MASK				(1 << 0)
 
-/* Used by CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_MPU_STATICDEP */
+/* Used by CM_MPU_STATICDEP, CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE */
 #define OMAP4430_DUCATI_STATDEP_SHIFT				0
-#define OMAP4430_DUCATI_STATDEP_MASK				BITFIELD(0, 0)
+#define OMAP4430_DUCATI_STATDEP_MASK				(1 << 0)
 
-/* Used by CM_SHADOW_FREQ_CONFIG1_RESTORE, CM_SHADOW_FREQ_CONFIG1 */
+/* Used by CM_SHADOW_FREQ_CONFIG1, CM_SHADOW_FREQ_CONFIG1_RESTORE */
 #define OMAP4430_FREQ_UPDATE_SHIFT				0
-#define OMAP4430_FREQ_UPDATE_MASK				BITFIELD(0, 0)
+#define OMAP4430_FREQ_UPDATE_MASK				(1 << 0)
 
-/* Used by CM_L3_2_DYNAMICDEP */
+/* Used by REVISION_CM1, REVISION_CM2 */
+#define OMAP4430_FUNC_SHIFT					16
+#define OMAP4430_FUNC_MASK					(0xfff << 16)
+
+/* Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE */
 #define OMAP4430_GFX_DYNDEP_SHIFT				10
-#define OMAP4430_GFX_DYNDEP_MASK				BITFIELD(10, 10)
+#define OMAP4430_GFX_DYNDEP_MASK				(1 << 10)
 
 /* Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP */
 #define OMAP4430_GFX_STATDEP_SHIFT				10
-#define OMAP4430_GFX_STATDEP_MASK				BITFIELD(10, 10)
+#define OMAP4430_GFX_STATDEP_MASK				(1 << 10)
 
-/* Used by CM_SHADOW_FREQ_CONFIG2 */
+/* Used by CM_SHADOW_FREQ_CONFIG2, CM_SHADOW_FREQ_CONFIG2_RESTORE */
 #define OMAP4430_GPMC_FREQ_UPDATE_SHIFT				0
-#define OMAP4430_GPMC_FREQ_UPDATE_MASK				BITFIELD(0, 0)
+#define OMAP4430_GPMC_FREQ_UPDATE_MASK				(1 << 0)
 
 /*
- * Used by CM_DIV_M4_DPLL_PER, CM_DIV_M4_DPLL_CORE_RESTORE,
- * CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA
+ * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_CORE_RESTORE,
+ * CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA, CM_DIV_M4_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT1_DIV_SHIFT			0
-#define OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK			BITFIELD(0, 4)
+#define OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK			(0x1f << 0)
 
 /*
- * Used by CM_DIV_M4_DPLL_PER, CM_DIV_M4_DPLL_CORE_RESTORE,
- * CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA
+ * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_CORE_RESTORE,
+ * CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA, CM_DIV_M4_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT1_DIVCHACK_SHIFT		5
-#define OMAP4430_HSDIVIDER_CLKOUT1_DIVCHACK_MASK		BITFIELD(5, 5)
+#define OMAP4430_HSDIVIDER_CLKOUT1_DIVCHACK_MASK		(1 << 5)
 
 /*
- * Used by CM_DIV_M4_DPLL_PER, CM_DIV_M4_DPLL_CORE_RESTORE,
- * CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA
+ * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_CORE_RESTORE,
+ * CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA, CM_DIV_M4_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT1_GATE_CTRL_SHIFT		8
-#define OMAP4430_HSDIVIDER_CLKOUT1_GATE_CTRL_MASK		BITFIELD(8, 8)
+#define OMAP4430_HSDIVIDER_CLKOUT1_GATE_CTRL_MASK		(1 << 8)
 
 /*
- * Used by CM_DIV_M4_DPLL_PER, CM_DIV_M4_DPLL_CORE_RESTORE,
- * CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA
+ * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_CORE_RESTORE,
+ * CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA, CM_DIV_M4_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT1_PWDN_SHIFT			12
-#define OMAP4430_HSDIVIDER_CLKOUT1_PWDN_MASK			BITFIELD(12, 12)
+#define OMAP4430_HSDIVIDER_CLKOUT1_PWDN_MASK			(1 << 12)
 
 /*
- * Used by CM_DIV_M5_DPLL_PER, CM_DIV_M5_DPLL_CORE_RESTORE,
- * CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA
+ * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_CORE_RESTORE,
+ * CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA, CM_DIV_M5_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT2_DIV_SHIFT			0
-#define OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK			BITFIELD(0, 4)
+#define OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK			(0x1f << 0)
 
 /*
- * Used by CM_DIV_M5_DPLL_PER, CM_DIV_M5_DPLL_CORE_RESTORE,
- * CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA
+ * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_CORE_RESTORE,
+ * CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA, CM_DIV_M5_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT2_DIVCHACK_SHIFT		5
-#define OMAP4430_HSDIVIDER_CLKOUT2_DIVCHACK_MASK		BITFIELD(5, 5)
+#define OMAP4430_HSDIVIDER_CLKOUT2_DIVCHACK_MASK		(1 << 5)
 
 /*
- * Used by CM_DIV_M5_DPLL_PER, CM_DIV_M5_DPLL_CORE_RESTORE,
- * CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA
+ * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_CORE_RESTORE,
+ * CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA, CM_DIV_M5_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT2_GATE_CTRL_SHIFT		8
-#define OMAP4430_HSDIVIDER_CLKOUT2_GATE_CTRL_MASK		BITFIELD(8, 8)
+#define OMAP4430_HSDIVIDER_CLKOUT2_GATE_CTRL_MASK		(1 << 8)
 
 /*
- * Used by CM_DIV_M5_DPLL_PER, CM_DIV_M5_DPLL_CORE_RESTORE,
- * CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA
+ * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_CORE_RESTORE,
+ * CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA, CM_DIV_M5_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT2_PWDN_SHIFT			12
-#define OMAP4430_HSDIVIDER_CLKOUT2_PWDN_MASK			BITFIELD(12, 12)
+#define OMAP4430_HSDIVIDER_CLKOUT2_PWDN_MASK			(1 << 12)
 
 /*
- * Used by CM_DIV_M6_DPLL_PER, CM_DIV_M6_DPLL_CORE_RESTORE,
- * CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY
+ * Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_CORE_RESTORE,
+ * CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT3_DIV_SHIFT			0
-#define OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK			BITFIELD(0, 4)
+#define OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK			(0x1f << 0)
 
 /*
- * Used by CM_DIV_M6_DPLL_PER, CM_DIV_M6_DPLL_CORE_RESTORE,
- * CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY
+ * Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_CORE_RESTORE,
+ * CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT3_DIVCHACK_SHIFT		5
-#define OMAP4430_HSDIVIDER_CLKOUT3_DIVCHACK_MASK		BITFIELD(5, 5)
+#define OMAP4430_HSDIVIDER_CLKOUT3_DIVCHACK_MASK		(1 << 5)
 
 /*
- * Used by CM_DIV_M6_DPLL_PER, CM_DIV_M6_DPLL_CORE_RESTORE,
- * CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY
+ * Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_CORE_RESTORE,
+ * CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT3_GATE_CTRL_SHIFT		8
-#define OMAP4430_HSDIVIDER_CLKOUT3_GATE_CTRL_MASK		BITFIELD(8, 8)
+#define OMAP4430_HSDIVIDER_CLKOUT3_GATE_CTRL_MASK		(1 << 8)
 
 /*
- * Used by CM_DIV_M6_DPLL_PER, CM_DIV_M6_DPLL_CORE_RESTORE,
- * CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY
+ * Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_CORE_RESTORE,
+ * CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT3_PWDN_SHIFT			12
-#define OMAP4430_HSDIVIDER_CLKOUT3_PWDN_MASK			BITFIELD(12, 12)
+#define OMAP4430_HSDIVIDER_CLKOUT3_PWDN_MASK			(1 << 12)
 
 /*
- * Used by CM_DIV_M7_DPLL_PER, CM_DIV_M7_DPLL_CORE_RESTORE,
- * CM_DIV_M7_DPLL_CORE
+ * Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_CORE_RESTORE,
+ * CM_DIV_M7_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT4_DIV_SHIFT			0
-#define OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK			BITFIELD(0, 4)
+#define OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK			(0x1f << 0)
 
 /*
- * Used by CM_DIV_M7_DPLL_PER, CM_DIV_M7_DPLL_CORE_RESTORE,
- * CM_DIV_M7_DPLL_CORE
+ * Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_CORE_RESTORE,
+ * CM_DIV_M7_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT4_DIVCHACK_SHIFT		5
-#define OMAP4430_HSDIVIDER_CLKOUT4_DIVCHACK_MASK		BITFIELD(5, 5)
+#define OMAP4430_HSDIVIDER_CLKOUT4_DIVCHACK_MASK		(1 << 5)
 
 /*
- * Used by CM_DIV_M7_DPLL_PER, CM_DIV_M7_DPLL_CORE_RESTORE,
- * CM_DIV_M7_DPLL_CORE
+ * Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_CORE_RESTORE,
+ * CM_DIV_M7_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT4_GATE_CTRL_SHIFT		8
-#define OMAP4430_HSDIVIDER_CLKOUT4_GATE_CTRL_MASK		BITFIELD(8, 8)
+#define OMAP4430_HSDIVIDER_CLKOUT4_GATE_CTRL_MASK		(1 << 8)
 
 /*
- * Used by CM_DIV_M7_DPLL_PER, CM_DIV_M7_DPLL_CORE_RESTORE,
- * CM_DIV_M7_DPLL_CORE
+ * Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_CORE_RESTORE,
+ * CM_DIV_M7_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT4_PWDN_SHIFT			12
-#define OMAP4430_HSDIVIDER_CLKOUT4_PWDN_MASK			BITFIELD(12, 12)
+#define OMAP4430_HSDIVIDER_CLKOUT4_PWDN_MASK			(1 << 12)
 
 /*
- * Used by PRM_PRM_PROFILING_CLKCTRL, CM_WKUP_GPIO1_CLKCTRL,
- * CM_WKUP_KEYBOARD_CLKCTRL, CM_WKUP_L4WKUP_CLKCTRL, CM_WKUP_RTC_CLKCTRL,
- * CM_WKUP_SARRAM_CLKCTRL, CM_WKUP_SYNCTIMER_CLKCTRL, CM_WKUP_TIMER12_CLKCTRL,
- * CM_WKUP_TIMER1_CLKCTRL, CM_WKUP_USIM_CLKCTRL, CM_WKUP_WDT1_CLKCTRL,
- * CM_WKUP_WDT2_CLKCTRL, CM_EMU_DEBUGSS_CLKCTRL, CM_D2D_MODEM_ICR_CLKCTRL,
- * CM_D2D_SAD2D_CLKCTRL, CM_D2D_SAD2D_FW_CLKCTRL, CM_DUCATI_DUCATI_CLKCTRL,
- * CM_L3INSTR_L3_3_CLKCTRL, CM_L3INSTR_L3_INSTR_CLKCTRL,
- * CM_L3INSTR_OCP_WP1_CLKCTRL, CM_L3_1_L3_1_CLKCTRL, CM_L3_2_GPMC_CLKCTRL,
- * CM_L3_2_L3_2_CLKCTRL, CM_L3_2_OCMC_RAM_CLKCTRL, CM_L4CFG_HW_SEM_CLKCTRL,
- * CM_L4CFG_L4_CFG_CLKCTRL, CM_L4CFG_MAILBOX_CLKCTRL, CM_L4CFG_SAR_ROM_CLKCTRL,
- * CM_MEMIF_DMM_CLKCTRL, CM_MEMIF_EMIF_1_CLKCTRL, CM_MEMIF_EMIF_2_CLKCTRL,
- * CM_MEMIF_EMIF_FW_CLKCTRL, CM_MEMIF_EMIF_H1_CLKCTRL,
- * CM_MEMIF_EMIF_H2_CLKCTRL, CM_SDMA_SDMA_CLKCTRL, CM_GFX_GFX_CLKCTRL,
- * CM_L4PER_ADC_CLKCTRL, CM_L4PER_DMTIMER10_CLKCTRL,
- * CM_L4PER_DMTIMER11_CLKCTRL, CM_L4PER_DMTIMER2_CLKCTRL,
- * CM_L4PER_DMTIMER3_CLKCTRL, CM_L4PER_DMTIMER4_CLKCTRL,
- * CM_L4PER_DMTIMER9_CLKCTRL, CM_L4PER_ELM_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL,
- * CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL, CM_L4PER_GPIO5_CLKCTRL,
- * CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_HDQ1W_CLKCTRL, CM_L4PER_HECC1_CLKCTRL,
- * CM_L4PER_HECC2_CLKCTRL, CM_L4PER_I2C1_CLKCTRL, CM_L4PER_I2C2_CLKCTRL,
- * CM_L4PER_I2C3_CLKCTRL, CM_L4PER_I2C4_CLKCTRL, CM_L4PER_I2C5_CLKCTRL,
- * CM_L4PER_L4PER_CLKCTRL, CM_L4PER_MCASP2_CLKCTRL, CM_L4PER_MCASP3_CLKCTRL,
- * CM_L4PER_MCBSP4_CLKCTRL, CM_L4PER_MCSPI1_CLKCTRL, CM_L4PER_MCSPI2_CLKCTRL,
- * CM_L4PER_MCSPI3_CLKCTRL, CM_L4PER_MCSPI4_CLKCTRL, CM_L4PER_MGATE_CLKCTRL,
- * CM_L4PER_MMCSD3_CLKCTRL, CM_L4PER_MMCSD4_CLKCTRL, CM_L4PER_MMCSD5_CLKCTRL,
- * CM_L4PER_MSPROHG_CLKCTRL, CM_L4PER_SLIMBUS2_CLKCTRL, CM_L4PER_UART1_CLKCTRL,
- * CM_L4PER_UART2_CLKCTRL, CM_L4PER_UART3_CLKCTRL, CM_L4PER_UART4_CLKCTRL,
- * CM_L4SEC_AES1_CLKCTRL, CM_L4SEC_AES2_CLKCTRL, CM_L4SEC_CRYPTODMA_CLKCTRL,
- * CM_L4SEC_DES3DES_CLKCTRL, CM_L4SEC_PKAEIP29_CLKCTRL, CM_L4SEC_RNG_CLKCTRL,
- * CM_L4SEC_SHA2MD51_CLKCTRL, CM_L3INIT_CCPTX_CLKCTRL, CM_L3INIT_EMAC_CLKCTRL,
+ * Used by CM1_ABE_AESS_CLKCTRL, CM1_ABE_DMIC_CLKCTRL, CM1_ABE_L4ABE_CLKCTRL,
+ * CM1_ABE_MCASP_CLKCTRL, CM1_ABE_MCBSP1_CLKCTRL, CM1_ABE_MCBSP2_CLKCTRL,
+ * CM1_ABE_MCBSP3_CLKCTRL, CM1_ABE_PDM_CLKCTRL, CM1_ABE_SLIMBUS_CLKCTRL,
+ * CM1_ABE_TIMER5_CLKCTRL, CM1_ABE_TIMER6_CLKCTRL, CM1_ABE_TIMER7_CLKCTRL,
+ * CM1_ABE_TIMER8_CLKCTRL, CM1_ABE_WDT3_CLKCTRL, CM_ALWON_MDMINTC_CLKCTRL,
+ * CM_ALWON_SR_CORE_CLKCTRL, CM_ALWON_SR_IVA_CLKCTRL, CM_ALWON_SR_MPU_CLKCTRL,
+ * CM_CAM_FDIF_CLKCTRL, CM_CAM_ISS_CLKCTRL, CM_CEFUSE_CEFUSE_CLKCTRL,
+ * CM_CM1_PROFILING_CLKCTRL, CM_CM1_PROFILING_CLKCTRL_RESTORE,
+ * CM_CM2_PROFILING_CLKCTRL, CM_CM2_PROFILING_CLKCTRL_RESTORE,
+ * CM_D2D_MODEM_ICR_CLKCTRL, CM_D2D_SAD2D_CLKCTRL, CM_D2D_SAD2D_FW_CLKCTRL,
+ * CM_DSS_DEISS_CLKCTRL, CM_DSS_DSS_CLKCTRL, CM_DUCATI_DUCATI_CLKCTRL,
+ * CM_EMU_DEBUGSS_CLKCTRL, CM_GFX_GFX_CLKCTRL, CM_IVAHD_IVAHD_CLKCTRL,
+ * CM_IVAHD_SL2_CLKCTRL, CM_L3INIT_CCPTX_CLKCTRL, CM_L3INIT_EMAC_CLKCTRL,
  * CM_L3INIT_HSI_CLKCTRL, CM_L3INIT_MMC1_CLKCTRL, CM_L3INIT_MMC2_CLKCTRL,
  * CM_L3INIT_MMC6_CLKCTRL, CM_L3INIT_P1500_CLKCTRL, CM_L3INIT_PCIESS_CLKCTRL,
  * CM_L3INIT_SATA_CLKCTRL, CM_L3INIT_TPPSS_CLKCTRL, CM_L3INIT_UNIPRO1_CLKCTRL,
  * CM_L3INIT_USBPHYOCP2SCP_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL,
- * CM_L3INIT_USB_HOST_FS_CLKCTRL, CM_L3INIT_USB_OTG_CLKCTRL,
- * CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_XHPI_CLKCTRL, CM_CAM_FDIF_CLKCTRL,
- * CM_CAM_ISS_CLKCTRL, CM_CEFUSE_CEFUSE_CLKCTRL,
- * CM_L3INIT_USB_HOST_CLKCTRL_RESTORE, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE,
- * CM_L3INSTR_L3_3_CLKCTRL_RESTORE, CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE,
- * CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE, CM_L4PER_GPIO2_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO3_CLKCTRL_RESTORE, CM_L4PER_GPIO4_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO5_CLKCTRL_RESTORE, CM_L4PER_GPIO6_CLKCTRL_RESTORE,
- * CM_ALWON_MDMINTC_CLKCTRL, CM_ALWON_SR_CORE_CLKCTRL, CM_ALWON_SR_IVA_CLKCTRL,
- * CM_ALWON_SR_MPU_CLKCTRL, CM_IVAHD_IVAHD_CLKCTRL, CM_IVAHD_SL2_CLKCTRL,
- * CM_DSS_DEISS_CLKCTRL, CM_DSS_DSS_CLKCTRL, CM_CM2_PROFILING_CLKCTRL,
- * CM_MPU_MPU_CLKCTRL, CM_TESLA_TESLA_CLKCTRL, CM1_ABE_AESS_CLKCTRL,
- * CM1_ABE_DMIC_CLKCTRL, CM1_ABE_L4ABE_CLKCTRL, CM1_ABE_MCASP_CLKCTRL,
- * CM1_ABE_MCBSP1_CLKCTRL, CM1_ABE_MCBSP2_CLKCTRL, CM1_ABE_MCBSP3_CLKCTRL,
- * CM1_ABE_PDM_CLKCTRL, CM1_ABE_SLIMBUS_CLKCTRL, CM1_ABE_TIMER5_CLKCTRL,
- * CM1_ABE_TIMER6_CLKCTRL, CM1_ABE_TIMER7_CLKCTRL, CM1_ABE_TIMER8_CLKCTRL,
- * CM1_ABE_WDT3_CLKCTRL, CM_CM1_PROFILING_CLKCTRL
+ * CM_L3INIT_USB_HOST_CLKCTRL_RESTORE, CM_L3INIT_USB_HOST_FS_CLKCTRL,
+ * CM_L3INIT_USB_OTG_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL,
+ * CM_L3INIT_USB_TLL_CLKCTRL_RESTORE, CM_L3INIT_XHPI_CLKCTRL,
+ * CM_L3INSTR_L3_3_CLKCTRL, CM_L3INSTR_L3_3_CLKCTRL_RESTORE,
+ * CM_L3INSTR_L3_INSTR_CLKCTRL, CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE,
+ * CM_L3INSTR_OCP_WP1_CLKCTRL, CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE,
+ * CM_L3_1_L3_1_CLKCTRL, CM_L3_2_GPMC_CLKCTRL, CM_L3_2_L3_2_CLKCTRL,
+ * CM_L3_2_OCMC_RAM_CLKCTRL, CM_L4CFG_HW_SEM_CLKCTRL, CM_L4CFG_L4_CFG_CLKCTRL,
+ * CM_L4CFG_MAILBOX_CLKCTRL, CM_L4CFG_SAR_ROM_CLKCTRL, CM_L4PER_ADC_CLKCTRL,
+ * CM_L4PER_DMTIMER10_CLKCTRL, CM_L4PER_DMTIMER11_CLKCTRL,
+ * CM_L4PER_DMTIMER2_CLKCTRL, CM_L4PER_DMTIMER3_CLKCTRL,
+ * CM_L4PER_DMTIMER4_CLKCTRL, CM_L4PER_DMTIMER9_CLKCTRL, CM_L4PER_ELM_CLKCTRL,
+ * CM_L4PER_GPIO2_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO3_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO4_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO5_CLKCTRL, CM_L4PER_GPIO5_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_GPIO6_CLKCTRL_RESTORE,
+ * CM_L4PER_HDQ1W_CLKCTRL, CM_L4PER_HECC1_CLKCTRL, CM_L4PER_HECC2_CLKCTRL,
+ * CM_L4PER_I2C1_CLKCTRL, CM_L4PER_I2C2_CLKCTRL, CM_L4PER_I2C3_CLKCTRL,
+ * CM_L4PER_I2C4_CLKCTRL, CM_L4PER_I2C5_CLKCTRL, CM_L4PER_L4PER_CLKCTRL,
+ * CM_L4PER_MCASP2_CLKCTRL, CM_L4PER_MCASP3_CLKCTRL, CM_L4PER_MCBSP4_CLKCTRL,
+ * CM_L4PER_MCSPI1_CLKCTRL, CM_L4PER_MCSPI2_CLKCTRL, CM_L4PER_MCSPI3_CLKCTRL,
+ * CM_L4PER_MCSPI4_CLKCTRL, CM_L4PER_MGATE_CLKCTRL, CM_L4PER_MMCSD3_CLKCTRL,
+ * CM_L4PER_MMCSD4_CLKCTRL, CM_L4PER_MMCSD5_CLKCTRL, CM_L4PER_MSPROHG_CLKCTRL,
+ * CM_L4PER_SLIMBUS2_CLKCTRL, CM_L4PER_UART1_CLKCTRL, CM_L4PER_UART2_CLKCTRL,
+ * CM_L4PER_UART3_CLKCTRL, CM_L4PER_UART4_CLKCTRL, CM_L4SEC_AES1_CLKCTRL,
+ * CM_L4SEC_AES2_CLKCTRL, CM_L4SEC_CRYPTODMA_CLKCTRL, CM_L4SEC_DES3DES_CLKCTRL,
+ * CM_L4SEC_PKAEIP29_CLKCTRL, CM_L4SEC_RNG_CLKCTRL, CM_L4SEC_SHA2MD51_CLKCTRL,
+ * CM_MEMIF_DMM_CLKCTRL, CM_MEMIF_EMIF_1_CLKCTRL, CM_MEMIF_EMIF_2_CLKCTRL,
+ * CM_MEMIF_EMIF_FW_CLKCTRL, CM_MEMIF_EMIF_H1_CLKCTRL,
+ * CM_MEMIF_EMIF_H2_CLKCTRL, CM_MPU_MPU_CLKCTRL, CM_SDMA_SDMA_CLKCTRL,
+ * CM_TESLA_TESLA_CLKCTRL, CM_WKUP_GPIO1_CLKCTRL, CM_WKUP_KEYBOARD_CLKCTRL,
+ * CM_WKUP_L4WKUP_CLKCTRL, CM_WKUP_RTC_CLKCTRL, CM_WKUP_SARRAM_CLKCTRL,
+ * CM_WKUP_SYNCTIMER_CLKCTRL, CM_WKUP_TIMER12_CLKCTRL, CM_WKUP_TIMER1_CLKCTRL,
+ * CM_WKUP_USIM_CLKCTRL, CM_WKUP_WDT1_CLKCTRL, CM_WKUP_WDT2_CLKCTRL
  */
 #define OMAP4430_IDLEST_SHIFT					16
-#define OMAP4430_IDLEST_MASK					BITFIELD(16, 17)
-
-/* Used by CM_DUCATI_DYNAMICDEP, CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP */
-#define OMAP4430_ISS_DYNDEP_SHIFT				9
-#define OMAP4430_ISS_DYNDEP_MASK				BITFIELD(9, 9)
+#define OMAP4430_IDLEST_MASK					(0x3 << 16)
 
 /*
- * Used by CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE,
- * CM_MPU_STATICDEP, CM_TESLA_STATICDEP
+ * Used by CM_DUCATI_DYNAMICDEP, CM_L3_2_DYNAMICDEP,
+ * CM_L3_2_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP, CM_L4CFG_DYNAMICDEP_RESTORE
+ */
+#define OMAP4430_ISS_DYNDEP_SHIFT				9
+#define OMAP4430_ISS_DYNDEP_MASK				(1 << 9)
+
+/*
+ * Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP,
+ * CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
  */
 #define OMAP4430_ISS_STATDEP_SHIFT				9
-#define OMAP4430_ISS_STATDEP_MASK				BITFIELD(9, 9)
+#define OMAP4430_ISS_STATDEP_MASK				(1 << 9)
 
-/* Used by CM_L3_2_DYNAMICDEP, CM_TESLA_DYNAMICDEP */
+/* Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE, CM_TESLA_DYNAMICDEP */
 #define OMAP4430_IVAHD_DYNDEP_SHIFT				2
-#define OMAP4430_IVAHD_DYNDEP_MASK				BITFIELD(2, 2)
+#define OMAP4430_IVAHD_DYNDEP_MASK				(1 << 2)
 
 /*
- * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP,
- * CM_GFX_STATICDEP, CM_L3INIT_STATICDEP, CM_CAM_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE, CM_DSS_STATICDEP, CM_MPU_STATICDEP,
- * CM_TESLA_STATICDEP
+ * Used by CM_CAM_STATICDEP, CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE,
+ * CM_DSS_STATICDEP, CM_DUCATI_STATICDEP, CM_GFX_STATICDEP,
+ * CM_L3INIT_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP,
+ * CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
  */
 #define OMAP4430_IVAHD_STATDEP_SHIFT				2
-#define OMAP4430_IVAHD_STATDEP_MASK				BITFIELD(2, 2)
+#define OMAP4430_IVAHD_STATDEP_MASK				(1 << 2)
 
-/* Used by CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP, CM_L4PER_DYNAMICDEP */
+/*
+ * Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
+ * CM_L4CFG_DYNAMICDEP_RESTORE, CM_L4PER_DYNAMICDEP, CM_L4PER_DYNAMICDEP_RESTORE
+ */
 #define OMAP4430_L3INIT_DYNDEP_SHIFT				7
-#define OMAP4430_L3INIT_DYNDEP_MASK				BITFIELD(7, 7)
+#define OMAP4430_L3INIT_DYNDEP_MASK				(1 << 7)
 
 /*
- * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE, CM_MPU_STATICDEP, CM_TESLA_STATICDEP
- */
-#define OMAP4430_L3INIT_STATDEP_SHIFT				7
-#define OMAP4430_L3INIT_STATDEP_MASK				BITFIELD(7, 7)
-
-/*
- * Used by CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP, CM_L3INIT_DYNAMICDEP,
- * CM_DSS_DYNAMICDEP, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP
- */
-#define OMAP4430_L3_1_DYNDEP_SHIFT				5
-#define OMAP4430_L3_1_DYNDEP_MASK				BITFIELD(5, 5)
-
-/*
- * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP,
- * CM_GFX_STATICDEP, CM_L4SEC_STATICDEP, CM_L3INIT_STATICDEP, CM_CAM_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE, CM_IVAHD_STATICDEP, CM_DSS_STATICDEP,
- * CM_MPU_STATICDEP, CM_TESLA_STATICDEP
- */
-#define OMAP4430_L3_1_STATDEP_SHIFT				5
-#define OMAP4430_L3_1_STATDEP_MASK				BITFIELD(5, 5)
-
-/*
- * Used by CM_EMU_DYNAMICDEP, CM_D2D_DYNAMICDEP, CM_DUCATI_DYNAMICDEP,
- * CM_L3_1_DYNAMICDEP, CM_L4CFG_DYNAMICDEP, CM_SDMA_DYNAMICDEP,
- * CM_GFX_DYNAMICDEP, CM_L4SEC_DYNAMICDEP, CM_L3INIT_DYNAMICDEP,
- * CM_CAM_DYNAMICDEP, CM_IVAHD_DYNAMICDEP
- */
-#define OMAP4430_L3_2_DYNDEP_SHIFT				6
-#define OMAP4430_L3_2_DYNDEP_MASK				BITFIELD(6, 6)
-
-/*
- * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP,
- * CM_GFX_STATICDEP, CM_L4SEC_STATICDEP, CM_L3INIT_STATICDEP, CM_CAM_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE, CM_IVAHD_STATICDEP, CM_DSS_STATICDEP,
- * CM_MPU_STATICDEP, CM_TESLA_STATICDEP
- */
-#define OMAP4430_L3_2_STATDEP_SHIFT				6
-#define OMAP4430_L3_2_STATDEP_MASK				BITFIELD(6, 6)
-
-/* Used by CM_L3_1_DYNAMICDEP */
-#define OMAP4430_L4CFG_DYNDEP_SHIFT				12
-#define OMAP4430_L4CFG_DYNDEP_MASK				BITFIELD(12, 12)
-
-/*
- * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP,
- * CM_L3INIT_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_MPU_STATICDEP,
+ * Used by CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE, CM_DUCATI_STATICDEP,
+ * CM_MPU_STATICDEP, CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE,
  * CM_TESLA_STATICDEP
  */
-#define OMAP4430_L4CFG_STATDEP_SHIFT				12
-#define OMAP4430_L4CFG_STATDEP_MASK				BITFIELD(12, 12)
-
-/* Used by CM_L3_2_DYNAMICDEP */
-#define OMAP4430_L4PER_DYNDEP_SHIFT				13
-#define OMAP4430_L4PER_DYNDEP_MASK				BITFIELD(13, 13)
+#define OMAP4430_L3INIT_STATDEP_SHIFT				7
+#define OMAP4430_L3INIT_STATDEP_MASK				(1 << 7)
 
 /*
- * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP,
- * CM_L4SEC_STATICDEP, CM_L3INIT_STATICDEP, CM_SDMA_STATICDEP_RESTORE,
- * CM_MPU_STATICDEP, CM_TESLA_STATICDEP
+ * Used by CM_DSS_DYNAMICDEP, CM_L3INIT_DYNAMICDEP, CM_L3_2_DYNAMICDEP,
+ * CM_L3_2_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
+ * CM_L4CFG_DYNAMICDEP_RESTORE, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP
+ */
+#define OMAP4430_L3_1_DYNDEP_SHIFT				5
+#define OMAP4430_L3_1_DYNDEP_MASK				(1 << 5)
+
+/*
+ * Used by CM_CAM_STATICDEP, CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE,
+ * CM_DSS_STATICDEP, CM_DUCATI_STATICDEP, CM_GFX_STATICDEP, CM_IVAHD_STATICDEP,
+ * CM_L3INIT_STATICDEP, CM_L4SEC_STATICDEP, CM_MPU_STATICDEP,
+ * CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
+ */
+#define OMAP4430_L3_1_STATDEP_SHIFT				5
+#define OMAP4430_L3_1_STATDEP_MASK				(1 << 5)
+
+/*
+ * Used by CM_CAM_DYNAMICDEP, CM_D2D_DYNAMICDEP, CM_D2D_DYNAMICDEP_RESTORE,
+ * CM_DUCATI_DYNAMICDEP, CM_EMU_DYNAMICDEP, CM_GFX_DYNAMICDEP,
+ * CM_IVAHD_DYNAMICDEP, CM_L3INIT_DYNAMICDEP, CM_L3_1_DYNAMICDEP,
+ * CM_L3_1_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
+ * CM_L4CFG_DYNAMICDEP_RESTORE, CM_L4SEC_DYNAMICDEP, CM_SDMA_DYNAMICDEP
+ */
+#define OMAP4430_L3_2_DYNDEP_SHIFT				6
+#define OMAP4430_L3_2_DYNDEP_MASK				(1 << 6)
+
+/*
+ * Used by CM_CAM_STATICDEP, CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE,
+ * CM_DSS_STATICDEP, CM_DUCATI_STATICDEP, CM_GFX_STATICDEP, CM_IVAHD_STATICDEP,
+ * CM_L3INIT_STATICDEP, CM_L4SEC_STATICDEP, CM_MPU_STATICDEP,
+ * CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
+ */
+#define OMAP4430_L3_2_STATDEP_SHIFT				6
+#define OMAP4430_L3_2_STATDEP_MASK				(1 << 6)
+
+/* Used by CM_L3_1_DYNAMICDEP, CM_L3_1_DYNAMICDEP_RESTORE */
+#define OMAP4430_L4CFG_DYNDEP_SHIFT				12
+#define OMAP4430_L4CFG_DYNDEP_MASK				(1 << 12)
+
+/*
+ * Used by CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE, CM_DUCATI_STATICDEP,
+ * CM_L3INIT_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP,
+ * CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
+ */
+#define OMAP4430_L4CFG_STATDEP_SHIFT				12
+#define OMAP4430_L4CFG_STATDEP_MASK				(1 << 12)
+
+/* Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE */
+#define OMAP4430_L4PER_DYNDEP_SHIFT				13
+#define OMAP4430_L4PER_DYNDEP_MASK				(1 << 13)
+
+/*
+ * Used by CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE, CM_DUCATI_STATICDEP,
+ * CM_L3INIT_STATICDEP, CM_L4SEC_STATICDEP, CM_MPU_STATICDEP,
+ * CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
  */
 #define OMAP4430_L4PER_STATDEP_SHIFT				13
-#define OMAP4430_L4PER_STATDEP_MASK				BITFIELD(13, 13)
-
-/* Used by CM_L3_2_DYNAMICDEP, CM_L4PER_DYNAMICDEP */
-#define OMAP4430_L4SEC_DYNDEP_SHIFT				14
-#define OMAP4430_L4SEC_DYNDEP_MASK				BITFIELD(14, 14)
+#define OMAP4430_L4PER_STATDEP_MASK				(1 << 13)
 
 /*
- * Used by CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP, CM_L3INIT_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE, CM_MPU_STATICDEP
+ * Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE, CM_L4PER_DYNAMICDEP,
+ * CM_L4PER_DYNAMICDEP_RESTORE
+ */
+#define OMAP4430_L4SEC_DYNDEP_SHIFT				14
+#define OMAP4430_L4SEC_DYNDEP_MASK				(1 << 14)
+
+/*
+ * Used by CM_DUCATI_STATICDEP, CM_L3INIT_STATICDEP, CM_MPU_STATICDEP,
+ * CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE
  */
 #define OMAP4430_L4SEC_STATDEP_SHIFT				14
-#define OMAP4430_L4SEC_STATDEP_MASK				BITFIELD(14, 14)
+#define OMAP4430_L4SEC_STATDEP_MASK				(1 << 14)
 
-/* Used by CM_L4CFG_DYNAMICDEP */
+/* Used by CM_L4CFG_DYNAMICDEP, CM_L4CFG_DYNAMICDEP_RESTORE */
 #define OMAP4430_L4WKUP_DYNDEP_SHIFT				15
-#define OMAP4430_L4WKUP_DYNDEP_MASK				BITFIELD(15, 15)
+#define OMAP4430_L4WKUP_DYNDEP_MASK				(1 << 15)
 
 /*
- * Used by CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP, CM_L3INIT_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE, CM_MPU_STATICDEP, CM_TESLA_STATICDEP
+ * Used by CM_DUCATI_STATICDEP, CM_L3INIT_STATICDEP, CM_MPU_STATICDEP,
+ * CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
  */
 #define OMAP4430_L4WKUP_STATDEP_SHIFT				15
-#define OMAP4430_L4WKUP_STATDEP_MASK				BITFIELD(15, 15)
+#define OMAP4430_L4WKUP_STATDEP_MASK				(1 << 15)
 
 /*
- * Used by CM_D2D_DYNAMICDEP, CM_L3_1_DYNAMICDEP, CM_L4CFG_DYNAMICDEP,
- * CM_MPU_DYNAMICDEP
+ * Used by CM_D2D_DYNAMICDEP, CM_D2D_DYNAMICDEP_RESTORE, CM_L3_1_DYNAMICDEP,
+ * CM_L3_1_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
+ * CM_L4CFG_DYNAMICDEP_RESTORE, CM_MPU_DYNAMICDEP
  */
 #define OMAP4430_MEMIF_DYNDEP_SHIFT				4
-#define OMAP4430_MEMIF_DYNDEP_MASK				BITFIELD(4, 4)
+#define OMAP4430_MEMIF_DYNDEP_MASK				(1 << 4)
 
 /*
- * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP,
- * CM_GFX_STATICDEP, CM_L4SEC_STATICDEP, CM_L3INIT_STATICDEP, CM_CAM_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE, CM_IVAHD_STATICDEP, CM_DSS_STATICDEP,
- * CM_MPU_STATICDEP, CM_TESLA_STATICDEP
+ * Used by CM_CAM_STATICDEP, CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE,
+ * CM_DSS_STATICDEP, CM_DUCATI_STATICDEP, CM_GFX_STATICDEP, CM_IVAHD_STATICDEP,
+ * CM_L3INIT_STATICDEP, CM_L4SEC_STATICDEP, CM_MPU_STATICDEP,
+ * CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
  */
 #define OMAP4430_MEMIF_STATDEP_SHIFT				4
-#define OMAP4430_MEMIF_STATDEP_MASK				BITFIELD(4, 4)
+#define OMAP4430_MEMIF_STATDEP_MASK				(1 << 4)
 
 /*
- * Used by CM_SSC_MODFREQDIV_DPLL_PER, CM_SSC_MODFREQDIV_DPLL_UNIPRO,
- * CM_SSC_MODFREQDIV_DPLL_USB, CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE,
- * CM_SSC_MODFREQDIV_DPLL_ABE, CM_SSC_MODFREQDIV_DPLL_CORE,
- * CM_SSC_MODFREQDIV_DPLL_DDRPHY, CM_SSC_MODFREQDIV_DPLL_IVA,
- * CM_SSC_MODFREQDIV_DPLL_MPU
+ * Used by CM_SSC_MODFREQDIV_DPLL_ABE, CM_SSC_MODFREQDIV_DPLL_CORE,
+ * CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE, CM_SSC_MODFREQDIV_DPLL_DDRPHY,
+ * CM_SSC_MODFREQDIV_DPLL_IVA, CM_SSC_MODFREQDIV_DPLL_MPU,
+ * CM_SSC_MODFREQDIV_DPLL_PER, CM_SSC_MODFREQDIV_DPLL_UNIPRO,
+ * CM_SSC_MODFREQDIV_DPLL_USB
  */
 #define OMAP4430_MODFREQDIV_EXPONENT_SHIFT			8
-#define OMAP4430_MODFREQDIV_EXPONENT_MASK			BITFIELD(8, 10)
+#define OMAP4430_MODFREQDIV_EXPONENT_MASK			(0x7 << 8)
 
 /*
- * Used by CM_SSC_MODFREQDIV_DPLL_PER, CM_SSC_MODFREQDIV_DPLL_UNIPRO,
- * CM_SSC_MODFREQDIV_DPLL_USB, CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE,
- * CM_SSC_MODFREQDIV_DPLL_ABE, CM_SSC_MODFREQDIV_DPLL_CORE,
- * CM_SSC_MODFREQDIV_DPLL_DDRPHY, CM_SSC_MODFREQDIV_DPLL_IVA,
- * CM_SSC_MODFREQDIV_DPLL_MPU
+ * Used by CM_SSC_MODFREQDIV_DPLL_ABE, CM_SSC_MODFREQDIV_DPLL_CORE,
+ * CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE, CM_SSC_MODFREQDIV_DPLL_DDRPHY,
+ * CM_SSC_MODFREQDIV_DPLL_IVA, CM_SSC_MODFREQDIV_DPLL_MPU,
+ * CM_SSC_MODFREQDIV_DPLL_PER, CM_SSC_MODFREQDIV_DPLL_UNIPRO,
+ * CM_SSC_MODFREQDIV_DPLL_USB
  */
 #define OMAP4430_MODFREQDIV_MANTISSA_SHIFT			0
-#define OMAP4430_MODFREQDIV_MANTISSA_MASK			BITFIELD(0, 6)
+#define OMAP4430_MODFREQDIV_MANTISSA_MASK			(0x7f << 0)
 
 /*
- * Used by PRM_PRM_PROFILING_CLKCTRL, CM_WKUP_GPIO1_CLKCTRL,
- * CM_WKUP_KEYBOARD_CLKCTRL, CM_WKUP_L4WKUP_CLKCTRL, CM_WKUP_RTC_CLKCTRL,
- * CM_WKUP_SARRAM_CLKCTRL, CM_WKUP_SYNCTIMER_CLKCTRL, CM_WKUP_TIMER12_CLKCTRL,
- * CM_WKUP_TIMER1_CLKCTRL, CM_WKUP_USIM_CLKCTRL, CM_WKUP_WDT1_CLKCTRL,
- * CM_WKUP_WDT2_CLKCTRL, CM_EMU_DEBUGSS_CLKCTRL, CM_D2D_MODEM_ICR_CLKCTRL,
- * CM_D2D_SAD2D_CLKCTRL, CM_D2D_SAD2D_FW_CLKCTRL, CM_DUCATI_DUCATI_CLKCTRL,
- * CM_L3INSTR_L3_3_CLKCTRL, CM_L3INSTR_L3_INSTR_CLKCTRL,
- * CM_L3INSTR_OCP_WP1_CLKCTRL, CM_L3_1_L3_1_CLKCTRL, CM_L3_2_GPMC_CLKCTRL,
- * CM_L3_2_L3_2_CLKCTRL, CM_L3_2_OCMC_RAM_CLKCTRL, CM_L4CFG_HW_SEM_CLKCTRL,
- * CM_L4CFG_L4_CFG_CLKCTRL, CM_L4CFG_MAILBOX_CLKCTRL, CM_L4CFG_SAR_ROM_CLKCTRL,
- * CM_MEMIF_DMM_CLKCTRL, CM_MEMIF_EMIF_1_CLKCTRL, CM_MEMIF_EMIF_2_CLKCTRL,
- * CM_MEMIF_EMIF_FW_CLKCTRL, CM_MEMIF_EMIF_H1_CLKCTRL,
- * CM_MEMIF_EMIF_H2_CLKCTRL, CM_SDMA_SDMA_CLKCTRL, CM_GFX_GFX_CLKCTRL,
- * CM_L4PER_ADC_CLKCTRL, CM_L4PER_DMTIMER10_CLKCTRL,
- * CM_L4PER_DMTIMER11_CLKCTRL, CM_L4PER_DMTIMER2_CLKCTRL,
- * CM_L4PER_DMTIMER3_CLKCTRL, CM_L4PER_DMTIMER4_CLKCTRL,
- * CM_L4PER_DMTIMER9_CLKCTRL, CM_L4PER_ELM_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL,
- * CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL, CM_L4PER_GPIO5_CLKCTRL,
- * CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_HDQ1W_CLKCTRL, CM_L4PER_HECC1_CLKCTRL,
- * CM_L4PER_HECC2_CLKCTRL, CM_L4PER_I2C1_CLKCTRL, CM_L4PER_I2C2_CLKCTRL,
- * CM_L4PER_I2C3_CLKCTRL, CM_L4PER_I2C4_CLKCTRL, CM_L4PER_I2C5_CLKCTRL,
- * CM_L4PER_L4PER_CLKCTRL, CM_L4PER_MCASP2_CLKCTRL, CM_L4PER_MCASP3_CLKCTRL,
- * CM_L4PER_MCBSP4_CLKCTRL, CM_L4PER_MCSPI1_CLKCTRL, CM_L4PER_MCSPI2_CLKCTRL,
- * CM_L4PER_MCSPI3_CLKCTRL, CM_L4PER_MCSPI4_CLKCTRL, CM_L4PER_MGATE_CLKCTRL,
- * CM_L4PER_MMCSD3_CLKCTRL, CM_L4PER_MMCSD4_CLKCTRL, CM_L4PER_MMCSD5_CLKCTRL,
- * CM_L4PER_MSPROHG_CLKCTRL, CM_L4PER_SLIMBUS2_CLKCTRL, CM_L4PER_UART1_CLKCTRL,
- * CM_L4PER_UART2_CLKCTRL, CM_L4PER_UART3_CLKCTRL, CM_L4PER_UART4_CLKCTRL,
- * CM_L4SEC_AES1_CLKCTRL, CM_L4SEC_AES2_CLKCTRL, CM_L4SEC_CRYPTODMA_CLKCTRL,
- * CM_L4SEC_DES3DES_CLKCTRL, CM_L4SEC_PKAEIP29_CLKCTRL, CM_L4SEC_RNG_CLKCTRL,
- * CM_L4SEC_SHA2MD51_CLKCTRL, CM_L3INIT_CCPTX_CLKCTRL, CM_L3INIT_EMAC_CLKCTRL,
+ * Used by CM1_ABE_AESS_CLKCTRL, CM1_ABE_DMIC_CLKCTRL, CM1_ABE_L4ABE_CLKCTRL,
+ * CM1_ABE_MCASP_CLKCTRL, CM1_ABE_MCBSP1_CLKCTRL, CM1_ABE_MCBSP2_CLKCTRL,
+ * CM1_ABE_MCBSP3_CLKCTRL, CM1_ABE_PDM_CLKCTRL, CM1_ABE_SLIMBUS_CLKCTRL,
+ * CM1_ABE_TIMER5_CLKCTRL, CM1_ABE_TIMER6_CLKCTRL, CM1_ABE_TIMER7_CLKCTRL,
+ * CM1_ABE_TIMER8_CLKCTRL, CM1_ABE_WDT3_CLKCTRL, CM_ALWON_MDMINTC_CLKCTRL,
+ * CM_ALWON_SR_CORE_CLKCTRL, CM_ALWON_SR_IVA_CLKCTRL, CM_ALWON_SR_MPU_CLKCTRL,
+ * CM_CAM_FDIF_CLKCTRL, CM_CAM_ISS_CLKCTRL, CM_CEFUSE_CEFUSE_CLKCTRL,
+ * CM_CM1_PROFILING_CLKCTRL, CM_CM1_PROFILING_CLKCTRL_RESTORE,
+ * CM_CM2_PROFILING_CLKCTRL, CM_CM2_PROFILING_CLKCTRL_RESTORE,
+ * CM_D2D_MODEM_ICR_CLKCTRL, CM_D2D_SAD2D_CLKCTRL, CM_D2D_SAD2D_FW_CLKCTRL,
+ * CM_DSS_DEISS_CLKCTRL, CM_DSS_DSS_CLKCTRL, CM_DUCATI_DUCATI_CLKCTRL,
+ * CM_EMU_DEBUGSS_CLKCTRL, CM_GFX_GFX_CLKCTRL, CM_IVAHD_IVAHD_CLKCTRL,
+ * CM_IVAHD_SL2_CLKCTRL, CM_L3INIT_CCPTX_CLKCTRL, CM_L3INIT_EMAC_CLKCTRL,
  * CM_L3INIT_HSI_CLKCTRL, CM_L3INIT_MMC1_CLKCTRL, CM_L3INIT_MMC2_CLKCTRL,
  * CM_L3INIT_MMC6_CLKCTRL, CM_L3INIT_P1500_CLKCTRL, CM_L3INIT_PCIESS_CLKCTRL,
  * CM_L3INIT_SATA_CLKCTRL, CM_L3INIT_TPPSS_CLKCTRL, CM_L3INIT_UNIPRO1_CLKCTRL,
  * CM_L3INIT_USBPHYOCP2SCP_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL,
- * CM_L3INIT_USB_HOST_FS_CLKCTRL, CM_L3INIT_USB_OTG_CLKCTRL,
- * CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_XHPI_CLKCTRL, CM_CAM_FDIF_CLKCTRL,
- * CM_CAM_ISS_CLKCTRL, CM_CEFUSE_CEFUSE_CLKCTRL,
- * CM_L3INIT_USB_HOST_CLKCTRL_RESTORE, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE,
- * CM_L3INSTR_L3_3_CLKCTRL_RESTORE, CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE,
- * CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE, CM_L4PER_GPIO2_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO3_CLKCTRL_RESTORE, CM_L4PER_GPIO4_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO5_CLKCTRL_RESTORE, CM_L4PER_GPIO6_CLKCTRL_RESTORE,
- * CM_ALWON_MDMINTC_CLKCTRL, CM_ALWON_SR_CORE_CLKCTRL, CM_ALWON_SR_IVA_CLKCTRL,
- * CM_ALWON_SR_MPU_CLKCTRL, CM_IVAHD_IVAHD_CLKCTRL, CM_IVAHD_SL2_CLKCTRL,
- * CM_DSS_DEISS_CLKCTRL, CM_DSS_DSS_CLKCTRL, CM_CM2_PROFILING_CLKCTRL,
- * CM_MPU_MPU_CLKCTRL, CM_TESLA_TESLA_CLKCTRL, CM1_ABE_AESS_CLKCTRL,
- * CM1_ABE_DMIC_CLKCTRL, CM1_ABE_L4ABE_CLKCTRL, CM1_ABE_MCASP_CLKCTRL,
- * CM1_ABE_MCBSP1_CLKCTRL, CM1_ABE_MCBSP2_CLKCTRL, CM1_ABE_MCBSP3_CLKCTRL,
- * CM1_ABE_PDM_CLKCTRL, CM1_ABE_SLIMBUS_CLKCTRL, CM1_ABE_TIMER5_CLKCTRL,
- * CM1_ABE_TIMER6_CLKCTRL, CM1_ABE_TIMER7_CLKCTRL, CM1_ABE_TIMER8_CLKCTRL,
- * CM1_ABE_WDT3_CLKCTRL, CM_CM1_PROFILING_CLKCTRL
+ * CM_L3INIT_USB_HOST_CLKCTRL_RESTORE, CM_L3INIT_USB_HOST_FS_CLKCTRL,
+ * CM_L3INIT_USB_OTG_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL,
+ * CM_L3INIT_USB_TLL_CLKCTRL_RESTORE, CM_L3INIT_XHPI_CLKCTRL,
+ * CM_L3INSTR_L3_3_CLKCTRL, CM_L3INSTR_L3_3_CLKCTRL_RESTORE,
+ * CM_L3INSTR_L3_INSTR_CLKCTRL, CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE,
+ * CM_L3INSTR_OCP_WP1_CLKCTRL, CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE,
+ * CM_L3_1_L3_1_CLKCTRL, CM_L3_2_GPMC_CLKCTRL, CM_L3_2_L3_2_CLKCTRL,
+ * CM_L3_2_OCMC_RAM_CLKCTRL, CM_L4CFG_HW_SEM_CLKCTRL, CM_L4CFG_L4_CFG_CLKCTRL,
+ * CM_L4CFG_MAILBOX_CLKCTRL, CM_L4CFG_SAR_ROM_CLKCTRL, CM_L4PER_ADC_CLKCTRL,
+ * CM_L4PER_DMTIMER10_CLKCTRL, CM_L4PER_DMTIMER11_CLKCTRL,
+ * CM_L4PER_DMTIMER2_CLKCTRL, CM_L4PER_DMTIMER3_CLKCTRL,
+ * CM_L4PER_DMTIMER4_CLKCTRL, CM_L4PER_DMTIMER9_CLKCTRL, CM_L4PER_ELM_CLKCTRL,
+ * CM_L4PER_GPIO2_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO3_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO4_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO5_CLKCTRL, CM_L4PER_GPIO5_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_GPIO6_CLKCTRL_RESTORE,
+ * CM_L4PER_HDQ1W_CLKCTRL, CM_L4PER_HECC1_CLKCTRL, CM_L4PER_HECC2_CLKCTRL,
+ * CM_L4PER_I2C1_CLKCTRL, CM_L4PER_I2C2_CLKCTRL, CM_L4PER_I2C3_CLKCTRL,
+ * CM_L4PER_I2C4_CLKCTRL, CM_L4PER_I2C5_CLKCTRL, CM_L4PER_L4PER_CLKCTRL,
+ * CM_L4PER_MCASP2_CLKCTRL, CM_L4PER_MCASP3_CLKCTRL, CM_L4PER_MCBSP4_CLKCTRL,
+ * CM_L4PER_MCSPI1_CLKCTRL, CM_L4PER_MCSPI2_CLKCTRL, CM_L4PER_MCSPI3_CLKCTRL,
+ * CM_L4PER_MCSPI4_CLKCTRL, CM_L4PER_MGATE_CLKCTRL, CM_L4PER_MMCSD3_CLKCTRL,
+ * CM_L4PER_MMCSD4_CLKCTRL, CM_L4PER_MMCSD5_CLKCTRL, CM_L4PER_MSPROHG_CLKCTRL,
+ * CM_L4PER_SLIMBUS2_CLKCTRL, CM_L4PER_UART1_CLKCTRL, CM_L4PER_UART2_CLKCTRL,
+ * CM_L4PER_UART3_CLKCTRL, CM_L4PER_UART4_CLKCTRL, CM_L4SEC_AES1_CLKCTRL,
+ * CM_L4SEC_AES2_CLKCTRL, CM_L4SEC_CRYPTODMA_CLKCTRL, CM_L4SEC_DES3DES_CLKCTRL,
+ * CM_L4SEC_PKAEIP29_CLKCTRL, CM_L4SEC_RNG_CLKCTRL, CM_L4SEC_SHA2MD51_CLKCTRL,
+ * CM_MEMIF_DMM_CLKCTRL, CM_MEMIF_EMIF_1_CLKCTRL, CM_MEMIF_EMIF_2_CLKCTRL,
+ * CM_MEMIF_EMIF_FW_CLKCTRL, CM_MEMIF_EMIF_H1_CLKCTRL,
+ * CM_MEMIF_EMIF_H2_CLKCTRL, CM_MPU_MPU_CLKCTRL, CM_SDMA_SDMA_CLKCTRL,
+ * CM_TESLA_TESLA_CLKCTRL, CM_WKUP_GPIO1_CLKCTRL, CM_WKUP_KEYBOARD_CLKCTRL,
+ * CM_WKUP_L4WKUP_CLKCTRL, CM_WKUP_RTC_CLKCTRL, CM_WKUP_SARRAM_CLKCTRL,
+ * CM_WKUP_SYNCTIMER_CLKCTRL, CM_WKUP_TIMER12_CLKCTRL, CM_WKUP_TIMER1_CLKCTRL,
+ * CM_WKUP_USIM_CLKCTRL, CM_WKUP_WDT1_CLKCTRL, CM_WKUP_WDT2_CLKCTRL
  */
 #define OMAP4430_MODULEMODE_SHIFT				0
-#define OMAP4430_MODULEMODE_MASK				BITFIELD(0, 1)
+#define OMAP4430_MODULEMODE_MASK				(0x3 << 0)
 
 /* Used by CM_DSS_DSS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_48MHZ_CLK_SHIFT			9
-#define OMAP4430_OPTFCLKEN_48MHZ_CLK_MASK			BITFIELD(9, 9)
+#define OMAP4430_OPTFCLKEN_48MHZ_CLK_MASK			(1 << 9)
 
 /* Used by CM_WKUP_BANDGAP_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_BGAP_32K_SHIFT			8
-#define OMAP4430_OPTFCLKEN_BGAP_32K_MASK			BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_BGAP_32K_MASK			(1 << 8)
 
-/* Used by CM_L3INIT_USBPHYOCP2SCP_CLKCTRL */
-#define OMAP4430_OPTFCLKEN_CLK32K_SHIFT				9
-#define OMAP4430_OPTFCLKEN_CLK32K_MASK				BITFIELD(9, 9)
+/* Used by CM_ALWON_USBPHY_CLKCTRL */
+#define OMAP4430_OPTFCLKEN_CLK32K_SHIFT				8
+#define OMAP4430_OPTFCLKEN_CLK32K_MASK				(1 << 8)
 
 /* Used by CM_CAM_ISS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_CTRLCLK_SHIFT			8
-#define OMAP4430_OPTFCLKEN_CTRLCLK_MASK				BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_CTRLCLK_MASK				(1 << 8)
 
 /*
- * Used by CM_WKUP_GPIO1_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL,
- * CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL, CM_L4PER_GPIO5_CLKCTRL,
- * CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO3_CLKCTRL_RESTORE, CM_L4PER_GPIO4_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO5_CLKCTRL_RESTORE, CM_L4PER_GPIO6_CLKCTRL_RESTORE
+ * Used by CM_L4PER_GPIO2_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO3_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO4_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO5_CLKCTRL, CM_L4PER_GPIO5_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_GPIO6_CLKCTRL_RESTORE, CM_WKUP_GPIO1_CLKCTRL
  */
 #define OMAP4430_OPTFCLKEN_DBCLK_SHIFT				8
-#define OMAP4430_OPTFCLKEN_DBCLK_MASK				BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_DBCLK_MASK				(1 << 8)
 
 /* Used by CM_MEMIF_DLL_CLKCTRL, CM_MEMIF_DLL_H_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_DLL_CLK_SHIFT			8
-#define OMAP4430_OPTFCLKEN_DLL_CLK_MASK				BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_DLL_CLK_MASK				(1 << 8)
 
 /* Used by CM_DSS_DSS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_DSSCLK_SHIFT				8
-#define OMAP4430_OPTFCLKEN_DSSCLK_MASK				BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_DSSCLK_MASK				(1 << 8)
+
+/* Used by CM_WKUP_USIM_CLKCTRL */
+#define OMAP4430_OPTFCLKEN_FCLK_SHIFT				8
+#define OMAP4430_OPTFCLKEN_FCLK_MASK				(1 << 8)
 
 /* Used by CM1_ABE_SLIMBUS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_FCLK0_SHIFT				8
-#define OMAP4430_OPTFCLKEN_FCLK0_MASK				BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_FCLK0_MASK				(1 << 8)
 
 /* Used by CM1_ABE_SLIMBUS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_FCLK1_SHIFT				9
-#define OMAP4430_OPTFCLKEN_FCLK1_MASK				BITFIELD(9, 9)
+#define OMAP4430_OPTFCLKEN_FCLK1_MASK				(1 << 9)
 
 /* Used by CM1_ABE_SLIMBUS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_FCLK2_SHIFT				10
-#define OMAP4430_OPTFCLKEN_FCLK2_MASK				BITFIELD(10, 10)
+#define OMAP4430_OPTFCLKEN_FCLK2_MASK				(1 << 10)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_FUNC48MCLK_SHIFT			15
-#define OMAP4430_OPTFCLKEN_FUNC48MCLK_MASK			BITFIELD(15, 15)
+#define OMAP4430_OPTFCLKEN_FUNC48MCLK_MASK			(1 << 15)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_HSIC480M_P1_CLK_SHIFT		13
-#define OMAP4430_OPTFCLKEN_HSIC480M_P1_CLK_MASK			BITFIELD(13, 13)
+#define OMAP4430_OPTFCLKEN_HSIC480M_P1_CLK_MASK			(1 << 13)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_HSIC480M_P2_CLK_SHIFT		14
-#define OMAP4430_OPTFCLKEN_HSIC480M_P2_CLK_MASK			BITFIELD(14, 14)
+#define OMAP4430_OPTFCLKEN_HSIC480M_P2_CLK_MASK			(1 << 14)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK_SHIFT			11
-#define OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK_MASK			BITFIELD(11, 11)
+#define OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK_MASK			(1 << 11)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK_SHIFT			12
-#define OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK_MASK			BITFIELD(12, 12)
+#define OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK_MASK			(1 << 12)
 
 /* Used by CM_L4PER_SLIMBUS2_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_PER24MC_GFCLK_SHIFT			8
-#define OMAP4430_OPTFCLKEN_PER24MC_GFCLK_MASK			BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_PER24MC_GFCLK_MASK			(1 << 8)
 
 /* Used by CM_L4PER_SLIMBUS2_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_PERABE24M_GFCLK_SHIFT		9
-#define OMAP4430_OPTFCLKEN_PERABE24M_GFCLK_MASK			BITFIELD(9, 9)
+#define OMAP4430_OPTFCLKEN_PERABE24M_GFCLK_MASK			(1 << 9)
 
 /* Used by CM_L3INIT_USBPHYOCP2SCP_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_PHY_48M_SHIFT			8
-#define OMAP4430_OPTFCLKEN_PHY_48M_MASK				BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_PHY_48M_MASK				(1 << 8)
 
 /* Used by CM_L4PER_SLIMBUS2_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_SLIMBUS_CLK_SHIFT			10
-#define OMAP4430_OPTFCLKEN_SLIMBUS_CLK_MASK			BITFIELD(10, 10)
+#define OMAP4430_OPTFCLKEN_SLIMBUS_CLK_MASK			(1 << 10)
 
 /* Renamed from OPTFCLKEN_SLIMBUS_CLK Used by CM1_ABE_SLIMBUS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_SLIMBUS_CLK_11_11_SHIFT		11
-#define OMAP4430_OPTFCLKEN_SLIMBUS_CLK_11_11_MASK		BITFIELD(11, 11)
+#define OMAP4430_OPTFCLKEN_SLIMBUS_CLK_11_11_MASK		(1 << 11)
 
 /* Used by CM_DSS_DSS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_SYS_CLK_SHIFT			10
-#define OMAP4430_OPTFCLKEN_SYS_CLK_MASK				BITFIELD(10, 10)
+#define OMAP4430_OPTFCLKEN_SYS_CLK_MASK				(1 << 10)
 
 /* Used by CM_DSS_DSS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_TV_CLK_SHIFT				11
-#define OMAP4430_OPTFCLKEN_TV_CLK_MASK				BITFIELD(11, 11)
+#define OMAP4430_OPTFCLKEN_TV_CLK_MASK				(1 << 11)
 
 /* Used by CM_L3INIT_UNIPRO1_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_TXPHYCLK_SHIFT			8
-#define OMAP4430_OPTFCLKEN_TXPHYCLK_MASK			BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_TXPHYCLK_MASK			(1 << 8)
 
 /* Used by CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_USB_CH0_CLK_SHIFT			8
-#define OMAP4430_OPTFCLKEN_USB_CH0_CLK_MASK			BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_USB_CH0_CLK_MASK			(1 << 8)
 
 /* Used by CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_USB_CH1_CLK_SHIFT			9
-#define OMAP4430_OPTFCLKEN_USB_CH1_CLK_MASK			BITFIELD(9, 9)
+#define OMAP4430_OPTFCLKEN_USB_CH1_CLK_MASK			(1 << 9)
 
 /* Used by CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_USB_CH2_CLK_SHIFT			10
-#define OMAP4430_OPTFCLKEN_USB_CH2_CLK_MASK			BITFIELD(10, 10)
+#define OMAP4430_OPTFCLKEN_USB_CH2_CLK_MASK			(1 << 10)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_UTMI_P1_CLK_SHIFT			8
-#define OMAP4430_OPTFCLKEN_UTMI_P1_CLK_MASK			BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_UTMI_P1_CLK_MASK			(1 << 8)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_UTMI_P2_CLK_SHIFT			9
-#define OMAP4430_OPTFCLKEN_UTMI_P2_CLK_MASK			BITFIELD(9, 9)
+#define OMAP4430_OPTFCLKEN_UTMI_P2_CLK_MASK			(1 << 9)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_UTMI_P3_CLK_SHIFT			10
-#define OMAP4430_OPTFCLKEN_UTMI_P3_CLK_MASK			BITFIELD(10, 10)
+#define OMAP4430_OPTFCLKEN_UTMI_P3_CLK_MASK			(1 << 10)
 
 /* Used by CM_L3INIT_USB_OTG_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_XCLK_SHIFT				8
-#define OMAP4430_OPTFCLKEN_XCLK_MASK				BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_XCLK_MASK				(1 << 8)
 
-/* Used by CM_EMU_OVERRIDE_DPLL_PER, CM_EMU_OVERRIDE_DPLL_CORE */
+/* Used by CM_EMU_OVERRIDE_DPLL_CORE */
 #define OMAP4430_OVERRIDE_ENABLE_SHIFT				19
-#define OMAP4430_OVERRIDE_ENABLE_MASK				BITFIELD(19, 19)
+#define OMAP4430_OVERRIDE_ENABLE_MASK				(1 << 19)
 
 /* Used by CM_CLKSEL_ABE */
 #define OMAP4430_PAD_CLKS_GATE_SHIFT				8
-#define OMAP4430_PAD_CLKS_GATE_MASK				BITFIELD(8, 8)
+#define OMAP4430_PAD_CLKS_GATE_MASK				(1 << 8)
 
 /* Used by CM_CORE_DVFS_CURRENT, CM_IVA_DVFS_CURRENT */
 #define OMAP4430_PERF_CURRENT_SHIFT				0
-#define OMAP4430_PERF_CURRENT_MASK				BITFIELD(0, 7)
+#define OMAP4430_PERF_CURRENT_MASK				(0xff << 0)
 
 /*
  * Used by CM_CORE_DVFS_PERF1, CM_CORE_DVFS_PERF2, CM_CORE_DVFS_PERF3,
@@ -1316,159 +1355,173 @@
  * CM_IVA_DVFS_PERF_TESLA
  */
 #define OMAP4430_PERF_REQ_SHIFT					0
-#define OMAP4430_PERF_REQ_MASK					BITFIELD(0, 7)
-
-/* Used by CM_EMU_OVERRIDE_DPLL_PER */
-#define OMAP4430_PER_DPLL_EMU_DIV_SHIFT				0
-#define OMAP4430_PER_DPLL_EMU_DIV_MASK				BITFIELD(0, 6)
-
-/* Used by CM_EMU_OVERRIDE_DPLL_PER */
-#define OMAP4430_PER_DPLL_EMU_MULT_SHIFT			8
-#define OMAP4430_PER_DPLL_EMU_MULT_MASK				BITFIELD(8, 18)
+#define OMAP4430_PERF_REQ_MASK					(0xff << 0)
 
 /* Used by CM_RESTORE_ST */
 #define OMAP4430_PHASE1_COMPLETED_SHIFT				0
-#define OMAP4430_PHASE1_COMPLETED_MASK				BITFIELD(0, 0)
+#define OMAP4430_PHASE1_COMPLETED_MASK				(1 << 0)
 
 /* Used by CM_RESTORE_ST */
 #define OMAP4430_PHASE2A_COMPLETED_SHIFT			1
-#define OMAP4430_PHASE2A_COMPLETED_MASK				BITFIELD(1, 1)
+#define OMAP4430_PHASE2A_COMPLETED_MASK				(1 << 1)
 
 /* Used by CM_RESTORE_ST */
 #define OMAP4430_PHASE2B_COMPLETED_SHIFT			2
-#define OMAP4430_PHASE2B_COMPLETED_MASK				BITFIELD(2, 2)
+#define OMAP4430_PHASE2B_COMPLETED_MASK				(1 << 2)
 
 /* Used by CM_EMU_DEBUGSS_CLKCTRL */
 #define OMAP4430_PMD_STM_MUX_CTRL_SHIFT				20
-#define OMAP4430_PMD_STM_MUX_CTRL_MASK				BITFIELD(20, 21)
+#define OMAP4430_PMD_STM_MUX_CTRL_MASK				(0x3 << 20)
 
 /* Used by CM_EMU_DEBUGSS_CLKCTRL */
 #define OMAP4430_PMD_TRACE_MUX_CTRL_SHIFT			22
-#define OMAP4430_PMD_TRACE_MUX_CTRL_MASK			BITFIELD(22, 23)
+#define OMAP4430_PMD_TRACE_MUX_CTRL_MASK			(0x3 << 22)
 
-/* Used by CM_DYN_DEP_PRESCAL */
+/* Used by CM_DYN_DEP_PRESCAL, CM_DYN_DEP_PRESCAL_RESTORE */
 #define OMAP4430_PRESCAL_SHIFT					0
-#define OMAP4430_PRESCAL_MASK					BITFIELD(0, 5)
+#define OMAP4430_PRESCAL_MASK					(0x3f << 0)
 
-/* Used by REVISION_CM2, REVISION_CM1 */
-#define OMAP4430_REV_SHIFT					0
-#define OMAP4430_REV_MASK					BITFIELD(0, 7)
+/* Used by REVISION_CM1, REVISION_CM2 */
+#define OMAP4430_R_RTL_SHIFT					11
+#define OMAP4430_R_RTL_MASK					(0x1f << 11)
 
 /*
- * Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL,
- * CM_L3INIT_USB_HOST_CLKCTRL_RESTORE, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE
+ * Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE,
+ * CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE
  */
 #define OMAP4430_SAR_MODE_SHIFT					4
-#define OMAP4430_SAR_MODE_MASK					BITFIELD(4, 4)
+#define OMAP4430_SAR_MODE_MASK					(1 << 4)
 
 /* Used by CM_SCALE_FCLK */
 #define OMAP4430_SCALE_FCLK_SHIFT				0
-#define OMAP4430_SCALE_FCLK_MASK				BITFIELD(0, 0)
+#define OMAP4430_SCALE_FCLK_MASK				(1 << 0)
 
-/* Used by CM_L4CFG_DYNAMICDEP */
+/* Used by REVISION_CM1, REVISION_CM2 */
+#define OMAP4430_SCHEME_SHIFT					30
+#define OMAP4430_SCHEME_MASK					(0x3 << 30)
+
+/* Used by CM_L4CFG_DYNAMICDEP, CM_L4CFG_DYNAMICDEP_RESTORE */
 #define OMAP4430_SDMA_DYNDEP_SHIFT				11
-#define OMAP4430_SDMA_DYNDEP_MASK				BITFIELD(11, 11)
+#define OMAP4430_SDMA_DYNDEP_MASK				(1 << 11)
 
 /* Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP */
 #define OMAP4430_SDMA_STATDEP_SHIFT				11
-#define OMAP4430_SDMA_STATDEP_MASK				BITFIELD(11, 11)
+#define OMAP4430_SDMA_STATDEP_MASK				(1 << 11)
 
 /* Used by CM_CLKSEL_ABE */
 #define OMAP4430_SLIMBUS_CLK_GATE_SHIFT				10
-#define OMAP4430_SLIMBUS_CLK_GATE_MASK				BITFIELD(10, 10)
+#define OMAP4430_SLIMBUS_CLK_GATE_MASK				(1 << 10)
 
 /*
- * Used by CM_EMU_DEBUGSS_CLKCTRL, CM_D2D_SAD2D_CLKCTRL,
- * CM_DUCATI_DUCATI_CLKCTRL, CM_SDMA_SDMA_CLKCTRL, CM_GFX_GFX_CLKCTRL,
- * CM_L4SEC_CRYPTODMA_CLKCTRL, CM_L3INIT_CCPTX_CLKCTRL, CM_L3INIT_EMAC_CLKCTRL,
+ * Used by CM1_ABE_AESS_CLKCTRL, CM_CAM_FDIF_CLKCTRL, CM_CAM_ISS_CLKCTRL,
+ * CM_D2D_SAD2D_CLKCTRL, CM_DSS_DEISS_CLKCTRL, CM_DSS_DSS_CLKCTRL,
+ * CM_DUCATI_DUCATI_CLKCTRL, CM_EMU_DEBUGSS_CLKCTRL, CM_GFX_GFX_CLKCTRL,
+ * CM_IVAHD_IVAHD_CLKCTRL, CM_L3INIT_CCPTX_CLKCTRL, CM_L3INIT_EMAC_CLKCTRL,
  * CM_L3INIT_HSI_CLKCTRL, CM_L3INIT_MMC1_CLKCTRL, CM_L3INIT_MMC2_CLKCTRL,
  * CM_L3INIT_MMC6_CLKCTRL, CM_L3INIT_P1500_CLKCTRL, CM_L3INIT_PCIESS_CLKCTRL,
  * CM_L3INIT_SATA_CLKCTRL, CM_L3INIT_TPPSS_CLKCTRL, CM_L3INIT_UNIPRO1_CLKCTRL,
- * CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_FS_CLKCTRL,
- * CM_L3INIT_USB_OTG_CLKCTRL, CM_L3INIT_XHPI_CLKCTRL, CM_CAM_FDIF_CLKCTRL,
- * CM_CAM_ISS_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE,
- * CM_IVAHD_IVAHD_CLKCTRL, CM_DSS_DEISS_CLKCTRL, CM_DSS_DSS_CLKCTRL,
- * CM_MPU_MPU_CLKCTRL, CM_TESLA_TESLA_CLKCTRL, CM1_ABE_AESS_CLKCTRL
+ * CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE,
+ * CM_L3INIT_USB_HOST_FS_CLKCTRL, CM_L3INIT_USB_OTG_CLKCTRL,
+ * CM_L3INIT_XHPI_CLKCTRL, CM_L4SEC_CRYPTODMA_CLKCTRL, CM_MPU_MPU_CLKCTRL,
+ * CM_SDMA_SDMA_CLKCTRL, CM_TESLA_TESLA_CLKCTRL
  */
 #define OMAP4430_STBYST_SHIFT					18
-#define OMAP4430_STBYST_MASK					BITFIELD(18, 18)
+#define OMAP4430_STBYST_MASK					(1 << 18)
 
 /*
- * Used by CM_IDLEST_DPLL_PER, CM_IDLEST_DPLL_UNIPRO, CM_IDLEST_DPLL_USB,
- * CM_IDLEST_DPLL_ABE, CM_IDLEST_DPLL_CORE, CM_IDLEST_DPLL_DDRPHY,
- * CM_IDLEST_DPLL_IVA, CM_IDLEST_DPLL_MPU
+ * Used by CM_IDLEST_DPLL_ABE, CM_IDLEST_DPLL_CORE, CM_IDLEST_DPLL_DDRPHY,
+ * CM_IDLEST_DPLL_IVA, CM_IDLEST_DPLL_MPU, CM_IDLEST_DPLL_PER,
+ * CM_IDLEST_DPLL_UNIPRO, CM_IDLEST_DPLL_USB
  */
 #define OMAP4430_ST_DPLL_CLK_SHIFT				0
-#define OMAP4430_ST_DPLL_CLK_MASK				BITFIELD(0, 0)
+#define OMAP4430_ST_DPLL_CLK_MASK				(1 << 0)
 
 /* Used by CM_CLKDCOLDO_DPLL_USB */
 #define OMAP4430_ST_DPLL_CLKDCOLDO_SHIFT			9
-#define OMAP4430_ST_DPLL_CLKDCOLDO_MASK				BITFIELD(9, 9)
+#define OMAP4430_ST_DPLL_CLKDCOLDO_MASK				(1 << 9)
 
 /*
- * Used by CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_USB, CM_DIV_M2_DPLL_CORE_RESTORE,
- * CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE, CM_DIV_M2_DPLL_DDRPHY,
- * CM_DIV_M2_DPLL_MPU
+ * Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE,
+ * CM_DIV_M2_DPLL_CORE_RESTORE, CM_DIV_M2_DPLL_DDRPHY, CM_DIV_M2_DPLL_MPU,
+ * CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_USB
  */
 #define OMAP4430_ST_DPLL_CLKOUT_SHIFT				9
-#define OMAP4430_ST_DPLL_CLKOUT_MASK				BITFIELD(9, 9)
+#define OMAP4430_ST_DPLL_CLKOUT_MASK				(1 << 9)
 
 /*
- * Used by CM_DIV_M3_DPLL_PER, CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_ABE,
- * CM_DIV_M3_DPLL_CORE
+ * Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE,
+ * CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_PER
  */
 #define OMAP4430_ST_DPLL_CLKOUTHIF_SHIFT			9
-#define OMAP4430_ST_DPLL_CLKOUTHIF_MASK				BITFIELD(9, 9)
+#define OMAP4430_ST_DPLL_CLKOUTHIF_MASK				(1 << 9)
 
-/* Used by CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO, CM_DIV_M2_DPLL_ABE */
+/* Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO */
 #define OMAP4430_ST_DPLL_CLKOUTX2_SHIFT				11
-#define OMAP4430_ST_DPLL_CLKOUTX2_MASK				BITFIELD(11, 11)
+#define OMAP4430_ST_DPLL_CLKOUTX2_MASK				(1 << 11)
 
 /*
- * Used by CM_DIV_M4_DPLL_PER, CM_DIV_M4_DPLL_CORE_RESTORE,
- * CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA
+ * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_CORE_RESTORE,
+ * CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA, CM_DIV_M4_DPLL_PER
  */
 #define OMAP4430_ST_HSDIVIDER_CLKOUT1_SHIFT			9
-#define OMAP4430_ST_HSDIVIDER_CLKOUT1_MASK			BITFIELD(9, 9)
+#define OMAP4430_ST_HSDIVIDER_CLKOUT1_MASK			(1 << 9)
 
 /*
- * Used by CM_DIV_M5_DPLL_PER, CM_DIV_M5_DPLL_CORE_RESTORE,
- * CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA
+ * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_CORE_RESTORE,
+ * CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA, CM_DIV_M5_DPLL_PER
  */
 #define OMAP4430_ST_HSDIVIDER_CLKOUT2_SHIFT			9
-#define OMAP4430_ST_HSDIVIDER_CLKOUT2_MASK			BITFIELD(9, 9)
+#define OMAP4430_ST_HSDIVIDER_CLKOUT2_MASK			(1 << 9)
 
 /*
- * Used by CM_DIV_M6_DPLL_PER, CM_DIV_M6_DPLL_CORE_RESTORE,
- * CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY
+ * Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_CORE_RESTORE,
+ * CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER
  */
 #define OMAP4430_ST_HSDIVIDER_CLKOUT3_SHIFT			9
-#define OMAP4430_ST_HSDIVIDER_CLKOUT3_MASK			BITFIELD(9, 9)
+#define OMAP4430_ST_HSDIVIDER_CLKOUT3_MASK			(1 << 9)
 
 /*
- * Used by CM_DIV_M7_DPLL_PER, CM_DIV_M7_DPLL_CORE_RESTORE,
- * CM_DIV_M7_DPLL_CORE
+ * Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_CORE_RESTORE,
+ * CM_DIV_M7_DPLL_PER
  */
 #define OMAP4430_ST_HSDIVIDER_CLKOUT4_SHIFT			9
-#define OMAP4430_ST_HSDIVIDER_CLKOUT4_MASK			BITFIELD(9, 9)
+#define OMAP4430_ST_HSDIVIDER_CLKOUT4_MASK			(1 << 9)
+
+/*
+ * Used by CM_IDLEST_DPLL_ABE, CM_IDLEST_DPLL_CORE, CM_IDLEST_DPLL_DDRPHY,
+ * CM_IDLEST_DPLL_IVA, CM_IDLEST_DPLL_MPU, CM_IDLEST_DPLL_PER,
+ * CM_IDLEST_DPLL_UNIPRO, CM_IDLEST_DPLL_USB
+ */
+#define OMAP4430_ST_MN_BYPASS_SHIFT				8
+#define OMAP4430_ST_MN_BYPASS_MASK				(1 << 8)
 
 /* Used by CM_SYS_CLKSEL */
 #define OMAP4430_SYS_CLKSEL_SHIFT				0
-#define OMAP4430_SYS_CLKSEL_MASK				BITFIELD(0, 2)
+#define OMAP4430_SYS_CLKSEL_MASK				(0x7 << 0)
 
-/* Used by CM_L4CFG_DYNAMICDEP */
+/* Used by CM_L4CFG_DYNAMICDEP, CM_L4CFG_DYNAMICDEP_RESTORE */
 #define OMAP4430_TESLA_DYNDEP_SHIFT				1
-#define OMAP4430_TESLA_DYNDEP_MASK				BITFIELD(1, 1)
+#define OMAP4430_TESLA_DYNDEP_MASK				(1 << 1)
 
 /* Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP */
 #define OMAP4430_TESLA_STATDEP_SHIFT				1
-#define OMAP4430_TESLA_STATDEP_MASK				BITFIELD(1, 1)
+#define OMAP4430_TESLA_STATDEP_MASK				(1 << 1)
 
 /*
- * Used by CM_EMU_DYNAMICDEP, CM_D2D_DYNAMICDEP, CM_DUCATI_DYNAMICDEP,
- * CM_L3_1_DYNAMICDEP, CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP,
- * CM_L4PER_DYNAMICDEP, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP
+ * Used by CM_D2D_DYNAMICDEP, CM_D2D_DYNAMICDEP_RESTORE, CM_DUCATI_DYNAMICDEP,
+ * CM_EMU_DYNAMICDEP, CM_L3_1_DYNAMICDEP, CM_L3_1_DYNAMICDEP_RESTORE,
+ * CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
+ * CM_L4CFG_DYNAMICDEP_RESTORE, CM_L4PER_DYNAMICDEP,
+ * CM_L4PER_DYNAMICDEP_RESTORE, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP
  */
 #define OMAP4430_WINDOWSIZE_SHIFT				24
-#define OMAP4430_WINDOWSIZE_MASK				BITFIELD(24, 27)
+#define OMAP4430_WINDOWSIZE_MASK				(0xf << 24)
+
+/* Used by REVISION_CM1, REVISION_CM2 */
+#define OMAP4430_X_MAJOR_SHIFT					8
+#define OMAP4430_X_MAJOR_MASK					(0x7 << 8)
+
+/* Used by REVISION_CM1, REVISION_CM2 */
+#define OMAP4430_Y_MINOR_SHIFT					0
+#define OMAP4430_Y_MINOR_MASK					(0x3f << 0)
 #endif
diff --git a/arch/arm/mach-omap2/cm44xx.h b/arch/arm/mach-omap2/cm44xx.h
index 336d948..3c35a87 100644
--- a/arch/arm/mach-omap2/cm44xx.h
+++ b/arch/arm/mach-omap2/cm44xx.h
@@ -195,6 +195,42 @@
 #define OMAP4_CM1_ABE_WDT3_CLKCTRL_OFFSET		0x0088
 #define OMAP4430_CM1_ABE_WDT3_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0088)
 
+/* CM1.RESTORE_CM1 register offsets */
+#define OMAP4_CM_CLKSEL_CORE_RESTORE_OFFSET		0x0000
+#define OMAP4430_CM_CLKSEL_CORE_RESTORE			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0000)
+#define OMAP4_CM_DIV_M2_DPLL_CORE_RESTORE_OFFSET	0x0004
+#define OMAP4430_CM_DIV_M2_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0004)
+#define OMAP4_CM_DIV_M3_DPLL_CORE_RESTORE_OFFSET	0x0008
+#define OMAP4430_CM_DIV_M3_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0008)
+#define OMAP4_CM_DIV_M4_DPLL_CORE_RESTORE_OFFSET	0x000c
+#define OMAP4430_CM_DIV_M4_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x000c)
+#define OMAP4_CM_DIV_M5_DPLL_CORE_RESTORE_OFFSET	0x0010
+#define OMAP4430_CM_DIV_M5_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0010)
+#define OMAP4_CM_DIV_M6_DPLL_CORE_RESTORE_OFFSET	0x0014
+#define OMAP4430_CM_DIV_M6_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0014)
+#define OMAP4_CM_DIV_M7_DPLL_CORE_RESTORE_OFFSET	0x0018
+#define OMAP4430_CM_DIV_M7_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0018)
+#define OMAP4_CM_CLKSEL_DPLL_CORE_RESTORE_OFFSET	0x001c
+#define OMAP4430_CM_CLKSEL_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x001c)
+#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_CORE_RESTORE_OFFSET	0x0020
+#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_CORE_RESTORE	OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0020)
+#define OMAP4_CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE_OFFSET	0x0024
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE	OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0024)
+#define OMAP4_CM_CLKMODE_DPLL_CORE_RESTORE_OFFSET	0x0028
+#define OMAP4430_CM_CLKMODE_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0028)
+#define OMAP4_CM_SHADOW_FREQ_CONFIG2_RESTORE_OFFSET	0x002c
+#define OMAP4430_CM_SHADOW_FREQ_CONFIG2_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x002c)
+#define OMAP4_CM_SHADOW_FREQ_CONFIG1_RESTORE_OFFSET	0x0030
+#define OMAP4430_CM_SHADOW_FREQ_CONFIG1_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0030)
+#define OMAP4_CM_AUTOIDLE_DPLL_CORE_RESTORE_OFFSET	0x0034
+#define OMAP4430_CM_AUTOIDLE_DPLL_CORE_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0034)
+#define OMAP4_CM_MPU_CLKSTCTRL_RESTORE_OFFSET		0x0038
+#define OMAP4430_CM_MPU_CLKSTCTRL_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0038)
+#define OMAP4_CM_CM1_PROFILING_CLKCTRL_RESTORE_OFFSET	0x003c
+#define OMAP4430_CM_CM1_PROFILING_CLKCTRL_RESTORE	OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x003c)
+#define OMAP4_CM_DYN_DEP_PRESCAL_RESTORE_OFFSET		0x0040
+#define OMAP4430_CM_DYN_DEP_PRESCAL_RESTORE		OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0040)
+
 /* CM2 */
 
 /* CM2.OCP_SOCKET_CM2 register offsets */
@@ -252,8 +288,6 @@
 #define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_PER		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0068)
 #define OMAP4_CM_SSC_MODFREQDIV_DPLL_PER_OFFSET		0x006c
 #define OMAP4430_CM_SSC_MODFREQDIV_DPLL_PER		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x006c)
-#define OMAP4_CM_EMU_OVERRIDE_DPLL_PER_OFFSET		0x0070
-#define OMAP4430_CM_EMU_OVERRIDE_DPLL_PER		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0070)
 #define OMAP4_CM_CLKMODE_DPLL_USB_OFFSET		0x0080
 #define OMAP4430_CM_CLKMODE_DPLL_USB			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0080)
 #define OMAP4_CM_IDLEST_DPLL_USB_OFFSET			0x0084
@@ -296,6 +330,8 @@
 #define OMAP4430_CM_ALWON_SR_IVA_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_ALWAYS_ON_MOD, 0x0030)
 #define OMAP4_CM_ALWON_SR_CORE_CLKCTRL_OFFSET		0x0038
 #define OMAP4430_CM_ALWON_SR_CORE_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_ALWAYS_ON_MOD, 0x0038)
+#define OMAP4_CM_ALWON_USBPHY_CLKCTRL_OFFSET		0x0040
+#define OMAP4430_CM_ALWON_USBPHY_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_ALWAYS_ON_MOD, 0x0040)
 
 /* CM2.CORE_CM2 register offsets */
 #define OMAP4_CM_L3_1_CLKSTCTRL_OFFSET			0x0000
@@ -578,4 +614,54 @@
 #define OMAP4430_CM_CEFUSE_CLKSTCTRL			OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CEFUSE_MOD, 0x0000)
 #define OMAP4_CM_CEFUSE_CEFUSE_CLKCTRL_OFFSET		0x0020
 #define OMAP4430_CM_CEFUSE_CEFUSE_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CEFUSE_MOD, 0x0020)
+
+/* CM2.RESTORE_CM2 register offsets */
+#define OMAP4_CM_L3_1_CLKSTCTRL_RESTORE_OFFSET		0x0000
+#define OMAP4430_CM_L3_1_CLKSTCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0000)
+#define OMAP4_CM_L3_2_CLKSTCTRL_RESTORE_OFFSET		0x0004
+#define OMAP4430_CM_L3_2_CLKSTCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0004)
+#define OMAP4_CM_L4CFG_CLKSTCTRL_RESTORE_OFFSET		0x0008
+#define OMAP4430_CM_L4CFG_CLKSTCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0008)
+#define OMAP4_CM_MEMIF_CLKSTCTRL_RESTORE_OFFSET		0x000c
+#define OMAP4430_CM_MEMIF_CLKSTCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x000c)
+#define OMAP4_CM_L4PER_CLKSTCTRL_RESTORE_OFFSET		0x0010
+#define OMAP4430_CM_L4PER_CLKSTCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0010)
+#define OMAP4_CM_L3INIT_CLKSTCTRL_RESTORE_OFFSET	0x0014
+#define OMAP4430_CM_L3INIT_CLKSTCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0014)
+#define OMAP4_CM_L3INSTR_L3_3_CLKCTRL_RESTORE_OFFSET	0x0018
+#define OMAP4430_CM_L3INSTR_L3_3_CLKCTRL_RESTORE	OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0018)
+#define OMAP4_CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE_OFFSET	0x001c
+#define OMAP4430_CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE	OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x001c)
+#define OMAP4_CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE_OFFSET	0x0020
+#define OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE	OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0020)
+#define OMAP4_CM_CM2_PROFILING_CLKCTRL_RESTORE_OFFSET	0x0024
+#define OMAP4430_CM_CM2_PROFILING_CLKCTRL_RESTORE	OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0024)
+#define OMAP4_CM_D2D_STATICDEP_RESTORE_OFFSET		0x0028
+#define OMAP4430_CM_D2D_STATICDEP_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0028)
+#define OMAP4_CM_L3_1_DYNAMICDEP_RESTORE_OFFSET		0x002c
+#define OMAP4430_CM_L3_1_DYNAMICDEP_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x002c)
+#define OMAP4_CM_L3_2_DYNAMICDEP_RESTORE_OFFSET		0x0030
+#define OMAP4430_CM_L3_2_DYNAMICDEP_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0030)
+#define OMAP4_CM_D2D_DYNAMICDEP_RESTORE_OFFSET		0x0034
+#define OMAP4430_CM_D2D_DYNAMICDEP_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0034)
+#define OMAP4_CM_L4CFG_DYNAMICDEP_RESTORE_OFFSET	0x0038
+#define OMAP4430_CM_L4CFG_DYNAMICDEP_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0038)
+#define OMAP4_CM_L4PER_DYNAMICDEP_RESTORE_OFFSET	0x003c
+#define OMAP4430_CM_L4PER_DYNAMICDEP_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x003c)
+#define OMAP4_CM_L4PER_GPIO2_CLKCTRL_RESTORE_OFFSET	0x0040
+#define OMAP4430_CM_L4PER_GPIO2_CLKCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0040)
+#define OMAP4_CM_L4PER_GPIO3_CLKCTRL_RESTORE_OFFSET	0x0044
+#define OMAP4430_CM_L4PER_GPIO3_CLKCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0044)
+#define OMAP4_CM_L4PER_GPIO4_CLKCTRL_RESTORE_OFFSET	0x0048
+#define OMAP4430_CM_L4PER_GPIO4_CLKCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0048)
+#define OMAP4_CM_L4PER_GPIO5_CLKCTRL_RESTORE_OFFSET	0x004c
+#define OMAP4430_CM_L4PER_GPIO5_CLKCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x004c)
+#define OMAP4_CM_L4PER_GPIO6_CLKCTRL_RESTORE_OFFSET	0x0050
+#define OMAP4430_CM_L4PER_GPIO6_CLKCTRL_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0050)
+#define OMAP4_CM_L3INIT_USB_HOST_CLKCTRL_RESTORE_OFFSET	0x0054
+#define OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL_RESTORE	OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0054)
+#define OMAP4_CM_L3INIT_USB_TLL_CLKCTRL_RESTORE_OFFSET	0x0058
+#define OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL_RESTORE	OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0058)
+#define OMAP4_CM_SDMA_STATICDEP_RESTORE_OFFSET		0x005c
+#define OMAP4430_CM_SDMA_STATICDEP_RESTORE		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x005c)
 #endif
diff --git a/arch/arm/mach-omap2/cm4xxx.c b/arch/arm/mach-omap2/cm4xxx.c
index b101091..f8a660a 100644
--- a/arch/arm/mach-omap2/cm4xxx.c
+++ b/arch/arm/mach-omap2/cm4xxx.c
@@ -43,7 +43,6 @@
  *                 using separate functional clock
  *   0x3 disabled: Module is disabled and cannot be accessed
  *
- * TODO: Need to handle module accessible in idle state
  */
 int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg)
 {
@@ -52,9 +51,11 @@
 	if (!clkctrl_reg)
 		return 0;
 
-	omap_test_timeout(((__raw_readl(clkctrl_reg) &
-			    OMAP4430_IDLEST_MASK) == 0),
-			  MAX_MODULE_READY_TIME, i);
+	omap_test_timeout((
+		((__raw_readl(clkctrl_reg) & OMAP4430_IDLEST_MASK) == 0) ||
+		 (((__raw_readl(clkctrl_reg) & OMAP4430_IDLEST_MASK) >>
+		  OMAP4430_IDLEST_SHIFT) == 0x2)),
+		MAX_MODULE_READY_TIME, i);
 
 	return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
 }
diff --git a/arch/arm/mach-omap2/common.c b/arch/arm/mach-omap2/common.c
new file mode 100644
index 0000000..778929f
--- /dev/null
+++ b/arch/arm/mach-omap2/common.c
@@ -0,0 +1,135 @@
+/*
+ * linux/arch/arm/mach-omap2/common.c
+ *
+ * Code common to all OMAP2+ machines.
+ *
+ * Copyright (C) 2009 Texas Instruments
+ * Copyright (C) 2010 Nokia Corporation
+ * Tony Lindgren <tony@atomide.com>
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <plat/common.h>
+#include <plat/board.h>
+#include <plat/mux.h>
+
+#include <plat/clock.h>
+
+#include "sdrc.h"
+#include "control.h"
+
+/* Global address base setup code */
+
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+
+static void __init __omap2_set_globals(struct omap_globals *omap2_globals)
+{
+	omap2_set_globals_tap(omap2_globals);
+	omap2_set_globals_sdrc(omap2_globals);
+	omap2_set_globals_control(omap2_globals);
+	omap2_set_globals_prcm(omap2_globals);
+}
+
+#endif
+
+#if defined(CONFIG_ARCH_OMAP2420)
+
+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,
+	.uart1_phys	= OMAP2_UART1_BASE,
+	.uart2_phys	= OMAP2_UART2_BASE,
+	.uart3_phys	= OMAP2_UART3_BASE,
+};
+
+void __init omap2_set_globals_242x(void)
+{
+	__omap2_set_globals(&omap242x_globals);
+}
+#endif
+
+#if defined(CONFIG_ARCH_OMAP2430)
+
+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,
+	.uart1_phys	= OMAP2_UART1_BASE,
+	.uart2_phys	= OMAP2_UART2_BASE,
+	.uart3_phys	= OMAP2_UART3_BASE,
+};
+
+void __init omap2_set_globals_243x(void)
+{
+	__omap2_set_globals(&omap243x_globals);
+}
+#endif
+
+#if defined(CONFIG_ARCH_OMAP3)
+
+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,
+	.uart1_phys	= OMAP3_UART1_BASE,
+	.uart2_phys	= OMAP3_UART2_BASE,
+	.uart3_phys	= OMAP3_UART3_BASE,
+	.uart4_phys	= OMAP3_UART4_BASE,	/* Only on 3630 */
+};
+
+void __init omap2_set_globals_3xxx(void)
+{
+	__omap2_set_globals(&omap3_globals);
+}
+
+void __init omap3_map_io(void)
+{
+	omap2_set_globals_3xxx();
+	omap34xx_map_common_io();
+}
+#endif
+
+#if defined(CONFIG_ARCH_OMAP4)
+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,
+	.uart1_phys	= OMAP4_UART1_BASE,
+	.uart2_phys	= OMAP4_UART2_BASE,
+	.uart3_phys	= OMAP4_UART3_BASE,
+	.uart4_phys	= OMAP4_UART4_BASE,
+};
+
+void __init omap2_set_globals_443x(void)
+{
+	omap2_set_globals_tap(&omap4_globals);
+	omap2_set_globals_control(&omap4_globals);
+	omap2_set_globals_prcm(&omap4_globals);
+}
+#endif
+
diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c
index a8d20ee..1fa3294 100644
--- a/arch/arm/mach-omap2/control.c
+++ b/arch/arm/mach-omap2/control.c
@@ -16,15 +16,18 @@
 #include <linux/io.h>
 
 #include <plat/common.h>
-#include <plat/control.h>
 #include <plat/sdrc.h>
+
 #include "cm-regbits-34xx.h"
 #include "prm-regbits-34xx.h"
 #include "cm.h"
 #include "prm.h"
 #include "sdrc.h"
+#include "pm.h"
+#include "control.h"
 
 static void __iomem *omap2_ctrl_base;
+static void __iomem *omap4_ctrl_pad_base;
 
 #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
 struct omap3_scratchpad {
@@ -137,6 +140,7 @@
 #endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */
 
 #define OMAP_CTRL_REGADDR(reg)		(omap2_ctrl_base + (reg))
+#define OMAP4_CTRL_PAD_REGADDR(reg)	(omap4_ctrl_pad_base + (reg))
 
 void __init omap2_set_globals_control(struct omap_globals *omap2_globals)
 {
@@ -145,6 +149,12 @@
 		omap2_ctrl_base = ioremap(omap2_globals->ctrl, SZ_4K);
 		WARN_ON(!omap2_ctrl_base);
 	}
+
+	/* 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);
+	}
 }
 
 void __iomem *omap_ctrl_base_get(void)
@@ -182,6 +192,23 @@
 	__raw_writel(val, OMAP_CTRL_REGADDR(offset));
 }
 
+/*
+ * On OMAP4 control pad are not addressable from control
+ * core base. So the common omap_ctrl_read/write APIs breaks
+ * Hence export separate APIs to manage the omap4 pad control
+ * registers. This APIs will work only for OMAP4
+ */
+
+u32 omap4_ctrl_pad_readl(u16 offset)
+{
+	return __raw_readl(OMAP4_CTRL_PAD_REGADDR(offset));
+}
+
+void omap4_ctrl_pad_writel(u32 val, u16 offset)
+{
+	__raw_writel(val, OMAP4_CTRL_PAD_REGADDR(offset));
+}
+
 #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
 /*
  * Clears the scratchpad contents in case of cold boot-
@@ -190,7 +217,7 @@
 void omap3_clear_scratchpad_contents(void)
 {
 	u32 max_offset = OMAP343X_SCRATCHPAD_ROM_OFFSET;
-	u32 *v_addr;
+	void __iomem *v_addr;
 	u32 offset = 0;
 	v_addr = OMAP2_L4_IO_ADDRESS(OMAP343X_SCRATCHPAD_ROM);
 	if (prm_read_mod_reg(OMAP3430_GR_MOD, OMAP3_PRM_RSTST_OFFSET) &
@@ -206,7 +233,7 @@
 /* Populate the scratchpad structure with restore structure */
 void omap3_save_scratchpad_contents(void)
 {
-	void * __iomem scratchpad_address;
+	void  __iomem *scratchpad_address;
 	u32 arm_context_addr;
 	struct omap3_scratchpad scratchpad_contents;
 	struct omap3_scratchpad_prcm_block prcm_block_contents;
diff --git a/arch/arm/plat-omap/include/plat/control.h b/arch/arm/mach-omap2/control.h
similarity index 92%
rename from arch/arm/plat-omap/include/plat/control.h
rename to arch/arm/mach-omap2/control.h
index 131bf40..b6c6b7c 100644
--- a/arch/arm/plat-omap/include/plat/control.h
+++ b/arch/arm/mach-omap2/control.h
@@ -1,10 +1,10 @@
 /*
- * arch/arm/plat-omap/include/mach/control.h
+ * arch/arm/mach-omap2/control.h
  *
  * OMAP2/3/4 System Control Module definitions
  *
- * Copyright (C) 2007-2009 Texas Instruments, Inc.
- * Copyright (C) 2007-2008 Nokia Corporation
+ * Copyright (C) 2007-2010 Texas Instruments, Inc.
+ * Copyright (C) 2007-2008, 2010 Nokia Corporation
  *
  * Written by Paul Walmsley
  *
@@ -13,10 +13,14 @@
  * the Free Software Foundation.
  */
 
-#ifndef __ASM_ARCH_CONTROL_H
-#define __ASM_ARCH_CONTROL_H
+#ifndef __ARCH_ARM_MACH_OMAP2_CONTROL_H
+#define __ARCH_ARM_MACH_OMAP2_CONTROL_H
 
 #include <mach/io.h>
+#include <mach/ctrl_module_core_44xx.h>
+#include <mach/ctrl_module_wkup_44xx.h>
+#include <mach/ctrl_module_pad_core_44xx.h>
+#include <mach/ctrl_module_pad_wkup_44xx.h>
 
 #ifndef __ASSEMBLY__
 #define OMAP242X_CTRL_REGADDR(reg)					\
@@ -204,12 +208,6 @@
 #define OMAP3_PADCONF_SAD2D_MSTANDBY   0x250
 #define OMAP3_PADCONF_SAD2D_IDLEACK    0x254
 
-/* 44xx control status register offset */
-#define OMAP44XX_CONTROL_STATUS		0x2c4
-
-/* 44xx-only CONTROL_GENERAL register offsets */
-#define OMAP44XX_CONTROL_MMC1			0x628
-#define OMAP44XX_CONTROL_PBIAS_LITE		0x600
 /*
  * REVISIT: This list of registers is not comprehensive - there are more
  * that should be added.
@@ -225,6 +223,8 @@
 #define OMAP2_MMCSDIO1ADPCLKISEL	(1 << 24) /* MMC1 loop back clock */
 #define OMAP24XX_USBSTANDBYCTRL		(1 << 15)
 #define OMAP2_MCBSP2_CLKS_MASK		(1 << 6)
+#define OMAP2_MCBSP1_FSR_MASK		(1 << 4)
+#define OMAP2_MCBSP1_CLKR_MASK		(1 << 3)
 #define OMAP2_MCBSP1_CLKS_MASK		(1 << 2)
 
 /* CONTROL_DEVCONF1 bits */
@@ -255,23 +255,6 @@
 #define OMAP2_PBIASLITEPWRDNZ0		(1 << 1)
 #define OMAP2_PBIASLITEVMODE0		(1 << 0)
 
-/* CONTROL_PBIAS_LITE bits for OMAP4 */
-#define OMAP4_MMC1_PWRDNZ			(1 << 26)
-#define OMAP4_MMC1_PBIASLITE_HIZ_MODE		(1 << 25)
-#define OMAP4_MMC1_PBIASLITE_SUPPLY_HI_OUT	(1 << 24)
-#define OMAP4_MMC1_PBIASLITE_VMODE_ERROR	(1 << 23)
-#define OMAP4_MMC1_PBIASLITE_PWRDNZ		(1 << 22)
-#define OMAP4_MMC1_PBIASLITE_VMODE		(1 << 21)
-#define OMAP4_USBC1_ICUSB_PWRDNZ		(1 << 20)
-
-#define OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP0	(1 << 31)
-#define OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP1	(1 << 30)
-#define OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP2	(1 << 29)
-#define OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP3	(1 << 28)
-#define OMAP4_CONTROL_SDMMC1_DR0_SPEEDCTRL	(1 << 27)
-#define OMAP4_CONTROL_SDMMC1_DR1_SPEEDCTRL	(1 << 26)
-#define OMAP4_CONTROL_SDMMC1_DR2_SPEEDCTRL	(1 << 25)
-
 /* CONTROL_PROG_IO1 bits */
 #define OMAP3630_PRG_SDMMC1_SPEEDCTRL	(1 << 20)
 
@@ -338,12 +321,12 @@
 #define		FEAT_L2CACHE_256KB	3
 
 #define OMAP3_ISP_SHIFT			5
-#define OMAP3_ISP_MASK			(1<< OMAP3_ISP_SHIFT)
+#define OMAP3_ISP_MASK			(1 << OMAP3_ISP_SHIFT)
 #define		FEAT_ISP		0
 #define		FEAT_ISP_NONE		1
 
 #define OMAP3_NEON_SHIFT		4
-#define OMAP3_NEON_MASK			(1<< OMAP3_NEON_SHIFT)
+#define OMAP3_NEON_MASK			(1 << OMAP3_NEON_SHIFT)
 #define		FEAT_NEON		0
 #define		FEAT_NEON_NONE		1
 
@@ -354,9 +337,11 @@
 extern u8 omap_ctrl_readb(u16 offset);
 extern u16 omap_ctrl_readw(u16 offset);
 extern u32 omap_ctrl_readl(u16 offset);
+extern u32 omap4_ctrl_pad_readl(u16 offset);
 extern void omap_ctrl_writeb(u8 val, u16 offset);
 extern void omap_ctrl_writew(u16 val, u16 offset);
 extern void omap_ctrl_writel(u32 val, u16 offset);
+extern void omap4_ctrl_pad_writel(u32 val, u16 offset);
 
 extern void omap3_save_scratchpad_contents(void);
 extern void omap3_clear_scratchpad_contents(void);
@@ -371,11 +356,13 @@
 #define omap_ctrl_readb(x)		0
 #define omap_ctrl_readw(x)		0
 #define omap_ctrl_readl(x)		0
+#define omap4_ctrl_pad_readl(x)		0
 #define omap_ctrl_writeb(x, y)		WARN_ON(1)
 #define omap_ctrl_writew(x, y)		WARN_ON(1)
 #define omap_ctrl_writel(x, y)		WARN_ON(1)
+#define omap4_ctrl_pad_writel(x, y)	WARN_ON(1)
 #endif
 #endif	/* __ASSEMBLY__ */
 
-#endif /* __ASM_ARCH_CONTROL_H */
+#endif /* __ARCH_ARM_MACH_OMAP2_CONTROL_H */
 
diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index 3d3d035..0d50b45 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -29,10 +29,10 @@
 #include <plat/irqs.h>
 #include <plat/powerdomain.h>
 #include <plat/clockdomain.h>
-#include <plat/control.h>
 #include <plat/serial.h>
 
 #include "pm.h"
+#include "control.h"
 
 #ifdef CONFIG_CPU_IDLE
 
@@ -60,7 +60,8 @@
 
 struct omap3_processor_cx omap3_power_states[OMAP3_MAX_STATES];
 struct omap3_processor_cx current_cx_state;
-struct powerdomain *mpu_pd, *core_pd;
+struct powerdomain *mpu_pd, *core_pd, *per_pd;
+struct powerdomain *cam_pd;
 
 /*
  * The latencies/thresholds for various C states have
@@ -233,14 +234,60 @@
 			       struct cpuidle_state *state)
 {
 	struct cpuidle_state *new_state = next_valid_state(dev, state);
+	u32 core_next_state, per_next_state = 0, per_saved_state = 0;
+	u32 cam_state;
+	struct omap3_processor_cx *cx;
+	int ret;
 
 	if ((state->flags & CPUIDLE_FLAG_CHECK_BM) && omap3_idle_bm_check()) {
 		BUG_ON(!dev->safe_state);
 		new_state = dev->safe_state;
+		goto select_state;
 	}
 
+	cx = cpuidle_get_statedata(state);
+	core_next_state = cx->core_state;
+
+	/*
+	 * FIXME: we currently manage device-specific idle states
+	 *        for PER and CORE in combination with CPU-specific
+	 *        idle states.  This is wrong, and device-specific
+	 *        idle managment needs to be separated out into 
+	 *        its own code.
+	 */
+
+	/*
+	 * Prevent idle completely if CAM is active.
+	 * CAM does not have wakeup capability in OMAP3.
+	 */
+	cam_state = pwrdm_read_pwrst(cam_pd);
+	if (cam_state == PWRDM_POWER_ON) {
+		new_state = dev->safe_state;
+		goto select_state;
+	}
+
+	/*
+	 * Prevent PER off if CORE is not in retention or off as this
+	 * would disable PER wakeups completely.
+	 */
+	per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd);
+	if ((per_next_state == PWRDM_POWER_OFF) &&
+	    (core_next_state > PWRDM_POWER_RET))
+		per_next_state = PWRDM_POWER_RET;
+
+	/* Are we changing PER target state? */
+	if (per_next_state != per_saved_state)
+		pwrdm_set_next_pwrst(per_pd, per_next_state);
+
+select_state:
 	dev->last_state = new_state;
-	return omap3_enter_idle(dev, new_state);
+	ret = omap3_enter_idle(dev, new_state);
+
+	/* Restore original PER state if it was modified */
+	if (per_next_state != per_saved_state)
+		pwrdm_set_next_pwrst(per_pd, per_saved_state);
+
+	return ret;
 }
 
 DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev);
@@ -328,7 +375,8 @@
 			cpuidle_params_table[OMAP3_STATE_C2].threshold;
 	omap3_power_states[OMAP3_STATE_C2].mpu_state = PWRDM_POWER_ON;
 	omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_ON;
-	omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID;
+	omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID |
+				CPUIDLE_FLAG_CHECK_BM;
 
 	/* C3 . MPU CSWR + Core inactive */
 	omap3_power_states[OMAP3_STATE_C3].valid =
@@ -426,6 +474,8 @@
 
 	mpu_pd = pwrdm_lookup("mpu_pwrdm");
 	core_pd = pwrdm_lookup("core_pwrdm");
+	per_pd = pwrdm_lookup("per_pwrdm");
+	cam_pd = pwrdm_lookup("cam_pwrdm");
 
 	omap_init_power_states();
 	cpuidle_register_driver(&omap3_idle_driver);
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index c5cf1ba..5a0c148 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -9,12 +9,12 @@
  * (at your option) any later version.
  */
 
-#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/clk.h>
+#include <linux/err.h>
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
@@ -22,15 +22,17 @@
 #include <asm/mach/map.h>
 #include <asm/pmu.h>
 
-#include <plat/control.h>
 #include <plat/tc.h>
 #include <plat/board.h>
 #include <plat/mcbsp.h>
 #include <mach/gpio.h>
 #include <plat/mmc.h>
 #include <plat/dma.h>
+#include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
 
 #include "mux.h"
+#include "control.h"
 
 #if defined(CONFIG_VIDEO_OMAP2) || defined(CONFIG_VIDEO_OMAP2_MODULE)
 
@@ -538,7 +540,7 @@
 
 #if defined(CONFIG_CRYPTO_DEV_OMAP_AES) || defined(CONFIG_CRYPTO_DEV_OMAP_AES_MODULE)
 
-#ifdef CONFIG_ARCH_OMAP24XX
+#ifdef CONFIG_ARCH_OMAP2
 static struct resource omap2_aes_resources[] = {
 	{
 		.start	= OMAP24XX_SEC_AES_BASE,
@@ -560,7 +562,7 @@
 #define omap2_aes_resources_sz		0
 #endif
 
-#ifdef CONFIG_ARCH_OMAP34XX
+#ifdef CONFIG_ARCH_OMAP3
 static struct resource omap3_aes_resources[] = {
 	{
 		.start	= OMAP34XX_SEC_AES_BASE,
@@ -732,7 +734,7 @@
 		omap_mux_init_signal("sdmmc_dat0", 0);
 		omap_mux_init_signal("sdmmc_dat_dir0", 0);
 		omap_mux_init_signal("sdmmc_cmd_dir", 0);
-		if (mmc_controller->slots[0].wires == 4) {
+		if (mmc_controller->slots[0].caps & MMC_CAP_4_BIT_DATA) {
 			omap_mux_init_signal("sdmmc_dat1", 0);
 			omap_mux_init_signal("sdmmc_dat2", 0);
 			omap_mux_init_signal("sdmmc_dat3", 0);
@@ -760,8 +762,8 @@
 				OMAP_PIN_INPUT_PULLUP);
 			omap_mux_init_signal("sdmmc1_dat0",
 				OMAP_PIN_INPUT_PULLUP);
-			if (mmc_controller->slots[0].wires == 4 ||
-				mmc_controller->slots[0].wires == 8) {
+			if (mmc_controller->slots[0].caps &
+				(MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)) {
 				omap_mux_init_signal("sdmmc1_dat1",
 					OMAP_PIN_INPUT_PULLUP);
 				omap_mux_init_signal("sdmmc1_dat2",
@@ -769,7 +771,8 @@
 				omap_mux_init_signal("sdmmc1_dat3",
 					OMAP_PIN_INPUT_PULLUP);
 			}
-			if (mmc_controller->slots[0].wires == 8) {
+			if (mmc_controller->slots[0].caps &
+						MMC_CAP_8_BIT_DATA) {
 				omap_mux_init_signal("sdmmc1_dat4",
 					OMAP_PIN_INPUT_PULLUP);
 				omap_mux_init_signal("sdmmc1_dat5",
@@ -793,8 +796,8 @@
 			 * For 8 wire configurations, Lines DAT4, 5, 6 and 7 need to be muxed
 			 * in the board-*.c files
 			 */
-			if (mmc_controller->slots[0].wires == 4 ||
-				mmc_controller->slots[0].wires == 8) {
+			if (mmc_controller->slots[0].caps &
+				(MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)) {
 				omap_mux_init_signal("sdmmc2_dat1",
 					OMAP_PIN_INPUT_PULLUP);
 				omap_mux_init_signal("sdmmc2_dat2",
@@ -802,7 +805,8 @@
 				omap_mux_init_signal("sdmmc2_dat3",
 					OMAP_PIN_INPUT_PULLUP);
 			}
-			if (mmc_controller->slots[0].wires == 8) {
+			if (mmc_controller->slots[0].caps &
+							MMC_CAP_8_BIT_DATA) {
 				omap_mux_init_signal("sdmmc2_dat4.sdmmc2_dat4",
 					OMAP_PIN_INPUT_PULLUP);
 				omap_mux_init_signal("sdmmc2_dat5.sdmmc2_dat5",
@@ -853,13 +857,13 @@
 		case 3:
 			if (!cpu_is_omap44xx())
 				return;
-			base = OMAP4_MMC4_BASE + OMAP4_MMC_REG_OFFSET;
+			base = OMAP4_MMC4_BASE;
 			irq = OMAP44XX_IRQ_MMC4;
 			break;
 		case 4:
 			if (!cpu_is_omap44xx())
 				return;
-			base = OMAP4_MMC5_BASE + OMAP4_MMC_REG_OFFSET;
+			base = OMAP4_MMC5_BASE;
 			irq = OMAP44XX_IRQ_MMC5;
 			break;
 		default:
@@ -870,10 +874,8 @@
 			size = OMAP2420_MMC_SIZE;
 			name = "mmci-omap";
 		} else if (cpu_is_omap44xx()) {
-			if (i < 3) {
-				base += OMAP4_MMC_REG_OFFSET;
+			if (i < 3)
 				irq += OMAP44XX_IRQ_GIC_START;
-			}
 			size = OMAP4_HSMMC_SIZE;
 			name = "mmci-omap-hs";
 		} else {
@@ -949,11 +951,72 @@
 
 /*-------------------------------------------------------------------------*/
 
+/*
+ * Inorder to avoid any assumptions from bootloader regarding WDT
+ * settings, WDT module is reset during init. This enables the watchdog
+ * timer. Hence it is required to disable the watchdog after the WDT reset
+ * during init. Otherwise the system would reboot as per the default
+ * watchdog timer registers settings.
+ */
+#define OMAP_WDT_WPS	(0x34)
+#define OMAP_WDT_SPR	(0x48)
+
+static int omap2_disable_wdt(struct omap_hwmod *oh, void *unused)
+{
+	void __iomem *base;
+	int ret;
+
+	if (!oh) {
+		pr_err("%s: Could not look up wdtimer_hwmod\n", __func__);
+		return -EINVAL;
+	}
+
+	base = omap_hwmod_get_mpu_rt_va(oh);
+	if (!base) {
+		pr_err("%s: Could not get the base address for %s\n",
+				oh->name, __func__);
+		return -EINVAL;
+	}
+
+	/* Enable the clocks before accessing the WDT registers */
+	ret = omap_hwmod_enable(oh);
+	if (ret) {
+		pr_err("%s: Could not enable clocks for %s\n",
+				oh->name, __func__);
+		return ret;
+	}
+
+	/* sequence required to disable watchdog */
+	__raw_writel(0xAAAA, base + OMAP_WDT_SPR);
+	while (__raw_readl(base + OMAP_WDT_WPS) & 0x10)
+		cpu_relax();
+
+	__raw_writel(0x5555, base + OMAP_WDT_SPR);
+	while (__raw_readl(base + OMAP_WDT_WPS) & 0x10)
+		cpu_relax();
+
+	ret = omap_hwmod_idle(oh);
+	if (ret)
+		pr_err("%s: Could not disable clocks for %s\n",
+				oh->name, __func__);
+
+	return ret;
+}
+
+static void __init omap_disable_wdt(void)
+{
+	if (cpu_class_is_omap2())
+		omap_hwmod_for_each_by_class("wd_timer",
+						omap2_disable_wdt, NULL);
+	return;
+}
+
 static int __init omap2_init_devices(void)
 {
 	/* please keep these calls, and their implementations above,
 	 * in alphabetical order so they're easier to sort through.
 	 */
+	omap_disable_wdt();
 	omap_hsmmc_reset();
 	omap_init_audio();
 	omap_init_camera();
@@ -969,3 +1032,39 @@
 	return 0;
 }
 arch_initcall(omap2_init_devices);
+
+#if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE)
+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 omap_hwmod *oh;
+	char *oh_name = "wd_timer2";
+	char *dev_name = "omap_wdt";
+
+	if (!cpu_class_is_omap2())
+		return 0;
+
+	oh = omap_hwmod_lookup(oh_name);
+	if (!oh) {
+		pr_err("Could not look up wd_timer%d hwmod\n", id);
+		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), "Cant build omap_device for %s:%s.\n",
+				dev_name, oh->name);
+	return 0;
+}
+subsys_initcall(omap_init_wdt);
+#endif
diff --git a/arch/arm/mach-omap2/gpmc-smsc911x.c b/arch/arm/mach-omap2/gpmc-smsc911x.c
new file mode 100644
index 0000000..703f150
--- /dev/null
+++ b/arch/arm/mach-omap2/gpmc-smsc911x.c
@@ -0,0 +1,113 @@
+/*
+ * linux/arch/arm/mach-omap2/gpmc-smsc911x.c
+ *
+ * Copyright (C) 2009 Li-Pro.Net
+ * Stephan Linz <linz@li-pro.net>
+ *
+ * Modified from linux/arch/arm/mach-omap2/gpmc-smc91x.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/smsc911x.h>
+
+#include <plat/board.h>
+#include <plat/gpmc.h>
+#include <plat/gpmc-smsc911x.h>
+
+static struct omap_smsc911x_platform_data *gpmc_cfg;
+
+static struct resource gpmc_smsc911x_resources[] = {
+	[0] = {
+		.flags		= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct smsc911x_platform_config gpmc_smsc911x_config = {
+	.phy_interface	= PHY_INTERFACE_MODE_MII,
+	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.irq_type	= SMSC911X_IRQ_TYPE_OPEN_DRAIN,
+	.flags		= SMSC911X_USE_16BIT,
+};
+
+static struct platform_device gpmc_smsc911x_device = {
+	.name		= "smsc911x",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(gpmc_smsc911x_resources),
+	.resource	= gpmc_smsc911x_resources,
+	.dev		= {
+		.platform_data = &gpmc_smsc911x_config,
+	},
+};
+
+/*
+ * Initialize smsc911x device connected to the GPMC. Note that we
+ * assume that pin multiplexing is done in the board-*.c file,
+ * or in the bootloader.
+ */
+void __init gpmc_smsc911x_init(struct omap_smsc911x_platform_data *board_data)
+{
+	unsigned long cs_mem_base;
+	int ret;
+
+	gpmc_cfg = board_data;
+
+	if (gpmc_cs_request(gpmc_cfg->cs, SZ_16M, &cs_mem_base) < 0) {
+		printk(KERN_ERR "Failed to request GPMC mem for smsc911x\n");
+		return;
+	}
+
+	gpmc_smsc911x_resources[0].start = cs_mem_base + 0x0;
+	gpmc_smsc911x_resources[0].end = cs_mem_base + 0xff;
+
+	if (gpio_request(gpmc_cfg->gpio_irq, "smsc911x irq") < 0) {
+		printk(KERN_ERR "Failed to request GPIO%d for smsc911x IRQ\n",
+				gpmc_cfg->gpio_irq);
+		goto free1;
+	}
+
+	gpio_direction_input(gpmc_cfg->gpio_irq);
+	gpmc_smsc911x_resources[1].start = gpio_to_irq(gpmc_cfg->gpio_irq);
+	gpmc_smsc911x_resources[1].flags |=
+					(gpmc_cfg->flags & IRQF_TRIGGER_MASK);
+
+	if (gpio_is_valid(gpmc_cfg->gpio_reset)) {
+		ret = gpio_request(gpmc_cfg->gpio_reset, "smsc911x reset");
+		if (ret) {
+			printk(KERN_ERR "Failed to request GPIO%d for smsc911x reset\n",
+					gpmc_cfg->gpio_reset);
+			goto free2;
+		}
+
+		gpio_direction_output(gpmc_cfg->gpio_reset, 1);
+		gpio_set_value(gpmc_cfg->gpio_reset, 0);
+		msleep(100);
+		gpio_set_value(gpmc_cfg->gpio_reset, 1);
+	}
+
+	if (platform_device_register(&gpmc_smsc911x_device) < 0) {
+		printk(KERN_ERR "Unable to register smsc911x device\n");
+		gpio_free(gpmc_cfg->gpio_reset);
+		goto free2;
+	}
+
+	return;
+
+free2:
+	gpio_free(gpmc_cfg->gpio_irq);
+free1:
+	gpmc_cs_free(gpmc_cfg->cs);
+
+	printk(KERN_ERR "Could not initialize smsc911x\n");
+}
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index c8f647b..34272e4 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -14,11 +14,11 @@
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <mach/hardware.h>
-#include <plat/control.h>
 #include <plat/mmc.h>
 #include <plat/omap-pm.h>
 
 #include "hsmmc.h"
+#include "control.h"
 
 #if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
 
@@ -135,10 +135,11 @@
 	 *
 	 * FIXME handle VMMC1A as needed ...
 	 */
-	reg = omap_ctrl_readl(control_pbias_offset);
-	reg &= ~(OMAP4_MMC1_PBIASLITE_PWRDNZ | OMAP4_MMC1_PWRDNZ |
-					OMAP4_USBC1_ICUSB_PWRDNZ);
-	omap_ctrl_writel(reg, control_pbias_offset);
+	reg = omap4_ctrl_pad_readl(control_pbias_offset);
+	reg &= ~(OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK |
+		OMAP4_MMC1_PWRDNZ_MASK |
+		OMAP4_USBC1_ICUSB_PWRDNZ_MASK);
+	omap4_ctrl_pad_writel(reg, control_pbias_offset);
 }
 
 static void omap4_hsmmc1_after_set_reg(struct device *dev, int slot,
@@ -147,30 +148,33 @@
 	u32 reg;
 
 	if (power_on) {
-		reg = omap_ctrl_readl(control_pbias_offset);
-		reg |= OMAP4_MMC1_PBIASLITE_PWRDNZ;
+		reg = omap4_ctrl_pad_readl(control_pbias_offset);
+		reg |= OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK;
 		if ((1 << vdd) <= MMC_VDD_165_195)
-			reg &= ~OMAP4_MMC1_PBIASLITE_VMODE;
+			reg &= ~OMAP4_MMC1_PBIASLITE_VMODE_MASK;
 		else
-			reg |= OMAP4_MMC1_PBIASLITE_VMODE;
-		reg |= (OMAP4_MMC1_PBIASLITE_PWRDNZ | OMAP4_MMC1_PWRDNZ |
-						OMAP4_USBC1_ICUSB_PWRDNZ);
-		omap_ctrl_writel(reg, control_pbias_offset);
+			reg |= OMAP4_MMC1_PBIASLITE_VMODE_MASK;
+		reg |= (OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK |
+			OMAP4_MMC1_PWRDNZ_MASK |
+			OMAP4_USBC1_ICUSB_PWRDNZ_MASK);
+		omap4_ctrl_pad_writel(reg, control_pbias_offset);
 		/* 4 microsec delay for comparator to generate an error*/
 		udelay(4);
-		reg = omap_ctrl_readl(control_pbias_offset);
-		if (reg & OMAP4_MMC1_PBIASLITE_VMODE_ERROR) {
+		reg = omap4_ctrl_pad_readl(control_pbias_offset);
+		if (reg & OMAP4_MMC1_PBIASLITE_VMODE_ERROR_MASK) {
 			pr_err("Pbias Voltage is not same as LDO\n");
 			/* Caution : On VMODE_ERROR Power Down MMC IO */
-			reg &= ~(OMAP4_MMC1_PWRDNZ | OMAP4_USBC1_ICUSB_PWRDNZ);
-			omap_ctrl_writel(reg, control_pbias_offset);
+			reg &= ~(OMAP4_MMC1_PWRDNZ_MASK |
+				OMAP4_USBC1_ICUSB_PWRDNZ_MASK);
+			omap4_ctrl_pad_writel(reg, control_pbias_offset);
 		}
 	} else {
-		reg = omap_ctrl_readl(control_pbias_offset);
-		 reg |= (OMAP4_MMC1_PBIASLITE_PWRDNZ |
-			OMAP4_MMC1_PBIASLITE_VMODE | OMAP4_MMC1_PWRDNZ |
-			OMAP4_USBC1_ICUSB_PWRDNZ);
-		omap_ctrl_writel(reg, control_pbias_offset);
+		reg = omap4_ctrl_pad_readl(control_pbias_offset);
+		reg |= (OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK |
+			OMAP4_MMC1_PWRDNZ_MASK |
+			OMAP4_MMC1_PBIASLITE_VMODE_MASK |
+			OMAP4_USBC1_ICUSB_PWRDNZ_MASK);
+		omap4_ctrl_pad_writel(reg, control_pbias_offset);
 	}
 }
 
@@ -218,17 +222,18 @@
 			control_devconf1_offset = OMAP343X_CONTROL_DEVCONF1;
 		}
 	} else {
-		control_pbias_offset = OMAP44XX_CONTROL_PBIAS_LITE;
-		control_mmc1 = OMAP44XX_CONTROL_MMC1;
-		reg = omap_ctrl_readl(control_mmc1);
-		reg |= (OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP0 |
-			OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP1);
-		reg &= ~(OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP2 |
-			OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP3);
-		reg |= (OMAP4_CONTROL_SDMMC1_DR0_SPEEDCTRL |
-			OMAP4_CONTROL_SDMMC1_DR1_SPEEDCTRL |
-			OMAP4_CONTROL_SDMMC1_DR2_SPEEDCTRL);
-		omap_ctrl_writel(reg, control_mmc1);
+		control_pbias_offset =
+			OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PBIASLITE;
+		control_mmc1 = OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MMC1;
+		reg = omap4_ctrl_pad_readl(control_mmc1);
+		reg |= (OMAP4_SDMMC1_PUSTRENGTH_GRP0_MASK |
+			OMAP4_SDMMC1_PUSTRENGTH_GRP1_MASK);
+		reg &= ~(OMAP4_SDMMC1_PUSTRENGTH_GRP2_MASK |
+			OMAP4_SDMMC1_PUSTRENGTH_GRP3_MASK);
+		reg |= (OMAP4_USBC1_DR0_SPEEDCTRL_MASK|
+			OMAP4_SDMMC1_DR1_SPEEDCTRL_MASK |
+			OMAP4_SDMMC1_DR2_SPEEDCTRL_MASK);
+		omap4_ctrl_pad_writel(reg, control_mmc1);
 	}
 
 	for (c = controllers; c->mmc; c++) {
@@ -258,9 +263,13 @@
 				"mmc%islot%i", c->mmc, 1);
 		mmc->slots[0].name = hc->name;
 		mmc->nr_slots = 1;
-		mmc->slots[0].wires = c->wires;
+		mmc->slots[0].caps = c->caps;
 		mmc->slots[0].internal_clock = !c->ext_clock;
 		mmc->dma_mask = 0xffffffff;
+		if (cpu_is_omap44xx())
+			mmc->reg_offset = OMAP4_MMC_REG_OFFSET;
+		else
+			mmc->reg_offset = 0;
 
 		mmc->get_context_loss_count = hsmmc_get_context_loss;
 
@@ -298,6 +307,9 @@
 		else
 			mmc->slots[0].features |= HSMMC_HAS_PBIAS;
 
+		if (cpu_is_omap44xx() && (omap_rev() > OMAP4430_REV_ES1_0))
+			mmc->slots[0].features |= HSMMC_HAS_UPDATED_RESET;
+
 		switch (c->mmc) {
 		case 1:
 			if (mmc->slots[0].features & HSMMC_HAS_PBIAS) {
@@ -316,16 +328,20 @@
 			}
 
 			/* Omap3630 HSMMC1 supports only 4-bit */
-			if (cpu_is_omap3630() && c->wires > 4) {
-				c->wires = 4;
-				mmc->slots[0].wires = c->wires;
+			if (cpu_is_omap3630() &&
+					(c->caps & MMC_CAP_8_BIT_DATA)) {
+				c->caps &= ~MMC_CAP_8_BIT_DATA;
+				c->caps |= MMC_CAP_4_BIT_DATA;
+				mmc->slots[0].caps = c->caps;
 			}
 			break;
 		case 2:
 			if (c->ext_clock)
 				c->transceiver = 1;
-			if (c->transceiver && c->wires > 4)
-				c->wires = 4;
+			if (c->transceiver && (c->caps & MMC_CAP_8_BIT_DATA)) {
+				c->caps &= ~MMC_CAP_8_BIT_DATA;
+				c->caps |= MMC_CAP_4_BIT_DATA;
+			}
 			/* FALLTHROUGH */
 		case 3:
 			if (mmc->slots[0].features & HSMMC_HAS_PBIAS) {
diff --git a/arch/arm/mach-omap2/hsmmc.h b/arch/arm/mach-omap2/hsmmc.h
index 0f8a2e6..f119348 100644
--- a/arch/arm/mach-omap2/hsmmc.h
+++ b/arch/arm/mach-omap2/hsmmc.h
@@ -10,7 +10,8 @@
 
 struct omap2_hsmmc_info {
 	u8	mmc;		/* controller 1/2/3 */
-	u8	wires;		/* 1/4/8 wires */
+	u32	caps;		/* 4/8 wires and any additional host
+				 * capabilities OR'd (ref. linux/mmc/host.h) */
 	bool	transceiver;	/* MMC-2 option */
 	bool	ext_clock;	/* use external pin for input clock */
 	bool	cover_only;	/* No card detect - just cover switch */
diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
index 9a879f9..5f9086c 100644
--- a/arch/arm/mach-omap2/id.c
+++ b/arch/arm/mach-omap2/id.c
@@ -22,11 +22,12 @@
 #include <asm/cputype.h>
 
 #include <plat/common.h>
-#include <plat/control.h>
 #include <plat/cpu.h>
 
 #include <mach/id.h>
 
+#include "control.h"
+
 static struct omap_chip_id omap_chip;
 static unsigned int omap_revision;
 
@@ -60,7 +61,7 @@
 	} else if (cpu_is_omap34xx()) {
 		val = omap_ctrl_readl(OMAP343X_CONTROL_STATUS);
 	} else if (cpu_is_omap44xx()) {
-		val = omap_ctrl_readl(OMAP44XX_CONTROL_STATUS);
+		val = omap_ctrl_readl(OMAP4_CTRL_MODULE_CORE_STATUS);
 	} else {
 		pr_err("Cannot detect omap type!\n");
 		goto out;
@@ -298,7 +299,6 @@
 	u32 idcode;
 	u16 hawkeye;
 	u8 rev;
-	char *rev_name = "ES1.0";
 
 	/*
 	 * The IC rev detection is done with hawkeye and rev.
@@ -309,14 +309,39 @@
 	hawkeye = (idcode >> 12) & 0xffff;
 	rev = (idcode >> 28) & 0xff;
 
-	if ((hawkeye == 0xb852) && (rev == 0x0)) {
-		omap_revision = OMAP4430_REV_ES1_0;
-		omap_chip.oc |= CHIP_IS_OMAP4430ES1;
-		pr_info("OMAP%04x %s\n", omap_rev() >> 16, rev_name);
-		return;
+	/*
+	 * Few initial ES2.0 samples IDCODE is same as ES1.0
+	 * Use ARM register to detect the correct ES version
+	 */
+	if (!rev) {
+		idcode = read_cpuid(CPUID_ID);
+		rev = (idcode & 0xf) - 1;
 	}
 
-	pr_err("Unknown OMAP4 CPU id\n");
+	switch (hawkeye) {
+	case 0xb852:
+		switch (rev) {
+		case 0:
+			omap_revision = OMAP4430_REV_ES1_0;
+			omap_chip.oc |= CHIP_IS_OMAP4430ES1;
+			break;
+		case 1:
+			omap_revision = OMAP4430_REV_ES2_0;
+			omap_chip.oc |= CHIP_IS_OMAP4430ES2;
+			break;
+		default:
+			omap_revision = OMAP4430_REV_ES2_0;
+			omap_chip.oc |= CHIP_IS_OMAP4430ES2;
+	}
+	break;
+	default:
+		/* Unknown default to latest silicon rev as default*/
+		omap_revision = OMAP4430_REV_ES2_0;
+		omap_chip.oc |= CHIP_IS_OMAP4430ES2;
+	}
+
+	pr_info("OMAP%04x ES%d.0\n",
+			omap_rev() >> 16, ((omap_rev() >> 12) & 0xf) + 1);
 }
 
 #define OMAP3_SHOW_FEATURE(feat)		\
@@ -361,30 +386,54 @@
 		strcpy(cpu_name, "OMAP3503");
 	}
 
-	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:
-		strcpy(cpu_rev, "1.2");
-		break;
-	case OMAP_REVBITS_10:
-		strcpy(cpu_rev, "2.0");
-		break;
-	case OMAP_REVBITS_20:
-		strcpy(cpu_rev, "2.1");
-		break;
-	case OMAP_REVBITS_30:
-		strcpy(cpu_rev, "3.0");
-		break;
-	case OMAP_REVBITS_40:
-	/* FALLTHROUGH */
-	default:
-		/* Use the latest known revision as default */
-		strcpy(cpu_rev, "3.1");
+	if (cpu_is_omap3630()) {
+		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");
+		}
 	}
 
 	/* Print verbose information */
diff --git a/arch/arm/mach-omap2/include/mach/board-rx51.h b/arch/arm/mach-omap2/include/mach/board-rx51.h
new file mode 100644
index 0000000..b76f49e
--- /dev/null
+++ b/arch/arm/mach-omap2/include/mach/board-rx51.h
@@ -0,0 +1,11 @@
+/*
+ * Defines for rx51 boards
+ */
+
+#ifndef _OMAP_BOARD_RX51_H
+#define _OMAP_BOARD_RX51_H
+
+extern void __init rx51_peripherals_init(void);
+extern void __init rx51_video_mem_init(void);
+
+#endif
diff --git a/arch/arm/mach-omap2/include/mach/board-zoom.h b/arch/arm/mach-omap2/include/mach/board-zoom.h
index 80591fd..f93ca39 100644
--- a/arch/arm/mach-omap2/include/mach/board-zoom.h
+++ b/arch/arm/mach-omap2/include/mach/board-zoom.h
@@ -1,12 +1,8 @@
 /*
  * Defines for zoom boards
  */
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-
 #define ZOOM_NAND_CS    0
 
-extern void __init board_nand_init(struct mtd_partition *, u8 nr_parts, u8 cs);
 extern int __init zoom_debugboard_init(void);
 extern void __init zoom_peripherals_init(void);
 
diff --git a/arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h b/arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h
new file mode 100644
index 0000000..2f7ac70
--- /dev/null
+++ b/arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h
@@ -0,0 +1,391 @@
+/*
+ * OMAP44xx CTRL_MODULE_CORE registers and bitfields
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * Benoit Cousson (b-cousson@ti.com)
+ * Santosh Shilimkar (santosh.shilimkar@ti.com)
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_CORE_44XX_H
+#define __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_CORE_44XX_H
+
+
+/* Base address */
+#define OMAP4_CTRL_MODULE_CORE					0x4a002000
+
+/* Registers offset */
+#define OMAP4_CTRL_MODULE_CORE_IP_REVISION			0x0000
+#define OMAP4_CTRL_MODULE_CORE_IP_HWINFO			0x0004
+#define OMAP4_CTRL_MODULE_CORE_IP_SYSCONFIG			0x0010
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_DIE_ID_0		0x0200
+#define OMAP4_CTRL_MODULE_CORE_ID_CODE				0x0204
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_DIE_ID_1		0x0208
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_DIE_ID_2		0x020c
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_DIE_ID_3		0x0210
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_PROD_ID_0		0x0214
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_PROD_ID_1		0x0218
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_USB_CONF		0x021c
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_VDD_WKUP		0x0228
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_BGAP		0x0260
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_DPLL_0		0x0264
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_DPLL_1		0x0268
+#define OMAP4_CTRL_MODULE_CORE_STATUS				0x02c4
+#define OMAP4_CTRL_MODULE_CORE_DEV_CONF				0x0300
+#define OMAP4_CTRL_MODULE_CORE_LDOVBB_IVA_VOLTAGE_CTRL		0x0314
+#define OMAP4_CTRL_MODULE_CORE_LDOVBB_MPU_VOLTAGE_CTRL		0x0318
+#define OMAP4_CTRL_MODULE_CORE_LDOSRAM_IVA_VOLTAGE_CTRL		0x0320
+#define OMAP4_CTRL_MODULE_CORE_LDOSRAM_MPU_VOLTAGE_CTRL		0x0324
+#define OMAP4_CTRL_MODULE_CORE_LDOSRAM_CORE_VOLTAGE_CTRL	0x0328
+#define OMAP4_CTRL_MODULE_CORE_TEMP_SENSOR			0x032c
+#define OMAP4_CTRL_MODULE_CORE_DPLL_NWELL_TRIM_0		0x0330
+#define OMAP4_CTRL_MODULE_CORE_DPLL_NWELL_TRIM_1		0x0334
+#define OMAP4_CTRL_MODULE_CORE_USBOTGHS_CONTROL			0x033c
+#define OMAP4_CTRL_MODULE_CORE_DSS_CONTROL			0x0340
+#define OMAP4_CTRL_MODULE_CORE_HWOBS_CONTROL			0x0350
+#define OMAP4_CTRL_MODULE_CORE_DEBOBS_FINAL_MUX_SEL		0x0400
+#define OMAP4_CTRL_MODULE_CORE_DEBOBS_MMR_MPU			0x0408
+#define OMAP4_CTRL_MODULE_CORE_CONF_SDMA_REQ_SEL0		0x042c
+#define OMAP4_CTRL_MODULE_CORE_CONF_SDMA_REQ_SEL1		0x0430
+#define OMAP4_CTRL_MODULE_CORE_CONF_SDMA_REQ_SEL2		0x0434
+#define OMAP4_CTRL_MODULE_CORE_CONF_SDMA_REQ_SEL3		0x0438
+#define OMAP4_CTRL_MODULE_CORE_CONF_CLK_SEL0			0x0440
+#define OMAP4_CTRL_MODULE_CORE_CONF_CLK_SEL1			0x0444
+#define OMAP4_CTRL_MODULE_CORE_CONF_CLK_SEL2			0x0448
+#define OMAP4_CTRL_MODULE_CORE_CONF_DPLL_FREQLOCK_SEL		0x044c
+#define OMAP4_CTRL_MODULE_CORE_CONF_DPLL_TINITZ_SEL		0x0450
+#define OMAP4_CTRL_MODULE_CORE_CONF_DPLL_PHASELOCK_SEL		0x0454
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_0		0x0480
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_1		0x0484
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_2		0x0488
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_3		0x048c
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_4		0x0490
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_5		0x0494
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_6		0x0498
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_7		0x049c
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_8		0x04a0
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_9		0x04a4
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_10		0x04a8
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_11		0x04ac
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_12		0x04b0
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_13		0x04b4
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_14		0x04b8
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_15		0x04bc
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_16		0x04c0
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_17		0x04c4
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_18		0x04c8
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_19		0x04cc
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_20		0x04d0
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_21		0x04d4
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_22		0x04d8
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_23		0x04dc
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_24		0x04e0
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_25		0x04e4
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_26		0x04e8
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_27		0x04ec
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_28		0x04f0
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_29		0x04f4
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_30		0x04f8
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_31		0x04fc
+
+/* Registers shifts and masks */
+
+/* IP_REVISION */
+#define OMAP4_IP_REV_SCHEME_SHIFT			30
+#define OMAP4_IP_REV_SCHEME_MASK			(0x3 << 30)
+#define OMAP4_IP_REV_FUNC_SHIFT				16
+#define OMAP4_IP_REV_FUNC_MASK				(0xfff << 16)
+#define OMAP4_IP_REV_RTL_SHIFT				11
+#define OMAP4_IP_REV_RTL_MASK				(0x1f << 11)
+#define OMAP4_IP_REV_MAJOR_SHIFT			8
+#define OMAP4_IP_REV_MAJOR_MASK				(0x7 << 8)
+#define OMAP4_IP_REV_CUSTOM_SHIFT			6
+#define OMAP4_IP_REV_CUSTOM_MASK			(0x3 << 6)
+#define OMAP4_IP_REV_MINOR_SHIFT			0
+#define OMAP4_IP_REV_MINOR_MASK				(0x3f << 0)
+
+/* IP_HWINFO */
+#define OMAP4_IP_HWINFO_SHIFT				0
+#define OMAP4_IP_HWINFO_MASK				(0xffffffff << 0)
+
+/* IP_SYSCONFIG */
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_SHIFT		2
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_MASK		(0x3 << 2)
+
+/* STD_FUSE_DIE_ID_0 */
+#define OMAP4_STD_FUSE_DIE_ID_0_SHIFT			0
+#define OMAP4_STD_FUSE_DIE_ID_0_MASK			(0xffffffff << 0)
+
+/* ID_CODE */
+#define OMAP4_STD_FUSE_IDCODE_SHIFT			0
+#define OMAP4_STD_FUSE_IDCODE_MASK			(0xffffffff << 0)
+
+/* STD_FUSE_DIE_ID_1 */
+#define OMAP4_STD_FUSE_DIE_ID_1_SHIFT			0
+#define OMAP4_STD_FUSE_DIE_ID_1_MASK			(0xffffffff << 0)
+
+/* STD_FUSE_DIE_ID_2 */
+#define OMAP4_STD_FUSE_DIE_ID_2_SHIFT			0
+#define OMAP4_STD_FUSE_DIE_ID_2_MASK			(0xffffffff << 0)
+
+/* STD_FUSE_DIE_ID_3 */
+#define OMAP4_STD_FUSE_DIE_ID_3_SHIFT			0
+#define OMAP4_STD_FUSE_DIE_ID_3_MASK			(0xffffffff << 0)
+
+/* STD_FUSE_PROD_ID_0 */
+#define OMAP4_STD_FUSE_PROD_ID_0_SHIFT			0
+#define OMAP4_STD_FUSE_PROD_ID_0_MASK			(0xffffffff << 0)
+
+/* STD_FUSE_PROD_ID_1 */
+#define OMAP4_STD_FUSE_PROD_ID_1_SHIFT			0
+#define OMAP4_STD_FUSE_PROD_ID_1_MASK			(0xffffffff << 0)
+
+/* STD_FUSE_USB_CONF */
+#define OMAP4_USB_PROD_ID_SHIFT				16
+#define OMAP4_USB_PROD_ID_MASK				(0xffff << 16)
+#define OMAP4_USB_VENDOR_ID_SHIFT			0
+#define OMAP4_USB_VENDOR_ID_MASK			(0xffff << 0)
+
+/* STD_FUSE_OPP_VDD_WKUP */
+#define OMAP4_STD_FUSE_OPP_VDD_WKUP_SHIFT		0
+#define OMAP4_STD_FUSE_OPP_VDD_WKUP_MASK		(0xffffffff << 0)
+
+/* STD_FUSE_OPP_BGAP */
+#define OMAP4_STD_FUSE_OPP_BGAP_SHIFT			0
+#define OMAP4_STD_FUSE_OPP_BGAP_MASK			(0xffffffff << 0)
+
+/* STD_FUSE_OPP_DPLL_0 */
+#define OMAP4_STD_FUSE_OPP_DPLL_0_SHIFT			0
+#define OMAP4_STD_FUSE_OPP_DPLL_0_MASK			(0xffffffff << 0)
+
+/* STD_FUSE_OPP_DPLL_1 */
+#define OMAP4_STD_FUSE_OPP_DPLL_1_SHIFT			0
+#define OMAP4_STD_FUSE_OPP_DPLL_1_MASK			(0xffffffff << 0)
+
+/* STATUS */
+#define OMAP4_ATTILA_CONF_SHIFT				11
+#define OMAP4_ATTILA_CONF_MASK				(0x3 << 11)
+#define OMAP4_DEVICE_TYPE_SHIFT				8
+#define OMAP4_DEVICE_TYPE_MASK				(0x7 << 8)
+#define OMAP4_SYS_BOOT_SHIFT				0
+#define OMAP4_SYS_BOOT_MASK				(0xff << 0)
+
+/* DEV_CONF */
+#define OMAP4_DEV_CONF_SHIFT				1
+#define OMAP4_DEV_CONF_MASK				(0x7fffffff << 1)
+#define OMAP4_USBPHY_PD_SHIFT				0
+#define OMAP4_USBPHY_PD_MASK				(1 << 0)
+
+/* LDOVBB_IVA_VOLTAGE_CTRL */
+#define OMAP4_LDOVBBIVA_RBB_MUX_CTRL_SHIFT		26
+#define OMAP4_LDOVBBIVA_RBB_MUX_CTRL_MASK		(1 << 26)
+#define OMAP4_LDOVBBIVA_RBB_VSET_IN_SHIFT		21
+#define OMAP4_LDOVBBIVA_RBB_VSET_IN_MASK		(0x1f << 21)
+#define OMAP4_LDOVBBIVA_RBB_VSET_OUT_SHIFT		16
+#define OMAP4_LDOVBBIVA_RBB_VSET_OUT_MASK		(0x1f << 16)
+#define OMAP4_LDOVBBIVA_FBB_MUX_CTRL_SHIFT		10
+#define OMAP4_LDOVBBIVA_FBB_MUX_CTRL_MASK		(1 << 10)
+#define OMAP4_LDOVBBIVA_FBB_VSET_IN_SHIFT		5
+#define OMAP4_LDOVBBIVA_FBB_VSET_IN_MASK		(0x1f << 5)
+#define OMAP4_LDOVBBIVA_FBB_VSET_OUT_SHIFT		0
+#define OMAP4_LDOVBBIVA_FBB_VSET_OUT_MASK		(0x1f << 0)
+
+/* LDOVBB_MPU_VOLTAGE_CTRL */
+#define OMAP4_LDOVBBMPU_RBB_MUX_CTRL_SHIFT		26
+#define OMAP4_LDOVBBMPU_RBB_MUX_CTRL_MASK		(1 << 26)
+#define OMAP4_LDOVBBMPU_RBB_VSET_IN_SHIFT		21
+#define OMAP4_LDOVBBMPU_RBB_VSET_IN_MASK		(0x1f << 21)
+#define OMAP4_LDOVBBMPU_RBB_VSET_OUT_SHIFT		16
+#define OMAP4_LDOVBBMPU_RBB_VSET_OUT_MASK		(0x1f << 16)
+#define OMAP4_LDOVBBMPU_FBB_MUX_CTRL_SHIFT		10
+#define OMAP4_LDOVBBMPU_FBB_MUX_CTRL_MASK		(1 << 10)
+#define OMAP4_LDOVBBMPU_FBB_VSET_IN_SHIFT		5
+#define OMAP4_LDOVBBMPU_FBB_VSET_IN_MASK		(0x1f << 5)
+#define OMAP4_LDOVBBMPU_FBB_VSET_OUT_SHIFT		0
+#define OMAP4_LDOVBBMPU_FBB_VSET_OUT_MASK		(0x1f << 0)
+
+/* LDOSRAM_IVA_VOLTAGE_CTRL */
+#define OMAP4_LDOSRAMIVA_RETMODE_MUX_CTRL_SHIFT		26
+#define OMAP4_LDOSRAMIVA_RETMODE_MUX_CTRL_MASK		(1 << 26)
+#define OMAP4_LDOSRAMIVA_RETMODE_VSET_IN_SHIFT		21
+#define OMAP4_LDOSRAMIVA_RETMODE_VSET_IN_MASK		(0x1f << 21)
+#define OMAP4_LDOSRAMIVA_RETMODE_VSET_OUT_SHIFT		16
+#define OMAP4_LDOSRAMIVA_RETMODE_VSET_OUT_MASK		(0x1f << 16)
+#define OMAP4_LDOSRAMIVA_ACTMODE_MUX_CTRL_SHIFT		10
+#define OMAP4_LDOSRAMIVA_ACTMODE_MUX_CTRL_MASK		(1 << 10)
+#define OMAP4_LDOSRAMIVA_ACTMODE_VSET_IN_SHIFT		5
+#define OMAP4_LDOSRAMIVA_ACTMODE_VSET_IN_MASK		(0x1f << 5)
+#define OMAP4_LDOSRAMIVA_ACTMODE_VSET_OUT_SHIFT		0
+#define OMAP4_LDOSRAMIVA_ACTMODE_VSET_OUT_MASK		(0x1f << 0)
+
+/* LDOSRAM_MPU_VOLTAGE_CTRL */
+#define OMAP4_LDOSRAMMPU_RETMODE_MUX_CTRL_SHIFT		26
+#define OMAP4_LDOSRAMMPU_RETMODE_MUX_CTRL_MASK		(1 << 26)
+#define OMAP4_LDOSRAMMPU_RETMODE_VSET_IN_SHIFT		21
+#define OMAP4_LDOSRAMMPU_RETMODE_VSET_IN_MASK		(0x1f << 21)
+#define OMAP4_LDOSRAMMPU_RETMODE_VSET_OUT_SHIFT		16
+#define OMAP4_LDOSRAMMPU_RETMODE_VSET_OUT_MASK		(0x1f << 16)
+#define OMAP4_LDOSRAMMPU_ACTMODE_MUX_CTRL_SHIFT		10
+#define OMAP4_LDOSRAMMPU_ACTMODE_MUX_CTRL_MASK		(1 << 10)
+#define OMAP4_LDOSRAMMPU_ACTMODE_VSET_IN_SHIFT		5
+#define OMAP4_LDOSRAMMPU_ACTMODE_VSET_IN_MASK		(0x1f << 5)
+#define OMAP4_LDOSRAMMPU_ACTMODE_VSET_OUT_SHIFT		0
+#define OMAP4_LDOSRAMMPU_ACTMODE_VSET_OUT_MASK		(0x1f << 0)
+
+/* LDOSRAM_CORE_VOLTAGE_CTRL */
+#define OMAP4_LDOSRAMCORE_RETMODE_MUX_CTRL_SHIFT	26
+#define OMAP4_LDOSRAMCORE_RETMODE_MUX_CTRL_MASK		(1 << 26)
+#define OMAP4_LDOSRAMCORE_RETMODE_VSET_IN_SHIFT		21
+#define OMAP4_LDOSRAMCORE_RETMODE_VSET_IN_MASK		(0x1f << 21)
+#define OMAP4_LDOSRAMCORE_RETMODE_VSET_OUT_SHIFT	16
+#define OMAP4_LDOSRAMCORE_RETMODE_VSET_OUT_MASK		(0x1f << 16)
+#define OMAP4_LDOSRAMCORE_ACTMODE_MUX_CTRL_SHIFT	10
+#define OMAP4_LDOSRAMCORE_ACTMODE_MUX_CTRL_MASK		(1 << 10)
+#define OMAP4_LDOSRAMCORE_ACTMODE_VSET_IN_SHIFT		5
+#define OMAP4_LDOSRAMCORE_ACTMODE_VSET_IN_MASK		(0x1f << 5)
+#define OMAP4_LDOSRAMCORE_ACTMODE_VSET_OUT_SHIFT	0
+#define OMAP4_LDOSRAMCORE_ACTMODE_VSET_OUT_MASK		(0x1f << 0)
+
+/* TEMP_SENSOR */
+#define OMAP4_BGAP_TEMPSOFF_SHIFT			12
+#define OMAP4_BGAP_TEMPSOFF_MASK			(1 << 12)
+#define OMAP4_BGAP_TSHUT_SHIFT				11
+#define OMAP4_BGAP_TSHUT_MASK				(1 << 11)
+#define OMAP4_BGAP_TEMP_SENSOR_CONTCONV_SHIFT		10
+#define OMAP4_BGAP_TEMP_SENSOR_CONTCONV_MASK		(1 << 10)
+#define OMAP4_BGAP_TEMP_SENSOR_SOC_SHIFT		9
+#define OMAP4_BGAP_TEMP_SENSOR_SOC_MASK			(1 << 9)
+#define OMAP4_BGAP_TEMP_SENSOR_EOCZ_SHIFT		8
+#define OMAP4_BGAP_TEMP_SENSOR_EOCZ_MASK		(1 << 8)
+#define OMAP4_BGAP_TEMP_SENSOR_DTEMP_SHIFT		0
+#define OMAP4_BGAP_TEMP_SENSOR_DTEMP_MASK		(0xff << 0)
+
+/* DPLL_NWELL_TRIM_0 */
+#define OMAP4_DPLL_ABE_NWELL_TRIM_MUX_CTRL_SHIFT	29
+#define OMAP4_DPLL_ABE_NWELL_TRIM_MUX_CTRL_MASK		(1 << 29)
+#define OMAP4_DPLL_ABE_NWELL_TRIM_SHIFT			24
+#define OMAP4_DPLL_ABE_NWELL_TRIM_MASK			(0x1f << 24)
+#define OMAP4_DPLL_PER_NWELL_TRIM_MUX_CTRL_SHIFT	23
+#define OMAP4_DPLL_PER_NWELL_TRIM_MUX_CTRL_MASK		(1 << 23)
+#define OMAP4_DPLL_PER_NWELL_TRIM_SHIFT			18
+#define OMAP4_DPLL_PER_NWELL_TRIM_MASK			(0x1f << 18)
+#define OMAP4_DPLL_CORE_NWELL_TRIM_MUX_CTRL_SHIFT	17
+#define OMAP4_DPLL_CORE_NWELL_TRIM_MUX_CTRL_MASK	(1 << 17)
+#define OMAP4_DPLL_CORE_NWELL_TRIM_SHIFT		12
+#define OMAP4_DPLL_CORE_NWELL_TRIM_MASK			(0x1f << 12)
+#define OMAP4_DPLL_IVA_NWELL_TRIM_MUX_CTRL_SHIFT	11
+#define OMAP4_DPLL_IVA_NWELL_TRIM_MUX_CTRL_MASK		(1 << 11)
+#define OMAP4_DPLL_IVA_NWELL_TRIM_SHIFT			6
+#define OMAP4_DPLL_IVA_NWELL_TRIM_MASK			(0x1f << 6)
+#define OMAP4_DPLL_MPU_NWELL_TRIM_MUX_CTRL_SHIFT	5
+#define OMAP4_DPLL_MPU_NWELL_TRIM_MUX_CTRL_MASK		(1 << 5)
+#define OMAP4_DPLL_MPU_NWELL_TRIM_SHIFT			0
+#define OMAP4_DPLL_MPU_NWELL_TRIM_MASK			(0x1f << 0)
+
+/* DPLL_NWELL_TRIM_1 */
+#define OMAP4_DPLL_UNIPRO_NWELL_TRIM_MUX_CTRL_SHIFT	29
+#define OMAP4_DPLL_UNIPRO_NWELL_TRIM_MUX_CTRL_MASK	(1 << 29)
+#define OMAP4_DPLL_UNIPRO_NWELL_TRIM_SHIFT		24
+#define OMAP4_DPLL_UNIPRO_NWELL_TRIM_MASK		(0x1f << 24)
+#define OMAP4_DPLL_USB_NWELL_TRIM_MUX_CTRL_SHIFT	23
+#define OMAP4_DPLL_USB_NWELL_TRIM_MUX_CTRL_MASK		(1 << 23)
+#define OMAP4_DPLL_USB_NWELL_TRIM_SHIFT			18
+#define OMAP4_DPLL_USB_NWELL_TRIM_MASK			(0x1f << 18)
+#define OMAP4_DPLL_HDMI_NWELL_TRIM_MUX_CTRL_SHIFT	17
+#define OMAP4_DPLL_HDMI_NWELL_TRIM_MUX_CTRL_MASK	(1 << 17)
+#define OMAP4_DPLL_HDMI_NWELL_TRIM_SHIFT		12
+#define OMAP4_DPLL_HDMI_NWELL_TRIM_MASK			(0x1f << 12)
+#define OMAP4_DPLL_DSI2_NWELL_TRIM_MUX_CTRL_SHIFT	11
+#define OMAP4_DPLL_DSI2_NWELL_TRIM_MUX_CTRL_MASK	(1 << 11)
+#define OMAP4_DPLL_DSI2_NWELL_TRIM_SHIFT		6
+#define OMAP4_DPLL_DSI2_NWELL_TRIM_MASK			(0x1f << 6)
+#define OMAP4_DPLL_DSI1_NWELL_TRIM_MUX_CTRL_SHIFT	5
+#define OMAP4_DPLL_DSI1_NWELL_TRIM_MUX_CTRL_MASK	(1 << 5)
+#define OMAP4_DPLL_DSI1_NWELL_TRIM_SHIFT		0
+#define OMAP4_DPLL_DSI1_NWELL_TRIM_MASK			(0x1f << 0)
+
+/* USBOTGHS_CONTROL */
+#define OMAP4_DISCHRGVBUS_SHIFT				8
+#define OMAP4_DISCHRGVBUS_MASK				(1 << 8)
+#define OMAP4_CHRGVBUS_SHIFT				7
+#define OMAP4_CHRGVBUS_MASK				(1 << 7)
+#define OMAP4_DRVVBUS_SHIFT				6
+#define OMAP4_DRVVBUS_MASK				(1 << 6)
+#define OMAP4_IDPULLUP_SHIFT				5
+#define OMAP4_IDPULLUP_MASK				(1 << 5)
+#define OMAP4_IDDIG_SHIFT				4
+#define OMAP4_IDDIG_MASK				(1 << 4)
+#define OMAP4_SESSEND_SHIFT				3
+#define OMAP4_SESSEND_MASK				(1 << 3)
+#define OMAP4_VBUSVALID_SHIFT				2
+#define OMAP4_VBUSVALID_MASK				(1 << 2)
+#define OMAP4_BVALID_SHIFT				1
+#define OMAP4_BVALID_MASK				(1 << 1)
+#define OMAP4_AVALID_SHIFT				0
+#define OMAP4_AVALID_MASK				(1 << 0)
+
+/* DSS_CONTROL */
+#define OMAP4_DSS_MUX6_SELECT_SHIFT			0
+#define OMAP4_DSS_MUX6_SELECT_MASK			(1 << 0)
+
+/* HWOBS_CONTROL */
+#define OMAP4_HWOBS_CLKDIV_SEL_SHIFT			3
+#define OMAP4_HWOBS_CLKDIV_SEL_MASK			(0x1f << 3)
+#define OMAP4_HWOBS_ALL_ZERO_MODE_SHIFT			2
+#define OMAP4_HWOBS_ALL_ZERO_MODE_MASK			(1 << 2)
+#define OMAP4_HWOBS_ALL_ONE_MODE_SHIFT			1
+#define OMAP4_HWOBS_ALL_ONE_MODE_MASK			(1 << 1)
+#define OMAP4_HWOBS_MACRO_ENABLE_SHIFT			0
+#define OMAP4_HWOBS_MACRO_ENABLE_MASK			(1 << 0)
+
+/* DEBOBS_FINAL_MUX_SEL */
+#define OMAP4_SELECT_SHIFT				0
+#define OMAP4_SELECT_MASK				(0xffffffff << 0)
+
+/* DEBOBS_MMR_MPU */
+#define OMAP4_SELECT_DEBOBS_MMR_MPU_SHIFT		0
+#define OMAP4_SELECT_DEBOBS_MMR_MPU_MASK		(0xf << 0)
+
+/* CONF_SDMA_REQ_SEL0 */
+#define OMAP4_MULT_SHIFT				0
+#define OMAP4_MULT_MASK					(0x7f << 0)
+
+/* CONF_CLK_SEL0 */
+#define OMAP4_MULT_CONF_CLK_SEL0_SHIFT			0
+#define OMAP4_MULT_CONF_CLK_SEL0_MASK			(0x7 << 0)
+
+/* CONF_CLK_SEL1 */
+#define OMAP4_MULT_CONF_CLK_SEL1_SHIFT			0
+#define OMAP4_MULT_CONF_CLK_SEL1_MASK			(0x7 << 0)
+
+/* CONF_CLK_SEL2 */
+#define OMAP4_MULT_CONF_CLK_SEL2_SHIFT			0
+#define OMAP4_MULT_CONF_CLK_SEL2_MASK			(0x7 << 0)
+
+/* CONF_DPLL_FREQLOCK_SEL */
+#define OMAP4_MULT_CONF_DPLL_FREQLOCK_SEL_SHIFT		0
+#define OMAP4_MULT_CONF_DPLL_FREQLOCK_SEL_MASK		(0x7 << 0)
+
+/* CONF_DPLL_TINITZ_SEL */
+#define OMAP4_MULT_CONF_DPLL_TINITZ_SEL_SHIFT		0
+#define OMAP4_MULT_CONF_DPLL_TINITZ_SEL_MASK		(0x7 << 0)
+
+/* CONF_DPLL_PHASELOCK_SEL */
+#define OMAP4_MULT_CONF_DPLL_PHASELOCK_SEL_SHIFT	0
+#define OMAP4_MULT_CONF_DPLL_PHASELOCK_SEL_MASK		(0x7 << 0)
+
+/* CONF_DEBUG_SEL_TST_0 */
+#define OMAP4_MODE_SHIFT				0
+#define OMAP4_MODE_MASK					(0xf << 0)
+
+#endif
diff --git a/arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h b/arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h
new file mode 100644
index 0000000..c88420d
--- /dev/null
+++ b/arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h
@@ -0,0 +1,1409 @@
+/*
+ * OMAP44xx CTRL_MODULE_PAD_CORE registers and bitfields
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * Benoit Cousson (b-cousson@ti.com)
+ * Santosh Shilimkar (santosh.shilimkar@ti.com)
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_PAD_CORE_44XX_H
+#define __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_PAD_CORE_44XX_H
+
+
+/* Base address */
+#define OMAP4_CTRL_MODULE_PAD_CORE				0x4a100000
+
+/* Registers offset */
+#define OMAP4_CTRL_MODULE_PAD_CORE_IP_REVISION			0x0000
+#define OMAP4_CTRL_MODULE_PAD_CORE_IP_HWINFO			0x0004
+#define OMAP4_CTRL_MODULE_PAD_CORE_IP_SYSCONFIG			0x0010
+#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_0	0x01d8
+#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_1	0x01dc
+#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_2	0x01e0
+#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_3	0x01e4
+#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_4	0x01e8
+#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_5	0x01ec
+#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_6	0x01f0
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PADCONF_GLOBAL	0x05a0
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PADCONF_MODE		0x05a4
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART1IO_PADCONF_0	0x05a8
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART1IO_PADCONF_1	0x05ac
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART2IO_PADCONF_0	0x05b0
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART2IO_PADCONF_1	0x05b4
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART3IO_PADCONF_0	0x05b8
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART3IO_PADCONF_1	0x05bc
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART3IO_PADCONF_2	0x05c0
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_USBB_HSIC		0x05c4
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SLIMBUS		0x05c8
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PBIASLITE		0x0600
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_I2C_0		0x0604
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_CAMERA_RX		0x0608
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_AVDAC		0x060c
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_HDMI_TX_PHY		0x0610
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MMC2			0x0614
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY		0x0618
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MCBSPLP		0x061c
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_USB2PHYCORE		0x0620
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_I2C_1		0x0624
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MMC1			0x0628
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_HSI			0x062c
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_USB			0x0630
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_HDQ			0x0634
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_0		0x0638
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_1		0x063c
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_2		0x0640
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_3		0x0644
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_0		0x0648
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_1		0x064c
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_2		0x0650
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_3		0x0654
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_BUS_HOLD		0x0658
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_C2C			0x065c
+#define OMAP4_CTRL_MODULE_PAD_CORE_CORE_CONTROL_SPARE_RW	0x0660
+#define OMAP4_CTRL_MODULE_PAD_CORE_CORE_CONTROL_SPARE_R		0x0664
+#define OMAP4_CTRL_MODULE_PAD_CORE_CORE_CONTROL_SPARE_R_C0	0x0668
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_1		0x0700
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_2		0x0704
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_3		0x0708
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_4		0x070c
+
+/* Registers shifts and masks */
+
+/* IP_REVISION */
+#define OMAP4_IP_REV_SCHEME_SHIFT				30
+#define OMAP4_IP_REV_SCHEME_MASK				(0x3 << 30)
+#define OMAP4_IP_REV_FUNC_SHIFT					16
+#define OMAP4_IP_REV_FUNC_MASK					(0xfff << 16)
+#define OMAP4_IP_REV_RTL_SHIFT					11
+#define OMAP4_IP_REV_RTL_MASK					(0x1f << 11)
+#define OMAP4_IP_REV_MAJOR_SHIFT				8
+#define OMAP4_IP_REV_MAJOR_MASK					(0x7 << 8)
+#define OMAP4_IP_REV_CUSTOM_SHIFT				6
+#define OMAP4_IP_REV_CUSTOM_MASK				(0x3 << 6)
+#define OMAP4_IP_REV_MINOR_SHIFT				0
+#define OMAP4_IP_REV_MINOR_MASK					(0x3f << 0)
+
+/* IP_HWINFO */
+#define OMAP4_IP_HWINFO_SHIFT					0
+#define OMAP4_IP_HWINFO_MASK					(0xffffffff << 0)
+
+/* IP_SYSCONFIG */
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_SHIFT			2
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_MASK			(0x3 << 2)
+
+/* PADCONF_WAKEUPEVENT_0 */
+#define OMAP4_GPMC_CLK_DUPLICATEWAKEUPEVENT_SHIFT		31
+#define OMAP4_GPMC_CLK_DUPLICATEWAKEUPEVENT_MASK		(1 << 31)
+#define OMAP4_GPMC_NWP_DUPLICATEWAKEUPEVENT_SHIFT		30
+#define OMAP4_GPMC_NWP_DUPLICATEWAKEUPEVENT_MASK		(1 << 30)
+#define OMAP4_GPMC_NCS3_DUPLICATEWAKEUPEVENT_SHIFT		29
+#define OMAP4_GPMC_NCS3_DUPLICATEWAKEUPEVENT_MASK		(1 << 29)
+#define OMAP4_GPMC_NCS2_DUPLICATEWAKEUPEVENT_SHIFT		28
+#define OMAP4_GPMC_NCS2_DUPLICATEWAKEUPEVENT_MASK		(1 << 28)
+#define OMAP4_GPMC_NCS1_DUPLICATEWAKEUPEVENT_SHIFT		27
+#define OMAP4_GPMC_NCS1_DUPLICATEWAKEUPEVENT_MASK		(1 << 27)
+#define OMAP4_GPMC_NCS0_DUPLICATEWAKEUPEVENT_SHIFT		26
+#define OMAP4_GPMC_NCS0_DUPLICATEWAKEUPEVENT_MASK		(1 << 26)
+#define OMAP4_GPMC_A25_DUPLICATEWAKEUPEVENT_SHIFT		25
+#define OMAP4_GPMC_A25_DUPLICATEWAKEUPEVENT_MASK		(1 << 25)
+#define OMAP4_GPMC_A24_DUPLICATEWAKEUPEVENT_SHIFT		24
+#define OMAP4_GPMC_A24_DUPLICATEWAKEUPEVENT_MASK		(1 << 24)
+#define OMAP4_GPMC_A23_DUPLICATEWAKEUPEVENT_SHIFT		23
+#define OMAP4_GPMC_A23_DUPLICATEWAKEUPEVENT_MASK		(1 << 23)
+#define OMAP4_GPMC_A22_DUPLICATEWAKEUPEVENT_SHIFT		22
+#define OMAP4_GPMC_A22_DUPLICATEWAKEUPEVENT_MASK		(1 << 22)
+#define OMAP4_GPMC_A21_DUPLICATEWAKEUPEVENT_SHIFT		21
+#define OMAP4_GPMC_A21_DUPLICATEWAKEUPEVENT_MASK		(1 << 21)
+#define OMAP4_GPMC_A20_DUPLICATEWAKEUPEVENT_SHIFT		20
+#define OMAP4_GPMC_A20_DUPLICATEWAKEUPEVENT_MASK		(1 << 20)
+#define OMAP4_GPMC_A19_DUPLICATEWAKEUPEVENT_SHIFT		19
+#define OMAP4_GPMC_A19_DUPLICATEWAKEUPEVENT_MASK		(1 << 19)
+#define OMAP4_GPMC_A18_DUPLICATEWAKEUPEVENT_SHIFT		18
+#define OMAP4_GPMC_A18_DUPLICATEWAKEUPEVENT_MASK		(1 << 18)
+#define OMAP4_GPMC_A17_DUPLICATEWAKEUPEVENT_SHIFT		17
+#define OMAP4_GPMC_A17_DUPLICATEWAKEUPEVENT_MASK		(1 << 17)
+#define OMAP4_GPMC_A16_DUPLICATEWAKEUPEVENT_SHIFT		16
+#define OMAP4_GPMC_A16_DUPLICATEWAKEUPEVENT_MASK		(1 << 16)
+#define OMAP4_GPMC_AD15_DUPLICATEWAKEUPEVENT_SHIFT		15
+#define OMAP4_GPMC_AD15_DUPLICATEWAKEUPEVENT_MASK		(1 << 15)
+#define OMAP4_GPMC_AD14_DUPLICATEWAKEUPEVENT_SHIFT		14
+#define OMAP4_GPMC_AD14_DUPLICATEWAKEUPEVENT_MASK		(1 << 14)
+#define OMAP4_GPMC_AD13_DUPLICATEWAKEUPEVENT_SHIFT		13
+#define OMAP4_GPMC_AD13_DUPLICATEWAKEUPEVENT_MASK		(1 << 13)
+#define OMAP4_GPMC_AD12_DUPLICATEWAKEUPEVENT_SHIFT		12
+#define OMAP4_GPMC_AD12_DUPLICATEWAKEUPEVENT_MASK		(1 << 12)
+#define OMAP4_GPMC_AD11_DUPLICATEWAKEUPEVENT_SHIFT		11
+#define OMAP4_GPMC_AD11_DUPLICATEWAKEUPEVENT_MASK		(1 << 11)
+#define OMAP4_GPMC_AD10_DUPLICATEWAKEUPEVENT_SHIFT		10
+#define OMAP4_GPMC_AD10_DUPLICATEWAKEUPEVENT_MASK		(1 << 10)
+#define OMAP4_GPMC_AD9_DUPLICATEWAKEUPEVENT_SHIFT		9
+#define OMAP4_GPMC_AD9_DUPLICATEWAKEUPEVENT_MASK		(1 << 9)
+#define OMAP4_GPMC_AD8_DUPLICATEWAKEUPEVENT_SHIFT		8
+#define OMAP4_GPMC_AD8_DUPLICATEWAKEUPEVENT_MASK		(1 << 8)
+#define OMAP4_GPMC_AD7_DUPLICATEWAKEUPEVENT_SHIFT		7
+#define OMAP4_GPMC_AD7_DUPLICATEWAKEUPEVENT_MASK		(1 << 7)
+#define OMAP4_GPMC_AD6_DUPLICATEWAKEUPEVENT_SHIFT		6
+#define OMAP4_GPMC_AD6_DUPLICATEWAKEUPEVENT_MASK		(1 << 6)
+#define OMAP4_GPMC_AD5_DUPLICATEWAKEUPEVENT_SHIFT		5
+#define OMAP4_GPMC_AD5_DUPLICATEWAKEUPEVENT_MASK		(1 << 5)
+#define OMAP4_GPMC_AD4_DUPLICATEWAKEUPEVENT_SHIFT		4
+#define OMAP4_GPMC_AD4_DUPLICATEWAKEUPEVENT_MASK		(1 << 4)
+#define OMAP4_GPMC_AD3_DUPLICATEWAKEUPEVENT_SHIFT		3
+#define OMAP4_GPMC_AD3_DUPLICATEWAKEUPEVENT_MASK		(1 << 3)
+#define OMAP4_GPMC_AD2_DUPLICATEWAKEUPEVENT_SHIFT		2
+#define OMAP4_GPMC_AD2_DUPLICATEWAKEUPEVENT_MASK		(1 << 2)
+#define OMAP4_GPMC_AD1_DUPLICATEWAKEUPEVENT_SHIFT		1
+#define OMAP4_GPMC_AD1_DUPLICATEWAKEUPEVENT_MASK		(1 << 1)
+#define OMAP4_GPMC_AD0_DUPLICATEWAKEUPEVENT_SHIFT		0
+#define OMAP4_GPMC_AD0_DUPLICATEWAKEUPEVENT_MASK		(1 << 0)
+
+/* PADCONF_WAKEUPEVENT_1 */
+#define OMAP4_CAM_STROBE_DUPLICATEWAKEUPEVENT_SHIFT		31
+#define OMAP4_CAM_STROBE_DUPLICATEWAKEUPEVENT_MASK		(1 << 31)
+#define OMAP4_CAM_SHUTTER_DUPLICATEWAKEUPEVENT_SHIFT		30
+#define OMAP4_CAM_SHUTTER_DUPLICATEWAKEUPEVENT_MASK		(1 << 30)
+#define OMAP4_CSI22_DY1_DUPLICATEWAKEUPEVENT_SHIFT		29
+#define OMAP4_CSI22_DY1_DUPLICATEWAKEUPEVENT_MASK		(1 << 29)
+#define OMAP4_CSI22_DX1_DUPLICATEWAKEUPEVENT_SHIFT		28
+#define OMAP4_CSI22_DX1_DUPLICATEWAKEUPEVENT_MASK		(1 << 28)
+#define OMAP4_CSI22_DY0_DUPLICATEWAKEUPEVENT_SHIFT		27
+#define OMAP4_CSI22_DY0_DUPLICATEWAKEUPEVENT_MASK		(1 << 27)
+#define OMAP4_CSI22_DX0_DUPLICATEWAKEUPEVENT_SHIFT		26
+#define OMAP4_CSI22_DX0_DUPLICATEWAKEUPEVENT_MASK		(1 << 26)
+#define OMAP4_CSI21_DY4_DUPLICATEWAKEUPEVENT_SHIFT		25
+#define OMAP4_CSI21_DY4_DUPLICATEWAKEUPEVENT_MASK		(1 << 25)
+#define OMAP4_CSI21_DX4_DUPLICATEWAKEUPEVENT_SHIFT		24
+#define OMAP4_CSI21_DX4_DUPLICATEWAKEUPEVENT_MASK		(1 << 24)
+#define OMAP4_CSI21_DY3_DUPLICATEWAKEUPEVENT_SHIFT		23
+#define OMAP4_CSI21_DY3_DUPLICATEWAKEUPEVENT_MASK		(1 << 23)
+#define OMAP4_CSI21_DX3_DUPLICATEWAKEUPEVENT_SHIFT		22
+#define OMAP4_CSI21_DX3_DUPLICATEWAKEUPEVENT_MASK		(1 << 22)
+#define OMAP4_CSI21_DY2_DUPLICATEWAKEUPEVENT_SHIFT		21
+#define OMAP4_CSI21_DY2_DUPLICATEWAKEUPEVENT_MASK		(1 << 21)
+#define OMAP4_CSI21_DX2_DUPLICATEWAKEUPEVENT_SHIFT		20
+#define OMAP4_CSI21_DX2_DUPLICATEWAKEUPEVENT_MASK		(1 << 20)
+#define OMAP4_CSI21_DY1_DUPLICATEWAKEUPEVENT_SHIFT		19
+#define OMAP4_CSI21_DY1_DUPLICATEWAKEUPEVENT_MASK		(1 << 19)
+#define OMAP4_CSI21_DX1_DUPLICATEWAKEUPEVENT_SHIFT		18
+#define OMAP4_CSI21_DX1_DUPLICATEWAKEUPEVENT_MASK		(1 << 18)
+#define OMAP4_CSI21_DY0_DUPLICATEWAKEUPEVENT_SHIFT		17
+#define OMAP4_CSI21_DY0_DUPLICATEWAKEUPEVENT_MASK		(1 << 17)
+#define OMAP4_CSI21_DX0_DUPLICATEWAKEUPEVENT_SHIFT		16
+#define OMAP4_CSI21_DX0_DUPLICATEWAKEUPEVENT_MASK		(1 << 16)
+#define OMAP4_HDMI_DDC_SDA_DUPLICATEWAKEUPEVENT_SHIFT		15
+#define OMAP4_HDMI_DDC_SDA_DUPLICATEWAKEUPEVENT_MASK		(1 << 15)
+#define OMAP4_HDMI_DDC_SCL_DUPLICATEWAKEUPEVENT_SHIFT		14
+#define OMAP4_HDMI_DDC_SCL_DUPLICATEWAKEUPEVENT_MASK		(1 << 14)
+#define OMAP4_HDMI_CEC_DUPLICATEWAKEUPEVENT_SHIFT		13
+#define OMAP4_HDMI_CEC_DUPLICATEWAKEUPEVENT_MASK		(1 << 13)
+#define OMAP4_HDMI_HPD_DUPLICATEWAKEUPEVENT_SHIFT		12
+#define OMAP4_HDMI_HPD_DUPLICATEWAKEUPEVENT_MASK		(1 << 12)
+#define OMAP4_C2C_DATA15_DUPLICATEWAKEUPEVENT_SHIFT		11
+#define OMAP4_C2C_DATA15_DUPLICATEWAKEUPEVENT_MASK		(1 << 11)
+#define OMAP4_C2C_DATA14_DUPLICATEWAKEUPEVENT_SHIFT		10
+#define OMAP4_C2C_DATA14_DUPLICATEWAKEUPEVENT_MASK		(1 << 10)
+#define OMAP4_C2C_DATA13_DUPLICATEWAKEUPEVENT_SHIFT		9
+#define OMAP4_C2C_DATA13_DUPLICATEWAKEUPEVENT_MASK		(1 << 9)
+#define OMAP4_C2C_DATA12_DUPLICATEWAKEUPEVENT_SHIFT		8
+#define OMAP4_C2C_DATA12_DUPLICATEWAKEUPEVENT_MASK		(1 << 8)
+#define OMAP4_C2C_DATA11_DUPLICATEWAKEUPEVENT_SHIFT		7
+#define OMAP4_C2C_DATA11_DUPLICATEWAKEUPEVENT_MASK		(1 << 7)
+#define OMAP4_GPMC_WAIT1_DUPLICATEWAKEUPEVENT_SHIFT		6
+#define OMAP4_GPMC_WAIT1_DUPLICATEWAKEUPEVENT_MASK		(1 << 6)
+#define OMAP4_GPMC_WAIT0_DUPLICATEWAKEUPEVENT_SHIFT		5
+#define OMAP4_GPMC_WAIT0_DUPLICATEWAKEUPEVENT_MASK		(1 << 5)
+#define OMAP4_GPMC_NBE1_DUPLICATEWAKEUPEVENT_SHIFT		4
+#define OMAP4_GPMC_NBE1_DUPLICATEWAKEUPEVENT_MASK		(1 << 4)
+#define OMAP4_GPMC_NBE0_CLE_DUPLICATEWAKEUPEVENT_SHIFT		3
+#define OMAP4_GPMC_NBE0_CLE_DUPLICATEWAKEUPEVENT_MASK		(1 << 3)
+#define OMAP4_GPMC_NWE_DUPLICATEWAKEUPEVENT_SHIFT		2
+#define OMAP4_GPMC_NWE_DUPLICATEWAKEUPEVENT_MASK		(1 << 2)
+#define OMAP4_GPMC_NOE_DUPLICATEWAKEUPEVENT_SHIFT		1
+#define OMAP4_GPMC_NOE_DUPLICATEWAKEUPEVENT_MASK		(1 << 1)
+#define OMAP4_GPMC_NADV_ALE_DUPLICATEWAKEUPEVENT_SHIFT		0
+#define OMAP4_GPMC_NADV_ALE_DUPLICATEWAKEUPEVENT_MASK		(1 << 0)
+
+/* PADCONF_WAKEUPEVENT_2 */
+#define OMAP4_ABE_MCBSP1_CLKX_DUPLICATEWAKEUPEVENT_SHIFT	31
+#define OMAP4_ABE_MCBSP1_CLKX_DUPLICATEWAKEUPEVENT_MASK		(1 << 31)
+#define OMAP4_ABE_MCBSP2_FSX_DUPLICATEWAKEUPEVENT_SHIFT		30
+#define OMAP4_ABE_MCBSP2_FSX_DUPLICATEWAKEUPEVENT_MASK		(1 << 30)
+#define OMAP4_ABE_MCBSP2_DX_DUPLICATEWAKEUPEVENT_SHIFT		29
+#define OMAP4_ABE_MCBSP2_DX_DUPLICATEWAKEUPEVENT_MASK		(1 << 29)
+#define OMAP4_ABE_MCBSP2_DR_DUPLICATEWAKEUPEVENT_SHIFT		28
+#define OMAP4_ABE_MCBSP2_DR_DUPLICATEWAKEUPEVENT_MASK		(1 << 28)
+#define OMAP4_ABE_MCBSP2_CLKX_DUPLICATEWAKEUPEVENT_SHIFT	27
+#define OMAP4_ABE_MCBSP2_CLKX_DUPLICATEWAKEUPEVENT_MASK		(1 << 27)
+#define OMAP4_SDMMC1_DAT7_DUPLICATEWAKEUPEVENT_SHIFT		26
+#define OMAP4_SDMMC1_DAT7_DUPLICATEWAKEUPEVENT_MASK		(1 << 26)
+#define OMAP4_SDMMC1_DAT6_DUPLICATEWAKEUPEVENT_SHIFT		25
+#define OMAP4_SDMMC1_DAT6_DUPLICATEWAKEUPEVENT_MASK		(1 << 25)
+#define OMAP4_SDMMC1_DAT5_DUPLICATEWAKEUPEVENT_SHIFT		24
+#define OMAP4_SDMMC1_DAT5_DUPLICATEWAKEUPEVENT_MASK		(1 << 24)
+#define OMAP4_SDMMC1_DAT4_DUPLICATEWAKEUPEVENT_SHIFT		23
+#define OMAP4_SDMMC1_DAT4_DUPLICATEWAKEUPEVENT_MASK		(1 << 23)
+#define OMAP4_SDMMC1_DAT3_DUPLICATEWAKEUPEVENT_SHIFT		22
+#define OMAP4_SDMMC1_DAT3_DUPLICATEWAKEUPEVENT_MASK		(1 << 22)
+#define OMAP4_SDMMC1_DAT2_DUPLICATEWAKEUPEVENT_SHIFT		21
+#define OMAP4_SDMMC1_DAT2_DUPLICATEWAKEUPEVENT_MASK		(1 << 21)
+#define OMAP4_SDMMC1_DAT1_DUPLICATEWAKEUPEVENT_SHIFT		20
+#define OMAP4_SDMMC1_DAT1_DUPLICATEWAKEUPEVENT_MASK		(1 << 20)
+#define OMAP4_SDMMC1_DAT0_DUPLICATEWAKEUPEVENT_SHIFT		19
+#define OMAP4_SDMMC1_DAT0_DUPLICATEWAKEUPEVENT_MASK		(1 << 19)
+#define OMAP4_SDMMC1_CMD_DUPLICATEWAKEUPEVENT_SHIFT		18
+#define OMAP4_SDMMC1_CMD_DUPLICATEWAKEUPEVENT_MASK		(1 << 18)
+#define OMAP4_SDMMC1_CLK_DUPLICATEWAKEUPEVENT_SHIFT		17
+#define OMAP4_SDMMC1_CLK_DUPLICATEWAKEUPEVENT_MASK		(1 << 17)
+#define OMAP4_USBC1_ICUSB_DM_DUPLICATEWAKEUPEVENT_SHIFT		16
+#define OMAP4_USBC1_ICUSB_DM_DUPLICATEWAKEUPEVENT_MASK		(1 << 16)
+#define OMAP4_USBC1_ICUSB_DP_DUPLICATEWAKEUPEVENT_SHIFT		15
+#define OMAP4_USBC1_ICUSB_DP_DUPLICATEWAKEUPEVENT_MASK		(1 << 15)
+#define OMAP4_USBB1_HSIC_STROBE_DUPLICATEWAKEUPEVENT_SHIFT	14
+#define OMAP4_USBB1_HSIC_STROBE_DUPLICATEWAKEUPEVENT_MASK	(1 << 14)
+#define OMAP4_USBB1_HSIC_DATA_DUPLICATEWAKEUPEVENT_SHIFT	13
+#define OMAP4_USBB1_HSIC_DATA_DUPLICATEWAKEUPEVENT_MASK		(1 << 13)
+#define OMAP4_USBB1_ULPITLL_DAT7_DUPLICATEWAKEUPEVENT_SHIFT	12
+#define OMAP4_USBB1_ULPITLL_DAT7_DUPLICATEWAKEUPEVENT_MASK	(1 << 12)
+#define OMAP4_USBB1_ULPITLL_DAT6_DUPLICATEWAKEUPEVENT_SHIFT	11
+#define OMAP4_USBB1_ULPITLL_DAT6_DUPLICATEWAKEUPEVENT_MASK	(1 << 11)
+#define OMAP4_USBB1_ULPITLL_DAT5_DUPLICATEWAKEUPEVENT_SHIFT	10
+#define OMAP4_USBB1_ULPITLL_DAT5_DUPLICATEWAKEUPEVENT_MASK	(1 << 10)
+#define OMAP4_USBB1_ULPITLL_DAT4_DUPLICATEWAKEUPEVENT_SHIFT	9
+#define OMAP4_USBB1_ULPITLL_DAT4_DUPLICATEWAKEUPEVENT_MASK	(1 << 9)
+#define OMAP4_USBB1_ULPITLL_DAT3_DUPLICATEWAKEUPEVENT_SHIFT	8
+#define OMAP4_USBB1_ULPITLL_DAT3_DUPLICATEWAKEUPEVENT_MASK	(1 << 8)
+#define OMAP4_USBB1_ULPITLL_DAT2_DUPLICATEWAKEUPEVENT_SHIFT	7
+#define OMAP4_USBB1_ULPITLL_DAT2_DUPLICATEWAKEUPEVENT_MASK	(1 << 7)
+#define OMAP4_USBB1_ULPITLL_DAT1_DUPLICATEWAKEUPEVENT_SHIFT	6
+#define OMAP4_USBB1_ULPITLL_DAT1_DUPLICATEWAKEUPEVENT_MASK	(1 << 6)
+#define OMAP4_USBB1_ULPITLL_DAT0_DUPLICATEWAKEUPEVENT_SHIFT	5
+#define OMAP4_USBB1_ULPITLL_DAT0_DUPLICATEWAKEUPEVENT_MASK	(1 << 5)
+#define OMAP4_USBB1_ULPITLL_NXT_DUPLICATEWAKEUPEVENT_SHIFT	4
+#define OMAP4_USBB1_ULPITLL_NXT_DUPLICATEWAKEUPEVENT_MASK	(1 << 4)
+#define OMAP4_USBB1_ULPITLL_DIR_DUPLICATEWAKEUPEVENT_SHIFT	3
+#define OMAP4_USBB1_ULPITLL_DIR_DUPLICATEWAKEUPEVENT_MASK	(1 << 3)
+#define OMAP4_USBB1_ULPITLL_STP_DUPLICATEWAKEUPEVENT_SHIFT	2
+#define OMAP4_USBB1_ULPITLL_STP_DUPLICATEWAKEUPEVENT_MASK	(1 << 2)
+#define OMAP4_USBB1_ULPITLL_CLK_DUPLICATEWAKEUPEVENT_SHIFT	1
+#define OMAP4_USBB1_ULPITLL_CLK_DUPLICATEWAKEUPEVENT_MASK	(1 << 1)
+#define OMAP4_CAM_GLOBALRESET_DUPLICATEWAKEUPEVENT_SHIFT	0
+#define OMAP4_CAM_GLOBALRESET_DUPLICATEWAKEUPEVENT_MASK		(1 << 0)
+
+/* PADCONF_WAKEUPEVENT_3 */
+#define OMAP4_MCSPI1_CS3_DUPLICATEWAKEUPEVENT_SHIFT		31
+#define OMAP4_MCSPI1_CS3_DUPLICATEWAKEUPEVENT_MASK		(1 << 31)
+#define OMAP4_MCSPI1_CS2_DUPLICATEWAKEUPEVENT_SHIFT		30
+#define OMAP4_MCSPI1_CS2_DUPLICATEWAKEUPEVENT_MASK		(1 << 30)
+#define OMAP4_MCSPI1_CS1_DUPLICATEWAKEUPEVENT_SHIFT		29
+#define OMAP4_MCSPI1_CS1_DUPLICATEWAKEUPEVENT_MASK		(1 << 29)
+#define OMAP4_MCSPI1_CS0_DUPLICATEWAKEUPEVENT_SHIFT		28
+#define OMAP4_MCSPI1_CS0_DUPLICATEWAKEUPEVENT_MASK		(1 << 28)
+#define OMAP4_MCSPI1_SIMO_DUPLICATEWAKEUPEVENT_SHIFT		27
+#define OMAP4_MCSPI1_SIMO_DUPLICATEWAKEUPEVENT_MASK		(1 << 27)
+#define OMAP4_MCSPI1_SOMI_DUPLICATEWAKEUPEVENT_SHIFT		26
+#define OMAP4_MCSPI1_SOMI_DUPLICATEWAKEUPEVENT_MASK		(1 << 26)
+#define OMAP4_MCSPI1_CLK_DUPLICATEWAKEUPEVENT_SHIFT		25
+#define OMAP4_MCSPI1_CLK_DUPLICATEWAKEUPEVENT_MASK		(1 << 25)
+#define OMAP4_I2C4_SDA_DUPLICATEWAKEUPEVENT_SHIFT		24
+#define OMAP4_I2C4_SDA_DUPLICATEWAKEUPEVENT_MASK		(1 << 24)
+#define OMAP4_I2C4_SCL_DUPLICATEWAKEUPEVENT_SHIFT		23
+#define OMAP4_I2C4_SCL_DUPLICATEWAKEUPEVENT_MASK		(1 << 23)
+#define OMAP4_I2C3_SDA_DUPLICATEWAKEUPEVENT_SHIFT		22
+#define OMAP4_I2C3_SDA_DUPLICATEWAKEUPEVENT_MASK		(1 << 22)
+#define OMAP4_I2C3_SCL_DUPLICATEWAKEUPEVENT_SHIFT		21
+#define OMAP4_I2C3_SCL_DUPLICATEWAKEUPEVENT_MASK		(1 << 21)
+#define OMAP4_I2C2_SDA_DUPLICATEWAKEUPEVENT_SHIFT		20
+#define OMAP4_I2C2_SDA_DUPLICATEWAKEUPEVENT_MASK		(1 << 20)
+#define OMAP4_I2C2_SCL_DUPLICATEWAKEUPEVENT_SHIFT		19
+#define OMAP4_I2C2_SCL_DUPLICATEWAKEUPEVENT_MASK		(1 << 19)
+#define OMAP4_I2C1_SDA_DUPLICATEWAKEUPEVENT_SHIFT		18
+#define OMAP4_I2C1_SDA_DUPLICATEWAKEUPEVENT_MASK		(1 << 18)
+#define OMAP4_I2C1_SCL_DUPLICATEWAKEUPEVENT_SHIFT		17
+#define OMAP4_I2C1_SCL_DUPLICATEWAKEUPEVENT_MASK		(1 << 17)
+#define OMAP4_HDQ_SIO_DUPLICATEWAKEUPEVENT_SHIFT		16
+#define OMAP4_HDQ_SIO_DUPLICATEWAKEUPEVENT_MASK			(1 << 16)
+#define OMAP4_UART2_TX_DUPLICATEWAKEUPEVENT_SHIFT		15
+#define OMAP4_UART2_TX_DUPLICATEWAKEUPEVENT_MASK		(1 << 15)
+#define OMAP4_UART2_RX_DUPLICATEWAKEUPEVENT_SHIFT		14
+#define OMAP4_UART2_RX_DUPLICATEWAKEUPEVENT_MASK		(1 << 14)
+#define OMAP4_UART2_RTS_DUPLICATEWAKEUPEVENT_SHIFT		13
+#define OMAP4_UART2_RTS_DUPLICATEWAKEUPEVENT_MASK		(1 << 13)
+#define OMAP4_UART2_CTS_DUPLICATEWAKEUPEVENT_SHIFT		12
+#define OMAP4_UART2_CTS_DUPLICATEWAKEUPEVENT_MASK		(1 << 12)
+#define OMAP4_ABE_DMIC_DIN3_DUPLICATEWAKEUPEVENT_SHIFT		11
+#define OMAP4_ABE_DMIC_DIN3_DUPLICATEWAKEUPEVENT_MASK		(1 << 11)
+#define OMAP4_ABE_DMIC_DIN2_DUPLICATEWAKEUPEVENT_SHIFT		10
+#define OMAP4_ABE_DMIC_DIN2_DUPLICATEWAKEUPEVENT_MASK		(1 << 10)
+#define OMAP4_ABE_DMIC_DIN1_DUPLICATEWAKEUPEVENT_SHIFT		9
+#define OMAP4_ABE_DMIC_DIN1_DUPLICATEWAKEUPEVENT_MASK		(1 << 9)
+#define OMAP4_ABE_DMIC_CLK1_DUPLICATEWAKEUPEVENT_SHIFT		8
+#define OMAP4_ABE_DMIC_CLK1_DUPLICATEWAKEUPEVENT_MASK		(1 << 8)
+#define OMAP4_ABE_CLKS_DUPLICATEWAKEUPEVENT_SHIFT		7
+#define OMAP4_ABE_CLKS_DUPLICATEWAKEUPEVENT_MASK		(1 << 7)
+#define OMAP4_ABE_PDM_LB_CLK_DUPLICATEWAKEUPEVENT_SHIFT		6
+#define OMAP4_ABE_PDM_LB_CLK_DUPLICATEWAKEUPEVENT_MASK		(1 << 6)
+#define OMAP4_ABE_PDM_FRAME_DUPLICATEWAKEUPEVENT_SHIFT		5
+#define OMAP4_ABE_PDM_FRAME_DUPLICATEWAKEUPEVENT_MASK		(1 << 5)
+#define OMAP4_ABE_PDM_DL_DATA_DUPLICATEWAKEUPEVENT_SHIFT	4
+#define OMAP4_ABE_PDM_DL_DATA_DUPLICATEWAKEUPEVENT_MASK		(1 << 4)
+#define OMAP4_ABE_PDM_UL_DATA_DUPLICATEWAKEUPEVENT_SHIFT	3
+#define OMAP4_ABE_PDM_UL_DATA_DUPLICATEWAKEUPEVENT_MASK		(1 << 3)
+#define OMAP4_ABE_MCBSP1_FSX_DUPLICATEWAKEUPEVENT_SHIFT		2
+#define OMAP4_ABE_MCBSP1_FSX_DUPLICATEWAKEUPEVENT_MASK		(1 << 2)
+#define OMAP4_ABE_MCBSP1_DX_DUPLICATEWAKEUPEVENT_SHIFT		1
+#define OMAP4_ABE_MCBSP1_DX_DUPLICATEWAKEUPEVENT_MASK		(1 << 1)
+#define OMAP4_ABE_MCBSP1_DR_DUPLICATEWAKEUPEVENT_SHIFT		0
+#define OMAP4_ABE_MCBSP1_DR_DUPLICATEWAKEUPEVENT_MASK		(1 << 0)
+
+/* PADCONF_WAKEUPEVENT_4 */
+#define OMAP4_UNIPRO_TY0_DUPLICATEWAKEUPEVENT_SHIFT		31
+#define OMAP4_UNIPRO_TY0_DUPLICATEWAKEUPEVENT_MASK		(1 << 31)
+#define OMAP4_UNIPRO_TX0_DUPLICATEWAKEUPEVENT_SHIFT		30
+#define OMAP4_UNIPRO_TX0_DUPLICATEWAKEUPEVENT_MASK		(1 << 30)
+#define OMAP4_USBB2_HSIC_STROBE_DUPLICATEWAKEUPEVENT_SHIFT	29
+#define OMAP4_USBB2_HSIC_STROBE_DUPLICATEWAKEUPEVENT_MASK	(1 << 29)
+#define OMAP4_USBB2_HSIC_DATA_DUPLICATEWAKEUPEVENT_SHIFT	28
+#define OMAP4_USBB2_HSIC_DATA_DUPLICATEWAKEUPEVENT_MASK		(1 << 28)
+#define OMAP4_USBB2_ULPITLL_DAT7_DUPLICATEWAKEUPEVENT_SHIFT	27
+#define OMAP4_USBB2_ULPITLL_DAT7_DUPLICATEWAKEUPEVENT_MASK	(1 << 27)
+#define OMAP4_USBB2_ULPITLL_DAT6_DUPLICATEWAKEUPEVENT_SHIFT	26
+#define OMAP4_USBB2_ULPITLL_DAT6_DUPLICATEWAKEUPEVENT_MASK	(1 << 26)
+#define OMAP4_USBB2_ULPITLL_DAT5_DUPLICATEWAKEUPEVENT_SHIFT	25
+#define OMAP4_USBB2_ULPITLL_DAT5_DUPLICATEWAKEUPEVENT_MASK	(1 << 25)
+#define OMAP4_USBB2_ULPITLL_DAT4_DUPLICATEWAKEUPEVENT_SHIFT	24
+#define OMAP4_USBB2_ULPITLL_DAT4_DUPLICATEWAKEUPEVENT_MASK	(1 << 24)
+#define OMAP4_USBB2_ULPITLL_DAT3_DUPLICATEWAKEUPEVENT_SHIFT	23
+#define OMAP4_USBB2_ULPITLL_DAT3_DUPLICATEWAKEUPEVENT_MASK	(1 << 23)
+#define OMAP4_USBB2_ULPITLL_DAT2_DUPLICATEWAKEUPEVENT_SHIFT	22
+#define OMAP4_USBB2_ULPITLL_DAT2_DUPLICATEWAKEUPEVENT_MASK	(1 << 22)
+#define OMAP4_USBB2_ULPITLL_DAT1_DUPLICATEWAKEUPEVENT_SHIFT	21
+#define OMAP4_USBB2_ULPITLL_DAT1_DUPLICATEWAKEUPEVENT_MASK	(1 << 21)
+#define OMAP4_USBB2_ULPITLL_DAT0_DUPLICATEWAKEUPEVENT_SHIFT	20
+#define OMAP4_USBB2_ULPITLL_DAT0_DUPLICATEWAKEUPEVENT_MASK	(1 << 20)
+#define OMAP4_USBB2_ULPITLL_NXT_DUPLICATEWAKEUPEVENT_SHIFT	19
+#define OMAP4_USBB2_ULPITLL_NXT_DUPLICATEWAKEUPEVENT_MASK	(1 << 19)
+#define OMAP4_USBB2_ULPITLL_DIR_DUPLICATEWAKEUPEVENT_SHIFT	18
+#define OMAP4_USBB2_ULPITLL_DIR_DUPLICATEWAKEUPEVENT_MASK	(1 << 18)
+#define OMAP4_USBB2_ULPITLL_STP_DUPLICATEWAKEUPEVENT_SHIFT	17
+#define OMAP4_USBB2_ULPITLL_STP_DUPLICATEWAKEUPEVENT_MASK	(1 << 17)
+#define OMAP4_USBB2_ULPITLL_CLK_DUPLICATEWAKEUPEVENT_SHIFT	16
+#define OMAP4_USBB2_ULPITLL_CLK_DUPLICATEWAKEUPEVENT_MASK	(1 << 16)
+#define OMAP4_UART4_TX_DUPLICATEWAKEUPEVENT_SHIFT		15
+#define OMAP4_UART4_TX_DUPLICATEWAKEUPEVENT_MASK		(1 << 15)
+#define OMAP4_UART4_RX_DUPLICATEWAKEUPEVENT_SHIFT		14
+#define OMAP4_UART4_RX_DUPLICATEWAKEUPEVENT_MASK		(1 << 14)
+#define OMAP4_MCSPI4_CS0_DUPLICATEWAKEUPEVENT_SHIFT		13
+#define OMAP4_MCSPI4_CS0_DUPLICATEWAKEUPEVENT_MASK		(1 << 13)
+#define OMAP4_MCSPI4_SOMI_DUPLICATEWAKEUPEVENT_SHIFT		12
+#define OMAP4_MCSPI4_SOMI_DUPLICATEWAKEUPEVENT_MASK		(1 << 12)
+#define OMAP4_MCSPI4_SIMO_DUPLICATEWAKEUPEVENT_SHIFT		11
+#define OMAP4_MCSPI4_SIMO_DUPLICATEWAKEUPEVENT_MASK		(1 << 11)
+#define OMAP4_MCSPI4_CLK_DUPLICATEWAKEUPEVENT_SHIFT		10
+#define OMAP4_MCSPI4_CLK_DUPLICATEWAKEUPEVENT_MASK		(1 << 10)
+#define OMAP4_SDMMC5_DAT3_DUPLICATEWAKEUPEVENT_SHIFT		9
+#define OMAP4_SDMMC5_DAT3_DUPLICATEWAKEUPEVENT_MASK		(1 << 9)
+#define OMAP4_SDMMC5_DAT2_DUPLICATEWAKEUPEVENT_SHIFT		8
+#define OMAP4_SDMMC5_DAT2_DUPLICATEWAKEUPEVENT_MASK		(1 << 8)
+#define OMAP4_SDMMC5_DAT1_DUPLICATEWAKEUPEVENT_SHIFT		7
+#define OMAP4_SDMMC5_DAT1_DUPLICATEWAKEUPEVENT_MASK		(1 << 7)
+#define OMAP4_SDMMC5_DAT0_DUPLICATEWAKEUPEVENT_SHIFT		6
+#define OMAP4_SDMMC5_DAT0_DUPLICATEWAKEUPEVENT_MASK		(1 << 6)
+#define OMAP4_SDMMC5_CMD_DUPLICATEWAKEUPEVENT_SHIFT		5
+#define OMAP4_SDMMC5_CMD_DUPLICATEWAKEUPEVENT_MASK		(1 << 5)
+#define OMAP4_SDMMC5_CLK_DUPLICATEWAKEUPEVENT_SHIFT		4
+#define OMAP4_SDMMC5_CLK_DUPLICATEWAKEUPEVENT_MASK		(1 << 4)
+#define OMAP4_UART3_TX_IRTX_DUPLICATEWAKEUPEVENT_SHIFT		3
+#define OMAP4_UART3_TX_IRTX_DUPLICATEWAKEUPEVENT_MASK		(1 << 3)
+#define OMAP4_UART3_RX_IRRX_DUPLICATEWAKEUPEVENT_SHIFT		2
+#define OMAP4_UART3_RX_IRRX_DUPLICATEWAKEUPEVENT_MASK		(1 << 2)
+#define OMAP4_UART3_RTS_SD_DUPLICATEWAKEUPEVENT_SHIFT		1
+#define OMAP4_UART3_RTS_SD_DUPLICATEWAKEUPEVENT_MASK		(1 << 1)
+#define OMAP4_UART3_CTS_RCTX_DUPLICATEWAKEUPEVENT_SHIFT		0
+#define OMAP4_UART3_CTS_RCTX_DUPLICATEWAKEUPEVENT_MASK		(1 << 0)
+
+/* PADCONF_WAKEUPEVENT_5 */
+#define OMAP4_DPM_EMU11_DUPLICATEWAKEUPEVENT_SHIFT		31
+#define OMAP4_DPM_EMU11_DUPLICATEWAKEUPEVENT_MASK		(1 << 31)
+#define OMAP4_DPM_EMU10_DUPLICATEWAKEUPEVENT_SHIFT		30
+#define OMAP4_DPM_EMU10_DUPLICATEWAKEUPEVENT_MASK		(1 << 30)
+#define OMAP4_DPM_EMU9_DUPLICATEWAKEUPEVENT_SHIFT		29
+#define OMAP4_DPM_EMU9_DUPLICATEWAKEUPEVENT_MASK		(1 << 29)
+#define OMAP4_DPM_EMU8_DUPLICATEWAKEUPEVENT_SHIFT		28
+#define OMAP4_DPM_EMU8_DUPLICATEWAKEUPEVENT_MASK		(1 << 28)
+#define OMAP4_DPM_EMU7_DUPLICATEWAKEUPEVENT_SHIFT		27
+#define OMAP4_DPM_EMU7_DUPLICATEWAKEUPEVENT_MASK		(1 << 27)
+#define OMAP4_DPM_EMU6_DUPLICATEWAKEUPEVENT_SHIFT		26
+#define OMAP4_DPM_EMU6_DUPLICATEWAKEUPEVENT_MASK		(1 << 26)
+#define OMAP4_DPM_EMU5_DUPLICATEWAKEUPEVENT_SHIFT		25
+#define OMAP4_DPM_EMU5_DUPLICATEWAKEUPEVENT_MASK		(1 << 25)
+#define OMAP4_DPM_EMU4_DUPLICATEWAKEUPEVENT_SHIFT		24
+#define OMAP4_DPM_EMU4_DUPLICATEWAKEUPEVENT_MASK		(1 << 24)
+#define OMAP4_DPM_EMU3_DUPLICATEWAKEUPEVENT_SHIFT		23
+#define OMAP4_DPM_EMU3_DUPLICATEWAKEUPEVENT_MASK		(1 << 23)
+#define OMAP4_DPM_EMU2_DUPLICATEWAKEUPEVENT_SHIFT		22
+#define OMAP4_DPM_EMU2_DUPLICATEWAKEUPEVENT_MASK		(1 << 22)
+#define OMAP4_DPM_EMU1_DUPLICATEWAKEUPEVENT_SHIFT		21
+#define OMAP4_DPM_EMU1_DUPLICATEWAKEUPEVENT_MASK		(1 << 21)
+#define OMAP4_DPM_EMU0_DUPLICATEWAKEUPEVENT_SHIFT		20
+#define OMAP4_DPM_EMU0_DUPLICATEWAKEUPEVENT_MASK		(1 << 20)
+#define OMAP4_SYS_BOOT5_DUPLICATEWAKEUPEVENT_SHIFT		19
+#define OMAP4_SYS_BOOT5_DUPLICATEWAKEUPEVENT_MASK		(1 << 19)
+#define OMAP4_SYS_BOOT4_DUPLICATEWAKEUPEVENT_SHIFT		18
+#define OMAP4_SYS_BOOT4_DUPLICATEWAKEUPEVENT_MASK		(1 << 18)
+#define OMAP4_SYS_BOOT3_DUPLICATEWAKEUPEVENT_SHIFT		17
+#define OMAP4_SYS_BOOT3_DUPLICATEWAKEUPEVENT_MASK		(1 << 17)
+#define OMAP4_SYS_BOOT2_DUPLICATEWAKEUPEVENT_SHIFT		16
+#define OMAP4_SYS_BOOT2_DUPLICATEWAKEUPEVENT_MASK		(1 << 16)
+#define OMAP4_SYS_BOOT1_DUPLICATEWAKEUPEVENT_SHIFT		15
+#define OMAP4_SYS_BOOT1_DUPLICATEWAKEUPEVENT_MASK		(1 << 15)
+#define OMAP4_SYS_BOOT0_DUPLICATEWAKEUPEVENT_SHIFT		14
+#define OMAP4_SYS_BOOT0_DUPLICATEWAKEUPEVENT_MASK		(1 << 14)
+#define OMAP4_SYS_NIRQ2_DUPLICATEWAKEUPEVENT_SHIFT		13
+#define OMAP4_SYS_NIRQ2_DUPLICATEWAKEUPEVENT_MASK		(1 << 13)
+#define OMAP4_SYS_NIRQ1_DUPLICATEWAKEUPEVENT_SHIFT		12
+#define OMAP4_SYS_NIRQ1_DUPLICATEWAKEUPEVENT_MASK		(1 << 12)
+#define OMAP4_FREF_CLK2_OUT_DUPLICATEWAKEUPEVENT_SHIFT		11
+#define OMAP4_FREF_CLK2_OUT_DUPLICATEWAKEUPEVENT_MASK		(1 << 11)
+#define OMAP4_FREF_CLK1_OUT_DUPLICATEWAKEUPEVENT_SHIFT		10
+#define OMAP4_FREF_CLK1_OUT_DUPLICATEWAKEUPEVENT_MASK		(1 << 10)
+#define OMAP4_UNIPRO_RY2_DUPLICATEWAKEUPEVENT_SHIFT		9
+#define OMAP4_UNIPRO_RY2_DUPLICATEWAKEUPEVENT_MASK		(1 << 9)
+#define OMAP4_UNIPRO_RX2_DUPLICATEWAKEUPEVENT_SHIFT		8
+#define OMAP4_UNIPRO_RX2_DUPLICATEWAKEUPEVENT_MASK		(1 << 8)
+#define OMAP4_UNIPRO_RY1_DUPLICATEWAKEUPEVENT_SHIFT		7
+#define OMAP4_UNIPRO_RY1_DUPLICATEWAKEUPEVENT_MASK		(1 << 7)
+#define OMAP4_UNIPRO_RX1_DUPLICATEWAKEUPEVENT_SHIFT		6
+#define OMAP4_UNIPRO_RX1_DUPLICATEWAKEUPEVENT_MASK		(1 << 6)
+#define OMAP4_UNIPRO_RY0_DUPLICATEWAKEUPEVENT_SHIFT		5
+#define OMAP4_UNIPRO_RY0_DUPLICATEWAKEUPEVENT_MASK		(1 << 5)
+#define OMAP4_UNIPRO_RX0_DUPLICATEWAKEUPEVENT_SHIFT		4
+#define OMAP4_UNIPRO_RX0_DUPLICATEWAKEUPEVENT_MASK		(1 << 4)
+#define OMAP4_UNIPRO_TY2_DUPLICATEWAKEUPEVENT_SHIFT		3
+#define OMAP4_UNIPRO_TY2_DUPLICATEWAKEUPEVENT_MASK		(1 << 3)
+#define OMAP4_UNIPRO_TX2_DUPLICATEWAKEUPEVENT_SHIFT		2
+#define OMAP4_UNIPRO_TX2_DUPLICATEWAKEUPEVENT_MASK		(1 << 2)
+#define OMAP4_UNIPRO_TY1_DUPLICATEWAKEUPEVENT_SHIFT		1
+#define OMAP4_UNIPRO_TY1_DUPLICATEWAKEUPEVENT_MASK		(1 << 1)
+#define OMAP4_UNIPRO_TX1_DUPLICATEWAKEUPEVENT_SHIFT		0
+#define OMAP4_UNIPRO_TX1_DUPLICATEWAKEUPEVENT_MASK		(1 << 0)
+
+/* PADCONF_WAKEUPEVENT_6 */
+#define OMAP4_DPM_EMU19_DUPLICATEWAKEUPEVENT_SHIFT		7
+#define OMAP4_DPM_EMU19_DUPLICATEWAKEUPEVENT_MASK		(1 << 7)
+#define OMAP4_DPM_EMU18_DUPLICATEWAKEUPEVENT_SHIFT		6
+#define OMAP4_DPM_EMU18_DUPLICATEWAKEUPEVENT_MASK		(1 << 6)
+#define OMAP4_DPM_EMU17_DUPLICATEWAKEUPEVENT_SHIFT		5
+#define OMAP4_DPM_EMU17_DUPLICATEWAKEUPEVENT_MASK		(1 << 5)
+#define OMAP4_DPM_EMU16_DUPLICATEWAKEUPEVENT_SHIFT		4
+#define OMAP4_DPM_EMU16_DUPLICATEWAKEUPEVENT_MASK		(1 << 4)
+#define OMAP4_DPM_EMU15_DUPLICATEWAKEUPEVENT_SHIFT		3
+#define OMAP4_DPM_EMU15_DUPLICATEWAKEUPEVENT_MASK		(1 << 3)
+#define OMAP4_DPM_EMU14_DUPLICATEWAKEUPEVENT_SHIFT		2
+#define OMAP4_DPM_EMU14_DUPLICATEWAKEUPEVENT_MASK		(1 << 2)
+#define OMAP4_DPM_EMU13_DUPLICATEWAKEUPEVENT_SHIFT		1
+#define OMAP4_DPM_EMU13_DUPLICATEWAKEUPEVENT_MASK		(1 << 1)
+#define OMAP4_DPM_EMU12_DUPLICATEWAKEUPEVENT_SHIFT		0
+#define OMAP4_DPM_EMU12_DUPLICATEWAKEUPEVENT_MASK		(1 << 0)
+
+/* CONTROL_PADCONF_GLOBAL */
+#define OMAP4_FORCE_OFFMODE_EN_SHIFT				31
+#define OMAP4_FORCE_OFFMODE_EN_MASK				(1 << 31)
+
+/* CONTROL_PADCONF_MODE */
+#define OMAP4_VDDS_DV_BANK0_SHIFT				31
+#define OMAP4_VDDS_DV_BANK0_MASK				(1 << 31)
+#define OMAP4_VDDS_DV_BANK1_SHIFT				30
+#define OMAP4_VDDS_DV_BANK1_MASK				(1 << 30)
+#define OMAP4_VDDS_DV_BANK3_SHIFT				29
+#define OMAP4_VDDS_DV_BANK3_MASK				(1 << 29)
+#define OMAP4_VDDS_DV_BANK4_SHIFT				28
+#define OMAP4_VDDS_DV_BANK4_MASK				(1 << 28)
+#define OMAP4_VDDS_DV_BANK5_SHIFT				27
+#define OMAP4_VDDS_DV_BANK5_MASK				(1 << 27)
+#define OMAP4_VDDS_DV_BANK6_SHIFT				26
+#define OMAP4_VDDS_DV_BANK6_MASK				(1 << 26)
+#define OMAP4_VDDS_DV_C2C_SHIFT					25
+#define OMAP4_VDDS_DV_C2C_MASK					(1 << 25)
+#define OMAP4_VDDS_DV_CAM_SHIFT					24
+#define OMAP4_VDDS_DV_CAM_MASK					(1 << 24)
+#define OMAP4_VDDS_DV_GPMC_SHIFT				23
+#define OMAP4_VDDS_DV_GPMC_MASK					(1 << 23)
+#define OMAP4_VDDS_DV_SDMMC2_SHIFT				22
+#define OMAP4_VDDS_DV_SDMMC2_MASK				(1 << 22)
+
+/* CONTROL_SMART1IO_PADCONF_0 */
+#define OMAP4_ABE_DR0_SC_SHIFT					30
+#define OMAP4_ABE_DR0_SC_MASK					(0x3 << 30)
+#define OMAP4_CAM_DR0_SC_SHIFT					28
+#define OMAP4_CAM_DR0_SC_MASK					(0x3 << 28)
+#define OMAP4_FREF_DR2_SC_SHIFT					26
+#define OMAP4_FREF_DR2_SC_MASK					(0x3 << 26)
+#define OMAP4_FREF_DR3_SC_SHIFT					24
+#define OMAP4_FREF_DR3_SC_MASK					(0x3 << 24)
+#define OMAP4_GPIO_DR8_SC_SHIFT					22
+#define OMAP4_GPIO_DR8_SC_MASK					(0x3 << 22)
+#define OMAP4_GPIO_DR9_SC_SHIFT					20
+#define OMAP4_GPIO_DR9_SC_MASK					(0x3 << 20)
+#define OMAP4_GPMC_DR2_SC_SHIFT					18
+#define OMAP4_GPMC_DR2_SC_MASK					(0x3 << 18)
+#define OMAP4_GPMC_DR3_SC_SHIFT					16
+#define OMAP4_GPMC_DR3_SC_MASK					(0x3 << 16)
+#define OMAP4_GPMC_DR6_SC_SHIFT					14
+#define OMAP4_GPMC_DR6_SC_MASK					(0x3 << 14)
+#define OMAP4_HDMI_DR0_SC_SHIFT					12
+#define OMAP4_HDMI_DR0_SC_MASK					(0x3 << 12)
+#define OMAP4_MCSPI1_DR0_SC_SHIFT				10
+#define OMAP4_MCSPI1_DR0_SC_MASK				(0x3 << 10)
+#define OMAP4_UART1_DR0_SC_SHIFT				8
+#define OMAP4_UART1_DR0_SC_MASK					(0x3 << 8)
+#define OMAP4_UART3_DR0_SC_SHIFT				6
+#define OMAP4_UART3_DR0_SC_MASK					(0x3 << 6)
+#define OMAP4_UART3_DR1_SC_SHIFT				4
+#define OMAP4_UART3_DR1_SC_MASK					(0x3 << 4)
+#define OMAP4_UNIPRO_DR0_SC_SHIFT				2
+#define OMAP4_UNIPRO_DR0_SC_MASK				(0x3 << 2)
+#define OMAP4_UNIPRO_DR1_SC_SHIFT				0
+#define OMAP4_UNIPRO_DR1_SC_MASK				(0x3 << 0)
+
+/* CONTROL_SMART1IO_PADCONF_1 */
+#define OMAP4_ABE_DR0_LB_SHIFT					30
+#define OMAP4_ABE_DR0_LB_MASK					(0x3 << 30)
+#define OMAP4_CAM_DR0_LB_SHIFT					28
+#define OMAP4_CAM_DR0_LB_MASK					(0x3 << 28)
+#define OMAP4_FREF_DR2_LB_SHIFT					26
+#define OMAP4_FREF_DR2_LB_MASK					(0x3 << 26)
+#define OMAP4_FREF_DR3_LB_SHIFT					24
+#define OMAP4_FREF_DR3_LB_MASK					(0x3 << 24)
+#define OMAP4_GPIO_DR8_LB_SHIFT					22
+#define OMAP4_GPIO_DR8_LB_MASK					(0x3 << 22)
+#define OMAP4_GPIO_DR9_LB_SHIFT					20
+#define OMAP4_GPIO_DR9_LB_MASK					(0x3 << 20)
+#define OMAP4_GPMC_DR2_LB_SHIFT					18
+#define OMAP4_GPMC_DR2_LB_MASK					(0x3 << 18)
+#define OMAP4_GPMC_DR3_LB_SHIFT					16
+#define OMAP4_GPMC_DR3_LB_MASK					(0x3 << 16)
+#define OMAP4_GPMC_DR6_LB_SHIFT					14
+#define OMAP4_GPMC_DR6_LB_MASK					(0x3 << 14)
+#define OMAP4_HDMI_DR0_LB_SHIFT					12
+#define OMAP4_HDMI_DR0_LB_MASK					(0x3 << 12)
+#define OMAP4_MCSPI1_DR0_LB_SHIFT				10
+#define OMAP4_MCSPI1_DR0_LB_MASK				(0x3 << 10)
+#define OMAP4_UART1_DR0_LB_SHIFT				8
+#define OMAP4_UART1_DR0_LB_MASK					(0x3 << 8)
+#define OMAP4_UART3_DR0_LB_SHIFT				6
+#define OMAP4_UART3_DR0_LB_MASK					(0x3 << 6)
+#define OMAP4_UART3_DR1_LB_SHIFT				4
+#define OMAP4_UART3_DR1_LB_MASK					(0x3 << 4)
+#define OMAP4_UNIPRO_DR0_LB_SHIFT				2
+#define OMAP4_UNIPRO_DR0_LB_MASK				(0x3 << 2)
+#define OMAP4_UNIPRO_DR1_LB_SHIFT				0
+#define OMAP4_UNIPRO_DR1_LB_MASK				(0x3 << 0)
+
+/* CONTROL_SMART2IO_PADCONF_0 */
+#define OMAP4_C2C_DR0_LB_SHIFT					31
+#define OMAP4_C2C_DR0_LB_MASK					(1 << 31)
+#define OMAP4_DPM_DR1_LB_SHIFT					30
+#define OMAP4_DPM_DR1_LB_MASK					(1 << 30)
+#define OMAP4_DPM_DR2_LB_SHIFT					29
+#define OMAP4_DPM_DR2_LB_MASK					(1 << 29)
+#define OMAP4_DPM_DR3_LB_SHIFT					28
+#define OMAP4_DPM_DR3_LB_MASK					(1 << 28)
+#define OMAP4_GPIO_DR0_LB_SHIFT					27
+#define OMAP4_GPIO_DR0_LB_MASK					(1 << 27)
+#define OMAP4_GPIO_DR1_LB_SHIFT					26
+#define OMAP4_GPIO_DR1_LB_MASK					(1 << 26)
+#define OMAP4_GPIO_DR10_LB_SHIFT				25
+#define OMAP4_GPIO_DR10_LB_MASK					(1 << 25)
+#define OMAP4_GPIO_DR2_LB_SHIFT					24
+#define OMAP4_GPIO_DR2_LB_MASK					(1 << 24)
+#define OMAP4_GPMC_DR0_LB_SHIFT					23
+#define OMAP4_GPMC_DR0_LB_MASK					(1 << 23)
+#define OMAP4_GPMC_DR1_LB_SHIFT					22
+#define OMAP4_GPMC_DR1_LB_MASK					(1 << 22)
+#define OMAP4_GPMC_DR4_LB_SHIFT					21
+#define OMAP4_GPMC_DR4_LB_MASK					(1 << 21)
+#define OMAP4_GPMC_DR5_LB_SHIFT					20
+#define OMAP4_GPMC_DR5_LB_MASK					(1 << 20)
+#define OMAP4_GPMC_DR7_LB_SHIFT					19
+#define OMAP4_GPMC_DR7_LB_MASK					(1 << 19)
+#define OMAP4_HSI2_DR0_LB_SHIFT					18
+#define OMAP4_HSI2_DR0_LB_MASK					(1 << 18)
+#define OMAP4_HSI2_DR1_LB_SHIFT					17
+#define OMAP4_HSI2_DR1_LB_MASK					(1 << 17)
+#define OMAP4_HSI2_DR2_LB_SHIFT					16
+#define OMAP4_HSI2_DR2_LB_MASK					(1 << 16)
+#define OMAP4_KPD_DR0_LB_SHIFT					15
+#define OMAP4_KPD_DR0_LB_MASK					(1 << 15)
+#define OMAP4_KPD_DR1_LB_SHIFT					14
+#define OMAP4_KPD_DR1_LB_MASK					(1 << 14)
+#define OMAP4_PDM_DR0_LB_SHIFT					13
+#define OMAP4_PDM_DR0_LB_MASK					(1 << 13)
+#define OMAP4_SDMMC2_DR0_LB_SHIFT				12
+#define OMAP4_SDMMC2_DR0_LB_MASK				(1 << 12)
+#define OMAP4_SDMMC3_DR0_LB_SHIFT				11
+#define OMAP4_SDMMC3_DR0_LB_MASK				(1 << 11)
+#define OMAP4_SDMMC4_DR0_LB_SHIFT				10
+#define OMAP4_SDMMC4_DR0_LB_MASK				(1 << 10)
+#define OMAP4_SDMMC4_DR1_LB_SHIFT				9
+#define OMAP4_SDMMC4_DR1_LB_MASK				(1 << 9)
+#define OMAP4_SPI3_DR0_LB_SHIFT					8
+#define OMAP4_SPI3_DR0_LB_MASK					(1 << 8)
+#define OMAP4_SPI3_DR1_LB_SHIFT					7
+#define OMAP4_SPI3_DR1_LB_MASK					(1 << 7)
+#define OMAP4_UART3_DR2_LB_SHIFT				6
+#define OMAP4_UART3_DR2_LB_MASK					(1 << 6)
+#define OMAP4_UART3_DR3_LB_SHIFT				5
+#define OMAP4_UART3_DR3_LB_MASK					(1 << 5)
+#define OMAP4_UART3_DR4_LB_SHIFT				4
+#define OMAP4_UART3_DR4_LB_MASK					(1 << 4)
+#define OMAP4_UART3_DR5_LB_SHIFT				3
+#define OMAP4_UART3_DR5_LB_MASK					(1 << 3)
+#define OMAP4_USBA0_DR1_LB_SHIFT				2
+#define OMAP4_USBA0_DR1_LB_MASK					(1 << 2)
+#define OMAP4_USBA_DR2_LB_SHIFT					1
+#define OMAP4_USBA_DR2_LB_MASK					(1 << 1)
+
+/* CONTROL_SMART2IO_PADCONF_1 */
+#define OMAP4_USBB1_DR0_LB_SHIFT				31
+#define OMAP4_USBB1_DR0_LB_MASK					(1 << 31)
+#define OMAP4_USBB2_DR0_LB_SHIFT				30
+#define OMAP4_USBB2_DR0_LB_MASK					(1 << 30)
+#define OMAP4_USBA0_DR0_LB_SHIFT				29
+#define OMAP4_USBA0_DR0_LB_MASK					(1 << 29)
+
+/* CONTROL_SMART3IO_PADCONF_0 */
+#define OMAP4_DMIC_DR0_MB_SHIFT					30
+#define OMAP4_DMIC_DR0_MB_MASK					(0x3 << 30)
+#define OMAP4_GPIO_DR3_MB_SHIFT					28
+#define OMAP4_GPIO_DR3_MB_MASK					(0x3 << 28)
+#define OMAP4_GPIO_DR4_MB_SHIFT					26
+#define OMAP4_GPIO_DR4_MB_MASK					(0x3 << 26)
+#define OMAP4_GPIO_DR5_MB_SHIFT					24
+#define OMAP4_GPIO_DR5_MB_MASK					(0x3 << 24)
+#define OMAP4_GPIO_DR6_MB_SHIFT					22
+#define OMAP4_GPIO_DR6_MB_MASK					(0x3 << 22)
+#define OMAP4_HSI_DR1_MB_SHIFT					20
+#define OMAP4_HSI_DR1_MB_MASK					(0x3 << 20)
+#define OMAP4_HSI_DR2_MB_SHIFT					18
+#define OMAP4_HSI_DR2_MB_MASK					(0x3 << 18)
+#define OMAP4_HSI_DR3_MB_SHIFT					16
+#define OMAP4_HSI_DR3_MB_MASK					(0x3 << 16)
+#define OMAP4_MCBSP2_DR0_MB_SHIFT				14
+#define OMAP4_MCBSP2_DR0_MB_MASK				(0x3 << 14)
+#define OMAP4_MCSPI4_DR0_MB_SHIFT				12
+#define OMAP4_MCSPI4_DR0_MB_MASK				(0x3 << 12)
+#define OMAP4_MCSPI4_DR1_MB_SHIFT				10
+#define OMAP4_MCSPI4_DR1_MB_MASK				(0x3 << 10)
+#define OMAP4_SDMMC3_DR0_MB_SHIFT				8
+#define OMAP4_SDMMC3_DR0_MB_MASK				(0x3 << 8)
+#define OMAP4_SPI2_DR0_MB_SHIFT					0
+#define OMAP4_SPI2_DR0_MB_MASK					(0x3 << 0)
+
+/* CONTROL_SMART3IO_PADCONF_1 */
+#define OMAP4_SPI2_DR1_MB_SHIFT					30
+#define OMAP4_SPI2_DR1_MB_MASK					(0x3 << 30)
+#define OMAP4_SPI2_DR2_MB_SHIFT					28
+#define OMAP4_SPI2_DR2_MB_MASK					(0x3 << 28)
+#define OMAP4_UART2_DR0_MB_SHIFT				26
+#define OMAP4_UART2_DR0_MB_MASK					(0x3 << 26)
+#define OMAP4_UART2_DR1_MB_SHIFT				24
+#define OMAP4_UART2_DR1_MB_MASK					(0x3 << 24)
+#define OMAP4_UART4_DR0_MB_SHIFT				22
+#define OMAP4_UART4_DR0_MB_MASK					(0x3 << 22)
+#define OMAP4_HSI_DR0_MB_SHIFT					20
+#define OMAP4_HSI_DR0_MB_MASK					(0x3 << 20)
+
+/* CONTROL_SMART3IO_PADCONF_2 */
+#define OMAP4_DMIC_DR0_LB_SHIFT					31
+#define OMAP4_DMIC_DR0_LB_MASK					(1 << 31)
+#define OMAP4_GPIO_DR3_LB_SHIFT					30
+#define OMAP4_GPIO_DR3_LB_MASK					(1 << 30)
+#define OMAP4_GPIO_DR4_LB_SHIFT					29
+#define OMAP4_GPIO_DR4_LB_MASK					(1 << 29)
+#define OMAP4_GPIO_DR5_LB_SHIFT					28
+#define OMAP4_GPIO_DR5_LB_MASK					(1 << 28)
+#define OMAP4_GPIO_DR6_LB_SHIFT					27
+#define OMAP4_GPIO_DR6_LB_MASK					(1 << 27)
+#define OMAP4_HSI_DR1_LB_SHIFT					26
+#define OMAP4_HSI_DR1_LB_MASK					(1 << 26)
+#define OMAP4_HSI_DR2_LB_SHIFT					25
+#define OMAP4_HSI_DR2_LB_MASK					(1 << 25)
+#define OMAP4_HSI_DR3_LB_SHIFT					24
+#define OMAP4_HSI_DR3_LB_MASK					(1 << 24)
+#define OMAP4_MCBSP2_DR0_LB_SHIFT				23
+#define OMAP4_MCBSP2_DR0_LB_MASK				(1 << 23)
+#define OMAP4_MCSPI4_DR0_LB_SHIFT				22
+#define OMAP4_MCSPI4_DR0_LB_MASK				(1 << 22)
+#define OMAP4_MCSPI4_DR1_LB_SHIFT				21
+#define OMAP4_MCSPI4_DR1_LB_MASK				(1 << 21)
+#define OMAP4_SLIMBUS2_DR0_LB_SHIFT				18
+#define OMAP4_SLIMBUS2_DR0_LB_MASK				(1 << 18)
+#define OMAP4_SPI2_DR0_LB_SHIFT					16
+#define OMAP4_SPI2_DR0_LB_MASK					(1 << 16)
+#define OMAP4_SPI2_DR1_LB_SHIFT					15
+#define OMAP4_SPI2_DR1_LB_MASK					(1 << 15)
+#define OMAP4_SPI2_DR2_LB_SHIFT					14
+#define OMAP4_SPI2_DR2_LB_MASK					(1 << 14)
+#define OMAP4_UART2_DR0_LB_SHIFT				13
+#define OMAP4_UART2_DR0_LB_MASK					(1 << 13)
+#define OMAP4_UART2_DR1_LB_SHIFT				12
+#define OMAP4_UART2_DR1_LB_MASK					(1 << 12)
+#define OMAP4_UART4_DR0_LB_SHIFT				11
+#define OMAP4_UART4_DR0_LB_MASK					(1 << 11)
+#define OMAP4_HSI_DR0_LB_SHIFT					10
+#define OMAP4_HSI_DR0_LB_MASK					(1 << 10)
+
+/* CONTROL_USBB_HSIC */
+#define OMAP4_USBB2_DR1_SR_SHIFT				30
+#define OMAP4_USBB2_DR1_SR_MASK					(0x3 << 30)
+#define OMAP4_USBB2_DR1_I_SHIFT					27
+#define OMAP4_USBB2_DR1_I_MASK					(0x7 << 27)
+#define OMAP4_USBB1_DR1_SR_SHIFT				25
+#define OMAP4_USBB1_DR1_SR_MASK					(0x3 << 25)
+#define OMAP4_USBB1_DR1_I_SHIFT					22
+#define OMAP4_USBB1_DR1_I_MASK					(0x7 << 22)
+#define OMAP4_USBB1_HSIC_DATA_WD_SHIFT				20
+#define OMAP4_USBB1_HSIC_DATA_WD_MASK				(0x3 << 20)
+#define OMAP4_USBB1_HSIC_STROBE_WD_SHIFT			18
+#define OMAP4_USBB1_HSIC_STROBE_WD_MASK				(0x3 << 18)
+#define OMAP4_USBB2_HSIC_DATA_WD_SHIFT				16
+#define OMAP4_USBB2_HSIC_DATA_WD_MASK				(0x3 << 16)
+#define OMAP4_USBB2_HSIC_STROBE_WD_SHIFT			14
+#define OMAP4_USBB2_HSIC_STROBE_WD_MASK				(0x3 << 14)
+#define OMAP4_USBB1_HSIC_DATA_OFFMODE_WD_ENABLE_SHIFT		13
+#define OMAP4_USBB1_HSIC_DATA_OFFMODE_WD_ENABLE_MASK		(1 << 13)
+#define OMAP4_USBB1_HSIC_DATA_OFFMODE_WD_SHIFT			11
+#define OMAP4_USBB1_HSIC_DATA_OFFMODE_WD_MASK			(0x3 << 11)
+#define OMAP4_USBB1_HSIC_STROBE_OFFMODE_WD_ENABLE_SHIFT		10
+#define OMAP4_USBB1_HSIC_STROBE_OFFMODE_WD_ENABLE_MASK		(1 << 10)
+#define OMAP4_USBB1_HSIC_STROBE_OFFMODE_WD_SHIFT		8
+#define OMAP4_USBB1_HSIC_STROBE_OFFMODE_WD_MASK			(0x3 << 8)
+#define OMAP4_USBB2_HSIC_DATA_OFFMODE_WD_ENABLE_SHIFT		7
+#define OMAP4_USBB2_HSIC_DATA_OFFMODE_WD_ENABLE_MASK		(1 << 7)
+#define OMAP4_USBB2_HSIC_DATA_OFFMODE_WD_SHIFT			5
+#define OMAP4_USBB2_HSIC_DATA_OFFMODE_WD_MASK			(0x3 << 5)
+#define OMAP4_USBB2_HSIC_STROBE_OFFMODE_WD_ENABLE_SHIFT		4
+#define OMAP4_USBB2_HSIC_STROBE_OFFMODE_WD_ENABLE_MASK		(1 << 4)
+#define OMAP4_USBB2_HSIC_STROBE_OFFMODE_WD_SHIFT		2
+#define OMAP4_USBB2_HSIC_STROBE_OFFMODE_WD_MASK			(0x3 << 2)
+
+/* CONTROL_SLIMBUS */
+#define OMAP4_SLIMBUS1_DR0_MB_SHIFT				30
+#define OMAP4_SLIMBUS1_DR0_MB_MASK				(0x3 << 30)
+#define OMAP4_SLIMBUS1_DR1_MB_SHIFT				28
+#define OMAP4_SLIMBUS1_DR1_MB_MASK				(0x3 << 28)
+#define OMAP4_SLIMBUS2_DR0_MB_SHIFT				26
+#define OMAP4_SLIMBUS2_DR0_MB_MASK				(0x3 << 26)
+#define OMAP4_SLIMBUS2_DR1_MB_SHIFT				24
+#define OMAP4_SLIMBUS2_DR1_MB_MASK				(0x3 << 24)
+#define OMAP4_SLIMBUS2_DR2_MB_SHIFT				22
+#define OMAP4_SLIMBUS2_DR2_MB_MASK				(0x3 << 22)
+#define OMAP4_SLIMBUS2_DR3_MB_SHIFT				20
+#define OMAP4_SLIMBUS2_DR3_MB_MASK				(0x3 << 20)
+#define OMAP4_SLIMBUS1_DR0_LB_SHIFT				19
+#define OMAP4_SLIMBUS1_DR0_LB_MASK				(1 << 19)
+#define OMAP4_SLIMBUS2_DR1_LB_SHIFT				18
+#define OMAP4_SLIMBUS2_DR1_LB_MASK				(1 << 18)
+
+/* CONTROL_PBIASLITE */
+#define OMAP4_USIM_PBIASLITE_HIZ_MODE_SHIFT			31
+#define OMAP4_USIM_PBIASLITE_HIZ_MODE_MASK			(1 << 31)
+#define OMAP4_USIM_PBIASLITE_SUPPLY_HI_OUT_SHIFT		30
+#define OMAP4_USIM_PBIASLITE_SUPPLY_HI_OUT_MASK			(1 << 30)
+#define OMAP4_USIM_PBIASLITE_VMODE_ERROR_SHIFT			29
+#define OMAP4_USIM_PBIASLITE_VMODE_ERROR_MASK			(1 << 29)
+#define OMAP4_USIM_PBIASLITE_PWRDNZ_SHIFT			28
+#define OMAP4_USIM_PBIASLITE_PWRDNZ_MASK			(1 << 28)
+#define OMAP4_USIM_PBIASLITE_VMODE_SHIFT			27
+#define OMAP4_USIM_PBIASLITE_VMODE_MASK				(1 << 27)
+#define OMAP4_MMC1_PWRDNZ_SHIFT					26
+#define OMAP4_MMC1_PWRDNZ_MASK					(1 << 26)
+#define OMAP4_MMC1_PBIASLITE_HIZ_MODE_SHIFT			25
+#define OMAP4_MMC1_PBIASLITE_HIZ_MODE_MASK			(1 << 25)
+#define OMAP4_MMC1_PBIASLITE_SUPPLY_HI_OUT_SHIFT		24
+#define OMAP4_MMC1_PBIASLITE_SUPPLY_HI_OUT_MASK			(1 << 24)
+#define OMAP4_MMC1_PBIASLITE_VMODE_ERROR_SHIFT			23
+#define OMAP4_MMC1_PBIASLITE_VMODE_ERROR_MASK			(1 << 23)
+#define OMAP4_MMC1_PBIASLITE_PWRDNZ_SHIFT			22
+#define OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK			(1 << 22)
+#define OMAP4_MMC1_PBIASLITE_VMODE_SHIFT			21
+#define OMAP4_MMC1_PBIASLITE_VMODE_MASK				(1 << 21)
+#define OMAP4_USBC1_ICUSB_PWRDNZ_SHIFT				20
+#define OMAP4_USBC1_ICUSB_PWRDNZ_MASK				(1 << 20)
+
+/* CONTROL_I2C_0 */
+#define OMAP4_I2C4_SDA_GLFENB_SHIFT				31
+#define OMAP4_I2C4_SDA_GLFENB_MASK				(1 << 31)
+#define OMAP4_I2C4_SDA_LOAD_BITS_SHIFT				29
+#define OMAP4_I2C4_SDA_LOAD_BITS_MASK				(0x3 << 29)
+#define OMAP4_I2C4_SDA_PULLUPRESX_SHIFT				28
+#define OMAP4_I2C4_SDA_PULLUPRESX_MASK				(1 << 28)
+#define OMAP4_I2C3_SDA_GLFENB_SHIFT				27
+#define OMAP4_I2C3_SDA_GLFENB_MASK				(1 << 27)
+#define OMAP4_I2C3_SDA_LOAD_BITS_SHIFT				25
+#define OMAP4_I2C3_SDA_LOAD_BITS_MASK				(0x3 << 25)
+#define OMAP4_I2C3_SDA_PULLUPRESX_SHIFT				24
+#define OMAP4_I2C3_SDA_PULLUPRESX_MASK				(1 << 24)
+#define OMAP4_I2C2_SDA_GLFENB_SHIFT				23
+#define OMAP4_I2C2_SDA_GLFENB_MASK				(1 << 23)
+#define OMAP4_I2C2_SDA_LOAD_BITS_SHIFT				21
+#define OMAP4_I2C2_SDA_LOAD_BITS_MASK				(0x3 << 21)
+#define OMAP4_I2C2_SDA_PULLUPRESX_SHIFT				20
+#define OMAP4_I2C2_SDA_PULLUPRESX_MASK				(1 << 20)
+#define OMAP4_I2C1_SDA_GLFENB_SHIFT				19
+#define OMAP4_I2C1_SDA_GLFENB_MASK				(1 << 19)
+#define OMAP4_I2C1_SDA_LOAD_BITS_SHIFT				17
+#define OMAP4_I2C1_SDA_LOAD_BITS_MASK				(0x3 << 17)
+#define OMAP4_I2C1_SDA_PULLUPRESX_SHIFT				16
+#define OMAP4_I2C1_SDA_PULLUPRESX_MASK				(1 << 16)
+#define OMAP4_I2C4_SCL_GLFENB_SHIFT				15
+#define OMAP4_I2C4_SCL_GLFENB_MASK				(1 << 15)
+#define OMAP4_I2C4_SCL_LOAD_BITS_SHIFT				13
+#define OMAP4_I2C4_SCL_LOAD_BITS_MASK				(0x3 << 13)
+#define OMAP4_I2C4_SCL_PULLUPRESX_SHIFT				12
+#define OMAP4_I2C4_SCL_PULLUPRESX_MASK				(1 << 12)
+#define OMAP4_I2C3_SCL_GLFENB_SHIFT				11
+#define OMAP4_I2C3_SCL_GLFENB_MASK				(1 << 11)
+#define OMAP4_I2C3_SCL_LOAD_BITS_SHIFT				9
+#define OMAP4_I2C3_SCL_LOAD_BITS_MASK				(0x3 << 9)
+#define OMAP4_I2C3_SCL_PULLUPRESX_SHIFT				8
+#define OMAP4_I2C3_SCL_PULLUPRESX_MASK				(1 << 8)
+#define OMAP4_I2C2_SCL_GLFENB_SHIFT				7
+#define OMAP4_I2C2_SCL_GLFENB_MASK				(1 << 7)
+#define OMAP4_I2C2_SCL_LOAD_BITS_SHIFT				5
+#define OMAP4_I2C2_SCL_LOAD_BITS_MASK				(0x3 << 5)
+#define OMAP4_I2C2_SCL_PULLUPRESX_SHIFT				4
+#define OMAP4_I2C2_SCL_PULLUPRESX_MASK				(1 << 4)
+#define OMAP4_I2C1_SCL_GLFENB_SHIFT				3
+#define OMAP4_I2C1_SCL_GLFENB_MASK				(1 << 3)
+#define OMAP4_I2C1_SCL_LOAD_BITS_SHIFT				1
+#define OMAP4_I2C1_SCL_LOAD_BITS_MASK				(0x3 << 1)
+#define OMAP4_I2C1_SCL_PULLUPRESX_SHIFT				0
+#define OMAP4_I2C1_SCL_PULLUPRESX_MASK				(1 << 0)
+
+/* CONTROL_CAMERA_RX */
+#define OMAP4_CAMERARX_UNIPRO_CTRLCLKEN_SHIFT			31
+#define OMAP4_CAMERARX_UNIPRO_CTRLCLKEN_MASK			(1 << 31)
+#define OMAP4_CAMERARX_CSI22_LANEENABLE_SHIFT			29
+#define OMAP4_CAMERARX_CSI22_LANEENABLE_MASK			(0x3 << 29)
+#define OMAP4_CAMERARX_CSI21_LANEENABLE_SHIFT			24
+#define OMAP4_CAMERARX_CSI21_LANEENABLE_MASK			(0x1f << 24)
+#define OMAP4_CAMERARX_UNIPRO_CAMMODE_SHIFT			22
+#define OMAP4_CAMERARX_UNIPRO_CAMMODE_MASK			(0x3 << 22)
+#define OMAP4_CAMERARX_CSI22_CTRLCLKEN_SHIFT			21
+#define OMAP4_CAMERARX_CSI22_CTRLCLKEN_MASK			(1 << 21)
+#define OMAP4_CAMERARX_CSI22_CAMMODE_SHIFT			19
+#define OMAP4_CAMERARX_CSI22_CAMMODE_MASK			(0x3 << 19)
+#define OMAP4_CAMERARX_CSI21_CTRLCLKEN_SHIFT			18
+#define OMAP4_CAMERARX_CSI21_CTRLCLKEN_MASK			(1 << 18)
+#define OMAP4_CAMERARX_CSI21_CAMMODE_SHIFT			16
+#define OMAP4_CAMERARX_CSI21_CAMMODE_MASK			(0x3 << 16)
+
+/* CONTROL_AVDAC */
+#define OMAP4_AVDAC_ACEN_SHIFT					31
+#define OMAP4_AVDAC_ACEN_MASK					(1 << 31)
+#define OMAP4_AVDAC_TVOUTBYPASS_SHIFT				30
+#define OMAP4_AVDAC_TVOUTBYPASS_MASK				(1 << 30)
+#define OMAP4_AVDAC_INPUTINV_SHIFT				29
+#define OMAP4_AVDAC_INPUTINV_MASK				(1 << 29)
+#define OMAP4_AVDAC_CTL_SHIFT					13
+#define OMAP4_AVDAC_CTL_MASK					(0xffff << 13)
+#define OMAP4_AVDAC_CTL_WR_ACK_SHIFT				12
+#define OMAP4_AVDAC_CTL_WR_ACK_MASK				(1 << 12)
+
+/* CONTROL_HDMI_TX_PHY */
+#define OMAP4_HDMITXPHY_PADORDER_SHIFT				31
+#define OMAP4_HDMITXPHY_PADORDER_MASK				(1 << 31)
+#define OMAP4_HDMITXPHY_TXVALID_SHIFT				30
+#define OMAP4_HDMITXPHY_TXVALID_MASK				(1 << 30)
+#define OMAP4_HDMITXPHY_ENBYPASSCLK_SHIFT			29
+#define OMAP4_HDMITXPHY_ENBYPASSCLK_MASK			(1 << 29)
+#define OMAP4_HDMITXPHY_PD_PULLUPDET_SHIFT			28
+#define OMAP4_HDMITXPHY_PD_PULLUPDET_MASK			(1 << 28)
+
+/* CONTROL_MMC2 */
+#define OMAP4_MMC2_FEEDBACK_CLK_SEL_SHIFT			31
+#define OMAP4_MMC2_FEEDBACK_CLK_SEL_MASK			(1 << 31)
+
+/* CONTROL_DSIPHY */
+#define OMAP4_DSI2_LANEENABLE_SHIFT				29
+#define OMAP4_DSI2_LANEENABLE_MASK				(0x7 << 29)
+#define OMAP4_DSI1_LANEENABLE_SHIFT				24
+#define OMAP4_DSI1_LANEENABLE_MASK				(0x1f << 24)
+#define OMAP4_DSI1_PIPD_SHIFT					19
+#define OMAP4_DSI1_PIPD_MASK					(0x1f << 19)
+#define OMAP4_DSI2_PIPD_SHIFT					14
+#define OMAP4_DSI2_PIPD_MASK					(0x1f << 14)
+
+/* CONTROL_MCBSPLP */
+#define OMAP4_ALBCTRLRX_FSX_SHIFT				31
+#define OMAP4_ALBCTRLRX_FSX_MASK				(1 << 31)
+#define OMAP4_ALBCTRLRX_CLKX_SHIFT				30
+#define OMAP4_ALBCTRLRX_CLKX_MASK				(1 << 30)
+#define OMAP4_ABE_MCBSP1_DR_EN_SHIFT				29
+#define OMAP4_ABE_MCBSP1_DR_EN_MASK				(1 << 29)
+
+/* CONTROL_USB2PHYCORE */
+#define OMAP4_USB2PHY_AUTORESUME_EN_SHIFT			31
+#define OMAP4_USB2PHY_AUTORESUME_EN_MASK			(1 << 31)
+#define OMAP4_USB2PHY_DISCHGDET_SHIFT				30
+#define OMAP4_USB2PHY_DISCHGDET_MASK				(1 << 30)
+#define OMAP4_USB2PHY_GPIOMODE_SHIFT				29
+#define OMAP4_USB2PHY_GPIOMODE_MASK				(1 << 29)
+#define OMAP4_USB2PHY_CHG_DET_EXT_CTL_SHIFT			28
+#define OMAP4_USB2PHY_CHG_DET_EXT_CTL_MASK			(1 << 28)
+#define OMAP4_USB2PHY_RDM_PD_CHGDET_EN_SHIFT			27
+#define OMAP4_USB2PHY_RDM_PD_CHGDET_EN_MASK			(1 << 27)
+#define OMAP4_USB2PHY_RDP_PU_CHGDET_EN_SHIFT			26
+#define OMAP4_USB2PHY_RDP_PU_CHGDET_EN_MASK			(1 << 26)
+#define OMAP4_USB2PHY_CHG_VSRC_EN_SHIFT				25
+#define OMAP4_USB2PHY_CHG_VSRC_EN_MASK				(1 << 25)
+#define OMAP4_USB2PHY_CHG_ISINK_EN_SHIFT			24
+#define OMAP4_USB2PHY_CHG_ISINK_EN_MASK				(1 << 24)
+#define OMAP4_USB2PHY_CHG_DET_STATUS_SHIFT			21
+#define OMAP4_USB2PHY_CHG_DET_STATUS_MASK			(0x7 << 21)
+#define OMAP4_USB2PHY_CHG_DET_DM_COMP_SHIFT			20
+#define OMAP4_USB2PHY_CHG_DET_DM_COMP_MASK			(1 << 20)
+#define OMAP4_USB2PHY_CHG_DET_DP_COMP_SHIFT			19
+#define OMAP4_USB2PHY_CHG_DET_DP_COMP_MASK			(1 << 19)
+#define OMAP4_USB2PHY_DATADET_SHIFT				18
+#define OMAP4_USB2PHY_DATADET_MASK				(1 << 18)
+#define OMAP4_USB2PHY_SINKONDP_SHIFT				17
+#define OMAP4_USB2PHY_SINKONDP_MASK				(1 << 17)
+#define OMAP4_USB2PHY_SRCONDM_SHIFT				16
+#define OMAP4_USB2PHY_SRCONDM_MASK				(1 << 16)
+#define OMAP4_USB2PHY_RESTARTCHGDET_SHIFT			15
+#define OMAP4_USB2PHY_RESTARTCHGDET_MASK			(1 << 15)
+#define OMAP4_USB2PHY_CHGDETDONE_SHIFT				14
+#define OMAP4_USB2PHY_CHGDETDONE_MASK				(1 << 14)
+#define OMAP4_USB2PHY_CHGDETECTED_SHIFT				13
+#define OMAP4_USB2PHY_CHGDETECTED_MASK				(1 << 13)
+#define OMAP4_USB2PHY_MCPCPUEN_SHIFT				12
+#define OMAP4_USB2PHY_MCPCPUEN_MASK				(1 << 12)
+#define OMAP4_USB2PHY_MCPCMODEEN_SHIFT				11
+#define OMAP4_USB2PHY_MCPCMODEEN_MASK				(1 << 11)
+#define OMAP4_USB2PHY_RESETDONEMCLK_SHIFT			10
+#define OMAP4_USB2PHY_RESETDONEMCLK_MASK			(1 << 10)
+#define OMAP4_USB2PHY_UTMIRESETDONE_SHIFT			9
+#define OMAP4_USB2PHY_UTMIRESETDONE_MASK			(1 << 9)
+#define OMAP4_USB2PHY_TXBITSTUFFENABLE_SHIFT			8
+#define OMAP4_USB2PHY_TXBITSTUFFENABLE_MASK			(1 << 8)
+#define OMAP4_USB2PHY_DATAPOLARITYN_SHIFT			7
+#define OMAP4_USB2PHY_DATAPOLARITYN_MASK			(1 << 7)
+#define OMAP4_USBDPLL_FREQLOCK_SHIFT				6
+#define OMAP4_USBDPLL_FREQLOCK_MASK				(1 << 6)
+#define OMAP4_USB2PHY_RESETDONETCLK_SHIFT			5
+#define OMAP4_USB2PHY_RESETDONETCLK_MASK			(1 << 5)
+
+/* CONTROL_I2C_1 */
+#define OMAP4_HDMI_DDC_SDA_GLFENB_SHIFT				31
+#define OMAP4_HDMI_DDC_SDA_GLFENB_MASK				(1 << 31)
+#define OMAP4_HDMI_DDC_SDA_LOAD_BITS_SHIFT			29
+#define OMAP4_HDMI_DDC_SDA_LOAD_BITS_MASK			(0x3 << 29)
+#define OMAP4_HDMI_DDC_SDA_PULLUPRESX_SHIFT			28
+#define OMAP4_HDMI_DDC_SDA_PULLUPRESX_MASK			(1 << 28)
+#define OMAP4_HDMI_DDC_SCL_GLFENB_SHIFT				27
+#define OMAP4_HDMI_DDC_SCL_GLFENB_MASK				(1 << 27)
+#define OMAP4_HDMI_DDC_SCL_LOAD_BITS_SHIFT			25
+#define OMAP4_HDMI_DDC_SCL_LOAD_BITS_MASK			(0x3 << 25)
+#define OMAP4_HDMI_DDC_SCL_PULLUPRESX_SHIFT			24
+#define OMAP4_HDMI_DDC_SCL_PULLUPRESX_MASK			(1 << 24)
+#define OMAP4_HDMI_DDC_SDA_HSMODE_SHIFT				23
+#define OMAP4_HDMI_DDC_SDA_HSMODE_MASK				(1 << 23)
+#define OMAP4_HDMI_DDC_SDA_NMODE_SHIFT				22
+#define OMAP4_HDMI_DDC_SDA_NMODE_MASK				(1 << 22)
+#define OMAP4_HDMI_DDC_SCL_HSMODE_SHIFT				21
+#define OMAP4_HDMI_DDC_SCL_HSMODE_MASK				(1 << 21)
+#define OMAP4_HDMI_DDC_SCL_NMODE_SHIFT				20
+#define OMAP4_HDMI_DDC_SCL_NMODE_MASK				(1 << 20)
+
+/* CONTROL_MMC1 */
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP0_SHIFT			31
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP0_MASK			(1 << 31)
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP1_SHIFT			30
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP1_MASK			(1 << 30)
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP2_SHIFT			29
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP2_MASK			(1 << 29)
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP3_SHIFT			28
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP3_MASK			(1 << 28)
+#define OMAP4_SDMMC1_DR0_SPEEDCTRL_SHIFT			27
+#define OMAP4_SDMMC1_DR0_SPEEDCTRL_MASK				(1 << 27)
+#define OMAP4_SDMMC1_DR1_SPEEDCTRL_SHIFT			26
+#define OMAP4_SDMMC1_DR1_SPEEDCTRL_MASK				(1 << 26)
+#define OMAP4_SDMMC1_DR2_SPEEDCTRL_SHIFT			25
+#define OMAP4_SDMMC1_DR2_SPEEDCTRL_MASK				(1 << 25)
+#define OMAP4_USBC1_DR0_SPEEDCTRL_SHIFT				24
+#define OMAP4_USBC1_DR0_SPEEDCTRL_MASK				(1 << 24)
+#define OMAP4_USB_FD_CDEN_SHIFT					23
+#define OMAP4_USB_FD_CDEN_MASK					(1 << 23)
+#define OMAP4_USBC1_ICUSB_DP_PDDIS_SHIFT			22
+#define OMAP4_USBC1_ICUSB_DP_PDDIS_MASK				(1 << 22)
+#define OMAP4_USBC1_ICUSB_DM_PDDIS_SHIFT			21
+#define OMAP4_USBC1_ICUSB_DM_PDDIS_MASK				(1 << 21)
+
+/* CONTROL_HSI */
+#define OMAP4_HSI1_CALLOOP_SEL_SHIFT				31
+#define OMAP4_HSI1_CALLOOP_SEL_MASK				(1 << 31)
+#define OMAP4_HSI1_CALMUX_SEL_SHIFT				30
+#define OMAP4_HSI1_CALMUX_SEL_MASK				(1 << 30)
+#define OMAP4_HSI2_CALLOOP_SEL_SHIFT				29
+#define OMAP4_HSI2_CALLOOP_SEL_MASK				(1 << 29)
+#define OMAP4_HSI2_CALMUX_SEL_SHIFT				28
+#define OMAP4_HSI2_CALMUX_SEL_MASK				(1 << 28)
+
+/* CONTROL_USB */
+#define OMAP4_CARKIT_USBA0_ULPIPHY_DAT0_AUTO_EN_SHIFT		31
+#define OMAP4_CARKIT_USBA0_ULPIPHY_DAT0_AUTO_EN_MASK		(1 << 31)
+#define OMAP4_CARKIT_USBA0_ULPIPHY_DAT1_AUTO_EN_SHIFT		30
+#define OMAP4_CARKIT_USBA0_ULPIPHY_DAT1_AUTO_EN_MASK		(1 << 30)
+
+/* CONTROL_HDQ */
+#define OMAP4_HDQ_SIO_PWRDNZ_SHIFT				31
+#define OMAP4_HDQ_SIO_PWRDNZ_MASK				(1 << 31)
+
+/* CONTROL_LPDDR2IO1_0 */
+#define OMAP4_LPDDR2IO1_GR4_SR_SHIFT				30
+#define OMAP4_LPDDR2IO1_GR4_SR_MASK				(0x3 << 30)
+#define OMAP4_LPDDR2IO1_GR4_I_SHIFT				27
+#define OMAP4_LPDDR2IO1_GR4_I_MASK				(0x7 << 27)
+#define OMAP4_LPDDR2IO1_GR4_WD_SHIFT				25
+#define OMAP4_LPDDR2IO1_GR4_WD_MASK				(0x3 << 25)
+#define OMAP4_LPDDR2IO1_GR3_SR_SHIFT				22
+#define OMAP4_LPDDR2IO1_GR3_SR_MASK				(0x3 << 22)
+#define OMAP4_LPDDR2IO1_GR3_I_SHIFT				19
+#define OMAP4_LPDDR2IO1_GR3_I_MASK				(0x7 << 19)
+#define OMAP4_LPDDR2IO1_GR3_WD_SHIFT				17
+#define OMAP4_LPDDR2IO1_GR3_WD_MASK				(0x3 << 17)
+#define OMAP4_LPDDR2IO1_GR2_SR_SHIFT				14
+#define OMAP4_LPDDR2IO1_GR2_SR_MASK				(0x3 << 14)
+#define OMAP4_LPDDR2IO1_GR2_I_SHIFT				11
+#define OMAP4_LPDDR2IO1_GR2_I_MASK				(0x7 << 11)
+#define OMAP4_LPDDR2IO1_GR2_WD_SHIFT				9
+#define OMAP4_LPDDR2IO1_GR2_WD_MASK				(0x3 << 9)
+#define OMAP4_LPDDR2IO1_GR1_SR_SHIFT				6
+#define OMAP4_LPDDR2IO1_GR1_SR_MASK				(0x3 << 6)
+#define OMAP4_LPDDR2IO1_GR1_I_SHIFT				3
+#define OMAP4_LPDDR2IO1_GR1_I_MASK				(0x7 << 3)
+#define OMAP4_LPDDR2IO1_GR1_WD_SHIFT				1
+#define OMAP4_LPDDR2IO1_GR1_WD_MASK				(0x3 << 1)
+
+/* CONTROL_LPDDR2IO1_1 */
+#define OMAP4_LPDDR2IO1_GR8_SR_SHIFT				30
+#define OMAP4_LPDDR2IO1_GR8_SR_MASK				(0x3 << 30)
+#define OMAP4_LPDDR2IO1_GR8_I_SHIFT				27
+#define OMAP4_LPDDR2IO1_GR8_I_MASK				(0x7 << 27)
+#define OMAP4_LPDDR2IO1_GR8_WD_SHIFT				25
+#define OMAP4_LPDDR2IO1_GR8_WD_MASK				(0x3 << 25)
+#define OMAP4_LPDDR2IO1_GR7_SR_SHIFT				22
+#define OMAP4_LPDDR2IO1_GR7_SR_MASK				(0x3 << 22)
+#define OMAP4_LPDDR2IO1_GR7_I_SHIFT				19
+#define OMAP4_LPDDR2IO1_GR7_I_MASK				(0x7 << 19)
+#define OMAP4_LPDDR2IO1_GR7_WD_SHIFT				17
+#define OMAP4_LPDDR2IO1_GR7_WD_MASK				(0x3 << 17)
+#define OMAP4_LPDDR2IO1_GR6_SR_SHIFT				14
+#define OMAP4_LPDDR2IO1_GR6_SR_MASK				(0x3 << 14)
+#define OMAP4_LPDDR2IO1_GR6_I_SHIFT				11
+#define OMAP4_LPDDR2IO1_GR6_I_MASK				(0x7 << 11)
+#define OMAP4_LPDDR2IO1_GR6_WD_SHIFT				9
+#define OMAP4_LPDDR2IO1_GR6_WD_MASK				(0x3 << 9)
+#define OMAP4_LPDDR2IO1_GR5_SR_SHIFT				6
+#define OMAP4_LPDDR2IO1_GR5_SR_MASK				(0x3 << 6)
+#define OMAP4_LPDDR2IO1_GR5_I_SHIFT				3
+#define OMAP4_LPDDR2IO1_GR5_I_MASK				(0x7 << 3)
+#define OMAP4_LPDDR2IO1_GR5_WD_SHIFT				1
+#define OMAP4_LPDDR2IO1_GR5_WD_MASK				(0x3 << 1)
+
+/* CONTROL_LPDDR2IO1_2 */
+#define OMAP4_LPDDR2IO1_GR11_SR_SHIFT				30
+#define OMAP4_LPDDR2IO1_GR11_SR_MASK				(0x3 << 30)
+#define OMAP4_LPDDR2IO1_GR11_I_SHIFT				27
+#define OMAP4_LPDDR2IO1_GR11_I_MASK				(0x7 << 27)
+#define OMAP4_LPDDR2IO1_GR11_WD_SHIFT				25
+#define OMAP4_LPDDR2IO1_GR11_WD_MASK				(0x3 << 25)
+#define OMAP4_LPDDR2IO1_GR10_SR_SHIFT				22
+#define OMAP4_LPDDR2IO1_GR10_SR_MASK				(0x3 << 22)
+#define OMAP4_LPDDR2IO1_GR10_I_SHIFT				19
+#define OMAP4_LPDDR2IO1_GR10_I_MASK				(0x7 << 19)
+#define OMAP4_LPDDR2IO1_GR10_WD_SHIFT				17
+#define OMAP4_LPDDR2IO1_GR10_WD_MASK				(0x3 << 17)
+#define OMAP4_LPDDR2IO1_GR9_SR_SHIFT				14
+#define OMAP4_LPDDR2IO1_GR9_SR_MASK				(0x3 << 14)
+#define OMAP4_LPDDR2IO1_GR9_I_SHIFT				11
+#define OMAP4_LPDDR2IO1_GR9_I_MASK				(0x7 << 11)
+#define OMAP4_LPDDR2IO1_GR9_WD_SHIFT				9
+#define OMAP4_LPDDR2IO1_GR9_WD_MASK				(0x3 << 9)
+
+/* CONTROL_LPDDR2IO1_3 */
+#define OMAP4_LPDDR21_VREF_CA_CCAP0_SHIFT			31
+#define OMAP4_LPDDR21_VREF_CA_CCAP0_MASK			(1 << 31)
+#define OMAP4_LPDDR21_VREF_CA_CCAP1_SHIFT			30
+#define OMAP4_LPDDR21_VREF_CA_CCAP1_MASK			(1 << 30)
+#define OMAP4_LPDDR21_VREF_CA_INT_CCAP0_SHIFT			29
+#define OMAP4_LPDDR21_VREF_CA_INT_CCAP0_MASK			(1 << 29)
+#define OMAP4_LPDDR21_VREF_CA_INT_CCAP1_SHIFT			28
+#define OMAP4_LPDDR21_VREF_CA_INT_CCAP1_MASK			(1 << 28)
+#define OMAP4_LPDDR21_VREF_CA_INT_TAP0_SHIFT			27
+#define OMAP4_LPDDR21_VREF_CA_INT_TAP0_MASK			(1 << 27)
+#define OMAP4_LPDDR21_VREF_CA_INT_TAP1_SHIFT			26
+#define OMAP4_LPDDR21_VREF_CA_INT_TAP1_MASK			(1 << 26)
+#define OMAP4_LPDDR21_VREF_CA_TAP0_SHIFT			25
+#define OMAP4_LPDDR21_VREF_CA_TAP0_MASK				(1 << 25)
+#define OMAP4_LPDDR21_VREF_CA_TAP1_SHIFT			24
+#define OMAP4_LPDDR21_VREF_CA_TAP1_MASK				(1 << 24)
+#define OMAP4_LPDDR21_VREF_DQ0_INT_CCAP0_SHIFT			23
+#define OMAP4_LPDDR21_VREF_DQ0_INT_CCAP0_MASK			(1 << 23)
+#define OMAP4_LPDDR21_VREF_DQ0_INT_CCAP1_SHIFT			22
+#define OMAP4_LPDDR21_VREF_DQ0_INT_CCAP1_MASK			(1 << 22)
+#define OMAP4_LPDDR21_VREF_DQ0_INT_TAP0_SHIFT			21
+#define OMAP4_LPDDR21_VREF_DQ0_INT_TAP0_MASK			(1 << 21)
+#define OMAP4_LPDDR21_VREF_DQ0_INT_TAP1_SHIFT			20
+#define OMAP4_LPDDR21_VREF_DQ0_INT_TAP1_MASK			(1 << 20)
+#define OMAP4_LPDDR21_VREF_DQ1_INT_CCAP0_SHIFT			19
+#define OMAP4_LPDDR21_VREF_DQ1_INT_CCAP0_MASK			(1 << 19)
+#define OMAP4_LPDDR21_VREF_DQ1_INT_CCAP1_SHIFT			18
+#define OMAP4_LPDDR21_VREF_DQ1_INT_CCAP1_MASK			(1 << 18)
+#define OMAP4_LPDDR21_VREF_DQ1_INT_TAP0_SHIFT			17
+#define OMAP4_LPDDR21_VREF_DQ1_INT_TAP0_MASK			(1 << 17)
+#define OMAP4_LPDDR21_VREF_DQ1_INT_TAP1_SHIFT			16
+#define OMAP4_LPDDR21_VREF_DQ1_INT_TAP1_MASK			(1 << 16)
+#define OMAP4_LPDDR21_VREF_DQ_CCAP0_SHIFT			15
+#define OMAP4_LPDDR21_VREF_DQ_CCAP0_MASK			(1 << 15)
+#define OMAP4_LPDDR21_VREF_DQ_CCAP1_SHIFT			14
+#define OMAP4_LPDDR21_VREF_DQ_CCAP1_MASK			(1 << 14)
+#define OMAP4_LPDDR21_VREF_DQ_TAP0_SHIFT			13
+#define OMAP4_LPDDR21_VREF_DQ_TAP0_MASK				(1 << 13)
+#define OMAP4_LPDDR21_VREF_DQ_TAP1_SHIFT			12
+#define OMAP4_LPDDR21_VREF_DQ_TAP1_MASK				(1 << 12)
+
+/* CONTROL_LPDDR2IO2_0 */
+#define OMAP4_LPDDR2IO2_GR4_SR_SHIFT				30
+#define OMAP4_LPDDR2IO2_GR4_SR_MASK				(0x3 << 30)
+#define OMAP4_LPDDR2IO2_GR4_I_SHIFT				27
+#define OMAP4_LPDDR2IO2_GR4_I_MASK				(0x7 << 27)
+#define OMAP4_LPDDR2IO2_GR4_WD_SHIFT				25
+#define OMAP4_LPDDR2IO2_GR4_WD_MASK				(0x3 << 25)
+#define OMAP4_LPDDR2IO2_GR3_SR_SHIFT				22
+#define OMAP4_LPDDR2IO2_GR3_SR_MASK				(0x3 << 22)
+#define OMAP4_LPDDR2IO2_GR3_I_SHIFT				19
+#define OMAP4_LPDDR2IO2_GR3_I_MASK				(0x7 << 19)
+#define OMAP4_LPDDR2IO2_GR3_WD_SHIFT				17
+#define OMAP4_LPDDR2IO2_GR3_WD_MASK				(0x3 << 17)
+#define OMAP4_LPDDR2IO2_GR2_SR_SHIFT				14
+#define OMAP4_LPDDR2IO2_GR2_SR_MASK				(0x3 << 14)
+#define OMAP4_LPDDR2IO2_GR2_I_SHIFT				11
+#define OMAP4_LPDDR2IO2_GR2_I_MASK				(0x7 << 11)
+#define OMAP4_LPDDR2IO2_GR2_WD_SHIFT				9
+#define OMAP4_LPDDR2IO2_GR2_WD_MASK				(0x3 << 9)
+#define OMAP4_LPDDR2IO2_GR1_SR_SHIFT				6
+#define OMAP4_LPDDR2IO2_GR1_SR_MASK				(0x3 << 6)
+#define OMAP4_LPDDR2IO2_GR1_I_SHIFT				3
+#define OMAP4_LPDDR2IO2_GR1_I_MASK				(0x7 << 3)
+#define OMAP4_LPDDR2IO2_GR1_WD_SHIFT				1
+#define OMAP4_LPDDR2IO2_GR1_WD_MASK				(0x3 << 1)
+
+/* CONTROL_LPDDR2IO2_1 */
+#define OMAP4_LPDDR2IO2_GR8_SR_SHIFT				30
+#define OMAP4_LPDDR2IO2_GR8_SR_MASK				(0x3 << 30)
+#define OMAP4_LPDDR2IO2_GR8_I_SHIFT				27
+#define OMAP4_LPDDR2IO2_GR8_I_MASK				(0x7 << 27)
+#define OMAP4_LPDDR2IO2_GR8_WD_SHIFT				25
+#define OMAP4_LPDDR2IO2_GR8_WD_MASK				(0x3 << 25)
+#define OMAP4_LPDDR2IO2_GR7_SR_SHIFT				22
+#define OMAP4_LPDDR2IO2_GR7_SR_MASK				(0x3 << 22)
+#define OMAP4_LPDDR2IO2_GR7_I_SHIFT				19
+#define OMAP4_LPDDR2IO2_GR7_I_MASK				(0x7 << 19)
+#define OMAP4_LPDDR2IO2_GR7_WD_SHIFT				17
+#define OMAP4_LPDDR2IO2_GR7_WD_MASK				(0x3 << 17)
+#define OMAP4_LPDDR2IO2_GR6_SR_SHIFT				14
+#define OMAP4_LPDDR2IO2_GR6_SR_MASK				(0x3 << 14)
+#define OMAP4_LPDDR2IO2_GR6_I_SHIFT				11
+#define OMAP4_LPDDR2IO2_GR6_I_MASK				(0x7 << 11)
+#define OMAP4_LPDDR2IO2_GR6_WD_SHIFT				9
+#define OMAP4_LPDDR2IO2_GR6_WD_MASK				(0x3 << 9)
+#define OMAP4_LPDDR2IO2_GR5_SR_SHIFT				6
+#define OMAP4_LPDDR2IO2_GR5_SR_MASK				(0x3 << 6)
+#define OMAP4_LPDDR2IO2_GR5_I_SHIFT				3
+#define OMAP4_LPDDR2IO2_GR5_I_MASK				(0x7 << 3)
+#define OMAP4_LPDDR2IO2_GR5_WD_SHIFT				1
+#define OMAP4_LPDDR2IO2_GR5_WD_MASK				(0x3 << 1)
+
+/* CONTROL_LPDDR2IO2_2 */
+#define OMAP4_LPDDR2IO2_GR11_SR_SHIFT				30
+#define OMAP4_LPDDR2IO2_GR11_SR_MASK				(0x3 << 30)
+#define OMAP4_LPDDR2IO2_GR11_I_SHIFT				27
+#define OMAP4_LPDDR2IO2_GR11_I_MASK				(0x7 << 27)
+#define OMAP4_LPDDR2IO2_GR11_WD_SHIFT				25
+#define OMAP4_LPDDR2IO2_GR11_WD_MASK				(0x3 << 25)
+#define OMAP4_LPDDR2IO2_GR10_SR_SHIFT				22
+#define OMAP4_LPDDR2IO2_GR10_SR_MASK				(0x3 << 22)
+#define OMAP4_LPDDR2IO2_GR10_I_SHIFT				19
+#define OMAP4_LPDDR2IO2_GR10_I_MASK				(0x7 << 19)
+#define OMAP4_LPDDR2IO2_GR10_WD_SHIFT				17
+#define OMAP4_LPDDR2IO2_GR10_WD_MASK				(0x3 << 17)
+#define OMAP4_LPDDR2IO2_GR9_SR_SHIFT				14
+#define OMAP4_LPDDR2IO2_GR9_SR_MASK				(0x3 << 14)
+#define OMAP4_LPDDR2IO2_GR9_I_SHIFT				11
+#define OMAP4_LPDDR2IO2_GR9_I_MASK				(0x7 << 11)
+#define OMAP4_LPDDR2IO2_GR9_WD_SHIFT				9
+#define OMAP4_LPDDR2IO2_GR9_WD_MASK				(0x3 << 9)
+
+/* CONTROL_LPDDR2IO2_3 */
+#define OMAP4_LPDDR22_VREF_CA_CCAP0_SHIFT			31
+#define OMAP4_LPDDR22_VREF_CA_CCAP0_MASK			(1 << 31)
+#define OMAP4_LPDDR22_VREF_CA_CCAP1_SHIFT			30
+#define OMAP4_LPDDR22_VREF_CA_CCAP1_MASK			(1 << 30)
+#define OMAP4_LPDDR22_VREF_CA_INT_CCAP0_SHIFT			29
+#define OMAP4_LPDDR22_VREF_CA_INT_CCAP0_MASK			(1 << 29)
+#define OMAP4_LPDDR22_VREF_CA_INT_CCAP1_SHIFT			28
+#define OMAP4_LPDDR22_VREF_CA_INT_CCAP1_MASK			(1 << 28)
+#define OMAP4_LPDDR22_VREF_CA_INT_TAP0_SHIFT			27
+#define OMAP4_LPDDR22_VREF_CA_INT_TAP0_MASK			(1 << 27)
+#define OMAP4_LPDDR22_VREF_CA_INT_TAP1_SHIFT			26
+#define OMAP4_LPDDR22_VREF_CA_INT_TAP1_MASK			(1 << 26)
+#define OMAP4_LPDDR22_VREF_CA_TAP0_SHIFT			25
+#define OMAP4_LPDDR22_VREF_CA_TAP0_MASK				(1 << 25)
+#define OMAP4_LPDDR22_VREF_CA_TAP1_SHIFT			24
+#define OMAP4_LPDDR22_VREF_CA_TAP1_MASK				(1 << 24)
+#define OMAP4_LPDDR22_VREF_DQ0_INT_CCAP0_SHIFT			23
+#define OMAP4_LPDDR22_VREF_DQ0_INT_CCAP0_MASK			(1 << 23)
+#define OMAP4_LPDDR22_VREF_DQ0_INT_CCAP1_SHIFT			22
+#define OMAP4_LPDDR22_VREF_DQ0_INT_CCAP1_MASK			(1 << 22)
+#define OMAP4_LPDDR22_VREF_DQ0_INT_TAP0_SHIFT			21
+#define OMAP4_LPDDR22_VREF_DQ0_INT_TAP0_MASK			(1 << 21)
+#define OMAP4_LPDDR22_VREF_DQ0_INT_TAP1_SHIFT			20
+#define OMAP4_LPDDR22_VREF_DQ0_INT_TAP1_MASK			(1 << 20)
+#define OMAP4_LPDDR22_VREF_DQ1_INT_CCAP0_SHIFT			19
+#define OMAP4_LPDDR22_VREF_DQ1_INT_CCAP0_MASK			(1 << 19)
+#define OMAP4_LPDDR22_VREF_DQ1_INT_CCAP1_SHIFT			18
+#define OMAP4_LPDDR22_VREF_DQ1_INT_CCAP1_MASK			(1 << 18)
+#define OMAP4_LPDDR22_VREF_DQ1_INT_TAP0_SHIFT			17
+#define OMAP4_LPDDR22_VREF_DQ1_INT_TAP0_MASK			(1 << 17)
+#define OMAP4_LPDDR22_VREF_DQ1_INT_TAP1_SHIFT			16
+#define OMAP4_LPDDR22_VREF_DQ1_INT_TAP1_MASK			(1 << 16)
+#define OMAP4_LPDDR22_VREF_DQ_CCAP0_SHIFT			15
+#define OMAP4_LPDDR22_VREF_DQ_CCAP0_MASK			(1 << 15)
+#define OMAP4_LPDDR22_VREF_DQ_CCAP1_SHIFT			14
+#define OMAP4_LPDDR22_VREF_DQ_CCAP1_MASK			(1 << 14)
+#define OMAP4_LPDDR22_VREF_DQ_TAP0_SHIFT			13
+#define OMAP4_LPDDR22_VREF_DQ_TAP0_MASK				(1 << 13)
+#define OMAP4_LPDDR22_VREF_DQ_TAP1_SHIFT			12
+#define OMAP4_LPDDR22_VREF_DQ_TAP1_MASK				(1 << 12)
+
+/* CONTROL_BUS_HOLD */
+#define OMAP4_ABE_DMIC_DIN3_EN_SHIFT				31
+#define OMAP4_ABE_DMIC_DIN3_EN_MASK				(1 << 31)
+#define OMAP4_MCSPI1_CS3_EN_SHIFT				30
+#define OMAP4_MCSPI1_CS3_EN_MASK				(1 << 30)
+
+/* CONTROL_C2C */
+#define OMAP4_MIRROR_MODE_EN_SHIFT				31
+#define OMAP4_MIRROR_MODE_EN_MASK				(1 << 31)
+#define OMAP4_C2C_SPARE_SHIFT					24
+#define OMAP4_C2C_SPARE_MASK					(0x7f << 24)
+
+/* CORE_CONTROL_SPARE_RW */
+#define OMAP4_CORE_CONTROL_SPARE_RW_SHIFT			0
+#define OMAP4_CORE_CONTROL_SPARE_RW_MASK			(0xffffffff << 0)
+
+/* CORE_CONTROL_SPARE_R */
+#define OMAP4_CORE_CONTROL_SPARE_R_SHIFT			0
+#define OMAP4_CORE_CONTROL_SPARE_R_MASK				(0xffffffff << 0)
+
+/* CORE_CONTROL_SPARE_R_C0 */
+#define OMAP4_CORE_CONTROL_SPARE_R_C0_SHIFT			31
+#define OMAP4_CORE_CONTROL_SPARE_R_C0_MASK			(1 << 31)
+#define OMAP4_CORE_CONTROL_SPARE_R_C1_SHIFT			30
+#define OMAP4_CORE_CONTROL_SPARE_R_C1_MASK			(1 << 30)
+#define OMAP4_CORE_CONTROL_SPARE_R_C2_SHIFT			29
+#define OMAP4_CORE_CONTROL_SPARE_R_C2_MASK			(1 << 29)
+#define OMAP4_CORE_CONTROL_SPARE_R_C3_SHIFT			28
+#define OMAP4_CORE_CONTROL_SPARE_R_C3_MASK			(1 << 28)
+#define OMAP4_CORE_CONTROL_SPARE_R_C4_SHIFT			27
+#define OMAP4_CORE_CONTROL_SPARE_R_C4_MASK			(1 << 27)
+#define OMAP4_CORE_CONTROL_SPARE_R_C5_SHIFT			26
+#define OMAP4_CORE_CONTROL_SPARE_R_C5_MASK			(1 << 26)
+#define OMAP4_CORE_CONTROL_SPARE_R_C6_SHIFT			25
+#define OMAP4_CORE_CONTROL_SPARE_R_C6_MASK			(1 << 25)
+#define OMAP4_CORE_CONTROL_SPARE_R_C7_SHIFT			24
+#define OMAP4_CORE_CONTROL_SPARE_R_C7_MASK			(1 << 24)
+
+/* CONTROL_EFUSE_1 */
+#define OMAP4_AVDAC_TRIM_BYTE3_SHIFT				24
+#define OMAP4_AVDAC_TRIM_BYTE3_MASK				(0x7f << 24)
+#define OMAP4_AVDAC_TRIM_BYTE2_SHIFT				16
+#define OMAP4_AVDAC_TRIM_BYTE2_MASK				(0xff << 16)
+#define OMAP4_AVDAC_TRIM_BYTE1_SHIFT				8
+#define OMAP4_AVDAC_TRIM_BYTE1_MASK				(0xff << 8)
+#define OMAP4_AVDAC_TRIM_BYTE0_SHIFT				0
+#define OMAP4_AVDAC_TRIM_BYTE0_MASK				(0xff << 0)
+
+/* CONTROL_EFUSE_2 */
+#define OMAP4_EFUSE_SMART2TEST_P0_SHIFT				31
+#define OMAP4_EFUSE_SMART2TEST_P0_MASK				(1 << 31)
+#define OMAP4_EFUSE_SMART2TEST_P1_SHIFT				30
+#define OMAP4_EFUSE_SMART2TEST_P1_MASK				(1 << 30)
+#define OMAP4_EFUSE_SMART2TEST_P2_SHIFT				29
+#define OMAP4_EFUSE_SMART2TEST_P2_MASK				(1 << 29)
+#define OMAP4_EFUSE_SMART2TEST_P3_SHIFT				28
+#define OMAP4_EFUSE_SMART2TEST_P3_MASK				(1 << 28)
+#define OMAP4_EFUSE_SMART2TEST_N0_SHIFT				27
+#define OMAP4_EFUSE_SMART2TEST_N0_MASK				(1 << 27)
+#define OMAP4_EFUSE_SMART2TEST_N1_SHIFT				26
+#define OMAP4_EFUSE_SMART2TEST_N1_MASK				(1 << 26)
+#define OMAP4_EFUSE_SMART2TEST_N2_SHIFT				25
+#define OMAP4_EFUSE_SMART2TEST_N2_MASK				(1 << 25)
+#define OMAP4_EFUSE_SMART2TEST_N3_SHIFT				24
+#define OMAP4_EFUSE_SMART2TEST_N3_MASK				(1 << 24)
+#define OMAP4_LPDDR2_PTV_N1_SHIFT				23
+#define OMAP4_LPDDR2_PTV_N1_MASK				(1 << 23)
+#define OMAP4_LPDDR2_PTV_N2_SHIFT				22
+#define OMAP4_LPDDR2_PTV_N2_MASK				(1 << 22)
+#define OMAP4_LPDDR2_PTV_N3_SHIFT				21
+#define OMAP4_LPDDR2_PTV_N3_MASK				(1 << 21)
+#define OMAP4_LPDDR2_PTV_N4_SHIFT				20
+#define OMAP4_LPDDR2_PTV_N4_MASK				(1 << 20)
+#define OMAP4_LPDDR2_PTV_N5_SHIFT				19
+#define OMAP4_LPDDR2_PTV_N5_MASK				(1 << 19)
+#define OMAP4_LPDDR2_PTV_P1_SHIFT				18
+#define OMAP4_LPDDR2_PTV_P1_MASK				(1 << 18)
+#define OMAP4_LPDDR2_PTV_P2_SHIFT				17
+#define OMAP4_LPDDR2_PTV_P2_MASK				(1 << 17)
+#define OMAP4_LPDDR2_PTV_P3_SHIFT				16
+#define OMAP4_LPDDR2_PTV_P3_MASK				(1 << 16)
+#define OMAP4_LPDDR2_PTV_P4_SHIFT				15
+#define OMAP4_LPDDR2_PTV_P4_MASK				(1 << 15)
+#define OMAP4_LPDDR2_PTV_P5_SHIFT				14
+#define OMAP4_LPDDR2_PTV_P5_MASK				(1 << 14)
+
+/* CONTROL_EFUSE_3 */
+#define OMAP4_STD_FUSE_SPARE_1_SHIFT				24
+#define OMAP4_STD_FUSE_SPARE_1_MASK				(0xff << 24)
+#define OMAP4_STD_FUSE_SPARE_2_SHIFT				16
+#define OMAP4_STD_FUSE_SPARE_2_MASK				(0xff << 16)
+#define OMAP4_STD_FUSE_SPARE_3_SHIFT				8
+#define OMAP4_STD_FUSE_SPARE_3_MASK				(0xff << 8)
+#define OMAP4_STD_FUSE_SPARE_4_SHIFT				0
+#define OMAP4_STD_FUSE_SPARE_4_MASK				(0xff << 0)
+
+/* CONTROL_EFUSE_4 */
+#define OMAP4_STD_FUSE_SPARE_5_SHIFT				24
+#define OMAP4_STD_FUSE_SPARE_5_MASK				(0xff << 24)
+#define OMAP4_STD_FUSE_SPARE_6_SHIFT				16
+#define OMAP4_STD_FUSE_SPARE_6_MASK				(0xff << 16)
+#define OMAP4_STD_FUSE_SPARE_7_SHIFT				8
+#define OMAP4_STD_FUSE_SPARE_7_MASK				(0xff << 8)
+#define OMAP4_STD_FUSE_SPARE_8_SHIFT				0
+#define OMAP4_STD_FUSE_SPARE_8_MASK				(0xff << 0)
+
+#endif
diff --git a/arch/arm/mach-omap2/include/mach/ctrl_module_pad_wkup_44xx.h b/arch/arm/mach-omap2/include/mach/ctrl_module_pad_wkup_44xx.h
new file mode 100644
index 0000000..17c9b37
--- /dev/null
+++ b/arch/arm/mach-omap2/include/mach/ctrl_module_pad_wkup_44xx.h
@@ -0,0 +1,236 @@
+/*
+ * OMAP44xx CTRL_MODULE_PAD_WKUP registers and bitfields
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * Benoit Cousson (b-cousson@ti.com)
+ * Santosh Shilimkar (santosh.shilimkar@ti.com)
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_PAD_WKUP_44XX_H
+#define __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_PAD_WKUP_44XX_H
+
+
+/* Base address */
+#define OMAP4_CTRL_MODULE_PAD_WKUP					0x4a31e000
+
+/* Registers offset */
+#define OMAP4_CTRL_MODULE_PAD_WKUP_IP_REVISION				0x0000
+#define OMAP4_CTRL_MODULE_PAD_WKUP_IP_HWINFO				0x0004
+#define OMAP4_CTRL_MODULE_PAD_WKUP_IP_SYSCONFIG				0x0010
+#define OMAP4_CTRL_MODULE_PAD_WKUP_PADCONF_WAKEUPEVENT_0		0x007c
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_SMART1NOPMIO_PADCONF_0	0x05a0
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_SMART1NOPMIO_PADCONF_1	0x05a4
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_PADCONF_MODE			0x05a8
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_XTAL_OSCILLATOR		0x05ac
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_USIMIO			0x0600
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_I2C_2			0x0604
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_JTAG				0x0608
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_SYS				0x060c
+#define OMAP4_CTRL_MODULE_PAD_WKUP_WKUP_CONTROL_SPARE_RW		0x0614
+#define OMAP4_CTRL_MODULE_PAD_WKUP_WKUP_CONTROL_SPARE_R			0x0618
+#define OMAP4_CTRL_MODULE_PAD_WKUP_WKUP_CONTROL_SPARE_R_C0		0x061c
+
+/* Registers shifts and masks */
+
+/* IP_REVISION */
+#define OMAP4_IP_REV_SCHEME_SHIFT				30
+#define OMAP4_IP_REV_SCHEME_MASK				(0x3 << 30)
+#define OMAP4_IP_REV_FUNC_SHIFT					16
+#define OMAP4_IP_REV_FUNC_MASK					(0xfff << 16)
+#define OMAP4_IP_REV_RTL_SHIFT					11
+#define OMAP4_IP_REV_RTL_MASK					(0x1f << 11)
+#define OMAP4_IP_REV_MAJOR_SHIFT				8
+#define OMAP4_IP_REV_MAJOR_MASK					(0x7 << 8)
+#define OMAP4_IP_REV_CUSTOM_SHIFT				6
+#define OMAP4_IP_REV_CUSTOM_MASK				(0x3 << 6)
+#define OMAP4_IP_REV_MINOR_SHIFT				0
+#define OMAP4_IP_REV_MINOR_MASK					(0x3f << 0)
+
+/* IP_HWINFO */
+#define OMAP4_IP_HWINFO_SHIFT					0
+#define OMAP4_IP_HWINFO_MASK					(0xffffffff << 0)
+
+/* IP_SYSCONFIG */
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_SHIFT			2
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_MASK			(0x3 << 2)
+
+/* PADCONF_WAKEUPEVENT_0 */
+#define OMAP4_JTAG_TDO_DUPLICATEWAKEUPEVENT_SHIFT		24
+#define OMAP4_JTAG_TDO_DUPLICATEWAKEUPEVENT_MASK		(1 << 24)
+#define OMAP4_JTAG_TDI_DUPLICATEWAKEUPEVENT_SHIFT		23
+#define OMAP4_JTAG_TDI_DUPLICATEWAKEUPEVENT_MASK		(1 << 23)
+#define OMAP4_JTAG_TMS_TMSC_DUPLICATEWAKEUPEVENT_SHIFT		22
+#define OMAP4_JTAG_TMS_TMSC_DUPLICATEWAKEUPEVENT_MASK		(1 << 22)
+#define OMAP4_JTAG_RTCK_DUPLICATEWAKEUPEVENT_SHIFT		21
+#define OMAP4_JTAG_RTCK_DUPLICATEWAKEUPEVENT_MASK		(1 << 21)
+#define OMAP4_JTAG_TCK_DUPLICATEWAKEUPEVENT_SHIFT		20
+#define OMAP4_JTAG_TCK_DUPLICATEWAKEUPEVENT_MASK		(1 << 20)
+#define OMAP4_JTAG_NTRST_DUPLICATEWAKEUPEVENT_SHIFT		19
+#define OMAP4_JTAG_NTRST_DUPLICATEWAKEUPEVENT_MASK		(1 << 19)
+#define OMAP4_SYS_BOOT7_DUPLICATEWAKEUPEVENT_SHIFT		18
+#define OMAP4_SYS_BOOT7_DUPLICATEWAKEUPEVENT_MASK		(1 << 18)
+#define OMAP4_SYS_BOOT6_DUPLICATEWAKEUPEVENT_SHIFT		17
+#define OMAP4_SYS_BOOT6_DUPLICATEWAKEUPEVENT_MASK		(1 << 17)
+#define OMAP4_SYS_PWRON_RESET_OUT_DUPLICATEWAKEUPEVENT_SHIFT	16
+#define OMAP4_SYS_PWRON_RESET_OUT_DUPLICATEWAKEUPEVENT_MASK	(1 << 16)
+#define OMAP4_SYS_PWR_REQ_DUPLICATEWAKEUPEVENT_SHIFT		15
+#define OMAP4_SYS_PWR_REQ_DUPLICATEWAKEUPEVENT_MASK		(1 << 15)
+#define OMAP4_SYS_NRESWARM_DUPLICATEWAKEUPEVENT_SHIFT		14
+#define OMAP4_SYS_NRESWARM_DUPLICATEWAKEUPEVENT_MASK		(1 << 14)
+#define OMAP4_SYS_32K_DUPLICATEWAKEUPEVENT_SHIFT		13
+#define OMAP4_SYS_32K_DUPLICATEWAKEUPEVENT_MASK			(1 << 13)
+#define OMAP4_FREF_CLK4_OUT_DUPLICATEWAKEUPEVENT_SHIFT		12
+#define OMAP4_FREF_CLK4_OUT_DUPLICATEWAKEUPEVENT_MASK		(1 << 12)
+#define OMAP4_FREF_CLK4_REQ_DUPLICATEWAKEUPEVENT_SHIFT		11
+#define OMAP4_FREF_CLK4_REQ_DUPLICATEWAKEUPEVENT_MASK		(1 << 11)
+#define OMAP4_FREF_CLK3_OUT_DUPLICATEWAKEUPEVENT_SHIFT		10
+#define OMAP4_FREF_CLK3_OUT_DUPLICATEWAKEUPEVENT_MASK		(1 << 10)
+#define OMAP4_FREF_CLK3_REQ_DUPLICATEWAKEUPEVENT_SHIFT		9
+#define OMAP4_FREF_CLK3_REQ_DUPLICATEWAKEUPEVENT_MASK		(1 << 9)
+#define OMAP4_FREF_CLK0_OUT_DUPLICATEWAKEUPEVENT_SHIFT		8
+#define OMAP4_FREF_CLK0_OUT_DUPLICATEWAKEUPEVENT_MASK		(1 << 8)
+#define OMAP4_FREF_CLK_IOREQ_DUPLICATEWAKEUPEVENT_SHIFT		7
+#define OMAP4_FREF_CLK_IOREQ_DUPLICATEWAKEUPEVENT_MASK		(1 << 7)
+#define OMAP4_SR_SDA_DUPLICATEWAKEUPEVENT_SHIFT			6
+#define OMAP4_SR_SDA_DUPLICATEWAKEUPEVENT_MASK			(1 << 6)
+#define OMAP4_SR_SCL_DUPLICATEWAKEUPEVENT_SHIFT			5
+#define OMAP4_SR_SCL_DUPLICATEWAKEUPEVENT_MASK			(1 << 5)
+#define OMAP4_SIM_PWRCTRL_DUPLICATEWAKEUPEVENT_SHIFT		4
+#define OMAP4_SIM_PWRCTRL_DUPLICATEWAKEUPEVENT_MASK		(1 << 4)
+#define OMAP4_SIM_CD_DUPLICATEWAKEUPEVENT_SHIFT			3
+#define OMAP4_SIM_CD_DUPLICATEWAKEUPEVENT_MASK			(1 << 3)
+#define OMAP4_SIM_RESET_DUPLICATEWAKEUPEVENT_SHIFT		2
+#define OMAP4_SIM_RESET_DUPLICATEWAKEUPEVENT_MASK		(1 << 2)
+#define OMAP4_SIM_CLK_DUPLICATEWAKEUPEVENT_SHIFT		1
+#define OMAP4_SIM_CLK_DUPLICATEWAKEUPEVENT_MASK			(1 << 1)
+#define OMAP4_SIM_IO_DUPLICATEWAKEUPEVENT_SHIFT			0
+#define OMAP4_SIM_IO_DUPLICATEWAKEUPEVENT_MASK			(1 << 0)
+
+/* CONTROL_SMART1NOPMIO_PADCONF_0 */
+#define OMAP4_FREF_DR0_SC_SHIFT					30
+#define OMAP4_FREF_DR0_SC_MASK					(0x3 << 30)
+#define OMAP4_FREF_DR1_SC_SHIFT					28
+#define OMAP4_FREF_DR1_SC_MASK					(0x3 << 28)
+#define OMAP4_FREF_DR4_SC_SHIFT					26
+#define OMAP4_FREF_DR4_SC_MASK					(0x3 << 26)
+#define OMAP4_FREF_DR5_SC_SHIFT					24
+#define OMAP4_FREF_DR5_SC_MASK					(0x3 << 24)
+#define OMAP4_FREF_DR6_SC_SHIFT					22
+#define OMAP4_FREF_DR6_SC_MASK					(0x3 << 22)
+#define OMAP4_FREF_DR7_SC_SHIFT					20
+#define OMAP4_FREF_DR7_SC_MASK					(0x3 << 20)
+#define OMAP4_GPIO_DR7_SC_SHIFT					18
+#define OMAP4_GPIO_DR7_SC_MASK					(0x3 << 18)
+#define OMAP4_DPM_DR0_SC_SHIFT					14
+#define OMAP4_DPM_DR0_SC_MASK					(0x3 << 14)
+#define OMAP4_SIM_DR0_SC_SHIFT					12
+#define OMAP4_SIM_DR0_SC_MASK					(0x3 << 12)
+
+/* CONTROL_SMART1NOPMIO_PADCONF_1 */
+#define OMAP4_FREF_DR0_LB_SHIFT					30
+#define OMAP4_FREF_DR0_LB_MASK					(0x3 << 30)
+#define OMAP4_FREF_DR1_LB_SHIFT					28
+#define OMAP4_FREF_DR1_LB_MASK					(0x3 << 28)
+#define OMAP4_FREF_DR4_LB_SHIFT					26
+#define OMAP4_FREF_DR4_LB_MASK					(0x3 << 26)
+#define OMAP4_FREF_DR5_LB_SHIFT					24
+#define OMAP4_FREF_DR5_LB_MASK					(0x3 << 24)
+#define OMAP4_FREF_DR6_LB_SHIFT					22
+#define OMAP4_FREF_DR6_LB_MASK					(0x3 << 22)
+#define OMAP4_FREF_DR7_LB_SHIFT					20
+#define OMAP4_FREF_DR7_LB_MASK					(0x3 << 20)
+#define OMAP4_GPIO_DR7_LB_SHIFT					18
+#define OMAP4_GPIO_DR7_LB_MASK					(0x3 << 18)
+#define OMAP4_DPM_DR0_LB_SHIFT					14
+#define OMAP4_DPM_DR0_LB_MASK					(0x3 << 14)
+#define OMAP4_SIM_DR0_LB_SHIFT					12
+#define OMAP4_SIM_DR0_LB_MASK					(0x3 << 12)
+
+/* CONTROL_PADCONF_MODE */
+#define OMAP4_VDDS_DV_FREF_SHIFT				31
+#define OMAP4_VDDS_DV_FREF_MASK					(1 << 31)
+#define OMAP4_VDDS_DV_BANK2_SHIFT				30
+#define OMAP4_VDDS_DV_BANK2_MASK				(1 << 30)
+
+/* CONTROL_XTAL_OSCILLATOR */
+#define OMAP4_OSCILLATOR_BOOST_SHIFT				31
+#define OMAP4_OSCILLATOR_BOOST_MASK				(1 << 31)
+#define OMAP4_OSCILLATOR_OS_OUT_SHIFT				30
+#define OMAP4_OSCILLATOR_OS_OUT_MASK				(1 << 30)
+
+/* CONTROL_USIMIO */
+#define OMAP4_PAD_USIM_CLK_LOW_SHIFT				31
+#define OMAP4_PAD_USIM_CLK_LOW_MASK				(1 << 31)
+#define OMAP4_PAD_USIM_RST_LOW_SHIFT				29
+#define OMAP4_PAD_USIM_RST_LOW_MASK				(1 << 29)
+#define OMAP4_USIM_PWRDNZ_SHIFT					28
+#define OMAP4_USIM_PWRDNZ_MASK					(1 << 28)
+
+/* CONTROL_I2C_2 */
+#define OMAP4_SR_SDA_GLFENB_SHIFT				31
+#define OMAP4_SR_SDA_GLFENB_MASK				(1 << 31)
+#define OMAP4_SR_SDA_LOAD_BITS_SHIFT				29
+#define OMAP4_SR_SDA_LOAD_BITS_MASK				(0x3 << 29)
+#define OMAP4_SR_SDA_PULLUPRESX_SHIFT				28
+#define OMAP4_SR_SDA_PULLUPRESX_MASK				(1 << 28)
+#define OMAP4_SR_SCL_GLFENB_SHIFT				27
+#define OMAP4_SR_SCL_GLFENB_MASK				(1 << 27)
+#define OMAP4_SR_SCL_LOAD_BITS_SHIFT				25
+#define OMAP4_SR_SCL_LOAD_BITS_MASK				(0x3 << 25)
+#define OMAP4_SR_SCL_PULLUPRESX_SHIFT				24
+#define OMAP4_SR_SCL_PULLUPRESX_MASK				(1 << 24)
+
+/* CONTROL_JTAG */
+#define OMAP4_JTAG_NTRST_EN_SHIFT				31
+#define OMAP4_JTAG_NTRST_EN_MASK				(1 << 31)
+#define OMAP4_JTAG_TCK_EN_SHIFT					30
+#define OMAP4_JTAG_TCK_EN_MASK					(1 << 30)
+#define OMAP4_JTAG_RTCK_EN_SHIFT				29
+#define OMAP4_JTAG_RTCK_EN_MASK					(1 << 29)
+#define OMAP4_JTAG_TDI_EN_SHIFT					28
+#define OMAP4_JTAG_TDI_EN_MASK					(1 << 28)
+#define OMAP4_JTAG_TDO_EN_SHIFT					27
+#define OMAP4_JTAG_TDO_EN_MASK					(1 << 27)
+
+/* CONTROL_SYS */
+#define OMAP4_SYS_NRESWARM_PIPU_SHIFT				31
+#define OMAP4_SYS_NRESWARM_PIPU_MASK				(1 << 31)
+
+/* WKUP_CONTROL_SPARE_RW */
+#define OMAP4_WKUP_CONTROL_SPARE_RW_SHIFT			0
+#define OMAP4_WKUP_CONTROL_SPARE_RW_MASK			(0xffffffff << 0)
+
+/* WKUP_CONTROL_SPARE_R */
+#define OMAP4_WKUP_CONTROL_SPARE_R_SHIFT			0
+#define OMAP4_WKUP_CONTROL_SPARE_R_MASK				(0xffffffff << 0)
+
+/* WKUP_CONTROL_SPARE_R_C0 */
+#define OMAP4_WKUP_CONTROL_SPARE_R_C0_SHIFT			31
+#define OMAP4_WKUP_CONTROL_SPARE_R_C0_MASK			(1 << 31)
+#define OMAP4_WKUP_CONTROL_SPARE_R_C1_SHIFT			30
+#define OMAP4_WKUP_CONTROL_SPARE_R_C1_MASK			(1 << 30)
+#define OMAP4_WKUP_CONTROL_SPARE_R_C2_SHIFT			29
+#define OMAP4_WKUP_CONTROL_SPARE_R_C2_MASK			(1 << 29)
+#define OMAP4_WKUP_CONTROL_SPARE_R_C3_SHIFT			28
+#define OMAP4_WKUP_CONTROL_SPARE_R_C3_MASK			(1 << 28)
+#define OMAP4_WKUP_CONTROL_SPARE_R_C4_SHIFT			27
+#define OMAP4_WKUP_CONTROL_SPARE_R_C4_MASK			(1 << 27)
+#define OMAP4_WKUP_CONTROL_SPARE_R_C5_SHIFT			26
+#define OMAP4_WKUP_CONTROL_SPARE_R_C5_MASK			(1 << 26)
+#define OMAP4_WKUP_CONTROL_SPARE_R_C6_SHIFT			25
+#define OMAP4_WKUP_CONTROL_SPARE_R_C6_MASK			(1 << 25)
+#define OMAP4_WKUP_CONTROL_SPARE_R_C7_SHIFT			24
+#define OMAP4_WKUP_CONTROL_SPARE_R_C7_MASK			(1 << 24)
+
+#endif
diff --git a/arch/arm/mach-omap2/include/mach/ctrl_module_wkup_44xx.h b/arch/arm/mach-omap2/include/mach/ctrl_module_wkup_44xx.h
new file mode 100644
index 0000000..a0af9ba
--- /dev/null
+++ b/arch/arm/mach-omap2/include/mach/ctrl_module_wkup_44xx.h
@@ -0,0 +1,92 @@
+/*
+ * OMAP44xx CTRL_MODULE_WKUP registers and bitfields
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * Benoit Cousson (b-cousson@ti.com)
+ * Santosh Shilimkar (santosh.shilimkar@ti.com)
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_WKUP_44XX_H
+#define __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_WKUP_44XX_H
+
+
+/* Base address */
+#define OMAP4_CTRL_MODULE_WKUP				0x4a30c000
+
+/* Registers offset */
+#define OMAP4_CTRL_MODULE_WKUP_IP_REVISION		0x0000
+#define OMAP4_CTRL_MODULE_WKUP_IP_HWINFO		0x0004
+#define OMAP4_CTRL_MODULE_WKUP_IP_SYSCONFIG		0x0010
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_0	0x0460
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_1	0x0464
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_2	0x0468
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_3	0x046c
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_4	0x0470
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_5	0x0474
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_6	0x0478
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_7	0x047c
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_8	0x0480
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_9	0x0484
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_10	0x0488
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_11	0x048c
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_12	0x0490
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_13	0x0494
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_14	0x0498
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_15	0x049c
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_16	0x04a0
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_17	0x04a4
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_18	0x04a8
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_19	0x04ac
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_20	0x04b0
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_21	0x04b4
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_22	0x04b8
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_23	0x04bc
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_24	0x04c0
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_25	0x04c4
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_26	0x04c8
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_27	0x04cc
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_28	0x04d0
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_29	0x04d4
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_30	0x04d8
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_31	0x04dc
+
+/* Registers shifts and masks */
+
+/* IP_REVISION */
+#define OMAP4_IP_REV_SCHEME_SHIFT		30
+#define OMAP4_IP_REV_SCHEME_MASK		(0x3 << 30)
+#define OMAP4_IP_REV_FUNC_SHIFT			16
+#define OMAP4_IP_REV_FUNC_MASK			(0xfff << 16)
+#define OMAP4_IP_REV_RTL_SHIFT			11
+#define OMAP4_IP_REV_RTL_MASK			(0x1f << 11)
+#define OMAP4_IP_REV_MAJOR_SHIFT		8
+#define OMAP4_IP_REV_MAJOR_MASK			(0x7 << 8)
+#define OMAP4_IP_REV_CUSTOM_SHIFT		6
+#define OMAP4_IP_REV_CUSTOM_MASK		(0x3 << 6)
+#define OMAP4_IP_REV_MINOR_SHIFT		0
+#define OMAP4_IP_REV_MINOR_MASK			(0x3f << 0)
+
+/* IP_HWINFO */
+#define OMAP4_IP_HWINFO_SHIFT			0
+#define OMAP4_IP_HWINFO_MASK			(0xffffffff << 0)
+
+/* IP_SYSCONFIG */
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_SHIFT	2
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_MASK	(0x3 << 2)
+
+/* CONF_DEBUG_SEL_TST_0 */
+#define OMAP4_WKUP_MODE_SHIFT			0
+#define OMAP4_WKUP_MODE_MASK				(1 << 0)
+
+#endif
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index b9ea70b..40562dd 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -36,6 +36,7 @@
 #include "clock2xxx.h"
 #include "clock3xxx.h"
 #include "clock44xx.h"
+#include "io.h"
 
 #include <plat/omap-pm.h>
 #include <plat/powerdomain.h>
@@ -323,6 +324,9 @@
 		omap2430_hwmod_init();
 	else if (cpu_is_omap34xx())
 		omap3xxx_hwmod_init();
+	else if (cpu_is_omap44xx())
+		omap44xx_hwmod_init();
+
 	/* The OPP tables have to be registered before a clk init */
 	omap_pm_if_early_init(mpu_opps, dsp_opps, l3_opps);
 
@@ -342,9 +346,7 @@
 #ifndef CONFIG_PM_RUNTIME
 	skip_setup_idle = 1;
 #endif
-	if (cpu_is_omap24xx() || cpu_is_omap34xx())   /* FIXME: OMAP4 */
-		omap_hwmod_late_init(skip_setup_idle);
-
+	omap_hwmod_late_init(skip_setup_idle);
 	if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
 		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
new file mode 100644
index 0000000..fd230c6
--- /dev/null
+++ b/arch/arm/mach-omap2/io.h
@@ -0,0 +1,7 @@
+
+#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 26aeef5..32eeabe 100644
--- a/arch/arm/mach-omap2/irq.c
+++ b/arch/arm/mach-omap2/irq.c
@@ -47,7 +47,6 @@
 } __attribute__ ((aligned(4))) irq_banks[] = {
 	{
 		/* MPU INTC */
-		.base_reg	= 0,
 		.nr_irqs	= 96,
 	},
 };
diff --git a/arch/arm/mach-omap2/mailbox.c b/arch/arm/mach-omap2/mailbox.c
index 42dbfa4..40ddeca 100644
--- a/arch/arm/mach-omap2/mailbox.c
+++ b/arch/arm/mach-omap2/mailbox.c
@@ -181,7 +181,7 @@
 static void omap2_mbox_enable_irq(struct omap_mbox *mbox,
 		omap_mbox_type_t irq)
 {
-	struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
+	struct omap_mbox2_priv *p = mbox->priv;
 	u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
 
 	l = mbox_read_reg(p->irqenable);
@@ -192,7 +192,7 @@
 static void omap2_mbox_disable_irq(struct omap_mbox *mbox,
 		omap_mbox_type_t irq)
 {
-	struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
+	struct omap_mbox2_priv *p = mbox->priv;
 	u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
 	l = mbox_read_reg(p->irqdisable);
 	l &= ~bit;
@@ -202,7 +202,7 @@
 static void omap2_mbox_ack_irq(struct omap_mbox *mbox,
 		omap_mbox_type_t irq)
 {
-	struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
+	struct omap_mbox2_priv *p = mbox->priv;
 	u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
 
 	mbox_write_reg(bit, p->irqstatus);
@@ -214,7 +214,7 @@
 static int omap2_mbox_is_irq(struct omap_mbox *mbox,
 		omap_mbox_type_t irq)
 {
-	struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
+	struct omap_mbox2_priv *p = mbox->priv;
 	u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
 	u32 enable = mbox_read_reg(p->irqenable);
 	u32 status = mbox_read_reg(p->irqstatus);
diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c
index 467aae2..f9c9df5 100644
--- a/arch/arm/mach-omap2/mcbsp.c
+++ b/arch/arm/mach-omap2/mcbsp.c
@@ -23,29 +23,86 @@
 #include <plat/cpu.h>
 #include <plat/mcbsp.h>
 
-#include "mux.h"
+#include "control.h"
 
-static void omap2_mcbsp2_mux_setup(void)
+
+/* McBSP internal signal muxing functions */
+
+void omap2_mcbsp1_mux_clkr_src(u8 mux)
 {
-	omap_mux_init_signal("eac_ac_sclk.mcbsp2_clkx", OMAP_PULL_ENA);
-	omap_mux_init_signal("eac_ac_fs.mcbsp2_fsx", OMAP_PULL_ENA);
-	omap_mux_init_signal("eac_ac_din.mcbsp2_dr", OMAP_PULL_ENA);
-	omap_mux_init_signal("eac_ac_dout.mcbsp2_dx", OMAP_PULL_ENA);
-	omap_mux_init_gpio(117, OMAP_PULL_ENA);
-	/*
-	 * TODO: Need to add MUX settings for OMAP 2430 SDP
-	 */
-}
+	u32 v;
 
-static void omap2_mcbsp_request(unsigned int id)
+	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)
 {
-	if (cpu_is_omap2420() && (id == OMAP_MCBSP2))
-		omap2_mcbsp2_mux_setup();
-}
+	u32 v;
 
-static struct omap_mcbsp_ops omap2_mcbsp_ops = {
-	.request	= omap2_mcbsp_request,
-};
+	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);
+}
+EXPORT_SYMBOL(omap2_mcbsp1_mux_fsr_src);
+
+/* McBSP CLKS source switching function */
+
+int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id)
+{
+	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)
+		fck_src_name = "pad_fck";
+	else if (fck_src_id == MCBSP_CLKS_PRCM_SRC)
+		fck_src_name = "prcm_fck";
+	else
+		return -EINVAL;
+
+	fck_src = clk_get(mcbsp->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;
+	}
+
+	clk_disable(mcbsp->fclk);
+
+	r = clk_set_parent(mcbsp->fclk, fck_src);
+	if (IS_ERR_VALUE(r)) {
+		pr_err("omap-mcbsp: %s: could not clk_set_parent() to %s\n",
+		       "clks", fck_src_name);
+		clk_put(fck_src);
+		return -EINVAL;
+	}
+
+	clk_enable(mcbsp->fclk);
+
+	clk_put(fck_src);
+
+	return 0;
+}
+EXPORT_SYMBOL(omap2_mcbsp_set_clks_src);
+
+
+/* Platform data */
 
 #ifdef CONFIG_ARCH_OMAP2420
 static struct omap_mcbsp_platform_data omap2420_mcbsp_pdata[] = {
@@ -55,7 +112,6 @@
 		.dma_tx_sync	= OMAP24XX_DMA_MCBSP1_TX,
 		.rx_irq		= INT_24XX_MCBSP1_IRQ_RX,
 		.tx_irq		= INT_24XX_MCBSP1_IRQ_TX,
-		.ops		= &omap2_mcbsp_ops,
 	},
 	{
 		.phys_base	= OMAP24XX_MCBSP2_BASE,
@@ -63,7 +119,6 @@
 		.dma_tx_sync	= OMAP24XX_DMA_MCBSP2_TX,
 		.rx_irq		= INT_24XX_MCBSP2_IRQ_RX,
 		.tx_irq		= INT_24XX_MCBSP2_IRQ_TX,
-		.ops		= &omap2_mcbsp_ops,
 	},
 };
 #define OMAP2420_MCBSP_PDATA_SZ		ARRAY_SIZE(omap2420_mcbsp_pdata)
@@ -82,7 +137,6 @@
 		.dma_tx_sync	= OMAP24XX_DMA_MCBSP1_TX,
 		.rx_irq		= INT_24XX_MCBSP1_IRQ_RX,
 		.tx_irq		= INT_24XX_MCBSP1_IRQ_TX,
-		.ops		= &omap2_mcbsp_ops,
 	},
 	{
 		.phys_base	= OMAP24XX_MCBSP2_BASE,
@@ -90,7 +144,6 @@
 		.dma_tx_sync	= OMAP24XX_DMA_MCBSP2_TX,
 		.rx_irq		= INT_24XX_MCBSP2_IRQ_RX,
 		.tx_irq		= INT_24XX_MCBSP2_IRQ_TX,
-		.ops		= &omap2_mcbsp_ops,
 	},
 	{
 		.phys_base	= OMAP2430_MCBSP3_BASE,
@@ -98,7 +151,6 @@
 		.dma_tx_sync	= OMAP24XX_DMA_MCBSP3_TX,
 		.rx_irq		= INT_24XX_MCBSP3_IRQ_RX,
 		.tx_irq		= INT_24XX_MCBSP3_IRQ_TX,
-		.ops		= &omap2_mcbsp_ops,
 	},
 	{
 		.phys_base	= OMAP2430_MCBSP4_BASE,
@@ -106,7 +158,6 @@
 		.dma_tx_sync	= OMAP24XX_DMA_MCBSP4_TX,
 		.rx_irq		= INT_24XX_MCBSP4_IRQ_RX,
 		.tx_irq		= INT_24XX_MCBSP4_IRQ_TX,
-		.ops		= &omap2_mcbsp_ops,
 	},
 	{
 		.phys_base	= OMAP2430_MCBSP5_BASE,
@@ -114,7 +165,6 @@
 		.dma_tx_sync	= OMAP24XX_DMA_MCBSP5_TX,
 		.rx_irq		= INT_24XX_MCBSP5_IRQ_RX,
 		.tx_irq		= INT_24XX_MCBSP5_IRQ_TX,
-		.ops		= &omap2_mcbsp_ops,
 	},
 };
 #define OMAP2430_MCBSP_PDATA_SZ		ARRAY_SIZE(omap2430_mcbsp_pdata)
@@ -133,7 +183,6 @@
 		.dma_tx_sync	= OMAP24XX_DMA_MCBSP1_TX,
 		.rx_irq		= INT_24XX_MCBSP1_IRQ_RX,
 		.tx_irq		= INT_24XX_MCBSP1_IRQ_TX,
-		.ops		= &omap2_mcbsp_ops,
 		.buffer_size	= 0x80, /* The FIFO has 128 locations */
 	},
 	{
@@ -143,7 +192,6 @@
 		.dma_tx_sync	= OMAP24XX_DMA_MCBSP2_TX,
 		.rx_irq		= INT_24XX_MCBSP2_IRQ_RX,
 		.tx_irq		= INT_24XX_MCBSP2_IRQ_TX,
-		.ops		= &omap2_mcbsp_ops,
 		.buffer_size	= 0x500, /* The FIFO has 1024 + 256 locations */
 	},
 	{
@@ -153,7 +201,6 @@
 		.dma_tx_sync	= OMAP24XX_DMA_MCBSP3_TX,
 		.rx_irq		= INT_24XX_MCBSP3_IRQ_RX,
 		.tx_irq		= INT_24XX_MCBSP3_IRQ_TX,
-		.ops		= &omap2_mcbsp_ops,
 		.buffer_size	= 0x80, /* The FIFO has 128 locations */
 	},
 	{
@@ -162,7 +209,6 @@
 		.dma_tx_sync	= OMAP24XX_DMA_MCBSP4_TX,
 		.rx_irq		= INT_24XX_MCBSP4_IRQ_RX,
 		.tx_irq		= INT_24XX_MCBSP4_IRQ_TX,
-		.ops		= &omap2_mcbsp_ops,
 		.buffer_size	= 0x80, /* The FIFO has 128 locations */
 	},
 	{
@@ -171,7 +217,6 @@
 		.dma_tx_sync	= OMAP24XX_DMA_MCBSP5_TX,
 		.rx_irq		= INT_24XX_MCBSP5_IRQ_RX,
 		.tx_irq		= INT_24XX_MCBSP5_IRQ_TX,
-		.ops		= &omap2_mcbsp_ops,
 		.buffer_size	= 0x80, /* The FIFO has 128 locations */
 	},
 };
@@ -189,28 +234,24 @@
 		.dma_rx_sync    = OMAP44XX_DMA_MCBSP1_RX,
 		.dma_tx_sync    = OMAP44XX_DMA_MCBSP1_TX,
 		.tx_irq         = OMAP44XX_IRQ_MCBSP1,
-		.ops            = &omap2_mcbsp_ops,
 	},
 	{
 		.phys_base      = OMAP44XX_MCBSP2_BASE,
 		.dma_rx_sync    = OMAP44XX_DMA_MCBSP2_RX,
 		.dma_tx_sync    = OMAP44XX_DMA_MCBSP2_TX,
 		.tx_irq         = OMAP44XX_IRQ_MCBSP2,
-		.ops            = &omap2_mcbsp_ops,
 	},
 	{
 		.phys_base      = OMAP44XX_MCBSP3_BASE,
 		.dma_rx_sync    = OMAP44XX_DMA_MCBSP3_RX,
 		.dma_tx_sync    = OMAP44XX_DMA_MCBSP3_TX,
 		.tx_irq         = OMAP44XX_IRQ_MCBSP3,
-		.ops            = &omap2_mcbsp_ops,
 	},
 	{
 		.phys_base      = OMAP44XX_MCBSP4_BASE,
 		.dma_rx_sync    = OMAP44XX_DMA_MCBSP4_RX,
 		.dma_tx_sync    = OMAP44XX_DMA_MCBSP4_TX,
 		.tx_irq         = OMAP44XX_IRQ_MCBSP4,
-		.ops            = &omap2_mcbsp_ops,
 	},
 };
 #define OMAP44XX_MCBSP_PDATA_SZ		ARRAY_SIZE(omap44xx_mcbsp_pdata)
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index ab403b2..074536a 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -23,12 +23,11 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  */
-#include <linux/module.h>
+#include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
 #include <linux/list.h>
+#include <linux/slab.h>
 #include <linux/ctype.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
@@ -36,8 +35,7 @@
 
 #include <asm/system.h>
 
-#include <plat/control.h>
-
+#include "control.h"
 #include "mux.h"
 
 #define OMAP_MUX_BASE_OFFSET		0x30	/* Offset from CTRL_BASE */
@@ -87,7 +85,7 @@
 int __init omap_mux_init_gpio(int gpio, int val)
 {
 	struct omap_mux_entry *e;
-	struct omap_mux *gpio_mux;
+	struct omap_mux *gpio_mux = NULL;
 	u16 old_mode;
 	u16 mux_mode;
 	int found = 0;
@@ -127,17 +125,16 @@
 	return 0;
 }
 
-int __init omap_mux_init_signal(char *muxname, int val)
+int __init omap_mux_init_signal(const char *muxname, int val)
 {
 	struct omap_mux_entry *e;
-	char *m0_name = NULL, *mode_name = NULL;
-	int found = 0;
+	const char *mode_name;
+	int found = 0, mode0_len = 0;
 
 	mode_name = strchr(muxname, '.');
 	if (mode_name) {
-		*mode_name = '\0';
+		mode0_len = strlen(muxname) - strlen(mode_name);
 		mode_name++;
-		m0_name = muxname;
 	} else {
 		mode_name = muxname;
 	}
@@ -147,9 +144,11 @@
 		char *m0_entry = m->muxnames[0];
 		int i;
 
-		if (m0_name && strcmp(m0_name, m0_entry))
+		/* First check for full name in mode0.muxmode format */
+		if (mode0_len && strncmp(muxname, m0_entry, mode0_len))
 			continue;
 
+		/* Then check for muxmode only */
 		for (i = 0; i < OMAP_MUX_NR_MODES; i++) {
 			char *mode_cur = m->muxnames[i];
 
diff --git a/arch/arm/mach-omap2/mux.h b/arch/arm/mach-omap2/mux.h
index a8e040c..350c04f 100644
--- a/arch/arm/mach-omap2/mux.h
+++ b/arch/arm/mach-omap2/mux.h
@@ -120,7 +120,7 @@
  * @muxname:		Mux name in mode0_name.signal_name format
  * @val:		Options for the mux register value
  */
-int omap_mux_init_signal(char *muxname, int val);
+int omap_mux_init_signal(const char *muxname, int val);
 
 #else
 
diff --git a/arch/arm/mach-omap2/mux2420.c b/arch/arm/mach-omap2/mux2420.c
index fdb04a7..414af54 100644
--- a/arch/arm/mach-omap2/mux2420.c
+++ b/arch/arm/mach-omap2/mux2420.c
@@ -507,7 +507,7 @@
  * Balls for 447-pin POP package
  */
 #ifdef CONFIG_DEBUG_FS
-struct omap_ball __initdata omap2420_pop_ball[] = {
+static struct omap_ball __initdata omap2420_pop_ball[] = {
 	_OMAP2420_BALLENTRY(CAM_D0, "y4", NULL),
 	_OMAP2420_BALLENTRY(CAM_D1, "y3", NULL),
 	_OMAP2420_BALLENTRY(CAM_D2, "u7", NULL),
diff --git a/arch/arm/mach-omap2/mux2430.c b/arch/arm/mach-omap2/mux2430.c
index 7dcaaa8..84d2c5a 100644
--- a/arch/arm/mach-omap2/mux2430.c
+++ b/arch/arm/mach-omap2/mux2430.c
@@ -586,7 +586,7 @@
  * 447-pin s-PBGA Package, 0.00mm Ball Pitch (Bottom)
  */
 #ifdef CONFIG_DEBUG_FS
-struct omap_ball __initdata omap2430_pop_ball[] = {
+static struct omap_ball __initdata omap2430_pop_ball[] = {
 	_OMAP2430_BALLENTRY(CAM_D0, "t8", NULL),
 	_OMAP2430_BALLENTRY(CAM_D1, "t4", NULL),
 	_OMAP2430_BALLENTRY(CAM_D10, "r4", NULL),
diff --git a/arch/arm/mach-omap2/mux34xx.c b/arch/arm/mach-omap2/mux34xx.c
index f64d7ee..574e54e 100644
--- a/arch/arm/mach-omap2/mux34xx.c
+++ b/arch/arm/mach-omap2/mux34xx.c
@@ -931,7 +931,7 @@
  * Signals different on CUS package compared to superset
  */
 #if defined(CONFIG_OMAP_MUX) && defined(CONFIG_OMAP_PACKAGE_CUS)
-struct omap_mux __initdata omap3_cus_subset[] = {
+static struct omap_mux __initdata omap3_cus_subset[] = {
 	_OMAP3_MUXENTRY(CAM_D10, 109,
 		"cam_d10", NULL, NULL, NULL,
 		"gpio_109", NULL, NULL, "safe_mode"),
@@ -1077,7 +1077,7 @@
  */
 #if defined(CONFIG_OMAP_MUX) && defined(CONFIG_DEBUG_FS)		\
 		&& defined(CONFIG_OMAP_PACKAGE_CUS)
-struct omap_ball __initdata omap3_cus_ball[] = {
+static struct omap_ball __initdata omap3_cus_ball[] = {
 	_OMAP3_BALLENTRY(CAM_D0, "ab18", NULL),
 	_OMAP3_BALLENTRY(CAM_D1, "ac18", NULL),
 	_OMAP3_BALLENTRY(CAM_D10, "f21", NULL),
@@ -1269,7 +1269,7 @@
  * Signals different on CBB package comapared to superset
  */
 #if defined(CONFIG_OMAP_MUX) && defined(CONFIG_OMAP_PACKAGE_CBB)
-struct omap_mux __initdata omap3_cbb_subset[] = {
+static struct omap_mux __initdata omap3_cbb_subset[] = {
 	_OMAP3_MUXENTRY(CAM_D10, 109,
 		"cam_d10", NULL, NULL, NULL,
 		"gpio_109", NULL, NULL, "safe_mode"),
@@ -1390,7 +1390,7 @@
  */
 #if defined(CONFIG_OMAP_MUX) && defined(CONFIG_DEBUG_FS)		\
 		&& defined(CONFIG_OMAP_PACKAGE_CBB)
-struct omap_ball __initdata omap3_cbb_ball[] = {
+static struct omap_ball __initdata omap3_cbb_ball[] = {
 	_OMAP3_BALLENTRY(CAM_D0, "ag17", NULL),
 	_OMAP3_BALLENTRY(CAM_D1, "ah17", NULL),
 	_OMAP3_BALLENTRY(CAM_D10, "b25", NULL),
@@ -1600,7 +1600,7 @@
  * Signals different on 36XX CBP package comapared to 34XX CBC package
  */
 #if defined(CONFIG_OMAP_MUX) && defined(CONFIG_OMAP_PACKAGE_CBP)
-struct omap_mux __initdata omap36xx_cbp_subset[] = {
+static struct omap_mux __initdata omap36xx_cbp_subset[] = {
 	_OMAP3_MUXENTRY(CAM_D0, 99,
 		"cam_d0", NULL, "csi2_dx2", NULL,
 		"gpio_99", NULL, NULL, "safe_mode"),
@@ -1818,7 +1818,7 @@
  */
 #if defined(CONFIG_OMAP_MUX) && defined(CONFIG_DEBUG_FS)		\
 		&& defined (CONFIG_OMAP_PACKAGE_CBP)
-struct omap_ball __initdata omap36xx_cbp_ball[] = {
+static struct omap_ball __initdata omap36xx_cbp_ball[] = {
 	_OMAP3_BALLENTRY(CAM_D0, "ag17", NULL),
 	_OMAP3_BALLENTRY(CAM_D1, "ah17", NULL),
 	_OMAP3_BALLENTRY(CAM_D10, "b25", NULL),
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
index 13dc979..923f9f5 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -61,10 +61,14 @@
 	omap_smc1(0x102, 0x1);
 
 	/*
-	 * 32KB way size, 16-way associativity,
-	 * parity disabled
+	 * 16-way associativity, parity disabled
+	 * Way size - 32KB (es1.0)
+	 * Way size - 64KB (es2.0 +)
 	 */
-	l2x0_init(l2cache_base, 0x0e050000, 0xc0000fff);
+	if (omap_rev() == OMAP4430_REV_ES1_0)
+		l2x0_init(l2cache_base, 0x0e050000, 0xc0000fff);
+	else
+		l2x0_init(l2cache_base, 0x0e070000, 0xc0000fff);
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index cb911d7..5a30658 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -13,10 +13,102 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- * This code manages "OMAP modules" (on-chip devices) and their
- * integration with Linux device driver and bus code.
+ * Introduction
+ * ------------
+ * One way to view an OMAP SoC is as a collection of largely unrelated
+ * IP blocks connected by interconnects.  The IP blocks include
+ * devices such as ARM processors, audio serial interfaces, UARTs,
+ * etc.  Some of these devices, like the DSP, are created by TI;
+ * others, like the SGX, largely originate from external vendors.  In
+ * TI's documentation, on-chip devices are referred to as "OMAP
+ * modules."  Some of these IP blocks are identical across several
+ * OMAP versions.  Others are revised frequently.
  *
- * References:
+ * These OMAP modules are tied together by various interconnects.
+ * Most of the address and data flow between modules is via OCP-based
+ * interconnects such as the L3 and L4 buses; but there are other
+ * interconnects that distribute the hardware clock tree, handle idle
+ * and reset signaling, supply power, and connect the modules to
+ * various pads or balls on the OMAP package.
+ *
+ * OMAP hwmod provides a consistent way to describe the on-chip
+ * hardware blocks and their integration into the rest of the chip.
+ * This description can be automatically generated from the TI
+ * hardware database.  OMAP hwmod provides a standard, consistent API
+ * to reset, enable, idle, and disable these hardware blocks.  And
+ * hwmod provides a way for other core code, such as the Linux device
+ * code or the OMAP power management and address space mapping code,
+ * to query the hardware database.
+ *
+ * Using hwmod
+ * -----------
+ * Drivers won't call hwmod functions directly.  That is done by the
+ * omap_device code, and in rare occasions, by custom integration code
+ * in arch/arm/ *omap*.  The omap_device code includes functions to
+ * build a struct platform_device using omap_hwmod data, and that is
+ * currently how hwmod data is communicated to drivers and to the
+ * Linux driver model.  Most drivers will call omap_hwmod functions only
+ * indirectly, via pm_runtime*() functions.
+ *
+ * From a layering perspective, here is where the OMAP hwmod code
+ * fits into the kernel software stack:
+ *
+ *            +-------------------------------+
+ *            |      Device driver code       |
+ *            |      (e.g., drivers/)         |
+ *            +-------------------------------+
+ *            |      Linux driver model       |
+ *            |     (platform_device /        |
+ *            |  platform_driver data/code)   |
+ *            +-------------------------------+
+ *            | OMAP core-driver integration  |
+ *            |(arch/arm/mach-omap2/devices.c)|
+ *            +-------------------------------+
+ *            |      omap_device code         |
+ *            | (../plat-omap/omap_device.c)  |
+ *            +-------------------------------+
+ *   ---->    |    omap_hwmod code/data       |    <-----
+ *            | (../mach-omap2/omap_hwmod*)   |
+ *            +-------------------------------+
+ *            | OMAP clock/PRCM/register fns  |
+ *            | (__raw_{read,write}l, clk*)   |
+ *            +-------------------------------+
+ *
+ * Device drivers should not contain any OMAP-specific code or data in
+ * them.  They should only contain code to operate the IP block that
+ * the driver is responsible for.  This is because these IP blocks can
+ * also appear in other SoCs, either from TI (such as DaVinci) or from
+ * other manufacturers; and drivers should be reusable across other
+ * platforms.
+ *
+ * The OMAP hwmod code also will attempt to reset and idle all on-chip
+ * devices upon boot.  The goal here is for the kernel to be
+ * completely self-reliant and independent from bootloaders.  This is
+ * to ensure a repeatable configuration, both to ensure consistent
+ * runtime behavior, and to make it easier for others to reproduce
+ * bugs.
+ *
+ * OMAP module activity states
+ * ---------------------------
+ * The hwmod code considers modules to be in one of several activity
+ * states.  IP blocks start out in an UNKNOWN state, then once they
+ * are registered via the hwmod code, proceed to the REGISTERED state.
+ * Once their clock names are resolved to clock pointers, the module
+ * enters the CLKS_INITED state; and finally, once the module has been
+ * reset and the integration registers programmed, the INITIALIZED state
+ * is entered.  The hwmod code will then place the module into either
+ * the IDLE state to save power, or in the case of a critical system
+ * module, the ENABLED state.
+ *
+ * OMAP core integration code can then call omap_hwmod*() functions
+ * directly to move the module between the IDLE, ENABLED, and DISABLED
+ * states, as needed.  This is done during both the PM idle loop, and
+ * in the OMAP core integration code's implementation of the PM runtime
+ * functions.
+ *
+ * References
+ * ----------
+ * This is a partial list.
  * - OMAP2420 Multimedia Processor Silicon Revision 2.1.1, 2.2 (SWPU064)
  * - OMAP2430 Multimedia Device POP Silicon Revision 2.1 (SWPU090)
  * - OMAP34xx Multimedia Device Silicon Revision 3.1 (SWPU108)
@@ -50,11 +142,13 @@
 #include <plat/powerdomain.h>
 #include <plat/clock.h>
 #include <plat/omap_hwmod.h>
+#include <plat/prcm.h>
 
 #include "cm.h"
+#include "prm.h"
 
-/* Maximum microseconds to wait for OMAP module to reset */
-#define MAX_MODULE_RESET_WAIT		10000
+/* Maximum microseconds to wait for OMAP module to softreset */
+#define MAX_MODULE_SOFTRESET_WAIT	10000
 
 /* Name of the OMAP hwmod for the MPU */
 #define MPU_INITIATOR_NAME		"mpu"
@@ -90,7 +184,7 @@
 
 	/* XXX ensure module interface clock is up */
 
-	oh->_sysc_cache = omap_hwmod_readl(oh, oh->class->sysc->sysc_offs);
+	oh->_sysc_cache = omap_hwmod_read(oh, oh->class->sysc->sysc_offs);
 
 	if (!(oh->class->sysc->sysc_flags & SYSC_NO_CACHE))
 		oh->_int_flags |= _HWMOD_SYSCONFIG_LOADED;
@@ -117,7 +211,7 @@
 
 	if (oh->_sysc_cache != v) {
 		oh->_sysc_cache = v;
-		omap_hwmod_writel(v, oh, oh->class->sysc->sysc_offs);
+		omap_hwmod_write(v, oh, oh->class->sysc->sysc_offs);
 	}
 }
 
@@ -544,6 +638,36 @@
 	return 0;
 }
 
+static void _enable_optional_clocks(struct omap_hwmod *oh)
+{
+	struct omap_hwmod_opt_clk *oc;
+	int i;
+
+	pr_debug("omap_hwmod: %s: enabling optional clocks\n", oh->name);
+
+	for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
+		if (oc->_clk) {
+			pr_debug("omap_hwmod: enable %s:%s\n", oc->role,
+				 oc->_clk->name);
+			clk_enable(oc->_clk);
+		}
+}
+
+static void _disable_optional_clocks(struct omap_hwmod *oh)
+{
+	struct omap_hwmod_opt_clk *oc;
+	int i;
+
+	pr_debug("omap_hwmod: %s: disabling optional clocks\n", oh->name);
+
+	for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
+		if (oc->_clk) {
+			pr_debug("omap_hwmod: disable %s:%s\n", oc->role,
+				 oc->_clk->name);
+			clk_disable(oc->_clk);
+		}
+}
+
 /**
  * _find_mpu_port_index - find hwmod OCP slave port ID intended for MPU use
  * @oh: struct omap_hwmod *
@@ -622,7 +746,7 @@
 }
 
 /**
- * _sysc_enable - try to bring a module out of idle via OCP_SYSCONFIG
+ * _enable_sysc - try to bring a module out of idle via OCP_SYSCONFIG
  * @oh: struct omap_hwmod *
  *
  * If module is marked as SWSUP_SIDLE, force the module out of slave
@@ -630,7 +754,7 @@
  * as SWSUP_MSUSPEND, force the module out of master standby;
  * otherwise, configure it for smart-standby.  No return value.
  */
-static void _sysc_enable(struct omap_hwmod *oh)
+static void _enable_sysc(struct omap_hwmod *oh)
 {
 	u8 idlemode, sf;
 	u32 v;
@@ -653,14 +777,6 @@
 		_set_master_standbymode(oh, idlemode, &v);
 	}
 
-	if (sf & SYSC_HAS_AUTOIDLE) {
-		idlemode = (oh->flags & HWMOD_NO_OCP_AUTOIDLE) ?
-			0 : 1;
-		_set_module_autoidle(oh, idlemode, &v);
-	}
-
-	/* XXX OCP ENAWAKEUP bit? */
-
 	/*
 	 * XXX The clock framework should handle this, by
 	 * calling into this code.  But this must wait until the
@@ -671,10 +787,25 @@
 		_set_clockactivity(oh, oh->class->sysc->clockact, &v);
 
 	_write_sysconfig(v, oh);
+
+	/* If slave is in SMARTIDLE, also enable wakeup */
+	if ((sf & SYSC_HAS_SIDLEMODE) && !(oh->flags & HWMOD_SWSUP_SIDLE))
+		_enable_wakeup(oh);
+
+	/*
+	 * Set the autoidle bit only after setting the smartidle bit
+	 * Setting this will not have any impact on the other modules.
+	 */
+	if (sf & SYSC_HAS_AUTOIDLE) {
+		idlemode = (oh->flags & HWMOD_NO_OCP_AUTOIDLE) ?
+			0 : 1;
+		_set_module_autoidle(oh, idlemode, &v);
+		_write_sysconfig(v, oh);
+	}
 }
 
 /**
- * _sysc_idle - try to put a module into idle via OCP_SYSCONFIG
+ * _idle_sysc - try to put a module into idle via OCP_SYSCONFIG
  * @oh: struct omap_hwmod *
  *
  * If module is marked as SWSUP_SIDLE, force the module into slave
@@ -682,7 +813,7 @@
  * as SWSUP_MSUSPEND, force the module into master standby; otherwise,
  * configure it for smart-standby.  No return value.
  */
-static void _sysc_idle(struct omap_hwmod *oh)
+static void _idle_sysc(struct omap_hwmod *oh)
 {
 	u8 idlemode, sf;
 	u32 v;
@@ -709,13 +840,13 @@
 }
 
 /**
- * _sysc_shutdown - force a module into idle via OCP_SYSCONFIG
+ * _shutdown_sysc - force a module into idle via OCP_SYSCONFIG
  * @oh: struct omap_hwmod *
  *
  * Force the module into slave idle and master suspend. No return
  * value.
  */
-static void _sysc_shutdown(struct omap_hwmod *oh)
+static void _shutdown_sysc(struct omap_hwmod *oh)
 {
 	u32 v;
 	u8 sf;
@@ -767,10 +898,10 @@
  * @data: not used; pass NULL
  *
  * Called by omap_hwmod_late_init() (after omap2_clk_init()).
- * Resolves all clock names embedded in the hwmod.  Must be called
- * with omap_hwmod_mutex held.  Returns -EINVAL if the omap_hwmod
- * has not yet been registered or if the clocks have already been
- * initialized, 0 on success, or a non-zero error on failure.
+ * Resolves all clock names embedded in the hwmod.  Returns -EINVAL if
+ * the omap_hwmod has not yet been registered or if the clocks have
+ * already been initialized, 0 on success, or a non-zero error on
+ * failure.
  */
 static int _init_clocks(struct omap_hwmod *oh, void *data)
 {
@@ -834,56 +965,202 @@
 }
 
 /**
+ * _lookup_hardreset - return the register bit shift for this hwmod/reset line
+ * @oh: struct omap_hwmod *
+ * @name: name of the reset line in the context of this hwmod
+ *
+ * Return the bit position of the reset line that match the
+ * input name. Return -ENOENT if not found.
+ */
+static u8 _lookup_hardreset(struct omap_hwmod *oh, const char *name)
+{
+	int i;
+
+	for (i = 0; i < oh->rst_lines_cnt; i++) {
+		const char *rst_line = oh->rst_lines[i].name;
+		if (!strcmp(rst_line, name)) {
+			u8 shift = oh->rst_lines[i].rst_shift;
+			pr_debug("omap_hwmod: %s: _lookup_hardreset: %s: %d\n",
+				 oh->name, rst_line, shift);
+
+			return shift;
+		}
+	}
+
+	return -ENOENT;
+}
+
+/**
+ * _assert_hardreset - assert the HW reset line of submodules
+ * contained in the hwmod module.
+ * @oh: struct omap_hwmod *
+ * @name: name of the reset line to lookup and assert
+ *
+ * Some IP like dsp, ipu or iva contain processor that require
+ * an HW reset line to be assert / deassert in order to enable fully
+ * the IP.
+ */
+static int _assert_hardreset(struct omap_hwmod *oh, const char *name)
+{
+	u8 shift;
+
+	if (!oh)
+		return -EINVAL;
+
+	shift = _lookup_hardreset(oh, name);
+	if (IS_ERR_VALUE(shift))
+		return shift;
+
+	if (cpu_is_omap24xx() || cpu_is_omap34xx())
+		return omap2_prm_assert_hardreset(oh->prcm.omap2.module_offs,
+						  shift);
+	else if (cpu_is_omap44xx())
+		return omap4_prm_assert_hardreset(oh->prcm.omap4.rstctrl_reg,
+						  shift);
+	else
+		return -EINVAL;
+}
+
+/**
+ * _deassert_hardreset - deassert the HW reset line of submodules contained
+ * in the hwmod module.
+ * @oh: struct omap_hwmod *
+ * @name: name of the reset line to look up and deassert
+ *
+ * Some IP like dsp, ipu or iva contain processor that require
+ * an HW reset line to be assert / deassert in order to enable fully
+ * the IP.
+ */
+static int _deassert_hardreset(struct omap_hwmod *oh, const char *name)
+{
+	u8 shift;
+	int r;
+
+	if (!oh)
+		return -EINVAL;
+
+	shift = _lookup_hardreset(oh, name);
+	if (IS_ERR_VALUE(shift))
+		return shift;
+
+	if (cpu_is_omap24xx() || cpu_is_omap34xx())
+		r = omap2_prm_deassert_hardreset(oh->prcm.omap2.module_offs,
+						 shift);
+	else if (cpu_is_omap44xx())
+		r = omap4_prm_deassert_hardreset(oh->prcm.omap4.rstctrl_reg,
+						 shift);
+	else
+		return -EINVAL;
+
+	if (r == -EBUSY)
+		pr_warning("omap_hwmod: %s: failed to hardreset\n", oh->name);
+
+	return r;
+}
+
+/**
+ * _read_hardreset - read the HW reset line state of submodules
+ * contained in the hwmod module
+ * @oh: struct omap_hwmod *
+ * @name: name of the reset line to look up and read
+ *
+ * Return the state of the reset line.
+ */
+static int _read_hardreset(struct omap_hwmod *oh, const char *name)
+{
+	u8 shift;
+
+	if (!oh)
+		return -EINVAL;
+
+	shift = _lookup_hardreset(oh, name);
+	if (IS_ERR_VALUE(shift))
+		return shift;
+
+	if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
+		return omap2_prm_is_hardreset_asserted(oh->prcm.omap2.module_offs,
+						       shift);
+	} else if (cpu_is_omap44xx()) {
+		return omap4_prm_is_hardreset_asserted(oh->prcm.omap4.rstctrl_reg,
+						       shift);
+	} else {
+		return -EINVAL;
+	}
+}
+
+/**
  * _reset - reset an omap_hwmod
  * @oh: struct omap_hwmod *
  *
  * Resets an omap_hwmod @oh via the OCP_SYSCONFIG bit.  hwmod must be
- * enabled for this to work.  Must be called with omap_hwmod_mutex
- * held.  Returns -EINVAL if the hwmod cannot be reset this way or if
- * the hwmod is in the wrong state, -ETIMEDOUT if the module did not
- * reset in time, or 0 upon success.
+ * enabled for this to work.  Returns -EINVAL if the hwmod cannot be
+ * reset this way or if the hwmod is in the wrong state, -ETIMEDOUT if
+ * the module did not reset in time, or 0 upon success.
+ *
+ * In OMAP3 a specific SYSSTATUS register is used to get the reset status.
+ * Starting in OMAP4, some IPs does not have SYSSTATUS register and instead
+ * use the SYSCONFIG softreset bit to provide the status.
+ *
+ * Note that some IP like McBSP does have a reset control but no reset status.
  */
 static int _reset(struct omap_hwmod *oh)
 {
-	u32 r, v;
+	u32 v;
 	int c = 0;
+	int ret = 0;
 
 	if (!oh->class->sysc ||
-	    !(oh->class->sysc->sysc_flags & SYSC_HAS_SOFTRESET) ||
-	    (oh->class->sysc->sysc_flags & SYSS_MISSING))
+	    !(oh->class->sysc->sysc_flags & SYSC_HAS_SOFTRESET))
 		return -EINVAL;
 
 	/* clocks must be on for this operation */
 	if (oh->_state != _HWMOD_STATE_ENABLED) {
-		WARN(1, "omap_hwmod: %s: reset can only be entered from "
-		     "enabled state\n", oh->name);
+		pr_warning("omap_hwmod: %s: reset can only be entered from "
+			   "enabled state\n", oh->name);
 		return -EINVAL;
 	}
 
+	/* For some modules, all optionnal clocks need to be enabled as well */
+	if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET)
+		_enable_optional_clocks(oh);
+
 	pr_debug("omap_hwmod: %s: resetting\n", oh->name);
 
 	v = oh->_sysc_cache;
-	r = _set_softreset(oh, &v);
-	if (r)
-		return r;
+	ret = _set_softreset(oh, &v);
+	if (ret)
+		goto dis_opt_clks;
 	_write_sysconfig(v, oh);
 
-	omap_test_timeout((omap_hwmod_readl(oh, oh->class->sysc->syss_offs) &
-			   SYSS_RESETDONE_MASK),
-			  MAX_MODULE_RESET_WAIT, c);
+	if (oh->class->sysc->sysc_flags & SYSS_HAS_RESET_STATUS)
+		omap_test_timeout((omap_hwmod_read(oh,
+						    oh->class->sysc->syss_offs)
+				   & SYSS_RESETDONE_MASK),
+				  MAX_MODULE_SOFTRESET_WAIT, c);
+	else if (oh->class->sysc->sysc_flags & SYSC_HAS_RESET_STATUS)
+		omap_test_timeout(!(omap_hwmod_read(oh,
+						     oh->class->sysc->sysc_offs)
+				   & SYSC_TYPE2_SOFTRESET_MASK),
+				  MAX_MODULE_SOFTRESET_WAIT, c);
 
-	if (c == MAX_MODULE_RESET_WAIT)
-		WARN(1, "omap_hwmod: %s: failed to reset in %d usec\n",
-		     oh->name, MAX_MODULE_RESET_WAIT);
+	if (c == MAX_MODULE_SOFTRESET_WAIT)
+		pr_warning("omap_hwmod: %s: softreset failed (waited %d usec)\n",
+			   oh->name, MAX_MODULE_SOFTRESET_WAIT);
 	else
-		pr_debug("omap_hwmod: %s: reset in %d usec\n", oh->name, c);
+		pr_debug("omap_hwmod: %s: softreset in %d usec\n", oh->name, c);
 
 	/*
 	 * XXX add _HWMOD_STATE_WEDGED for modules that don't come back from
 	 * _wait_target_ready() or _reset()
 	 */
 
-	return (c == MAX_MODULE_RESET_WAIT) ? -ETIMEDOUT : 0;
+	ret = (c == MAX_MODULE_SOFTRESET_WAIT) ? -ETIMEDOUT : 0;
+
+dis_opt_clks:
+	if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET)
+		_disable_optional_clocks(oh);
+
+	return ret;
 }
 
 /**
@@ -891,9 +1168,11 @@
  * @oh: struct omap_hwmod *
  *
  * Enables an omap_hwmod @oh such that the MPU can access the hwmod's
- * register target.  Must be called with omap_hwmod_mutex held.
- * Returns -EINVAL if the hwmod is in the wrong state or passes along
- * the return value of _wait_target_ready().
+ * register target.  (This function has a full name --
+ * _omap_hwmod_enable() rather than simply _enable() -- because it is
+ * currently required by the pm34xx.c idle loop.)  Returns -EINVAL if
+ * the hwmod is in the wrong state or passes along the return value of
+ * _wait_target_ready().
  */
 int _omap_hwmod_enable(struct omap_hwmod *oh)
 {
@@ -909,6 +1188,15 @@
 
 	pr_debug("omap_hwmod: %s: enabling\n", oh->name);
 
+	/*
+	 * If an IP contains only one HW reset line, then de-assert it in order
+	 * to allow to enable the clocks. Otherwise the PRCM will return
+	 * Intransition status, and the init will failed.
+	 */
+	if ((oh->_state == _HWMOD_STATE_INITIALIZED ||
+	     oh->_state == _HWMOD_STATE_DISABLED) && oh->rst_lines_cnt == 1)
+		_deassert_hardreset(oh, oh->rst_lines[0].name);
+
 	/* XXX mux balls */
 
 	_add_initiator_dep(oh, mpu_oh);
@@ -922,7 +1210,7 @@
 		if (oh->class->sysc) {
 			if (!(oh->_int_flags & _HWMOD_SYSCONFIG_LOADED))
 				_update_sysc_cache(oh);
-			_sysc_enable(oh);
+			_enable_sysc(oh);
 		}
 	} else {
 		pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n",
@@ -933,12 +1221,14 @@
 }
 
 /**
- * _idle - idle an omap_hwmod
+ * _omap_hwmod_idle - idle an omap_hwmod
  * @oh: struct omap_hwmod *
  *
  * Idles an omap_hwmod @oh.  This should be called once the hwmod has
- * no further work.  Returns -EINVAL if the hwmod is in the wrong
- * state or returns 0.
+ * no further work.  (This function has a full name --
+ * _omap_hwmod_idle() rather than simply _idle() -- because it is
+ * currently required by the pm34xx.c idle loop.)  Returns -EINVAL if
+ * the hwmod is in the wrong state or returns 0.
  */
 int _omap_hwmod_idle(struct omap_hwmod *oh)
 {
@@ -951,7 +1241,7 @@
 	pr_debug("omap_hwmod: %s: idling\n", oh->name);
 
 	if (oh->class->sysc)
-		_sysc_idle(oh);
+		_idle_sysc(oh);
 	_del_initiator_dep(oh, mpu_oh);
 	_disable_clocks(oh);
 
@@ -981,10 +1271,21 @@
 	pr_debug("omap_hwmod: %s: disabling\n", oh->name);
 
 	if (oh->class->sysc)
-		_sysc_shutdown(oh);
-	_del_initiator_dep(oh, mpu_oh);
-	/* XXX what about the other system initiators here? DMA, tesla, d2d */
-	_disable_clocks(oh);
+		_shutdown_sysc(oh);
+
+	/*
+	 * If an IP contains only one HW reset line, then assert it
+	 * before disabling the clocks and shutting down the IP.
+	 */
+	if (oh->rst_lines_cnt == 1)
+		_assert_hardreset(oh, oh->rst_lines[0].name);
+
+	/* clocks and deps are already disabled in idle */
+	if (oh->_state == _HWMOD_STATE_ENABLED) {
+		_del_initiator_dep(oh, mpu_oh);
+		/* XXX what about the other system initiators here? dma, dsp */
+		_disable_clocks(oh);
+	}
 	/* XXX Should this code also force-disable the optional clocks? */
 
 	/* XXX mux any associated balls to safe mode */
@@ -1000,11 +1301,10 @@
  * @skip_setup_idle_p: do not idle hwmods at the end of the fn if 1
  *
  * Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh
- * OCP_SYSCONFIG register.  Must be called with omap_hwmod_mutex held.
- * @skip_setup_idle is intended to be used on a system that will not
- * call omap_hwmod_enable() to enable devices (e.g., a system without
- * PM runtime).  Returns -EINVAL if the hwmod is in the wrong state or
- * returns 0.
+ * OCP_SYSCONFIG register.  @skip_setup_idle is intended to be used on
+ * a system that will not call omap_hwmod_enable() to enable devices
+ * (e.g., a system without PM runtime).  Returns -EINVAL if the hwmod
+ * is in the wrong state or returns 0.
  */
 static int _setup(struct omap_hwmod *oh, void *data)
 {
@@ -1034,8 +1334,19 @@
 		}
 	}
 
+	mutex_init(&oh->_mutex);
 	oh->_state = _HWMOD_STATE_INITIALIZED;
 
+	/*
+	 * In the case of hwmod with hardreset that should not be
+	 * de-assert at boot time, we have to keep the module
+	 * initialized, because we cannot enable it properly with the
+	 * reset asserted. Exit without warning because that behavior is
+	 * expected.
+	 */
+	if ((oh->flags & HWMOD_INIT_NO_RESET) && oh->rst_lines_cnt == 1)
+		return 0;
+
 	r = _omap_hwmod_enable(oh);
 	if (r) {
 		pr_warning("omap_hwmod: %s: cannot be enabled (%d)\n",
@@ -1044,16 +1355,16 @@
 	}
 
 	if (!(oh->flags & HWMOD_INIT_NO_RESET)) {
+		_reset(oh);
+
 		/*
-		 * XXX Do the OCP_SYSCONFIG bits need to be
-		 * reprogrammed after a reset?  If not, then this can
-		 * be removed.  If they do, then probably the
-		 * _omap_hwmod_enable() function should be split to avoid the
-		 * rewrite of the OCP_SYSCONFIG register.
+		 * OCP_SYSCONFIG bits need to be reprogrammed after a softreset.
+		 * The _omap_hwmod_enable() function should be split to
+		 * avoid the rewrite of the OCP_SYSCONFIG register.
 		 */
 		if (oh->class->sysc) {
 			_update_sysc_cache(oh);
-			_sysc_enable(oh);
+			_enable_sysc(oh);
 		}
 	}
 
@@ -1067,14 +1378,20 @@
 
 /* Public functions */
 
-u32 omap_hwmod_readl(struct omap_hwmod *oh, u16 reg_offs)
+u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs)
 {
-	return __raw_readl(oh->_mpu_rt_va + reg_offs);
+	if (oh->flags & HWMOD_16BIT_REG)
+		return __raw_readw(oh->_mpu_rt_va + reg_offs);
+	else
+		return __raw_readl(oh->_mpu_rt_va + reg_offs);
 }
 
-void omap_hwmod_writel(u32 v, struct omap_hwmod *oh, u16 reg_offs)
+void omap_hwmod_write(u32 v, struct omap_hwmod *oh, u16 reg_offs)
 {
-	__raw_writel(v, oh->_mpu_rt_va + reg_offs);
+	if (oh->flags & HWMOD_16BIT_REG)
+		__raw_writew(v, oh->_mpu_rt_va + reg_offs);
+	else
+		__raw_writel(v, oh->_mpu_rt_va + reg_offs);
 }
 
 /**
@@ -1309,7 +1626,7 @@
  * omap_hwmod_enable - enable an omap_hwmod
  * @oh: struct omap_hwmod *
  *
- * Enable an omap_hwomd @oh.  Intended to be called by omap_device_enable().
+ * Enable an omap_hwmod @oh.  Intended to be called by omap_device_enable().
  * Returns -EINVAL on error or passes along the return value from _enable().
  */
 int omap_hwmod_enable(struct omap_hwmod *oh)
@@ -1319,9 +1636,9 @@
 	if (!oh)
 		return -EINVAL;
 
-	mutex_lock(&omap_hwmod_mutex);
+	mutex_lock(&oh->_mutex);
 	r = _omap_hwmod_enable(oh);
-	mutex_unlock(&omap_hwmod_mutex);
+	mutex_unlock(&oh->_mutex);
 
 	return r;
 }
@@ -1331,7 +1648,7 @@
  * omap_hwmod_idle - idle an omap_hwmod
  * @oh: struct omap_hwmod *
  *
- * Idle an omap_hwomd @oh.  Intended to be called by omap_device_idle().
+ * Idle an omap_hwmod @oh.  Intended to be called by omap_device_idle().
  * Returns -EINVAL on error or passes along the return value from _idle().
  */
 int omap_hwmod_idle(struct omap_hwmod *oh)
@@ -1339,9 +1656,9 @@
 	if (!oh)
 		return -EINVAL;
 
-	mutex_lock(&omap_hwmod_mutex);
+	mutex_lock(&oh->_mutex);
 	_omap_hwmod_idle(oh);
-	mutex_unlock(&omap_hwmod_mutex);
+	mutex_unlock(&oh->_mutex);
 
 	return 0;
 }
@@ -1350,7 +1667,7 @@
  * omap_hwmod_shutdown - shutdown an omap_hwmod
  * @oh: struct omap_hwmod *
  *
- * Shutdown an omap_hwomd @oh.  Intended to be called by
+ * Shutdown an omap_hwmod @oh.  Intended to be called by
  * omap_device_shutdown().  Returns -EINVAL on error or passes along
  * the return value from _shutdown().
  */
@@ -1359,9 +1676,9 @@
 	if (!oh)
 		return -EINVAL;
 
-	mutex_lock(&omap_hwmod_mutex);
+	mutex_lock(&oh->_mutex);
 	_shutdown(oh);
-	mutex_unlock(&omap_hwmod_mutex);
+	mutex_unlock(&oh->_mutex);
 
 	return 0;
 }
@@ -1374,9 +1691,9 @@
  */
 int omap_hwmod_enable_clocks(struct omap_hwmod *oh)
 {
-	mutex_lock(&omap_hwmod_mutex);
+	mutex_lock(&oh->_mutex);
 	_enable_clocks(oh);
-	mutex_unlock(&omap_hwmod_mutex);
+	mutex_unlock(&oh->_mutex);
 
 	return 0;
 }
@@ -1389,9 +1706,9 @@
  */
 int omap_hwmod_disable_clocks(struct omap_hwmod *oh)
 {
-	mutex_lock(&omap_hwmod_mutex);
+	mutex_lock(&oh->_mutex);
 	_disable_clocks(oh);
-	mutex_unlock(&omap_hwmod_mutex);
+	mutex_unlock(&oh->_mutex);
 
 	return 0;
 }
@@ -1421,7 +1738,7 @@
 	 * Forces posted writes to complete on the OCP thread handling
 	 * register writes
 	 */
-	omap_hwmod_readl(oh, oh->class->sysc->sysc_offs);
+	omap_hwmod_read(oh, oh->class->sysc->sysc_offs);
 }
 
 /**
@@ -1430,20 +1747,18 @@
  *
  * Under some conditions, a driver may wish to reset the entire device.
  * Called from omap_device code.  Returns -EINVAL on error or passes along
- * the return value from _reset()/_enable().
+ * the return value from _reset().
  */
 int omap_hwmod_reset(struct omap_hwmod *oh)
 {
 	int r;
 
-	if (!oh || !(oh->_state & _HWMOD_STATE_ENABLED))
+	if (!oh)
 		return -EINVAL;
 
-	mutex_lock(&omap_hwmod_mutex);
+	mutex_lock(&oh->_mutex);
 	r = _reset(oh);
-	if (!r)
-		r = _omap_hwmod_enable(oh);
-	mutex_unlock(&omap_hwmod_mutex);
+	mutex_unlock(&oh->_mutex);
 
 	return r;
 }
@@ -1468,7 +1783,7 @@
 {
 	int ret, i;
 
-	ret = oh->mpu_irqs_cnt + oh->sdma_chs_cnt;
+	ret = oh->mpu_irqs_cnt + oh->sdma_reqs_cnt;
 
 	for (i = 0; i < oh->slaves_cnt; i++)
 		ret += oh->slaves[i]->addr_cnt;
@@ -1501,10 +1816,10 @@
 		r++;
 	}
 
-	for (i = 0; i < oh->sdma_chs_cnt; i++) {
-		(res + r)->name = (oh->sdma_chs + i)->name;
-		(res + r)->start = (oh->sdma_chs + i)->dma_ch;
-		(res + r)->end = (oh->sdma_chs + i)->dma_ch;
+	for (i = 0; i < oh->sdma_reqs_cnt; i++) {
+		(res + r)->name = (oh->sdma_reqs + i)->name;
+		(res + r)->start = (oh->sdma_reqs + i)->dma_req;
+		(res + r)->end = (oh->sdma_reqs + i)->dma_req;
 		(res + r)->flags = IORESOURCE_DMA;
 		r++;
 	}
@@ -1644,9 +1959,9 @@
 	    !(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP))
 		return -EINVAL;
 
-	mutex_lock(&omap_hwmod_mutex);
+	mutex_lock(&oh->_mutex);
 	_enable_wakeup(oh);
-	mutex_unlock(&omap_hwmod_mutex);
+	mutex_unlock(&oh->_mutex);
 
 	return 0;
 }
@@ -1669,14 +1984,92 @@
 	    !(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP))
 		return -EINVAL;
 
-	mutex_lock(&omap_hwmod_mutex);
+	mutex_lock(&oh->_mutex);
 	_disable_wakeup(oh);
-	mutex_unlock(&omap_hwmod_mutex);
+	mutex_unlock(&oh->_mutex);
 
 	return 0;
 }
 
 /**
+ * omap_hwmod_assert_hardreset - assert the HW reset line of submodules
+ * contained in the hwmod module.
+ * @oh: struct omap_hwmod *
+ * @name: name of the reset line to lookup and assert
+ *
+ * Some IP like dsp, ipu or iva contain processor that require
+ * an HW reset line to be assert / deassert in order to enable fully
+ * the IP.  Returns -EINVAL if @oh is null or if the operation is not
+ * yet supported on this OMAP; otherwise, passes along the return value
+ * from _assert_hardreset().
+ */
+int omap_hwmod_assert_hardreset(struct omap_hwmod *oh, const char *name)
+{
+	int ret;
+
+	if (!oh)
+		return -EINVAL;
+
+	mutex_lock(&oh->_mutex);
+	ret = _assert_hardreset(oh, name);
+	mutex_unlock(&oh->_mutex);
+
+	return ret;
+}
+
+/**
+ * omap_hwmod_deassert_hardreset - deassert the HW reset line of submodules
+ * contained in the hwmod module.
+ * @oh: struct omap_hwmod *
+ * @name: name of the reset line to look up and deassert
+ *
+ * Some IP like dsp, ipu or iva contain processor that require
+ * an HW reset line to be assert / deassert in order to enable fully
+ * the IP.  Returns -EINVAL if @oh is null or if the operation is not
+ * yet supported on this OMAP; otherwise, passes along the return value
+ * from _deassert_hardreset().
+ */
+int omap_hwmod_deassert_hardreset(struct omap_hwmod *oh, const char *name)
+{
+	int ret;
+
+	if (!oh)
+		return -EINVAL;
+
+	mutex_lock(&oh->_mutex);
+	ret = _deassert_hardreset(oh, name);
+	mutex_unlock(&oh->_mutex);
+
+	return ret;
+}
+
+/**
+ * omap_hwmod_read_hardreset - read the HW reset line state of submodules
+ * contained in the hwmod module
+ * @oh: struct omap_hwmod *
+ * @name: name of the reset line to look up and read
+ *
+ * Return the current state of the hwmod @oh's reset line named @name:
+ * returns -EINVAL upon parameter error or if this operation
+ * is unsupported on the current OMAP; otherwise, passes along the return
+ * value from _read_hardreset().
+ */
+int omap_hwmod_read_hardreset(struct omap_hwmod *oh, const char *name)
+{
+	int ret;
+
+	if (!oh)
+		return -EINVAL;
+
+	mutex_lock(&oh->_mutex);
+	ret = _read_hardreset(oh, name);
+	mutex_unlock(&oh->_mutex);
+
+	return ret;
+}
+
+
+/**
  * omap_hwmod_for_each_by_class - call @fn for each hwmod of class @classname
  * @classname: struct omap_hwmod_class name to search for
  * @fn: callback function pointer to call for each hwmod in class @classname
diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index 3cc768e..adf6e36 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -15,10 +15,12 @@
 #include <mach/irqs.h>
 #include <plat/cpu.h>
 #include <plat/dma.h>
+#include <plat/serial.h>
 
 #include "omap_hwmod_common_data.h"
 
 #include "prm-regbits-24xx.h"
+#include "cm-regbits-24xx.h"
 
 /*
  * OMAP2420 hardware module integration data
@@ -33,6 +35,7 @@
 static struct omap_hwmod omap2420_iva_hwmod;
 static struct omap_hwmod omap2420_l3_main_hwmod;
 static struct omap_hwmod omap2420_l4_core_hwmod;
+static struct omap_hwmod omap2420_wd_timer2_hwmod;
 
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap2420_l3_main__l4_core = {
@@ -71,6 +74,9 @@
 };
 
 static struct omap_hwmod omap2420_l4_wkup_hwmod;
+static struct omap_hwmod omap2420_uart1_hwmod;
+static struct omap_hwmod omap2420_uart2_hwmod;
+static struct omap_hwmod omap2420_uart3_hwmod;
 
 /* L4_CORE -> L4_WKUP interface */
 static struct omap_hwmod_ocp_if omap2420_l4_core__l4_wkup = {
@@ -79,6 +85,60 @@
 	.user	= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* L4 CORE -> UART1 interface */
+static struct omap_hwmod_addr_space omap2420_uart1_addr_space[] = {
+	{
+		.pa_start	= OMAP2_UART1_BASE,
+		.pa_end		= OMAP2_UART1_BASE + SZ_8K - 1,
+		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2_l4_core__uart1 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_uart1_hwmod,
+	.clk		= "uart1_ick",
+	.addr		= omap2420_uart1_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2420_uart1_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 CORE -> UART2 interface */
+static struct omap_hwmod_addr_space omap2420_uart2_addr_space[] = {
+	{
+		.pa_start	= OMAP2_UART2_BASE,
+		.pa_end		= OMAP2_UART2_BASE + SZ_1K - 1,
+		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2_l4_core__uart2 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_uart2_hwmod,
+	.clk		= "uart2_ick",
+	.addr		= omap2420_uart2_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2420_uart2_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 PER -> UART3 interface */
+static struct omap_hwmod_addr_space omap2420_uart3_addr_space[] = {
+	{
+		.pa_start	= OMAP2_UART3_BASE,
+		.pa_end		= OMAP2_UART3_BASE + SZ_1K - 1,
+		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2_l4_core__uart3 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_uart3_hwmod,
+	.clk		= "uart3_ick",
+	.addr		= omap2420_uart3_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2420_uart3_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* Slave interfaces on the L4_CORE interconnect */
 static struct omap_hwmod_ocp_if *omap2420_l4_core_slaves[] = {
 	&omap2420_l3_main__l4_core,
@@ -87,6 +147,9 @@
 /* Master interfaces on the L4_CORE interconnect */
 static struct omap_hwmod_ocp_if *omap2420_l4_core_masters[] = {
 	&omap2420_l4_core__l4_wkup,
+	&omap2_l4_core__uart1,
+	&omap2_l4_core__uart2,
+	&omap2_l4_core__uart3,
 };
 
 /* L4 CORE */
@@ -165,12 +228,206 @@
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
+/* l4_wkup -> wd_timer2 */
+static struct omap_hwmod_addr_space omap2420_wd_timer2_addrs[] = {
+	{
+		.pa_start	= 0x48022000,
+		.pa_end		= 0x4802207f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2420_l4_wkup__wd_timer2 = {
+	.master		= &omap2420_l4_wkup_hwmod,
+	.slave		= &omap2420_wd_timer2_hwmod,
+	.clk		= "mpu_wdt_ick",
+	.addr		= omap2420_wd_timer2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_wd_timer2_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/*
+ * 'wd_timer' class
+ * 32-bit watchdog upward counter that generates a pulse on the reset pin on
+ * overflow condition
+ */
+
+static struct omap_hwmod_class_sysconfig omap2420_wd_timer_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_EMUFREE | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2420_wd_timer_hwmod_class = {
+	.name = "wd_timer",
+	.sysc = &omap2420_wd_timer_sysc,
+};
+
+/* wd_timer2 */
+static struct omap_hwmod_ocp_if *omap2420_wd_timer2_slaves[] = {
+	&omap2420_l4_wkup__wd_timer2,
+};
+
+static struct omap_hwmod omap2420_wd_timer2_hwmod = {
+	.name		= "wd_timer2",
+	.class		= &omap2420_wd_timer_hwmod_class,
+	.main_clk	= "mpu_wdt_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_MPU_WDT_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_MPU_WDT_SHIFT,
+		},
+	},
+	.slaves		= omap2420_wd_timer2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_wd_timer2_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
+/* UART */
+
+static struct omap_hwmod_class_sysconfig uart_sysc = {
+	.rev_offs	= 0x50,
+	.sysc_offs	= 0x54,
+	.syss_offs	= 0x58,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class uart_class = {
+	.name = "uart",
+	.sysc = &uart_sysc,
+};
+
+/* UART1 */
+
+static struct omap_hwmod_irq_info uart1_mpu_irqs[] = {
+	{ .irq = INT_24XX_UART1_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart1_sdma_reqs[] = {
+	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART1_RX, },
+	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART1_TX, },
+};
+
+static struct omap_hwmod_ocp_if *omap2420_uart1_slaves[] = {
+	&omap2_l4_core__uart1,
+};
+
+static struct omap_hwmod omap2420_uart1_hwmod = {
+	.name		= "uart1",
+	.mpu_irqs	= uart1_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(uart1_mpu_irqs),
+	.sdma_reqs	= uart1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(uart1_sdma_reqs),
+	.main_clk	= "uart1_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_UART1_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_EN_UART1_SHIFT,
+		},
+	},
+	.slaves		= omap2420_uart1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_uart1_slaves),
+	.class		= &uart_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
+/* UART2 */
+
+static struct omap_hwmod_irq_info uart2_mpu_irqs[] = {
+	{ .irq = INT_24XX_UART2_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart2_sdma_reqs[] = {
+	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART2_RX, },
+	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART2_TX, },
+};
+
+static struct omap_hwmod_ocp_if *omap2420_uart2_slaves[] = {
+	&omap2_l4_core__uart2,
+};
+
+static struct omap_hwmod omap2420_uart2_hwmod = {
+	.name		= "uart2",
+	.mpu_irqs	= uart2_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(uart2_mpu_irqs),
+	.sdma_reqs	= uart2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(uart2_sdma_reqs),
+	.main_clk	= "uart2_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_UART2_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_EN_UART2_SHIFT,
+		},
+	},
+	.slaves		= omap2420_uart2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_uart2_slaves),
+	.class		= &uart_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
+/* UART3 */
+
+static struct omap_hwmod_irq_info uart3_mpu_irqs[] = {
+	{ .irq = INT_24XX_UART3_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart3_sdma_reqs[] = {
+	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART3_RX, },
+	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART3_TX, },
+};
+
+static struct omap_hwmod_ocp_if *omap2420_uart3_slaves[] = {
+	&omap2_l4_core__uart3,
+};
+
+static struct omap_hwmod omap2420_uart3_hwmod = {
+	.name		= "uart3",
+	.mpu_irqs	= uart3_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(uart3_mpu_irqs),
+	.sdma_reqs	= uart3_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(uart3_sdma_reqs),
+	.main_clk	= "uart3_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 2,
+			.module_bit = OMAP24XX_EN_UART3_SHIFT,
+			.idlest_reg_id = 2,
+			.idlest_idle_bit = OMAP24XX_EN_UART3_SHIFT,
+		},
+	},
+	.slaves		= omap2420_uart3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_uart3_slaves),
+	.class		= &uart_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
 static __initdata struct omap_hwmod *omap2420_hwmods[] = {
 	&omap2420_l3_main_hwmod,
 	&omap2420_l4_core_hwmod,
 	&omap2420_l4_wkup_hwmod,
 	&omap2420_mpu_hwmod,
 	&omap2420_iva_hwmod,
+	&omap2420_wd_timer2_hwmod,
+	&omap2420_uart1_hwmod,
+	&omap2420_uart2_hwmod,
+	&omap2420_uart3_hwmod,
 	NULL,
 };
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index 4526628..12d939e 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -15,10 +15,12 @@
 #include <mach/irqs.h>
 #include <plat/cpu.h>
 #include <plat/dma.h>
+#include <plat/serial.h>
 
 #include "omap_hwmod_common_data.h"
 
 #include "prm-regbits-24xx.h"
+#include "cm-regbits-24xx.h"
 
 /*
  * OMAP2430 hardware module integration data
@@ -33,6 +35,7 @@
 static struct omap_hwmod omap2430_iva_hwmod;
 static struct omap_hwmod omap2430_l3_main_hwmod;
 static struct omap_hwmod omap2430_l4_core_hwmod;
+static struct omap_hwmod omap2430_wd_timer2_hwmod;
 
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap2430_l3_main__l4_core = {
@@ -71,6 +74,9 @@
 };
 
 static struct omap_hwmod omap2430_l4_wkup_hwmod;
+static struct omap_hwmod omap2430_uart1_hwmod;
+static struct omap_hwmod omap2430_uart2_hwmod;
+static struct omap_hwmod omap2430_uart3_hwmod;
 
 /* L4_CORE -> L4_WKUP interface */
 static struct omap_hwmod_ocp_if omap2430_l4_core__l4_wkup = {
@@ -79,6 +85,60 @@
 	.user	= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* L4 CORE -> UART1 interface */
+static struct omap_hwmod_addr_space omap2430_uart1_addr_space[] = {
+	{
+		.pa_start	= OMAP2_UART1_BASE,
+		.pa_end		= OMAP2_UART1_BASE + SZ_8K - 1,
+		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2_l4_core__uart1 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_uart1_hwmod,
+	.clk		= "uart1_ick",
+	.addr		= omap2430_uart1_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2430_uart1_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 CORE -> UART2 interface */
+static struct omap_hwmod_addr_space omap2430_uart2_addr_space[] = {
+	{
+		.pa_start	= OMAP2_UART2_BASE,
+		.pa_end		= OMAP2_UART2_BASE + SZ_1K - 1,
+		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2_l4_core__uart2 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_uart2_hwmod,
+	.clk		= "uart2_ick",
+	.addr		= omap2430_uart2_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2430_uart2_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 PER -> UART3 interface */
+static struct omap_hwmod_addr_space omap2430_uart3_addr_space[] = {
+	{
+		.pa_start	= OMAP2_UART3_BASE,
+		.pa_end		= OMAP2_UART3_BASE + SZ_1K - 1,
+		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2_l4_core__uart3 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_uart3_hwmod,
+	.clk		= "uart3_ick",
+	.addr		= omap2430_uart3_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2430_uart3_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* Slave interfaces on the L4_CORE interconnect */
 static struct omap_hwmod_ocp_if *omap2430_l4_core_slaves[] = {
 	&omap2430_l3_main__l4_core,
@@ -104,6 +164,9 @@
 /* Slave interfaces on the L4_WKUP interconnect */
 static struct omap_hwmod_ocp_if *omap2430_l4_wkup_slaves[] = {
 	&omap2430_l4_core__l4_wkup,
+	&omap2_l4_core__uart1,
+	&omap2_l4_core__uart2,
+	&omap2_l4_core__uart3,
 };
 
 /* Master interfaces on the L4_WKUP interconnect */
@@ -165,12 +228,206 @@
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
+/* l4_wkup -> wd_timer2 */
+static struct omap_hwmod_addr_space omap2430_wd_timer2_addrs[] = {
+	{
+		.pa_start	= 0x49016000,
+		.pa_end		= 0x4901607f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_wkup__wd_timer2 = {
+	.master		= &omap2430_l4_wkup_hwmod,
+	.slave		= &omap2430_wd_timer2_hwmod,
+	.clk		= "mpu_wdt_ick",
+	.addr		= omap2430_wd_timer2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_wd_timer2_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/*
+ * 'wd_timer' class
+ * 32-bit watchdog upward counter that generates a pulse on the reset pin on
+ * overflow condition
+ */
+
+static struct omap_hwmod_class_sysconfig omap2430_wd_timer_sysc = {
+	.rev_offs	= 0x0,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_EMUFREE | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2430_wd_timer_hwmod_class = {
+	.name = "wd_timer",
+	.sysc = &omap2430_wd_timer_sysc,
+};
+
+/* wd_timer2 */
+static struct omap_hwmod_ocp_if *omap2430_wd_timer2_slaves[] = {
+	&omap2430_l4_wkup__wd_timer2,
+};
+
+static struct omap_hwmod omap2430_wd_timer2_hwmod = {
+	.name		= "wd_timer2",
+	.class		= &omap2430_wd_timer_hwmod_class,
+	.main_clk	= "mpu_wdt_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_MPU_WDT_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_MPU_WDT_SHIFT,
+		},
+	},
+	.slaves		= omap2430_wd_timer2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_wd_timer2_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* UART */
+
+static struct omap_hwmod_class_sysconfig uart_sysc = {
+	.rev_offs	= 0x50,
+	.sysc_offs	= 0x54,
+	.syss_offs	= 0x58,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class uart_class = {
+	.name = "uart",
+	.sysc = &uart_sysc,
+};
+
+/* UART1 */
+
+static struct omap_hwmod_irq_info uart1_mpu_irqs[] = {
+	{ .irq = INT_24XX_UART1_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart1_sdma_reqs[] = {
+	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART1_RX, },
+	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART1_TX, },
+};
+
+static struct omap_hwmod_ocp_if *omap2430_uart1_slaves[] = {
+	&omap2_l4_core__uart1,
+};
+
+static struct omap_hwmod omap2430_uart1_hwmod = {
+	.name		= "uart1",
+	.mpu_irqs	= uart1_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(uart1_mpu_irqs),
+	.sdma_reqs	= uart1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(uart1_sdma_reqs),
+	.main_clk	= "uart1_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_UART1_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_EN_UART1_SHIFT,
+		},
+	},
+	.slaves		= omap2430_uart1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_uart1_slaves),
+	.class		= &uart_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* UART2 */
+
+static struct omap_hwmod_irq_info uart2_mpu_irqs[] = {
+	{ .irq = INT_24XX_UART2_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart2_sdma_reqs[] = {
+	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART2_RX, },
+	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART2_TX, },
+};
+
+static struct omap_hwmod_ocp_if *omap2430_uart2_slaves[] = {
+	&omap2_l4_core__uart2,
+};
+
+static struct omap_hwmod omap2430_uart2_hwmod = {
+	.name		= "uart2",
+	.mpu_irqs	= uart2_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(uart2_mpu_irqs),
+	.sdma_reqs	= uart2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(uart2_sdma_reqs),
+	.main_clk	= "uart2_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_UART2_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_EN_UART2_SHIFT,
+		},
+	},
+	.slaves		= omap2430_uart2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_uart2_slaves),
+	.class		= &uart_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* UART3 */
+
+static struct omap_hwmod_irq_info uart3_mpu_irqs[] = {
+	{ .irq = INT_24XX_UART3_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart3_sdma_reqs[] = {
+	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART3_RX, },
+	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART3_TX, },
+};
+
+static struct omap_hwmod_ocp_if *omap2430_uart3_slaves[] = {
+	&omap2_l4_core__uart3,
+};
+
+static struct omap_hwmod omap2430_uart3_hwmod = {
+	.name		= "uart3",
+	.mpu_irqs	= uart3_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(uart3_mpu_irqs),
+	.sdma_reqs	= uart3_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(uart3_sdma_reqs),
+	.main_clk	= "uart3_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 2,
+			.module_bit = OMAP24XX_EN_UART3_SHIFT,
+			.idlest_reg_id = 2,
+			.idlest_idle_bit = OMAP24XX_EN_UART3_SHIFT,
+		},
+	},
+	.slaves		= omap2430_uart3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_uart3_slaves),
+	.class		= &uart_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
 static __initdata struct omap_hwmod *omap2430_hwmods[] = {
 	&omap2430_l3_main_hwmod,
 	&omap2430_l4_core_hwmod,
 	&omap2430_l4_wkup_hwmod,
 	&omap2430_mpu_hwmod,
 	&omap2430_iva_hwmod,
+	&omap2430_wd_timer2_hwmod,
+	&omap2430_uart1_hwmod,
+	&omap2430_uart2_hwmod,
+	&omap2430_uart3_hwmod,
 	NULL,
 };
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 5d8eb58..cb97ecf 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -17,10 +17,12 @@
 #include <mach/irqs.h>
 #include <plat/cpu.h>
 #include <plat/dma.h>
+#include <plat/serial.h>
 
 #include "omap_hwmod_common_data.h"
 
 #include "prm-regbits-34xx.h"
+#include "cm-regbits-34xx.h"
 
 /*
  * OMAP3xxx hardware module integration data
@@ -36,6 +38,7 @@
 static struct omap_hwmod omap3xxx_l3_main_hwmod;
 static struct omap_hwmod omap3xxx_l4_core_hwmod;
 static struct omap_hwmod omap3xxx_l4_per_hwmod;
+static struct omap_hwmod omap3xxx_wd_timer2_hwmod;
 
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap3xxx_l3_main__l4_core = {
@@ -82,6 +85,10 @@
 };
 
 static struct omap_hwmod omap3xxx_l4_wkup_hwmod;
+static struct omap_hwmod omap3xxx_uart1_hwmod;
+static struct omap_hwmod omap3xxx_uart2_hwmod;
+static struct omap_hwmod omap3xxx_uart3_hwmod;
+static struct omap_hwmod omap3xxx_uart4_hwmod;
 
 /* L4_CORE -> L4_WKUP interface */
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__l4_wkup = {
@@ -90,6 +97,78 @@
 	.user	= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* L4 CORE -> UART1 interface */
+static struct omap_hwmod_addr_space omap3xxx_uart1_addr_space[] = {
+	{
+		.pa_start	= OMAP3_UART1_BASE,
+		.pa_end		= OMAP3_UART1_BASE + SZ_8K - 1,
+		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3_l4_core__uart1 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_uart1_hwmod,
+	.clk		= "uart1_ick",
+	.addr		= omap3xxx_uart1_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_uart1_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 CORE -> UART2 interface */
+static struct omap_hwmod_addr_space omap3xxx_uart2_addr_space[] = {
+	{
+		.pa_start	= OMAP3_UART2_BASE,
+		.pa_end		= OMAP3_UART2_BASE + SZ_1K - 1,
+		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3_l4_core__uart2 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_uart2_hwmod,
+	.clk		= "uart2_ick",
+	.addr		= omap3xxx_uart2_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_uart2_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 PER -> UART3 interface */
+static struct omap_hwmod_addr_space omap3xxx_uart3_addr_space[] = {
+	{
+		.pa_start	= OMAP3_UART3_BASE,
+		.pa_end		= OMAP3_UART3_BASE + SZ_1K - 1,
+		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3_l4_per__uart3 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_uart3_hwmod,
+	.clk		= "uart3_ick",
+	.addr		= omap3xxx_uart3_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_uart3_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 PER -> UART4 interface */
+static struct omap_hwmod_addr_space omap3xxx_uart4_addr_space[] = {
+	{
+		.pa_start	= OMAP3_UART4_BASE,
+		.pa_end		= OMAP3_UART4_BASE + SZ_1K - 1,
+		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3_l4_per__uart4 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_uart4_hwmod,
+	.clk		= "uart4_ick",
+	.addr		= omap3xxx_uart4_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_uart4_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* Slave interfaces on the L4_CORE interconnect */
 static struct omap_hwmod_ocp_if *omap3xxx_l4_core_slaves[] = {
 	&omap3xxx_l3_main__l4_core,
@@ -98,6 +177,8 @@
 /* Master interfaces on the L4_CORE interconnect */
 static struct omap_hwmod_ocp_if *omap3xxx_l4_core_masters[] = {
 	&omap3xxx_l4_core__l4_wkup,
+	&omap3_l4_core__uart1,
+	&omap3_l4_core__uart2,
 };
 
 /* L4 CORE */
@@ -119,6 +200,8 @@
 
 /* Master interfaces on the L4_PER interconnect */
 static struct omap_hwmod_ocp_if *omap3xxx_l4_per_masters[] = {
+	&omap3_l4_per__uart3,
+	&omap3_l4_per__uart4,
 };
 
 /* L4 PER */
@@ -197,6 +280,235 @@
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
+/* l4_wkup -> wd_timer2 */
+static struct omap_hwmod_addr_space omap3xxx_wd_timer2_addrs[] = {
+	{
+		.pa_start	= 0x48314000,
+		.pa_end		= 0x4831407f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__wd_timer2 = {
+	.master		= &omap3xxx_l4_wkup_hwmod,
+	.slave		= &omap3xxx_wd_timer2_hwmod,
+	.clk		= "wdt2_ick",
+	.addr		= omap3xxx_wd_timer2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_wd_timer2_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/*
+ * 'wd_timer' class
+ * 32-bit watchdog upward counter that generates a pulse on the reset pin on
+ * overflow condition
+ */
+
+static struct omap_hwmod_class_sysconfig omap3xxx_wd_timer_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_EMUFREE |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3xxx_wd_timer_hwmod_class = {
+	.name = "wd_timer",
+	.sysc = &omap3xxx_wd_timer_sysc,
+};
+
+/* wd_timer2 */
+static struct omap_hwmod_ocp_if *omap3xxx_wd_timer2_slaves[] = {
+	&omap3xxx_l4_wkup__wd_timer2,
+};
+
+static struct omap_hwmod omap3xxx_wd_timer2_hwmod = {
+	.name		= "wd_timer2",
+	.class		= &omap3xxx_wd_timer_hwmod_class,
+	.main_clk	= "wdt2_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_WDT2_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_WDT2_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_wd_timer2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_wd_timer2_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* UART common */
+
+static struct omap_hwmod_class_sysconfig uart_sysc = {
+	.rev_offs	= 0x50,
+	.sysc_offs	= 0x54,
+	.syss_offs	= 0x58,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class uart_class = {
+	.name = "uart",
+	.sysc = &uart_sysc,
+};
+
+/* UART1 */
+
+static struct omap_hwmod_irq_info uart1_mpu_irqs[] = {
+	{ .irq = INT_24XX_UART1_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart1_sdma_reqs[] = {
+	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART1_TX, },
+	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART1_RX, },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_uart1_slaves[] = {
+	&omap3_l4_core__uart1,
+};
+
+static struct omap_hwmod omap3xxx_uart1_hwmod = {
+	.name		= "uart1",
+	.mpu_irqs	= uart1_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(uart1_mpu_irqs),
+	.sdma_reqs	= uart1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(uart1_sdma_reqs),
+	.main_clk	= "uart1_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_UART1_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_EN_UART1_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_uart1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_uart1_slaves),
+	.class		= &uart_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* UART2 */
+
+static struct omap_hwmod_irq_info uart2_mpu_irqs[] = {
+	{ .irq = INT_24XX_UART2_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart2_sdma_reqs[] = {
+	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART2_TX, },
+	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART2_RX, },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_uart2_slaves[] = {
+	&omap3_l4_core__uart2,
+};
+
+static struct omap_hwmod omap3xxx_uart2_hwmod = {
+	.name		= "uart2",
+	.mpu_irqs	= uart2_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(uart2_mpu_irqs),
+	.sdma_reqs	= uart2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(uart2_sdma_reqs),
+	.main_clk	= "uart2_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_UART2_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_EN_UART2_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_uart2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_uart2_slaves),
+	.class		= &uart_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* UART3 */
+
+static struct omap_hwmod_irq_info uart3_mpu_irqs[] = {
+	{ .irq = INT_24XX_UART3_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart3_sdma_reqs[] = {
+	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART3_TX, },
+	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART3_RX, },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_uart3_slaves[] = {
+	&omap3_l4_per__uart3,
+};
+
+static struct omap_hwmod omap3xxx_uart3_hwmod = {
+	.name		= "uart3",
+	.mpu_irqs	= uart3_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(uart3_mpu_irqs),
+	.sdma_reqs	= uart3_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(uart3_sdma_reqs),
+	.main_clk	= "uart3_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = OMAP3430_PER_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_UART3_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_EN_UART3_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_uart3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_uart3_slaves),
+	.class		= &uart_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* UART4 */
+
+static struct omap_hwmod_irq_info uart4_mpu_irqs[] = {
+	{ .irq = INT_36XX_UART4_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart4_sdma_reqs[] = {
+	{ .name = "rx",	.dma_req = OMAP36XX_DMA_UART4_RX, },
+	{ .name = "tx",	.dma_req = OMAP36XX_DMA_UART4_TX, },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_uart4_slaves[] = {
+	&omap3_l4_per__uart4,
+};
+
+static struct omap_hwmod omap3xxx_uart4_hwmod = {
+	.name		= "uart4",
+	.mpu_irqs	= uart4_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(uart4_mpu_irqs),
+	.sdma_reqs	= uart4_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(uart4_sdma_reqs),
+	.main_clk	= "uart4_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = OMAP3430_PER_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3630_EN_UART4_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3630_EN_UART4_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_uart4_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_uart4_slaves),
+	.class		= &uart_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
+};
+
 static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
 	&omap3xxx_l3_main_hwmod,
 	&omap3xxx_l4_core_hwmod,
@@ -204,6 +516,11 @@
 	&omap3xxx_l4_wkup_hwmod,
 	&omap3xxx_mpu_hwmod,
 	&omap3xxx_iva_hwmod,
+	&omap3xxx_wd_timer2_hwmod,
+	&omap3xxx_uart1_hwmod,
+	&omap3xxx_uart2_hwmod,
+	&omap3xxx_uart3_hwmod,
+	&omap3xxx_uart4_hwmod,
 	NULL,
 };
 
@@ -211,5 +528,3 @@
 {
 	return omap_hwmod_init(omap3xxx_hwmods);
 }
-
-
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
new file mode 100644
index 0000000..7274db4d
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -0,0 +1,850 @@
+/*
+ * Hardware modules present on the OMAP44xx chips
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2009-2010 Nokia Corporation
+ *
+ * Paul Walmsley
+ * Benoit Cousson
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/io.h>
+
+#include <plat/omap_hwmod.h>
+#include <plat/cpu.h>
+
+#include "omap_hwmod_common_data.h"
+
+#include "cm.h"
+#include "prm-regbits-44xx.h"
+
+/* Base offset for all OMAP4 interrupts external to MPUSS */
+#define OMAP44XX_IRQ_GIC_START	32
+
+/* Base offset for all OMAP4 dma requests */
+#define OMAP44XX_DMA_REQ_START  1
+
+/* Backward references (IPs with Bus Master capability) */
+static struct omap_hwmod omap44xx_dmm_hwmod;
+static struct omap_hwmod omap44xx_emif_fw_hwmod;
+static struct omap_hwmod omap44xx_l3_instr_hwmod;
+static struct omap_hwmod omap44xx_l3_main_1_hwmod;
+static struct omap_hwmod omap44xx_l3_main_2_hwmod;
+static struct omap_hwmod omap44xx_l3_main_3_hwmod;
+static struct omap_hwmod omap44xx_l4_abe_hwmod;
+static struct omap_hwmod omap44xx_l4_cfg_hwmod;
+static struct omap_hwmod omap44xx_l4_per_hwmod;
+static struct omap_hwmod omap44xx_l4_wkup_hwmod;
+static struct omap_hwmod omap44xx_mpu_hwmod;
+static struct omap_hwmod omap44xx_mpu_private_hwmod;
+
+/*
+ * Interconnects omap_hwmod structures
+ * hwmods that compose the global OMAP interconnect
+ */
+
+/*
+ * 'dmm' class
+ * instance(s): dmm
+ */
+static struct omap_hwmod_class omap44xx_dmm_hwmod_class = {
+	.name = "dmm",
+};
+
+/* dmm interface data */
+/* l3_main_1 -> dmm */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_1__dmm = {
+	.master		= &omap44xx_l3_main_1_hwmod,
+	.slave		= &omap44xx_dmm_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mpu -> dmm */
+static struct omap_hwmod_ocp_if omap44xx_mpu__dmm = {
+	.master		= &omap44xx_mpu_hwmod,
+	.slave		= &omap44xx_dmm_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dmm slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_dmm_slaves[] = {
+	&omap44xx_l3_main_1__dmm,
+	&omap44xx_mpu__dmm,
+};
+
+static struct omap_hwmod_irq_info omap44xx_dmm_irqs[] = {
+	{ .irq = 113 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod omap44xx_dmm_hwmod = {
+	.name		= "dmm",
+	.class		= &omap44xx_dmm_hwmod_class,
+	.slaves		= omap44xx_dmm_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_dmm_slaves),
+	.mpu_irqs	= omap44xx_dmm_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dmm_irqs),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'emif_fw' class
+ * instance(s): emif_fw
+ */
+static struct omap_hwmod_class omap44xx_emif_fw_hwmod_class = {
+	.name = "emif_fw",
+};
+
+/* emif_fw interface data */
+/* dmm -> emif_fw */
+static struct omap_hwmod_ocp_if omap44xx_dmm__emif_fw = {
+	.master		= &omap44xx_dmm_hwmod,
+	.slave		= &omap44xx_emif_fw_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg -> emif_fw */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__emif_fw = {
+	.master		= &omap44xx_l4_cfg_hwmod,
+	.slave		= &omap44xx_emif_fw_hwmod,
+	.clk		= "l4_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* emif_fw slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_emif_fw_slaves[] = {
+	&omap44xx_dmm__emif_fw,
+	&omap44xx_l4_cfg__emif_fw,
+};
+
+static struct omap_hwmod omap44xx_emif_fw_hwmod = {
+	.name		= "emif_fw",
+	.class		= &omap44xx_emif_fw_hwmod_class,
+	.slaves		= omap44xx_emif_fw_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_emif_fw_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'l3' class
+ * instance(s): l3_instr, l3_main_1, l3_main_2, l3_main_3
+ */
+static struct omap_hwmod_class omap44xx_l3_hwmod_class = {
+	.name = "l3",
+};
+
+/* l3_instr interface data */
+/* l3_main_3 -> l3_instr */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_3__l3_instr = {
+	.master		= &omap44xx_l3_main_3_hwmod,
+	.slave		= &omap44xx_l3_instr_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_instr slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l3_instr_slaves[] = {
+	&omap44xx_l3_main_3__l3_instr,
+};
+
+static struct omap_hwmod omap44xx_l3_instr_hwmod = {
+	.name		= "l3_instr",
+	.class		= &omap44xx_l3_hwmod_class,
+	.slaves		= omap44xx_l3_instr_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_l3_instr_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* l3_main_2 -> l3_main_1 */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__l3_main_1 = {
+	.master		= &omap44xx_l3_main_2_hwmod,
+	.slave		= &omap44xx_l3_main_1_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg -> l3_main_1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_1 = {
+	.master		= &omap44xx_l4_cfg_hwmod,
+	.slave		= &omap44xx_l3_main_1_hwmod,
+	.clk		= "l4_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mpu -> l3_main_1 */
+static struct omap_hwmod_ocp_if omap44xx_mpu__l3_main_1 = {
+	.master		= &omap44xx_mpu_hwmod,
+	.slave		= &omap44xx_l3_main_1_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_1 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l3_main_1_slaves[] = {
+	&omap44xx_l3_main_2__l3_main_1,
+	&omap44xx_l4_cfg__l3_main_1,
+	&omap44xx_mpu__l3_main_1,
+};
+
+static struct omap_hwmod omap44xx_l3_main_1_hwmod = {
+	.name		= "l3_main_1",
+	.class		= &omap44xx_l3_hwmod_class,
+	.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 interface data */
+/* l3_main_1 -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l3_main_2 = {
+	.master		= &omap44xx_l3_main_1_hwmod,
+	.slave		= &omap44xx_l3_main_2_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_2 = {
+	.master		= &omap44xx_l4_cfg_hwmod,
+	.slave		= &omap44xx_l3_main_2_hwmod,
+	.clk		= "l4_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_2 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l3_main_2_slaves[] = {
+	&omap44xx_l3_main_1__l3_main_2,
+	&omap44xx_l4_cfg__l3_main_2,
+};
+
+static struct omap_hwmod omap44xx_l3_main_2_hwmod = {
+	.name		= "l3_main_2",
+	.class		= &omap44xx_l3_hwmod_class,
+	.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 interface data */
+/* l3_main_1 -> l3_main_3 */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l3_main_3 = {
+	.master		= &omap44xx_l3_main_1_hwmod,
+	.slave		= &omap44xx_l3_main_3_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_2 -> l3_main_3 */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__l3_main_3 = {
+	.master		= &omap44xx_l3_main_2_hwmod,
+	.slave		= &omap44xx_l3_main_3_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg -> l3_main_3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_3 = {
+	.master		= &omap44xx_l4_cfg_hwmod,
+	.slave		= &omap44xx_l3_main_3_hwmod,
+	.clk		= "l4_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_3 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l3_main_3_slaves[] = {
+	&omap44xx_l3_main_1__l3_main_3,
+	&omap44xx_l3_main_2__l3_main_3,
+	&omap44xx_l4_cfg__l3_main_3,
+};
+
+static struct omap_hwmod omap44xx_l3_main_3_hwmod = {
+	.name		= "l3_main_3",
+	.class		= &omap44xx_l3_hwmod_class,
+	.slaves		= omap44xx_l3_main_3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_l3_main_3_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'l4' class
+ * instance(s): l4_abe, l4_cfg, l4_per, l4_wkup
+ */
+static struct omap_hwmod_class omap44xx_l4_hwmod_class = {
+	.name = "l4",
+};
+
+/* l4_abe interface data */
+/* l3_main_1 -> l4_abe */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l4_abe = {
+	.master		= &omap44xx_l3_main_1_hwmod,
+	.slave		= &omap44xx_l4_abe_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mpu -> l4_abe */
+static struct omap_hwmod_ocp_if omap44xx_mpu__l4_abe = {
+	.master		= &omap44xx_mpu_hwmod,
+	.slave		= &omap44xx_l4_abe_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_abe slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l4_abe_slaves[] = {
+	&omap44xx_l3_main_1__l4_abe,
+	&omap44xx_mpu__l4_abe,
+};
+
+static struct omap_hwmod omap44xx_l4_abe_hwmod = {
+	.name		= "l4_abe",
+	.class		= &omap44xx_l4_hwmod_class,
+	.slaves		= omap44xx_l4_abe_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_l4_abe_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* l4_cfg interface data */
+/* l3_main_1 -> l4_cfg */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l4_cfg = {
+	.master		= &omap44xx_l3_main_1_hwmod,
+	.slave		= &omap44xx_l4_cfg_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l4_cfg_slaves[] = {
+	&omap44xx_l3_main_1__l4_cfg,
+};
+
+static struct omap_hwmod omap44xx_l4_cfg_hwmod = {
+	.name		= "l4_cfg",
+	.class		= &omap44xx_l4_hwmod_class,
+	.slaves		= omap44xx_l4_cfg_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_l4_cfg_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* l4_per interface data */
+/* l3_main_2 -> l4_per */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__l4_per = {
+	.master		= &omap44xx_l3_main_2_hwmod,
+	.slave		= &omap44xx_l4_per_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l4_per_slaves[] = {
+	&omap44xx_l3_main_2__l4_per,
+};
+
+static struct omap_hwmod omap44xx_l4_per_hwmod = {
+	.name		= "l4_per",
+	.class		= &omap44xx_l4_hwmod_class,
+	.slaves		= omap44xx_l4_per_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_l4_per_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* l4_wkup interface data */
+/* l4_cfg -> l4_wkup */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l4_wkup = {
+	.master		= &omap44xx_l4_cfg_hwmod,
+	.slave		= &omap44xx_l4_wkup_hwmod,
+	.clk		= "l4_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_wkup slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l4_wkup_slaves[] = {
+	&omap44xx_l4_cfg__l4_wkup,
+};
+
+static struct omap_hwmod omap44xx_l4_wkup_hwmod = {
+	.name		= "l4_wkup",
+	.class		= &omap44xx_l4_hwmod_class,
+	.slaves		= omap44xx_l4_wkup_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_l4_wkup_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'mpu_bus' class
+ * instance(s): mpu_private
+ */
+static struct omap_hwmod_class omap44xx_mpu_bus_hwmod_class = {
+	.name = "mpu_bus",
+};
+
+/* mpu_private interface data */
+/* mpu -> mpu_private */
+static struct omap_hwmod_ocp_if omap44xx_mpu__mpu_private = {
+	.master		= &omap44xx_mpu_hwmod,
+	.slave		= &omap44xx_mpu_private_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mpu_private slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mpu_private_slaves[] = {
+	&omap44xx_mpu__mpu_private,
+};
+
+static struct omap_hwmod omap44xx_mpu_private_hwmod = {
+	.name		= "mpu_private",
+	.class		= &omap44xx_mpu_bus_hwmod_class,
+	.slaves		= omap44xx_mpu_private_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mpu_private_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'mpu' class
+ * mpu sub-system
+ */
+
+static struct omap_hwmod_class omap44xx_mpu_hwmod_class = {
+	.name = "mpu",
+};
+
+/* mpu */
+static struct omap_hwmod_irq_info omap44xx_mpu_irqs[] = {
+	{ .name = "pl310", .irq = 0 + OMAP44XX_IRQ_GIC_START },
+	{ .name = "cti0", .irq = 1 + OMAP44XX_IRQ_GIC_START },
+	{ .name = "cti1", .irq = 2 + OMAP44XX_IRQ_GIC_START },
+};
+
+/* mpu master ports */
+static struct omap_hwmod_ocp_if *omap44xx_mpu_masters[] = {
+	&omap44xx_mpu__l3_main_1,
+	&omap44xx_mpu__l4_abe,
+	&omap44xx_mpu__dmm,
+};
+
+static struct omap_hwmod omap44xx_mpu_hwmod = {
+	.name		= "mpu",
+	.class		= &omap44xx_mpu_hwmod_class,
+	.flags		= (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
+	.mpu_irqs	= omap44xx_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mpu_irqs),
+	.main_clk	= "dpll_mpu_m2_ck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_MPU_MPU_CLKCTRL,
+		},
+	},
+	.masters	= omap44xx_mpu_masters,
+	.masters_cnt	= ARRAY_SIZE(omap44xx_mpu_masters),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'wd_timer' class
+ * 32-bit watchdog upward counter that generates a pulse on the reset pin on
+ * overflow condition
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_wd_timer_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_EMUFREE |
+			   SYSC_HAS_SOFTRESET),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+/*
+ * 'uart' class
+ * universal asynchronous receiver/transmitter (uart)
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_uart_sysc = {
+	.rev_offs	= 0x0050,
+	.sysc_offs	= 0x0054,
+	.syss_offs	= 0x0058,
+	.sysc_flags	= (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_wd_timer_hwmod_class = {
+	.name = "wd_timer",
+	.sysc = &omap44xx_wd_timer_sysc,
+};
+
+/* wd_timer2 */
+static struct omap_hwmod omap44xx_wd_timer2_hwmod;
+static struct omap_hwmod_irq_info omap44xx_wd_timer2_irqs[] = {
+	{ .irq = 80 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_wd_timer2_addrs[] = {
+	{
+		.pa_start	= 0x4a314000,
+		.pa_end		= 0x4a31407f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_class omap44xx_uart_hwmod_class = {
+	.name = "uart",
+	.sysc = &omap44xx_uart_sysc,
+};
+
+/* uart1 */
+static struct omap_hwmod omap44xx_uart1_hwmod;
+static struct omap_hwmod_irq_info omap44xx_uart1_irqs[] = {
+	{ .irq = 72 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_uart1_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = 48 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx", .dma_req = 49 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_uart1_addrs[] = {
+	{
+		.pa_start	= 0x4806a000,
+		.pa_end		= 0x4806a0ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> uart1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__uart1 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_uart1_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_uart1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_uart1_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* uart1 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_uart1_slaves[] = {
+	&omap44xx_l4_per__uart1,
+};
+
+static struct omap_hwmod omap44xx_uart1_hwmod = {
+	.name		= "uart1",
+	.class		= &omap44xx_uart_hwmod_class,
+	.mpu_irqs	= omap44xx_uart1_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_uart1_irqs),
+	.sdma_reqs	= omap44xx_uart1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_uart1_sdma_reqs),
+	.main_clk	= "uart1_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_UART1_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_uart1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_uart1_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* uart2 */
+static struct omap_hwmod omap44xx_uart2_hwmod;
+static struct omap_hwmod_irq_info omap44xx_uart2_irqs[] = {
+	{ .irq = 73 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_uart2_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = 50 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx", .dma_req = 51 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_uart2_addrs[] = {
+	{
+		.pa_start	= 0x4806c000,
+		.pa_end		= 0x4806c0ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_wkup -> wd_timer2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_wkup__wd_timer2 = {
+	.master		= &omap44xx_l4_wkup_hwmod,
+	.slave		= &omap44xx_wd_timer2_hwmod,
+	.clk		= "l4_wkup_clk_mux_ck",
+	.addr		= omap44xx_wd_timer2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_wd_timer2_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* wd_timer2 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_wd_timer2_slaves[] = {
+	&omap44xx_l4_wkup__wd_timer2,
+};
+
+static struct omap_hwmod omap44xx_wd_timer2_hwmod = {
+	.name		= "wd_timer2",
+	.class		= &omap44xx_wd_timer_hwmod_class,
+	.mpu_irqs	= omap44xx_wd_timer2_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_wd_timer2_irqs),
+	.main_clk	= "wd_timer2_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_WKUP_WDT2_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_wd_timer2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_wd_timer2_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* wd_timer3 */
+static struct omap_hwmod omap44xx_wd_timer3_hwmod;
+static struct omap_hwmod_irq_info omap44xx_wd_timer3_irqs[] = {
+	{ .irq = 36 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_wd_timer3_addrs[] = {
+	{
+		.pa_start	= 0x40130000,
+		.pa_end		= 0x4013007f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> uart2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__uart2 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_uart2_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_uart2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_uart2_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* uart2 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_uart2_slaves[] = {
+	&omap44xx_l4_per__uart2,
+};
+
+static struct omap_hwmod omap44xx_uart2_hwmod = {
+	.name		= "uart2",
+	.class		= &omap44xx_uart_hwmod_class,
+	.mpu_irqs	= omap44xx_uart2_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_uart2_irqs),
+	.sdma_reqs	= omap44xx_uart2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_uart2_sdma_reqs),
+	.main_clk	= "uart2_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_UART2_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_uart2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_uart2_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* uart3 */
+static struct omap_hwmod omap44xx_uart3_hwmod;
+static struct omap_hwmod_irq_info omap44xx_uart3_irqs[] = {
+	{ .irq = 74 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_uart3_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = 52 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx", .dma_req = 53 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_uart3_addrs[] = {
+	{
+		.pa_start	= 0x48020000,
+		.pa_end		= 0x480200ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> wd_timer3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__wd_timer3 = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_wd_timer3_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_wd_timer3_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_wd_timer3_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+/* l4_abe -> wd_timer3 (dma) */
+static struct omap_hwmod_addr_space omap44xx_wd_timer3_dma_addrs[] = {
+	{
+		.pa_start	= 0x49030000,
+		.pa_end		= 0x4903007f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> uart3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__uart3 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_uart3_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_uart3_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_uart3_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* uart3 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_uart3_slaves[] = {
+	&omap44xx_l4_per__uart3,
+};
+
+static struct omap_hwmod omap44xx_uart3_hwmod = {
+	.name		= "uart3",
+	.class		= &omap44xx_uart_hwmod_class,
+	.flags		= (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
+	.mpu_irqs	= omap44xx_uart3_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_uart3_irqs),
+	.sdma_reqs	= omap44xx_uart3_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_uart3_sdma_reqs),
+	.main_clk	= "uart3_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_UART3_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_uart3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_uart3_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* uart4 */
+static struct omap_hwmod omap44xx_uart4_hwmod;
+static struct omap_hwmod_irq_info omap44xx_uart4_irqs[] = {
+	{ .irq = 70 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_uart4_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = 54 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx", .dma_req = 55 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_uart4_addrs[] = {
+	{
+		.pa_start	= 0x4806e000,
+		.pa_end		= 0x4806e0ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__wd_timer3_dma = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_wd_timer3_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_wd_timer3_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_wd_timer3_dma_addrs),
+	.user		= OCP_USER_SDMA,
+};
+
+/* wd_timer3 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_wd_timer3_slaves[] = {
+	&omap44xx_l4_abe__wd_timer3,
+	&omap44xx_l4_abe__wd_timer3_dma,
+};
+
+static struct omap_hwmod omap44xx_wd_timer3_hwmod = {
+	.name		= "wd_timer3",
+	.class		= &omap44xx_wd_timer_hwmod_class,
+	.mpu_irqs	= omap44xx_wd_timer3_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_wd_timer3_irqs),
+	.main_clk	= "wd_timer3_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM1_ABE_WDT3_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_wd_timer3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_wd_timer3_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* l4_per -> uart4 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__uart4 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_uart4_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_uart4_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_uart4_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* uart4 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_uart4_slaves[] = {
+	&omap44xx_l4_per__uart4,
+};
+
+static struct omap_hwmod omap44xx_uart4_hwmod = {
+	.name		= "uart4",
+	.class		= &omap44xx_uart_hwmod_class,
+	.mpu_irqs	= omap44xx_uart4_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_uart4_irqs),
+	.sdma_reqs	= omap44xx_uart4_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_uart4_sdma_reqs),
+	.main_clk	= "uart4_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_UART4_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_uart4_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_uart4_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
+	/* dmm class */
+	&omap44xx_dmm_hwmod,
+	/* emif_fw class */
+	&omap44xx_emif_fw_hwmod,
+	/* l3 class */
+	&omap44xx_l3_instr_hwmod,
+	&omap44xx_l3_main_1_hwmod,
+	&omap44xx_l3_main_2_hwmod,
+	&omap44xx_l3_main_3_hwmod,
+	/* l4 class */
+	&omap44xx_l4_abe_hwmod,
+	&omap44xx_l4_cfg_hwmod,
+	&omap44xx_l4_per_hwmod,
+	&omap44xx_l4_wkup_hwmod,
+	/* mpu_bus class */
+	&omap44xx_mpu_private_hwmod,
+
+	/* mpu class */
+	&omap44xx_mpu_hwmod,
+	/* wd_timer class */
+	&omap44xx_wd_timer2_hwmod,
+	&omap44xx_wd_timer3_hwmod,
+
+	/* uart class */
+	&omap44xx_uart1_hwmod,
+	&omap44xx_uart2_hwmod,
+	&omap44xx_uart3_hwmod,
+	&omap44xx_uart4_hwmod,
+	NULL,
+};
+
+int __init omap44xx_hwmod_init(void)
+{
+	return omap_hwmod_init(omap44xx_hwmods);
+}
+
diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index 723b44e..5e81517 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -31,12 +31,17 @@
 #include <plat/board.h>
 #include <plat/powerdomain.h>
 #include <plat/clockdomain.h>
+#include <plat/dmtimer.h>
 
 #include "prm.h"
 #include "cm.h"
 #include "pm.h"
 
 int omap2_pm_debug;
+u32 enable_off_mode;
+u32 sleep_while_idle;
+u32 wakeup_timer_seconds;
+u32 wakeup_timer_milliseconds;
 
 #define DUMP_PRM_MOD_REG(mod, reg)    \
 	regs[reg_count].name = #mod "." #reg; \
@@ -162,7 +167,7 @@
 
 static void pm_dbg_regset_store(u32 *ptr);
 
-struct dentry *pm_dbg_dir;
+static struct dentry *pm_dbg_dir;
 
 static int pm_dbg_init_done;
 
@@ -349,6 +354,23 @@
 	pwrdm->timer = t;
 }
 
+void omap2_pm_wakeup_on_timer(u32 seconds, u32 milliseconds)
+{
+	u32 tick_rate, cycles;
+
+	if (!seconds && !milliseconds)
+		return;
+
+	tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer_wakeup));
+	cycles = tick_rate * seconds + tick_rate * milliseconds / 1000;
+	omap_dm_timer_stop(gptimer_wakeup);
+	omap_dm_timer_set_load_start(gptimer_wakeup, 0, 0xffffffff - cycles);
+
+	pr_info("PM: Resume timer in %u.%03u secs"
+		" (%d ticks at %d ticks/sec.)\n",
+		seconds, milliseconds, cycles, tick_rate);
+}
+
 static int clkdm_dbg_show_counter(struct clockdomain *clkdm, void *user)
 {
 	struct seq_file *s = (struct seq_file *)user;
@@ -494,8 +516,10 @@
 
 static int pwrdm_suspend_get(void *data, u64 *val)
 {
-	int ret;
-	ret = omap3_pm_get_suspend_state((struct powerdomain *)data);
+	int ret = -EINVAL;
+
+	if (cpu_is_omap34xx())
+		ret = omap3_pm_get_suspend_state((struct powerdomain *)data);
 	*val = ret;
 
 	if (ret >= 0)
@@ -505,7 +529,10 @@
 
 static int pwrdm_suspend_set(void *data, u64 val)
 {
-	return omap3_pm_set_suspend_state((struct powerdomain *)data, (int)val);
+	if (cpu_is_omap34xx())
+		return omap3_pm_set_suspend_state(
+			(struct powerdomain *)data, (int)val);
+	return -EINVAL;
 }
 
 DEFINE_SIMPLE_ATTRIBUTE(pwrdm_suspend_fops, pwrdm_suspend_get,
@@ -553,8 +580,10 @@
 
 	*option = val;
 
-	if (option == &enable_off_mode)
-		omap3_pm_off_mode_enable(val);
+	if (option == &enable_off_mode) {
+		if (cpu_is_omap34xx())
+			omap3_pm_off_mode_enable(val);
+	}
 
 	return 0;
 }
@@ -609,6 +638,9 @@
 				   &sleep_while_idle, &pm_dbg_option_fops);
 	(void) debugfs_create_file("wakeup_timer_seconds", S_IRUGO | S_IWUGO, d,
 				   &wakeup_timer_seconds, &pm_dbg_option_fops);
+	(void) debugfs_create_file("wakeup_timer_milliseconds",
+			S_IRUGO | S_IWUGO, d, &wakeup_timer_milliseconds,
+			&pm_dbg_option_fops);
 	pm_dbg_init_done = 1;
 
 	return 0;
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 68f9f2e..59ca03b 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -18,11 +18,15 @@
 #include <plat/omap_device.h>
 #include <plat/common.h>
 
+#include <plat/powerdomain.h>
+#include <plat/clockdomain.h>
+
 static struct omap_device_pm_latency *pm_lats;
 
 static struct device *mpu_dev;
-static struct device *dsp_dev;
+static struct device *iva_dev;
 static struct device *l3_dev;
+static struct device *dsp_dev;
 
 struct device *omap2_get_mpuss_device(void)
 {
@@ -30,10 +34,10 @@
 	return mpu_dev;
 }
 
-struct device *omap2_get_dsp_device(void)
+struct device *omap2_get_iva_device(void)
 {
-	WARN_ON_ONCE(!dsp_dev);
-	return dsp_dev;
+	WARN_ON_ONCE(!iva_dev);
+	return iva_dev;
 }
 
 struct device *omap2_get_l3_device(void)
@@ -42,6 +46,13 @@
 	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)
 {
@@ -69,8 +80,60 @@
 static void omap2_init_processor_devices(void)
 {
 	_init_omap_device("mpu", &mpu_dev);
-	_init_omap_device("iva", &dsp_dev);
-	_init_omap_device("l3_main", &l3_dev);
+	_init_omap_device("iva", &iva_dev);
+	if (cpu_is_omap44xx()) {
+		_init_omap_device("l3_main_1", &l3_dev);
+		_init_omap_device("dsp", &dsp_dev);
+	} else {
+		_init_omap_device("l3_main", &l3_dev);
+	}
+}
+
+/*
+ * This sets pwrdm state (other than mpu & core. Currently only ON &
+ * RET are supported. Function is assuming that clkdm doesn't have
+ * hw_sup mode enabled.
+ */
+int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
+{
+	u32 cur_state;
+	int sleep_switch = 0;
+	int ret = 0;
+
+	if (pwrdm == NULL || IS_ERR(pwrdm))
+		return -EINVAL;
+
+	while (!(pwrdm->pwrsts & (1 << state))) {
+		if (state == PWRDM_POWER_OFF)
+			return ret;
+		state--;
+	}
+
+	cur_state = pwrdm_read_next_pwrst(pwrdm);
+	if (cur_state == state)
+		return ret;
+
+	if (pwrdm_read_pwrst(pwrdm) < PWRDM_POWER_ON) {
+		omap2_clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
+		sleep_switch = 1;
+		pwrdm_wait_transition(pwrdm);
+	}
+
+	ret = pwrdm_set_next_pwrst(pwrdm, state);
+	if (ret) {
+		printk(KERN_ERR "Unable to set state of powerdomain: %s\n",
+		       pwrdm->name);
+		goto err;
+	}
+
+	if (sleep_switch) {
+		omap2_clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
+		pwrdm_wait_transition(pwrdm);
+		pwrdm_state_switch(pwrdm);
+	}
+
+err:
+	return ret;
 }
 
 static int __init omap2_common_pm_init(void)
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 3de6ece..0d75bfd 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -13,14 +13,11 @@
 
 #include <plat/powerdomain.h>
 
-extern u32 enable_off_mode;
-extern u32 sleep_while_idle;
-
 extern void *omap3_secure_ram_storage;
 extern void omap3_pm_off_mode_enable(int);
 extern void omap_sram_idle(void);
 extern int omap3_can_sleep(void);
-extern int set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
+extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
 extern int omap3_idle_init(void);
 
 struct cpuidle_params {
@@ -48,10 +45,16 @@
 
 #ifdef CONFIG_PM_DEBUG
 extern void omap2_pm_dump(int mode, int resume, unsigned int us);
+extern void omap2_pm_wakeup_on_timer(u32 seconds, u32 milliseconds);
 extern int omap2_pm_debug;
+extern u32 enable_off_mode;
+extern u32 sleep_while_idle;
 #else
 #define omap2_pm_dump(mode, resume, us)		do {} while (0);
+#define omap2_pm_wakeup_on_timer(seconds, milliseconds)	do {} while (0);
 #define omap2_pm_debug				0
+#define enable_off_mode 0
+#define sleep_while_idle 0
 #endif
 
 #if defined(CONFIG_CPU_IDLE)
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index 6aeedea..a40457d 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -38,7 +38,6 @@
 #include <mach/irqs.h>
 #include <plat/clock.h>
 #include <plat/sram.h>
-#include <plat/control.h>
 #include <plat/dma.h>
 #include <plat/board.h>
 
@@ -48,6 +47,7 @@
 #include "cm-regbits-24xx.h"
 #include "sdrc.h"
 #include "pm.h"
+#include "control.h"
 
 #include <plat/powerdomain.h>
 #include <plat/clockdomain.h>
@@ -245,6 +245,8 @@
 {
 	if (omap2_fclks_active())
 		return 0;
+	if (!omap_uart_can_sleep())
+		return 0;
 	if (osc_ck->usecount > 1)
 		return 0;
 	if (omap_dma_running())
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 7b03426..75c0cd1 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -32,13 +32,11 @@
 #include <plat/sram.h>
 #include <plat/clockdomain.h>
 #include <plat/powerdomain.h>
-#include <plat/control.h>
 #include <plat/serial.h>
 #include <plat/sdrc.h>
 #include <plat/prcm.h>
 #include <plat/gpmc.h>
 #include <plat/dma.h>
-#include <plat/dmtimer.h>
 
 #include <asm/tlbflush.h>
 
@@ -49,16 +47,12 @@
 #include "prm.h"
 #include "pm.h"
 #include "sdrc.h"
+#include "control.h"
 
 /* Scratchpad offsets */
-#define OMAP343X_TABLE_ADDRESS_OFFSET	   0x31
-#define OMAP343X_TABLE_VALUE_OFFSET	   0x30
-#define OMAP343X_CONTROL_REG_VALUE_OFFSET  0x32
-
-u32 enable_off_mode;
-u32 sleep_while_idle;
-u32 wakeup_timer_seconds;
-u32 wakeup_timer_milliseconds;
+#define OMAP343X_TABLE_ADDRESS_OFFSET	   0xc4
+#define OMAP343X_TABLE_VALUE_OFFSET	   0xc0
+#define OMAP343X_CONTROL_REG_VALUE_OFFSET  0xc8
 
 struct power_state {
 	struct powerdomain *pwrdm;
@@ -316,7 +310,7 @@
 /* Function to restore the table entry that was modified for enabling MMU */
 static void restore_table_entry(void)
 {
-	u32 *scratchpad_address;
+	void __iomem *scratchpad_address;
 	u32 previous_value, control_reg_value;
 	u32 *address;
 
@@ -351,7 +345,6 @@
 	int core_next_state = PWRDM_POWER_ON;
 	int core_prev_state, per_prev_state;
 	u32 sdrc_pwr = 0;
-	int per_state_modified = 0;
 
 	if (!_omap_sram_idle)
 		return;
@@ -385,9 +378,9 @@
 	/* Enable IO-PAD and IO-CHAIN wakeups */
 	per_next_state = pwrdm_read_next_pwrst(per_pwrdm);
 	core_next_state = pwrdm_read_next_pwrst(core_pwrdm);
-	if (omap3_has_io_wakeup() && \
-			(per_next_state < PWRDM_POWER_ON ||
-			core_next_state < PWRDM_POWER_ON)) {
+	if (omap3_has_io_wakeup() &&
+	    (per_next_state < PWRDM_POWER_ON ||
+	     core_next_state < PWRDM_POWER_ON)) {
 		prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, PM_WKEN);
 		omap3_enable_io_chain();
 	}
@@ -395,20 +388,12 @@
 	/* PER */
 	if (per_next_state < PWRDM_POWER_ON) {
 		omap_uart_prepare_idle(2);
+		omap_uart_prepare_idle(3);
 		omap2_gpio_prepare_for_idle(per_next_state);
-		if (per_next_state == PWRDM_POWER_OFF) {
-			if (core_next_state == PWRDM_POWER_ON) {
-				per_next_state = PWRDM_POWER_RET;
-				pwrdm_set_next_pwrst(per_pwrdm, per_next_state);
-				per_state_modified = 1;
-			} else
+		if (per_next_state == PWRDM_POWER_OFF)
 				omap3_per_save_context();
-		}
 	}
 
-	if (pwrdm_read_pwrst(cam_pwrdm) == PWRDM_POWER_ON)
-		omap2_clkdm_deny_idle(mpu_pwrdm->pwrdm_clkdms[0]);
-
 	/* CORE */
 	if (core_next_state < PWRDM_POWER_ON) {
 		omap_uart_prepare_idle(0);
@@ -475,8 +460,7 @@
 		if (per_prev_state == PWRDM_POWER_OFF)
 			omap3_per_restore_context();
 		omap_uart_resume_idle(2);
-		if (per_state_modified)
-			pwrdm_set_next_pwrst(per_pwrdm, PWRDM_POWER_OFF);
+		omap_uart_resume_idle(3);
 	}
 
 	/* Disable IO-PAD and IO-CHAIN wakeup */
@@ -501,51 +485,6 @@
 	return 1;
 }
 
-/* This sets pwrdm state (other than mpu & core. Currently only ON &
- * RET are supported. Function is assuming that clkdm doesn't have
- * hw_sup mode enabled. */
-int set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
-{
-	u32 cur_state;
-	int sleep_switch = 0;
-	int ret = 0;
-
-	if (pwrdm == NULL || IS_ERR(pwrdm))
-		return -EINVAL;
-
-	while (!(pwrdm->pwrsts & (1 << state))) {
-		if (state == PWRDM_POWER_OFF)
-			return ret;
-		state--;
-	}
-
-	cur_state = pwrdm_read_next_pwrst(pwrdm);
-	if (cur_state == state)
-		return ret;
-
-	if (pwrdm_read_pwrst(pwrdm) < PWRDM_POWER_ON) {
-		omap2_clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
-		sleep_switch = 1;
-		pwrdm_wait_transition(pwrdm);
-	}
-
-	ret = pwrdm_set_next_pwrst(pwrdm, state);
-	if (ret) {
-		printk(KERN_ERR "Unable to set state of powerdomain: %s\n",
-		       pwrdm->name);
-		goto err;
-	}
-
-	if (sleep_switch) {
-		omap2_clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
-		pwrdm_wait_transition(pwrdm);
-		pwrdm_state_switch(pwrdm);
-	}
-
-err:
-	return ret;
-}
-
 static void omap3_pm_idle(void)
 {
 	local_irq_disable();
@@ -567,23 +506,6 @@
 #ifdef CONFIG_SUSPEND
 static suspend_state_t suspend_state;
 
-static void omap2_pm_wakeup_on_timer(u32 seconds, u32 milliseconds)
-{
-	u32 tick_rate, cycles;
-
-	if (!seconds && !milliseconds)
-		return;
-
-	tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer_wakeup));
-	cycles = tick_rate * seconds + tick_rate * milliseconds / 1000;
-	omap_dm_timer_stop(gptimer_wakeup);
-	omap_dm_timer_set_load_start(gptimer_wakeup, 0, 0xffffffff - cycles);
-
-	pr_info("PM: Resume timer in %u.%03u secs"
-		" (%d ticks at %d ticks/sec.)\n",
-		seconds, milliseconds, cycles, tick_rate);
-}
-
 static int omap3_pm_prepare(void)
 {
 	disable_hlt();
@@ -604,7 +526,7 @@
 		pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm);
 	/* Set ones wanted by suspend */
 	list_for_each_entry(pwrst, &pwrst_list, node) {
-		if (set_pwrdm_state(pwrst->pwrdm, pwrst->next_state))
+		if (omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state))
 			goto restore;
 		if (pwrdm_clear_all_prev_pwrst(pwrst->pwrdm))
 			goto restore;
@@ -625,7 +547,7 @@
 			       pwrst->pwrdm->name, pwrst->next_state);
 			ret = -1;
 		}
-		set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state);
+		omap_set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state);
 	}
 	if (ret)
 		printk(KERN_ERR "Could not enter target state in pm_suspend\n");
@@ -756,6 +678,14 @@
 
 static void __init prcm_setup_regs(void)
 {
+	u32 omap3630_auto_uart4_mask = cpu_is_omap3630() ?
+					OMAP3630_AUTO_UART4_MASK : 0;
+	u32 omap3630_en_uart4_mask = cpu_is_omap3630() ?
+					OMAP3630_EN_UART4_MASK : 0;
+	u32 omap3630_grpsel_uart4_mask = cpu_is_omap3630() ?
+					OMAP3630_GRPSEL_UART4_MASK : 0;
+
+
 	/* XXX Reset all wkdeps. This should be done when initializing
 	 * powerdomains */
 	prm_write_mod_reg(0, OMAP3430_IVA2_MOD, PM_WKDEP);
@@ -842,6 +772,7 @@
 		CM_AUTOIDLE);
 
 	cm_write_mod_reg(
+		omap3630_auto_uart4_mask |
 		OMAP3430_AUTO_GPIO6_MASK |
 		OMAP3430_AUTO_GPIO5_MASK |
 		OMAP3430_AUTO_GPIO4_MASK |
@@ -918,14 +849,16 @@
 				OMAP3430_DSS_MOD, PM_WKEN);
 
 	/* Enable wakeups in PER */
-	prm_write_mod_reg(OMAP3430_EN_GPIO2_MASK | OMAP3430_EN_GPIO3_MASK |
+	prm_write_mod_reg(omap3630_en_uart4_mask |
+			  OMAP3430_EN_GPIO2_MASK | OMAP3430_EN_GPIO3_MASK |
 			  OMAP3430_EN_GPIO4_MASK | OMAP3430_EN_GPIO5_MASK |
 			  OMAP3430_EN_GPIO6_MASK | OMAP3430_EN_UART3_MASK |
 			  OMAP3430_EN_MCBSP2_MASK | OMAP3430_EN_MCBSP3_MASK |
 			  OMAP3430_EN_MCBSP4_MASK,
 			  OMAP3430_PER_MOD, PM_WKEN);
 	/* and allow them to wake up MPU */
-	prm_write_mod_reg(OMAP3430_GRPSEL_GPIO2_MASK |
+	prm_write_mod_reg(omap3630_grpsel_uart4_mask |
+			  OMAP3430_GRPSEL_GPIO2_MASK |
 			  OMAP3430_GRPSEL_GPIO3_MASK |
 			  OMAP3430_GRPSEL_GPIO4_MASK |
 			  OMAP3430_GRPSEL_GPIO5_MASK |
@@ -974,7 +907,7 @@
 
 	list_for_each_entry(pwrst, &pwrst_list, node) {
 		pwrst->next_state = state;
-		set_pwrdm_state(pwrst->pwrdm, state);
+		omap_set_pwrdm_state(pwrst->pwrdm, state);
 	}
 }
 
@@ -1019,7 +952,7 @@
 	if (pwrdm_has_hdwr_sar(pwrdm))
 		pwrdm_enable_hdwr_sar(pwrdm);
 
-	return set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
+	return omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
 }
 
 /*
@@ -1029,9 +962,6 @@
  */
 static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
 {
-	clkdm_clear_all_wkdeps(clkdm);
-	clkdm_clear_all_sleepdeps(clkdm);
-
 	if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
 		omap2_clkdm_allow_idle(clkdm);
 	else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&
diff --git a/arch/arm/mach-omap2/pm_bus.c b/arch/arm/mach-omap2/pm_bus.c
new file mode 100644
index 0000000..784989f
--- /dev/null
+++ b/arch/arm/mach-omap2/pm_bus.c
@@ -0,0 +1,85 @@
+/*
+ * Runtime PM support code for OMAP
+ *
+ * Author: Kevin Hilman, Deep Root Systems, LLC
+ *
+ * Copyright (C) 2010 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/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/pm_runtime.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+
+#include <plat/omap_device.h>
+#include <plat/omap-pm.h>
+
+#ifdef CONFIG_PM_RUNTIME
+int omap_pm_runtime_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	int r, ret = 0;
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	ret = pm_generic_runtime_suspend(dev);
+
+	if (!ret && dev->parent == &omap_device_parent) {
+		r = omap_device_idle(pdev);
+		WARN_ON(r);
+	}
+
+	return ret;
+};
+
+int omap_pm_runtime_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	int r;
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	if (dev->parent == &omap_device_parent) {
+		r = omap_device_enable(pdev);
+		WARN_ON(r);
+	}
+
+	return pm_generic_runtime_resume(dev);
+};
+#else
+#define omap_pm_runtime_suspend NULL
+#define omap_pm_runtime_resume NULL
+#endif /* CONFIG_PM_RUNTIME */
+
+static int __init omap_pm_runtime_init(void)
+{
+	const struct dev_pm_ops *pm;
+	struct dev_pm_ops *omap_pm;
+
+	pm = platform_bus_get_pm_ops();
+	if (!pm) {
+		pr_err("%s: unable to get dev_pm_ops from platform_bus\n",
+			__func__);
+		return -ENODEV;
+	}
+
+	omap_pm = kmemdup(pm, sizeof(struct dev_pm_ops), GFP_KERNEL);
+	if (!omap_pm) {
+		pr_err("%s: unable to alloc memory for new dev_pm_ops\n",
+			__func__);
+		return -ENOMEM;
+	}
+
+	omap_pm->runtime_suspend = omap_pm_runtime_suspend;
+	omap_pm->runtime_resume = omap_pm_runtime_resume;
+
+	platform_bus_set_pm_ops(omap_pm);
+
+	return 0;
+}
+core_initcall(omap_pm_runtime_init);
diff --git a/arch/arm/mach-omap2/powerdomains44xx.h b/arch/arm/mach-omap2/powerdomains44xx.h
index c721951..9c01b55 100644
--- a/arch/arm/mach-omap2/powerdomains44xx.h
+++ b/arch/arm/mach-omap2/powerdomains44xx.h
@@ -98,7 +98,7 @@
 	.prcm_offs	  = OMAP4430_PRM_DSS_MOD,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRSTS_OFF_RET,
+	.pwrsts_logic_ret = PWRSTS_OFF,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
 		[0] = PWRDM_POWER_OFF,	/* dss_mem */
diff --git a/arch/arm/mach-omap2/prcm-common.h b/arch/arm/mach-omap2/prcm-common.h
index 995b7ed..298a22a 100644
--- a/arch/arm/mach-omap2/prcm-common.h
+++ b/arch/arm/mach-omap2/prcm-common.h
@@ -382,6 +382,9 @@
 #define OMAP3430_EN_MPU_SHIFT				1
 
 /* CM_FCLKEN_PER, CM_ICLKEN_PER, PM_WKEN_PER shared bits */
+
+#define OMAP3630_EN_UART4_MASK				(1 << 18)
+#define OMAP3630_EN_UART4_SHIFT				18
 #define OMAP3430_EN_GPIO6_MASK				(1 << 17)
 #define OMAP3430_EN_GPIO6_SHIFT				17
 #define OMAP3430_EN_GPIO5_MASK				(1 << 16)
@@ -422,6 +425,8 @@
 #define OMAP3430_EN_MCBSP2_SHIFT			0
 
 /* CM_IDLEST_PER, PM_WKST_PER shared bits */
+#define OMAP3630_ST_UART4_SHIFT				18
+#define OMAP3630_ST_UART4_MASK				(1 << 18)
 #define OMAP3430_ST_GPIO6_SHIFT				17
 #define OMAP3430_ST_GPIO6_MASK				(1 << 17)
 #define OMAP3430_ST_GPIO5_SHIFT				16
diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
index c201374..a51846e 100644
--- a/arch/arm/mach-omap2/prcm.c
+++ b/arch/arm/mach-omap2/prcm.c
@@ -26,13 +26,14 @@
 #include <plat/common.h>
 #include <plat/prcm.h>
 #include <plat/irqs.h>
-#include <plat/control.h>
 
 #include "clock.h"
 #include "clock2xxx.h"
 #include "cm.h"
 #include "prm.h"
 #include "prm-regbits-24xx.h"
+#include "prm-regbits-44xx.h"
+#include "control.h"
 
 static void __iomem *prm_base;
 static void __iomem *cm_base;
@@ -118,7 +119,7 @@
 	u32 wkup_pm_wken;
 };
 
-struct omap3_prcm_regs prcm_context;
+static struct omap3_prcm_regs prcm_context;
 
 u32 omap_prcm_get_reset_sources(void)
 {
@@ -161,8 +162,8 @@
 		prm_set_mod_reg_bits(OMAP_RST_DPLL3_MASK, prcm_offs,
 						 OMAP2_RM_RSTCTRL);
 	if (cpu_is_omap44xx())
-		prm_set_mod_reg_bits(OMAP_RST_DPLL3_MASK, prcm_offs,
-						 OMAP4_RM_RSTCTRL);
+		prm_set_mod_reg_bits(OMAP4430_RST_GLOBAL_WARM_SW_MASK,
+				     prcm_offs, OMAP4_RM_RSTCTRL);
 }
 
 static inline u32 __omap_prcm_read(void __iomem *base, s16 module, u16 reg)
@@ -215,6 +216,30 @@
 	return v;
 }
 
+/* Read a PRM register, AND it, and shift the result down to bit 0 */
+u32 omap4_prm_read_bits_shift(void __iomem *reg, u32 mask)
+{
+	u32 v;
+
+	v = __raw_readl(reg);
+	v &= mask;
+	v >>= __ffs(mask);
+
+	return v;
+}
+
+/* Read-modify-write a register in a PRM module. Caller must lock */
+u32 omap4_prm_rmw_reg_bits(u32 mask, u32 bits, void __iomem *reg)
+{
+	u32 v;
+
+	v = __raw_readl(reg);
+	v &= ~mask;
+	v |= bits;
+	__raw_writel(v, reg);
+
+	return v;
+}
 /* Read a register in a CM module */
 u32 cm_read_mod_reg(s16 module, u16 idx)
 {
diff --git a/arch/arm/mach-omap2/prm-regbits-34xx.h b/arch/arm/mach-omap2/prm-regbits-34xx.h
index 7fd6023..9e63cb7 100644
--- a/arch/arm/mach-omap2/prm-regbits-34xx.h
+++ b/arch/arm/mach-omap2/prm-regbits-34xx.h
@@ -122,6 +122,7 @@
 #define OMAP3430_MEMRETSTATE_MASK			(1 << 8)
 
 /* PM_MPUGRPSEL_PER, PM_IVA2GRPSEL_PER shared bits */
+#define OMAP3630_GRPSEL_UART4_MASK			(1 << 18)
 #define OMAP3430_GRPSEL_GPIO6_MASK			(1 << 17)
 #define OMAP3430_GRPSEL_GPIO5_MASK			(1 << 16)
 #define OMAP3430_GRPSEL_GPIO4_MASK			(1 << 15)
diff --git a/arch/arm/mach-omap2/prm-regbits-44xx.h b/arch/arm/mach-omap2/prm-regbits-44xx.h
index 597be4a..25b19b6 100644
--- a/arch/arm/mach-omap2/prm-regbits-44xx.h
+++ b/arch/arm/mach-omap2/prm-regbits-44xx.h
@@ -1,8 +1,8 @@
 /*
  * OMAP44xx Power Management register bits
  *
- * Copyright (C) 2009 Texas Instruments, Inc.
- * Copyright (C) 2009 Nokia Corporation
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2009-2010 Nokia Corporation
  *
  * Paul Walmsley (paul@pwsan.com)
  * Rajendra Nayak (rnayak@ti.com)
@@ -30,587 +30,611 @@
  * PRM_LDO_SRAM_MPU_SETUP
  */
 #define OMAP4430_ABBOFF_ACT_EXPORT_SHIFT				1
-#define OMAP4430_ABBOFF_ACT_EXPORT_MASK					BITFIELD(1, 1)
+#define OMAP4430_ABBOFF_ACT_EXPORT_MASK					(1 << 1)
 
 /*
  * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP,
  * PRM_LDO_SRAM_MPU_SETUP
  */
 #define OMAP4430_ABBOFF_SLEEP_EXPORT_SHIFT				2
-#define OMAP4430_ABBOFF_SLEEP_EXPORT_MASK				BITFIELD(2, 2)
+#define OMAP4430_ABBOFF_SLEEP_EXPORT_MASK				(1 << 2)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_ABB_IVA_DONE_EN_SHIFT					31
-#define OMAP4430_ABB_IVA_DONE_EN_MASK					BITFIELD(31, 31)
+#define OMAP4430_ABB_IVA_DONE_EN_MASK					(1 << 31)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_ABB_IVA_DONE_ST_SHIFT					31
-#define OMAP4430_ABB_IVA_DONE_ST_MASK					BITFIELD(31, 31)
+#define OMAP4430_ABB_IVA_DONE_ST_MASK					(1 << 31)
 
 /* Used by PRM_IRQENABLE_MPU_2 */
 #define OMAP4430_ABB_MPU_DONE_EN_SHIFT					7
-#define OMAP4430_ABB_MPU_DONE_EN_MASK					BITFIELD(7, 7)
+#define OMAP4430_ABB_MPU_DONE_EN_MASK					(1 << 7)
 
 /* Used by PRM_IRQSTATUS_MPU_2 */
 #define OMAP4430_ABB_MPU_DONE_ST_SHIFT					7
-#define OMAP4430_ABB_MPU_DONE_ST_MASK					BITFIELD(7, 7)
+#define OMAP4430_ABB_MPU_DONE_ST_MASK					(1 << 7)
 
 /* Used by PRM_LDO_ABB_IVA_SETUP, PRM_LDO_ABB_MPU_SETUP */
 #define OMAP4430_ACTIVE_FBB_SEL_SHIFT					2
-#define OMAP4430_ACTIVE_FBB_SEL_MASK					BITFIELD(2, 2)
+#define OMAP4430_ACTIVE_FBB_SEL_MASK					(1 << 2)
 
 /* Used by PRM_LDO_ABB_IVA_SETUP, PRM_LDO_ABB_MPU_SETUP */
 #define OMAP4430_ACTIVE_RBB_SEL_SHIFT					1
-#define OMAP4430_ACTIVE_RBB_SEL_MASK					BITFIELD(1, 1)
+#define OMAP4430_ACTIVE_RBB_SEL_MASK					(1 << 1)
 
 /* Used by PM_ABE_PWRSTCTRL */
 #define OMAP4430_AESSMEM_ONSTATE_SHIFT					16
-#define OMAP4430_AESSMEM_ONSTATE_MASK					BITFIELD(16, 17)
+#define OMAP4430_AESSMEM_ONSTATE_MASK					(0x3 << 16)
 
 /* Used by PM_ABE_PWRSTCTRL */
 #define OMAP4430_AESSMEM_RETSTATE_SHIFT					8
-#define OMAP4430_AESSMEM_RETSTATE_MASK					BITFIELD(8, 8)
+#define OMAP4430_AESSMEM_RETSTATE_MASK					(1 << 8)
 
 /* Used by PM_ABE_PWRSTST */
 #define OMAP4430_AESSMEM_STATEST_SHIFT					4
-#define OMAP4430_AESSMEM_STATEST_MASK					BITFIELD(4, 5)
+#define OMAP4430_AESSMEM_STATEST_MASK					(0x3 << 4)
 
 /*
  * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP,
  * PRM_LDO_SRAM_MPU_SETUP
  */
 #define OMAP4430_AIPOFF_SHIFT						8
-#define OMAP4430_AIPOFF_MASK						BITFIELD(8, 8)
+#define OMAP4430_AIPOFF_MASK						(1 << 8)
 
 /* Used by PRM_VOLTCTRL */
 #define OMAP4430_AUTO_CTRL_VDD_CORE_L_SHIFT				0
-#define OMAP4430_AUTO_CTRL_VDD_CORE_L_MASK				BITFIELD(0, 1)
+#define OMAP4430_AUTO_CTRL_VDD_CORE_L_MASK				(0x3 << 0)
 
 /* Used by PRM_VOLTCTRL */
 #define OMAP4430_AUTO_CTRL_VDD_IVA_L_SHIFT				4
-#define OMAP4430_AUTO_CTRL_VDD_IVA_L_MASK				BITFIELD(4, 5)
+#define OMAP4430_AUTO_CTRL_VDD_IVA_L_MASK				(0x3 << 4)
 
 /* Used by PRM_VOLTCTRL */
 #define OMAP4430_AUTO_CTRL_VDD_MPU_L_SHIFT				2
-#define OMAP4430_AUTO_CTRL_VDD_MPU_L_MASK				BITFIELD(2, 3)
+#define OMAP4430_AUTO_CTRL_VDD_MPU_L_MASK				(0x3 << 2)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_BYPS_RA_ERR_SHIFT					25
+#define OMAP4430_BYPS_RA_ERR_MASK					(1 << 25)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_BYPS_SA_ERR_SHIFT					24
+#define OMAP4430_BYPS_SA_ERR_MASK					(1 << 24)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_BYPS_TIMEOUT_ERR_SHIFT					26
+#define OMAP4430_BYPS_TIMEOUT_ERR_MASK					(1 << 26)
+
+/* Used by PRM_RSTST */
+#define OMAP4430_C2C_RST_SHIFT						10
+#define OMAP4430_C2C_RST_MASK						(1 << 10)
 
 /* Used by PM_CAM_PWRSTCTRL */
 #define OMAP4430_CAM_MEM_ONSTATE_SHIFT					16
-#define OMAP4430_CAM_MEM_ONSTATE_MASK					BITFIELD(16, 17)
+#define OMAP4430_CAM_MEM_ONSTATE_MASK					(0x3 << 16)
 
 /* Used by PM_CAM_PWRSTST */
 #define OMAP4430_CAM_MEM_STATEST_SHIFT					4
-#define OMAP4430_CAM_MEM_STATEST_MASK					BITFIELD(4, 5)
+#define OMAP4430_CAM_MEM_STATEST_MASK					(0x3 << 4)
 
 /* Used by PRM_CLKREQCTRL */
 #define OMAP4430_CLKREQ_COND_SHIFT					0
-#define OMAP4430_CLKREQ_COND_MASK					BITFIELD(0, 2)
+#define OMAP4430_CLKREQ_COND_MASK					(0x7 << 0)
 
 /* Used by PRM_VC_VAL_SMPS_RA_CMD */
 #define OMAP4430_CMDRA_VDD_CORE_L_SHIFT					0
-#define OMAP4430_CMDRA_VDD_CORE_L_MASK					BITFIELD(0, 7)
+#define OMAP4430_CMDRA_VDD_CORE_L_MASK					(0xff << 0)
 
 /* Used by PRM_VC_VAL_SMPS_RA_CMD */
 #define OMAP4430_CMDRA_VDD_IVA_L_SHIFT					8
-#define OMAP4430_CMDRA_VDD_IVA_L_MASK					BITFIELD(8, 15)
+#define OMAP4430_CMDRA_VDD_IVA_L_MASK					(0xff << 8)
 
 /* Used by PRM_VC_VAL_SMPS_RA_CMD */
 #define OMAP4430_CMDRA_VDD_MPU_L_SHIFT					16
-#define OMAP4430_CMDRA_VDD_MPU_L_MASK					BITFIELD(16, 23)
+#define OMAP4430_CMDRA_VDD_MPU_L_MASK					(0xff << 16)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_CMD_VDD_CORE_L_SHIFT					4
-#define OMAP4430_CMD_VDD_CORE_L_MASK					BITFIELD(4, 4)
+#define OMAP4430_CMD_VDD_CORE_L_MASK					(1 << 4)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_CMD_VDD_IVA_L_SHIFT					12
-#define OMAP4430_CMD_VDD_IVA_L_MASK					BITFIELD(12, 12)
+#define OMAP4430_CMD_VDD_IVA_L_MASK					(1 << 12)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_CMD_VDD_MPU_L_SHIFT					17
-#define OMAP4430_CMD_VDD_MPU_L_MASK					BITFIELD(17, 17)
+#define OMAP4430_CMD_VDD_MPU_L_MASK					(1 << 17)
 
 /* Used by PM_CORE_PWRSTCTRL */
 #define OMAP4430_CORE_OCMRAM_ONSTATE_SHIFT				18
-#define OMAP4430_CORE_OCMRAM_ONSTATE_MASK				BITFIELD(18, 19)
+#define OMAP4430_CORE_OCMRAM_ONSTATE_MASK				(0x3 << 18)
 
 /* Used by PM_CORE_PWRSTCTRL */
 #define OMAP4430_CORE_OCMRAM_RETSTATE_SHIFT				9
-#define OMAP4430_CORE_OCMRAM_RETSTATE_MASK				BITFIELD(9, 9)
+#define OMAP4430_CORE_OCMRAM_RETSTATE_MASK				(1 << 9)
 
 /* Used by PM_CORE_PWRSTST */
 #define OMAP4430_CORE_OCMRAM_STATEST_SHIFT				6
-#define OMAP4430_CORE_OCMRAM_STATEST_MASK				BITFIELD(6, 7)
+#define OMAP4430_CORE_OCMRAM_STATEST_MASK				(0x3 << 6)
 
 /* Used by PM_CORE_PWRSTCTRL */
 #define OMAP4430_CORE_OTHER_BANK_ONSTATE_SHIFT				16
-#define OMAP4430_CORE_OTHER_BANK_ONSTATE_MASK				BITFIELD(16, 17)
+#define OMAP4430_CORE_OTHER_BANK_ONSTATE_MASK				(0x3 << 16)
 
 /* Used by PM_CORE_PWRSTCTRL */
 #define OMAP4430_CORE_OTHER_BANK_RETSTATE_SHIFT				8
-#define OMAP4430_CORE_OTHER_BANK_RETSTATE_MASK				BITFIELD(8, 8)
+#define OMAP4430_CORE_OTHER_BANK_RETSTATE_MASK				(1 << 8)
 
 /* Used by PM_CORE_PWRSTST */
 #define OMAP4430_CORE_OTHER_BANK_STATEST_SHIFT				4
-#define OMAP4430_CORE_OTHER_BANK_STATEST_MASK				BITFIELD(4, 5)
+#define OMAP4430_CORE_OTHER_BANK_STATEST_MASK				(0x3 << 4)
+
+/* Used by REVISION_PRM */
+#define OMAP4430_CUSTOM_SHIFT						6
+#define OMAP4430_CUSTOM_MASK						(0x3 << 6)
 
 /* Used by PRM_VC_VAL_BYPASS */
 #define OMAP4430_DATA_SHIFT						16
-#define OMAP4430_DATA_MASK						BITFIELD(16, 23)
+#define OMAP4430_DATA_MASK						(0xff << 16)
 
 /* Used by PRM_DEVICE_OFF_CTRL */
 #define OMAP4430_DEVICE_OFF_ENABLE_SHIFT				0
-#define OMAP4430_DEVICE_OFF_ENABLE_MASK					BITFIELD(0, 0)
+#define OMAP4430_DEVICE_OFF_ENABLE_MASK					(1 << 0)
 
 /* Used by PRM_VC_CFG_I2C_MODE */
 #define OMAP4430_DFILTEREN_SHIFT					6
-#define OMAP4430_DFILTEREN_MASK						BITFIELD(6, 6)
-
-/* Used by PRM_IRQENABLE_MPU, PRM_IRQENABLE_TESLA */
-#define OMAP4430_DPLL_ABE_RECAL_EN_SHIFT				4
-#define OMAP4430_DPLL_ABE_RECAL_EN_MASK					BITFIELD(4, 4)
-
-/* Used by PRM_IRQSTATUS_MPU, PRM_IRQSTATUS_TESLA */
-#define OMAP4430_DPLL_ABE_RECAL_ST_SHIFT				4
-#define OMAP4430_DPLL_ABE_RECAL_ST_MASK					BITFIELD(4, 4)
-
-/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
-#define OMAP4430_DPLL_CORE_RECAL_EN_SHIFT				0
-#define OMAP4430_DPLL_CORE_RECAL_EN_MASK				BITFIELD(0, 0)
-
-/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
-#define OMAP4430_DPLL_CORE_RECAL_ST_SHIFT				0
-#define OMAP4430_DPLL_CORE_RECAL_ST_MASK				BITFIELD(0, 0)
-
-/* Used by PRM_IRQENABLE_MPU */
-#define OMAP4430_DPLL_DDRPHY_RECAL_EN_SHIFT				6
-#define OMAP4430_DPLL_DDRPHY_RECAL_EN_MASK				BITFIELD(6, 6)
-
-/* Used by PRM_IRQSTATUS_MPU */
-#define OMAP4430_DPLL_DDRPHY_RECAL_ST_SHIFT				6
-#define OMAP4430_DPLL_DDRPHY_RECAL_ST_MASK				BITFIELD(6, 6)
-
-/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU, PRM_IRQENABLE_TESLA */
-#define OMAP4430_DPLL_IVA_RECAL_EN_SHIFT				2
-#define OMAP4430_DPLL_IVA_RECAL_EN_MASK					BITFIELD(2, 2)
-
-/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU, PRM_IRQSTATUS_TESLA */
-#define OMAP4430_DPLL_IVA_RECAL_ST_SHIFT				2
-#define OMAP4430_DPLL_IVA_RECAL_ST_MASK					BITFIELD(2, 2)
-
-/* Used by PRM_IRQENABLE_MPU */
-#define OMAP4430_DPLL_MPU_RECAL_EN_SHIFT				1
-#define OMAP4430_DPLL_MPU_RECAL_EN_MASK					BITFIELD(1, 1)
-
-/* Used by PRM_IRQSTATUS_MPU */
-#define OMAP4430_DPLL_MPU_RECAL_ST_SHIFT				1
-#define OMAP4430_DPLL_MPU_RECAL_ST_MASK					BITFIELD(1, 1)
-
-/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
-#define OMAP4430_DPLL_PER_RECAL_EN_SHIFT				3
-#define OMAP4430_DPLL_PER_RECAL_EN_MASK					BITFIELD(3, 3)
-
-/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
-#define OMAP4430_DPLL_PER_RECAL_ST_SHIFT				3
-#define OMAP4430_DPLL_PER_RECAL_ST_MASK					BITFIELD(3, 3)
-
-/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
-#define OMAP4430_DPLL_UNIPRO_RECAL_EN_SHIFT				7
-#define OMAP4430_DPLL_UNIPRO_RECAL_EN_MASK				BITFIELD(7, 7)
-
-/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
-#define OMAP4430_DPLL_UNIPRO_RECAL_ST_SHIFT				7
-#define OMAP4430_DPLL_UNIPRO_RECAL_ST_MASK				BITFIELD(7, 7)
-
-/* Used by PRM_IRQENABLE_MPU */
-#define OMAP4430_DPLL_USB_RECAL_EN_SHIFT				5
-#define OMAP4430_DPLL_USB_RECAL_EN_MASK					BITFIELD(5, 5)
-
-/* Used by PRM_IRQSTATUS_MPU */
-#define OMAP4430_DPLL_USB_RECAL_ST_SHIFT				5
-#define OMAP4430_DPLL_USB_RECAL_ST_MASK					BITFIELD(5, 5)
-
-/* Used by PM_DSS_PWRSTCTRL */
-#define OMAP4430_DSS_MEM_ONSTATE_SHIFT					16
-#define OMAP4430_DSS_MEM_ONSTATE_MASK					BITFIELD(16, 17)
-
-/* Used by PM_DSS_PWRSTCTRL */
-#define OMAP4430_DSS_MEM_RETSTATE_SHIFT					8
-#define OMAP4430_DSS_MEM_RETSTATE_MASK					BITFIELD(8, 8)
-
-/* Used by PM_DSS_PWRSTST */
-#define OMAP4430_DSS_MEM_STATEST_SHIFT					4
-#define OMAP4430_DSS_MEM_STATEST_MASK					BITFIELD(4, 5)
-
-/* Used by PM_CORE_PWRSTCTRL */
-#define OMAP4430_DUCATI_L2RAM_ONSTATE_SHIFT				20
-#define OMAP4430_DUCATI_L2RAM_ONSTATE_MASK				BITFIELD(20, 21)
-
-/* Used by PM_CORE_PWRSTCTRL */
-#define OMAP4430_DUCATI_L2RAM_RETSTATE_SHIFT				10
-#define OMAP4430_DUCATI_L2RAM_RETSTATE_MASK				BITFIELD(10, 10)
-
-/* Used by PM_CORE_PWRSTST */
-#define OMAP4430_DUCATI_L2RAM_STATEST_SHIFT				8
-#define OMAP4430_DUCATI_L2RAM_STATEST_MASK				BITFIELD(8, 9)
-
-/* Used by PM_CORE_PWRSTCTRL */
-#define OMAP4430_DUCATI_UNICACHE_ONSTATE_SHIFT				22
-#define OMAP4430_DUCATI_UNICACHE_ONSTATE_MASK				BITFIELD(22, 23)
-
-/* Used by PM_CORE_PWRSTCTRL */
-#define OMAP4430_DUCATI_UNICACHE_RETSTATE_SHIFT				11
-#define OMAP4430_DUCATI_UNICACHE_RETSTATE_MASK				BITFIELD(11, 11)
-
-/* Used by PM_CORE_PWRSTST */
-#define OMAP4430_DUCATI_UNICACHE_STATEST_SHIFT				10
-#define OMAP4430_DUCATI_UNICACHE_STATEST_MASK				BITFIELD(10, 11)
-
-/* Used by RM_MPU_RSTST */
-#define OMAP4430_EMULATION_RST_SHIFT					0
-#define OMAP4430_EMULATION_RST_MASK					BITFIELD(0, 0)
-
-/* Used by RM_DUCATI_RSTST */
-#define OMAP4430_EMULATION_RST1ST_SHIFT					3
-#define OMAP4430_EMULATION_RST1ST_MASK					BITFIELD(3, 3)
-
-/* Used by RM_DUCATI_RSTST */
-#define OMAP4430_EMULATION_RST2ST_SHIFT					4
-#define OMAP4430_EMULATION_RST2ST_MASK					BITFIELD(4, 4)
-
-/* Used by RM_IVAHD_RSTST */
-#define OMAP4430_EMULATION_SEQ1_RST1ST_SHIFT				3
-#define OMAP4430_EMULATION_SEQ1_RST1ST_MASK				BITFIELD(3, 3)
-
-/* Used by RM_IVAHD_RSTST */
-#define OMAP4430_EMULATION_SEQ2_RST2ST_SHIFT				4
-#define OMAP4430_EMULATION_SEQ2_RST2ST_MASK				BITFIELD(4, 4)
-
-/* Used by PM_EMU_PWRSTCTRL */
-#define OMAP4430_EMU_BANK_ONSTATE_SHIFT					16
-#define OMAP4430_EMU_BANK_ONSTATE_MASK					BITFIELD(16, 17)
-
-/* Used by PM_EMU_PWRSTST */
-#define OMAP4430_EMU_BANK_STATEST_SHIFT					4
-#define OMAP4430_EMU_BANK_STATEST_MASK					BITFIELD(4, 5)
+#define OMAP4430_DFILTEREN_MASK						(1 << 6)
 
 /*
  * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP,
  * PRM_LDO_SRAM_MPU_SETUP, PRM_SRAM_WKUP_SETUP
  */
-#define OMAP4430_ENABLE_RTA_EXPORT_SHIFT				0
-#define OMAP4430_ENABLE_RTA_EXPORT_MASK					BITFIELD(0, 0)
+#define OMAP4430_DISABLE_RTA_EXPORT_SHIFT				0
+#define OMAP4430_DISABLE_RTA_EXPORT_MASK				(1 << 0)
+
+/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU, PRM_IRQENABLE_TESLA */
+#define OMAP4430_DPLL_ABE_RECAL_EN_SHIFT				4
+#define OMAP4430_DPLL_ABE_RECAL_EN_MASK					(1 << 4)
+
+/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU, PRM_IRQSTATUS_TESLA */
+#define OMAP4430_DPLL_ABE_RECAL_ST_SHIFT				4
+#define OMAP4430_DPLL_ABE_RECAL_ST_MASK					(1 << 4)
+
+/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
+#define OMAP4430_DPLL_CORE_RECAL_EN_SHIFT				0
+#define OMAP4430_DPLL_CORE_RECAL_EN_MASK				(1 << 0)
+
+/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
+#define OMAP4430_DPLL_CORE_RECAL_ST_SHIFT				0
+#define OMAP4430_DPLL_CORE_RECAL_ST_MASK				(1 << 0)
+
+/* Used by PRM_IRQENABLE_MPU */
+#define OMAP4430_DPLL_DDRPHY_RECAL_EN_SHIFT				6
+#define OMAP4430_DPLL_DDRPHY_RECAL_EN_MASK				(1 << 6)
+
+/* Used by PRM_IRQSTATUS_MPU */
+#define OMAP4430_DPLL_DDRPHY_RECAL_ST_SHIFT				6
+#define OMAP4430_DPLL_DDRPHY_RECAL_ST_MASK				(1 << 6)
+
+/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU, PRM_IRQENABLE_TESLA */
+#define OMAP4430_DPLL_IVA_RECAL_EN_SHIFT				2
+#define OMAP4430_DPLL_IVA_RECAL_EN_MASK					(1 << 2)
+
+/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU, PRM_IRQSTATUS_TESLA */
+#define OMAP4430_DPLL_IVA_RECAL_ST_SHIFT				2
+#define OMAP4430_DPLL_IVA_RECAL_ST_MASK					(1 << 2)
+
+/* Used by PRM_IRQENABLE_MPU */
+#define OMAP4430_DPLL_MPU_RECAL_EN_SHIFT				1
+#define OMAP4430_DPLL_MPU_RECAL_EN_MASK					(1 << 1)
+
+/* Used by PRM_IRQSTATUS_MPU */
+#define OMAP4430_DPLL_MPU_RECAL_ST_SHIFT				1
+#define OMAP4430_DPLL_MPU_RECAL_ST_MASK					(1 << 1)
+
+/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
+#define OMAP4430_DPLL_PER_RECAL_EN_SHIFT				3
+#define OMAP4430_DPLL_PER_RECAL_EN_MASK					(1 << 3)
+
+/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
+#define OMAP4430_DPLL_PER_RECAL_ST_SHIFT				3
+#define OMAP4430_DPLL_PER_RECAL_ST_MASK					(1 << 3)
+
+/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
+#define OMAP4430_DPLL_UNIPRO_RECAL_EN_SHIFT				7
+#define OMAP4430_DPLL_UNIPRO_RECAL_EN_MASK				(1 << 7)
+
+/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
+#define OMAP4430_DPLL_UNIPRO_RECAL_ST_SHIFT				7
+#define OMAP4430_DPLL_UNIPRO_RECAL_ST_MASK				(1 << 7)
+
+/* Used by PM_DSS_PWRSTCTRL */
+#define OMAP4430_DSS_MEM_ONSTATE_SHIFT					16
+#define OMAP4430_DSS_MEM_ONSTATE_MASK					(0x3 << 16)
+
+/* Used by PM_DSS_PWRSTCTRL */
+#define OMAP4430_DSS_MEM_RETSTATE_SHIFT					8
+#define OMAP4430_DSS_MEM_RETSTATE_MASK					(1 << 8)
+
+/* Used by PM_DSS_PWRSTST */
+#define OMAP4430_DSS_MEM_STATEST_SHIFT					4
+#define OMAP4430_DSS_MEM_STATEST_MASK					(0x3 << 4)
+
+/* Used by PM_CORE_PWRSTCTRL */
+#define OMAP4430_DUCATI_L2RAM_ONSTATE_SHIFT				20
+#define OMAP4430_DUCATI_L2RAM_ONSTATE_MASK				(0x3 << 20)
+
+/* Used by PM_CORE_PWRSTCTRL */
+#define OMAP4430_DUCATI_L2RAM_RETSTATE_SHIFT				10
+#define OMAP4430_DUCATI_L2RAM_RETSTATE_MASK				(1 << 10)
+
+/* Used by PM_CORE_PWRSTST */
+#define OMAP4430_DUCATI_L2RAM_STATEST_SHIFT				8
+#define OMAP4430_DUCATI_L2RAM_STATEST_MASK				(0x3 << 8)
+
+/* Used by PM_CORE_PWRSTCTRL */
+#define OMAP4430_DUCATI_UNICACHE_ONSTATE_SHIFT				22
+#define OMAP4430_DUCATI_UNICACHE_ONSTATE_MASK				(0x3 << 22)
+
+/* Used by PM_CORE_PWRSTCTRL */
+#define OMAP4430_DUCATI_UNICACHE_RETSTATE_SHIFT				11
+#define OMAP4430_DUCATI_UNICACHE_RETSTATE_MASK				(1 << 11)
+
+/* Used by PM_CORE_PWRSTST */
+#define OMAP4430_DUCATI_UNICACHE_STATEST_SHIFT				10
+#define OMAP4430_DUCATI_UNICACHE_STATEST_MASK				(0x3 << 10)
+
+/* Used by RM_MPU_RSTST */
+#define OMAP4430_EMULATION_RST_SHIFT					0
+#define OMAP4430_EMULATION_RST_MASK					(1 << 0)
+
+/* Used by RM_DUCATI_RSTST */
+#define OMAP4430_EMULATION_RST1ST_SHIFT					3
+#define OMAP4430_EMULATION_RST1ST_MASK					(1 << 3)
+
+/* Used by RM_DUCATI_RSTST */
+#define OMAP4430_EMULATION_RST2ST_SHIFT					4
+#define OMAP4430_EMULATION_RST2ST_MASK					(1 << 4)
+
+/* Used by RM_IVAHD_RSTST */
+#define OMAP4430_EMULATION_SEQ1_RST1ST_SHIFT				3
+#define OMAP4430_EMULATION_SEQ1_RST1ST_MASK				(1 << 3)
+
+/* Used by RM_IVAHD_RSTST */
+#define OMAP4430_EMULATION_SEQ2_RST2ST_SHIFT				4
+#define OMAP4430_EMULATION_SEQ2_RST2ST_MASK				(1 << 4)
+
+/* Used by PM_EMU_PWRSTCTRL */
+#define OMAP4430_EMU_BANK_ONSTATE_SHIFT					16
+#define OMAP4430_EMU_BANK_ONSTATE_MASK					(0x3 << 16)
+
+/* Used by PM_EMU_PWRSTST */
+#define OMAP4430_EMU_BANK_STATEST_SHIFT					4
+#define OMAP4430_EMU_BANK_STATEST_MASK					(0x3 << 4)
 
 /*
  * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP,
  * PRM_LDO_SRAM_MPU_SETUP
  */
-#define OMAP4430_ENFUNC1_SHIFT						3
-#define OMAP4430_ENFUNC1_MASK						BITFIELD(3, 3)
+#define OMAP4430_ENFUNC1_EXPORT_SHIFT					3
+#define OMAP4430_ENFUNC1_EXPORT_MASK					(1 << 3)
 
 /*
  * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP,
  * PRM_LDO_SRAM_MPU_SETUP
  */
-#define OMAP4430_ENFUNC3_SHIFT						5
-#define OMAP4430_ENFUNC3_MASK						BITFIELD(5, 5)
+#define OMAP4430_ENFUNC3_EXPORT_SHIFT					5
+#define OMAP4430_ENFUNC3_EXPORT_MASK					(1 << 5)
 
 /*
  * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP,
  * PRM_LDO_SRAM_MPU_SETUP
  */
 #define OMAP4430_ENFUNC4_SHIFT						6
-#define OMAP4430_ENFUNC4_MASK						BITFIELD(6, 6)
+#define OMAP4430_ENFUNC4_MASK						(1 << 6)
 
 /*
  * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP,
  * PRM_LDO_SRAM_MPU_SETUP
  */
 #define OMAP4430_ENFUNC5_SHIFT						7
-#define OMAP4430_ENFUNC5_MASK						BITFIELD(7, 7)
+#define OMAP4430_ENFUNC5_MASK						(1 << 7)
 
 /* Used by PRM_VP_CORE_CONFIG, PRM_VP_IVA_CONFIG, PRM_VP_MPU_CONFIG */
 #define OMAP4430_ERRORGAIN_SHIFT					16
-#define OMAP4430_ERRORGAIN_MASK						BITFIELD(16, 23)
+#define OMAP4430_ERRORGAIN_MASK						(0xff << 16)
 
 /* Used by PRM_VP_CORE_CONFIG, PRM_VP_IVA_CONFIG, PRM_VP_MPU_CONFIG */
 #define OMAP4430_ERROROFFSET_SHIFT					24
-#define OMAP4430_ERROROFFSET_MASK					BITFIELD(24, 31)
+#define OMAP4430_ERROROFFSET_MASK					(0xff << 24)
 
 /* Used by PRM_RSTST */
 #define OMAP4430_EXTERNAL_WARM_RST_SHIFT				5
-#define OMAP4430_EXTERNAL_WARM_RST_MASK					BITFIELD(5, 5)
+#define OMAP4430_EXTERNAL_WARM_RST_MASK					(1 << 5)
 
 /* Used by PRM_VP_CORE_CONFIG, PRM_VP_IVA_CONFIG, PRM_VP_MPU_CONFIG */
 #define OMAP4430_FORCEUPDATE_SHIFT					1
-#define OMAP4430_FORCEUPDATE_MASK					BITFIELD(1, 1)
+#define OMAP4430_FORCEUPDATE_MASK					(1 << 1)
 
 /* Used by PRM_VP_CORE_VOLTAGE, PRM_VP_IVA_VOLTAGE, PRM_VP_MPU_VOLTAGE */
 #define OMAP4430_FORCEUPDATEWAIT_SHIFT					8
-#define OMAP4430_FORCEUPDATEWAIT_MASK					BITFIELD(8, 31)
+#define OMAP4430_FORCEUPDATEWAIT_MASK					(0xffffff << 8)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_TESLA */
 #define OMAP4430_FORCEWKUP_EN_SHIFT					10
-#define OMAP4430_FORCEWKUP_EN_MASK					BITFIELD(10, 10)
+#define OMAP4430_FORCEWKUP_EN_MASK					(1 << 10)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_TESLA */
 #define OMAP4430_FORCEWKUP_ST_SHIFT					10
-#define OMAP4430_FORCEWKUP_ST_MASK					BITFIELD(10, 10)
+#define OMAP4430_FORCEWKUP_ST_MASK					(1 << 10)
+
+/* Used by REVISION_PRM */
+#define OMAP4430_FUNC_SHIFT						16
+#define OMAP4430_FUNC_MASK						(0xfff << 16)
 
 /* Used by PM_GFX_PWRSTCTRL */
 #define OMAP4430_GFX_MEM_ONSTATE_SHIFT					16
-#define OMAP4430_GFX_MEM_ONSTATE_MASK					BITFIELD(16, 17)
+#define OMAP4430_GFX_MEM_ONSTATE_MASK					(0x3 << 16)
 
 /* Used by PM_GFX_PWRSTST */
 #define OMAP4430_GFX_MEM_STATEST_SHIFT					4
-#define OMAP4430_GFX_MEM_STATEST_MASK					BITFIELD(4, 5)
+#define OMAP4430_GFX_MEM_STATEST_MASK					(0x3 << 4)
 
 /* Used by PRM_RSTST */
 #define OMAP4430_GLOBAL_COLD_RST_SHIFT					0
-#define OMAP4430_GLOBAL_COLD_RST_MASK					BITFIELD(0, 0)
+#define OMAP4430_GLOBAL_COLD_RST_MASK					(1 << 0)
 
 /* Used by PRM_RSTST */
 #define OMAP4430_GLOBAL_WARM_SW_RST_SHIFT				1
-#define OMAP4430_GLOBAL_WARM_SW_RST_MASK				BITFIELD(1, 1)
+#define OMAP4430_GLOBAL_WARM_SW_RST_MASK				(1 << 1)
 
 /* Used by PRM_IO_PMCTRL */
 #define OMAP4430_GLOBAL_WUEN_SHIFT					16
-#define OMAP4430_GLOBAL_WUEN_MASK					BITFIELD(16, 16)
+#define OMAP4430_GLOBAL_WUEN_MASK					(1 << 16)
 
 /* Used by PRM_VC_CFG_I2C_MODE */
 #define OMAP4430_HSMCODE_SHIFT						0
-#define OMAP4430_HSMCODE_MASK						BITFIELD(0, 2)
+#define OMAP4430_HSMCODE_MASK						(0x7 << 0)
 
 /* Used by PRM_VC_CFG_I2C_MODE */
 #define OMAP4430_HSMODEEN_SHIFT						3
-#define OMAP4430_HSMODEEN_MASK						BITFIELD(3, 3)
+#define OMAP4430_HSMODEEN_MASK						(1 << 3)
 
 /* Used by PRM_VC_CFG_I2C_CLK */
 #define OMAP4430_HSSCLH_SHIFT						16
-#define OMAP4430_HSSCLH_MASK						BITFIELD(16, 23)
+#define OMAP4430_HSSCLH_MASK						(0xff << 16)
 
 /* Used by PRM_VC_CFG_I2C_CLK */
 #define OMAP4430_HSSCLL_SHIFT						24
-#define OMAP4430_HSSCLL_MASK						BITFIELD(24, 31)
+#define OMAP4430_HSSCLL_MASK						(0xff << 24)
 
 /* Used by PM_IVAHD_PWRSTCTRL */
 #define OMAP4430_HWA_MEM_ONSTATE_SHIFT					16
-#define OMAP4430_HWA_MEM_ONSTATE_MASK					BITFIELD(16, 17)
+#define OMAP4430_HWA_MEM_ONSTATE_MASK					(0x3 << 16)
 
 /* Used by PM_IVAHD_PWRSTCTRL */
 #define OMAP4430_HWA_MEM_RETSTATE_SHIFT					8
-#define OMAP4430_HWA_MEM_RETSTATE_MASK					BITFIELD(8, 8)
+#define OMAP4430_HWA_MEM_RETSTATE_MASK					(1 << 8)
 
 /* Used by PM_IVAHD_PWRSTST */
 #define OMAP4430_HWA_MEM_STATEST_SHIFT					4
-#define OMAP4430_HWA_MEM_STATEST_MASK					BITFIELD(4, 5)
+#define OMAP4430_HWA_MEM_STATEST_MASK					(0x3 << 4)
 
 /* Used by RM_MPU_RSTST */
 #define OMAP4430_ICECRUSHER_MPU_RST_SHIFT				1
-#define OMAP4430_ICECRUSHER_MPU_RST_MASK				BITFIELD(1, 1)
+#define OMAP4430_ICECRUSHER_MPU_RST_MASK				(1 << 1)
 
 /* Used by RM_DUCATI_RSTST */
 #define OMAP4430_ICECRUSHER_RST1ST_SHIFT				5
-#define OMAP4430_ICECRUSHER_RST1ST_MASK					BITFIELD(5, 5)
+#define OMAP4430_ICECRUSHER_RST1ST_MASK					(1 << 5)
 
 /* Used by RM_DUCATI_RSTST */
 #define OMAP4430_ICECRUSHER_RST2ST_SHIFT				6
-#define OMAP4430_ICECRUSHER_RST2ST_MASK					BITFIELD(6, 6)
+#define OMAP4430_ICECRUSHER_RST2ST_MASK					(1 << 6)
 
 /* Used by RM_IVAHD_RSTST */
 #define OMAP4430_ICECRUSHER_SEQ1_RST1ST_SHIFT				5
-#define OMAP4430_ICECRUSHER_SEQ1_RST1ST_MASK				BITFIELD(5, 5)
+#define OMAP4430_ICECRUSHER_SEQ1_RST1ST_MASK				(1 << 5)
 
 /* Used by RM_IVAHD_RSTST */
 #define OMAP4430_ICECRUSHER_SEQ2_RST2ST_SHIFT				6
-#define OMAP4430_ICECRUSHER_SEQ2_RST2ST_MASK				BITFIELD(6, 6)
+#define OMAP4430_ICECRUSHER_SEQ2_RST2ST_MASK				(1 << 6)
 
 /* Used by PRM_RSTST */
 #define OMAP4430_ICEPICK_RST_SHIFT					9
-#define OMAP4430_ICEPICK_RST_MASK					BITFIELD(9, 9)
+#define OMAP4430_ICEPICK_RST_MASK					(1 << 9)
 
 /* Used by PRM_VP_CORE_CONFIG, PRM_VP_IVA_CONFIG, PRM_VP_MPU_CONFIG */
 #define OMAP4430_INITVDD_SHIFT						2
-#define OMAP4430_INITVDD_MASK						BITFIELD(2, 2)
+#define OMAP4430_INITVDD_MASK						(1 << 2)
 
 /* Used by PRM_VP_CORE_CONFIG, PRM_VP_IVA_CONFIG, PRM_VP_MPU_CONFIG */
 #define OMAP4430_INITVOLTAGE_SHIFT					8
-#define OMAP4430_INITVOLTAGE_MASK					BITFIELD(8, 15)
+#define OMAP4430_INITVOLTAGE_MASK					(0xff << 8)
 
 /*
- * Used by PM_EMU_PWRSTST, PM_CORE_PWRSTST, PM_CAM_PWRSTST, PM_L3INIT_PWRSTST,
- * PM_ABE_PWRSTST, PM_GFX_PWRSTST, PM_MPU_PWRSTST, PM_CEFUSE_PWRSTST,
- * PM_DSS_PWRSTST, PM_L4PER_PWRSTST, PM_TESLA_PWRSTST, PM_IVAHD_PWRSTST
+ * Used by PM_ABE_PWRSTST, PM_CAM_PWRSTST, PM_CEFUSE_PWRSTST, PM_CORE_PWRSTST,
+ * PM_DSS_PWRSTST, PM_EMU_PWRSTST, PM_GFX_PWRSTST, PM_IVAHD_PWRSTST,
+ * PM_L3INIT_PWRSTST, PM_L4PER_PWRSTST, PM_MPU_PWRSTST, PM_TESLA_PWRSTST
  */
 #define OMAP4430_INTRANSITION_SHIFT					20
-#define OMAP4430_INTRANSITION_MASK					BITFIELD(20, 20)
+#define OMAP4430_INTRANSITION_MASK					(1 << 20)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_IO_EN_SHIFT						9
-#define OMAP4430_IO_EN_MASK						BITFIELD(9, 9)
+#define OMAP4430_IO_EN_MASK						(1 << 9)
 
 /* Used by PRM_IO_PMCTRL */
 #define OMAP4430_IO_ON_STATUS_SHIFT					5
-#define OMAP4430_IO_ON_STATUS_MASK					BITFIELD(5, 5)
+#define OMAP4430_IO_ON_STATUS_MASK					(1 << 5)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_IO_ST_SHIFT						9
-#define OMAP4430_IO_ST_MASK						BITFIELD(9, 9)
+#define OMAP4430_IO_ST_MASK						(1 << 9)
 
 /* Used by PRM_IO_PMCTRL */
 #define OMAP4430_ISOCLK_OVERRIDE_SHIFT					0
-#define OMAP4430_ISOCLK_OVERRIDE_MASK					BITFIELD(0, 0)
+#define OMAP4430_ISOCLK_OVERRIDE_MASK					(1 << 0)
 
 /* Used by PRM_IO_PMCTRL */
 #define OMAP4430_ISOCLK_STATUS_SHIFT					1
-#define OMAP4430_ISOCLK_STATUS_MASK					BITFIELD(1, 1)
+#define OMAP4430_ISOCLK_STATUS_MASK					(1 << 1)
 
 /* Used by PRM_IO_PMCTRL */
 #define OMAP4430_ISOOVR_EXTEND_SHIFT					4
-#define OMAP4430_ISOOVR_EXTEND_MASK					BITFIELD(4, 4)
+#define OMAP4430_ISOOVR_EXTEND_MASK					(1 << 4)
 
 /* Used by PRM_IO_COUNT */
 #define OMAP4430_ISO_2_ON_TIME_SHIFT					0
-#define OMAP4430_ISO_2_ON_TIME_MASK					BITFIELD(0, 7)
+#define OMAP4430_ISO_2_ON_TIME_MASK					(0xff << 0)
 
 /* Used by PM_L3INIT_PWRSTCTRL */
 #define OMAP4430_L3INIT_BANK1_ONSTATE_SHIFT				16
-#define OMAP4430_L3INIT_BANK1_ONSTATE_MASK				BITFIELD(16, 17)
+#define OMAP4430_L3INIT_BANK1_ONSTATE_MASK				(0x3 << 16)
 
 /* Used by PM_L3INIT_PWRSTCTRL */
 #define OMAP4430_L3INIT_BANK1_RETSTATE_SHIFT				8
-#define OMAP4430_L3INIT_BANK1_RETSTATE_MASK				BITFIELD(8, 8)
+#define OMAP4430_L3INIT_BANK1_RETSTATE_MASK				(1 << 8)
 
 /* Used by PM_L3INIT_PWRSTST */
 #define OMAP4430_L3INIT_BANK1_STATEST_SHIFT				4
-#define OMAP4430_L3INIT_BANK1_STATEST_MASK				BITFIELD(4, 5)
+#define OMAP4430_L3INIT_BANK1_STATEST_MASK				(0x3 << 4)
 
 /*
- * Used by PM_CORE_PWRSTCTRL, PM_L3INIT_PWRSTCTRL, PM_ABE_PWRSTCTRL,
- * PM_MPU_PWRSTCTRL, PM_DSS_PWRSTCTRL, PM_L4PER_PWRSTCTRL, PM_TESLA_PWRSTCTRL,
- * PM_IVAHD_PWRSTCTRL
+ * Used by PM_ABE_PWRSTST, PM_CORE_PWRSTST, PM_IVAHD_PWRSTST,
+ * PM_L3INIT_PWRSTST, PM_L4PER_PWRSTST, PM_MPU_PWRSTST, PM_TESLA_PWRSTST
+ */
+#define OMAP4430_LASTPOWERSTATEENTERED_SHIFT				24
+#define OMAP4430_LASTPOWERSTATEENTERED_MASK				(0x3 << 24)
+
+/*
+ * Used by PM_ABE_PWRSTCTRL, PM_CORE_PWRSTCTRL, PM_DSS_PWRSTCTRL,
+ * PM_IVAHD_PWRSTCTRL, PM_L3INIT_PWRSTCTRL, PM_L4PER_PWRSTCTRL,
+ * PM_MPU_PWRSTCTRL, PM_TESLA_PWRSTCTRL
  */
 #define OMAP4430_LOGICRETSTATE_SHIFT					2
-#define OMAP4430_LOGICRETSTATE_MASK					BITFIELD(2, 2)
+#define OMAP4430_LOGICRETSTATE_MASK					(1 << 2)
 
 /*
- * Used by PM_EMU_PWRSTST, PM_CORE_PWRSTST, PM_CAM_PWRSTST, PM_L3INIT_PWRSTST,
- * PM_ABE_PWRSTST, PM_GFX_PWRSTST, PM_MPU_PWRSTST, PM_CEFUSE_PWRSTST,
- * PM_DSS_PWRSTST, PM_L4PER_PWRSTST, PM_TESLA_PWRSTST, PM_IVAHD_PWRSTST
+ * Used by PM_ABE_PWRSTST, PM_CAM_PWRSTST, PM_CEFUSE_PWRSTST, PM_CORE_PWRSTST,
+ * PM_DSS_PWRSTST, PM_EMU_PWRSTST, PM_GFX_PWRSTST, PM_IVAHD_PWRSTST,
+ * PM_L3INIT_PWRSTST, PM_L4PER_PWRSTST, PM_MPU_PWRSTST, PM_TESLA_PWRSTST
  */
 #define OMAP4430_LOGICSTATEST_SHIFT					2
-#define OMAP4430_LOGICSTATEST_MASK					BITFIELD(2, 2)
+#define OMAP4430_LOGICSTATEST_MASK					(1 << 2)
 
 /*
- * Used by RM_WKUP_GPIO1_CONTEXT, RM_WKUP_KEYBOARD_CONTEXT,
- * RM_WKUP_L4WKUP_CONTEXT, RM_WKUP_RTC_CONTEXT, RM_WKUP_SARRAM_CONTEXT,
- * RM_WKUP_SYNCTIMER_CONTEXT, RM_WKUP_TIMER12_CONTEXT, RM_WKUP_TIMER1_CONTEXT,
- * RM_WKUP_USIM_CONTEXT, RM_WKUP_WDT1_CONTEXT, RM_WKUP_WDT2_CONTEXT,
- * RM_EMU_DEBUGSS_CONTEXT, RM_D2D_SAD2D_CONTEXT, RM_D2D_SAD2D_FW_CONTEXT,
- * RM_DUCATI_DUCATI_CONTEXT, RM_L3INSTR_L3_3_CONTEXT,
- * RM_L3INSTR_L3_INSTR_CONTEXT, RM_L3INSTR_OCP_WP1_CONTEXT,
- * RM_L3_1_L3_1_CONTEXT, RM_L3_2_L3_2_CONTEXT, RM_L3_2_OCMC_RAM_CONTEXT,
- * RM_L4CFG_L4_CFG_CONTEXT, RM_L4CFG_SAR_ROM_CONTEXT, RM_MEMIF_DLL_CONTEXT,
- * RM_MEMIF_DLL_H_CONTEXT, RM_MEMIF_DMM_CONTEXT, RM_MEMIF_EMIF_FW_CONTEXT,
- * RM_CAM_FDIF_CONTEXT, RM_CAM_ISS_CONTEXT, RM_L3INIT_CCPTX_CONTEXT,
- * RM_L3INIT_EMAC_CONTEXT, RM_L3INIT_P1500_CONTEXT, RM_L3INIT_PCIESS_CONTEXT,
- * RM_L3INIT_SATA_CONTEXT, RM_L3INIT_TPPSS_CONTEXT, RM_L3INIT_UNIPRO1_CONTEXT,
- * RM_L3INIT_USBPHYOCP2SCP_CONTEXT, RM_L3INIT_XHPI_CONTEXT,
- * RM_ABE_AESS_CONTEXT, RM_ABE_DMIC_CONTEXT, RM_ABE_MCASP_CONTEXT,
+ * Used by RM_ABE_AESS_CONTEXT, RM_ABE_DMIC_CONTEXT, RM_ABE_MCASP_CONTEXT,
  * RM_ABE_MCBSP1_CONTEXT, RM_ABE_MCBSP2_CONTEXT, RM_ABE_MCBSP3_CONTEXT,
  * RM_ABE_PDM_CONTEXT, RM_ABE_SLIMBUS_CONTEXT, RM_ABE_TIMER5_CONTEXT,
  * RM_ABE_TIMER6_CONTEXT, RM_ABE_TIMER7_CONTEXT, RM_ABE_TIMER8_CONTEXT,
- * RM_ABE_WDT3_CONTEXT, RM_GFX_GFX_CONTEXT, RM_MPU_MPU_CONTEXT,
- * RM_CEFUSE_CEFUSE_CONTEXT, RM_ALWON_MDMINTC_CONTEXT,
- * RM_ALWON_SR_CORE_CONTEXT, RM_ALWON_SR_IVA_CONTEXT, RM_ALWON_SR_MPU_CONTEXT,
- * RM_DSS_DEISS_CONTEXT, RM_DSS_DSS_CONTEXT, RM_L4PER_ADC_CONTEXT,
- * RM_L4PER_DMTIMER10_CONTEXT, RM_L4PER_DMTIMER11_CONTEXT,
- * RM_L4PER_DMTIMER2_CONTEXT, RM_L4PER_DMTIMER3_CONTEXT,
- * RM_L4PER_DMTIMER4_CONTEXT, RM_L4PER_DMTIMER9_CONTEXT, RM_L4PER_ELM_CONTEXT,
- * RM_L4PER_HDQ1W_CONTEXT, RM_L4PER_HECC1_CONTEXT, RM_L4PER_HECC2_CONTEXT,
- * RM_L4PER_I2C2_CONTEXT, RM_L4PER_I2C3_CONTEXT, RM_L4PER_I2C4_CONTEXT,
- * RM_L4PER_I2C5_CONTEXT, RM_L4PER_L4_PER_CONTEXT, RM_L4PER_MCASP2_CONTEXT,
- * RM_L4PER_MCASP3_CONTEXT, RM_L4PER_MCBSP4_CONTEXT, RM_L4PER_MCSPI1_CONTEXT,
- * RM_L4PER_MCSPI2_CONTEXT, RM_L4PER_MCSPI3_CONTEXT, RM_L4PER_MCSPI4_CONTEXT,
- * RM_L4PER_MGATE_CONTEXT, RM_L4PER_MMCSD3_CONTEXT, RM_L4PER_MMCSD4_CONTEXT,
- * RM_L4PER_MMCSD5_CONTEXT, RM_L4PER_MSPROHG_CONTEXT,
- * RM_L4PER_SLIMBUS2_CONTEXT, RM_L4SEC_PKAEIP29_CONTEXT,
- * RM_TESLA_TESLA_CONTEXT, RM_IVAHD_IVAHD_CONTEXT, RM_IVAHD_SL2_CONTEXT
+ * RM_ABE_WDT3_CONTEXT, RM_ALWON_MDMINTC_CONTEXT, RM_ALWON_SR_CORE_CONTEXT,
+ * RM_ALWON_SR_IVA_CONTEXT, RM_ALWON_SR_MPU_CONTEXT, RM_CAM_FDIF_CONTEXT,
+ * RM_CAM_ISS_CONTEXT, RM_CEFUSE_CEFUSE_CONTEXT, RM_D2D_SAD2D_CONTEXT,
+ * RM_D2D_SAD2D_FW_CONTEXT, RM_DSS_DEISS_CONTEXT, RM_DSS_DSS_CONTEXT,
+ * RM_DUCATI_DUCATI_CONTEXT, RM_EMU_DEBUGSS_CONTEXT, RM_GFX_GFX_CONTEXT,
+ * RM_IVAHD_IVAHD_CONTEXT, RM_IVAHD_SL2_CONTEXT, RM_L3INIT_CCPTX_CONTEXT,
+ * RM_L3INIT_EMAC_CONTEXT, RM_L3INIT_P1500_CONTEXT, RM_L3INIT_PCIESS_CONTEXT,
+ * RM_L3INIT_SATA_CONTEXT, RM_L3INIT_TPPSS_CONTEXT, RM_L3INIT_UNIPRO1_CONTEXT,
+ * RM_L3INIT_USBPHYOCP2SCP_CONTEXT, RM_L3INIT_XHPI_CONTEXT,
+ * RM_L3INSTR_L3_3_CONTEXT, RM_L3INSTR_L3_INSTR_CONTEXT,
+ * RM_L3INSTR_OCP_WP1_CONTEXT, RM_L3_1_L3_1_CONTEXT, RM_L3_2_L3_2_CONTEXT,
+ * RM_L3_2_OCMC_RAM_CONTEXT, RM_L4CFG_L4_CFG_CONTEXT, RM_L4CFG_SAR_ROM_CONTEXT,
+ * RM_L4PER_ADC_CONTEXT, RM_L4PER_DMTIMER10_CONTEXT,
+ * RM_L4PER_DMTIMER11_CONTEXT, RM_L4PER_DMTIMER2_CONTEXT,
+ * RM_L4PER_DMTIMER3_CONTEXT, RM_L4PER_DMTIMER4_CONTEXT,
+ * RM_L4PER_DMTIMER9_CONTEXT, RM_L4PER_ELM_CONTEXT, RM_L4PER_HDQ1W_CONTEXT,
+ * RM_L4PER_HECC1_CONTEXT, RM_L4PER_HECC2_CONTEXT, RM_L4PER_I2C2_CONTEXT,
+ * RM_L4PER_I2C3_CONTEXT, RM_L4PER_I2C4_CONTEXT, RM_L4PER_I2C5_CONTEXT,
+ * RM_L4PER_L4_PER_CONTEXT, RM_L4PER_MCASP2_CONTEXT, RM_L4PER_MCASP3_CONTEXT,
+ * RM_L4PER_MCBSP4_CONTEXT, RM_L4PER_MCSPI1_CONTEXT, RM_L4PER_MCSPI2_CONTEXT,
+ * RM_L4PER_MCSPI3_CONTEXT, RM_L4PER_MCSPI4_CONTEXT, RM_L4PER_MGATE_CONTEXT,
+ * RM_L4PER_MMCSD3_CONTEXT, RM_L4PER_MMCSD4_CONTEXT, RM_L4PER_MMCSD5_CONTEXT,
+ * RM_L4PER_MSPROHG_CONTEXT, RM_L4PER_SLIMBUS2_CONTEXT,
+ * RM_L4SEC_PKAEIP29_CONTEXT, RM_MEMIF_DLL_CONTEXT, RM_MEMIF_DLL_H_CONTEXT,
+ * RM_MEMIF_DMM_CONTEXT, RM_MEMIF_EMIF_1_CONTEXT, RM_MEMIF_EMIF_2_CONTEXT,
+ * RM_MEMIF_EMIF_FW_CONTEXT, RM_MPU_MPU_CONTEXT, RM_TESLA_TESLA_CONTEXT,
+ * RM_WKUP_GPIO1_CONTEXT, RM_WKUP_KEYBOARD_CONTEXT, RM_WKUP_L4WKUP_CONTEXT,
+ * RM_WKUP_RTC_CONTEXT, RM_WKUP_SARRAM_CONTEXT, RM_WKUP_SYNCTIMER_CONTEXT,
+ * RM_WKUP_TIMER12_CONTEXT, RM_WKUP_TIMER1_CONTEXT, RM_WKUP_USIM_CONTEXT,
+ * RM_WKUP_WDT1_CONTEXT, RM_WKUP_WDT2_CONTEXT
  */
 #define OMAP4430_LOSTCONTEXT_DFF_SHIFT					0
-#define OMAP4430_LOSTCONTEXT_DFF_MASK					BITFIELD(0, 0)
+#define OMAP4430_LOSTCONTEXT_DFF_MASK					(1 << 0)
 
 /*
  * Used by RM_D2D_MODEM_ICR_CONTEXT, RM_D2D_SAD2D_CONTEXT,
- * RM_D2D_SAD2D_FW_CONTEXT, RM_DUCATI_DUCATI_CONTEXT, RM_L3INSTR_L3_3_CONTEXT,
+ * RM_D2D_SAD2D_FW_CONTEXT, RM_DSS_DSS_CONTEXT, RM_DUCATI_DUCATI_CONTEXT,
+ * RM_L3INIT_HSI_CONTEXT, RM_L3INIT_MMC1_CONTEXT, RM_L3INIT_MMC2_CONTEXT,
+ * RM_L3INIT_MMC6_CONTEXT, RM_L3INIT_USB_HOST_CONTEXT,
+ * RM_L3INIT_USB_HOST_FS_CONTEXT, RM_L3INIT_USB_OTG_CONTEXT,
+ * RM_L3INIT_USB_TLL_CONTEXT, RM_L3INSTR_L3_3_CONTEXT,
  * RM_L3INSTR_OCP_WP1_CONTEXT, RM_L3_1_L3_1_CONTEXT, RM_L3_2_GPMC_CONTEXT,
  * RM_L3_2_L3_2_CONTEXT, RM_L4CFG_HW_SEM_CONTEXT, RM_L4CFG_L4_CFG_CONTEXT,
- * RM_L4CFG_MAILBOX_CONTEXT, RM_MEMIF_DMM_CONTEXT, RM_MEMIF_EMIF_1_CONTEXT,
- * RM_MEMIF_EMIF_2_CONTEXT, RM_MEMIF_EMIF_FW_CONTEXT, RM_MEMIF_EMIF_H1_CONTEXT,
- * RM_MEMIF_EMIF_H2_CONTEXT, RM_SDMA_SDMA_CONTEXT, RM_L3INIT_HSI_CONTEXT,
- * RM_L3INIT_MMC1_CONTEXT, RM_L3INIT_MMC2_CONTEXT, RM_L3INIT_MMC6_CONTEXT,
- * RM_L3INIT_USB_HOST_CONTEXT, RM_L3INIT_USB_HOST_FS_CONTEXT,
- * RM_L3INIT_USB_OTG_CONTEXT, RM_L3INIT_USB_TLL_CONTEXT, RM_DSS_DSS_CONTEXT,
- * RM_L4PER_GPIO2_CONTEXT, RM_L4PER_GPIO3_CONTEXT, RM_L4PER_GPIO4_CONTEXT,
- * RM_L4PER_GPIO5_CONTEXT, RM_L4PER_GPIO6_CONTEXT, RM_L4PER_I2C1_CONTEXT,
- * RM_L4PER_L4_PER_CONTEXT, RM_L4PER_UART1_CONTEXT, RM_L4PER_UART2_CONTEXT,
- * RM_L4PER_UART3_CONTEXT, RM_L4PER_UART4_CONTEXT, RM_L4SEC_AES1_CONTEXT,
- * RM_L4SEC_AES2_CONTEXT, RM_L4SEC_CRYPTODMA_CONTEXT, RM_L4SEC_DES3DES_CONTEXT,
- * RM_L4SEC_RNG_CONTEXT, RM_L4SEC_SHA2MD51_CONTEXT, RM_TESLA_TESLA_CONTEXT
+ * RM_L4CFG_MAILBOX_CONTEXT, RM_L4PER_GPIO2_CONTEXT, RM_L4PER_GPIO3_CONTEXT,
+ * RM_L4PER_GPIO4_CONTEXT, RM_L4PER_GPIO5_CONTEXT, RM_L4PER_GPIO6_CONTEXT,
+ * RM_L4PER_I2C1_CONTEXT, RM_L4PER_L4_PER_CONTEXT, RM_L4PER_UART1_CONTEXT,
+ * RM_L4PER_UART2_CONTEXT, RM_L4PER_UART3_CONTEXT, RM_L4PER_UART4_CONTEXT,
+ * RM_L4SEC_AES1_CONTEXT, RM_L4SEC_AES2_CONTEXT, RM_L4SEC_CRYPTODMA_CONTEXT,
+ * RM_L4SEC_DES3DES_CONTEXT, RM_L4SEC_RNG_CONTEXT, RM_L4SEC_SHA2MD51_CONTEXT,
+ * RM_MEMIF_DMM_CONTEXT, RM_MEMIF_EMIF_1_CONTEXT, RM_MEMIF_EMIF_2_CONTEXT,
+ * RM_MEMIF_EMIF_FW_CONTEXT, RM_MEMIF_EMIF_H1_CONTEXT,
+ * RM_MEMIF_EMIF_H2_CONTEXT, RM_SDMA_SDMA_CONTEXT, RM_TESLA_TESLA_CONTEXT
  */
 #define OMAP4430_LOSTCONTEXT_RFF_SHIFT					1
-#define OMAP4430_LOSTCONTEXT_RFF_MASK					BITFIELD(1, 1)
+#define OMAP4430_LOSTCONTEXT_RFF_MASK					(1 << 1)
 
 /* Used by RM_ABE_AESS_CONTEXT */
 #define OMAP4430_LOSTMEM_AESSMEM_SHIFT					8
-#define OMAP4430_LOSTMEM_AESSMEM_MASK					BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_AESSMEM_MASK					(1 << 8)
 
 /* Used by RM_CAM_FDIF_CONTEXT, RM_CAM_ISS_CONTEXT */
 #define OMAP4430_LOSTMEM_CAM_MEM_SHIFT					8
-#define OMAP4430_LOSTMEM_CAM_MEM_MASK					BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_CAM_MEM_MASK					(1 << 8)
 
 /* Used by RM_L3INSTR_OCP_WP1_CONTEXT */
 #define OMAP4430_LOSTMEM_CORE_NRET_BANK_SHIFT				8
-#define OMAP4430_LOSTMEM_CORE_NRET_BANK_MASK				BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_CORE_NRET_BANK_MASK				(1 << 8)
 
 /* Renamed from LOSTMEM_CORE_NRET_BANK Used by RM_MEMIF_DMM_CONTEXT */
 #define OMAP4430_LOSTMEM_CORE_NRET_BANK_9_9_SHIFT			9
-#define OMAP4430_LOSTMEM_CORE_NRET_BANK_9_9_MASK			BITFIELD(9, 9)
+#define OMAP4430_LOSTMEM_CORE_NRET_BANK_9_9_MASK			(1 << 9)
 
 /* Used by RM_L3_2_OCMC_RAM_CONTEXT */
 #define OMAP4430_LOSTMEM_CORE_OCMRAM_SHIFT				8
-#define OMAP4430_LOSTMEM_CORE_OCMRAM_MASK				BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_CORE_OCMRAM_MASK				(1 << 8)
 
 /*
  * Used by RM_D2D_MODEM_ICR_CONTEXT, RM_MEMIF_DMM_CONTEXT,
  * RM_SDMA_SDMA_CONTEXT
  */
 #define OMAP4430_LOSTMEM_CORE_OTHER_BANK_SHIFT				8
-#define OMAP4430_LOSTMEM_CORE_OTHER_BANK_MASK				BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_CORE_OTHER_BANK_MASK				(1 << 8)
 
 /* Used by RM_DSS_DEISS_CONTEXT, RM_DSS_DSS_CONTEXT */
 #define OMAP4430_LOSTMEM_DSS_MEM_SHIFT					8
-#define OMAP4430_LOSTMEM_DSS_MEM_MASK					BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_DSS_MEM_MASK					(1 << 8)
 
 /* Used by RM_DUCATI_DUCATI_CONTEXT */
 #define OMAP4430_LOSTMEM_DUCATI_L2RAM_SHIFT				9
-#define OMAP4430_LOSTMEM_DUCATI_L2RAM_MASK				BITFIELD(9, 9)
+#define OMAP4430_LOSTMEM_DUCATI_L2RAM_MASK				(1 << 9)
 
 /* Used by RM_DUCATI_DUCATI_CONTEXT */
 #define OMAP4430_LOSTMEM_DUCATI_UNICACHE_SHIFT				8
-#define OMAP4430_LOSTMEM_DUCATI_UNICACHE_MASK				BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_DUCATI_UNICACHE_MASK				(1 << 8)
 
 /* Used by RM_EMU_DEBUGSS_CONTEXT */
 #define OMAP4430_LOSTMEM_EMU_BANK_SHIFT					8
-#define OMAP4430_LOSTMEM_EMU_BANK_MASK					BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_EMU_BANK_MASK					(1 << 8)
 
 /* Used by RM_GFX_GFX_CONTEXT */
 #define OMAP4430_LOSTMEM_GFX_MEM_SHIFT					8
-#define OMAP4430_LOSTMEM_GFX_MEM_MASK					BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_GFX_MEM_MASK					(1 << 8)
 
 /* Used by RM_IVAHD_IVAHD_CONTEXT */
 #define OMAP4430_LOSTMEM_HWA_MEM_SHIFT					10
-#define OMAP4430_LOSTMEM_HWA_MEM_MASK					BITFIELD(10, 10)
+#define OMAP4430_LOSTMEM_HWA_MEM_MASK					(1 << 10)
 
 /*
  * Used by RM_L3INIT_CCPTX_CONTEXT, RM_L3INIT_EMAC_CONTEXT,
@@ -620,19 +644,19 @@
  * RM_L3INIT_USB_OTG_CONTEXT, RM_L3INIT_XHPI_CONTEXT
  */
 #define OMAP4430_LOSTMEM_L3INIT_BANK1_SHIFT				8
-#define OMAP4430_LOSTMEM_L3INIT_BANK1_MASK				BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_L3INIT_BANK1_MASK				(1 << 8)
 
 /* Used by RM_MPU_MPU_CONTEXT */
 #define OMAP4430_LOSTMEM_MPU_L1_SHIFT					8
-#define OMAP4430_LOSTMEM_MPU_L1_MASK					BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_MPU_L1_MASK					(1 << 8)
 
 /* Used by RM_MPU_MPU_CONTEXT */
 #define OMAP4430_LOSTMEM_MPU_L2_SHIFT					9
-#define OMAP4430_LOSTMEM_MPU_L2_MASK					BITFIELD(9, 9)
+#define OMAP4430_LOSTMEM_MPU_L2_MASK					(1 << 9)
 
 /* Used by RM_MPU_MPU_CONTEXT */
 #define OMAP4430_LOSTMEM_MPU_RAM_SHIFT					10
-#define OMAP4430_LOSTMEM_MPU_RAM_MASK					BITFIELD(10, 10)
+#define OMAP4430_LOSTMEM_MPU_RAM_MASK					(1 << 10)
 
 /*
  * Used by RM_L4PER_HECC1_CONTEXT, RM_L4PER_HECC2_CONTEXT,
@@ -640,14 +664,14 @@
  * RM_L4PER_MMCSD5_CONTEXT, RM_L4PER_SLIMBUS2_CONTEXT, RM_L4SEC_PKAEIP29_CONTEXT
  */
 #define OMAP4430_LOSTMEM_NONRETAINED_BANK_SHIFT				8
-#define OMAP4430_LOSTMEM_NONRETAINED_BANK_MASK				BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_NONRETAINED_BANK_MASK				(1 << 8)
 
 /*
  * Used by RM_ABE_DMIC_CONTEXT, RM_ABE_MCBSP1_CONTEXT, RM_ABE_MCBSP2_CONTEXT,
  * RM_ABE_MCBSP3_CONTEXT, RM_ABE_PDM_CONTEXT, RM_ABE_SLIMBUS_CONTEXT
  */
 #define OMAP4430_LOSTMEM_PERIHPMEM_SHIFT				8
-#define OMAP4430_LOSTMEM_PERIHPMEM_MASK					BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_PERIHPMEM_MASK					(1 << 8)
 
 /*
  * Used by RM_L4PER_MSPROHG_CONTEXT, RM_L4PER_UART1_CONTEXT,
@@ -655,245 +679,237 @@
  * RM_L4SEC_CRYPTODMA_CONTEXT
  */
 #define OMAP4430_LOSTMEM_RETAINED_BANK_SHIFT				8
-#define OMAP4430_LOSTMEM_RETAINED_BANK_MASK				BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_RETAINED_BANK_MASK				(1 << 8)
 
 /* Used by RM_IVAHD_SL2_CONTEXT */
 #define OMAP4430_LOSTMEM_SL2_MEM_SHIFT					8
-#define OMAP4430_LOSTMEM_SL2_MEM_MASK					BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_SL2_MEM_MASK					(1 << 8)
 
 /* Used by RM_IVAHD_IVAHD_CONTEXT */
 #define OMAP4430_LOSTMEM_TCM1_MEM_SHIFT					8
-#define OMAP4430_LOSTMEM_TCM1_MEM_MASK					BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_TCM1_MEM_MASK					(1 << 8)
 
 /* Used by RM_IVAHD_IVAHD_CONTEXT */
 #define OMAP4430_LOSTMEM_TCM2_MEM_SHIFT					9
-#define OMAP4430_LOSTMEM_TCM2_MEM_MASK					BITFIELD(9, 9)
+#define OMAP4430_LOSTMEM_TCM2_MEM_MASK					(1 << 9)
 
 /* Used by RM_TESLA_TESLA_CONTEXT */
 #define OMAP4430_LOSTMEM_TESLA_EDMA_SHIFT				10
-#define OMAP4430_LOSTMEM_TESLA_EDMA_MASK				BITFIELD(10, 10)
+#define OMAP4430_LOSTMEM_TESLA_EDMA_MASK				(1 << 10)
 
 /* Used by RM_TESLA_TESLA_CONTEXT */
 #define OMAP4430_LOSTMEM_TESLA_L1_SHIFT					8
-#define OMAP4430_LOSTMEM_TESLA_L1_MASK					BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_TESLA_L1_MASK					(1 << 8)
 
 /* Used by RM_TESLA_TESLA_CONTEXT */
 #define OMAP4430_LOSTMEM_TESLA_L2_SHIFT					9
-#define OMAP4430_LOSTMEM_TESLA_L2_MASK					BITFIELD(9, 9)
+#define OMAP4430_LOSTMEM_TESLA_L2_MASK					(1 << 9)
 
 /* Used by RM_WKUP_SARRAM_CONTEXT */
 #define OMAP4430_LOSTMEM_WKUP_BANK_SHIFT				8
-#define OMAP4430_LOSTMEM_WKUP_BANK_MASK					BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_WKUP_BANK_MASK					(1 << 8)
 
 /*
- * Used by PM_CORE_PWRSTCTRL, PM_CAM_PWRSTCTRL, PM_L3INIT_PWRSTCTRL,
- * PM_ABE_PWRSTCTRL, PM_GFX_PWRSTCTRL, PM_MPU_PWRSTCTRL, PM_CEFUSE_PWRSTCTRL,
- * PM_DSS_PWRSTCTRL, PM_L4PER_PWRSTCTRL, PM_TESLA_PWRSTCTRL, PM_IVAHD_PWRSTCTRL
+ * Used by PM_ABE_PWRSTCTRL, PM_CAM_PWRSTCTRL, PM_CEFUSE_PWRSTCTRL,
+ * PM_CORE_PWRSTCTRL, PM_DSS_PWRSTCTRL, PM_GFX_PWRSTCTRL, PM_IVAHD_PWRSTCTRL,
+ * PM_L3INIT_PWRSTCTRL, PM_L4PER_PWRSTCTRL, PM_MPU_PWRSTCTRL, PM_TESLA_PWRSTCTRL
  */
 #define OMAP4430_LOWPOWERSTATECHANGE_SHIFT				4
-#define OMAP4430_LOWPOWERSTATECHANGE_MASK				BITFIELD(4, 4)
-
-/* Used by PM_CORE_PWRSTCTRL */
-#define OMAP4430_MEMORYCHANGE_SHIFT					3
-#define OMAP4430_MEMORYCHANGE_MASK					BITFIELD(3, 3)
+#define OMAP4430_LOWPOWERSTATECHANGE_MASK				(1 << 4)
 
 /* Used by PRM_MODEM_IF_CTRL */
 #define OMAP4430_MODEM_READY_SHIFT					1
-#define OMAP4430_MODEM_READY_MASK					BITFIELD(1, 1)
+#define OMAP4430_MODEM_READY_MASK					(1 << 1)
 
 /* Used by PRM_MODEM_IF_CTRL */
 #define OMAP4430_MODEM_SHUTDOWN_IRQ_SHIFT				9
-#define OMAP4430_MODEM_SHUTDOWN_IRQ_MASK				BITFIELD(9, 9)
+#define OMAP4430_MODEM_SHUTDOWN_IRQ_MASK				(1 << 9)
 
 /* Used by PRM_MODEM_IF_CTRL */
 #define OMAP4430_MODEM_SLEEP_ST_SHIFT					16
-#define OMAP4430_MODEM_SLEEP_ST_MASK					BITFIELD(16, 16)
+#define OMAP4430_MODEM_SLEEP_ST_MASK					(1 << 16)
 
 /* Used by PRM_MODEM_IF_CTRL */
 #define OMAP4430_MODEM_WAKE_IRQ_SHIFT					8
-#define OMAP4430_MODEM_WAKE_IRQ_MASK					BITFIELD(8, 8)
+#define OMAP4430_MODEM_WAKE_IRQ_MASK					(1 << 8)
 
 /* Used by PM_MPU_PWRSTCTRL */
 #define OMAP4430_MPU_L1_ONSTATE_SHIFT					16
-#define OMAP4430_MPU_L1_ONSTATE_MASK					BITFIELD(16, 17)
+#define OMAP4430_MPU_L1_ONSTATE_MASK					(0x3 << 16)
 
 /* Used by PM_MPU_PWRSTCTRL */
 #define OMAP4430_MPU_L1_RETSTATE_SHIFT					8
-#define OMAP4430_MPU_L1_RETSTATE_MASK					BITFIELD(8, 8)
+#define OMAP4430_MPU_L1_RETSTATE_MASK					(1 << 8)
 
 /* Used by PM_MPU_PWRSTST */
 #define OMAP4430_MPU_L1_STATEST_SHIFT					4
-#define OMAP4430_MPU_L1_STATEST_MASK					BITFIELD(4, 5)
+#define OMAP4430_MPU_L1_STATEST_MASK					(0x3 << 4)
 
 /* Used by PM_MPU_PWRSTCTRL */
 #define OMAP4430_MPU_L2_ONSTATE_SHIFT					18
-#define OMAP4430_MPU_L2_ONSTATE_MASK					BITFIELD(18, 19)
+#define OMAP4430_MPU_L2_ONSTATE_MASK					(0x3 << 18)
 
 /* Used by PM_MPU_PWRSTCTRL */
 #define OMAP4430_MPU_L2_RETSTATE_SHIFT					9
-#define OMAP4430_MPU_L2_RETSTATE_MASK					BITFIELD(9, 9)
+#define OMAP4430_MPU_L2_RETSTATE_MASK					(1 << 9)
 
 /* Used by PM_MPU_PWRSTST */
 #define OMAP4430_MPU_L2_STATEST_SHIFT					6
-#define OMAP4430_MPU_L2_STATEST_MASK					BITFIELD(6, 7)
+#define OMAP4430_MPU_L2_STATEST_MASK					(0x3 << 6)
 
 /* Used by PM_MPU_PWRSTCTRL */
 #define OMAP4430_MPU_RAM_ONSTATE_SHIFT					20
-#define OMAP4430_MPU_RAM_ONSTATE_MASK					BITFIELD(20, 21)
+#define OMAP4430_MPU_RAM_ONSTATE_MASK					(0x3 << 20)
 
 /* Used by PM_MPU_PWRSTCTRL */
 #define OMAP4430_MPU_RAM_RETSTATE_SHIFT					10
-#define OMAP4430_MPU_RAM_RETSTATE_MASK					BITFIELD(10, 10)
+#define OMAP4430_MPU_RAM_RETSTATE_MASK					(1 << 10)
 
 /* Used by PM_MPU_PWRSTST */
 #define OMAP4430_MPU_RAM_STATEST_SHIFT					8
-#define OMAP4430_MPU_RAM_STATEST_MASK					BITFIELD(8, 9)
+#define OMAP4430_MPU_RAM_STATEST_MASK					(0x3 << 8)
 
 /* Used by PRM_RSTST */
 #define OMAP4430_MPU_SECURITY_VIOL_RST_SHIFT				2
-#define OMAP4430_MPU_SECURITY_VIOL_RST_MASK				BITFIELD(2, 2)
+#define OMAP4430_MPU_SECURITY_VIOL_RST_MASK				(1 << 2)
 
 /* Used by PRM_RSTST */
 #define OMAP4430_MPU_WDT_RST_SHIFT					3
-#define OMAP4430_MPU_WDT_RST_MASK					BITFIELD(3, 3)
+#define OMAP4430_MPU_WDT_RST_MASK					(1 << 3)
 
 /* Used by PM_L4PER_PWRSTCTRL */
 #define OMAP4430_NONRETAINED_BANK_ONSTATE_SHIFT				18
-#define OMAP4430_NONRETAINED_BANK_ONSTATE_MASK				BITFIELD(18, 19)
+#define OMAP4430_NONRETAINED_BANK_ONSTATE_MASK				(0x3 << 18)
 
 /* Used by PM_L4PER_PWRSTCTRL */
 #define OMAP4430_NONRETAINED_BANK_RETSTATE_SHIFT			9
-#define OMAP4430_NONRETAINED_BANK_RETSTATE_MASK				BITFIELD(9, 9)
+#define OMAP4430_NONRETAINED_BANK_RETSTATE_MASK				(1 << 9)
 
 /* Used by PM_L4PER_PWRSTST */
 #define OMAP4430_NONRETAINED_BANK_STATEST_SHIFT				6
-#define OMAP4430_NONRETAINED_BANK_STATEST_MASK				BITFIELD(6, 7)
+#define OMAP4430_NONRETAINED_BANK_STATEST_MASK				(0x3 << 6)
 
 /* Used by PM_CORE_PWRSTCTRL */
 #define OMAP4430_OCP_NRET_BANK_ONSTATE_SHIFT				24
-#define OMAP4430_OCP_NRET_BANK_ONSTATE_MASK				BITFIELD(24, 25)
+#define OMAP4430_OCP_NRET_BANK_ONSTATE_MASK				(0x3 << 24)
 
 /* Used by PM_CORE_PWRSTCTRL */
 #define OMAP4430_OCP_NRET_BANK_RETSTATE_SHIFT				12
-#define OMAP4430_OCP_NRET_BANK_RETSTATE_MASK				BITFIELD(12, 12)
+#define OMAP4430_OCP_NRET_BANK_RETSTATE_MASK				(1 << 12)
 
 /* Used by PM_CORE_PWRSTST */
 #define OMAP4430_OCP_NRET_BANK_STATEST_SHIFT				12
-#define OMAP4430_OCP_NRET_BANK_STATEST_MASK				BITFIELD(12, 13)
+#define OMAP4430_OCP_NRET_BANK_STATEST_MASK				(0x3 << 12)
 
 /*
  * Used by PRM_VC_VAL_CMD_VDD_CORE_L, PRM_VC_VAL_CMD_VDD_IVA_L,
  * PRM_VC_VAL_CMD_VDD_MPU_L
  */
 #define OMAP4430_OFF_SHIFT						0
-#define OMAP4430_OFF_MASK						BITFIELD(0, 7)
-
-/* Used by PRM_LDO_BANDGAP_CTRL */
-#define OMAP4430_OFF_ENABLE_SHIFT					0
-#define OMAP4430_OFF_ENABLE_MASK					BITFIELD(0, 0)
+#define OMAP4430_OFF_MASK						(0xff << 0)
 
 /*
  * Used by PRM_VC_VAL_CMD_VDD_CORE_L, PRM_VC_VAL_CMD_VDD_IVA_L,
  * PRM_VC_VAL_CMD_VDD_MPU_L
  */
 #define OMAP4430_ON_SHIFT						24
-#define OMAP4430_ON_MASK						BITFIELD(24, 31)
+#define OMAP4430_ON_MASK						(0xff << 24)
 
 /*
  * Used by PRM_VC_VAL_CMD_VDD_CORE_L, PRM_VC_VAL_CMD_VDD_IVA_L,
  * PRM_VC_VAL_CMD_VDD_MPU_L
  */
 #define OMAP4430_ONLP_SHIFT						16
-#define OMAP4430_ONLP_MASK						BITFIELD(16, 23)
+#define OMAP4430_ONLP_MASK						(0xff << 16)
 
 /* Used by PRM_LDO_ABB_IVA_CTRL, PRM_LDO_ABB_MPU_CTRL */
 #define OMAP4430_OPP_CHANGE_SHIFT					2
-#define OMAP4430_OPP_CHANGE_MASK					BITFIELD(2, 2)
+#define OMAP4430_OPP_CHANGE_MASK					(1 << 2)
 
 /* Used by PRM_LDO_ABB_IVA_CTRL, PRM_LDO_ABB_MPU_CTRL */
 #define OMAP4430_OPP_SEL_SHIFT						0
-#define OMAP4430_OPP_SEL_MASK						BITFIELD(0, 1)
+#define OMAP4430_OPP_SEL_MASK						(0x3 << 0)
 
 /* Used by PRM_SRAM_COUNT */
 #define OMAP4430_PCHARGECNT_VALUE_SHIFT					0
-#define OMAP4430_PCHARGECNT_VALUE_MASK					BITFIELD(0, 5)
+#define OMAP4430_PCHARGECNT_VALUE_MASK					(0x3f << 0)
 
 /* Used by PRM_PSCON_COUNT */
 #define OMAP4430_PCHARGE_TIME_SHIFT					0
-#define OMAP4430_PCHARGE_TIME_MASK					BITFIELD(0, 7)
+#define OMAP4430_PCHARGE_TIME_MASK					(0xff << 0)
 
 /* Used by PM_ABE_PWRSTCTRL */
 #define OMAP4430_PERIPHMEM_ONSTATE_SHIFT				20
-#define OMAP4430_PERIPHMEM_ONSTATE_MASK					BITFIELD(20, 21)
+#define OMAP4430_PERIPHMEM_ONSTATE_MASK					(0x3 << 20)
 
 /* Used by PM_ABE_PWRSTCTRL */
 #define OMAP4430_PERIPHMEM_RETSTATE_SHIFT				10
-#define OMAP4430_PERIPHMEM_RETSTATE_MASK				BITFIELD(10, 10)
+#define OMAP4430_PERIPHMEM_RETSTATE_MASK				(1 << 10)
 
 /* Used by PM_ABE_PWRSTST */
 #define OMAP4430_PERIPHMEM_STATEST_SHIFT				8
-#define OMAP4430_PERIPHMEM_STATEST_MASK					BITFIELD(8, 9)
+#define OMAP4430_PERIPHMEM_STATEST_MASK					(0x3 << 8)
 
 /* Used by PRM_PHASE1_CNDP */
 #define OMAP4430_PHASE1_CNDP_SHIFT					0
-#define OMAP4430_PHASE1_CNDP_MASK					BITFIELD(0, 31)
+#define OMAP4430_PHASE1_CNDP_MASK					(0xffffffff << 0)
 
 /* Used by PRM_PHASE2A_CNDP */
 #define OMAP4430_PHASE2A_CNDP_SHIFT					0
-#define OMAP4430_PHASE2A_CNDP_MASK					BITFIELD(0, 31)
+#define OMAP4430_PHASE2A_CNDP_MASK					(0xffffffff << 0)
 
 /* Used by PRM_PHASE2B_CNDP */
 #define OMAP4430_PHASE2B_CNDP_SHIFT					0
-#define OMAP4430_PHASE2B_CNDP_MASK					BITFIELD(0, 31)
+#define OMAP4430_PHASE2B_CNDP_MASK					(0xffffffff << 0)
 
 /* Used by PRM_PSCON_COUNT */
 #define OMAP4430_PONOUT_2_PGOODIN_TIME_SHIFT				8
-#define OMAP4430_PONOUT_2_PGOODIN_TIME_MASK				BITFIELD(8, 15)
+#define OMAP4430_PONOUT_2_PGOODIN_TIME_MASK				(0xff << 8)
 
 /*
- * Used by PM_EMU_PWRSTCTRL, PM_CORE_PWRSTCTRL, PM_CAM_PWRSTCTRL,
- * PM_L3INIT_PWRSTCTRL, PM_ABE_PWRSTCTRL, PM_GFX_PWRSTCTRL, PM_MPU_PWRSTCTRL,
- * PM_CEFUSE_PWRSTCTRL, PM_DSS_PWRSTCTRL, PM_L4PER_PWRSTCTRL,
- * PM_TESLA_PWRSTCTRL, PM_IVAHD_PWRSTCTRL
+ * Used by PM_ABE_PWRSTCTRL, PM_CAM_PWRSTCTRL, PM_CEFUSE_PWRSTCTRL,
+ * PM_CORE_PWRSTCTRL, PM_DSS_PWRSTCTRL, PM_EMU_PWRSTCTRL, PM_GFX_PWRSTCTRL,
+ * PM_IVAHD_PWRSTCTRL, PM_L3INIT_PWRSTCTRL, PM_L4PER_PWRSTCTRL,
+ * PM_MPU_PWRSTCTRL, PM_TESLA_PWRSTCTRL
  */
 #define OMAP4430_POWERSTATE_SHIFT					0
-#define OMAP4430_POWERSTATE_MASK					BITFIELD(0, 1)
+#define OMAP4430_POWERSTATE_MASK					(0x3 << 0)
 
 /*
- * Used by PM_EMU_PWRSTST, PM_CORE_PWRSTST, PM_CAM_PWRSTST, PM_L3INIT_PWRSTST,
- * PM_ABE_PWRSTST, PM_GFX_PWRSTST, PM_MPU_PWRSTST, PM_CEFUSE_PWRSTST,
- * PM_DSS_PWRSTST, PM_L4PER_PWRSTST, PM_TESLA_PWRSTST, PM_IVAHD_PWRSTST
+ * Used by PM_ABE_PWRSTST, PM_CAM_PWRSTST, PM_CEFUSE_PWRSTST, PM_CORE_PWRSTST,
+ * PM_DSS_PWRSTST, PM_EMU_PWRSTST, PM_GFX_PWRSTST, PM_IVAHD_PWRSTST,
+ * PM_L3INIT_PWRSTST, PM_L4PER_PWRSTST, PM_MPU_PWRSTST, PM_TESLA_PWRSTST
  */
 #define OMAP4430_POWERSTATEST_SHIFT					0
-#define OMAP4430_POWERSTATEST_MASK					BITFIELD(0, 1)
+#define OMAP4430_POWERSTATEST_MASK					(0x3 << 0)
 
 /* Used by PRM_PWRREQCTRL */
 #define OMAP4430_PWRREQ_COND_SHIFT					0
-#define OMAP4430_PWRREQ_COND_MASK					BITFIELD(0, 1)
+#define OMAP4430_PWRREQ_COND_MASK					(0x3 << 0)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_RACEN_VDD_CORE_L_SHIFT					3
-#define OMAP4430_RACEN_VDD_CORE_L_MASK					BITFIELD(3, 3)
+#define OMAP4430_RACEN_VDD_CORE_L_MASK					(1 << 3)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_RACEN_VDD_IVA_L_SHIFT					11
-#define OMAP4430_RACEN_VDD_IVA_L_MASK					BITFIELD(11, 11)
+#define OMAP4430_RACEN_VDD_IVA_L_MASK					(1 << 11)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_RACEN_VDD_MPU_L_SHIFT					20
-#define OMAP4430_RACEN_VDD_MPU_L_MASK					BITFIELD(20, 20)
+#define OMAP4430_RACEN_VDD_MPU_L_MASK					(1 << 20)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_RAC_VDD_CORE_L_SHIFT					2
-#define OMAP4430_RAC_VDD_CORE_L_MASK					BITFIELD(2, 2)
+#define OMAP4430_RAC_VDD_CORE_L_MASK					(1 << 2)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_RAC_VDD_IVA_L_SHIFT					10
-#define OMAP4430_RAC_VDD_IVA_L_MASK					BITFIELD(10, 10)
+#define OMAP4430_RAC_VDD_IVA_L_MASK					(1 << 10)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_RAC_VDD_MPU_L_SHIFT					19
-#define OMAP4430_RAC_VDD_MPU_L_MASK					BITFIELD(19, 19)
+#define OMAP4430_RAC_VDD_MPU_L_MASK					(1 << 19)
 
 /*
  * Used by PRM_VOLTSETUP_CORE_OFF, PRM_VOLTSETUP_CORE_RET_SLEEP,
@@ -901,7 +917,7 @@
  * PRM_VOLTSETUP_MPU_RET_SLEEP
  */
 #define OMAP4430_RAMP_DOWN_COUNT_SHIFT					16
-#define OMAP4430_RAMP_DOWN_COUNT_MASK					BITFIELD(16, 21)
+#define OMAP4430_RAMP_DOWN_COUNT_MASK					(0x3f << 16)
 
 /*
  * Used by PRM_VOLTSETUP_CORE_OFF, PRM_VOLTSETUP_CORE_RET_SLEEP,
@@ -909,7 +925,7 @@
  * PRM_VOLTSETUP_MPU_RET_SLEEP
  */
 #define OMAP4430_RAMP_DOWN_PRESCAL_SHIFT				24
-#define OMAP4430_RAMP_DOWN_PRESCAL_MASK					BITFIELD(24, 25)
+#define OMAP4430_RAMP_DOWN_PRESCAL_MASK					(0x3 << 24)
 
 /*
  * Used by PRM_VOLTSETUP_CORE_OFF, PRM_VOLTSETUP_CORE_RET_SLEEP,
@@ -917,7 +933,7 @@
  * PRM_VOLTSETUP_MPU_RET_SLEEP
  */
 #define OMAP4430_RAMP_UP_COUNT_SHIFT					0
-#define OMAP4430_RAMP_UP_COUNT_MASK					BITFIELD(0, 5)
+#define OMAP4430_RAMP_UP_COUNT_MASK					(0x3f << 0)
 
 /*
  * Used by PRM_VOLTSETUP_CORE_OFF, PRM_VOLTSETUP_CORE_RET_SLEEP,
@@ -925,1281 +941,1381 @@
  * PRM_VOLTSETUP_MPU_RET_SLEEP
  */
 #define OMAP4430_RAMP_UP_PRESCAL_SHIFT					8
-#define OMAP4430_RAMP_UP_PRESCAL_MASK					BITFIELD(8, 9)
+#define OMAP4430_RAMP_UP_PRESCAL_MASK					(0x3 << 8)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_RAV_VDD_CORE_L_SHIFT					1
-#define OMAP4430_RAV_VDD_CORE_L_MASK					BITFIELD(1, 1)
+#define OMAP4430_RAV_VDD_CORE_L_MASK					(1 << 1)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_RAV_VDD_IVA_L_SHIFT					9
-#define OMAP4430_RAV_VDD_IVA_L_MASK					BITFIELD(9, 9)
+#define OMAP4430_RAV_VDD_IVA_L_MASK					(1 << 9)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_RAV_VDD_MPU_L_SHIFT					18
-#define OMAP4430_RAV_VDD_MPU_L_MASK					BITFIELD(18, 18)
+#define OMAP4430_RAV_VDD_MPU_L_MASK					(1 << 18)
 
 /* Used by PRM_VC_VAL_BYPASS */
 #define OMAP4430_REGADDR_SHIFT						8
-#define OMAP4430_REGADDR_MASK						BITFIELD(8, 15)
+#define OMAP4430_REGADDR_MASK						(0xff << 8)
 
 /*
  * Used by PRM_VC_VAL_CMD_VDD_CORE_L, PRM_VC_VAL_CMD_VDD_IVA_L,
  * PRM_VC_VAL_CMD_VDD_MPU_L
  */
 #define OMAP4430_RET_SHIFT						8
-#define OMAP4430_RET_MASK						BITFIELD(8, 15)
+#define OMAP4430_RET_MASK						(0xff << 8)
 
 /* Used by PM_L4PER_PWRSTCTRL */
 #define OMAP4430_RETAINED_BANK_ONSTATE_SHIFT				16
-#define OMAP4430_RETAINED_BANK_ONSTATE_MASK				BITFIELD(16, 17)
+#define OMAP4430_RETAINED_BANK_ONSTATE_MASK				(0x3 << 16)
 
 /* Used by PM_L4PER_PWRSTCTRL */
 #define OMAP4430_RETAINED_BANK_RETSTATE_SHIFT				8
-#define OMAP4430_RETAINED_BANK_RETSTATE_MASK				BITFIELD(8, 8)
+#define OMAP4430_RETAINED_BANK_RETSTATE_MASK				(1 << 8)
 
 /* Used by PM_L4PER_PWRSTST */
 #define OMAP4430_RETAINED_BANK_STATEST_SHIFT				4
-#define OMAP4430_RETAINED_BANK_STATEST_MASK				BITFIELD(4, 5)
+#define OMAP4430_RETAINED_BANK_STATEST_MASK				(0x3 << 4)
 
 /*
  * Used by PRM_LDO_SRAM_CORE_CTRL, PRM_LDO_SRAM_IVA_CTRL,
  * PRM_LDO_SRAM_MPU_CTRL
  */
 #define OMAP4430_RETMODE_ENABLE_SHIFT					0
-#define OMAP4430_RETMODE_ENABLE_MASK					BITFIELD(0, 0)
+#define OMAP4430_RETMODE_ENABLE_MASK					(1 << 0)
 
-/* Used by REVISION_PRM */
-#define OMAP4430_REV_SHIFT						0
-#define OMAP4430_REV_MASK						BITFIELD(0, 7)
-
-/* Used by RM_DUCATI_RSTCTRL, RM_TESLA_RSTCTRL, RM_IVAHD_RSTCTRL */
+/* Used by RM_DUCATI_RSTCTRL, RM_IVAHD_RSTCTRL, RM_TESLA_RSTCTRL */
 #define OMAP4430_RST1_SHIFT						0
-#define OMAP4430_RST1_MASK						BITFIELD(0, 0)
+#define OMAP4430_RST1_MASK						(1 << 0)
 
-/* Used by RM_DUCATI_RSTST, RM_TESLA_RSTST, RM_IVAHD_RSTST */
+/* Used by RM_DUCATI_RSTST, RM_IVAHD_RSTST, RM_TESLA_RSTST */
 #define OMAP4430_RST1ST_SHIFT						0
-#define OMAP4430_RST1ST_MASK						BITFIELD(0, 0)
+#define OMAP4430_RST1ST_MASK						(1 << 0)
 
-/* Used by RM_DUCATI_RSTCTRL, RM_TESLA_RSTCTRL, RM_IVAHD_RSTCTRL */
+/* Used by RM_DUCATI_RSTCTRL, RM_IVAHD_RSTCTRL, RM_TESLA_RSTCTRL */
 #define OMAP4430_RST2_SHIFT						1
-#define OMAP4430_RST2_MASK						BITFIELD(1, 1)
+#define OMAP4430_RST2_MASK						(1 << 1)
 
-/* Used by RM_DUCATI_RSTST, RM_TESLA_RSTST, RM_IVAHD_RSTST */
+/* Used by RM_DUCATI_RSTST, RM_IVAHD_RSTST, RM_TESLA_RSTST */
 #define OMAP4430_RST2ST_SHIFT						1
-#define OMAP4430_RST2ST_MASK						BITFIELD(1, 1)
+#define OMAP4430_RST2ST_MASK						(1 << 1)
 
 /* Used by RM_DUCATI_RSTCTRL, RM_IVAHD_RSTCTRL */
 #define OMAP4430_RST3_SHIFT						2
-#define OMAP4430_RST3_MASK						BITFIELD(2, 2)
+#define OMAP4430_RST3_MASK						(1 << 2)
 
 /* Used by RM_DUCATI_RSTST, RM_IVAHD_RSTST */
 #define OMAP4430_RST3ST_SHIFT						2
-#define OMAP4430_RST3ST_MASK						BITFIELD(2, 2)
+#define OMAP4430_RST3ST_MASK						(1 << 2)
 
 /* Used by PRM_RSTTIME */
 #define OMAP4430_RSTTIME1_SHIFT						0
-#define OMAP4430_RSTTIME1_MASK						BITFIELD(0, 9)
+#define OMAP4430_RSTTIME1_MASK						(0x3ff << 0)
 
 /* Used by PRM_RSTTIME */
 #define OMAP4430_RSTTIME2_SHIFT						10
-#define OMAP4430_RSTTIME2_MASK						BITFIELD(10, 14)
+#define OMAP4430_RSTTIME2_MASK						(0x1f << 10)
 
 /* Used by PRM_RSTCTRL */
 #define OMAP4430_RST_GLOBAL_COLD_SW_SHIFT				1
-#define OMAP4430_RST_GLOBAL_COLD_SW_MASK				BITFIELD(1, 1)
+#define OMAP4430_RST_GLOBAL_COLD_SW_MASK				(1 << 1)
 
 /* Used by PRM_RSTCTRL */
 #define OMAP4430_RST_GLOBAL_WARM_SW_SHIFT				0
-#define OMAP4430_RST_GLOBAL_WARM_SW_MASK				BITFIELD(0, 0)
+#define OMAP4430_RST_GLOBAL_WARM_SW_MASK				(1 << 0)
+
+/* Used by REVISION_PRM */
+#define OMAP4430_R_RTL_SHIFT						11
+#define OMAP4430_R_RTL_MASK						(0x1f << 11)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_SA_VDD_CORE_L_SHIFT					0
-#define OMAP4430_SA_VDD_CORE_L_MASK					BITFIELD(0, 0)
+#define OMAP4430_SA_VDD_CORE_L_MASK					(1 << 0)
 
 /* Renamed from SA_VDD_CORE_L Used by PRM_VC_SMPS_SA */
 #define OMAP4430_SA_VDD_CORE_L_0_6_SHIFT				0
-#define OMAP4430_SA_VDD_CORE_L_0_6_MASK					BITFIELD(0, 6)
+#define OMAP4430_SA_VDD_CORE_L_0_6_MASK					(0x7f << 0)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_SA_VDD_IVA_L_SHIFT					8
-#define OMAP4430_SA_VDD_IVA_L_MASK					BITFIELD(8, 8)
+#define OMAP4430_SA_VDD_IVA_L_MASK					(1 << 8)
 
 /* Renamed from SA_VDD_IVA_L Used by PRM_VC_SMPS_SA */
 #define OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_SHIFT			8
-#define OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_MASK			BITFIELD(8, 14)
+#define OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_MASK			(0x7f << 8)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_SA_VDD_MPU_L_SHIFT					16
-#define OMAP4430_SA_VDD_MPU_L_MASK					BITFIELD(16, 16)
+#define OMAP4430_SA_VDD_MPU_L_MASK					(1 << 16)
 
 /* Renamed from SA_VDD_MPU_L Used by PRM_VC_SMPS_SA */
 #define OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_SHIFT			16
-#define OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_MASK			BITFIELD(16, 22)
+#define OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_MASK			(0x7f << 16)
+
+/* Used by REVISION_PRM */
+#define OMAP4430_SCHEME_SHIFT						30
+#define OMAP4430_SCHEME_MASK						(0x3 << 30)
 
 /* Used by PRM_VC_CFG_I2C_CLK */
 #define OMAP4430_SCLH_SHIFT						0
-#define OMAP4430_SCLH_MASK						BITFIELD(0, 7)
+#define OMAP4430_SCLH_MASK						(0xff << 0)
 
 /* Used by PRM_VC_CFG_I2C_CLK */
 #define OMAP4430_SCLL_SHIFT						8
-#define OMAP4430_SCLL_MASK						BITFIELD(8, 15)
+#define OMAP4430_SCLL_MASK						(0xff << 8)
 
 /* Used by PRM_RSTST */
 #define OMAP4430_SECURE_WDT_RST_SHIFT					4
-#define OMAP4430_SECURE_WDT_RST_MASK					BITFIELD(4, 4)
+#define OMAP4430_SECURE_WDT_RST_MASK					(1 << 4)
 
 /* Used by PM_IVAHD_PWRSTCTRL */
 #define OMAP4430_SL2_MEM_ONSTATE_SHIFT					18
-#define OMAP4430_SL2_MEM_ONSTATE_MASK					BITFIELD(18, 19)
+#define OMAP4430_SL2_MEM_ONSTATE_MASK					(0x3 << 18)
 
 /* Used by PM_IVAHD_PWRSTCTRL */
 #define OMAP4430_SL2_MEM_RETSTATE_SHIFT					9
-#define OMAP4430_SL2_MEM_RETSTATE_MASK					BITFIELD(9, 9)
+#define OMAP4430_SL2_MEM_RETSTATE_MASK					(1 << 9)
 
 /* Used by PM_IVAHD_PWRSTST */
 #define OMAP4430_SL2_MEM_STATEST_SHIFT					6
-#define OMAP4430_SL2_MEM_STATEST_MASK					BITFIELD(6, 7)
+#define OMAP4430_SL2_MEM_STATEST_MASK					(0x3 << 6)
 
 /* Used by PRM_VC_VAL_BYPASS */
 #define OMAP4430_SLAVEADDR_SHIFT					0
-#define OMAP4430_SLAVEADDR_MASK						BITFIELD(0, 6)
+#define OMAP4430_SLAVEADDR_MASK						(0x7f << 0)
 
 /* Used by PRM_LDO_ABB_IVA_SETUP, PRM_LDO_ABB_MPU_SETUP */
 #define OMAP4430_SLEEP_RBB_SEL_SHIFT					3
-#define OMAP4430_SLEEP_RBB_SEL_MASK					BITFIELD(3, 3)
+#define OMAP4430_SLEEP_RBB_SEL_MASK					(1 << 3)
 
 /* Used by PRM_SRAM_COUNT */
 #define OMAP4430_SLPCNT_VALUE_SHIFT					16
-#define OMAP4430_SLPCNT_VALUE_MASK					BITFIELD(16, 23)
+#define OMAP4430_SLPCNT_VALUE_MASK					(0xff << 16)
 
 /* Used by PRM_VP_CORE_VSTEPMAX, PRM_VP_IVA_VSTEPMAX, PRM_VP_MPU_VSTEPMAX */
 #define OMAP4430_SMPSWAITTIMEMAX_SHIFT					8
-#define OMAP4430_SMPSWAITTIMEMAX_MASK					BITFIELD(8, 23)
+#define OMAP4430_SMPSWAITTIMEMAX_MASK					(0xffff << 8)
 
 /* Used by PRM_VP_CORE_VSTEPMIN, PRM_VP_IVA_VSTEPMIN, PRM_VP_MPU_VSTEPMIN */
 #define OMAP4430_SMPSWAITTIMEMIN_SHIFT					8
-#define OMAP4430_SMPSWAITTIMEMIN_MASK					BITFIELD(8, 23)
+#define OMAP4430_SMPSWAITTIMEMIN_MASK					(0xffff << 8)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_SMPS_RA_ERR_CORE_SHIFT					1
+#define OMAP4430_SMPS_RA_ERR_CORE_MASK					(1 << 1)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_SMPS_RA_ERR_IVA_SHIFT					9
+#define OMAP4430_SMPS_RA_ERR_IVA_MASK					(1 << 9)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_SMPS_RA_ERR_MPU_SHIFT					17
+#define OMAP4430_SMPS_RA_ERR_MPU_MASK					(1 << 17)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_SMPS_SA_ERR_CORE_SHIFT					0
+#define OMAP4430_SMPS_SA_ERR_CORE_MASK					(1 << 0)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_SMPS_SA_ERR_IVA_SHIFT					8
+#define OMAP4430_SMPS_SA_ERR_IVA_MASK					(1 << 8)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_SMPS_SA_ERR_MPU_SHIFT					16
+#define OMAP4430_SMPS_SA_ERR_MPU_MASK					(1 << 16)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_SMPS_TIMEOUT_ERR_CORE_SHIFT				2
+#define OMAP4430_SMPS_TIMEOUT_ERR_CORE_MASK				(1 << 2)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_SMPS_TIMEOUT_ERR_IVA_SHIFT				10
+#define OMAP4430_SMPS_TIMEOUT_ERR_IVA_MASK				(1 << 10)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_SMPS_TIMEOUT_ERR_MPU_SHIFT				18
+#define OMAP4430_SMPS_TIMEOUT_ERR_MPU_MASK				(1 << 18)
 
 /* Used by PRM_LDO_ABB_IVA_SETUP, PRM_LDO_ABB_MPU_SETUP */
 #define OMAP4430_SR2EN_SHIFT						0
-#define OMAP4430_SR2EN_MASK						BITFIELD(0, 0)
+#define OMAP4430_SR2EN_MASK						(1 << 0)
 
 /* Used by PRM_LDO_ABB_IVA_CTRL, PRM_LDO_ABB_MPU_CTRL */
 #define OMAP4430_SR2_IN_TRANSITION_SHIFT				6
-#define OMAP4430_SR2_IN_TRANSITION_MASK					BITFIELD(6, 6)
+#define OMAP4430_SR2_IN_TRANSITION_MASK					(1 << 6)
 
 /* Used by PRM_LDO_ABB_IVA_CTRL, PRM_LDO_ABB_MPU_CTRL */
 #define OMAP4430_SR2_STATUS_SHIFT					3
-#define OMAP4430_SR2_STATUS_MASK					BITFIELD(3, 4)
+#define OMAP4430_SR2_STATUS_MASK					(0x3 << 3)
 
 /* Used by PRM_LDO_ABB_IVA_SETUP, PRM_LDO_ABB_MPU_SETUP */
 #define OMAP4430_SR2_WTCNT_VALUE_SHIFT					8
-#define OMAP4430_SR2_WTCNT_VALUE_MASK					BITFIELD(8, 15)
+#define OMAP4430_SR2_WTCNT_VALUE_MASK					(0xff << 8)
 
 /*
  * Used by PRM_LDO_SRAM_CORE_CTRL, PRM_LDO_SRAM_IVA_CTRL,
  * PRM_LDO_SRAM_MPU_CTRL
  */
 #define OMAP4430_SRAMLDO_STATUS_SHIFT					8
-#define OMAP4430_SRAMLDO_STATUS_MASK					BITFIELD(8, 8)
+#define OMAP4430_SRAMLDO_STATUS_MASK					(1 << 8)
 
 /*
  * Used by PRM_LDO_SRAM_CORE_CTRL, PRM_LDO_SRAM_IVA_CTRL,
  * PRM_LDO_SRAM_MPU_CTRL
  */
 #define OMAP4430_SRAM_IN_TRANSITION_SHIFT				9
-#define OMAP4430_SRAM_IN_TRANSITION_MASK				BITFIELD(9, 9)
+#define OMAP4430_SRAM_IN_TRANSITION_MASK				(1 << 9)
 
 /* Used by PRM_VC_CFG_I2C_MODE */
 #define OMAP4430_SRMODEEN_SHIFT						4
-#define OMAP4430_SRMODEEN_MASK						BITFIELD(4, 4)
+#define OMAP4430_SRMODEEN_MASK						(1 << 4)
 
 /* Used by PRM_VOLTSETUP_WARMRESET */
 #define OMAP4430_STABLE_COUNT_SHIFT					0
-#define OMAP4430_STABLE_COUNT_MASK					BITFIELD(0, 5)
+#define OMAP4430_STABLE_COUNT_MASK					(0x3f << 0)
 
 /* Used by PRM_VOLTSETUP_WARMRESET */
 #define OMAP4430_STABLE_PRESCAL_SHIFT					8
-#define OMAP4430_STABLE_PRESCAL_MASK					BITFIELD(8, 9)
+#define OMAP4430_STABLE_PRESCAL_MASK					(0x3 << 8)
+
+/* Used by PRM_LDO_BANDGAP_SETUP */
+#define OMAP4430_STARTUP_COUNT_SHIFT					0
+#define OMAP4430_STARTUP_COUNT_MASK					(0xff << 0)
+
+/* Renamed from STARTUP_COUNT Used by PRM_SRAM_COUNT */
+#define OMAP4430_STARTUP_COUNT_24_31_SHIFT				24
+#define OMAP4430_STARTUP_COUNT_24_31_MASK				(0xff << 24)
 
 /* Used by PM_IVAHD_PWRSTCTRL */
 #define OMAP4430_TCM1_MEM_ONSTATE_SHIFT					20
-#define OMAP4430_TCM1_MEM_ONSTATE_MASK					BITFIELD(20, 21)
+#define OMAP4430_TCM1_MEM_ONSTATE_MASK					(0x3 << 20)
 
 /* Used by PM_IVAHD_PWRSTCTRL */
 #define OMAP4430_TCM1_MEM_RETSTATE_SHIFT				10
-#define OMAP4430_TCM1_MEM_RETSTATE_MASK					BITFIELD(10, 10)
+#define OMAP4430_TCM1_MEM_RETSTATE_MASK					(1 << 10)
 
 /* Used by PM_IVAHD_PWRSTST */
 #define OMAP4430_TCM1_MEM_STATEST_SHIFT					8
-#define OMAP4430_TCM1_MEM_STATEST_MASK					BITFIELD(8, 9)
+#define OMAP4430_TCM1_MEM_STATEST_MASK					(0x3 << 8)
 
 /* Used by PM_IVAHD_PWRSTCTRL */
 #define OMAP4430_TCM2_MEM_ONSTATE_SHIFT					22
-#define OMAP4430_TCM2_MEM_ONSTATE_MASK					BITFIELD(22, 23)
+#define OMAP4430_TCM2_MEM_ONSTATE_MASK					(0x3 << 22)
 
 /* Used by PM_IVAHD_PWRSTCTRL */
 #define OMAP4430_TCM2_MEM_RETSTATE_SHIFT				11
-#define OMAP4430_TCM2_MEM_RETSTATE_MASK					BITFIELD(11, 11)
+#define OMAP4430_TCM2_MEM_RETSTATE_MASK					(1 << 11)
 
 /* Used by PM_IVAHD_PWRSTST */
 #define OMAP4430_TCM2_MEM_STATEST_SHIFT					10
-#define OMAP4430_TCM2_MEM_STATEST_MASK					BITFIELD(10, 11)
+#define OMAP4430_TCM2_MEM_STATEST_MASK					(0x3 << 10)
 
 /* Used by RM_TESLA_RSTST */
 #define OMAP4430_TESLASS_EMU_RSTST_SHIFT				2
-#define OMAP4430_TESLASS_EMU_RSTST_MASK					BITFIELD(2, 2)
+#define OMAP4430_TESLASS_EMU_RSTST_MASK					(1 << 2)
 
 /* Used by RM_TESLA_RSTST */
 #define OMAP4430_TESLA_DSP_EMU_REQ_RSTST_SHIFT				3
-#define OMAP4430_TESLA_DSP_EMU_REQ_RSTST_MASK				BITFIELD(3, 3)
+#define OMAP4430_TESLA_DSP_EMU_REQ_RSTST_MASK				(1 << 3)
 
 /* Used by PM_TESLA_PWRSTCTRL */
 #define OMAP4430_TESLA_EDMA_ONSTATE_SHIFT				20
-#define OMAP4430_TESLA_EDMA_ONSTATE_MASK				BITFIELD(20, 21)
+#define OMAP4430_TESLA_EDMA_ONSTATE_MASK				(0x3 << 20)
 
 /* Used by PM_TESLA_PWRSTCTRL */
 #define OMAP4430_TESLA_EDMA_RETSTATE_SHIFT				10
-#define OMAP4430_TESLA_EDMA_RETSTATE_MASK				BITFIELD(10, 10)
+#define OMAP4430_TESLA_EDMA_RETSTATE_MASK				(1 << 10)
 
 /* Used by PM_TESLA_PWRSTST */
 #define OMAP4430_TESLA_EDMA_STATEST_SHIFT				8
-#define OMAP4430_TESLA_EDMA_STATEST_MASK				BITFIELD(8, 9)
+#define OMAP4430_TESLA_EDMA_STATEST_MASK				(0x3 << 8)
 
 /* Used by PM_TESLA_PWRSTCTRL */
 #define OMAP4430_TESLA_L1_ONSTATE_SHIFT					16
-#define OMAP4430_TESLA_L1_ONSTATE_MASK					BITFIELD(16, 17)
+#define OMAP4430_TESLA_L1_ONSTATE_MASK					(0x3 << 16)
 
 /* Used by PM_TESLA_PWRSTCTRL */
 #define OMAP4430_TESLA_L1_RETSTATE_SHIFT				8
-#define OMAP4430_TESLA_L1_RETSTATE_MASK					BITFIELD(8, 8)
+#define OMAP4430_TESLA_L1_RETSTATE_MASK					(1 << 8)
 
 /* Used by PM_TESLA_PWRSTST */
 #define OMAP4430_TESLA_L1_STATEST_SHIFT					4
-#define OMAP4430_TESLA_L1_STATEST_MASK					BITFIELD(4, 5)
+#define OMAP4430_TESLA_L1_STATEST_MASK					(0x3 << 4)
 
 /* Used by PM_TESLA_PWRSTCTRL */
 #define OMAP4430_TESLA_L2_ONSTATE_SHIFT					18
-#define OMAP4430_TESLA_L2_ONSTATE_MASK					BITFIELD(18, 19)
+#define OMAP4430_TESLA_L2_ONSTATE_MASK					(0x3 << 18)
 
 /* Used by PM_TESLA_PWRSTCTRL */
 #define OMAP4430_TESLA_L2_RETSTATE_SHIFT				9
-#define OMAP4430_TESLA_L2_RETSTATE_MASK					BITFIELD(9, 9)
+#define OMAP4430_TESLA_L2_RETSTATE_MASK					(1 << 9)
 
 /* Used by PM_TESLA_PWRSTST */
 #define OMAP4430_TESLA_L2_STATEST_SHIFT					6
-#define OMAP4430_TESLA_L2_STATEST_MASK					BITFIELD(6, 7)
+#define OMAP4430_TESLA_L2_STATEST_MASK					(0x3 << 6)
 
 /* Used by PRM_VP_CORE_VLIMITTO, PRM_VP_IVA_VLIMITTO, PRM_VP_MPU_VLIMITTO */
 #define OMAP4430_TIMEOUT_SHIFT						0
-#define OMAP4430_TIMEOUT_MASK						BITFIELD(0, 15)
+#define OMAP4430_TIMEOUT_MASK						(0xffff << 0)
 
 /* Used by PRM_VP_CORE_CONFIG, PRM_VP_IVA_CONFIG, PRM_VP_MPU_CONFIG */
 #define OMAP4430_TIMEOUTEN_SHIFT					3
-#define OMAP4430_TIMEOUTEN_MASK						BITFIELD(3, 3)
+#define OMAP4430_TIMEOUTEN_MASK						(1 << 3)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_TRANSITION_EN_SHIFT					8
-#define OMAP4430_TRANSITION_EN_MASK					BITFIELD(8, 8)
+#define OMAP4430_TRANSITION_EN_MASK					(1 << 8)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_TRANSITION_ST_SHIFT					8
-#define OMAP4430_TRANSITION_ST_MASK					BITFIELD(8, 8)
+#define OMAP4430_TRANSITION_ST_MASK					(1 << 8)
 
 /* Used by PRM_VC_VAL_BYPASS */
 #define OMAP4430_VALID_SHIFT						24
-#define OMAP4430_VALID_MASK						BITFIELD(24, 24)
+#define OMAP4430_VALID_MASK						(1 << 24)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VC_BYPASSACK_EN_SHIFT					14
-#define OMAP4430_VC_BYPASSACK_EN_MASK					BITFIELD(14, 14)
+#define OMAP4430_VC_BYPASSACK_EN_MASK					(1 << 14)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VC_BYPASSACK_ST_SHIFT					14
-#define OMAP4430_VC_BYPASSACK_ST_MASK					BITFIELD(14, 14)
+#define OMAP4430_VC_BYPASSACK_ST_MASK					(1 << 14)
+
+/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
+#define OMAP4430_VC_CORE_VPACK_EN_SHIFT					22
+#define OMAP4430_VC_CORE_VPACK_EN_MASK					(1 << 22)
+
+/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
+#define OMAP4430_VC_CORE_VPACK_ST_SHIFT					22
+#define OMAP4430_VC_CORE_VPACK_ST_MASK					(1 << 22)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VC_IVA_VPACK_EN_SHIFT					30
-#define OMAP4430_VC_IVA_VPACK_EN_MASK					BITFIELD(30, 30)
+#define OMAP4430_VC_IVA_VPACK_EN_MASK					(1 << 30)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VC_IVA_VPACK_ST_SHIFT					30
-#define OMAP4430_VC_IVA_VPACK_ST_MASK					BITFIELD(30, 30)
+#define OMAP4430_VC_IVA_VPACK_ST_MASK					(1 << 30)
 
 /* Used by PRM_IRQENABLE_MPU_2 */
 #define OMAP4430_VC_MPU_VPACK_EN_SHIFT					6
-#define OMAP4430_VC_MPU_VPACK_EN_MASK					BITFIELD(6, 6)
+#define OMAP4430_VC_MPU_VPACK_EN_MASK					(1 << 6)
 
 /* Used by PRM_IRQSTATUS_MPU_2 */
 #define OMAP4430_VC_MPU_VPACK_ST_SHIFT					6
-#define OMAP4430_VC_MPU_VPACK_ST_MASK					BITFIELD(6, 6)
+#define OMAP4430_VC_MPU_VPACK_ST_MASK					(1 << 6)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VC_RAERR_EN_SHIFT					12
-#define OMAP4430_VC_RAERR_EN_MASK					BITFIELD(12, 12)
+#define OMAP4430_VC_RAERR_EN_MASK					(1 << 12)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VC_RAERR_ST_SHIFT					12
-#define OMAP4430_VC_RAERR_ST_MASK					BITFIELD(12, 12)
+#define OMAP4430_VC_RAERR_ST_MASK					(1 << 12)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VC_SAERR_EN_SHIFT					11
-#define OMAP4430_VC_SAERR_EN_MASK					BITFIELD(11, 11)
+#define OMAP4430_VC_SAERR_EN_MASK					(1 << 11)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VC_SAERR_ST_SHIFT					11
-#define OMAP4430_VC_SAERR_ST_MASK					BITFIELD(11, 11)
+#define OMAP4430_VC_SAERR_ST_MASK					(1 << 11)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VC_TOERR_EN_SHIFT					13
-#define OMAP4430_VC_TOERR_EN_MASK					BITFIELD(13, 13)
+#define OMAP4430_VC_TOERR_EN_MASK					(1 << 13)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VC_TOERR_ST_SHIFT					13
-#define OMAP4430_VC_TOERR_ST_MASK					BITFIELD(13, 13)
+#define OMAP4430_VC_TOERR_ST_MASK					(1 << 13)
 
 /* Used by PRM_VP_CORE_VLIMITTO, PRM_VP_IVA_VLIMITTO, PRM_VP_MPU_VLIMITTO */
 #define OMAP4430_VDDMAX_SHIFT						24
-#define OMAP4430_VDDMAX_MASK						BITFIELD(24, 31)
+#define OMAP4430_VDDMAX_MASK						(0xff << 24)
 
 /* Used by PRM_VP_CORE_VLIMITTO, PRM_VP_IVA_VLIMITTO, PRM_VP_MPU_VLIMITTO */
 #define OMAP4430_VDDMIN_SHIFT						16
-#define OMAP4430_VDDMIN_MASK						BITFIELD(16, 23)
+#define OMAP4430_VDDMIN_MASK						(0xff << 16)
 
 /* Used by PRM_VOLTCTRL */
 #define OMAP4430_VDD_CORE_I2C_DISABLE_SHIFT				12
-#define OMAP4430_VDD_CORE_I2C_DISABLE_MASK				BITFIELD(12, 12)
+#define OMAP4430_VDD_CORE_I2C_DISABLE_MASK				(1 << 12)
 
 /* Used by PRM_RSTST */
 #define OMAP4430_VDD_CORE_VOLT_MGR_RST_SHIFT				8
-#define OMAP4430_VDD_CORE_VOLT_MGR_RST_MASK				BITFIELD(8, 8)
+#define OMAP4430_VDD_CORE_VOLT_MGR_RST_MASK				(1 << 8)
 
 /* Used by PRM_VOLTCTRL */
 #define OMAP4430_VDD_IVA_I2C_DISABLE_SHIFT				14
-#define OMAP4430_VDD_IVA_I2C_DISABLE_MASK				BITFIELD(14, 14)
+#define OMAP4430_VDD_IVA_I2C_DISABLE_MASK				(1 << 14)
 
 /* Used by PRM_VOLTCTRL */
 #define OMAP4430_VDD_IVA_PRESENCE_SHIFT					9
-#define OMAP4430_VDD_IVA_PRESENCE_MASK					BITFIELD(9, 9)
+#define OMAP4430_VDD_IVA_PRESENCE_MASK					(1 << 9)
 
 /* Used by PRM_RSTST */
 #define OMAP4430_VDD_IVA_VOLT_MGR_RST_SHIFT				7
-#define OMAP4430_VDD_IVA_VOLT_MGR_RST_MASK				BITFIELD(7, 7)
+#define OMAP4430_VDD_IVA_VOLT_MGR_RST_MASK				(1 << 7)
 
 /* Used by PRM_VOLTCTRL */
 #define OMAP4430_VDD_MPU_I2C_DISABLE_SHIFT				13
-#define OMAP4430_VDD_MPU_I2C_DISABLE_MASK				BITFIELD(13, 13)
+#define OMAP4430_VDD_MPU_I2C_DISABLE_MASK				(1 << 13)
 
 /* Used by PRM_VOLTCTRL */
 #define OMAP4430_VDD_MPU_PRESENCE_SHIFT					8
-#define OMAP4430_VDD_MPU_PRESENCE_MASK					BITFIELD(8, 8)
+#define OMAP4430_VDD_MPU_PRESENCE_MASK					(1 << 8)
 
 /* Used by PRM_RSTST */
 #define OMAP4430_VDD_MPU_VOLT_MGR_RST_SHIFT				6
-#define OMAP4430_VDD_MPU_VOLT_MGR_RST_MASK				BITFIELD(6, 6)
+#define OMAP4430_VDD_MPU_VOLT_MGR_RST_MASK				(1 << 6)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_VFSM_RA_ERR_CORE_SHIFT					4
+#define OMAP4430_VFSM_RA_ERR_CORE_MASK					(1 << 4)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_VFSM_RA_ERR_IVA_SHIFT					12
+#define OMAP4430_VFSM_RA_ERR_IVA_MASK					(1 << 12)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_VFSM_RA_ERR_MPU_SHIFT					20
+#define OMAP4430_VFSM_RA_ERR_MPU_MASK					(1 << 20)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_VFSM_SA_ERR_CORE_SHIFT					3
+#define OMAP4430_VFSM_SA_ERR_CORE_MASK					(1 << 3)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_VFSM_SA_ERR_IVA_SHIFT					11
+#define OMAP4430_VFSM_SA_ERR_IVA_MASK					(1 << 11)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_VFSM_SA_ERR_MPU_SHIFT					19
+#define OMAP4430_VFSM_SA_ERR_MPU_MASK					(1 << 19)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_VFSM_TIMEOUT_ERR_CORE_SHIFT				5
+#define OMAP4430_VFSM_TIMEOUT_ERR_CORE_MASK				(1 << 5)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_VFSM_TIMEOUT_ERR_IVA_SHIFT				13
+#define OMAP4430_VFSM_TIMEOUT_ERR_IVA_MASK				(1 << 13)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_VFSM_TIMEOUT_ERR_MPU_SHIFT				21
+#define OMAP4430_VFSM_TIMEOUT_ERR_MPU_MASK				(1 << 21)
 
 /* Used by PRM_VC_VAL_SMPS_RA_VOL */
 #define OMAP4430_VOLRA_VDD_CORE_L_SHIFT					0
-#define OMAP4430_VOLRA_VDD_CORE_L_MASK					BITFIELD(0, 7)
+#define OMAP4430_VOLRA_VDD_CORE_L_MASK					(0xff << 0)
 
 /* Used by PRM_VC_VAL_SMPS_RA_VOL */
 #define OMAP4430_VOLRA_VDD_IVA_L_SHIFT					8
-#define OMAP4430_VOLRA_VDD_IVA_L_MASK					BITFIELD(8, 15)
+#define OMAP4430_VOLRA_VDD_IVA_L_MASK					(0xff << 8)
 
 /* Used by PRM_VC_VAL_SMPS_RA_VOL */
 #define OMAP4430_VOLRA_VDD_MPU_L_SHIFT					16
-#define OMAP4430_VOLRA_VDD_MPU_L_MASK					BITFIELD(16, 23)
+#define OMAP4430_VOLRA_VDD_MPU_L_MASK					(0xff << 16)
 
 /* Used by PRM_VP_CORE_CONFIG, PRM_VP_IVA_CONFIG, PRM_VP_MPU_CONFIG */
 #define OMAP4430_VPENABLE_SHIFT						0
-#define OMAP4430_VPENABLE_MASK						BITFIELD(0, 0)
+#define OMAP4430_VPENABLE_MASK						(1 << 0)
 
 /* Used by PRM_VP_CORE_STATUS, PRM_VP_IVA_STATUS, PRM_VP_MPU_STATUS */
 #define OMAP4430_VPINIDLE_SHIFT						0
-#define OMAP4430_VPINIDLE_MASK						BITFIELD(0, 0)
+#define OMAP4430_VPINIDLE_MASK						(1 << 0)
 
 /* Used by PRM_VP_CORE_VOLTAGE, PRM_VP_IVA_VOLTAGE, PRM_VP_MPU_VOLTAGE */
 #define OMAP4430_VPVOLTAGE_SHIFT					0
-#define OMAP4430_VPVOLTAGE_MASK						BITFIELD(0, 7)
+#define OMAP4430_VPVOLTAGE_MASK						(0xff << 0)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_CORE_EQVALUE_EN_SHIFT				20
-#define OMAP4430_VP_CORE_EQVALUE_EN_MASK				BITFIELD(20, 20)
+#define OMAP4430_VP_CORE_EQVALUE_EN_MASK				(1 << 20)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_CORE_EQVALUE_ST_SHIFT				20
-#define OMAP4430_VP_CORE_EQVALUE_ST_MASK				BITFIELD(20, 20)
+#define OMAP4430_VP_CORE_EQVALUE_ST_MASK				(1 << 20)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_CORE_MAXVDD_EN_SHIFT				18
-#define OMAP4430_VP_CORE_MAXVDD_EN_MASK					BITFIELD(18, 18)
+#define OMAP4430_VP_CORE_MAXVDD_EN_MASK					(1 << 18)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_CORE_MAXVDD_ST_SHIFT				18
-#define OMAP4430_VP_CORE_MAXVDD_ST_MASK					BITFIELD(18, 18)
+#define OMAP4430_VP_CORE_MAXVDD_ST_MASK					(1 << 18)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_CORE_MINVDD_EN_SHIFT				17
-#define OMAP4430_VP_CORE_MINVDD_EN_MASK					BITFIELD(17, 17)
+#define OMAP4430_VP_CORE_MINVDD_EN_MASK					(1 << 17)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_CORE_MINVDD_ST_SHIFT				17
-#define OMAP4430_VP_CORE_MINVDD_ST_MASK					BITFIELD(17, 17)
+#define OMAP4430_VP_CORE_MINVDD_ST_MASK					(1 << 17)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_CORE_NOSMPSACK_EN_SHIFT				19
-#define OMAP4430_VP_CORE_NOSMPSACK_EN_MASK				BITFIELD(19, 19)
+#define OMAP4430_VP_CORE_NOSMPSACK_EN_MASK				(1 << 19)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_CORE_NOSMPSACK_ST_SHIFT				19
-#define OMAP4430_VP_CORE_NOSMPSACK_ST_MASK				BITFIELD(19, 19)
+#define OMAP4430_VP_CORE_NOSMPSACK_ST_MASK				(1 << 19)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_CORE_OPPCHANGEDONE_EN_SHIFT				16
-#define OMAP4430_VP_CORE_OPPCHANGEDONE_EN_MASK				BITFIELD(16, 16)
+#define OMAP4430_VP_CORE_OPPCHANGEDONE_EN_MASK				(1 << 16)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_CORE_OPPCHANGEDONE_ST_SHIFT				16
-#define OMAP4430_VP_CORE_OPPCHANGEDONE_ST_MASK				BITFIELD(16, 16)
+#define OMAP4430_VP_CORE_OPPCHANGEDONE_ST_MASK				(1 << 16)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_CORE_TRANXDONE_EN_SHIFT				21
-#define OMAP4430_VP_CORE_TRANXDONE_EN_MASK				BITFIELD(21, 21)
+#define OMAP4430_VP_CORE_TRANXDONE_EN_MASK				(1 << 21)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_CORE_TRANXDONE_ST_SHIFT				21
-#define OMAP4430_VP_CORE_TRANXDONE_ST_MASK				BITFIELD(21, 21)
+#define OMAP4430_VP_CORE_TRANXDONE_ST_MASK				(1 << 21)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_IVA_EQVALUE_EN_SHIFT				28
-#define OMAP4430_VP_IVA_EQVALUE_EN_MASK					BITFIELD(28, 28)
+#define OMAP4430_VP_IVA_EQVALUE_EN_MASK					(1 << 28)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_IVA_EQVALUE_ST_SHIFT				28
-#define OMAP4430_VP_IVA_EQVALUE_ST_MASK					BITFIELD(28, 28)
+#define OMAP4430_VP_IVA_EQVALUE_ST_MASK					(1 << 28)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_IVA_MAXVDD_EN_SHIFT					26
-#define OMAP4430_VP_IVA_MAXVDD_EN_MASK					BITFIELD(26, 26)
+#define OMAP4430_VP_IVA_MAXVDD_EN_MASK					(1 << 26)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_IVA_MAXVDD_ST_SHIFT					26
-#define OMAP4430_VP_IVA_MAXVDD_ST_MASK					BITFIELD(26, 26)
+#define OMAP4430_VP_IVA_MAXVDD_ST_MASK					(1 << 26)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_IVA_MINVDD_EN_SHIFT					25
-#define OMAP4430_VP_IVA_MINVDD_EN_MASK					BITFIELD(25, 25)
+#define OMAP4430_VP_IVA_MINVDD_EN_MASK					(1 << 25)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_IVA_MINVDD_ST_SHIFT					25
-#define OMAP4430_VP_IVA_MINVDD_ST_MASK					BITFIELD(25, 25)
+#define OMAP4430_VP_IVA_MINVDD_ST_MASK					(1 << 25)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_IVA_NOSMPSACK_EN_SHIFT				27
-#define OMAP4430_VP_IVA_NOSMPSACK_EN_MASK				BITFIELD(27, 27)
+#define OMAP4430_VP_IVA_NOSMPSACK_EN_MASK				(1 << 27)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_IVA_NOSMPSACK_ST_SHIFT				27
-#define OMAP4430_VP_IVA_NOSMPSACK_ST_MASK				BITFIELD(27, 27)
+#define OMAP4430_VP_IVA_NOSMPSACK_ST_MASK				(1 << 27)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_IVA_OPPCHANGEDONE_EN_SHIFT				24
-#define OMAP4430_VP_IVA_OPPCHANGEDONE_EN_MASK				BITFIELD(24, 24)
+#define OMAP4430_VP_IVA_OPPCHANGEDONE_EN_MASK				(1 << 24)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_IVA_OPPCHANGEDONE_ST_SHIFT				24
-#define OMAP4430_VP_IVA_OPPCHANGEDONE_ST_MASK				BITFIELD(24, 24)
+#define OMAP4430_VP_IVA_OPPCHANGEDONE_ST_MASK				(1 << 24)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_IVA_TRANXDONE_EN_SHIFT				29
-#define OMAP4430_VP_IVA_TRANXDONE_EN_MASK				BITFIELD(29, 29)
+#define OMAP4430_VP_IVA_TRANXDONE_EN_MASK				(1 << 29)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_IVA_TRANXDONE_ST_SHIFT				29
-#define OMAP4430_VP_IVA_TRANXDONE_ST_MASK				BITFIELD(29, 29)
+#define OMAP4430_VP_IVA_TRANXDONE_ST_MASK				(1 << 29)
 
 /* Used by PRM_IRQENABLE_MPU_2 */
 #define OMAP4430_VP_MPU_EQVALUE_EN_SHIFT				4
-#define OMAP4430_VP_MPU_EQVALUE_EN_MASK					BITFIELD(4, 4)
+#define OMAP4430_VP_MPU_EQVALUE_EN_MASK					(1 << 4)
 
 /* Used by PRM_IRQSTATUS_MPU_2 */
 #define OMAP4430_VP_MPU_EQVALUE_ST_SHIFT				4
-#define OMAP4430_VP_MPU_EQVALUE_ST_MASK					BITFIELD(4, 4)
+#define OMAP4430_VP_MPU_EQVALUE_ST_MASK					(1 << 4)
 
 /* Used by PRM_IRQENABLE_MPU_2 */
 #define OMAP4430_VP_MPU_MAXVDD_EN_SHIFT					2
-#define OMAP4430_VP_MPU_MAXVDD_EN_MASK					BITFIELD(2, 2)
+#define OMAP4430_VP_MPU_MAXVDD_EN_MASK					(1 << 2)
 
 /* Used by PRM_IRQSTATUS_MPU_2 */
 #define OMAP4430_VP_MPU_MAXVDD_ST_SHIFT					2
-#define OMAP4430_VP_MPU_MAXVDD_ST_MASK					BITFIELD(2, 2)
+#define OMAP4430_VP_MPU_MAXVDD_ST_MASK					(1 << 2)
 
 /* Used by PRM_IRQENABLE_MPU_2 */
 #define OMAP4430_VP_MPU_MINVDD_EN_SHIFT					1
-#define OMAP4430_VP_MPU_MINVDD_EN_MASK					BITFIELD(1, 1)
+#define OMAP4430_VP_MPU_MINVDD_EN_MASK					(1 << 1)
 
 /* Used by PRM_IRQSTATUS_MPU_2 */
 #define OMAP4430_VP_MPU_MINVDD_ST_SHIFT					1
-#define OMAP4430_VP_MPU_MINVDD_ST_MASK					BITFIELD(1, 1)
+#define OMAP4430_VP_MPU_MINVDD_ST_MASK					(1 << 1)
 
 /* Used by PRM_IRQENABLE_MPU_2 */
 #define OMAP4430_VP_MPU_NOSMPSACK_EN_SHIFT				3
-#define OMAP4430_VP_MPU_NOSMPSACK_EN_MASK				BITFIELD(3, 3)
+#define OMAP4430_VP_MPU_NOSMPSACK_EN_MASK				(1 << 3)
 
 /* Used by PRM_IRQSTATUS_MPU_2 */
 #define OMAP4430_VP_MPU_NOSMPSACK_ST_SHIFT				3
-#define OMAP4430_VP_MPU_NOSMPSACK_ST_MASK				BITFIELD(3, 3)
+#define OMAP4430_VP_MPU_NOSMPSACK_ST_MASK				(1 << 3)
 
 /* Used by PRM_IRQENABLE_MPU_2 */
 #define OMAP4430_VP_MPU_OPPCHANGEDONE_EN_SHIFT				0
-#define OMAP4430_VP_MPU_OPPCHANGEDONE_EN_MASK				BITFIELD(0, 0)
+#define OMAP4430_VP_MPU_OPPCHANGEDONE_EN_MASK				(1 << 0)
 
 /* Used by PRM_IRQSTATUS_MPU_2 */
 #define OMAP4430_VP_MPU_OPPCHANGEDONE_ST_SHIFT				0
-#define OMAP4430_VP_MPU_OPPCHANGEDONE_ST_MASK				BITFIELD(0, 0)
+#define OMAP4430_VP_MPU_OPPCHANGEDONE_ST_MASK				(1 << 0)
 
 /* Used by PRM_IRQENABLE_MPU_2 */
 #define OMAP4430_VP_MPU_TRANXDONE_EN_SHIFT				5
-#define OMAP4430_VP_MPU_TRANXDONE_EN_MASK				BITFIELD(5, 5)
+#define OMAP4430_VP_MPU_TRANXDONE_EN_MASK				(1 << 5)
 
 /* Used by PRM_IRQSTATUS_MPU_2 */
 #define OMAP4430_VP_MPU_TRANXDONE_ST_SHIFT				5
-#define OMAP4430_VP_MPU_TRANXDONE_ST_MASK				BITFIELD(5, 5)
+#define OMAP4430_VP_MPU_TRANXDONE_ST_MASK				(1 << 5)
 
 /* Used by PRM_SRAM_COUNT */
 #define OMAP4430_VSETUPCNT_VALUE_SHIFT					8
-#define OMAP4430_VSETUPCNT_VALUE_MASK					BITFIELD(8, 15)
+#define OMAP4430_VSETUPCNT_VALUE_MASK					(0xff << 8)
 
 /* Used by PRM_VP_CORE_VSTEPMAX, PRM_VP_IVA_VSTEPMAX, PRM_VP_MPU_VSTEPMAX */
 #define OMAP4430_VSTEPMAX_SHIFT						0
-#define OMAP4430_VSTEPMAX_MASK						BITFIELD(0, 7)
+#define OMAP4430_VSTEPMAX_MASK						(0xff << 0)
 
 /* Used by PRM_VP_CORE_VSTEPMIN, PRM_VP_IVA_VSTEPMIN, PRM_VP_MPU_VSTEPMIN */
 #define OMAP4430_VSTEPMIN_SHIFT						0
-#define OMAP4430_VSTEPMIN_MASK						BITFIELD(0, 7)
+#define OMAP4430_VSTEPMIN_MASK						(0xff << 0)
 
 /* Used by PRM_MODEM_IF_CTRL */
 #define OMAP4430_WAKE_MODEM_SHIFT					0
-#define OMAP4430_WAKE_MODEM_MASK					BITFIELD(0, 0)
+#define OMAP4430_WAKE_MODEM_MASK					(1 << 0)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DISPC_DUCATI_SHIFT				1
-#define OMAP4430_WKUPDEP_DISPC_DUCATI_MASK				BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_DISPC_DUCATI_MASK				(1 << 1)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DISPC_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_DISPC_MPU_MASK					BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_DISPC_MPU_MASK					(1 << 0)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DISPC_SDMA_SHIFT				3
-#define OMAP4430_WKUPDEP_DISPC_SDMA_MASK				BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_DISPC_SDMA_MASK				(1 << 3)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DISPC_TESLA_SHIFT				2
-#define OMAP4430_WKUPDEP_DISPC_TESLA_MASK				BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_DISPC_TESLA_MASK				(1 << 2)
 
 /* Used by PM_ABE_DMIC_WKDEP */
 #define OMAP4430_WKUPDEP_DMIC_DMA_SDMA_SHIFT				7
-#define OMAP4430_WKUPDEP_DMIC_DMA_SDMA_MASK				BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_DMIC_DMA_SDMA_MASK				(1 << 7)
 
 /* Used by PM_ABE_DMIC_WKDEP */
 #define OMAP4430_WKUPDEP_DMIC_DMA_TESLA_SHIFT				6
-#define OMAP4430_WKUPDEP_DMIC_DMA_TESLA_MASK				BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_DMIC_DMA_TESLA_MASK				(1 << 6)
 
 /* Used by PM_ABE_DMIC_WKDEP */
 #define OMAP4430_WKUPDEP_DMIC_IRQ_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_DMIC_IRQ_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_DMIC_IRQ_MPU_MASK				(1 << 0)
 
 /* Used by PM_ABE_DMIC_WKDEP */
 #define OMAP4430_WKUPDEP_DMIC_IRQ_TESLA_SHIFT				2
-#define OMAP4430_WKUPDEP_DMIC_IRQ_TESLA_MASK				BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_DMIC_IRQ_TESLA_MASK				(1 << 2)
 
 /* Used by PM_L4PER_DMTIMER10_WKDEP */
 #define OMAP4430_WKUPDEP_DMTIMER10_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_DMTIMER10_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_DMTIMER10_MPU_MASK				(1 << 0)
 
 /* Used by PM_L4PER_DMTIMER11_WKDEP */
 #define OMAP4430_WKUPDEP_DMTIMER11_DUCATI_SHIFT				1
-#define OMAP4430_WKUPDEP_DMTIMER11_DUCATI_MASK				BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_DMTIMER11_DUCATI_MASK				(1 << 1)
 
 /* Used by PM_L4PER_DMTIMER11_WKDEP */
 #define OMAP4430_WKUPDEP_DMTIMER11_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_DMTIMER11_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_DMTIMER11_MPU_MASK				(1 << 0)
 
 /* Used by PM_L4PER_DMTIMER2_WKDEP */
 #define OMAP4430_WKUPDEP_DMTIMER2_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_DMTIMER2_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_DMTIMER2_MPU_MASK				(1 << 0)
 
 /* Used by PM_L4PER_DMTIMER3_WKDEP */
 #define OMAP4430_WKUPDEP_DMTIMER3_DUCATI_SHIFT				1
-#define OMAP4430_WKUPDEP_DMTIMER3_DUCATI_MASK				BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_DMTIMER3_DUCATI_MASK				(1 << 1)
 
 /* Used by PM_L4PER_DMTIMER3_WKDEP */
 #define OMAP4430_WKUPDEP_DMTIMER3_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_DMTIMER3_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_DMTIMER3_MPU_MASK				(1 << 0)
 
 /* Used by PM_L4PER_DMTIMER4_WKDEP */
 #define OMAP4430_WKUPDEP_DMTIMER4_DUCATI_SHIFT				1
-#define OMAP4430_WKUPDEP_DMTIMER4_DUCATI_MASK				BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_DMTIMER4_DUCATI_MASK				(1 << 1)
 
 /* Used by PM_L4PER_DMTIMER4_WKDEP */
 #define OMAP4430_WKUPDEP_DMTIMER4_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_DMTIMER4_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_DMTIMER4_MPU_MASK				(1 << 0)
 
 /* Used by PM_L4PER_DMTIMER9_WKDEP */
 #define OMAP4430_WKUPDEP_DMTIMER9_DUCATI_SHIFT				1
-#define OMAP4430_WKUPDEP_DMTIMER9_DUCATI_MASK				BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_DMTIMER9_DUCATI_MASK				(1 << 1)
 
 /* Used by PM_L4PER_DMTIMER9_WKDEP */
 #define OMAP4430_WKUPDEP_DMTIMER9_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_DMTIMER9_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_DMTIMER9_MPU_MASK				(1 << 0)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DSI1_DUCATI_SHIFT				5
-#define OMAP4430_WKUPDEP_DSI1_DUCATI_MASK				BITFIELD(5, 5)
+#define OMAP4430_WKUPDEP_DSI1_DUCATI_MASK				(1 << 5)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DSI1_MPU_SHIFT					4
-#define OMAP4430_WKUPDEP_DSI1_MPU_MASK					BITFIELD(4, 4)
+#define OMAP4430_WKUPDEP_DSI1_MPU_MASK					(1 << 4)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DSI1_SDMA_SHIFT				7
-#define OMAP4430_WKUPDEP_DSI1_SDMA_MASK					BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_DSI1_SDMA_MASK					(1 << 7)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DSI1_TESLA_SHIFT				6
-#define OMAP4430_WKUPDEP_DSI1_TESLA_MASK				BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_DSI1_TESLA_MASK				(1 << 6)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DSI2_DUCATI_SHIFT				9
-#define OMAP4430_WKUPDEP_DSI2_DUCATI_MASK				BITFIELD(9, 9)
+#define OMAP4430_WKUPDEP_DSI2_DUCATI_MASK				(1 << 9)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DSI2_MPU_SHIFT					8
-#define OMAP4430_WKUPDEP_DSI2_MPU_MASK					BITFIELD(8, 8)
+#define OMAP4430_WKUPDEP_DSI2_MPU_MASK					(1 << 8)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DSI2_SDMA_SHIFT				11
-#define OMAP4430_WKUPDEP_DSI2_SDMA_MASK					BITFIELD(11, 11)
+#define OMAP4430_WKUPDEP_DSI2_SDMA_MASK					(1 << 11)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DSI2_TESLA_SHIFT				10
-#define OMAP4430_WKUPDEP_DSI2_TESLA_MASK				BITFIELD(10, 10)
+#define OMAP4430_WKUPDEP_DSI2_TESLA_MASK				(1 << 10)
 
 /* Used by PM_WKUP_GPIO1_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO1_IRQ1_DUCATI_SHIFT			1
-#define OMAP4430_WKUPDEP_GPIO1_IRQ1_DUCATI_MASK				BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_GPIO1_IRQ1_DUCATI_MASK				(1 << 1)
 
 /* Used by PM_WKUP_GPIO1_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO1_IRQ1_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_GPIO1_IRQ1_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_GPIO1_IRQ1_MPU_MASK				(1 << 0)
 
 /* Used by PM_WKUP_GPIO1_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO1_IRQ2_TESLA_SHIFT				6
-#define OMAP4430_WKUPDEP_GPIO1_IRQ2_TESLA_MASK				BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_GPIO1_IRQ2_TESLA_MASK				(1 << 6)
 
 /* Used by PM_L4PER_GPIO2_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO2_IRQ1_DUCATI_SHIFT			1
-#define OMAP4430_WKUPDEP_GPIO2_IRQ1_DUCATI_MASK				BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_GPIO2_IRQ1_DUCATI_MASK				(1 << 1)
 
 /* Used by PM_L4PER_GPIO2_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO2_IRQ1_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_GPIO2_IRQ1_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_GPIO2_IRQ1_MPU_MASK				(1 << 0)
 
 /* Used by PM_L4PER_GPIO2_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO2_IRQ2_TESLA_SHIFT				6
-#define OMAP4430_WKUPDEP_GPIO2_IRQ2_TESLA_MASK				BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_GPIO2_IRQ2_TESLA_MASK				(1 << 6)
 
 /* Used by PM_L4PER_GPIO3_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO3_IRQ1_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_GPIO3_IRQ1_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_GPIO3_IRQ1_MPU_MASK				(1 << 0)
 
 /* Used by PM_L4PER_GPIO3_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO3_IRQ2_TESLA_SHIFT				6
-#define OMAP4430_WKUPDEP_GPIO3_IRQ2_TESLA_MASK				BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_GPIO3_IRQ2_TESLA_MASK				(1 << 6)
 
 /* Used by PM_L4PER_GPIO4_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO4_IRQ1_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_GPIO4_IRQ1_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_GPIO4_IRQ1_MPU_MASK				(1 << 0)
 
 /* Used by PM_L4PER_GPIO4_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO4_IRQ2_TESLA_SHIFT				6
-#define OMAP4430_WKUPDEP_GPIO4_IRQ2_TESLA_MASK				BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_GPIO4_IRQ2_TESLA_MASK				(1 << 6)
 
 /* Used by PM_L4PER_GPIO5_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO5_IRQ1_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_GPIO5_IRQ1_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_GPIO5_IRQ1_MPU_MASK				(1 << 0)
 
 /* Used by PM_L4PER_GPIO5_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO5_IRQ2_TESLA_SHIFT				6
-#define OMAP4430_WKUPDEP_GPIO5_IRQ2_TESLA_MASK				BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_GPIO5_IRQ2_TESLA_MASK				(1 << 6)
 
 /* Used by PM_L4PER_GPIO6_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO6_IRQ1_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_GPIO6_IRQ1_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_GPIO6_IRQ1_MPU_MASK				(1 << 0)
 
 /* Used by PM_L4PER_GPIO6_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO6_IRQ2_TESLA_SHIFT				6
-#define OMAP4430_WKUPDEP_GPIO6_IRQ2_TESLA_MASK				BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_GPIO6_IRQ2_TESLA_MASK				(1 << 6)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_HDMIDMA_SDMA_SHIFT				19
-#define OMAP4430_WKUPDEP_HDMIDMA_SDMA_MASK				BITFIELD(19, 19)
+#define OMAP4430_WKUPDEP_HDMIDMA_SDMA_MASK				(1 << 19)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_HDMIIRQ_DUCATI_SHIFT				13
-#define OMAP4430_WKUPDEP_HDMIIRQ_DUCATI_MASK				BITFIELD(13, 13)
+#define OMAP4430_WKUPDEP_HDMIIRQ_DUCATI_MASK				(1 << 13)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_HDMIIRQ_MPU_SHIFT				12
-#define OMAP4430_WKUPDEP_HDMIIRQ_MPU_MASK				BITFIELD(12, 12)
+#define OMAP4430_WKUPDEP_HDMIIRQ_MPU_MASK				(1 << 12)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_HDMIIRQ_TESLA_SHIFT				14
-#define OMAP4430_WKUPDEP_HDMIIRQ_TESLA_MASK				BITFIELD(14, 14)
+#define OMAP4430_WKUPDEP_HDMIIRQ_TESLA_MASK				(1 << 14)
 
 /* Used by PM_L4PER_HECC1_WKDEP */
 #define OMAP4430_WKUPDEP_HECC1_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_HECC1_MPU_MASK					BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_HECC1_MPU_MASK					(1 << 0)
 
 /* Used by PM_L4PER_HECC2_WKDEP */
 #define OMAP4430_WKUPDEP_HECC2_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_HECC2_MPU_MASK					BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_HECC2_MPU_MASK					(1 << 0)
 
 /* Used by PM_L3INIT_HSI_WKDEP */
 #define OMAP4430_WKUPDEP_HSI_DSP_TESLA_SHIFT				6
-#define OMAP4430_WKUPDEP_HSI_DSP_TESLA_MASK				BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_HSI_DSP_TESLA_MASK				(1 << 6)
 
 /* Used by PM_L3INIT_HSI_WKDEP */
 #define OMAP4430_WKUPDEP_HSI_MCU_DUCATI_SHIFT				1
-#define OMAP4430_WKUPDEP_HSI_MCU_DUCATI_MASK				BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_HSI_MCU_DUCATI_MASK				(1 << 1)
 
 /* Used by PM_L3INIT_HSI_WKDEP */
 #define OMAP4430_WKUPDEP_HSI_MCU_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_HSI_MCU_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_HSI_MCU_MPU_MASK				(1 << 0)
 
 /* Used by PM_L4PER_I2C1_WKDEP */
 #define OMAP4430_WKUPDEP_I2C1_DMA_SDMA_SHIFT				7
-#define OMAP4430_WKUPDEP_I2C1_DMA_SDMA_MASK				BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_I2C1_DMA_SDMA_MASK				(1 << 7)
 
 /* Used by PM_L4PER_I2C1_WKDEP */
 #define OMAP4430_WKUPDEP_I2C1_IRQ_DUCATI_SHIFT				1
-#define OMAP4430_WKUPDEP_I2C1_IRQ_DUCATI_MASK				BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_I2C1_IRQ_DUCATI_MASK				(1 << 1)
 
 /* Used by PM_L4PER_I2C1_WKDEP */
 #define OMAP4430_WKUPDEP_I2C1_IRQ_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_I2C1_IRQ_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_I2C1_IRQ_MPU_MASK				(1 << 0)
 
 /* Used by PM_L4PER_I2C2_WKDEP */
 #define OMAP4430_WKUPDEP_I2C2_DMA_SDMA_SHIFT				7
-#define OMAP4430_WKUPDEP_I2C2_DMA_SDMA_MASK				BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_I2C2_DMA_SDMA_MASK				(1 << 7)
 
 /* Used by PM_L4PER_I2C2_WKDEP */
 #define OMAP4430_WKUPDEP_I2C2_IRQ_DUCATI_SHIFT				1
-#define OMAP4430_WKUPDEP_I2C2_IRQ_DUCATI_MASK				BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_I2C2_IRQ_DUCATI_MASK				(1 << 1)
 
 /* Used by PM_L4PER_I2C2_WKDEP */
 #define OMAP4430_WKUPDEP_I2C2_IRQ_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_I2C2_IRQ_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_I2C2_IRQ_MPU_MASK				(1 << 0)
 
 /* Used by PM_L4PER_I2C3_WKDEP */
 #define OMAP4430_WKUPDEP_I2C3_DMA_SDMA_SHIFT				7
-#define OMAP4430_WKUPDEP_I2C3_DMA_SDMA_MASK				BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_I2C3_DMA_SDMA_MASK				(1 << 7)
 
 /* Used by PM_L4PER_I2C3_WKDEP */
 #define OMAP4430_WKUPDEP_I2C3_IRQ_DUCATI_SHIFT				1
-#define OMAP4430_WKUPDEP_I2C3_IRQ_DUCATI_MASK				BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_I2C3_IRQ_DUCATI_MASK				(1 << 1)
 
 /* Used by PM_L4PER_I2C3_WKDEP */
 #define OMAP4430_WKUPDEP_I2C3_IRQ_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_I2C3_IRQ_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_I2C3_IRQ_MPU_MASK				(1 << 0)
 
 /* Used by PM_L4PER_I2C4_WKDEP */
 #define OMAP4430_WKUPDEP_I2C4_DMA_SDMA_SHIFT				7
-#define OMAP4430_WKUPDEP_I2C4_DMA_SDMA_MASK				BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_I2C4_DMA_SDMA_MASK				(1 << 7)
 
 /* Used by PM_L4PER_I2C4_WKDEP */
 #define OMAP4430_WKUPDEP_I2C4_IRQ_DUCATI_SHIFT				1
-#define OMAP4430_WKUPDEP_I2C4_IRQ_DUCATI_MASK				BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_I2C4_IRQ_DUCATI_MASK				(1 << 1)
 
 /* Used by PM_L4PER_I2C4_WKDEP */
 #define OMAP4430_WKUPDEP_I2C4_IRQ_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_I2C4_IRQ_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_I2C4_IRQ_MPU_MASK				(1 << 0)
 
 /* Used by PM_L4PER_I2C5_WKDEP */
 #define OMAP4430_WKUPDEP_I2C5_DMA_SDMA_SHIFT				7
-#define OMAP4430_WKUPDEP_I2C5_DMA_SDMA_MASK				BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_I2C5_DMA_SDMA_MASK				(1 << 7)
 
 /* Used by PM_L4PER_I2C5_WKDEP */
 #define OMAP4430_WKUPDEP_I2C5_IRQ_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_I2C5_IRQ_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_I2C5_IRQ_MPU_MASK				(1 << 0)
 
 /* Used by PM_WKUP_KEYBOARD_WKDEP */
 #define OMAP4430_WKUPDEP_KEYBOARD_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_KEYBOARD_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_KEYBOARD_MPU_MASK				(1 << 0)
 
 /* Used by PM_ABE_MCASP_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP1_DMA_SDMA_SHIFT				7
-#define OMAP4430_WKUPDEP_MCASP1_DMA_SDMA_MASK				BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_MCASP1_DMA_SDMA_MASK				(1 << 7)
 
 /* Used by PM_ABE_MCASP_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP1_DMA_TESLA_SHIFT				6
-#define OMAP4430_WKUPDEP_MCASP1_DMA_TESLA_MASK				BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_MCASP1_DMA_TESLA_MASK				(1 << 6)
 
 /* Used by PM_ABE_MCASP_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP1_IRQ_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_MCASP1_IRQ_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCASP1_IRQ_MPU_MASK				(1 << 0)
 
 /* Used by PM_ABE_MCASP_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP1_IRQ_TESLA_SHIFT				2
-#define OMAP4430_WKUPDEP_MCASP1_IRQ_TESLA_MASK				BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCASP1_IRQ_TESLA_MASK				(1 << 2)
 
 /* Used by PM_L4PER_MCASP2_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP2_DMA_SDMA_SHIFT				7
-#define OMAP4430_WKUPDEP_MCASP2_DMA_SDMA_MASK				BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_MCASP2_DMA_SDMA_MASK				(1 << 7)
 
 /* Used by PM_L4PER_MCASP2_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP2_DMA_TESLA_SHIFT				6
-#define OMAP4430_WKUPDEP_MCASP2_DMA_TESLA_MASK				BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_MCASP2_DMA_TESLA_MASK				(1 << 6)
 
 /* Used by PM_L4PER_MCASP2_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP2_IRQ_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_MCASP2_IRQ_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCASP2_IRQ_MPU_MASK				(1 << 0)
 
 /* Used by PM_L4PER_MCASP2_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP2_IRQ_TESLA_SHIFT				2
-#define OMAP4430_WKUPDEP_MCASP2_IRQ_TESLA_MASK				BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCASP2_IRQ_TESLA_MASK				(1 << 2)
 
 /* Used by PM_L4PER_MCASP3_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP3_DMA_SDMA_SHIFT				7
-#define OMAP4430_WKUPDEP_MCASP3_DMA_SDMA_MASK				BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_MCASP3_DMA_SDMA_MASK				(1 << 7)
 
 /* Used by PM_L4PER_MCASP3_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP3_DMA_TESLA_SHIFT				6
-#define OMAP4430_WKUPDEP_MCASP3_DMA_TESLA_MASK				BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_MCASP3_DMA_TESLA_MASK				(1 << 6)
 
 /* Used by PM_L4PER_MCASP3_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP3_IRQ_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_MCASP3_IRQ_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCASP3_IRQ_MPU_MASK				(1 << 0)
 
 /* Used by PM_L4PER_MCASP3_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP3_IRQ_TESLA_SHIFT				2
-#define OMAP4430_WKUPDEP_MCASP3_IRQ_TESLA_MASK				BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCASP3_IRQ_TESLA_MASK				(1 << 2)
 
 /* Used by PM_ABE_MCBSP1_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP1_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_MCBSP1_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCBSP1_MPU_MASK				(1 << 0)
 
 /* Used by PM_ABE_MCBSP1_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP1_SDMA_SHIFT				3
-#define OMAP4430_WKUPDEP_MCBSP1_SDMA_MASK				BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCBSP1_SDMA_MASK				(1 << 3)
 
 /* Used by PM_ABE_MCBSP1_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP1_TESLA_SHIFT				2
-#define OMAP4430_WKUPDEP_MCBSP1_TESLA_MASK				BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCBSP1_TESLA_MASK				(1 << 2)
 
 /* Used by PM_ABE_MCBSP2_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP2_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_MCBSP2_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCBSP2_MPU_MASK				(1 << 0)
 
 /* Used by PM_ABE_MCBSP2_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP2_SDMA_SHIFT				3
-#define OMAP4430_WKUPDEP_MCBSP2_SDMA_MASK				BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCBSP2_SDMA_MASK				(1 << 3)
 
 /* Used by PM_ABE_MCBSP2_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP2_TESLA_SHIFT				2
-#define OMAP4430_WKUPDEP_MCBSP2_TESLA_MASK				BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCBSP2_TESLA_MASK				(1 << 2)
 
 /* Used by PM_ABE_MCBSP3_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP3_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_MCBSP3_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCBSP3_MPU_MASK				(1 << 0)
 
 /* Used by PM_ABE_MCBSP3_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP3_SDMA_SHIFT				3
-#define OMAP4430_WKUPDEP_MCBSP3_SDMA_MASK				BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCBSP3_SDMA_MASK				(1 << 3)
 
 /* Used by PM_ABE_MCBSP3_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP3_TESLA_SHIFT				2
-#define OMAP4430_WKUPDEP_MCBSP3_TESLA_MASK				BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCBSP3_TESLA_MASK				(1 << 2)
 
 /* Used by PM_L4PER_MCBSP4_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP4_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_MCBSP4_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCBSP4_MPU_MASK				(1 << 0)
 
 /* Used by PM_L4PER_MCBSP4_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP4_SDMA_SHIFT				3
-#define OMAP4430_WKUPDEP_MCBSP4_SDMA_MASK				BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCBSP4_SDMA_MASK				(1 << 3)
 
 /* Used by PM_L4PER_MCBSP4_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP4_TESLA_SHIFT				2
-#define OMAP4430_WKUPDEP_MCBSP4_TESLA_MASK				BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCBSP4_TESLA_MASK				(1 << 2)
 
 /* Used by PM_L4PER_MCSPI1_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI1_DUCATI_SHIFT				1
-#define OMAP4430_WKUPDEP_MCSPI1_DUCATI_MASK				BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MCSPI1_DUCATI_MASK				(1 << 1)
 
 /* Used by PM_L4PER_MCSPI1_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI1_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_MCSPI1_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCSPI1_MPU_MASK				(1 << 0)
 
 /* Used by PM_L4PER_MCSPI1_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI1_SDMA_SHIFT				3
-#define OMAP4430_WKUPDEP_MCSPI1_SDMA_MASK				BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCSPI1_SDMA_MASK				(1 << 3)
 
 /* Used by PM_L4PER_MCSPI1_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI1_TESLA_SHIFT				2
-#define OMAP4430_WKUPDEP_MCSPI1_TESLA_MASK				BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCSPI1_TESLA_MASK				(1 << 2)
 
 /* Used by PM_L4PER_MCSPI2_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI2_DUCATI_SHIFT				1
-#define OMAP4430_WKUPDEP_MCSPI2_DUCATI_MASK				BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MCSPI2_DUCATI_MASK				(1 << 1)
 
 /* Used by PM_L4PER_MCSPI2_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI2_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_MCSPI2_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCSPI2_MPU_MASK				(1 << 0)
 
 /* Used by PM_L4PER_MCSPI2_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI2_SDMA_SHIFT				3
-#define OMAP4430_WKUPDEP_MCSPI2_SDMA_MASK				BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCSPI2_SDMA_MASK				(1 << 3)
 
 /* Used by PM_L4PER_MCSPI3_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI3_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_MCSPI3_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCSPI3_MPU_MASK				(1 << 0)
 
 /* Used by PM_L4PER_MCSPI3_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI3_SDMA_SHIFT				3
-#define OMAP4430_WKUPDEP_MCSPI3_SDMA_MASK				BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCSPI3_SDMA_MASK				(1 << 3)
 
 /* Used by PM_L4PER_MCSPI4_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI4_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_MCSPI4_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCSPI4_MPU_MASK				(1 << 0)
 
 /* Used by PM_L4PER_MCSPI4_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI4_SDMA_SHIFT				3
-#define OMAP4430_WKUPDEP_MCSPI4_SDMA_MASK				BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCSPI4_SDMA_MASK				(1 << 3)
 
 /* Used by PM_L3INIT_MMC1_WKDEP */
 #define OMAP4430_WKUPDEP_MMC1_DUCATI_SHIFT				1
-#define OMAP4430_WKUPDEP_MMC1_DUCATI_MASK				BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MMC1_DUCATI_MASK				(1 << 1)
 
 /* Used by PM_L3INIT_MMC1_WKDEP */
 #define OMAP4430_WKUPDEP_MMC1_MPU_SHIFT					0
-#define OMAP4430_WKUPDEP_MMC1_MPU_MASK					BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MMC1_MPU_MASK					(1 << 0)
 
 /* Used by PM_L3INIT_MMC1_WKDEP */
 #define OMAP4430_WKUPDEP_MMC1_SDMA_SHIFT				3
-#define OMAP4430_WKUPDEP_MMC1_SDMA_MASK					BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MMC1_SDMA_MASK					(1 << 3)
 
 /* Used by PM_L3INIT_MMC1_WKDEP */
 #define OMAP4430_WKUPDEP_MMC1_TESLA_SHIFT				2
-#define OMAP4430_WKUPDEP_MMC1_TESLA_MASK				BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MMC1_TESLA_MASK				(1 << 2)
 
 /* Used by PM_L3INIT_MMC2_WKDEP */
 #define OMAP4430_WKUPDEP_MMC2_DUCATI_SHIFT				1
-#define OMAP4430_WKUPDEP_MMC2_DUCATI_MASK				BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MMC2_DUCATI_MASK				(1 << 1)
 
 /* Used by PM_L3INIT_MMC2_WKDEP */
 #define OMAP4430_WKUPDEP_MMC2_MPU_SHIFT					0
-#define OMAP4430_WKUPDEP_MMC2_MPU_MASK					BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MMC2_MPU_MASK					(1 << 0)
 
 /* Used by PM_L3INIT_MMC2_WKDEP */
 #define OMAP4430_WKUPDEP_MMC2_SDMA_SHIFT				3
-#define OMAP4430_WKUPDEP_MMC2_SDMA_MASK					BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MMC2_SDMA_MASK					(1 << 3)
 
 /* Used by PM_L3INIT_MMC2_WKDEP */
 #define OMAP4430_WKUPDEP_MMC2_TESLA_SHIFT				2
-#define OMAP4430_WKUPDEP_MMC2_TESLA_MASK				BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MMC2_TESLA_MASK				(1 << 2)
 
 /* Used by PM_L3INIT_MMC6_WKDEP */
 #define OMAP4430_WKUPDEP_MMC6_DUCATI_SHIFT				1
-#define OMAP4430_WKUPDEP_MMC6_DUCATI_MASK				BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MMC6_DUCATI_MASK				(1 << 1)
 
 /* Used by PM_L3INIT_MMC6_WKDEP */
 #define OMAP4430_WKUPDEP_MMC6_MPU_SHIFT					0
-#define OMAP4430_WKUPDEP_MMC6_MPU_MASK					BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MMC6_MPU_MASK					(1 << 0)
 
 /* Used by PM_L3INIT_MMC6_WKDEP */
 #define OMAP4430_WKUPDEP_MMC6_TESLA_SHIFT				2
-#define OMAP4430_WKUPDEP_MMC6_TESLA_MASK				BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MMC6_TESLA_MASK				(1 << 2)
 
 /* Used by PM_L4PER_MMCSD3_WKDEP */
 #define OMAP4430_WKUPDEP_MMCSD3_DUCATI_SHIFT				1
-#define OMAP4430_WKUPDEP_MMCSD3_DUCATI_MASK				BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MMCSD3_DUCATI_MASK				(1 << 1)
 
 /* Used by PM_L4PER_MMCSD3_WKDEP */
 #define OMAP4430_WKUPDEP_MMCSD3_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_MMCSD3_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MMCSD3_MPU_MASK				(1 << 0)
 
 /* Used by PM_L4PER_MMCSD3_WKDEP */
 #define OMAP4430_WKUPDEP_MMCSD3_SDMA_SHIFT				3
-#define OMAP4430_WKUPDEP_MMCSD3_SDMA_MASK				BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MMCSD3_SDMA_MASK				(1 << 3)
 
 /* Used by PM_L4PER_MMCSD4_WKDEP */
 #define OMAP4430_WKUPDEP_MMCSD4_DUCATI_SHIFT				1
-#define OMAP4430_WKUPDEP_MMCSD4_DUCATI_MASK				BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MMCSD4_DUCATI_MASK				(1 << 1)
 
 /* Used by PM_L4PER_MMCSD4_WKDEP */
 #define OMAP4430_WKUPDEP_MMCSD4_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_MMCSD4_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MMCSD4_MPU_MASK				(1 << 0)
 
 /* Used by PM_L4PER_MMCSD4_WKDEP */
 #define OMAP4430_WKUPDEP_MMCSD4_SDMA_SHIFT				3
-#define OMAP4430_WKUPDEP_MMCSD4_SDMA_MASK				BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MMCSD4_SDMA_MASK				(1 << 3)
 
 /* Used by PM_L4PER_MMCSD5_WKDEP */
 #define OMAP4430_WKUPDEP_MMCSD5_DUCATI_SHIFT				1
-#define OMAP4430_WKUPDEP_MMCSD5_DUCATI_MASK				BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MMCSD5_DUCATI_MASK				(1 << 1)
 
 /* Used by PM_L4PER_MMCSD5_WKDEP */
 #define OMAP4430_WKUPDEP_MMCSD5_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_MMCSD5_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MMCSD5_MPU_MASK				(1 << 0)
 
 /* Used by PM_L4PER_MMCSD5_WKDEP */
 #define OMAP4430_WKUPDEP_MMCSD5_SDMA_SHIFT				3
-#define OMAP4430_WKUPDEP_MMCSD5_SDMA_MASK				BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MMCSD5_SDMA_MASK				(1 << 3)
 
 /* Used by PM_L3INIT_PCIESS_WKDEP */
 #define OMAP4430_WKUPDEP_PCIESS_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_PCIESS_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_PCIESS_MPU_MASK				(1 << 0)
 
 /* Used by PM_L3INIT_PCIESS_WKDEP */
 #define OMAP4430_WKUPDEP_PCIESS_TESLA_SHIFT				2
-#define OMAP4430_WKUPDEP_PCIESS_TESLA_MASK				BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_PCIESS_TESLA_MASK				(1 << 2)
 
 /* Used by PM_ABE_PDM_WKDEP */
 #define OMAP4430_WKUPDEP_PDM_DMA_SDMA_SHIFT				7
-#define OMAP4430_WKUPDEP_PDM_DMA_SDMA_MASK				BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_PDM_DMA_SDMA_MASK				(1 << 7)
 
 /* Used by PM_ABE_PDM_WKDEP */
 #define OMAP4430_WKUPDEP_PDM_DMA_TESLA_SHIFT				6
-#define OMAP4430_WKUPDEP_PDM_DMA_TESLA_MASK				BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_PDM_DMA_TESLA_MASK				(1 << 6)
 
 /* Used by PM_ABE_PDM_WKDEP */
 #define OMAP4430_WKUPDEP_PDM_IRQ_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_PDM_IRQ_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_PDM_IRQ_MPU_MASK				(1 << 0)
 
 /* Used by PM_ABE_PDM_WKDEP */
 #define OMAP4430_WKUPDEP_PDM_IRQ_TESLA_SHIFT				2
-#define OMAP4430_WKUPDEP_PDM_IRQ_TESLA_MASK				BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_PDM_IRQ_TESLA_MASK				(1 << 2)
 
 /* Used by PM_WKUP_RTC_WKDEP */
 #define OMAP4430_WKUPDEP_RTC_MPU_SHIFT					0
-#define OMAP4430_WKUPDEP_RTC_MPU_MASK					BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_RTC_MPU_MASK					(1 << 0)
 
 /* Used by PM_L3INIT_SATA_WKDEP */
 #define OMAP4430_WKUPDEP_SATA_MPU_SHIFT					0
-#define OMAP4430_WKUPDEP_SATA_MPU_MASK					BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_SATA_MPU_MASK					(1 << 0)
 
 /* Used by PM_L3INIT_SATA_WKDEP */
 #define OMAP4430_WKUPDEP_SATA_TESLA_SHIFT				2
-#define OMAP4430_WKUPDEP_SATA_TESLA_MASK				BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_SATA_TESLA_MASK				(1 << 2)
 
 /* Used by PM_ABE_SLIMBUS_WKDEP */
 #define OMAP4430_WKUPDEP_SLIMBUS1_DMA_SDMA_SHIFT			7
-#define OMAP4430_WKUPDEP_SLIMBUS1_DMA_SDMA_MASK				BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_SLIMBUS1_DMA_SDMA_MASK				(1 << 7)
 
 /* Used by PM_ABE_SLIMBUS_WKDEP */
 #define OMAP4430_WKUPDEP_SLIMBUS1_DMA_TESLA_SHIFT			6
-#define OMAP4430_WKUPDEP_SLIMBUS1_DMA_TESLA_MASK			BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_SLIMBUS1_DMA_TESLA_MASK			(1 << 6)
 
 /* Used by PM_ABE_SLIMBUS_WKDEP */
 #define OMAP4430_WKUPDEP_SLIMBUS1_IRQ_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_SLIMBUS1_IRQ_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_SLIMBUS1_IRQ_MPU_MASK				(1 << 0)
 
 /* Used by PM_ABE_SLIMBUS_WKDEP */
 #define OMAP4430_WKUPDEP_SLIMBUS1_IRQ_TESLA_SHIFT			2
-#define OMAP4430_WKUPDEP_SLIMBUS1_IRQ_TESLA_MASK			BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_SLIMBUS1_IRQ_TESLA_MASK			(1 << 2)
 
 /* Used by PM_L4PER_SLIMBUS2_WKDEP */
 #define OMAP4430_WKUPDEP_SLIMBUS2_DMA_SDMA_SHIFT			7
-#define OMAP4430_WKUPDEP_SLIMBUS2_DMA_SDMA_MASK				BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_SLIMBUS2_DMA_SDMA_MASK				(1 << 7)
 
 /* Used by PM_L4PER_SLIMBUS2_WKDEP */
 #define OMAP4430_WKUPDEP_SLIMBUS2_DMA_TESLA_SHIFT			6
-#define OMAP4430_WKUPDEP_SLIMBUS2_DMA_TESLA_MASK			BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_SLIMBUS2_DMA_TESLA_MASK			(1 << 6)
 
 /* Used by PM_L4PER_SLIMBUS2_WKDEP */
 #define OMAP4430_WKUPDEP_SLIMBUS2_IRQ_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_SLIMBUS2_IRQ_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_SLIMBUS2_IRQ_MPU_MASK				(1 << 0)
 
 /* Used by PM_L4PER_SLIMBUS2_WKDEP */
 #define OMAP4430_WKUPDEP_SLIMBUS2_IRQ_TESLA_SHIFT			2
-#define OMAP4430_WKUPDEP_SLIMBUS2_IRQ_TESLA_MASK			BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_SLIMBUS2_IRQ_TESLA_MASK			(1 << 2)
 
 /* Used by PM_ALWON_SR_CORE_WKDEP */
 #define OMAP4430_WKUPDEP_SR_CORE_DUCATI_SHIFT				1
-#define OMAP4430_WKUPDEP_SR_CORE_DUCATI_MASK				BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_SR_CORE_DUCATI_MASK				(1 << 1)
 
 /* Used by PM_ALWON_SR_CORE_WKDEP */
 #define OMAP4430_WKUPDEP_SR_CORE_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_SR_CORE_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_SR_CORE_MPU_MASK				(1 << 0)
 
 /* Used by PM_ALWON_SR_IVA_WKDEP */
 #define OMAP4430_WKUPDEP_SR_IVA_DUCATI_SHIFT				1
-#define OMAP4430_WKUPDEP_SR_IVA_DUCATI_MASK				BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_SR_IVA_DUCATI_MASK				(1 << 1)
 
 /* Used by PM_ALWON_SR_IVA_WKDEP */
 #define OMAP4430_WKUPDEP_SR_IVA_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_SR_IVA_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_SR_IVA_MPU_MASK				(1 << 0)
 
 /* Used by PM_ALWON_SR_MPU_WKDEP */
 #define OMAP4430_WKUPDEP_SR_MPU_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_SR_MPU_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_SR_MPU_MPU_MASK				(1 << 0)
 
 /* Used by PM_WKUP_TIMER12_WKDEP */
 #define OMAP4430_WKUPDEP_TIMER12_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_TIMER12_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_TIMER12_MPU_MASK				(1 << 0)
 
 /* Used by PM_WKUP_TIMER1_WKDEP */
 #define OMAP4430_WKUPDEP_TIMER1_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_TIMER1_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_TIMER1_MPU_MASK				(1 << 0)
 
 /* Used by PM_ABE_TIMER5_WKDEP */
 #define OMAP4430_WKUPDEP_TIMER5_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_TIMER5_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_TIMER5_MPU_MASK				(1 << 0)
 
 /* Used by PM_ABE_TIMER5_WKDEP */
 #define OMAP4430_WKUPDEP_TIMER5_TESLA_SHIFT				2
-#define OMAP4430_WKUPDEP_TIMER5_TESLA_MASK				BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_TIMER5_TESLA_MASK				(1 << 2)
 
 /* Used by PM_ABE_TIMER6_WKDEP */
 #define OMAP4430_WKUPDEP_TIMER6_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_TIMER6_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_TIMER6_MPU_MASK				(1 << 0)
 
 /* Used by PM_ABE_TIMER6_WKDEP */
 #define OMAP4430_WKUPDEP_TIMER6_TESLA_SHIFT				2
-#define OMAP4430_WKUPDEP_TIMER6_TESLA_MASK				BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_TIMER6_TESLA_MASK				(1 << 2)
 
 /* Used by PM_ABE_TIMER7_WKDEP */
 #define OMAP4430_WKUPDEP_TIMER7_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_TIMER7_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_TIMER7_MPU_MASK				(1 << 0)
 
 /* Used by PM_ABE_TIMER7_WKDEP */
 #define OMAP4430_WKUPDEP_TIMER7_TESLA_SHIFT				2
-#define OMAP4430_WKUPDEP_TIMER7_TESLA_MASK				BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_TIMER7_TESLA_MASK				(1 << 2)
 
 /* Used by PM_ABE_TIMER8_WKDEP */
 #define OMAP4430_WKUPDEP_TIMER8_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_TIMER8_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_TIMER8_MPU_MASK				(1 << 0)
 
 /* Used by PM_ABE_TIMER8_WKDEP */
 #define OMAP4430_WKUPDEP_TIMER8_TESLA_SHIFT				2
-#define OMAP4430_WKUPDEP_TIMER8_TESLA_MASK				BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_TIMER8_TESLA_MASK				(1 << 2)
 
 /* Used by PM_L4PER_UART1_WKDEP */
 #define OMAP4430_WKUPDEP_UART1_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_UART1_MPU_MASK					BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_UART1_MPU_MASK					(1 << 0)
 
 /* Used by PM_L4PER_UART1_WKDEP */
 #define OMAP4430_WKUPDEP_UART1_SDMA_SHIFT				3
-#define OMAP4430_WKUPDEP_UART1_SDMA_MASK				BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_UART1_SDMA_MASK				(1 << 3)
 
 /* Used by PM_L4PER_UART2_WKDEP */
 #define OMAP4430_WKUPDEP_UART2_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_UART2_MPU_MASK					BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_UART2_MPU_MASK					(1 << 0)
 
 /* Used by PM_L4PER_UART2_WKDEP */
 #define OMAP4430_WKUPDEP_UART2_SDMA_SHIFT				3
-#define OMAP4430_WKUPDEP_UART2_SDMA_MASK				BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_UART2_SDMA_MASK				(1 << 3)
 
 /* Used by PM_L4PER_UART3_WKDEP */
 #define OMAP4430_WKUPDEP_UART3_DUCATI_SHIFT				1
-#define OMAP4430_WKUPDEP_UART3_DUCATI_MASK				BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_UART3_DUCATI_MASK				(1 << 1)
 
 /* Used by PM_L4PER_UART3_WKDEP */
 #define OMAP4430_WKUPDEP_UART3_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_UART3_MPU_MASK					BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_UART3_MPU_MASK					(1 << 0)
 
 /* Used by PM_L4PER_UART3_WKDEP */
 #define OMAP4430_WKUPDEP_UART3_SDMA_SHIFT				3
-#define OMAP4430_WKUPDEP_UART3_SDMA_MASK				BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_UART3_SDMA_MASK				(1 << 3)
 
 /* Used by PM_L4PER_UART3_WKDEP */
 #define OMAP4430_WKUPDEP_UART3_TESLA_SHIFT				2
-#define OMAP4430_WKUPDEP_UART3_TESLA_MASK				BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_UART3_TESLA_MASK				(1 << 2)
 
 /* Used by PM_L4PER_UART4_WKDEP */
 #define OMAP4430_WKUPDEP_UART4_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_UART4_MPU_MASK					BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_UART4_MPU_MASK					(1 << 0)
 
 /* Used by PM_L4PER_UART4_WKDEP */
 #define OMAP4430_WKUPDEP_UART4_SDMA_SHIFT				3
-#define OMAP4430_WKUPDEP_UART4_SDMA_MASK				BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_UART4_SDMA_MASK				(1 << 3)
 
 /* Used by PM_L3INIT_UNIPRO1_WKDEP */
 #define OMAP4430_WKUPDEP_UNIPRO1_DUCATI_SHIFT				1
-#define OMAP4430_WKUPDEP_UNIPRO1_DUCATI_MASK				BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_UNIPRO1_DUCATI_MASK				(1 << 1)
 
 /* Used by PM_L3INIT_UNIPRO1_WKDEP */
 #define OMAP4430_WKUPDEP_UNIPRO1_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_UNIPRO1_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_UNIPRO1_MPU_MASK				(1 << 0)
 
 /* Used by PM_L3INIT_USB_HOST_WKDEP */
 #define OMAP4430_WKUPDEP_USB_HOST_DUCATI_SHIFT				1
-#define OMAP4430_WKUPDEP_USB_HOST_DUCATI_MASK				BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_USB_HOST_DUCATI_MASK				(1 << 1)
 
 /* Used by PM_L3INIT_USB_HOST_FS_WKDEP */
 #define OMAP4430_WKUPDEP_USB_HOST_FS_DUCATI_SHIFT			1
-#define OMAP4430_WKUPDEP_USB_HOST_FS_DUCATI_MASK			BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_USB_HOST_FS_DUCATI_MASK			(1 << 1)
 
 /* Used by PM_L3INIT_USB_HOST_FS_WKDEP */
 #define OMAP4430_WKUPDEP_USB_HOST_FS_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_USB_HOST_FS_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_USB_HOST_FS_MPU_MASK				(1 << 0)
 
 /* Used by PM_L3INIT_USB_HOST_WKDEP */
 #define OMAP4430_WKUPDEP_USB_HOST_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_USB_HOST_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_USB_HOST_MPU_MASK				(1 << 0)
 
 /* Used by PM_L3INIT_USB_OTG_WKDEP */
 #define OMAP4430_WKUPDEP_USB_OTG_DUCATI_SHIFT				1
-#define OMAP4430_WKUPDEP_USB_OTG_DUCATI_MASK				BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_USB_OTG_DUCATI_MASK				(1 << 1)
 
 /* Used by PM_L3INIT_USB_OTG_WKDEP */
 #define OMAP4430_WKUPDEP_USB_OTG_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_USB_OTG_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_USB_OTG_MPU_MASK				(1 << 0)
 
 /* Used by PM_L3INIT_USB_TLL_WKDEP */
 #define OMAP4430_WKUPDEP_USB_TLL_DUCATI_SHIFT				1
-#define OMAP4430_WKUPDEP_USB_TLL_DUCATI_MASK				BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_USB_TLL_DUCATI_MASK				(1 << 1)
 
 /* Used by PM_L3INIT_USB_TLL_WKDEP */
 #define OMAP4430_WKUPDEP_USB_TLL_MPU_SHIFT				0
-#define OMAP4430_WKUPDEP_USB_TLL_MPU_MASK				BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_USB_TLL_MPU_MASK				(1 << 0)
 
 /* Used by PM_WKUP_USIM_WKDEP */
 #define OMAP4430_WKUPDEP_USIM_MPU_SHIFT					0
-#define OMAP4430_WKUPDEP_USIM_MPU_MASK					BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_USIM_MPU_MASK					(1 << 0)
 
 /* Used by PM_WKUP_USIM_WKDEP */
 #define OMAP4430_WKUPDEP_USIM_SDMA_SHIFT				3
-#define OMAP4430_WKUPDEP_USIM_SDMA_MASK					BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_USIM_SDMA_MASK					(1 << 3)
 
 /* Used by PM_WKUP_WDT2_WKDEP */
 #define OMAP4430_WKUPDEP_WDT2_DUCATI_SHIFT				1
-#define OMAP4430_WKUPDEP_WDT2_DUCATI_MASK				BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_WDT2_DUCATI_MASK				(1 << 1)
 
 /* Used by PM_WKUP_WDT2_WKDEP */
 #define OMAP4430_WKUPDEP_WDT2_MPU_SHIFT					0
-#define OMAP4430_WKUPDEP_WDT2_MPU_MASK					BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_WDT2_MPU_MASK					(1 << 0)
 
 /* Used by PM_ABE_WDT3_WKDEP */
 #define OMAP4430_WKUPDEP_WDT3_MPU_SHIFT					0
-#define OMAP4430_WKUPDEP_WDT3_MPU_MASK					BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_WDT3_MPU_MASK					(1 << 0)
 
 /* Used by PM_L3INIT_HSI_WKDEP */
 #define OMAP4430_WKUPDEP_WGM_HSI_WAKE_MPU_SHIFT				8
-#define OMAP4430_WKUPDEP_WGM_HSI_WAKE_MPU_MASK				BITFIELD(8, 8)
+#define OMAP4430_WKUPDEP_WGM_HSI_WAKE_MPU_MASK				(1 << 8)
 
 /* Used by PM_L3INIT_XHPI_WKDEP */
 #define OMAP4430_WKUPDEP_XHPI_DUCATI_SHIFT				1
-#define OMAP4430_WKUPDEP_XHPI_DUCATI_MASK				BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_XHPI_DUCATI_MASK				(1 << 1)
 
 /* Used by PRM_IO_PMCTRL */
 #define OMAP4430_WUCLK_CTRL_SHIFT					8
-#define OMAP4430_WUCLK_CTRL_MASK					BITFIELD(8, 8)
+#define OMAP4430_WUCLK_CTRL_MASK					(1 << 8)
 
 /* Used by PRM_IO_PMCTRL */
 #define OMAP4430_WUCLK_STATUS_SHIFT					9
-#define OMAP4430_WUCLK_STATUS_MASK					BITFIELD(9, 9)
+#define OMAP4430_WUCLK_STATUS_MASK					(1 << 9)
+
+/* Used by REVISION_PRM */
+#define OMAP4430_X_MAJOR_SHIFT						8
+#define OMAP4430_X_MAJOR_MASK						(0x7 << 8)
+
+/* Used by REVISION_PRM */
+#define OMAP4430_Y_MINOR_SHIFT						0
+#define OMAP4430_Y_MINOR_MASK						(0x3f << 0)
 #endif
diff --git a/arch/arm/mach-omap2/prm.h b/arch/arm/mach-omap2/prm.h
index 588873b..7be040b 100644
--- a/arch/arm/mach-omap2/prm.h
+++ b/arch/arm/mach-omap2/prm.h
@@ -5,7 +5,7 @@
  * OMAP2/3 Power/Reset Management (PRM) register definitions
  *
  * Copyright (C) 2007-2009 Texas Instruments, Inc.
- * Copyright (C) 2009 Nokia Corporation
+ * Copyright (C) 2010 Nokia Corporation
  *
  * Written by Paul Walmsley
  *
@@ -246,6 +246,15 @@
 	return prm_rmw_mod_reg_bits(bits, 0x0, module, idx);
 }
 
+/* These omap2_ PRM functions apply to both OMAP2 and 3 */
+int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift);
+int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift);
+int omap2_prm_deassert_hardreset(s16 prm_mod, u8 shift);
+
+int omap4_prm_is_hardreset_asserted(void __iomem *rstctrl_reg, u8 shift);
+int omap4_prm_assert_hardreset(void __iomem *rstctrl_reg, u8 shift);
+int omap4_prm_deassert_hardreset(void __iomem *rstctrl_reg, u8 shift);
+
 #endif
 
 /*
@@ -398,4 +407,11 @@
 #define OMAP_POWERSTATE_MASK				(0x3 << 0)
 
 
+/*
+ * MAX_MODULE_HARDRESET_WAIT: Maximum microseconds to wait for an OMAP
+ * submodule to exit hardreset
+ */
+#define MAX_MODULE_HARDRESET_WAIT		10000
+
+
 #endif
diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.c b/arch/arm/mach-omap2/prm2xxx_3xxx.c
new file mode 100644
index 0000000..421771e
--- /dev/null
+++ b/arch/arm/mach-omap2/prm2xxx_3xxx.c
@@ -0,0 +1,110 @@
+/*
+ * OMAP2/3 PRM module functions
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Copyright (C) 2010 Nokia Corporation
+ * Benoît Cousson
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+
+#include <plat/common.h>
+#include <plat/cpu.h>
+#include <plat/prcm.h>
+
+#include "prm.h"
+#include "prm-regbits-24xx.h"
+#include "prm-regbits-34xx.h"
+
+/**
+ * omap2_prm_is_hardreset_asserted - read the HW reset line state of
+ * submodules contained in the hwmod module
+ * @prm_mod: PRM submodule base (e.g. CORE_MOD)
+ * @shift: register bit shift corresponding to the reset line to check
+ *
+ * Returns 1 if the (sub)module hardreset line is currently asserted,
+ * 0 if the (sub)module hardreset line is not currently asserted, or
+ * -EINVAL if called while running on a non-OMAP2/3 chip.
+ */
+int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift)
+{
+	if (!(cpu_is_omap24xx() || cpu_is_omap34xx()))
+		return -EINVAL;
+
+	return prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL,
+				       (1 << shift));
+}
+
+/**
+ * omap2_prm_assert_hardreset - assert the HW reset line of a submodule
+ * @prm_mod: PRM submodule base (e.g. CORE_MOD)
+ * @shift: register bit shift corresponding to the reset line to assert
+ *
+ * Some IPs like dsp or iva contain processors that require an HW
+ * reset line to be asserted / deasserted in order to fully enable the
+ * IP.  These modules may have multiple hard-reset lines that reset
+ * different 'submodules' inside the IP block.  This function will
+ * place the submodule into reset.  Returns 0 upon success or -EINVAL
+ * upon an argument error.
+ */
+int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift)
+{
+	u32 mask;
+
+	if (!(cpu_is_omap24xx() || cpu_is_omap34xx()))
+		return -EINVAL;
+
+	mask = 1 << shift;
+	prm_rmw_mod_reg_bits(mask, mask, prm_mod, OMAP2_RM_RSTCTRL);
+
+	return 0;
+}
+
+/**
+ * omap2_prm_deassert_hardreset - deassert a submodule hardreset line and wait
+ * @prm_mod: PRM submodule base (e.g. CORE_MOD)
+ * @shift: register bit shift corresponding to the reset line to deassert
+ *
+ * Some IPs like dsp or iva contain processors that require an HW
+ * reset line to be asserted / deasserted in order to fully enable the
+ * IP.  These modules may have multiple hard-reset lines that reset
+ * different 'submodules' inside the IP block.  This function will
+ * take the submodule out of reset and wait until the PRCM indicates
+ * that the reset has completed before returning.  Returns 0 upon success or
+ * -EINVAL upon an argument error, -EEXIST if the submodule was already out
+ * of reset, or -EBUSY if the submodule did not exit reset promptly.
+ */
+int omap2_prm_deassert_hardreset(s16 prm_mod, u8 shift)
+{
+	u32 mask;
+	int c;
+
+	if (!(cpu_is_omap24xx() || cpu_is_omap34xx()))
+		return -EINVAL;
+
+	mask = 1 << shift;
+
+	/* Check the current status to avoid de-asserting the line twice */
+	if (prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL, mask) == 0)
+		return -EEXIST;
+
+	/* Clear the reset status by writing 1 to the status bit */
+	prm_rmw_mod_reg_bits(0xffffffff, mask, prm_mod, OMAP2_RM_RSTST);
+	/* de-assert the reset control line */
+	prm_rmw_mod_reg_bits(mask, 0, prm_mod, OMAP2_RM_RSTCTRL);
+	/* wait the status to be set */
+	omap_test_timeout(prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTST,
+						  mask),
+			  MAX_MODULE_HARDRESET_WAIT, c);
+
+	return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
+}
+
diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c
new file mode 100644
index 0000000..a1ff918
--- /dev/null
+++ b/arch/arm/mach-omap2/prm44xx.c
@@ -0,0 +1,116 @@
+/*
+ * OMAP4 PRM module functions
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Copyright (C) 2010 Nokia Corporation
+ * Benoît Cousson
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+
+#include <plat/common.h>
+#include <plat/cpu.h>
+#include <plat/prcm.h>
+
+#include "prm.h"
+#include "prm-regbits-44xx.h"
+
+/*
+ * Address offset (in bytes) between the reset control and the reset
+ * status registers: 4 bytes on OMAP4
+ */
+#define OMAP4_RST_CTRL_ST_OFFSET		4
+
+/**
+ * omap4_prm_is_hardreset_asserted - read the HW reset line state of
+ * submodules contained in the hwmod module
+ * @rstctrl_reg: RM_RSTCTRL register address for this module
+ * @shift: register bit shift corresponding to the reset line to check
+ *
+ * Returns 1 if the (sub)module hardreset line is currently asserted,
+ * 0 if the (sub)module hardreset line is not currently asserted, or
+ * -EINVAL upon parameter error.
+ */
+int omap4_prm_is_hardreset_asserted(void __iomem *rstctrl_reg, u8 shift)
+{
+	if (!cpu_is_omap44xx() || !rstctrl_reg)
+		return -EINVAL;
+
+	return omap4_prm_read_bits_shift(rstctrl_reg, (1 << shift));
+}
+
+/**
+ * omap4_prm_assert_hardreset - assert the HW reset line of a submodule
+ * @rstctrl_reg: RM_RSTCTRL register address for this module
+ * @shift: register bit shift corresponding to the reset line to assert
+ *
+ * Some IPs like dsp, ipu or iva contain processors that require an HW
+ * reset line to be asserted / deasserted in order to fully enable the
+ * IP.  These modules may have multiple hard-reset lines that reset
+ * different 'submodules' inside the IP block.  This function will
+ * place the submodule into reset.  Returns 0 upon success or -EINVAL
+ * upon an argument error.
+ */
+int omap4_prm_assert_hardreset(void __iomem *rstctrl_reg, u8 shift)
+{
+	u32 mask;
+
+	if (!cpu_is_omap44xx() || !rstctrl_reg)
+		return -EINVAL;
+
+	mask = 1 << shift;
+	omap4_prm_rmw_reg_bits(mask, mask, rstctrl_reg);
+
+	return 0;
+}
+
+/**
+ * omap4_prm_deassert_hardreset - deassert a submodule hardreset line and wait
+ * @rstctrl_reg: RM_RSTCTRL register address for this module
+ * @shift: register bit shift corresponding to the reset line to deassert
+ *
+ * Some IPs like dsp, ipu or iva contain processors that require an HW
+ * reset line to be asserted / deasserted in order to fully enable the
+ * IP.  These modules may have multiple hard-reset lines that reset
+ * different 'submodules' inside the IP block.  This function will
+ * take the submodule out of reset and wait until the PRCM indicates
+ * that the reset has completed before returning.  Returns 0 upon success or
+ * -EINVAL upon an argument error, -EEXIST if the submodule was already out
+ * of reset, or -EBUSY if the submodule did not exit reset promptly.
+ */
+int omap4_prm_deassert_hardreset(void __iomem *rstctrl_reg, u8 shift)
+{
+	u32 mask;
+	void __iomem *rstst_reg;
+	int c;
+
+	if (!cpu_is_omap44xx() || !rstctrl_reg)
+		return -EINVAL;
+
+	rstst_reg = rstctrl_reg + OMAP4_RST_CTRL_ST_OFFSET;
+
+	mask = 1 << shift;
+
+	/* Check the current status to avoid de-asserting the line twice */
+	if (omap4_prm_read_bits_shift(rstctrl_reg, mask) == 0)
+		return -EEXIST;
+
+	/* Clear the reset status by writing 1 to the status bit */
+	omap4_prm_rmw_reg_bits(0xffffffff, mask, rstst_reg);
+	/* de-assert the reset control line */
+	omap4_prm_rmw_reg_bits(mask, 0, rstctrl_reg);
+	/* wait the status to be set */
+	omap_test_timeout(omap4_prm_read_bits_shift(rstst_reg, mask),
+			  MAX_MODULE_HARDRESET_WAIT, c);
+
+	return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
+}
+
diff --git a/arch/arm/mach-omap2/prm44xx.h b/arch/arm/mach-omap2/prm44xx.h
index fe8ef26..59839db 100644
--- a/arch/arm/mach-omap2/prm44xx.h
+++ b/arch/arm/mach-omap2/prm44xx.h
@@ -44,14 +44,12 @@
 #define OMAP4430_PRM_IRQSTATUS_TESLA			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x0030)
 #define OMAP4_PRM_IRQENABLE_TESLA_OFFSET		0x0038
 #define OMAP4430_PRM_IRQENABLE_TESLA			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x0038)
-#define OMAP4_PRM_PRM_PROFILING_CLKCTRL_OFFSET		0x0040
-#define OMAP4430_PRM_PRM_PROFILING_CLKCTRL		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x0040)
+#define OMAP4_CM_PRM_PROFILING_CLKCTRL_OFFSET		0x0040
+#define OMAP4430_CM_PRM_PROFILING_CLKCTRL		OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x0040)
 
 /* PRM.CKGEN_PRM register offsets */
 #define OMAP4_CM_ABE_DSS_SYS_CLKSEL_OFFSET		0x0000
 #define OMAP4430_CM_ABE_DSS_SYS_CLKSEL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CKGEN_MOD, 0x0000)
-#define OMAP4_CM_DPLL_SYS_REF_CLKSEL_OFFSET		0x0004
-#define OMAP4430_CM_DPLL_SYS_REF_CLKSEL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CKGEN_MOD, 0x0004)
 #define OMAP4_CM_L4_WKUP_CLKSEL_OFFSET			0x0008
 #define OMAP4430_CM_L4_WKUP_CLKSEL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CKGEN_MOD, 0x0008)
 #define OMAP4_CM_ABE_PLL_REF_CLKSEL_OFFSET		0x000c
@@ -686,8 +684,8 @@
 #define OMAP4430_PRM_LDO_ABB_IVA_SETUP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00d8)
 #define OMAP4_PRM_LDO_ABB_IVA_CTRL_OFFSET		0x00dc
 #define OMAP4430_PRM_LDO_ABB_IVA_CTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00dc)
-#define OMAP4_PRM_LDO_BANDGAP_CTRL_OFFSET		0x00e0
-#define OMAP4430_PRM_LDO_BANDGAP_CTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00e0)
+#define OMAP4_PRM_LDO_BANDGAP_SETUP_OFFSET		0x00e0
+#define OMAP4430_PRM_LDO_BANDGAP_SETUP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00e0)
 #define OMAP4_PRM_DEVICE_OFF_CTRL_OFFSET		0x00e4
 #define OMAP4430_PRM_DEVICE_OFF_CTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00e4)
 #define OMAP4_PRM_PHASE1_CNDP_OFFSET			0x00e8
@@ -698,6 +696,8 @@
 #define OMAP4430_PRM_PHASE2B_CNDP			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00f0)
 #define OMAP4_PRM_MODEM_IF_CTRL_OFFSET			0x00f4
 #define OMAP4430_PRM_MODEM_IF_CTRL			OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00f4)
+#define OMAP4_PRM_VC_ERRST_OFFSET			0x00f8
+#define OMAP4430_PRM_VC_ERRST				OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00f8)
 
 /*
  * PRCM_MPU
@@ -715,6 +715,8 @@
 /* PRCM_MPU.DEVICE_PRM register offsets */
 #define OMAP4_PRCM_MPU_PRM_RSTST_OFFSET			0x0000
 #define OMAP4430_PRCM_MPU_PRM_RSTST			OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_DEVICE_PRM_MOD, 0x0000)
+#define OMAP4_PRCM_MPU_PRM_PSCON_COUNT_OFFSET		0x0004
+#define OMAP4430_PRCM_MPU_PRM_PSCON_COUNT		OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_DEVICE_PRM_MOD, 0x0004)
 
 /* PRCM_MPU.CPU0 register offsets */
 #define OMAP4_PM_CPU0_PWRSTCTRL_OFFSET			0x0000
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 566e991..becf0e3 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -19,20 +19,31 @@
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/serial_8250.h>
 #include <linux/serial_reg.h>
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/serial_8250.h>
+#include <linux/pm_runtime.h>
+
+#ifdef CONFIG_SERIAL_OMAP
+#include <plat/omap-serial.h>
+#endif
 
 #include <plat/common.h>
 #include <plat/board.h>
 #include <plat/clock.h>
-#include <plat/control.h>
+#include <plat/dma.h>
+#include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
 
 #include "prm.h"
 #include "pm.h"
+#include "cm.h"
 #include "prm-regbits-34xx.h"
+#include "control.h"
 
 #define UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV	0x52
 #define UART_OMAP_WER		0x17	/* Wake-up enable register */
@@ -48,6 +59,8 @@
  */
 #define DEFAULT_TIMEOUT 0
 
+#define MAX_UART_HWMOD_NAME_LEN		16
+
 struct omap_uart_state {
 	int num;
 	int can_sleep;
@@ -58,14 +71,21 @@
 	void __iomem *wk_en;
 	u32 wk_mask;
 	u32 padconf;
+	u32 dma_enabled;
 
 	struct clk *ick;
 	struct clk *fck;
 	int clocked;
 
-	struct plat_serial8250_port *p;
+	int irq;
+	int regshift;
+	int irqflags;
+	void __iomem *membase;
+	resource_size_t mapbase;
+
 	struct list_head node;
-	struct platform_device pdev;
+	struct omap_hwmod *oh;
+	struct platform_device *pdev;
 
 	u32 errata;
 #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
@@ -83,75 +103,47 @@
 };
 
 static LIST_HEAD(uart_list);
+static u8 num_uarts;
 
-static struct plat_serial8250_port serial_platform_data0[] = {
-	{
-		.irq		= 72,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.iotype		= UPIO_MEM,
-		.regshift	= 2,
-		.uartclk	= OMAP24XX_BASE_BAUD * 16,
-	}, {
-		.flags		= 0
-	}
-};
-
-static struct plat_serial8250_port serial_platform_data1[] = {
-	{
-		.irq		= 73,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.iotype		= UPIO_MEM,
-		.regshift	= 2,
-		.uartclk	= OMAP24XX_BASE_BAUD * 16,
-	}, {
-		.flags		= 0
-	}
-};
-
-static struct plat_serial8250_port serial_platform_data2[] = {
-	{
-		.irq		= 74,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.iotype		= UPIO_MEM,
-		.regshift	= 2,
-		.uartclk	= OMAP24XX_BASE_BAUD * 16,
-	}, {
-		.flags		= 0
-	}
-};
-
-static struct plat_serial8250_port serial_platform_data3[] = {
-	{
-		.irq		= 70,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.iotype		= UPIO_MEM,
-		.regshift	= 2,
-		.uartclk	= OMAP24XX_BASE_BAUD * 16,
-	}, {
-		.flags		= 0
-	}
-};
-
-void __init omap2_set_globals_uart(struct omap_globals *omap2_globals)
+/*
+ * Since these idle/enable hooks are used in the idle path itself
+ * which has interrupts disabled, use the non-locking versions of
+ * the hwmod enable/disable functions.
+ */
+static int uart_idle_hwmod(struct omap_device *od)
 {
-	serial_platform_data0[0].mapbase = omap2_globals->uart1_phys;
-	serial_platform_data1[0].mapbase = omap2_globals->uart2_phys;
-	serial_platform_data2[0].mapbase = omap2_globals->uart3_phys;
-	serial_platform_data3[0].mapbase = omap2_globals->uart4_phys;
+	_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)
+					     int offset)
 {
 	offset <<= up->regshift;
 	return (unsigned int)__raw_readb(up->membase + offset);
 }
 
-static inline unsigned int serial_read_reg(struct plat_serial8250_port *up,
+static inline unsigned int serial_read_reg(struct omap_uart_state *uart,
 					   int offset)
 {
-	offset <<= up->regshift;
-	return (unsigned int)__raw_readb(up->membase + offset);
+	offset <<= uart->regshift;
+	return (unsigned int)__raw_readb(uart->membase + offset);
 }
 
 static inline void __serial_write_reg(struct uart_port *up, int offset,
@@ -161,11 +153,11 @@
 	__raw_writeb(value, up->membase + offset);
 }
 
-static inline void serial_write_reg(struct plat_serial8250_port *p, int offset,
+static inline void serial_write_reg(struct omap_uart_state *uart, int offset,
 				    int value)
 {
-	offset <<= p->regshift;
-	__raw_writeb(value, p->membase + offset);
+	offset <<= uart->regshift;
+	__raw_writeb(value, uart->membase + offset);
 }
 
 /*
@@ -173,14 +165,12 @@
  * properly. Note that the TX watermark initialization may not be needed
  * once the 8250.c watermark handling code is merged.
  */
+
 static inline void __init omap_uart_reset(struct omap_uart_state *uart)
 {
-	struct plat_serial8250_port *p = uart->p;
-
-	serial_write_reg(p, UART_OMAP_MDR1, 0x07);
-	serial_write_reg(p, UART_OMAP_SCR, 0x08);
-	serial_write_reg(p, UART_OMAP_MDR1, 0x00);
-	serial_write_reg(p, UART_OMAP_SYSC, (0x02 << 3) | (1 << 2) | (1 << 0));
+	serial_write_reg(uart, UART_OMAP_MDR1, 0x07);
+	serial_write_reg(uart, UART_OMAP_SCR, 0x08);
+	serial_write_reg(uart, UART_OMAP_MDR1, 0x00);
 }
 
 #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)
@@ -197,24 +187,23 @@
 static void omap_uart_mdr1_errataset(struct omap_uart_state *uart, u8 mdr1_val,
 		u8 fcr_val)
 {
-	struct plat_serial8250_port *p = uart->p;
 	u8 timeout = 255;
 
-	serial_write_reg(p, UART_OMAP_MDR1, mdr1_val);
+	serial_write_reg(uart, UART_OMAP_MDR1, mdr1_val);
 	udelay(2);
-	serial_write_reg(p, UART_FCR, fcr_val | UART_FCR_CLEAR_XMIT |
+	serial_write_reg(uart, UART_FCR, fcr_val | UART_FCR_CLEAR_XMIT |
 			UART_FCR_CLEAR_RCVR);
 	/*
 	 * Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and
 	 * TX_FIFO_E bit is 1.
 	 */
-	while (UART_LSR_THRE != (serial_read_reg(p, UART_LSR) &
+	while (UART_LSR_THRE != (serial_read_reg(uart, UART_LSR) &
 				(UART_LSR_THRE | UART_LSR_DR))) {
 		timeout--;
 		if (!timeout) {
 			/* Should *never* happen. we warn and carry on */
-			dev_crit(&uart->pdev.dev, "Errata i202: timedout %x\n",
-				serial_read_reg(p, UART_LSR));
+			dev_crit(&uart->pdev->dev, "Errata i202: timedout %x\n",
+			serial_read_reg(uart, UART_LSR));
 			break;
 		}
 		udelay(1);
@@ -224,23 +213,22 @@
 static void omap_uart_save_context(struct omap_uart_state *uart)
 {
 	u16 lcr = 0;
-	struct plat_serial8250_port *p = uart->p;
 
 	if (!enable_off_mode)
 		return;
 
-	lcr = serial_read_reg(p, UART_LCR);
-	serial_write_reg(p, UART_LCR, 0xBF);
-	uart->dll = serial_read_reg(p, UART_DLL);
-	uart->dlh = serial_read_reg(p, UART_DLM);
-	serial_write_reg(p, UART_LCR, lcr);
-	uart->ier = serial_read_reg(p, UART_IER);
-	uart->sysc = serial_read_reg(p, UART_OMAP_SYSC);
-	uart->scr = serial_read_reg(p, UART_OMAP_SCR);
-	uart->wer = serial_read_reg(p, UART_OMAP_WER);
-	serial_write_reg(p, UART_LCR, 0x80);
-	uart->mcr = serial_read_reg(p, UART_MCR);
-	serial_write_reg(p, UART_LCR, lcr);
+	lcr = serial_read_reg(uart, UART_LCR);
+	serial_write_reg(uart, UART_LCR, 0xBF);
+	uart->dll = serial_read_reg(uart, UART_DLL);
+	uart->dlh = serial_read_reg(uart, UART_DLM);
+	serial_write_reg(uart, UART_LCR, lcr);
+	uart->ier = serial_read_reg(uart, UART_IER);
+	uart->sysc = serial_read_reg(uart, UART_OMAP_SYSC);
+	uart->scr = serial_read_reg(uart, UART_OMAP_SCR);
+	uart->wer = serial_read_reg(uart, UART_OMAP_WER);
+	serial_write_reg(uart, UART_LCR, 0x80);
+	uart->mcr = serial_read_reg(uart, UART_MCR);
+	serial_write_reg(uart, UART_LCR, lcr);
 
 	uart->context_valid = 1;
 }
@@ -248,7 +236,6 @@
 static void omap_uart_restore_context(struct omap_uart_state *uart)
 {
 	u16 efr = 0;
-	struct plat_serial8250_port *p = uart->p;
 
 	if (!enable_off_mode)
 		return;
@@ -261,29 +248,30 @@
 	if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS)
 		omap_uart_mdr1_errataset(uart, 0x07, 0xA0);
 	else
-		serial_write_reg(p, UART_OMAP_MDR1, 0x7);
-	serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
-	efr = serial_read_reg(p, UART_EFR);
-	serial_write_reg(p, UART_EFR, UART_EFR_ECB);
-	serial_write_reg(p, UART_LCR, 0x0); /* Operational mode */
-	serial_write_reg(p, UART_IER, 0x0);
-	serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
-	serial_write_reg(p, UART_DLL, uart->dll);
-	serial_write_reg(p, UART_DLM, uart->dlh);
-	serial_write_reg(p, UART_LCR, 0x0); /* Operational mode */
-	serial_write_reg(p, UART_IER, uart->ier);
-	serial_write_reg(p, UART_LCR, 0x80);
-	serial_write_reg(p, UART_MCR, uart->mcr);
-	serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
-	serial_write_reg(p, UART_EFR, efr);
-	serial_write_reg(p, UART_LCR, UART_LCR_WLEN8);
-	serial_write_reg(p, UART_OMAP_SCR, uart->scr);
-	serial_write_reg(p, UART_OMAP_WER, uart->wer);
-	serial_write_reg(p, UART_OMAP_SYSC, uart->sysc);
+		serial_write_reg(uart, UART_OMAP_MDR1, 0x7);
+	serial_write_reg(uart, UART_LCR, 0xBF); /* Config B mode */
+	efr = serial_read_reg(uart, UART_EFR);
+	serial_write_reg(uart, UART_EFR, UART_EFR_ECB);
+	serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */
+	serial_write_reg(uart, UART_IER, 0x0);
+	serial_write_reg(uart, UART_LCR, 0xBF); /* Config B mode */
+	serial_write_reg(uart, UART_DLL, uart->dll);
+	serial_write_reg(uart, UART_DLM, uart->dlh);
+	serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */
+	serial_write_reg(uart, UART_IER, uart->ier);
+	serial_write_reg(uart, UART_LCR, 0x80);
+	serial_write_reg(uart, UART_MCR, uart->mcr);
+	serial_write_reg(uart, UART_LCR, 0xBF); /* Config B mode */
+	serial_write_reg(uart, UART_EFR, efr);
+	serial_write_reg(uart, UART_LCR, UART_LCR_WLEN8);
+	serial_write_reg(uart, UART_OMAP_SCR, uart->scr);
+	serial_write_reg(uart, UART_OMAP_WER, uart->wer);
+	serial_write_reg(uart, UART_OMAP_SYSC, uart->sysc);
 	if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS)
 		omap_uart_mdr1_errataset(uart, 0x00, 0xA1);
 	else
-		serial_write_reg(p, UART_OMAP_MDR1, 0x00); /* UART 16x mode */
+		/* UART 16x mode */
+		serial_write_reg(uart, UART_OMAP_MDR1, 0x00);
 }
 #else
 static inline void omap_uart_save_context(struct omap_uart_state *uart) {}
@@ -295,8 +283,7 @@
 	if (uart->clocked)
 		return;
 
-	clk_enable(uart->ick);
-	clk_enable(uart->fck);
+	omap_device_enable(uart->pdev);
 	uart->clocked = 1;
 	omap_uart_restore_context(uart);
 }
@@ -310,8 +297,7 @@
 
 	omap_uart_save_context(uart);
 	uart->clocked = 0;
-	clk_disable(uart->ick);
-	clk_disable(uart->fck);
+	omap_device_idle(uart->pdev);
 }
 
 static void omap_uart_enable_wakeup(struct omap_uart_state *uart)
@@ -349,18 +335,24 @@
 }
 
 static void omap_uart_smart_idle_enable(struct omap_uart_state *uart,
-					  int enable)
+					       int enable)
 {
-	struct plat_serial8250_port *p = uart->p;
-	u16 sysc;
+	u8 idlemode;
 
-	sysc = serial_read_reg(p, UART_OMAP_SYSC) & 0x7;
-	if (enable)
-		sysc |= 0x2 << 3;
-	else
-		sysc |= 0x1 << 3;
+	if (enable) {
+		/**
+		 * Errata 2.15: [UART]:Cannot Acknowledge Idle Requests
+		 * in Smartidle Mode When Configured for DMA Operations.
+		 */
+		if (uart->dma_enabled)
+			idlemode = HWMOD_IDLEMODE_FORCE;
+		else
+			idlemode = HWMOD_IDLEMODE_SMART;
+	} else {
+		idlemode = HWMOD_IDLEMODE_NO;
+	}
 
-	serial_write_reg(p, UART_OMAP_SYSC, sysc);
+	omap_hwmod_set_slave_idlemode(uart->oh, idlemode);
 }
 
 static void omap_uart_block_sleep(struct omap_uart_state *uart)
@@ -377,7 +369,7 @@
 
 static void omap_uart_allow_sleep(struct omap_uart_state *uart)
 {
-	if (device_may_wakeup(&uart->pdev.dev))
+	if (device_may_wakeup(&uart->pdev->dev))
 		omap_uart_enable_wakeup(uart);
 	else
 		omap_uart_disable_wakeup(uart);
@@ -472,6 +464,7 @@
  * UART will not idle or sleep for its timeout period.
  *
  **/
+/* static int first_interrupt; */
 static irqreturn_t omap_uart_interrupt(int irq, void *dev_id)
 {
 	struct omap_uart_state *uart = dev_id;
@@ -483,7 +476,6 @@
 
 static void omap_uart_idle_init(struct omap_uart_state *uart)
 {
-	struct plat_serial8250_port *p = uart->p;
 	int ret;
 
 	uart->can_sleep = 0;
@@ -495,7 +487,7 @@
 	omap_uart_smart_idle_enable(uart, 0);
 
 	if (cpu_is_omap34xx()) {
-		u32 mod = (uart->num == 2) ? OMAP3430_PER_MOD : CORE_MOD;
+		u32 mod = (uart->num > 1) ? OMAP3430_PER_MOD : CORE_MOD;
 		u32 wk_mask = 0;
 		u32 padconf = 0;
 
@@ -514,19 +506,17 @@
 			wk_mask = OMAP3430_ST_UART3_MASK;
 			padconf = 0x19e;
 			break;
+		case 3:
+			wk_mask = OMAP3630_ST_UART4_MASK;
+			padconf = 0x0d2;
+			break;
 		}
 		uart->wk_mask = wk_mask;
 		uart->padconf = padconf;
 	} else if (cpu_is_omap24xx()) {
 		u32 wk_mask = 0;
+		u32 wk_en = PM_WKEN1, wk_st = PM_WKST1;
 
-		if (cpu_is_omap2430()) {
-			uart->wk_en = OMAP2430_PRM_REGADDR(CORE_MOD, PM_WKEN1);
-			uart->wk_st = OMAP2430_PRM_REGADDR(CORE_MOD, PM_WKST1);
-		} else if (cpu_is_omap2420()) {
-			uart->wk_en = OMAP2420_PRM_REGADDR(CORE_MOD, PM_WKEN1);
-			uart->wk_st = OMAP2420_PRM_REGADDR(CORE_MOD, PM_WKST1);
-		}
 		switch (uart->num) {
 		case 0:
 			wk_mask = OMAP24XX_ST_UART1_MASK;
@@ -535,10 +525,19 @@
 			wk_mask = OMAP24XX_ST_UART2_MASK;
 			break;
 		case 2:
+			wk_en = OMAP24XX_PM_WKEN2;
+			wk_st = OMAP24XX_PM_WKST2;
 			wk_mask = OMAP24XX_ST_UART3_MASK;
 			break;
 		}
 		uart->wk_mask = wk_mask;
+		if (cpu_is_omap2430()) {
+			uart->wk_en = OMAP2430_PRM_REGADDR(CORE_MOD, wk_en);
+			uart->wk_st = OMAP2430_PRM_REGADDR(CORE_MOD, wk_st);
+		} else if (cpu_is_omap2420()) {
+			uart->wk_en = OMAP2420_PRM_REGADDR(CORE_MOD, wk_en);
+			uart->wk_st = OMAP2420_PRM_REGADDR(CORE_MOD, wk_st);
+		}
 	} else {
 		uart->wk_en = NULL;
 		uart->wk_st = NULL;
@@ -546,9 +545,9 @@
 		uart->padconf = 0;
 	}
 
-	p->irqflags |= IRQF_SHARED;
-	ret = request_irq(p->irq, omap_uart_interrupt, IRQF_SHARED,
-			  "serial idle", (void *)uart);
+	uart->irqflags |= IRQF_SHARED;
+	ret = request_threaded_irq(uart->irq, NULL, omap_uart_interrupt,
+				   IRQF_SHARED, "serial idle", (void *)uart);
 	WARN_ON(ret);
 }
 
@@ -558,11 +557,17 @@
 	struct omap_uart_state *uart;
 
 	list_for_each_entry(uart, &uart_list, node) {
-		if (enable)
-			ret = request_irq(uart->p->irq, omap_uart_interrupt,
-				IRQF_SHARED, "serial idle", (void *)uart);
-		else
-			free_irq(uart->p->irq, (void *)uart);
+		if (enable) {
+			pm_runtime_put_sync(&uart->pdev->dev);
+			ret = request_threaded_irq(uart->irq, NULL,
+						   omap_uart_interrupt,
+						   IRQF_SHARED,
+						   "serial idle",
+						   (void *)uart);
+		} else {
+			pm_runtime_get_noresume(&uart->pdev->dev);
+			free_irq(uart->irq, (void *)uart);
+		}
 	}
 }
 
@@ -570,10 +575,9 @@
 				  struct device_attribute *attr,
 				  char *buf)
 {
-	struct platform_device *pdev = container_of(dev,
-					struct platform_device, dev);
-	struct omap_uart_state *uart = container_of(pdev,
-					struct omap_uart_state, pdev);
+	struct platform_device *pdev = to_platform_device(dev);
+	struct omap_device *odev = to_omap_device(pdev);
+	struct omap_uart_state *uart = odev->hwmods[0]->dev_attr;
 
 	return sprintf(buf, "%u\n", uart->timeout / HZ);
 }
@@ -582,10 +586,9 @@
 				   struct device_attribute *attr,
 				   const char *buf, size_t n)
 {
-	struct platform_device *pdev = container_of(dev,
-					struct platform_device, dev);
-	struct omap_uart_state *uart = container_of(pdev,
-					struct omap_uart_state, pdev);
+	struct platform_device *pdev = to_platform_device(dev);
+	struct omap_device *odev = to_omap_device(pdev);
+	struct omap_uart_state *uart = odev->hwmods[0]->dev_attr;
 	unsigned int value;
 
 	if (sscanf(buf, "%u", &value) != 1) {
@@ -608,48 +611,15 @@
 #define DEV_CREATE_FILE(dev, attr) WARN_ON(device_create_file(dev, attr))
 #else
 static inline void omap_uart_idle_init(struct omap_uart_state *uart) {}
+static void omap_uart_block_sleep(struct omap_uart_state *uart)
+{
+	/* Needed to enable UART clocks when built without CONFIG_PM */
+	omap_uart_enable_clocks(uart);
+}
 #define DEV_CREATE_FILE(dev, attr)
 #endif /* CONFIG_PM */
 
-static struct omap_uart_state omap_uart[] = {
-	{
-		.pdev = {
-			.name			= "serial8250",
-			.id			= PLAT8250_DEV_PLATFORM,
-			.dev			= {
-				.platform_data	= serial_platform_data0,
-			},
-		},
-	}, {
-		.pdev = {
-			.name			= "serial8250",
-			.id			= PLAT8250_DEV_PLATFORM1,
-			.dev			= {
-				.platform_data	= serial_platform_data1,
-			},
-		},
-	}, {
-		.pdev = {
-			.name			= "serial8250",
-			.id			= PLAT8250_DEV_PLATFORM2,
-			.dev			= {
-				.platform_data	= serial_platform_data2,
-			},
-		},
-	},
-#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
-	{
-		.pdev = {
-			.name			= "serial8250",
-			.id			= 3,
-			.dev			= {
-				.platform_data	= serial_platform_data3,
-			},
-		},
-	},
-#endif
-};
-
+#ifndef CONFIG_SERIAL_OMAP
 /*
  * Override the default 8250 read handler: mem_serial_in()
  * Empty RX fifo read causes an abort on omap3630 and omap4
@@ -682,71 +652,44 @@
 	}
 	__serial_write_reg(up, offset, value);
 }
+#endif
+
 void __init omap_serial_early_init(void)
 {
-	int i, nr_ports;
-	char name[16];
+	int i = 0;
 
-	if (!(cpu_is_omap3630() || cpu_is_omap4430()))
-		nr_ports = 3;
-	else
-		nr_ports = ARRAY_SIZE(omap_uart);
+	do {
+		char oh_name[MAX_UART_HWMOD_NAME_LEN];
+		struct omap_hwmod *oh;
+		struct omap_uart_state *uart;
 
-	/*
-	 * Make sure the serial ports are muxed on at this point.
-	 * You have to mux them off in device drivers later on
-	 * if not needed.
-	 */
+		snprintf(oh_name, MAX_UART_HWMOD_NAME_LEN,
+			 "uart%d", i + 1);
+		oh = omap_hwmod_lookup(oh_name);
+		if (!oh)
+			break;
 
-	for (i = 0; i < nr_ports; i++) {
-		struct omap_uart_state *uart = &omap_uart[i];
-		struct platform_device *pdev = &uart->pdev;
-		struct device *dev = &pdev->dev;
-		struct plat_serial8250_port *p = dev->platform_data;
+		uart = kzalloc(sizeof(struct omap_uart_state), GFP_KERNEL);
+		if (WARN_ON(!uart))
+			return;
 
-		/* Don't map zero-based physical address */
-		if (p->mapbase == 0) {
-			dev_warn(dev, "no physical address for uart#%d,"
-				 " so skipping early_init...\n", i);
-			continue;
-		}
+		uart->oh = oh;
+		uart->num = i++;
+		list_add_tail(&uart->node, &uart_list);
+		num_uarts++;
+
 		/*
-		 * Module 4KB + L4 interconnect 4KB
-		 * Static mapping, never released
+		 * NOTE: omap_hwmod_init() has not yet been called,
+		 *       so no hwmod functions will work yet.
 		 */
-		p->membase = ioremap(p->mapbase, SZ_8K);
-		if (!p->membase) {
-			dev_err(dev, "ioremap failed for uart%i\n", i + 1);
-			continue;
-		}
 
-		sprintf(name, "uart%d_ick", i + 1);
-		uart->ick = clk_get(NULL, name);
-		if (IS_ERR(uart->ick)) {
-			dev_err(dev, "Could not get uart%d_ick\n", i + 1);
-			uart->ick = NULL;
-		}
-
-		sprintf(name, "uart%d_fck", i+1);
-		uart->fck = clk_get(NULL, name);
-		if (IS_ERR(uart->fck)) {
-			dev_err(dev, "Could not get uart%d_fck\n", i + 1);
-			uart->fck = NULL;
-		}
-
-		/* FIXME: Remove this once the clkdev is ready */
-		if (!cpu_is_omap44xx()) {
-			if (!uart->ick || !uart->fck)
-				continue;
-		}
-
-		uart->num = i;
-		p->private_data = uart;
-		uart->p = p;
-
-		if (cpu_is_omap44xx())
-			p->irq += 32;
-	}
+		/*
+		 * During UART early init, device need to be probed
+		 * to determine SoC specific init before omap_device
+		 * is ready.  Therefore, don't allow idle here
+		 */
+		uart->oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET;
+	} while (1);
 }
 
 /**
@@ -763,53 +706,135 @@
 void __init omap_serial_init_port(int port)
 {
 	struct omap_uart_state *uart;
-	struct platform_device *pdev;
-	struct device *dev;
+	struct omap_hwmod *oh;
+	struct omap_device *od;
+	void *pdata = NULL;
+	u32 pdata_size = 0;
+	char *name;
+#ifndef CONFIG_SERIAL_OMAP
+	struct plat_serial8250_port ports[2] = {
+		{},
+		{.flags = 0},
+	};
+	struct plat_serial8250_port *p = &ports[0];
+#else
+	struct omap_uart_port_info omap_up;
+#endif
 
-	BUG_ON(port < 0);
-	BUG_ON(port >= ARRAY_SIZE(omap_uart));
-
-	uart = &omap_uart[port];
-	pdev = &uart->pdev;
-	dev = &pdev->dev;
-
-	/* Don't proceed if there's no clocks available */
-	if (unlikely(!uart->ick || !uart->fck)) {
-		WARN(1, "%s: can't init uart%d, no clocks available\n",
-		     kobject_name(&dev->kobj), port);
+	if (WARN_ON(port < 0))
 		return;
-	}
-
-	omap_uart_enable_clocks(uart);
-
-	omap_uart_reset(uart);
-	omap_uart_idle_init(uart);
-
-	list_add_tail(&uart->node, &uart_list);
-
-	if (WARN_ON(platform_device_register(pdev)))
+	if (WARN_ON(port >= num_uarts))
 		return;
 
-	if ((cpu_is_omap34xx() && uart->padconf) ||
-	    (uart->wk_en && uart->wk_mask)) {
-		device_init_wakeup(dev, true);
-		DEV_CREATE_FILE(dev, &dev_attr_sleep_timeout);
-	}
+	list_for_each_entry(uart, &uart_list, node)
+		if (port == uart->num)
+			break;
+
+	oh = uart->oh;
+	uart->dma_enabled = 0;
+#ifndef CONFIG_SERIAL_OMAP
+	name = "serial8250";
+
+	/*
+	 * !! 8250 driver does not use standard IORESOURCE* It
+	 * has it's own custom pdata that can be taken from
+	 * the hwmod resource data.  But, this needs to be
+	 * done after the build.
+	 *
+	 * ?? does it have to be done before the register ??
+	 * YES, because platform_device_data_add() copies
+	 * pdata, it does not use a pointer.
+	 */
+	p->flags = UPF_BOOT_AUTOCONF;
+	p->iotype = UPIO_MEM;
+	p->regshift = 2;
+	p->uartclk = OMAP24XX_BASE_BAUD * 16;
+	p->irq = oh->mpu_irqs[0].irq;
+	p->mapbase = oh->slaves[0]->addr->pa_start;
+	p->membase = omap_hwmod_get_mpu_rt_va(oh);
+	p->irqflags = IRQF_SHARED;
+	p->private_data = uart;
 
 	/*
 	 * omap44xx: Never read empty UART fifo
 	 * omap3xxx: Never read empty UART fifo on UARTs
 	 * with IP rev >=0x52
 	 */
+	uart->regshift = p->regshift;
+	uart->membase = p->membase;
 	if (cpu_is_omap44xx())
 		uart->errata |= UART_ERRATA_FIFO_FULL_ABORT;
-	else if ((serial_read_reg(uart->p, UART_OMAP_MVER) & 0xFF)
+	else if ((serial_read_reg(uart, UART_OMAP_MVER) & 0xFF)
 			>= UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV)
 		uart->errata |= UART_ERRATA_FIFO_FULL_ABORT;
 
 	if (uart->errata & UART_ERRATA_FIFO_FULL_ABORT) {
-		uart->p->serial_in = serial_in_override;
-		uart->p->serial_out = serial_out_override;
+		p->serial_in = serial_in_override;
+		p->serial_out = serial_out_override;
+	}
+
+	pdata = &ports[0];
+	pdata_size = 2 * sizeof(struct plat_serial8250_port);
+#else
+
+	name = DRIVER_NAME;
+
+	omap_up.dma_enabled = uart->dma_enabled;
+	omap_up.uartclk = OMAP24XX_BASE_BAUD * 16;
+	omap_up.mapbase = oh->slaves[0]->addr->pa_start;
+	omap_up.membase = omap_hwmod_get_mpu_rt_va(oh);
+	omap_up.irqflags = IRQF_SHARED;
+	omap_up.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+
+	pdata = &omap_up;
+	pdata_size = sizeof(struct omap_uart_port_info);
+#endif
+
+	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",
+	     name, oh->name);
+
+	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;
+
+	oh->dev_attr = uart;
+
+	/*
+	 * Because of early UART probing, UART did not get idled
+	 * on init.  Now that omap_device is ready, ensure full idle
+	 * before doing omap_device_enable().
+	 */
+	omap_hwmod_idle(uart->oh);
+
+	omap_device_enable(uart->pdev);
+	omap_uart_idle_init(uart);
+	omap_uart_reset(uart);
+	omap_hwmod_enable_wakeup(uart->oh);
+	omap_device_idle(uart->pdev);
+
+	/*
+	 * Need to block sleep long enough for interrupt driven
+	 * driver to start.  Console driver is in polling mode
+	 * so device needs to be kept enabled while polling driver
+	 * is in use.
+	 */
+	if (uart->timeout)
+		uart->timeout = (30 * HZ);
+	omap_uart_block_sleep(uart);
+	uart->timeout = DEFAULT_TIMEOUT;
+
+	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);
 	}
 
 	/* Enable the MDR1 errata for OMAP3 */
@@ -826,13 +851,8 @@
  */
 void __init omap_serial_init(void)
 {
-	int i, nr_ports;
+	struct omap_uart_state *uart;
 
-	if (!(cpu_is_omap3630() || cpu_is_omap4430()))
-		nr_ports = 3;
-	else
-		nr_ports = ARRAY_SIZE(omap_uart);
-
-	for (i = 0; i < nr_ports; i++)
-		omap_serial_init_port(i);
+	list_for_each_entry(uart, &uart_list, node)
+		omap_serial_init_port(uart->num);
 }
diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S
index ba53191..2fb205a 100644
--- a/arch/arm/mach-omap2/sleep34xx.S
+++ b/arch/arm/mach-omap2/sleep34xx.S
@@ -27,11 +27,11 @@
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <mach/io.h>
-#include <plat/control.h>
 
 #include "cm.h"
 #include "prm.h"
 #include "sdrc.h"
+#include "control.h"
 
 #define SDRC_SCRATCHPAD_SEM_V	0xfa00291c
 
diff --git a/arch/arm/mach-omap2/sram34xx.S b/arch/arm/mach-omap2/sram34xx.S
index de99ba2..3637274 100644
--- a/arch/arm/mach-omap2/sram34xx.S
+++ b/arch/arm/mach-omap2/sram34xx.S
@@ -129,8 +129,11 @@
 	ldr	r4, [sp, #80]
 	str     r4, omap_sdrc_mr_1_val
 skip_cs1_params:
+	mrc	p15, 0, r8, c1, c0, 0	@ read ctrl register
+	bic	r10, r8, #0x800		@ clear Z-bit, disable branch prediction
+	mcr	p15, 0, r10, c1, c0, 0	@ write ctrl register
 	dsb				@ flush buffered writes to interconnect
-
+	isb				@ prevent speculative exec past here
 	cmp	r3, #1			@ if increasing SDRC clk rate,
 	bleq	configure_sdrc		@ program the SDRC regs early (for RFR)
 	cmp	r1, #SDRC_UNLOCK_DLL	@ set the intended DLL state
@@ -148,6 +151,7 @@
 	beq	return_to_sdram		@ return to SDRAM code, otherwise,
 	bl	configure_sdrc		@ reprogram SDRC regs now
 return_to_sdram:
+	mcr	p15, 0, r8, c1, c0, 0	@ restore ctrl register
 	isb				@ prevent speculative exec past here
 	mov 	r0, #0 			@ return value
 	ldmfd	sp!, {r1-r12, pc}	@ restore regs and return
diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c
index 74fbed8..e13c29e 100644
--- a/arch/arm/mach-omap2/timer-gp.c
+++ b/arch/arm/mach-omap2/timer-gp.c
@@ -40,6 +40,8 @@
 #include <plat/dmtimer.h>
 #include <asm/localtimer.h>
 
+#include "timer-gp.h"
+
 /* MAX_GPTIMER_ID: number of GPTIMERs on the chip */
 #define MAX_GPTIMER_ID		12
 
@@ -228,8 +230,10 @@
 static void __init omap2_gp_timer_init(void)
 {
 #ifdef CONFIG_LOCAL_TIMERS
-	twd_base = ioremap(OMAP44XX_LOCAL_TWD_BASE, SZ_256);
-	BUG_ON(!twd_base);
+	if (cpu_is_omap44xx()) {
+		twd_base = ioremap(OMAP44XX_LOCAL_TWD_BASE, SZ_256);
+		BUG_ON(!twd_base);
+	}
 #endif
 	omap_dm_timer_init();
 
diff --git a/arch/arm/plat-omap/include/plat/timer-gp.h b/arch/arm/mach-omap2/timer-gp.h
similarity index 86%
rename from arch/arm/plat-omap/include/plat/timer-gp.h
rename to arch/arm/mach-omap2/timer-gp.h
index c88d346..5c1072c 100644
--- a/arch/arm/plat-omap/include/plat/timer-gp.h
+++ b/arch/arm/mach-omap2/timer-gp.h
@@ -11,7 +11,6 @@
 #ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_TIMER_GP_H
 #define __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_TIMER_GP_H
 
-int __init omap2_gp_clockevent_set_gptimer(u8 id);
+extern int __init omap2_gp_clockevent_set_gptimer(u8 id);
 
 #endif
-
diff --git a/arch/arm/mach-omap2/usb-fs.c b/arch/arm/mach-omap2/usb-fs.c
index a216d88..1481078 100644
--- a/arch/arm/mach-omap2/usb-fs.c
+++ b/arch/arm/mach-omap2/usb-fs.c
@@ -29,18 +29,18 @@
 
 #include <asm/irq.h>
 
-#include <plat/control.h>
 #include <plat/usb.h>
 #include <plat/board.h>
 
+#include "control.h"
+#include "mux.h"
+
 #define INT_USB_IRQ_GEN		INT_24XX_USB_IRQ_GEN
 #define INT_USB_IRQ_NISO	INT_24XX_USB_IRQ_NISO
 #define INT_USB_IRQ_ISO		INT_24XX_USB_IRQ_ISO
 #define INT_USB_IRQ_HGEN	INT_24XX_USB_IRQ_HGEN
 #define INT_USB_IRQ_OTG		INT_24XX_USB_IRQ_OTG
 
-#include "mux.h"
-
 #if defined(CONFIG_ARCH_OMAP2)
 
 #ifdef	CONFIG_USB_GADGET_OMAP
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index a57713c..acd9552 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -16,6 +16,10 @@
 
 endchoice
 
+config TEGRA_PCI
+	bool "PCI Express support"
+	select PCI
+
 comment "Tegra board type"
 
 config MACH_HARMONY
@@ -47,4 +51,11 @@
 
 endchoice
 
+config TEGRA_SYSTEM_DMA
+	bool "Enable system DMA driver for NVIDIA Tegra SoCs"
+	default y
+	help
+	  Adds system DMA functionality for NVIDIA Tegra SoCs, used by
+	  several Tegra device drivers
+
 endif
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 51e9370..cdbc68e 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -1,14 +1,21 @@
 obj-y                                   += common.o
 obj-y                                   += io.o
-obj-y                                   += irq.o
+obj-y                                   += irq.o legacy_irq.o
 obj-y                                   += clock.o
 obj-y                                   += timer.o
 obj-y                                   += gpio.o
 obj-y                                   += pinmux.o
+obj-y					+= fuse.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += clock.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += tegra2_clocks.o
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += tegra2_dvfs.o
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= pinmux-t2-tables.o
 obj-$(CONFIG_SMP)                       += platsmp.o localtimer.o headsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)               += hotplug.o
+obj-$(CONFIG_TEGRA_SYSTEM_DMA)		+= dma.o
+obj-$(CONFIG_CPU_FREQ)                  += cpu-tegra.o
+obj-$(CONFIG_TEGRA_PCI)			+= pcie.o
 
 obj-${CONFIG_MACH_HARMONY}              += board-harmony.o
 obj-${CONFIG_MACH_HARMONY}              += board-harmony-pinmux.o
+obj-${CONFIG_MACH_HARMONY}              += board-harmony-pcie.o
diff --git a/arch/arm/mach-tegra/board-harmony-pcie.c b/arch/arm/mach-tegra/board-harmony-pcie.c
new file mode 100644
index 0000000..f7e7d45
--- /dev/null
+++ b/arch/arm/mach-tegra/board-harmony-pcie.c
@@ -0,0 +1,57 @@
+/*
+ * arch/arm/mach-tegra/board-harmony-pcie.c
+ *
+ * Copyright (C) 2010 CompuLab, Ltd.
+ * Mike Rapoport <mike@compulab.co.il>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/err.h>
+#include <linux/regulator/consumer.h>
+
+#include <asm/mach-types.h>
+
+#include <mach/pinmux.h>
+#include "board.h"
+
+#ifdef CONFIG_TEGRA_PCI
+
+static int __init harmony_pcie_init(void)
+{
+	int err;
+
+	if (!machine_is_harmony())
+		return 0;
+
+	tegra_pinmux_set_tristate(TEGRA_PINGROUP_GPV, TEGRA_TRI_NORMAL);
+	tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXA, TEGRA_TRI_NORMAL);
+	tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXK, TEGRA_TRI_NORMAL);
+
+	err = tegra_pcie_init(true, true);
+	if (err)
+		goto err_pcie;
+
+	return 0;
+
+err_pcie:
+	tegra_pinmux_set_tristate(TEGRA_PINGROUP_GPV, TEGRA_TRI_TRISTATE);
+	tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXA, TEGRA_TRI_TRISTATE);
+	tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXK, TEGRA_TRI_TRISTATE);
+
+	return err;
+}
+
+subsys_initcall(harmony_pcie_init);
+
+#endif
diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h
index 3d06354..0de565c 100644
--- a/arch/arm/mach-tegra/board.h
+++ b/arch/arm/mach-tegra/board.h
@@ -27,6 +27,7 @@
 void __init tegra_map_common_io(void);
 void __init tegra_init_irq(void);
 void __init tegra_init_clock(void);
+int __init tegra_pcie_init(bool init_port0, bool init_port1);
 
 extern struct sys_timer tegra_timer;
 #endif
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c
index 03ad578..ae19f95 100644
--- a/arch/arm/mach-tegra/clock.c
+++ b/arch/arm/mach-tegra/clock.c
@@ -24,13 +24,80 @@
 #include <linux/debugfs.h>
 #include <linux/slab.h>
 #include <linux/seq_file.h>
+#include <linux/regulator/consumer.h>
 #include <asm/clkdev.h>
 
 #include "clock.h"
+#include "board.h"
+#include "fuse.h"
 
 static LIST_HEAD(clocks);
 
 static DEFINE_SPINLOCK(clock_lock);
+static DEFINE_MUTEX(dvfs_lock);
+
+static int clk_is_dvfs(struct clk *c)
+{
+	return (c->dvfs != NULL);
+};
+
+static int dvfs_set_rate(struct dvfs *d, unsigned long rate)
+{
+	struct dvfs_table *t;
+
+	if (d->table == NULL)
+		return -ENODEV;
+
+	for (t = d->table; t->rate != 0; t++) {
+		if (rate <= t->rate) {
+			if (!d->reg)
+				return 0;
+
+			return regulator_set_voltage(d->reg,
+				t->millivolts * 1000,
+				d->max_millivolts * 1000);
+		}
+	}
+
+	return -EINVAL;
+}
+
+static void dvfs_init(struct clk *c)
+{
+	int process_id;
+	int i;
+	struct dvfs_table *table;
+
+	process_id = c->dvfs->cpu ? tegra_core_process_id() :
+		tegra_cpu_process_id();
+
+	for (i = 0; i < c->dvfs->process_id_table_length; i++)
+		if (process_id == c->dvfs->process_id_table[i].process_id)
+			c->dvfs->table = c->dvfs->process_id_table[i].table;
+
+	if (c->dvfs->table == NULL) {
+		pr_err("Failed to find dvfs table for clock %s process %d\n",
+			c->name, process_id);
+		return;
+	}
+
+	c->dvfs->max_millivolts = 0;
+	for (table = c->dvfs->table; table->rate != 0; table++)
+		if (c->dvfs->max_millivolts < table->millivolts)
+			c->dvfs->max_millivolts = table->millivolts;
+
+	c->dvfs->reg = regulator_get(NULL, c->dvfs->reg_id);
+
+	if (IS_ERR(c->dvfs->reg)) {
+		pr_err("Failed to get regulator %s for clock %s\n",
+			c->dvfs->reg_id, c->name);
+		c->dvfs->reg = NULL;
+		return;
+	}
+
+	if (c->refcnt > 0)
+		dvfs_set_rate(c->dvfs, c->rate);
+}
 
 struct clk *tegra_get_clock_by_name(const char *name)
 {
@@ -48,14 +115,31 @@
 	return ret;
 }
 
+static void clk_recalculate_rate(struct clk *c)
+{
+	u64 rate;
+
+	if (!c->parent)
+		return;
+
+	rate = c->parent->rate;
+
+	if (c->mul != 0 && c->div != 0) {
+		rate = rate * c->mul;
+		do_div(rate, c->div);
+	}
+
+	if (rate > c->max_rate)
+		pr_warn("clocks: Set clock %s to rate %llu, max is %lu\n",
+			c->name, rate, c->max_rate);
+
+	c->rate = rate;
+}
+
 int clk_reparent(struct clk *c, struct clk *parent)
 {
 	pr_debug("%s: %s\n", __func__, c->name);
-	if (c->refcnt && c->parent)
-		clk_disable_locked(c->parent);
 	c->parent = parent;
-	if (c->refcnt && c->parent)
-		clk_enable_locked(c->parent);
 	list_del(&c->sibling);
 	list_add_tail(&c->sibling, &parent->children);
 	return 0;
@@ -67,8 +151,7 @@
 	pr_debug("%s: %s\n", __func__, c->name);
 	list_for_each_entry(clkp, &c->children, sibling) {
 		pr_debug("   %s\n", clkp->name);
-		if (clkp->ops->recalculate_rate)
-			clkp->ops->recalculate_rate(clkp);
+		clk_recalculate_rate(clkp);
 		propagate_rate(clkp);
 	}
 }
@@ -77,6 +160,8 @@
 {
 	unsigned long flags;
 
+	pr_debug("%s: %s\n", __func__, c->name);
+
 	spin_lock_irqsave(&clock_lock, flags);
 
 	INIT_LIST_HEAD(&c->children);
@@ -85,6 +170,8 @@
 	if (c->ops && c->ops->init)
 		c->ops->init(c);
 
+	clk_recalculate_rate(c);
+
 	list_add(&c->node, &clocks);
 
 	if (c->parent)
@@ -122,13 +209,38 @@
 	return 0;
 }
 
+int clk_enable_cansleep(struct clk *c)
+{
+	int ret;
+	unsigned long flags;
+
+	mutex_lock(&dvfs_lock);
+
+	if (clk_is_dvfs(c) && c->refcnt > 0)
+		dvfs_set_rate(c->dvfs, c->rate);
+
+	spin_lock_irqsave(&clock_lock, flags);
+	ret = clk_enable_locked(c);
+	spin_unlock_irqrestore(&clock_lock, flags);
+
+	mutex_unlock(&dvfs_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(clk_enable_cansleep);
+
 int clk_enable(struct clk *c)
 {
 	int ret;
 	unsigned long flags;
+
+	if (clk_is_dvfs(c))
+		BUG();
+
 	spin_lock_irqsave(&clock_lock, flags);
 	ret = clk_enable_locked(c);
 	spin_unlock_irqrestore(&clock_lock, flags);
+
 	return ret;
 }
 EXPORT_SYMBOL(clk_enable);
@@ -152,9 +264,30 @@
 	c->refcnt--;
 }
 
+void clk_disable_cansleep(struct clk *c)
+{
+	unsigned long flags;
+
+	mutex_lock(&dvfs_lock);
+
+	spin_lock_irqsave(&clock_lock, flags);
+	clk_disable_locked(c);
+	spin_unlock_irqrestore(&clock_lock, flags);
+
+	if (clk_is_dvfs(c) && c->refcnt == 0)
+		dvfs_set_rate(c->dvfs, c->rate);
+
+	mutex_unlock(&dvfs_lock);
+}
+EXPORT_SYMBOL(clk_disable_cansleep);
+
 void clk_disable(struct clk *c)
 {
 	unsigned long flags;
+
+	if (clk_is_dvfs(c))
+		BUG();
+
 	spin_lock_irqsave(&clock_lock, flags);
 	clk_disable_locked(c);
 	spin_unlock_irqrestore(&clock_lock, flags);
@@ -175,6 +308,8 @@
 	if (ret)
 		return ret;
 
+	clk_recalculate_rate(c);
+
 	propagate_rate(c);
 
 	return 0;
@@ -197,22 +332,69 @@
 }
 EXPORT_SYMBOL(clk_get_parent);
 
+int clk_set_rate_locked(struct clk *c, unsigned long rate)
+{
+	int ret;
+
+	if (rate > c->max_rate)
+		rate = c->max_rate;
+
+	if (!c->ops || !c->ops->set_rate)
+		return -ENOSYS;
+
+	ret = c->ops->set_rate(c, rate);
+
+	if (ret)
+		return ret;
+
+	clk_recalculate_rate(c);
+
+	propagate_rate(c);
+
+	return 0;
+}
+
+int clk_set_rate_cansleep(struct clk *c, unsigned long rate)
+{
+	int ret = 0;
+	unsigned long flags;
+
+	pr_debug("%s: %s\n", __func__, c->name);
+
+	mutex_lock(&dvfs_lock);
+
+	if (rate > c->rate)
+		ret = dvfs_set_rate(c->dvfs, rate);
+	if (ret)
+		goto out;
+
+	spin_lock_irqsave(&clock_lock, flags);
+	ret = clk_set_rate_locked(c, rate);
+	spin_unlock_irqrestore(&clock_lock, flags);
+
+	if (ret)
+		goto out;
+
+	ret = dvfs_set_rate(c->dvfs, rate);
+
+out:
+	mutex_unlock(&dvfs_lock);
+	return ret;
+}
+EXPORT_SYMBOL(clk_set_rate_cansleep);
+
 int clk_set_rate(struct clk *c, unsigned long rate)
 {
 	int ret = 0;
 	unsigned long flags;
 
-	spin_lock_irqsave(&clock_lock, flags);
-
 	pr_debug("%s: %s\n", __func__, c->name);
 
-	if (c->ops && c->ops->set_rate)
-		ret = c->ops->set_rate(c, rate);
-	else
-		ret = -ENOSYS;
+	if (clk_is_dvfs(c))
+		BUG();
 
-	propagate_rate(c);
-
+	spin_lock_irqsave(&clock_lock, flags);
+	ret = clk_set_rate_locked(c, rate);
 	spin_unlock_irqrestore(&clock_lock, flags);
 
 	return ret;
@@ -235,6 +417,20 @@
 }
 EXPORT_SYMBOL(clk_get_rate);
 
+long clk_round_rate(struct clk *c, unsigned long rate)
+{
+	pr_debug("%s: %s\n", __func__, c->name);
+
+	if (!c->ops || !c->ops->round_rate)
+		return -ENOSYS;
+
+	if (rate > c->max_rate)
+		rate = c->max_rate;
+
+	return c->ops->round_rate(c, rate);
+}
+EXPORT_SYMBOL(clk_round_rate);
+
 static int tegra_clk_init_one_from_table(struct tegra_clk_init_table *table)
 {
 	struct clk *c;
@@ -308,13 +504,28 @@
 }
 EXPORT_SYMBOL(tegra_periph_reset_assert);
 
-int __init tegra_init_clock(void)
+void __init tegra_init_clock(void)
 {
 	tegra2_init_clocks();
+}
+
+int __init tegra_init_dvfs(void)
+{
+	struct clk *c, *safe;
+
+	mutex_lock(&dvfs_lock);
+
+	list_for_each_entry_safe(c, safe, &clocks, node)
+		if (c->dvfs)
+			dvfs_init(c);
+
+	mutex_unlock(&dvfs_lock);
 
 	return 0;
 }
 
+late_initcall(tegra_init_dvfs);
+
 #ifdef CONFIG_DEBUG_FS
 static struct dentry *clk_debugfs_root;
 
@@ -324,7 +535,7 @@
 	struct clk *child;
 	struct clk *safe;
 	const char *state = "uninit";
-	char div[5] = {0};
+	char div[8] = {0};
 
 	if (c->state == ON)
 		state = "on";
@@ -332,16 +543,26 @@
 		state = "off";
 
 	if (c->mul != 0 && c->div != 0) {
-		BUG_ON(c->mul > 2);
-		if (c->mul > c->div)
-			snprintf(div, sizeof(div), "x%d", c->mul / c->div);
-		else
+		if (c->mul > c->div) {
+			int mul = c->mul / c->div;
+			int mul2 = (c->mul * 10 / c->div) % 10;
+			int mul3 = (c->mul * 10) % c->div;
+			if (mul2 == 0 && mul3 == 0)
+				snprintf(div, sizeof(div), "x%d", mul);
+			else if (mul3 == 0)
+				snprintf(div, sizeof(div), "x%d.%d", mul, mul2);
+			else
+				snprintf(div, sizeof(div), "x%d.%d..", mul, mul2);
+		} else {
 			snprintf(div, sizeof(div), "%d%s", c->div / c->mul,
 				(c->div % c->mul) ? ".5" : "");
+		}
 	}
 
-	seq_printf(s, "%*s%-*s %-6s %-3d %-5s %-10lu\n",
-		level * 3 + 1, c->set ? "" : "*",
+	seq_printf(s, "%*s%c%c%-*s %-6s %-3d %-8s %-10lu\n",
+		level * 3 + 1, "",
+		c->rate > c->max_rate ? '!' : ' ',
+		!c->set ? '*' : ' ',
 		30 - level * 3, c->name,
 		state, c->refcnt, div, c->rate);
 	list_for_each_entry_safe(child, safe, &c->children, sibling) {
@@ -353,8 +574,8 @@
 {
 	struct clk *c;
 	unsigned long flags;
-	seq_printf(s, " clock                          state  ref div   rate      \n");
-	seq_printf(s, "-----------------------------------------------------------\n");
+	seq_printf(s, "   clock                          state  ref div      rate\n");
+	seq_printf(s, "--------------------------------------------------------------\n");
 	spin_lock_irqsave(&clock_lock, flags);
 	list_for_each_entry(c, &clocks, node)
 		if (c->parent == NULL)
diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h
index af7c70e..94fd859 100644
--- a/arch/arm/mach-tegra/clock.h
+++ b/arch/arm/mach-tegra/clock.h
@@ -27,18 +27,43 @@
 #define DIV_U71			(1 << 1)
 #define DIV_U71_FIXED		(1 << 2)
 #define DIV_2			(1 << 3)
-#define PLL_FIXED		(1 << 4)
-#define PLL_HAS_CPCON		(1 << 5)
-#define MUX			(1 << 6)
-#define PLLD			(1 << 7)
-#define PERIPH_NO_RESET		(1 << 8)
-#define PERIPH_NO_ENB		(1 << 9)
-#define PERIPH_EMC_ENB		(1 << 10)
-#define PERIPH_MANUAL_RESET	(1 << 11)
-#define PLL_ALT_MISC_REG	(1 << 12)
+#define DIV_U16			(1 << 4)
+#define PLL_FIXED		(1 << 5)
+#define PLL_HAS_CPCON		(1 << 6)
+#define MUX			(1 << 7)
+#define PLLD			(1 << 8)
+#define PERIPH_NO_RESET		(1 << 9)
+#define PERIPH_NO_ENB		(1 << 10)
+#define PERIPH_EMC_ENB		(1 << 11)
+#define PERIPH_MANUAL_RESET	(1 << 12)
+#define PLL_ALT_MISC_REG	(1 << 13)
+#define PLLU			(1 << 14)
 #define ENABLE_ON_INIT		(1 << 28)
 
 struct clk;
+struct regulator;
+
+struct dvfs_table {
+	unsigned long rate;
+	int millivolts;
+};
+
+struct dvfs_process_id_table {
+	int process_id;
+	struct dvfs_table *table;
+};
+
+
+struct dvfs {
+	struct regulator *reg;
+	struct dvfs_table *table;
+	int max_millivolts;
+
+	int process_id_table_length;
+	const char *reg_id;
+	bool cpu;
+	struct dvfs_process_id_table process_id_table[];
+};
 
 struct clk_mux_sel {
 	struct clk	*input;
@@ -58,12 +83,9 @@
 	void		(*init)(struct clk *);
 	int		(*enable)(struct clk *);
 	void		(*disable)(struct clk *);
-	void		(*recalc)(struct clk *);
 	int		(*set_parent)(struct clk *, struct clk *);
 	int		(*set_rate)(struct clk *, unsigned long);
-	unsigned long	(*get_rate)(struct clk *);
 	long		(*round_rate)(struct clk *, unsigned long);
-	unsigned long	(*recalculate_rate)(struct clk *);
 };
 
 enum clk_state {
@@ -85,6 +107,7 @@
 	struct clk			*parent;
 	struct clk_lookup		lookup;
 	unsigned long			rate;
+	unsigned long			max_rate;
 	u32				flags;
 	u32				refcnt;
 	const char			*name;
@@ -103,10 +126,6 @@
 	unsigned long			cf_max;
 	unsigned long			vco_min;
 	unsigned long			vco_max;
-	u32				m;
-	u32				n;
-	u32				p;
-	u32				cpcon;
 	const struct clk_pll_table	*pll_table;
 
 	/* DIV */
@@ -117,6 +136,12 @@
 	const struct clk_mux_sel	*inputs;
 	u32				sel;
 	u32				reg_mask;
+
+	/* Virtual cpu clock */
+	struct clk			*main;
+	struct clk			*backup;
+
+	struct dvfs			*dvfs;
 };
 
 
@@ -141,6 +166,7 @@
 void clk_disable_locked(struct clk *c);
 int clk_enable_locked(struct clk *c);
 int clk_set_parent_locked(struct clk *c, struct clk *parent);
+int clk_set_rate_locked(struct clk *c, unsigned long rate);
 int clk_reparent(struct clk *c, struct clk *parent);
 void tegra_clk_init_from_table(struct tegra_clk_init_table *table);
 
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
index 039a514..7c91e2b 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -19,13 +19,17 @@
 
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
 
 #include <asm/hardware/cache-l2x0.h>
 
 #include <mach/iomap.h>
+#include <mach/dma.h>
 
 #include "board.h"
 #include "clock.h"
+#include "fuse.h"
 
 static __initdata struct tegra_clk_init_table common_clk_init_table[] = {
 	/* name		parent		rate		enabled */
@@ -35,8 +39,8 @@
 	{ "pll_p_out2",	"pll_p",	48000000,	true },
 	{ "pll_p_out3",	"pll_p",	72000000,	true },
 	{ "pll_p_out4",	"pll_p",	108000000,	true },
-	{ "sys",	"pll_p_out4",	108000000,	true },
-	{ "hclk",	"sys",		108000000,	true },
+	{ "sclk",	"pll_p_out4",	108000000,	true },
+	{ "hclk",	"sclk",		108000000,	true },
 	{ "pclk",	"hclk",		54000000,	true },
 	{ NULL,		NULL,		0,		0},
 };
@@ -51,11 +55,16 @@
 
 	l2x0_init(p, 0x6C080001, 0x8200c3fe);
 #endif
+
 }
 
 void __init tegra_common_init(void)
 {
+	tegra_init_fuse();
 	tegra_init_clock();
 	tegra_clk_init_from_table(common_clk_init_table);
 	tegra_init_cache();
+#ifdef CONFIG_TEGRA_SYSTEM_DMA
+	tegra_dma_init();
+#endif
 }
diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c
new file mode 100644
index 0000000..fea5719
--- /dev/null
+++ b/arch/arm/mach-tegra/cpu-tegra.c
@@ -0,0 +1,185 @@
+/*
+ * arch/arm/mach-tegra/cpu-tegra.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@google.com>
+ *	Based on arch/arm/plat-omap/cpu-omap.c, (C) 2005 Nokia Corporation
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/cpufreq.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+
+#include <mach/hardware.h>
+#include <mach/clk.h>
+
+/* Frequency table index must be sequential starting at 0 */
+static struct cpufreq_frequency_table freq_table[] = {
+	{ 0, 312000 },
+	{ 1, 456000 },
+	{ 2, 608000 },
+	{ 3, 760000 },
+	{ 4, 816000 },
+	{ 5, 912000 },
+	{ 6, 1000000 },
+	{ 7, CPUFREQ_TABLE_END },
+};
+
+#define NUM_CPUS	2
+
+static struct clk *cpu_clk;
+
+static unsigned long target_cpu_speed[NUM_CPUS];
+
+int tegra_verify_speed(struct cpufreq_policy *policy)
+{
+	return cpufreq_frequency_table_verify(policy, freq_table);
+}
+
+unsigned int tegra_getspeed(unsigned int cpu)
+{
+	unsigned long rate;
+
+	if (cpu >= NUM_CPUS)
+		return 0;
+
+	rate = clk_get_rate(cpu_clk) / 1000;
+	return rate;
+}
+
+static int tegra_update_cpu_speed(void)
+{
+	int i;
+	unsigned long rate = 0;
+	int ret = 0;
+	struct cpufreq_freqs freqs;
+
+	for_each_online_cpu(i)
+		rate = max(rate, target_cpu_speed[i]);
+
+	freqs.old = tegra_getspeed(0);
+	freqs.new = rate;
+
+	if (freqs.old == freqs.new)
+		return ret;
+
+	for_each_online_cpu(freqs.cpu)
+		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+#ifdef CONFIG_CPU_FREQ_DEBUG
+	printk(KERN_DEBUG "cpufreq-tegra: transition: %u --> %u\n",
+	       freqs.old, freqs.new);
+#endif
+
+	ret = clk_set_rate_cansleep(cpu_clk, freqs.new * 1000);
+	if (ret) {
+		pr_err("cpu-tegra: Failed to set cpu frequency to %d kHz\n",
+			freqs.new);
+		return ret;
+	}
+
+	for_each_online_cpu(freqs.cpu)
+		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+	return 0;
+}
+
+static int tegra_target(struct cpufreq_policy *policy,
+		       unsigned int target_freq,
+		       unsigned int relation)
+{
+	int idx;
+	unsigned int freq;
+
+	cpufreq_frequency_table_target(policy, freq_table, target_freq,
+		relation, &idx);
+
+	freq = freq_table[idx].frequency;
+
+	target_cpu_speed[policy->cpu] = freq;
+
+	return tegra_update_cpu_speed();
+}
+
+static int tegra_cpu_init(struct cpufreq_policy *policy)
+{
+	if (policy->cpu >= NUM_CPUS)
+		return -EINVAL;
+
+	cpu_clk = clk_get_sys(NULL, "cpu");
+	if (IS_ERR(cpu_clk))
+		return PTR_ERR(cpu_clk);
+
+	cpufreq_frequency_table_cpuinfo(policy, freq_table);
+	cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
+	policy->cur = tegra_getspeed(policy->cpu);
+	target_cpu_speed[policy->cpu] = policy->cur;
+
+	/* FIXME: what's the actual transition time? */
+	policy->cpuinfo.transition_latency = 300 * 1000;
+
+	policy->shared_type = CPUFREQ_SHARED_TYPE_ALL;
+	cpumask_copy(policy->related_cpus, cpu_possible_mask);
+
+	return 0;
+}
+
+static int tegra_cpu_exit(struct cpufreq_policy *policy)
+{
+	cpufreq_frequency_table_cpuinfo(policy, freq_table);
+	clk_put(cpu_clk);
+	return 0;
+}
+
+static struct freq_attr *tegra_cpufreq_attr[] = {
+	&cpufreq_freq_attr_scaling_available_freqs,
+	NULL,
+};
+
+static struct cpufreq_driver tegra_cpufreq_driver = {
+	.verify		= tegra_verify_speed,
+	.target		= tegra_target,
+	.get		= tegra_getspeed,
+	.init		= tegra_cpu_init,
+	.exit		= tegra_cpu_exit,
+	.name		= "tegra",
+	.attr		= tegra_cpufreq_attr,
+};
+
+static int __init tegra_cpufreq_init(void)
+{
+	return cpufreq_register_driver(&tegra_cpufreq_driver);
+}
+
+static void __exit tegra_cpufreq_exit(void)
+{
+        cpufreq_unregister_driver(&tegra_cpufreq_driver);
+}
+
+
+MODULE_AUTHOR("Colin Cross <ccross@android.com>");
+MODULE_DESCRIPTION("cpufreq driver for Nvidia Tegra2");
+MODULE_LICENSE("GPL");
+module_init(tegra_cpufreq_init);
+module_exit(tegra_cpufreq_exit);
diff --git a/arch/arm/mach-tegra/dma.c b/arch/arm/mach-tegra/dma.c
new file mode 100644
index 0000000..edda6ec
--- /dev/null
+++ b/arch/arm/mach-tegra/dma.c
@@ -0,0 +1,752 @@
+/*
+ * arch/arm/mach-tegra/dma.c
+ *
+ * System DMA driver for NVIDIA Tegra SoCs
+ *
+ * Copyright (c) 2008-2009, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/err.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <mach/dma.h>
+#include <mach/irqs.h>
+#include <mach/iomap.h>
+
+#define APB_DMA_GEN				0x000
+#define GEN_ENABLE				(1<<31)
+
+#define APB_DMA_CNTRL				0x010
+
+#define APB_DMA_IRQ_MASK			0x01c
+
+#define APB_DMA_IRQ_MASK_SET			0x020
+
+#define APB_DMA_CHAN_CSR			0x000
+#define CSR_ENB					(1<<31)
+#define CSR_IE_EOC				(1<<30)
+#define CSR_HOLD				(1<<29)
+#define CSR_DIR					(1<<28)
+#define CSR_ONCE				(1<<27)
+#define CSR_FLOW				(1<<21)
+#define CSR_REQ_SEL_SHIFT			16
+#define CSR_REQ_SEL_MASK			(0x1F<<CSR_REQ_SEL_SHIFT)
+#define CSR_REQ_SEL_INVALID			(31<<CSR_REQ_SEL_SHIFT)
+#define CSR_WCOUNT_SHIFT			2
+#define CSR_WCOUNT_MASK				0xFFFC
+
+#define APB_DMA_CHAN_STA				0x004
+#define STA_BUSY				(1<<31)
+#define STA_ISE_EOC				(1<<30)
+#define STA_HALT				(1<<29)
+#define STA_PING_PONG				(1<<28)
+#define STA_COUNT_SHIFT				2
+#define STA_COUNT_MASK				0xFFFC
+
+#define APB_DMA_CHAN_AHB_PTR				0x010
+
+#define APB_DMA_CHAN_AHB_SEQ				0x014
+#define AHB_SEQ_INTR_ENB			(1<<31)
+#define AHB_SEQ_BUS_WIDTH_SHIFT			28
+#define AHB_SEQ_BUS_WIDTH_MASK			(0x7<<AHB_SEQ_BUS_WIDTH_SHIFT)
+#define AHB_SEQ_BUS_WIDTH_8			(0<<AHB_SEQ_BUS_WIDTH_SHIFT)
+#define AHB_SEQ_BUS_WIDTH_16			(1<<AHB_SEQ_BUS_WIDTH_SHIFT)
+#define AHB_SEQ_BUS_WIDTH_32			(2<<AHB_SEQ_BUS_WIDTH_SHIFT)
+#define AHB_SEQ_BUS_WIDTH_64			(3<<AHB_SEQ_BUS_WIDTH_SHIFT)
+#define AHB_SEQ_BUS_WIDTH_128			(4<<AHB_SEQ_BUS_WIDTH_SHIFT)
+#define AHB_SEQ_DATA_SWAP			(1<<27)
+#define AHB_SEQ_BURST_MASK			(0x7<<24)
+#define AHB_SEQ_BURST_1				(4<<24)
+#define AHB_SEQ_BURST_4				(5<<24)
+#define AHB_SEQ_BURST_8				(6<<24)
+#define AHB_SEQ_DBL_BUF				(1<<19)
+#define AHB_SEQ_WRAP_SHIFT			16
+#define AHB_SEQ_WRAP_MASK			(0x7<<AHB_SEQ_WRAP_SHIFT)
+
+#define APB_DMA_CHAN_APB_PTR				0x018
+
+#define APB_DMA_CHAN_APB_SEQ				0x01c
+#define APB_SEQ_BUS_WIDTH_SHIFT			28
+#define APB_SEQ_BUS_WIDTH_MASK			(0x7<<APB_SEQ_BUS_WIDTH_SHIFT)
+#define APB_SEQ_BUS_WIDTH_8			(0<<APB_SEQ_BUS_WIDTH_SHIFT)
+#define APB_SEQ_BUS_WIDTH_16			(1<<APB_SEQ_BUS_WIDTH_SHIFT)
+#define APB_SEQ_BUS_WIDTH_32			(2<<APB_SEQ_BUS_WIDTH_SHIFT)
+#define APB_SEQ_BUS_WIDTH_64			(3<<APB_SEQ_BUS_WIDTH_SHIFT)
+#define APB_SEQ_BUS_WIDTH_128			(4<<APB_SEQ_BUS_WIDTH_SHIFT)
+#define APB_SEQ_DATA_SWAP			(1<<27)
+#define APB_SEQ_WRAP_SHIFT			16
+#define APB_SEQ_WRAP_MASK			(0x7<<APB_SEQ_WRAP_SHIFT)
+
+#define TEGRA_SYSTEM_DMA_CH_NR			16
+#define TEGRA_SYSTEM_DMA_AVP_CH_NUM		4
+#define TEGRA_SYSTEM_DMA_CH_MIN			0
+#define TEGRA_SYSTEM_DMA_CH_MAX	\
+	(TEGRA_SYSTEM_DMA_CH_NR - TEGRA_SYSTEM_DMA_AVP_CH_NUM - 1)
+
+#define NV_DMA_MAX_TRASFER_SIZE 0x10000
+
+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};
+
+const unsigned int bus_width_table[5] = {8, 16, 32, 64, 128};
+
+#define TEGRA_DMA_NAME_SIZE 16
+struct tegra_dma_channel {
+	struct list_head	list;
+	int			id;
+	spinlock_t		lock;
+	char			name[TEGRA_DMA_NAME_SIZE];
+	void  __iomem		*addr;
+	int			mode;
+	int			irq;
+
+	/* Register shadow */
+	u32			csr;
+	u32			ahb_seq;
+	u32			ahb_ptr;
+	u32			apb_seq;
+	u32			apb_ptr;
+};
+
+#define  NV_DMA_MAX_CHANNELS  32
+
+static DECLARE_BITMAP(channel_usage, NV_DMA_MAX_CHANNELS);
+static struct tegra_dma_channel dma_channels[NV_DMA_MAX_CHANNELS];
+
+static void tegra_dma_update_hw(struct tegra_dma_channel *ch,
+	struct tegra_dma_req *req);
+static void tegra_dma_update_hw_partial(struct tegra_dma_channel *ch,
+	struct tegra_dma_req *req);
+static void tegra_dma_init_hw(struct tegra_dma_channel *ch);
+static void tegra_dma_stop(struct tegra_dma_channel *ch);
+
+void tegra_dma_flush(struct tegra_dma_channel *ch)
+{
+}
+EXPORT_SYMBOL(tegra_dma_flush);
+
+void tegra_dma_dequeue(struct tegra_dma_channel *ch)
+{
+	struct tegra_dma_req *req;
+
+	req = list_entry(ch->list.next, typeof(*req), node);
+
+	tegra_dma_dequeue_req(ch, req);
+	return;
+}
+
+void tegra_dma_stop(struct tegra_dma_channel *ch)
+{
+	unsigned int csr;
+	unsigned int status;
+
+	csr = ch->csr;
+	csr &= ~CSR_IE_EOC;
+	writel(csr, ch->addr + APB_DMA_CHAN_CSR);
+
+	csr &= ~CSR_ENB;
+	writel(csr, ch->addr + APB_DMA_CHAN_CSR);
+
+	status = readl(ch->addr + APB_DMA_CHAN_STA);
+	if (status & STA_ISE_EOC)
+		writel(status, ch->addr + APB_DMA_CHAN_STA);
+}
+
+int tegra_dma_cancel(struct tegra_dma_channel *ch)
+{
+	unsigned int csr;
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&ch->lock, irq_flags);
+	while (!list_empty(&ch->list))
+		list_del(ch->list.next);
+
+	csr = ch->csr;
+	csr &= ~CSR_REQ_SEL_MASK;
+	csr |= CSR_REQ_SEL_INVALID;
+
+	/* Set the enable as that is not shadowed */
+	csr |= CSR_ENB;
+	writel(csr, ch->addr + APB_DMA_CHAN_CSR);
+
+	tegra_dma_stop(ch);
+
+	spin_unlock_irqrestore(&ch->lock, irq_flags);
+	return 0;
+}
+
+int tegra_dma_dequeue_req(struct tegra_dma_channel *ch,
+	struct tegra_dma_req *_req)
+{
+	unsigned int csr;
+	unsigned int status;
+	struct tegra_dma_req *req = NULL;
+	int found = 0;
+	unsigned long irq_flags;
+	int to_transfer;
+	int req_transfer_count;
+
+	spin_lock_irqsave(&ch->lock, irq_flags);
+	list_for_each_entry(req, &ch->list, node) {
+		if (req == _req) {
+			list_del(&req->node);
+			found = 1;
+			break;
+		}
+	}
+	if (!found) {
+		spin_unlock_irqrestore(&ch->lock, irq_flags);
+		return 0;
+	}
+
+	/* STOP the DMA and get the transfer count.
+	 * Getting the transfer count is tricky.
+	 *  - Change the source selector to invalid to stop the DMA from
+	 *    FIFO to memory.
+	 *  - Read the status register to know the number of pending
+	 *    bytes to be transfered.
+	 *  - Finally stop or program the DMA to the next buffer in the
+	 *    list.
+	 */
+	csr = ch->csr;
+	csr &= ~CSR_REQ_SEL_MASK;
+	csr |= CSR_REQ_SEL_INVALID;
+
+	/* Set the enable as that is not shadowed */
+	csr |= CSR_ENB;
+	writel(csr, ch->addr + APB_DMA_CHAN_CSR);
+
+	/* Get the transfer count */
+	status = readl(ch->addr + APB_DMA_CHAN_STA);
+	to_transfer = (status & STA_COUNT_MASK) >> STA_COUNT_SHIFT;
+	req_transfer_count = (ch->csr & CSR_WCOUNT_MASK) >> CSR_WCOUNT_SHIFT;
+	req_transfer_count += 1;
+	to_transfer += 1;
+
+	req->bytes_transferred = req_transfer_count;
+
+	if (status & STA_BUSY)
+		req->bytes_transferred -= to_transfer;
+
+	/* In continous transfer mode, DMA only tracks the count of the
+	 * half DMA buffer. So, if the DMA already finished half the DMA
+	 * then add the half buffer to the completed count.
+	 *
+	 *	FIXME: There can be a race here. What if the req to
+	 *	dequue happens at the same time as the DMA just moved to
+	 *	the new buffer and SW didn't yet received the interrupt?
+	 */
+	if (ch->mode & TEGRA_DMA_MODE_CONTINOUS)
+		if (req->buffer_status == TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL)
+			req->bytes_transferred += req_transfer_count;
+
+	req->bytes_transferred *= 4;
+
+	tegra_dma_stop(ch);
+	if (!list_empty(&ch->list)) {
+		/* if the list is not empty, queue the next request */
+		struct tegra_dma_req *next_req;
+		next_req = list_entry(ch->list.next,
+			typeof(*next_req), node);
+		tegra_dma_update_hw(ch, next_req);
+	}
+	req->status = -TEGRA_DMA_REQ_ERROR_ABORTED;
+
+	spin_unlock_irqrestore(&ch->lock, irq_flags);
+
+	/* Callback should be called without any lock */
+	req->complete(req);
+	return 0;
+}
+EXPORT_SYMBOL(tegra_dma_dequeue_req);
+
+bool tegra_dma_is_empty(struct tegra_dma_channel *ch)
+{
+	unsigned long irq_flags;
+	bool is_empty;
+
+	spin_lock_irqsave(&ch->lock, irq_flags);
+	if (list_empty(&ch->list))
+		is_empty = true;
+	else
+		is_empty = false;
+	spin_unlock_irqrestore(&ch->lock, irq_flags);
+	return is_empty;
+}
+EXPORT_SYMBOL(tegra_dma_is_empty);
+
+bool tegra_dma_is_req_inflight(struct tegra_dma_channel *ch,
+	struct tegra_dma_req *_req)
+{
+	unsigned long irq_flags;
+	struct tegra_dma_req *req;
+
+	spin_lock_irqsave(&ch->lock, irq_flags);
+	list_for_each_entry(req, &ch->list, node) {
+		if (req == _req) {
+			spin_unlock_irqrestore(&ch->lock, irq_flags);
+			return true;
+		}
+	}
+	spin_unlock_irqrestore(&ch->lock, irq_flags);
+	return false;
+}
+EXPORT_SYMBOL(tegra_dma_is_req_inflight);
+
+int tegra_dma_enqueue_req(struct tegra_dma_channel *ch,
+	struct tegra_dma_req *req)
+{
+	unsigned long irq_flags;
+	int start_dma = 0;
+
+	if (req->size > NV_DMA_MAX_TRASFER_SIZE ||
+		req->source_addr & 0x3 || req->dest_addr & 0x3) {
+		pr_err("Invalid DMA request for channel %d\n", ch->id);
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&ch->lock, irq_flags);
+
+	req->bytes_transferred = 0;
+	req->status = 0;
+	req->buffer_status = 0;
+	if (list_empty(&ch->list))
+		start_dma = 1;
+
+	list_add_tail(&req->node, &ch->list);
+
+	if (start_dma)
+		tegra_dma_update_hw(ch, req);
+
+	spin_unlock_irqrestore(&ch->lock, irq_flags);
+
+	return 0;
+}
+EXPORT_SYMBOL(tegra_dma_enqueue_req);
+
+struct tegra_dma_channel *tegra_dma_allocate_channel(int mode)
+{
+	int channel;
+	struct tegra_dma_channel *ch;
+
+	/* first channel is the shared channel */
+	if (mode & TEGRA_DMA_SHARED) {
+		channel = TEGRA_SYSTEM_DMA_CH_MIN;
+	} else {
+		channel = find_first_zero_bit(channel_usage,
+			ARRAY_SIZE(dma_channels));
+		if (channel >= ARRAY_SIZE(dma_channels))
+			return NULL;
+	}
+	__set_bit(channel, channel_usage);
+	ch = &dma_channels[channel];
+	ch->mode = mode;
+	return ch;
+}
+EXPORT_SYMBOL(tegra_dma_allocate_channel);
+
+void tegra_dma_free_channel(struct tegra_dma_channel *ch)
+{
+	if (ch->mode & TEGRA_DMA_SHARED)
+		return;
+	tegra_dma_cancel(ch);
+	__clear_bit(ch->id, channel_usage);
+}
+EXPORT_SYMBOL(tegra_dma_free_channel);
+
+static void tegra_dma_update_hw_partial(struct tegra_dma_channel *ch,
+	struct tegra_dma_req *req)
+{
+	if (req->to_memory) {
+		ch->apb_ptr = req->source_addr;
+		ch->ahb_ptr = req->dest_addr;
+	} else {
+		ch->apb_ptr = req->dest_addr;
+		ch->ahb_ptr = req->source_addr;
+	}
+	writel(ch->apb_ptr, ch->addr + APB_DMA_CHAN_APB_PTR);
+	writel(ch->ahb_ptr, ch->addr + APB_DMA_CHAN_AHB_PTR);
+
+	req->status = TEGRA_DMA_REQ_INFLIGHT;
+	return;
+}
+
+static void tegra_dma_update_hw(struct tegra_dma_channel *ch,
+	struct tegra_dma_req *req)
+{
+	int ahb_addr_wrap;
+	int apb_addr_wrap;
+	int ahb_bus_width;
+	int apb_bus_width;
+	int index;
+	unsigned long csr;
+
+
+	ch->csr |= CSR_FLOW;
+	ch->csr &= ~CSR_REQ_SEL_MASK;
+	ch->csr |= req->req_sel << CSR_REQ_SEL_SHIFT;
+	ch->ahb_seq &= ~AHB_SEQ_BURST_MASK;
+	ch->ahb_seq |= AHB_SEQ_BURST_1;
+
+	/* One shot mode is always single buffered,
+	 * continuous mode is always double buffered
+	 * */
+	if (ch->mode & TEGRA_DMA_MODE_ONESHOT) {
+		ch->csr |= CSR_ONCE;
+		ch->ahb_seq &= ~AHB_SEQ_DBL_BUF;
+		ch->csr &= ~CSR_WCOUNT_MASK;
+		ch->csr |= ((req->size>>2) - 1) << CSR_WCOUNT_SHIFT;
+	} else {
+		ch->csr &= ~CSR_ONCE;
+		ch->ahb_seq |= AHB_SEQ_DBL_BUF;
+
+		/* In double buffered mode, we set the size to half the
+		 * requested size and interrupt when half the buffer
+		 * is full */
+		ch->csr &= ~CSR_WCOUNT_MASK;
+		ch->csr |= ((req->size>>3) - 1) << CSR_WCOUNT_SHIFT;
+	}
+
+	if (req->to_memory) {
+		ch->csr &= ~CSR_DIR;
+		ch->apb_ptr = req->source_addr;
+		ch->ahb_ptr = req->dest_addr;
+
+		apb_addr_wrap = req->source_wrap;
+		ahb_addr_wrap = req->dest_wrap;
+		apb_bus_width = req->source_bus_width;
+		ahb_bus_width = req->dest_bus_width;
+
+	} else {
+		ch->csr |= CSR_DIR;
+		ch->apb_ptr = req->dest_addr;
+		ch->ahb_ptr = req->source_addr;
+
+		apb_addr_wrap = req->dest_wrap;
+		ahb_addr_wrap = req->source_wrap;
+		apb_bus_width = req->dest_bus_width;
+		ahb_bus_width = req->source_bus_width;
+	}
+
+	apb_addr_wrap >>= 2;
+	ahb_addr_wrap >>= 2;
+
+	/* set address wrap for APB size */
+	index = 0;
+	do  {
+		if (apb_addr_wrap_table[index] == apb_addr_wrap)
+			break;
+		index++;
+	} while (index < ARRAY_SIZE(apb_addr_wrap_table));
+	BUG_ON(index == ARRAY_SIZE(apb_addr_wrap_table));
+	ch->apb_seq &= ~APB_SEQ_WRAP_MASK;
+	ch->apb_seq |= index << APB_SEQ_WRAP_SHIFT;
+
+	/* set address wrap for AHB size */
+	index = 0;
+	do  {
+		if (ahb_addr_wrap_table[index] == ahb_addr_wrap)
+			break;
+		index++;
+	} while (index < ARRAY_SIZE(ahb_addr_wrap_table));
+	BUG_ON(index == ARRAY_SIZE(ahb_addr_wrap_table));
+	ch->ahb_seq &= ~AHB_SEQ_WRAP_MASK;
+	ch->ahb_seq |= index << AHB_SEQ_WRAP_SHIFT;
+
+	for (index = 0; index < ARRAY_SIZE(bus_width_table); index++) {
+		if (bus_width_table[index] == ahb_bus_width)
+			break;
+	}
+	BUG_ON(index == ARRAY_SIZE(bus_width_table));
+	ch->ahb_seq &= ~AHB_SEQ_BUS_WIDTH_MASK;
+	ch->ahb_seq |= index << AHB_SEQ_BUS_WIDTH_SHIFT;
+
+	for (index = 0; index < ARRAY_SIZE(bus_width_table); index++) {
+		if (bus_width_table[index] == apb_bus_width)
+			break;
+	}
+	BUG_ON(index == ARRAY_SIZE(bus_width_table));
+	ch->apb_seq &= ~APB_SEQ_BUS_WIDTH_MASK;
+	ch->apb_seq |= index << APB_SEQ_BUS_WIDTH_SHIFT;
+
+	ch->csr |= CSR_IE_EOC;
+
+	/* update hw registers with the shadow */
+	writel(ch->csr, ch->addr + APB_DMA_CHAN_CSR);
+	writel(ch->apb_seq, ch->addr + APB_DMA_CHAN_APB_SEQ);
+	writel(ch->apb_ptr, ch->addr + APB_DMA_CHAN_APB_PTR);
+	writel(ch->ahb_seq, ch->addr + APB_DMA_CHAN_AHB_SEQ);
+	writel(ch->ahb_ptr, ch->addr + APB_DMA_CHAN_AHB_PTR);
+
+	csr = ch->csr | CSR_ENB;
+	writel(csr, ch->addr + APB_DMA_CHAN_CSR);
+
+	req->status = TEGRA_DMA_REQ_INFLIGHT;
+}
+
+static void tegra_dma_init_hw(struct tegra_dma_channel *ch)
+{
+	/* One shot with an interrupt to CPU after transfer */
+	ch->csr = CSR_ONCE | CSR_IE_EOC;
+	ch->ahb_seq = AHB_SEQ_BUS_WIDTH_32 | AHB_SEQ_INTR_ENB;
+	ch->apb_seq = APB_SEQ_BUS_WIDTH_32 | 1 << APB_SEQ_WRAP_SHIFT;
+}
+
+static void handle_oneshot_dma(struct tegra_dma_channel *ch)
+{
+	struct tegra_dma_req *req;
+
+	spin_lock(&ch->lock);
+	if (list_empty(&ch->list)) {
+		spin_unlock(&ch->lock);
+		return;
+	}
+
+	req = list_entry(ch->list.next, typeof(*req), node);
+	if (req) {
+		int bytes_transferred;
+
+		bytes_transferred =
+			(ch->csr & CSR_WCOUNT_MASK) >> CSR_WCOUNT_SHIFT;
+		bytes_transferred += 1;
+		bytes_transferred <<= 2;
+
+		list_del(&req->node);
+		req->bytes_transferred = bytes_transferred;
+		req->status = TEGRA_DMA_REQ_SUCCESS;
+
+		spin_unlock(&ch->lock);
+		/* Callback should be called without any lock */
+		pr_debug("%s: transferred %d bytes\n", __func__,
+			req->bytes_transferred);
+		req->complete(req);
+		spin_lock(&ch->lock);
+	}
+
+	if (!list_empty(&ch->list)) {
+		req = list_entry(ch->list.next, typeof(*req), node);
+		/* the complete function we just called may have enqueued
+		   another req, in which case dma has already started */
+		if (req->status != TEGRA_DMA_REQ_INFLIGHT)
+			tegra_dma_update_hw(ch, req);
+	}
+	spin_unlock(&ch->lock);
+}
+
+static void handle_continuous_dma(struct tegra_dma_channel *ch)
+{
+	struct tegra_dma_req *req;
+
+	spin_lock(&ch->lock);
+	if (list_empty(&ch->list)) {
+		spin_unlock(&ch->lock);
+		return;
+	}
+
+	req = list_entry(ch->list.next, typeof(*req), node);
+	if (req) {
+		if (req->buffer_status == TEGRA_DMA_REQ_BUF_STATUS_EMPTY) {
+			/* Load the next request into the hardware, if available
+			 * */
+			if (!list_is_last(&req->node, &ch->list)) {
+				struct tegra_dma_req *next_req;
+
+				next_req = list_entry(req->node.next,
+					typeof(*next_req), node);
+				tegra_dma_update_hw_partial(ch, next_req);
+			}
+			req->buffer_status = TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL;
+			req->status = TEGRA_DMA_REQ_SUCCESS;
+			/* DMA lock is NOT held when callback is called */
+			spin_unlock(&ch->lock);
+			if (likely(req->threshold))
+				req->threshold(req);
+			return;
+
+		} else if (req->buffer_status ==
+			TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL) {
+			/* Callback when the buffer is completely full (i.e on
+			 * the second  interrupt */
+			int bytes_transferred;
+
+			bytes_transferred =
+				(ch->csr & CSR_WCOUNT_MASK) >> CSR_WCOUNT_SHIFT;
+			bytes_transferred += 1;
+			bytes_transferred <<= 3;
+
+			req->buffer_status = TEGRA_DMA_REQ_BUF_STATUS_FULL;
+			req->bytes_transferred = bytes_transferred;
+			req->status = TEGRA_DMA_REQ_SUCCESS;
+			list_del(&req->node);
+
+			/* DMA lock is NOT held when callbak is called */
+			spin_unlock(&ch->lock);
+			req->complete(req);
+			return;
+
+		} else {
+			BUG();
+		}
+	}
+	spin_unlock(&ch->lock);
+}
+
+static irqreturn_t dma_isr(int irq, void *data)
+{
+	struct tegra_dma_channel *ch = data;
+	unsigned long status;
+
+	status = readl(ch->addr + APB_DMA_CHAN_STA);
+	if (status & STA_ISE_EOC)
+		writel(status, ch->addr + APB_DMA_CHAN_STA);
+	else {
+		pr_warning("Got a spurious ISR for DMA channel %d\n", ch->id);
+		return IRQ_HANDLED;
+	}
+	return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t dma_thread_fn(int irq, void *data)
+{
+	struct tegra_dma_channel *ch = data;
+
+	if (ch->mode & TEGRA_DMA_MODE_ONESHOT)
+		handle_oneshot_dma(ch);
+	else
+		handle_continuous_dma(ch);
+
+
+	return IRQ_HANDLED;
+}
+
+int __init tegra_dma_init(void)
+{
+	int ret = 0;
+	int i;
+	unsigned int irq;
+	void __iomem *addr;
+
+	addr = IO_ADDRESS(TEGRA_APB_DMA_BASE);
+	writel(GEN_ENABLE, addr + APB_DMA_GEN);
+	writel(0, addr + APB_DMA_CNTRL);
+	writel(0xFFFFFFFFul >> (31 - TEGRA_SYSTEM_DMA_CH_MAX),
+	       addr + APB_DMA_IRQ_MASK_SET);
+
+	memset(channel_usage, 0, sizeof(channel_usage));
+	memset(dma_channels, 0, sizeof(dma_channels));
+
+	/* Reserve all the channels we are not supposed to touch */
+	for (i = 0; i < TEGRA_SYSTEM_DMA_CH_MIN; i++)
+		__set_bit(i, channel_usage);
+
+	for (i = TEGRA_SYSTEM_DMA_CH_MIN; i <= TEGRA_SYSTEM_DMA_CH_MAX; i++) {
+		struct tegra_dma_channel *ch = &dma_channels[i];
+
+		__clear_bit(i, channel_usage);
+
+		ch->id = i;
+		snprintf(ch->name, TEGRA_DMA_NAME_SIZE, "dma_channel_%d", i);
+
+		ch->addr = IO_ADDRESS(TEGRA_APB_DMA_CH0_BASE +
+			TEGRA_APB_DMA_CH0_SIZE * i);
+
+		spin_lock_init(&ch->lock);
+		INIT_LIST_HEAD(&ch->list);
+		tegra_dma_init_hw(ch);
+
+		irq = INT_APB_DMA_CH0 + i;
+		ret = request_threaded_irq(irq, dma_isr, dma_thread_fn, 0,
+			dma_channels[i].name, ch);
+		if (ret) {
+			pr_err("Failed to register IRQ %d for DMA %d\n",
+				irq, i);
+			goto fail;
+		}
+		ch->irq = irq;
+	}
+	/* mark the shared channel allocated */
+	__set_bit(TEGRA_SYSTEM_DMA_CH_MIN, channel_usage);
+
+	for (i = TEGRA_SYSTEM_DMA_CH_MAX+1; i < NV_DMA_MAX_CHANNELS; i++)
+		__set_bit(i, channel_usage);
+
+	return ret;
+fail:
+	writel(0, addr + APB_DMA_GEN);
+	for (i = TEGRA_SYSTEM_DMA_CH_MIN; i <= TEGRA_SYSTEM_DMA_CH_MAX; i++) {
+		struct tegra_dma_channel *ch = &dma_channels[i];
+		if (ch->irq)
+			free_irq(ch->irq, ch);
+	}
+	return ret;
+}
+
+#ifdef CONFIG_PM
+static u32 apb_dma[5*TEGRA_SYSTEM_DMA_CH_NR + 3];
+
+void tegra_dma_suspend(void)
+{
+	void __iomem *addr = IO_ADDRESS(TEGRA_APB_DMA_BASE);
+	u32 *ctx = apb_dma;
+	int i;
+
+	*ctx++ = readl(addr + APB_DMA_GEN);
+	*ctx++ = readl(addr + APB_DMA_CNTRL);
+	*ctx++ = readl(addr + APB_DMA_IRQ_MASK);
+
+	for (i = 0; i < TEGRA_SYSTEM_DMA_CH_NR; i++) {
+		addr = IO_ADDRESS(TEGRA_APB_DMA_CH0_BASE +
+				  TEGRA_APB_DMA_CH0_SIZE * i);
+
+		*ctx++ = readl(addr + APB_DMA_CHAN_CSR);
+		*ctx++ = readl(addr + APB_DMA_CHAN_AHB_PTR);
+		*ctx++ = readl(addr + APB_DMA_CHAN_AHB_SEQ);
+		*ctx++ = readl(addr + APB_DMA_CHAN_APB_PTR);
+		*ctx++ = readl(addr + APB_DMA_CHAN_APB_SEQ);
+	}
+}
+
+void tegra_dma_resume(void)
+{
+	void __iomem *addr = IO_ADDRESS(TEGRA_APB_DMA_BASE);
+	u32 *ctx = apb_dma;
+	int i;
+
+	writel(*ctx++, addr + APB_DMA_GEN);
+	writel(*ctx++, addr + APB_DMA_CNTRL);
+	writel(*ctx++, addr + APB_DMA_IRQ_MASK);
+
+	for (i = 0; i < TEGRA_SYSTEM_DMA_CH_NR; i++) {
+		addr = IO_ADDRESS(TEGRA_APB_DMA_CH0_BASE +
+				  TEGRA_APB_DMA_CH0_SIZE * i);
+
+		writel(*ctx++, addr + APB_DMA_CHAN_CSR);
+		writel(*ctx++, addr + APB_DMA_CHAN_AHB_PTR);
+		writel(*ctx++, addr + APB_DMA_CHAN_AHB_SEQ);
+		writel(*ctx++, addr + APB_DMA_CHAN_APB_PTR);
+		writel(*ctx++, addr + APB_DMA_CHAN_APB_SEQ);
+	}
+}
+
+#endif
diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c
new file mode 100644
index 0000000..1fa26d9
--- /dev/null
+++ b/arch/arm/mach-tegra/fuse.c
@@ -0,0 +1,84 @@
+/*
+ * arch/arm/mach-tegra/fuse.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+#include <mach/iomap.h>
+
+#include "fuse.h"
+
+#define FUSE_UID_LOW		0x108
+#define FUSE_UID_HIGH		0x10c
+#define FUSE_SKU_INFO		0x110
+#define FUSE_SPARE_BIT		0x200
+
+static inline u32 fuse_readl(unsigned long offset)
+{
+	return readl(IO_TO_VIRT(TEGRA_FUSE_BASE + offset));
+}
+
+static inline void fuse_writel(u32 value, unsigned long offset)
+{
+	writel(value, IO_TO_VIRT(TEGRA_FUSE_BASE + offset));
+}
+
+void tegra_init_fuse(void)
+{
+	u32 reg = readl(IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48));
+	reg |= 1 << 28;
+	writel(reg, IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48));
+
+	pr_info("Tegra SKU: %d CPU Process: %d Core Process: %d\n",
+		tegra_sku_id(), tegra_cpu_process_id(),
+		tegra_core_process_id());
+}
+
+unsigned long long tegra_chip_uid(void)
+{
+	unsigned long long lo, hi;
+
+	lo = fuse_readl(FUSE_UID_LOW);
+	hi = fuse_readl(FUSE_UID_HIGH);
+	return (hi << 32ull) | lo;
+}
+
+int tegra_sku_id(void)
+{
+	int sku_id;
+	u32 reg = fuse_readl(FUSE_SKU_INFO);
+	sku_id = reg & 0xFF;
+	return sku_id;
+}
+
+int tegra_cpu_process_id(void)
+{
+	int cpu_process_id;
+	u32 reg = fuse_readl(FUSE_SPARE_BIT);
+	cpu_process_id = (reg >> 6) & 3;
+	return cpu_process_id;
+}
+
+int tegra_core_process_id(void)
+{
+	int core_process_id;
+	u32 reg = fuse_readl(FUSE_SPARE_BIT);
+	core_process_id = (reg >> 12) & 3;
+	return core_process_id;
+}
diff --git a/arch/arm/mach-tegra/fuse.h b/arch/arm/mach-tegra/fuse.h
new file mode 100644
index 0000000..584b2e2
--- /dev/null
+++ b/arch/arm/mach-tegra/fuse.h
@@ -0,0 +1,24 @@
+/*
+ * arch/arm/mach-tegra/fuse.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+unsigned long long tegra_chip_uid(void);
+int tegra_sku_id(void);
+int tegra_cpu_process_id(void);
+int tegra_core_process_id(void);
+void tegra_init_fuse(void);
diff --git a/arch/arm/mach-tegra/gpio.c b/arch/arm/mach-tegra/gpio.c
index fe78fba..0775265 100644
--- a/arch/arm/mach-tegra/gpio.c
+++ b/arch/arm/mach-tegra/gpio.c
@@ -19,6 +19,7 @@
 
 #include <linux/init.h>
 #include <linux/irq.h>
+#include <linux/interrupt.h>
 
 #include <linux/io.h>
 #include <linux/gpio.h>
@@ -60,6 +61,13 @@
 	int bank;
 	int irq;
 	spinlock_t lvl_lock[4];
+#ifdef CONFIG_PM
+	u32 cnf[4];
+	u32 out[4];
+	u32 oe[4];
+	u32 int_enb[4];
+	u32 int_lvl[4];
+#endif
 };
 
 
@@ -131,7 +139,7 @@
 	.direction_output	= tegra_gpio_direction_output,
 	.set			= tegra_gpio_set,
 	.base			= 0,
-	.ngpio			= ARCH_NR_GPIOS,
+	.ngpio			= TEGRA_NR_GPIOS,
 };
 
 static void tegra_gpio_irq_ack(unsigned int irq)
@@ -244,6 +252,76 @@
 
 }
 
+#ifdef CONFIG_PM
+void tegra_gpio_resume(void)
+{
+	unsigned long flags;
+	int b, p, i;
+
+	local_irq_save(flags);
+
+	for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) {
+		struct tegra_gpio_bank *bank = &tegra_gpio_banks[b];
+
+		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));
+		}
+	}
+
+	local_irq_restore(flags);
+
+	for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) {
+		struct irq_desc *desc = irq_to_desc(i);
+		if (!desc || (desc->status & IRQ_WAKEUP))
+			continue;
+		enable_irq(i);
+	}
+}
+
+void tegra_gpio_suspend(void)
+{
+	unsigned long flags;
+	int b, p, i;
+
+	for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) {
+		struct irq_desc *desc = irq_to_desc(i);
+		if (!desc)
+			continue;
+		if (desc->status & IRQ_WAKEUP) {
+			int gpio = i - INT_GPIO_BASE;
+			pr_debug("gpio %d.%d is wakeup\n", gpio/8, gpio&7);
+			continue;
+		}
+		disable_irq(i);
+	}
+
+	local_irq_save(flags);
+	for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) {
+		struct tegra_gpio_bank *bank = &tegra_gpio_banks[b];
+
+		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));
+		}
+	}
+	local_irq_restore(flags);
+}
+
+static int tegra_gpio_wake_enable(unsigned int irq, unsigned int enable)
+{
+	struct tegra_gpio_bank *bank = get_irq_chip_data(irq);
+	return set_irq_wake(bank->irq, enable);
+}
+#endif
 
 static struct irq_chip tegra_gpio_irq_chip = {
 	.name		= "GPIO",
@@ -251,6 +329,9 @@
 	.mask		= tegra_gpio_irq_mask,
 	.unmask		= tegra_gpio_irq_unmask,
 	.set_type	= tegra_gpio_irq_set_type,
+#ifdef CONFIG_PM
+	.set_wake	= tegra_gpio_wake_enable,
+#endif
 };
 
 
@@ -274,7 +355,7 @@
 
 	gpiochip_add(&tegra_gpio_chip);
 
-	for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + ARCH_NR_GPIOS); i++) {
+	for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) {
 		bank = &tegra_gpio_banks[GPIO_BANK(irq_to_gpio(i))];
 
 		lockdep_set_class(&irq_desc[i].lock, &gpio_lock_class);
@@ -312,15 +393,16 @@
 	for (i = 0; i < 7; i++) {
 		for (j = 0; j < 4; j++) {
 			int gpio = tegra_gpio_compose(i, j, 0);
-			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)));
+			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)));
 		}
 	}
 	return 0;
diff --git a/arch/arm/mach-tegra/include/mach/clk.h b/arch/arm/mach-tegra/include/mach/clk.h
index 2896f25..d772395 100644
--- a/arch/arm/mach-tegra/include/mach/clk.h
+++ b/arch/arm/mach-tegra/include/mach/clk.h
@@ -23,4 +23,9 @@
 void tegra_periph_reset_deassert(struct clk *c);
 void tegra_periph_reset_assert(struct clk *c);
 
+int clk_enable_cansleep(struct clk *clk);
+void clk_disable_cansleep(struct clk *clk);
+int clk_set_rate_cansleep(struct clk *clk, unsigned long rate);
+int clk_set_parent_cansleep(struct clk *clk, struct clk *parent);
+
 #endif
diff --git a/arch/arm/mach-tegra/include/mach/dma.h b/arch/arm/mach-tegra/include/mach/dma.h
new file mode 100644
index 0000000..39011bd
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/dma.h
@@ -0,0 +1,155 @@
+/*
+ * arch/arm/mach-tegra/include/mach/dma.h
+ *
+ * Copyright (c) 2008-2009, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __MACH_TEGRA_DMA_H
+#define __MACH_TEGRA_DMA_H
+
+#include <linux/list.h>
+
+#if defined(CONFIG_TEGRA_SYSTEM_DMA)
+
+struct tegra_dma_req;
+struct tegra_dma_channel;
+
+#define TEGRA_DMA_REQ_SEL_CNTR			0
+#define TEGRA_DMA_REQ_SEL_I2S_2			1
+#define TEGRA_DMA_REQ_SEL_I2S_1			2
+#define TEGRA_DMA_REQ_SEL_SPD_I			3
+#define TEGRA_DMA_REQ_SEL_UI_I			4
+#define TEGRA_DMA_REQ_SEL_MIPI			5
+#define TEGRA_DMA_REQ_SEL_I2S2_2		6
+#define TEGRA_DMA_REQ_SEL_I2S2_1		7
+#define TEGRA_DMA_REQ_SEL_UARTA			8
+#define TEGRA_DMA_REQ_SEL_UARTB			9
+#define TEGRA_DMA_REQ_SEL_UARTC			10
+#define TEGRA_DMA_REQ_SEL_SPI			11
+#define TEGRA_DMA_REQ_SEL_AC97			12
+#define TEGRA_DMA_REQ_SEL_ACMODEM		13
+#define TEGRA_DMA_REQ_SEL_SL4B			14
+#define TEGRA_DMA_REQ_SEL_SL2B1			15
+#define TEGRA_DMA_REQ_SEL_SL2B2			16
+#define TEGRA_DMA_REQ_SEL_SL2B3			17
+#define TEGRA_DMA_REQ_SEL_SL2B4			18
+#define TEGRA_DMA_REQ_SEL_UARTD			19
+#define TEGRA_DMA_REQ_SEL_UARTE			20
+#define TEGRA_DMA_REQ_SEL_I2C			21
+#define TEGRA_DMA_REQ_SEL_I2C2			22
+#define TEGRA_DMA_REQ_SEL_I2C3			23
+#define TEGRA_DMA_REQ_SEL_DVC_I2C		24
+#define TEGRA_DMA_REQ_SEL_OWR			25
+#define TEGRA_DMA_REQ_SEL_INVALID		31
+
+enum tegra_dma_mode {
+	TEGRA_DMA_SHARED = 1,
+	TEGRA_DMA_MODE_CONTINOUS = 2,
+	TEGRA_DMA_MODE_ONESHOT = 4,
+};
+
+enum tegra_dma_req_error {
+	TEGRA_DMA_REQ_SUCCESS = 0,
+	TEGRA_DMA_REQ_ERROR_ABORTED,
+	TEGRA_DMA_REQ_INFLIGHT,
+};
+
+enum tegra_dma_req_buff_status {
+	TEGRA_DMA_REQ_BUF_STATUS_EMPTY = 0,
+	TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL,
+	TEGRA_DMA_REQ_BUF_STATUS_FULL,
+};
+
+struct tegra_dma_req {
+	struct list_head node;
+	unsigned int modid;
+	int instance;
+
+	/* Called when the req is complete and from the DMA ISR context.
+	 * When this is called the req structure is no longer queued by
+	 * the DMA channel.
+	 *
+	 * State of the DMA depends on the number of req it has. If there are
+	 * no DMA requests queued up, then it will STOP the DMA. It there are
+	 * more requests in the DMA, then it will queue the next request.
+	 */
+	void (*complete)(struct tegra_dma_req *req);
+
+	/*  This is a called from the DMA ISR context when the DMA is still in
+	 *  progress and is actively filling same buffer.
+	 *
+	 *  In case of continous mode receive, this threshold is 1/2 the buffer
+	 *  size. In other cases, this will not even be called as there is no
+	 *  hardware support for it.
+	 *
+	 * In the case of continous mode receive, if there is next req already
+	 * queued, DMA programs the HW to use that req when this req is
+	 * completed. If there is no "next req" queued, then DMA ISR doesn't do
+	 * anything before calling this callback.
+	 *
+	 *	This is mainly used by the cases, where the clients has queued
+	 *	only one req and want to get some sort of DMA threshold
+	 *	callback to program the next buffer.
+	 *
+	 */
+	void (*threshold)(struct tegra_dma_req *req);
+
+	/* 1 to copy to memory.
+	 * 0 to copy from the memory to device FIFO */
+	int to_memory;
+
+	void *virt_addr;
+
+	unsigned long source_addr;
+	unsigned long dest_addr;
+	unsigned long dest_wrap;
+	unsigned long source_wrap;
+	unsigned long source_bus_width;
+	unsigned long dest_bus_width;
+	unsigned long req_sel;
+	unsigned int size;
+
+	/* Updated by the DMA driver on the conpletion of the request. */
+	int bytes_transferred;
+	int status;
+
+	/* DMA completion tracking information */
+	int buffer_status;
+
+	/* Client specific data */
+	void *dev;
+};
+
+int tegra_dma_enqueue_req(struct tegra_dma_channel *ch,
+	struct tegra_dma_req *req);
+int tegra_dma_dequeue_req(struct tegra_dma_channel *ch,
+	struct tegra_dma_req *req);
+void tegra_dma_dequeue(struct tegra_dma_channel *ch);
+void tegra_dma_flush(struct tegra_dma_channel *ch);
+
+bool tegra_dma_is_req_inflight(struct tegra_dma_channel *ch,
+	struct tegra_dma_req *req);
+bool tegra_dma_is_empty(struct tegra_dma_channel *ch);
+
+struct tegra_dma_channel *tegra_dma_allocate_channel(int mode);
+void tegra_dma_free_channel(struct tegra_dma_channel *ch);
+
+int __init tegra_dma_init(void);
+
+#endif
+
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/gpio.h b/arch/arm/mach-tegra/include/mach/gpio.h
index 540e822..e31f486 100644
--- a/arch/arm/mach-tegra/include/mach/gpio.h
+++ b/arch/arm/mach-tegra/include/mach/gpio.h
@@ -22,7 +22,7 @@
 
 #include <mach/irqs.h>
 
-#define ARCH_NR_GPIOS		INT_GPIO_NR
+#define TEGRA_NR_GPIOS		INT_GPIO_NR
 
 #include <asm-generic/gpio.h>
 
@@ -35,7 +35,7 @@
 
 static inline int gpio_to_irq(unsigned int gpio)
 {
-	if (gpio < ARCH_NR_GPIOS)
+	if (gpio < TEGRA_NR_GPIOS)
 		return INT_GPIO_BASE + gpio;
 	return -EINVAL;
 }
diff --git a/arch/arm/mach-tegra/include/mach/hardware.h b/arch/arm/mach-tegra/include/mach/hardware.h
index 6014edf..56e43b3 100644
--- a/arch/arm/mach-tegra/include/mach/hardware.h
+++ b/arch/arm/mach-tegra/include/mach/hardware.h
@@ -21,4 +21,8 @@
 #ifndef __MACH_TEGRA_HARDWARE_H
 #define __MACH_TEGRA_HARDWARE_H
 
+#define PCIBIOS_MIN_IO			0x1000
+#define PCIBIOS_MIN_MEM			0
+#define pcibios_assign_all_busses()	1
+
 #endif
diff --git a/arch/arm/mach-tegra/include/mach/io.h b/arch/arm/mach-tegra/include/mach/io.h
index 35edfc3..f0981b1 100644
--- a/arch/arm/mach-tegra/include/mach/io.h
+++ b/arch/arm/mach-tegra/include/mach/io.h
@@ -21,7 +21,7 @@
 #ifndef __MACH_TEGRA_IO_H
 #define __MACH_TEGRA_IO_H
 
-#define IO_SPACE_LIMIT 0xffffffff
+#define IO_SPACE_LIMIT 0xffff
 
 /* On TEGRA, many peripherals are very closely packed in
  * two 256MB io windows (that actually only use about 64KB
@@ -33,6 +33,10 @@
  *
  */
 
+#define IO_IRAM_PHYS	0x40000000
+#define IO_IRAM_VIRT	0xFE400000
+#define IO_IRAM_SIZE	SZ_256K
+
 #define IO_CPU_PHYS     0x50040000
 #define IO_CPU_VIRT     0xFE000000
 #define IO_CPU_SIZE	SZ_16K
@@ -55,6 +59,8 @@
 		IO_TO_VIRT_XLATE((n), IO_APB_PHYS, IO_APB_VIRT) :	\
 	IO_TO_VIRT_BETWEEN((n), IO_CPU_PHYS, IO_CPU_SIZE) ?		\
 		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)
 
 #ifndef __ASSEMBLER__
@@ -67,10 +73,20 @@
 
 #define IO_ADDRESS(n) ((void __iomem *) IO_TO_VIRT(n))
 
+#ifdef CONFIG_TEGRA_PCI
+extern void __iomem *tegra_pcie_io_base;
+
+static inline void __iomem *__io(unsigned long addr)
+{
+	return tegra_pcie_io_base + (addr & IO_SPACE_LIMIT);
+}
+#else
 static inline void __iomem *__io(unsigned long addr)
 {
 	return (void __iomem *)addr;
 }
+#endif
+
 #define __io(a)         __io(a)
 #define __mem_pci(a)    (a)
 
diff --git a/arch/arm/mach-tegra/include/mach/iomap.h b/arch/arm/mach-tegra/include/mach/iomap.h
index 1741f7d..44a4f4b 100644
--- a/arch/arm/mach-tegra/include/mach/iomap.h
+++ b/arch/arm/mach-tegra/include/mach/iomap.h
@@ -23,9 +23,15 @@
 
 #include <asm/sizes.h>
 
+#define TEGRA_IRAM_BASE			0x40000000
+#define TEGRA_IRAM_SIZE			SZ_256K
+
 #define TEGRA_ARM_PERIF_BASE		0x50040000
 #define TEGRA_ARM_PERIF_SIZE		SZ_8K
 
+#define TEGRA_ARM_PL310_BASE		0x50043000
+#define TEGRA_ARM_PL310_SIZE		SZ_4K
+
 #define TEGRA_ARM_INT_DIST_BASE		0x50041000
 #define TEGRA_ARM_INT_DIST_SIZE		SZ_4K
 
@@ -68,7 +74,22 @@
 #define TEGRA_FLOW_CTRL_BASE		0x60007000
 #define TEGRA_FLOW_CTRL_SIZE		20
 
-#define TEGRA_STATMON_BASE		0x6000C4000
+#define TEGRA_AHB_DMA_BASE		0x60008000
+#define TEGRA_AHB_DMA_SIZE		SZ_4K
+
+#define TEGRA_AHB_DMA_CH0_BASE		0x60009000
+#define TEGRA_AHB_DMA_CH0_SIZE		32
+
+#define TEGRA_APB_DMA_BASE		0x6000A000
+#define TEGRA_APB_DMA_SIZE		SZ_4K
+
+#define TEGRA_APB_DMA_CH0_BASE		0x6000B000
+#define TEGRA_APB_DMA_CH0_SIZE		32
+
+#define TEGRA_AHB_GIZMO_BASE		0x6000C004
+#define TEGRA_AHB_GIZMO_SIZE		0x10C
+
+#define TEGRA_STATMON_BASE		0x6000C400
 #define TEGRA_STATMON_SIZE		SZ_1K
 
 #define TEGRA_GPIO_BASE			0x6000D000
@@ -137,7 +158,7 @@
 #define TEGRA_I2C3_BASE			0x7000C500
 #define TEGRA_I2C3_SIZE			SZ_256
 
-#define TEGRA_OWR_BASE			0x7000D000
+#define TEGRA_OWR_BASE			0x7000C600
 #define TEGRA_OWR_SIZE			80
 
 #define TEGRA_DVC_BASE			0x7000D000
@@ -182,12 +203,12 @@
 #define TEGRA_USB_BASE			0xC5000000
 #define TEGRA_USB_SIZE			SZ_16K
 
-#define TEGRA_USB1_BASE			0xC5004000
-#define TEGRA_USB1_SIZE			SZ_16K
-
-#define TEGRA_USB2_BASE			0xC5008000
+#define TEGRA_USB2_BASE			0xC5004000
 #define TEGRA_USB2_SIZE			SZ_16K
 
+#define TEGRA_USB3_BASE			0xC5008000
+#define TEGRA_USB3_SIZE			SZ_16K
+
 #define TEGRA_SDMMC1_BASE		0xC8000000
 #define TEGRA_SDMMC1_SIZE		SZ_512
 
diff --git a/arch/arm/mach-tegra/include/mach/irqs.h b/arch/arm/mach-tegra/include/mach/irqs.h
index 20f640e..71bbf34 100644
--- a/arch/arm/mach-tegra/include/mach/irqs.h
+++ b/arch/arm/mach-tegra/include/mach/irqs.h
@@ -25,6 +25,7 @@
 
 #define IRQ_LOCALTIMER                  29
 
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
 /* Primary Interrupt Controller */
 #define INT_PRI_BASE			(INT_GIC_BASE + 32)
 #define INT_TMR1			(INT_PRI_BASE + 0)
@@ -169,5 +170,6 @@
 #define INT_GPIO_NR			(28 * 8)
 
 #define NR_IRQS				(INT_GPIO_BASE + INT_GPIO_NR)
+#endif
 
 #endif
diff --git a/arch/arm/mach-tegra/include/mach/legacy_irq.h b/arch/arm/mach-tegra/include/mach/legacy_irq.h
new file mode 100644
index 0000000..db1eb3d
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/legacy_irq.h
@@ -0,0 +1,31 @@
+/*
+ * arch/arm/mach-tegra/include/mach/legacy_irq.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ * Author: Colin Cross <ccross@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _ARCH_ARM_MACH_TEGRA_LEGARY_IRQ_H
+#define _ARCH_ARM_MACH_TEGRA_LEGARY_IRQ_H
+
+void tegra_legacy_mask_irq(unsigned int irq);
+void tegra_legacy_unmask_irq(unsigned int irq);
+void tegra_legacy_select_fiq(unsigned int irq, bool fiq);
+void tegra_legacy_force_irq_set(unsigned int irq);
+void tegra_legacy_force_irq_clr(unsigned int irq);
+int tegra_legacy_force_irq_status(unsigned int irq);
+void tegra_legacy_select_fiq(unsigned int irq, bool fiq);
+unsigned long tegra_legacy_vfiq(int nr);
+unsigned long tegra_legacy_class(int nr);
+
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/pinmux-t2.h b/arch/arm/mach-tegra/include/mach/pinmux-t2.h
new file mode 100644
index 0000000..e5b9d74
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/pinmux-t2.h
@@ -0,0 +1,174 @@
+/*
+ * linux/arch/arm/mach-tegra/include/mach/pinmux-t2.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MACH_TEGRA_PINMUX_T2_H
+#define __MACH_TEGRA_PINMUX_T2_H
+
+enum tegra_pingroup {
+	TEGRA_PINGROUP_ATA = 0,
+	TEGRA_PINGROUP_ATB,
+	TEGRA_PINGROUP_ATC,
+	TEGRA_PINGROUP_ATD,
+	TEGRA_PINGROUP_ATE,
+	TEGRA_PINGROUP_CDEV1,
+	TEGRA_PINGROUP_CDEV2,
+	TEGRA_PINGROUP_CRTP,
+	TEGRA_PINGROUP_CSUS,
+	TEGRA_PINGROUP_DAP1,
+	TEGRA_PINGROUP_DAP2,
+	TEGRA_PINGROUP_DAP3,
+	TEGRA_PINGROUP_DAP4,
+	TEGRA_PINGROUP_DDC,
+	TEGRA_PINGROUP_DTA,
+	TEGRA_PINGROUP_DTB,
+	TEGRA_PINGROUP_DTC,
+	TEGRA_PINGROUP_DTD,
+	TEGRA_PINGROUP_DTE,
+	TEGRA_PINGROUP_DTF,
+	TEGRA_PINGROUP_GMA,
+	TEGRA_PINGROUP_GMB,
+	TEGRA_PINGROUP_GMC,
+	TEGRA_PINGROUP_GMD,
+	TEGRA_PINGROUP_GME,
+	TEGRA_PINGROUP_GPU,
+	TEGRA_PINGROUP_GPU7,
+	TEGRA_PINGROUP_GPV,
+	TEGRA_PINGROUP_HDINT,
+	TEGRA_PINGROUP_I2CP,
+	TEGRA_PINGROUP_IRRX,
+	TEGRA_PINGROUP_IRTX,
+	TEGRA_PINGROUP_KBCA,
+	TEGRA_PINGROUP_KBCB,
+	TEGRA_PINGROUP_KBCC,
+	TEGRA_PINGROUP_KBCD,
+	TEGRA_PINGROUP_KBCE,
+	TEGRA_PINGROUP_KBCF,
+	TEGRA_PINGROUP_LCSN,
+	TEGRA_PINGROUP_LD0,
+	TEGRA_PINGROUP_LD1,
+	TEGRA_PINGROUP_LD10,
+	TEGRA_PINGROUP_LD11,
+	TEGRA_PINGROUP_LD12,
+	TEGRA_PINGROUP_LD13,
+	TEGRA_PINGROUP_LD14,
+	TEGRA_PINGROUP_LD15,
+	TEGRA_PINGROUP_LD16,
+	TEGRA_PINGROUP_LD17,
+	TEGRA_PINGROUP_LD2,
+	TEGRA_PINGROUP_LD3,
+	TEGRA_PINGROUP_LD4,
+	TEGRA_PINGROUP_LD5,
+	TEGRA_PINGROUP_LD6,
+	TEGRA_PINGROUP_LD7,
+	TEGRA_PINGROUP_LD8,
+	TEGRA_PINGROUP_LD9,
+	TEGRA_PINGROUP_LDC,
+	TEGRA_PINGROUP_LDI,
+	TEGRA_PINGROUP_LHP0,
+	TEGRA_PINGROUP_LHP1,
+	TEGRA_PINGROUP_LHP2,
+	TEGRA_PINGROUP_LHS,
+	TEGRA_PINGROUP_LM0,
+	TEGRA_PINGROUP_LM1,
+	TEGRA_PINGROUP_LPP,
+	TEGRA_PINGROUP_LPW0,
+	TEGRA_PINGROUP_LPW1,
+	TEGRA_PINGROUP_LPW2,
+	TEGRA_PINGROUP_LSC0,
+	TEGRA_PINGROUP_LSC1,
+	TEGRA_PINGROUP_LSCK,
+	TEGRA_PINGROUP_LSDA,
+	TEGRA_PINGROUP_LSDI,
+	TEGRA_PINGROUP_LSPI,
+	TEGRA_PINGROUP_LVP0,
+	TEGRA_PINGROUP_LVP1,
+	TEGRA_PINGROUP_LVS,
+	TEGRA_PINGROUP_OWC,
+	TEGRA_PINGROUP_PMC,
+	TEGRA_PINGROUP_PTA,
+	TEGRA_PINGROUP_RM,
+	TEGRA_PINGROUP_SDB,
+	TEGRA_PINGROUP_SDC,
+	TEGRA_PINGROUP_SDD,
+	TEGRA_PINGROUP_SDIO1,
+	TEGRA_PINGROUP_SLXA,
+	TEGRA_PINGROUP_SLXC,
+	TEGRA_PINGROUP_SLXD,
+	TEGRA_PINGROUP_SLXK,
+	TEGRA_PINGROUP_SPDI,
+	TEGRA_PINGROUP_SPDO,
+	TEGRA_PINGROUP_SPIA,
+	TEGRA_PINGROUP_SPIB,
+	TEGRA_PINGROUP_SPIC,
+	TEGRA_PINGROUP_SPID,
+	TEGRA_PINGROUP_SPIE,
+	TEGRA_PINGROUP_SPIF,
+	TEGRA_PINGROUP_SPIG,
+	TEGRA_PINGROUP_SPIH,
+	TEGRA_PINGROUP_UAA,
+	TEGRA_PINGROUP_UAB,
+	TEGRA_PINGROUP_UAC,
+	TEGRA_PINGROUP_UAD,
+	TEGRA_PINGROUP_UCA,
+	TEGRA_PINGROUP_UCB,
+	TEGRA_PINGROUP_UDA,
+	/* these pin groups only have pullup and pull down control */
+	TEGRA_PINGROUP_CK32,
+	TEGRA_PINGROUP_DDRC,
+	TEGRA_PINGROUP_PMCA,
+	TEGRA_PINGROUP_PMCB,
+	TEGRA_PINGROUP_PMCC,
+	TEGRA_PINGROUP_PMCD,
+	TEGRA_PINGROUP_PMCE,
+	TEGRA_PINGROUP_XM2C,
+	TEGRA_PINGROUP_XM2D,
+	TEGRA_MAX_PINGROUP,
+};
+
+enum tegra_drive_pingroup {
+	TEGRA_DRIVE_PINGROUP_AO1 = 0,
+	TEGRA_DRIVE_PINGROUP_AO2,
+	TEGRA_DRIVE_PINGROUP_AT1,
+	TEGRA_DRIVE_PINGROUP_AT2,
+	TEGRA_DRIVE_PINGROUP_CDEV1,
+	TEGRA_DRIVE_PINGROUP_CDEV2,
+	TEGRA_DRIVE_PINGROUP_CSUS,
+	TEGRA_DRIVE_PINGROUP_DAP1,
+	TEGRA_DRIVE_PINGROUP_DAP2,
+	TEGRA_DRIVE_PINGROUP_DAP3,
+	TEGRA_DRIVE_PINGROUP_DAP4,
+	TEGRA_DRIVE_PINGROUP_DBG,
+	TEGRA_DRIVE_PINGROUP_LCD1,
+	TEGRA_DRIVE_PINGROUP_LCD2,
+	TEGRA_DRIVE_PINGROUP_SDMMC2,
+	TEGRA_DRIVE_PINGROUP_SDMMC3,
+	TEGRA_DRIVE_PINGROUP_SPI,
+	TEGRA_DRIVE_PINGROUP_UAA,
+	TEGRA_DRIVE_PINGROUP_UAB,
+	TEGRA_DRIVE_PINGROUP_UART2,
+	TEGRA_DRIVE_PINGROUP_UART3,
+	TEGRA_DRIVE_PINGROUP_VI1,
+	TEGRA_DRIVE_PINGROUP_VI2,
+	TEGRA_DRIVE_PINGROUP_XM2A,
+	TEGRA_DRIVE_PINGROUP_XM2C,
+	TEGRA_DRIVE_PINGROUP_XM2D,
+	TEGRA_DRIVE_PINGROUP_XM2CLK,
+	TEGRA_DRIVE_PINGROUP_MEMCOMP,
+	TEGRA_MAX_DRIVE_PINGROUP,
+};
+
+#endif
+
diff --git a/arch/arm/mach-tegra/include/mach/pinmux.h b/arch/arm/mach-tegra/include/mach/pinmux.h
index 41c8ce5..defd877 100644
--- a/arch/arm/mach-tegra/include/mach/pinmux.h
+++ b/arch/arm/mach-tegra/include/mach/pinmux.h
@@ -17,126 +17,11 @@
 #ifndef __MACH_TEGRA_PINMUX_H
 #define __MACH_TEGRA_PINMUX_H
 
-enum tegra_pingroup {
-	TEGRA_PINGROUP_ATA = 0,
-	TEGRA_PINGROUP_ATB,
-	TEGRA_PINGROUP_ATC,
-	TEGRA_PINGROUP_ATD,
-	TEGRA_PINGROUP_ATE,
-	TEGRA_PINGROUP_CDEV1,
-	TEGRA_PINGROUP_CDEV2,
-	TEGRA_PINGROUP_CRTP,
-	TEGRA_PINGROUP_CSUS,
-	TEGRA_PINGROUP_DAP1,
-	TEGRA_PINGROUP_DAP2,
-	TEGRA_PINGROUP_DAP3,
-	TEGRA_PINGROUP_DAP4,
-	TEGRA_PINGROUP_DDC,
-	TEGRA_PINGROUP_DTA,
-	TEGRA_PINGROUP_DTB,
-	TEGRA_PINGROUP_DTC,
-	TEGRA_PINGROUP_DTD,
-	TEGRA_PINGROUP_DTE,
-	TEGRA_PINGROUP_DTF,
-	TEGRA_PINGROUP_GMA,
-	TEGRA_PINGROUP_GMB,
-	TEGRA_PINGROUP_GMC,
-	TEGRA_PINGROUP_GMD,
-	TEGRA_PINGROUP_GME,
-	TEGRA_PINGROUP_GPU,
-	TEGRA_PINGROUP_GPU7,
-	TEGRA_PINGROUP_GPV,
-	TEGRA_PINGROUP_HDINT,
-	TEGRA_PINGROUP_I2CP,
-	TEGRA_PINGROUP_IRRX,
-	TEGRA_PINGROUP_IRTX,
-	TEGRA_PINGROUP_KBCA,
-	TEGRA_PINGROUP_KBCB,
-	TEGRA_PINGROUP_KBCC,
-	TEGRA_PINGROUP_KBCD,
-	TEGRA_PINGROUP_KBCE,
-	TEGRA_PINGROUP_KBCF,
-	TEGRA_PINGROUP_LCSN,
-	TEGRA_PINGROUP_LD0,
-	TEGRA_PINGROUP_LD1,
-	TEGRA_PINGROUP_LD10,
-	TEGRA_PINGROUP_LD11,
-	TEGRA_PINGROUP_LD12,
-	TEGRA_PINGROUP_LD13,
-	TEGRA_PINGROUP_LD14,
-	TEGRA_PINGROUP_LD15,
-	TEGRA_PINGROUP_LD16,
-	TEGRA_PINGROUP_LD17,
-	TEGRA_PINGROUP_LD2,
-	TEGRA_PINGROUP_LD3,
-	TEGRA_PINGROUP_LD4,
-	TEGRA_PINGROUP_LD5,
-	TEGRA_PINGROUP_LD6,
-	TEGRA_PINGROUP_LD7,
-	TEGRA_PINGROUP_LD8,
-	TEGRA_PINGROUP_LD9,
-	TEGRA_PINGROUP_LDC,
-	TEGRA_PINGROUP_LDI,
-	TEGRA_PINGROUP_LHP0,
-	TEGRA_PINGROUP_LHP1,
-	TEGRA_PINGROUP_LHP2,
-	TEGRA_PINGROUP_LHS,
-	TEGRA_PINGROUP_LM0,
-	TEGRA_PINGROUP_LM1,
-	TEGRA_PINGROUP_LPP,
-	TEGRA_PINGROUP_LPW0,
-	TEGRA_PINGROUP_LPW1,
-	TEGRA_PINGROUP_LPW2,
-	TEGRA_PINGROUP_LSC0,
-	TEGRA_PINGROUP_LSC1,
-	TEGRA_PINGROUP_LSCK,
-	TEGRA_PINGROUP_LSDA,
-	TEGRA_PINGROUP_LSDI,
-	TEGRA_PINGROUP_LSPI,
-	TEGRA_PINGROUP_LVP0,
-	TEGRA_PINGROUP_LVP1,
-	TEGRA_PINGROUP_LVS,
-	TEGRA_PINGROUP_OWC,
-	TEGRA_PINGROUP_PMC,
-	TEGRA_PINGROUP_PTA,
-	TEGRA_PINGROUP_RM,
-	TEGRA_PINGROUP_SDB,
-	TEGRA_PINGROUP_SDC,
-	TEGRA_PINGROUP_SDD,
-	TEGRA_PINGROUP_SDIO1,
-	TEGRA_PINGROUP_SLXA,
-	TEGRA_PINGROUP_SLXC,
-	TEGRA_PINGROUP_SLXD,
-	TEGRA_PINGROUP_SLXK,
-	TEGRA_PINGROUP_SPDI,
-	TEGRA_PINGROUP_SPDO,
-	TEGRA_PINGROUP_SPIA,
-	TEGRA_PINGROUP_SPIB,
-	TEGRA_PINGROUP_SPIC,
-	TEGRA_PINGROUP_SPID,
-	TEGRA_PINGROUP_SPIE,
-	TEGRA_PINGROUP_SPIF,
-	TEGRA_PINGROUP_SPIG,
-	TEGRA_PINGROUP_SPIH,
-	TEGRA_PINGROUP_UAA,
-	TEGRA_PINGROUP_UAB,
-	TEGRA_PINGROUP_UAC,
-	TEGRA_PINGROUP_UAD,
-	TEGRA_PINGROUP_UCA,
-	TEGRA_PINGROUP_UCB,
-	TEGRA_PINGROUP_UDA,
-	/* these pin groups only have pullup and pull down control */
-	TEGRA_PINGROUP_CK32,
-	TEGRA_PINGROUP_DDRC,
-	TEGRA_PINGROUP_PMCA,
-	TEGRA_PINGROUP_PMCB,
-	TEGRA_PINGROUP_PMCC,
-	TEGRA_PINGROUP_PMCD,
-	TEGRA_PINGROUP_PMCE,
-	TEGRA_PINGROUP_XM2C,
-	TEGRA_PINGROUP_XM2D,
-	TEGRA_MAX_PINGROUP,
-};
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
+#include "pinmux-t2.h"
+#else
+#error "Undefined Tegra architecture"
+#endif
 
 enum tegra_mux_func {
 	TEGRA_MUX_RSVD = 0x8000,
@@ -205,6 +90,7 @@
 	TEGRA_MUX_VI,
 	TEGRA_MUX_VI_SENSOR_CLK,
 	TEGRA_MUX_XIO,
+	TEGRA_MUX_SAFE,
 	TEGRA_MAX_MUX,
 };
 
@@ -219,6 +105,18 @@
 	TEGRA_TRI_TRISTATE = 1,
 };
 
+enum tegra_vddio {
+	TEGRA_VDDIO_BB = 0,
+	TEGRA_VDDIO_LCD,
+	TEGRA_VDDIO_VI,
+	TEGRA_VDDIO_UART,
+	TEGRA_VDDIO_DDR,
+	TEGRA_VDDIO_NAND,
+	TEGRA_VDDIO_SYS,
+	TEGRA_VDDIO_AUDIO,
+	TEGRA_VDDIO_SD,
+};
+
 struct tegra_pingroup_config {
 	enum tegra_pingroup	pingroup;
 	enum tegra_mux_func	func;
@@ -270,38 +168,6 @@
 	TEGRA_MAX_PULL,
 };
 
-enum tegra_drive_pingroup {
-	TEGRA_DRIVE_PINGROUP_AO1 = 0,
-	TEGRA_DRIVE_PINGROUP_AO2,
-	TEGRA_DRIVE_PINGROUP_AT1,
-	TEGRA_DRIVE_PINGROUP_AT2,
-	TEGRA_DRIVE_PINGROUP_CDEV1,
-	TEGRA_DRIVE_PINGROUP_CDEV2,
-	TEGRA_DRIVE_PINGROUP_CSUS,
-	TEGRA_DRIVE_PINGROUP_DAP1,
-	TEGRA_DRIVE_PINGROUP_DAP2,
-	TEGRA_DRIVE_PINGROUP_DAP3,
-	TEGRA_DRIVE_PINGROUP_DAP4,
-	TEGRA_DRIVE_PINGROUP_DBG,
-	TEGRA_DRIVE_PINGROUP_LCD1,
-	TEGRA_DRIVE_PINGROUP_LCD2,
-	TEGRA_DRIVE_PINGROUP_SDMMC2,
-	TEGRA_DRIVE_PINGROUP_SDMMC3,
-	TEGRA_DRIVE_PINGROUP_SPI,
-	TEGRA_DRIVE_PINGROUP_UAA,
-	TEGRA_DRIVE_PINGROUP_UAB,
-	TEGRA_DRIVE_PINGROUP_UART2,
-	TEGRA_DRIVE_PINGROUP_UART3,
-	TEGRA_DRIVE_PINGROUP_VI1,
-	TEGRA_DRIVE_PINGROUP_VI2,
-	TEGRA_DRIVE_PINGROUP_XM2A,
-	TEGRA_DRIVE_PINGROUP_XM2C,
-	TEGRA_DRIVE_PINGROUP_XM2D,
-	TEGRA_DRIVE_PINGROUP_XM2CLK,
-	TEGRA_DRIVE_PINGROUP_MEMCOMP,
-	TEGRA_MAX_DRIVE_PINGROUP,
-};
-
 enum tegra_drive {
 	TEGRA_DRIVE_DIV_8 = 0,
 	TEGRA_DRIVE_DIV_4,
@@ -331,18 +197,44 @@
 	enum tegra_slew slew_falling;
 };
 
-int tegra_pinmux_set_func(enum tegra_pingroup pg, enum tegra_mux_func func);
-int tegra_pinmux_set_tristate(enum tegra_pingroup pg, enum tegra_tristate tristate);
-int tegra_pinmux_set_pullupdown(enum tegra_pingroup pg, enum tegra_pullupdown pupd);
+struct tegra_drive_pingroup_desc {
+	const char *name;
+	s16 reg;
+};
 
-void tegra_pinmux_config_pingroup(enum tegra_pingroup pingroup,
-	enum tegra_mux_func func, enum tegra_pullupdown pupd,
+struct tegra_pingroup_desc {
+	const char *name;
+	int funcs[4];
+	int func_safe;
+	int vddio;
+	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 */
+	s8 tri_bit; 	/* offset into the TRISTATE_REG_* register bit */
+	s8 mux_bit;	/* offset into the PIN_MUX_CTL_* register bit */
+	s8 pupd_bit;	/* offset into the PULL_UPDOWN_REG_* register bit */
+};
+
+extern const struct tegra_pingroup_desc tegra_soc_pingroups[];
+extern const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[];
+
+int tegra_pinmux_set_tristate(enum tegra_pingroup pg,
 	enum tegra_tristate tristate);
+int tegra_pinmux_set_pullupdown(enum tegra_pingroup pg,
+	enum tegra_pullupdown pupd);
 
-void tegra_pinmux_config_table(struct tegra_pingroup_config *config, int len);
+void tegra_pinmux_config_table(const struct tegra_pingroup_config *config,
+	int len);
 
 void tegra_drive_pinmux_config_table(struct tegra_drive_pingroup_config *config,
 	int len);
-
+void tegra_pinmux_set_safe_pinmux_table(const struct tegra_pingroup_config *config,
+	int len);
+void tegra_pinmux_config_pinmux_table(const struct tegra_pingroup_config *config,
+	int len);
+void tegra_pinmux_config_tristate_table(const struct tegra_pingroup_config *config,
+	int len, enum tegra_tristate tristate);
+void tegra_pinmux_config_pullupdown_table(const struct tegra_pingroup_config *config,
+	int len, enum tegra_pullupdown pupd);
 #endif
 
diff --git a/arch/arm/mach-tegra/io.c b/arch/arm/mach-tegra/io.c
index 9fe2c5c..31848a9 100644
--- a/arch/arm/mach-tegra/io.c
+++ b/arch/arm/mach-tegra/io.c
@@ -49,6 +49,12 @@
 		.length = IO_CPU_SIZE,
 		.type = MT_DEVICE,
 	},
+	{
+		.virtual = IO_IRAM_VIRT,
+		.pfn = __phys_to_pfn(IO_IRAM_PHYS),
+		.length = IO_IRAM_SIZE,
+		.type = MT_DEVICE,
+	},
 };
 
 void __init tegra_map_common_io(void)
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
index 1fdbe70..50a8dfb 100644
--- a/arch/arm/mach-tegra/irq.c
+++ b/arch/arm/mach-tegra/irq.c
@@ -4,6 +4,8 @@
  * Author:
  *	Colin Cross <ccross@google.com>
  *
+ * Copyright (C) 2010, NVIDIA Corporation
+ *
  * 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.
@@ -27,8 +29,143 @@
 
 #include "board.h"
 
+#define INT_SYS_NR	(INT_GPIO_BASE - INT_PRI_BASE)
+#define INT_SYS_SZ	(INT_SEC_BASE - INT_PRI_BASE)
+#define PPI_NR		((INT_SYS_NR+INT_SYS_SZ-1)/INT_SYS_SZ)
+
+#define APBDMA_IRQ_STA_CPU  0x14
+#define APBDMA_IRQ_MASK_SET 0x20
+#define APBDMA_IRQ_MASK_CLR 0x24
+
+#define ICTLR_CPU_IER		0x20
+#define ICTLR_CPU_IER_SET	0x24
+#define ICTLR_CPU_IER_CLR	0x28
+#define ICTLR_CPU_IEP_CLASS	0x2c
+#define ICTLR_COP_IER		0x30
+#define ICTLR_COP_IER_SET	0x34
+#define ICTLR_COP_IER_CLR	0x38
+#define ICTLR_COP_IEP_CLASS	0x3c
+
+static void (*gic_mask_irq)(unsigned int irq);
+static void (*gic_unmask_irq)(unsigned int irq);
+
+#define irq_to_ictlr(irq) (((irq)-32) >> 5)
+static void __iomem *tegra_ictlr_base = IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE);
+#define ictlr_to_virt(ictlr) (tegra_ictlr_base + (ictlr)*0x100)
+
+static void tegra_mask(unsigned int irq)
+{
+	void __iomem *addr = ictlr_to_virt(irq_to_ictlr(irq));
+	gic_mask_irq(irq);
+	writel(1<<(irq&31), addr+ICTLR_CPU_IER_CLR);
+}
+
+static void tegra_unmask(unsigned int irq)
+{
+	void __iomem *addr = ictlr_to_virt(irq_to_ictlr(irq));
+	gic_unmask_irq(irq);
+	writel(1<<(irq&31), addr+ICTLR_CPU_IER_SET);
+}
+
+#ifdef CONFIG_PM
+
+static int tegra_set_wake(unsigned int irq, unsigned int on)
+{
+	return 0;
+}
+#endif
+
+static struct irq_chip tegra_irq = {
+	.name		= "PPI",
+	.mask		= tegra_mask,
+	.unmask		= tegra_unmask,
+#ifdef CONFIG_PM
+	.set_wake	= tegra_set_wake,
+#endif
+};
+
 void __init tegra_init_irq(void)
 {
+	struct irq_chip *gic;
+	unsigned int i;
+
+	for (i = 0; i < PPI_NR; i++) {
+		writel(~0, ictlr_to_virt(i) + ICTLR_CPU_IER_CLR);
+		writel(0, ictlr_to_virt(i) + ICTLR_CPU_IEP_CLASS);
+	}
+
 	gic_dist_init(0, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE), 29);
 	gic_cpu_init(0, IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
+
+	gic = get_irq_chip(29);
+	gic_unmask_irq = gic->unmask;
+	gic_mask_irq = gic->mask;
+	tegra_irq.ack = gic->ack;
+#ifdef CONFIG_SMP
+	tegra_irq.set_affinity = gic->set_affinity;
+#endif
+
+	for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) {
+		set_irq_chip(i, &tegra_irq);
+		set_irq_handler(i, handle_level_irq);
+		set_irq_flags(i, IRQF_VALID);
+	}
 }
+
+#ifdef CONFIG_PM
+static u32 cop_ier[PPI_NR];
+static u32 cpu_ier[PPI_NR];
+static u32 cpu_iep[PPI_NR];
+
+void tegra_irq_suspend(void)
+{
+	unsigned long flags;
+	int i;
+
+	for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) {
+		struct irq_desc *desc = irq_to_desc(i);
+		if (!desc)
+			continue;
+		if (desc->status & IRQ_WAKEUP) {
+			pr_debug("irq %d is wakeup\n", i);
+			continue;
+		}
+		disable_irq(i);
+	}
+
+	local_irq_save(flags);
+	for (i = 0; i < PPI_NR; i++) {
+		void __iomem *ictlr = ictlr_to_virt(i);
+		cpu_ier[i] = readl(ictlr + ICTLR_CPU_IER);
+		cpu_iep[i] = readl(ictlr + ICTLR_CPU_IEP_CLASS);
+		cop_ier[i] = readl(ictlr + ICTLR_COP_IER);
+		writel(~0, ictlr + ICTLR_COP_IER_CLR);
+	}
+	local_irq_restore(flags);
+}
+
+void tegra_irq_resume(void)
+{
+	unsigned long flags;
+	int i;
+
+	local_irq_save(flags);
+	for (i = 0; i < PPI_NR; i++) {
+		void __iomem *ictlr = ictlr_to_virt(i);
+		writel(cpu_iep[i], ictlr + ICTLR_CPU_IEP_CLASS);
+		writel(~0ul, ictlr + ICTLR_CPU_IER_CLR);
+		writel(cpu_ier[i], ictlr + ICTLR_CPU_IER_SET);
+		writel(0, ictlr + ICTLR_COP_IEP_CLASS);
+		writel(~0ul, ictlr + ICTLR_COP_IER_CLR);
+		writel(cop_ier[i], ictlr + ICTLR_COP_IER_SET);
+	}
+	local_irq_restore(flags);
+
+	for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) {
+		struct irq_desc *desc = irq_to_desc(i);
+		if (!desc || (desc->status & IRQ_WAKEUP))
+			continue;
+		enable_irq(i);
+	}
+}
+#endif
diff --git a/arch/arm/mach-tegra/legacy_irq.c b/arch/arm/mach-tegra/legacy_irq.c
new file mode 100644
index 0000000..7cc8601
--- /dev/null
+++ b/arch/arm/mach-tegra/legacy_irq.c
@@ -0,0 +1,114 @@
+/*
+ * arch/arm/mach-tegra/legacy_irq.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ * Author: Colin Cross <ccross@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <mach/iomap.h>
+#include <mach/legacy_irq.h>
+
+#define ICTLR_CPU_IER		0x20
+#define ICTLR_CPU_IER_SET	0x24
+#define ICTLR_CPU_IER_CLR	0x28
+#define ICTLR_CPU_IEP_CLASS	0x2C
+#define ICTLR_CPU_IEP_VFIQ	0x08
+#define ICTLR_CPU_IEP_FIR	0x14
+#define ICTLR_CPU_IEP_FIR_SET	0x18
+#define ICTLR_CPU_IEP_FIR_CLR	0x1c
+
+static void __iomem *ictlr_reg_base[] = {
+	IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE),
+	IO_ADDRESS(TEGRA_SECONDARY_ICTLR_BASE),
+	IO_ADDRESS(TEGRA_TERTIARY_ICTLR_BASE),
+	IO_ADDRESS(TEGRA_QUATERNARY_ICTLR_BASE),
+};
+
+/* When going into deep sleep, the CPU is powered down, taking the GIC with it
+   In order to wake, the wake interrupts need to be enabled in the legacy
+   interrupt controller. */
+void tegra_legacy_unmask_irq(unsigned int irq)
+{
+	void __iomem *base;
+	pr_debug("%s: %d\n", __func__, irq);
+
+	irq -= 32;
+	base = ictlr_reg_base[irq>>5];
+	writel(1 << (irq & 31), base + ICTLR_CPU_IER_SET);
+}
+
+void tegra_legacy_mask_irq(unsigned int irq)
+{
+	void __iomem *base;
+	pr_debug("%s: %d\n", __func__, irq);
+
+	irq -= 32;
+	base = ictlr_reg_base[irq>>5];
+	writel(1 << (irq & 31), base + ICTLR_CPU_IER_CLR);
+}
+
+void tegra_legacy_force_irq_set(unsigned int irq)
+{
+	void __iomem *base;
+	pr_debug("%s: %d\n", __func__, irq);
+
+	irq -= 32;
+	base = ictlr_reg_base[irq>>5];
+	writel(1 << (irq & 31), base + ICTLR_CPU_IEP_FIR_SET);
+}
+
+void tegra_legacy_force_irq_clr(unsigned int irq)
+{
+	void __iomem *base;
+	pr_debug("%s: %d\n", __func__, irq);
+
+	irq -= 32;
+	base = ictlr_reg_base[irq>>5];
+	writel(1 << (irq & 31), base + ICTLR_CPU_IEP_FIR_CLR);
+}
+
+int tegra_legacy_force_irq_status(unsigned int irq)
+{
+	void __iomem *base;
+	pr_debug("%s: %d\n", __func__, irq);
+
+	irq -= 32;
+	base = ictlr_reg_base[irq>>5];
+	return !!(readl(base + ICTLR_CPU_IEP_FIR) & (1 << (irq & 31)));
+}
+
+void tegra_legacy_select_fiq(unsigned int irq, bool fiq)
+{
+	void __iomem *base;
+	pr_debug("%s: %d\n", __func__, irq);
+
+	irq -= 32;
+	base = ictlr_reg_base[irq>>5];
+	writel(fiq << (irq & 31), base + ICTLR_CPU_IEP_CLASS);
+}
+
+unsigned long tegra_legacy_vfiq(int nr)
+{
+	void __iomem *base;
+	base = ictlr_reg_base[nr];
+	return readl(base + ICTLR_CPU_IEP_VFIQ);
+}
+
+unsigned long tegra_legacy_class(int nr)
+{
+	void __iomem *base;
+	base = ictlr_reg_base[nr];
+	return readl(base + ICTLR_CPU_IEP_CLASS);
+}
diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c
new file mode 100644
index 0000000..53f5fa3
--- /dev/null
+++ b/arch/arm/mach-tegra/pcie.c
@@ -0,0 +1,915 @@
+/*
+ * arch/arm/mach-tegra/pci.c
+ *
+ * PCIe host controller driver for TEGRA(2) SOCs
+ *
+ * Copyright (c) 2010, CompuLab, Ltd.
+ * Author: Mike Rapoport <mike@compulab.co.il>
+ *
+ * Based on NVIDIA PCIe driver
+ * Copyright (c) 2008-2009, NVIDIA Corporation.
+ *
+ * Bits taken from arch/arm/mach-dove/pcie.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+
+#include <asm/sizes.h>
+#include <asm/mach/pci.h>
+
+#include <mach/pinmux.h>
+#include <mach/iomap.h>
+#include <mach/clk.h>
+
+/* register definitions */
+#define AFI_OFFSET	0x3800
+#define PADS_OFFSET	0x3000
+#define RP0_OFFSET	0x0000
+#define RP1_OFFSET	0x1000
+
+#define AFI_AXI_BAR0_SZ	0x00
+#define AFI_AXI_BAR1_SZ	0x04
+#define AFI_AXI_BAR2_SZ	0x08
+#define AFI_AXI_BAR3_SZ	0x0c
+#define AFI_AXI_BAR4_SZ	0x10
+#define AFI_AXI_BAR5_SZ	0x14
+
+#define AFI_AXI_BAR0_START	0x18
+#define AFI_AXI_BAR1_START	0x1c
+#define AFI_AXI_BAR2_START	0x20
+#define AFI_AXI_BAR3_START	0x24
+#define AFI_AXI_BAR4_START	0x28
+#define AFI_AXI_BAR5_START	0x2c
+
+#define AFI_FPCI_BAR0	0x30
+#define AFI_FPCI_BAR1	0x34
+#define AFI_FPCI_BAR2	0x38
+#define AFI_FPCI_BAR3	0x3c
+#define AFI_FPCI_BAR4	0x40
+#define AFI_FPCI_BAR5	0x44
+
+#define AFI_CACHE_BAR0_SZ	0x48
+#define AFI_CACHE_BAR0_ST	0x4c
+#define AFI_CACHE_BAR1_SZ	0x50
+#define AFI_CACHE_BAR1_ST	0x54
+
+#define AFI_MSI_BAR_SZ		0x60
+#define AFI_MSI_FPCI_BAR_ST	0x64
+#define AFI_MSI_AXI_BAR_ST	0x68
+
+#define AFI_CONFIGURATION		0xac
+#define  AFI_CONFIGURATION_EN_FPCI	(1 << 0)
+
+#define AFI_FPCI_ERROR_MASKS	0xb0
+
+#define AFI_INTR_MASK		0xb4
+#define  AFI_INTR_MASK_INT_MASK	(1 << 0)
+#define  AFI_INTR_MASK_MSI_MASK	(1 << 8)
+
+#define AFI_INTR_CODE		0xb8
+#define  AFI_INTR_CODE_MASK	0xf
+#define  AFI_INTR_MASTER_ABORT	4
+#define  AFI_INTR_LEGACY	6
+
+#define AFI_INTR_SIGNATURE	0xbc
+#define AFI_SM_INTR_ENABLE	0xc4
+
+#define AFI_AFI_INTR_ENABLE		0xc8
+#define  AFI_INTR_EN_INI_SLVERR		(1 << 0)
+#define  AFI_INTR_EN_INI_DECERR		(1 << 1)
+#define  AFI_INTR_EN_TGT_SLVERR		(1 << 2)
+#define  AFI_INTR_EN_TGT_DECERR		(1 << 3)
+#define  AFI_INTR_EN_TGT_WRERR		(1 << 4)
+#define  AFI_INTR_EN_DFPCI_DECERR	(1 << 5)
+#define  AFI_INTR_EN_AXI_DECERR		(1 << 6)
+#define  AFI_INTR_EN_FPCI_TIMEOUT	(1 << 7)
+
+#define AFI_PCIE_CONFIG					0x0f8
+#define  AFI_PCIE_CONFIG_PCIEC0_DISABLE_DEVICE		(1 << 1)
+#define  AFI_PCIE_CONFIG_PCIEC1_DISABLE_DEVICE		(1 << 2)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_MASK	(0xf << 20)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_SINGLE	(0x0 << 20)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_DUAL	(0x1 << 20)
+
+#define AFI_FUSE			0x104
+#define  AFI_FUSE_PCIE_T0_GEN2_DIS	(1 << 2)
+
+#define AFI_PEX0_CTRL			0x110
+#define AFI_PEX1_CTRL			0x118
+#define  AFI_PEX_CTRL_RST		(1 << 0)
+#define  AFI_PEX_CTRL_REFCLK_EN		(1 << 3)
+
+#define RP_VEND_XP	0x00000F00
+#define  RP_VEND_XP_DL_UP	(1 << 30)
+
+#define RP_LINK_CONTROL_STATUS			0x00000090
+#define  RP_LINK_CONTROL_STATUS_LINKSTAT_MASK	0x3fff0000
+
+#define PADS_CTL_SEL		0x0000009C
+
+#define PADS_CTL		0x000000A0
+#define  PADS_CTL_IDDQ_1L	(1 << 0)
+#define  PADS_CTL_TX_DATA_EN_1L	(1 << 6)
+#define  PADS_CTL_RX_DATA_EN_1L	(1 << 10)
+
+#define PADS_PLL_CTL				0x000000B8
+#define  PADS_PLL_CTL_RST_B4SM			(1 << 1)
+#define  PADS_PLL_CTL_LOCKDET			(1 << 8)
+#define  PADS_PLL_CTL_REFCLK_MASK		(0x3 << 16)
+#define  PADS_PLL_CTL_REFCLK_INTERNAL_CML	(0 << 16)
+#define  PADS_PLL_CTL_REFCLK_INTERNAL_CMOS	(1 << 16)
+#define  PADS_PLL_CTL_REFCLK_EXTERNAL		(2 << 16)
+#define  PADS_PLL_CTL_TXCLKREF_MASK		(0x1 << 20)
+#define  PADS_PLL_CTL_TXCLKREF_DIV10		(0 << 20)
+#define  PADS_PLL_CTL_TXCLKREF_DIV5		(1 << 20)
+
+/* PMC access is required for PCIE xclk (un)clamping */
+#define PMC_SCRATCH42		0x144
+#define PMC_SCRATCH42_PCX_CLAMP	(1 << 0)
+
+static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
+
+#define pmc_writel(value, reg) \
+	__raw_writel(value, (u32)reg_pmc_base + (reg))
+#define pmc_readl(reg) \
+	__raw_readl((u32)reg_pmc_base + (reg))
+
+/*
+ * Tegra2 defines 1GB in the AXI address map for PCIe.
+ *
+ * That address space is split into different regions, with sizes and
+ * offsets as follows:
+ *
+ * 0x80000000 - 0x80003fff - PCI controller registers
+ * 0x80004000 - 0x80103fff - PCI configuration space
+ * 0x80104000 - 0x80203fff - PCI extended configuration space
+ * 0x80203fff - 0x803fffff - unused
+ * 0x80400000 - 0x8040ffff - downstream IO
+ * 0x80410000 - 0x8fffffff - unused
+ * 0x90000000 - 0x9fffffff - non-prefetchable memory
+ * 0xa0000000 - 0xbfffffff - prefetchable memory
+ */
+#define TEGRA_PCIE_BASE		0x80000000
+
+#define PCIE_REGS_SZ		SZ_16K
+#define PCIE_CFG_OFF		PCIE_REGS_SZ
+#define PCIE_CFG_SZ		SZ_1M
+#define PCIE_EXT_CFG_OFF	(PCIE_CFG_SZ + PCIE_CFG_OFF)
+#define PCIE_EXT_CFG_SZ		SZ_1M
+#define PCIE_IOMAP_SZ		(PCIE_REGS_SZ + PCIE_CFG_SZ + PCIE_EXT_CFG_SZ)
+
+#define MMIO_BASE		(TEGRA_PCIE_BASE + SZ_4M)
+#define MMIO_SIZE		SZ_64K
+#define MEM_BASE_0		(TEGRA_PCIE_BASE + SZ_256M)
+#define MEM_SIZE_0		SZ_128M
+#define MEM_BASE_1		(MEM_BASE_0 + MEM_SIZE_0)
+#define MEM_SIZE_1		SZ_128M
+#define PREFETCH_MEM_BASE_0	(MEM_BASE_1 + MEM_SIZE_1)
+#define PREFETCH_MEM_SIZE_0	SZ_128M
+#define PREFETCH_MEM_BASE_1	(PREFETCH_MEM_BASE_0 + PREFETCH_MEM_SIZE_0)
+#define PREFETCH_MEM_SIZE_1	SZ_128M
+
+#define  PCIE_CONF_BUS(b)	((b) << 16)
+#define  PCIE_CONF_DEV(d)	((d) << 11)
+#define  PCIE_CONF_FUNC(f)	((f) << 8)
+#define  PCIE_CONF_REG(r)	\
+	(((r) & ~0x3) | (((r) < 256) ? PCIE_CFG_OFF : PCIE_EXT_CFG_OFF))
+
+struct tegra_pcie_port {
+	int			index;
+	u8			root_bus_nr;
+	void __iomem		*base;
+
+	bool			link_up;
+
+	char			io_space_name[16];
+	char			mem_space_name[16];
+	char			prefetch_space_name[20];
+	struct resource		res[3];
+};
+
+struct tegra_pcie_info {
+	struct tegra_pcie_port	port[2];
+	int			num_ports;
+
+	void __iomem		*regs;
+	struct resource		res_mmio;
+
+	struct clk		*pex_clk;
+	struct clk		*afi_clk;
+	struct clk		*pcie_xclk;
+	struct clk		*pll_e;
+};
+
+static struct tegra_pcie_info tegra_pcie = {
+	.res_mmio = {
+		.name = "PCI IO",
+		.start = MMIO_BASE,
+		.end = MMIO_BASE + MMIO_SIZE - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+void __iomem *tegra_pcie_io_base;
+EXPORT_SYMBOL(tegra_pcie_io_base);
+
+static inline void afi_writel(u32 value, unsigned long offset)
+{
+	writel(value, offset + AFI_OFFSET + tegra_pcie.regs);
+}
+
+static inline u32 afi_readl(unsigned long offset)
+{
+	return readl(offset + AFI_OFFSET + tegra_pcie.regs);
+}
+
+static inline void pads_writel(u32 value, unsigned long offset)
+{
+	writel(value, offset + PADS_OFFSET + tegra_pcie.regs);
+}
+
+static inline u32 pads_readl(unsigned long offset)
+{
+	return readl(offset + PADS_OFFSET + tegra_pcie.regs);
+}
+
+static struct tegra_pcie_port *bus_to_port(int bus)
+{
+	int i;
+
+	for (i = tegra_pcie.num_ports - 1; i >= 0; i--) {
+		int rbus = tegra_pcie.port[i].root_bus_nr;
+		if (rbus != -1 && rbus == bus)
+			break;
+	}
+
+	return i >= 0 ? tegra_pcie.port + i : NULL;
+}
+
+static int tegra_pcie_read_conf(struct pci_bus *bus, unsigned int devfn,
+				int where, int size, u32 *val)
+{
+	struct tegra_pcie_port *pp = bus_to_port(bus->number);
+	void __iomem *addr;
+
+	if (pp) {
+		if (devfn != 0) {
+			*val = 0xffffffff;
+			return PCIBIOS_DEVICE_NOT_FOUND;
+		}
+
+		addr = pp->base + (where & ~0x3);
+	} else {
+		addr = tegra_pcie.regs + (PCIE_CONF_BUS(bus->number) +
+					  PCIE_CONF_DEV(PCI_SLOT(devfn)) +
+					  PCIE_CONF_FUNC(PCI_FUNC(devfn)) +
+					  PCIE_CONF_REG(where));
+	}
+
+	*val = readl(addr);
+
+	if (size == 1)
+		*val = (*val >> (8 * (where & 3))) & 0xff;
+	else if (size == 2)
+		*val = (*val >> (8 * (where & 3))) & 0xffff;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int tegra_pcie_write_conf(struct pci_bus *bus, unsigned int devfn,
+				 int where, int size, u32 val)
+{
+	struct tegra_pcie_port *pp = bus_to_port(bus->number);
+	void __iomem *addr;
+
+	u32 mask;
+	u32 tmp;
+
+	if (pp) {
+		if (devfn != 0)
+			return PCIBIOS_DEVICE_NOT_FOUND;
+
+		addr = pp->base + (where & ~0x3);
+	} else {
+		addr = tegra_pcie.regs + (PCIE_CONF_BUS(bus->number) +
+					  PCIE_CONF_DEV(PCI_SLOT(devfn)) +
+					  PCIE_CONF_FUNC(PCI_FUNC(devfn)) +
+					  PCIE_CONF_REG(where));
+	}
+
+	if (size == 4) {
+		writel(val, addr);
+		return PCIBIOS_SUCCESSFUL;
+	}
+
+	if (size == 2)
+		mask = ~(0xffff << ((where & 0x3) * 8));
+	else if (size == 1)
+		mask = ~(0xff << ((where & 0x3) * 8));
+	else
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	tmp = readl(addr) & mask;
+	tmp |= val << ((where & 0x3) * 8);
+	writel(tmp, addr);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops tegra_pcie_ops = {
+	.read	= tegra_pcie_read_conf,
+	.write	= tegra_pcie_write_conf,
+};
+
+static void __devinit tegra_pcie_fixup_bridge(struct pci_dev *dev)
+{
+	u16 reg;
+
+	if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE) {
+		pci_read_config_word(dev, PCI_COMMAND, &reg);
+		reg |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+			PCI_COMMAND_MASTER | PCI_COMMAND_SERR);
+		pci_write_config_word(dev, PCI_COMMAND, reg);
+	}
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, tegra_pcie_fixup_bridge);
+
+/* Tegra PCIE root complex wrongly reports device class */
+static void __devinit tegra_pcie_fixup_class(struct pci_dev *dev)
+{
+	dev->class = PCI_CLASS_BRIDGE_PCI << 8;
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0bf0, tegra_pcie_fixup_class);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0bf1, tegra_pcie_fixup_class);
+
+/* Tegra PCIE requires relaxed ordering */
+static void __devinit tegra_pcie_relax_enable(struct pci_dev *dev)
+{
+	u16 val16;
+	int pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+
+	if (pos <= 0) {
+		dev_err(&dev->dev, "skipping relaxed ordering fixup\n");
+		return;
+	}
+
+	pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &val16);
+	val16 |= PCI_EXP_DEVCTL_RELAX_EN;
+	pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, val16);
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, tegra_pcie_relax_enable);
+
+static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
+{
+	struct tegra_pcie_port *pp;
+
+	if (nr >= tegra_pcie.num_ports)
+		return 0;
+
+	pp = tegra_pcie.port + nr;
+	pp->root_bus_nr = sys->busnr;
+
+	/*
+	 * IORESOURCE_IO
+	 */
+	snprintf(pp->io_space_name, sizeof(pp->io_space_name),
+		 "PCIe %d I/O", pp->index);
+	pp->io_space_name[sizeof(pp->io_space_name) - 1] = 0;
+	pp->res[0].name = pp->io_space_name;
+	if (pp->index == 0) {
+		pp->res[0].start = PCIBIOS_MIN_IO;
+		pp->res[0].end = pp->res[0].start + SZ_32K - 1;
+	} else {
+		pp->res[0].start = PCIBIOS_MIN_IO + SZ_32K;
+		pp->res[0].end = IO_SPACE_LIMIT;
+	}
+	pp->res[0].flags = IORESOURCE_IO;
+	if (request_resource(&ioport_resource, &pp->res[0]))
+		panic("Request PCIe IO resource failed\n");
+	sys->resource[0] = &pp->res[0];
+
+	/*
+	 * IORESOURCE_MEM
+	 */
+	snprintf(pp->mem_space_name, sizeof(pp->mem_space_name),
+		 "PCIe %d MEM", pp->index);
+	pp->mem_space_name[sizeof(pp->mem_space_name) - 1] = 0;
+	pp->res[1].name = pp->mem_space_name;
+	if (pp->index == 0) {
+		pp->res[1].start = MEM_BASE_0;
+		pp->res[1].end = pp->res[1].start + MEM_SIZE_0 - 1;
+	} else {
+		pp->res[1].start = MEM_BASE_1;
+		pp->res[1].end = pp->res[1].start + MEM_SIZE_1 - 1;
+	}
+	pp->res[1].flags = IORESOURCE_MEM;
+	if (request_resource(&iomem_resource, &pp->res[1]))
+		panic("Request PCIe Memory resource failed\n");
+	sys->resource[1] = &pp->res[1];
+
+	/*
+	 * IORESOURCE_MEM | IORESOURCE_PREFETCH
+	 */
+	snprintf(pp->prefetch_space_name, sizeof(pp->prefetch_space_name),
+		 "PCIe %d PREFETCH MEM", pp->index);
+	pp->prefetch_space_name[sizeof(pp->prefetch_space_name) - 1] = 0;
+	pp->res[2].name = pp->prefetch_space_name;
+	if (pp->index == 0) {
+		pp->res[2].start = PREFETCH_MEM_BASE_0;
+		pp->res[2].end = pp->res[2].start + PREFETCH_MEM_SIZE_0 - 1;
+	} else {
+		pp->res[2].start = PREFETCH_MEM_BASE_1;
+		pp->res[2].end = pp->res[2].start + PREFETCH_MEM_SIZE_1 - 1;
+	}
+	pp->res[2].flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
+	if (request_resource(&iomem_resource, &pp->res[2]))
+		panic("Request PCIe Prefetch Memory resource failed\n");
+	sys->resource[2] = &pp->res[2];
+
+	return 1;
+}
+
+static int tegra_pcie_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	return INT_PCIE_INTR;
+}
+
+static struct pci_bus __init *tegra_pcie_scan_bus(int nr,
+						  struct pci_sys_data *sys)
+{
+	struct tegra_pcie_port *pp;
+
+	if (nr >= tegra_pcie.num_ports)
+		return 0;
+
+	pp = tegra_pcie.port + nr;
+	pp->root_bus_nr = sys->busnr;
+
+	return pci_scan_bus(sys->busnr, &tegra_pcie_ops, sys);
+}
+
+static struct hw_pci tegra_pcie_hw __initdata = {
+	.nr_controllers	= 2,
+	.setup		= tegra_pcie_setup,
+	.scan		= tegra_pcie_scan_bus,
+	.swizzle	= pci_std_swizzle,
+	.map_irq	= tegra_pcie_map_irq,
+};
+
+
+static irqreturn_t tegra_pcie_isr(int irq, void *arg)
+{
+	const char *err_msg[] = {
+		"Unknown",
+		"AXI slave error",
+		"AXI decode error",
+		"Target abort",
+		"Master abort",
+		"Invalid write",
+		"Response decoding error",
+		"AXI response decoding error",
+		"Transcation timeout",
+	};
+
+	u32 code, signature;
+
+	code = afi_readl(AFI_INTR_CODE) & AFI_INTR_CODE_MASK;
+	signature = afi_readl(AFI_INTR_SIGNATURE);
+	afi_writel(0, AFI_INTR_CODE);
+
+	if (code == AFI_INTR_LEGACY)
+		return IRQ_NONE;
+
+	if (code >= ARRAY_SIZE(err_msg))
+		code = 0;
+
+	/*
+	 * do not pollute kernel log with master abort reports since they
+	 * happen a lot during enumeration
+	 */
+	if (code == AFI_INTR_MASTER_ABORT)
+		pr_debug("PCIE: %s, signature: %08x\n", err_msg[code], signature);
+	else
+		pr_err("PCIE: %s, signature: %08x\n", err_msg[code], signature);
+
+	return IRQ_HANDLED;
+}
+
+static void tegra_pcie_setup_translations(void)
+{
+	u32 fpci_bar;
+	u32 size;
+	u32 axi_address;
+
+	/* Bar 0: config Bar */
+	fpci_bar = ((u32)0xfdff << 16);
+	size = PCIE_CFG_SZ;
+	axi_address = TEGRA_PCIE_BASE + PCIE_CFG_OFF;
+	afi_writel(axi_address, AFI_AXI_BAR0_START);
+	afi_writel(size >> 12, AFI_AXI_BAR0_SZ);
+	afi_writel(fpci_bar, AFI_FPCI_BAR0);
+
+	/* Bar 1: extended config Bar */
+	fpci_bar = ((u32)0xfe1 << 20);
+	size = PCIE_EXT_CFG_SZ;
+	axi_address = TEGRA_PCIE_BASE + PCIE_EXT_CFG_OFF;
+	afi_writel(axi_address, AFI_AXI_BAR1_START);
+	afi_writel(size >> 12, AFI_AXI_BAR1_SZ);
+	afi_writel(fpci_bar, AFI_FPCI_BAR1);
+
+	/* Bar 2: downstream IO bar */
+	fpci_bar = ((__u32)0xfdfc << 16);
+	size = MMIO_SIZE;
+	axi_address = MMIO_BASE;
+	afi_writel(axi_address, AFI_AXI_BAR2_START);
+	afi_writel(size >> 12, AFI_AXI_BAR2_SZ);
+	afi_writel(fpci_bar, AFI_FPCI_BAR2);
+
+	/* Bar 3: prefetchable memory BAR */
+	fpci_bar = (((PREFETCH_MEM_BASE_0 >> 12) & 0x0fffffff) << 4) | 0x1;
+	size =  PREFETCH_MEM_SIZE_0 +  PREFETCH_MEM_SIZE_1;
+	axi_address = PREFETCH_MEM_BASE_0;
+	afi_writel(axi_address, AFI_AXI_BAR3_START);
+	afi_writel(size >> 12, AFI_AXI_BAR3_SZ);
+	afi_writel(fpci_bar, AFI_FPCI_BAR3);
+
+	/* Bar 4: non prefetchable memory BAR */
+	fpci_bar = (((MEM_BASE_0 >> 12)	& 0x0FFFFFFF) << 4) | 0x1;
+	size = MEM_SIZE_0 + MEM_SIZE_1;
+	axi_address = MEM_BASE_0;
+	afi_writel(axi_address, AFI_AXI_BAR4_START);
+	afi_writel(size >> 12, AFI_AXI_BAR4_SZ);
+	afi_writel(fpci_bar, AFI_FPCI_BAR4);
+
+	/* Bar 5: NULL out the remaining BAR as it is not used */
+	fpci_bar = 0;
+	size = 0;
+	axi_address = 0;
+	afi_writel(axi_address, AFI_AXI_BAR5_START);
+	afi_writel(size >> 12, AFI_AXI_BAR5_SZ);
+	afi_writel(fpci_bar, AFI_FPCI_BAR5);
+
+	/* map all upstream transactions as uncached */
+	afi_writel(PHYS_OFFSET, AFI_CACHE_BAR0_ST);
+	afi_writel(0, AFI_CACHE_BAR0_SZ);
+	afi_writel(0, AFI_CACHE_BAR1_ST);
+	afi_writel(0, AFI_CACHE_BAR1_SZ);
+
+	/* No MSI */
+	afi_writel(0, AFI_MSI_FPCI_BAR_ST);
+	afi_writel(0, AFI_MSI_BAR_SZ);
+	afi_writel(0, AFI_MSI_AXI_BAR_ST);
+	afi_writel(0, AFI_MSI_BAR_SZ);
+}
+
+static void tegra_pcie_enable_controller(void)
+{
+	u32 val, reg;
+	int i;
+
+	/* Enable slot clock and pulse the reset signals */
+	for (i = 0, reg = AFI_PEX0_CTRL; i < 2; i++, reg += 0x8) {
+		val = afi_readl(reg) |  AFI_PEX_CTRL_REFCLK_EN;
+		afi_writel(val, reg);
+		val &= ~AFI_PEX_CTRL_RST;
+		afi_writel(val, reg);
+
+		val = afi_readl(reg) | AFI_PEX_CTRL_RST;
+		afi_writel(val, reg);
+	}
+
+	/* Enable dual controller and both ports */
+	val = afi_readl(AFI_PCIE_CONFIG);
+	val &= ~(AFI_PCIE_CONFIG_PCIEC0_DISABLE_DEVICE |
+		 AFI_PCIE_CONFIG_PCIEC1_DISABLE_DEVICE |
+		 AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_MASK);
+	val |= AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_DUAL;
+	afi_writel(val, AFI_PCIE_CONFIG);
+
+	val = afi_readl(AFI_FUSE) & ~AFI_FUSE_PCIE_T0_GEN2_DIS;
+	afi_writel(val, AFI_FUSE);
+
+	/* Initialze internal PHY, enable up to 16 PCIE lanes */
+	pads_writel(0x0, PADS_CTL_SEL);
+
+	/* override IDDQ to 1 on all 4 lanes */
+	val = pads_readl(PADS_CTL) | PADS_CTL_IDDQ_1L;
+	pads_writel(val, PADS_CTL);
+
+	/*
+	 * set up PHY PLL inputs select PLLE output as refclock,
+	 * set TX ref sel to div10 (not div5)
+	 */
+	val = pads_readl(PADS_PLL_CTL);
+	val &= ~(PADS_PLL_CTL_REFCLK_MASK | PADS_PLL_CTL_TXCLKREF_MASK);
+	val |= (PADS_PLL_CTL_REFCLK_INTERNAL_CML | PADS_PLL_CTL_TXCLKREF_DIV10);
+	pads_writel(val, PADS_PLL_CTL);
+
+	/* take PLL out of reset  */
+	val = pads_readl(PADS_PLL_CTL) | PADS_PLL_CTL_RST_B4SM;
+	pads_writel(val, PADS_PLL_CTL);
+
+	/*
+	 * Hack, set the clock voltage to the DEFAULT provided by hw folks.
+	 * This doesn't exist in the documentation
+	 */
+	pads_writel(0xfa5cfa5c, 0xc8);
+
+	/* Wait for the PLL to lock */
+	do {
+		val = pads_readl(PADS_PLL_CTL);
+	} while (!(val & PADS_PLL_CTL_LOCKDET));
+
+	/* turn off IDDQ override */
+	val = pads_readl(PADS_CTL) & ~PADS_CTL_IDDQ_1L;
+	pads_writel(val, PADS_CTL);
+
+	/* enable TX/RX data */
+	val = pads_readl(PADS_CTL);
+	val |= (PADS_CTL_TX_DATA_EN_1L | PADS_CTL_RX_DATA_EN_1L);
+	pads_writel(val, PADS_CTL);
+
+	/* Take the PCIe interface module out of reset */
+	tegra_periph_reset_deassert(tegra_pcie.pcie_xclk);
+
+	/* Finally enable PCIe */
+	val = afi_readl(AFI_CONFIGURATION) | AFI_CONFIGURATION_EN_FPCI;
+	afi_writel(val, AFI_CONFIGURATION);
+
+	val = (AFI_INTR_EN_INI_SLVERR | AFI_INTR_EN_INI_DECERR |
+	       AFI_INTR_EN_TGT_SLVERR | AFI_INTR_EN_TGT_DECERR |
+	       AFI_INTR_EN_TGT_WRERR | AFI_INTR_EN_DFPCI_DECERR);
+	afi_writel(val, AFI_AFI_INTR_ENABLE);
+	afi_writel(0xffffffff, AFI_SM_INTR_ENABLE);
+
+	/* FIXME: No MSI for now, only INT */
+	afi_writel(AFI_INTR_MASK_INT_MASK, AFI_INTR_MASK);
+
+	/* Disable all execptions */
+	afi_writel(0, AFI_FPCI_ERROR_MASKS);
+
+	return;
+}
+
+static void tegra_pcie_xclk_clamp(bool clamp)
+{
+	u32 reg;
+
+	reg = pmc_readl(PMC_SCRATCH42) & ~PMC_SCRATCH42_PCX_CLAMP;
+
+	if (clamp)
+		reg |= PMC_SCRATCH42_PCX_CLAMP;
+
+	pmc_writel(reg, PMC_SCRATCH42);
+}
+
+static int tegra_pcie_power_on(void)
+{
+	tegra_pcie_xclk_clamp(true);
+	tegra_periph_reset_assert(tegra_pcie.pcie_xclk);
+	tegra_pcie_xclk_clamp(false);
+
+	clk_enable(tegra_pcie.afi_clk);
+	clk_enable(tegra_pcie.pex_clk);
+	return clk_enable(tegra_pcie.pll_e);
+}
+
+static void tegra_pcie_power_off(void)
+{
+	tegra_periph_reset_assert(tegra_pcie.pcie_xclk);
+	tegra_periph_reset_assert(tegra_pcie.afi_clk);
+	tegra_periph_reset_assert(tegra_pcie.pex_clk);
+
+	tegra_pcie_xclk_clamp(true);
+}
+
+static int tegra_pcie_clocks_get(void)
+{
+	int err;
+
+	tegra_pcie.pex_clk = clk_get(NULL, "pex");
+	if (IS_ERR(tegra_pcie.pex_clk))
+		return PTR_ERR(tegra_pcie.pex_clk);
+
+	tegra_pcie.afi_clk = clk_get(NULL, "afi");
+	if (IS_ERR(tegra_pcie.afi_clk)) {
+		err = PTR_ERR(tegra_pcie.afi_clk);
+		goto err_afi_clk;
+	}
+
+	tegra_pcie.pcie_xclk = clk_get(NULL, "pcie_xclk");
+	if (IS_ERR(tegra_pcie.pcie_xclk)) {
+		err =  PTR_ERR(tegra_pcie.pcie_xclk);
+		goto err_pcie_xclk;
+	}
+
+	tegra_pcie.pll_e = clk_get_sys(NULL, "pll_e");
+	if (IS_ERR(tegra_pcie.pll_e)) {
+		err = PTR_ERR(tegra_pcie.pll_e);
+		goto err_pll_e;
+	}
+
+	return 0;
+
+err_pll_e:
+	clk_put(tegra_pcie.pcie_xclk);
+err_pcie_xclk:
+	clk_put(tegra_pcie.afi_clk);
+err_afi_clk:
+	clk_put(tegra_pcie.pex_clk);
+
+	return err;
+}
+
+static void tegra_pcie_clocks_put(void)
+{
+	clk_put(tegra_pcie.pll_e);
+	clk_put(tegra_pcie.pcie_xclk);
+	clk_put(tegra_pcie.afi_clk);
+	clk_put(tegra_pcie.pex_clk);
+}
+
+static int __init tegra_pcie_get_resources(void)
+{
+	struct resource *res_mmio = &tegra_pcie.res_mmio;
+	int err;
+
+	err = tegra_pcie_clocks_get();
+	if (err) {
+		pr_err("PCIE: failed to get clocks: %d\n", err);
+		return err;
+	}
+
+	err = tegra_pcie_power_on();
+	if (err) {
+		pr_err("PCIE: failed to power up: %d\n", err);
+		goto err_pwr_on;
+	}
+
+	tegra_pcie.regs = ioremap_nocache(TEGRA_PCIE_BASE, PCIE_IOMAP_SZ);
+	if (tegra_pcie.regs == NULL) {
+		pr_err("PCIE: Failed to map PCI/AFI registers\n");
+		err = -ENOMEM;
+		goto err_map_reg;
+	}
+
+	err = request_resource(&iomem_resource, res_mmio);
+	if (err) {
+		pr_err("PCIE: Failed to request resources: %d\n", err);
+		goto err_req_io;
+	}
+
+	tegra_pcie_io_base = ioremap_nocache(res_mmio->start,
+					     resource_size(res_mmio));
+	if (tegra_pcie_io_base == NULL) {
+		pr_err("PCIE: Failed to map IO\n");
+		err = -ENOMEM;
+		goto err_map_io;
+	}
+
+	err = request_irq(INT_PCIE_INTR, tegra_pcie_isr,
+			  IRQF_SHARED, "PCIE", &tegra_pcie);
+	if (err) {
+		pr_err("PCIE: Failed to register IRQ: %d\n", err);
+		goto err_irq;
+	}
+	set_irq_flags(INT_PCIE_INTR, IRQF_VALID);
+
+	return 0;
+
+err_irq:
+	iounmap(tegra_pcie_io_base);
+err_map_io:
+	release_resource(&tegra_pcie.res_mmio);
+err_req_io:
+	iounmap(tegra_pcie.regs);
+err_map_reg:
+	tegra_pcie_power_off();
+err_pwr_on:
+	tegra_pcie_clocks_put();
+
+	return err;
+}
+
+/*
+ * FIXME: If there are no PCIe cards attached, then calling this function
+ * can result in the increase of the bootup time as there are big timeout
+ * loops.
+ */
+#define TEGRA_PCIE_LINKUP_TIMEOUT	200	/* up to 1.2 seconds */
+static bool tegra_pcie_check_link(struct tegra_pcie_port *pp, int idx,
+				  u32 reset_reg)
+{
+	u32 reg;
+	int retries = 3;
+	int timeout;
+
+	do {
+		timeout = TEGRA_PCIE_LINKUP_TIMEOUT;
+		while (timeout) {
+			reg = readl(pp->base + RP_VEND_XP);
+
+			if (reg & RP_VEND_XP_DL_UP)
+				break;
+
+			mdelay(1);
+			timeout--;
+		}
+
+		if (!timeout)  {
+			pr_err("PCIE: port %d: link down, retrying\n", idx);
+			goto retry;
+		}
+
+		timeout = TEGRA_PCIE_LINKUP_TIMEOUT;
+		while (timeout) {
+			reg = readl(pp->base + RP_LINK_CONTROL_STATUS);
+
+			if (reg & 0x20000000)
+				return true;
+
+			mdelay(1);
+			timeout--;
+		}
+
+retry:
+		/* Pulse the PEX reset */
+		reg = afi_readl(reset_reg) | AFI_PEX_CTRL_RST;
+		afi_writel(reg, reset_reg);
+		mdelay(1);
+		reg = afi_readl(reset_reg) & ~AFI_PEX_CTRL_RST;
+		afi_writel(reg, reset_reg);
+
+		retries--;
+	} while (retries);
+
+	return false;
+}
+
+static void __init tegra_pcie_add_port(int index, u32 offset, u32 reset_reg)
+{
+	struct tegra_pcie_port *pp;
+
+	pp = tegra_pcie.port + tegra_pcie.num_ports;
+
+	pp->index = -1;
+	pp->base = tegra_pcie.regs + offset;
+	pp->link_up = tegra_pcie_check_link(pp, index, reset_reg);
+
+	if (!pp->link_up) {
+		pp->base = NULL;
+		printk(KERN_INFO "PCIE: port %d: link down, ignoring\n", index);
+		return;
+	}
+
+	tegra_pcie.num_ports++;
+	pp->index = index;
+	pp->root_bus_nr = -1;
+	memset(pp->res, 0, sizeof(pp->res));
+}
+
+int __init tegra_pcie_init(bool init_port0, bool init_port1)
+{
+	int err;
+
+	if (!(init_port0 || init_port1))
+		return -ENODEV;
+
+	err = tegra_pcie_get_resources();
+	if (err)
+		return err;
+
+	tegra_pcie_enable_controller();
+
+	/* setup the AFI address translations */
+	tegra_pcie_setup_translations();
+
+	if (init_port0)
+		tegra_pcie_add_port(0, RP0_OFFSET, AFI_PEX0_CTRL);
+
+	if (init_port1)
+		tegra_pcie_add_port(1, RP1_OFFSET, AFI_PEX1_CTRL);
+
+	pci_common_init(&tegra_pcie_hw);
+
+	return 0;
+}
diff --git a/arch/arm/mach-tegra/pinmux-t2-tables.c b/arch/arm/mach-tegra/pinmux-t2-tables.c
new file mode 100644
index 0000000..a6ea34e
--- /dev/null
+++ b/arch/arm/mach-tegra/pinmux-t2-tables.c
@@ -0,0 +1,260 @@
+/*
+ * linux/arch/arm/mach-tegra/pinmux-t2-tables.c
+ *
+ * Common pinmux configurations for Tegra 2 SoCs
+ *
+ * Copyright (C) 2010 NVIDIA Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <mach/iomap.h>
+#include <mach/pinmux.h>
+
+#define DRIVE_PINGROUP(pg_name, r)				\
+	[TEGRA_DRIVE_PINGROUP_ ## pg_name] = {			\
+		.name = #pg_name,				\
+		.reg = r					\
+	}
+
+const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE_PINGROUP] = {
+	DRIVE_PINGROUP(AO1,		0x868),
+	DRIVE_PINGROUP(AO2,		0x86c),
+	DRIVE_PINGROUP(AT1,		0x870),
+	DRIVE_PINGROUP(AT2,		0x874),
+	DRIVE_PINGROUP(CDEV1,		0x878),
+	DRIVE_PINGROUP(CDEV2,		0x87c),
+	DRIVE_PINGROUP(CSUS,		0x880),
+	DRIVE_PINGROUP(DAP1,		0x884),
+	DRIVE_PINGROUP(DAP2,		0x888),
+	DRIVE_PINGROUP(DAP3,		0x88c),
+	DRIVE_PINGROUP(DAP4,		0x890),
+	DRIVE_PINGROUP(DBG,		0x894),
+	DRIVE_PINGROUP(LCD1,		0x898),
+	DRIVE_PINGROUP(LCD2,		0x89c),
+	DRIVE_PINGROUP(SDMMC2,		0x8a0),
+	DRIVE_PINGROUP(SDMMC3,		0x8a4),
+	DRIVE_PINGROUP(SPI,		0x8a8),
+	DRIVE_PINGROUP(UAA,		0x8ac),
+	DRIVE_PINGROUP(UAB,		0x8b0),
+	DRIVE_PINGROUP(UART2,		0x8b4),
+	DRIVE_PINGROUP(UART3,		0x8b8),
+	DRIVE_PINGROUP(VI1,		0x8bc),
+	DRIVE_PINGROUP(VI2,		0x8c0),
+	DRIVE_PINGROUP(XM2A,		0x8c4),
+	DRIVE_PINGROUP(XM2C,		0x8c8),
+	DRIVE_PINGROUP(XM2D,		0x8cc),
+	DRIVE_PINGROUP(XM2CLK,		0x8d0),
+	DRIVE_PINGROUP(MEMCOMP,		0x8d4),
+};
+
+#define PINGROUP(pg_name, vdd, f0, f1, f2, f3, f_safe,		\
+		 tri_r, tri_b, mux_r, mux_b, pupd_r, pupd_b)	\
+	[TEGRA_PINGROUP_ ## pg_name] = {			\
+		.name = #pg_name,				\
+		.vddio = TEGRA_VDDIO_ ## vdd,			\
+		.funcs = {					\
+			TEGRA_MUX_ ## f0,			\
+			TEGRA_MUX_ ## f1,			\
+			TEGRA_MUX_ ## f2,			\
+			TEGRA_MUX_ ## f3,			\
+		},						\
+		.func_safe = TEGRA_MUX_ ## f_safe,		\
+		.tri_reg = tri_r,				\
+		.tri_bit = tri_b,				\
+		.mux_reg = mux_r,				\
+		.mux_bit = mux_b,				\
+		.pupd_reg = pupd_r,				\
+		.pupd_bit = pupd_b,				\
+	}
+
+const struct tegra_pingroup_desc tegra_soc_pingroups[TEGRA_MAX_PINGROUP] = {
+	PINGROUP(ATA,   NAND,  IDE,       NAND,      GMI,       RSVD,          IDE,       0x14, 0,  0x80, 24, 0xA0, 0),
+	PINGROUP(ATB,   NAND,  IDE,       NAND,      GMI,       SDIO4,         IDE,       0x14, 1,  0x80, 16, 0xA0, 2),
+	PINGROUP(ATC,   NAND,  IDE,       NAND,      GMI,       SDIO4,         IDE,       0x14, 2,  0x80, 22, 0xA0, 4),
+	PINGROUP(ATD,   NAND,  IDE,       NAND,      GMI,       SDIO4,         IDE,       0x14, 3,  0x80, 20, 0xA0, 6),
+	PINGROUP(ATE,   NAND,  IDE,       NAND,      GMI,       RSVD,          IDE,       0x18, 25, 0x80, 12, 0xA0, 8),
+	PINGROUP(CDEV1, AUDIO, OSC,       PLLA_OUT,  PLLM_OUT1, AUDIO_SYNC,    OSC,       0x14, 4,  0x88, 2,  0xA8, 0),
+	PINGROUP(CDEV2, AUDIO, OSC,       AHB_CLK,   APB_CLK,   PLLP_OUT4,     OSC,       0x14, 5,  0x88, 4,  0xA8, 2),
+	PINGROUP(CRTP,  LCD,   CRT,       RSVD,      RSVD,      RSVD,          RSVD,      0x20, 14, 0x98, 20, 0xA4, 24),
+	PINGROUP(CSUS,  VI,    PLLC_OUT1, PLLP_OUT2, PLLP_OUT3, VI_SENSOR_CLK, PLLC_OUT1, 0x14, 6,  0x88, 6,  0xAC, 24),
+	PINGROUP(DAP1,  AUDIO, DAP1,      RSVD,      GMI,       SDIO2,         DAP1,      0x14, 7,  0x88, 20, 0xA0, 10),
+	PINGROUP(DAP2,  AUDIO, DAP2,      TWC,       RSVD,      GMI,           DAP2,      0x14, 8,  0x88, 22, 0xA0, 12),
+	PINGROUP(DAP3,  BB,    DAP3,      RSVD,      RSVD,      RSVD,          DAP3,      0x14, 9,  0x88, 24, 0xA0, 14),
+	PINGROUP(DAP4,  UART,  DAP4,      RSVD,      GMI,       RSVD,          DAP4,      0x14, 10, 0x88, 26, 0xA0, 16),
+	PINGROUP(DDC,   LCD,   I2C2,      RSVD,      RSVD,      RSVD,          RSVD4,     0x18, 31, 0x88, 0,  0xB0, 28),
+	PINGROUP(DTA,   VI,    RSVD,      SDIO2,     VI,        RSVD,          RSVD4,     0x14, 11, 0x84, 20, 0xA0, 18),
+	PINGROUP(DTB,   VI,    RSVD,      RSVD,      VI,        SPI1,          RSVD1,     0x14, 12, 0x84, 22, 0xA0, 20),
+	PINGROUP(DTC,   VI,    RSVD,      RSVD,      VI,        RSVD,          RSVD1,     0x14, 13, 0x84, 26, 0xA0, 22),
+	PINGROUP(DTD,   VI,    RSVD,      SDIO2,     VI,        RSVD,          RSVD1,     0x14, 14, 0x84, 28, 0xA0, 24),
+	PINGROUP(DTE,   VI,    RSVD,      RSVD,      VI,        SPI1,          RSVD1,     0x14, 15, 0x84, 30, 0xA0, 26),
+	PINGROUP(DTF,   VI,    I2C3,      RSVD,      VI,        RSVD,          RSVD4,     0x20, 12, 0x98, 30, 0xA0, 28),
+	PINGROUP(GMA,   NAND,  UARTE,     SPI3,      GMI,       SDIO4,         SPI3,      0x14, 28, 0x84, 0,  0xB0, 20),
+	PINGROUP(GMB,   NAND,  IDE,       NAND,      GMI,       GMI_INT,       GMI,       0x18, 29, 0x88, 28, 0xB0, 22),
+	PINGROUP(GMC,   NAND,  UARTD,     SPI4,      GMI,       SFLASH,        SPI4,      0x14, 29, 0x84, 2,  0xB0, 24),
+	PINGROUP(GMD,   NAND,  RSVD,      NAND,      GMI,       SFLASH,        GMI,       0x18, 30, 0x88, 30, 0xB0, 26),
+	PINGROUP(GME,   NAND,  RSVD,      DAP5,      GMI,       SDIO4,         GMI,       0x18, 0,  0x8C, 0,  0xA8, 24),
+	PINGROUP(GPU,   UART,  PWM,       UARTA,     GMI,       RSVD,          RSVD4,     0x14, 16, 0x8C, 4,  0xA4, 20),
+	PINGROUP(GPU7,  SYS,   RTCK,      RSVD,      RSVD,      RSVD,          RTCK,      0x20, 11, 0x98, 28, 0xA4, 6),
+	PINGROUP(GPV,   SD,    PCIE,      RSVD,      RSVD,      RSVD,          PCIE,      0x14, 17, 0x8C, 2,  0xA0, 30),
+	PINGROUP(HDINT, LCD,   HDMI,      RSVD,      RSVD,      RSVD,          HDMI,      0x1C, 23, 0x84, 4,  0xAC, 22),
+	PINGROUP(I2CP,  SYS,   I2C,       RSVD,      RSVD,      RSVD,          RSVD4,     0x14, 18, 0x88, 8,  0xA4, 2),
+	PINGROUP(IRRX,  UART,  UARTA,     UARTB,     GMI,       SPI4,          UARTB,     0x14, 20, 0x88, 18, 0xA8, 22),
+	PINGROUP(IRTX,  UART,  UARTA,     UARTB,     GMI,       SPI4,          UARTB,     0x14, 19, 0x88, 16, 0xA8, 20),
+	PINGROUP(KBCA,  SYS,   KBC,       NAND,      SDIO2,     EMC_TEST0_DLL, KBC,       0x14, 22, 0x88, 10, 0xA4, 8),
+	PINGROUP(KBCB,  SYS,   KBC,       NAND,      SDIO2,     MIO,           KBC,       0x14, 21, 0x88, 12, 0xA4, 10),
+	PINGROUP(KBCC,  SYS,   KBC,       NAND,      TRACE,     EMC_TEST1_DLL, KBC,       0x18, 26, 0x88, 14, 0xA4, 12),
+	PINGROUP(KBCD,  SYS,   KBC,       NAND,      SDIO2,     MIO,           KBC,       0x20, 10, 0x98, 26, 0xA4, 14),
+	PINGROUP(KBCE,  SYS,   KBC,       NAND,      OWR,       RSVD,          KBC,       0x14, 26, 0x80, 28, 0xB0, 2),
+	PINGROUP(KBCF,  SYS,   KBC,       NAND,      TRACE,     MIO,           KBC,       0x14, 27, 0x80, 26, 0xB0, 0),
+	PINGROUP(LCSN,  LCD,   DISPLAYA,  DISPLAYB,  SPI3,      RSVD,          RSVD4,     0x1C, 31, 0x90, 12, 0xAC, 20),
+	PINGROUP(LD0,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 0,  0x94, 0,  0xAC, 12),
+	PINGROUP(LD1,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 1,  0x94, 2,  0xAC, 12),
+	PINGROUP(LD10,  LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 10, 0x94, 20, 0xAC, 12),
+	PINGROUP(LD11,  LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 11, 0x94, 22, 0xAC, 12),
+	PINGROUP(LD12,  LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 12, 0x94, 24, 0xAC, 12),
+	PINGROUP(LD13,  LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 13, 0x94, 26, 0xAC, 12),
+	PINGROUP(LD14,  LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 14, 0x94, 28, 0xAC, 12),
+	PINGROUP(LD15,  LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 15, 0x94, 30, 0xAC, 12),
+	PINGROUP(LD16,  LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 16, 0x98, 0,  0xAC, 12),
+	PINGROUP(LD17,  LCD,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          RSVD4,     0x1C, 17, 0x98, 2,  0xAC, 12),
+	PINGROUP(LD2,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 2,  0x94, 4,  0xAC, 12),
+	PINGROUP(LD3,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 3,  0x94, 6,  0xAC, 12),
+	PINGROUP(LD4,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 4,  0x94, 8,  0xAC, 12),
+	PINGROUP(LD5,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 5,  0x94, 10, 0xAC, 12),
+	PINGROUP(LD6,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 6,  0x94, 12, 0xAC, 12),
+	PINGROUP(LD7,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 7,  0x94, 14, 0xAC, 12),
+	PINGROUP(LD8,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 8,  0x94, 16, 0xAC, 12),
+	PINGROUP(LD9,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 9,  0x94, 18, 0xAC, 12),
+	PINGROUP(LDC,   LCD,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          RSVD4,     0x1C, 30, 0x90, 14, 0xAC, 20),
+	PINGROUP(LDI,   LCD,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          RSVD4,     0x20, 6,  0x98, 16, 0xAC, 18),
+	PINGROUP(LHP0,  LCD,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          RSVD4,     0x1C, 18, 0x98, 10, 0xAC, 16),
+	PINGROUP(LHP1,  LCD,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          RSVD4,     0x1C, 19, 0x98, 4,  0xAC, 14),
+	PINGROUP(LHP2,  LCD,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          RSVD4,     0x1C, 20, 0x98, 6,  0xAC, 14),
+	PINGROUP(LHS,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x20, 7,  0x90, 22, 0xAC, 22),
+	PINGROUP(LM0,   LCD,   DISPLAYA,  DISPLAYB,  SPI3,      RSVD,          RSVD4,     0x1C, 24, 0x90, 26, 0xAC, 22),
+	PINGROUP(LM1,   LCD,   DISPLAYA,  DISPLAYB,  RSVD,      CRT,           RSVD3,     0x1C, 25, 0x90, 28, 0xAC, 22),
+	PINGROUP(LPP,   LCD,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          RSVD4,     0x20, 8,  0x98, 14, 0xAC, 18),
+	PINGROUP(LPW0,  LCD,   DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          DISPLAYA,  0x20, 3,  0x90, 0,  0xAC, 20),
+	PINGROUP(LPW1,  LCD,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          RSVD4,     0x20, 4,  0x90, 2,  0xAC, 20),
+	PINGROUP(LPW2,  LCD,   DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          DISPLAYA,  0x20, 5,  0x90, 4,  0xAC, 20),
+	PINGROUP(LSC0,  LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 27, 0x90, 18, 0xAC, 22),
+	PINGROUP(LSC1,  LCD,   DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          DISPLAYA,  0x1C, 28, 0x90, 20, 0xAC, 20),
+	PINGROUP(LSCK,  LCD,   DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          DISPLAYA,  0x1C, 29, 0x90, 16, 0xAC, 20),
+	PINGROUP(LSDA,  LCD,   DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          DISPLAYA,  0x20, 1,  0x90, 8,  0xAC, 20),
+	PINGROUP(LSDI,  LCD,   DISPLAYA,  DISPLAYB,  SPI3,      RSVD,          DISPLAYA,  0x20, 2,  0x90, 6,  0xAC, 20),
+	PINGROUP(LSPI,  LCD,   DISPLAYA,  DISPLAYB,  XIO,       HDMI,          DISPLAYA,  0x20, 0,  0x90, 10, 0xAC, 22),
+	PINGROUP(LVP0,  LCD,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          RSVD4,     0x1C, 21, 0x90, 30, 0xAC, 22),
+	PINGROUP(LVP1,  LCD,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          RSVD4,     0x1C, 22, 0x98, 8,  0xAC, 16),
+	PINGROUP(LVS,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 26, 0x90, 24, 0xAC, 22),
+	PINGROUP(OWC,   SYS,   OWR,       RSVD,      RSVD,      RSVD,          OWR,       0x14, 31, 0x84, 8,  0xB0, 30),
+	PINGROUP(PMC,   SYS,   PWR_ON,    PWR_INTR,  RSVD,      RSVD,          PWR_ON,    0x14, 23, 0x98, 18, -1,   -1),
+	PINGROUP(PTA,   NAND,  I2C2,      HDMI,      GMI,       RSVD,          RSVD4,     0x14, 24, 0x98, 22, 0xA4, 4),
+	PINGROUP(RM,    UART,  I2C,       RSVD,      RSVD,      RSVD,          RSVD4,     0x14, 25, 0x80, 14, 0xA4, 0),
+	PINGROUP(SDB,   SD,    UARTA,     PWM,       SDIO3,     SPI2,          PWM,       0x20, 15, 0x8C, 10, -1,   -1),
+	PINGROUP(SDC,   SD,    PWM,       TWC,       SDIO3,     SPI3,          TWC,       0x18, 1,  0x8C, 12, 0xAC, 28),
+	PINGROUP(SDD,   SD,    UARTA,     PWM,       SDIO3,     SPI3,          PWM,       0x18, 2,  0x8C, 14, 0xAC, 30),
+	PINGROUP(SDIO1, BB,    SDIO1,     RSVD,      UARTE,     UARTA,         RSVD2,     0x14, 30, 0x80, 30, 0xB0, 18),
+	PINGROUP(SLXA,  SD,    PCIE,      SPI4,      SDIO3,     SPI2,          PCIE,      0x18, 3,  0x84, 6,  0xA4, 22),
+	PINGROUP(SLXC,  SD,    SPDIF,     SPI4,      SDIO3,     SPI2,          SPI4,      0x18, 5,  0x84, 10, 0xA4, 26),
+	PINGROUP(SLXD,  SD,    SPDIF,     SPI4,      SDIO3,     SPI2,          SPI4,      0x18, 6,  0x84, 12, 0xA4, 28),
+	PINGROUP(SLXK,  SD,    PCIE,      SPI4,      SDIO3,     SPI2,          PCIE,      0x18, 7,  0x84, 14, 0xA4, 30),
+	PINGROUP(SPDI,  AUDIO, SPDIF,     RSVD,      I2C,       SDIO2,         RSVD2,     0x18, 8,  0x8C, 8,  0xA4, 16),
+	PINGROUP(SPDO,  AUDIO, SPDIF,     RSVD,      I2C,       SDIO2,         RSVD2,     0x18, 9,  0x8C, 6,  0xA4, 18),
+	PINGROUP(SPIA,  AUDIO, SPI1,      SPI2,      SPI3,      GMI,           GMI,       0x18, 10, 0x8C, 30, 0xA8, 4),
+	PINGROUP(SPIB,  AUDIO, SPI1,      SPI2,      SPI3,      GMI,           GMI,       0x18, 11, 0x8C, 28, 0xA8, 6),
+	PINGROUP(SPIC,  AUDIO, SPI1,      SPI2,      SPI3,      GMI,           GMI,       0x18, 12, 0x8C, 26, 0xA8, 8),
+	PINGROUP(SPID,  AUDIO, SPI2,      SPI1,      SPI2_ALT,  GMI,           GMI,       0x18, 13, 0x8C, 24, 0xA8, 10),
+	PINGROUP(SPIE,  AUDIO, SPI2,      SPI1,      SPI2_ALT,  GMI,           GMI,       0x18, 14, 0x8C, 22, 0xA8, 12),
+	PINGROUP(SPIF,  AUDIO, SPI3,      SPI1,      SPI2,      RSVD,          RSVD4,     0x18, 15, 0x8C, 20, 0xA8, 14),
+	PINGROUP(SPIG,  AUDIO, SPI3,      SPI2,      SPI2_ALT,  I2C,           SPI2_ALT,  0x18, 16, 0x8C, 18, 0xA8, 16),
+	PINGROUP(SPIH,  AUDIO, SPI3,      SPI2,      SPI2_ALT,  I2C,           SPI2_ALT,  0x18, 17, 0x8C, 16, 0xA8, 18),
+	PINGROUP(UAA,   BB,    SPI3,      MIPI_HS,   UARTA,     ULPI,          MIPI_HS,   0x18, 18, 0x80, 0,  0xAC, 0),
+	PINGROUP(UAB,   BB,    SPI2,      MIPI_HS,   UARTA,     ULPI,          MIPI_HS,   0x18, 19, 0x80, 2,  0xAC, 2),
+	PINGROUP(UAC,   BB,    OWR,       RSVD,      RSVD,      RSVD,          RSVD4,     0x18, 20, 0x80, 4,  0xAC, 4),
+	PINGROUP(UAD,   UART,  IRDA,      SPDIF,     UARTA,     SPI4,          SPDIF,     0x18, 21, 0x80, 6,  0xAC, 6),
+	PINGROUP(UCA,   UART,  UARTC,     RSVD,      GMI,       RSVD,          RSVD4,     0x18, 22, 0x84, 16, 0xAC, 8),
+	PINGROUP(UCB,   UART,  UARTC,     PWM,       GMI,       RSVD,          RSVD4,     0x18, 23, 0x84, 18, 0xAC, 10),
+	PINGROUP(UDA,   BB,    SPI1,      RSVD,      UARTD,     ULPI,          RSVD2,     0x20, 13, 0x80, 8,  0xB0, 16),
+	/* these pin groups only have pullup and pull down control */
+	PINGROUP(CK32,  SYS,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xB0, 14),
+	PINGROUP(DDRC,  DDR,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xAC, 26),
+	PINGROUP(PMCA,  SYS,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xB0, 4),
+	PINGROUP(PMCB,  SYS,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xB0, 6),
+	PINGROUP(PMCC,  SYS,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xB0, 8),
+	PINGROUP(PMCD,  SYS,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xB0, 10),
+	PINGROUP(PMCE,  SYS,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xB0, 12),
+	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];
+
+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 < TRISTATE_REG_NUM; i++)
+		*ctx++ = pg_readl(TRISTATE_REG_A + i*4);
+
+	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);
+}
+
+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);
+}
+#endif
diff --git a/arch/arm/mach-tegra/pinmux.c b/arch/arm/mach-tegra/pinmux.c
index 13ae102..f80d507 100644
--- a/arch/arm/mach-tegra/pinmux.c
+++ b/arch/arm/mach-tegra/pinmux.c
@@ -14,7 +14,8 @@
  *
  */
 
-
+#include <linux/init.h>
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/spinlock.h>
@@ -23,21 +24,6 @@
 #include <mach/iomap.h>
 #include <mach/pinmux.h>
 
-
-#define TEGRA_TRI_STATE(x)	(0x14 + (4 * (x)))
-#define TEGRA_PP_MUX_CTL(x)	(0x80 + (4 * (x)))
-#define TEGRA_PP_PU_PD(x)	(0xa0 + (4 * (x)))
-
-#define REG_A 0
-#define REG_B 1
-#define REG_C 2
-#define REG_D 3
-#define REG_E 4
-#define REG_F 5
-#define REG_G 6
-
-#define REG_N -1
-
 #define HSM_EN(reg)	(((reg) >> 2) & 0x1)
 #define SCHMT_EN(reg)	(((reg) >> 3) & 0x1)
 #define LPMD(reg)	(((reg) >> 4) & 0x3)
@@ -46,154 +32,8 @@
 #define SLWR(reg)	(((reg) >> 28) & 0x3)
 #define SLWF(reg)	(((reg) >> 30) & 0x3)
 
-struct tegra_pingroup_desc {
-	const char *name;
-	int funcs[4];
-	s8 tri_reg; 	/* offset into the TRISTATE_REG_* register bank */
-	s8 tri_bit; 	/* offset into the TRISTATE_REG_* register bit */
-	s8 mux_reg;	/* offset into the PIN_MUX_CTL_* register bank */
-	s8 mux_bit;	/* offset into the PIN_MUX_CTL_* register bit */
-	s8 pupd_reg;	/* offset into the PULL_UPDOWN_REG_* register bank */
-	s8 pupd_bit;	/* offset into the PULL_UPDOWN_REG_* register bit */
-};
-
-#define PINGROUP(pg_name, f0, f1, f2, f3,			\
-		 tri_r, tri_b, mux_r, mux_b, pupd_r, pupd_b)	\
-	[TEGRA_PINGROUP_ ## pg_name] = {			\
-		.name = #pg_name,				\
-		.funcs = {					\
-			TEGRA_MUX_ ## f0,			\
-			TEGRA_MUX_ ## f1,			\
-			TEGRA_MUX_ ## f2,			\
-			TEGRA_MUX_ ## f3,			\
-		},						\
-		.tri_reg = REG_ ## tri_r,			\
-		.tri_bit = tri_b,				\
-		.mux_reg = REG_ ## mux_r,			\
-		.mux_bit = mux_b,				\
-		.pupd_reg = REG_ ## pupd_r,			\
-		.pupd_bit = pupd_b,				\
-	}
-
-static const struct tegra_pingroup_desc pingroups[TEGRA_MAX_PINGROUP] = {
-	PINGROUP(ATA,   IDE,       NAND,      GMI,       RSVD,          A, 0,  A, 24, A, 0),
-	PINGROUP(ATB,   IDE,       NAND,      GMI,       SDIO4,         A, 1,  A, 16, A, 2),
-	PINGROUP(ATC,   IDE,       NAND,      GMI,       SDIO4,         A, 2,  A, 22, A, 4),
-	PINGROUP(ATD,   IDE,       NAND,      GMI,       SDIO4,         A, 3,  A, 20, A, 6),
-	PINGROUP(ATE,   IDE,       NAND,      GMI,       RSVD,          B, 25, A, 12, A, 8),
-	PINGROUP(CDEV1, OSC,       PLLA_OUT,  PLLM_OUT1, AUDIO_SYNC,    A, 4,  C, 2,  C, 0),
-	PINGROUP(CDEV2, OSC,       AHB_CLK,   APB_CLK,   PLLP_OUT4,     A, 5,  C, 4,  C, 2),
-	PINGROUP(CRTP,  CRT,       RSVD,      RSVD,      RSVD,          D, 14, G, 20, B, 24),
-	PINGROUP(CSUS,  PLLC_OUT1, PLLP_OUT2, PLLP_OUT3, VI_SENSOR_CLK, A, 6,  C, 6,  D, 24),
-	PINGROUP(DAP1,  DAP1,      RSVD,      GMI,       SDIO2,         A, 7,  C, 20, A, 10),
-	PINGROUP(DAP2,  DAP2,      TWC,       RSVD,      GMI,           A, 8,  C, 22, A, 12),
-	PINGROUP(DAP3,  DAP3,      RSVD,      RSVD,      RSVD,          A, 9,  C, 24, A, 14),
-	PINGROUP(DAP4,  DAP4,      RSVD,      GMI,       RSVD,          A, 10, C, 26, A, 16),
-	PINGROUP(DDC,   I2C2,      RSVD,      RSVD,      RSVD,          B, 31, C, 0,  E, 28),
-	PINGROUP(DTA,   RSVD,      SDIO2,     VI,        RSVD,          A, 11, B, 20, A, 18),
-	PINGROUP(DTB,   RSVD,      RSVD,      VI,        SPI1,          A, 12, B, 22, A, 20),
-	PINGROUP(DTC,   RSVD,      RSVD,      VI,        RSVD,          A, 13, B, 26, A, 22),
-	PINGROUP(DTD,   RSVD,      SDIO2,     VI,        RSVD,          A, 14, B, 28, A, 24),
-	PINGROUP(DTE,   RSVD,      RSVD,      VI,        SPI1,          A, 15, B, 30, A, 26),
-	PINGROUP(DTF,   I2C3,      RSVD,      VI,        RSVD,          D, 12, G, 30, A, 28),
-	PINGROUP(GMA,   UARTE,     SPI3,      GMI,       SDIO4,         A, 28, B, 0,  E, 20),
-	PINGROUP(GMB,   IDE,       NAND,      GMI,       GMI_INT,       B, 29, C, 28, E, 22),
-	PINGROUP(GMC,   UARTD,     SPI4,      GMI,       SFLASH,        A, 29, B, 2,  E, 24),
-	PINGROUP(GMD,   RSVD,      NAND,      GMI,       SFLASH,        B, 30, C, 30, E, 26),
-	PINGROUP(GME,   RSVD,      DAP5,      GMI,       SDIO4,         B, 0,  D, 0,  C, 24),
-	PINGROUP(GPU,   PWM,       UARTA,     GMI,       RSVD,          A, 16, D, 4,  B, 20),
-	PINGROUP(GPU7,  RTCK,      RSVD,      RSVD,      RSVD,          D, 11, G, 28, B, 6),
-	PINGROUP(GPV,   PCIE,      RSVD,      RSVD,      RSVD,          A, 17, D, 2,  A, 30),
-	PINGROUP(HDINT, HDMI,      RSVD,      RSVD,      RSVD,          C, 23, B, 4,  D, 22),
-	PINGROUP(I2CP,  I2C,       RSVD,      RSVD,      RSVD,          A, 18, C, 8,  B, 2),
-	PINGROUP(IRRX,  UARTA,     UARTB,     GMI,       SPI4,          A, 20, C, 18, C, 22),
-	PINGROUP(IRTX,  UARTA,     UARTB,     GMI,       SPI4,          A, 19, C, 16, C, 20),
-	PINGROUP(KBCA,  KBC,       NAND,      SDIO2,     EMC_TEST0_DLL, A, 22, C, 10, B, 8),
-	PINGROUP(KBCB,  KBC,       NAND,      SDIO2,     MIO,           A, 21, C, 12, B, 10),
-	PINGROUP(KBCC,  KBC,       NAND,      TRACE,     EMC_TEST1_DLL, B, 26, C, 14, B, 12),
-	PINGROUP(KBCD,  KBC,       NAND,      SDIO2,     MIO,           D, 10, G, 26, B, 14),
-	PINGROUP(KBCE,  KBC,       NAND,      OWR,       RSVD,          A, 26, A, 28, E, 2),
-	PINGROUP(KBCF,  KBC,       NAND,      TRACE,     MIO,           A, 27, A, 26, E, 0),
-	PINGROUP(LCSN,  DISPLAYA,  DISPLAYB,  SPI3,      RSVD,          C, 31, E, 12, D, 20),
-	PINGROUP(LD0,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 0,  F, 0,  D, 12),
-	PINGROUP(LD1,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 1,  F, 2,  D, 12),
-	PINGROUP(LD10,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 10, F, 20, D, 12),
-	PINGROUP(LD11,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 11, F, 22, D, 12),
-	PINGROUP(LD12,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 12, F, 24, D, 12),
-	PINGROUP(LD13,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 13, F, 26, D, 12),
-	PINGROUP(LD14,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 14, F, 28, D, 12),
-	PINGROUP(LD15,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 15, F, 30, D, 12),
-	PINGROUP(LD16,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 16, G, 0,  D, 12),
-	PINGROUP(LD17,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 17, G, 2,  D, 12),
-	PINGROUP(LD2,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 2,  F, 4,  D, 12),
-	PINGROUP(LD3,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 3,  F, 6,  D, 12),
-	PINGROUP(LD4,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 4,  F, 8,  D, 12),
-	PINGROUP(LD5,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 5,  F, 10, D, 12),
-	PINGROUP(LD6,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 6,  F, 12, D, 12),
-	PINGROUP(LD7,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 7,  F, 14, D, 12),
-	PINGROUP(LD8,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 8,  F, 16, D, 12),
-	PINGROUP(LD9,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 9,  F, 18, D, 12),
-	PINGROUP(LDC,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 30, E, 14, D, 20),
-	PINGROUP(LDI,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          D, 6,  G, 16, D, 18),
-	PINGROUP(LHP0,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 18, G, 10, D, 16),
-	PINGROUP(LHP1,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 19, G, 4,  D, 14),
-	PINGROUP(LHP2,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 20, G, 6,  D, 14),
-	PINGROUP(LHS,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          D, 7,  E, 22, D, 22),
-	PINGROUP(LM0,   DISPLAYA,  DISPLAYB,  SPI3,      RSVD,          C, 24, E, 26, D, 22),
-	PINGROUP(LM1,   DISPLAYA,  DISPLAYB,  RSVD,      CRT,           C, 25, E, 28, D, 22),
-	PINGROUP(LPP,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          D, 8,  G, 14, D, 18),
-	PINGROUP(LPW0,  DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          D, 3,  E, 0,  D, 20),
-	PINGROUP(LPW1,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          D, 4,  E, 2,  D, 20),
-	PINGROUP(LPW2,  DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          D, 5,  E, 4,  D, 20),
-	PINGROUP(LSC0,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 27, E, 18, D, 22),
-	PINGROUP(LSC1,  DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          C, 28, E, 20, D, 20),
-	PINGROUP(LSCK,  DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          C, 29, E, 16, D, 20),
-	PINGROUP(LSDA,  DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          D, 1,  E, 8,  D, 20),
-	PINGROUP(LSDI,  DISPLAYA,  DISPLAYB,  SPI3,      RSVD,          D, 2,  E, 6,  D, 20),
-	PINGROUP(LSPI,  DISPLAYA,  DISPLAYB,  XIO,       HDMI,          D, 0,  E, 10, D, 22),
-	PINGROUP(LVP0,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 21, E, 30, D, 22),
-	PINGROUP(LVP1,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 22, G, 8,  D, 16),
-	PINGROUP(LVS,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 26, E, 24, D, 22),
-	PINGROUP(OWC,   OWR,       RSVD,      RSVD,      RSVD,          A, 31, B, 8,  E, 30),
-	PINGROUP(PMC,   PWR_ON,    PWR_INTR,  RSVD,      RSVD,          A, 23, G, 18, N, -1),
-	PINGROUP(PTA,   I2C2,      HDMI,      GMI,       RSVD,          A, 24, G, 22, B, 4),
-	PINGROUP(RM,    I2C,       RSVD,      RSVD,      RSVD,          A, 25, A, 14, B, 0),
-	PINGROUP(SDB,   UARTA,     PWM,       SDIO3,     SPI2,          D, 15, D, 10, N, -1),
-	PINGROUP(SDC,   PWM,       TWC,       SDIO3,     SPI3,          B, 1,  D, 12, D, 28),
-	PINGROUP(SDD,   UARTA,     PWM,       SDIO3,     SPI3,          B, 2,  D, 14, D, 30),
-	PINGROUP(SDIO1, SDIO1,     RSVD,      UARTE,     UARTA,         A, 30, A, 30, E, 18),
-	PINGROUP(SLXA,  PCIE,      SPI4,      SDIO3,     SPI2,          B, 3,  B, 6,  B, 22),
-	PINGROUP(SLXC,  SPDIF,     SPI4,      SDIO3,     SPI2,          B, 5,  B, 10, B, 26),
-	PINGROUP(SLXD,  SPDIF,     SPI4,      SDIO3,     SPI2,          B, 6,  B, 12, B, 28),
-	PINGROUP(SLXK,  PCIE,      SPI4,      SDIO3,     SPI2,          B, 7,  B, 14, B, 30),
-	PINGROUP(SPDI,  SPDIF,     RSVD,      I2C,       SDIO2,         B, 8,  D, 8,  B, 16),
-	PINGROUP(SPDO,  SPDIF,     RSVD,      I2C,       SDIO2,         B, 9,  D, 6,  B, 18),
-	PINGROUP(SPIA,  SPI1,      SPI2,      SPI3,      GMI,           B, 10, D, 30, C, 4),
-	PINGROUP(SPIB,  SPI1,      SPI2,      SPI3,      GMI,           B, 11, D, 28, C, 6),
-	PINGROUP(SPIC,  SPI1,      SPI2,      SPI3,      GMI,           B, 12, D, 26, C, 8),
-	PINGROUP(SPID,  SPI2,      SPI1,      SPI2_ALT,  GMI,           B, 13, D, 24, C, 10),
-	PINGROUP(SPIE,  SPI2,      SPI1,      SPI2_ALT,  GMI,           B, 14, D, 22, C, 12),
-	PINGROUP(SPIF,  SPI3,      SPI1,      SPI2,      RSVD,          B, 15, D, 20, C, 14),
-	PINGROUP(SPIG,  SPI3,      SPI2,      SPI2_ALT,  I2C,           B, 16, D, 18, C, 16),
-	PINGROUP(SPIH,  SPI3,      SPI2,      SPI2_ALT,  I2C,           B, 17, D, 16, C, 18),
-	PINGROUP(UAA,   SPI3,      MIPI_HS,   UARTA,     ULPI,          B, 18, A, 0,  D, 0),
-	PINGROUP(UAB,   SPI2,      MIPI_HS,   UARTA,     ULPI,          B, 19, A, 2,  D, 2),
-	PINGROUP(UAC,   OWR,       RSVD,      RSVD,      RSVD,          B, 20, A, 4,  D, 4),
-	PINGROUP(UAD,   IRDA,      SPDIF,     UARTA,     SPI4,          B, 21, A, 6,  D, 6),
-	PINGROUP(UCA,   UARTC,     RSVD,      GMI,       RSVD,          B, 22, B, 16, D, 8),
-	PINGROUP(UCB,   UARTC,     PWM,       GMI,       RSVD,          B, 23, B, 18, D, 10),
-	PINGROUP(UDA,   SPI1,      RSVD,      UARTD,     ULPI,          D, 13, A, 8,  E, 16),
-	/* these pin groups only have pullup and pull down control */
-	PINGROUP(CK32,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  E, 14),
-	PINGROUP(DDRC,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  D, 26),
-	PINGROUP(PMCA,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  E, 4),
-	PINGROUP(PMCB,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  E, 6),
-	PINGROUP(PMCC,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  E, 8),
-	PINGROUP(PMCD,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  E, 10),
-	PINGROUP(PMCE,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  E, 12),
-	PINGROUP(XM2C,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  C, 30),
-	PINGROUP(XM2D,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  C, 28),
-};
+static const struct tegra_pingroup_desc *const pingroups = tegra_soc_pingroups;
+static const struct tegra_drive_pingroup_desc *const drive_pingroups = tegra_soc_drive_pingroups;
 
 static char *tegra_mux_names[TEGRA_MAX_MUX] = {
 	[TEGRA_MUX_AHB_CLK] = "AHB_CLK",
@@ -256,48 +96,7 @@
 	[TEGRA_MUX_VI] = "VI",
 	[TEGRA_MUX_VI_SENSOR_CLK] = "VI_SENSOR_CLK",
 	[TEGRA_MUX_XIO] = "XIO",
-};
-
-struct tegra_drive_pingroup_desc {
-	const char *name;
-	s16 reg;
-};
-
-#define DRIVE_PINGROUP(pg_name, r)				\
-	[TEGRA_DRIVE_PINGROUP_ ## pg_name] = {			\
-		.name = #pg_name,				\
-		.reg = r					\
-	}
-
-static const struct tegra_drive_pingroup_desc drive_pingroups[TEGRA_MAX_PINGROUP] = {
-	DRIVE_PINGROUP(AO1,		0x868),
-	DRIVE_PINGROUP(AO2,		0x86c),
-	DRIVE_PINGROUP(AT1,		0x870),
-	DRIVE_PINGROUP(AT2,		0x874),
-	DRIVE_PINGROUP(CDEV1,		0x878),
-	DRIVE_PINGROUP(CDEV2,		0x87c),
-	DRIVE_PINGROUP(CSUS,		0x880),
-	DRIVE_PINGROUP(DAP1,		0x884),
-	DRIVE_PINGROUP(DAP2,		0x888),
-	DRIVE_PINGROUP(DAP3,		0x88c),
-	DRIVE_PINGROUP(DAP4,		0x890),
-	DRIVE_PINGROUP(DBG,		0x894),
-	DRIVE_PINGROUP(LCD1,		0x898),
-	DRIVE_PINGROUP(LCD2,		0x89c),
-	DRIVE_PINGROUP(SDMMC2,	0x8a0),
-	DRIVE_PINGROUP(SDMMC3,	0x8a4),
-	DRIVE_PINGROUP(SPI,		0x8a8),
-	DRIVE_PINGROUP(UAA,		0x8ac),
-	DRIVE_PINGROUP(UAB,		0x8b0),
-	DRIVE_PINGROUP(UART2,		0x8b4),
-	DRIVE_PINGROUP(UART3,		0x8b8),
-	DRIVE_PINGROUP(VI1,		0x8bc),
-	DRIVE_PINGROUP(VI2,		0x8c0),
-	DRIVE_PINGROUP(XM2A,		0x8c4),
-	DRIVE_PINGROUP(XM2C,		0x8c8),
-	DRIVE_PINGROUP(XM2D,		0x8cc),
-	DRIVE_PINGROUP(XM2CLK,	0x8d0),
-	DRIVE_PINGROUP(MEMCOMP,	0x8d4),
+	[TEGRA_MUX_SAFE] = "<safe>",
 };
 
 static const char *tegra_drive_names[TEGRA_MAX_DRIVE] = {
@@ -381,22 +180,27 @@
 	writel(value, IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
 }
 
-int tegra_pinmux_set_func(enum tegra_pingroup pg, enum tegra_mux_func func)
+static int tegra_pinmux_set_func(const struct tegra_pingroup_config *config)
 {
 	int mux = -1;
 	int i;
 	unsigned long reg;
 	unsigned long flags;
+	enum tegra_pingroup pg = config->pingroup;
+	enum tegra_mux_func func = config->func;
 
 	if (pg < 0 || pg >=  TEGRA_MAX_PINGROUP)
 		return -ERANGE;
 
-	if (pingroups[pg].mux_reg == REG_N)
+	if (pingroups[pg].mux_reg < 0)
 		return -EINVAL;
 
 	if (func < 0)
 		return -ERANGE;
 
+	if (func == TEGRA_MUX_SAFE)
+		func = pingroups[pg].func_safe;
+
 	if (func & TEGRA_MUX_RSVD) {
 		mux = func & 0x3;
 	} else {
@@ -413,10 +217,10 @@
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(TEGRA_PP_MUX_CTL(pingroups[pg].mux_reg));
+	reg = pg_readl(pingroups[pg].mux_reg);
 	reg &= ~(0x3 << pingroups[pg].mux_bit);
 	reg |= mux << pingroups[pg].mux_bit;
-	pg_writel(reg, TEGRA_PP_MUX_CTL(pingroups[pg].mux_reg));
+	pg_writel(reg, pingroups[pg].mux_reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -432,16 +236,16 @@
 	if (pg < 0 || pg >=  TEGRA_MAX_PINGROUP)
 		return -ERANGE;
 
-	if (pingroups[pg].tri_reg == REG_N)
+	if (pingroups[pg].tri_reg < 0)
 		return -EINVAL;
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(TEGRA_TRI_STATE(pingroups[pg].tri_reg));
+	reg = pg_readl(pingroups[pg].tri_reg);
 	reg &= ~(0x1 << pingroups[pg].tri_bit);
 	if (tristate)
 		reg |= 1 << pingroups[pg].tri_bit;
-	pg_writel(reg, TEGRA_TRI_STATE(pingroups[pg].tri_reg));
+	pg_writel(reg, pingroups[pg].tri_reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -457,7 +261,7 @@
 	if (pg < 0 || pg >=  TEGRA_MAX_PINGROUP)
 		return -ERANGE;
 
-	if (pingroups[pg].pupd_reg == REG_N)
+	if (pingroups[pg].pupd_reg < 0)
 		return -EINVAL;
 
 	if (pupd != TEGRA_PUPD_NORMAL &&
@@ -468,38 +272,39 @@
 
 	spin_lock_irqsave(&mux_lock, flags);
 
-	reg = pg_readl(TEGRA_PP_PU_PD(pingroups[pg].pupd_reg));
+	reg = pg_readl(pingroups[pg].pupd_reg);
 	reg &= ~(0x3 << pingroups[pg].pupd_bit);
 	reg |= pupd << pingroups[pg].pupd_bit;
-	pg_writel(reg, TEGRA_PP_PU_PD(pingroups[pg].pupd_reg));
+	pg_writel(reg, pingroups[pg].pupd_reg);
 
 	spin_unlock_irqrestore(&mux_lock, flags);
 
 	return 0;
 }
 
-void tegra_pinmux_config_pingroup(enum tegra_pingroup pingroup,
-				 enum tegra_mux_func func,
-				 enum tegra_pullupdown pupd,
-				 enum tegra_tristate tristate)
+static void tegra_pinmux_config_pingroup(const struct tegra_pingroup_config *config)
 {
+	enum tegra_pingroup pingroup = config->pingroup;
+	enum tegra_mux_func func     = config->func;
+	enum tegra_pullupdown pupd   = config->pupd;
+	enum tegra_tristate tristate = config->tristate;
 	int err;
 
-	if (pingroups[pingroup].mux_reg != REG_N) {
-		err = tegra_pinmux_set_func(pingroup, func);
+	if (pingroups[pingroup].mux_reg >= 0) {
+		err = tegra_pinmux_set_func(config);
 		if (err < 0)
 			pr_err("pinmux: can't set pingroup %s func to %s: %d\n",
 			       pingroup_name(pingroup), func_name(func), err);
 	}
 
-	if (pingroups[pingroup].pupd_reg != REG_N) {
+	if (pingroups[pingroup].pupd_reg >= 0) {
 		err = tegra_pinmux_set_pullupdown(pingroup, pupd);
 		if (err < 0)
 			pr_err("pinmux: can't set pingroup %s pullupdown to %s: %d\n",
 			       pingroup_name(pingroup), pupd_name(pupd), err);
 	}
 
-	if (pingroups[pingroup].tri_reg != REG_N) {
+	if (pingroups[pingroup].tri_reg >= 0) {
 		err = tegra_pinmux_set_tristate(pingroup, tristate);
 		if (err < 0)
 			pr_err("pinmux: can't set pingroup %s tristate to %s: %d\n",
@@ -507,17 +312,12 @@
 	}
 }
 
-
-
-void tegra_pinmux_config_table(struct tegra_pingroup_config *config, int len)
+void tegra_pinmux_config_table(const struct tegra_pingroup_config *config, int len)
 {
 	int i;
 
 	for (i = 0; i < len; i++)
-		tegra_pinmux_config_pingroup(config[i].pingroup,
-					     config[i].func,
-					     config[i].pupd,
-					     config[i].tristate);
+		tegra_pinmux_config_pingroup(&config[i]);
 }
 
 static const char *drive_pinmux_name(enum tegra_drive_pingroup pg)
@@ -784,6 +584,86 @@
 						     config[i].slew_falling);
 }
 
+void tegra_pinmux_set_safe_pinmux_table(const struct tegra_pingroup_config *config,
+	int len)
+{
+	int i;
+	struct tegra_pingroup_config c;
+
+	for (i = 0; i < len; i++) {
+		int err;
+		c = config[i];
+		if (c.pingroup < 0 || c.pingroup >= TEGRA_MAX_PINGROUP) {
+			WARN_ON(1);
+			continue;
+		}
+		c.func = pingroups[c.pingroup].func_safe;
+		err = tegra_pinmux_set_func(&c);
+		if (err < 0)
+			pr_err("%s: tegra_pinmux_set_func returned %d setting "
+			       "%s to %s\n", __func__, err,
+			       pingroup_name(c.pingroup), func_name(c.func));
+	}
+}
+
+void tegra_pinmux_config_pinmux_table(const struct tegra_pingroup_config *config,
+	int len)
+{
+	int i;
+
+	for (i = 0; i < len; i++) {
+		int err;
+		if (config[i].pingroup < 0 ||
+		    config[i].pingroup >= TEGRA_MAX_PINGROUP) {
+			WARN_ON(1);
+			continue;
+		}
+		err = tegra_pinmux_set_func(&config[i]);
+		if (err < 0)
+			pr_err("%s: tegra_pinmux_set_func returned %d setting "
+			       "%s to %s\n", __func__, err,
+			       pingroup_name(config[i].pingroup),
+			       func_name(config[i].func));
+	}
+}
+
+void tegra_pinmux_config_tristate_table(const struct tegra_pingroup_config *config,
+	int len, enum tegra_tristate tristate)
+{
+	int i;
+	int err;
+	enum tegra_pingroup pingroup;
+
+	for (i = 0; i < len; i++) {
+		pingroup = config[i].pingroup;
+		if (pingroups[pingroup].tri_reg >= 0) {
+			err = tegra_pinmux_set_tristate(pingroup, tristate);
+			if (err < 0)
+				pr_err("pinmux: can't set pingroup %s tristate"
+					" to %s: %d\n",	pingroup_name(pingroup),
+					tri_name(tristate), err);
+		}
+	}
+}
+
+void tegra_pinmux_config_pullupdown_table(const struct tegra_pingroup_config *config,
+	int len, enum tegra_pullupdown pupd)
+{
+	int i;
+	int err;
+	enum tegra_pingroup pingroup;
+
+	for (i = 0; i < len; i++) {
+		pingroup = config[i].pingroup;
+		if (pingroups[pingroup].pupd_reg >= 0) {
+			err = tegra_pinmux_set_pullupdown(pingroup, pupd);
+			if (err < 0)
+				pr_err("pinmux: can't set pingroup %s pullupdown"
+					" to %s: %d\n",	pingroup_name(pingroup),
+					pupd_name(pupd), err);
+		}
+	}
+}
 
 #ifdef	CONFIG_DEBUG_FS
 
@@ -812,11 +692,11 @@
 		len = strlen(pingroups[i].name);
 		dbg_pad_field(s, 5 - len);
 
-		if (pingroups[i].mux_reg == REG_N) {
+		if (pingroups[i].mux_reg < 0) {
 			seq_printf(s, "TEGRA_MUX_NONE");
 			len = strlen("NONE");
 		} else {
-			mux = (pg_readl(TEGRA_PP_MUX_CTL(pingroups[i].mux_reg)) >>
+			mux = (pg_readl(pingroups[i].mux_reg) >>
 			       pingroups[i].mux_bit) & 0x3;
 			if (pingroups[i].funcs[mux] == TEGRA_MUX_RSVD) {
 				seq_printf(s, "TEGRA_MUX_RSVD%1lu", mux+1);
@@ -829,21 +709,21 @@
 		}
 		dbg_pad_field(s, 13-len);
 
-		if (pingroups[i].mux_reg == REG_N) {
+		if (pingroups[i].pupd_reg < 0) {
 			seq_printf(s, "TEGRA_PUPD_NORMAL");
 			len = strlen("NORMAL");
 		} else {
-			pupd = (pg_readl(TEGRA_PP_PU_PD(pingroups[i].pupd_reg)) >>
+			pupd = (pg_readl(pingroups[i].pupd_reg) >>
 				pingroups[i].pupd_bit) & 0x3;
 			seq_printf(s, "TEGRA_PUPD_%s", pupd_name(pupd));
 			len = strlen(pupd_name(pupd));
 		}
 		dbg_pad_field(s, 9 - len);
 
-		if (pingroups[i].tri_reg == REG_N) {
+		if (pingroups[i].tri_reg < 0) {
 			seq_printf(s, "TEGRA_TRI_NORMAL");
 		} else {
-			tri = (pg_readl(TEGRA_TRI_STATE(pingroups[i].tri_reg)) >>
+			tri = (pg_readl(pingroups[i].tri_reg) >>
 			       pingroups[i].tri_bit) & 0x1;
 
 			seq_printf(s, "TEGRA_TRI_%s", tri_name(tri));
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c
index 4261632..ae3b308 100644
--- a/arch/arm/mach-tegra/tegra2_clocks.c
+++ b/arch/arm/mach-tegra/tegra2_clocks.c
@@ -30,14 +30,21 @@
 #include <mach/iomap.h>
 
 #include "clock.h"
+#include "fuse.h"
+#include "tegra2_dvfs.h"
 
 #define RST_DEVICES			0x004
 #define RST_DEVICES_SET			0x300
 #define RST_DEVICES_CLR			0x304
+#define RST_DEVICES_NUM			3
 
 #define CLK_OUT_ENB			0x010
 #define CLK_OUT_ENB_SET			0x320
 #define CLK_OUT_ENB_CLR			0x324
+#define CLK_OUT_ENB_NUM			3
+
+#define CLK_MASK_ARM			0x44
+#define MISC_CLK_ENB			0x48
 
 #define OSC_CTRL			0x50
 #define OSC_CTRL_OSC_FREQ_MASK		(3<<30)
@@ -45,6 +52,7 @@
 #define OSC_CTRL_OSC_FREQ_19_2MHZ	(1<<30)
 #define OSC_CTRL_OSC_FREQ_12MHZ		(2<<30)
 #define OSC_CTRL_OSC_FREQ_26MHZ		(3<<30)
+#define OSC_CTRL_MASK			0x3f2
 
 #define OSC_FREQ_DET			0x58
 #define OSC_FREQ_DET_TRIG		(1<<31)
@@ -53,10 +61,17 @@
 #define OSC_FREQ_DET_BUSY		(1<<31)
 #define OSC_FREQ_DET_CNT_MASK		0xFFFF
 
+#define PERIPH_CLK_SOURCE_I2S1		0x100
+#define PERIPH_CLK_SOURCE_EMC		0x19c
+#define PERIPH_CLK_SOURCE_OSC		0x1fc
+#define PERIPH_CLK_SOURCE_NUM \
+	((PERIPH_CLK_SOURCE_OSC - PERIPH_CLK_SOURCE_I2S1) / 4)
+
 #define PERIPH_CLK_SOURCE_MASK		(3<<30)
 #define PERIPH_CLK_SOURCE_SHIFT		30
 #define PERIPH_CLK_SOURCE_ENABLE	(1<<28)
-#define PERIPH_CLK_SOURCE_DIV_MASK	0xFF
+#define PERIPH_CLK_SOURCE_DIVU71_MASK	0xFF
+#define PERIPH_CLK_SOURCE_DIVU16_MASK	0xFFFF
 #define PERIPH_CLK_SOURCE_DIV_SHIFT	0
 
 #define PLL_BASE			0x0
@@ -79,8 +94,9 @@
 #define PLL_OUT_RESET_DISABLE		(1<<0)
 
 #define PLL_MISC(c)			(((c)->flags & PLL_ALT_MISC_REG) ? 0x4 : 0xc)
+#define PLL_MISC_LOCK_ENABLE(c)		(((c)->flags & PLLU) ? (1<<22) : (1<<18))
+
 #define PLL_MISC_DCCON_SHIFT		20
-#define PLL_MISC_LOCK_ENABLE		(1<<18)
 #define PLL_MISC_CPCON_SHIFT		8
 #define PLL_MISC_CPCON_MASK		(0xF<<PLL_MISC_CPCON_SHIFT)
 #define PLL_MISC_LFCON_SHIFT		4
@@ -88,10 +104,14 @@
 #define PLL_MISC_VCOCON_SHIFT		0
 #define PLL_MISC_VCOCON_MASK		(0xF<<PLL_MISC_VCOCON_SHIFT)
 
+#define PLLU_BASE_POST_DIV		(1<<20)
+
 #define PLLD_MISC_CLKENABLE		(1<<30)
 #define PLLD_MISC_DIV_RST		(1<<23)
 #define PLLD_MISC_DCCON_SHIFT		12
 
+#define PLLE_MISC_READY			(1 << 15)
+
 #define PERIPH_CLK_TO_ENB_REG(c)	((c->clk_num / 32) * 4)
 #define PERIPH_CLK_TO_ENB_SET_REG(c)	((c->clk_num / 32) * 8)
 #define PERIPH_CLK_TO_ENB_BIT(c)	(1 << (c->clk_num % 32))
@@ -143,31 +163,38 @@
 	}
 }
 
-static int clk_div71_get_divider(struct clk *c, unsigned long rate)
+static int clk_div71_get_divider(unsigned long parent_rate, unsigned long rate)
 {
-	unsigned long divider_u71;
+	s64 divider_u71 = parent_rate * 2;
+	divider_u71 += rate - 1;
+	do_div(divider_u71, rate);
 
-	divider_u71 = DIV_ROUND_UP(c->rate * 2, rate);
+	if (divider_u71 - 2 < 0)
+		return 0;
 
-	if (divider_u71 - 2 > 255 || divider_u71 - 2 < 0)
+	if (divider_u71 - 2 > 255)
 		return -EINVAL;
 
 	return divider_u71 - 2;
 }
 
-static unsigned long tegra2_clk_recalculate_rate(struct clk *c)
+static int clk_div16_get_divider(unsigned long parent_rate, unsigned long rate)
 {
-	unsigned long rate;
-	rate = c->parent->rate;
+	s64 divider_u16;
 
-	if (c->mul != 0 && c->div != 0)
-		c->rate = rate * c->mul / c->div;
-	else
-		c->rate = rate;
-	return c->rate;
+	divider_u16 = parent_rate;
+	divider_u16 += rate - 1;
+	do_div(divider_u16, rate);
+
+	if (divider_u16 - 1 < 0)
+		return 0;
+
+	if (divider_u16 - 1 > 255)
+		return -EINVAL;
+
+	return divider_u16 - 1;
 }
 
-
 /* clk_m functions */
 static unsigned long tegra2_clk_m_autodetect_rate(struct clk *c)
 {
@@ -244,7 +271,6 @@
 	}
 	BUG_ON(sel->input == NULL);
 	c->parent = sel->input;
-	tegra2_clk_recalculate_rate(c);
 }
 
 static int tegra2_super_clk_enable(struct clk *c)
@@ -266,6 +292,7 @@
 	u32 val;
 	const struct clk_mux_sel *sel;
 	int shift;
+
 	val = clk_readl(c->reg + SUPER_CLK_MUX);;
 	BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) &&
 		((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
@@ -273,11 +300,18 @@
 		SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT;
 	for (sel = c->inputs; sel->input != NULL; sel++) {
 		if (sel->input == p) {
-			clk_reparent(c, p);
 			val &= ~(SUPER_SOURCE_MASK << shift);
 			val |= sel->value << shift;
+
+			if (c->refcnt)
+				clk_enable_locked(p);
+
 			clk_writel(val, c->reg);
-			c->rate = c->parent->rate;
+
+			if (c->refcnt && c->parent)
+				clk_disable_locked(c->parent);
+
+			clk_reparent(c, p);
 			return 0;
 		}
 	}
@@ -289,7 +323,61 @@
 	.enable			= tegra2_super_clk_enable,
 	.disable		= tegra2_super_clk_disable,
 	.set_parent		= tegra2_super_clk_set_parent,
-	.recalculate_rate	= tegra2_clk_recalculate_rate,
+};
+
+/* virtual cpu clock functions */
+/* some clocks can not be stopped (cpu, memory bus) while the SoC is running.
+   To change the frequency of these clocks, the parent pll may need to be
+   reprogrammed, so the clock must be moved off the pll, the pll reprogrammed,
+   and then the clock moved back to the pll.  To hide this sequence, a virtual
+   clock handles it.
+ */
+static void tegra2_cpu_clk_init(struct clk *c)
+{
+}
+
+static int tegra2_cpu_clk_enable(struct clk *c)
+{
+	return 0;
+}
+
+static void tegra2_cpu_clk_disable(struct clk *c)
+{
+	pr_debug("%s on clock %s\n", __func__, c->name);
+
+	/* oops - don't disable the CPU clock! */
+	BUG();
+}
+
+static int tegra2_cpu_clk_set_rate(struct clk *c, unsigned long rate)
+{
+	int ret;
+	ret = clk_set_parent_locked(c->parent, c->backup);
+	if (ret) {
+		pr_err("Failed to switch cpu to clock %s\n", c->backup->name);
+		return ret;
+	}
+
+	ret = clk_set_rate_locked(c->main, rate);
+	if (ret) {
+		pr_err("Failed to change cpu pll to %lu\n", rate);
+		return ret;
+	}
+
+	ret = clk_set_parent_locked(c->parent, c->main);
+	if (ret) {
+		pr_err("Failed to switch cpu to clock %s\n", c->main->name);
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct clk_ops tegra_cpu_ops = {
+	.init     = tegra2_cpu_clk_init,
+	.enable   = tegra2_cpu_clk_enable,
+	.disable  = tegra2_cpu_clk_disable,
+	.set_rate = tegra2_cpu_clk_set_rate,
 };
 
 /* bus clock functions */
@@ -299,7 +387,6 @@
 	c->state = ((val >> c->reg_shift) & BUS_CLK_DISABLE) ? OFF : ON;
 	c->div = ((val >> c->reg_shift) & BUS_CLK_DIV_MASK) + 1;
 	c->mul = 1;
-	tegra2_clk_recalculate_rate(c);
 }
 
 static int tegra2_bus_clk_enable(struct clk *c)
@@ -340,27 +427,15 @@
 	.enable			= tegra2_bus_clk_enable,
 	.disable		= tegra2_bus_clk_disable,
 	.set_rate		= tegra2_bus_clk_set_rate,
-	.recalculate_rate	= tegra2_clk_recalculate_rate,
 };
 
 /* PLL Functions */
-static unsigned long tegra2_pll_clk_recalculate_rate(struct clk *c)
-{
-	u64 rate;
-	rate = c->parent->rate;
-	rate *= c->n;
-	do_div(rate, c->m);
-	if (c->p == 2)
-		rate >>= 1;
-	c->rate = rate;
-	return c->rate;
-}
-
 static int tegra2_pll_clk_wait_for_lock(struct clk *c)
 {
 	ktime_t before;
 
 	before = ktime_get();
+
 	while (!(clk_readl(c->reg + PLL_BASE) & PLL_BASE_LOCK)) {
 		if (ktime_us_delta(ktime_get(), before) > 5000) {
 			pr_err("Timed out waiting for lock bit on pll %s",
@@ -380,24 +455,19 @@
 
 	if (c->flags & PLL_FIXED && !(val & PLL_BASE_OVERRIDE)) {
 		pr_warning("Clock %s has unknown fixed frequency\n", c->name);
-		c->n = 1;
-		c->m = 0;
-		c->p = 1;
+		c->mul = 1;
+		c->div = 1;
 	} else if (val & PLL_BASE_BYPASS) {
-		c->n = 1;
-		c->m = 1;
-		c->p = 1;
+		c->mul = 1;
+		c->div = 1;
 	} else {
-		c->n = (val & PLL_BASE_DIVN_MASK) >> PLL_BASE_DIVN_SHIFT;
-		c->m = (val & PLL_BASE_DIVM_MASK) >> PLL_BASE_DIVM_SHIFT;
-		c->p = (val & PLL_BASE_DIVP_MASK) ? 2 : 1;
+		c->mul = (val & PLL_BASE_DIVN_MASK) >> PLL_BASE_DIVN_SHIFT;
+		c->div = (val & PLL_BASE_DIVM_MASK) >> PLL_BASE_DIVM_SHIFT;
+		if (c->flags & PLLU)
+			c->div *= (val & PLLU_BASE_POST_DIV) ? 1 : 2;
+		else
+			c->div *= (val & PLL_BASE_DIVP_MASK) ? 2 : 1;
 	}
-
-	val = clk_readl(c->reg + PLL_MISC(c));
-	if (c->flags & PLL_HAS_CPCON)
-		c->cpcon = (val & PLL_MISC_CPCON_MASK) >> PLL_MISC_CPCON_SHIFT;
-
-	tegra2_pll_clk_recalculate_rate(c);
 }
 
 static int tegra2_pll_clk_enable(struct clk *c)
@@ -411,7 +481,7 @@
 	clk_writel(val, c->reg + PLL_BASE);
 
 	val = clk_readl(c->reg + PLL_MISC(c));
-	val |= PLL_MISC_LOCK_ENABLE;
+	val |= PLL_MISC_LOCK_ENABLE(c);
 	clk_writel(val, c->reg + PLL_MISC(c));
 
 	tegra2_pll_clk_wait_for_lock(c);
@@ -441,33 +511,36 @@
 	input_rate = c->parent->rate;
 	for (sel = c->pll_table; sel->input_rate != 0; sel++) {
 		if (sel->input_rate == input_rate && sel->output_rate == rate) {
-			c->n = sel->n;
-			c->m = sel->m;
-			c->p = sel->p;
-			c->cpcon = sel->cpcon;
+			c->mul = sel->n;
+			c->div = sel->m * sel->p;
 
 			val = clk_readl(c->reg + PLL_BASE);
 			if (c->flags & PLL_FIXED)
 				val |= PLL_BASE_OVERRIDE;
 			val &= ~(PLL_BASE_DIVP_MASK | PLL_BASE_DIVN_MASK |
 				 PLL_BASE_DIVM_MASK);
-			val |= (c->m << PLL_BASE_DIVM_SHIFT) |
-				(c->n << PLL_BASE_DIVN_SHIFT);
-			BUG_ON(c->p > 2);
-			if (c->p == 2)
-				val |= 1 << PLL_BASE_DIVP_SHIFT;
+			val |= (sel->m << PLL_BASE_DIVM_SHIFT) |
+				(sel->n << PLL_BASE_DIVN_SHIFT);
+			BUG_ON(sel->p < 1 || sel->p > 2);
+			if (c->flags & PLLU) {
+				if (sel->p == 1)
+					val |= PLLU_BASE_POST_DIV;
+			} else {
+				if (sel->p == 2)
+					val |= 1 << PLL_BASE_DIVP_SHIFT;
+			}
 			clk_writel(val, c->reg + PLL_BASE);
 
 			if (c->flags & PLL_HAS_CPCON) {
-				val = c->cpcon << PLL_MISC_CPCON_SHIFT;
-				val |= PLL_MISC_LOCK_ENABLE;
+				val = clk_readl(c->reg + PLL_MISC(c));
+				val &= ~PLL_MISC_CPCON_MASK;
+				val |= sel->cpcon << PLL_MISC_CPCON_SHIFT;
 				clk_writel(val, c->reg + PLL_MISC(c));
 			}
 
 			if (c->state == ON)
 				tegra2_pll_clk_enable(c);
 
-			c->rate = rate;
 			return 0;
 		}
 	}
@@ -479,7 +552,46 @@
 	.enable			= tegra2_pll_clk_enable,
 	.disable		= tegra2_pll_clk_disable,
 	.set_rate		= tegra2_pll_clk_set_rate,
-	.recalculate_rate	= tegra2_pll_clk_recalculate_rate,
+};
+
+static void tegra2_pllx_clk_init(struct clk *c)
+{
+	tegra2_pll_clk_init(c);
+
+	if (tegra_sku_id() == 7)
+		c->max_rate = 750000000;
+}
+
+static struct clk_ops tegra_pllx_ops = {
+	.init     = tegra2_pllx_clk_init,
+	.enable   = tegra2_pll_clk_enable,
+	.disable  = tegra2_pll_clk_disable,
+	.set_rate = tegra2_pll_clk_set_rate,
+};
+
+static int tegra2_plle_clk_enable(struct clk *c)
+{
+	u32 val;
+
+	pr_debug("%s on clock %s\n", __func__, c->name);
+
+	mdelay(1);
+
+	val = clk_readl(c->reg + PLL_BASE);
+	if (!(val & PLLE_MISC_READY))
+		return -EBUSY;
+
+	val = clk_readl(c->reg + PLL_BASE);
+	val |= PLL_BASE_ENABLE | PLL_BASE_BYPASS;
+	clk_writel(val, c->reg + PLL_BASE);
+
+	return 0;
+}
+
+static struct clk_ops tegra_plle_ops = {
+	.init       = tegra2_pll_clk_init,
+	.enable     = tegra2_plle_clk_enable,
+	.set_rate   = tegra2_pll_clk_set_rate,
 };
 
 /* Clock divider ops */
@@ -503,8 +615,6 @@
 		c->div = 1;
 		c->mul = 1;
 	}
-
-	tegra2_clk_recalculate_rate(c);
 }
 
 static int tegra2_pll_div_clk_enable(struct clk *c)
@@ -565,7 +675,7 @@
 	int divider_u71;
 	pr_debug("%s: %s %lu\n", __func__, c->name, rate);
 	if (c->flags & DIV_U71) {
-		divider_u71 = clk_div71_get_divider(c->parent, rate);
+		divider_u71 = clk_div71_get_divider(c->parent->rate, rate);
 		if (divider_u71 >= 0) {
 			val = clk_readl(c->reg);
 			new_val = val >> c->reg_shift;
@@ -580,25 +690,37 @@
 			clk_writel(val, c->reg);
 			c->div = divider_u71 + 2;
 			c->mul = 2;
-			tegra2_clk_recalculate_rate(c);
 			return 0;
 		}
 	} else if (c->flags & DIV_2) {
-		if (c->parent->rate == rate * 2) {
-			c->rate = rate;
+		if (c->parent->rate == rate * 2)
 			return 0;
-		}
 	}
 	return -EINVAL;
 }
 
+static long tegra2_pll_div_clk_round_rate(struct clk *c, unsigned long rate)
+{
+	int divider;
+	pr_debug("%s: %s %lu\n", __func__, c->name, rate);
+
+	if (c->flags & DIV_U71) {
+		divider = clk_div71_get_divider(c->parent->rate, rate);
+		if (divider < 0)
+			return divider;
+		return c->parent->rate * 2 / (divider + 2);
+	} else if (c->flags & DIV_2) {
+		return c->parent->rate / 2;
+	}
+	return -EINVAL;
+}
 
 static struct clk_ops tegra_pll_div_ops = {
 	.init			= tegra2_pll_div_clk_init,
 	.enable			= tegra2_pll_div_clk_enable,
 	.disable		= tegra2_pll_div_clk_disable,
 	.set_rate		= tegra2_pll_div_clk_set_rate,
-	.recalculate_rate	= tegra2_clk_recalculate_rate,
+	.round_rate		= tegra2_pll_div_clk_round_rate,
 };
 
 /* Periph clk ops */
@@ -621,9 +743,13 @@
 	}
 
 	if (c->flags & DIV_U71) {
-		u32 divu71 = val & PERIPH_CLK_SOURCE_DIV_MASK;
+		u32 divu71 = val & PERIPH_CLK_SOURCE_DIVU71_MASK;
 		c->div = divu71 + 2;
 		c->mul = 2;
+	} else if (c->flags & DIV_U16) {
+		u32 divu16 = val & PERIPH_CLK_SOURCE_DIVU16_MASK;
+		c->div = divu16 + 1;
+		c->mul = 1;
 	} else {
 		c->div = 1;
 		c->mul = 1;
@@ -637,7 +763,6 @@
 		if (clk_readl(RST_DEVICES + PERIPH_CLK_TO_ENB_REG(c)) &
 				PERIPH_CLK_TO_ENB_BIT(c))
 			c->state = OFF;
-	tegra2_clk_recalculate_rate(c);
 }
 
 static int tegra2_periph_clk_enable(struct clk *c)
@@ -692,12 +817,19 @@
 	pr_debug("%s: %s %s\n", __func__, c->name, p->name);
 	for (sel = c->inputs; sel->input != NULL; sel++) {
 		if (sel->input == p) {
-			clk_reparent(c, p);
 			val = clk_readl(c->reg);
 			val &= ~PERIPH_CLK_SOURCE_MASK;
 			val |= (sel->value) << PERIPH_CLK_SOURCE_SHIFT;
+
+			if (c->refcnt)
+				clk_enable_locked(p);
+
 			clk_writel(val, c->reg);
-			c->rate = c->parent->rate;
+
+			if (c->refcnt && c->parent)
+				clk_disable_locked(c->parent);
+
+			clk_reparent(c, p);
 			return 0;
 		}
 	}
@@ -708,20 +840,55 @@
 static int tegra2_periph_clk_set_rate(struct clk *c, unsigned long rate)
 {
 	u32 val;
-	int divider_u71;
+	int divider;
 	pr_debug("%s: %lu\n", __func__, rate);
 	if (c->flags & DIV_U71) {
-		divider_u71 = clk_div71_get_divider(c->parent, rate);
-		if (divider_u71 >= 0) {
+		divider = clk_div71_get_divider(c->parent->rate, rate);
+		if (divider >= 0) {
 			val = clk_readl(c->reg);
-			val &= ~PERIPH_CLK_SOURCE_DIV_MASK;
-			val |= divider_u71;
+			val &= ~PERIPH_CLK_SOURCE_DIVU71_MASK;
+			val |= divider;
 			clk_writel(val, c->reg);
-			c->div = divider_u71 + 2;
+			c->div = divider + 2;
 			c->mul = 2;
-			tegra2_clk_recalculate_rate(c);
 			return 0;
 		}
+	} else if (c->flags & DIV_U16) {
+		divider = clk_div16_get_divider(c->parent->rate, rate);
+		if (divider >= 0) {
+			val = clk_readl(c->reg);
+			val &= ~PERIPH_CLK_SOURCE_DIVU16_MASK;
+			val |= divider;
+			clk_writel(val, c->reg);
+			c->div = divider + 1;
+			c->mul = 1;
+			return 0;
+		}
+	} else if (c->parent->rate <= rate) {
+		c->div = 1;
+		c->mul = 1;
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static long tegra2_periph_clk_round_rate(struct clk *c,
+	unsigned long rate)
+{
+	int divider;
+	pr_debug("%s: %s %lu\n", __func__, c->name, rate);
+
+	if (c->flags & DIV_U71) {
+		divider = clk_div71_get_divider(c->parent->rate, rate);
+		if (divider < 0)
+			return divider;
+
+		return c->parent->rate * 2 / (divider + 2);
+	} else if (c->flags & DIV_U16) {
+		divider = clk_div16_get_divider(c->parent->rate, rate);
+		if (divider < 0)
+			return divider;
+		return c->parent->rate / (divider + 1);
 	}
 	return -EINVAL;
 }
@@ -732,7 +899,7 @@
 	.disable		= &tegra2_periph_clk_disable,
 	.set_parent		= &tegra2_periph_clk_set_parent,
 	.set_rate		= &tegra2_periph_clk_set_rate,
-	.recalculate_rate	= &tegra2_clk_recalculate_rate,
+	.round_rate		= &tegra2_periph_clk_round_rate,
 };
 
 /* Clock doubler ops */
@@ -744,21 +911,108 @@
 	if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
 			PERIPH_CLK_TO_ENB_BIT(c)))
 		c->state = OFF;
-	tegra2_clk_recalculate_rate(c);
 };
 
+static int tegra2_clk_double_set_rate(struct clk *c, unsigned long rate)
+{
+	if (rate != 2 * c->parent->rate)
+		return -EINVAL;
+	c->mul = 2;
+	c->div = 1;
+	return 0;
+}
+
 static struct clk_ops tegra_clk_double_ops = {
 	.init			= &tegra2_clk_double_init,
 	.enable			= &tegra2_periph_clk_enable,
 	.disable		= &tegra2_periph_clk_disable,
-	.recalculate_rate	= &tegra2_clk_recalculate_rate,
+	.set_rate		= &tegra2_clk_double_set_rate,
+};
+
+static void tegra2_audio_sync_clk_init(struct clk *c)
+{
+	int source;
+	const struct clk_mux_sel *sel;
+	u32 val = clk_readl(c->reg);
+	c->state = (val & (1<<4)) ? OFF : ON;
+	source = val & 0xf;
+	for (sel = c->inputs; sel->input != NULL; sel++)
+		if (sel->value == source)
+			break;
+	BUG_ON(sel->input == NULL);
+	c->parent = sel->input;
+}
+
+static int tegra2_audio_sync_clk_enable(struct clk *c)
+{
+	clk_writel(0, c->reg);
+	return 0;
+}
+
+static void tegra2_audio_sync_clk_disable(struct clk *c)
+{
+	clk_writel(1, c->reg);
+}
+
+static int tegra2_audio_sync_clk_set_parent(struct clk *c, struct clk *p)
+{
+	u32 val;
+	const struct clk_mux_sel *sel;
+	for (sel = c->inputs; sel->input != NULL; sel++) {
+		if (sel->input == p) {
+			val = clk_readl(c->reg);
+			val &= ~0xf;
+			val |= sel->value;
+
+			if (c->refcnt)
+				clk_enable_locked(p);
+
+			clk_writel(val, c->reg);
+
+			if (c->refcnt && c->parent)
+				clk_disable_locked(c->parent);
+
+			clk_reparent(c, p);
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
+static int tegra2_audio_sync_clk_set_rate(struct clk *c, unsigned long rate)
+{
+	unsigned long parent_rate;
+	if (!c->parent) {
+		pr_err("%s: clock has no parent\n", __func__);
+		return -EINVAL;
+	}
+	parent_rate = c->parent->rate;
+	if (rate != parent_rate) {
+		pr_err("%s: %s/%ld differs from parent %s/%ld\n",
+			__func__,
+			c->name, rate,
+			c->parent->name, parent_rate);
+		return -EINVAL;
+	}
+	c->rate = parent_rate;
+	return 0;
+}
+
+static struct clk_ops tegra_audio_sync_clk_ops = {
+	.init       = tegra2_audio_sync_clk_init,
+	.enable     = tegra2_audio_sync_clk_enable,
+	.disable    = tegra2_audio_sync_clk_disable,
+	.set_rate   = tegra2_audio_sync_clk_set_rate,
+	.set_parent = tegra2_audio_sync_clk_set_parent,
 };
 
 /* Clock definitions */
 static struct clk tegra_clk_32k = {
 	.name = "clk_32k",
-	.rate = 32678,
+	.rate = 32768,
 	.ops  = NULL,
+	.max_rate = 32768,
 };
 
 static struct clk_pll_table tegra_pll_s_table[] = {
@@ -782,6 +1036,7 @@
 	.vco_min   = 12000000,
 	.vco_max   = 26000000,
 	.pll_table = tegra_pll_s_table,
+	.max_rate  = 26000000,
 };
 
 static struct clk_mux_sel tegra_clk_m_sel[] = {
@@ -797,6 +1052,7 @@
 	.reg       = 0x1fc,
 	.reg_mask  = (1<<28),
 	.reg_shift = 28,
+	.max_rate  = 26000000,
 };
 
 static struct clk_pll_table tegra_pll_c_table[] = {
@@ -816,6 +1072,7 @@
 	.vco_min   = 20000000,
 	.vco_max   = 1400000000,
 	.pll_table = tegra_pll_c_table,
+	.max_rate  = 600000000,
 };
 
 static struct clk tegra_pll_c_out1 = {
@@ -825,9 +1082,18 @@
 	.parent    = &tegra_pll_c,
 	.reg       = 0x84,
 	.reg_shift = 0,
+	.max_rate  = 600000000,
 };
 
 static struct clk_pll_table tegra_pll_m_table[] = {
+	{ 12000000, 666000000, 666, 12, 1, 8},
+	{ 13000000, 666000000, 666, 13, 1, 8},
+	{ 19200000, 666000000, 555, 16, 1, 8},
+	{ 26000000, 666000000, 666, 26, 1, 8},
+	{ 12000000, 600000000, 600, 12, 1, 8},
+	{ 13000000, 600000000, 600, 13, 1, 8},
+	{ 19200000, 600000000, 375, 12, 1, 6},
+	{ 26000000, 600000000, 600, 26, 1, 8},
 	{ 0, 0, 0, 0, 0, 0 },
 };
 
@@ -844,6 +1110,7 @@
 	.vco_min   = 20000000,
 	.vco_max   = 1200000000,
 	.pll_table = tegra_pll_m_table,
+	.max_rate  = 800000000,
 };
 
 static struct clk tegra_pll_m_out1 = {
@@ -853,6 +1120,7 @@
 	.parent    = &tegra_pll_m,
 	.reg       = 0x94,
 	.reg_shift = 0,
+	.max_rate  = 600000000,
 };
 
 static struct clk_pll_table tegra_pll_p_table[] = {
@@ -880,6 +1148,7 @@
 	.vco_min   = 20000000,
 	.vco_max   = 1400000000,
 	.pll_table = tegra_pll_p_table,
+	.max_rate  = 432000000,
 };
 
 static struct clk tegra_pll_p_out1 = {
@@ -889,6 +1158,7 @@
 	.parent    = &tegra_pll_p,
 	.reg       = 0xa4,
 	.reg_shift = 0,
+	.max_rate  = 432000000,
 };
 
 static struct clk tegra_pll_p_out2 = {
@@ -898,6 +1168,7 @@
 	.parent    = &tegra_pll_p,
 	.reg       = 0xa4,
 	.reg_shift = 16,
+	.max_rate  = 432000000,
 };
 
 static struct clk tegra_pll_p_out3 = {
@@ -907,6 +1178,7 @@
 	.parent    = &tegra_pll_p,
 	.reg       = 0xa8,
 	.reg_shift = 0,
+	.max_rate  = 432000000,
 };
 
 static struct clk tegra_pll_p_out4 = {
@@ -916,6 +1188,7 @@
 	.parent    = &tegra_pll_p,
 	.reg       = 0xa8,
 	.reg_shift = 16,
+	.max_rate  = 432000000,
 };
 
 static struct clk_pll_table tegra_pll_a_table[] = {
@@ -923,6 +1196,7 @@
 	{ 28800000, 73728000, 64, 25, 1, 1},
 	{ 28800000, 11289600, 49, 25, 1, 1},
 	{ 28800000, 12288000, 64, 25, 1, 1},
+	{ 28800000, 24000000,  5,  6, 1, 1},
 	{ 0, 0, 0, 0, 0, 0 },
 };
 
@@ -939,6 +1213,7 @@
 	.vco_min   = 20000000,
 	.vco_max   = 1400000000,
 	.pll_table = tegra_pll_a_table,
+	.max_rate  = 56448000,
 };
 
 static struct clk tegra_pll_a_out0 = {
@@ -948,6 +1223,7 @@
 	.parent    = &tegra_pll_a,
 	.reg       = 0xb4,
 	.reg_shift = 0,
+	.max_rate  = 56448000,
 };
 
 static struct clk_pll_table tegra_pll_d_table[] = {
@@ -971,6 +1247,7 @@
 	.vco_min   = 40000000,
 	.vco_max   = 1000000000,
 	.pll_table = tegra_pll_d_table,
+	.max_rate  = 1000000000,
 };
 
 static struct clk tegra_pll_d_out0 = {
@@ -978,19 +1255,20 @@
 	.ops       = &tegra_pll_div_ops,
 	.flags     = DIV_2 | PLLD,
 	.parent    = &tegra_pll_d,
+	.max_rate  = 500000000,
 };
 
 static struct clk_pll_table tegra_pll_u_table[] = {
-	{ 12000000, 480000000, 960, 12, 1, 0},
-	{ 13000000, 480000000, 960, 13, 1, 0},
-	{ 19200000, 480000000, 200, 4,  1, 0},
-	{ 26000000, 480000000, 960, 26, 1, 0},
+	{ 12000000, 480000000, 960, 12, 2, 0},
+	{ 13000000, 480000000, 960, 13, 2, 0},
+	{ 19200000, 480000000, 200, 4,  2, 0},
+	{ 26000000, 480000000, 960, 26, 2, 0},
 	{ 0, 0, 0, 0, 0, 0 },
 };
 
 static struct clk tegra_pll_u = {
 	.name      = "pll_u",
-	.flags     = 0,
+	.flags     = PLLU,
 	.ops       = &tegra_pll_ops,
 	.reg       = 0xc0,
 	.input_min = 2000000,
@@ -1001,24 +1279,59 @@
 	.vco_min   = 480000000,
 	.vco_max   = 960000000,
 	.pll_table = tegra_pll_u_table,
+	.max_rate  = 480000000,
 };
 
 static struct clk_pll_table tegra_pll_x_table[] = {
+	/* 1 GHz */
 	{ 12000000, 1000000000, 1000, 12, 1, 12},
 	{ 13000000, 1000000000, 1000, 13, 1, 12},
 	{ 19200000, 1000000000, 625,  12, 1, 8},
 	{ 26000000, 1000000000, 1000, 26, 1, 12},
-	{ 12000000, 750000000,  750,  12, 1, 12},
-	{ 13000000, 750000000,  750,  13, 1, 12},
-	{ 19200000, 750000000,  625,  16, 1, 8},
-	{ 26000000, 750000000,  750,  26, 1, 12},
+
+	/* 912 MHz */
+	{ 12000000, 912000000,  912,  12, 1, 12},
+	{ 13000000, 912000000,  912,  13, 1, 12},
+	{ 19200000, 912000000,  760,  16, 1, 8},
+	{ 26000000, 912000000,  912,  26, 1, 12},
+
+	/* 816 MHz */
+	{ 12000000, 816000000,  816,  12, 1, 12},
+	{ 13000000, 816000000,  816,  13, 1, 12},
+	{ 19200000, 816000000,  680,  16, 1, 8},
+	{ 26000000, 816000000,  816,  26, 1, 12},
+
+	/* 760 MHz */
+	{ 12000000, 760000000,  760,  12, 1, 12},
+	{ 13000000, 760000000,  760,  13, 1, 12},
+	{ 19200000, 760000000,  950,  24, 1, 8},
+	{ 26000000, 760000000,  760,  26, 1, 12},
+
+	/* 608 MHz */
+	{ 12000000, 608000000,  760,  12, 1, 12},
+	{ 13000000, 608000000,  760,  13, 1, 12},
+	{ 19200000, 608000000,  380,  12, 1, 8},
+	{ 26000000, 608000000,  760,  26, 1, 12},
+
+	/* 456 MHz */
+	{ 12000000, 456000000,  456,  12, 1, 12},
+	{ 13000000, 456000000,  456,  13, 1, 12},
+	{ 19200000, 456000000,  380,  16, 1, 8},
+	{ 26000000, 456000000,  456,  26, 1, 12},
+
+	/* 312 MHz */
+	{ 12000000, 312000000,  312,  12, 1, 12},
+	{ 13000000, 312000000,  312,  13, 1, 12},
+	{ 19200000, 312000000,  260,  16, 1, 8},
+	{ 26000000, 312000000,  312,  26, 1, 12},
+
 	{ 0, 0, 0, 0, 0, 0 },
 };
 
 static struct clk tegra_pll_x = {
 	.name      = "pll_x",
 	.flags     = PLL_HAS_CPCON | PLL_ALT_MISC_REG,
-	.ops       = &tegra_pll_ops,
+	.ops       = &tegra_pllx_ops,
 	.reg       = 0xe0,
 	.input_min = 2000000,
 	.input_max = 31000000,
@@ -1028,6 +1341,24 @@
 	.vco_min   = 20000000,
 	.vco_max   = 1200000000,
 	.pll_table = tegra_pll_x_table,
+	.max_rate  = 1000000000,
+};
+
+static struct clk_pll_table tegra_pll_e_table[] = {
+	{ 12000000, 100000000,  200,  24, 1, 0 },
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+static struct clk tegra_pll_e = {
+	.name      = "pll_e",
+	.flags	   = PLL_ALT_MISC_REG,
+	.ops       = &tegra_plle_ops,
+	.input_min = 12000000,
+	.input_max = 12000000,
+	.max_rate  = 100000000,
+	.parent    = &tegra_clk_m,
+	.reg       = 0xe8,
+	.pll_table = tegra_pll_e_table,
 };
 
 static struct clk tegra_clk_d = {
@@ -1038,19 +1369,77 @@
 	.reg       = 0x34,
 	.reg_shift = 12,
 	.parent    = &tegra_clk_m,
+	.max_rate  = 52000000,
 };
 
-/* FIXME: need tegra_audio
+/* initialized before peripheral clocks */
+static struct clk_mux_sel mux_audio_sync_clk[8+1];
+static const struct audio_sources {
+	const char *name;
+	int value;
+} mux_audio_sync_clk_sources[] = {
+	{ .name = "spdif_in", .value = 0 },
+	{ .name = "i2s1", .value = 1 },
+	{ .name = "i2s2", .value = 2 },
+	{ .name = "pll_a_out0", .value = 4 },
+#if 0 /* FIXME: not implemented */
+	{ .name = "ac97", .value = 3 },
+	{ .name = "ext_audio_clk2", .value = 5 },
+	{ .name = "ext_audio_clk1", .value = 6 },
+	{ .name = "ext_vimclk", .value = 7 },
+#endif
+	{ 0, 0 }
+};
+
+static struct clk tegra_clk_audio = {
+	.name      = "audio",
+	.inputs    = mux_audio_sync_clk,
+	.reg       = 0x38,
+	.max_rate  = 24000000,
+	.ops       = &tegra_audio_sync_clk_ops
+};
+
 static struct clk tegra_clk_audio_2x = {
-	.name      = "clk_d",
+	.name      = "audio_2x",
 	.flags     = PERIPH_NO_RESET,
+	.max_rate  = 48000000,
 	.ops       = &tegra_clk_double_ops,
 	.clk_num   = 89,
 	.reg       = 0x34,
 	.reg_shift = 8,
-	.parent    = &tegra_audio,
+	.parent    = &tegra_clk_audio,
+};
+
+struct clk_lookup tegra_audio_clk_lookups[] = {
+	{ .con_id = "audio", .clk = &tegra_clk_audio },
+	{ .con_id = "audio_2x", .clk = &tegra_clk_audio_2x }
+};
+
+/* This is called after peripheral clocks are initialized, as the
+ * audio_sync clock depends on some of the peripheral clocks.
+ */
+
+static void init_audio_sync_clock_mux(void)
+{
+	int i;
+	struct clk_mux_sel *sel = mux_audio_sync_clk;
+	const struct audio_sources *src = mux_audio_sync_clk_sources;
+	struct clk_lookup *lookup;
+
+	for (i = 0; src->name; i++, sel++, src++) {
+		sel->input = tegra_get_clock_by_name(src->name);
+		if (!sel->input)
+			pr_err("%s: could not find clk %s\n", __func__,
+				src->name);
+		sel->value = src->value;
+	}
+
+	lookup = tegra_audio_clk_lookups;
+	for (i = 0; i < ARRAY_SIZE(tegra_audio_clk_lookups); i++, lookup++) {
+		clk_init(lookup->clk);
+		clkdev_add(lookup);
+	}
 }
-*/
 
 static struct clk_mux_sel mux_cclk[] = {
 	{ .input = &tegra_clk_m,	.value = 0},
@@ -1077,27 +1466,40 @@
 	{ 0, 0},
 };
 
-static struct clk tegra_clk_cpu = {
-	.name	= "cpu",
+static struct clk tegra_clk_cclk = {
+	.name	= "cclk",
 	.inputs	= mux_cclk,
 	.reg	= 0x20,
 	.ops	= &tegra_super_ops,
+	.max_rate = 1000000000,
 };
 
-static struct clk tegra_clk_sys = {
-	.name	= "sys",
+static struct clk tegra_clk_sclk = {
+	.name	= "sclk",
 	.inputs	= mux_sclk,
 	.reg	= 0x28,
 	.ops	= &tegra_super_ops,
+	.max_rate = 600000000,
+};
+
+static struct clk tegra_clk_virtual_cpu = {
+	.name      = "cpu",
+	.parent    = &tegra_clk_cclk,
+	.main      = &tegra_pll_x,
+	.backup    = &tegra_clk_m,
+	.ops       = &tegra_cpu_ops,
+	.max_rate  = 1000000000,
+	.dvfs      = &tegra_dvfs_virtual_cpu_dvfs,
 };
 
 static struct clk tegra_clk_hclk = {
 	.name		= "hclk",
 	.flags		= DIV_BUS,
-	.parent		= &tegra_clk_sys,
+	.parent		= &tegra_clk_sclk,
 	.reg		= 0x30,
 	.reg_shift	= 4,
 	.ops		= &tegra_bus_ops,
+	.max_rate       = 240000000,
 };
 
 static struct clk tegra_clk_pclk = {
@@ -1107,6 +1509,7 @@
 	.reg		= 0x30,
 	.reg_shift	= 0,
 	.ops		= &tegra_bus_ops,
+	.max_rate       = 108000000,
 };
 
 static struct clk_mux_sel mux_pllm_pllc_pllp_plla[] = {
@@ -1133,10 +1536,9 @@
 	{ 0, 0},
 };
 
-static struct clk_mux_sel mux_plla_audio_pllp_clkm[] = {
-	{.input = &tegra_pll_a, .value = 0},
-	/* FIXME: no mux defined for tegra_audio
-	{.input = &tegra_audio, .value = 1},*/
+static struct clk_mux_sel mux_pllaout0_audio2x_pllp_clkm[] = {
+	{.input = &tegra_pll_a_out0, .value = 0},
+	{.input = &tegra_clk_audio_2x, .value = 1},
 	{.input = &tegra_pll_p, .value = 2},
 	{.input = &tegra_clk_m, .value = 3},
 	{ 0, 0},
@@ -1153,8 +1555,7 @@
 static struct clk_mux_sel mux_pllp_pllc_audio_clkm_clk32[] = {
 	{.input = &tegra_pll_p,     .value = 0},
 	{.input = &tegra_pll_c,     .value = 1},
-	/* FIXME: no mux defined for tegra_audio
-	{.input = &tegra_audio,     .value = 2},*/
+	{.input = &tegra_clk_audio,     .value = 2},
 	{.input = &tegra_clk_m,     .value = 3},
 	{.input = &tegra_clk_32k,   .value = 4},
 	{ 0, 0},
@@ -1187,7 +1588,7 @@
 	{ 0, 0},
 };
 
-#define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, _inputs, _flags) \
+#define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, _max, _inputs, _flags) \
 	{						\
 		.name      = _name,			\
 		.lookup    = {				\
@@ -1199,72 +1600,79 @@
 		.reg       = _reg,			\
 		.inputs    = _inputs,			\
 		.flags     = _flags,			\
+		.max_rate  = _max,			\
 	}
 
 struct clk tegra_periph_clks[] = {
-	PERIPH_CLK("rtc",	"rtc-tegra",		NULL,	4,	0,	mux_clk_32k,			PERIPH_NO_RESET),
-	PERIPH_CLK("timer",	"timer",		NULL,	5,	0,	mux_clk_m,			0),
-	PERIPH_CLK("i2s1",	"i2s.0",		NULL,	11,	0x100,	mux_plla_audio_pllp_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("i2s2",	"i2s.1",		NULL,	18,	0x104,	mux_plla_audio_pllp_clkm,	MUX | DIV_U71),
+	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),
+	PERIPH_CLK("i2s1",	"i2s.0",		NULL,	11,	0x100,	26000000,  mux_pllaout0_audio2x_pllp_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("i2s2",	"i2s.1",		NULL,	18,	0x104,	26000000,  mux_pllaout0_audio2x_pllp_clkm,	MUX | DIV_U71),
 	/* FIXME: spdif has 2 clocks but 1 enable */
-	PERIPH_CLK("spdif_out",	"spdif_out",		NULL,	10,	0x108,	mux_plla_audio_pllp_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("spdif_in",	"spdif_in",		NULL,	10,	0x10c,	mux_pllp_pllc_pllm,		MUX | DIV_U71),
-	PERIPH_CLK("pwm",	"pwm",			NULL,	17,	0x110,	mux_pllp_pllc_audio_clkm_clk32,	MUX | DIV_U71),
-	PERIPH_CLK("spi",	"spi",			NULL,	43,	0x114,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("xio",	"xio",			NULL,	45,	0x120,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("twc",	"twc",			NULL,	16,	0x12c,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("sbc1",	"spi_tegra.0",		NULL,	41,	0x134,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("sbc2",	"spi_tegra.1",		NULL,	44,	0x118,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("sbc3",	"spi_tegra.2",		NULL,	46,	0x11c,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("sbc4",	"spi_tegra.3",		NULL,	68,	0x1b4,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("ide",	"ide",			NULL,	25,	0x144,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("ndflash",	"tegra_nand",		NULL,	13,	0x160,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("spdif_out",	"spdif_out",		NULL,	10,	0x108,	100000000, mux_pllaout0_audio2x_pllp_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("spdif_in",	"spdif_in",		NULL,	10,	0x10c,	100000000, mux_pllp_pllc_pllm,		MUX | DIV_U71),
+	PERIPH_CLK("pwm",	"pwm",			NULL,	17,	0x110,	432000000, mux_pllp_pllc_audio_clkm_clk32,	MUX | DIV_U71),
+	PERIPH_CLK("spi",	"spi",			NULL,	43,	0x114,	40000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("xio",	"xio",			NULL,	45,	0x120,	150000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("twc",	"twc",			NULL,	16,	0x12c,	150000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("sbc1",	"spi_tegra.0",		NULL,	41,	0x134,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("sbc2",	"spi_tegra.1",		NULL,	44,	0x118,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("sbc3",	"spi_tegra.2",		NULL,	46,	0x11c,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("sbc4",	"spi_tegra.3",		NULL,	68,	0x1b4,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("ide",	"ide",			NULL,	25,	0x144,	100000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* requires min voltage */
+	PERIPH_CLK("ndflash",	"tegra_nand",		NULL,	13,	0x160,	164000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
 	/* FIXME: vfir shares an enable with uartb */
-	PERIPH_CLK("vfir",	"vfir",			NULL,	7,	0x168,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("sdmmc1",	"sdhci-tegra.0",	NULL,	14,	0x150,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("sdmmc2",	"sdhci-tegra.1",	NULL,	9,	0x154,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("sdmmc3",	"sdhci-tegra.2",	NULL,	69,	0x1bc,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("sdmmc4",	"sdhci-tegra.3",	NULL,	15,	0x160,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("vde",	"vde",			NULL,	61,	0x1c8,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("csite",	"csite",		NULL,	73,	0x1d4,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("vfir",	"vfir",			NULL,	7,	0x168,	72000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("sdmmc1",	"sdhci-tegra.0",	NULL,	14,	0x150,	52000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
+	PERIPH_CLK("sdmmc2",	"sdhci-tegra.1",	NULL,	9,	0x154,	52000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
+	PERIPH_CLK("sdmmc3",	"sdhci-tegra.2",	NULL,	69,	0x1bc,	52000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
+	PERIPH_CLK("sdmmc4",	"sdhci-tegra.3",	NULL,	15,	0x160,	52000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
+	PERIPH_CLK("vde",	"vde",			NULL,	61,	0x1c8,	250000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage and process_id */
+	PERIPH_CLK("csite",	"csite",		NULL,	73,	0x1d4,	144000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* max rate ??? */
 	/* FIXME: what is la? */
-	PERIPH_CLK("la",	"la",			NULL,	76,	0x1f8,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("owr",	"owr",			NULL,	71,	0x1cc,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("nor",	"nor",			NULL,	42,	0x1d0,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("mipi",	"mipi",			NULL,	50,	0x174,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("i2c1",	"tegra-i2c.0",		NULL,	12,	0x124,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("i2c2",	"tegra-i2c.1",		NULL,	54,	0x198,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("i2c3",	"tegra-i2c.2",		NULL,	67,	0x1b8,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("dvc",	"tegra-i2c.3",		NULL,	47,	0x128,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("i2c1_i2c",	"tegra-i2c.0",		"i2c",	0,	0,	mux_pllp_out3,			0),
-	PERIPH_CLK("i2c2_i2c",	"tegra-i2c.1",		"i2c",	0,	0,	mux_pllp_out3,			0),
-	PERIPH_CLK("i2c3_i2c",	"tegra-i2c.2",		"i2c",	0,	0,	mux_pllp_out3,			0),
-	PERIPH_CLK("dvc_i2c",	"tegra-i2c.3",		"i2c",	0,	0,	mux_pllp_out3,			0),
-	PERIPH_CLK("uarta",	"uart.0",		NULL,	6,	0x178,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("uartb",	"uart.1",		NULL,	7,	0x17c,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("uartc",	"uart.2",		NULL,	55,	0x1a0,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("uartd",	"uart.3",		NULL,	65,	0x1c0,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("uarte",	"uart.4",		NULL,	66,	0x1c4,	mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("3d",	"3d",			NULL,	24,	0x158,	mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | PERIPH_MANUAL_RESET),
-	PERIPH_CLK("2d",	"2d",			NULL,	21,	0x15c,	mux_pllm_pllc_pllp_plla,	MUX | DIV_U71),
+	PERIPH_CLK("la",	"la",			NULL,	76,	0x1f8,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("owr",	"tegra_w1",		NULL,	71,	0x1cc,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("nor",	"nor",			NULL,	42,	0x1d0,	92000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* requires min voltage */
+	PERIPH_CLK("mipi",	"mipi",			NULL,	50,	0x174,	60000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
+	PERIPH_CLK("i2c1",	"tegra-i2c.0",		NULL,	12,	0x124,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U16),
+	PERIPH_CLK("i2c2",	"tegra-i2c.1",		NULL,	54,	0x198,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U16),
+	PERIPH_CLK("i2c3",	"tegra-i2c.2",		NULL,	67,	0x1b8,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U16),
+	PERIPH_CLK("dvc",	"tegra-i2c.3",		NULL,	47,	0x128,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U16),
+	PERIPH_CLK("i2c1_i2c",	"tegra-i2c.0",		"i2c",	0,	0,	72000000,  mux_pllp_out3,			0),
+	PERIPH_CLK("i2c2_i2c",	"tegra-i2c.1",		"i2c",	0,	0,	72000000,  mux_pllp_out3,			0),
+	PERIPH_CLK("i2c3_i2c",	"tegra-i2c.2",		"i2c",	0,	0,	72000000,  mux_pllp_out3,			0),
+	PERIPH_CLK("dvc_i2c",	"tegra-i2c.3",		"i2c",	0,	0,	72000000,  mux_pllp_out3,			0),
+	PERIPH_CLK("uarta",	"uart.0",		NULL,	6,	0x178,	216000000, mux_pllp_pllc_pllm_clkm,	MUX),
+	PERIPH_CLK("uartb",	"uart.1",		NULL,	7,	0x17c,	216000000, mux_pllp_pllc_pllm_clkm,	MUX),
+	PERIPH_CLK("uartc",	"uart.2",		NULL,	55,	0x1a0,	216000000, mux_pllp_pllc_pllm_clkm,	MUX),
+	PERIPH_CLK("uartd",	"uart.3",		NULL,	65,	0x1c0,	216000000, mux_pllp_pllc_pllm_clkm,	MUX),
+	PERIPH_CLK("uarte",	"uart.4",		NULL,	66,	0x1c4,	216000000, mux_pllp_pllc_pllm_clkm,	MUX),
+	PERIPH_CLK("3d",	"3d",			NULL,	24,	0x158,	300000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | PERIPH_MANUAL_RESET), /* scales with voltage and process_id */
+	PERIPH_CLK("2d",	"2d",			NULL,	21,	0x15c,	300000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71), /* scales with voltage and process_id */
 	/* FIXME: vi and vi_sensor share an enable */
-	PERIPH_CLK("vi",	"vi",			NULL,	20,	0x148,	mux_pllm_pllc_pllp_plla,	MUX | DIV_U71),
-	PERIPH_CLK("vi_sensor",	"vi_sensor",		NULL,	20,	0x1a8,	mux_pllm_pllc_pllp_plla,	MUX | DIV_U71),
-	PERIPH_CLK("epp",	"epp",			NULL,	19,	0x16c,	mux_pllm_pllc_pllp_plla,	MUX | DIV_U71),
-	PERIPH_CLK("mpe",	"mpe",			NULL,	60,	0x170,	mux_pllm_pllc_pllp_plla,	MUX | DIV_U71),
-	PERIPH_CLK("host1x",	"host1x",		NULL,	28,	0x180,	mux_pllm_pllc_pllp_plla,	MUX | DIV_U71),
+	PERIPH_CLK("vi",	"vi",			NULL,	20,	0x148,	150000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71), /* scales with voltage and process_id */
+	PERIPH_CLK("vi_sensor",	"vi_sensor",		NULL,	20,	0x1a8,	150000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | PERIPH_NO_RESET), /* scales with voltage and process_id */
+	PERIPH_CLK("epp",	"epp",			NULL,	19,	0x16c,	300000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71), /* scales with voltage and process_id */
+	PERIPH_CLK("mpe",	"mpe",			NULL,	60,	0x170,	250000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71), /* scales with voltage and process_id */
+	PERIPH_CLK("host1x",	"host1x",		NULL,	28,	0x180,	166000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71), /* scales with voltage and process_id */
 	/* FIXME: cve and tvo share an enable	*/
-	PERIPH_CLK("cve",	"cve",			NULL,	49,	0x140,	mux_pllp_plld_pllc_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("tvo",	"tvo",			NULL,	49,	0x188,	mux_pllp_plld_pllc_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("hdmi",	"hdmi",			NULL,	51,	0x18c,	mux_pllp_plld_pllc_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("tvdac",	"tvdac",		NULL,	53,	0x194,	mux_pllp_plld_pllc_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("disp1",	"tegrafb.0",		NULL,	27,	0x138,	mux_pllp_plld_pllc_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("disp2",	"tegrafb.1",		NULL,	26,	0x13c,	mux_pllp_plld_pllc_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("usbd",	"fsl-tegra-udc",	NULL,	22,	0,	mux_clk_m,			0),
-	PERIPH_CLK("usb2",	"usb.1",		NULL,	58,	0,	mux_clk_m,			0),
-	PERIPH_CLK("usb3",	"usb.2",		NULL,	59,	0,	mux_clk_m,			0),
-	PERIPH_CLK("emc",	"emc",			NULL,	57,	0x19c,	mux_pllm_pllc_pllp_clkm,	MUX | DIV_U71 | PERIPH_EMC_ENB),
-	PERIPH_CLK("dsi",	"dsi",			NULL,	48,	0,	mux_plld,			0),
+	PERIPH_CLK("cve",	"cve",			NULL,	49,	0x140,	250000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* requires min voltage */
+	PERIPH_CLK("tvo",	"tvo",			NULL,	49,	0x188,	250000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* requires min voltage */
+	PERIPH_CLK("hdmi",	"hdmi",			NULL,	51,	0x18c,	148500000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* requires min voltage */
+	PERIPH_CLK("tvdac",	"tvdac",		NULL,	53,	0x194,	250000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* requires min voltage */
+	PERIPH_CLK("disp1",	"tegrafb.0",		NULL,	27,	0x138,	190000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* scales with voltage and process_id */
+	PERIPH_CLK("disp2",	"tegrafb.1",		NULL,	26,	0x13c,	190000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* scales with voltage and process_id */
+	PERIPH_CLK("usbd",	"fsl-tegra-udc",	NULL,	22,	0,	480000000, mux_clk_m,			0), /* requires min voltage */
+	PERIPH_CLK("usb2",	"tegra-ehci.1",		NULL,	58,	0,	480000000, mux_clk_m,			0), /* requires min voltage */
+	PERIPH_CLK("usb3",	"tegra-ehci.2",		NULL,	59,	0,	480000000, mux_clk_m,			0), /* requires min voltage */
+	PERIPH_CLK("emc",	"emc",			NULL,	57,	0x19c,	800000000, mux_pllm_pllc_pllp_clkm,	MUX | DIV_U71 | PERIPH_EMC_ENB),
+	PERIPH_CLK("dsi",	"dsi",			NULL,	48,	0,	500000000, mux_plld,			0), /* scales with voltage */
+	PERIPH_CLK("csi",	"csi",			NULL,	52,	0,	72000000,  mux_pllp_out3,		0),
+	PERIPH_CLK("isp",	"isp",			NULL,	23,	0,	150000000, mux_clk_m,			0), /* same frequency as VI */
+	PERIPH_CLK("csus",	"csus",			NULL,	92,	0,	150000000, mux_clk_m,			PERIPH_NO_RESET),
+	PERIPH_CLK("pex",       NULL,			"pex",  70,     0,	26000000,  mux_clk_m,			PERIPH_MANUAL_RESET),
+	PERIPH_CLK("afi",       NULL,			"afi",  72,     0,	26000000,  mux_clk_m,			PERIPH_MANUAL_RESET),
+	PERIPH_CLK("pcie_xclk", NULL,		  "pcie_xclk",  74,     0,	26000000,  mux_clk_m,			PERIPH_MANUAL_RESET),
 };
 
 #define CLK_DUPLICATE(_name, _dev, _con)		\
@@ -1286,6 +1694,9 @@
 	CLK_DUPLICATE("uartc",	"tegra_uart.2",	NULL),
 	CLK_DUPLICATE("uartd",	"tegra_uart.3",	NULL),
 	CLK_DUPLICATE("uarte",	"tegra_uart.4",	NULL),
+	CLK_DUPLICATE("host1x", "tegrafb.0", "host1x"),
+	CLK_DUPLICATE("host1x", "tegrafb.1", "host1x"),
+	CLK_DUPLICATE("usbd", "tegra-ehci.0", NULL),
 };
 
 #define CLK(dev, con, ck)	\
@@ -1315,11 +1726,13 @@
 	CLK(NULL,	"pll_d_out0",	&tegra_pll_d_out0),
 	CLK(NULL,	"pll_u",	&tegra_pll_u),
 	CLK(NULL,	"pll_x",	&tegra_pll_x),
-	CLK(NULL,	"cpu",		&tegra_clk_cpu),
-	CLK(NULL,	"sys",		&tegra_clk_sys),
+	CLK(NULL,	"pll_e",	&tegra_pll_e),
+	CLK(NULL,	"cclk",		&tegra_clk_cclk),
+	CLK(NULL,	"sclk",		&tegra_clk_sclk),
 	CLK(NULL,	"hclk",		&tegra_clk_hclk),
 	CLK(NULL,	"pclk",		&tegra_clk_pclk),
 	CLK(NULL,	"clk_d",	&tegra_clk_d),
+	CLK(NULL,	"cpu",		&tegra_clk_virtual_cpu),
 };
 
 void __init tegra2_init_clocks(void)
@@ -1356,4 +1769,75 @@
 				cd->name);
 		}
 	}
+
+	init_audio_sync_clock_mux();
 }
+
+#ifdef CONFIG_PM
+static u32 clk_rst_suspend[RST_DEVICES_NUM + CLK_OUT_ENB_NUM +
+			   PERIPH_CLK_SOURCE_NUM + 3];
+
+void tegra_clk_suspend(void)
+{
+	unsigned long off, i;
+	u32 *ctx = clk_rst_suspend;
+
+	*ctx++ = clk_readl(OSC_CTRL) & OSC_CTRL_MASK;
+
+	for (off = PERIPH_CLK_SOURCE_I2S1; off <= PERIPH_CLK_SOURCE_OSC;
+			off += 4) {
+		if (off == PERIPH_CLK_SOURCE_EMC)
+			continue;
+		*ctx++ = clk_readl(off);
+	}
+
+	off = RST_DEVICES;
+	for (i = 0; i < RST_DEVICES_NUM; i++, off += 4)
+		*ctx++ = clk_readl(off);
+
+	off = CLK_OUT_ENB;
+	for (i = 0; i < CLK_OUT_ENB_NUM; i++, off += 4)
+		*ctx++ = clk_readl(off);
+
+	*ctx++ = clk_readl(MISC_CLK_ENB);
+	*ctx++ = clk_readl(CLK_MASK_ARM);
+}
+
+void tegra_clk_resume(void)
+{
+	unsigned long off, i;
+	const u32 *ctx = clk_rst_suspend;
+	u32 val;
+
+	val = clk_readl(OSC_CTRL) & ~OSC_CTRL_MASK;
+	val |= *ctx++;
+	clk_writel(val, OSC_CTRL);
+
+	/* enable all clocks before configuring clock sources */
+	clk_writel(0xbffffff9ul, CLK_OUT_ENB);
+	clk_writel(0xfefffff7ul, CLK_OUT_ENB + 4);
+	clk_writel(0x77f01bfful, CLK_OUT_ENB + 8);
+	wmb();
+
+	for (off = PERIPH_CLK_SOURCE_I2S1; off <= PERIPH_CLK_SOURCE_OSC;
+			off += 4) {
+		if (off == PERIPH_CLK_SOURCE_EMC)
+			continue;
+		clk_writel(*ctx++, off);
+	}
+	wmb();
+
+	off = RST_DEVICES;
+	for (i = 0; i < RST_DEVICES_NUM; i++, off += 4)
+		clk_writel(*ctx++, off);
+	wmb();
+
+	off = CLK_OUT_ENB;
+	for (i = 0; i < CLK_OUT_ENB_NUM; i++, off += 4)
+		clk_writel(*ctx++, off);
+	wmb();
+
+	clk_writel(*ctx++, MISC_CLK_ENB);
+	clk_writel(*ctx++, CLK_MASK_ARM);
+}
+#endif
diff --git a/arch/arm/mach-tegra/tegra2_dvfs.c b/arch/arm/mach-tegra/tegra2_dvfs.c
new file mode 100644
index 0000000..5529c23
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra2_dvfs.c
@@ -0,0 +1,86 @@
+/*
+ * arch/arm/mach-tegra/tegra2_dvfs.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+
+#include "clock.h"
+#include "tegra2_dvfs.h"
+
+static struct dvfs_table virtual_cpu_process_0[] = {
+	{314000000,  750},
+	{456000000,  825},
+	{608000000,  900},
+	{760000000,  975},
+	{817000000,  1000},
+	{912000000,  1050},
+	{1000000000, 1100},
+	{0, 0},
+};
+
+static struct dvfs_table virtual_cpu_process_1[] = {
+	{314000000,  750},
+	{456000000,  825},
+	{618000000,  900},
+	{770000000,  975},
+	{827000000,  1000},
+	{922000000,  1050},
+	{1000000000, 1100},
+	{0, 0},
+};
+
+static struct dvfs_table virtual_cpu_process_2[] = {
+	{494000000,  750},
+	{675000000,  825},
+	{817000000,  875},
+	{922000000,  925},
+	{1000000000, 975},
+	{0, 0},
+};
+
+static struct dvfs_table virtual_cpu_process_3[] = {
+	{730000000,  750},
+	{760000000,  775},
+	{845000000,  800},
+	{1000000000, 875},
+	{0, 0},
+};
+
+struct dvfs tegra_dvfs_virtual_cpu_dvfs = {
+	.reg_id = "vdd_cpu",
+	.process_id_table = {
+		{
+			.process_id = 0,
+			.table = virtual_cpu_process_0,
+		},
+		{
+			.process_id = 1,
+			.table = virtual_cpu_process_1,
+		},
+		{
+			.process_id = 2,
+			.table = virtual_cpu_process_2,
+		},
+		{
+			.process_id = 3,
+			.table = virtual_cpu_process_3,
+		},
+	},
+	.process_id_table_length = 4,
+	.cpu = 1,
+};
diff --git a/arch/arm/mach-tegra/tegra2_dvfs.h b/arch/arm/mach-tegra/tegra2_dvfs.h
new file mode 100644
index 0000000..f8c1adb
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra2_dvfs.h
@@ -0,0 +1,20 @@
+/*
+ * arch/arm/mach-tegra/tegra2_dvfs.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+extern struct dvfs tegra_dvfs_virtual_cpu_dvfs;
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
index 8440d95..c493d72 100644
--- a/arch/arm/mm/fault-armv.c
+++ b/arch/arm/mm/fault-armv.c
@@ -89,13 +89,13 @@
 	 * open-code the spin-locking.
 	 */
 	ptl = pte_lockptr(vma->vm_mm, pmd);
-	pte = pte_offset_map_nested(pmd, address);
+	pte = pte_offset_map(pmd, address);
 	spin_lock(ptl);
 
 	ret = do_adjust_pte(vma, address, pfn, pte);
 
 	spin_unlock(ptl);
-	pte_unmap_nested(pte);
+	pte_unmap(pte);
 
 	return ret;
 }
diff --git a/arch/arm/mm/highmem.c b/arch/arm/mm/highmem.c
index 1fbdb55..c00f119 100644
--- a/arch/arm/mm/highmem.c
+++ b/arch/arm/mm/highmem.c
@@ -36,18 +36,17 @@
 }
 EXPORT_SYMBOL(kunmap);
 
-void *kmap_atomic(struct page *page, enum km_type type)
+void *__kmap_atomic(struct page *page)
 {
 	unsigned int idx;
 	unsigned long vaddr;
 	void *kmap;
+	int type;
 
 	pagefault_disable();
 	if (!PageHighMem(page))
 		return page_address(page);
 
-	debug_kmap_atomic(type);
-
 #ifdef CONFIG_DEBUG_HIGHMEM
 	/*
 	 * There is no cache coherency issue when non VIVT, so force the
@@ -61,6 +60,8 @@
 	if (kmap)
 		return kmap;
 
+	type = kmap_atomic_idx_push();
+
 	idx = type + KM_TYPE_NR * smp_processor_id();
 	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
 #ifdef CONFIG_DEBUG_HIGHMEM
@@ -80,14 +81,17 @@
 
 	return (void *)vaddr;
 }
-EXPORT_SYMBOL(kmap_atomic);
+EXPORT_SYMBOL(__kmap_atomic);
 
-void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type)
+void __kunmap_atomic(void *kvaddr)
 {
 	unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
-	unsigned int idx = type + KM_TYPE_NR * smp_processor_id();
+	int idx, type;
 
 	if (kvaddr >= (void *)FIXADDR_START) {
+		type = kmap_atomic_idx_pop();
+		idx = type + KM_TYPE_NR * smp_processor_id();
+
 		if (cache_is_vivt())
 			__cpuc_flush_dcache_area((void *)vaddr, PAGE_SIZE);
 #ifdef CONFIG_DEBUG_HIGHMEM
@@ -103,15 +107,16 @@
 	}
 	pagefault_enable();
 }
-EXPORT_SYMBOL(kunmap_atomic_notypecheck);
+EXPORT_SYMBOL(__kunmap_atomic);
 
-void *kmap_atomic_pfn(unsigned long pfn, enum km_type type)
+void *kmap_atomic_pfn(unsigned long pfn)
 {
-	unsigned int idx;
 	unsigned long vaddr;
+	int idx, type;
 
 	pagefault_disable();
 
+	type = kmap_atomic_idx_push();
 	idx = type + KM_TYPE_NR * smp_processor_id();
 	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
 #ifdef CONFIG_DEBUG_HIGHMEM
diff --git a/arch/arm/mm/pgd.c b/arch/arm/mm/pgd.c
index be5f58e..69bbfc6 100644
--- a/arch/arm/mm/pgd.c
+++ b/arch/arm/mm/pgd.c
@@ -57,9 +57,9 @@
 			goto no_pte;
 
 		init_pmd = pmd_offset(init_pgd, 0);
-		init_pte = pte_offset_map_nested(init_pmd, 0);
+		init_pte = pte_offset_map(init_pmd, 0);
 		set_pte_ext(new_pte, *init_pte, 0);
-		pte_unmap_nested(init_pte);
+		pte_unmap(init_pte);
 		pte_unmap(new_pte);
 	}
 
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index a92cb49..92c5bb7 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -19,7 +19,7 @@
 	bool "TI OMAP2/3/4"
 	select COMMON_CLKDEV
 	help
-	  "Systems based on omap24xx, omap34xx or omap44xx"
+	  "Systems based on OMAP2, OMAP3 or OMAP4"
 
 endchoice
 
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index 9405831..a4a1285 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -4,7 +4,7 @@
 
 # Common support
 obj-y := common.o sram.o clock.o devices.o dma.o mux.o gpio.o \
-	 usb.o fb.o io.o
+	 usb.o fb.o io.o counter_32k.o
 obj-m :=
 obj-n :=
 obj-  :=
@@ -31,4 +31,4 @@
 # OMAP mailbox framework
 obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox.o
 
-obj-$(CONFIG_OMAP_PM_NOOP) += omap-pm-noop.o
\ No newline at end of file
+obj-$(CONFIG_OMAP_PM_NOOP) += omap-pm-noop.o
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index 7190cbd..fc62fb5 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -60,7 +60,7 @@
 
 	spin_lock_irqsave(&clockfw_lock, flags);
 	if (clk->usecount == 0) {
-		printk(KERN_ERR "Trying disable clock %s with 0 usecount\n",
+		pr_err("Trying disable clock %s with 0 usecount\n",
 		       clk->name);
 		WARN_ON(1);
 		goto out;
@@ -397,6 +397,7 @@
 	struct clk *ck;
 	unsigned long flags;
 
+	pr_info("clock: disabling unused clocks to save power\n");
 	list_for_each_entry(ck, &clocks, node) {
 		if (ck->ops == &clkops_null)
 			continue;
@@ -418,7 +419,7 @@
 int __init clk_init(struct clk_functions * custom_clocks)
 {
 	if (!custom_clocks) {
-		printk(KERN_ERR "No custom clock functions registered\n");
+		pr_err("No custom clock functions registered\n");
 		BUG();
 	}
 
diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c
index 3008e71..221a675 100644
--- a/arch/arm/plat-omap/common.c
+++ b/arch/arm/plat-omap/common.c
@@ -11,38 +11,15 @@
  * 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/delay.h>
-#include <linux/console.h>
-#include <linux/serial.h>
-#include <linux/tty.h>
-#include <linux/serial_8250.h>
-#include <linux/serial_reg.h>
-#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/omapfb.h>
 
-#include <mach/hardware.h>
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/mach/map.h>
-#include <asm/setup.h>
-
 #include <plat/common.h>
 #include <plat/board.h>
-#include <plat/control.h>
-#include <plat/mux.h>
-#include <plat/fpga.h>
-#include <plat/serial.h>
 #include <plat/vram.h>
 
-#include <plat/clock.h>
-
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-# include "../mach-omap2/sdrc.h"
-#endif
 
 #define NO_LENGTH_CHECK 0xffffffff
 
@@ -88,270 +65,3 @@
 	omapfb_reserve_sdram_memblock();
 	omap_vram_reserve_sdram_memblock();
 }
-
-/*
- * 32KHz clocksource ... always available, on pretty most chips except
- * OMAP 730 and 1510.  Other timers could be used as clocksources, with
- * higher resolution in free-running counter modes (e.g. 12 MHz xtal),
- * but systems won't necessarily want to spend resources that way.
- */
-
-#define OMAP16XX_TIMER_32K_SYNCHRONIZED		0xfffbc410
-
-#if !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX))
-
-#include <linux/clocksource.h>
-
-/*
- * offset_32k holds the init time counter value. It is then subtracted
- * from every counter read to achieve a counter that counts time from the
- * kernel boot (needed for sched_clock()).
- */
-static u32 offset_32k __read_mostly;
-
-#ifdef CONFIG_ARCH_OMAP16XX
-static cycle_t omap16xx_32k_read(struct clocksource *cs)
-{
-	return omap_readl(OMAP16XX_TIMER_32K_SYNCHRONIZED) - offset_32k;
-}
-#else
-#define omap16xx_32k_read	NULL
-#endif
-
-#ifdef CONFIG_ARCH_OMAP2420
-static cycle_t omap2420_32k_read(struct clocksource *cs)
-{
-	return omap_readl(OMAP2420_32KSYNCT_BASE + 0x10) - offset_32k;
-}
-#else
-#define omap2420_32k_read	NULL
-#endif
-
-#ifdef CONFIG_ARCH_OMAP2430
-static cycle_t omap2430_32k_read(struct clocksource *cs)
-{
-	return omap_readl(OMAP2430_32KSYNCT_BASE + 0x10) - offset_32k;
-}
-#else
-#define omap2430_32k_read	NULL
-#endif
-
-#ifdef CONFIG_ARCH_OMAP3
-static cycle_t omap34xx_32k_read(struct clocksource *cs)
-{
-	return omap_readl(OMAP3430_32KSYNCT_BASE + 0x10) - offset_32k;
-}
-#else
-#define omap34xx_32k_read	NULL
-#endif
-
-#ifdef CONFIG_ARCH_OMAP4
-static cycle_t omap44xx_32k_read(struct clocksource *cs)
-{
-	return omap_readl(OMAP4430_32KSYNCT_BASE + 0x10) - offset_32k;
-}
-#else
-#define omap44xx_32k_read	NULL
-#endif
-
-/*
- * Kernel assumes that sched_clock can be called early but may not have
- * things ready yet.
- */
-static cycle_t omap_32k_read_dummy(struct clocksource *cs)
-{
-	return 0;
-}
-
-static struct clocksource clocksource_32k = {
-	.name		= "32k_counter",
-	.rating		= 250,
-	.read		= omap_32k_read_dummy,
-	.mask		= CLOCKSOURCE_MASK(32),
-	.shift		= 10,
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-/*
- * Returns current time from boot in nsecs. It's OK for this to wrap
- * around for now, as it's just a relative time stamp.
- */
-unsigned long long sched_clock(void)
-{
-	return clocksource_cyc2ns(clocksource_32k.read(&clocksource_32k),
-				  clocksource_32k.mult, clocksource_32k.shift);
-}
-
-/**
- * read_persistent_clock -  Return time from a persistent clock.
- *
- * Reads the time from a source which isn't disabled during PM, the
- * 32k sync timer.  Convert the cycles elapsed since last read into
- * nsecs and adds to a monotonically increasing timespec.
- */
-static struct timespec persistent_ts;
-static cycles_t cycles, last_cycles;
-void read_persistent_clock(struct timespec *ts)
-{
-	unsigned long long nsecs;
-	cycles_t delta;
-	struct timespec *tsp = &persistent_ts;
-
-	last_cycles = cycles;
-	cycles = clocksource_32k.read(&clocksource_32k);
-	delta = cycles - last_cycles;
-
-	nsecs = clocksource_cyc2ns(delta,
-				   clocksource_32k.mult, clocksource_32k.shift);
-
-	timespec_add_ns(tsp, nsecs);
-	*ts = *tsp;
-}
-
-static int __init omap_init_clocksource_32k(void)
-{
-	static char err[] __initdata = KERN_ERR
-			"%s: can't register clocksource!\n";
-
-	if (cpu_is_omap16xx() || cpu_class_is_omap2()) {
-		struct clk *sync_32k_ick;
-
-		if (cpu_is_omap16xx())
-			clocksource_32k.read = omap16xx_32k_read;
-		else if (cpu_is_omap2420())
-			clocksource_32k.read = omap2420_32k_read;
-		else if (cpu_is_omap2430())
-			clocksource_32k.read = omap2430_32k_read;
-		else if (cpu_is_omap34xx())
-			clocksource_32k.read = omap34xx_32k_read;
-		else if (cpu_is_omap44xx())
-			clocksource_32k.read = omap44xx_32k_read;
-		else
-			return -ENODEV;
-
-		sync_32k_ick = clk_get(NULL, "omap_32ksync_ick");
-		if (sync_32k_ick)
-			clk_enable(sync_32k_ick);
-
-		clocksource_32k.mult = clocksource_hz2mult(32768,
-					    clocksource_32k.shift);
-
-		offset_32k = clocksource_32k.read(&clocksource_32k);
-
-		if (clocksource_register(&clocksource_32k))
-			printk(err, clocksource_32k.name);
-	}
-	return 0;
-}
-arch_initcall(omap_init_clocksource_32k);
-
-#endif	/* !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX)) */
-
-/* Global address base setup code */
-
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-
-static void __init __omap2_set_globals(struct omap_globals *omap2_globals)
-{
-	omap2_set_globals_tap(omap2_globals);
-	omap2_set_globals_sdrc(omap2_globals);
-	omap2_set_globals_control(omap2_globals);
-	omap2_set_globals_prcm(omap2_globals);
-	omap2_set_globals_uart(omap2_globals);
-}
-
-#endif
-
-#if defined(CONFIG_ARCH_OMAP2420)
-
-static struct omap_globals omap242x_globals = {
-	.class	= OMAP242X_CLASS,
-	.tap	= OMAP2_L4_IO_ADDRESS(0x48014000),
-	.sdrc	= OMAP2420_SDRC_BASE,
-	.sms	= OMAP2420_SMS_BASE,
-	.ctrl	= OMAP2420_CTRL_BASE,
-	.prm	= OMAP2420_PRM_BASE,
-	.cm	= OMAP2420_CM_BASE,
-	.uart1_phys	= OMAP2_UART1_BASE,
-	.uart2_phys	= OMAP2_UART2_BASE,
-	.uart3_phys	= OMAP2_UART3_BASE,
-};
-
-void __init omap2_set_globals_242x(void)
-{
-	__omap2_set_globals(&omap242x_globals);
-}
-#endif
-
-#if defined(CONFIG_ARCH_OMAP2430)
-
-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,
-	.uart1_phys	= OMAP2_UART1_BASE,
-	.uart2_phys	= OMAP2_UART2_BASE,
-	.uart3_phys	= OMAP2_UART3_BASE,
-};
-
-void __init omap2_set_globals_243x(void)
-{
-	__omap2_set_globals(&omap243x_globals);
-}
-#endif
-
-#if defined(CONFIG_ARCH_OMAP3)
-
-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,
-	.uart1_phys	= OMAP3_UART1_BASE,
-	.uart2_phys	= OMAP3_UART2_BASE,
-	.uart3_phys	= OMAP3_UART3_BASE,
-	.uart4_phys	= OMAP3_UART4_BASE,	/* Only on 3630 */
-};
-
-void __init omap2_set_globals_3xxx(void)
-{
-	__omap2_set_globals(&omap3_globals);
-}
-
-void __init omap3_map_io(void)
-{
-	omap2_set_globals_3xxx();
-	omap34xx_map_common_io();
-}
-#endif
-
-#if defined(CONFIG_ARCH_OMAP4)
-static struct omap_globals omap4_globals = {
-	.class	= OMAP443X_CLASS,
-	.tap	= OMAP2_L4_IO_ADDRESS(OMAP443X_SCM_BASE),
-	.ctrl	= OMAP443X_CTRL_BASE,
-	.prm	= OMAP4430_PRM_BASE,
-	.cm	= OMAP4430_CM_BASE,
-	.cm2	= OMAP4430_CM2_BASE,
-	.uart1_phys	= OMAP4_UART1_BASE,
-	.uart2_phys	= OMAP4_UART2_BASE,
-	.uart3_phys	= OMAP4_UART3_BASE,
-	.uart4_phys	= OMAP4_UART4_BASE,
-};
-
-void __init omap2_set_globals_443x(void)
-{
-	omap2_set_globals_tap(&omap4_globals);
-	omap2_set_globals_control(&omap4_globals);
-	omap2_set_globals_prcm(&omap4_globals);
-	omap2_set_globals_uart(&omap4_globals);
-}
-#endif
-
diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c
new file mode 100644
index 0000000..155fe43
--- /dev/null
+++ b/arch/arm/plat-omap/counter_32k.c
@@ -0,0 +1,183 @@
+/*
+ * OMAP 32ksynctimer/counter_32k-related code
+ *
+ * Copyright (C) 2009 Texas Instruments
+ * Copyright (C) 2010 Nokia Corporation
+ * Tony Lindgren <tony@atomide.com>
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@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.
+ *
+ * NOTE: This timer is not the same timer as the old OMAP1 MPU timer.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <plat/common.h>
+#include <plat/board.h>
+
+#include <plat/clock.h>
+
+
+/*
+ * 32KHz clocksource ... always available, on pretty most chips except
+ * OMAP 730 and 1510.  Other timers could be used as clocksources, with
+ * higher resolution in free-running counter modes (e.g. 12 MHz xtal),
+ * but systems won't necessarily want to spend resources that way.
+ */
+
+#define OMAP16XX_TIMER_32K_SYNCHRONIZED		0xfffbc410
+
+#if !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX))
+
+#include <linux/clocksource.h>
+
+/*
+ * offset_32k holds the init time counter value. It is then subtracted
+ * from every counter read to achieve a counter that counts time from the
+ * kernel boot (needed for sched_clock()).
+ */
+static u32 offset_32k __read_mostly;
+
+#ifdef CONFIG_ARCH_OMAP16XX
+static cycle_t omap16xx_32k_read(struct clocksource *cs)
+{
+	return omap_readl(OMAP16XX_TIMER_32K_SYNCHRONIZED) - offset_32k;
+}
+#else
+#define omap16xx_32k_read	NULL
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2420
+static cycle_t omap2420_32k_read(struct clocksource *cs)
+{
+	return omap_readl(OMAP2420_32KSYNCT_BASE + 0x10) - offset_32k;
+}
+#else
+#define omap2420_32k_read	NULL
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2430
+static cycle_t omap2430_32k_read(struct clocksource *cs)
+{
+	return omap_readl(OMAP2430_32KSYNCT_BASE + 0x10) - offset_32k;
+}
+#else
+#define omap2430_32k_read	NULL
+#endif
+
+#ifdef CONFIG_ARCH_OMAP3
+static cycle_t omap34xx_32k_read(struct clocksource *cs)
+{
+	return omap_readl(OMAP3430_32KSYNCT_BASE + 0x10) - offset_32k;
+}
+#else
+#define omap34xx_32k_read	NULL
+#endif
+
+#ifdef CONFIG_ARCH_OMAP4
+static cycle_t omap44xx_32k_read(struct clocksource *cs)
+{
+	return omap_readl(OMAP4430_32KSYNCT_BASE + 0x10) - offset_32k;
+}
+#else
+#define omap44xx_32k_read	NULL
+#endif
+
+/*
+ * Kernel assumes that sched_clock can be called early but may not have
+ * things ready yet.
+ */
+static cycle_t omap_32k_read_dummy(struct clocksource *cs)
+{
+	return 0;
+}
+
+static struct clocksource clocksource_32k = {
+	.name		= "32k_counter",
+	.rating		= 250,
+	.read		= omap_32k_read_dummy,
+	.mask		= CLOCKSOURCE_MASK(32),
+	.shift		= 10,
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+/*
+ * Returns current time from boot in nsecs. It's OK for this to wrap
+ * around for now, as it's just a relative time stamp.
+ */
+unsigned long long sched_clock(void)
+{
+	return clocksource_cyc2ns(clocksource_32k.read(&clocksource_32k),
+				  clocksource_32k.mult, clocksource_32k.shift);
+}
+
+/**
+ * read_persistent_clock -  Return time from a persistent clock.
+ *
+ * Reads the time from a source which isn't disabled during PM, the
+ * 32k sync timer.  Convert the cycles elapsed since last read into
+ * nsecs and adds to a monotonically increasing timespec.
+ */
+static struct timespec persistent_ts;
+static cycles_t cycles, last_cycles;
+void read_persistent_clock(struct timespec *ts)
+{
+	unsigned long long nsecs;
+	cycles_t delta;
+	struct timespec *tsp = &persistent_ts;
+
+	last_cycles = cycles;
+	cycles = clocksource_32k.read(&clocksource_32k);
+	delta = cycles - last_cycles;
+
+	nsecs = clocksource_cyc2ns(delta,
+				   clocksource_32k.mult, clocksource_32k.shift);
+
+	timespec_add_ns(tsp, nsecs);
+	*ts = *tsp;
+}
+
+static int __init omap_init_clocksource_32k(void)
+{
+	static char err[] __initdata = KERN_ERR
+			"%s: can't register clocksource!\n";
+
+	if (cpu_is_omap16xx() || cpu_class_is_omap2()) {
+		struct clk *sync_32k_ick;
+
+		if (cpu_is_omap16xx())
+			clocksource_32k.read = omap16xx_32k_read;
+		else if (cpu_is_omap2420())
+			clocksource_32k.read = omap2420_32k_read;
+		else if (cpu_is_omap2430())
+			clocksource_32k.read = omap2430_32k_read;
+		else if (cpu_is_omap34xx())
+			clocksource_32k.read = omap34xx_32k_read;
+		else if (cpu_is_omap44xx())
+			clocksource_32k.read = omap44xx_32k_read;
+		else
+			return -ENODEV;
+
+		sync_32k_ick = clk_get(NULL, "omap_32ksync_ick");
+		if (sync_32k_ick)
+			clk_enable(sync_32k_ick);
+
+		clocksource_32k.mult = clocksource_hz2mult(32768,
+					    clocksource_32k.shift);
+
+		offset_32k = clocksource_32k.read(&clocksource_32k);
+
+		if (clocksource_register(&clocksource_32k))
+			printk(err, clocksource_32k.name);
+	}
+	return 0;
+}
+arch_initcall(omap_init_clocksource_32k);
+
+#endif	/* !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX)) */
+
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
index 6d3d333..11c54ec 100644
--- a/arch/arm/plat-omap/cpu-omap.c
+++ b/arch/arm/plat-omap/cpu-omap.c
@@ -40,7 +40,7 @@
 
 /* TODO: Add support for SDRAM timing changes */
 
-int omap_verify_speed(struct cpufreq_policy *policy)
+static int omap_verify_speed(struct cpufreq_policy *policy)
 {
 	if (freq_table)
 		return cpufreq_frequency_table_verify(policy, freq_table);
@@ -58,7 +58,7 @@
 	return 0;
 }
 
-unsigned int omap_getspeed(unsigned int cpu)
+static unsigned int omap_getspeed(unsigned int cpu)
 {
 	unsigned long rate;
 
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c
index d1920be..1e2383e 100644
--- a/arch/arm/plat-omap/devices.c
+++ b/arch/arm/plat-omap/devices.c
@@ -21,7 +21,6 @@
 #include <asm/mach/map.h>
 
 #include <plat/tc.h>
-#include <plat/control.h>
 #include <plat/board.h>
 #include <plat/mmc.h>
 #include <mach/gpio.h>
@@ -232,46 +231,6 @@
 static inline void omap_init_uwire(void) {}
 #endif
 
-/*-------------------------------------------------------------------------*/
-
-#if	defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE)
-
-static struct resource wdt_resources[] = {
-	{
-		.flags		= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device omap_wdt_device = {
-	.name	   = "omap_wdt",
-	.id	     = -1,
-	.num_resources	= ARRAY_SIZE(wdt_resources),
-	.resource	= wdt_resources,
-};
-
-static void omap_init_wdt(void)
-{
-	if (cpu_is_omap16xx())
-		wdt_resources[0].start = 0xfffeb000;
-	else if (cpu_is_omap2420())
-		wdt_resources[0].start = 0x48022000; /* WDT2 */
-	else if (cpu_is_omap2430())
-		wdt_resources[0].start = 0x49016000; /* WDT2 */
-	else if (cpu_is_omap343x())
-		wdt_resources[0].start = 0x48314000; /* WDT2 */
-	else if (cpu_is_omap44xx())
-		wdt_resources[0].start = 0x4a314000;
-	else
-		return;
-
-	wdt_resources[0].end = wdt_resources[0].start + 0x4f;
-
-	(void) platform_device_register(&omap_wdt_device);
-}
-#else
-static inline void omap_init_wdt(void) {}
-#endif
-
 /*
  * This gets called after board-specific INIT_MACHINE, and initializes most
  * on-chip peripherals accessible on this board (except for few like USB):
@@ -300,7 +259,6 @@
 	omap_init_rng();
 	omap_init_mcpdm();
 	omap_init_uwire();
-	omap_init_wdt();
 	return 0;
 }
 arch_initcall(omap_init_devices);
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index ec7eddf..f5c5b8d 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -30,6 +30,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/delay.h>
 
 #include <asm/system.h>
 #include <mach/hardware.h>
@@ -996,11 +997,17 @@
 	l = dma_read(CCR(lch));
 
 	/*
-	 * Errata: On ES2.0 BUFFERING disable must be set.
-	 * This will always fail on ES1.0
+	 * Errata: Inter Frame DMA buffering issue (All OMAP2420 and
+	 * OMAP2430ES1.0): DMA will wrongly buffer elements if packing and
+	 * bursting is enabled. This might result in data gets stalled in
+	 * FIFO at the end of the block.
+	 * Workaround: DMA channels must have BUFFERING_DISABLED bit set to
+	 * guarantee no data will stay in the DMA FIFO in case inter frame
+	 * buffering occurs.
 	 */
-	if (cpu_is_omap24xx())
-		l |= OMAP_DMA_CCR_EN;
+	if (cpu_is_omap2420() ||
+	    (cpu_is_omap2430() && (omap_type() == OMAP2430_REV_ES1_0)))
+		l |= OMAP_DMA_CCR_BUFFERING_DISABLE;
 
 	l |= OMAP_DMA_CCR_EN;
 	dma_write(l, CCR(lch));
@@ -1018,8 +1025,39 @@
 		dma_write(0, CICR(lch));
 
 	l = dma_read(CCR(lch));
-	l &= ~OMAP_DMA_CCR_EN;
-	dma_write(l, CCR(lch));
+	/* OMAP3 Errata i541: sDMA FIFO draining does not finish */
+	if (cpu_is_omap34xx() && (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) {
+		int i = 0;
+		u32 sys_cf;
+
+		/* Configure No-Standby */
+		l = dma_read(OCP_SYSCONFIG);
+		sys_cf = l;
+		l &= ~DMA_SYSCONFIG_MIDLEMODE_MASK;
+		l |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE);
+		dma_write(l , OCP_SYSCONFIG);
+
+		l = dma_read(CCR(lch));
+		l &= ~OMAP_DMA_CCR_EN;
+		dma_write(l, CCR(lch));
+
+		/* Wait for sDMA FIFO drain */
+		l = dma_read(CCR(lch));
+		while (i < 100 && (l & (OMAP_DMA_CCR_RD_ACTIVE |
+					OMAP_DMA_CCR_WR_ACTIVE))) {
+			udelay(5);
+			i++;
+			l = dma_read(CCR(lch));
+		}
+		if (i >= 100)
+			printk(KERN_ERR "DMA drain did not complete on "
+					"lch %d\n", lch);
+		/* Restore OCP_SYSCONFIG */
+		dma_write(sys_cf, OCP_SYSCONFIG);
+	} else {
+		l &= ~OMAP_DMA_CCR_EN;
+		dma_write(l, CCR(lch));
+	}
 
 	if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
 		int next_lch, cur_lch = lch;
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 44bafda..1d706cf 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -581,7 +581,7 @@
 	 * When the functional clock disappears, too quick writes seem
 	 * to cause an abort. XXX Is this still necessary?
 	 */
-	__delay(150000);
+	__delay(300000);
 
 	return ret;
 }
diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c
index 7193481..c9e5d72 100644
--- a/arch/arm/plat-omap/fb.c
+++ b/arch/arm/plat-omap/fb.c
@@ -36,6 +36,8 @@
 #include <plat/board.h>
 #include <plat/sram.h>
 
+#include "fb.h"
+
 #if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
 
 static struct omapfb_platform_data omapfb_config;
@@ -94,7 +96,7 @@
  * Get the region_idx`th region from board config/ATAG and convert it to
  * our internal format.
  */
-static int get_fbmem_region(int region_idx, struct omapfb_mem_region *rg)
+static int __init get_fbmem_region(int region_idx, struct omapfb_mem_region *rg)
 {
 	const struct omap_fbmem_config	*conf;
 	u32				paddr;
@@ -126,7 +128,7 @@
 	 * type = 0 && paddr = 0, a default don't care case maps to
 	 * the SDRAM type.
 	 */
-	if (rg->type || (!rg->type && !rg->paddr))
+	if (rg->type || !rg->paddr)
 		return 0;
 	if (ranges_overlap(rg->paddr, rg->size, mem_start, mem_size)) {
 		rg->type = mem_type;
@@ -258,7 +260,7 @@
  * this point, since the driver built as a module would have problem with
  * freeing / reallocating the regions.
  */
-unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
+unsigned long __init omapfb_reserve_sram(unsigned long sram_pstart,
 				  unsigned long sram_vstart,
 				  unsigned long sram_size,
 				  unsigned long pstart_avail,
@@ -332,7 +334,7 @@
 	omapfb_config.ctrl_platform_data = data;
 }
 
-static inline int omap_init_fb(void)
+static int __init omap_init_fb(void)
 {
 	const struct omap_lcd_config *conf;
 
@@ -377,7 +379,7 @@
 	omapfb_config = *data;
 }
 
-static inline int omap_init_fb(void)
+static int __init omap_init_fb(void)
 {
 	return platform_device_register(&omap_fb_device);
 }
@@ -388,7 +390,7 @@
 {
 }
 
-unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
+unsigned long __init omapfb_reserve_sram(unsigned long sram_pstart,
 				  unsigned long sram_vstart,
 				  unsigned long sram_size,
 				  unsigned long start_avail,
@@ -407,7 +409,7 @@
 {
 }
 
-unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
+unsigned long __init omapfb_reserve_sram(unsigned long sram_pstart,
 				  unsigned long sram_vstart,
 				  unsigned long sram_size,
 				  unsigned long start_avail,
diff --git a/arch/arm/plat-omap/fb.h b/arch/arm/plat-omap/fb.h
new file mode 100644
index 0000000..d765d0b
--- /dev/null
+++ b/arch/arm/plat-omap/fb.h
@@ -0,0 +1,10 @@
+#ifndef __PLAT_OMAP_FB_H__
+#define __PLAT_OMAP_FB_H__
+
+extern unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
+					 unsigned long sram_vstart,
+					 unsigned long sram_size,
+					 unsigned long pstart_avail,
+					 unsigned long size_avail);
+
+#endif /* __PLAT_OMAP_FB_H__ */
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index 7951eef..c05c653 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -2084,9 +2084,10 @@
 
 	for (i = min; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
-		u32 l1, l2;
+		u32 l1 = 0, l2 = 0;
+		int j;
 
-		if (bank->dbck_enable_mask)
+		for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
 			clk_disable(bank->dbck);
 
 		if (power_state > PWRDM_POWER_OFF)
@@ -2151,9 +2152,10 @@
 		min = 1;
 	for (i = min; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
-		u32 l, gen, gen0, gen1;
+		u32 l = 0, gen, gen0, gen1;
+		int j;
 
-		if (bank->dbck_enable_mask)
+		for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
 			clk_enable(bank->dbck);
 
 		if (!workaround_enabled)
diff --git a/arch/arm/plat-omap/include/plat/common.h b/arch/arm/plat-omap/include/plat/common.h
index 9776b41..a9d69a0 100644
--- a/arch/arm/plat-omap/include/plat/common.h
+++ b/arch/arm/plat-omap/include/plat/common.h
@@ -47,6 +47,7 @@
 	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;
@@ -66,7 +67,6 @@
 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 omap2_set_globals_uart(struct omap_globals *);
 
 void omap3_map_io(void);
 
@@ -91,7 +91,8 @@
 })
 
 extern struct device *omap2_get_mpuss_device(void);
-extern struct device *omap2_get_dsp_device(void);
+extern struct device *omap2_get_iva_device(void);
 extern struct device *omap2_get_l3_device(void);
+extern struct device *omap4_get_dsp_device(void);
 
 #endif /* __ARCH_ARM_MACH_OMAP_COMMON_H */
diff --git a/arch/arm/plat-omap/include/plat/cpu.h b/arch/arm/plat-omap/include/plat/cpu.h
index 2e2ae53..3fd8b40 100644
--- a/arch/arm/plat-omap/include/plat/cpu.h
+++ b/arch/arm/plat-omap/include/plat/cpu.h
@@ -68,10 +68,9 @@
 #define OMAP_REVBITS_00		0x00
 #define OMAP_REVBITS_01		0x01
 #define OMAP_REVBITS_02		0x02
-#define OMAP_REVBITS_10		0x10
-#define OMAP_REVBITS_20		0x20
-#define OMAP_REVBITS_30		0x30
-#define OMAP_REVBITS_40		0x40
+#define OMAP_REVBITS_03		0x03
+#define OMAP_REVBITS_04		0x04
+#define OMAP_REVBITS_05		0x05
 
 /*
  * Get the CPU revision for OMAP devices
@@ -363,23 +362,24 @@
 
 /* Various silicon revisions for omap2 */
 #define OMAP242X_CLASS		0x24200024
-#define OMAP2420_REV_ES1_0	0x24200024
-#define OMAP2420_REV_ES2_0	0x24201024
+#define OMAP2420_REV_ES1_0	OMAP242X_CLASS
+#define OMAP2420_REV_ES2_0	(OMAP242X_CLASS | (OMAP_REVBITS_01 << 8))
 
 #define OMAP243X_CLASS		0x24300024
-#define OMAP2430_REV_ES1_0	0x24300024
+#define OMAP2430_REV_ES1_0	OMAP243X_CLASS
 
 #define OMAP343X_CLASS		0x34300034
-#define OMAP3430_REV_ES1_0	0x34300034
-#define OMAP3430_REV_ES2_0	0x34301034
-#define OMAP3430_REV_ES2_1	0x34302034
-#define OMAP3430_REV_ES3_0	0x34303034
-#define OMAP3430_REV_ES3_1	0x34304034
-#define OMAP3430_REV_ES3_1_2	0x34305034
+#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 OMAP3630_REV_ES1_0	0x36300034
-#define OMAP3630_REV_ES1_1	0x36300134
-#define OMAP3630_REV_ES1_2	0x36300234
+#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 OMAP35XX_CLASS		0x35000034
 #define OMAP3503_REV(v)		(OMAP35XX_CLASS | (0x3503 << 16) | (v << 8))
@@ -390,7 +390,8 @@
 #define OMAP3517_REV(v)		(OMAP35XX_CLASS | (0x3517 << 16) | (v << 8))
 
 #define OMAP443X_CLASS		0x44300044
-#define OMAP4430_REV_ES1_0	0x44300044
+#define OMAP4430_REV_ES1_0	OMAP443X_CLASS
+#define OMAP4430_REV_ES2_0	0x44301044
 
 /*
  * omap_chip bits
@@ -417,10 +418,12 @@
 #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_OMAP24XX		(CHIP_IS_OMAP2420 | CHIP_IS_OMAP2430)
 
-#define CHIP_IS_OMAP4430		(CHIP_IS_OMAP4430ES1)
+#define CHIP_IS_OMAP4430		(CHIP_IS_OMAP4430ES1 | \
+						 CHIP_IS_OMAP4430ES2)
 
 /*
  * "GE" here represents "greater than or equal to" in terms of ES
diff --git a/arch/arm/plat-omap/include/plat/display.h b/arch/arm/plat-omap/include/plat/display.h
index 8bd15bd..c915a66 100644
--- a/arch/arm/plat-omap/include/plat/display.h
+++ b/arch/arm/plat-omap/include/plat/display.h
@@ -81,37 +81,6 @@
 	OMAP_DSS_COLOR_ARGB32	= 1 << 11, /* ARGB32 */
 	OMAP_DSS_COLOR_RGBA32	= 1 << 12, /* RGBA32 */
 	OMAP_DSS_COLOR_RGBX32	= 1 << 13, /* RGBx32 */
-
-	OMAP_DSS_COLOR_GFX_OMAP2 =
-		OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
-		OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
-		OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_RGB16 |
-		OMAP_DSS_COLOR_RGB24U | OMAP_DSS_COLOR_RGB24P,
-
-	OMAP_DSS_COLOR_VID_OMAP2 =
-		OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
-		OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 |
-		OMAP_DSS_COLOR_UYVY,
-
-	OMAP_DSS_COLOR_GFX_OMAP3 =
-		OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
-		OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
-		OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
-		OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
-		OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
-		OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
-
-	OMAP_DSS_COLOR_VID1_OMAP3 =
-		OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_RGB16 |
-		OMAP_DSS_COLOR_RGB24U | OMAP_DSS_COLOR_RGB24P |
-		OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_UYVY,
-
-	OMAP_DSS_COLOR_VID2_OMAP3 =
-		OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
-		OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
-		OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 |
-		OMAP_DSS_COLOR_UYVY | OMAP_DSS_COLOR_ARGB32 |
-		OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
 };
 
 enum omap_lcd_display_type {
diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h
index af3a039..0cce4ca 100644
--- a/arch/arm/plat-omap/include/plat/dma.h
+++ b/arch/arm/plat-omap/include/plat/dma.h
@@ -319,6 +319,8 @@
 #define OMAP34XX_DMA_USIM_TX		79	/* S_DMA_78 */
 #define OMAP34XX_DMA_USIM_RX		80	/* S_DMA_79 */
 
+#define OMAP36XX_DMA_UART4_TX		81	/* S_DMA_80 */
+#define OMAP36XX_DMA_UART4_RX		82	/* S_DMA_81 */
 /*----------------------------------------------------------------------------*/
 
 #define OMAP1_DMA_TOUT_IRQ		(1 << 0)
@@ -335,6 +337,10 @@
 #define OMAP2_DMA_MISALIGNED_ERR_IRQ	(1 << 11)
 
 #define OMAP_DMA_CCR_EN			(1 << 7)
+#define OMAP_DMA_CCR_RD_ACTIVE		(1 << 9)
+#define OMAP_DMA_CCR_WR_ACTIVE		(1 << 10)
+#define OMAP_DMA_CCR_SEL_SRC_DST_SYNC	(1 << 24)
+#define OMAP_DMA_CCR_BUFFERING_DISABLE	(1 << 25)
 
 #define OMAP_DMA_DATA_TYPE_S8		0x00
 #define OMAP_DMA_DATA_TYPE_S16		0x01
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
index 20f1054..dfa3aff 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -45,6 +45,8 @@
 #define OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE	0x02
 
 struct omap_dm_timer;
+extern struct omap_dm_timer *gptimer_wakeup;
+extern struct sys_timer omap_timer;
 struct clk;
 
 int omap_dm_timer_init(void);
diff --git a/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h b/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h
new file mode 100644
index 0000000..872de0bf
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h
@@ -0,0 +1,35 @@
+/*
+ * arch/arm/plat-omap/include/plat/gpmc-smsc911x.h
+ *
+ * Copyright (C) 2009 Li-Pro.Net
+ * Stephan Linz <linz@li-pro.net>
+ *
+ * Modified from arch/arm/plat-omap/include/plat/gpmc-smc91x.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_OMAP_GPMC_SMSC911X_H__
+
+struct omap_smsc911x_platform_data {
+	int	cs;
+	int	gpio_irq;
+	int	gpio_reset;
+	u32	flags;
+};
+
+#if defined(CONFIG_SMSC911X) || \
+	defined(CONFIG_SMSC911X_MODULE)
+
+extern void gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d);
+
+#else
+
+static inline void gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d)
+{
+}
+
+#endif
+#endif
diff --git a/arch/arm/plat-omap/include/plat/i2c.h b/arch/arm/plat-omap/include/plat/i2c.h
index 87f6bf2..36a0bef 100644
--- a/arch/arm/plat-omap/include/plat/i2c.h
+++ b/arch/arm/plat-omap/include/plat/i2c.h
@@ -18,6 +18,8 @@
  * 02110-1301 USA
  *
  */
+#ifndef __ASM__ARCH_OMAP_I2C_H
+#define __ASM__ARCH_OMAP_I2C_H
 
 #include <linux/i2c.h>
 
@@ -36,3 +38,5 @@
 
 void __init omap1_i2c_mux_pins(int bus_id);
 void __init omap2_i2c_mux_pins(int bus_id);
+
+#endif /* __ASM__ARCH_OMAP_I2C_H */
diff --git a/arch/arm/plat-omap/include/plat/irqs.h b/arch/arm/plat-omap/include/plat/irqs.h
index c01d9f0..65e20a6 100644
--- a/arch/arm/plat-omap/include/plat/irqs.h
+++ b/arch/arm/plat-omap/include/plat/irqs.h
@@ -345,6 +345,8 @@
 #define INT_34XX_MMC3_IRQ	94
 #define INT_34XX_GPT12_IRQ	95
 
+#define INT_36XX_UART4_IRQ	80
+
 #define INT_35XX_HECC0_IRQ		24
 #define INT_35XX_HECC1_IRQ		28
 #define INT_35XX_EMAC_C0_RXTHRESH_IRQ	67
diff --git a/arch/arm/plat-omap/include/plat/mcbsp.h b/arch/arm/plat-omap/include/plat/mcbsp.h
index 5b20103..b87d83c 100644
--- a/arch/arm/plat-omap/include/plat/mcbsp.h
+++ b/arch/arm/plat-omap/include/plat/mcbsp.h
@@ -319,6 +319,18 @@
 #define RFSREN			0x0002
 #define RSYNCERREN		0x0001
 
+/* CLKR signal muxing options */
+#define CLKR_SRC_CLKR		0
+#define CLKR_SRC_CLKX		1
+
+/* FSR signal muxing options */
+#define FSR_SRC_FSR		0
+#define FSR_SRC_FSX		1
+
+/* McBSP functional clock sources */
+#define MCBSP_CLKS_PRCM_SRC	0
+#define MCBSP_CLKS_PAD_SRC	1
+
 /* we don't do multichannel for now */
 struct omap_mcbsp_reg_cfg {
 	u16 spcr2;
@@ -405,6 +417,7 @@
 struct omap_mcbsp_ops {
 	void (*request)(unsigned int);
 	void (*free)(unsigned int);
+	int (*set_clks_src)(u8, u8);
 };
 
 struct omap_mcbsp_platform_data {
@@ -471,6 +484,9 @@
 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];
+
 int omap_mcbsp_init(void);
 void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config,
 					int size);
@@ -509,6 +525,8 @@
 int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 * word);
 
 
+/* McBSP functional clock source changing function */
+extern int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id);
 /* SPI specific API */
 void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * spi_cfg);
 
@@ -517,6 +535,10 @@
 int omap_mcbsp_pollwrite(unsigned int id, u16 buf);
 int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type);
 
+/* McBSP signal muxing API */
+void omap2_mcbsp1_mux_clkr_src(u8 mux);
+void omap2_mcbsp1_mux_fsr_src(u8 mux);
+
 #ifdef CONFIG_ARCH_OMAP3
 /* Sidetone specific API */
 int omap_st_set_chgain(unsigned int id, int channel, s16 chgain);
diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h
index 9b89ec6..f57f36a 100644
--- a/arch/arm/plat-omap/include/plat/mmc.h
+++ b/arch/arm/plat-omap/include/plat/mmc.h
@@ -71,12 +71,17 @@
 
 	u64 dma_mask;
 
+	/* Register offset deviation */
+	u16 reg_offset;
+
 	struct omap_mmc_slot_data {
 
-		/* 4 wire signaling is optional, and is used for SD/SDIO/HSMMC;
-		 * 8 wire signaling is also optional, and is used with HSMMC
+		/*
+		 * 4/8 wires and any additional host capabilities
+		 * need to OR'd all capabilities (ref. linux/mmc/host.h)
 		 */
-		u8 wires;
+		u8  wires;	/* Used for the MMC driver on omap1 and 2420 */
+		u32 caps;	/* Used for the MMC driver on 2430 and later */
 
 		/*
 		 * nomux means "standard" muxing is wrong on this board, and
@@ -104,6 +109,7 @@
 
 		/* we can put the features above into this variable */
 #define HSMMC_HAS_PBIAS		(1 << 0)
+#define HSMMC_HAS_UPDATED_RESET	(1 << 1)
 		unsigned features;
 
 		int switch_pin;			/* gpio (card detect) */
diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h
new file mode 100644
index 0000000..c8dae02
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/omap-serial.h
@@ -0,0 +1,128 @@
+/*
+ * Driver for OMAP-UART controller.
+ * Based on drivers/serial/8250.c
+ *
+ * Copyright (C) 2010 Texas Instruments.
+ *
+ * Authors:
+ *	Govindraj R	<govindraj.raja@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 as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __OMAP_SERIAL_H__
+#define __OMAP_SERIAL_H__
+
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+
+#include <plat/mux.h>
+
+#define DRIVER_NAME	"omap-hsuart"
+
+/*
+ * Use tty device name as ttyO, [O -> OMAP]
+ * in bootargs we specify as console=ttyO0 if uart1
+ * is used as console uart.
+ */
+#define OMAP_SERIAL_NAME	"ttyO"
+
+#define OMAP_MDR1_DISABLE	0x07
+#define OMAP_MDR1_MODE13X	0x03
+#define OMAP_MDR1_MODE16X	0x00
+#define OMAP_MODE13X_SPEED	230400
+
+/*
+ * LCR = 0XBF: Switch to Configuration Mode B.
+ * In configuration mode b allow access
+ * to EFR,DLL,DLH.
+ * Reference OMAP TRM Chapter 17
+ * Section: 1.4.3 Mode Selection
+ */
+#define OMAP_UART_LCR_CONF_MDB	0XBF
+
+/* WER = 0x7F
+ * Enable module level wakeup in WER reg
+ */
+#define OMAP_UART_WER_MOD_WKUP	0X7F
+
+/* Enable XON/XOFF flow control on output */
+#define OMAP_UART_SW_TX		0x04
+
+/* Enable XON/XOFF flow control on input */
+#define OMAP_UART_SW_RX		0x04
+
+#define OMAP_UART_SYSC_RESET	0X07
+#define OMAP_UART_TCR_TRIG	0X0F
+#define OMAP_UART_SW_CLR	0XF0
+#define OMAP_UART_FIFO_CLR	0X06
+
+#define OMAP_UART_DMA_CH_FREE	-1
+
+#define RX_TIMEOUT		(3 * HZ)
+#define OMAP_MAX_HSUART_PORTS	4
+
+#define MSR_SAVE_FLAGS		UART_MSR_ANY_DELTA
+
+struct omap_uart_port_info {
+	bool			dma_enabled;	/* To specify DMA Mode */
+	unsigned int		uartclk;	/* UART clock rate */
+	void __iomem		*membase;	/* ioremap cookie or NULL */
+	resource_size_t		mapbase;	/* resource base */
+	unsigned long		irqflags;	/* request_irq flags */
+	upf_t			flags;		/* UPF_* flags */
+};
+
+struct uart_omap_dma {
+	u8			uart_dma_tx;
+	u8			uart_dma_rx;
+	int			rx_dma_channel;
+	int			tx_dma_channel;
+	dma_addr_t		rx_buf_dma_phys;
+	dma_addr_t		tx_buf_dma_phys;
+	unsigned int		uart_base;
+	/*
+	 * Buffer for rx dma.It is not required for tx because the buffer
+	 * comes from port structure.
+	 */
+	unsigned char		*rx_buf;
+	unsigned int		prev_rx_dma_pos;
+	int			tx_buf_size;
+	int			tx_dma_used;
+	int			rx_dma_used;
+	spinlock_t		tx_lock;
+	spinlock_t		rx_lock;
+	/* timer to poll activity on rx dma */
+	struct timer_list	rx_timer;
+	int			rx_buf_size;
+	int			rx_timeout;
+};
+
+struct uart_omap_port {
+	struct uart_port	port;
+	struct uart_omap_dma	uart_dma;
+	struct platform_device	*pdev;
+
+	unsigned char		ier;
+	unsigned char		lcr;
+	unsigned char		mcr;
+	unsigned char		fcr;
+	unsigned char		efr;
+
+	int			use_dma;
+	/*
+	 * Some bits in registers are cleared on a read, so they must
+	 * be saved whenever the register is read but the bits will not
+	 * be immediately processed.
+	 */
+	unsigned int		lsr_break_flag;
+	unsigned char		msr_saved_flags;
+	char			name[20];
+	unsigned long		port_activity;
+};
+
+#endif /* __OMAP_SERIAL_H__ */
diff --git a/arch/arm/plat-omap/include/plat/omap24xx.h b/arch/arm/plat-omap/include/plat/omap24xx.h
index 7055672..92df9e2 100644
--- a/arch/arm/plat-omap/include/plat/omap24xx.h
+++ b/arch/arm/plat-omap/include/plat/omap24xx.h
@@ -40,7 +40,7 @@
 #define OMAP24XX_IC_BASE	(L4_24XX_BASE + 0xfe000)
 #define OMAP24XX_IVA_INTC_BASE	0x40000000
 
-#define OMAP2420_CTRL_BASE	L4_24XX_BASE
+#define OMAP242X_CTRL_BASE	L4_24XX_BASE
 #define OMAP2420_32KSYNCT_BASE	(L4_24XX_BASE + 0x4000)
 #define OMAP2420_PRCM_BASE	(L4_24XX_BASE + 0x8000)
 #define OMAP2420_CM_BASE	(L4_24XX_BASE + 0x8000)
diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h
index 25cd9ac..28e2d1a 100644
--- a/arch/arm/plat-omap/include/plat/omap_device.h
+++ b/arch/arm/plat-omap/include/plat/omap_device.h
@@ -36,6 +36,8 @@
 
 #include <plat/omap_hwmod.h>
 
+extern struct device omap_device_parent;
+
 /* omap_device._state values */
 #define OMAP_DEVICE_STATE_UNKNOWN	0
 #define OMAP_DEVICE_STATE_ENABLED	1
@@ -62,7 +64,6 @@
  *
  */
 struct omap_device {
-	u32                             magic;
 	struct platform_device		pdev;
 	struct omap_hwmod		**hwmods;
 	struct omap_device_pm_latency	*pm_lats;
@@ -82,7 +83,6 @@
 
 /* Core code interface */
 
-bool omap_device_is_valid(struct omap_device *od);
 int omap_device_count_resources(struct omap_device *od);
 int omap_device_fill_resources(struct omap_device *od, struct resource *res);
 
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index a4e508d..7eaa8ed 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -14,19 +14,16 @@
  *
  * These headers and macros are used to define OMAP on-chip module
  * data and their integration with other OMAP modules and Linux.
- *
- * References:
- * - OMAP2420 Multimedia Processor Silicon Revision 2.1.1, 2.2 (SWPU064)
- * - OMAP2430 Multimedia Device POP Silicon Revision 2.1 (SWPU090)
- * - OMAP34xx Multimedia Device Silicon Revision 3.1 (SWPU108)
- * - OMAP4430 Multimedia Device Silicon Revision 1.0 (SWPU140)
- * - Open Core Protocol Specification 2.2
+ * Copious documentation and references can also be found in the
+ * omap_hwmod code, in arch/arm/mach-omap2/omap_hwmod.c (as of this
+ * writing).
  *
  * To do:
  * - add interconnect error log structures
  * - add pinmuxing
  * - init_conn_id_bit (CONNID_BIT_VECTOR)
  * - implement default hwmod SMS/SDRC flags?
+ * - remove unused fields
  *
  */
 #ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_HWMOD_H
@@ -35,6 +32,7 @@
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/ioport.h>
+#include <linux/mutex.h>
 #include <plat/cpu.h>
 
 struct omap_device;
@@ -96,7 +94,7 @@
 /**
  * struct omap_hwmod_dma_info - DMA channels used by the hwmod
  * @name: name of the DMA channel (module local name)
- * @dma_ch: DMA channel ID
+ * @dma_req: DMA request ID
  *
  * @name should be something short, e.g., "tx" or "rx".  It is for use
  * by platform_get_resource_byname().  It is defined locally to the
@@ -104,7 +102,20 @@
  */
 struct omap_hwmod_dma_info {
 	const char	*name;
-	u16		dma_ch;
+	u16		dma_req;
+};
+
+/**
+ * struct omap_hwmod_rst_info - IPs reset lines use by hwmod
+ * @name: name of the reset line (module local name)
+ * @rst_shift: Offset of the reset bit
+ *
+ * @name should be something short, e.g., "cpu0" or "rst". It is defined
+ * locally to the hwmod.
+ */
+struct omap_hwmod_rst_info {
+	const char	*name;
+	u8		rst_shift;
 };
 
 /**
@@ -237,8 +248,9 @@
 #define SYSC_HAS_CLOCKACTIVITY	(1 << 4)
 #define SYSC_HAS_SIDLEMODE	(1 << 5)
 #define SYSC_HAS_MIDLEMODE	(1 << 6)
-#define SYSS_MISSING		(1 << 7)
+#define SYSS_HAS_RESET_STATUS	(1 << 7)
 #define SYSC_NO_CACHE		(1 << 8)  /* XXX SW flag, belongs elsewhere */
+#define SYSC_HAS_RESET_STATUS	(1 << 9)
 
 /* omap_hwmod_sysconfig.clockact flags */
 #define CLOCKACT_TEST_BOTH	0x0
@@ -327,10 +339,12 @@
 /**
  * struct omap_hwmod_omap4_prcm - OMAP4-specific PRCM data
  * @clkctrl_reg: PRCM address of the clock control register
+ * @rstctrl_reg: adress of the XXX_RSTCTRL register located in the PRM
  * @submodule_wkdep_bit: bit shift of the WKDEP range
  */
 struct omap_hwmod_omap4_prcm {
 	void __iomem	*clkctrl_reg;
+	void __iomem	*rstctrl_reg;
 	u8		submodule_wkdep_bit;
 };
 
@@ -352,6 +366,11 @@
  * HWMOD_SET_DEFAULT_CLOCKACT: program CLOCKACTIVITY bits at startup
  * HWMOD_NO_IDLEST : this module does not have idle status - this is the case
  *     only for few initiator modules on OMAP2 & 3.
+ * HWMOD_CONTROL_OPT_CLKS_IN_RESET: Enable all optional clocks during reset.
+ *     This is needed for devices like DSS that require optional clocks enabled
+ *     in order to complete the reset. Optional clocks will be disabled
+ *     again after the reset.
+ * HWMOD_16BIT_REG: Module has 16bit registers
  */
 #define HWMOD_SWSUP_SIDLE			(1 << 0)
 #define HWMOD_SWSUP_MSTANDBY			(1 << 1)
@@ -360,6 +379,8 @@
 #define HWMOD_NO_OCP_AUTOIDLE			(1 << 4)
 #define HWMOD_SET_DEFAULT_CLOCKACT		(1 << 5)
 #define HWMOD_NO_IDLEST				(1 << 6)
+#define HWMOD_CONTROL_OPT_CLKS_IN_RESET		(1 << 7)
+#define HWMOD_16BIT_REG				(1 << 8)
 
 /*
  * omap_hwmod._int_flags definitions
@@ -410,7 +431,7 @@
  * @class: struct omap_hwmod_class * to the class of this hwmod
  * @od: struct omap_device currently associated with this hwmod (internal use)
  * @mpu_irqs: ptr to an array of MPU IRQs (see also mpu_irqs_cnt)
- * @sdma_chs: ptr to an array of SDMA channel IDs (see also sdma_chs_cnt)
+ * @sdma_reqs: ptr to an array of System DMA request IDs (see sdma_reqs_cnt)
  * @prcm: PRCM data pertaining to this hwmod
  * @main_clk: main clock: OMAP clock name
  * @_clk: pointer to the main struct clk (filled in at runtime)
@@ -424,7 +445,7 @@
  * @msuspendmux_reg_id: CONTROL_MSUSPENDMUX register ID (1-6)
  * @msuspendmux_shift: CONTROL_MSUSPENDMUX register bit shift
  * @mpu_irqs_cnt: number of @mpu_irqs
- * @sdma_chs_cnt: number of @sdma_chs
+ * @sdma_reqs_cnt: number of @sdma_reqs
  * @opt_clks_cnt: number of @opt_clks
  * @master_cnt: number of @master entries
  * @slaves_cnt: number of @slave entries
@@ -433,6 +454,7 @@
  * @_state: internal-use hwmod state
  * @flags: hwmod flags (documented below)
  * @omap_chip: OMAP chips this hwmod is present on
+ * @_mutex: mutex serializing operations on this hwmod
  * @node: list node for hwmod list (internal use)
  *
  * @main_clk refers to this module's "main clock," which for our
@@ -448,7 +470,8 @@
 	struct omap_hwmod_class		*class;
 	struct omap_device		*od;
 	struct omap_hwmod_irq_info	*mpu_irqs;
-	struct omap_hwmod_dma_info	*sdma_chs;
+	struct omap_hwmod_dma_info	*sdma_reqs;
+	struct omap_hwmod_rst_info	*rst_lines;
 	union {
 		struct omap_hwmod_omap2_prcm omap2;
 		struct omap_hwmod_omap4_prcm omap4;
@@ -461,6 +484,7 @@
 	void				*dev_attr;
 	u32				_sysc_cache;
 	void __iomem			*_mpu_rt_va;
+	struct mutex			_mutex;
 	struct list_head		node;
 	u16				flags;
 	u8				_mpu_port_index;
@@ -468,7 +492,8 @@
 	u8				msuspendmux_shift;
 	u8				response_lat;
 	u8				mpu_irqs_cnt;
-	u8				sdma_chs_cnt;
+	u8				sdma_reqs_cnt;
+	u8				rst_lines_cnt;
 	u8				opt_clks_cnt;
 	u8				masters_cnt;
 	u8				slaves_cnt;
@@ -492,6 +517,10 @@
 int _omap_hwmod_idle(struct omap_hwmod *oh);
 int omap_hwmod_shutdown(struct omap_hwmod *oh);
 
+int omap_hwmod_assert_hardreset(struct omap_hwmod *oh, const char *name);
+int omap_hwmod_deassert_hardreset(struct omap_hwmod *oh, const char *name);
+int omap_hwmod_read_hardreset(struct omap_hwmod *oh, const char *name);
+
 int omap_hwmod_enable_clocks(struct omap_hwmod *oh);
 int omap_hwmod_disable_clocks(struct omap_hwmod *oh);
 
@@ -500,8 +529,8 @@
 int omap_hwmod_reset(struct omap_hwmod *oh);
 void omap_hwmod_ocp_barrier(struct omap_hwmod *oh);
 
-void omap_hwmod_writel(u32 v, struct omap_hwmod *oh, u16 reg_offs);
-u32 omap_hwmod_readl(struct omap_hwmod *oh, u16 reg_offs);
+void omap_hwmod_write(u32 v, struct omap_hwmod *oh, u16 reg_offs);
+u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs);
 
 int omap_hwmod_count_resources(struct omap_hwmod *oh);
 int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res);
@@ -534,5 +563,6 @@
 extern int omap2420_hwmod_init(void);
 extern int omap2430_hwmod_init(void);
 extern int omap3xxx_hwmod_init(void);
+extern int omap44xx_hwmod_init(void);
 
 #endif
diff --git a/arch/arm/plat-omap/include/plat/powerdomain.h b/arch/arm/plat-omap/include/plat/powerdomain.h
index fb6ec74..9ca420d 100644
--- a/arch/arm/plat-omap/include/plat/powerdomain.h
+++ b/arch/arm/plat-omap/include/plat/powerdomain.h
@@ -32,6 +32,7 @@
 
 /* Powerdomain allowable state bitfields */
 #define PWRSTS_ON		(1 << PWRDM_POWER_ON)
+#define PWRSTS_OFF		(1 << PWRDM_POWER_OFF)
 #define PWRSTS_OFF_ON		((1 << PWRDM_POWER_OFF) | \
 				 (1 << PWRDM_POWER_ON))
 
@@ -161,5 +162,6 @@
 int pwrdm_clkdm_state_switch(struct clockdomain *clkdm);
 int pwrdm_pre_transition(void);
 int pwrdm_post_transition(void);
+int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
 
 #endif
diff --git a/arch/arm/plat-omap/include/plat/prcm.h b/arch/arm/plat-omap/include/plat/prcm.h
index 9fbd914..ab77442 100644
--- a/arch/arm/plat-omap/include/plat/prcm.h
+++ b/arch/arm/plat-omap/include/plat/prcm.h
@@ -38,6 +38,8 @@
 void prm_write_mod_reg(u32 val, s16 module, u16 idx);
 u32 prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx);
 u32 prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask);
+u32 omap4_prm_read_bits_shift(void __iomem *reg, u32 mask);
+u32 omap4_prm_rmw_reg_bits(u32 mask, u32 bits, void __iomem *reg);
 u32 cm_read_mod_reg(s16 module, u16 idx);
 void cm_write_mod_reg(u32 val, s16 module, u16 idx);
 u32 cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx);
diff --git a/arch/arm/plat-omap/include/plat/sdrc.h b/arch/arm/plat-omap/include/plat/sdrc.h
index 7b76f50..efd87c8 100644
--- a/arch/arm/plat-omap/include/plat/sdrc.h
+++ b/arch/arm/plat-omap/include/plat/sdrc.h
@@ -147,6 +147,7 @@
 };
 
 extern void omap2xxx_sdrc_init_params(u32 force_lock_to_unlock_mode);
+struct omap_sdrc_params *rx51_get_sdram_timings(void);
 
 u32 omap2xxx_sdrc_dll_is_unlocked(void);
 u32 omap2xxx_sdrc_reprogram(u32 level, u32 force);
diff --git a/arch/arm/plat-omap/include/plat/sram.h b/arch/arm/plat-omap/include/plat/sram.h
index 16a1b45..5905100 100644
--- a/arch/arm/plat-omap/include/plat/sram.h
+++ b/arch/arm/plat-omap/include/plat/sram.h
@@ -11,7 +11,6 @@
 #ifndef __ARCH_ARM_OMAP_SRAM_H
 #define __ARCH_ARM_OMAP_SRAM_H
 
-extern int __init omap_sram_init(void);
 extern void * omap_sram_push(void * start, unsigned long size);
 extern void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl);
 
diff --git a/arch/arm/plat-omap/include/plat/uncompress.h b/arch/arm/plat-omap/include/plat/uncompress.h
index ddf723b..9036e37 100644
--- a/arch/arm/plat-omap/include/plat/uncompress.h
+++ b/arch/arm/plat-omap/include/plat/uncompress.h
@@ -139,10 +139,14 @@
 		DEBUG_LL_OMAP2(1, omap3evm);
 		DEBUG_LL_OMAP3(1, omap_3430sdp);
 		DEBUG_LL_OMAP3(1, omap_3630sdp);
+		DEBUG_LL_OMAP3(1, omap3530_lv_som);
+		DEBUG_LL_OMAP3(1, omap3_torpedo);
 
 		/* omap3 based boards using UART3 */
 		DEBUG_LL_OMAP3(3, cm_t35);
+		DEBUG_LL_OMAP3(3, cm_t3517);
 		DEBUG_LL_OMAP3(3, igep0020);
+		DEBUG_LL_OMAP3(3, igep0030);
 		DEBUG_LL_OMAP3(3, nokia_rx51);
 		DEBUG_LL_OMAP3(3, omap3517evm);
 		DEBUG_LL_OMAP3(3, omap3_beagle);
@@ -153,6 +157,7 @@
 
 		/* omap4 based boards using UART3 */
 		DEBUG_LL_OMAP4(3, omap_4430sdp);
+		DEBUG_LL_OMAP4(3, omap4_panda);
 
 		/* zoom2/3 external uart */
 		DEBUG_LL_ZOOM(omap_zoom2);
diff --git a/arch/arm/plat-omap/include/plat/usb.h b/arch/arm/plat-omap/include/plat/usb.h
index 9feddac..59c7fe7 100644
--- a/arch/arm/plat-omap/include/plat/usb.h
+++ b/arch/arm/plat-omap/include/plat/usb.h
@@ -105,7 +105,7 @@
 #if defined(CONFIG_ARCH_OMAP_OTG) || defined(CONFIG_ARCH_OMAP_OTG_MODULE)
 void omap2_usbfs_init(struct omap_usb_config *pdata);
 #else
-static inline omap2_usbfs_init(struct omap_usb_config *pdata)
+static inline void omap2_usbfs_init(struct omap_usb_config *pdata)
 {
 }
 #endif
diff --git a/arch/arm/plat-omap/include/plat/vrfb.h b/arch/arm/plat-omap/include/plat/vrfb.h
index d8a03ce..3792bde 100644
--- a/arch/arm/plat-omap/include/plat/vrfb.h
+++ b/arch/arm/plat-omap/include/plat/vrfb.h
@@ -35,6 +35,7 @@
 	bool yuv_mode;
 };
 
+#ifdef CONFIG_OMAP2_VRFB
 extern int omap_vrfb_request_ctx(struct vrfb *vrfb);
 extern void omap_vrfb_release_ctx(struct vrfb *vrfb);
 extern void omap_vrfb_adjust_size(u16 *width, u16 *height,
@@ -47,4 +48,19 @@
 extern int omap_vrfb_map_angle(struct vrfb *vrfb, u16 height, u8 rot);
 extern void omap_vrfb_restore_context(void);
 
+#else
+static inline int omap_vrfb_request_ctx(struct vrfb *vrfb) { return 0; }
+static inline void omap_vrfb_release_ctx(struct vrfb *vrfb) {}
+static inline void omap_vrfb_adjust_size(u16 *width, u16 *height,
+		u8 bytespp) {}
+static inline u32 omap_vrfb_min_phys_size(u16 width, u16 height, u8 bytespp)
+		{ return 0; }
+static inline u16 omap_vrfb_max_height(u32 phys_size, u16 width, u8 bytespp)
+		{ return 0; }
+static inline void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
+		u16 width, u16 height, unsigned bytespp, bool yuv_mode) {}
+static inline int omap_vrfb_map_angle(struct vrfb *vrfb, u16 height, u8 rot)
+		{ return 0; }
+static inline void omap_vrfb_restore_context(void) {}
+#endif
 #endif /* __VRFB_H */
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index 0c8612f..eac4b97 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -33,7 +33,7 @@
 struct omap_mcbsp **mcbsp_ptr;
 int omap_mcbsp_count, omap_mcbsp_cache_size;
 
-void omap_mcbsp_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
+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;
@@ -47,7 +47,7 @@
 	}
 }
 
-int omap_mcbsp_read(struct omap_mcbsp *mcbsp, u16 reg, bool from_cache)
+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) :
@@ -62,12 +62,12 @@
 }
 
 #ifdef CONFIG_ARCH_OMAP3
-void omap_mcbsp_st_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
+static void omap_mcbsp_st_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
 {
 	__raw_writel(val, mcbsp->st_data->io_base_st + reg);
 }
 
-int omap_mcbsp_st_read(struct omap_mcbsp *mcbsp, u16 reg)
+static int omap_mcbsp_st_read(struct omap_mcbsp *mcbsp, u16 reg)
 {
 	return __raw_readl(mcbsp->st_data->io_base_st + reg);
 }
@@ -80,9 +80,6 @@
 #define MCBSP_READ_CACHE(mcbsp, reg) \
 		omap_mcbsp_read(mcbsp, OMAP_MCBSP_REG_##reg, 1)
 
-#define omap_mcbsp_check_valid_id(id)	(id < omap_mcbsp_count)
-#define id_to_mcbsp_ptr(id)		mcbsp_ptr[id];
-
 #define MCBSP_ST_READ(mcbsp, reg) \
 			omap_mcbsp_st_read(mcbsp, OMAP_ST_REG_##reg)
 #define MCBSP_ST_WRITE(mcbsp, reg, val) \
@@ -878,7 +875,7 @@
 void omap_mcbsp_start(unsigned int id, int tx, int rx)
 {
 	struct omap_mcbsp *mcbsp;
-	int idle;
+	int enable_srg = 0;
 	u16 w;
 
 	if (!omap_mcbsp_check_valid_id(id)) {
@@ -893,10 +890,13 @@
 	mcbsp->rx_word_length = (MCBSP_READ_CACHE(mcbsp, RCR1) >> 5) & 0x7;
 	mcbsp->tx_word_length = (MCBSP_READ_CACHE(mcbsp, XCR1) >> 5) & 0x7;
 
-	idle = !((MCBSP_READ_CACHE(mcbsp, SPCR2) |
-			MCBSP_READ_CACHE(mcbsp, SPCR1)) & 1);
+	/* Only enable SRG, if McBSP is master */
+	w = MCBSP_READ_CACHE(mcbsp, PCR0);
+	if (w & (FSXM | FSRM | CLKXM | CLKRM))
+		enable_srg = !((MCBSP_READ_CACHE(mcbsp, SPCR2) |
+				MCBSP_READ_CACHE(mcbsp, SPCR1)) & 1);
 
-	if (idle) {
+	if (enable_srg) {
 		/* Start the sample generator */
 		w = MCBSP_READ_CACHE(mcbsp, SPCR2);
 		MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 6));
@@ -919,7 +919,7 @@
 	 */
 	udelay(500);
 
-	if (idle) {
+	if (enable_srg) {
 		/* Start frame sync */
 		w = MCBSP_READ_CACHE(mcbsp, SPCR2);
 		MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 7));
@@ -1645,7 +1645,7 @@
 	.attrs = (struct attribute **)sidetone_attrs,
 };
 
-int __devinit omap_st_add(struct omap_mcbsp *mcbsp)
+static int __devinit omap_st_add(struct omap_mcbsp *mcbsp)
 {
 	struct omap_mcbsp_platform_data *pdata = mcbsp->pdata;
 	struct omap_mcbsp_st_data *st_data;
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index d2b1609..abe933c 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -82,6 +82,7 @@
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/clk.h>
 
 #include <plat/omap_device.h>
 #include <plat/omap_hwmod.h>
@@ -90,12 +91,6 @@
 #define USE_WAKEUP_LAT			0
 #define IGNORE_WAKEUP_LAT		1
 
-/*
- * OMAP_DEVICE_MAGIC: used to determine whether a struct omap_device
- * obtained via container_of() is in fact a struct omap_device
- */
-#define OMAP_DEVICE_MAGIC		 0xf00dcafe
-
 /* Private functions */
 
 /**
@@ -243,6 +238,44 @@
 	return container_of(pdev, struct omap_device, pdev);
 }
 
+/**
+ * _add_optional_clock_alias - Add clock alias for hwmod optional clocks
+ * @od: struct omap_device *od
+ *
+ * For every optional clock present per hwmod per omap_device, this function
+ * adds an entry in the clocks list of the form <dev-id=dev_name, con-id=role>
+ * if an entry is already present in it with the form <dev-id=NULL, con-id=role>
+ *
+ * The function is called from inside omap_device_build_ss(), after
+ * omap_device_register.
+ *
+ * This allows drivers to get a pointer to its optional clocks based on its role
+ * by calling clk_get(<dev*>, <role>).
+ *
+ * No return value.
+ */
+static void _add_optional_clock_alias(struct omap_device *od,
+				      struct omap_hwmod *oh)
+{
+	int i;
+
+	for (i = 0; i < oh->opt_clks_cnt; i++) {
+		struct omap_hwmod_opt_clk *oc;
+		int r;
+
+		oc = &oh->opt_clks[i];
+
+		if (!oc->_clk)
+			continue;
+
+		r = clk_add_alias(oc->role, dev_name(&od->pdev.dev),
+				  (char *)oc->clk, &od->pdev.dev);
+		if (r)
+			pr_err("omap_device: %s: clk_add_alias for %s failed\n",
+			       dev_name(&od->pdev.dev), oc->role);
+	}
+}
+
 
 /* Public functions for use by core code */
 
@@ -257,12 +290,11 @@
  */
 int omap_device_count_resources(struct omap_device *od)
 {
-	struct omap_hwmod *oh;
 	int c = 0;
 	int i;
 
-	for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++)
-		c += omap_hwmod_count_resources(oh);
+	for (i = 0; i < od->hwmods_cnt; i++)
+		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);
@@ -289,12 +321,11 @@
  */
 int omap_device_fill_resources(struct omap_device *od, struct resource *res)
 {
-	struct omap_hwmod *oh;
 	int c = 0;
 	int i, r;
 
-	for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++) {
-		r = omap_hwmod_fill_resources(oh, res);
+	for (i = 0; i < od->hwmods_cnt; i++) {
+		r = omap_hwmod_fill_resources(od->hwmods[i], res);
 		res += r;
 		c += r;
 	}
@@ -414,15 +445,15 @@
 	od->pm_lats = pm_lats;
 	od->pm_lats_cnt = pm_lats_cnt;
 
-	od->magic = OMAP_DEVICE_MAGIC;
-
 	if (is_early_device)
 		ret = omap_early_device_register(od);
 	else
 		ret = omap_device_register(od);
 
-	for (i = 0; i < oh_cnt; i++)
+	for (i = 0; i < oh_cnt; i++) {
 		hwmods[i]->od = od;
+		_add_optional_clock_alias(od, hwmods[i]);
+	}
 
 	if (ret)
 		goto odbs_exit4;
@@ -473,6 +504,7 @@
 {
 	pr_debug("omap_device: %s: registering\n", od->pdev.name);
 
+	od->pdev.dev.parent = &omap_device_parent;
 	return platform_device_register(&od->pdev);
 }
 
@@ -566,7 +598,6 @@
 {
 	int ret, i;
 	struct omap_device *od;
-	struct omap_hwmod *oh;
 
 	od = _find_by_pdev(pdev);
 
@@ -579,8 +610,8 @@
 
 	ret = _omap_device_deactivate(od, IGNORE_WAKEUP_LAT);
 
-	for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++)
-		omap_hwmod_shutdown(oh);
+	for (i = 0; i < od->hwmods_cnt; i++)
+		omap_hwmod_shutdown(od->hwmods[i]);
 
 	od->_state = OMAP_DEVICE_STATE_SHUTDOWN;
 
@@ -627,18 +658,6 @@
 }
 
 /**
- * omap_device_is_valid - Check if pointer is a valid omap_device
- * @od: struct omap_device *
- *
- * Return whether struct omap_device pointer @od points to a valid
- * omap_device.
- */
-bool omap_device_is_valid(struct omap_device *od)
-{
-	return (od && od->magic == OMAP_DEVICE_MAGIC);
-}
-
-/**
  * omap_device_get_pwrdm - return the powerdomain * associated with @od
  * @od: struct omap_device *
  *
@@ -692,11 +711,10 @@
  */
 int omap_device_enable_hwmods(struct omap_device *od)
 {
-	struct omap_hwmod *oh;
 	int i;
 
-	for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++)
-		omap_hwmod_enable(oh);
+	for (i = 0; i < od->hwmods_cnt; i++)
+		omap_hwmod_enable(od->hwmods[i]);
 
 	/* XXX pass along return value here? */
 	return 0;
@@ -710,11 +728,10 @@
  */
 int omap_device_idle_hwmods(struct omap_device *od)
 {
-	struct omap_hwmod *oh;
 	int i;
 
-	for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++)
-		omap_hwmod_idle(oh);
+	for (i = 0; i < od->hwmods_cnt; i++)
+		omap_hwmod_idle(od->hwmods[i]);
 
 	/* XXX pass along return value here? */
 	return 0;
@@ -729,11 +746,10 @@
  */
 int omap_device_disable_clocks(struct omap_device *od)
 {
-	struct omap_hwmod *oh;
 	int i;
 
-	for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++)
-		omap_hwmod_disable_clocks(oh);
+	for (i = 0; i < od->hwmods_cnt; i++)
+		omap_hwmod_disable_clocks(od->hwmods[i]);
 
 	/* XXX pass along return value here? */
 	return 0;
@@ -748,12 +764,22 @@
  */
 int omap_device_enable_clocks(struct omap_device *od)
 {
-	struct omap_hwmod *oh;
 	int i;
 
-	for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++)
-		omap_hwmod_enable_clocks(oh);
+	for (i = 0; i < od->hwmods_cnt; i++)
+		omap_hwmod_enable_clocks(od->hwmods[i]);
 
 	/* XXX pass along return value here? */
 	return 0;
 }
+
+struct device omap_device_parent = {
+	.init_name	= "omap",
+	.parent         = &platform_bus,
+};
+
+static int __init omap_device_init(void)
+{
+	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 10b3b4c..e2c8eeb 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -19,6 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/omapfb.h>
 
 #include <asm/tlb.h>
 #include <asm/cacheflush.h>
@@ -30,8 +31,8 @@
 #include <plat/cpu.h>
 #include <plat/vram.h>
 
-#include <plat/control.h>
-
+#include "sram.h"
+#include "fb.h"
 #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
 # include "../mach-omap2/prm.h"
 # include "../mach-omap2/cm.h"
@@ -53,7 +54,7 @@
 #define OMAP4_SRAM_PUB_PA	(OMAP4_SRAM_PA + 0x4000)
 #define OMAP4_SRAM_PUB_VA	(OMAP4_SRAM_VA + 0x4000)
 
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+#if defined(CONFIG_ARCH_OMAP2PLUS)
 #define SRAM_BOOTLOADER_SZ	0x00
 #else
 #define SRAM_BOOTLOADER_SZ	0x80
@@ -68,7 +69,6 @@
 #define OMAP34XX_VA_WRITEPERM0		OMAP2_L3_IO_ADDRESS(0x68012858)
 #define OMAP34XX_VA_ADDR_MATCH2		OMAP2_L3_IO_ADDRESS(0x68012880)
 #define OMAP34XX_VA_SMS_RG_ATT0		OMAP2_L3_IO_ADDRESS(0x6C000048)
-#define OMAP34XX_VA_CONTROL_STAT	OMAP2_L4_IO_ADDRESS(0x480022F0)
 
 #define GP_DEVICE		0x300
 
@@ -79,12 +79,6 @@
 static unsigned long omap_sram_size;
 static unsigned long omap_sram_ceil;
 
-extern unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
-					 unsigned long sram_vstart,
-					 unsigned long sram_size,
-					 unsigned long pstart_avail,
-					 unsigned long size_avail);
-
 /*
  * Depending on the target RAMFS firewall setup, the public usable amount of
  * SRAM varies.  The default accessible size for all device types is 2k. A GP
@@ -93,16 +87,7 @@
  */
 static int is_sram_locked(void)
 {
-	int type = 0;
-
-	if (cpu_is_omap44xx())
-		/* Not yet supported */
-		return 0;
-
-	if (cpu_is_omap242x())
-		type = omap_rev() & OMAP2_DEVICETYPE_MASK;
-
-	if (type == GP_DEVICE) {
+	if (OMAP2_DEVICE_TYPE_GP == omap_type()) {
 		/* RAMFW: R/W access to all initiators for all qualifier sets */
 		if (cpu_is_omap242x()) {
 			__raw_writel(0xFF, OMAP24XX_VA_REQINFOPERM0); /* all q-vects */
@@ -127,7 +112,7 @@
  * to secure SRAM will hang the system. Also the SRAM is not
  * yet mapped at this point.
  */
-void __init omap_detect_sram(void)
+static void __init omap_detect_sram(void)
 {
 	unsigned long reserved;
 
@@ -213,7 +198,7 @@
 /*
  * Note that we cannot use ioremap for SRAM, as clock init needs SRAM early.
  */
-void __init omap_map_sram(void)
+static void __init omap_map_sram(void)
 {
 	unsigned long base;
 
@@ -330,7 +315,7 @@
 #endif
 
 #ifdef CONFIG_ARCH_OMAP2420
-int __init omap242x_sram_init(void)
+static int __init omap242x_sram_init(void)
 {
 	_omap2_sram_ddr_init = omap_sram_push(omap242x_sram_ddr_init,
 					omap242x_sram_ddr_init_sz);
@@ -351,7 +336,7 @@
 #endif
 
 #ifdef CONFIG_ARCH_OMAP2430
-int __init omap243x_sram_init(void)
+static int __init omap243x_sram_init(void)
 {
 	_omap2_sram_ddr_init = omap_sram_push(omap243x_sram_ddr_init,
 					omap243x_sram_ddr_init_sz);
@@ -407,7 +392,7 @@
 }
 #endif /* CONFIG_PM */
 
-int __init omap34xx_sram_init(void)
+static int __init omap34xx_sram_init(void)
 {
 	_omap3_sram_configure_core_dpll =
 		omap_sram_push(omap3_sram_configure_core_dpll,
@@ -423,7 +408,7 @@
 #endif
 
 #ifdef CONFIG_ARCH_OMAP4
-int __init omap44xx_sram_init(void)
+static int __init omap44xx_sram_init(void)
 {
 	printk(KERN_ERR "FIXME: %s not implemented\n", __func__);
 
diff --git a/arch/arm/plat-omap/sram.h b/arch/arm/plat-omap/sram.h
new file mode 100644
index 0000000..29b43ef
--- /dev/null
+++ b/arch/arm/plat-omap/sram.h
@@ -0,0 +1,6 @@
+#ifndef __PLAT_OMAP_SRAM_H__
+#define __PLAT_OMAP_SRAM_H__
+
+extern int __init omap_sram_init(void);
+
+#endif /* __PLAT_OMAP_SRAM_H__ */
diff --git a/arch/avr32/include/asm/pgtable.h b/arch/avr32/include/asm/pgtable.h
index a9ae30c..6fbfea6 100644
--- a/arch/avr32/include/asm/pgtable.h
+++ b/arch/avr32/include/asm/pgtable.h
@@ -319,9 +319,7 @@
 #define pte_offset_kernel(dir, address)					\
 	((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(address))
 #define pte_offset_map(dir, address) pte_offset_kernel(dir, address)
-#define pte_offset_map_nested(dir, address) pte_offset_kernel(dir, address)
 #define pte_unmap(pte)		do { } while (0)
-#define pte_unmap_nested(pte)	do { } while (0)
 
 struct vm_area_struct;
 extern void update_mmu_cache(struct vm_area_struct * vma,
diff --git a/arch/blackfin/Kconfig.debug b/arch/blackfin/Kconfig.debug
index d1825cb..acb8379 100644
--- a/arch/blackfin/Kconfig.debug
+++ b/arch/blackfin/Kconfig.debug
@@ -102,17 +102,6 @@
 
 endchoice
 
-config DEBUG_ICACHE_CHECK
-	bool "Check Instruction cache coherency"
-	depends on DEBUG_KERNEL
-	depends on DEBUG_HWERR
-	help
-	  Say Y here if you are getting weird unexplained errors. This will
-	  ensure that icache is what SDRAM says it should be by doing a
-	  byte wise comparison between SDRAM and instruction cache. This
-	  also relocates the irq_panic() function to L1 memory, (which is
-	  un-cached).
-
 config DEBUG_HUNT_FOR_ZERO
 	bool "Catch NULL pointer reads/writes"
 	default y
diff --git a/arch/blackfin/configs/BF518F-EZBRD_defconfig b/arch/blackfin/configs/BF518F-EZBRD_defconfig
index 46fac1bf..c0b988e 100644
--- a/arch/blackfin/configs/BF518F-EZBRD_defconfig
+++ b/arch/blackfin/configs/BF518F-EZBRD_defconfig
@@ -35,6 +35,7 @@
 CONFIG_BANK_3=0x99B2
 CONFIG_BINFMT_FLAT=y
 CONFIG_BINFMT_ZFLAT=y
+CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -114,7 +115,6 @@
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_CCITT=m
diff --git a/arch/blackfin/configs/BF526-EZBRD_defconfig b/arch/blackfin/configs/BF526-EZBRD_defconfig
index 8024080..864af5b 100644
--- a/arch/blackfin/configs/BF526-EZBRD_defconfig
+++ b/arch/blackfin/configs/BF526-EZBRD_defconfig
@@ -40,6 +40,7 @@
 CONFIG_BANK_3=0x99B2
 CONFIG_BINFMT_FLAT=y
 CONFIG_BINFMT_ZFLAT=y
+CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -152,7 +153,6 @@
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_CCITT=m
diff --git a/arch/blackfin/configs/BF527-AD7160-EVAL_defconfig b/arch/blackfin/configs/BF527-AD7160-EVAL_defconfig
index 08c55f6..7b6a337 100644
--- a/arch/blackfin/configs/BF527-AD7160-EVAL_defconfig
+++ b/arch/blackfin/configs/BF527-AD7160-EVAL_defconfig
@@ -9,6 +9,7 @@
 # CONFIG_ELF_CORE is not set
 # CONFIG_AIO is not set
 CONFIG_SLAB=y
+CONFIG_MMAP_ALLOW_UNINITIALIZED=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
@@ -101,5 +102,4 @@
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRC_CCITT=m
diff --git a/arch/blackfin/configs/BF527-EZKIT-V2_defconfig b/arch/blackfin/configs/BF527-EZKIT-V2_defconfig
index 4a91255..4faa6b4 100644
--- a/arch/blackfin/configs/BF527-EZKIT-V2_defconfig
+++ b/arch/blackfin/configs/BF527-EZKIT-V2_defconfig
@@ -20,6 +20,7 @@
 # CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_BF527=y
 CONFIG_BF_REV_0_2=y
@@ -38,6 +39,7 @@
 CONFIG_BANK_3=0x99B2
 CONFIG_BINFMT_FLAT=y
 CONFIG_BINFMT_ZFLAT=y
+CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -181,6 +183,5 @@
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/blackfin/configs/BF527-EZKIT_defconfig b/arch/blackfin/configs/BF527-EZKIT_defconfig
index 8ccf3ce..9d893eb 100644
--- a/arch/blackfin/configs/BF527-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF527-EZKIT_defconfig
@@ -20,6 +20,7 @@
 # CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_BF527=y
 CONFIG_BF_REV_0_1=y
@@ -37,6 +38,7 @@
 CONFIG_BANK_3=0x99B2
 CONFIG_BINFMT_FLAT=y
 CONFIG_BINFMT_ZFLAT=y
+CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -173,6 +175,5 @@
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/blackfin/configs/BF527-TLL6527M_defconfig b/arch/blackfin/configs/BF527-TLL6527M_defconfig
index 92ded5e..97a2767 100644
--- a/arch/blackfin/configs/BF527-TLL6527M_defconfig
+++ b/arch/blackfin/configs/BF527-TLL6527M_defconfig
@@ -174,7 +174,6 @@
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC7=m
diff --git a/arch/blackfin/configs/BF533-EZKIT_defconfig b/arch/blackfin/configs/BF533-EZKIT_defconfig
index c40e0f1..f847743 100644
--- a/arch/blackfin/configs/BF533-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF533-EZKIT_defconfig
@@ -20,6 +20,7 @@
 # CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_BFIN533_EZKIT=y
 CONFIG_TIMER0=11
@@ -107,6 +108,5 @@
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/blackfin/configs/BF533-STAMP_defconfig b/arch/blackfin/configs/BF533-STAMP_defconfig
index aa8c1d7..0e7262c 100644
--- a/arch/blackfin/configs/BF533-STAMP_defconfig
+++ b/arch/blackfin/configs/BF533-STAMP_defconfig
@@ -20,6 +20,7 @@
 # CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_TIMER0=11
 CONFIG_HIGH_RES_TIMERS=y
@@ -121,6 +122,5 @@
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/blackfin/configs/BF537-STAMP_defconfig b/arch/blackfin/configs/BF537-STAMP_defconfig
index f245c0b..4d14a00 100644
--- a/arch/blackfin/configs/BF537-STAMP_defconfig
+++ b/arch/blackfin/configs/BF537-STAMP_defconfig
@@ -20,9 +20,9 @@
 # CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_BF537=y
-CONFIG_IRQ_ERROR=11
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
 CONFIG_BFIN_GPTIMERS=m
@@ -133,6 +133,5 @@
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/blackfin/configs/BF538-EZKIT_defconfig b/arch/blackfin/configs/BF538-EZKIT_defconfig
index 74a330c..fbee9d7 100644
--- a/arch/blackfin/configs/BF538-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF538-EZKIT_defconfig
@@ -20,6 +20,7 @@
 # CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_BF538=y
 CONFIG_IRQ_TIMER0=12
@@ -31,6 +32,7 @@
 CONFIG_BANK_3=0x99B2
 CONFIG_BINFMT_FLAT=y
 CONFIG_BINFMT_ZFLAT=y
+CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -129,6 +131,5 @@
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/blackfin/configs/BF548-EZKIT_defconfig b/arch/blackfin/configs/BF548-EZKIT_defconfig
index 29373cb..05dd11d 100644
--- a/arch/blackfin/configs/BF548-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF548-EZKIT_defconfig
@@ -40,6 +40,7 @@
 CONFIG_EBIU_FCTLVAL=0x6
 CONFIG_BINFMT_FLAT=y
 CONFIG_BINFMT_ZFLAT=y
+CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -62,7 +63,7 @@
 CONFIG_IRTTY_SIR=m
 CONFIG_BFIN_SIR=m
 CONFIG_BFIN_SIR3=y
-CONFIG_LIB80211=m
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_FW_LOADER=m
 CONFIG_MTD=y
@@ -92,6 +93,7 @@
 CONFIG_SMSC911X=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 is not set
 CONFIG_INPUT_EVDEV=m
diff --git a/arch/blackfin/configs/BF561-ACVILON_defconfig b/arch/blackfin/configs/BF561-ACVILON_defconfig
index 1f12034..bcb14d1 100644
--- a/arch/blackfin/configs/BF561-ACVILON_defconfig
+++ b/arch/blackfin/configs/BF561-ACVILON_defconfig
@@ -14,6 +14,7 @@
 # CONFIG_EVENTFD is not set
 # CONFIG_AIO is not set
 CONFIG_SLAB=y
+CONFIG_MMAP_ALLOW_UNINITIALIZED=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_LBDAF is not set
@@ -44,6 +45,7 @@
 CONFIG_SYN_COOKIES=y
 # CONFIG_INET_LRO is not set
 # CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
@@ -71,6 +73,7 @@
 CONFIG_SMSC911X=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
@@ -147,5 +150,4 @@
 CONFIG_DEBUG_MMRS=y
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/blackfin/configs/BF561-EZKIT_defconfig b/arch/blackfin/configs/BF561-EZKIT_defconfig
index 8913d99..843aaa5 100644
--- a/arch/blackfin/configs/BF561-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF561-EZKIT_defconfig
@@ -35,6 +35,7 @@
 CONFIG_BANK_3=0xAAC2
 CONFIG_BINFMT_FLAT=y
 CONFIG_BINFMT_ZFLAT=y
+CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
diff --git a/arch/blackfin/configs/BlackStamp_defconfig b/arch/blackfin/configs/BlackStamp_defconfig
index 0242917b..dae7adf 100644
--- a/arch/blackfin/configs/BlackStamp_defconfig
+++ b/arch/blackfin/configs/BlackStamp_defconfig
@@ -40,6 +40,7 @@
 CONFIG_IP_PNP=y
 # CONFIG_INET_LRO is not set
 # CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
@@ -63,6 +64,7 @@
 CONFIG_SMC91X=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=m
 # CONFIG_INPUT_KEYBOARD is not set
@@ -104,5 +106,4 @@
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRC_CCITT=m
diff --git a/arch/blackfin/configs/CM-BF527_defconfig b/arch/blackfin/configs/CM-BF527_defconfig
index 0512fef..f341424 100644
--- a/arch/blackfin/configs/CM-BF527_defconfig
+++ b/arch/blackfin/configs/CM-BF527_defconfig
@@ -50,6 +50,7 @@
 # CONFIG_INET_LRO is not set
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
@@ -70,9 +71,9 @@
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_BFIN_MAC=y
-CONFIG_BFIN_MAC_RMII=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
@@ -124,7 +125,6 @@
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_EARLY_PRINTK=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_CCITT=m
diff --git a/arch/blackfin/configs/CM-BF533_defconfig b/arch/blackfin/configs/CM-BF533_defconfig
index 05e09be..8c7e08f 100644
--- a/arch/blackfin/configs/CM-BF533_defconfig
+++ b/arch/blackfin/configs/CM-BF533_defconfig
@@ -33,6 +33,7 @@
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
 CONFIG_MTD_PARTITIONS=y
@@ -47,6 +48,7 @@
 CONFIG_NETDEVICES=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
@@ -72,7 +74,6 @@
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRC_CCITT=y
 CONFIG_CRC_ITU_T=y
 CONFIG_CRC7=y
diff --git a/arch/blackfin/configs/CM-BF537E_defconfig b/arch/blackfin/configs/CM-BF537E_defconfig
index d2eb532..bd3cb76 100644
--- a/arch/blackfin/configs/CM-BF537E_defconfig
+++ b/arch/blackfin/configs/CM-BF537E_defconfig
@@ -48,6 +48,7 @@
 # CONFIG_INET_LRO is not set
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
@@ -65,6 +66,7 @@
 CONFIG_BFIN_MAC=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
@@ -99,7 +101,6 @@
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_CCITT=m
diff --git a/arch/blackfin/configs/CM-BF537U_defconfig b/arch/blackfin/configs/CM-BF537U_defconfig
index 9d52c44..82224f3 100644
--- a/arch/blackfin/configs/CM-BF537U_defconfig
+++ b/arch/blackfin/configs/CM-BF537U_defconfig
@@ -44,6 +44,7 @@
 # CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
@@ -59,6 +60,7 @@
 CONFIG_NETDEVICES=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
@@ -90,7 +92,6 @@
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRC_CCITT=m
 CONFIG_CRC_ITU_T=y
 CONFIG_CRC7=y
diff --git a/arch/blackfin/configs/CM-BF548_defconfig b/arch/blackfin/configs/CM-BF548_defconfig
index 9de13cf..433598c 100644
--- a/arch/blackfin/configs/CM-BF548_defconfig
+++ b/arch/blackfin/configs/CM-BF548_defconfig
@@ -49,6 +49,7 @@
 # CONFIG_INET_LRO is not set
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
@@ -71,6 +72,7 @@
 CONFIG_SMSC911X=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=m
 CONFIG_INPUT_EVBUG=m
@@ -167,7 +169,6 @@
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
 CONFIG_CRC_CCITT=m
diff --git a/arch/blackfin/configs/CM-BF561_defconfig b/arch/blackfin/configs/CM-BF561_defconfig
index 238353a..ded7d84 100644
--- a/arch/blackfin/configs/CM-BF561_defconfig
+++ b/arch/blackfin/configs/CM-BF561_defconfig
@@ -48,6 +48,7 @@
 # CONFIG_INET_LRO is not set
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
 CONFIG_MTD_PARTITIONS=y
@@ -67,6 +68,7 @@
 CONFIG_SMSC911X=m
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
@@ -99,7 +101,6 @@
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRC_CCITT=m
 CONFIG_CRC_ITU_T=y
 CONFIG_CRC7=y
diff --git a/arch/blackfin/configs/H8606_defconfig b/arch/blackfin/configs/H8606_defconfig
index 0cb524e..700fb70 100644
--- a/arch/blackfin/configs/H8606_defconfig
+++ b/arch/blackfin/configs/H8606_defconfig
@@ -33,6 +33,7 @@
 CONFIG_IRCOMM=m
 CONFIG_IRDA_CACHE_LAST_LSAP=y
 CONFIG_IRTTY_SIR=m
+# CONFIG_WIRELESS is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
 CONFIG_MTD_PARTITIONS=y
@@ -50,6 +51,7 @@
 CONFIG_DM9000=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=y
 # CONFIG_KEYBOARD_ATKBD is not set
@@ -84,4 +86,3 @@
 CONFIG_NLS=m
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
diff --git a/arch/blackfin/configs/IP0X_defconfig b/arch/blackfin/configs/IP0X_defconfig
index 2a3411ef..b40156d 100644
--- a/arch/blackfin/configs/IP0X_defconfig
+++ b/arch/blackfin/configs/IP0X_defconfig
@@ -41,6 +41,7 @@
 CONFIG_IP_NF_FILTER=y
 CONFIG_IP_NF_TARGET_REJECT=y
 CONFIG_IP_NF_MANGLE=y
+# CONFIG_WIRELESS is not set
 CONFIG_MTD=y
 CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CHAR=y
@@ -60,6 +61,7 @@
 CONFIG_DM9000=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
@@ -89,5 +91,4 @@
 CONFIG_NLS_ISO8859_1=y
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRC_CCITT=y
diff --git a/arch/blackfin/configs/PNAV-10_defconfig b/arch/blackfin/configs/PNAV-10_defconfig
index fea3033..be866d9 100644
--- a/arch/blackfin/configs/PNAV-10_defconfig
+++ b/arch/blackfin/configs/PNAV-10_defconfig
@@ -14,6 +14,7 @@
 # CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_BF537=y
 CONFIG_IRQ_TIMER0=12
@@ -107,7 +108,6 @@
 # CONFIG_DEBUG_HUNT_FOR_ZERO is not set
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 # CONFIG_ACCESS_CHECK is not set
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_CCITT=m
diff --git a/arch/blackfin/configs/SRV1_defconfig b/arch/blackfin/configs/SRV1_defconfig
index 9811b31..b64bdf7 100644
--- a/arch/blackfin/configs/SRV1_defconfig
+++ b/arch/blackfin/configs/SRV1_defconfig
@@ -35,6 +35,7 @@
 CONFIG_IRCOMM=m
 CONFIG_IRDA_CACHE_LAST_LSAP=y
 CONFIG_IRTTY_SIR=m
+# CONFIG_WIRELESS is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
 CONFIG_MTD_PARTITIONS=y
@@ -51,6 +52,7 @@
 CONFIG_NETDEVICES=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=m
 # CONFIG_INPUT_KEYBOARD is not set
@@ -85,4 +87,3 @@
 CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
diff --git a/arch/blackfin/configs/TCM-BF518_defconfig b/arch/blackfin/configs/TCM-BF518_defconfig
index 412bf79..1bccd9a 100644
--- a/arch/blackfin/configs/TCM-BF518_defconfig
+++ b/arch/blackfin/configs/TCM-BF518_defconfig
@@ -128,7 +128,6 @@
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_CCITT=m
diff --git a/arch/blackfin/configs/TCM-BF537_defconfig b/arch/blackfin/configs/TCM-BF537_defconfig
index 04bf52c..00ce899 100644
--- a/arch/blackfin/configs/TCM-BF537_defconfig
+++ b/arch/blackfin/configs/TCM-BF537_defconfig
@@ -40,6 +40,7 @@
 CONFIG_INET=y
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
@@ -57,6 +58,7 @@
 CONFIG_BFIN_MAC=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
diff --git a/arch/blackfin/include/asm/bfin5xx_spi.h b/arch/blackfin/include/asm/bfin5xx_spi.h
index 0b5136e..5392583 100644
--- a/arch/blackfin/include/asm/bfin5xx_spi.h
+++ b/arch/blackfin/include/asm/bfin5xx_spi.h
@@ -60,6 +60,8 @@
 	__BFP(shadow);
 };
 
+#undef __BFP
+
 #define MAX_CTRL_CS          8  /* cs in spi controller */
 
 /* device.platform_data for SSP controller devices */
diff --git a/arch/blackfin/include/asm/bfin_ppi.h b/arch/blackfin/include/asm/bfin_ppi.h
index 0039008..3be05fa 100644
--- a/arch/blackfin/include/asm/bfin_ppi.h
+++ b/arch/blackfin/include/asm/bfin_ppi.h
@@ -48,4 +48,6 @@
 	u32 clip;
 };
 
+#undef __BFP
+
 #endif
diff --git a/arch/blackfin/include/asm/bfin_twi.h b/arch/blackfin/include/asm/bfin_twi.h
new file mode 100644
index 0000000..e767d64
--- /dev/null
+++ b/arch/blackfin/include/asm/bfin_twi.h
@@ -0,0 +1,45 @@
+/*
+ * bfin_twi.h - interface to Blackfin TWIs
+ *
+ * Copyright 2005-2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __ASM_BFIN_TWI_H__
+#define __ASM_BFIN_TWI_H__
+
+#include <linux/types.h>
+
+/*
+ * All Blackfin system MMRs are padded to 32bits even if the register
+ * itself is only 16bits.  So use a helper macro to streamline this.
+ */
+#define __BFP(m) u16 m; u16 __pad_##m
+
+/*
+ * bfin twi registers layout
+ */
+struct bfin_twi_regs {
+	__BFP(clkdiv);
+	__BFP(control);
+	__BFP(slave_ctl);
+	__BFP(slave_stat);
+	__BFP(slave_addr);
+	__BFP(master_ctl);
+	__BFP(master_stat);
+	__BFP(master_addr);
+	__BFP(int_stat);
+	__BFP(int_mask);
+	__BFP(fifo_ctl);
+	__BFP(fifo_stat);
+	u32 __pad[20];
+	__BFP(xmt_data8);
+	__BFP(xmt_data16);
+	__BFP(rcv_data8);
+	__BFP(rcv_data16);
+};
+
+#undef __BFP
+
+#endif
diff --git a/arch/blackfin/include/asm/cdef_LPBlackfin.h b/arch/blackfin/include/asm/cdef_LPBlackfin.h
index a1f6817..59af63c 100644
--- a/arch/blackfin/include/asm/cdef_LPBlackfin.h
+++ b/arch/blackfin/include/asm/cdef_LPBlackfin.h
@@ -179,7 +179,7 @@
 #define bfin_write_ITEST_DATA0(val)          bfin_write32(ITEST_DATA0,val)
 #define bfin_write_ITEST_DATA1(val)          bfin_write32(ITEST_DATA1,val)
 
-#if ANOMALY_05000481
+#if !ANOMALY_05000481
 #define bfin_read_ITEST_COMMAND()            bfin_read32(ITEST_COMMAND)
 #define bfin_read_ITEST_DATA0()              bfin_read32(ITEST_DATA0)
 #define bfin_read_ITEST_DATA1()              bfin_read32(ITEST_DATA1)
diff --git a/arch/blackfin/include/asm/entry.h b/arch/blackfin/include/asm/entry.h
index a6886f6..4104d57 100644
--- a/arch/blackfin/include/asm/entry.h
+++ b/arch/blackfin/include/asm/entry.h
@@ -15,14 +15,6 @@
 #define	LFLUSH_I_AND_D	0x00000808
 #define	LSIGTRAP	5
 
-/* process bits for task_struct.flags */
-#define	PF_TRACESYS_OFF	3
-#define	PF_TRACESYS_BIT	5
-#define	PF_PTRACED_OFF	3
-#define	PF_PTRACED_BIT	4
-#define	PF_DTRACE_OFF	1
-#define	PF_DTRACE_BIT	5
-
 /*
  * NOTE!  The single-stepping code assumes that all interrupt handlers
  * start by saving SYSCFG on the stack with their first instruction.
diff --git a/arch/blackfin/mach-bf518/boards/ezbrd.c b/arch/blackfin/mach-bf518/boards/ezbrd.c
index f95e609..b894c8a 100644
--- a/arch/blackfin/mach-bf518/boards/ezbrd.c
+++ b/arch/blackfin/mach-bf518/boards/ezbrd.c
@@ -87,13 +87,55 @@
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = {
+	P_MII0_ETxD0,
+	P_MII0_ETxD1,
+	P_MII0_ETxEN,
+	P_MII0_ERxD0,
+	P_MII0_ERxD1,
+	P_MII0_TxCLK,
+	P_MII0_PHYINT,
+	P_MII0_CRS,
+	P_MII0_MDC,
+	P_MII0_MDIO,
+	0
+};
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+	{
+		.addr = 1,
+		.irq = IRQ_MAC_PHYINT,
+	},
+	{
+		.addr = 2,
+		.irq = IRQ_MAC_PHYINT,
+	},
+	{
+		.addr = 3,
+		.irq = IRQ_MAC_PHYINT,
+	},
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+	.phydev_number = 3,
+	.phydev_data = bfin_phydev_data,
+	.phy_mode = PHY_INTERFACE_MODE_MII,
+	.mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
 	.name = "bfin_mii_bus",
+	.dev = {
+		.platform_data = &bfin_mii_bus_data,
+	}
 };
 
 static struct platform_device bfin_mac_device = {
 	.name = "bfin_mac",
-	.dev.platform_data = &bfin_mii_bus,
+	.dev = {
+		.platform_data = &bfin_mii_bus,
+	}
 };
 
 #if defined(CONFIG_NET_DSA_KSZ8893M) || defined(CONFIG_NET_DSA_KSZ8893M_MODULE)
diff --git a/arch/blackfin/mach-bf518/boards/tcm-bf518.c b/arch/blackfin/mach-bf518/boards/tcm-bf518.c
index bead810..e6ce1d7 100644
--- a/arch/blackfin/mach-bf518/boards/tcm-bf518.c
+++ b/arch/blackfin/mach-bf518/boards/tcm-bf518.c
@@ -81,13 +81,35 @@
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_MII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+	{
+		.addr = 1,
+		.irq = IRQ_MAC_PHYINT,
+	},
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+	.phydev_number = 1,
+	.phydev_data = bfin_phydev_data,
+	.phy_mode = PHY_INTERFACE_MODE_MII,
+	.mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
 	.name = "bfin_mii_bus",
+	.dev = {
+		.platform_data = &bfin_mii_bus_data,
+	}
 };
 
 static struct platform_device bfin_mac_device = {
 	.name = "bfin_mac",
-	.dev.platform_data = &bfin_mii_bus,
+	.dev = {
+		.platform_data = &bfin_mii_bus,
+	}
 };
 #endif
 
diff --git a/arch/blackfin/mach-bf527/boards/cm_bf527.c b/arch/blackfin/mach-bf527/boards/cm_bf527.c
index 38037c7..2c31af7 100644
--- a/arch/blackfin/mach-bf527/boards/cm_bf527.c
+++ b/arch/blackfin/mach-bf527/boards/cm_bf527.c
@@ -273,13 +273,35 @@
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_RMII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+	{
+		.addr = 1,
+		.irq = IRQ_MAC_PHYINT,
+	},
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+	.phydev_number = 1,
+	.phydev_data = bfin_phydev_data,
+	.phy_mode = PHY_INTERFACE_MODE_RMII,
+	.mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
 	.name = "bfin_mii_bus",
+	.dev = {
+		.platform_data = &bfin_mii_bus_data,
+	}
 };
 
 static struct platform_device bfin_mac_device = {
 	.name = "bfin_mac",
-	.dev.platform_data = &bfin_mii_bus,
+	.dev = {
+		.platform_data = &bfin_mii_bus,
+	}
 };
 #endif
 
diff --git a/arch/blackfin/mach-bf527/boards/ezbrd.c b/arch/blackfin/mach-bf527/boards/ezbrd.c
index 6cc64a1..9a736a8 100644
--- a/arch/blackfin/mach-bf527/boards/ezbrd.c
+++ b/arch/blackfin/mach-bf527/boards/ezbrd.c
@@ -193,13 +193,35 @@
 
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_RMII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+	{
+		.addr = 1,
+		.irq = IRQ_MAC_PHYINT,
+	},
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+	.phydev_number = 1,
+	.phydev_data = bfin_phydev_data,
+	.phy_mode = PHY_INTERFACE_MODE_RMII,
+	.mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
 	.name = "bfin_mii_bus",
+	.dev = {
+		.platform_data = &bfin_mii_bus_data,
+	}
 };
 
 static struct platform_device bfin_mac_device = {
 	.name = "bfin_mac",
-	.dev.platform_data = &bfin_mii_bus,
+	.dev = {
+		.platform_data = &bfin_mii_bus,
+	}
 };
 #endif
 
diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c
index df82723..9222bc0 100644
--- a/arch/blackfin/mach-bf527/boards/ezkit.c
+++ b/arch/blackfin/mach-bf527/boards/ezkit.c
@@ -366,13 +366,35 @@
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_RMII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+	{
+		.addr = 1,
+		.irq = IRQ_MAC_PHYINT,
+	},
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+	.phydev_number = 1,
+	.phydev_data = bfin_phydev_data,
+	.phy_mode = PHY_INTERFACE_MODE_RMII,
+	.mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
 	.name = "bfin_mii_bus",
+	.dev = {
+		.platform_data = &bfin_mii_bus_data,
+	}
 };
 
 static struct platform_device bfin_mac_device = {
 	.name = "bfin_mac",
-	.dev.platform_data = &bfin_mii_bus,
+	.dev = {
+		.platform_data = &bfin_mii_bus,
+	}
 };
 #endif
 
diff --git a/arch/blackfin/mach-bf527/boards/tll6527m.c b/arch/blackfin/mach-bf527/boards/tll6527m.c
index ae4130e..9ec5757 100644
--- a/arch/blackfin/mach-bf527/boards/tll6527m.c
+++ b/arch/blackfin/mach-bf527/boards/tll6527m.c
@@ -257,13 +257,35 @@
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_RMII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+	{
+		.addr = 1,
+		.irq = IRQ_MAC_PHYINT,
+	},
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+	.phydev_number = 1,
+	.phydev_data = bfin_phydev_data,
+	.phy_mode = PHY_INTERFACE_MODE_RMII,
+	.mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
 	.name = "bfin_mii_bus",
+	.dev = {
+		.platform_data = &bfin_mii_bus_data,
+	}
 };
 
 static struct platform_device bfin_mac_device = {
 	.name = "bfin_mac",
-	.dev.platform_data = &bfin_mii_bus,
+	.dev = {
+		.platform_data = &bfin_mii_bus,
+	}
 };
 #endif
 
diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537e.c b/arch/blackfin/mach-bf537/boards/cm_bf537e.c
index e2e7be4..836698c 100644
--- a/arch/blackfin/mach-bf537/boards/cm_bf537e.c
+++ b/arch/blackfin/mach-bf537/boards/cm_bf537e.c
@@ -597,13 +597,35 @@
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_MII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+	{
+		.addr = 1,
+		.irq = IRQ_MAC_PHYINT,
+	},
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+	.phydev_number = 1,
+	.phydev_data = bfin_phydev_data,
+	.phy_mode = PHY_INTERFACE_MODE_MII,
+	.mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
 	.name = "bfin_mii_bus",
+	.dev = {
+		.platform_data = &bfin_mii_bus_data,
+	}
 };
 
 static struct platform_device bfin_mac_device = {
 	.name = "bfin_mac",
-	.dev.platform_data = &bfin_mii_bus,
+	.dev = {
+		.platform_data = &bfin_mii_bus,
+	}
 };
 #endif
 
diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537u.c b/arch/blackfin/mach-bf537/boards/cm_bf537u.c
index 752c833..2a85670 100644
--- a/arch/blackfin/mach-bf537/boards/cm_bf537u.c
+++ b/arch/blackfin/mach-bf537/boards/cm_bf537u.c
@@ -562,13 +562,35 @@
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_MII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+	{
+		.addr = 1,
+		.irq = IRQ_MAC_PHYINT,
+	},
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+	.phydev_number = 1,
+	.phydev_data = bfin_phydev_data,
+	.phy_mode = PHY_INTERFACE_MODE_MII,
+	.mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
 	.name = "bfin_mii_bus",
+	.dev = {
+		.platform_data = &bfin_mii_bus_data,
+	}
 };
 
 static struct platform_device bfin_mac_device = {
 	.name = "bfin_mac",
-	.dev.platform_data = &bfin_mii_bus,
+	.dev = {
+		.platform_data = &bfin_mii_bus,
+	}
 };
 #endif
 
diff --git a/arch/blackfin/mach-bf537/boards/minotaur.c b/arch/blackfin/mach-bf537/boards/minotaur.c
index 05d4599..4980051 100644
--- a/arch/blackfin/mach-bf537/boards/minotaur.c
+++ b/arch/blackfin/mach-bf537/boards/minotaur.c
@@ -68,13 +68,35 @@
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_MII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+	{
+		.addr = 1,
+		.irq = IRQ_MAC_PHYINT,
+	},
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+	.phydev_number = 1,
+	.phydev_data = bfin_phydev_data,
+	.phy_mode = PHY_INTERFACE_MODE_MII,
+	.mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
 	.name = "bfin_mii_bus",
+	.dev = {
+		.platform_data = &bfin_mii_bus_data,
+	}
 };
 
 static struct platform_device bfin_mac_device = {
 	.name = "bfin_mac",
-	.dev.platform_data = &bfin_mii_bus,
+	.dev = {
+		.platform_data = &bfin_mii_bus,
+	}
 };
 #endif
 
diff --git a/arch/blackfin/mach-bf537/boards/pnav10.c b/arch/blackfin/mach-bf537/boards/pnav10.c
index 6b03808..b958078 100644
--- a/arch/blackfin/mach-bf537/boards/pnav10.c
+++ b/arch/blackfin/mach-bf537/boards/pnav10.c
@@ -99,13 +99,35 @@
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_RMII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+	{
+		.addr = 1,
+		.irq = IRQ_MAC_PHYINT,
+	},
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+	.phydev_number = 1,
+	.phydev_data = bfin_phydev_data,
+	.phy_mode = PHY_INTERFACE_MODE_RMII,
+	.mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
 	.name = "bfin_mii_bus",
+	.dev = {
+		.platform_data = &bfin_mii_bus_data,
+	}
 };
 
 static struct platform_device bfin_mac_device = {
 	.name = "bfin_mac",
-	.dev.platform_data = &bfin_mii_bus,
+	.dev = {
+		.platform_data = &bfin_mii_bus,
+	}
 };
 #endif
 
diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c
index cd2c797..3aa344c 100644
--- a/arch/blackfin/mach-bf537/boards/stamp.c
+++ b/arch/blackfin/mach-bf537/boards/stamp.c
@@ -327,13 +327,35 @@
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_MII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+	{
+		.addr = 1,
+		.irq = PHY_POLL, /* IRQ_MAC_PHYINT */
+	},
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+	.phydev_number = 1,
+	.phydev_data = bfin_phydev_data,
+	.phy_mode = PHY_INTERFACE_MODE_MII,
+	.mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
 	.name = "bfin_mii_bus",
+	.dev = {
+		.platform_data = &bfin_mii_bus_data,
+	}
 };
 
 static struct platform_device bfin_mac_device = {
 	.name = "bfin_mac",
-	.dev.platform_data = &bfin_mii_bus,
+	.dev = {
+		.platform_data = &bfin_mii_bus,
+	}
 };
 #endif
 
diff --git a/arch/blackfin/mach-bf537/boards/tcm_bf537.c b/arch/blackfin/mach-bf537/boards/tcm_bf537.c
index a4d62b5..31498ad 100644
--- a/arch/blackfin/mach-bf537/boards/tcm_bf537.c
+++ b/arch/blackfin/mach-bf537/boards/tcm_bf537.c
@@ -564,13 +564,35 @@
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_MII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+	{
+		.addr = 1,
+		.irq = IRQ_MAC_PHYINT,
+	},
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+	.phydev_number = 1,
+	.phydev_data = bfin_phydev_data,
+	.phy_mode = PHY_INTERFACE_MODE_MII,
+	.mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
 	.name = "bfin_mii_bus",
+	.dev = {
+		.platform_data = &bfin_mii_bus_data,
+	}
 };
 
 static struct platform_device bfin_mac_device = {
 	.name = "bfin_mac",
-	.dev.platform_data = &bfin_mii_bus,
+	.dev = {
+		.platform_data = &bfin_mii_bus,
+	}
 };
 #endif
 
diff --git a/arch/blackfin/mach-common/Makefile b/arch/blackfin/mach-common/Makefile
index 814cb48..ff299f2 100644
--- a/arch/blackfin/mach-common/Makefile
+++ b/arch/blackfin/mach-common/Makefile
@@ -11,4 +11,3 @@
 obj-$(CONFIG_CPU_VOLTAGE) += dpmc.o
 obj-$(CONFIG_SMP)         += smp.o
 obj-$(CONFIG_BFIN_KERNEL_CLOCK) += clocks-init.o
-obj-$(CONFIG_DEBUG_ICACHE_CHECK) += irqpanic.o
diff --git a/arch/blackfin/mach-common/irqpanic.c b/arch/blackfin/mach-common/irqpanic.c
deleted file mode 100644
index c649624..0000000
--- a/arch/blackfin/mach-common/irqpanic.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * panic kernel with dump information
- *
- * Copyright 2005-2009 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/module.h>
-#include <linux/kernel_stat.h>
-#include <linux/sched.h>
-#include <asm/blackfin.h>
-
-#define L1_ICACHE_START 0xffa10000
-#define L1_ICACHE_END   0xffa13fff
-
-/*
- * irq_panic - calls panic with string setup
- */
-__attribute__ ((l1_text))
-asmlinkage void irq_panic(int reason, struct pt_regs *regs)
-{
-	unsigned int cmd, tag, ca, cache_hi, cache_lo, *pa;
-	unsigned short i, j, die;
-	unsigned int bad[10][6];
-
-	/* check entire cache for coherency
-	 * Since printk is in cacheable memory,
-	 * don't call it until you have checked everything
-	*/
-
-	die = 0;
-	i = 0;
-
-	/* check icache */
-
-	for (ca = L1_ICACHE_START; ca <= L1_ICACHE_END && i < 10; ca += 32) {
-
-		/* Grab various address bits for the itest_cmd fields                      */
-		cmd = (((ca & 0x3000) << 4) |	/* ca[13:12] for SBNK[1:0]             */
-		       ((ca & 0x0c00) << 16) |	/* ca[11:10] for WAYSEL[1:0]           */
-		       ((ca & 0x3f8)) |	/* ca[09:03] for SET[4:0] and DW[1:0]  */
-		       0);	/* Access Tag, Read access             */
-
-		SSYNC();
-		bfin_write_ITEST_COMMAND(cmd);
-		SSYNC();
-		tag = bfin_read_ITEST_DATA0();
-		SSYNC();
-
-		/* if tag is marked as valid, check it */
-		if (tag & 1) {
-			/* The icache is arranged in 4 groups of 64-bits */
-			for (j = 0; j < 32; j += 8) {
-				cmd = ((((ca + j) & 0x3000) << 4) |	/* ca[13:12] for SBNK[1:0]             */
-				       (((ca + j) & 0x0c00) << 16) |	/* ca[11:10] for WAYSEL[1:0]           */
-				       (((ca + j) & 0x3f8)) |	/* ca[09:03] for SET[4:0] and DW[1:0]  */
-				       4);	/* Access Data, Read access             */
-
-				SSYNC();
-				bfin_write_ITEST_COMMAND(cmd);
-				SSYNC();
-
-				cache_hi = bfin_read_ITEST_DATA1();
-				cache_lo = bfin_read_ITEST_DATA0();
-
-				pa = ((unsigned int *)((tag & 0xffffcc00) |
-						       ((ca + j) & ~(0xffffcc00))));
-
-				/*
-				 * Debugging this, enable
-				 *
-				 * printk("addr: %08x %08x%08x | %08x%08x\n",
-				 *  ((unsigned int *)((tag & 0xffffcc00)  | ((ca+j) & ~(0xffffcc00)))),
-				 *   cache_hi, cache_lo, *(pa+1), *pa);
-				 */
-
-				if (cache_hi != *(pa + 1) || cache_lo != *pa) {
-					/* Since icache is not working, stay out of it, by not printing */
-					die = 1;
-					bad[i][0] = (ca + j);
-					bad[i][1] = cache_hi;
-					bad[i][2] = cache_lo;
-					bad[i][3] = ((tag & 0xffffcc00) |
-					     	((ca + j) & ~(0xffffcc00)));
-					bad[i][4] = *(pa + 1);
-					bad[i][5] = *(pa);
-					i++;
-				}
-			}
-		}
-	}
-	if (die) {
-		printk(KERN_EMERG "icache coherency error\n");
-		for (j = 0; j <= i; j++) {
-			printk(KERN_EMERG
-			    "cache address   : %08x  cache value : %08x%08x\n",
-			     bad[j][0], bad[j][1], bad[j][2]);
-			printk(KERN_EMERG
-			    "physical address: %08x  SDRAM value : %08x%08x\n",
-			     bad[j][3], bad[j][4], bad[j][5]);
-		}
-		panic("icache coherency error");
-	} else
-		printk(KERN_EMERG "icache checked, and OK\n");
-}
diff --git a/arch/cris/include/asm/pgtable.h b/arch/cris/include/asm/pgtable.h
index f63d6fc..9eaae21 100644
--- a/arch/cris/include/asm/pgtable.h
+++ b/arch/cris/include/asm/pgtable.h
@@ -248,10 +248,8 @@
 	((pte_t *) pmd_page_vaddr(*(dir)) +  __pte_offset(address))
 #define pte_offset_map(dir, address) \
 	((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
-#define pte_offset_map_nested(dir, address) pte_offset_map(dir, address)
 
 #define pte_unmap(pte) do { } while (0)
-#define pte_unmap_nested(pte) do { } while (0)
 #define pte_pfn(x)		((unsigned long)(__va((x).pte)) >> PAGE_SHIFT)
 #define pfn_pte(pfn, prot)	__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
 
diff --git a/arch/frv/include/asm/highmem.h b/arch/frv/include/asm/highmem.h
index cb4c317..a8d6565 100644
--- a/arch/frv/include/asm/highmem.h
+++ b/arch/frv/include/asm/highmem.h
@@ -112,12 +112,11 @@
 	(void *) damlr;										  \
 })
 
-static inline void *kmap_atomic(struct page *page, enum km_type type)
+static inline void *kmap_atomic_primary(struct page *page, enum km_type type)
 {
 	unsigned long paddr;
 
 	pagefault_disable();
-	debug_kmap_atomic(type);
 	paddr = page_to_phys(page);
 
 	switch (type) {
@@ -125,14 +124,6 @@
         case 1:		return __kmap_atomic_primary(1, paddr, 3);
         case 2:		return __kmap_atomic_primary(2, paddr, 4);
         case 3:		return __kmap_atomic_primary(3, paddr, 5);
-        case 4:		return __kmap_atomic_primary(4, paddr, 6);
-        case 5:		return __kmap_atomic_primary(5, paddr, 7);
-        case 6:		return __kmap_atomic_primary(6, paddr, 8);
-        case 7:		return __kmap_atomic_primary(7, paddr, 9);
-        case 8:		return __kmap_atomic_primary(8, paddr, 10);
-
-	case 9 ... 9 + NR_TLB_LINES - 1:
-		return __kmap_atomic_secondary(type - 9, paddr);
 
 	default:
 		BUG();
@@ -152,22 +143,13 @@
 	asm volatile("tlbpr %0,gr0,#4,#1" : : "r"(vaddr) : "memory");	\
 } while(0)
 
-static inline void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type)
+static inline void kunmap_atomic_primary(void *kvaddr, enum km_type type)
 {
 	switch (type) {
         case 0:		__kunmap_atomic_primary(0, 2);	break;
         case 1:		__kunmap_atomic_primary(1, 3);	break;
         case 2:		__kunmap_atomic_primary(2, 4);	break;
         case 3:		__kunmap_atomic_primary(3, 5);	break;
-        case 4:		__kunmap_atomic_primary(4, 6);	break;
-        case 5:		__kunmap_atomic_primary(5, 7);	break;
-        case 6:		__kunmap_atomic_primary(6, 8);	break;
-        case 7:		__kunmap_atomic_primary(7, 9);	break;
-        case 8:		__kunmap_atomic_primary(8, 10);	break;
-
-	case 9 ... 9 + NR_TLB_LINES - 1:
-		__kunmap_atomic_secondary(type - 9, kvaddr);
-		break;
 
 	default:
 		BUG();
@@ -175,6 +157,9 @@
 	pagefault_enable();
 }
 
+void *__kmap_atomic(struct page *page);
+void __kunmap_atomic(void *kvaddr);
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __KERNEL__ */
diff --git a/arch/frv/include/asm/pgtable.h b/arch/frv/include/asm/pgtable.h
index c18b0d3..6bc241e 100644
--- a/arch/frv/include/asm/pgtable.h
+++ b/arch/frv/include/asm/pgtable.h
@@ -451,17 +451,12 @@
 
 #if defined(CONFIG_HIGHPTE)
 #define pte_offset_map(dir, address) \
-	((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE0) + pte_index(address))
-#define pte_offset_map_nested(dir, address) \
-	((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE1) + pte_index(address))
-#define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0)
-#define pte_unmap_nested(pte) kunmap_atomic((pte), KM_PTE1)
+	((pte_t *)kmap_atomic(pmd_page(*(dir))) + pte_index(address))
+#define pte_unmap(pte) kunmap_atomic(pte)
 #else
 #define pte_offset_map(dir, address) \
 	((pte_t *)page_address(pmd_page(*(dir))) + pte_index(address))
-#define pte_offset_map_nested(dir, address) pte_offset_map((dir), (address))
 #define pte_unmap(pte) do { } while (0)
-#define pte_unmap_nested(pte) do { } while (0)
 #endif
 
 /*
diff --git a/arch/frv/mb93090-mb00/pci-dma.c b/arch/frv/mb93090-mb00/pci-dma.c
index 85d110b..41098a3 100644
--- a/arch/frv/mb93090-mb00/pci-dma.c
+++ b/arch/frv/mb93090-mb00/pci-dma.c
@@ -61,14 +61,14 @@
 	dampr2 = __get_DAMPR(2);
 
 	for (i = 0; i < nents; i++) {
-		vaddr = kmap_atomic(sg_page(&sg[i]), __KM_CACHE);
+		vaddr = kmap_atomic_primary(sg_page(&sg[i]), __KM_CACHE);
 
 		frv_dcache_writeback((unsigned long) vaddr,
 				     (unsigned long) vaddr + PAGE_SIZE);
 
 	}
 
-	kunmap_atomic(vaddr, __KM_CACHE);
+	kunmap_atomic_primary(vaddr, __KM_CACHE);
 	if (dampr2) {
 		__set_DAMPR(2, dampr2);
 		__set_IAMPR(2, dampr2);
diff --git a/arch/frv/mm/cache-page.c b/arch/frv/mm/cache-page.c
index 0261cbe..b24ade2 100644
--- a/arch/frv/mm/cache-page.c
+++ b/arch/frv/mm/cache-page.c
@@ -26,11 +26,11 @@
 
 	dampr2 = __get_DAMPR(2);
 
-	vaddr = kmap_atomic(page, __KM_CACHE);
+	vaddr = kmap_atomic_primary(page, __KM_CACHE);
 
 	frv_dcache_writeback((unsigned long) vaddr, (unsigned long) vaddr + PAGE_SIZE);
 
-	kunmap_atomic(vaddr, __KM_CACHE);
+	kunmap_atomic_primary(vaddr, __KM_CACHE);
 
 	if (dampr2) {
 		__set_DAMPR(2, dampr2);
@@ -54,12 +54,12 @@
 
 	dampr2 = __get_DAMPR(2);
 
-	vaddr = kmap_atomic(page, __KM_CACHE);
+	vaddr = kmap_atomic_primary(page, __KM_CACHE);
 
 	start = (start & ~PAGE_MASK) | (unsigned long) vaddr;
 	frv_cache_wback_inv(start, start + len);
 
-	kunmap_atomic(vaddr, __KM_CACHE);
+	kunmap_atomic_primary(vaddr, __KM_CACHE);
 
 	if (dampr2) {
 		__set_DAMPR(2, dampr2);
diff --git a/arch/frv/mm/highmem.c b/arch/frv/mm/highmem.c
index eadd076..61088dc 100644
--- a/arch/frv/mm/highmem.c
+++ b/arch/frv/mm/highmem.c
@@ -36,3 +36,53 @@
 {
 	return virt_to_page(ptr);
 }
+
+void *__kmap_atomic(struct page *page)
+{
+	unsigned long paddr;
+	int type;
+
+	pagefault_disable();
+	type = kmap_atomic_idx_push();
+	paddr = page_to_phys(page);
+
+	switch (type) {
+	/*
+	 * The first 4 primary maps are reserved for architecture code
+	 */
+	case 0:		return __kmap_atomic_primary(4, paddr, 6);
+	case 1:		return __kmap_atomic_primary(5, paddr, 7);
+	case 2:		return __kmap_atomic_primary(6, paddr, 8);
+	case 3:		return __kmap_atomic_primary(7, paddr, 9);
+	case 4:		return __kmap_atomic_primary(8, paddr, 10);
+
+	case 5 ... 5 + NR_TLB_LINES - 1:
+		return __kmap_atomic_secondary(type - 5, paddr);
+
+	default:
+		BUG();
+		return NULL;
+	}
+}
+EXPORT_SYMBOL(__kmap_atomic);
+
+void __kunmap_atomic(void *kvaddr)
+{
+	int type = kmap_atomic_idx_pop();
+	switch (type) {
+	case 0:		__kunmap_atomic_primary(4, 6);	break;
+	case 1:		__kunmap_atomic_primary(5, 7);	break;
+	case 2:		__kunmap_atomic_primary(6, 8);	break;
+	case 3:		__kunmap_atomic_primary(7, 9);	break;
+	case 4:		__kunmap_atomic_primary(8, 10);	break;
+
+	case 5 ... 5 + NR_TLB_LINES - 1:
+		__kunmap_atomic_secondary(type - 5, kvaddr);
+		break;
+
+	default:
+		BUG();
+	}
+	pagefault_enable();
+}
+EXPORT_SYMBOL(__kunmap_atomic);
diff --git a/arch/ia64/include/asm/pgtable.h b/arch/ia64/include/asm/pgtable.h
index c3286f4..1a97af3 100644
--- a/arch/ia64/include/asm/pgtable.h
+++ b/arch/ia64/include/asm/pgtable.h
@@ -406,9 +406,7 @@
 #define pte_index(addr)	 	(((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
 #define pte_offset_kernel(dir,addr)	((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(addr))
 #define pte_offset_map(dir,addr)	pte_offset_kernel(dir, addr)
-#define pte_offset_map_nested(dir,addr)	pte_offset_map(dir, addr)
 #define pte_unmap(pte)			do { } while (0)
-#define pte_unmap_nested(pte)		do { } while (0)
 
 /* atomic versions of the some PTE manipulations: */
 
diff --git a/arch/ia64/include/asm/siginfo.h b/arch/ia64/include/asm/siginfo.h
index 118d429..c8fcaa2 100644
--- a/arch/ia64/include/asm/siginfo.h
+++ b/arch/ia64/include/asm/siginfo.h
@@ -62,6 +62,7 @@
 			int _imm;		/* immediate value for "break" */
 			unsigned int _flags;	/* see below */
 			unsigned long _isr;	/* isr */
+			short _addr_lsb;	/* lsb of faulting address */
 		} _sigfault;
 
 		/* SIGPOLL */
diff --git a/arch/m32r/include/asm/pgtable.h b/arch/m32r/include/asm/pgtable.h
index e6359c5..8a28cfe 100644
--- a/arch/m32r/include/asm/pgtable.h
+++ b/arch/m32r/include/asm/pgtable.h
@@ -332,9 +332,7 @@
 	((pte_t *)pmd_page_vaddr(*(dir)) + pte_index(address))
 #define pte_offset_map(dir, address)	\
 	((pte_t *)page_address(pmd_page(*(dir))) + pte_index(address))
-#define pte_offset_map_nested(dir, address)	pte_offset_map(dir, address)
 #define pte_unmap(pte)		do { } while (0)
-#define pte_unmap_nested(pte)	do { } while (0)
 
 /* Encode and de-code a swap entry */
 #define __swp_type(x)			(((x).val >> 2) & 0x1f)
diff --git a/arch/m68k/include/asm/entry_mm.h b/arch/m68k/include/asm/entry_mm.h
index e41fea3..73b8c8f 100644
--- a/arch/m68k/include/asm/entry_mm.h
+++ b/arch/m68k/include/asm/entry_mm.h
@@ -50,14 +50,6 @@
 
 LFLUSH_I_AND_D = 0x00000808
 
-/* process bits for task_struct.ptrace */
-PT_TRACESYS_OFF = 3
-PT_TRACESYS_BIT = 1
-PT_PTRACED_OFF = 3
-PT_PTRACED_BIT = 0
-PT_DTRACE_OFF = 3
-PT_DTRACE_BIT = 2
-
 #define SAVE_ALL_INT save_all_int
 #define SAVE_ALL_SYS save_all_sys
 #define RESTORE_ALL restore_all
diff --git a/arch/m68k/include/asm/entry_no.h b/arch/m68k/include/asm/entry_no.h
index 80e4149..26be277 100644
--- a/arch/m68k/include/asm/entry_no.h
+++ b/arch/m68k/include/asm/entry_no.h
@@ -32,16 +32,6 @@
 
 #ifdef __ASSEMBLY__
 
-/* process bits for task_struct.flags */
-PF_TRACESYS_OFF = 3
-PF_TRACESYS_BIT = 5
-PF_PTRACED_OFF = 3
-PF_PTRACED_BIT = 4
-PF_DTRACE_OFF = 1
-PF_DTRACE_BIT = 5
-
-LENOSYS = 38
-
 #define SWITCH_STACK_SIZE (6*4+4)	/* Includes return address */
 
 /*
diff --git a/arch/m68k/include/asm/motorola_pgtable.h b/arch/m68k/include/asm/motorola_pgtable.h
index 8e9a8a7..45bd3f5 100644
--- a/arch/m68k/include/asm/motorola_pgtable.h
+++ b/arch/m68k/include/asm/motorola_pgtable.h
@@ -221,9 +221,7 @@
 }
 
 #define pte_offset_map(pmdp,address) ((pte_t *)__pmd_page(*pmdp) + (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
-#define pte_offset_map_nested(pmdp, address) pte_offset_map(pmdp, address)
 #define pte_unmap(pte)		((void)0)
-#define pte_unmap_nested(pte)	((void)0)
 
 /*
  * Allocate and free page tables. The xxx_kernel() versions are
diff --git a/arch/m68k/include/asm/sun3_pgtable.h b/arch/m68k/include/asm/sun3_pgtable.h
index f847ec7..cf5fad9 100644
--- a/arch/m68k/include/asm/sun3_pgtable.h
+++ b/arch/m68k/include/asm/sun3_pgtable.h
@@ -219,9 +219,7 @@
 #define pte_offset_kernel(pmd, address) ((pte_t *) __pmd_page(*pmd) + pte_index(address))
 /* FIXME: should we bother with kmap() here? */
 #define pte_offset_map(pmd, address) ((pte_t *)kmap(pmd_page(*pmd)) + pte_index(address))
-#define pte_offset_map_nested(pmd, address) pte_offset_map(pmd, address)
 #define pte_unmap(pte) kunmap(pte)
-#define pte_unmap_nested(pte) kunmap(pte)
 
 /* Macros to (de)construct the fake PTEs representing swap pages. */
 #define __swp_type(x)		((x).val & 0x7F)
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
index 692fdfc..dad40fc 100644
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -121,6 +121,23 @@
 	  Set this to have arguments from the default kernel command string
 	  override those passed by the boot loader.
 
+config SECCOMP
+	bool "Enable seccomp to safely compute untrusted bytecode"
+	depends on PROC_FS
+	default y
+	help
+	  This kernel feature is useful for number crunching applications
+	  that may need to compute untrusted bytecode during their
+	  execution. By using pipes or other transports made available to
+	  the process as file descriptors supporting the read/write
+	  syscalls, it's possible to isolate those applications in
+	  their own address space using seccomp. Once seccomp is
+	  enabled via /proc/<pid>/seccomp, it cannot be disabled
+	  and the task is only allowed to execute a few safe syscalls
+	  defined by each seccomp mode.
+
+	  If unsure, say Y. Only embedded should say N here.
+
 endmenu
 
 menu "Advanced setup"
diff --git a/arch/microblaze/Kconfig.debug b/arch/microblaze/Kconfig.debug
index e6e5e0d..e66e25c 100644
--- a/arch/microblaze/Kconfig.debug
+++ b/arch/microblaze/Kconfig.debug
@@ -10,7 +10,7 @@
 
 config EARLY_PRINTK
 	bool "Early printk function for kernel"
-	depends on SERIAL_UARTLITE_CONSOLE
+	depends on SERIAL_UARTLITE_CONSOLE || SERIAL_8250_CONSOLE
 	default n
 	help
 	  This option turns on/off early printk messages to console.
diff --git a/arch/microblaze/Makefile b/arch/microblaze/Makefile
index 592c707..15f1f1d 100644
--- a/arch/microblaze/Makefile
+++ b/arch/microblaze/Makefile
@@ -42,11 +42,8 @@
 LDFLAGS		:=
 LDFLAGS_vmlinux	:=
 
-LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
-
 head-y := arch/microblaze/kernel/head.o
 libs-y += arch/microblaze/lib/
-libs-y += $(LIBGCC)
 core-y += arch/microblaze/kernel/
 core-y += arch/microblaze/mm/
 core-y += arch/microblaze/platform/
@@ -72,12 +69,16 @@
 
 all: linux.bin
 
-BOOT_TARGETS = linux.bin linux.bin.gz simpleImage.%
+# With make 3.82 we cannot mix normal and wildcard targets
+BOOT_TARGETS1 = linux.bin linux.bin.gz
+BOOT_TARGETS2 = simpleImage.%
 
 archclean:
 	$(Q)$(MAKE) $(clean)=$(boot)
 
-$(BOOT_TARGETS): vmlinux
+$(BOOT_TARGETS1): vmlinux
+	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+$(BOOT_TARGETS2): vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
 define archhelp
diff --git a/arch/microblaze/include/asm/byteorder.h b/arch/microblaze/include/asm/byteorder.h
index ce9c587..3190276 100644
--- a/arch/microblaze/include/asm/byteorder.h
+++ b/arch/microblaze/include/asm/byteorder.h
@@ -1,6 +1,10 @@
 #ifndef _ASM_MICROBLAZE_BYTEORDER_H
 #define _ASM_MICROBLAZE_BYTEORDER_H
 
+#ifdef __MICROBLAZEEL__
+#include <linux/byteorder/little_endian.h>
+#else
 #include <linux/byteorder/big_endian.h>
+#endif
 
 #endif /* _ASM_MICROBLAZE_BYTEORDER_H */
diff --git a/arch/microblaze/include/asm/checksum.h b/arch/microblaze/include/asm/checksum.h
index 128bf03..0185cbe 100644
--- a/arch/microblaze/include/asm/checksum.h
+++ b/arch/microblaze/include/asm/checksum.h
@@ -24,8 +24,13 @@
 		"addc %0, %0, %3\n\t"
 		"addc %0, %0, r0\n\t"
 		: "+&d" (sum)
-		: "d" (saddr), "d" (daddr), "d" (len + proto));
-
+		: "d" (saddr), "d" (daddr),
+#ifdef __MICROBLAZEEL__
+	"d" ((len + proto) << 8)
+#else
+	"d" (len + proto)
+#endif
+);
 	return sum;
 }
 
diff --git a/arch/microblaze/include/asm/cpuinfo.h b/arch/microblaze/include/asm/cpuinfo.h
index b4f5ca3..cd25753 100644
--- a/arch/microblaze/include/asm/cpuinfo.h
+++ b/arch/microblaze/include/asm/cpuinfo.h
@@ -38,6 +38,7 @@
 	u32 use_exc;
 	u32 ver_code;
 	u32 mmu;
+	u32 endian;
 
 	/* CPU caches */
 	u32 use_icache;
@@ -76,7 +77,6 @@
 	u32 num_rd_brk;
 	u32 num_wr_brk;
 	u32 cpu_clock_freq; /* store real freq of cpu */
-	u32 freq_div_hz; /* store freq/HZ */
 
 	/* FPGA family */
 	u32 fpga_family_code;
@@ -97,7 +97,8 @@
 static inline unsigned int fcpu(struct device_node *cpu, char *n)
 {
 	int *val;
-	return (val = (int *) of_get_property(cpu, n, NULL)) ? *val : 0;
+	return (val = (int *) of_get_property(cpu, n, NULL)) ?
+							be32_to_cpup(val) : 0;
 }
 
 #endif /* _ASM_MICROBLAZE_CPUINFO_H */
diff --git a/arch/microblaze/include/asm/elf.h b/arch/microblaze/include/asm/elf.h
index 732caf1..098dfdd 100644
--- a/arch/microblaze/include/asm/elf.h
+++ b/arch/microblaze/include/asm/elf.h
@@ -71,7 +71,7 @@
 
 #define ELF_ET_DYN_BASE         (0x08000000)
 
-#ifdef __LITTLE_ENDIAN__
+#ifdef __MICROBLAZEEL__
 #define ELF_DATA	ELFDATA2LSB
 #else
 #define ELF_DATA	ELFDATA2MSB
diff --git a/arch/microblaze/include/asm/gpio.h b/arch/microblaze/include/asm/gpio.h
index 2345ac3..2b2c18b 100644
--- a/arch/microblaze/include/asm/gpio.h
+++ b/arch/microblaze/include/asm/gpio.h
@@ -38,12 +38,9 @@
 	return __gpio_cansleep(gpio);
 }
 
-/*
- * Not implemented, yet.
- */
 static inline int gpio_to_irq(unsigned int gpio)
 {
-	return -ENOSYS;
+	return __gpio_to_irq(gpio);
 }
 
 static inline int irq_to_gpio(unsigned int irq)
diff --git a/arch/microblaze/include/asm/io.h b/arch/microblaze/include/asm/io.h
index 00b5398..eae3222 100644
--- a/arch/microblaze/include/asm/io.h
+++ b/arch/microblaze/include/asm/io.h
@@ -243,6 +243,8 @@
 #define out_8(a, v) __raw_writeb((v), (a))
 #define in_8(a) __raw_readb(a)
 
+#define mmiowb()
+
 #define ioport_map(port, nr)	((void __iomem *)(port))
 #define ioport_unmap(addr)
 
diff --git a/arch/microblaze/include/asm/page.h b/arch/microblaze/include/asm/page.h
index cf377d9..ed9d0f6 100644
--- a/arch/microblaze/include/asm/page.h
+++ b/arch/microblaze/include/asm/page.h
@@ -205,9 +205,6 @@
 #define TOPHYS(addr)  __virt_to_phys(addr)
 
 #ifdef CONFIG_MMU
-#ifdef CONFIG_CONTIGUOUS_PAGE_ALLOC
-#define WANT_PAGE_VIRTUAL 1 /* page alloc 2 relies on this */
-#endif
 
 #define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
 				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
diff --git a/arch/microblaze/include/asm/pci.h b/arch/microblaze/include/asm/pci.h
index 5a388ee..2232ff94 100644
--- a/arch/microblaze/include/asm/pci.h
+++ b/arch/microblaze/include/asm/pci.h
@@ -165,5 +165,7 @@
 static inline void __init xilinx_pci_init(void) { return; }
 #endif
 
+#include <asm-generic/pci-dma-compat.h>
+
 #endif	/* __KERNEL__ */
 #endif /* __ASM_MICROBLAZE_PCI_H */
diff --git a/arch/microblaze/include/asm/pgalloc.h b/arch/microblaze/include/asm/pgalloc.h
index c614a89..ebd3579 100644
--- a/arch/microblaze/include/asm/pgalloc.h
+++ b/arch/microblaze/include/asm/pgalloc.h
@@ -165,7 +165,8 @@
 
 #define __pte_free_tlb(tlb, pte, addr)	pte_free((tlb)->mm, (pte))
 
-#define pmd_populate(mm, pmd, pte)	(pmd_val(*(pmd)) = page_address(pte))
+#define pmd_populate(mm, pmd, pte) \
+			(pmd_val(*(pmd)) = (unsigned long)page_address(pte))
 
 #define pmd_populate_kernel(mm, pmd, pte) \
 		(pmd_val(*(pmd)) = (unsigned long) (pte))
diff --git a/arch/microblaze/include/asm/pgtable.h b/arch/microblaze/include/asm/pgtable.h
index ca2d928..cae268c2 100644
--- a/arch/microblaze/include/asm/pgtable.h
+++ b/arch/microblaze/include/asm/pgtable.h
@@ -57,6 +57,13 @@
 
 #define pgprot_noncached_wc(prot)	prot
 
+/*
+ * All 32bit addresses are effectively valid for vmalloc...
+ * Sort of meaningless for non-VM targets.
+ */
+#define	VMALLOC_START	0
+#define	VMALLOC_END	0xffffffff
+
 #else /* CONFIG_MMU */
 
 #include <asm-generic/4level-fixup.h>
@@ -497,12 +504,9 @@
 #define pte_offset_kernel(dir, addr)	\
 	((pte_t *) pmd_page_kernel(*(dir)) + pte_index(addr))
 #define pte_offset_map(dir, addr)		\
-	((pte_t *) kmap_atomic(pmd_page(*(dir)), KM_PTE0) + pte_index(addr))
-#define pte_offset_map_nested(dir, addr)	\
-	((pte_t *) kmap_atomic(pmd_page(*(dir)), KM_PTE1) + pte_index(addr))
+	((pte_t *) kmap_atomic(pmd_page(*(dir))) + pte_index(addr))
 
-#define pte_unmap(pte)		kunmap_atomic(pte, KM_PTE0)
-#define pte_unmap_nested(pte)	kunmap_atomic(pte, KM_PTE1)
+#define pte_unmap(pte)		kunmap_atomic(pte)
 
 /* Encode and decode a nonlinear file mapping entry */
 #define PTE_FILE_MAX_BITS	29
diff --git a/arch/microblaze/include/asm/prom.h b/arch/microblaze/include/asm/prom.h
index 101fa09..bdc3831 100644
--- a/arch/microblaze/include/asm/prom.h
+++ b/arch/microblaze/include/asm/prom.h
@@ -27,6 +27,7 @@
 
 /* Other Prototypes */
 extern int early_uartlite_console(void);
+extern int early_uart16550_console(void);
 
 #ifdef CONFIG_PCI
 /*
diff --git a/arch/microblaze/include/asm/pvr.h b/arch/microblaze/include/asm/pvr.h
index 9578666..37db96a 100644
--- a/arch/microblaze/include/asm/pvr.h
+++ b/arch/microblaze/include/asm/pvr.h
@@ -30,7 +30,9 @@
 #define PVR0_USE_EXC_MASK		0x04000000
 #define PVR0_USE_ICACHE_MASK		0x02000000
 #define PVR0_USE_DCACHE_MASK		0x01000000
-#define PVR0_USE_MMU			0x00800000	/* new */
+#define PVR0_USE_MMU			0x00800000
+#define PVR0_USE_BTC			0x00400000
+#define PVR0_ENDI			0x00200000
 #define PVR0_VERSION_MASK		0x0000FF00
 #define PVR0_USER1_MASK			0x000000FF
 
@@ -38,9 +40,9 @@
 #define PVR1_USER2_MASK			0xFFFFFFFF
 
 /* Configuration PVR masks */
-#define PVR2_D_OPB_MASK			0x80000000
+#define PVR2_D_OPB_MASK			0x80000000 /* or AXI */
 #define PVR2_D_LMB_MASK			0x40000000
-#define PVR2_I_OPB_MASK			0x20000000
+#define PVR2_I_OPB_MASK			0x20000000 /* or AXI */
 #define PVR2_I_LMB_MASK			0x10000000
 #define PVR2_INTERRUPT_IS_EDGE_MASK	0x08000000
 #define PVR2_EDGE_IS_POSITIVE_MASK	0x04000000
@@ -63,8 +65,8 @@
 #define PVR2_OPCODE_0x0_ILL_MASK	0x00000040
 #define PVR2_UNALIGNED_EXC_MASK		0x00000020
 #define PVR2_ILL_OPCODE_EXC_MASK	0x00000010
-#define PVR2_IOPB_BUS_EXC_MASK		0x00000008
-#define PVR2_DOPB_BUS_EXC_MASK		0x00000004
+#define PVR2_IOPB_BUS_EXC_MASK		0x00000008 /* or AXI */
+#define PVR2_DOPB_BUS_EXC_MASK		0x00000004 /* or AXI */
 #define PVR2_DIV_ZERO_EXC_MASK		0x00000002
 #define PVR2_FPU_EXC_MASK		0x00000001
 
@@ -208,6 +210,8 @@
 #define PVR_MMU_TLB_ACCESS(pvr)	(pvr.pvr[11] & PVR11_MMU_TLB_ACCESS)
 #define PVR_MMU_ZONES(pvr)	(pvr.pvr[11] & PVR11_MMU_ZONES)
 
+/* endian */
+#define PVR_ENDIAN(pvr)	(pvr.pvr[0] & PVR0_ENDI)
 
 int cpu_has_pvr(void);
 void get_pvr(struct pvr_s *pvr);
diff --git a/arch/microblaze/include/asm/seccomp.h b/arch/microblaze/include/asm/seccomp.h
new file mode 100644
index 0000000..0d91275
--- /dev/null
+++ b/arch/microblaze/include/asm/seccomp.h
@@ -0,0 +1,16 @@
+#ifndef _ASM_MICROBLAZE_SECCOMP_H
+#define _ASM_MICROBLAZE_SECCOMP_H
+
+#include <linux/unistd.h>
+
+#define __NR_seccomp_read		__NR_read
+#define __NR_seccomp_write		__NR_write
+#define __NR_seccomp_exit		__NR_exit
+#define __NR_seccomp_sigreturn		__NR_sigreturn
+
+#define __NR_seccomp_read_32		__NR_read
+#define __NR_seccomp_write_32		__NR_write
+#define __NR_seccomp_exit_32		__NR_exit
+#define __NR_seccomp_sigreturn_32	__NR_sigreturn
+
+#endif	/* _ASM_MICROBLAZE_SECCOMP_H */
diff --git a/arch/microblaze/include/asm/setup.h b/arch/microblaze/include/asm/setup.h
index 782b5c8..8f39689 100644
--- a/arch/microblaze/include/asm/setup.h
+++ b/arch/microblaze/include/asm/setup.h
@@ -25,6 +25,12 @@
 int setup_early_printk(char *opt);
 void disable_early_printk(void);
 
+#if defined(CONFIG_EARLY_PRINTK)
+#define eprintk early_printk
+#else
+#define eprintk printk
+#endif
+
 void heartbeat(void);
 void setup_heartbeat(void);
 
diff --git a/arch/microblaze/include/asm/thread_info.h b/arch/microblaze/include/asm/thread_info.h
index 8a8e9fc..b73da2a 100644
--- a/arch/microblaze/include/asm/thread_info.h
+++ b/arch/microblaze/include/asm/thread_info.h
@@ -127,23 +127,19 @@
 #define TIF_SECCOMP		10      /* secure computing */
 #define TIF_FREEZE		14	/* Freezing for suspend */
 
-/* FIXME change in entry.S */
-#define TIF_KERNEL_TRACE	8	/* kernel trace active */
-
 /* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_POLLING_NRFLAG	16
 
-#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_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
-#define _TIF_FREEZE		(1<<TIF_FREEZE)
+#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_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
+#define _TIF_FREEZE		(1 << TIF_FREEZE)
 #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP		(1 << TIF_SECCOMP)
-#define _TIF_KERNEL_TRACE	(1 << TIF_KERNEL_TRACE)
 
 /* work to do in syscall trace */
 #define _TIF_WORK_SYSCALL_MASK  (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | \
diff --git a/arch/microblaze/include/asm/unaligned.h b/arch/microblaze/include/asm/unaligned.h
index 3658d91..2b97cbe 100644
--- a/arch/microblaze/include/asm/unaligned.h
+++ b/arch/microblaze/include/asm/unaligned.h
@@ -12,12 +12,18 @@
 
 # ifdef __KERNEL__
 
-# include <linux/unaligned/be_struct.h>
+# include <linux/unaligned/be_byteshift.h>
 # include <linux/unaligned/le_byteshift.h>
 # include <linux/unaligned/generic.h>
 
-# define get_unaligned	__get_unaligned_be
-# define put_unaligned	__put_unaligned_be
+
+#  ifdef __MICROBLAZEEL__
+#   define get_unaligned	__get_unaligned_le
+#   define put_unaligned	__put_unaligned_le
+#  else
+#   define get_unaligned	__get_unaligned_be
+#   define put_unaligned	__put_unaligned_be
+#  endif
 
 # endif	/* __KERNEL__ */
 #endif /* _ASM_MICROBLAZE_UNALIGNED_H */
diff --git a/arch/microblaze/include/asm/unistd.h b/arch/microblaze/include/asm/unistd.h
index 2b67e92..d770b00 100644
--- a/arch/microblaze/include/asm/unistd.h
+++ b/arch/microblaze/include/asm/unistd.h
@@ -383,8 +383,11 @@
 #define __NR_rt_tgsigqueueinfo	365 /* new */
 #define __NR_perf_event_open	366 /* new */
 #define __NR_recvmmsg		367 /* new */
+#define __NR_fanotify_init	368
+#define __NR_fanotify_mark	369
+#define __NR_prlimit64		370
 
-#define __NR_syscalls		368
+#define __NR_syscalls		371
 
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
diff --git a/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c b/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
index f72dbd6..f70a604 100644
--- a/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
+++ b/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
@@ -72,6 +72,7 @@
 	CI(pvr_user2, USER2);
 
 	CI(mmu, USE_MMU);
+	CI(endian, ENDIAN);
 
 	CI(use_icache, USE_ICACHE);
 	CI(icache_tagbits, ICACHE_ADDR_TAG_BITS);
diff --git a/arch/microblaze/kernel/cpu/cpuinfo-static.c b/arch/microblaze/kernel/cpu/cpuinfo-static.c
index 6095aa6..b16b994 100644
--- a/arch/microblaze/kernel/cpu/cpuinfo-static.c
+++ b/arch/microblaze/kernel/cpu/cpuinfo-static.c
@@ -119,6 +119,7 @@
 	ci->pvr_user2 = fcpu(cpu, "xlnx,pvr-user2");
 
 	ci->mmu = fcpu(cpu, "xlnx,use-mmu");
+	ci->endian = fcpu(cpu, "xlnx,endianness");
 
 	ci->ver_code = 0;
 	ci->fpga_family_code = 0;
diff --git a/arch/microblaze/kernel/cpu/cpuinfo.c b/arch/microblaze/kernel/cpu/cpuinfo.c
index 255ef88..87c79fa 100644
--- a/arch/microblaze/kernel/cpu/cpuinfo.c
+++ b/arch/microblaze/kernel/cpu/cpuinfo.c
@@ -30,6 +30,8 @@
 	{"7.20.c", 0x0e},
 	{"7.20.d", 0x0f},
 	{"7.30.a", 0x10},
+	{"7.30.b", 0x11},
+	{"8.00.a", 0x12},
 	{NULL, 0},
 };
 
diff --git a/arch/microblaze/kernel/cpu/mb.c b/arch/microblaze/kernel/cpu/mb.c
index 7086e35..b4048af 100644
--- a/arch/microblaze/kernel/cpu/mb.c
+++ b/arch/microblaze/kernel/cpu/mb.c
@@ -51,11 +51,12 @@
 	count = seq_printf(m,
 			"CPU-Family:	MicroBlaze\n"
 			"FPGA-Arch:	%s\n"
-			"CPU-Ver:	%s\n"
+			"CPU-Ver:	%s, %s endian\n"
 			"CPU-MHz:	%d.%02d\n"
 			"BogoMips:	%lu.%02lu\n",
 			fpga_family,
 			cpu_ver,
+			cpuinfo.endian ? "little" : "big",
 			cpuinfo.cpu_clock_freq /
 			1000000,
 			cpuinfo.cpu_clock_freq %
diff --git a/arch/microblaze/kernel/cpu/pvr.c b/arch/microblaze/kernel/cpu/pvr.c
index 9bee938..e01afa6 100644
--- a/arch/microblaze/kernel/cpu/pvr.c
+++ b/arch/microblaze/kernel/cpu/pvr.c
@@ -27,7 +27,7 @@
 	register unsigned tmp __asm__("r3");			\
 	tmp = 0x0;	/* Prevent warning about unused */	\
 	__asm__ __volatile__ (					\
-			".byte 0x94,0x60,0xa0, " #pvrid "\n\t"	\
+			"mfs	%0, rpvr" #pvrid ";"	\
 			: "=r" (tmp) : : "memory"); 		\
 	val = tmp;						\
 }
diff --git a/arch/microblaze/kernel/early_printk.c b/arch/microblaze/kernel/early_printk.c
index 7de8492..c3616a0 100644
--- a/arch/microblaze/kernel/early_printk.c
+++ b/arch/microblaze/kernel/early_printk.c
@@ -24,7 +24,8 @@
 static u32 early_console_initialized;
 static u32 base_addr;
 
-static void early_printk_putc(char c)
+#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
+static void early_printk_uartlite_putc(char c)
 {
 	/*
 	 * Limit how many times we'll spin waiting for TX FIFO status.
@@ -45,25 +46,70 @@
 		out_be32(base_addr + 4, c & 0xff);
 }
 
-static void early_printk_write(struct console *unused,
+static void early_printk_uartlite_write(struct console *unused,
 					const char *s, unsigned n)
 {
 	while (*s && n-- > 0) {
-		early_printk_putc(*s);
+		early_printk_uartlite_putc(*s);
 		if (*s == '\n')
-			early_printk_putc('\r');
+			early_printk_uartlite_putc('\r');
 		s++;
 	}
 }
 
-static struct console early_serial_console = {
+static struct console early_serial_uartlite_console = {
 	.name = "earlyser",
-	.write = early_printk_write,
+	.write = early_printk_uartlite_write,
 	.flags = CON_PRINTBUFFER,
 	.index = -1,
 };
+#endif /* CONFIG_SERIAL_UARTLITE_CONSOLE */
 
-static struct console *early_console = &early_serial_console;
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+static void early_printk_uart16550_putc(char c)
+{
+	/*
+	 * Limit how many times we'll spin waiting for TX FIFO status.
+	 * This will prevent lockups if the base address is incorrectly
+	 * set, or any other issue on the UARTLITE.
+	 * This limit is pretty arbitrary, unless we are at about 10 baud
+	 * we'll never timeout on a working UART.
+	 */
+
+	#define UART_LSR_TEMT	0x40 /* Transmitter empty */
+	#define UART_LSR_THRE	0x20 /* Transmit-hold-register empty */
+	#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+	unsigned retries = 10000;
+
+	while (--retries &&
+		!((in_be32(base_addr + 0x14) & BOTH_EMPTY) == BOTH_EMPTY))
+		;
+
+	if (retries)
+		out_be32(base_addr, c & 0xff);
+}
+
+static void early_printk_uart16550_write(struct console *unused,
+					const char *s, unsigned n)
+{
+	while (*s && n-- > 0) {
+		early_printk_uart16550_putc(*s);
+		if (*s == '\n')
+			early_printk_uart16550_putc('\r');
+		s++;
+	}
+}
+
+static struct console early_serial_uart16550_console = {
+	.name = "earlyser",
+	.write = early_printk_uart16550_write,
+	.flags = CON_PRINTBUFFER,
+	.index = -1,
+};
+#endif /* CONFIG_SERIAL_8250_CONSOLE */
+
+static struct console *early_console;
 
 void early_printk(const char *fmt, ...)
 {
@@ -84,20 +130,43 @@
 	if (early_console_initialized)
 		return 1;
 
+#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
 	base_addr = early_uartlite_console();
 	if (base_addr) {
 		early_console_initialized = 1;
 #ifdef CONFIG_MMU
 		early_console_reg_tlb_alloc(base_addr);
 #endif
+		early_console = &early_serial_uartlite_console;
 		early_printk("early_printk_console is enabled at 0x%08x\n",
 							base_addr);
 
 		/* register_console(early_console); */
 
 		return 0;
-	} else
-		return 1;
+	}
+#endif /* CONFIG_SERIAL_UARTLITE_CONSOLE */
+
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+	base_addr = early_uart16550_console();
+	base_addr &= ~3; /* clear register offset */
+	if (base_addr) {
+		early_console_initialized = 1;
+#ifdef CONFIG_MMU
+		early_console_reg_tlb_alloc(base_addr);
+#endif
+		early_console = &early_serial_uart16550_console;
+
+		early_printk("early_printk_console is enabled at 0x%08x\n",
+							base_addr);
+
+		/* register_console(early_console); */
+
+		return 0;
+	}
+#endif /* CONFIG_SERIAL_8250_CONSOLE */
+
+	return 1;
 }
 
 void __init disable_early_printk(void)
diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S
index 304882e..819238b 100644
--- a/arch/microblaze/kernel/entry.S
+++ b/arch/microblaze/kernel/entry.S
@@ -186,6 +186,8 @@
 	swi	r13, r1, PTO+PT_R13;	/* Save SDA2 */			\
 	swi	r14, r1, PTO+PT_PC;	/* PC, before IRQ/trap */	\
 	swi	r15, r1, PTO+PT_R15;	/* Save LP */			\
+	swi	r16, r1, PTO+PT_R16;					\
+	swi	r17, r1, PTO+PT_R17;					\
 	swi	r18, r1, PTO+PT_R18;	/* Save asm scratch reg */	\
 	swi	r19, r1, PTO+PT_R19;					\
 	swi	r20, r1, PTO+PT_R20;					\
@@ -220,6 +222,8 @@
 	lwi	r13, r1, PTO+PT_R13;	/* restore SDA2 */		\
 	lwi	r14, r1, PTO+PT_PC;	/* RESTORE_LINK PC, before IRQ/trap */\
 	lwi	r15, r1, PTO+PT_R15;	/* restore LP */		\
+	lwi	r16, r1, PTO+PT_R16;					\
+	lwi	r17, r1, PTO+PT_R17;					\
 	lwi	r18, r1, PTO+PT_R18;	/* restore asm scratch reg */	\
 	lwi	r19, r1, PTO+PT_R19;					\
 	lwi	r20, r1, PTO+PT_R20;					\
@@ -295,6 +299,8 @@
 	/* addik	r1, r1, -STATE_SAVE_SIZE; */
 	addik r1, r1, THREAD_SIZE + CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE;
 	SAVE_REGS
+	swi	r0, r1, PTO + PT_R3
+	swi	r0, r1, PTO + PT_R4
 
 	lwi	r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
 	swi	r11, r1, PTO+PT_R1;		/* Store user SP.  */
@@ -458,14 +464,8 @@
 	addik	r8, r1, PTO;		/* add user context as 4th arg */
 
 C_ENTRY(sys_rt_sigreturn_wrapper):
-	swi	r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
-	swi	r4, r1, PTO+PT_R4;
-	brlid	r15, sys_rt_sigreturn	/* Do real work */
+	brid	sys_rt_sigreturn	/* Do real work */
 	addik	r5, r1, PTO;		/* add user context as 1st arg */
-	lwi	r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
-	lwi	r4, r1, PTO+PT_R4;
-	bri ret_from_trap /* fall through will not work here due to align */
-	nop;
 
 /*
  * HW EXCEPTION rutine start
@@ -765,9 +765,7 @@
 	/* save all regs to pt_reg structure */
 	swi	r0, r1, PTO+PT_R0;	/* R0 must be saved too */
 	swi	r14, r1, PTO+PT_R14	/* rewrite saved R14 value */
-	swi	r16, r1, PTO+PT_R16
 	swi	r16, r1, PTO+PT_PC; /* PC and r16 are the same */
-	swi	r17, r1, PTO+PT_R17
 	/* save special purpose registers to pt_regs */
 	mfs	r11, rear;
 	swi	r11, r1, PTO+PT_EAR;
@@ -801,8 +799,6 @@
 
 	addik	r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack.  */
 	SAVE_REGS;
-	swi	r17, r1, PTO+PT_R17;
-	swi	r16, r1, PTO+PT_R16;
 	swi	r16, r1, PTO+PT_PC;	/* Save LP */
 	swi	r0, r1, PTO + PT_MODE; /* Was in user-mode.  */
 	lwi	r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
@@ -848,8 +844,6 @@
 	tophys(r1,r1);
 	/* MS: Restore all regs */
 	RESTORE_REGS
-	lwi	r17, r1, PTO+PT_R17;
-	lwi	r16, r1, PTO+PT_R16;
 	addik	r1, r1, STATE_SAVE_SIZE	 /* Clean up stack space */
 	lwi	r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer */
 DBTRAP_return_user: /* MS: Make global symbol for debugging */
@@ -863,7 +857,6 @@
 	RESTORE_REGS
 	lwi	r14, r1, PTO+PT_R14;
 	lwi	r16, r1, PTO+PT_PC;
-	lwi	r17, r1, PTO+PT_R17;
 	addik	r1, r1, STATE_SAVE_SIZE; /* MS: Clean up stack space */
 	tovirt(r1,r1);
 DBTRAP_return_kernel: /* MS: Make global symbol for debugging */
diff --git a/arch/microblaze/kernel/exceptions.c b/arch/microblaze/kernel/exceptions.c
index b98ee8d..478f294 100644
--- a/arch/microblaze/kernel/exceptions.c
+++ b/arch/microblaze/kernel/exceptions.c
@@ -72,7 +72,6 @@
 							int fsr, int addr)
 {
 #ifdef CONFIG_MMU
-	int code;
 	addr = regs->pc;
 #endif
 
@@ -86,8 +85,7 @@
 	switch (type & 0x1F) {
 	case MICROBLAZE_ILL_OPCODE_EXCEPTION:
 		if (user_mode(regs)) {
-			pr_debug(KERN_WARNING "Illegal opcode exception " \
-							"in user mode.\n");
+			pr_debug("Illegal opcode exception in user mode\n");
 			_exception(SIGILL, regs, ILL_ILLOPC, addr);
 			return;
 		}
@@ -97,8 +95,7 @@
 		break;
 	case MICROBLAZE_IBUS_EXCEPTION:
 		if (user_mode(regs)) {
-			pr_debug(KERN_WARNING "Instruction bus error " \
-						"exception in user mode.\n");
+			pr_debug("Instruction bus error exception in user mode\n");
 			_exception(SIGBUS, regs, BUS_ADRERR, addr);
 			return;
 		}
@@ -108,8 +105,7 @@
 		break;
 	case MICROBLAZE_DBUS_EXCEPTION:
 		if (user_mode(regs)) {
-			pr_debug(KERN_WARNING "Data bus error exception " \
-							"in user mode.\n");
+			pr_debug("Data bus error exception in user mode\n");
 			_exception(SIGBUS, regs, BUS_ADRERR, addr);
 			return;
 		}
@@ -119,8 +115,7 @@
 		break;
 	case MICROBLAZE_DIV_ZERO_EXCEPTION:
 		if (user_mode(regs)) {
-			pr_debug(KERN_WARNING "Divide by zero exception " \
-							"in user mode\n");
+			pr_debug("Divide by zero exception in user mode\n");
 			_exception(SIGILL, regs, FPE_INTDIV, addr);
 			return;
 		}
@@ -129,7 +124,7 @@
 		die("Divide by zero exception", regs, SIGBUS);
 		break;
 	case MICROBLAZE_FPU_EXCEPTION:
-		pr_debug(KERN_WARNING "FPU exception\n");
+		pr_debug("FPU exception\n");
 		/* IEEE FP exception */
 		/* I removed fsr variable and use code var for storing fsr */
 		if (fsr & FSR_IO)
@@ -147,14 +142,8 @@
 
 #ifdef CONFIG_MMU
 	case MICROBLAZE_PRIVILEGED_EXCEPTION:
-		pr_debug(KERN_WARNING "Privileged exception\n");
-		/* "brk r0,r0" - used as debug breakpoint - old toolchain */
-		if (get_user(code, (unsigned long *)regs->pc) == 0
-			&& code == 0x980c0000) {
-			_exception(SIGTRAP, regs, TRAP_BRKPT, addr);
-		} else {
-			_exception(SIGILL, regs, ILL_PRVOPC, addr);
-		}
+		pr_debug("Privileged exception\n");
+		_exception(SIGILL, regs, ILL_PRVOPC, addr);
 		break;
 #endif
 	default:
diff --git a/arch/microblaze/kernel/heartbeat.c b/arch/microblaze/kernel/heartbeat.c
index 5227517..154756f 100644
--- a/arch/microblaze/kernel/heartbeat.c
+++ b/arch/microblaze/kernel/heartbeat.c
@@ -47,11 +47,10 @@
 	struct device_node *gpio = NULL;
 	int *prop;
 	int j;
-	char *gpio_list[] = {
-				"xlnx,xps-gpio-1.00.a",
-				"xlnx,opb-gpio-1.00.a",
-				NULL
-			};
+	const char * const gpio_list[] = {
+		"xlnx,xps-gpio-1.00.a",
+		NULL
+	};
 
 	for (j = 0; gpio_list[j] != NULL; j++) {
 		gpio = of_find_compatible_node(NULL, NULL, gpio_list[j]);
@@ -60,7 +59,7 @@
 	}
 
 	if (gpio) {
-		base_addr = *(int *) of_get_property(gpio, "reg", NULL);
+		base_addr = be32_to_cpup(of_get_property(gpio, "reg", NULL));
 		base_addr = (unsigned long) ioremap(base_addr, PAGE_SIZE);
 		printk(KERN_NOTICE "Heartbeat GPIO at 0x%x\n", base_addr);
 
diff --git a/arch/microblaze/kernel/intc.c b/arch/microblaze/kernel/intc.c
index 03172c1..d61ea33 100644
--- a/arch/microblaze/kernel/intc.c
+++ b/arch/microblaze/kernel/intc.c
@@ -126,11 +126,8 @@
 				0
 			};
 #endif
-	static char *intc_list[] = {
+	const char * const intc_list[] = {
 				"xlnx,xps-intc-1.00.a",
-				"xlnx,opb-intc-1.00.c",
-				"xlnx,opb-intc-1.00.b",
-				"xlnx,opb-intc-1.00.a",
 				NULL
 			};
 
@@ -141,12 +138,15 @@
 	}
 	BUG_ON(!intc);
 
-	intc_baseaddr = *(int *) of_get_property(intc, "reg", NULL);
+	intc_baseaddr = be32_to_cpup(of_get_property(intc,
+								"reg", NULL));
 	intc_baseaddr = (unsigned long) ioremap(intc_baseaddr, PAGE_SIZE);
-	nr_irq = *(int *) of_get_property(intc, "xlnx,num-intr-inputs", NULL);
+	nr_irq = be32_to_cpup(of_get_property(intc,
+						"xlnx,num-intr-inputs", NULL));
 
 	intr_type =
-		*(int *) of_get_property(intc, "xlnx,kind-of-intr", NULL);
+		be32_to_cpup(of_get_property(intc,
+						"xlnx,kind-of-intr", NULL));
 	if (intr_type >= (1 << (nr_irq + 1)))
 		printk(KERN_INFO " ERROR: Mismatch in kind-of-intr param\n");
 
diff --git a/arch/microblaze/kernel/kgdb.c b/arch/microblaze/kernel/kgdb.c
index bfc006b..09a5e82 100644
--- a/arch/microblaze/kernel/kgdb.c
+++ b/arch/microblaze/kernel/kgdb.c
@@ -80,7 +80,7 @@
 void microblaze_kgdb_break(struct pt_regs *regs)
 {
 	if (kgdb_handle_exception(1, SIGTRAP, 0, regs) != 0)
-		return 0;
+		return;
 
 	/* Jump over the first arch_kgdb_breakpoint which is barrier to
 	 * get kgdb work. The same solution is used for powerpc */
@@ -114,7 +114,6 @@
 {
 	char *ptr;
 	unsigned long address;
-	int cpu = smp_processor_id();
 
 	switch (remcom_in_buffer[0]) {
 	case 'c':
@@ -143,5 +142,9 @@
  * Global data
  */
 struct kgdb_arch arch_kgdb_ops = {
+#ifdef __MICROBLAZEEL__
+	.gdb_bpt_instr = {0x18, 0x00, 0x0c, 0xba}, /* brki r16, 0x18 */
+#else
 	.gdb_bpt_instr = {0xba, 0x0c, 0x00, 0x18}, /* brki r16, 0x18 */
+#endif
 };
diff --git a/arch/microblaze/kernel/microblaze_ksyms.c b/arch/microblaze/kernel/microblaze_ksyms.c
index ff85f77..5cb0341 100644
--- a/arch/microblaze/kernel/microblaze_ksyms.c
+++ b/arch/microblaze/kernel/microblaze_ksyms.c
@@ -15,37 +15,13 @@
 #include <linux/syscalls.h>
 
 #include <asm/checksum.h>
+#include <asm/cacheflush.h>
 #include <linux/io.h>
 #include <asm/page.h>
 #include <asm/system.h>
 #include <linux/ftrace.h>
 #include <linux/uaccess.h>
 
-/*
- * libgcc functions - functions that are used internally by the
- * compiler... (prototypes are not correct though, but that
- * doesn't really matter since they're not versioned).
- */
-extern void __ashldi3(void);
-EXPORT_SYMBOL(__ashldi3);
-extern void __ashrdi3(void);
-EXPORT_SYMBOL(__ashrdi3);
-extern void __divsi3(void);
-EXPORT_SYMBOL(__divsi3);
-extern void __lshrdi3(void);
-EXPORT_SYMBOL(__lshrdi3);
-extern void __modsi3(void);
-EXPORT_SYMBOL(__modsi3);
-extern void __mulsi3(void);
-EXPORT_SYMBOL(__mulsi3);
-extern void __muldi3(void);
-EXPORT_SYMBOL(__muldi3);
-extern void __ucmpdi2(void);
-EXPORT_SYMBOL(__ucmpdi2);
-extern void __udivsi3(void);
-EXPORT_SYMBOL(__udivsi3);
-extern void __umodsi3(void);
-EXPORT_SYMBOL(__umodsi3);
 extern char *_ebss;
 EXPORT_SYMBOL_GPL(_ebss);
 #ifdef CONFIG_FUNCTION_TRACER
@@ -63,3 +39,9 @@
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(memmove);
 #endif
+
+#ifdef CONFIG_MMU
+EXPORT_SYMBOL(empty_zero_page);
+#endif
+
+EXPORT_SYMBOL(mbc);
diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c
index bacbd3d..a105301 100644
--- a/arch/microblaze/kernel/prom.c
+++ b/arch/microblaze/kernel/prom.c
@@ -72,11 +72,12 @@
 /* find compatible node with uartlite */
 	p = of_get_flat_dt_prop(node, "compatible", &l);
 	if ((strncmp(p, "xlnx,xps-uartlite", 17) != 0) &&
-			(strncmp(p, "xlnx,opb-uartlite", 17) != 0))
+			(strncmp(p, "xlnx,opb-uartlite", 17) != 0) &&
+			(strncmp(p, "xlnx,axi-uartlite", 17) != 0))
 		return 0;
 
 	addr = of_get_flat_dt_prop(node, "reg", &l);
-	return *addr; /* return address */
+	return be32_to_cpup(addr); /* return address */
 }
 
 /* this function is looking for early uartlite console - Microblaze specific */
@@ -84,6 +85,40 @@
 {
 	return of_scan_flat_dt(early_init_dt_scan_serial, NULL);
 }
+
+/* MS this is Microblaze specifig function */
+static int __init early_init_dt_scan_serial_full(unsigned long node,
+				const char *uname, int depth, void *data)
+{
+	unsigned long l;
+	char *p;
+	unsigned int addr;
+
+	pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
+
+/* find all serial nodes */
+	if (strncmp(uname, "serial", 6) != 0)
+		return 0;
+
+	early_init_dt_check_for_initrd(node);
+
+/* find compatible node with uartlite */
+	p = of_get_flat_dt_prop(node, "compatible", &l);
+
+	if ((strncmp(p, "xlnx,xps-uart16550", 18) != 0) &&
+		(strncmp(p, "xlnx,axi-uart16550", 18) != 0))
+		return 0;
+
+	addr = *(u32 *)of_get_flat_dt_prop(node, "reg", &l);
+	addr += *(u32 *)of_get_flat_dt_prop(node, "reg-offset", &l);
+	return be32_to_cpu(addr); /* return address */
+}
+
+/* this function is looking for early uartlite console - Microblaze specific */
+int __init early_uart16550_console(void)
+{
+	return of_scan_flat_dt(early_init_dt_scan_serial_full, NULL);
+}
 #endif
 
 void __init early_init_devtree(void *params)
diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c
index f5f7688..bb1558e 100644
--- a/arch/microblaze/kernel/setup.c
+++ b/arch/microblaze/kernel/setup.c
@@ -92,12 +92,6 @@
 }
 #endif	/* CONFIG_MTD_UCLINUX_EBSS */
 
-#if defined(CONFIG_EARLY_PRINTK) && defined(CONFIG_SERIAL_UARTLITE_CONSOLE)
-#define eprintk early_printk
-#else
-#define eprintk printk
-#endif
-
 void __init machine_early_init(const char *cmdline, unsigned int ram,
 		unsigned int fdt, unsigned int msr)
 {
diff --git a/arch/microblaze/kernel/syscall_table.S b/arch/microblaze/kernel/syscall_table.S
index 03376dc..e88a930 100644
--- a/arch/microblaze/kernel/syscall_table.S
+++ b/arch/microblaze/kernel/syscall_table.S
@@ -372,3 +372,6 @@
 	.long sys_rt_tgsigqueueinfo	/* 365 */
 	.long sys_perf_event_open
 	.long sys_recvmmsg
+	.long sys_fanotify_init
+	.long sys_fanotify_mark
+	.long sys_prlimit64	/* 370 */
diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c
index b1380ae..a5aa33d 100644
--- a/arch/microblaze/kernel/timer.c
+++ b/arch/microblaze/kernel/timer.c
@@ -38,6 +38,9 @@
 #define TIMER_BASE	timer_baseaddr
 #endif
 
+unsigned int freq_div_hz;
+unsigned int timer_clock_freq;
+
 #define TCSR0	(0x00)
 #define TLR0	(0x04)
 #define TCR0	(0x08)
@@ -115,7 +118,7 @@
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
 		printk(KERN_INFO "%s: periodic\n", __func__);
-		microblaze_timer0_start_periodic(cpuinfo.freq_div_hz);
+		microblaze_timer0_start_periodic(freq_div_hz);
 		break;
 	case CLOCK_EVT_MODE_ONESHOT:
 		printk(KERN_INFO "%s: oneshot\n", __func__);
@@ -168,7 +171,7 @@
 static __init void microblaze_clockevent_init(void)
 {
 	clockevent_microblaze_timer.mult =
-		div_sc(cpuinfo.cpu_clock_freq, NSEC_PER_SEC,
+		div_sc(timer_clock_freq, NSEC_PER_SEC,
 				clockevent_microblaze_timer.shift);
 	clockevent_microblaze_timer.max_delta_ns =
 		clockevent_delta2ns((u32)~0, &clockevent_microblaze_timer);
@@ -201,7 +204,7 @@
 
 int __init init_microblaze_timecounter(void)
 {
-	microblaze_cc.mult = div_sc(cpuinfo.cpu_clock_freq, NSEC_PER_SEC,
+	microblaze_cc.mult = div_sc(timer_clock_freq, NSEC_PER_SEC,
 				microblaze_cc.shift);
 
 	timecounter_init(&microblaze_tc, &microblaze_cc, sched_clock());
@@ -221,7 +224,7 @@
 static int __init microblaze_clocksource_init(void)
 {
 	clocksource_microblaze.mult =
-			clocksource_hz2mult(cpuinfo.cpu_clock_freq,
+			clocksource_hz2mult(timer_clock_freq,
 						clocksource_microblaze.shift);
 	if (clocksource_register(&clocksource_microblaze))
 		panic("failed to register clocksource");
@@ -247,6 +250,7 @@
 	u32 irq, i = 0;
 	u32 timer_num = 1;
 	struct device_node *timer = NULL;
+	const void *prop;
 #ifdef CONFIG_SELFMOD_TIMER
 	unsigned int timer_baseaddr = 0;
 	int arr_func[] = {
@@ -258,12 +262,10 @@
 				0
 			};
 #endif
-	char *timer_list[] = {
-				"xlnx,xps-timer-1.00.a",
-				"xlnx,opb-timer-1.00.b",
-				"xlnx,opb-timer-1.00.a",
-				NULL
-			};
+	const char * const timer_list[] = {
+		"xlnx,xps-timer-1.00.a",
+		NULL
+	};
 
 	for (i = 0; timer_list[i] != NULL; i++) {
 		timer = of_find_compatible_node(NULL, NULL, timer_list[i]);
@@ -272,13 +274,13 @@
 	}
 	BUG_ON(!timer);
 
-	timer_baseaddr = *(int *) of_get_property(timer, "reg", NULL);
+	timer_baseaddr = be32_to_cpup(of_get_property(timer, "reg", NULL));
 	timer_baseaddr = (unsigned long) ioremap(timer_baseaddr, PAGE_SIZE);
-	irq = *(int *) of_get_property(timer, "interrupts", NULL);
-	timer_num =
-		*(int *) of_get_property(timer, "xlnx,one-timer-only", NULL);
+	irq = be32_to_cpup(of_get_property(timer, "interrupts", NULL));
+	timer_num = be32_to_cpup(of_get_property(timer,
+						"xlnx,one-timer-only", NULL));
 	if (timer_num) {
-		printk(KERN_EMERG "Please enable two timers in HW\n");
+		eprintk(KERN_EMERG "Please enable two timers in HW\n");
 		BUG();
 	}
 
@@ -288,7 +290,14 @@
 	printk(KERN_INFO "%s #0 at 0x%08x, irq=%d\n",
 		timer_list[i], timer_baseaddr, irq);
 
-	cpuinfo.freq_div_hz = cpuinfo.cpu_clock_freq / HZ;
+	/* If there is clock-frequency property than use it */
+	prop = of_get_property(timer, "clock-frequency", NULL);
+	if (prop)
+		timer_clock_freq = be32_to_cpup(prop);
+	else
+		timer_clock_freq = cpuinfo.cpu_clock_freq;
+
+	freq_div_hz = timer_clock_freq / HZ;
 
 	setup_irq(irq, &timer_irqaction);
 #ifdef CONFIG_HEART_BEAT
diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S
index a09f296..96a88c3 100644
--- a/arch/microblaze/kernel/vmlinux.lds.S
+++ b/arch/microblaze/kernel/vmlinux.lds.S
@@ -8,7 +8,6 @@
  * for more details.
  */
 
-OUTPUT_FORMAT("elf32-microblaze", "elf32-microblaze", "elf32-microblaze")
 OUTPUT_ARCH(microblaze)
 ENTRY(microblaze_start)
 
@@ -16,7 +15,11 @@
 #include <asm-generic/vmlinux.lds.h>
 #include <asm/thread_info.h>
 
+#ifdef __MICROBLAZEEL__
+jiffies = jiffies_64;
+#else
 jiffies = jiffies_64 + 4;
+#endif
 
 SECTIONS {
 	. = CONFIG_KERNEL_START;
diff --git a/arch/microblaze/lib/Makefile b/arch/microblaze/lib/Makefile
index 4dfe47d..f1fcbff 100644
--- a/arch/microblaze/lib/Makefile
+++ b/arch/microblaze/lib/Makefile
@@ -11,3 +11,13 @@
 endif
 
 lib-y += uaccess_old.o
+
+lib-y += ashldi3.o
+lib-y += ashrdi3.o
+lib-y += divsi3.o
+lib-y += lshrdi3.o
+lib-y += modsi3.o
+lib-y += muldi3.o
+lib-y += mulsi3.o
+lib-y += udivsi3.o
+lib-y += umodsi3.o
diff --git a/arch/microblaze/lib/ashldi3.c b/arch/microblaze/lib/ashldi3.c
new file mode 100644
index 0000000..beb80f31
--- /dev/null
+++ b/arch/microblaze/lib/ashldi3.c
@@ -0,0 +1,29 @@
+#include <linux/module.h>
+
+#include "libgcc.h"
+
+long long __ashldi3(long long u, word_type b)
+{
+	DWunion uu, w;
+	word_type bm;
+
+	if (b == 0)
+		return u;
+
+	uu.ll = u;
+	bm = 32 - b;
+
+	if (bm <= 0) {
+		w.s.low = 0;
+		w.s.high = (unsigned int) uu.s.low << -bm;
+	} else {
+		const unsigned int carries = (unsigned int) uu.s.low >> bm;
+
+		w.s.low = (unsigned int) uu.s.low << b;
+		w.s.high = ((unsigned int) uu.s.high << b) | carries;
+	}
+
+	return w.ll;
+}
+
+EXPORT_SYMBOL(__ashldi3);
diff --git a/arch/microblaze/lib/ashrdi3.c b/arch/microblaze/lib/ashrdi3.c
new file mode 100644
index 0000000..c884a91
--- /dev/null
+++ b/arch/microblaze/lib/ashrdi3.c
@@ -0,0 +1,31 @@
+#include <linux/module.h>
+
+#include "libgcc.h"
+
+long long __ashrdi3(long long u, word_type b)
+{
+	DWunion uu, w;
+	word_type bm;
+
+	if (b == 0)
+		return u;
+
+	uu.ll = u;
+	bm = 32 - b;
+
+	if (bm <= 0) {
+		/* w.s.high = 1..1 or 0..0 */
+		w.s.high =
+		    uu.s.high >> 31;
+		w.s.low = uu.s.high >> -bm;
+	} else {
+		const unsigned int carries = (unsigned int) uu.s.high << bm;
+
+		w.s.high = uu.s.high >> b;
+		w.s.low = ((unsigned int) uu.s.low >> b) | carries;
+	}
+
+	return w.ll;
+}
+
+EXPORT_SYMBOL(__ashrdi3);
diff --git a/arch/microblaze/lib/divsi3.S b/arch/microblaze/lib/divsi3.S
new file mode 100644
index 0000000..595b02d
--- /dev/null
+++ b/arch/microblaze/lib/divsi3.S
@@ -0,0 +1,73 @@
+#include <linux/linkage.h>
+
+/*
+* Divide operation for 32 bit integers.
+*	Input :	Dividend in Reg r5
+*		Divisor in Reg r6
+*	Output: Result in Reg r3
+*/
+	.text
+	.globl	__divsi3
+	.type __divsi3, @function
+	.ent __divsi3
+__divsi3:
+	.frame	r1, 0, r15
+
+	addik	r1, r1, -16
+	swi	r28, r1, 0
+	swi	r29, r1, 4
+	swi	r30, r1, 8
+	swi	r31, r1, 12
+
+	beqi	r6, div_by_zero /* div_by_zero - division error */
+	beqi	r5, result_is_zero /* result is zero */
+	bgeid	r5, r5_pos
+	xor	r28, r5, r6 /* get the sign of the result */
+	rsubi	r5, r5, 0 /* make r5 positive */
+r5_pos:
+	bgei	r6, r6_pos
+	rsubi	r6, r6, 0 /* make r6 positive */
+r6_pos:
+	addik	r30, r0, 0 /* clear mod */
+	addik	r3, r0, 0 /* clear div */
+	addik	r29, r0, 32 /* initialize the loop count */
+
+	/* first part try to find the first '1' in the r5 */
+div0:
+	blti	r5, div2 /* this traps r5 == 0x80000000 */
+div1:
+	add	r5, r5, r5 /* left shift logical r5 */
+	bgtid	r5, div1
+	addik	r29, r29, -1
+div2:
+	/* left shift logical r5 get the '1' into the carry */
+	add	r5, r5, r5
+	addc	r30, r30, r30 /* move that bit into the mod register */
+	rsub	r31, r6, r30 /* try to subtract (r30 a r6) */
+	blti	r31, mod_too_small
+	/* move the r31 to mod since the result was positive */
+	or	r30, r0, r31
+	addik	r3, r3, 1
+mod_too_small:
+	addik	r29, r29, -1
+	beqi	r29, loop_end
+	add	r3, r3, r3 /* shift in the '1' into div */
+	bri	div2 /* div2 */
+loop_end:
+	bgei	r28, return_here
+	brid	return_here
+	rsubi	r3, r3, 0 /* negate the result */
+div_by_zero:
+result_is_zero:
+	or	r3, r0, r0 /* set result to 0 */
+return_here:
+/* restore values of csrs and that of r3 and the divisor and the dividend */
+	lwi	r28, r1, 0
+	lwi	r29, r1, 4
+	lwi	r30, r1, 8
+	lwi	r31, r1, 12
+	rtsd	r15, 8
+	addik	r1, r1, 16
+
+.size __divsi3, . - __divsi3
+.end __divsi3
diff --git a/arch/microblaze/lib/libgcc.h b/arch/microblaze/lib/libgcc.h
new file mode 100644
index 0000000..05909d58
--- /dev/null
+++ b/arch/microblaze/lib/libgcc.h
@@ -0,0 +1,25 @@
+#ifndef __ASM_LIBGCC_H
+#define __ASM_LIBGCC_H
+
+#include <asm/byteorder.h>
+
+typedef int word_type __attribute__ ((mode (__word__)));
+
+#ifdef __BIG_ENDIAN
+struct DWstruct {
+	int high, low;
+};
+#elif defined(__LITTLE_ENDIAN)
+struct DWstruct {
+	int low, high;
+};
+#else
+#error I feel sick.
+#endif
+
+typedef union {
+	struct DWstruct s;
+	long long ll;
+} DWunion;
+
+#endif /* __ASM_LIBGCC_H */
diff --git a/arch/microblaze/lib/lshrdi3.c b/arch/microblaze/lib/lshrdi3.c
new file mode 100644
index 0000000..dcf8d68
--- /dev/null
+++ b/arch/microblaze/lib/lshrdi3.c
@@ -0,0 +1,29 @@
+#include <linux/module.h>
+
+#include "libgcc.h"
+
+long long __lshrdi3(long long u, word_type b)
+{
+	DWunion uu, w;
+	word_type bm;
+
+	if (b == 0)
+		return u;
+
+	uu.ll = u;
+	bm = 32 - b;
+
+	if (bm <= 0) {
+		w.s.high = 0;
+		w.s.low = (unsigned int) uu.s.high >> -bm;
+	} else {
+		const unsigned int carries = (unsigned int) uu.s.high << bm;
+
+		w.s.high = (unsigned int) uu.s.high >> b;
+		w.s.low = ((unsigned int) uu.s.low >> b) | carries;
+	}
+
+	return w.ll;
+}
+
+EXPORT_SYMBOL(__lshrdi3);
diff --git a/arch/microblaze/lib/memcpy.c b/arch/microblaze/lib/memcpy.c
index 014bac9..cc495d7d 100644
--- a/arch/microblaze/lib/memcpy.c
+++ b/arch/microblaze/lib/memcpy.c
@@ -33,17 +33,24 @@
 #include <asm/system.h>
 
 #ifdef __HAVE_ARCH_MEMCPY
+#ifndef CONFIG_OPT_LIB_FUNCTION
 void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c)
 {
 	const char *src = v_src;
 	char *dst = v_dst;
-#ifndef CONFIG_OPT_LIB_FUNCTION
+
 	/* Simple, byte oriented memcpy. */
 	while (c--)
 		*dst++ = *src++;
 
 	return v_dst;
-#else
+}
+#else /* CONFIG_OPT_LIB_FUNCTION */
+void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c)
+{
+	const char *src = v_src;
+	char *dst = v_dst;
+
 	/* The following code tries to optimize the copy by using unsigned
 	 * alignment. This will work fine if both source and destination are
 	 * aligned on the same boundary. However, if they are aligned on
@@ -86,7 +93,7 @@
 		case 0x1:	/* Unaligned - Off by 1 */
 			/* Word align the source */
 			i_src = (const void *) ((unsigned)src & ~3);
-
+#ifndef __MICROBLAZEEL__
 			/* Load the holding buffer */
 			buf_hold = *i_src++ << 8;
 
@@ -95,7 +102,16 @@
 				*i_dst++ = buf_hold | value >> 24;
 				buf_hold = value << 8;
 			}
+#else
+			/* Load the holding buffer */
+			buf_hold = (*i_src++ & 0xFFFFFF00) >>8;
 
+			for (; c >= 4; c -= 4) {
+				value = *i_src++;
+				*i_dst++ = buf_hold | ((value & 0xFF) << 24);
+				buf_hold = (value & 0xFFFFFF00) >>8;
+			}
+#endif
 			/* Realign the source */
 			src = (const void *)i_src;
 			src -= 3;
@@ -103,7 +119,7 @@
 		case 0x2:	/* Unaligned - Off by 2 */
 			/* Word align the source */
 			i_src = (const void *) ((unsigned)src & ~3);
-
+#ifndef __MICROBLAZEEL__
 			/* Load the holding buffer */
 			buf_hold = *i_src++ << 16;
 
@@ -112,7 +128,16 @@
 				*i_dst++ = buf_hold | value >> 16;
 				buf_hold = value << 16;
 			}
+#else
+			/* Load the holding buffer */
+			buf_hold = (*i_src++ & 0xFFFF0000 )>>16;
 
+			for (; c >= 4; c -= 4) {
+				value = *i_src++;
+				*i_dst++ = buf_hold | ((value & 0xFFFF)<<16);
+				buf_hold = (value & 0xFFFF0000) >>16;
+			}
+#endif
 			/* Realign the source */
 			src = (const void *)i_src;
 			src -= 2;
@@ -120,7 +145,7 @@
 		case 0x3:	/* Unaligned - Off by 3 */
 			/* Word align the source */
 			i_src = (const void *) ((unsigned)src & ~3);
-
+#ifndef __MICROBLAZEEL__
 			/* Load the holding buffer */
 			buf_hold = *i_src++ << 24;
 
@@ -129,7 +154,16 @@
 				*i_dst++ = buf_hold | value >> 8;
 				buf_hold = value << 24;
 			}
+#else
+			/* Load the holding buffer */
+			buf_hold = (*i_src++ & 0xFF000000) >> 24;
 
+			for (; c >= 4; c -= 4) {
+				value = *i_src++;
+				*i_dst++ = buf_hold | ((value & 0xFFFFFF) << 8);
+				buf_hold = (value & 0xFF000000) >> 24;
+			}
+#endif
 			/* Realign the source */
 			src = (const void *)i_src;
 			src -= 1;
@@ -150,7 +184,7 @@
 	}
 
 	return v_dst;
-#endif
 }
+#endif /* CONFIG_OPT_LIB_FUNCTION */
 EXPORT_SYMBOL(memcpy);
 #endif /* __HAVE_ARCH_MEMCPY */
diff --git a/arch/microblaze/lib/memmove.c b/arch/microblaze/lib/memmove.c
index 0929198..123e361 100644
--- a/arch/microblaze/lib/memmove.c
+++ b/arch/microblaze/lib/memmove.c
@@ -31,16 +31,12 @@
 #include <linux/string.h>
 
 #ifdef __HAVE_ARCH_MEMMOVE
+#ifndef CONFIG_OPT_LIB_FUNCTION
 void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
 {
 	const char *src = v_src;
 	char *dst = v_dst;
 
-#ifdef CONFIG_OPT_LIB_FUNCTION
-	const uint32_t *i_src;
-	uint32_t *i_dst;
-#endif
-
 	if (!c)
 		return v_dst;
 
@@ -48,7 +44,6 @@
 	if (v_dst <= v_src)
 		return memcpy(v_dst, v_src, c);
 
-#ifndef CONFIG_OPT_LIB_FUNCTION
 	/* copy backwards, from end to beginning */
 	src += c;
 	dst += c;
@@ -58,7 +53,22 @@
 		*--dst = *--src;
 
 	return v_dst;
-#else
+}
+#else /* CONFIG_OPT_LIB_FUNCTION */
+void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
+{
+	const char *src = v_src;
+	char *dst = v_dst;
+	const uint32_t *i_src;
+	uint32_t *i_dst;
+
+	if (!c)
+		return v_dst;
+
+	/* Use memcpy when source is higher than dest */
+	if (v_dst <= v_src)
+		return memcpy(v_dst, v_src, c);
+
 	/* The following code tries to optimize the copy by using unsigned
 	 * alignment. This will work fine if both source and destination are
 	 * aligned on the same boundary. However, if they are aligned on
@@ -104,7 +114,7 @@
 		case 0x1:	/* Unaligned - Off by 1 */
 			/* Word align the source */
 			i_src = (const void *) (((unsigned)src + 4) & ~3);
-
+#ifndef __MICROBLAZEEL__
 			/* Load the holding buffer */
 			buf_hold = *--i_src >> 24;
 
@@ -113,7 +123,16 @@
 				*--i_dst = buf_hold << 8 | value;
 				buf_hold = value >> 24;
 			}
+#else
+			/* Load the holding buffer */
+			buf_hold = (*--i_src & 0xFF) << 24;
 
+			for (; c >= 4; c -= 4) {
+				value = *--i_src;
+				*--i_dst = buf_hold | ((value & 0xFFFFFF00)>>8);
+				buf_hold = (value  & 0xFF) << 24;
+			}
+#endif
 			/* Realign the source */
 			src = (const void *)i_src;
 			src += 1;
@@ -121,7 +140,7 @@
 		case 0x2:	/* Unaligned - Off by 2 */
 			/* Word align the source */
 			i_src = (const void *) (((unsigned)src + 4) & ~3);
-
+#ifndef __MICROBLAZEEL__
 			/* Load the holding buffer */
 			buf_hold = *--i_src >> 16;
 
@@ -130,7 +149,16 @@
 				*--i_dst = buf_hold << 16 | value;
 				buf_hold = value >> 16;
 			}
+#else
+			/* Load the holding buffer */
+			buf_hold = (*--i_src & 0xFFFF) << 16;
 
+			for (; c >= 4; c -= 4) {
+				value = *--i_src;
+				*--i_dst = buf_hold | ((value & 0xFFFF0000)>>16);
+				buf_hold = (value & 0xFFFF) << 16;
+			}
+#endif
 			/* Realign the source */
 			src = (const void *)i_src;
 			src += 2;
@@ -138,7 +166,7 @@
 		case 0x3:	/* Unaligned - Off by 3 */
 			/* Word align the source */
 			i_src = (const void *) (((unsigned)src + 4) & ~3);
-
+#ifndef __MICROBLAZEEL__
 			/* Load the holding buffer */
 			buf_hold = *--i_src >> 8;
 
@@ -147,7 +175,16 @@
 				*--i_dst = buf_hold << 24 | value;
 				buf_hold = value >> 8;
 			}
+#else
+			/* Load the holding buffer */
+			buf_hold = (*--i_src & 0xFFFFFF) << 8;
 
+			for (; c >= 4; c -= 4) {
+				value = *--i_src;
+				*--i_dst = buf_hold | ((value & 0xFF000000)>> 24);
+				buf_hold = (value & 0xFFFFFF) << 8;;
+			}
+#endif
 			/* Realign the source */
 			src = (const void *)i_src;
 			src += 3;
@@ -169,7 +206,7 @@
 		*--dst = *--src;
 	}
 	return v_dst;
-#endif
 }
+#endif /* CONFIG_OPT_LIB_FUNCTION */
 EXPORT_SYMBOL(memmove);
 #endif /* __HAVE_ARCH_MEMMOVE */
diff --git a/arch/microblaze/lib/memset.c b/arch/microblaze/lib/memset.c
index ecfb663..834565d 100644
--- a/arch/microblaze/lib/memset.c
+++ b/arch/microblaze/lib/memset.c
@@ -31,17 +31,30 @@
 #include <linux/string.h>
 
 #ifdef __HAVE_ARCH_MEMSET
+#ifndef CONFIG_OPT_LIB_FUNCTION
 void *memset(void *v_src, int c, __kernel_size_t n)
 {
 	char *src = v_src;
-#ifdef CONFIG_OPT_LIB_FUNCTION
-	uint32_t *i_src;
-	uint32_t w32 = 0;
-#endif
+
 	/* Truncate c to 8 bits */
 	c = (c & 0xFF);
 
-#ifdef CONFIG_OPT_LIB_FUNCTION
+	/* Simple, byte oriented memset or the rest of count. */
+	while (n--)
+		*src++ = c;
+
+	return v_src;
+}
+#else /* CONFIG_OPT_LIB_FUNCTION */
+void *memset(void *v_src, int c, __kernel_size_t n)
+{
+	char *src = v_src;
+	uint32_t *i_src;
+	uint32_t w32 = 0;
+
+	/* Truncate c to 8 bits */
+	c = (c & 0xFF);
+
 	if (unlikely(c)) {
 		/* Make a repeating word out of it */
 		w32 = c;
@@ -72,12 +85,13 @@
 
 		src  = (void *)i_src;
 	}
-#endif
+
 	/* Simple, byte oriented memset or the rest of count. */
 	while (n--)
 		*src++ = c;
 
 	return v_src;
 }
+#endif /* CONFIG_OPT_LIB_FUNCTION */
 EXPORT_SYMBOL(memset);
 #endif /* __HAVE_ARCH_MEMSET */
diff --git a/arch/microblaze/lib/modsi3.S b/arch/microblaze/lib/modsi3.S
new file mode 100644
index 0000000..84e0bee
--- /dev/null
+++ b/arch/microblaze/lib/modsi3.S
@@ -0,0 +1,73 @@
+#include <linux/linkage.h>
+
+/*
+* modulo operation for 32 bit integers.
+*	Input :	op1 in Reg r5
+*		op2 in Reg r6
+*	Output: op1 mod op2 in Reg r3
+*/
+
+	.text
+	.globl	__modsi3
+	.type __modsi3,  @function
+	.ent __modsi3
+
+__modsi3:
+	.frame	r1, 0, r15
+
+	addik	r1, r1, -16
+	swi	r28, r1, 0
+	swi	r29, r1, 4
+	swi	r30, r1, 8
+	swi	r31, r1, 12
+
+	beqi	r6, div_by_zero /* div_by_zero division error */
+	beqi	r5, result_is_zero /* result is zero */
+	bgeid	r5, r5_pos
+	/* get the sign of the result [ depends only on the first arg] */
+	add	r28, r5, r0
+	rsubi	r5, r5, 0	 /* make r5 positive */
+r5_pos:
+	bgei	r6, r6_pos
+	rsubi	r6, r6, 0	 /* make r6 positive */
+r6_pos:
+	addik	r3, r0, 0 /* clear mod */
+	addik	r30, r0, 0 /* clear div */
+	addik	r29, r0, 32 /* initialize the loop count */
+/* first part try to find the first '1' in the r5 */
+div1:
+	add	r5, r5, r5 /* left shift logical r5 */
+	bgeid	r5, div1
+	addik	r29, r29, -1
+div2:
+	/* left shift logical r5 get the '1' into the carry */
+	add	r5, r5, r5
+	addc	r3, r3, r3 /* move that bit into the mod register */
+	rsub	r31, r6, r3 /* try to subtract (r30 a r6) */
+	blti	r31, mod_too_small
+	/* move the r31 to mod since the result was positive */
+	or	r3, r0, r31
+	addik	r30, r30, 1
+mod_too_small:
+	addik	r29, r29, -1
+	beqi	r29, loop_end
+	add	r30, r30, r30 /* shift in the '1' into div */
+	bri	div2 /* div2 */
+loop_end:
+	bgei	r28, return_here
+	brid	return_here
+	rsubi	r3, r3, 0 /* negate the result */
+div_by_zero:
+result_is_zero:
+	or	r3, r0, r0 /* set result to 0 [both mod as well as div are 0] */
+return_here:
+/* restore values of csrs and that of r3 and the divisor and the dividend */
+	lwi	r28, r1, 0
+	lwi	r29, r1, 4
+	lwi	r30, r1, 8
+	lwi	r31, r1, 12
+	rtsd	r15, 8
+	addik	r1, r1, 16
+
+.size __modsi3,  . - __modsi3
+.end __modsi3
diff --git a/arch/microblaze/lib/muldi3.S b/arch/microblaze/lib/muldi3.S
new file mode 100644
index 0000000..ceeaa8c
--- /dev/null
+++ b/arch/microblaze/lib/muldi3.S
@@ -0,0 +1,121 @@
+#include <linux/linkage.h>
+
+/*
+ * Multiply operation for 64 bit integers, for devices with hard multiply
+ *	Input :	Operand1[H] in Reg r5
+ *		Operand1[L] in Reg r6
+ *		Operand2[H] in Reg r7
+ *		Operand2[L] in Reg r8
+ *	Output: Result[H] in Reg r3
+ *		Result[L] in Reg r4
+ *
+ * Explaination:
+ *
+ *	Both the input numbers are divided into 16 bit number as follows
+ *		op1 = A B C D
+ *		op2 = E F G H
+ *	result = D * H
+ *		 + (C * H + D * G) << 16
+ *		 + (B * H + C * G + D * F) << 32
+ *		 + (A * H + B * G + C * F + D * E) << 48
+ *
+ *	Only 64 bits of the output are considered
+ */
+
+	.text
+	.globl	__muldi3
+	.type __muldi3, @function
+	.ent __muldi3
+
+__muldi3:
+	addi	r1, r1, -40
+
+/* Save the input operands on the caller's stack */
+	swi	r5, r1, 44
+	swi	r6, r1, 48
+	swi	r7, r1, 52
+	swi	r8, r1, 56
+
+/* Store all the callee saved registers */
+	sw	r20, r1, r0
+	swi	r21, r1, 4
+	swi	r22, r1, 8
+	swi	r23, r1, 12
+	swi	r24, r1, 16
+	swi	r25, r1, 20
+	swi	r26, r1, 24
+	swi	r27, r1, 28
+
+/* Load all the 16 bit values for A thru H */
+	lhui	r20, r1, 44 /* A */
+	lhui	r21, r1, 46 /* B */
+	lhui	r22, r1, 48 /* C */
+	lhui	r23, r1, 50 /* D */
+	lhui	r24, r1, 52 /* E */
+	lhui	r25, r1, 54 /* F */
+	lhui	r26, r1, 56 /* G */
+	lhui	r27, r1, 58 /* H */
+
+/* D * H ==> LSB of the result on stack ==> Store1 */
+	mul	r9, r23, r27
+	swi	r9, r1, 36 /* Pos2 and Pos3 */
+
+/* Hi (Store1) + C * H + D * G ==> Store2 ==> Pos1 and Pos2 */
+/* Store the carry generated in position 2 for Pos 3 */
+	lhui	r11, r1, 36 /* Pos2 */
+	mul	r9, r22, r27 /* C * H */
+	mul	r10, r23, r26 /* D * G */
+	add	r9, r9, r10
+	addc	r12, r0, r0
+	add	r9, r9, r11
+	addc	r12, r12, r0 /* Store the Carry */
+	shi	r9, r1, 36 /* Store Pos2 */
+	swi	r9, r1, 32
+	lhui	r11, r1, 32
+	shi	r11, r1, 34 /* Store Pos1 */
+
+/* Hi (Store2) + B * H + C * G + D * F ==> Store3 ==> Pos0 and Pos1 */
+	mul	r9, r21, r27 /* B * H */
+	mul	r10, r22, r26 /* C * G */
+	mul	r7, r23, r25 /* D * F */
+	add	r9, r9, r11
+	add	r9, r9, r10
+	add	r9, r9, r7
+	swi	r9, r1, 32 /* Pos0 and Pos1 */
+
+/* Hi (Store3) + A * H + B * G + C * F + D * E ==> Store3 ==> Pos0 */
+	lhui	r11, r1, 32 /* Pos0 */
+	mul	r9, r20, r27 /* A * H */
+	mul	r10, r21, r26 /* B * G */
+	mul	r7, r22, r25 /* C * F */
+	mul	r8, r23, r24 /* D * E */
+	add	r9, r9, r11
+	add 	r9, r9, r10
+	add	r9, r9, r7
+	add	r9, r9, r8
+	sext16	r9, r9 /* Sign extend the MSB */
+	shi	r9, r1, 32
+
+/* Move results to r3 and r4 */
+	lhui	r3, r1, 32
+	add	r3, r3, r12
+	shi	r3, r1, 32
+	lwi	r3, r1, 32 /* Hi Part */
+	lwi	r4, r1, 36 /* Lo Part */
+
+/* Restore Callee saved registers */
+	lw	r20, r1, r0
+	lwi	r21, r1, 4
+	lwi	r22, r1, 8
+	lwi	r23, r1, 12
+	lwi	r24, r1, 16
+	lwi	r25, r1, 20
+	lwi	r26, r1, 24
+	lwi	r27, r1, 28
+
+/* Restore Frame and return */
+	rtsd	r15, 8
+	addi	r1, r1, 40
+
+.size __muldi3, . - __muldi3
+.end __muldi3
diff --git a/arch/microblaze/lib/mulsi3.S b/arch/microblaze/lib/mulsi3.S
new file mode 100644
index 0000000..90bd7b9
--- /dev/null
+++ b/arch/microblaze/lib/mulsi3.S
@@ -0,0 +1,46 @@
+#include <linux/linkage.h>
+
+/*
+ * Multiply operation for 32 bit integers.
+ *	Input :	Operand1 in Reg r5
+ *		Operand2 in Reg r6
+ *	Output: Result [op1 * op2] in Reg r3
+ */
+	.text
+	.globl	__mulsi3
+	.type __mulsi3,  @function
+	.ent __mulsi3
+
+__mulsi3:
+	.frame	r1, 0, r15
+	add	r3, r0, r0
+	beqi	r5, result_is_zero /* multiply by zero */
+	beqi	r6, result_is_zero /* multiply by zero */
+	bgeid	r5, r5_pos
+	xor	r4, r5, r6 /* get the sign of the result */
+	rsubi	r5, r5, 0 /* make r5 positive */
+r5_pos:
+	bgei	r6, r6_pos
+	rsubi	r6, r6, 0 /* make r6 positive */
+r6_pos:
+	bri	l1
+l2:
+	add	r5, r5, r5
+l1:
+	srl	r6, r6
+	addc	r7, r0, r0
+	beqi	r7, l2
+	bneid	r6, l2
+	add	r3, r3, r5
+	blti	r4, negateresult
+	rtsd	r15, 8
+	nop
+negateresult:
+	rtsd	r15, 8
+	rsub	r3, r3, r0
+result_is_zero:
+	rtsd	r15, 8
+	addi	r3, r0, 0
+
+.size __mulsi3,  . - __mulsi3
+.end __mulsi3
diff --git a/arch/microblaze/lib/udivsi3.S b/arch/microblaze/lib/udivsi3.S
new file mode 100644
index 0000000..64cf57e
--- /dev/null
+++ b/arch/microblaze/lib/udivsi3.S
@@ -0,0 +1,84 @@
+#include <linux/linkage.h>
+
+/*
+* Unsigned divide operation.
+*	Input :	Divisor in Reg r5
+*		Dividend in Reg r6
+*	Output: Result in Reg r3
+*/
+
+	.text
+	.globl	__udivsi3
+	.type __udivsi3, @function
+	.ent __udivsi3
+
+__udivsi3:
+
+	.frame	r1, 0, r15
+
+	addik	r1, r1, -12
+	swi	r29, r1, 0
+	swi	r30, r1, 4
+	swi	r31, r1, 8
+
+	beqi	r6, div_by_zero /* div_by_zero /* division error */
+	beqid	r5, result_is_zero /* result is zero */
+	addik	r30, r0, 0 /* clear mod */
+	addik	r29, r0, 32 /* initialize the loop count */
+
+/* check if r6 and r5 are equal - if yes, return 1 */
+	rsub	r18, r5, r6
+	beqid	r18, return_here
+	addik	r3, r0, 1
+
+/* check if (uns)r6 is greater than (uns)r5. in that case, just return 0 */
+	xor	r18, r5, r6
+	bgeid	r18, 16
+	add	r3, r0, r0 /* we would anyways clear r3 */
+	blti	r6, return_here /* r6[bit 31 = 1] hence is greater */
+	bri	checkr6
+	rsub	r18, r6, r5 /* microblazecmp */
+	blti	r18, return_here
+
+/* if r6 [bit 31] is set, then return result as 1 */
+checkr6:
+	bgti	r6, div0
+	brid	return_here
+	addik	r3, r0, 1
+
+/* first part try to find the first '1' in the r5 */
+div0:
+	blti	r5, div2
+div1:
+	add	r5, r5, r5 /* left shift logical r5 */
+	bgtid	r5, div1
+	addik	r29, r29, -1
+div2:
+/* left shift logical r5 get the '1' into the carry */
+	add	r5, r5, r5
+	addc	r30, r30, r30 /* move that bit into the mod register */
+	rsub	r31, r6, r30 /* try to subtract (r30 a r6) */
+	blti	r31, mod_too_small
+/* move the r31 to mod since the result was positive */
+	or	r30, r0, r31
+	addik	r3, r3, 1
+mod_too_small:
+	addik	r29, r29, -1
+	beqi	r29, loop_end
+	add	r3, r3, r3 /* shift in the '1' into div */
+	bri	div2 /* div2 */
+loop_end:
+	bri	return_here
+div_by_zero:
+result_is_zero:
+	or	r3, r0, r0 /* set result to 0 */
+return_here:
+/* restore values of csrs and that of r3 and the divisor and the dividend */
+	lwi	r29, r1, 0
+	lwi	r30, r1, 4
+	lwi	r31, r1, 8
+	rtsd	r15, 8
+	addik	r1, r1, 12
+
+.size __udivsi3, . - __udivsi3
+.end __udivsi3
diff --git a/arch/microblaze/lib/umodsi3.S b/arch/microblaze/lib/umodsi3.S
new file mode 100644
index 0000000..17d16ba
--- /dev/null
+++ b/arch/microblaze/lib/umodsi3.S
@@ -0,0 +1,86 @@
+#include <linux/linkage.h>
+
+/*
+ * Unsigned modulo operation for 32 bit integers.
+ *	Input :	op1 in Reg r5
+ *		op2 in Reg r6
+ *	Output: op1 mod op2 in Reg r3
+ */
+
+	.text
+	.globl	__umodsi3
+	.type __umodsi3, @function
+	.ent __umodsi3
+
+__umodsi3:
+	.frame	r1, 0, r15
+
+	addik	r1, r1, -12
+	swi	r29, r1, 0
+	swi	r30, r1, 4
+	swi	r31, r1, 8
+
+	beqi	r6, div_by_zero /* div_by_zero - division error */
+	beqid	r5, result_is_zero /* result is zero */
+	addik	r3, r0, 0 /* clear div */
+	addik	r30, r0, 0 /* clear mod */
+	addik	r29, r0, 32 /* initialize the loop count */
+
+/* check if r6 and r5 are equal /* if yes, return 0 */
+	rsub	r18, r5, r6
+	beqi	r18, return_here
+
+/* check if (uns)r6 is greater than (uns)r5. in that case, just return r5 */
+	xor	r18, r5, r6
+	bgeid	r18, 16
+	addik	r3, r5, 0
+	blti	r6, return_here
+	bri	$lcheckr6
+	rsub	r18, r5, r6 /* microblazecmp */
+	bgti	r18, return_here
+
+/* if r6 [bit 31] is set, then return result as r5-r6 */
+$lcheckr6:
+	bgtid	r6, div0
+	addik	r3, r0, 0
+	addik	r18, r0, 0x7fffffff
+	and	r5, r5, r18
+	and	r6, r6, r18
+	brid	return_here
+	rsub	r3, r6, r5
+/* first part: try to find the first '1' in the r5 */
+div0:
+	blti	r5, div2
+div1:
+	add	r5, r5, r5 /* left shift logical r5 */
+	bgeid	r5, div1
+	addik	r29, r29, -1
+div2:
+	/* left shift logical r5 get the '1' into the carry */
+	add	r5, r5, r5
+	addc	r3, r3, r3 /* move that bit into the mod register */
+	rsub	r31, r6, r3 /* try to subtract (r3 a r6) */
+	blti	r31, mod_too_small
+	/* move the r31 to mod since the result was positive */
+	or	r3, r0, r31
+	addik	r30, r30, 1
+mod_too_small:
+	addik	r29, r29, -1
+	beqi	r29, loop_end
+	add	r30, r30, r30 /* shift in the '1' into div */
+	bri	div2 /* div2 */
+loop_end:
+	bri	return_here
+div_by_zero:
+result_is_zero:
+	or	r3, r0, r0 /* set result to 0 */
+return_here:
+/* restore values of csrs and that of r3 and the divisor and the dividend */
+	lwi	r29, r1, 0
+	lwi	r30, r1, 4
+	lwi	r31, r1, 8
+	rtsd	r15, 8
+	addik	r1, r1, 12
+
+.size __umodsi3, . - __umodsi3
+.end __umodsi3
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index 55ef532..e363615 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -60,21 +60,6 @@
 }
 EXPORT_SYMBOL(get_pci_dma_ops);
 
-int pci_set_dma_mask(struct pci_dev *dev, u64 mask)
-{
-	return dma_set_mask(&dev->dev, mask);
-}
-
-int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
-{
-	int rc;
-
-	rc = dma_set_mask(&dev->dev, mask);
-	dev->dev.coherent_dma_mask = dev->dma_mask;
-
-	return rc;
-}
-
 struct pci_controller *pcibios_alloc_controller(struct device_node *dev)
 {
 	struct pci_controller *phb;
@@ -1075,8 +1060,6 @@
 		 bus->number, bus->self ? pci_name(bus->self) : "PHB");
 
 	list_for_each_entry(dev, &bus->devices, bus_list) {
-		struct dev_archdata *sd = &dev->dev.archdata;
-
 		/* Setup OF node pointer in archdata */
 		dev->dev.of_node = pci_device_to_OF_node(dev);
 
@@ -1086,8 +1069,8 @@
 		set_dev_node(&dev->dev, pcibus_to_node(dev->bus));
 
 		/* Hook up default DMA ops */
-		sd->dma_ops = pci_dma_ops;
-		sd->dma_data = (void *)PCI_DRAM_OFFSET;
+		set_dma_ops(&dev->dev, pci_dma_ops);
+		dev->dev.archdata.dma_data = (void *)PCI_DRAM_OFFSET;
 
 		/* Read default IRQs and fixup if necessary */
 		pci_read_irq_line(dev);
diff --git a/arch/microblaze/platform/generic/system.dts b/arch/microblaze/platform/generic/system.dts
index 2d5c417..3f85df2 100644
--- a/arch/microblaze/platform/generic/system.dts
+++ b/arch/microblaze/platform/generic/system.dts
@@ -85,6 +85,7 @@
 			xlnx,dynamic-bus-sizing = <0x1>;
 			xlnx,edge-is-positive = <0x1>;
 			xlnx,family = "virtex5";
+			xlnx,endianness = <0x1>;
 			xlnx,fpu-exception = <0x1>;
 			xlnx,fsl-data-size = <0x20>;
 			xlnx,fsl-exception = <0x0>;
@@ -218,6 +219,7 @@
 			#address-cells = <1>;
 			#size-cells = <1>;
 			compatible = "xlnx,compound";
+			ranges ;
 			ethernet@81c00000 {
 				compatible = "xlnx,xps-ll-temac-1.01.b", "xlnx,xps-ll-temac-1.00.a";
 				device_type = "network";
@@ -332,6 +334,7 @@
 			#address-cells = <1>;
 			#size-cells = <1>;
 			compatible = "xlnx,mpmc-4.02.a";
+			ranges ;
 			PIM3: sdma@84600180 {
 				compatible = "xlnx,ll-dma-1.00.a";
 				interrupt-parent = <&xps_intc_0>;
diff --git a/arch/microblaze/platform/platform.c b/arch/microblaze/platform/platform.c
index 5b89b58..b9529ca 100644
--- a/arch/microblaze/platform/platform.c
+++ b/arch/microblaze/platform/platform.c
@@ -17,9 +17,6 @@
 
 static struct of_device_id xilinx_of_bus_ids[] __initdata = {
 	{ .compatible = "simple-bus", },
-	{ .compatible = "xlnx,plb-v46-1.00.a", },
-	{ .compatible = "xlnx,opb-v20-1.10.c", },
-	{ .compatible = "xlnx,opb-v20-1.10.b", },
 	{ .compatible = "xlnx,compound", },
 	{}
 };
diff --git a/arch/mips/include/asm/highmem.h b/arch/mips/include/asm/highmem.h
index 75753ca..77e6440 100644
--- a/arch/mips/include/asm/highmem.h
+++ b/arch/mips/include/asm/highmem.h
@@ -45,18 +45,12 @@
 extern void * kmap_high(struct page *page);
 extern void kunmap_high(struct page *page);
 
-extern void *__kmap(struct page *page);
-extern void __kunmap(struct page *page);
-extern void *__kmap_atomic(struct page *page, enum km_type type);
-extern void __kunmap_atomic_notypecheck(void *kvaddr, enum km_type type);
-extern void *kmap_atomic_pfn(unsigned long pfn, enum km_type type);
-extern struct page *__kmap_atomic_to_page(void *ptr);
-
-#define kmap			__kmap
-#define kunmap			__kunmap
-#define kmap_atomic		__kmap_atomic
-#define kunmap_atomic_notypecheck		__kunmap_atomic_notypecheck
-#define kmap_atomic_to_page	__kmap_atomic_to_page
+extern void *kmap(struct page *page);
+extern void kunmap(struct page *page);
+extern void *__kmap_atomic(struct page *page);
+extern void __kunmap_atomic(void *kvaddr);
+extern void *kmap_atomic_pfn(unsigned long pfn);
+extern struct page *kmap_atomic_to_page(void *ptr);
 
 #define flush_cache_kmaps()	flush_cache_all()
 
diff --git a/arch/mips/include/asm/pgtable-32.h b/arch/mips/include/asm/pgtable-32.h
index ae90412..8a153d2 100644
--- a/arch/mips/include/asm/pgtable-32.h
+++ b/arch/mips/include/asm/pgtable-32.h
@@ -154,10 +154,7 @@
 
 #define pte_offset_map(dir, address)                                    \
 	((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
-#define pte_offset_map_nested(dir, address)                             \
-	((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
 #define pte_unmap(pte) ((void)(pte))
-#define pte_unmap_nested(pte) ((void)(pte))
 
 #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
 
diff --git a/arch/mips/include/asm/pgtable-64.h b/arch/mips/include/asm/pgtable-64.h
index 1be4b0f..f008960 100644
--- a/arch/mips/include/asm/pgtable-64.h
+++ b/arch/mips/include/asm/pgtable-64.h
@@ -257,10 +257,7 @@
 	((pte_t *) pmd_page_vaddr(*(dir)) + __pte_offset(address))
 #define pte_offset_map(dir, address)					\
 	((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
-#define pte_offset_map_nested(dir, address)				\
-	((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
 #define pte_unmap(pte) ((void)(pte))
-#define pte_unmap_nested(pte) ((void)(pte))
 
 /*
  * Initialize a new pgd / pmd table with invalid pointers.
diff --git a/arch/mips/mm/highmem.c b/arch/mips/mm/highmem.c
index 6a2b1bf..1e69b1f 100644
--- a/arch/mips/mm/highmem.c
+++ b/arch/mips/mm/highmem.c
@@ -9,7 +9,7 @@
 
 unsigned long highstart_pfn, highend_pfn;
 
-void *__kmap(struct page *page)
+void *kmap(struct page *page)
 {
 	void *addr;
 
@@ -21,16 +21,16 @@
 
 	return addr;
 }
-EXPORT_SYMBOL(__kmap);
+EXPORT_SYMBOL(kmap);
 
-void __kunmap(struct page *page)
+void kunmap(struct page *page)
 {
 	BUG_ON(in_interrupt());
 	if (!PageHighMem(page))
 		return;
 	kunmap_high(page);
 }
-EXPORT_SYMBOL(__kunmap);
+EXPORT_SYMBOL(kunmap);
 
 /*
  * kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because
@@ -41,17 +41,17 @@
  * kmaps are appropriate for short, tight code paths only.
  */
 
-void *__kmap_atomic(struct page *page, enum km_type type)
+void *__kmap_atomic(struct page *page)
 {
-	enum fixed_addresses idx;
 	unsigned long vaddr;
+	int idx, type;
 
 	/* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
 	pagefault_disable();
 	if (!PageHighMem(page))
 		return page_address(page);
 
-	debug_kmap_atomic(type);
+	type = kmap_atomic_idx_push();
 	idx = type + KM_TYPE_NR*smp_processor_id();
 	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
 #ifdef CONFIG_DEBUG_HIGHMEM
@@ -64,43 +64,47 @@
 }
 EXPORT_SYMBOL(__kmap_atomic);
 
-void __kunmap_atomic_notypecheck(void *kvaddr, enum km_type type)
+void __kunmap_atomic(void *kvaddr)
 {
-#ifdef CONFIG_DEBUG_HIGHMEM
 	unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
-	enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
+	int type;
 
 	if (vaddr < FIXADDR_START) { // FIXME
 		pagefault_enable();
 		return;
 	}
 
-	BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
+	type = kmap_atomic_idx_pop();
+#ifdef CONFIG_DEBUG_HIGHMEM
+	{
+		int idx = type + KM_TYPE_NR * smp_processor_id();
 
-	/*
-	 * force other mappings to Oops if they'll try to access
-	 * this pte without first remap it
-	 */
-	pte_clear(&init_mm, vaddr, kmap_pte-idx);
-	local_flush_tlb_one(vaddr);
+		BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
+
+		/*
+		 * force other mappings to Oops if they'll try to access
+		 * this pte without first remap it
+		 */
+		pte_clear(&init_mm, vaddr, kmap_pte-idx);
+		local_flush_tlb_one(vaddr);
+	}
 #endif
-
 	pagefault_enable();
 }
-EXPORT_SYMBOL(__kunmap_atomic_notypecheck);
+EXPORT_SYMBOL(__kunmap_atomic);
 
 /*
  * This is the same as kmap_atomic() but can map memory that doesn't
  * have a struct page associated with it.
  */
-void *kmap_atomic_pfn(unsigned long pfn, enum km_type type)
+void *kmap_atomic_pfn(unsigned long pfn)
 {
-	enum fixed_addresses idx;
 	unsigned long vaddr;
+	int idx, type;
 
 	pagefault_disable();
 
-	debug_kmap_atomic(type);
+	type = kmap_atomic_idx_push();
 	idx = type + KM_TYPE_NR*smp_processor_id();
 	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
 	set_pte(kmap_pte-idx, pfn_pte(pfn, PAGE_KERNEL));
@@ -109,7 +113,7 @@
 	return (void*) vaddr;
 }
 
-struct page *__kmap_atomic_to_page(void *ptr)
+struct page *kmap_atomic_to_page(void *ptr)
 {
 	unsigned long idx, vaddr = (unsigned long)ptr;
 	pte_t *pte;
diff --git a/arch/mn10300/include/asm/highmem.h b/arch/mn10300/include/asm/highmem.h
index b0b187a..f577ba2 100644
--- a/arch/mn10300/include/asm/highmem.h
+++ b/arch/mn10300/include/asm/highmem.h
@@ -70,15 +70,16 @@
  * be used in IRQ contexts, so in some (very limited) cases we need
  * it.
  */
-static inline unsigned long kmap_atomic(struct page *page, enum km_type type)
+static inline unsigned long __kmap_atomic(struct page *page)
 {
-	enum fixed_addresses idx;
 	unsigned long vaddr;
+	int idx, type;
 
+	pagefault_disable();
 	if (page < highmem_start_page)
 		return page_address(page);
 
-	debug_kmap_atomic(type);
+	type = kmap_atomic_idx_push();
 	idx = type + KM_TYPE_NR * smp_processor_id();
 	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
 #if HIGHMEM_DEBUG
@@ -91,26 +92,35 @@
 	return vaddr;
 }
 
-static inline void kunmap_atomic_notypecheck(unsigned long vaddr, enum km_type type)
+static inline void __kunmap_atomic(unsigned long vaddr)
 {
-#if HIGHMEM_DEBUG
-	enum fixed_addresses idx = type + KM_TYPE_NR * smp_processor_id();
+	int type;
 
-	if (vaddr < FIXADDR_START) /* FIXME */
+	if (vaddr < FIXADDR_START) { /* FIXME */
+		pagefault_enable();
 		return;
+	}
 
-	if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx))
-		BUG();
+	type = kmap_atomic_idx_pop();
 
-	/*
-	 * force other mappings to Oops if they'll try to access
-	 * this pte without first remap it
-	 */
-	pte_clear(kmap_pte - idx);
-	__flush_tlb_one(vaddr);
+#if HIGHMEM_DEBUG
+	{
+		unsigned int idx;
+		idx = type + KM_TYPE_NR * smp_processor_id();
+
+		if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx))
+			BUG();
+
+		/*
+		 * force other mappings to Oops if they'll try to access
+		 * this pte without first remap it
+		 */
+		pte_clear(kmap_pte - idx);
+		__flush_tlb_one(vaddr);
+	}
 #endif
+	pagefault_enable();
 }
-
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_HIGHMEM_H */
diff --git a/arch/mn10300/include/asm/pgtable.h b/arch/mn10300/include/asm/pgtable.h
index 16d8857..b049a8b 100644
--- a/arch/mn10300/include/asm/pgtable.h
+++ b/arch/mn10300/include/asm/pgtable.h
@@ -457,9 +457,7 @@
 
 #define pte_offset_map(dir, address) \
 	((pte_t *) page_address(pmd_page(*(dir))) + pte_index(address))
-#define pte_offset_map_nested(dir, address) pte_offset_map(dir, address)
 #define pte_unmap(pte)		do {} while (0)
-#define pte_unmap_nested(pte)	do {} while (0)
 
 /*
  * The MN10300 has external MMU info in the form of a TLB: this is adapted from
diff --git a/arch/mn10300/kernel/vmlinux.lds.S b/arch/mn10300/kernel/vmlinux.lds.S
index 10549dc..febbeee 100644
--- a/arch/mn10300/kernel/vmlinux.lds.S
+++ b/arch/mn10300/kernel/vmlinux.lds.S
@@ -70,7 +70,7 @@
 	.exit.text : { EXIT_TEXT; }
 	.exit.data : { EXIT_DATA; }
 
-  PERCPU(32)
+  PERCPU(PAGE_SIZE)
   . = ALIGN(PAGE_SIZE);
   __init_end = .;
   /* freed after init ends here */
diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h
index 01c1503..865f37a 100644
--- a/arch/parisc/include/asm/pgtable.h
+++ b/arch/parisc/include/asm/pgtable.h
@@ -397,9 +397,7 @@
 #define pte_offset_kernel(pmd, address) \
 	((pte_t *) pmd_page_vaddr(*(pmd)) + pte_index(address))
 #define pte_offset_map(pmd, address) pte_offset_kernel(pmd, address)
-#define pte_offset_map_nested(pmd, address) pte_offset_kernel(pmd, address)
 #define pte_unmap(pte) do { } while (0)
-#define pte_unmap_nested(pte) do { } while (0)
 
 #define pte_unmap(pte)			do { } while (0)
 #define pte_unmap_nested(pte)		do { } while (0)
diff --git a/arch/powerpc/include/asm/highmem.h b/arch/powerpc/include/asm/highmem.h
index d10d64a..dbc2640 100644
--- a/arch/powerpc/include/asm/highmem.h
+++ b/arch/powerpc/include/asm/highmem.h
@@ -60,9 +60,8 @@
 
 extern void *kmap_high(struct page *page);
 extern void kunmap_high(struct page *page);
-extern void *kmap_atomic_prot(struct page *page, enum km_type type,
-			      pgprot_t prot);
-extern void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type);
+extern void *kmap_atomic_prot(struct page *page, pgprot_t prot);
+extern void __kunmap_atomic(void *kvaddr);
 
 static inline void *kmap(struct page *page)
 {
@@ -80,9 +79,9 @@
 	kunmap_high(page);
 }
 
-static inline void *kmap_atomic(struct page *page, enum km_type type)
+static inline void *__kmap_atomic(struct page *page)
 {
-	return kmap_atomic_prot(page, type, kmap_prot);
+	return kmap_atomic_prot(page, kmap_prot);
 }
 
 static inline struct page *kmap_atomic_to_page(void *ptr)
diff --git a/arch/powerpc/include/asm/pgtable-ppc32.h b/arch/powerpc/include/asm/pgtable-ppc32.h
index a7db96f..47edde8 100644
--- a/arch/powerpc/include/asm/pgtable-ppc32.h
+++ b/arch/powerpc/include/asm/pgtable-ppc32.h
@@ -308,12 +308,8 @@
 #define pte_offset_kernel(dir, addr)	\
 	((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(addr))
 #define pte_offset_map(dir, addr)		\
-	((pte_t *) kmap_atomic(pmd_page(*(dir)), KM_PTE0) + pte_index(addr))
-#define pte_offset_map_nested(dir, addr)	\
-	((pte_t *) kmap_atomic(pmd_page(*(dir)), KM_PTE1) + pte_index(addr))
-
-#define pte_unmap(pte)		kunmap_atomic(pte, KM_PTE0)
-#define pte_unmap_nested(pte)	kunmap_atomic(pte, KM_PTE1)
+	((pte_t *) kmap_atomic(pmd_page(*(dir))) + pte_index(addr))
+#define pte_unmap(pte)		kunmap_atomic(pte)
 
 /*
  * Encode and decode a swap entry.
diff --git a/arch/powerpc/include/asm/pgtable-ppc64.h b/arch/powerpc/include/asm/pgtable-ppc64.h
index 4986504..2b09cd5 100644
--- a/arch/powerpc/include/asm/pgtable-ppc64.h
+++ b/arch/powerpc/include/asm/pgtable-ppc64.h
@@ -193,9 +193,7 @@
   (((pte_t *) pmd_page_vaddr(*(dir))) + (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
 
 #define pte_offset_map(dir,addr)	pte_offset_kernel((dir), (addr))
-#define pte_offset_map_nested(dir,addr)	pte_offset_kernel((dir), (addr))
 #define pte_unmap(pte)			do { } while(0)
-#define pte_unmap_nested(pte)		do { } while(0)
 
 /* to find an entry in a kernel page-table-directory */
 /* This now only contains the vmalloc pages */
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index d692989..441d2a7 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -238,9 +238,7 @@
 	 * memory in this pool does not change.
 	 */
 	if (spare_needed && reserve_freed) {
-		tmp = min(spare_needed, min(reserve_freed,
-		                            (viodev->cmo.entitled -
-		                             VIO_CMO_MIN_ENT)));
+		tmp = min3(spare_needed, reserve_freed, (viodev->cmo.entitled - VIO_CMO_MIN_ENT));
 
 		vio_cmo.spare += tmp;
 		viodev->cmo.entitled -= tmp;
diff --git a/arch/powerpc/mm/highmem.c b/arch/powerpc/mm/highmem.c
index 857d417..b0848b4 100644
--- a/arch/powerpc/mm/highmem.c
+++ b/arch/powerpc/mm/highmem.c
@@ -29,17 +29,17 @@
  * be used in IRQ contexts, so in some (very limited) cases we need
  * it.
  */
-void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
+void *kmap_atomic_prot(struct page *page, pgprot_t prot)
 {
-	unsigned int idx;
 	unsigned long vaddr;
+	int idx, type;
 
 	/* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
 	pagefault_disable();
 	if (!PageHighMem(page))
 		return page_address(page);
 
-	debug_kmap_atomic(type);
+	type = kmap_atomic_idx_push();
 	idx = type + KM_TYPE_NR*smp_processor_id();
 	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
 #ifdef CONFIG_DEBUG_HIGHMEM
@@ -52,26 +52,33 @@
 }
 EXPORT_SYMBOL(kmap_atomic_prot);
 
-void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type)
+void __kunmap_atomic(void *kvaddr)
 {
-#ifdef CONFIG_DEBUG_HIGHMEM
 	unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
-	enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
+	int type;
 
 	if (vaddr < __fix_to_virt(FIX_KMAP_END)) {
 		pagefault_enable();
 		return;
 	}
 
-	BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
+	type = kmap_atomic_idx_pop();
 
-	/*
-	 * force other mappings to Oops if they'll try to access
-	 * this pte without first remap it
-	 */
-	pte_clear(&init_mm, vaddr, kmap_pte-idx);
-	local_flush_tlb_page(NULL, vaddr);
+#ifdef CONFIG_DEBUG_HIGHMEM
+	{
+		unsigned int idx;
+
+		idx = type + KM_TYPE_NR * smp_processor_id();
+		BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
+
+		/*
+		 * force other mappings to Oops if they'll try to access
+		 * this pte without first remap it
+		 */
+		pte_clear(&init_mm, vaddr, kmap_pte-idx);
+		local_flush_tlb_page(NULL, vaddr);
+	}
 #endif
 	pagefault_enable();
 }
-EXPORT_SYMBOL(kunmap_atomic_notypecheck);
+EXPORT_SYMBOL(__kunmap_atomic);
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index 986dc94..02ace34 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -1094,9 +1094,7 @@
 #define pte_offset(pmd, addr) ((pte_t *) pmd_deref(*(pmd)) + pte_index(addr))
 #define pte_offset_kernel(pmd, address) pte_offset(pmd,address)
 #define pte_offset_map(pmd, address) pte_offset_kernel(pmd, address)
-#define pte_offset_map_nested(pmd, address) pte_offset_kernel(pmd, address)
 #define pte_unmap(pte) do { } while (0)
-#define pte_unmap_nested(pte) do { } while (0)
 
 /*
  * 31 bit swap entry format:
diff --git a/arch/score/include/asm/pgtable.h b/arch/score/include/asm/pgtable.h
index ccf38f0..2fd4698 100644
--- a/arch/score/include/asm/pgtable.h
+++ b/arch/score/include/asm/pgtable.h
@@ -88,10 +88,7 @@
 
 #define pte_offset_map(dir, address)	\
 	((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
-#define pte_offset_map_nested(dir, address)	\
-	((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
 #define pte_unmap(pte) ((void)(pte))
-#define pte_unmap_nested(pte) ((void)(pte))
 
 /*
  * Bits 9(_PAGE_PRESENT) and 10(_PAGE_FILE)are taken,
diff --git a/arch/sh/include/asm/pgtable_32.h b/arch/sh/include/asm/pgtable_32.h
index e172d69..69fdfbf 100644
--- a/arch/sh/include/asm/pgtable_32.h
+++ b/arch/sh/include/asm/pgtable_32.h
@@ -429,10 +429,7 @@
 #define pte_offset_kernel(dir, address) \
 	((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(address))
 #define pte_offset_map(dir, address)		pte_offset_kernel(dir, address)
-#define pte_offset_map_nested(dir, address)	pte_offset_kernel(dir, address)
-
 #define pte_unmap(pte)		do { } while (0)
-#define pte_unmap_nested(pte)	do { } while (0)
 
 #ifdef CONFIG_X2TLB
 #define pte_ERROR(e) \
diff --git a/arch/sh/include/asm/pgtable_64.h b/arch/sh/include/asm/pgtable_64.h
index 0ee4677..10a4811 100644
--- a/arch/sh/include/asm/pgtable_64.h
+++ b/arch/sh/include/asm/pgtable_64.h
@@ -84,9 +84,7 @@
 		((pte_t *) ((pmd_val(*(dir))) & PAGE_MASK) + pte_index((addr)))
 
 #define pte_offset_map(dir,addr)	pte_offset_kernel(dir, addr)
-#define pte_offset_map_nested(dir,addr)	pte_offset_kernel(dir, addr)
 #define pte_unmap(pte)		do { } while (0)
-#define pte_unmap_nested(pte)	do { } while (0)
 
 #ifndef __ASSEMBLY__
 #define IOBASE_VADDR	0xff000000
diff --git a/arch/sparc/include/asm/highmem.h b/arch/sparc/include/asm/highmem.h
index ec23b0a..3d7afbb 100644
--- a/arch/sparc/include/asm/highmem.h
+++ b/arch/sparc/include/asm/highmem.h
@@ -70,8 +70,8 @@
 	kunmap_high(page);
 }
 
-extern void *kmap_atomic(struct page *page, enum km_type type);
-extern void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type);
+extern void *__kmap_atomic(struct page *page);
+extern void __kunmap_atomic(void *kvaddr);
 extern struct page *kmap_atomic_to_page(void *vaddr);
 
 #define flush_cache_kmaps()	flush_cache_all()
diff --git a/arch/sparc/include/asm/pgtable_32.h b/arch/sparc/include/asm/pgtable_32.h
index 0ece77f..303bd4d 100644
--- a/arch/sparc/include/asm/pgtable_32.h
+++ b/arch/sparc/include/asm/pgtable_32.h
@@ -304,10 +304,7 @@
  * and sun4c is guaranteed to have no highmem anyway.
  */
 #define pte_offset_map(d, a)		pte_offset_kernel(d,a)
-#define pte_offset_map_nested(d, a)	pte_offset_kernel(d,a)
-
 #define pte_unmap(pte)		do{}while(0)
-#define pte_unmap_nested(pte)	do{}while(0)
 
 /* Certain architectures need to do special things when pte's
  * within a page table are directly modified.  Thus, the following
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
index f5b5fa7..f8dddb7 100644
--- a/arch/sparc/include/asm/pgtable_64.h
+++ b/arch/sparc/include/asm/pgtable_64.h
@@ -652,9 +652,7 @@
 	 ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
 #define pte_offset_kernel		pte_index
 #define pte_offset_map			pte_index
-#define pte_offset_map_nested		pte_index
 #define pte_unmap(pte)			do { } while (0)
-#define pte_unmap_nested(pte)		do { } while (0)
 
 /* Actual page table PTE updates.  */
 extern void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, pte_t *ptep, pte_t orig);
diff --git a/arch/sparc/mm/highmem.c b/arch/sparc/mm/highmem.c
index e139e9c..5e50c09 100644
--- a/arch/sparc/mm/highmem.c
+++ b/arch/sparc/mm/highmem.c
@@ -29,17 +29,17 @@
 #include <asm/tlbflush.h>
 #include <asm/fixmap.h>
 
-void *kmap_atomic(struct page *page, enum km_type type)
+void *__kmap_atomic(struct page *page)
 {
-	unsigned long idx;
 	unsigned long vaddr;
+	long idx, type;
 
 	/* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
 	pagefault_disable();
 	if (!PageHighMem(page))
 		return page_address(page);
 
-	debug_kmap_atomic(type);
+	type = kmap_atomic_idx_push();
 	idx = type + KM_TYPE_NR*smp_processor_id();
 	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
 
@@ -63,44 +63,50 @@
 
 	return (void*) vaddr;
 }
-EXPORT_SYMBOL(kmap_atomic);
+EXPORT_SYMBOL(__kmap_atomic);
 
-void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type)
+void __kunmap_atomic(void *kvaddr)
 {
-#ifdef CONFIG_DEBUG_HIGHMEM
 	unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
-	unsigned long idx = type + KM_TYPE_NR*smp_processor_id();
+	int type;
 
 	if (vaddr < FIXADDR_START) { // FIXME
 		pagefault_enable();
 		return;
 	}
 
-	BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx));
+	type = kmap_atomic_idx_pop();
 
-/* XXX Fix - Anton */
+#ifdef CONFIG_DEBUG_HIGHMEM
+	{
+		unsigned long idx;
+
+		idx = type + KM_TYPE_NR * smp_processor_id();
+		BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx));
+
+		/* XXX Fix - Anton */
 #if 0
-	__flush_cache_one(vaddr);
+		__flush_cache_one(vaddr);
 #else
-	flush_cache_all();
+		flush_cache_all();
 #endif
 
-	/*
-	 * force other mappings to Oops if they'll try to access
-	 * this pte without first remap it
-	 */
-	pte_clear(&init_mm, vaddr, kmap_pte-idx);
-/* XXX Fix - Anton */
+		/*
+		 * force other mappings to Oops if they'll try to access
+		 * this pte without first remap it
+		 */
+		pte_clear(&init_mm, vaddr, kmap_pte-idx);
+		/* XXX Fix - Anton */
 #if 0
-	__flush_tlb_one(vaddr);
+		__flush_tlb_one(vaddr);
 #else
-	flush_tlb_all();
+		flush_tlb_all();
 #endif
+	}
 #endif
-
 	pagefault_enable();
 }
-EXPORT_SYMBOL(kunmap_atomic_notypecheck);
+EXPORT_SYMBOL(__kunmap_atomic);
 
 /* We may be fed a pagetable here by ptep_to_xxx and others. */
 struct page *kmap_atomic_to_page(void *ptr)
diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig
index 1eb308c..89cfee0 100644
--- a/arch/tile/Kconfig
+++ b/arch/tile/Kconfig
@@ -96,6 +96,7 @@
 
 config TILE
 	def_bool y
+	select HAVE_KVM if !TILEGX
 	select GENERIC_FIND_FIRST_BIT
 	select GENERIC_FIND_NEXT_BIT
 	select USE_GENERIC_SMP_HELPERS
@@ -236,9 +237,9 @@
 	  If you are not absolutely sure what you are doing, leave this
 	  option alone!
 
-	config VMSPLIT_375G
+	config VMSPLIT_3_75G
 		bool "3.75G/0.25G user/kernel split (no kernel networking)"
-	config VMSPLIT_35G
+	config VMSPLIT_3_5G
 		bool "3.5G/0.5G user/kernel split"
 	config VMSPLIT_3G
 		bool "3G/1G user/kernel split"
@@ -252,8 +253,8 @@
 
 config PAGE_OFFSET
 	hex
-	default 0xF0000000 if VMSPLIT_375G
-	default 0xE0000000 if VMSPLIT_35G
+	default 0xF0000000 if VMSPLIT_3_75G
+	default 0xE0000000 if VMSPLIT_3_5G
 	default 0xB0000000 if VMSPLIT_3G_OPT
 	default 0x80000000 if VMSPLIT_2G
 	default 0x40000000 if VMSPLIT_1G
@@ -314,6 +315,15 @@
 	bool "Hardwall support to allow access to user dynamic network"
 	default y
 
+config KERNEL_PL
+	int "Processor protection level for kernel"
+	range 1 2
+	default "1"
+	---help---
+	  This setting determines the processor protection level the
+	  kernel will be built to run at.  Generally you should use
+	  the default value here.
+
 endmenu  # Tilera-specific configuration
 
 menu "Bus options"
@@ -354,3 +364,5 @@
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
+
+source "arch/tile/kvm/Kconfig"
diff --git a/arch/tile/Makefile b/arch/tile/Makefile
index fd8f6bb..17acce7 100644
--- a/arch/tile/Makefile
+++ b/arch/tile/Makefile
@@ -26,8 +26,9 @@
   endif
 endif
 
-
+ifneq ($(CONFIG_DEBUG_EXTRA_FLAGS),"")
 KBUILD_CFLAGS   += $(CONFIG_DEBUG_EXTRA_FLAGS)
+endif
 
 LIBGCC_PATH     := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
 
@@ -49,6 +50,20 @@
 libs-y		+= arch/tile/lib/
 libs-y		+= $(LIBGCC_PATH)
 
-
 # See arch/tile/Kbuild for content of core part of the kernel
 core-y		+= arch/tile/
+
+core-$(CONFIG_KVM) += arch/tile/kvm/
+
+ifdef TILERA_ROOT
+INSTALL_PATH ?= $(TILERA_ROOT)/tile/boot
+endif
+
+install:
+	install -D -m 755 vmlinux $(INSTALL_PATH)/vmlinux-$(KERNELRELEASE)
+	install -D -m 644 .config $(INSTALL_PATH)/config-$(KERNELRELEASE)
+	install -D -m 644 System.map $(INSTALL_PATH)/System.map-$(KERNELRELEASE)
+
+define archhelp
+	echo '  install         - install kernel into $(INSTALL_PATH)'
+endef
diff --git a/arch/tile/include/arch/sim.h b/arch/tile/include/arch/sim.h
new file mode 100644
index 0000000..74b7c16
--- /dev/null
+++ b/arch/tile/include/arch/sim.h
@@ -0,0 +1,619 @@
+/*
+ * Copyright 2010 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/**
+ * @file
+ *
+ * Provides an API for controlling the simulator at runtime.
+ */
+
+/**
+ * @addtogroup arch_sim
+ * @{
+ *
+ * An API for controlling the simulator at runtime.
+ *
+ * The simulator's behavior can be modified while it is running.
+ * For example, human-readable trace output can be enabled and disabled
+ * around code of interest.
+ *
+ * There are two ways to modify simulator behavior:
+ * programmatically, by calling various sim_* functions, and
+ * interactively, by entering commands like "sim set functional true"
+ * at the tile-monitor prompt.  Typing "sim help" at that prompt provides
+ * a list of interactive commands.
+ *
+ * All interactive commands can also be executed programmatically by
+ * passing a string to the sim_command function.
+ */
+
+#ifndef __ARCH_SIM_H__
+#define __ARCH_SIM_H__
+
+#include <arch/sim_def.h>
+#include <arch/abi.h>
+
+#ifndef __ASSEMBLER__
+
+#include <arch/spr_def.h>
+
+
+/**
+ * Return true if the current program is running under a simulator,
+ * rather than on real hardware.  If running on hardware, other "sim_xxx()"
+ * calls have no useful effect.
+ */
+static inline int
+sim_is_simulator(void)
+{
+  return __insn_mfspr(SPR_SIM_CONTROL) != 0;
+}
+
+
+/**
+ * Checkpoint the simulator state to a checkpoint file.
+ *
+ * The checkpoint file name is either the default or the name specified
+ * on the command line with "--checkpoint-file".
+ */
+static __inline void
+sim_checkpoint(void)
+{
+  __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_CHECKPOINT);
+}
+
+
+/**
+ * Report whether or not various kinds of simulator tracing are enabled.
+ *
+ * @return The bitwise OR of these values:
+ *
+ * SIM_TRACE_CYCLES (--trace-cycles),
+ * SIM_TRACE_ROUTER (--trace-router),
+ * SIM_TRACE_REGISTER_WRITES (--trace-register-writes),
+ * SIM_TRACE_DISASM (--trace-disasm),
+ * SIM_TRACE_STALL_INFO (--trace-stall-info)
+ * SIM_TRACE_MEMORY_CONTROLLER (--trace-memory-controller)
+ * SIM_TRACE_L2_CACHE (--trace-l2)
+ * SIM_TRACE_LINES (--trace-lines)
+ */
+static __inline unsigned int
+sim_get_tracing(void)
+{
+  return __insn_mfspr(SPR_SIM_CONTROL) & SIM_TRACE_FLAG_MASK;
+}
+
+
+/**
+ * Turn on or off different kinds of simulator tracing.
+ *
+ * @param mask Either one of these special values:
+ *
+ * SIM_TRACE_NONE (turns off tracing),
+ * SIM_TRACE_ALL (turns on all possible tracing).
+ *
+ * or the bitwise OR of these values:
+ *
+ * SIM_TRACE_CYCLES (--trace-cycles),
+ * SIM_TRACE_ROUTER (--trace-router),
+ * SIM_TRACE_REGISTER_WRITES (--trace-register-writes),
+ * SIM_TRACE_DISASM (--trace-disasm),
+ * SIM_TRACE_STALL_INFO (--trace-stall-info)
+ * SIM_TRACE_MEMORY_CONTROLLER (--trace-memory-controller)
+ * SIM_TRACE_L2_CACHE (--trace-l2)
+ * SIM_TRACE_LINES (--trace-lines)
+ */
+static __inline void
+sim_set_tracing(unsigned int mask)
+{
+  __insn_mtspr(SPR_SIM_CONTROL, SIM_TRACE_SPR_ARG(mask));
+}
+
+
+/**
+ * Request dumping of different kinds of simulator state.
+ *
+ * @param mask Either this special value:
+ *
+ * SIM_DUMP_ALL (dump all known state)
+ *
+ * or the bitwise OR of these values:
+ *
+ * SIM_DUMP_REGS (the register file),
+ * SIM_DUMP_SPRS (the SPRs),
+ * SIM_DUMP_ITLB (the iTLB),
+ * SIM_DUMP_DTLB (the dTLB),
+ * SIM_DUMP_L1I (the L1 I-cache),
+ * SIM_DUMP_L1D (the L1 D-cache),
+ * SIM_DUMP_L2 (the L2 cache),
+ * SIM_DUMP_SNREGS (the switch register file),
+ * SIM_DUMP_SNITLB (the switch iTLB),
+ * SIM_DUMP_SNL1I (the switch L1 I-cache),
+ * SIM_DUMP_BACKTRACE (the current backtrace)
+ */
+static __inline void
+sim_dump(unsigned int mask)
+{
+  __insn_mtspr(SPR_SIM_CONTROL, SIM_DUMP_SPR_ARG(mask));
+}
+
+
+/**
+ * Print a string to the simulator stdout.
+ *
+ * @param str The string to be written; a newline is automatically added.
+ */
+static __inline void
+sim_print_string(const char* str)
+{
+  int i;
+  for (i = 0; str[i] != 0; i++)
+  {
+    __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PUTC |
+                 (str[i] << _SIM_CONTROL_OPERATOR_BITS));
+  }
+  __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PUTC |
+               (SIM_PUTC_FLUSH_STRING << _SIM_CONTROL_OPERATOR_BITS));
+}
+
+
+/**
+ * Execute a simulator command string.
+ *
+ * Type 'sim help' at the tile-monitor prompt to learn what commands
+ * are available.  Note the use of the tile-monitor "sim" command to
+ * pass commands to the simulator.
+ *
+ * The argument to sim_command() does not include the leading "sim"
+ * prefix used at the tile-monitor prompt; for example, you might call
+ * sim_command("trace disasm").
+ */
+static __inline void
+sim_command(const char* str)
+{
+  int c;
+  do
+  {
+    c = *str++;
+    __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_COMMAND |
+                 (c << _SIM_CONTROL_OPERATOR_BITS));
+  }
+  while (c);
+}
+
+
+
+#ifndef __DOXYGEN__
+
+/**
+ * The underlying implementation of "_sim_syscall()".
+ *
+ * We use extra "and" instructions to ensure that all the values
+ * we are passing to the simulator are actually valid in the registers
+ * (i.e. returned from memory) prior to the SIM_CONTROL spr.
+ */
+static __inline int _sim_syscall0(int val)
+{
+  long result;
+  __asm__ __volatile__ ("mtspr SIM_CONTROL, r0"
+                        : "=R00" (result) : "R00" (val));
+  return result;
+}
+
+static __inline int _sim_syscall1(int val, long arg1)
+{
+  long result;
+  __asm__ __volatile__ ("{ and zero, r1, r1; mtspr SIM_CONTROL, r0 }"
+                        : "=R00" (result) : "R00" (val), "R01" (arg1));
+  return result;
+}
+
+static __inline int _sim_syscall2(int val, long arg1, long arg2)
+{
+  long result;
+  __asm__ __volatile__ ("{ and zero, r1, r2; mtspr SIM_CONTROL, r0 }"
+                        : "=R00" (result)
+                        : "R00" (val), "R01" (arg1), "R02" (arg2));
+  return result;
+}
+
+/* Note that _sim_syscall3() and higher are technically at risk of
+   receiving an interrupt right before the mtspr bundle, in which case
+   the register values for arguments 3 and up may still be in flight
+   to the core from a stack frame reload. */
+
+static __inline int _sim_syscall3(int val, long arg1, long arg2, long arg3)
+{
+  long result;
+  __asm__ __volatile__ ("{ and zero, r3, r3 };"
+                        "{ and zero, r1, r2; mtspr SIM_CONTROL, r0 }"
+                        : "=R00" (result)
+                        : "R00" (val), "R01" (arg1), "R02" (arg2),
+                          "R03" (arg3));
+  return result;
+}
+
+static __inline int _sim_syscall4(int val, long arg1, long arg2, long arg3,
+                                  long arg4)
+{
+  long result;
+  __asm__ __volatile__ ("{ and zero, r3, r4 };"
+                        "{ and zero, r1, r2; mtspr SIM_CONTROL, r0 }"
+                        : "=R00" (result)
+                        : "R00" (val), "R01" (arg1), "R02" (arg2),
+                          "R03" (arg3), "R04" (arg4));
+  return result;
+}
+
+static __inline int _sim_syscall5(int val, long arg1, long arg2, long arg3,
+                                  long arg4, long arg5)
+{
+  long result;
+  __asm__ __volatile__ ("{ and zero, r3, r4; and zero, r5, r5 };"
+                        "{ and zero, r1, r2; mtspr SIM_CONTROL, r0 }"
+                        : "=R00" (result)
+                        : "R00" (val), "R01" (arg1), "R02" (arg2),
+                          "R03" (arg3), "R04" (arg4), "R05" (arg5));
+  return result;
+}
+
+
+/**
+ * Make a special syscall to the simulator itself, if running under
+ * simulation. This is used as the implementation of other functions
+ * and should not be used outside this file.
+ *
+ * @param syscall_num The simulator syscall number.
+ * @param nr The number of additional arguments provided.
+ *
+ * @return Varies by syscall.
+ */
+#define _sim_syscall(syscall_num, nr, args...) \
+  _sim_syscall##nr( \
+    ((syscall_num) << _SIM_CONTROL_OPERATOR_BITS) | SIM_CONTROL_SYSCALL, args)
+
+
+/* Values for the "access_mask" parameters below. */
+#define SIM_WATCHPOINT_READ    1
+#define SIM_WATCHPOINT_WRITE   2
+#define SIM_WATCHPOINT_EXECUTE 4
+
+
+static __inline int
+sim_add_watchpoint(unsigned int process_id,
+                   unsigned long address,
+                   unsigned long size,
+                   unsigned int access_mask,
+                   unsigned long user_data)
+{
+  return _sim_syscall(SIM_SYSCALL_ADD_WATCHPOINT, 5, process_id,
+                     address, size, access_mask, user_data);
+}
+
+
+static __inline int
+sim_remove_watchpoint(unsigned int process_id,
+                      unsigned long address,
+                      unsigned long size,
+                      unsigned int access_mask,
+                      unsigned long user_data)
+{
+  return _sim_syscall(SIM_SYSCALL_REMOVE_WATCHPOINT, 5, process_id,
+                     address, size, access_mask, user_data);
+}
+
+
+/**
+ * Return value from sim_query_watchpoint.
+ */
+struct SimQueryWatchpointStatus
+{
+  /**
+   * 0 if a watchpoint fired, 1 if no watchpoint fired, or -1 for
+   * error (meaning a bad process_id).
+   */
+  int syscall_status;
+
+  /**
+   * The address of the watchpoint that fired (this is the address
+   * passed to sim_add_watchpoint, not an address within that range
+   * that actually triggered the watchpoint).
+   */
+  unsigned long address;
+
+  /** The arbitrary user_data installed by sim_add_watchpoint. */
+  unsigned long user_data;
+};
+
+
+static __inline struct SimQueryWatchpointStatus
+sim_query_watchpoint(unsigned int process_id)
+{
+  struct SimQueryWatchpointStatus status;
+  long val = SIM_CONTROL_SYSCALL |
+    (SIM_SYSCALL_QUERY_WATCHPOINT << _SIM_CONTROL_OPERATOR_BITS);
+  __asm__ __volatile__ ("{ and zero, r1, r1; mtspr SIM_CONTROL, r0 }"
+                        : "=R00" (status.syscall_status),
+                          "=R01" (status.address),
+                          "=R02" (status.user_data)
+                        : "R00" (val), "R01" (process_id));
+  return status;
+}
+
+
+/* On the simulator, confirm lines have been evicted everywhere. */
+static __inline void
+sim_validate_lines_evicted(unsigned long long pa, unsigned long length)
+{
+#ifdef __LP64__
+  _sim_syscall(SIM_SYSCALL_VALIDATE_LINES_EVICTED, 2, pa, length);
+#else
+  _sim_syscall(SIM_SYSCALL_VALIDATE_LINES_EVICTED, 4,
+               0 /* dummy */, (long)(pa), (long)(pa >> 32), length);
+#endif
+}
+
+
+#endif /* !__DOXYGEN__ */
+
+
+
+
+/**
+ * Modify the shaping parameters of a shim.
+ *
+ * @param shim The shim to modify. One of:
+ *   SIM_CONTROL_SHAPING_GBE_0
+ *   SIM_CONTROL_SHAPING_GBE_1
+ *   SIM_CONTROL_SHAPING_GBE_2
+ *   SIM_CONTROL_SHAPING_GBE_3
+ *   SIM_CONTROL_SHAPING_XGBE_0
+ *   SIM_CONTROL_SHAPING_XGBE_1
+ *
+ * @param type The type of shaping. This should be the same type of
+ * shaping that is already in place on the shim. One of:
+ *   SIM_CONTROL_SHAPING_MULTIPLIER
+ *   SIM_CONTROL_SHAPING_PPS
+ *   SIM_CONTROL_SHAPING_BPS
+ *
+ * @param units The magnitude of the rate. One of:
+ *   SIM_CONTROL_SHAPING_UNITS_SINGLE
+ *   SIM_CONTROL_SHAPING_UNITS_KILO
+ *   SIM_CONTROL_SHAPING_UNITS_MEGA
+ *   SIM_CONTROL_SHAPING_UNITS_GIGA
+ *
+ * @param rate The rate to which to change it. This must fit in
+ * SIM_CONTROL_SHAPING_RATE_BITS bits or a warning is issued and
+ * the shaping is not changed.
+ *
+ * @return 0 if no problems were detected in the arguments to sim_set_shaping
+ * or 1 if problems were detected (for example, rate does not fit in 17 bits).
+ */
+static __inline int
+sim_set_shaping(unsigned shim,
+                unsigned type,
+                unsigned units,
+                unsigned rate)
+{
+  if ((rate & ~((1 << SIM_CONTROL_SHAPING_RATE_BITS) - 1)) != 0)
+    return 1;
+
+  __insn_mtspr(SPR_SIM_CONTROL, SIM_SHAPING_SPR_ARG(shim, type, units, rate));
+  return 0;
+}
+
+#ifdef __tilegx__
+
+/** Enable a set of mPIPE links.  Pass a -1 link_mask to enable all links. */
+static __inline void
+sim_enable_mpipe_links(unsigned mpipe, unsigned long link_mask)
+{
+  __insn_mtspr(SPR_SIM_CONTROL,
+               (SIM_CONTROL_ENABLE_MPIPE_LINK_MAGIC_BYTE |
+                (mpipe << 8) | (1 << 16) | ((uint_reg_t)link_mask << 32)));
+}
+
+/** Disable a set of mPIPE links.  Pass a -1 link_mask to disable all links. */
+static __inline void
+sim_disable_mpipe_links(unsigned mpipe, unsigned long link_mask)
+{
+  __insn_mtspr(SPR_SIM_CONTROL,
+               (SIM_CONTROL_ENABLE_MPIPE_LINK_MAGIC_BYTE |
+                (mpipe << 8) | (0 << 16) | ((uint_reg_t)link_mask << 32)));
+}
+
+#endif /* __tilegx__ */
+
+
+/*
+ * An API for changing "functional" mode.
+ */
+
+#ifndef __DOXYGEN__
+
+#define sim_enable_functional() \
+  __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_ENABLE_FUNCTIONAL)
+
+#define sim_disable_functional() \
+  __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_DISABLE_FUNCTIONAL)
+
+#endif /* __DOXYGEN__ */
+
+
+/*
+ * Profiler support.
+ */
+
+/**
+ * Turn profiling on for the current task.
+ *
+ * Note that this has no effect if run in an environment without
+ * profiling support (thus, the proper flags to the simulator must
+ * be supplied).
+ */
+static __inline void
+sim_profiler_enable(void)
+{
+  __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PROFILER_ENABLE);
+}
+
+
+/** Turn profiling off for the current task. */
+static __inline void
+sim_profiler_disable(void)
+{
+  __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PROFILER_DISABLE);
+}
+
+
+/**
+ * Turn profiling on or off for the current task.
+ *
+ * @param enabled If true, turns on profiling. If false, turns it off.
+ *
+ * Note that this has no effect if run in an environment without
+ * profiling support (thus, the proper flags to the simulator must
+ * be supplied).
+ */
+static __inline void
+sim_profiler_set_enabled(int enabled)
+{
+  int val =
+    enabled ? SIM_CONTROL_PROFILER_ENABLE : SIM_CONTROL_PROFILER_DISABLE;
+  __insn_mtspr(SPR_SIM_CONTROL, val);
+}
+
+
+/**
+ * Return true if and only if profiling is currently enabled
+ * for the current task.
+ *
+ * This returns false even if sim_profiler_enable() was called
+ * if the current execution environment does not support profiling.
+ */
+static __inline int
+sim_profiler_is_enabled(void)
+{
+  return ((__insn_mfspr(SPR_SIM_CONTROL) & SIM_PROFILER_ENABLED_MASK) != 0);
+}
+
+
+/**
+ * Reset profiling counters to zero for the current task.
+ *
+ * Resetting can be done while profiling is enabled.  It does not affect
+ * the chip-wide profiling counters.
+ */
+static __inline void
+sim_profiler_clear(void)
+{
+  __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PROFILER_CLEAR);
+}
+
+
+/**
+ * Enable specified chip-level profiling counters.
+ *
+ * Does not affect the per-task profiling counters.
+ *
+ * @param mask Either this special value:
+ *
+ * SIM_CHIP_ALL (enables all chip-level components).
+ *
+ * or the bitwise OR of these values:
+ *
+ * SIM_CHIP_MEMCTL (enable all memory controllers)
+ * SIM_CHIP_XAUI (enable all XAUI controllers)
+ * SIM_CHIP_MPIPE (enable all MPIPE controllers)
+ */
+static __inline void
+sim_profiler_chip_enable(unsigned int mask)
+{
+  __insn_mtspr(SPR_SIM_CONTROL, SIM_PROFILER_CHIP_ENABLE_SPR_ARG(mask));
+}
+
+
+/**
+ * Disable specified chip-level profiling counters.
+ *
+ * Does not affect the per-task profiling counters.
+ *
+ * @param mask Either this special value:
+ *
+ * SIM_CHIP_ALL (disables all chip-level components).
+ *
+ * or the bitwise OR of these values:
+ *
+ * SIM_CHIP_MEMCTL (disable all memory controllers)
+ * SIM_CHIP_XAUI (disable all XAUI controllers)
+ * SIM_CHIP_MPIPE (disable all MPIPE controllers)
+ */
+static __inline void
+sim_profiler_chip_disable(unsigned int mask)
+{
+  __insn_mtspr(SPR_SIM_CONTROL, SIM_PROFILER_CHIP_DISABLE_SPR_ARG(mask));
+}
+
+
+/**
+ * Reset specified chip-level profiling counters to zero.
+ *
+ * Does not affect the per-task profiling counters.
+ *
+ * @param mask Either this special value:
+ *
+ * SIM_CHIP_ALL (clears all chip-level components).
+ *
+ * or the bitwise OR of these values:
+ *
+ * SIM_CHIP_MEMCTL (clear all memory controllers)
+ * SIM_CHIP_XAUI (clear all XAUI controllers)
+ * SIM_CHIP_MPIPE (clear all MPIPE controllers)
+ */
+static __inline void
+sim_profiler_chip_clear(unsigned int mask)
+{
+  __insn_mtspr(SPR_SIM_CONTROL, SIM_PROFILER_CHIP_CLEAR_SPR_ARG(mask));
+}
+
+
+/*
+ * Event support.
+ */
+
+#ifndef __DOXYGEN__
+
+static __inline void
+sim_event_begin(unsigned int x)
+{
+#if defined(__tile__) && !defined(__NO_EVENT_SPR__)
+  __insn_mtspr(SPR_EVENT_BEGIN, x);
+#endif
+}
+
+static __inline void
+sim_event_end(unsigned int x)
+{
+#if defined(__tile__) && !defined(__NO_EVENT_SPR__)
+  __insn_mtspr(SPR_EVENT_END, x);
+#endif
+}
+
+#endif /* !__DOXYGEN__ */
+
+#endif /* !__ASSEMBLER__ */
+
+#endif /* !__ARCH_SIM_H__ */
+
+/** @} */
diff --git a/arch/tile/include/arch/sim_def.h b/arch/tile/include/arch/sim_def.h
index 6418fbd..7a17082 100644
--- a/arch/tile/include/arch/sim_def.h
+++ b/arch/tile/include/arch/sim_def.h
@@ -1,477 +1,461 @@
-// Copyright 2010 Tilera Corporation. All Rights Reserved.
-//
-//   This program is free software; you can redistribute it and/or
-//   modify it under the terms of the GNU General Public License
-//   as published by the Free Software Foundation, version 2.
-//
-//   This program is distributed in the hope that it will be useful, but
-//   WITHOUT ANY WARRANTY; without even the implied warranty of
-//   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
-//   NON INFRINGEMENT.  See the GNU General Public License for
-//   more details.
+/*
+ * Copyright 2010 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
 
-//! @file
-//!
-//! Some low-level simulator definitions.
-//!
+/**
+ * @file
+ *
+ * Some low-level simulator definitions.
+ */
 
 #ifndef __ARCH_SIM_DEF_H__
 #define __ARCH_SIM_DEF_H__
 
 
-//! Internal: the low bits of the SIM_CONTROL_* SPR values specify
-//! the operation to perform, and the remaining bits are
-//! an operation-specific parameter (often unused).
-//!
+/**
+ * Internal: the low bits of the SIM_CONTROL_* SPR values specify
+ * the operation to perform, and the remaining bits are
+ * an operation-specific parameter (often unused).
+ */
 #define _SIM_CONTROL_OPERATOR_BITS 8
 
 
-//== Values which can be written to SPR_SIM_CONTROL.
+/*
+ * Values which can be written to SPR_SIM_CONTROL.
+ */
 
-//! If written to SPR_SIM_CONTROL, stops profiling.
-//!
+/** If written to SPR_SIM_CONTROL, stops profiling. */
 #define SIM_CONTROL_PROFILER_DISABLE 0
 
-//! If written to SPR_SIM_CONTROL, starts profiling.
-//!
+/** If written to SPR_SIM_CONTROL, starts profiling. */
 #define SIM_CONTROL_PROFILER_ENABLE 1
 
-//! If written to SPR_SIM_CONTROL, clears profiling counters.
-//!
+/** If written to SPR_SIM_CONTROL, clears profiling counters. */
 #define SIM_CONTROL_PROFILER_CLEAR 2
 
-//! If written to SPR_SIM_CONTROL, checkpoints the simulator.
-//!
+/** If written to SPR_SIM_CONTROL, checkpoints the simulator. */
 #define SIM_CONTROL_CHECKPOINT 3
 
-//! If written to SPR_SIM_CONTROL, combined with a mask (shifted by 8),
-//! sets the tracing mask to the given mask. See "sim_set_tracing()".
-//!
+/**
+ * If written to SPR_SIM_CONTROL, combined with a mask (shifted by 8),
+ * sets the tracing mask to the given mask. See "sim_set_tracing()".
+ */
 #define SIM_CONTROL_SET_TRACING 4
 
-//! If written to SPR_SIM_CONTROL, combined with a mask (shifted by 8),
-//! dumps the requested items of machine state to the log.
-//!
+/**
+ * If written to SPR_SIM_CONTROL, combined with a mask (shifted by 8),
+ * dumps the requested items of machine state to the log.
+ */
 #define SIM_CONTROL_DUMP 5
 
-//! If written to SPR_SIM_CONTROL, clears chip-level profiling counters.
-//!
+/** If written to SPR_SIM_CONTROL, clears chip-level profiling counters. */
 #define SIM_CONTROL_PROFILER_CHIP_CLEAR 6
 
-//! If written to SPR_SIM_CONTROL, disables chip-level profiling.
-//!
+/** If written to SPR_SIM_CONTROL, disables chip-level profiling. */
 #define SIM_CONTROL_PROFILER_CHIP_DISABLE 7
 
-//! If written to SPR_SIM_CONTROL, enables chip-level profiling.
-//!
+/** If written to SPR_SIM_CONTROL, enables chip-level profiling. */
 #define SIM_CONTROL_PROFILER_CHIP_ENABLE 8
 
-//! If written to SPR_SIM_CONTROL, enables chip-level functional mode
-//!
+/** If written to SPR_SIM_CONTROL, enables chip-level functional mode */
 #define SIM_CONTROL_ENABLE_FUNCTIONAL 9
 
-//! If written to SPR_SIM_CONTROL, disables chip-level functional mode.
-//!
+/** If written to SPR_SIM_CONTROL, disables chip-level functional mode. */
 #define SIM_CONTROL_DISABLE_FUNCTIONAL 10
 
-//! If written to SPR_SIM_CONTROL, enables chip-level functional mode.
-//! All tiles must perform this write for functional mode to be enabled.
-//! Ignored in naked boot mode unless --functional is specified.
-//! WARNING: Only the hypervisor startup code should use this!
-//!
+/**
+ * If written to SPR_SIM_CONTROL, enables chip-level functional mode.
+ * All tiles must perform this write for functional mode to be enabled.
+ * Ignored in naked boot mode unless --functional is specified.
+ * WARNING: Only the hypervisor startup code should use this!
+ */
 #define SIM_CONTROL_ENABLE_FUNCTIONAL_BARRIER 11
 
-//! If written to SPR_SIM_CONTROL, combined with a character (shifted by 8),
-//! writes a string directly to the simulator output.  Written to once for
-//! each character in the string, plus a final NUL.  Instead of NUL,
-//! you can also use "SIM_PUTC_FLUSH_STRING" or "SIM_PUTC_FLUSH_BINARY".
-//!
-// ISSUE: Document the meaning of "newline", and the handling of NUL.
-//
+/**
+ * If written to SPR_SIM_CONTROL, combined with a character (shifted by 8),
+ * writes a string directly to the simulator output.  Written to once for
+ * each character in the string, plus a final NUL.  Instead of NUL,
+ * you can also use "SIM_PUTC_FLUSH_STRING" or "SIM_PUTC_FLUSH_BINARY".
+ */
+/* ISSUE: Document the meaning of "newline", and the handling of NUL. */
 #define SIM_CONTROL_PUTC 12
 
-//! If written to SPR_SIM_CONTROL, clears the --grind-coherence state for
-//! this core.  This is intended to be used before a loop that will
-//! invalidate the cache by loading new data and evicting all current data.
-//! Generally speaking, this API should only be used by system code.
-//!
+/**
+ * If written to SPR_SIM_CONTROL, clears the --grind-coherence state for
+ * this core.  This is intended to be used before a loop that will
+ * invalidate the cache by loading new data and evicting all current data.
+ * Generally speaking, this API should only be used by system code.
+ */
 #define SIM_CONTROL_GRINDER_CLEAR 13
 
-//! If written to SPR_SIM_CONTROL, shuts down the simulator.
-//!
+/** If written to SPR_SIM_CONTROL, shuts down the simulator. */
 #define SIM_CONTROL_SHUTDOWN 14
 
-//! If written to SPR_SIM_CONTROL, combined with a pid (shifted by 8),
-//! indicates that a fork syscall just created the given process.
-//!
+/**
+ * If written to SPR_SIM_CONTROL, combined with a pid (shifted by 8),
+ * indicates that a fork syscall just created the given process.
+ */
 #define SIM_CONTROL_OS_FORK 15
 
-//! If written to SPR_SIM_CONTROL, combined with a pid (shifted by 8),
-//! indicates that an exit syscall was just executed by the given process.
-//!
+/**
+ * If written to SPR_SIM_CONTROL, combined with a pid (shifted by 8),
+ * indicates that an exit syscall was just executed by the given process.
+ */
 #define SIM_CONTROL_OS_EXIT 16
 
-//! If written to SPR_SIM_CONTROL, combined with a pid (shifted by 8),
-//! indicates that the OS just switched to the given process.
-//!
+/**
+ * If written to SPR_SIM_CONTROL, combined with a pid (shifted by 8),
+ * indicates that the OS just switched to the given process.
+ */
 #define SIM_CONTROL_OS_SWITCH 17
 
-//! If written to SPR_SIM_CONTROL, combined with a character (shifted by 8),
-//! indicates that an exec syscall was just executed. Written to once for
-//! each character in the executable name, plus a final NUL.
-//!
+/**
+ * If written to SPR_SIM_CONTROL, combined with a character (shifted by 8),
+ * indicates that an exec syscall was just executed. Written to once for
+ * each character in the executable name, plus a final NUL.
+ */
 #define SIM_CONTROL_OS_EXEC 18
 
-//! If written to SPR_SIM_CONTROL, combined with a character (shifted by 8),
-//! indicates that an interpreter (PT_INTERP) was loaded.  Written to once
-//! for each character in "ADDR:PATH", plus a final NUL, where "ADDR" is a
-//! hex load address starting with "0x", and "PATH" is the executable name.
-//!
+/**
+ * If written to SPR_SIM_CONTROL, combined with a character (shifted by 8),
+ * indicates that an interpreter (PT_INTERP) was loaded.  Written to once
+ * for each character in "ADDR:PATH", plus a final NUL, where "ADDR" is a
+ * hex load address starting with "0x", and "PATH" is the executable name.
+ */
 #define SIM_CONTROL_OS_INTERP 19
 
-//! If written to SPR_SIM_CONTROL, combined with a character (shifted by 8),
-//! indicates that a dll was loaded.  Written to once for each character
-//! in "ADDR:PATH", plus a final NUL, where "ADDR" is a hexadecimal load
-//! address starting with "0x", and "PATH" is the executable name.
-//!
+/**
+ * If written to SPR_SIM_CONTROL, combined with a character (shifted by 8),
+ * indicates that a dll was loaded.  Written to once for each character
+ * in "ADDR:PATH", plus a final NUL, where "ADDR" is a hexadecimal load
+ * address starting with "0x", and "PATH" is the executable name.
+ */
 #define SIM_CONTROL_DLOPEN 20
 
-//! If written to SPR_SIM_CONTROL, combined with a character (shifted by 8),
-//! indicates that a dll was unloaded.  Written to once for each character
-//! in "ADDR", plus a final NUL, where "ADDR" is a hexadecimal load
-//! address starting with "0x".
-//!
+/**
+ * If written to SPR_SIM_CONTROL, combined with a character (shifted by 8),
+ * indicates that a dll was unloaded.  Written to once for each character
+ * in "ADDR", plus a final NUL, where "ADDR" is a hexadecimal load
+ * address starting with "0x".
+ */
 #define SIM_CONTROL_DLCLOSE 21
 
-//! If written to SPR_SIM_CONTROL, combined with a flag (shifted by 8),
-//! indicates whether to allow data reads to remotely-cached
-//! dirty cache lines to be cached locally without grinder warnings or
-//! assertions (used by Linux kernel fast memcpy).
-//!
+/**
+ * If written to SPR_SIM_CONTROL, combined with a flag (shifted by 8),
+ * indicates whether to allow data reads to remotely-cached
+ * dirty cache lines to be cached locally without grinder warnings or
+ * assertions (used by Linux kernel fast memcpy).
+ */
 #define SIM_CONTROL_ALLOW_MULTIPLE_CACHING 22
 
-//! If written to SPR_SIM_CONTROL, enables memory tracing.
-//!
+/** If written to SPR_SIM_CONTROL, enables memory tracing. */
 #define SIM_CONTROL_ENABLE_MEM_LOGGING 23
 
-//! If written to SPR_SIM_CONTROL, disables memory tracing.
-//!
+/** If written to SPR_SIM_CONTROL, disables memory tracing. */
 #define SIM_CONTROL_DISABLE_MEM_LOGGING 24
 
-//! If written to SPR_SIM_CONTROL, changes the shaping parameters of one of
-//! the gbe or xgbe shims. Must specify the shim id, the type, the units, and
-//! the rate, as defined in SIM_SHAPING_SPR_ARG.
-//!
+/**
+ * If written to SPR_SIM_CONTROL, changes the shaping parameters of one of
+ * the gbe or xgbe shims. Must specify the shim id, the type, the units, and
+ * the rate, as defined in SIM_SHAPING_SPR_ARG.
+ */
 #define SIM_CONTROL_SHAPING 25
 
-//! If written to SPR_SIM_CONTROL, combined with character (shifted by 8),
-//! requests that a simulator command be executed.  Written to once for each
-//! character in the command, plus a final NUL.
-//!
+/**
+ * If written to SPR_SIM_CONTROL, combined with character (shifted by 8),
+ * requests that a simulator command be executed.  Written to once for each
+ * character in the command, plus a final NUL.
+ */
 #define SIM_CONTROL_COMMAND 26
 
-//! If written to SPR_SIM_CONTROL, indicates that the simulated system
-//! is panicking, to allow debugging via --debug-on-panic.
-//!
+/**
+ * If written to SPR_SIM_CONTROL, indicates that the simulated system
+ * is panicking, to allow debugging via --debug-on-panic.
+ */
 #define SIM_CONTROL_PANIC 27
 
-//! If written to SPR_SIM_CONTROL, triggers a simulator syscall.
-//! See "sim_syscall()" for more info.
-//!
+/**
+ * If written to SPR_SIM_CONTROL, triggers a simulator syscall.
+ * See "sim_syscall()" for more info.
+ */
 #define SIM_CONTROL_SYSCALL 32
 
-//! If written to SPR_SIM_CONTROL, combined with a pid (shifted by 8),
-//! provides the pid that subsequent SIM_CONTROL_OS_FORK writes should
-//! use as the pid, rather than the default previous SIM_CONTROL_OS_SWITCH.
-//!
+/**
+ * If written to SPR_SIM_CONTROL, combined with a pid (shifted by 8),
+ * provides the pid that subsequent SIM_CONTROL_OS_FORK writes should
+ * use as the pid, rather than the default previous SIM_CONTROL_OS_SWITCH.
+ */
 #define SIM_CONTROL_OS_FORK_PARENT 33
 
-//! If written to SPR_SIM_CONTROL, combined with a mPIPE shim number
-//! (shifted by 8), clears the pending magic data section.  The cleared
-//! pending magic data section and any subsequently appended magic bytes
-//! will only take effect when the classifier blast programmer is run.
+/**
+ * If written to SPR_SIM_CONTROL, combined with a mPIPE shim number
+ * (shifted by 8), clears the pending magic data section.  The cleared
+ * pending magic data section and any subsequently appended magic bytes
+ * will only take effect when the classifier blast programmer is run.
+ */
 #define SIM_CONTROL_CLEAR_MPIPE_MAGIC_BYTES 34
 
-//! If written to SPR_SIM_CONTROL, combined with a mPIPE shim number
-//! (shifted by 8) and a byte of data (shifted by 16), appends that byte
-//! to the shim's pending magic data section.  The pending magic data
-//! section takes effect when the classifier blast programmer is run.
+/**
+ * If written to SPR_SIM_CONTROL, combined with a mPIPE shim number
+ * (shifted by 8) and a byte of data (shifted by 16), appends that byte
+ * to the shim's pending magic data section.  The pending magic data
+ * section takes effect when the classifier blast programmer is run.
+ */
 #define SIM_CONTROL_APPEND_MPIPE_MAGIC_BYTE 35
 
-//! If written to SPR_SIM_CONTROL, combined with a mPIPE shim number
-//! (shifted by 8), an enable=1/disable=0 bit (shifted by 16), and a
-//! mask of links (shifted by 32), enable or disable the corresponding
-//! mPIPE links.
+/**
+ * If written to SPR_SIM_CONTROL, combined with a mPIPE shim number
+ * (shifted by 8), an enable=1/disable=0 bit (shifted by 16), and a
+ * mask of links (shifted by 32), enable or disable the corresponding
+ * mPIPE links.
+ */
 #define SIM_CONTROL_ENABLE_MPIPE_LINK_MAGIC_BYTE 36
 
-//== Syscall numbers for use with "sim_syscall()".
 
-//! Syscall number for sim_add_watchpoint().
-//!
+/*
+ * Syscall numbers for use with "sim_syscall()".
+ */
+
+/** Syscall number for sim_add_watchpoint(). */
 #define SIM_SYSCALL_ADD_WATCHPOINT 2
 
-//! Syscall number for sim_remove_watchpoint().
-//!
+/** Syscall number for sim_remove_watchpoint(). */
 #define SIM_SYSCALL_REMOVE_WATCHPOINT 3
 
-//! Syscall number for sim_query_watchpoint().
-//!
+/** Syscall number for sim_query_watchpoint(). */
 #define SIM_SYSCALL_QUERY_WATCHPOINT 4
 
-//! Syscall number that asserts that the cache lines whose 64-bit PA
-//! is passed as the second argument to sim_syscall(), and over a
-//! range passed as the third argument, are no longer in cache.
-//! The simulator raises an error if this is not the case.
-//!
+/**
+ * Syscall number that asserts that the cache lines whose 64-bit PA
+ * is passed as the second argument to sim_syscall(), and over a
+ * range passed as the third argument, are no longer in cache.
+ * The simulator raises an error if this is not the case.
+ */
 #define SIM_SYSCALL_VALIDATE_LINES_EVICTED 5
 
 
-//== Bit masks which can be shifted by 8, combined with
-//== SIM_CONTROL_SET_TRACING, and written to SPR_SIM_CONTROL.
+/*
+ * Bit masks which can be shifted by 8, combined with
+ * SIM_CONTROL_SET_TRACING, and written to SPR_SIM_CONTROL.
+ */
 
-//! @addtogroup arch_sim
-//! @{
+/**
+ * @addtogroup arch_sim
+ * @{
+ */
 
-//! Enable --trace-cycle when passed to simulator_set_tracing().
-//!
+/** Enable --trace-cycle when passed to simulator_set_tracing(). */
 #define SIM_TRACE_CYCLES          0x01
 
-//! Enable --trace-router when passed to simulator_set_tracing().
-//!
+/** Enable --trace-router when passed to simulator_set_tracing(). */
 #define SIM_TRACE_ROUTER          0x02
 
-//! Enable --trace-register-writes when passed to simulator_set_tracing().
-//!
+/** Enable --trace-register-writes when passed to simulator_set_tracing(). */
 #define SIM_TRACE_REGISTER_WRITES 0x04
 
-//! Enable --trace-disasm when passed to simulator_set_tracing().
-//!
+/** Enable --trace-disasm when passed to simulator_set_tracing(). */
 #define SIM_TRACE_DISASM          0x08
 
-//! Enable --trace-stall-info when passed to simulator_set_tracing().
-//!
+/** Enable --trace-stall-info when passed to simulator_set_tracing(). */
 #define SIM_TRACE_STALL_INFO      0x10
 
-//! Enable --trace-memory-controller when passed to simulator_set_tracing().
-//!
+/** Enable --trace-memory-controller when passed to simulator_set_tracing(). */
 #define SIM_TRACE_MEMORY_CONTROLLER 0x20
 
-//! Enable --trace-l2 when passed to simulator_set_tracing().
-//!
+/** Enable --trace-l2 when passed to simulator_set_tracing(). */
 #define SIM_TRACE_L2_CACHE 0x40
 
-//! Enable --trace-lines when passed to simulator_set_tracing().
-//!
+/** Enable --trace-lines when passed to simulator_set_tracing(). */
 #define SIM_TRACE_LINES 0x80
 
-//! Turn off all tracing when passed to simulator_set_tracing().
-//!
+/** Turn off all tracing when passed to simulator_set_tracing(). */
 #define SIM_TRACE_NONE 0
 
-//! Turn on all tracing when passed to simulator_set_tracing().
-//!
+/** Turn on all tracing when passed to simulator_set_tracing(). */
 #define SIM_TRACE_ALL (-1)
 
-//! @}
+/** @} */
 
-//! Computes the value to write to SPR_SIM_CONTROL to set tracing flags.
-//!
+/** Computes the value to write to SPR_SIM_CONTROL to set tracing flags. */
 #define SIM_TRACE_SPR_ARG(mask) \
   (SIM_CONTROL_SET_TRACING | ((mask) << _SIM_CONTROL_OPERATOR_BITS))
 
 
-//== Bit masks which can be shifted by 8, combined with
-//== SIM_CONTROL_DUMP, and written to SPR_SIM_CONTROL.
+/*
+ * Bit masks which can be shifted by 8, combined with
+ * SIM_CONTROL_DUMP, and written to SPR_SIM_CONTROL.
+ */
 
-//! @addtogroup arch_sim
-//! @{
+/**
+ * @addtogroup arch_sim
+ * @{
+ */
 
-//! Dump the general-purpose registers.
-//!
+/** Dump the general-purpose registers. */
 #define SIM_DUMP_REGS          0x001
 
-//! Dump the SPRs.
-//!
+/** Dump the SPRs. */
 #define SIM_DUMP_SPRS          0x002
 
-//! Dump the ITLB.
-//!
+/** Dump the ITLB. */
 #define SIM_DUMP_ITLB          0x004
 
-//! Dump the DTLB.
-//!
+/** Dump the DTLB. */
 #define SIM_DUMP_DTLB          0x008
 
-//! Dump the L1 I-cache.
-//!
+/** Dump the L1 I-cache. */
 #define SIM_DUMP_L1I           0x010
 
-//! Dump the L1 D-cache.
-//!
+/** Dump the L1 D-cache. */
 #define SIM_DUMP_L1D           0x020
 
-//! Dump the L2 cache.
-//!
+/** Dump the L2 cache. */
 #define SIM_DUMP_L2            0x040
 
-//! Dump the switch registers.
-//!
+/** Dump the switch registers. */
 #define SIM_DUMP_SNREGS        0x080
 
-//! Dump the switch ITLB.
-//!
+/** Dump the switch ITLB. */
 #define SIM_DUMP_SNITLB        0x100
 
-//! Dump the switch L1 I-cache.
-//!
+/** Dump the switch L1 I-cache. */
 #define SIM_DUMP_SNL1I         0x200
 
-//! Dump the current backtrace.
-//!
+/** Dump the current backtrace. */
 #define SIM_DUMP_BACKTRACE     0x400
 
-//! Only dump valid lines in caches.
-//!
+/** Only dump valid lines in caches. */
 #define SIM_DUMP_VALID_LINES   0x800
 
-//! Dump everything that is dumpable.
-//!
+/** Dump everything that is dumpable. */
 #define SIM_DUMP_ALL (-1 & ~SIM_DUMP_VALID_LINES)
 
-// @}
+/** @} */
 
-//! Computes the value to write to SPR_SIM_CONTROL to dump machine state.
-//!
+/** Computes the value to write to SPR_SIM_CONTROL to dump machine state. */
 #define SIM_DUMP_SPR_ARG(mask) \
   (SIM_CONTROL_DUMP | ((mask) << _SIM_CONTROL_OPERATOR_BITS))
 
 
-//== Bit masks which can be shifted by 8, combined with
-//== SIM_CONTROL_PROFILER_CHIP_xxx, and written to SPR_SIM_CONTROL.
+/*
+ * Bit masks which can be shifted by 8, combined with
+ * SIM_CONTROL_PROFILER_CHIP_xxx, and written to SPR_SIM_CONTROL.
+ */
 
-//! @addtogroup arch_sim
-//! @{
+/**
+ * @addtogroup arch_sim
+ * @{
+ */
 
-//! Use with with SIM_PROFILER_CHIP_xxx to control the memory controllers.
-//!
+/** Use with with SIM_PROFILER_CHIP_xxx to control the memory controllers. */
 #define SIM_CHIP_MEMCTL        0x001
 
-//! Use with with SIM_PROFILER_CHIP_xxx to control the XAUI interface.
-//!
+/** Use with with SIM_PROFILER_CHIP_xxx to control the XAUI interface. */
 #define SIM_CHIP_XAUI          0x002
 
-//! Use with with SIM_PROFILER_CHIP_xxx to control the PCIe interface.
-//!
+/** Use with with SIM_PROFILER_CHIP_xxx to control the PCIe interface. */
 #define SIM_CHIP_PCIE          0x004
 
-//! Use with with SIM_PROFILER_CHIP_xxx to control the MPIPE interface.
-//!
+/** Use with with SIM_PROFILER_CHIP_xxx to control the MPIPE interface. */
 #define SIM_CHIP_MPIPE         0x008
 
-//! Reference all chip devices.
-//!
+/** Use with with SIM_PROFILER_CHIP_xxx to control the TRIO interface. */
+#define SIM_CHIP_TRIO          0x010
+
+/** Reference all chip devices. */
 #define SIM_CHIP_ALL (-1)
 
-//! @}
+/** @} */
 
-//! Computes the value to write to SPR_SIM_CONTROL to clear chip statistics.
-//!
+/** Computes the value to write to SPR_SIM_CONTROL to clear chip statistics. */
 #define SIM_PROFILER_CHIP_CLEAR_SPR_ARG(mask) \
   (SIM_CONTROL_PROFILER_CHIP_CLEAR | ((mask) << _SIM_CONTROL_OPERATOR_BITS))
 
-//! Computes the value to write to SPR_SIM_CONTROL to disable chip statistics.
-//!
+/** Computes the value to write to SPR_SIM_CONTROL to disable chip statistics.*/
 #define SIM_PROFILER_CHIP_DISABLE_SPR_ARG(mask) \
   (SIM_CONTROL_PROFILER_CHIP_DISABLE | ((mask) << _SIM_CONTROL_OPERATOR_BITS))
 
-//! Computes the value to write to SPR_SIM_CONTROL to enable chip statistics.
-//!
+/** Computes the value to write to SPR_SIM_CONTROL to enable chip statistics. */
 #define SIM_PROFILER_CHIP_ENABLE_SPR_ARG(mask) \
   (SIM_CONTROL_PROFILER_CHIP_ENABLE | ((mask) << _SIM_CONTROL_OPERATOR_BITS))
 
 
 
-// Shim bitrate controls.
+/* Shim bitrate controls. */
 
-//! The number of bits used to store the shim id.
-//!
+/** The number of bits used to store the shim id. */
 #define SIM_CONTROL_SHAPING_SHIM_ID_BITS 3
 
-//! @addtogroup arch_sim
-//! @{
+/**
+ * @addtogroup arch_sim
+ * @{
+ */
 
-//! Change the gbe 0 bitrate.
-//!
+/** Change the gbe 0 bitrate. */
 #define SIM_CONTROL_SHAPING_GBE_0 0x0
 
-//! Change the gbe 1 bitrate.
-//!
+/** Change the gbe 1 bitrate. */
 #define SIM_CONTROL_SHAPING_GBE_1 0x1
 
-//! Change the gbe 2 bitrate.
-//!
+/** Change the gbe 2 bitrate. */
 #define SIM_CONTROL_SHAPING_GBE_2 0x2
 
-//! Change the gbe 3 bitrate.
-//!
+/** Change the gbe 3 bitrate. */
 #define SIM_CONTROL_SHAPING_GBE_3 0x3
 
-//! Change the xgbe 0 bitrate.
-//!
+/** Change the xgbe 0 bitrate. */
 #define SIM_CONTROL_SHAPING_XGBE_0 0x4
 
-//! Change the xgbe 1 bitrate.
-//!
+/** Change the xgbe 1 bitrate. */
 #define SIM_CONTROL_SHAPING_XGBE_1 0x5
 
-//! The type of shaping to do.
-//!
+/** The type of shaping to do. */
 #define SIM_CONTROL_SHAPING_TYPE_BITS 2
 
-//! Control the multiplier.
-//!
+/** Control the multiplier. */
 #define SIM_CONTROL_SHAPING_MULTIPLIER 0
 
-//! Control the PPS.
-//!
+/** Control the PPS. */
 #define SIM_CONTROL_SHAPING_PPS 1
 
-//! Control the BPS.
-//!
+/** Control the BPS. */
 #define SIM_CONTROL_SHAPING_BPS 2
 
-//! The number of bits for the units for the shaping parameter.
-//!
+/** The number of bits for the units for the shaping parameter. */
 #define SIM_CONTROL_SHAPING_UNITS_BITS 2
 
-//! Provide a number in single units.
-//!
+/** Provide a number in single units. */
 #define SIM_CONTROL_SHAPING_UNITS_SINGLE 0
 
-//! Provide a number in kilo units.
-//!
+/** Provide a number in kilo units. */
 #define SIM_CONTROL_SHAPING_UNITS_KILO 1
 
-//! Provide a number in mega units.
-//!
+/** Provide a number in mega units. */
 #define SIM_CONTROL_SHAPING_UNITS_MEGA 2
 
-//! Provide a number in giga units.
-//!
+/** Provide a number in giga units. */
 #define SIM_CONTROL_SHAPING_UNITS_GIGA 3
 
-// @}
+/** @} */
 
-//! How many bits are available for the rate.
-//!
+/** How many bits are available for the rate. */
 #define SIM_CONTROL_SHAPING_RATE_BITS \
   (32 - (_SIM_CONTROL_OPERATOR_BITS + \
          SIM_CONTROL_SHAPING_SHIM_ID_BITS + \
          SIM_CONTROL_SHAPING_TYPE_BITS + \
          SIM_CONTROL_SHAPING_UNITS_BITS))
 
-//! Computes the value to write to SPR_SIM_CONTROL to change a bitrate.
-//!
+/** Computes the value to write to SPR_SIM_CONTROL to change a bitrate. */
 #define SIM_SHAPING_SPR_ARG(shim, type, units, rate) \
   (SIM_CONTROL_SHAPING | \
    ((shim) | \
@@ -483,30 +467,36 @@
                SIM_CONTROL_SHAPING_UNITS_BITS))) << _SIM_CONTROL_OPERATOR_BITS)
 
 
-//== Values returned when reading SPR_SIM_CONTROL.
-// ISSUE: These names should share a longer common prefix.
+/*
+ * Values returned when reading SPR_SIM_CONTROL.
+ * ISSUE: These names should share a longer common prefix.
+ */
 
-//! When reading SPR_SIM_CONTROL, the mask of simulator tracing bits
-//! (SIM_TRACE_xxx values).
-//!
+/**
+ * When reading SPR_SIM_CONTROL, the mask of simulator tracing bits
+ * (SIM_TRACE_xxx values).
+ */
 #define SIM_TRACE_FLAG_MASK 0xFFFF
 
-//! When reading SPR_SIM_CONTROL, the mask for whether profiling is enabled.
-//!
+/** When reading SPR_SIM_CONTROL, the mask for whether profiling is enabled. */
 #define SIM_PROFILER_ENABLED_MASK 0x10000
 
 
-//== Special arguments for "SIM_CONTROL_PUTC".
+/*
+ * Special arguments for "SIM_CONTROL_PUTC".
+ */
 
-//! Flag value for forcing a PUTC string-flush, including
-//! coordinate/cycle prefix and newline.
-//!
+/**
+ * Flag value for forcing a PUTC string-flush, including
+ * coordinate/cycle prefix and newline.
+ */
 #define SIM_PUTC_FLUSH_STRING 0x100
 
-//! Flag value for forcing a PUTC binary-data-flush, which skips the
-//! prefix and does not append a newline.
-//!
+/**
+ * Flag value for forcing a PUTC binary-data-flush, which skips the
+ * prefix and does not append a newline.
+ */
 #define SIM_PUTC_FLUSH_BINARY 0x101
 
 
-#endif //__ARCH_SIM_DEF_H__
+#endif /* __ARCH_SIM_DEF_H__ */
diff --git a/arch/tile/include/arch/spr_def.h b/arch/tile/include/arch/spr_def.h
index c8fdbd9..442fcba 100644
--- a/arch/tile/include/arch/spr_def.h
+++ b/arch/tile/include/arch/spr_def.h
@@ -12,8 +12,93 @@
  *   more details.
  */
 
+/*
+ * In addition to including the proper base SPR definition file, depending
+ * on machine architecture, this file defines several macros which allow
+ * kernel code to use protection-level dependent SPRs without worrying
+ * about which PL it's running at.  In these macros, the PL that the SPR
+ * or interrupt number applies to is replaced by K.
+ */
+
+#if CONFIG_KERNEL_PL != 1 && CONFIG_KERNEL_PL != 2
+#error CONFIG_KERNEL_PL must be 1 or 2
+#endif
+
+/* Concatenate 4 strings. */
+#define __concat4(a, b, c, d) a ## b ## c ## d
+#define _concat4(a, b, c, d)  __concat4(a, b, c, d)
+
 #ifdef __tilegx__
 #include <arch/spr_def_64.h>
+
+/* TILE-Gx dependent, protection-level dependent SPRs. */
+
+#define SPR_INTERRUPT_MASK_K \
+	_concat4(SPR_INTERRUPT_MASK_, CONFIG_KERNEL_PL,,)
+#define SPR_INTERRUPT_MASK_SET_K \
+	_concat4(SPR_INTERRUPT_MASK_SET_, CONFIG_KERNEL_PL,,)
+#define SPR_INTERRUPT_MASK_RESET_K \
+	_concat4(SPR_INTERRUPT_MASK_RESET_, CONFIG_KERNEL_PL,,)
+#define SPR_INTERRUPT_VECTOR_BASE_K \
+	_concat4(SPR_INTERRUPT_VECTOR_BASE_, CONFIG_KERNEL_PL,,)
+
+#define SPR_IPI_MASK_K \
+	_concat4(SPR_IPI_MASK_, CONFIG_KERNEL_PL,,)
+#define SPR_IPI_MASK_RESET_K \
+	_concat4(SPR_IPI_MASK_RESET_, CONFIG_KERNEL_PL,,)
+#define SPR_IPI_MASK_SET_K \
+	_concat4(SPR_IPI_MASK_SET_, CONFIG_KERNEL_PL,,)
+#define SPR_IPI_EVENT_K \
+	_concat4(SPR_IPI_EVENT_, CONFIG_KERNEL_PL,,)
+#define SPR_IPI_EVENT_RESET_K \
+	_concat4(SPR_IPI_EVENT_RESET_, CONFIG_KERNEL_PL,,)
+#define SPR_IPI_MASK_SET_K \
+	_concat4(SPR_IPI_MASK_SET_, CONFIG_KERNEL_PL,,)
+#define INT_IPI_K \
+	_concat4(INT_IPI_, CONFIG_KERNEL_PL,,)
+
+#define SPR_SINGLE_STEP_CONTROL_K \
+	_concat4(SPR_SINGLE_STEP_CONTROL_, CONFIG_KERNEL_PL,,)
+#define SPR_SINGLE_STEP_EN_K_K \
+	_concat4(SPR_SINGLE_STEP_EN_, CONFIG_KERNEL_PL, _, CONFIG_KERNEL_PL)
+#define INT_SINGLE_STEP_K \
+	_concat4(INT_SINGLE_STEP_, CONFIG_KERNEL_PL,,)
+
 #else
 #include <arch/spr_def_32.h>
+
+/* TILEPro dependent, protection-level dependent SPRs. */
+
+#define SPR_INTERRUPT_MASK_K_0 \
+	_concat4(SPR_INTERRUPT_MASK_, CONFIG_KERNEL_PL, _0,)
+#define SPR_INTERRUPT_MASK_K_1 \
+	_concat4(SPR_INTERRUPT_MASK_, CONFIG_KERNEL_PL, _1,)
+#define SPR_INTERRUPT_MASK_SET_K_0 \
+	_concat4(SPR_INTERRUPT_MASK_SET_, CONFIG_KERNEL_PL, _0,)
+#define SPR_INTERRUPT_MASK_SET_K_1 \
+	_concat4(SPR_INTERRUPT_MASK_SET_, CONFIG_KERNEL_PL, _1,)
+#define SPR_INTERRUPT_MASK_RESET_K_0 \
+	_concat4(SPR_INTERRUPT_MASK_RESET_, CONFIG_KERNEL_PL, _0,)
+#define SPR_INTERRUPT_MASK_RESET_K_1 \
+	_concat4(SPR_INTERRUPT_MASK_RESET_, CONFIG_KERNEL_PL, _1,)
+
 #endif
+
+/* Generic protection-level dependent SPRs. */
+
+#define SPR_SYSTEM_SAVE_K_0 \
+	_concat4(SPR_SYSTEM_SAVE_, CONFIG_KERNEL_PL, _0,)
+#define SPR_SYSTEM_SAVE_K_1 \
+	_concat4(SPR_SYSTEM_SAVE_, CONFIG_KERNEL_PL, _1,)
+#define SPR_SYSTEM_SAVE_K_2 \
+	_concat4(SPR_SYSTEM_SAVE_, CONFIG_KERNEL_PL, _2,)
+#define SPR_SYSTEM_SAVE_K_3 \
+	_concat4(SPR_SYSTEM_SAVE_, CONFIG_KERNEL_PL, _3,)
+#define SPR_EX_CONTEXT_K_0 \
+	_concat4(SPR_EX_CONTEXT_, CONFIG_KERNEL_PL, _0,)
+#define SPR_EX_CONTEXT_K_1 \
+	_concat4(SPR_EX_CONTEXT_, CONFIG_KERNEL_PL, _1,)
+#define SPR_INTCTRL_K_STATUS \
+	_concat4(SPR_INTCTRL_, CONFIG_KERNEL_PL, _STATUS,)
+#define INT_INTCTRL_K \
+	_concat4(INT_INTCTRL_, CONFIG_KERNEL_PL,,)
diff --git a/arch/tile/include/arch/spr_def_32.h b/arch/tile/include/arch/spr_def_32.h
index b4fc068..bbc1f4c 100644
--- a/arch/tile/include/arch/spr_def_32.h
+++ b/arch/tile/include/arch/spr_def_32.h
@@ -56,58 +56,93 @@
 #define SPR_EX_CONTEXT_1_1__ICS_SHIFT 2
 #define SPR_EX_CONTEXT_1_1__ICS_RMASK 0x1
 #define SPR_EX_CONTEXT_1_1__ICS_MASK  0x4
+#define SPR_EX_CONTEXT_2_0 0x4605
+#define SPR_EX_CONTEXT_2_1 0x4606
+#define SPR_EX_CONTEXT_2_1__PL_SHIFT 0
+#define SPR_EX_CONTEXT_2_1__PL_RMASK 0x3
+#define SPR_EX_CONTEXT_2_1__PL_MASK  0x3
+#define SPR_EX_CONTEXT_2_1__ICS_SHIFT 2
+#define SPR_EX_CONTEXT_2_1__ICS_RMASK 0x1
+#define SPR_EX_CONTEXT_2_1__ICS_MASK  0x4
 #define SPR_FAIL 0x4e09
 #define SPR_INTCTRL_0_STATUS 0x4a07
 #define SPR_INTCTRL_1_STATUS 0x4807
+#define SPR_INTCTRL_2_STATUS 0x4607
 #define SPR_INTERRUPT_CRITICAL_SECTION 0x4e0a
 #define SPR_INTERRUPT_MASK_0_0 0x4a08
 #define SPR_INTERRUPT_MASK_0_1 0x4a09
 #define SPR_INTERRUPT_MASK_1_0 0x4809
 #define SPR_INTERRUPT_MASK_1_1 0x480a
+#define SPR_INTERRUPT_MASK_2_0 0x4608
+#define SPR_INTERRUPT_MASK_2_1 0x4609
 #define SPR_INTERRUPT_MASK_RESET_0_0 0x4a0a
 #define SPR_INTERRUPT_MASK_RESET_0_1 0x4a0b
 #define SPR_INTERRUPT_MASK_RESET_1_0 0x480b
 #define SPR_INTERRUPT_MASK_RESET_1_1 0x480c
+#define SPR_INTERRUPT_MASK_RESET_2_0 0x460a
+#define SPR_INTERRUPT_MASK_RESET_2_1 0x460b
 #define SPR_INTERRUPT_MASK_SET_0_0 0x4a0c
 #define SPR_INTERRUPT_MASK_SET_0_1 0x4a0d
 #define SPR_INTERRUPT_MASK_SET_1_0 0x480d
 #define SPR_INTERRUPT_MASK_SET_1_1 0x480e
+#define SPR_INTERRUPT_MASK_SET_2_0 0x460c
+#define SPR_INTERRUPT_MASK_SET_2_1 0x460d
 #define SPR_MPL_DMA_CPL_SET_0 0x5800
 #define SPR_MPL_DMA_CPL_SET_1 0x5801
+#define SPR_MPL_DMA_CPL_SET_2 0x5802
 #define SPR_MPL_DMA_NOTIFY_SET_0 0x3800
 #define SPR_MPL_DMA_NOTIFY_SET_1 0x3801
+#define SPR_MPL_DMA_NOTIFY_SET_2 0x3802
 #define SPR_MPL_INTCTRL_0_SET_0 0x4a00
 #define SPR_MPL_INTCTRL_0_SET_1 0x4a01
+#define SPR_MPL_INTCTRL_0_SET_2 0x4a02
 #define SPR_MPL_INTCTRL_1_SET_0 0x4800
 #define SPR_MPL_INTCTRL_1_SET_1 0x4801
+#define SPR_MPL_INTCTRL_1_SET_2 0x4802
+#define SPR_MPL_INTCTRL_2_SET_0 0x4600
+#define SPR_MPL_INTCTRL_2_SET_1 0x4601
+#define SPR_MPL_INTCTRL_2_SET_2 0x4602
 #define SPR_MPL_SN_ACCESS_SET_0 0x0800
 #define SPR_MPL_SN_ACCESS_SET_1 0x0801
+#define SPR_MPL_SN_ACCESS_SET_2 0x0802
 #define SPR_MPL_SN_CPL_SET_0 0x5a00
 #define SPR_MPL_SN_CPL_SET_1 0x5a01
+#define SPR_MPL_SN_CPL_SET_2 0x5a02
 #define SPR_MPL_SN_FIREWALL_SET_0 0x2c00
 #define SPR_MPL_SN_FIREWALL_SET_1 0x2c01
+#define SPR_MPL_SN_FIREWALL_SET_2 0x2c02
 #define SPR_MPL_SN_NOTIFY_SET_0 0x2a00
 #define SPR_MPL_SN_NOTIFY_SET_1 0x2a01
+#define SPR_MPL_SN_NOTIFY_SET_2 0x2a02
 #define SPR_MPL_UDN_ACCESS_SET_0 0x0c00
 #define SPR_MPL_UDN_ACCESS_SET_1 0x0c01
+#define SPR_MPL_UDN_ACCESS_SET_2 0x0c02
 #define SPR_MPL_UDN_AVAIL_SET_0 0x4000
 #define SPR_MPL_UDN_AVAIL_SET_1 0x4001
+#define SPR_MPL_UDN_AVAIL_SET_2 0x4002
 #define SPR_MPL_UDN_CA_SET_0 0x3c00
 #define SPR_MPL_UDN_CA_SET_1 0x3c01
+#define SPR_MPL_UDN_CA_SET_2 0x3c02
 #define SPR_MPL_UDN_COMPLETE_SET_0 0x1400
 #define SPR_MPL_UDN_COMPLETE_SET_1 0x1401
+#define SPR_MPL_UDN_COMPLETE_SET_2 0x1402
 #define SPR_MPL_UDN_FIREWALL_SET_0 0x3000
 #define SPR_MPL_UDN_FIREWALL_SET_1 0x3001
+#define SPR_MPL_UDN_FIREWALL_SET_2 0x3002
 #define SPR_MPL_UDN_REFILL_SET_0 0x1000
 #define SPR_MPL_UDN_REFILL_SET_1 0x1001
+#define SPR_MPL_UDN_REFILL_SET_2 0x1002
 #define SPR_MPL_UDN_TIMER_SET_0 0x3600
 #define SPR_MPL_UDN_TIMER_SET_1 0x3601
+#define SPR_MPL_UDN_TIMER_SET_2 0x3602
 #define SPR_MPL_WORLD_ACCESS_SET_0 0x4e00
 #define SPR_MPL_WORLD_ACCESS_SET_1 0x4e01
+#define SPR_MPL_WORLD_ACCESS_SET_2 0x4e02
 #define SPR_PASS 0x4e0b
 #define SPR_PERF_COUNT_0 0x4205
 #define SPR_PERF_COUNT_1 0x4206
 #define SPR_PERF_COUNT_CTL 0x4207
+#define SPR_PERF_COUNT_DN_CTL 0x4210
 #define SPR_PERF_COUNT_STS 0x4208
 #define SPR_PROC_STATUS 0x4f00
 #define SPR_SIM_CONTROL 0x4e0c
@@ -124,6 +159,10 @@
 #define SPR_SYSTEM_SAVE_1_1 0x4901
 #define SPR_SYSTEM_SAVE_1_2 0x4902
 #define SPR_SYSTEM_SAVE_1_3 0x4903
+#define SPR_SYSTEM_SAVE_2_0 0x4700
+#define SPR_SYSTEM_SAVE_2_1 0x4701
+#define SPR_SYSTEM_SAVE_2_2 0x4702
+#define SPR_SYSTEM_SAVE_2_3 0x4703
 #define SPR_TILE_COORD 0x4c17
 #define SPR_TILE_RTF_HWM 0x4e10
 #define SPR_TILE_TIMER_CONTROL 0x3205
diff --git a/arch/tile/include/asm/backtrace.h b/arch/tile/include/asm/backtrace.h
index 758ca46..f18887d 100644
--- a/arch/tile/include/asm/backtrace.h
+++ b/arch/tile/include/asm/backtrace.h
@@ -146,7 +146,10 @@
 
 	CALLER_SP_IN_R52_BASE = 4,
 
-	CALLER_SP_OFFSET_BASE = 8
+	CALLER_SP_OFFSET_BASE = 8,
+
+	/* Marks the entry point of certain functions. */
+	ENTRY_POINT_INFO_OP = 16
 };
 
 
diff --git a/arch/tile/include/asm/compat.h b/arch/tile/include/asm/compat.h
index 8b60ec8..c3ae570 100644
--- a/arch/tile/include/asm/compat.h
+++ b/arch/tile/include/asm/compat.h
@@ -216,15 +216,16 @@
 struct compat_sigaltstack;
 long compat_sys_execve(const char __user *path,
 		       const compat_uptr_t __user *argv,
-		       const compat_uptr_t __user *envp);
+		       const compat_uptr_t __user *envp, struct pt_regs *);
 long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act,
 			     struct compat_sigaction __user *oact,
 			     size_t sigsetsize);
 long compat_sys_rt_sigqueueinfo(int pid, int sig,
 				struct compat_siginfo __user *uinfo);
-long compat_sys_rt_sigreturn(void);
+long compat_sys_rt_sigreturn(struct pt_regs *);
 long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
-			    struct compat_sigaltstack __user *uoss_ptr);
+			    struct compat_sigaltstack __user *uoss_ptr,
+			    struct pt_regs *);
 long compat_sys_truncate64(char __user *filename, u32 dummy, u32 low, u32 high);
 long compat_sys_ftruncate64(unsigned int fd, u32 dummy, u32 low, u32 high);
 long compat_sys_pread64(unsigned int fd, char __user *ubuf, size_t count,
@@ -255,4 +256,12 @@
 /* Tilera Linux syscalls that don't have "compat" versions. */
 #define compat_sys_flush_cache sys_flush_cache
 
+/* These are the intvec_64.S trampolines. */
+long _compat_sys_execve(const char __user *path,
+			const compat_uptr_t __user *argv,
+			const compat_uptr_t __user *envp);
+long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
+			    struct compat_sigaltstack __user *uoss_ptr);
+long _compat_sys_rt_sigreturn(void);
+
 #endif /* _ASM_TILE_COMPAT_H */
diff --git a/arch/tile/include/asm/highmem.h b/arch/tile/include/asm/highmem.h
index d155db6..e0f7ee18 100644
--- a/arch/tile/include/asm/highmem.h
+++ b/arch/tile/include/asm/highmem.h
@@ -60,12 +60,12 @@
 /* This macro is used only in map_new_virtual() to map "page". */
 #define kmap_prot page_to_kpgprot(page)
 
-void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type);
-void *kmap_atomic_pfn(unsigned long pfn, enum km_type type);
-void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot);
+void *__kmap_atomic(struct page *page);
+void __kunmap_atomic(void *kvaddr);
+void *kmap_atomic_pfn(unsigned long pfn);
+void *kmap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot);
 struct page *kmap_atomic_to_page(void *ptr);
-void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot);
-void *kmap_atomic(struct page *page, enum km_type type);
+void *kmap_atomic_prot(struct page *page, pgprot_t prot);
 void kmap_atomic_fix_kpte(struct page *page, int finished);
 
 #define flush_cache_kmaps()	do { } while (0)
diff --git a/arch/tile/include/asm/irqflags.h b/arch/tile/include/asm/irqflags.h
index a11d483..641e4ff 100644
--- a/arch/tile/include/asm/irqflags.h
+++ b/arch/tile/include/asm/irqflags.h
@@ -47,53 +47,53 @@
 	int __n = (n); \
 	int __mask = 1 << (__n & 0x1f); \
 	if (__n < 32) \
-		__insn_mtspr(SPR_INTERRUPT_MASK_SET_1_0, __mask); \
+		__insn_mtspr(SPR_INTERRUPT_MASK_SET_K_0, __mask); \
 	else \
-		__insn_mtspr(SPR_INTERRUPT_MASK_SET_1_1, __mask); \
+		__insn_mtspr(SPR_INTERRUPT_MASK_SET_K_1, __mask); \
 } while (0)
 #define interrupt_mask_reset(n) do { \
 	int __n = (n); \
 	int __mask = 1 << (__n & 0x1f); \
 	if (__n < 32) \
-		__insn_mtspr(SPR_INTERRUPT_MASK_RESET_1_0, __mask); \
+		__insn_mtspr(SPR_INTERRUPT_MASK_RESET_K_0, __mask); \
 	else \
-		__insn_mtspr(SPR_INTERRUPT_MASK_RESET_1_1, __mask); \
+		__insn_mtspr(SPR_INTERRUPT_MASK_RESET_K_1, __mask); \
 } while (0)
 #define interrupt_mask_check(n) ({ \
 	int __n = (n); \
 	(((__n < 32) ? \
-	 __insn_mfspr(SPR_INTERRUPT_MASK_1_0) : \
-	 __insn_mfspr(SPR_INTERRUPT_MASK_1_1)) \
+	 __insn_mfspr(SPR_INTERRUPT_MASK_K_0) : \
+	 __insn_mfspr(SPR_INTERRUPT_MASK_K_1)) \
 	  >> (__n & 0x1f)) & 1; \
 })
 #define interrupt_mask_set_mask(mask) do { \
 	unsigned long long __m = (mask); \
-	__insn_mtspr(SPR_INTERRUPT_MASK_SET_1_0, (unsigned long)(__m)); \
-	__insn_mtspr(SPR_INTERRUPT_MASK_SET_1_1, (unsigned long)(__m>>32)); \
+	__insn_mtspr(SPR_INTERRUPT_MASK_SET_K_0, (unsigned long)(__m)); \
+	__insn_mtspr(SPR_INTERRUPT_MASK_SET_K_1, (unsigned long)(__m>>32)); \
 } while (0)
 #define interrupt_mask_reset_mask(mask) do { \
 	unsigned long long __m = (mask); \
-	__insn_mtspr(SPR_INTERRUPT_MASK_RESET_1_0, (unsigned long)(__m)); \
-	__insn_mtspr(SPR_INTERRUPT_MASK_RESET_1_1, (unsigned long)(__m>>32)); \
+	__insn_mtspr(SPR_INTERRUPT_MASK_RESET_K_0, (unsigned long)(__m)); \
+	__insn_mtspr(SPR_INTERRUPT_MASK_RESET_K_1, (unsigned long)(__m>>32)); \
 } while (0)
 #else
 #define interrupt_mask_set(n) \
-	__insn_mtspr(SPR_INTERRUPT_MASK_SET_1, (1UL << (n)))
+	__insn_mtspr(SPR_INTERRUPT_MASK_SET_K, (1UL << (n)))
 #define interrupt_mask_reset(n) \
-	__insn_mtspr(SPR_INTERRUPT_MASK_RESET_1, (1UL << (n)))
+	__insn_mtspr(SPR_INTERRUPT_MASK_RESET_K, (1UL << (n)))
 #define interrupt_mask_check(n) \
-	((__insn_mfspr(SPR_INTERRUPT_MASK_1) >> (n)) & 1)
+	((__insn_mfspr(SPR_INTERRUPT_MASK_K) >> (n)) & 1)
 #define interrupt_mask_set_mask(mask) \
-	__insn_mtspr(SPR_INTERRUPT_MASK_SET_1, (mask))
+	__insn_mtspr(SPR_INTERRUPT_MASK_SET_K, (mask))
 #define interrupt_mask_reset_mask(mask) \
-	__insn_mtspr(SPR_INTERRUPT_MASK_RESET_1, (mask))
+	__insn_mtspr(SPR_INTERRUPT_MASK_RESET_K, (mask))
 #endif
 
 /*
  * The set of interrupts we want active if irqs are enabled.
  * Note that in particular, the tile timer interrupt comes and goes
  * from this set, since we have no other way to turn off the timer.
- * Likewise, INTCTRL_1 is removed and re-added during device
+ * Likewise, INTCTRL_K is removed and re-added during device
  * interrupts, as is the the hardwall UDN_FIREWALL interrupt.
  * We use a low bit (MEM_ERROR) as our sentinel value and make sure it
  * is always claimed as an "active interrupt" so we can query that bit
@@ -170,14 +170,14 @@
 
 /* Return 0 or 1 to indicate whether interrupts are currently disabled. */
 #define IRQS_DISABLED(tmp)					\
-	mfspr   tmp, INTERRUPT_MASK_1;				\
+	mfspr   tmp, SPR_INTERRUPT_MASK_K;			\
 	andi    tmp, tmp, 1
 
 /* Load up a pointer to &interrupts_enabled_mask. */
 #define GET_INTERRUPTS_ENABLED_MASK_PTR(reg)			\
-	moveli reg, hw2_last(interrupts_enabled_mask); \
-	shl16insli reg, reg, hw1(interrupts_enabled_mask); \
-	shl16insli reg, reg, hw0(interrupts_enabled_mask); \
+	moveli reg, hw2_last(interrupts_enabled_mask);		\
+	shl16insli reg, reg, hw1(interrupts_enabled_mask);	\
+	shl16insli reg, reg, hw0(interrupts_enabled_mask);	\
 	add     reg, reg, tp
 
 /* Disable interrupts. */
@@ -185,18 +185,18 @@
 	moveli  tmp0, hw2_last(LINUX_MASKABLE_INTERRUPTS);	\
 	shl16insli tmp0, tmp0, hw1(LINUX_MASKABLE_INTERRUPTS);	\
 	shl16insli tmp0, tmp0, hw0(LINUX_MASKABLE_INTERRUPTS);	\
-	mtspr   INTERRUPT_MASK_SET_1, tmp0
+	mtspr   SPR_INTERRUPT_MASK_SET_K, tmp0
 
 /* Disable ALL synchronous interrupts (used by NMI entry). */
 #define IRQ_DISABLE_ALL(tmp)					\
 	movei   tmp, -1;					\
-	mtspr   INTERRUPT_MASK_SET_1, tmp
+	mtspr   SPR_INTERRUPT_MASK_SET_K, tmp
 
 /* Enable interrupts. */
 #define IRQ_ENABLE(tmp0, tmp1)					\
 	GET_INTERRUPTS_ENABLED_MASK_PTR(tmp0);			\
 	ld      tmp0, tmp0;					\
-	mtspr   INTERRUPT_MASK_RESET_1, tmp0
+	mtspr   SPR_INTERRUPT_MASK_RESET_K, tmp0
 
 #else /* !__tilegx__ */
 
@@ -210,14 +210,14 @@
  * (making the original code's write of the "high" mask word idempotent).
  */
 #define IRQS_DISABLED(tmp)					\
-	mfspr   tmp, INTERRUPT_MASK_1_0;			\
+	mfspr   tmp, SPR_INTERRUPT_MASK_K_0;			\
 	shri    tmp, tmp, INT_MEM_ERROR;			\
 	andi    tmp, tmp, 1
 
 /* Load up a pointer to &interrupts_enabled_mask. */
 #define GET_INTERRUPTS_ENABLED_MASK_PTR(reg)			\
-	moveli  reg, lo16(interrupts_enabled_mask);	\
-	auli    reg, reg, ha16(interrupts_enabled_mask);\
+	moveli  reg, lo16(interrupts_enabled_mask);		\
+	auli    reg, reg, ha16(interrupts_enabled_mask);	\
 	add     reg, reg, tp
 
 /* Disable interrupts. */
@@ -227,16 +227,16 @@
 	 moveli tmp1, lo16(LINUX_MASKABLE_INTERRUPTS)		\
 	};							\
 	{							\
-	 mtspr  INTERRUPT_MASK_SET_1_0, tmp0;			\
+	 mtspr  SPR_INTERRUPT_MASK_SET_K_0, tmp0;		\
 	 auli   tmp1, tmp1, ha16(LINUX_MASKABLE_INTERRUPTS)	\
 	};							\
-	mtspr   INTERRUPT_MASK_SET_1_1, tmp1
+	mtspr   SPR_INTERRUPT_MASK_SET_K_1, tmp1
 
 /* Disable ALL synchronous interrupts (used by NMI entry). */
 #define IRQ_DISABLE_ALL(tmp)					\
 	movei   tmp, -1;					\
-	mtspr   INTERRUPT_MASK_SET_1_0, tmp;			\
-	mtspr   INTERRUPT_MASK_SET_1_1, tmp
+	mtspr   SPR_INTERRUPT_MASK_SET_K_0, tmp;		\
+	mtspr   SPR_INTERRUPT_MASK_SET_K_1, tmp
 
 /* Enable interrupts. */
 #define IRQ_ENABLE(tmp0, tmp1)					\
@@ -246,8 +246,8 @@
 	 addi   tmp1, tmp0, 4					\
 	};							\
 	lw      tmp1, tmp1;					\
-	mtspr   INTERRUPT_MASK_RESET_1_0, tmp0;			\
-	mtspr   INTERRUPT_MASK_RESET_1_1, tmp1
+	mtspr   SPR_INTERRUPT_MASK_RESET_K_0, tmp0;		\
+	mtspr   SPR_INTERRUPT_MASK_RESET_K_1, tmp1
 #endif
 
 /*
diff --git a/arch/tile/include/asm/mman.h b/arch/tile/include/asm/mman.h
index 4c6811e..81b8fc3 100644
--- a/arch/tile/include/asm/mman.h
+++ b/arch/tile/include/asm/mman.h
@@ -23,6 +23,7 @@
 #define MAP_POPULATE	0x0040		/* populate (prefault) pagetables */
 #define MAP_NONBLOCK	0x0080		/* do not block on IO */
 #define MAP_GROWSDOWN	0x0100		/* stack-like segment */
+#define MAP_STACK	MAP_GROWSDOWN	/* provide convenience alias */
 #define MAP_LOCKED	0x0200		/* pages are locked */
 #define MAP_NORESERVE	0x0400		/* don't check for reservations */
 #define MAP_DENYWRITE	0x0800		/* ETXTBSY */
diff --git a/arch/tile/include/asm/page.h b/arch/tile/include/asm/page.h
index 7d90641..7979a45 100644
--- a/arch/tile/include/asm/page.h
+++ b/arch/tile/include/asm/page.h
@@ -199,17 +199,17 @@
  * If you want more physical memory than this then see the CONFIG_HIGHMEM
  * option in the kernel configuration.
  *
- * The top two 16MB chunks in the table below (VIRT and HV) are
- * unavailable to Linux.  Since the kernel interrupt vectors must live
- * at 0xfd000000, we map all of the bottom of RAM at this address with
- * a huge page table entry to minimize its ITLB footprint (as well as
- * at PAGE_OFFSET).  The last architected requirement is that user
- * interrupt vectors live at 0xfc000000, so we make that range of
- * memory available to user processes.  The remaining regions are sized
- * as shown; after the first four addresses, we show "typical" values,
- * since the actual addresses depend on kernel #defines.
+ * The top 16MB chunk in the table below is unavailable to Linux.  Since
+ * the kernel interrupt vectors must live at ether 0xfe000000 or 0xfd000000
+ * (depending on whether the kernel is at PL2 or Pl1), we map all of the
+ * bottom of RAM at this address with a huge page table entry to minimize
+ * its ITLB footprint (as well as at PAGE_OFFSET).  The last architected
+ * requirement is that user interrupt vectors live at 0xfc000000, so we
+ * make that range of memory available to user processes.  The remaining
+ * regions are sized as shown; the first four addresses use the PL 1
+ * values, and after that, we show "typical" values, since the actual
+ * addresses depend on kernel #defines.
  *
- * MEM_VIRT_INTRPT                 0xff000000
  * MEM_HV_INTRPT                   0xfe000000
  * MEM_SV_INTRPT (kernel code)     0xfd000000
  * MEM_USER_INTRPT (user vector)   0xfc000000
@@ -221,9 +221,14 @@
  */
 
 #define MEM_USER_INTRPT		_AC(0xfc000000, UL)
+#if CONFIG_KERNEL_PL == 1
 #define MEM_SV_INTRPT		_AC(0xfd000000, UL)
 #define MEM_HV_INTRPT		_AC(0xfe000000, UL)
-#define MEM_VIRT_INTRPT		_AC(0xff000000, UL)
+#else
+#define MEM_GUEST_INTRPT	_AC(0xfd000000, UL)
+#define MEM_SV_INTRPT		_AC(0xfe000000, UL)
+#define MEM_HV_INTRPT		_AC(0xff000000, UL)
+#endif
 
 #define INTRPT_SIZE		0x4000
 
diff --git a/arch/tile/include/asm/pgtable.h b/arch/tile/include/asm/pgtable.h
index b336737..dc4ccdd 100644
--- a/arch/tile/include/asm/pgtable.h
+++ b/arch/tile/include/asm/pgtable.h
@@ -347,15 +347,10 @@
 extern pte_t *_pte_offset_map(pmd_t *, unsigned long address, enum km_type);
 #define pte_offset_map(dir, address) \
 	_pte_offset_map(dir, address, KM_PTE0)
-#define pte_offset_map_nested(dir, address) \
-	_pte_offset_map(dir, address, KM_PTE1)
 #define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0)
-#define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1)
 #else
 #define pte_offset_map(dir, address) pte_offset_kernel(dir, address)
-#define pte_offset_map_nested(dir, address) pte_offset_map(dir, address)
 #define pte_unmap(pte) do { } while (0)
-#define pte_unmap_nested(pte) do { } while (0)
 #endif
 
 /* Clear a non-executable kernel PTE and flush it from the TLB. */
diff --git a/arch/tile/include/asm/processor.h b/arch/tile/include/asm/processor.h
index ccd5f84..1747ff3 100644
--- a/arch/tile/include/asm/processor.h
+++ b/arch/tile/include/asm/processor.h
@@ -328,18 +328,21 @@
  * Note that assembly code assumes that USER_PL is zero.
  */
 #define USER_PL 0
-#define KERNEL_PL 1
+#if CONFIG_KERNEL_PL == 2
+#define GUEST_PL 1
+#endif
+#define KERNEL_PL CONFIG_KERNEL_PL
 
-/* SYSTEM_SAVE_1_0 holds the current cpu number ORed with ksp0. */
+/* SYSTEM_SAVE_K_0 holds the current cpu number ORed with ksp0. */
 #define CPU_LOG_MASK_VALUE 12
 #define CPU_MASK_VALUE ((1 << CPU_LOG_MASK_VALUE) - 1)
 #if CONFIG_NR_CPUS > CPU_MASK_VALUE
 # error Too many cpus!
 #endif
 #define raw_smp_processor_id() \
-	((int)__insn_mfspr(SPR_SYSTEM_SAVE_1_0) & CPU_MASK_VALUE)
+	((int)__insn_mfspr(SPR_SYSTEM_SAVE_K_0) & CPU_MASK_VALUE)
 #define get_current_ksp0() \
-	(__insn_mfspr(SPR_SYSTEM_SAVE_1_0) & ~CPU_MASK_VALUE)
+	(__insn_mfspr(SPR_SYSTEM_SAVE_K_0) & ~CPU_MASK_VALUE)
 #define next_current_ksp0(task) ({ \
 	unsigned long __ksp0 = task_ksp0(task); \
 	int __cpu = raw_smp_processor_id(); \
diff --git a/arch/tile/include/asm/ptrace.h b/arch/tile/include/asm/ptrace.h
index 4a02bb0..ac6d343 100644
--- a/arch/tile/include/asm/ptrace.h
+++ b/arch/tile/include/asm/ptrace.h
@@ -62,8 +62,8 @@
 	pt_reg_t lr;		/* aliases regs[TREG_LR] */
 
 	/* Saved special registers. */
-	pt_reg_t pc;		/* stored in EX_CONTEXT_1_0 */
-	pt_reg_t ex1;		/* stored in EX_CONTEXT_1_1 (PL and ICS bit) */
+	pt_reg_t pc;		/* stored in EX_CONTEXT_K_0 */
+	pt_reg_t ex1;		/* stored in EX_CONTEXT_K_1 (PL and ICS bit) */
 	pt_reg_t faultnum;	/* fault number (INT_SWINT_1 for syscall) */
 	pt_reg_t orig_r0;	/* r0 at syscall entry, else zero */
 	pt_reg_t flags;		/* flags (see below) */
diff --git a/arch/tile/include/asm/syscalls.h b/arch/tile/include/asm/syscalls.h
index ce99ffe..3b5507c 100644
--- a/arch/tile/include/asm/syscalls.h
+++ b/arch/tile/include/asm/syscalls.h
@@ -32,8 +32,9 @@
 
 /*
  * Note that by convention, any syscall which requires the current
- * register set takes an additional "struct pt_regs *" pointer; the
- * sys_xxx() function just adds the pointer and tail-calls to _sys_xxx().
+ * register set takes an additional "struct pt_regs *" pointer; a
+ * _sys_xxx() trampoline in intvec*.S just sets up the pointer and
+ * jumps to sys_xxx().
  */
 
 /* kernel/sys.c */
@@ -43,66 +44,17 @@
 int sys32_fadvise64_64(int fd, u32 offset_lo, u32 offset_hi,
 		       u32 len_lo, u32 len_hi, int advice);
 long sys_flush_cache(void);
-long sys_mmap2(unsigned long addr, unsigned long len,
-	       unsigned long prot, unsigned long flags,
-	       unsigned long fd, unsigned long pgoff);
-#ifdef __tilegx__
-long sys_mmap(unsigned long addr, unsigned long len,
-	      unsigned long prot, unsigned long flags,
-	      unsigned long fd, off_t pgoff);
+#ifndef __tilegx__  /* No mmap() in the 32-bit kernel. */
+#define sys_mmap sys_mmap
 #endif
 
-/* kernel/process.c */
-long sys_clone(unsigned long clone_flags, unsigned long newsp,
-	       void __user *parent_tid, void __user *child_tid);
-long _sys_clone(unsigned long clone_flags, unsigned long newsp,
-		void __user *parent_tid, void __user *child_tid,
-		struct pt_regs *regs);
-long sys_fork(void);
-long _sys_fork(struct pt_regs *regs);
-long sys_vfork(void);
-long _sys_vfork(struct pt_regs *regs);
-long sys_execve(const char __user *filename,
-		const char __user *const __user *argv,
-		const char __user *const __user *envp);
-long _sys_execve(const char __user *filename,
-		 const char __user *const __user *argv,
-		 const char __user *const __user *envp, struct pt_regs *regs);
-
-/* kernel/signal.c */
-long sys_sigaltstack(const stack_t __user *, stack_t __user *);
-long _sys_sigaltstack(const stack_t __user *, stack_t __user *,
-		      struct pt_regs *);
-long sys_rt_sigreturn(void);
-long _sys_rt_sigreturn(struct pt_regs *regs);
-
-/* platform-independent functions */
-long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize);
-long sys_rt_sigaction(int sig, const struct sigaction __user *act,
-		      struct sigaction __user *oact, size_t sigsetsize);
-
 #ifndef __tilegx__
 /* mm/fault.c */
-int sys_cmpxchg_badaddr(unsigned long address);
-int _sys_cmpxchg_badaddr(unsigned long address, struct pt_regs *);
+long sys_cmpxchg_badaddr(unsigned long address, struct pt_regs *);
+long _sys_cmpxchg_badaddr(unsigned long address);
 #endif
 
 #ifdef CONFIG_COMPAT
-long compat_sys_execve(const char __user *path,
-		       const compat_uptr_t __user *argv,
-		       const compat_uptr_t __user *envp);
-long _compat_sys_execve(const char __user *path,
-			const compat_uptr_t __user *argv,
-			const compat_uptr_t __user *envp,
-			struct pt_regs *regs);
-long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
-			    struct compat_sigaltstack __user *uoss_ptr);
-long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
-			     struct compat_sigaltstack __user *uoss_ptr,
-			     struct pt_regs *regs);
-long compat_sys_rt_sigreturn(void);
-long _compat_sys_rt_sigreturn(struct pt_regs *regs);
-
 /* These four are not defined for 64-bit, but serve as "compat" syscalls. */
 long sys_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg);
 long sys_fstat64(unsigned long fd, struct stat64 __user *statbuf);
@@ -110,4 +62,15 @@
 long sys_ftruncate64(unsigned int fd, loff_t length);
 #endif
 
+/* These are the intvec*.S trampolines. */
+long _sys_sigaltstack(const stack_t __user *, stack_t __user *);
+long _sys_rt_sigreturn(void);
+long _sys_clone(unsigned long clone_flags, unsigned long newsp,
+		void __user *parent_tid, void __user *child_tid);
+long _sys_execve(const char __user *filename,
+		 const char __user *const __user *argv,
+		 const char __user *const __user *envp);
+
+#include <asm-generic/syscalls.h>
+
 #endif /* _ASM_TILE_SYSCALLS_H */
diff --git a/arch/tile/include/asm/system.h b/arch/tile/include/asm/system.h
index f749be3..5388850 100644
--- a/arch/tile/include/asm/system.h
+++ b/arch/tile/include/asm/system.h
@@ -89,6 +89,10 @@
 #define get_cycles_low() __insn_mfspr(SPR_CYCLE)   /* just get all 64 bits */
 #endif
 
+#if !CHIP_HAS_MF_WAITS_FOR_VICTIMS()
+int __mb_incoherent(void);  /* Helper routine for mb_incoherent(). */
+#endif
+
 /* Fence to guarantee visibility of stores to incoherent memory. */
 static inline void
 mb_incoherent(void)
@@ -97,7 +101,6 @@
 
 #if !CHIP_HAS_MF_WAITS_FOR_VICTIMS()
 	{
-		int __mb_incoherent(void);
 #if CHIP_HAS_TILE_WRITE_PENDING()
 		const unsigned long WRITE_TIMEOUT_CYCLES = 400;
 		unsigned long start = get_cycles_low();
@@ -161,7 +164,7 @@
 /* Helper function for _switch_to(). */
 extern struct task_struct *__switch_to(struct task_struct *prev,
 				       struct task_struct *next,
-				       unsigned long new_system_save_1_0);
+				       unsigned long new_system_save_k_0);
 
 /* Address that switched-away from tasks are at. */
 extern unsigned long get_switch_to_pc(void);
@@ -214,13 +217,6 @@
 } while (0)
 #endif
 
-/* Invoke the simulator "syscall" mechanism (see arch/tile/kernel/entry.S). */
-extern int _sim_syscall(int syscall_num, ...);
-#define sim_syscall(syscall_num, ...) \
-	_sim_syscall(SIM_CONTROL_SYSCALL + \
-		((syscall_num) << _SIM_CONTROL_OPERATOR_BITS), \
-		## __VA_ARGS__)
-
 /*
  * Kernel threads can check to see if they need to migrate their
  * stack whenever they return from a context switch; for user
diff --git a/arch/tile/include/asm/traps.h b/arch/tile/include/asm/traps.h
index 432a9c1..d06e35f 100644
--- a/arch/tile/include/asm/traps.h
+++ b/arch/tile/include/asm/traps.h
@@ -59,4 +59,8 @@
 void do_breakpoint(struct pt_regs *, int fault_num);
 
 
+#ifdef __tilegx__
+void gx_singlestep_handle(struct pt_regs *, int fault_num);
+#endif
+
 #endif /* _ASM_TILE_SYSCALLS_H */
diff --git a/arch/tile/include/hv/hypervisor.h b/arch/tile/include/hv/hypervisor.h
index 9bd303a..f672544 100644
--- a/arch/tile/include/hv/hypervisor.h
+++ b/arch/tile/include/hv/hypervisor.h
@@ -1003,37 +1003,37 @@
  *  when these occur in a client's interrupt critical section, they must
  *  be delivered through the downcall mechanism.
  *
- *  A downcall is initially delivered to the client as an INTCTRL_1
- *  interrupt.  Upon entry to the INTCTRL_1 vector, the client must
- *  immediately invoke the hv_downcall_dispatch service.  This service
- *  will not return; instead it will cause one of the client's actual
- *  downcall-handling interrupt vectors to be entered.  The EX_CONTEXT
- *  registers in the client will be set so that when the client irets,
- *  it will return to the code which was interrupted by the INTCTRL_1
- *  interrupt.
+ *  A downcall is initially delivered to the client as an INTCTRL_CL
+ *  interrupt, where CL is the client's PL.  Upon entry to the INTCTRL_CL
+ *  vector, the client must immediately invoke the hv_downcall_dispatch
+ *  service.  This service will not return; instead it will cause one of
+ *  the client's actual downcall-handling interrupt vectors to be entered.
+ *  The EX_CONTEXT registers in the client will be set so that when the
+ *  client irets, it will return to the code which was interrupted by the
+ *  INTCTRL_CL interrupt.
  *
- *  Under some circumstances, the firing of INTCTRL_1 can race with
+ *  Under some circumstances, the firing of INTCTRL_CL can race with
  *  the lowering of a device interrupt.  In such a case, the
  *  hv_downcall_dispatch service may issue an iret instruction instead
  *  of entering one of the client's actual downcall-handling interrupt
  *  vectors.  This will return execution to the location that was
- *  interrupted by INTCTRL_1.
+ *  interrupted by INTCTRL_CL.
  *
  *  Any saving of registers should be done by the actual handling
- *  vectors; no registers should be changed by the INTCTRL_1 handler.
+ *  vectors; no registers should be changed by the INTCTRL_CL handler.
  *  In particular, the client should not use a jal instruction to invoke
  *  the hv_downcall_dispatch service, as that would overwrite the client's
  *  lr register.  Note that the hv_downcall_dispatch service may overwrite
  *  one or more of the client's system save registers.
  *
- *  The client must not modify the INTCTRL_1_STATUS SPR.  The hypervisor
+ *  The client must not modify the INTCTRL_CL_STATUS SPR.  The hypervisor
  *  will set this register to cause a downcall to happen, and will clear
  *  it when no further downcalls are pending.
  *
- *  When a downcall vector is entered, the INTCTRL_1 interrupt will be
+ *  When a downcall vector is entered, the INTCTRL_CL interrupt will be
  *  masked.  When the client is done processing a downcall, and is ready
  *  to accept another, it must unmask this interrupt; if more downcalls
- *  are pending, this will cause the INTCTRL_1 vector to be reentered.
+ *  are pending, this will cause the INTCTRL_CL vector to be reentered.
  *  Currently the following interrupt vectors can be entered through a
  *  downcall:
  *
diff --git a/arch/tile/kernel/backtrace.c b/arch/tile/kernel/backtrace.c
index d3c41c1..55a6a74 100644
--- a/arch/tile/kernel/backtrace.c
+++ b/arch/tile/kernel/backtrace.c
@@ -369,6 +369,10 @@
 					/* Weird; reserved value, ignore it. */
 					continue;
 				}
+				if (info_operand & ENTRY_POINT_INFO_OP)	{
+					/* This info op is ignored by the backtracer. */
+					continue;
+				}
 
 				/* Skip info ops which are not in the
 				 * "one_ago" mode we want right now.
diff --git a/arch/tile/kernel/compat.c b/arch/tile/kernel/compat.c
index b1e06d0..77739cd 100644
--- a/arch/tile/kernel/compat.c
+++ b/arch/tile/kernel/compat.c
@@ -154,8 +154,14 @@
 #define compat_sys_fstat64 sys_newfstat
 #define compat_sys_fstatat64 sys_newfstatat
 
-/* Pass full 64-bit values through ptrace. */
-#define compat_sys_ptrace tile_compat_sys_ptrace
+/* The native sys_ptrace dynamically handles compat binaries. */
+#define compat_sys_ptrace sys_ptrace
+
+/* Call the trampolines to manage pt_regs where necessary. */
+#define compat_sys_execve _compat_sys_execve
+#define compat_sys_sigaltstack _compat_sys_sigaltstack
+#define compat_sys_rt_sigreturn _compat_sys_rt_sigreturn
+#define sys_clone _sys_clone
 
 /*
  * Note that we can't include <linux/unistd.h> here since the header
diff --git a/arch/tile/kernel/compat_signal.c b/arch/tile/kernel/compat_signal.c
index 9c710db..fb64b99 100644
--- a/arch/tile/kernel/compat_signal.c
+++ b/arch/tile/kernel/compat_signal.c
@@ -256,9 +256,9 @@
 	return err;
 }
 
-long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
-			     struct compat_sigaltstack __user *uoss_ptr,
-			     struct pt_regs *regs)
+long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
+			    struct compat_sigaltstack __user *uoss_ptr,
+			    struct pt_regs *regs)
 {
 	stack_t uss, uoss;
 	int ret;
@@ -291,7 +291,7 @@
 	return ret;
 }
 
-long _compat_sys_rt_sigreturn(struct pt_regs *regs)
+long compat_sys_rt_sigreturn(struct pt_regs *regs)
 {
 	struct compat_rt_sigframe __user *frame =
 		(struct compat_rt_sigframe __user *) compat_ptr(regs->sp);
@@ -312,7 +312,7 @@
 	if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
 		goto badframe;
 
-	if (_compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0)
+	if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0)
 		goto badframe;
 
 	return r0;
diff --git a/arch/tile/kernel/entry.S b/arch/tile/kernel/entry.S
index 3d01383..fd8dc42 100644
--- a/arch/tile/kernel/entry.S
+++ b/arch/tile/kernel/entry.S
@@ -15,7 +15,9 @@
 #include <linux/linkage.h>
 #include <linux/unistd.h>
 #include <asm/irqflags.h>
+#include <asm/processor.h>
 #include <arch/abi.h>
+#include <arch/spr_def.h>
 
 #ifdef __tilegx__
 #define bnzt bnezt
@@ -25,28 +27,6 @@
 	{ move r0, lr; jrp lr }
 	STD_ENDPROC(current_text_addr)
 
-STD_ENTRY(_sim_syscall)
-	/*
-	 * Wait for r0-r9 to be ready (and lr on the off chance we
-	 * want the syscall to locate its caller), then make a magic
-	 * simulator syscall.
-	 *
-	 * We carefully stall until the registers are readable in case they
-	 * are the target of a slow load, etc. so that tile-sim will
-	 * definitely be able to read all of them inside the magic syscall.
-	 *
-	 * Technically this is wrong for r3-r9 and lr, since an interrupt
-	 * could come in and restore the registers with a slow load right
-	 * before executing the mtspr. We may need to modify tile-sim to
-	 * explicitly stall for this case, but we do not yet have
-	 * a way to implement such a stall.
-	 */
-	{ and zero, lr, r9 ; and zero, r8, r7 }
-	{ and zero, r6, r5 ; and zero, r4, r3 }
-	{ and zero, r2, r1 ; mtspr SIM_CONTROL, r0 }
-	{ jrp lr }
-	STD_ENDPROC(_sim_syscall)
-
 /*
  * Implement execve().  The i386 code has a note that forking from kernel
  * space results in no copy on write until the execve, so we should be
@@ -102,7 +82,7 @@
 STD_ENTRY(cpu_idle_on_new_stack)
 	{
 	 move sp, r1
-	 mtspr SYSTEM_SAVE_1_0, r2
+	 mtspr SPR_SYSTEM_SAVE_K_0, r2
 	}
 	jal free_thread_info
 	j cpu_idle
@@ -124,15 +104,15 @@
 STD_ENTRY(_cpu_idle)
 	{
 	 lnk r0
-	 movei r1, 1
+	 movei r1, KERNEL_PL
 	}
 	{
 	 addli r0, r0, _cpu_idle_nap - .
 	 mtspr INTERRUPT_CRITICAL_SECTION, r1
 	}
-	IRQ_ENABLE(r2, r3)         /* unmask, but still with ICS set */
-	mtspr EX_CONTEXT_1_1, r1   /* PL1, ICS clear */
-	mtspr EX_CONTEXT_1_0, r0
+	IRQ_ENABLE(r2, r3)             /* unmask, but still with ICS set */
+	mtspr SPR_EX_CONTEXT_K_1, r1   /* Kernel PL, ICS clear */
+	mtspr SPR_EX_CONTEXT_K_0, r0
 	iret
 	.global _cpu_idle_nap
 _cpu_idle_nap:
diff --git a/arch/tile/kernel/head_32.S b/arch/tile/kernel/head_32.S
index 2b4f6c0..90e7c44 100644
--- a/arch/tile/kernel/head_32.S
+++ b/arch/tile/kernel/head_32.S
@@ -23,6 +23,7 @@
 #include <asm/asm-offsets.h>
 #include <hv/hypervisor.h>
 #include <arch/chip.h>
+#include <arch/spr_def.h>
 
 /*
  * This module contains the entry code for kernel images. It performs the
@@ -76,7 +77,7 @@
 	}
 1:
 
-	/* Get our processor number and save it away in SAVE_1_0. */
+	/* Get our processor number and save it away in SAVE_K_0. */
 	jal hv_inquire_topology
 	mulll_uu r4, r1, r2        /* r1 == y, r2 == width */
 	add r4, r4, r0             /* r0 == x, so r4 == cpu == y*width + x */
@@ -124,7 +125,7 @@
 	lw r0, r0
 	lw sp, r1
 	or r4, sp, r4
-	mtspr SYSTEM_SAVE_1_0, r4  /* save ksp0 + cpu */
+	mtspr SPR_SYSTEM_SAVE_K_0, r4  /* save ksp0 + cpu */
 	addi sp, sp, -STACK_TOP_DELTA
 	{
 	  move lr, zero   /* stop backtraces in the called function */
diff --git a/arch/tile/kernel/intvec_32.S b/arch/tile/kernel/intvec_32.S
index 8f58bdf..f5821626 100644
--- a/arch/tile/kernel/intvec_32.S
+++ b/arch/tile/kernel/intvec_32.S
@@ -32,8 +32,8 @@
 # error "No support for kernel preemption currently"
 #endif
 
-#if INT_INTCTRL_1 < 32 || INT_INTCTRL_1 >= 48
-# error INT_INTCTRL_1 coded to set high interrupt mask
+#if INT_INTCTRL_K < 32 || INT_INTCTRL_K >= 48
+# error INT_INTCTRL_K coded to set high interrupt mask
 #endif
 
 #define PTREGS_PTR(reg, ptreg) addli reg, sp, C_ABI_SAVE_AREA_SIZE + (ptreg)
@@ -132,8 +132,8 @@
 
 	/* Temporarily save a register so we have somewhere to work. */
 
-	mtspr   SYSTEM_SAVE_1_1, r0
-	mfspr   r0, EX_CONTEXT_1_1
+	mtspr   SPR_SYSTEM_SAVE_K_1, r0
+	mfspr   r0, SPR_EX_CONTEXT_K_1
 
 	/* The cmpxchg code clears sp to force us to reset it here on fault. */
 	{
@@ -167,18 +167,18 @@
 	 * The page_fault handler may be downcalled directly by the
 	 * hypervisor even when Linux is running and has ICS set.
 	 *
-	 * In this case the contents of EX_CONTEXT_1_1 reflect the
+	 * In this case the contents of EX_CONTEXT_K_1 reflect the
 	 * previous fault and can't be relied on to choose whether or
 	 * not to reinitialize the stack pointer.  So we add a test
-	 * to see whether SYSTEM_SAVE_1_2 has the high bit set,
+	 * to see whether SYSTEM_SAVE_K_2 has the high bit set,
 	 * and if so we don't reinitialize sp, since we must be coming
 	 * from Linux.  (In fact the precise case is !(val & ~1),
 	 * but any Linux PC has to have the high bit set.)
 	 *
-	 * Note that the hypervisor *always* sets SYSTEM_SAVE_1_2 for
+	 * Note that the hypervisor *always* sets SYSTEM_SAVE_K_2 for
 	 * any path that turns into a downcall to one of our TLB handlers.
 	 */
-	mfspr   r0, SYSTEM_SAVE_1_2
+	mfspr   r0, SPR_SYSTEM_SAVE_K_2
 	{
 	 blz    r0, 0f    /* high bit in S_S_1_2 is for a PC to use */
 	 move   r0, sp
@@ -187,12 +187,12 @@
 
 2:
 	/*
-	 * SYSTEM_SAVE_1_0 holds the cpu number in the low bits, and
+	 * SYSTEM_SAVE_K_0 holds the cpu number in the low bits, and
 	 * the current stack top in the higher bits.  So we recover
 	 * our stack top by just masking off the low bits, then
 	 * point sp at the top aligned address on the actual stack page.
 	 */
-	mfspr   r0, SYSTEM_SAVE_1_0
+	mfspr   r0, SPR_SYSTEM_SAVE_K_0
 	mm      r0, r0, zero, LOG2_THREAD_SIZE, 31
 
 0:
@@ -254,7 +254,7 @@
 	 sw     sp, r3
 	 addli  sp, sp, PTREGS_OFFSET_PC - PTREGS_OFFSET_REG(3)
 	}
-	mfspr   r0, EX_CONTEXT_1_0
+	mfspr   r0, SPR_EX_CONTEXT_K_0
 	.ifc \processing,handle_syscall
 	/*
 	 * Bump the saved PC by one bundle so that when we return, we won't
@@ -267,7 +267,7 @@
 	 sw     sp, r0
 	 addli  sp, sp, PTREGS_OFFSET_EX1 - PTREGS_OFFSET_PC
 	}
-	mfspr   r0, EX_CONTEXT_1_1
+	mfspr   r0, SPR_EX_CONTEXT_K_1
 	{
 	 sw     sp, r0
 	 addi   sp, sp, PTREGS_OFFSET_FAULTNUM - PTREGS_OFFSET_EX1
@@ -289,7 +289,7 @@
 	 .endif
 	 addli  sp, sp, PTREGS_OFFSET_REG(0) - PTREGS_OFFSET_FAULTNUM
 	}
-	mfspr   r0, SYSTEM_SAVE_1_1    /* Original r0 */
+	mfspr   r0, SPR_SYSTEM_SAVE_K_1    /* Original r0 */
 	{
 	 sw     sp, r0
 	 addi   sp, sp, -PTREGS_OFFSET_REG(0) - 4
@@ -309,12 +309,12 @@
 	 * See discussion below at "finish_interrupt_save".
 	 */
 	.ifc \c_routine, do_page_fault
-	mfspr   r2, SYSTEM_SAVE_1_3   /* address of page fault */
-	mfspr   r3, SYSTEM_SAVE_1_2   /* info about page fault */
+	mfspr   r2, SPR_SYSTEM_SAVE_K_3   /* address of page fault */
+	mfspr   r3, SPR_SYSTEM_SAVE_K_2   /* info about page fault */
 	.else
 	.ifc \vecnum, INT_DOUBLE_FAULT
 	{
-	 mfspr  r2, SYSTEM_SAVE_1_2   /* double fault info from HV */
+	 mfspr  r2, SPR_SYSTEM_SAVE_K_2   /* double fault info from HV */
 	 movei  r3, 0
 	}
 	.else
@@ -467,7 +467,7 @@
 	/* Load tp with our per-cpu offset. */
 #ifdef CONFIG_SMP
 	{
-	 mfspr  r20, SYSTEM_SAVE_1_0
+	 mfspr  r20, SPR_SYSTEM_SAVE_K_0
 	 moveli r21, lo16(__per_cpu_offset)
 	}
 	{
@@ -487,7 +487,7 @@
 	 * We load flags in r32 here so we can jump to .Lrestore_regs
 	 * directly after do_page_fault_ics() if necessary.
 	 */
-	mfspr   r32, EX_CONTEXT_1_1
+	mfspr   r32, SPR_EX_CONTEXT_K_1
 	{
 	 andi   r32, r32, SPR_EX_CONTEXT_1_1__PL_MASK  /* mask off ICS */
 	 PTREGS_PTR(r21, PTREGS_OFFSET_FLAGS)
@@ -957,11 +957,11 @@
 	pop_reg_zero r21, r3, sp, PTREGS_OFFSET_EX1 - PTREGS_OFFSET_PC
 	pop_reg_zero lr, r4, sp, PTREGS_OFFSET_REG(52) - PTREGS_OFFSET_EX1
 	{
-	 mtspr  EX_CONTEXT_1_0, r21
+	 mtspr  SPR_EX_CONTEXT_K_0, r21
 	 move   r5, zero
 	}
 	{
-	 mtspr  EX_CONTEXT_1_1, lr
+	 mtspr  SPR_EX_CONTEXT_K_1, lr
 	 andi   lr, lr, SPR_EX_CONTEXT_1_1__PL_MASK  /* mask off ICS */
 	}
 
@@ -1020,7 +1020,7 @@
 
 	/* Set r1 to errno if we are returning an error, otherwise zero. */
 	{
-	 moveli r29, 1024
+	 moveli r29, 4096
 	 sub    r1, zero, r0
 	}
 	slt_u   r29, r1, r29
@@ -1199,7 +1199,7 @@
 	STD_ENDPROC(interrupt_return)
 
 	/*
-	 * This interrupt variant clears the INT_INTCTRL_1 interrupt mask bit
+	 * This interrupt variant clears the INT_INTCTRL_K interrupt mask bit
 	 * before returning, so we can properly get more downcalls.
 	 */
 	.pushsection .text.handle_interrupt_downcall,"ax"
@@ -1208,11 +1208,11 @@
 	check_single_stepping normal, .Ldispatch_downcall
 .Ldispatch_downcall:
 
-	/* Clear INTCTRL_1 from the set of interrupts we ever enable. */
+	/* Clear INTCTRL_K from the set of interrupts we ever enable. */
 	GET_INTERRUPTS_ENABLED_MASK_PTR(r30)
 	{
 	 addi   r30, r30, 4
-	 movei  r31, INT_MASK(INT_INTCTRL_1)
+	 movei  r31, INT_MASK(INT_INTCTRL_K)
 	}
 	{
 	 lw     r20, r30
@@ -1227,7 +1227,7 @@
 	}
 	FEEDBACK_REENTER(handle_interrupt_downcall)
 
-	/* Allow INTCTRL_1 to be enabled next time we enable interrupts. */
+	/* Allow INTCTRL_K to be enabled next time we enable interrupts. */
 	lw      r20, r30
 	or      r20, r20, r31
 	sw      r30, r20
@@ -1472,7 +1472,12 @@
 	lw      r26, r24
 	sw      r28, r26
 
-	/* Clear TIF_SINGLESTEP */
+	/*
+	 * Clear TIF_SINGLESTEP to prevent recursion if we execute an ill.
+	 * The normal non-arch flow redundantly clears TIF_SINGLESTEP, but we
+	 * need to clear it here and can't really impose on all other arches.
+	 * So what's another write between friends?
+	 */
 	GET_THREAD_INFO(r0)
 
 	addi    r1, r0, THREAD_INFO_FLAGS_OFFSET
@@ -1509,7 +1514,7 @@
 /* Various stub interrupt handlers and syscall handlers */
 
 STD_ENTRY_LOCAL(_kernel_double_fault)
-	mfspr   r1, EX_CONTEXT_1_0
+	mfspr   r1, SPR_EX_CONTEXT_K_0
 	move    r2, lr
 	move    r3, sp
 	move    r4, r52
@@ -1518,34 +1523,29 @@
 	STD_ENDPROC(_kernel_double_fault)
 
 STD_ENTRY_LOCAL(bad_intr)
-	mfspr   r2, EX_CONTEXT_1_0
+	mfspr   r2, SPR_EX_CONTEXT_K_0
 	panic   "Unhandled interrupt %#x: PC %#lx"
 	STD_ENDPROC(bad_intr)
 
 /* Put address of pt_regs in reg and jump. */
 #define PTREGS_SYSCALL(x, reg)                          \
-	STD_ENTRY(x);                                   \
+	STD_ENTRY(_##x);                                \
 	{                                               \
 	 PTREGS_PTR(reg, PTREGS_OFFSET_BASE);           \
-	 j      _##x                                    \
+	 j      x                                       \
 	};                                              \
-	STD_ENDPROC(x)
+	STD_ENDPROC(_##x)
 
 PTREGS_SYSCALL(sys_execve, r3)
 PTREGS_SYSCALL(sys_sigaltstack, r2)
 PTREGS_SYSCALL(sys_rt_sigreturn, r0)
+PTREGS_SYSCALL(sys_cmpxchg_badaddr, r1)
 
-/* Save additional callee-saves to pt_regs, put address in reg and jump. */
-#define PTREGS_SYSCALL_ALL_REGS(x, reg)                 \
-	STD_ENTRY(x);                                   \
-	push_extra_callee_saves reg;                    \
-	j       _##x;                                   \
-	STD_ENDPROC(x)
-
-PTREGS_SYSCALL_ALL_REGS(sys_fork, r0)
-PTREGS_SYSCALL_ALL_REGS(sys_vfork, r0)
-PTREGS_SYSCALL_ALL_REGS(sys_clone, r4)
-PTREGS_SYSCALL_ALL_REGS(sys_cmpxchg_badaddr, r1)
+/* Save additional callee-saves to pt_regs, put address in r4 and jump. */
+STD_ENTRY(_sys_clone)
+	push_extra_callee_saves r4
+	j       sys_clone
+	STD_ENDPROC(_sys_clone)
 
 /*
  * This entrypoint is taken for the cmpxchg and atomic_update fast
@@ -1558,12 +1558,14 @@
  * to be available to it on entry.  It does not modify any callee-save
  * registers (including "lr").  It does not check what PL it is being
  * called at, so you'd better not call it other than at PL0.
+ * The <atomic.h> wrapper assumes it only clobbers r20-r29, so if
+ * it ever is necessary to use more registers, be aware.
  *
  * It does not use the stack, but since it might be re-interrupted by
  * a page fault which would assume the stack was valid, it does
  * save/restore the stack pointer and zero it out to make sure it gets reset.
  * Since we always keep interrupts disabled, the hypervisor won't
- * clobber our EX_CONTEXT_1_x registers, so we don't save/restore them
+ * clobber our EX_CONTEXT_K_x registers, so we don't save/restore them
  * (other than to advance the PC on return).
  *
  * We have to manually validate the user vs kernel address range
@@ -1769,7 +1771,7 @@
 	/* Do slow mtspr here so the following "mf" waits less. */
 	{
 	 move   sp, r27
-	 mtspr  EX_CONTEXT_1_0, r28
+	 mtspr  SPR_EX_CONTEXT_K_0, r28
 	}
 	mf
 
@@ -1788,7 +1790,7 @@
 	}
 	{
 	 move   sp, r27
-	 mtspr  EX_CONTEXT_1_0, r28
+	 mtspr  SPR_EX_CONTEXT_K_0, r28
 	}
 	iret
 
@@ -1816,7 +1818,7 @@
 #endif
 
 	/* Issue the slow SPR here while the tns result is in flight. */
-	mfspr   r28, EX_CONTEXT_1_0
+	mfspr   r28, SPR_EX_CONTEXT_K_0
 
 	{
 	 addi   r28, r28, 8    /* return to the instruction after the swint1 */
@@ -1904,7 +1906,7 @@
 .Lcmpxchg64_mismatch:
 	{
 	 move   sp, r27
-	 mtspr  EX_CONTEXT_1_0, r28
+	 mtspr  SPR_EX_CONTEXT_K_0, r28
 	}
 	mf
 	{
@@ -1985,8 +1987,13 @@
 	int_hand     INT_PERF_COUNT, PERF_COUNT, \
 		     op_handle_perf_interrupt, handle_nmi
 	int_hand     INT_INTCTRL_3, INTCTRL_3, bad_intr
+#if CONFIG_KERNEL_PL == 2
+	dc_dispatch  INT_INTCTRL_2, INTCTRL_2
+	int_hand     INT_INTCTRL_1, INTCTRL_1, bad_intr
+#else
 	int_hand     INT_INTCTRL_2, INTCTRL_2, bad_intr
 	dc_dispatch  INT_INTCTRL_1, INTCTRL_1
+#endif
 	int_hand     INT_INTCTRL_0, INTCTRL_0, bad_intr
 	int_hand     INT_MESSAGE_RCV_DWNCL, MESSAGE_RCV_DWNCL, \
 		     hv_message_intr, handle_interrupt_downcall
diff --git a/arch/tile/kernel/irq.c b/arch/tile/kernel/irq.c
index 9a27d56..e639176 100644
--- a/arch/tile/kernel/irq.c
+++ b/arch/tile/kernel/irq.c
@@ -61,9 +61,9 @@
 
 #if CHIP_HAS_IPI()
 /* Use SPRs to manipulate device interrupts. */
-#define mask_irqs(irq_mask) __insn_mtspr(SPR_IPI_MASK_SET_1, irq_mask)
-#define unmask_irqs(irq_mask) __insn_mtspr(SPR_IPI_MASK_RESET_1, irq_mask)
-#define clear_irqs(irq_mask) __insn_mtspr(SPR_IPI_EVENT_RESET_1, irq_mask)
+#define mask_irqs(irq_mask) __insn_mtspr(SPR_IPI_MASK_SET_K, irq_mask)
+#define unmask_irqs(irq_mask) __insn_mtspr(SPR_IPI_MASK_RESET_K, irq_mask)
+#define clear_irqs(irq_mask) __insn_mtspr(SPR_IPI_EVENT_RESET_K, irq_mask)
 #else
 /* Use HV to manipulate device interrupts. */
 #define mask_irqs(irq_mask) hv_disable_intr(irq_mask)
@@ -89,16 +89,16 @@
 	 * masked by a previous interrupt.  Then, mask out the ones
 	 * we're going to handle.
 	 */
-	unsigned long masked = __insn_mfspr(SPR_IPI_MASK_1);
-	original_irqs = __insn_mfspr(SPR_IPI_EVENT_1) & ~masked;
-	__insn_mtspr(SPR_IPI_MASK_SET_1, original_irqs);
+	unsigned long masked = __insn_mfspr(SPR_IPI_MASK_K);
+	original_irqs = __insn_mfspr(SPR_IPI_EVENT_K) & ~masked;
+	__insn_mtspr(SPR_IPI_MASK_SET_K, original_irqs);
 #else
 	/*
 	 * Hypervisor performs the equivalent of the Gx code above and
 	 * then puts the pending interrupt mask into a system save reg
 	 * for us to find.
 	 */
-	original_irqs = __insn_mfspr(SPR_SYSTEM_SAVE_1_3);
+	original_irqs = __insn_mfspr(SPR_SYSTEM_SAVE_K_3);
 #endif
 	remaining_irqs = original_irqs;
 
@@ -225,7 +225,7 @@
 	/* Enable interrupt delivery. */
 	unmask_irqs(~0UL);
 #if CHIP_HAS_IPI()
-	raw_local_irq_unmask(INT_IPI_1);
+	raw_local_irq_unmask(INT_IPI_K);
 #endif
 }
 
diff --git a/arch/tile/kernel/messaging.c b/arch/tile/kernel/messaging.c
index 6d23ed2..997e393 100644
--- a/arch/tile/kernel/messaging.c
+++ b/arch/tile/kernel/messaging.c
@@ -34,7 +34,7 @@
 		panic("hv_register_message_state: error %d", rc);
 
 	/* Make sure downcall interrupts will be enabled. */
-	raw_local_irq_unmask(INT_INTCTRL_1);
+	raw_local_irq_unmask(INT_INTCTRL_K);
 }
 
 void hv_message_intr(struct pt_regs *regs, int intnum)
diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c
index 84c2911..8430f45 100644
--- a/arch/tile/kernel/process.c
+++ b/arch/tile/kernel/process.c
@@ -214,9 +214,10 @@
 	/*
 	 * Copy the callee-saved registers from the passed pt_regs struct
 	 * into the context-switch callee-saved registers area.
-	 * We have to restore the callee-saved registers since we may
-	 * be cloning a userspace task with userspace register state,
-	 * and we won't be unwinding the same kernel frames to restore them.
+	 * This way when we start the interrupt-return sequence, the
+	 * callee-save registers will be correctly in registers, which
+	 * is how we assume the compiler leaves them as we start doing
+	 * the normal return-from-interrupt path after calling C code.
 	 * Zero out the C ABI save area to mark the top of the stack.
 	 */
 	ksp = (unsigned long) childregs;
@@ -304,15 +305,25 @@
 /* Allow user processes to access the DMA SPRs */
 void grant_dma_mpls(void)
 {
+#if CONFIG_KERNEL_PL == 2
+	__insn_mtspr(SPR_MPL_DMA_CPL_SET_1, 1);
+	__insn_mtspr(SPR_MPL_DMA_NOTIFY_SET_1, 1);
+#else
 	__insn_mtspr(SPR_MPL_DMA_CPL_SET_0, 1);
 	__insn_mtspr(SPR_MPL_DMA_NOTIFY_SET_0, 1);
+#endif
 }
 
 /* Forbid user processes from accessing the DMA SPRs */
 void restrict_dma_mpls(void)
 {
+#if CONFIG_KERNEL_PL == 2
+	__insn_mtspr(SPR_MPL_DMA_CPL_SET_2, 1);
+	__insn_mtspr(SPR_MPL_DMA_NOTIFY_SET_2, 1);
+#else
 	__insn_mtspr(SPR_MPL_DMA_CPL_SET_1, 1);
 	__insn_mtspr(SPR_MPL_DMA_NOTIFY_SET_1, 1);
+#endif
 }
 
 /* Pause the DMA engine, then save off its state registers. */
@@ -523,19 +534,14 @@
 	 * Switch kernel SP, PC, and callee-saved registers.
 	 * In the context of the new task, return the old task pointer
 	 * (i.e. the task that actually called __switch_to).
-	 * Pass the value to use for SYSTEM_SAVE_1_0 when we reset our sp.
+	 * Pass the value to use for SYSTEM_SAVE_K_0 when we reset our sp.
 	 */
 	return __switch_to(prev, next, next_current_ksp0(next));
 }
 
-long _sys_fork(struct pt_regs *regs)
-{
-	return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL);
-}
-
-long _sys_clone(unsigned long clone_flags, unsigned long newsp,
-		void __user *parent_tidptr, void __user *child_tidptr,
-		struct pt_regs *regs)
+SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
+		void __user *, parent_tidptr, void __user *, child_tidptr,
+		struct pt_regs *, regs)
 {
 	if (!newsp)
 		newsp = regs->sp;
@@ -543,18 +549,13 @@
 		       parent_tidptr, child_tidptr);
 }
 
-long _sys_vfork(struct pt_regs *regs)
-{
-	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp,
-		       regs, 0, NULL, NULL);
-}
-
 /*
  * sys_execve() executes a new program.
  */
-long _sys_execve(const char __user *path,
-		 const char __user *const __user *argv,
-		 const char __user *const __user *envp, struct pt_regs *regs)
+SYSCALL_DEFINE4(execve, const char __user *, path,
+		const char __user *const __user *, argv,
+		const char __user *const __user *, envp,
+		struct pt_regs *, regs)
 {
 	long error;
 	char *filename;
@@ -570,9 +571,10 @@
 }
 
 #ifdef CONFIG_COMPAT
-long _compat_sys_execve(const char __user *path,
-			const compat_uptr_t __user *argv,
-			const compat_uptr_t __user *envp, struct pt_regs *regs)
+long compat_sys_execve(const char __user *path,
+		       const compat_uptr_t __user *argv,
+		       const compat_uptr_t __user *envp,
+		       struct pt_regs *regs)
 {
 	long error;
 	char *filename;
diff --git a/arch/tile/kernel/ptrace.c b/arch/tile/kernel/ptrace.c
index 7161bd0..5b20c28 100644
--- a/arch/tile/kernel/ptrace.c
+++ b/arch/tile/kernel/ptrace.c
@@ -32,25 +32,6 @@
 }
 
 /*
- * This routine will put a word on the process's privileged stack.
- */
-static void putreg(struct task_struct *task,
-		   unsigned long addr, unsigned long value)
-{
-	unsigned int regno = addr / sizeof(unsigned long);
-	struct pt_regs *childregs = task_pt_regs(task);
-	childregs->regs[regno] = value;
-	childregs->flags |= PT_FLAGS_RESTORE_REGS;
-}
-
-static unsigned long getreg(struct task_struct *task, unsigned long addr)
-{
-	unsigned int regno = addr / sizeof(unsigned long);
-	struct pt_regs *childregs = task_pt_regs(task);
-	return childregs->regs[regno];
-}
-
-/*
  * Called by kernel/ptrace.c when detaching..
  */
 void ptrace_disable(struct task_struct *child)
@@ -66,59 +47,72 @@
 
 long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
-	unsigned long __user *datap;
+	unsigned long __user *datap = (long __user __force *)data;
 	unsigned long tmp;
 	int i;
 	long ret = -EIO;
-
-#ifdef CONFIG_COMPAT
-	if (task_thread_info(current)->status & TS_COMPAT)
-		data = (u32)data;
-	if (task_thread_info(child)->status & TS_COMPAT)
-		addr = (u32)addr;
-#endif
-	datap = (unsigned long __user __force *)data;
+	unsigned long *childregs;
+	char *childreg;
 
 	switch (request) {
 
 	case PTRACE_PEEKUSR:  /* Read register from pt_regs. */
-		if (addr & (sizeof(data)-1))
-			break;
 		if (addr < 0 || addr >= PTREGS_SIZE)
 			break;
-		tmp = getreg(child, addr);   /* Read register */
-		ret = put_user(tmp, datap);
+		childreg = (char *)task_pt_regs(child) + addr;
+#ifdef CONFIG_COMPAT
+		if (is_compat_task()) {
+			if (addr & (sizeof(compat_long_t)-1))
+				break;
+			ret = put_user(*(compat_long_t *)childreg,
+				       (compat_long_t __user *)datap);
+		} else
+#endif
+		{
+			if (addr & (sizeof(long)-1))
+				break;
+			ret = put_user(*(long *)childreg, datap);
+		}
 		break;
 
 	case PTRACE_POKEUSR:  /* Write register in pt_regs. */
-		if (addr & (sizeof(data)-1))
-			break;
 		if (addr < 0 || addr >= PTREGS_SIZE)
 			break;
-		putreg(child, addr, data);   /* Write register */
+		childreg = (char *)task_pt_regs(child) + addr;
+#ifdef CONFIG_COMPAT
+		if (is_compat_task()) {
+			if (addr & (sizeof(compat_long_t)-1))
+				break;
+			*(compat_long_t *)childreg = data;
+		} else
+#endif
+		{
+			if (addr & (sizeof(long)-1))
+				break;
+			*(long *)childreg = data;
+		}
 		ret = 0;
 		break;
 
 	case PTRACE_GETREGS:  /* Get all registers from the child. */
 		if (!access_ok(VERIFY_WRITE, datap, PTREGS_SIZE))
 			break;
-		for (i = 0; i < PTREGS_SIZE; i += sizeof(long)) {
-			ret = __put_user(getreg(child, i), datap);
+		childregs = (long *)task_pt_regs(child);
+		for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) {
+			ret = __put_user(childregs[i], &datap[i]);
 			if (ret != 0)
 				break;
-			datap++;
 		}
 		break;
 
 	case PTRACE_SETREGS:  /* Set all registers in the child. */
 		if (!access_ok(VERIFY_READ, datap, PTREGS_SIZE))
 			break;
-		for (i = 0; i < PTREGS_SIZE; i += sizeof(long)) {
-			ret = __get_user(tmp, datap);
+		childregs = (long *)task_pt_regs(child);
+		for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) {
+			ret = __get_user(childregs[i], &datap[i]);
 			if (ret != 0)
 				break;
-			putreg(child, i, tmp);
-			datap++;
 		}
 		break;
 
diff --git a/arch/tile/kernel/regs_32.S b/arch/tile/kernel/regs_32.S
index e88d6e12..caa1310 100644
--- a/arch/tile/kernel/regs_32.S
+++ b/arch/tile/kernel/regs_32.S
@@ -85,7 +85,7 @@
 	{
 	  /* Update sp and ksp0 simultaneously to avoid backtracer warnings. */
 	  move sp, r13
-	  mtspr SYSTEM_SAVE_1_0, r2
+	  mtspr SPR_SYSTEM_SAVE_K_0, r2
 	}
 	FOR_EACH_CALLEE_SAVED_REG(LOAD_REG)
 .L__switch_to_pc:
diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c
index e7d54c7..f3a50e7 100644
--- a/arch/tile/kernel/setup.c
+++ b/arch/tile/kernel/setup.c
@@ -187,11 +187,11 @@
 
 #ifdef CONFIG_HIGHMEM
 /*
- * Determine for each controller where its lowmem is mapped and how
- * much of it is mapped there.  On controller zero, the first few
- * megabytes are mapped at 0xfd000000 as code, so in principle we
- * could start our data mappings higher up, but for now we don't
- * bother, to avoid additional confusion.
+ * Determine for each controller where its lowmem is mapped and how much of
+ * it is mapped there.  On controller zero, the first few megabytes are
+ * already mapped in as code at MEM_SV_INTRPT, so in principle we could
+ * start our data mappings higher up, but for now we don't bother, to avoid
+ * additional confusion.
  *
  * One question is whether, on systems with more than 768 Mb and
  * controllers of different sizes, to map in a proportionate amount of
@@ -311,7 +311,7 @@
 #endif
 
 	/* We are using a char to hold the cpu_2_node[] mapping */
-	BUG_ON(MAX_NUMNODES > 127);
+	BUILD_BUG_ON(MAX_NUMNODES > 127);
 
 	/* Discover the ranges of memory available to us */
 	for (i = 0; ; ++i) {
@@ -876,6 +876,9 @@
 #if CHIP_HAS_SN_PROC()
 	raw_local_irq_unmask(INT_SNITLB_MISS);
 #endif
+#ifdef __tilegx__
+	raw_local_irq_unmask(INT_SINGLE_STEP_K);
+#endif
 
 	/*
 	 * Allow user access to many generic SPRs, like the cycle
@@ -893,11 +896,12 @@
 #endif
 
 	/*
-	 * Set the MPL for interrupt control 0 to user level.
-	 * This includes access to the SYSTEM_SAVE and EX_CONTEXT SPRs,
-	 * as well as the PL 0 interrupt mask.
+	 * Set the MPL for interrupt control 0 & 1 to the corresponding
+	 * values.  This includes access to the SYSTEM_SAVE and EX_CONTEXT
+	 * SPRs, as well as the interrupt mask.
 	 */
 	__insn_mtspr(SPR_MPL_INTCTRL_0_SET_0, 1);
+	__insn_mtspr(SPR_MPL_INTCTRL_1_SET_1, 1);
 
 	/* Initialize IRQ support for this cpu. */
 	setup_irq_regs();
@@ -1033,7 +1037,7 @@
 	 * In addition, make sure we CAN'T use the end of memory, since
 	 * we use the last chunk of each pgd for the pgd_list.
 	 */
-	int i, fc_fd_ok = 0;
+	int i, user_kernel_ok = 0;
 	unsigned long max_va = 0;
 	unsigned long list_va =
 		((PGD_LIST_OFFSET / sizeof(pgd_t)) << PGDIR_SHIFT);
@@ -1044,13 +1048,13 @@
 			break;
 		if (range.start <= MEM_USER_INTRPT &&
 		    range.start + range.size >= MEM_HV_INTRPT)
-			fc_fd_ok = 1;
+			user_kernel_ok = 1;
 		if (range.start == 0)
 			max_va = range.size;
 		BUG_ON(range.start + range.size > list_va);
 	}
-	if (!fc_fd_ok)
-		early_panic("Hypervisor not configured for VAs 0xfc/0xfd\n");
+	if (!user_kernel_ok)
+		early_panic("Hypervisor not configured for user/kernel VAs\n");
 	if (max_va == 0)
 		early_panic("Hypervisor not configured for low VAs\n");
 	if (max_va < KERNEL_HIGH_VADDR)
@@ -1334,6 +1338,10 @@
 	pte_t *pte;
 
 	BUG_ON(pgd_addr_invalid(addr));
+	if (addr < VMALLOC_START || addr >= VMALLOC_END)
+		panic("PCPU addr %#lx outside vmalloc range %#lx..%#lx;"
+		      " try increasing CONFIG_VMALLOC_RESERVE\n",
+		      addr, VMALLOC_START, VMALLOC_END);
 
 	pgd = swapper_pg_dir + pgd_index(addr);
 	pud = pud_offset(pgd, addr);
diff --git a/arch/tile/kernel/signal.c b/arch/tile/kernel/signal.c
index ce183aa..fb28e85 100644
--- a/arch/tile/kernel/signal.c
+++ b/arch/tile/kernel/signal.c
@@ -41,8 +41,8 @@
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
 
-long _sys_sigaltstack(const stack_t __user *uss,
-		      stack_t __user *uoss, struct pt_regs *regs)
+SYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss,
+		stack_t __user *, uoss, struct pt_regs *, regs)
 {
 	return do_sigaltstack(uss, uoss, regs->sp);
 }
@@ -78,7 +78,7 @@
 }
 
 /* sigreturn() returns long since it restores r0 in the interrupted code. */
-long _sys_rt_sigreturn(struct pt_regs *regs)
+SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs)
 {
 	struct rt_sigframe __user *frame =
 		(struct rt_sigframe __user *)(regs->sp);
diff --git a/arch/tile/kernel/single_step.c b/arch/tile/kernel/single_step.c
index 5ec4b9c..1eb3b39 100644
--- a/arch/tile/kernel/single_step.c
+++ b/arch/tile/kernel/single_step.c
@@ -15,7 +15,7 @@
  * Derived from iLib's single-stepping code.
  */
 
-#ifndef __tilegx__   /* No support for single-step yet. */
+#ifndef __tilegx__   /* Hardware support for single step unavailable. */
 
 /* These functions are only used on the TILE platform */
 #include <linux/slab.h>
@@ -660,4 +660,75 @@
 		regs->pc += 8;
 }
 
+#else
+#include <linux/smp.h>
+#include <linux/ptrace.h>
+#include <arch/spr_def.h>
+
+static DEFINE_PER_CPU(unsigned long, ss_saved_pc);
+
+
+/*
+ * Called directly on the occasion of an interrupt.
+ *
+ * If the process doesn't have single step set, then we use this as an
+ * opportunity to turn single step off.
+ *
+ * It has been mentioned that we could conditionally turn off single stepping
+ * on each entry into the kernel and rely on single_step_once to turn it
+ * on for the processes that matter (as we already do), but this
+ * implementation is somewhat more efficient in that we muck with registers
+ * once on a bum interrupt rather than on every entry into the kernel.
+ *
+ * If SINGLE_STEP_CONTROL_K has CANCELED set, then an interrupt occurred,
+ * so we have to run through this process again before we can say that an
+ * instruction has executed.
+ *
+ * swint will set CANCELED, but it's a legitimate instruction.  Fortunately
+ * it changes the PC.  If it hasn't changed, then we know that the interrupt
+ * wasn't generated by swint and we'll need to run this process again before
+ * we can say an instruction has executed.
+ *
+ * If either CANCELED == 0 or the PC's changed, we send out SIGTRAPs and get
+ * on with our lives.
+ */
+
+void gx_singlestep_handle(struct pt_regs *regs, int fault_num)
+{
+	unsigned long *ss_pc = &__get_cpu_var(ss_saved_pc);
+	struct thread_info *info = (void *)current_thread_info();
+	int is_single_step = test_ti_thread_flag(info, TIF_SINGLESTEP);
+	unsigned long control = __insn_mfspr(SPR_SINGLE_STEP_CONTROL_K);
+
+	if (is_single_step == 0) {
+		__insn_mtspr(SPR_SINGLE_STEP_EN_K_K, 0);
+
+	} else if ((*ss_pc != regs->pc) ||
+		   (!(control & SPR_SINGLE_STEP_CONTROL_1__CANCELED_MASK))) {
+
+		ptrace_notify(SIGTRAP);
+		control |= SPR_SINGLE_STEP_CONTROL_1__CANCELED_MASK;
+		control |= SPR_SINGLE_STEP_CONTROL_1__INHIBIT_MASK;
+		__insn_mtspr(SPR_SINGLE_STEP_CONTROL_K, control);
+	}
+}
+
+
+/*
+ * Called from need_singlestep.  Set up the control registers and the enable
+ * register, then return back.
+ */
+
+void single_step_once(struct pt_regs *regs)
+{
+	unsigned long *ss_pc = &__get_cpu_var(ss_saved_pc);
+	unsigned long control = __insn_mfspr(SPR_SINGLE_STEP_CONTROL_K);
+
+	*ss_pc = regs->pc;
+	control |= SPR_SINGLE_STEP_CONTROL_1__CANCELED_MASK;
+	control |= SPR_SINGLE_STEP_CONTROL_1__INHIBIT_MASK;
+	__insn_mtspr(SPR_SINGLE_STEP_CONTROL_K, control);
+	__insn_mtspr(SPR_SINGLE_STEP_EN_K_K, 1 << USER_PL);
+}
+
 #endif /* !__tilegx__ */
diff --git a/arch/tile/kernel/smp.c b/arch/tile/kernel/smp.c
index 1cb5ec7..75255d9 100644
--- a/arch/tile/kernel/smp.c
+++ b/arch/tile/kernel/smp.c
@@ -212,7 +212,7 @@
 
 		tile.x = cpu_x(cpu);
 		tile.y = cpu_y(cpu);
-		if (hv_get_ipi_pte(tile, 1, &pte) != 0)
+		if (hv_get_ipi_pte(tile, KERNEL_PL, &pte) != 0)
 			panic("Failed to initialize IPI for cpu %d\n", cpu);
 
 		offset = hv_pte_get_pfn(pte) << PAGE_SHIFT;
diff --git a/arch/tile/kernel/stack.c b/arch/tile/kernel/stack.c
index ea2e0ce..0d54106b 100644
--- a/arch/tile/kernel/stack.c
+++ b/arch/tile/kernel/stack.c
@@ -30,6 +30,10 @@
 #include <arch/abi.h>
 #include <arch/interrupts.h>
 
+#define KBT_ONGOING	0  /* Backtrace still ongoing */
+#define KBT_DONE	1  /* Backtrace cleanly completed */
+#define KBT_RUNNING	2  /* Can't run backtrace on a running task */
+#define KBT_LOOP	3  /* Backtrace entered a loop */
 
 /* Is address on the specified kernel stack? */
 static int in_kernel_stack(struct KBacktraceIterator *kbt, VirtualAddress sp)
@@ -207,11 +211,11 @@
 	for (;;) {
 		do {
 			if (!KBacktraceIterator_is_sigreturn(kbt))
-				return 1;
+				return KBT_ONGOING;
 		} while (backtrace_next(&kbt->it));
 
 		if (!KBacktraceIterator_restart(kbt))
-			return 0;
+			return KBT_DONE;
 	}
 }
 
@@ -264,7 +268,7 @@
 	kbt->pgtable = NULL;
 	kbt->verbose = 0;   /* override in caller if desired */
 	kbt->profile = 0;   /* override in caller if desired */
-	kbt->end = 0;
+	kbt->end = KBT_ONGOING;
 	kbt->new_context = 0;
 	if (is_current) {
 		HV_PhysAddr pgdir_pa = hv_inquire_context().page_table;
@@ -290,7 +294,7 @@
 	if (regs == NULL) {
 		if (is_current || t->state == TASK_RUNNING) {
 			/* Can't do this; we need registers */
-			kbt->end = 1;
+			kbt->end = KBT_RUNNING;
 			return;
 		}
 		pc = get_switch_to_pc();
@@ -305,26 +309,29 @@
 	}
 
 	backtrace_init(&kbt->it, read_memory_func, kbt, pc, lr, sp, r52);
-	kbt->end = !KBacktraceIterator_next_item_inclusive(kbt);
+	kbt->end = KBacktraceIterator_next_item_inclusive(kbt);
 }
 EXPORT_SYMBOL(KBacktraceIterator_init);
 
 int KBacktraceIterator_end(struct KBacktraceIterator *kbt)
 {
-	return kbt->end;
+	return kbt->end != KBT_ONGOING;
 }
 EXPORT_SYMBOL(KBacktraceIterator_end);
 
 void KBacktraceIterator_next(struct KBacktraceIterator *kbt)
 {
+	VirtualAddress old_pc = kbt->it.pc, old_sp = kbt->it.sp;
 	kbt->new_context = 0;
-	if (!backtrace_next(&kbt->it) &&
-	    !KBacktraceIterator_restart(kbt)) {
-			kbt->end = 1;
-			return;
-		}
-
-	kbt->end = !KBacktraceIterator_next_item_inclusive(kbt);
+	if (!backtrace_next(&kbt->it) && !KBacktraceIterator_restart(kbt)) {
+		kbt->end = KBT_DONE;
+		return;
+	}
+	kbt->end = KBacktraceIterator_next_item_inclusive(kbt);
+	if (old_pc == kbt->it.pc && old_sp == kbt->it.sp) {
+		/* Trapped in a loop; give up. */
+		kbt->end = KBT_LOOP;
+	}
 }
 EXPORT_SYMBOL(KBacktraceIterator_next);
 
@@ -387,6 +394,8 @@
 			break;
 		}
 	}
+	if (kbt->end == KBT_LOOP)
+		pr_err("Stack dump stopped; next frame identical to this one\n");
 	if (headers)
 		pr_err("Stack dump complete\n");
 }
diff --git a/arch/tile/kernel/sys.c b/arch/tile/kernel/sys.c
index f0f87ea..7e76466 100644
--- a/arch/tile/kernel/sys.c
+++ b/arch/tile/kernel/sys.c
@@ -110,6 +110,15 @@
 #define sys_sync_file_range sys_sync_file_range2
 #endif
 
+/* Call the trampolines to manage pt_regs where necessary. */
+#define sys_execve _sys_execve
+#define sys_sigaltstack _sys_sigaltstack
+#define sys_rt_sigreturn _sys_rt_sigreturn
+#define sys_clone _sys_clone
+#ifndef __tilegx__
+#define sys_cmpxchg_badaddr _sys_cmpxchg_badaddr
+#endif
+
 /*
  * Note that we can't include <linux/unistd.h> here since the header
  * guard will defeat us; <asm/unistd.h> checks for __SYSCALL as well.
diff --git a/arch/tile/kernel/traps.c b/arch/tile/kernel/traps.c
index 0f362dc..5474fc2 100644
--- a/arch/tile/kernel/traps.c
+++ b/arch/tile/kernel/traps.c
@@ -260,7 +260,7 @@
 		address = regs->pc;
 		break;
 	case INT_UNALIGN_DATA:
-#ifndef __tilegx__  /* FIXME: GX: no single-step yet */
+#ifndef __tilegx__  /* Emulated support for single step debugging */
 		if (unaligned_fixup >= 0) {
 			struct single_step_state *state =
 				current_thread_info()->step_state;
@@ -278,7 +278,7 @@
 	case INT_DOUBLE_FAULT:
 		/*
 		 * For double fault, "reason" is actually passed as
-		 * SYSTEM_SAVE_1_2, the hypervisor's double-fault info, so
+		 * SYSTEM_SAVE_K_2, the hypervisor's double-fault info, so
 		 * we can provide the original fault number rather than
 		 * the uninteresting "INT_DOUBLE_FAULT" so the user can
 		 * learn what actually struck while PL0 ICS was set.
diff --git a/arch/tile/kvm/Kconfig b/arch/tile/kvm/Kconfig
new file mode 100644
index 0000000..b88f9c0
--- /dev/null
+++ b/arch/tile/kvm/Kconfig
@@ -0,0 +1,38 @@
+#
+# KVM configuration
+#
+
+source "virt/kvm/Kconfig"
+
+menuconfig VIRTUALIZATION
+	bool "Virtualization"
+	---help---
+	  Say Y here to get to see options for using your Linux host to run
+	  other operating systems inside virtual machines (guests).
+	  This option alone does not add any kernel code.
+
+	  If you say N, all options in this submenu will be skipped and
+	  disabled.
+
+if VIRTUALIZATION
+
+config KVM
+	tristate "Kernel-based Virtual Machine (KVM) support"
+	depends on HAVE_KVM && MODULES && EXPERIMENTAL
+	select PREEMPT_NOTIFIERS
+	select ANON_INODES
+	---help---
+	  Support hosting paravirtualized guest machines.
+
+	  This module provides access to the hardware capabilities through
+	  a character device node named /dev/kvm.
+
+	  To compile this as a module, choose M here: the module
+	  will be called kvm.
+
+	  If unsure, say N.
+
+source drivers/vhost/Kconfig
+source drivers/virtio/Kconfig
+
+endif # VIRTUALIZATION
diff --git a/arch/tile/lib/Makefile b/arch/tile/lib/Makefile
index 746dc81..93122d5 100644
--- a/arch/tile/lib/Makefile
+++ b/arch/tile/lib/Makefile
@@ -3,8 +3,8 @@
 #
 
 lib-y = cacheflush.o checksum.o cpumask.o delay.o \
-	mb_incoherent.o uaccess.o \
-	memcpy_$(BITS).o memchr_$(BITS).o memmove_$(BITS).o memset_$(BITS).o \
+	mb_incoherent.o uaccess.o memmove.o \
+	memcpy_$(BITS).o memchr_$(BITS).o memset_$(BITS).o \
 	strchr_$(BITS).o strlen_$(BITS).o
 
 ifeq ($(CONFIG_TILEGX),y)
diff --git a/arch/tile/lib/atomic_32.c b/arch/tile/lib/atomic_32.c
index 8040b42..7a5cc70 100644
--- a/arch/tile/lib/atomic_32.c
+++ b/arch/tile/lib/atomic_32.c
@@ -300,7 +300,7 @@
 #else /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */
 
 	/* Validate power-of-two and "bigger than cpus" assumption */
-	BUG_ON(ATOMIC_HASH_SIZE & (ATOMIC_HASH_SIZE-1));
+	BUILD_BUG_ON(ATOMIC_HASH_SIZE & (ATOMIC_HASH_SIZE-1));
 	BUG_ON(ATOMIC_HASH_SIZE < nr_cpu_ids);
 
 	/*
@@ -314,17 +314,17 @@
 	BUG_ON((unsigned long)atomic_locks % PAGE_SIZE != 0);
 
 	/* The locks must all fit on one page. */
-	BUG_ON(ATOMIC_HASH_SIZE * sizeof(int) > PAGE_SIZE);
+	BUILD_BUG_ON(ATOMIC_HASH_SIZE * sizeof(int) > PAGE_SIZE);
 
 	/*
 	 * We use the page offset of the atomic value's address as
 	 * an index into atomic_locks, excluding the low 3 bits.
 	 * That should not produce more indices than ATOMIC_HASH_SIZE.
 	 */
-	BUG_ON((PAGE_SIZE >> 3) > ATOMIC_HASH_SIZE);
+	BUILD_BUG_ON((PAGE_SIZE >> 3) > ATOMIC_HASH_SIZE);
 
 #endif /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */
 
 	/* The futex code makes this assumption, so we validate it here. */
-	BUG_ON(sizeof(atomic_t) != sizeof(int));
+	BUILD_BUG_ON(sizeof(atomic_t) != sizeof(int));
 }
diff --git a/arch/tile/lib/exports.c b/arch/tile/lib/exports.c
index ce5dbf5..1509c55 100644
--- a/arch/tile/lib/exports.c
+++ b/arch/tile/lib/exports.c
@@ -45,6 +45,9 @@
 EXPORT_SYMBOL(__copy_in_user_inatomic);
 #endif
 
+/* arch/tile/lib/mb_incoherent.S */
+EXPORT_SYMBOL(__mb_incoherent);
+
 /* hypervisor glue */
 #include <hv/hypervisor.h>
 EXPORT_SYMBOL(hv_dev_open);
diff --git a/arch/tile/lib/memcpy_32.S b/arch/tile/lib/memcpy_32.S
index 30c3b7e..2a419a6 100644
--- a/arch/tile/lib/memcpy_32.S
+++ b/arch/tile/lib/memcpy_32.S
@@ -10,14 +10,16 @@
  *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
  *   NON INFRINGEMENT.  See the GNU General Public License for
  *   more details.
- *
- * This file shares the implementation of the userspace memcpy and
- * the kernel's memcpy, copy_to_user and copy_from_user.
  */
 
 #include <arch/chip.h>
 
 
+/*
+ * This file shares the implementation of the userspace memcpy and
+ * the kernel's memcpy, copy_to_user and copy_from_user.
+ */
+
 #include <linux/linkage.h>
 
 /* On TILE64, we wrap these functions via arch/tile/lib/memcpy_tile64.c */
@@ -53,9 +55,9 @@
  */
 ENTRY(__copy_from_user_inatomic)
 .type __copy_from_user_inatomic, @function
-        FEEDBACK_ENTER_EXPLICIT(__copy_from_user_inatomic, \
+	FEEDBACK_ENTER_EXPLICIT(__copy_from_user_inatomic, \
 	  .text.memcpy_common, \
-          .Lend_memcpy_common - __copy_from_user_inatomic)
+	  .Lend_memcpy_common - __copy_from_user_inatomic)
 	{ movei r29, IS_COPY_FROM_USER; j memcpy_common }
 	.size __copy_from_user_inatomic, . - __copy_from_user_inatomic
 
@@ -64,7 +66,7 @@
  */
 ENTRY(__copy_from_user_zeroing)
 .type __copy_from_user_zeroing, @function
-        FEEDBACK_REENTER(__copy_from_user_inatomic)
+	FEEDBACK_REENTER(__copy_from_user_inatomic)
 	{ movei r29, IS_COPY_FROM_USER_ZEROING; j memcpy_common }
 	.size __copy_from_user_zeroing, . - __copy_from_user_zeroing
 
@@ -74,13 +76,13 @@
  */
 ENTRY(__copy_to_user_inatomic)
 .type __copy_to_user_inatomic, @function
-        FEEDBACK_REENTER(__copy_from_user_inatomic)
+	FEEDBACK_REENTER(__copy_from_user_inatomic)
 	{ movei r29, IS_COPY_TO_USER; j memcpy_common }
 	.size __copy_to_user_inatomic, . - __copy_to_user_inatomic
 
 ENTRY(memcpy)
 .type memcpy, @function
-        FEEDBACK_REENTER(__copy_from_user_inatomic)
+	FEEDBACK_REENTER(__copy_from_user_inatomic)
 	{ movei r29, IS_MEMCPY }
 	.size memcpy, . - memcpy
 	/* Fall through */
@@ -157,35 +159,35 @@
 	{ addi r3, r1, 60; andi r9, r9, -64 }
 
 #if CHIP_HAS_WH64()
-        /* No need to prefetch dst, we'll just do the wh64
-         * right before we copy a line.
+	/* No need to prefetch dst, we'll just do the wh64
+	 * right before we copy a line.
 	 */
 #endif
 
 EX:	{ lw r5, r3; addi r3, r3, 64; movei r4, 1 }
-        /* Intentionally stall for a few cycles to leave L2 cache alone. */
-        { bnzt zero, .; move r27, lr }
+	/* Intentionally stall for a few cycles to leave L2 cache alone. */
+	{ bnzt zero, .; move r27, lr }
 EX:	{ lw r6, r3; addi r3, r3, 64 }
-        /* Intentionally stall for a few cycles to leave L2 cache alone. */
-        { bnzt zero, . }
+	/* Intentionally stall for a few cycles to leave L2 cache alone. */
+	{ bnzt zero, . }
 EX:	{ lw r7, r3; addi r3, r3, 64 }
 #if !CHIP_HAS_WH64()
-        /* Prefetch the dest */
-        /* Intentionally stall for a few cycles to leave L2 cache alone. */
-        { bnzt zero, . }
-        /* Use a real load to cause a TLB miss if necessary.  We aren't using
-         * r28, so this should be fine.
-         */
+	/* Prefetch the dest */
+	/* Intentionally stall for a few cycles to leave L2 cache alone. */
+	{ bnzt zero, . }
+	/* Use a real load to cause a TLB miss if necessary.  We aren't using
+	 * r28, so this should be fine.
+	 */
 EX:	{ lw r28, r9; addi r9, r9, 64 }
-        /* Intentionally stall for a few cycles to leave L2 cache alone. */
-        { bnzt zero, . }
-        { prefetch r9; addi r9, r9, 64 }
-        /* Intentionally stall for a few cycles to leave L2 cache alone. */
-        { bnzt zero, . }
-        { prefetch r9; addi r9, r9, 64 }
+	/* Intentionally stall for a few cycles to leave L2 cache alone. */
+	{ bnzt zero, . }
+	{ prefetch r9; addi r9, r9, 64 }
+	/* Intentionally stall for a few cycles to leave L2 cache alone. */
+	{ bnzt zero, . }
+	{ prefetch r9; addi r9, r9, 64 }
 #endif
-        /* Intentionally stall for a few cycles to leave L2 cache alone. */
-        { bz zero, .Lbig_loop2 }
+	/* Intentionally stall for a few cycles to leave L2 cache alone. */
+	{ bz zero, .Lbig_loop2 }
 
 	/* On entry to this loop:
 	 * - r0 points to the start of dst line 0
@@ -197,7 +199,7 @@
 	 *   to some "safe" recently loaded address.
 	 * - r5 contains *(r1 + 60)       [i.e. last word of source line 0]
 	 * - r6 contains *(r1 + 64 + 60)  [i.e. last word of source line 1]
-         * - r9 contains ((r0 + 63) & -64)
+	 * - r9 contains ((r0 + 63) & -64)
 	 *     [start of next dst cache line.]
 	 */
 
@@ -208,137 +210,137 @@
 	/* Copy line 0, first stalling until r5 is ready. */
 EX:	{ move r12, r5; lw r16, r1 }
 	{ bz r4, .Lcopy_8_check; slti_u r8, r2, 8 }
-        /* Prefetch several lines ahead. */
+	/* Prefetch several lines ahead. */
 EX:	{ lw r5, r3; addi r3, r3, 64 }
-        { jal .Lcopy_line }
+	{ jal .Lcopy_line }
 
 	/* Copy line 1, first stalling until r6 is ready. */
 EX:	{ move r12, r6; lw r16, r1 }
 	{ bz r4, .Lcopy_8_check; slti_u r8, r2, 8 }
-        /* Prefetch several lines ahead. */
+	/* Prefetch several lines ahead. */
 EX:	{ lw r6, r3; addi r3, r3, 64 }
 	{ jal .Lcopy_line }
 
 	/* Copy line 2, first stalling until r7 is ready. */
 EX:	{ move r12, r7; lw r16, r1 }
 	{ bz r4, .Lcopy_8_check; slti_u r8, r2, 8 }
-        /* Prefetch several lines ahead. */
+	/* Prefetch several lines ahead. */
 EX:	{ lw r7, r3; addi r3, r3, 64 }
-        /* Use up a caches-busy cycle by jumping back to the top of the
-         * loop. Might as well get it out of the way now.
-         */
-        { j .Lbig_loop }
+	/* Use up a caches-busy cycle by jumping back to the top of the
+	 * loop. Might as well get it out of the way now.
+	 */
+	{ j .Lbig_loop }
 
 
 	/* On entry:
 	 * - r0 points to the destination line.
 	 * - r1 points to the source line.
-         * - r3 is the next prefetch address.
+	 * - r3 is the next prefetch address.
 	 * - r9 holds the last address used for wh64.
 	 * - r12 = WORD_15
-         * - r16 = WORD_0.
-         * - r17 == r1 + 16.
-         * - r27 holds saved lr to restore.
+	 * - r16 = WORD_0.
+	 * - r17 == r1 + 16.
+	 * - r27 holds saved lr to restore.
 	 *
 	 * On exit:
 	 * - r0 is incremented by 64.
 	 * - r1 is incremented by 64, unless that would point to a word
-         *   beyond the end of the source array, in which case it is redirected
-         *   to point to an arbitrary word already in the cache.
+	 *   beyond the end of the source array, in which case it is redirected
+	 *   to point to an arbitrary word already in the cache.
 	 * - r2 is decremented by 64.
-         * - r3 is unchanged, unless it points to a word beyond the
-         *   end of the source array, in which case it is redirected
-         *   to point to an arbitrary word already in the cache.
-         *   Redirecting is OK since if we are that close to the end
-         *   of the array we will not come back to this subroutine
-         *   and use the contents of the prefetched address.
+	 * - r3 is unchanged, unless it points to a word beyond the
+	 *   end of the source array, in which case it is redirected
+	 *   to point to an arbitrary word already in the cache.
+	 *   Redirecting is OK since if we are that close to the end
+	 *   of the array we will not come back to this subroutine
+	 *   and use the contents of the prefetched address.
 	 * - r4 is nonzero iff r2 >= 64.
-         * - r9 is incremented by 64, unless it points beyond the
-         *   end of the last full destination cache line, in which
-         *   case it is redirected to a "safe address" that can be
-         *   clobbered (sp - 64)
+	 * - r9 is incremented by 64, unless it points beyond the
+	 *   end of the last full destination cache line, in which
+	 *   case it is redirected to a "safe address" that can be
+	 *   clobbered (sp - 64)
 	 * - lr contains the value in r27.
 	 */
 
 /* r26 unused */
 
 .Lcopy_line:
-        /* TODO: when r3 goes past the end, we would like to redirect it
-         * to prefetch the last partial cache line (if any) just once, for the
-         * benefit of the final cleanup loop. But we don't want to
-         * prefetch that line more than once, or subsequent prefetches
-         * will go into the RTF. But then .Lbig_loop should unconditionally
-         * branch to top of loop to execute final prefetch, and its
-         * nop should become a conditional branch.
-         */
+	/* TODO: when r3 goes past the end, we would like to redirect it
+	 * to prefetch the last partial cache line (if any) just once, for the
+	 * benefit of the final cleanup loop. But we don't want to
+	 * prefetch that line more than once, or subsequent prefetches
+	 * will go into the RTF. But then .Lbig_loop should unconditionally
+	 * branch to top of loop to execute final prefetch, and its
+	 * nop should become a conditional branch.
+	 */
 
-        /* We need two non-memory cycles here to cover the resources
-         * used by the loads initiated by the caller.
-         */
-        { add r15, r1, r2 }
+	/* We need two non-memory cycles here to cover the resources
+	 * used by the loads initiated by the caller.
+	 */
+	{ add r15, r1, r2 }
 .Lcopy_line2:
-        { slt_u r13, r3, r15; addi r17, r1, 16 }
+	{ slt_u r13, r3, r15; addi r17, r1, 16 }
 
-        /* NOTE: this will stall for one cycle as L1 is busy. */
+	/* NOTE: this will stall for one cycle as L1 is busy. */
 
-        /* Fill second L1D line. */
+	/* Fill second L1D line. */
 EX:	{ lw r17, r17; addi r1, r1, 48; mvz r3, r13, r1 } /* r17 = WORD_4 */
 
 #if CHIP_HAS_WH64()
-        /* Prepare destination line for writing. */
+	/* Prepare destination line for writing. */
 EX:	{ wh64 r9; addi r9, r9, 64 }
 #else
-        /* Prefetch dest line */
+	/* Prefetch dest line */
 	{ prefetch r9; addi r9, r9, 64 }
 #endif
-        /* Load seven words that are L1D hits to cover wh64 L2 usage. */
+	/* Load seven words that are L1D hits to cover wh64 L2 usage. */
 
-        /* Load the three remaining words from the last L1D line, which
-         * we know has already filled the L1D.
-         */
+	/* Load the three remaining words from the last L1D line, which
+	 * we know has already filled the L1D.
+	 */
 EX:	{ lw r4, r1;  addi r1, r1, 4;   addi r20, r1, 16 }   /* r4 = WORD_12 */
 EX:	{ lw r8, r1;  addi r1, r1, 4;   slt_u r13, r20, r15 }/* r8 = WORD_13 */
 EX:	{ lw r11, r1; addi r1, r1, -52; mvz r20, r13, r1 }  /* r11 = WORD_14 */
 
-        /* Load the three remaining words from the first L1D line, first
-         * stalling until it has filled by "looking at" r16.
-         */
+	/* Load the three remaining words from the first L1D line, first
+	 * stalling until it has filled by "looking at" r16.
+	 */
 EX:	{ lw r13, r1; addi r1, r1, 4; move zero, r16 }   /* r13 = WORD_1 */
 EX:	{ lw r14, r1; addi r1, r1, 4 }                   /* r14 = WORD_2 */
 EX:	{ lw r15, r1; addi r1, r1, 8; addi r10, r0, 60 } /* r15 = WORD_3 */
 
-        /* Load second word from the second L1D line, first
-         * stalling until it has filled by "looking at" r17.
-         */
+	/* Load second word from the second L1D line, first
+	 * stalling until it has filled by "looking at" r17.
+	 */
 EX:	{ lw r19, r1; addi r1, r1, 4; move zero, r17 }  /* r19 = WORD_5 */
 
-        /* Store last word to the destination line, potentially dirtying it
-         * for the first time, which keeps the L2 busy for two cycles.
-         */
+	/* Store last word to the destination line, potentially dirtying it
+	 * for the first time, which keeps the L2 busy for two cycles.
+	 */
 EX:	{ sw r10, r12 }                                 /* store(WORD_15) */
 
-        /* Use two L1D hits to cover the sw L2 access above. */
+	/* Use two L1D hits to cover the sw L2 access above. */
 EX:	{ lw r10, r1; addi r1, r1, 4 }                  /* r10 = WORD_6 */
 EX:	{ lw r12, r1; addi r1, r1, 4 }                  /* r12 = WORD_7 */
 
-        /* Fill third L1D line. */
+	/* Fill third L1D line. */
 EX:	{ lw r18, r1; addi r1, r1, 4 }                  /* r18 = WORD_8 */
 
-        /* Store first L1D line. */
+	/* Store first L1D line. */
 EX:	{ sw r0, r16; addi r0, r0, 4; add r16, r0, r2 } /* store(WORD_0) */
 EX:	{ sw r0, r13; addi r0, r0, 4; andi r16, r16, -64 } /* store(WORD_1) */
 EX:	{ sw r0, r14; addi r0, r0, 4; slt_u r16, r9, r16 } /* store(WORD_2) */
 #if CHIP_HAS_WH64()
 EX:	{ sw r0, r15; addi r0, r0, 4; addi r13, sp, -64 } /* store(WORD_3) */
 #else
-        /* Back up the r9 to a cache line we are already storing to
+	/* Back up the r9 to a cache line we are already storing to
 	 * if it gets past the end of the dest vector.  Strictly speaking,
 	 * we don't need to back up to the start of a cache line, but it's free
 	 * and tidy, so why not?
-         */
+	 */
 EX:	{ sw r0, r15; addi r0, r0, 4; andi r13, r0, -64 } /* store(WORD_3) */
 #endif
-        /* Store second L1D line. */
+	/* Store second L1D line. */
 EX:	{ sw r0, r17; addi r0, r0, 4; mvz r9, r16, r13 }/* store(WORD_4) */
 EX:	{ sw r0, r19; addi r0, r0, 4 }                  /* store(WORD_5) */
 EX:	{ sw r0, r10; addi r0, r0, 4 }                  /* store(WORD_6) */
@@ -348,30 +350,30 @@
 EX:	{ lw r14, r1; addi r1, r1, 4 }                  /* r14 = WORD_10 */
 EX:	{ lw r15, r1; move r1, r20   }                  /* r15 = WORD_11 */
 
-        /* Store third L1D line. */
+	/* Store third L1D line. */
 EX:	{ sw r0, r18; addi r0, r0, 4 }                  /* store(WORD_8) */
 EX:	{ sw r0, r13; addi r0, r0, 4 }                  /* store(WORD_9) */
 EX:	{ sw r0, r14; addi r0, r0, 4 }                  /* store(WORD_10) */
 EX:	{ sw r0, r15; addi r0, r0, 4 }                  /* store(WORD_11) */
 
-        /* Store rest of fourth L1D line. */
+	/* Store rest of fourth L1D line. */
 EX:	{ sw r0, r4;  addi r0, r0, 4 }                  /* store(WORD_12) */
-        {
+	{
 EX:	sw r0, r8                                       /* store(WORD_13) */
-        addi r0, r0, 4
+	addi r0, r0, 4
 	/* Will r2 be > 64 after we subtract 64 below? */
-        shri r4, r2, 7
-        }
-        {
+	shri r4, r2, 7
+	}
+	{
 EX:	sw r0, r11                                      /* store(WORD_14) */
-        addi r0, r0, 8
-        /* Record 64 bytes successfully copied. */
-        addi r2, r2, -64
-        }
+	addi r0, r0, 8
+	/* Record 64 bytes successfully copied. */
+	addi r2, r2, -64
+	}
 
 	{ jrp lr; move lr, r27 }
 
-        /* Convey to the backtrace library that the stack frame is size
+	/* Convey to the backtrace library that the stack frame is size
 	 * zero, and the real return address is on the stack rather than
 	 * in 'lr'.
 	 */
diff --git a/arch/tile/lib/memmove_32.c b/arch/tile/lib/memmove.c
similarity index 100%
rename from arch/tile/lib/memmove_32.c
rename to arch/tile/lib/memmove.c
diff --git a/arch/tile/lib/memset_32.c b/arch/tile/lib/memset_32.c
index d014c1f..57dbb3a 100644
--- a/arch/tile/lib/memset_32.c
+++ b/arch/tile/lib/memset_32.c
@@ -18,6 +18,7 @@
 #include <linux/string.h>
 #include <linux/module.h>
 
+#undef memset
 
 void *memset(void *s, int c, size_t n)
 {
diff --git a/arch/tile/lib/strlen_32.c b/arch/tile/lib/strlen_32.c
index f26f88e..4974292 100644
--- a/arch/tile/lib/strlen_32.c
+++ b/arch/tile/lib/strlen_32.c
@@ -16,6 +16,8 @@
 #include <linux/string.h>
 #include <linux/module.h>
 
+#undef strlen
+
 size_t strlen(const char *s)
 {
 	/* Get an aligned pointer. */
diff --git a/arch/tile/mm/fault.c b/arch/tile/mm/fault.c
index 704f3e8..f295b4a 100644
--- a/arch/tile/mm/fault.c
+++ b/arch/tile/mm/fault.c
@@ -66,10 +66,10 @@
 #ifndef __tilegx__
 /*
  * Synthesize the fault a PL0 process would get by doing a word-load of
- * an unaligned address or a high kernel address.  Called indirectly
- * from sys_cmpxchg() in kernel/intvec.S.
+ * an unaligned address or a high kernel address.
  */
-int _sys_cmpxchg_badaddr(unsigned long address, struct pt_regs *regs)
+SYSCALL_DEFINE2(cmpxchg_badaddr, unsigned long, address,
+		struct pt_regs *, regs)
 {
 	if (address >= PAGE_OFFSET)
 		force_sig_info_fault(SIGSEGV, SEGV_MAPERR, address,
@@ -563,10 +563,10 @@
 /*
  * When we take an ITLB or DTLB fault or access violation in the
  * supervisor while the critical section bit is set, the hypervisor is
- * reluctant to write new values into the EX_CONTEXT_1_x registers,
+ * reluctant to write new values into the EX_CONTEXT_K_x registers,
  * since that might indicate we have not yet squirreled the SPR
  * contents away and can thus safely take a recursive interrupt.
- * Accordingly, the hypervisor passes us the PC via SYSTEM_SAVE_1_2.
+ * Accordingly, the hypervisor passes us the PC via SYSTEM_SAVE_K_2.
  *
  * Note that this routine is called before homecache_tlb_defer_enter(),
  * which means that we can properly unlock any atomics that might
@@ -610,7 +610,7 @@
 	 * fault.  We didn't set up a kernel stack on initial entry to
 	 * sys_cmpxchg, but instead had one set up by the fault, which
 	 * (because sys_cmpxchg never releases ICS) came to us via the
-	 * SYSTEM_SAVE_1_2 mechanism, and thus EX_CONTEXT_1_[01] are
+	 * SYSTEM_SAVE_K_2 mechanism, and thus EX_CONTEXT_K_[01] are
 	 * still referencing the original user code.  We release the
 	 * atomic lock and rewrite pt_regs so that it appears that we
 	 * came from user-space directly, and after we finish the
diff --git a/arch/tile/mm/highmem.c b/arch/tile/mm/highmem.c
index 12ab137..8ef6595 100644
--- a/arch/tile/mm/highmem.c
+++ b/arch/tile/mm/highmem.c
@@ -56,50 +56,6 @@
 }
 EXPORT_SYMBOL(kunmap);
 
-static void debug_kmap_atomic_prot(enum km_type type)
-{
-#ifdef CONFIG_DEBUG_HIGHMEM
-	static unsigned warn_count = 10;
-
-	if (unlikely(warn_count == 0))
-		return;
-
-	if (unlikely(in_interrupt())) {
-		if (in_irq()) {
-			if (type != KM_IRQ0 && type != KM_IRQ1 &&
-			    type != KM_BIO_SRC_IRQ &&
-			    /* type != KM_BIO_DST_IRQ && */
-			    type != KM_BOUNCE_READ) {
-				WARN_ON(1);
-				warn_count--;
-			}
-		} else if (!irqs_disabled()) {	/* softirq */
-			if (type != KM_IRQ0 && type != KM_IRQ1 &&
-			    type != KM_SOFTIRQ0 && type != KM_SOFTIRQ1 &&
-			    type != KM_SKB_SUNRPC_DATA &&
-			    type != KM_SKB_DATA_SOFTIRQ &&
-			    type != KM_BOUNCE_READ) {
-				WARN_ON(1);
-				warn_count--;
-			}
-		}
-	}
-
-	if (type == KM_IRQ0 || type == KM_IRQ1 || type == KM_BOUNCE_READ ||
-	    type == KM_BIO_SRC_IRQ /* || type == KM_BIO_DST_IRQ */) {
-		if (!irqs_disabled()) {
-			WARN_ON(1);
-			warn_count--;
-		}
-	} else if (type == KM_SOFTIRQ0 || type == KM_SOFTIRQ1) {
-		if (irq_count() == 0 && !irqs_disabled()) {
-			WARN_ON(1);
-			warn_count--;
-		}
-	}
-#endif
-}
-
 /*
  * Describe a single atomic mapping of a page on a given cpu at a
  * given address, and allow it to be linked into a list.
@@ -240,10 +196,10 @@
  * When holding an atomic kmap is is not legal to sleep, so atomic
  * kmaps are appropriate for short, tight code paths only.
  */
-void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
+void *kmap_atomic_prot(struct page *page, pgprot_t prot)
 {
-	enum fixed_addresses idx;
 	unsigned long vaddr;
+	int idx, type;
 	pte_t *pte;
 
 	/* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
@@ -255,8 +211,7 @@
 	if (!PageHighMem(page))
 		return page_address(page);
 
-	debug_kmap_atomic_prot(type);
-
+	type = kmap_atomic_idx_push();
 	idx = type + KM_TYPE_NR*smp_processor_id();
 	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
 	pte = kmap_get_pte(vaddr);
@@ -269,25 +224,31 @@
 }
 EXPORT_SYMBOL(kmap_atomic_prot);
 
-void *kmap_atomic(struct page *page, enum km_type type)
+void *__kmap_atomic(struct page *page)
 {
 	/* PAGE_NONE is a magic value that tells us to check immutability. */
 	return kmap_atomic_prot(page, type, PAGE_NONE);
 }
-EXPORT_SYMBOL(kmap_atomic);
+EXPORT_SYMBOL(__kmap_atomic);
 
-void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type)
+void __kunmap_atomic(void *kvaddr)
 {
 	unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
-	enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
 
-	/*
-	 * Force other mappings to Oops if they try to access this pte without
-	 * first remapping it.  Keeping stale mappings around is a bad idea.
-	 */
-	if (vaddr == __fix_to_virt(FIX_KMAP_BEGIN+idx)) {
+	if (vaddr >= __fix_to_virt(FIX_KMAP_END) &&
+	    vaddr <= __fix_to_virt(FIX_KMAP_BEGIN)) {
 		pte_t *pte = kmap_get_pte(vaddr);
 		pte_t pteval = *pte;
+		int idx, type;
+
+		type = kmap_atomic_idx_pop();
+		idx = type + KM_TYPE_NR*smp_processor_id();
+
+		/*
+		 * Force other mappings to Oops if they try to access this pte
+		 * without first remapping it.  Keeping stale mappings around
+		 * is a bad idea.
+		 */
 		BUG_ON(!pte_present(pteval) && !pte_migrating(pteval));
 		kmap_atomic_unregister(pte_page(pteval), vaddr);
 		kpte_clear_flush(pte, vaddr);
@@ -300,19 +261,19 @@
 	arch_flush_lazy_mmu_mode();
 	pagefault_enable();
 }
-EXPORT_SYMBOL(kunmap_atomic_notypecheck);
+EXPORT_SYMBOL(__kunmap_atomic);
 
 /*
  * This API is supposed to allow us to map memory without a "struct page".
  * Currently we don't support this, though this may change in the future.
  */
-void *kmap_atomic_pfn(unsigned long pfn, enum km_type type)
+void *kmap_atomic_pfn(unsigned long pfn)
 {
-	return kmap_atomic(pfn_to_page(pfn), type);
+	return kmap_atomic(pfn_to_page(pfn));
 }
-void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot)
+void *kmap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot)
 {
-	return kmap_atomic_prot(pfn_to_page(pfn), type, prot);
+	return kmap_atomic_prot(pfn_to_page(pfn), prot);
 }
 
 struct page *kmap_atomic_to_page(void *ptr)
diff --git a/arch/tile/mm/homecache.c b/arch/tile/mm/homecache.c
index fb3b4a5..d78df3a 100644
--- a/arch/tile/mm/homecache.c
+++ b/arch/tile/mm/homecache.c
@@ -37,6 +37,8 @@
 #include <asm/pgalloc.h>
 #include <asm/homecache.h>
 
+#include <arch/sim.h>
+
 #include "migrate.h"
 
 
@@ -217,13 +219,6 @@
 	return (length >= CHIP_L2_CACHE_SIZE()) ? HV_FLUSH_EVICT_L2 : length;
 }
 
-/* On the simulator, confirm lines have been evicted everywhere. */
-static void validate_lines_evicted(unsigned long pfn, size_t length)
-{
-	sim_syscall(SIM_SYSCALL_VALIDATE_LINES_EVICTED,
-		    (HV_PhysAddr)pfn << PAGE_SHIFT, length);
-}
-
 /* Flush a page out of whatever cache(s) it is in. */
 void homecache_flush_cache(struct page *page, int order)
 {
@@ -234,7 +229,7 @@
 
 	homecache_mask(page, pages, &home_mask);
 	flush_remote(pfn, length, &home_mask, 0, 0, 0, NULL, NULL, 0);
-	validate_lines_evicted(pfn, pages * PAGE_SIZE);
+	sim_validate_lines_evicted(PFN_PHYS(pfn), pages * PAGE_SIZE);
 }
 
 
diff --git a/arch/tile/mm/init.c b/arch/tile/mm/init.c
index d89c9ea..78e1982 100644
--- a/arch/tile/mm/init.c
+++ b/arch/tile/mm/init.c
@@ -1060,7 +1060,7 @@
 
 	/*
 	 * Free the pages mapped from 0xc0000000 that correspond to code
-	 * pages from 0xfd000000 that we won't use again after init.
+	 * pages from MEM_SV_INTRPT that we won't use again after init.
 	 */
 	free_init_pages("unused kernel text",
 			(unsigned long)_sinittext - text_delta,
diff --git a/arch/um/Kconfig.um b/arch/um/Kconfig.um
index ec2b8da..50d6aa2 100644
--- a/arch/um/Kconfig.um
+++ b/arch/um/Kconfig.um
@@ -120,6 +120,9 @@
 
 	  If you don't know what to do, say N.
 
+config GENERIC_HARDIRQS_NO__DO_IRQ
+	def_bool y
+
 config NR_CPUS
 	int "Maximum number of CPUs (2-32)"
 	range 2 32
@@ -147,3 +150,6 @@
 	  This option determines the size of UML kernel stacks.  They will
 	  be 1 << order pages.  The default is OK unless you're running Valgrind
 	  on UML, in which case, set this to 3.
+
+config NO_DMA
+	def_bool y
diff --git a/arch/um/defconfig b/arch/um/defconfig
index 6bd456f..564f3de 100644
--- a/arch/um/defconfig
+++ b/arch/um/defconfig
@@ -566,7 +566,6 @@
 # CONFIG_CRC7 is not set
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
-CONFIG_HAS_DMA=y
 
 #
 # SCSI device support
diff --git a/arch/um/include/asm/dma-mapping.h b/arch/um/include/asm/dma-mapping.h
deleted file mode 100644
index 1f469e80..0000000
--- a/arch/um/include/asm/dma-mapping.h
+++ /dev/null
@@ -1,112 +0,0 @@
-#ifndef _ASM_DMA_MAPPING_H
-#define _ASM_DMA_MAPPING_H
-
-#include <asm/scatterlist.h>
-
-static inline int
-dma_supported(struct device *dev, u64 mask)
-{
-	BUG();
-	return(0);
-}
-
-static inline int
-dma_set_mask(struct device *dev, u64 dma_mask)
-{
-	BUG();
-	return(0);
-}
-
-static inline void *
-dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
-		   gfp_t flag)
-{
-	BUG();
-	return((void *) 0);
-}
-
-static inline void
-dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
-		  dma_addr_t dma_handle)
-{
-	BUG();
-}
-
-static inline dma_addr_t
-dma_map_single(struct device *dev, void *cpu_addr, size_t size,
-	       enum dma_data_direction direction)
-{
-	BUG();
-	return(0);
-}
-
-static inline void
-dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
-		 enum dma_data_direction direction)
-{
-	BUG();
-}
-
-static inline dma_addr_t
-dma_map_page(struct device *dev, struct page *page,
-	     unsigned long offset, size_t size,
-	     enum dma_data_direction direction)
-{
-	BUG();
-	return(0);
-}
-
-static inline void
-dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
-	       enum dma_data_direction direction)
-{
-	BUG();
-}
-
-static inline int
-dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-	   enum dma_data_direction direction)
-{
-	BUG();
-	return(0);
-}
-
-static inline void
-dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
-	     enum dma_data_direction direction)
-{
-	BUG();
-}
-
-static inline void
-dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
-		enum dma_data_direction direction)
-{
-	BUG();
-}
-
-static inline void
-dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
-	    enum dma_data_direction direction)
-{
-	BUG();
-}
-
-#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 void
-dma_cache_sync(struct device *dev, void *vaddr, size_t size,
-	       enum dma_data_direction direction)
-{
-	BUG();
-}
-
-static inline int
-dma_mapping_error(struct device *dev, dma_addr_t dma_handle)
-{
-	BUG();
-	return 0;
-}
-
-#endif
diff --git a/arch/um/include/asm/pgtable.h b/arch/um/include/asm/pgtable.h
index a9f7251..41474fb 100644
--- a/arch/um/include/asm/pgtable.h
+++ b/arch/um/include/asm/pgtable.h
@@ -338,9 +338,7 @@
 	((pte_t *) pmd_page_vaddr(*(dir)) +  pte_index(address))
 #define pte_offset_map(dir, address) \
 	((pte_t *)page_address(pmd_page(*(dir))) + pte_index(address))
-#define pte_offset_map_nested(dir, address) pte_offset_map(dir, address)
 #define pte_unmap(pte) do { } while (0)
-#define pte_unmap_nested(pte) do { } while (0)
 
 struct mm_struct;
 extern pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr);
diff --git a/arch/um/include/asm/system.h b/arch/um/include/asm/system.h
index 93af1cf..68a90ec 100644
--- a/arch/um/include/asm/system.h
+++ b/arch/um/include/asm/system.h
@@ -8,23 +8,38 @@
 extern void block_signals(void);
 extern void unblock_signals(void);
 
-#define local_save_flags(flags) do { typecheck(unsigned long, flags); \
-				     (flags) = get_signals(); } while(0)
-#define local_irq_restore(flags) do { typecheck(unsigned long, flags); \
-				      set_signals(flags); } while(0)
+static inline unsigned long arch_local_save_flags(void)
+{
+	return get_signals();
+}
 
-#define local_irq_save(flags) do { local_save_flags(flags); \
-                                   local_irq_disable(); } while(0)
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+	set_signals(flags);
+}
 
-#define local_irq_enable() unblock_signals()
-#define local_irq_disable() block_signals()
+static inline void arch_local_irq_enable(void)
+{
+	unblock_signals();
+}
 
-#define irqs_disabled()                 \
-({                                      \
-        unsigned long flags;            \
-        local_save_flags(flags);        \
-        (flags == 0);                   \
-})
+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)
diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S
index 6926801..a3cab6d 100644
--- a/arch/um/kernel/dyn.lds.S
+++ b/arch/um/kernel/dyn.lds.S
@@ -50,8 +50,18 @@
   .rela.got       : { *(.rela.got) }
   .rel.bss        : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
   .rela.bss       : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
-  .rel.plt        : { *(.rel.plt) }
-  .rela.plt       : { *(.rela.plt) }
+  .rel.plt : {
+	*(.rel.plt)
+	PROVIDE_HIDDEN(__rel_iplt_start = .);
+	*(.rel.iplt)
+	PROVIDE_HIDDEN(__rel_iplt_end = .);
+  }
+  .rela.plt : {
+	*(.rela.plt)
+	PROVIDE_HIDDEN(__rela_iplt_start = .);
+	*(.rela.iplt)
+	PROVIDE_HIDDEN(__rela_iplt_end = .);
+  }
   .init           : {
     KEEP (*(.init))
   } =0x90909090
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index a746e30..3f0ac9e 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -334,7 +334,7 @@
 {
 	struct pt_regs *old_regs = set_irq_regs((struct pt_regs *)regs);
 	irq_enter();
-	__do_IRQ(irq);
+	generic_handle_irq(irq);
 	irq_exit();
 	set_irq_regs(old_regs);
 	return 1;
@@ -391,17 +391,10 @@
 {
 	int i;
 
-	irq_desc[TIMER_IRQ].status = IRQ_DISABLED;
-	irq_desc[TIMER_IRQ].action = NULL;
-	irq_desc[TIMER_IRQ].depth = 1;
-	irq_desc[TIMER_IRQ].chip = &SIGVTALRM_irq_type;
-	enable_irq(TIMER_IRQ);
+	set_irq_chip_and_handler(TIMER_IRQ, &SIGVTALRM_irq_type, handle_edge_irq);
+
 	for (i = 1; i < NR_IRQS; i++) {
-		irq_desc[i].status = IRQ_DISABLED;
-		irq_desc[i].action = NULL;
-		irq_desc[i].depth = 1;
-		irq_desc[i].chip = &normal_irq_type;
-		enable_irq(i);
+		set_irq_chip_and_handler(i, &normal_irq_type, handle_edge_irq);
 	}
 }
 
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S
index ec63785..fbd9940 100644
--- a/arch/um/kernel/uml.lds.S
+++ b/arch/um/kernel/uml.lds.S
@@ -22,7 +22,7 @@
   _text = .;
   _stext = .;
   __init_begin = .;
-  INIT_TEXT_SECTION(PAGE_SIZE)
+  INIT_TEXT_SECTION(0)
   . = ALIGN(PAGE_SIZE);
 
   .text      :
@@ -43,6 +43,23 @@
 	__syscall_stub_end = .;
   }
 
+  /*
+   * These are needed even in a static link, even if they wind up being empty.
+   * Newer glibc needs these __rel{,a}_iplt_{start,end} symbols.
+   */
+  .rel.plt : {
+	*(.rel.plt)
+	PROVIDE_HIDDEN(__rel_iplt_start = .);
+	*(.rel.iplt)
+	PROVIDE_HIDDEN(__rel_iplt_end = .);
+  }
+  .rela.plt : {
+	*(.rela.plt)
+	PROVIDE_HIDDEN(__rela_iplt_start = .);
+	*(.rela.iplt)
+	PROVIDE_HIDDEN(__rela_iplt_end = .);
+  }
+
   #include "asm/common.lds.S"
 
   init.data : { INIT_DATA }
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c
index dec5678..6e3359d 100644
--- a/arch/um/os-Linux/time.c
+++ b/arch/um/os-Linux/time.c
@@ -60,7 +60,7 @@
 long long disable_timer(void)
 {
 	struct itimerval time = ((struct itimerval) { { 0, 0 }, { 0, 0 } });
-	int remain, max = UM_NSEC_PER_SEC / UM_HZ;
+	long long remain, max = UM_NSEC_PER_SEC / UM_HZ;
 
 	if (setitimer(ITIMER_VIRTUAL, &time, &time) < 0)
 		printk(UM_KERN_ERR "disable_timer - setitimer failed, "
diff --git a/arch/x86/include/asm/highmem.h b/arch/x86/include/asm/highmem.h
index 8caac76..3bd0402 100644
--- a/arch/x86/include/asm/highmem.h
+++ b/arch/x86/include/asm/highmem.h
@@ -59,11 +59,12 @@
 
 void *kmap(struct page *page);
 void kunmap(struct page *page);
-void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot);
-void *kmap_atomic(struct page *page, enum km_type type);
-void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type);
-void *kmap_atomic_pfn(unsigned long pfn, enum km_type type);
-void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot);
+
+void *kmap_atomic_prot(struct page *page, pgprot_t prot);
+void *__kmap_atomic(struct page *page);
+void __kunmap_atomic(void *kvaddr);
+void *kmap_atomic_pfn(unsigned long pfn);
+void *kmap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot);
 struct page *kmap_atomic_to_page(void *ptr);
 
 #define flush_cache_kmaps()	do { } while (0)
diff --git a/arch/x86/include/asm/iomap.h b/arch/x86/include/asm/iomap.h
index c4191b3..363e33e 100644
--- a/arch/x86/include/asm/iomap.h
+++ b/arch/x86/include/asm/iomap.h
@@ -27,10 +27,10 @@
 #include <asm/tlbflush.h>
 
 void __iomem *
-iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot);
+iomap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot);
 
 void
-iounmap_atomic(void __iomem *kvaddr, enum km_type type);
+iounmap_atomic(void __iomem *kvaddr);
 
 int
 iomap_create_wc(resource_size_t base, unsigned long size, pgprot_t *prot);
diff --git a/arch/x86/include/asm/pgtable_32.h b/arch/x86/include/asm/pgtable_32.h
index 8abde9e..0c92113 100644
--- a/arch/x86/include/asm/pgtable_32.h
+++ b/arch/x86/include/asm/pgtable_32.h
@@ -49,24 +49,14 @@
 #endif
 
 #if defined(CONFIG_HIGHPTE)
-#define __KM_PTE			\
-	(in_nmi() ? KM_NMI_PTE : 	\
-	 in_irq() ? KM_IRQ_PTE :	\
-	 KM_PTE0)
 #define pte_offset_map(dir, address)					\
-	((pte_t *)kmap_atomic(pmd_page(*(dir)), __KM_PTE) +		\
+	((pte_t *)kmap_atomic(pmd_page(*(dir))) +		\
 	 pte_index((address)))
-#define pte_offset_map_nested(dir, address)				\
-	((pte_t *)kmap_atomic(pmd_page(*(dir)), KM_PTE1) +		\
-	 pte_index((address)))
-#define pte_unmap(pte) kunmap_atomic((pte), __KM_PTE)
-#define pte_unmap_nested(pte) kunmap_atomic((pte), KM_PTE1)
+#define pte_unmap(pte) kunmap_atomic((pte))
 #else
 #define pte_offset_map(dir, address)					\
 	((pte_t *)page_address(pmd_page(*(dir))) + pte_index((address)))
-#define pte_offset_map_nested(dir, address) pte_offset_map((dir), (address))
 #define pte_unmap(pte) do { } while (0)
-#define pte_unmap_nested(pte) do { } while (0)
 #endif
 
 /* Clear a kernel PTE and flush it from the TLB */
diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h
index f96ac9b..f86da20 100644
--- a/arch/x86/include/asm/pgtable_64.h
+++ b/arch/x86/include/asm/pgtable_64.h
@@ -127,9 +127,7 @@
 
 /* x86-64 always has all page tables mapped. */
 #define pte_offset_map(dir, address) pte_offset_kernel((dir), (address))
-#define pte_offset_map_nested(dir, address) pte_offset_kernel((dir), (address))
 #define pte_unmap(pte) ((void)(pte))/* NOP */
-#define pte_unmap_nested(pte) ((void)(pte)) /* NOP */
 
 #define update_mmu_cache(vma, address, ptep) do { } while (0)
 
diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
index cd8da24..a2baafb 100644
--- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -701,6 +701,7 @@
 		per_cpu(acfreq_data, policy->cpu) = NULL;
 		acpi_processor_unregister_performance(data->acpi_data,
 						      policy->cpu);
+		kfree(data->freq_table);
 		kfree(data);
 	}
 
diff --git a/arch/x86/kernel/cpu/cpufreq/cpufreq-nforce2.c b/arch/x86/kernel/cpu/cpufreq/cpufreq-nforce2.c
index 733093d..141abeb 100644
--- a/arch/x86/kernel/cpu/cpufreq/cpufreq-nforce2.c
+++ b/arch/x86/kernel/cpu/cpufreq/cpufreq-nforce2.c
@@ -393,7 +393,7 @@
  * Detects nForce2 A2 and C1 stepping
  *
  */
-static unsigned int nforce2_detect_chipset(void)
+static int nforce2_detect_chipset(void)
 {
 	nforce2_dev = pci_get_subsys(PCI_VENDOR_ID_NVIDIA,
 					PCI_DEVICE_ID_NVIDIA_NFORCE2,
diff --git a/arch/x86/kernel/cpu/cpufreq/longrun.c b/arch/x86/kernel/cpu/cpufreq/longrun.c
index fc09f14..d9f5136 100644
--- a/arch/x86/kernel/cpu/cpufreq/longrun.c
+++ b/arch/x86/kernel/cpu/cpufreq/longrun.c
@@ -35,7 +35,7 @@
  * Reads the current LongRun policy by access to MSR_TMTA_LONGRUN_FLAGS
  * and MSR_TMTA_LONGRUN_CTRL
  */
-static void __init longrun_get_policy(struct cpufreq_policy *policy)
+static void __cpuinit longrun_get_policy(struct cpufreq_policy *policy)
 {
 	u32 msr_lo, msr_hi;
 
@@ -165,7 +165,7 @@
  * TMTA rules:
  * performance_pctg = (target_freq - low_freq)/(high_freq - low_freq)
  */
-static unsigned int __cpuinit longrun_determine_freqs(unsigned int *low_freq,
+static int __cpuinit longrun_determine_freqs(unsigned int *low_freq,
 						      unsigned int *high_freq)
 {
 	u32 msr_lo, msr_hi;
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c
index 12cd823..17ad033 100644
--- a/arch/x86/kernel/cpu/intel_cacheinfo.c
+++ b/arch/x86/kernel/cpu/intel_cacheinfo.c
@@ -327,6 +327,7 @@
 	l3->subcaches[3] = sc3 = !(val & BIT(12)) + !(val & BIT(13));
 
 	l3->indices = (max(max(max(sc0, sc1), sc2), sc3) << 10) - 1;
+	l3->indices = (max(max3(sc0, sc1, sc2), sc3) << 10) - 1;
 }
 
 static struct amd_l3_cache * __cpuinit amd_init_l3_cache(int node)
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index fe73c18..c1e8c7a 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -49,7 +49,6 @@
 copy_from_user_nmi(void *to, const void __user *from, unsigned long n)
 {
 	unsigned long offset, addr = (unsigned long)from;
-	int type = in_nmi() ? KM_NMI : KM_IRQ0;
 	unsigned long size, len = 0;
 	struct page *page;
 	void *map;
@@ -63,9 +62,9 @@
 		offset = addr & (PAGE_SIZE - 1);
 		size = min(PAGE_SIZE - offset, n - len);
 
-		map = kmap_atomic(page, type);
+		map = kmap_atomic(page);
 		memcpy(to, map+offset, size);
-		kunmap_atomic(map, type);
+		kunmap_atomic(map);
 		put_page(page);
 
 		len  += size;
diff --git a/arch/x86/kernel/crash_dump_32.c b/arch/x86/kernel/crash_dump_32.c
index 6741455..d5cd139 100644
--- a/arch/x86/kernel/crash_dump_32.c
+++ b/arch/x86/kernel/crash_dump_32.c
@@ -61,7 +61,7 @@
 	if (!is_crashed_pfn_valid(pfn))
 		return -EFAULT;
 
-	vaddr = kmap_atomic_pfn(pfn, KM_PTE0);
+	vaddr = kmap_atomic_pfn(pfn);
 
 	if (!userbuf) {
 		memcpy(buf, (vaddr + offset), csize);
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index aff0b3c..ae03cab 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -713,7 +713,7 @@
 
 	switch (action & 0xf) {
 	case CPU_ONLINE:
-		INIT_DELAYED_WORK_ON_STACK(&work.work, hpet_work);
+		INIT_DELAYED_WORK_ONSTACK(&work.work, hpet_work);
 		init_completion(&work.complete);
 		/* FIXME: add schedule_work_on() */
 		schedule_delayed_work_on(cpu, &work.work, 0);
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 6af1185..6c7faec 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -747,7 +747,7 @@
 		.done	= COMPLETION_INITIALIZER_ONSTACK(c_idle.done),
 	};
 
-	INIT_WORK_ON_STACK(&c_idle.work, do_fork_idle);
+	INIT_WORK_ONSTACK(&c_idle.work, do_fork_idle);
 
 	alternatives_smp_switch(1);
 
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 79b0b37..7d90ceb 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -11,6 +11,7 @@
 #include <linux/kprobes.h>		/* __kprobes, ...		*/
 #include <linux/mmiotrace.h>		/* kmmio_handler, ...		*/
 #include <linux/perf_event.h>		/* perf_sw_event		*/
+#include <linux/hugetlb.h>		/* hstate_index_to_shift	*/
 
 #include <asm/traps.h>			/* dotraplinkage, ...		*/
 #include <asm/pgalloc.h>		/* pgd_*(), ...			*/
@@ -160,15 +161,20 @@
 
 static void
 force_sig_info_fault(int si_signo, int si_code, unsigned long address,
-		     struct task_struct *tsk)
+		     struct task_struct *tsk, int fault)
 {
+	unsigned lsb = 0;
 	siginfo_t info;
 
 	info.si_signo	= si_signo;
 	info.si_errno	= 0;
 	info.si_code	= si_code;
 	info.si_addr	= (void __user *)address;
-	info.si_addr_lsb = si_code == BUS_MCEERR_AR ? PAGE_SHIFT : 0;
+	if (fault & VM_FAULT_HWPOISON_LARGE)
+		lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault)); 
+	if (fault & VM_FAULT_HWPOISON)
+		lsb = PAGE_SHIFT;
+	info.si_addr_lsb = lsb;
 
 	force_sig_info(si_signo, &info, tsk);
 }
@@ -722,7 +728,7 @@
 		tsk->thread.error_code	= error_code | (address >= TASK_SIZE);
 		tsk->thread.trap_no	= 14;
 
-		force_sig_info_fault(SIGSEGV, si_code, address, tsk);
+		force_sig_info_fault(SIGSEGV, si_code, address, tsk, 0);
 
 		return;
 	}
@@ -807,14 +813,14 @@
 	tsk->thread.trap_no	= 14;
 
 #ifdef CONFIG_MEMORY_FAILURE
-	if (fault & VM_FAULT_HWPOISON) {
+	if (fault & (VM_FAULT_HWPOISON|VM_FAULT_HWPOISON_LARGE)) {
 		printk(KERN_ERR
 	"MCE: Killing %s:%d due to hardware memory corruption fault at %lx\n",
 			tsk->comm, tsk->pid, address);
 		code = BUS_MCEERR_AR;
 	}
 #endif
-	force_sig_info_fault(SIGBUS, code, address, tsk);
+	force_sig_info_fault(SIGBUS, code, address, tsk, fault);
 }
 
 static noinline void
@@ -824,7 +830,8 @@
 	if (fault & VM_FAULT_OOM) {
 		out_of_memory(regs, error_code, address);
 	} else {
-		if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON))
+		if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON|
+			     VM_FAULT_HWPOISON_LARGE))
 			do_sigbus(regs, error_code, address, fault);
 		else
 			BUG();
@@ -912,9 +919,9 @@
 int show_unhandled_signals = 1;
 
 static inline int
-access_error(unsigned long error_code, int write, struct vm_area_struct *vma)
+access_error(unsigned long error_code, struct vm_area_struct *vma)
 {
-	if (write) {
+	if (error_code & PF_WRITE) {
 		/* write, present and write, not present: */
 		if (unlikely(!(vma->vm_flags & VM_WRITE)))
 			return 1;
@@ -949,8 +956,10 @@
 	struct task_struct *tsk;
 	unsigned long address;
 	struct mm_struct *mm;
-	int write;
 	int fault;
+	int write = error_code & PF_WRITE;
+	unsigned int flags = FAULT_FLAG_ALLOW_RETRY |
+					(write ? FAULT_FLAG_WRITE : 0);
 
 	tsk = current;
 	mm = tsk->mm;
@@ -1061,6 +1070,7 @@
 			bad_area_nosemaphore(regs, error_code, address);
 			return;
 		}
+retry:
 		down_read(&mm->mmap_sem);
 	} else {
 		/*
@@ -1104,9 +1114,7 @@
 	 * we can handle it..
 	 */
 good_area:
-	write = error_code & PF_WRITE;
-
-	if (unlikely(access_error(error_code, write, vma))) {
+	if (unlikely(access_error(error_code, vma))) {
 		bad_area_access_error(regs, error_code, address);
 		return;
 	}
@@ -1116,21 +1124,34 @@
 	 * make sure we exit gracefully rather than endlessly redo
 	 * the fault:
 	 */
-	fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0);
+	fault = handle_mm_fault(mm, vma, address, flags);
 
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		mm_fault_error(regs, error_code, address, fault);
 		return;
 	}
 
-	if (fault & VM_FAULT_MAJOR) {
-		tsk->maj_flt++;
-		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
-				     regs, address);
-	} else {
-		tsk->min_flt++;
-		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
-				     regs, address);
+	/*
+	 * Major/minor page fault accounting is only done on the
+	 * initial attempt. If we go through a retry, it is extremely
+	 * likely that the page will be found in page cache at that point.
+	 */
+	if (flags & FAULT_FLAG_ALLOW_RETRY) {
+		if (fault & VM_FAULT_MAJOR) {
+			tsk->maj_flt++;
+			perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
+				      regs, address);
+		} else {
+			tsk->min_flt++;
+			perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
+				      regs, address);
+		}
+		if (fault & VM_FAULT_RETRY) {
+			/* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
+			 * of starvation. */
+			flags &= ~FAULT_FLAG_ALLOW_RETRY;
+			goto retry;
+		}
 	}
 
 	check_v8086_mode(regs, address, tsk);
diff --git a/arch/x86/mm/highmem_32.c b/arch/x86/mm/highmem_32.c
index 5e8fa12..d723e36 100644
--- a/arch/x86/mm/highmem_32.c
+++ b/arch/x86/mm/highmem_32.c
@@ -9,6 +9,7 @@
 		return page_address(page);
 	return kmap_high(page);
 }
+EXPORT_SYMBOL(kmap);
 
 void kunmap(struct page *page)
 {
@@ -18,6 +19,7 @@
 		return;
 	kunmap_high(page);
 }
+EXPORT_SYMBOL(kunmap);
 
 /*
  * kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because
@@ -27,10 +29,10 @@
  * However when holding an atomic kmap it is not legal to sleep, so atomic
  * kmaps are appropriate for short, tight code paths only.
  */
-void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
+void *kmap_atomic_prot(struct page *page, pgprot_t prot)
 {
-	enum fixed_addresses idx;
 	unsigned long vaddr;
+	int idx, type;
 
 	/* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
 	pagefault_disable();
@@ -38,8 +40,7 @@
 	if (!PageHighMem(page))
 		return page_address(page);
 
-	debug_kmap_atomic(type);
-
+	type = kmap_atomic_idx_push();
 	idx = type + KM_TYPE_NR*smp_processor_id();
 	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
 	BUG_ON(!pte_none(*(kmap_pte-idx)));
@@ -47,44 +48,56 @@
 
 	return (void *)vaddr;
 }
+EXPORT_SYMBOL(kmap_atomic_prot);
 
-void *kmap_atomic(struct page *page, enum km_type type)
+void *__kmap_atomic(struct page *page)
 {
-	return kmap_atomic_prot(page, type, kmap_prot);
+	return kmap_atomic_prot(page, kmap_prot);
 }
-
-void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type)
-{
-	unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
-	enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
-
-	/*
-	 * Force other mappings to Oops if they'll try to access this pte
-	 * without first remap it.  Keeping stale mappings around is a bad idea
-	 * also, in case the page changes cacheability attributes or becomes
-	 * a protected page in a hypervisor.
-	 */
-	if (vaddr == __fix_to_virt(FIX_KMAP_BEGIN+idx))
-		kpte_clear_flush(kmap_pte-idx, vaddr);
-	else {
-#ifdef CONFIG_DEBUG_HIGHMEM
-		BUG_ON(vaddr < PAGE_OFFSET);
-		BUG_ON(vaddr >= (unsigned long)high_memory);
-#endif
-	}
-
-	pagefault_enable();
-}
+EXPORT_SYMBOL(__kmap_atomic);
 
 /*
  * This is the same as kmap_atomic() but can map memory that doesn't
  * have a struct page associated with it.
  */
-void *kmap_atomic_pfn(unsigned long pfn, enum km_type type)
+void *kmap_atomic_pfn(unsigned long pfn)
 {
-	return kmap_atomic_prot_pfn(pfn, type, kmap_prot);
+	return kmap_atomic_prot_pfn(pfn, kmap_prot);
 }
-EXPORT_SYMBOL_GPL(kmap_atomic_pfn); /* temporarily in use by i915 GEM until vmap */
+EXPORT_SYMBOL_GPL(kmap_atomic_pfn);
+
+void __kunmap_atomic(void *kvaddr)
+{
+	unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
+
+	if (vaddr >= __fix_to_virt(FIX_KMAP_END) &&
+	    vaddr <= __fix_to_virt(FIX_KMAP_BEGIN)) {
+		int idx, type;
+
+		type = kmap_atomic_idx_pop();
+		idx = type + KM_TYPE_NR * smp_processor_id();
+
+#ifdef CONFIG_DEBUG_HIGHMEM
+		WARN_ON_ONCE(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
+#endif
+		/*
+		 * Force other mappings to Oops if they'll try to access this
+		 * pte without first remap it.  Keeping stale mappings around
+		 * is a bad idea also, in case the page changes cacheability
+		 * attributes or becomes a protected page in a hypervisor.
+		 */
+		kpte_clear_flush(kmap_pte-idx, vaddr);
+	}
+#ifdef CONFIG_DEBUG_HIGHMEM
+	else {
+		BUG_ON(vaddr < PAGE_OFFSET);
+		BUG_ON(vaddr >= (unsigned long)high_memory);
+	}
+#endif
+
+	pagefault_enable();
+}
+EXPORT_SYMBOL(__kunmap_atomic);
 
 struct page *kmap_atomic_to_page(void *ptr)
 {
@@ -98,12 +111,6 @@
 	pte = kmap_pte - (idx - FIX_KMAP_BEGIN);
 	return pte_page(*pte);
 }
-
-EXPORT_SYMBOL(kmap);
-EXPORT_SYMBOL(kunmap);
-EXPORT_SYMBOL(kmap_atomic);
-EXPORT_SYMBOL(kunmap_atomic_notypecheck);
-EXPORT_SYMBOL(kmap_atomic_prot);
 EXPORT_SYMBOL(kmap_atomic_to_page);
 
 void __init set_highmem_pages_init(void)
diff --git a/arch/x86/mm/iomap_32.c b/arch/x86/mm/iomap_32.c
index 72fc70c..75a3d7f 100644
--- a/arch/x86/mm/iomap_32.c
+++ b/arch/x86/mm/iomap_32.c
@@ -48,21 +48,20 @@
 }
 EXPORT_SYMBOL_GPL(iomap_create_wc);
 
-void
-iomap_free(resource_size_t base, unsigned long size)
+void iomap_free(resource_size_t base, unsigned long size)
 {
 	io_free_memtype(base, base + size);
 }
 EXPORT_SYMBOL_GPL(iomap_free);
 
-void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot)
+void *kmap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot)
 {
-	enum fixed_addresses idx;
 	unsigned long vaddr;
+	int idx, type;
 
 	pagefault_disable();
 
-	debug_kmap_atomic(type);
+	type = kmap_atomic_idx_push();
 	idx = type + KM_TYPE_NR * smp_processor_id();
 	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
 	set_pte(kmap_pte - idx, pfn_pte(pfn, prot));
@@ -72,10 +71,10 @@
 }
 
 /*
- * Map 'pfn' using fixed map 'type' and protections 'prot'
+ * Map 'pfn' using protections 'prot'
  */
 void __iomem *
-iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot)
+iomap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot)
 {
 	/*
 	 * For non-PAT systems, promote PAGE_KERNEL_WC to PAGE_KERNEL_UC_MINUS.
@@ -86,24 +85,33 @@
 	if (!pat_enabled && pgprot_val(prot) == pgprot_val(PAGE_KERNEL_WC))
 		prot = PAGE_KERNEL_UC_MINUS;
 
-	return (void __force __iomem *) kmap_atomic_prot_pfn(pfn, type, prot);
+	return (void __force __iomem *) kmap_atomic_prot_pfn(pfn, prot);
 }
 EXPORT_SYMBOL_GPL(iomap_atomic_prot_pfn);
 
 void
-iounmap_atomic(void __iomem *kvaddr, enum km_type type)
+iounmap_atomic(void __iomem *kvaddr)
 {
 	unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
-	enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
 
-	/*
-	 * Force other mappings to Oops if they'll try to access this pte
-	 * without first remap it.  Keeping stale mappings around is a bad idea
-	 * also, in case the page changes cacheability attributes or becomes
-	 * a protected page in a hypervisor.
-	 */
-	if (vaddr == __fix_to_virt(FIX_KMAP_BEGIN+idx))
+	if (vaddr >= __fix_to_virt(FIX_KMAP_END) &&
+	    vaddr <= __fix_to_virt(FIX_KMAP_BEGIN)) {
+		int idx, type;
+
+		type = kmap_atomic_idx_pop();
+		idx = type + KM_TYPE_NR * smp_processor_id();
+
+#ifdef CONFIG_DEBUG_HIGHMEM
+		WARN_ON_ONCE(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
+#endif
+		/*
+		 * Force other mappings to Oops if they'll try to access this
+		 * pte without first remap it.  Keeping stale mappings around
+		 * is a bad idea also, in case the page changes cacheability
+		 * attributes or becomes a protected page in a hypervisor.
+		 */
 		kpte_clear_flush(kmap_pte-idx, vaddr);
+	}
 
 	pagefault_enable();
 }
diff --git a/arch/xtensa/include/asm/pgtable.h b/arch/xtensa/include/asm/pgtable.h
index 76bf355..b03c043 100644
--- a/arch/xtensa/include/asm/pgtable.h
+++ b/arch/xtensa/include/asm/pgtable.h
@@ -324,10 +324,7 @@
 #define pte_offset_kernel(dir,addr) 					\
 	((pte_t*) pmd_page_vaddr(*(dir)) + pte_index(addr))
 #define pte_offset_map(dir,addr)	pte_offset_kernel((dir),(addr))
-#define pte_offset_map_nested(dir,addr)	pte_offset_kernel((dir),(addr))
-
 #define pte_unmap(pte)		do { } while (0)
-#define pte_unmap_nested(pte)	do { } while (0)
 
 
 /*
diff --git a/crypto/async_tx/async_memcpy.c b/crypto/async_tx/async_memcpy.c
index 0ec1fb6..518c22b 100644
--- a/crypto/async_tx/async_memcpy.c
+++ b/crypto/async_tx/async_memcpy.c
@@ -83,8 +83,8 @@
 
 		memcpy(dest_buf, src_buf, len);
 
-		kunmap_atomic(dest_buf, KM_USER0);
 		kunmap_atomic(src_buf, KM_USER1);
+		kunmap_atomic(dest_buf, KM_USER0);
 
 		async_tx_sync_epilog(submit);
 	}
diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c
index 90d26c9..7a72192 100644
--- a/crypto/blkcipher.c
+++ b/crypto/blkcipher.c
@@ -89,9 +89,9 @@
 		memcpy(walk->dst.virt.addr, walk->page, n);
 		blkcipher_unmap_dst(walk);
 	} else if (!(walk->flags & BLKCIPHER_WALK_PHYS)) {
-		blkcipher_unmap_src(walk);
 		if (walk->flags & BLKCIPHER_WALK_DIFF)
 			blkcipher_unmap_dst(walk);
+		blkcipher_unmap_src(walk);
 	}
 
 	scatterwalk_advance(&walk->in, n);
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 88681ac..3f3489c 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -9,7 +9,6 @@
 	depends on PCI
 	depends on PM
 	select PNP
-	select CPU_IDLE
 	default y
 	help
 	  Advanced Configuration and Power Interface (ACPI) support for 
@@ -66,7 +65,6 @@
 config ACPI_PROCFS_POWER
 	bool "Deprecated power /proc/acpi directories"
 	depends on PROC_FS
-	default y
 	help
 	  For backwards compatibility, this option allows
           deprecated power /proc/acpi/ directories to exist, even when
@@ -90,13 +88,6 @@
 	  To compile this driver as a module, choose M here:
 	  the module will be called power-meter.
 
-config ACPI_SYSFS_POWER
-	bool "Future power /sys interface"
-	select POWER_SUPPLY
-	default y
-	help
-	  Say N to disable power /sys interface
-
 config ACPI_EC_DEBUGFS
 	tristate "EC read/write access through /sys/kernel/debug/ec"
 	default n
@@ -136,6 +127,7 @@
 config ACPI_AC
 	tristate "AC Adapter"
 	depends on X86
+	select POWER_SUPPLY
 	default y
 	help
 	  This driver supports the AC Adapter object, which indicates
@@ -148,6 +140,7 @@
 config ACPI_BATTERY
 	tristate "Battery"
 	depends on X86
+	select POWER_SUPPLY
 	default y
 	help
 	  This driver adds support for battery information through
@@ -206,6 +199,7 @@
 config ACPI_PROCESSOR
 	tristate "Processor"
 	select THERMAL
+	select CPU_IDLE
 	default y
 	help
 	  This driver installs ACPI as the idle handler for Linux and uses
@@ -364,6 +358,7 @@
 config ACPI_SBS
 	tristate "Smart Battery System"
 	depends on X86
+	select POWER_SUPPLY
 	help
 	  This driver supports the Smart Battery System, another
 	  type of access to battery information, found on some laptops.
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index 56205a0..ba9afea 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -32,9 +32,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #endif
-#ifdef CONFIG_ACPI_SYSFS_POWER
 #include <linux/power_supply.h>
-#endif
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 
@@ -86,9 +84,7 @@
 };
 
 struct acpi_ac {
-#ifdef CONFIG_ACPI_SYSFS_POWER
 	struct power_supply charger;
-#endif
 	struct acpi_device * device;
 	unsigned long long state;
 };
@@ -104,7 +100,6 @@
 	.release = single_release,
 };
 #endif
-#ifdef CONFIG_ACPI_SYSFS_POWER
 static int get_ac_property(struct power_supply *psy,
 			   enum power_supply_property psp,
 			   union power_supply_propval *val)
@@ -123,7 +118,6 @@
 static enum power_supply_property ac_props[] = {
 	POWER_SUPPLY_PROP_ONLINE,
 };
-#endif
 /* --------------------------------------------------------------------------
                                AC Adapter Management
    -------------------------------------------------------------------------- */
@@ -247,9 +241,7 @@
 						  dev_name(&device->dev), event,
 						  (u32) ac->state);
 		acpi_notifier_call_chain(device, event, (u32) ac->state);
-#ifdef CONFIG_ACPI_SYSFS_POWER
 		kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE);
-#endif
 	}
 
 	return;
@@ -282,14 +274,12 @@
 #endif
 	if (result)
 		goto end;
-#ifdef CONFIG_ACPI_SYSFS_POWER
 	ac->charger.name = acpi_device_bid(device);
 	ac->charger.type = POWER_SUPPLY_TYPE_MAINS;
 	ac->charger.properties = ac_props;
 	ac->charger.num_properties = ARRAY_SIZE(ac_props);
 	ac->charger.get_property = get_ac_property;
 	power_supply_register(&ac->device->dev, &ac->charger);
-#endif
 
 	printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
 	       acpi_device_name(device), acpi_device_bid(device),
@@ -316,10 +306,8 @@
 	old_state = ac->state;
 	if (acpi_ac_get_state(ac))
 		return 0;
-#ifdef CONFIG_ACPI_SYSFS_POWER
 	if (old_state != ac->state)
 		kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE);
-#endif
 	return 0;
 }
 
@@ -333,10 +321,8 @@
 
 	ac = acpi_driver_data(device);
 
-#ifdef CONFIG_ACPI_SYSFS_POWER
 	if (ac->charger.dev)
 		power_supply_unregister(&ac->charger);
-#endif
 #ifdef CONFIG_ACPI_PROCFS_POWER
 	acpi_ac_remove_fs(device);
 #endif
diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile
index d93cc06..a7e1d1a 100644
--- a/drivers/acpi/acpica/Makefile
+++ b/drivers/acpi/acpica/Makefile
@@ -21,7 +21,7 @@
 	 excreate.o  exmisc.o   exoparg2.o  exregion.o  exstore.o   exutils.o \
 	 exdump.o    exmutex.o  exoparg3.o  exresnte.o  exstoren.o  exdebug.o
 
-acpi-y += hwacpi.o  hwgpe.o  hwregs.o  hwsleep.o hwxface.o hwvalid.o
+acpi-y += hwacpi.o  hwgpe.o  hwregs.o  hwsleep.o hwxface.o hwvalid.o hwpci.o
 
 acpi-$(ACPI_FUTURE_USAGE) += hwtimer.o
 
@@ -44,4 +44,5 @@
 
 acpi-y += utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \
 		utcopy.o utdelete.o utglobal.o utmath.o utobject.o \
-		utstate.o utmutex.o utobject.o utresrc.o utlock.o utids.o
+		utstate.o utmutex.o utobject.o utresrc.o utlock.o utids.o \
+		utosi.o utxferror.o
diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h
index 48faf3e..72e9d5e 100644
--- a/drivers/acpi/acpica/acdebug.h
+++ b/drivers/acpi/acpica/acdebug.h
@@ -105,6 +105,8 @@
 acpi_status
 acpi_db_display_objects(char *obj_type_arg, char *display_count_arg);
 
+void acpi_db_display_interfaces(char *action_arg, char *interface_name_arg);
+
 acpi_status acpi_db_find_name_in_namespace(char *name_arg);
 
 void acpi_db_set_scope(char *name);
diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h
index 36867cd..a6f99cc 100644
--- a/drivers/acpi/acpica/acevents.h
+++ b/drivers/acpi/acpica/acevents.h
@@ -105,8 +105,9 @@
 			 struct acpi_gpe_block_info **return_gpe_block);
 
 acpi_status
-acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
-			     struct acpi_gpe_block_info *gpe_block);
+acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
+			     struct acpi_gpe_block_info *gpe_block,
+			     void *ignored);
 
 acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block);
 
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h
index 1d19214..ad88fca 100644
--- a/drivers/acpi/acpica/acglobal.h
+++ b/drivers/acpi/acpica/acglobal.h
@@ -132,6 +132,7 @@
 u32 acpi_current_gpe_count;
 u32 acpi_gbl_trace_flags;
 acpi_name acpi_gbl_trace_method_name;
+u8 acpi_gbl_system_awake_and_running;
 
 #endif
 
@@ -187,6 +188,10 @@
 ACPI_EXTERN u8 acpi_gbl_integer_byte_width;
 ACPI_EXTERN u8 acpi_gbl_integer_nybble_width;
 
+/* Mutex for _OSI support */
+
+ACPI_EXTERN acpi_mutex acpi_gbl_osi_mutex;
+
 /* Reader/Writer lock is used for namespace walk and dynamic table unload */
 
 ACPI_EXTERN struct acpi_rw_lock acpi_gbl_namespace_rw_lock;
@@ -255,6 +260,7 @@
 ACPI_EXTERN acpi_tbl_handler acpi_gbl_table_handler;
 ACPI_EXTERN void *acpi_gbl_table_handler_context;
 ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk;
+ACPI_EXTERN acpi_interface_handler acpi_gbl_interface_handler;
 
 /* Owner ID support */
 
@@ -273,8 +279,8 @@
 ACPI_EXTERN u8 acpi_gbl_step_to_next_call;
 ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present;
 ACPI_EXTERN u8 acpi_gbl_events_initialized;
-ACPI_EXTERN u8 acpi_gbl_system_awake_and_running;
 ACPI_EXTERN u8 acpi_gbl_osi_data;
+ACPI_EXTERN struct acpi_interface_info *acpi_gbl_supported_interfaces;
 
 #ifndef DEFINE_ACPI_GLOBALS
 
@@ -364,6 +370,7 @@
 ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head;
 ACPI_EXTERN struct acpi_gpe_block_info
 *acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS];
+ACPI_EXTERN u8 acpi_all_gpes_initialized;
 
 /*****************************************************************************
  *
diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h
index 120b3af..167470a 100644
--- a/drivers/acpi/acpica/achware.h
+++ b/drivers/acpi/acpica/achware.h
@@ -121,6 +121,13 @@
 				 struct acpi_gpe_block_info *gpe_block,
 				 void *context);
 
+/*
+ * hwpci - PCI configuration support
+ */
+acpi_status
+acpi_hw_derive_pci_id(struct acpi_pci_id *pci_id,
+		      acpi_handle root_pci_device, acpi_handle pci_region);
+
 #ifdef	ACPI_FUTURE_USAGE
 /*
  * hwtimer - ACPI Timer prototypes
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
index 7dad916..2ceb0c0 100644
--- a/drivers/acpi/acpica/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -413,6 +413,7 @@
 	void *context;		/* Context to be passed to handler */
 	struct acpi_namespace_node *method_node;	/* Method node for this GPE level (saved) */
 	u8 orig_flags;		/* Original misc info about this GPE */
+	u8 orig_enabled;	/* Set if the GPE was originally enabled */
 };
 
 union acpi_gpe_dispatch_info {
@@ -457,6 +458,7 @@
 	u32 register_count;	/* Number of register pairs in block */
 	u16 gpe_count;		/* Number of individual GPEs in block */
 	u8 block_base_number;	/* Base GPE number for this block */
+	u8 initialized;         /* If set, the GPE block has been initialized */
 };
 
 /* Information about GPE interrupt handlers, one per each interrupt level used for GPEs */
@@ -473,7 +475,6 @@
 	struct acpi_gpe_block_info *gpe_block;
 	u16 count;
 	acpi_owner_id owner_id;
-	u8 enable_this_gpe;
 	u8 execute_by_owner_id;
 };
 
@@ -854,7 +855,7 @@
 	ACPI_BITMASK_POWER_BUTTON_STATUS   | \
 	ACPI_BITMASK_SLEEP_BUTTON_STATUS   | \
 	ACPI_BITMASK_RT_CLOCK_STATUS       | \
-	ACPI_BITMASK_PCIEXP_WAKE_DISABLE   | \
+	ACPI_BITMASK_PCIEXP_WAKE_STATUS    | \
 	ACPI_BITMASK_WAKE_STATUS)
 
 #define ACPI_BITMASK_TIMER_ENABLE               0x0001
@@ -909,15 +910,21 @@
 #define ACPI_OSI_WIN_VISTA              0x07
 #define ACPI_OSI_WINSRV_2008            0x08
 #define ACPI_OSI_WIN_VISTA_SP1          0x09
-#define ACPI_OSI_WIN_7                  0x0A
+#define ACPI_OSI_WIN_VISTA_SP2          0x0A
+#define ACPI_OSI_WIN_7                  0x0B
 
 #define ACPI_ALWAYS_ILLEGAL             0x00
 
 struct acpi_interface_info {
 	char *name;
+	struct acpi_interface_info *next;
+	u8 flags;
 	u8 value;
 };
 
+#define ACPI_OSI_INVALID                0x01
+#define ACPI_OSI_DYNAMIC                0x02
+
 struct acpi_port_info {
 	char *name;
 	u16 start;
@@ -997,7 +1004,7 @@
 struct acpi_db_method_info {
 	acpi_handle main_thread_gate;
 	acpi_handle thread_complete_gate;
-	u32 *threads;
+	acpi_thread_id *threads;
 	u32 num_threads;
 	u32 num_created;
 	u32 num_completed;
diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h
index 9894929..8d5c9e0 100644
--- a/drivers/acpi/acpica/acmacros.h
+++ b/drivers/acpi/acpica/acmacros.h
@@ -338,8 +338,8 @@
  * the plist contains a set of parens to allow variable-length lists.
  * These macros are used for both the debug and non-debug versions of the code.
  */
-#define ACPI_ERROR_NAMESPACE(s, e)      acpi_ns_report_error (AE_INFO, s, e);
-#define ACPI_ERROR_METHOD(s, n, p, e)   acpi_ns_report_method_error (AE_INFO, s, n, p, e);
+#define ACPI_ERROR_NAMESPACE(s, e)      acpi_ut_namespace_error (AE_INFO, s, e);
+#define ACPI_ERROR_METHOD(s, n, p, e)   acpi_ut_method_error (AE_INFO, s, n, p, e);
 #define ACPI_WARN_PREDEFINED(plist)     acpi_ut_predefined_warning plist
 #define ACPI_INFO_PREDEFINED(plist)     acpi_ut_predefined_info plist
 
diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h
index 9f60ff0..d44d3bc 100644
--- a/drivers/acpi/acpica/acnamesp.h
+++ b/drivers/acpi/acpica/acnamesp.h
@@ -339,18 +339,6 @@
 u32 acpi_ns_local(acpi_object_type type);
 
 void
-acpi_ns_report_error(const char *module_name,
-		     u32 line_number,
-		     const char *internal_name, acpi_status lookup_status);
-
-void
-acpi_ns_report_method_error(const char *module_name,
-			    u32 line_number,
-			    const char *message,
-			    struct acpi_namespace_node *node,
-			    const char *path, acpi_status lookup_status);
-
-void
 acpi_ns_print_node_pathname(struct acpi_namespace_node *node, const char *msg);
 
 acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info);
diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h
index 54857fa..bdbfaf22b 100644
--- a/drivers/acpi/acpica/acobject.h
+++ b/drivers/acpi/acpica/acobject.h
@@ -248,7 +248,7 @@
 	u32                             base_byte_offset;   /* Byte offset within containing object */\
 	u32                             value;              /* Value to store into the Bank or Index register */\
 	u8                              start_field_bit_offset;/* Bit offset within first field datum (0-63) */\
-	u8                              access_bit_width;	/* Read/Write size in bits (8-64) */
+
 
 struct acpi_object_field_common {	/* COMMON FIELD (for BUFFER, REGION, BANK, and INDEX fields) */
 	ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object *region_obj;	/* Parent Operation Region object (REGION/BANK fields only) */
diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h
index 35df755..72e4183 100644
--- a/drivers/acpi/acpica/acutils.h
+++ b/drivers/acpi/acpica/acutils.h
@@ -312,8 +312,6 @@
 /*
  * uteval - object evaluation
  */
-acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state);
-
 acpi_status
 acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
 			char *path,
@@ -395,6 +393,21 @@
 acpi_ut_get_object_size(union acpi_operand_object *obj, acpi_size * obj_length);
 
 /*
+ * utosi - Support for the _OSI predefined control method
+ */
+acpi_status acpi_ut_initialize_interfaces(void);
+
+void acpi_ut_interface_terminate(void);
+
+acpi_status acpi_ut_install_interface(acpi_string interface_name);
+
+acpi_status acpi_ut_remove_interface(acpi_string interface_name);
+
+struct acpi_interface_info *acpi_ut_get_interface(acpi_string interface_name);
+
+acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state);
+
+/*
  * utstate - Generic state creation/cache routines
  */
 void
@@ -473,17 +486,6 @@
 
 acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 * ret_integer);
 
-void ACPI_INTERNAL_VAR_XFACE
-acpi_ut_predefined_warning(const char *module_name,
-			   u32 line_number,
-			   char *pathname,
-			   u8 node_flags, const char *format, ...);
-
-void ACPI_INTERNAL_VAR_XFACE
-acpi_ut_predefined_info(const char *module_name,
-			u32 line_number,
-			char *pathname, u8 node_flags, const char *format, ...);
-
 /* Values for Base above (16=Hex, 10=Decimal) */
 
 #define ACPI_ANY_BASE        0
@@ -574,6 +576,32 @@
 acpi_ut_create_list(char *list_name,
 		    u16 object_size, struct acpi_memory_list **return_cache);
 
-#endif
+#endif				/* ACPI_DBG_TRACK_ALLOCATIONS */
+
+/*
+ * utxferror - various error/warning output functions
+ */
+void ACPI_INTERNAL_VAR_XFACE
+acpi_ut_predefined_warning(const char *module_name,
+			   u32 line_number,
+			   char *pathname,
+			   u8 node_flags, const char *format, ...);
+
+void ACPI_INTERNAL_VAR_XFACE
+acpi_ut_predefined_info(const char *module_name,
+			u32 line_number,
+			char *pathname, u8 node_flags, const char *format, ...);
+
+void
+acpi_ut_namespace_error(const char *module_name,
+			u32 line_number,
+			const char *internal_name, acpi_status lookup_status);
+
+void
+acpi_ut_method_error(const char *module_name,
+		     u32 line_number,
+		     const char *message,
+		     struct acpi_namespace_node *node,
+		     const char *path, acpi_status lookup_status);
 
 #endif				/* _ACUTILS_H */
diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c
index 64750ee..d94dd89 100644
--- a/drivers/acpi/acpica/dsmethod.c
+++ b/drivers/acpi/acpica/dsmethod.c
@@ -573,7 +573,7 @@
 
 				acpi_os_release_mutex(method_desc->method.
 						      mutex->mutex.os_mutex);
-				method_desc->method.mutex->mutex.thread_id = NULL;
+				method_desc->method.mutex->mutex.thread_id = 0;
 			}
 		}
 
diff --git a/drivers/acpi/acpica/dswexec.c b/drivers/acpi/acpica/dswexec.c
index d555b37..6b0b5d0 100644
--- a/drivers/acpi/acpica/dswexec.c
+++ b/drivers/acpi/acpica/dswexec.c
@@ -300,10 +300,25 @@
 			 * we must enter this object into the namespace.  The created
 			 * object is temporary and will be deleted upon completion of
 			 * the execution of this method.
+			 *
+			 * Note 10/2010: Except for the Scope() op. This opcode does
+			 * not actually create a new object, it refers to an existing
+			 * object. However, for Scope(), we want to indeed open a
+			 * new scope.
 			 */
-			status = acpi_ds_load2_begin_op(walk_state, NULL);
+			if (op->common.aml_opcode != AML_SCOPE_OP) {
+				status =
+				    acpi_ds_load2_begin_op(walk_state, NULL);
+			} else {
+				status =
+				    acpi_ds_scope_stack_push(op->named.node,
+							     op->named.node->
+							     type, walk_state);
+				if (ACPI_FAILURE(status)) {
+					return_ACPI_STATUS(status);
+				}
+			}
 		}
-
 		break;
 
 	case AML_CLASS_EXECUTE:
diff --git a/drivers/acpi/acpica/evevent.c b/drivers/acpi/acpica/evevent.c
index 3036188..c61c3039 100644
--- a/drivers/acpi/acpica/evevent.c
+++ b/drivers/acpi/acpica/evevent.c
@@ -95,47 +95,6 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ev_install_fadt_gpes
- *
- * PARAMETERS:  None
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Completes initialization of the FADT-defined GPE blocks
- *              (0 and 1). The HW must be fully initialized at this point,
- *              including global lock support.
- *
- ******************************************************************************/
-
-acpi_status acpi_ev_install_fadt_gpes(void)
-{
-	acpi_status status;
-
-	ACPI_FUNCTION_TRACE(ev_install_fadt_gpes);
-
-	/* Namespace must be locked */
-
-	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
-	if (ACPI_FAILURE(status)) {
-		return (status);
-	}
-
-	/* FADT GPE Block 0 */
-
-	(void)acpi_ev_initialize_gpe_block(acpi_gbl_fadt_gpe_device,
-					   acpi_gbl_gpe_fadt_blocks[0]);
-
-	/* FADT GPE Block 1 */
-
-	(void)acpi_ev_initialize_gpe_block(acpi_gbl_fadt_gpe_device,
-					   acpi_gbl_gpe_fadt_blocks[1]);
-
-	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
-	return_ACPI_STATUS(AE_OK);
-}
-
-/*******************************************************************************
- *
  * FUNCTION:    acpi_ev_install_xrupt_handlers
  *
  * PARAMETERS:  None
diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c
index 85445fb..020add3 100644
--- a/drivers/acpi/acpica/evgpeblk.c
+++ b/drivers/acpi/acpica/evgpeblk.c
@@ -363,6 +363,7 @@
 	gpe_block->gpe_count = (u16)(register_count * ACPI_GPE_REGISTER_WIDTH);
 	gpe_block->register_count = register_count;
 	gpe_block->block_base_number = gpe_block_base_number;
+	gpe_block->initialized = FALSE;
 
 	ACPI_MEMCPY(&gpe_block->block_address, gpe_block_address,
 		    sizeof(struct acpi_generic_address));
@@ -385,11 +386,12 @@
 		return_ACPI_STATUS(status);
 	}
 
+	acpi_all_gpes_initialized = FALSE;
+
 	/* Find all GPE methods (_Lxx or_Exx) for this block */
 
 	walk_info.gpe_block = gpe_block;
 	walk_info.gpe_device = gpe_device;
-	walk_info.enable_this_gpe = FALSE;
 	walk_info.execute_by_owner_id = FALSE;
 
 	status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD, gpe_device,
@@ -434,35 +436,34 @@
  ******************************************************************************/
 
 acpi_status
-acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
-			     struct acpi_gpe_block_info *gpe_block)
+acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
+			     struct acpi_gpe_block_info *gpe_block,
+			     void *ignored)
 {
 	acpi_status status;
 	struct acpi_gpe_event_info *gpe_event_info;
 	u32 gpe_enabled_count;
 	u32 gpe_index;
-	u32 gpe_number;
 	u32 i;
 	u32 j;
 
 	ACPI_FUNCTION_TRACE(ev_initialize_gpe_block);
 
-	/* Ignore a null GPE block (e.g., if no GPE block 1 exists) */
-
-	if (!gpe_block) {
+	/*
+	 * Ignore a null GPE block (e.g., if no GPE block 1 exists) and
+	 * GPE blocks that have been initialized already.
+	 */
+	if (!gpe_block || gpe_block->initialized) {
 		return_ACPI_STATUS(AE_OK);
 	}
 
 	/*
-	 * Enable all GPEs that have a corresponding method.  Any other GPEs
-	 * within this block must be enabled via the acpi_enable_gpe interface.
+	 * Enable all GPEs that have a corresponding method and have the
+	 * ACPI_GPE_CAN_WAKE flag unset.  Any other GPEs within this block must
+	 * be enabled via the acpi_enable_gpe() interface.
 	 */
 	gpe_enabled_count = 0;
 
-	if (gpe_device == acpi_gbl_fadt_gpe_device) {
-		gpe_device = NULL;
-	}
-
 	for (i = 0; i < gpe_block->register_count; i++) {
 		for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
 
@@ -470,27 +471,19 @@
 
 			gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j;
 			gpe_event_info = &gpe_block->event_info[gpe_index];
-			gpe_number = gpe_index + gpe_block->block_base_number;
 
 			/* Ignore GPEs that have no corresponding _Lxx/_Exx method */
 
-			if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD)) {
+			if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD)
+			    || (gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
 				continue;
 			}
 
-			/*
-			 * If the GPE has already been enabled for runtime
-			 * signaling, make sure it remains enabled, but do not
-			 * increment its reference counter.
-			 */
-			status = gpe_event_info->runtime_count ?
-				acpi_ev_enable_gpe(gpe_event_info) :
-				acpi_enable_gpe(gpe_device, gpe_number);
-
+			status = acpi_raw_enable_gpe(gpe_event_info);
 			if (ACPI_FAILURE(status)) {
 				ACPI_EXCEPTION((AE_INFO, status,
-						"Could not enable GPE 0x%02X",
-						gpe_number));
+					"Could not enable GPE 0x%02X",
+					gpe_index + gpe_block->block_base_number));
 				continue;
 			}
 
@@ -504,5 +497,7 @@
 				  gpe_enabled_count));
 	}
 
+	gpe_block->initialized = TRUE;
+
 	return_ACPI_STATUS(AE_OK);
 }
diff --git a/drivers/acpi/acpica/evgpeinit.c b/drivers/acpi/acpica/evgpeinit.c
index 3084c5d..2c7def9 100644
--- a/drivers/acpi/acpica/evgpeinit.c
+++ b/drivers/acpi/acpica/evgpeinit.c
@@ -210,8 +210,7 @@
  *
  * DESCRIPTION: Check for new GPE methods (_Lxx/_Exx) made available as a
  *              result of a Load() or load_table() operation. If new GPE
- *              methods have been installed, register the new methods and
- *              enable and runtime GPEs that are associated with them.
+ *              methods have been installed, register the new methods.
  *
  ******************************************************************************/
 
@@ -239,7 +238,6 @@
 	walk_info.owner_id = table_owner_id;
 	walk_info.execute_by_owner_id = TRUE;
 	walk_info.count = 0;
-	walk_info.enable_this_gpe = TRUE;
 
 	/* Walk the interrupt level descriptor list */
 
@@ -301,8 +299,6 @@
  *
  * If walk_info->execute_by_owner_id is TRUE, we only execute examine GPE methods
  *    with that owner.
- * If walk_info->enable_this_gpe is TRUE, the GPE that is referred to by a GPE
- *    method is immediately enabled (Used for Load/load_table operators)
  *
  ******************************************************************************/
 
@@ -315,8 +311,6 @@
 	struct acpi_gpe_walk_info *walk_info =
 	    ACPI_CAST_PTR(struct acpi_gpe_walk_info, context);
 	struct acpi_gpe_event_info *gpe_event_info;
-	struct acpi_namespace_node *gpe_device;
-	acpi_status status;
 	u32 gpe_number;
 	char name[ACPI_NAME_SIZE + 1];
 	u8 type;
@@ -421,29 +415,6 @@
 	gpe_event_info->flags |= (u8)(type | ACPI_GPE_DISPATCH_METHOD);
 	gpe_event_info->dispatch.method_node = method_node;
 
-	/*
-	 * Enable this GPE if requested. This only happens when during the
-	 * execution of a Load or load_table operator. We have found a new
-	 * GPE method and want to immediately enable the GPE if it is a
-	 * runtime GPE.
-	 */
-	if (walk_info->enable_this_gpe) {
-
-		walk_info->count++;
-		gpe_device = walk_info->gpe_device;
-
-		if (gpe_device == acpi_gbl_fadt_gpe_device) {
-			gpe_device = NULL;
-		}
-
-		status = acpi_enable_gpe(gpe_device, gpe_number);
-		if (ACPI_FAILURE(status)) {
-			ACPI_EXCEPTION((AE_INFO, status,
-					"Could not enable GPE 0x%02X",
-					gpe_number));
-		}
-	}
-
 	ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
 			  "Registered GPE method %s as GPE number 0x%.2X\n",
 			  name, gpe_number));
diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c
index df0aea9..fcaed9f 100644
--- a/drivers/acpi/acpica/evmisc.c
+++ b/drivers/acpi/acpica/evmisc.c
@@ -553,7 +553,7 @@
 	acpi_gbl_global_lock_acquired = FALSE;
 
 	/* Release the local GL mutex */
-	acpi_ev_global_lock_thread_id = NULL;
+	acpi_ev_global_lock_thread_id = 0;
 	acpi_ev_global_lock_acquired = 0;
 	acpi_os_release_mutex(acpi_gbl_global_lock_mutex->mutex.os_mutex);
 	return_ACPI_STATUS(status);
diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c
index f40d271..0b47a6d 100644
--- a/drivers/acpi/acpica/evrgnini.c
+++ b/drivers/acpi/acpica/evrgnini.c
@@ -289,8 +289,8 @@
 	}
 
 	/*
-	 * Get the PCI device and function numbers from the _ADR object contained
-	 * in the parent's scope.
+	 * Get the PCI device and function numbers from the _ADR object
+	 * contained in the parent's scope.
 	 */
 	status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR,
 						 pci_device_node, &pci_value);
@@ -320,9 +320,15 @@
 		pci_id->bus = ACPI_LOWORD(pci_value);
 	}
 
-	/* Complete this device's pci_id */
+	/* Complete/update the PCI ID for this device */
 
-	acpi_os_derive_pci_id(pci_root_node, region_obj->region.node, &pci_id);
+	status =
+	    acpi_hw_derive_pci_id(pci_id, pci_root_node,
+				  region_obj->region.node);
+	if (ACPI_FAILURE(status)) {
+		ACPI_FREE(pci_id);
+		return_ACPI_STATUS(status);
+	}
 
 	*region_context = pci_id;
 	return_ACPI_STATUS(AE_OK);
diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c
index 14e48ad..36af222 100644
--- a/drivers/acpi/acpica/evxface.c
+++ b/drivers/acpi/acpica/evxface.c
@@ -726,15 +726,16 @@
 			(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
 
 	/*
-	 * If the GPE is associated with a method and it cannot wake up the
-	 * system from sleep states, it was enabled automatically during
-	 * initialization, so it has to be disabled now to avoid spurious
-	 * execution of the handler.
+	 * If the GPE is associated with a method, it might have been enabled
+	 * automatically during initialization, in which case it has to be
+	 * disabled now to avoid spurious execution of the handler.
 	 */
 
 	if ((handler->orig_flags & ACPI_GPE_DISPATCH_METHOD)
-	    && !(gpe_event_info->flags & ACPI_GPE_CAN_WAKE))
+	    && gpe_event_info->runtime_count) {
+		handler->orig_enabled = 1;
 		(void)acpi_raw_disable_gpe(gpe_event_info);
+	}
 
 	/* Install the handler */
 
@@ -837,13 +838,13 @@
 	gpe_event_info->flags |= handler->orig_flags;
 
 	/*
-	 * If the GPE was previously associated with a method and it cannot wake
-	 * up the system from sleep states, it should be enabled at this point
-	 * to restore the post-initialization configuration.
+	 * If the GPE was previously associated with a method and it was
+	 * enabled, it should be enabled at this point to restore the
+	 * post-initialization configuration.
 	 */
 
 	if ((handler->orig_flags & ACPI_GPE_DISPATCH_METHOD)
-	    && !(gpe_event_info->flags & ACPI_GPE_CAN_WAKE))
+	    && handler->orig_enabled)
 		(void)acpi_raw_enable_gpe(gpe_event_info);
 
 	/* Now we can free the handler object */
diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c
index 3048255..a1dabe3 100644
--- a/drivers/acpi/acpica/evxfevnt.c
+++ b/drivers/acpi/acpica/evxfevnt.c
@@ -379,21 +379,12 @@
 	/* Ensure that we have a valid GPE number */
 
 	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
-	if (!gpe_event_info) {
+	if (gpe_event_info) {
+		gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
+	} else {
 		status = AE_BAD_PARAMETER;
-		goto unlock_and_exit;
 	}
 
-	if (gpe_event_info->flags & ACPI_GPE_CAN_WAKE) {
-		goto unlock_and_exit;
-	}
-
-	gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
-	if (gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD) {
-		(void)acpi_raw_disable_gpe(gpe_event_info);
-	}
-
-unlock_and_exit:
 	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
 	return_ACPI_STATUS(status);
 }
@@ -651,7 +642,7 @@
 		       struct acpi_generic_address *gpe_block_address,
 		       u32 register_count, u32 interrupt_number)
 {
-	acpi_status status;
+	acpi_status status = AE_OK;
 	union acpi_operand_object *obj_desc;
 	struct acpi_namespace_node *node;
 	struct acpi_gpe_block_info *gpe_block;
@@ -715,10 +706,6 @@
 
 	obj_desc->device.gpe_block = gpe_block;
 
-	/* Enable the runtime GPEs in the new block */
-
-	status = acpi_ev_initialize_gpe_block(node, gpe_block);
-
       unlock_and_exit:
 	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 	return_ACPI_STATUS(status);
@@ -924,3 +911,43 @@
 
 	return_ACPI_STATUS(status);
 }
+
+/******************************************************************************
+ *
+ * FUNCTION:    acpi_update_gpes
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Enable all GPEs that have associated _Lxx or _Exx methods and
+ *              are not pointed to by any device _PRW methods indicating that
+ *              these GPEs are generally intended for system or device wakeup
+ *              (such GPEs have to be enabled directly when the devices whose
+ *              _PRW methods point to them are set up for wakeup signaling).
+ *
+ ******************************************************************************/
+
+acpi_status acpi_update_gpes(void)
+{
+	acpi_status status;
+
+	ACPI_FUNCTION_TRACE(acpi_update_gpes);
+
+	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+	if (ACPI_FAILURE(status)) {
+		return_ACPI_STATUS(status);
+	} else if (acpi_all_gpes_initialized) {
+		goto unlock;
+	}
+
+	status = acpi_ev_walk_gpe_list(acpi_ev_initialize_gpe_block, NULL);
+	if (ACPI_SUCCESS(status)) {
+		acpi_all_gpes_initialized = TRUE;
+	}
+
+unlock:
+	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+
+	return_ACPI_STATUS(status);
+}
diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c
index 541cbc1..ce9314f 100644
--- a/drivers/acpi/acpica/evxfregn.c
+++ b/drivers/acpi/acpica/evxfregn.c
@@ -64,6 +64,12 @@
  *
  * DESCRIPTION: Install a handler for all op_regions of a given space_id.
  *
+ * NOTE: This function should only be called after acpi_enable_subsystem has
+ * been called. This is because any _REG methods associated with the Space ID
+ * are executed here, and these methods can only be safely executed after
+ * the default handlers have been installed and the hardware has been
+ * initialized (via acpi_enable_subsystem.)
+ *
  ******************************************************************************/
 acpi_status
 acpi_install_address_space_handler(acpi_handle device,
diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c
index 0472173..38293fd 100644
--- a/drivers/acpi/acpica/exfldio.c
+++ b/drivers/acpi/acpica/exfldio.c
@@ -119,8 +119,8 @@
 	}
 
 	/*
-	 * Exit now for SMBus or IPMI address space, it has a non-linear address space
-	 * and the request cannot be directly validated
+	 * Exit now for SMBus or IPMI address space, it has a non-linear
+	 * address space and the request cannot be directly validated
 	 */
 	if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS ||
 	    rgn_desc->region.space_id == ACPI_ADR_SPACE_IPMI) {
@@ -147,8 +147,7 @@
 	 * (Region length is specified in bytes)
 	 */
 	if (rgn_desc->region.length <
-	    (obj_desc->common_field.base_byte_offset +
-	     field_datum_byte_offset +
+	    (obj_desc->common_field.base_byte_offset + field_datum_byte_offset +
 	     obj_desc->common_field.access_byte_width)) {
 		if (acpi_gbl_enable_interpreter_slack) {
 			/*
@@ -680,6 +679,7 @@
 	u32 buffer_tail_bits;
 	u32 datum_count;
 	u32 field_datum_count;
+	u32 access_bit_width;
 	u32 i;
 
 	ACPI_FUNCTION_TRACE(ex_extract_from_field);
@@ -694,16 +694,36 @@
 
 		return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
 	}
+
 	ACPI_MEMSET(buffer, 0, buffer_length);
+	access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width);
+
+	/* Handle the simple case here */
+
+	if ((obj_desc->common_field.start_field_bit_offset == 0) &&
+	    (obj_desc->common_field.bit_length == access_bit_width)) {
+		status = acpi_ex_field_datum_io(obj_desc, 0, buffer, ACPI_READ);
+		return_ACPI_STATUS(status);
+	}
+
+/* TBD: Move to common setup code */
+
+	/* Field algorithm is limited to sizeof(u64), truncate if needed */
+
+	if (obj_desc->common_field.access_byte_width > sizeof(u64)) {
+		obj_desc->common_field.access_byte_width = sizeof(u64);
+		access_bit_width = sizeof(u64) * 8;
+	}
 
 	/* Compute the number of datums (access width data items) */
 
-	datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
-				       obj_desc->common_field.access_bit_width);
+	datum_count =
+	    ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
+			     access_bit_width);
+
 	field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
 					     obj_desc->common_field.
 					     start_field_bit_offset,
-					     obj_desc->common_field.
 					     access_bit_width);
 
 	/* Priming read from the field */
@@ -738,12 +758,11 @@
 		 * This avoids the differences in behavior between different compilers
 		 * concerning shift values larger than the target data width.
 		 */
-		if ((obj_desc->common_field.access_bit_width -
-		     obj_desc->common_field.start_field_bit_offset) <
+		if (access_bit_width -
+		    obj_desc->common_field.start_field_bit_offset <
 		    ACPI_INTEGER_BIT_SIZE) {
 			merged_datum |=
-			    raw_datum << (obj_desc->common_field.
-					  access_bit_width -
+			    raw_datum << (access_bit_width -
 					  obj_desc->common_field.
 					  start_field_bit_offset);
 		}
@@ -765,8 +784,7 @@
 
 	/* Mask off any extra bits in the last datum */
 
-	buffer_tail_bits = obj_desc->common_field.bit_length %
-	    obj_desc->common_field.access_bit_width;
+	buffer_tail_bits = obj_desc->common_field.bit_length % access_bit_width;
 	if (buffer_tail_bits) {
 		merged_datum &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
 	}
@@ -798,6 +816,7 @@
 acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
 			  void *buffer, u32 buffer_length)
 {
+	void *new_buffer;
 	acpi_status status;
 	u64 mask;
 	u64 width_mask;
@@ -808,9 +827,9 @@
 	u32 buffer_tail_bits;
 	u32 datum_count;
 	u32 field_datum_count;
-	u32 i;
+	u32 access_bit_width;
 	u32 required_length;
-	void *new_buffer;
+	u32 i;
 
 	ACPI_FUNCTION_TRACE(ex_insert_into_field);
 
@@ -844,17 +863,24 @@
 		buffer_length = required_length;
 	}
 
+/* TBD: Move to common setup code */
+
+	/* Algo is limited to sizeof(u64), so cut the access_byte_width */
+	if (obj_desc->common_field.access_byte_width > sizeof(u64)) {
+		obj_desc->common_field.access_byte_width = sizeof(u64);
+	}
+
+	access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width);
+
 	/*
 	 * Create the bitmasks used for bit insertion.
 	 * Note: This if/else is used to bypass compiler differences with the
 	 * shift operator
 	 */
-	if (obj_desc->common_field.access_bit_width == ACPI_INTEGER_BIT_SIZE) {
+	if (access_bit_width == ACPI_INTEGER_BIT_SIZE) {
 		width_mask = ACPI_UINT64_MAX;
 	} else {
-		width_mask =
-		    ACPI_MASK_BITS_ABOVE(obj_desc->common_field.
-					 access_bit_width);
+		width_mask = ACPI_MASK_BITS_ABOVE(access_bit_width);
 	}
 
 	mask = width_mask &
@@ -863,12 +889,11 @@
 	/* Compute the number of datums (access width data items) */
 
 	datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
-				       obj_desc->common_field.access_bit_width);
+				       access_bit_width);
 
 	field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
 					     obj_desc->common_field.
 					     start_field_bit_offset,
-					     obj_desc->common_field.
 					     access_bit_width);
 
 	/* Get initial Datum from the input buffer */
@@ -905,12 +930,11 @@
 		 * This avoids the differences in behavior between different compilers
 		 * concerning shift values larger than the target data width.
 		 */
-		if ((obj_desc->common_field.access_bit_width -
+		if ((access_bit_width -
 		     obj_desc->common_field.start_field_bit_offset) <
 		    ACPI_INTEGER_BIT_SIZE) {
 			merged_datum =
-			    raw_datum >> (obj_desc->common_field.
-					  access_bit_width -
+			    raw_datum >> (access_bit_width -
 					  obj_desc->common_field.
 					  start_field_bit_offset);
 		} else {
@@ -929,6 +953,7 @@
 		ACPI_MEMCPY(&raw_datum, ((char *)buffer) + buffer_offset,
 			    ACPI_MIN(obj_desc->common_field.access_byte_width,
 				     buffer_length - buffer_offset));
+
 		merged_datum |=
 		    raw_datum << obj_desc->common_field.start_field_bit_offset;
 	}
@@ -937,7 +962,7 @@
 
 	buffer_tail_bits = (obj_desc->common_field.bit_length +
 			    obj_desc->common_field.start_field_bit_offset) %
-	    obj_desc->common_field.access_bit_width;
+	    access_bit_width;
 	if (buffer_tail_bits) {
 		mask &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
 	}
diff --git a/drivers/acpi/acpica/exmutex.c b/drivers/acpi/acpica/exmutex.c
index f73be97..6af14e4 100644
--- a/drivers/acpi/acpica/exmutex.c
+++ b/drivers/acpi/acpica/exmutex.c
@@ -336,7 +336,7 @@
 
 	/* Clear mutex info */
 
-	obj_desc->mutex.thread_id = NULL;
+	obj_desc->mutex.thread_id = 0;
 	return_ACPI_STATUS(status);
 }
 
@@ -393,10 +393,10 @@
 	if ((owner_thread->thread_id != walk_state->thread->thread_id) &&
 	    (obj_desc != acpi_gbl_global_lock_mutex)) {
 		ACPI_ERROR((AE_INFO,
-			    "Thread %p cannot release Mutex [%4.4s] acquired by thread %p",
-			    ACPI_CAST_PTR(void, walk_state->thread->thread_id),
+			    "Thread %u cannot release Mutex [%4.4s] acquired by thread %u",
+			    (u32)walk_state->thread->thread_id,
 			    acpi_ut_get_node_name(obj_desc->mutex.node),
-			    ACPI_CAST_PTR(void, owner_thread->thread_id)));
+			    (u32)owner_thread->thread_id));
 		return_ACPI_STATUS(AE_AML_NOT_OWNER);
 	}
 
@@ -488,7 +488,7 @@
 		/* Mark mutex unowned */
 
 		obj_desc->mutex.owner_thread = NULL;
-		obj_desc->mutex.thread_id = NULL;
+		obj_desc->mutex.thread_id = 0;
 
 		/* Update Thread sync_level (Last mutex is the important one) */
 
diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c
index 98a331d..7aae29f 100644
--- a/drivers/acpi/acpica/exprep.c
+++ b/drivers/acpi/acpica/exprep.c
@@ -355,12 +355,10 @@
 		return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
 	}
 
-	/* Setup width (access granularity) fields */
+	/* Setup width (access granularity) fields (values are: 1, 2, 4, 8) */
 
 	obj_desc->common_field.access_byte_width = (u8)
-	    ACPI_DIV_8(access_bit_width);	/* 1,  2,  4,  8 */
-
-	obj_desc->common_field.access_bit_width = (u8) access_bit_width;
+	    ACPI_DIV_8(access_bit_width);
 
 	/*
 	 * base_byte_offset is the address of the start of the field within the
@@ -405,8 +403,9 @@
 {
 	union acpi_operand_object *obj_desc;
 	union acpi_operand_object *second_desc = NULL;
-	u32 type;
 	acpi_status status;
+	u32 access_byte_width;
+	u32 type;
 
 	ACPI_FUNCTION_TRACE(ex_prep_field_value);
 
@@ -421,8 +420,8 @@
 		type = acpi_ns_get_type(info->region_node);
 		if (type != ACPI_TYPE_REGION) {
 			ACPI_ERROR((AE_INFO,
-				    "Needed Region, found type 0x%X (%s)",
-				    type, acpi_ut_get_type_name(type)));
+				    "Needed Region, found type 0x%X (%s)", type,
+				    acpi_ut_get_type_name(type)));
 
 			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 		}
@@ -438,7 +437,8 @@
 	/* Initialize areas of the object that are common to all fields */
 
 	obj_desc->common_field.node = info->field_node;
-	status = acpi_ex_prep_common_field_object(obj_desc, info->field_flags,
+	status = acpi_ex_prep_common_field_object(obj_desc,
+						  info->field_flags,
 						  info->attribute,
 						  info->field_bit_position,
 						  info->field_bit_length);
@@ -455,27 +455,26 @@
 		obj_desc->field.region_obj =
 		    acpi_ns_get_attached_object(info->region_node);
 
+		/* Allow full data read from EC address space */
+
+		if ((obj_desc->field.region_obj->region.space_id ==
+		     ACPI_ADR_SPACE_EC)
+		    && (obj_desc->common_field.bit_length > 8)) {
+			access_byte_width =
+			    ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.
+							bit_length);
+
+			/* Maximum byte width supported is 255 */
+
+			if (access_byte_width < 256) {
+				obj_desc->common_field.access_byte_width =
+				    (u8)access_byte_width;
+			}
+		}
 		/* An additional reference for the container */
 
 		acpi_ut_add_reference(obj_desc->field.region_obj);
 
-		/* allow full data read from EC address space */
-		if (obj_desc->field.region_obj->region.space_id ==
-			ACPI_ADR_SPACE_EC) {
-			if (obj_desc->common_field.bit_length > 8) {
-				unsigned width =
-					ACPI_ROUND_BITS_UP_TO_BYTES(
-					obj_desc->common_field.bit_length);
-				// access_bit_width is u8, don't overflow it
-				if (width > 8)
-					width = 8;
-				obj_desc->common_field.access_byte_width =
-							width;
-				obj_desc->common_field.access_bit_width =
-							8 * width;
-			}
-		}
-
 		ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
 				  "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n",
 				  obj_desc->field.start_field_bit_offset,
diff --git a/drivers/acpi/acpica/exregion.c b/drivers/acpi/acpica/exregion.c
index 8819d2a..de17e10 100644
--- a/drivers/acpi/acpica/exregion.c
+++ b/drivers/acpi/acpica/exregion.c
@@ -353,7 +353,6 @@
 	acpi_status status = AE_OK;
 	struct acpi_pci_id *pci_id;
 	u16 pci_register;
-	u32 value32;
 
 	ACPI_FUNCTION_TRACE(ex_pci_config_space_handler);
 
@@ -381,8 +380,7 @@
 	case ACPI_READ:
 
 		status = acpi_os_read_pci_configuration(pci_id, pci_register,
-							&value32, bit_width);
-		*value = value32;
+							value, bit_width);
 		break;
 
 	case ACPI_WRITE:
diff --git a/drivers/acpi/acpica/hwpci.c b/drivers/acpi/acpica/hwpci.c
new file mode 100644
index 0000000..ad21c7d
--- /dev/null
+++ b/drivers/acpi/acpica/hwpci.c
@@ -0,0 +1,412 @@
+/*******************************************************************************
+ *
+ * Module Name: hwpci - Obtain PCI bus, device, and function numbers
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2010, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+
+#define _COMPONENT          ACPI_NAMESPACE
+ACPI_MODULE_NAME("hwpci")
+
+/* PCI configuration space values */
+#define PCI_CFG_HEADER_TYPE_REG             0x0E
+#define PCI_CFG_PRIMARY_BUS_NUMBER_REG      0x18
+#define PCI_CFG_SECONDARY_BUS_NUMBER_REG    0x19
+/* PCI header values */
+#define PCI_HEADER_TYPE_MASK                0x7F
+#define PCI_TYPE_BRIDGE                     0x01
+#define PCI_TYPE_CARDBUS_BRIDGE             0x02
+typedef struct acpi_pci_device {
+	acpi_handle device;
+	struct acpi_pci_device *next;
+
+} acpi_pci_device;
+
+/* Local prototypes */
+
+static acpi_status
+acpi_hw_build_pci_list(acpi_handle root_pci_device,
+		       acpi_handle pci_region,
+		       struct acpi_pci_device **return_list_head);
+
+static acpi_status
+acpi_hw_process_pci_list(struct acpi_pci_id *pci_id,
+			 struct acpi_pci_device *list_head);
+
+static void acpi_hw_delete_pci_list(struct acpi_pci_device *list_head);
+
+static acpi_status
+acpi_hw_get_pci_device_info(struct acpi_pci_id *pci_id,
+			    acpi_handle pci_device,
+			    u16 *bus_number, u8 *is_bridge);
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_hw_derive_pci_id
+ *
+ * PARAMETERS:  pci_id              - Initial values for the PCI ID. May be
+ *                                    modified by this function.
+ *              root_pci_device     - A handle to a PCI device object. This
+ *                                    object must be a PCI Root Bridge having a
+ *                                    _HID value of either PNP0A03 or PNP0A08
+ *              pci_region          - A handle to a PCI configuration space
+ *                                    Operation Region being initialized
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: This function derives a full PCI ID for a PCI device,
+ *              consisting of a Segment number, Bus number, Device number,
+ *              and function code.
+ *
+ *              The PCI hardware dynamically configures PCI bus numbers
+ *              depending on the bus topology discovered during system
+ *              initialization. This function is invoked during configuration
+ *              of a PCI_Config Operation Region in order to (possibly) update
+ *              the Bus/Device/Function numbers in the pci_id with the actual
+ *              values as determined by the hardware and operating system
+ *              configuration.
+ *
+ *              The pci_id parameter is initially populated during the Operation
+ *              Region initialization. This function is then called, and is
+ *              will make any necessary modifications to the Bus, Device, or
+ *              Function number PCI ID subfields as appropriate for the
+ *              current hardware and OS configuration.
+ *
+ * NOTE:        Created 08/2010. Replaces the previous OSL acpi_os_derive_pci_id
+ *              interface since this feature is OS-independent. This module
+ *              specifically avoids any use of recursion by building a local
+ *              temporary device list.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_hw_derive_pci_id(struct acpi_pci_id *pci_id,
+		      acpi_handle root_pci_device, acpi_handle pci_region)
+{
+	acpi_status status;
+	struct acpi_pci_device *list_head = NULL;
+
+	ACPI_FUNCTION_TRACE(hw_derive_pci_id);
+
+	if (!pci_id) {
+		return_ACPI_STATUS(AE_BAD_PARAMETER);
+	}
+
+	/* Build a list of PCI devices, from pci_region up to root_pci_device */
+
+	status =
+	    acpi_hw_build_pci_list(root_pci_device, pci_region, &list_head);
+	if (ACPI_SUCCESS(status)) {
+
+		/* Walk the list, updating the PCI device/function/bus numbers */
+
+		status = acpi_hw_process_pci_list(pci_id, list_head);
+	}
+
+	/* Always delete the list */
+
+	acpi_hw_delete_pci_list(list_head);
+	return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_hw_build_pci_list
+ *
+ * PARAMETERS:  root_pci_device     - A handle to a PCI device object. This
+ *                                    object is guaranteed to be a PCI Root
+ *                                    Bridge having a _HID value of either
+ *                                    PNP0A03 or PNP0A08
+ *              pci_region          - A handle to the PCI configuration space
+ *                                    Operation Region
+ *              return_list_head    - Where the PCI device list is returned
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Builds a list of devices from the input PCI region up to the
+ *              Root PCI device for this namespace subtree.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_hw_build_pci_list(acpi_handle root_pci_device,
+		       acpi_handle pci_region,
+		       struct acpi_pci_device **return_list_head)
+{
+	acpi_handle current_device;
+	acpi_handle parent_device;
+	acpi_status status;
+	struct acpi_pci_device *list_element;
+	struct acpi_pci_device *list_head = NULL;
+
+	/*
+	 * Ascend namespace branch until the root_pci_device is reached, building
+	 * a list of device nodes. Loop will exit when either the PCI device is
+	 * found, or the root of the namespace is reached.
+	 */
+	current_device = pci_region;
+	while (1) {
+		status = acpi_get_parent(current_device, &parent_device);
+		if (ACPI_FAILURE(status)) {
+			return (status);
+		}
+
+		/* Finished when we reach the PCI root device (PNP0A03 or PNP0A08) */
+
+		if (parent_device == root_pci_device) {
+			*return_list_head = list_head;
+			return (AE_OK);
+		}
+
+		list_element = ACPI_ALLOCATE(sizeof(struct acpi_pci_device));
+		if (!list_element) {
+			return (AE_NO_MEMORY);
+		}
+
+		/* Put new element at the head of the list */
+
+		list_element->next = list_head;
+		list_element->device = parent_device;
+		list_head = list_element;
+
+		current_device = parent_device;
+	}
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_hw_process_pci_list
+ *
+ * PARAMETERS:  pci_id              - Initial values for the PCI ID. May be
+ *                                    modified by this function.
+ *              list_head           - Device list created by
+ *                                    acpi_hw_build_pci_list
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Walk downward through the PCI device list, getting the device
+ *              info for each, via the PCI configuration space and updating
+ *              the PCI ID as necessary. Deletes the list during traversal.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_hw_process_pci_list(struct acpi_pci_id *pci_id,
+			 struct acpi_pci_device *list_head)
+{
+	acpi_status status = AE_OK;
+	struct acpi_pci_device *info;
+	u16 bus_number;
+	u8 is_bridge = TRUE;
+
+	ACPI_FUNCTION_NAME(hw_process_pci_list);
+
+	ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+			  "Input PciId:  Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X\n",
+			  pci_id->segment, pci_id->bus, pci_id->device,
+			  pci_id->function));
+
+	bus_number = pci_id->bus;
+
+	/*
+	 * Descend down the namespace tree, collecting PCI device, function,
+	 * and bus numbers. bus_number is only important for PCI bridges.
+	 * Algorithm: As we descend the tree, use the last valid PCI device,
+	 * function, and bus numbers that are discovered, and assign them
+	 * to the PCI ID for the target device.
+	 */
+	info = list_head;
+	while (info) {
+		status = acpi_hw_get_pci_device_info(pci_id, info->device,
+						     &bus_number, &is_bridge);
+		if (ACPI_FAILURE(status)) {
+			return_ACPI_STATUS(status);
+		}
+
+		info = info->next;
+	}
+
+	ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+			  "Output PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X "
+			  "Status %X BusNumber %X IsBridge %X\n",
+			  pci_id->segment, pci_id->bus, pci_id->device,
+			  pci_id->function, status, bus_number, is_bridge));
+
+	return_ACPI_STATUS(AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_hw_delete_pci_list
+ *
+ * PARAMETERS:  list_head           - Device list created by
+ *                                    acpi_hw_build_pci_list
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Free the entire PCI list.
+ *
+ ******************************************************************************/
+
+static void acpi_hw_delete_pci_list(struct acpi_pci_device *list_head)
+{
+	struct acpi_pci_device *next;
+	struct acpi_pci_device *previous;
+
+	next = list_head;
+	while (next) {
+		previous = next;
+		next = previous->next;
+		ACPI_FREE(previous);
+	}
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_hw_get_pci_device_info
+ *
+ * PARAMETERS:  pci_id              - Initial values for the PCI ID. May be
+ *                                    modified by this function.
+ *              pci_device          - Handle for the PCI device object
+ *              bus_number          - Where a PCI bridge bus number is returned
+ *              is_bridge           - Return value, indicates if this PCI
+ *                                    device is a PCI bridge
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Get the device info for a single PCI device object. Get the
+ *              _ADR (contains PCI device and function numbers), and for PCI
+ *              bridge devices, get the bus number from PCI configuration
+ *              space.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_hw_get_pci_device_info(struct acpi_pci_id *pci_id,
+			    acpi_handle pci_device,
+			    u16 *bus_number, u8 *is_bridge)
+{
+	acpi_status status;
+	acpi_object_type object_type;
+	u64 return_value;
+	u64 pci_value;
+
+	/* We only care about objects of type Device */
+
+	status = acpi_get_type(pci_device, &object_type);
+	if (ACPI_FAILURE(status)) {
+		return (status);
+	}
+
+	if (object_type != ACPI_TYPE_DEVICE) {
+		return (AE_OK);
+	}
+
+	/* We need an _ADR. Ignore device if not present */
+
+	status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR,
+						 pci_device, &return_value);
+	if (ACPI_FAILURE(status)) {
+		return (AE_OK);
+	}
+
+	/*
+	 * From _ADR, get the PCI Device and Function and
+	 * update the PCI ID.
+	 */
+	pci_id->device = ACPI_HIWORD(ACPI_LODWORD(return_value));
+	pci_id->function = ACPI_LOWORD(ACPI_LODWORD(return_value));
+
+	/*
+	 * If the previous device was a bridge, use the previous
+	 * device bus number
+	 */
+	if (*is_bridge) {
+		pci_id->bus = *bus_number;
+	}
+
+	/*
+	 * Get the bus numbers from PCI Config space:
+	 *
+	 * First, get the PCI header_type
+	 */
+	*is_bridge = FALSE;
+	status = acpi_os_read_pci_configuration(pci_id,
+						PCI_CFG_HEADER_TYPE_REG,
+						&pci_value, 8);
+	if (ACPI_FAILURE(status)) {
+		return (status);
+	}
+
+	/* We only care about bridges (1=pci_bridge, 2=card_bus_bridge) */
+
+	pci_value &= PCI_HEADER_TYPE_MASK;
+
+	if ((pci_value != PCI_TYPE_BRIDGE) &&
+	    (pci_value != PCI_TYPE_CARDBUS_BRIDGE)) {
+		return (AE_OK);
+	}
+
+	/* Bridge: Get the Primary bus_number */
+
+	status = acpi_os_read_pci_configuration(pci_id,
+						PCI_CFG_PRIMARY_BUS_NUMBER_REG,
+						&pci_value, 8);
+	if (ACPI_FAILURE(status)) {
+		return (status);
+	}
+
+	*is_bridge = TRUE;
+	pci_id->bus = (u16)pci_value;
+
+	/* Bridge: Get the Secondary bus_number */
+
+	status = acpi_os_read_pci_configuration(pci_id,
+						PCI_CFG_SECONDARY_BUS_NUMBER_REG,
+						&pci_value, 8);
+	if (ACPI_FAILURE(status)) {
+		return (status);
+	}
+
+	*bus_number = (u16)pci_value;
+	return (AE_OK);
+}
diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c
index 4009498..4ef9f43 100644
--- a/drivers/acpi/acpica/nsrepair2.c
+++ b/drivers/acpi/acpica/nsrepair2.c
@@ -74,10 +74,18 @@
 		   union acpi_operand_object **return_object_ptr);
 
 static acpi_status
+acpi_ns_repair_CID(struct acpi_predefined_data *data,
+		   union acpi_operand_object **return_object_ptr);
+
+static acpi_status
 acpi_ns_repair_FDE(struct acpi_predefined_data *data,
 		   union acpi_operand_object **return_object_ptr);
 
 static acpi_status
+acpi_ns_repair_HID(struct acpi_predefined_data *data,
+		   union acpi_operand_object **return_object_ptr);
+
+static acpi_status
 acpi_ns_repair_PSS(struct acpi_predefined_data *data,
 		   union acpi_operand_object **return_object_ptr);
 
@@ -108,8 +116,10 @@
  * As necessary:
  *
  * _ALR: Sort the list ascending by ambient_illuminance
+ * _CID: Strings: uppercase all, remove any leading asterisk
  * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs
  * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs
+ * _HID: Strings: uppercase all, remove any leading asterisk
  * _PSS: Sort the list descending by Power
  * _TSS: Sort the list descending by Power
  *
@@ -122,8 +132,10 @@
  */
 static const struct acpi_repair_info acpi_ns_repairable_names[] = {
 	{"_ALR", acpi_ns_repair_ALR},
+	{"_CID", acpi_ns_repair_CID},
 	{"_FDE", acpi_ns_repair_FDE},
 	{"_GTM", acpi_ns_repair_FDE},	/* _GTM has same repair as _FDE */
+	{"_HID", acpi_ns_repair_HID},
 	{"_PSS", acpi_ns_repair_PSS},
 	{"_TSS", acpi_ns_repair_TSS},
 	{{0, 0, 0, 0}, NULL}	/* Table terminator */
@@ -321,6 +333,157 @@
 
 /******************************************************************************
  *
+ * FUNCTION:    acpi_ns_repair_CID
+ *
+ * PARAMETERS:  Data                - Pointer to validation data structure
+ *              return_object_ptr   - Pointer to the object returned from the
+ *                                    evaluation of a method or object
+ *
+ * RETURN:      Status. AE_OK if object is OK or was repaired successfully
+ *
+ * DESCRIPTION: Repair for the _CID object. If a string, ensure that all
+ *              letters are uppercase and that there is no leading asterisk.
+ *              If a Package, ensure same for all string elements.
+ *
+ *****************************************************************************/
+
+static acpi_status
+acpi_ns_repair_CID(struct acpi_predefined_data *data,
+		   union acpi_operand_object **return_object_ptr)
+{
+	acpi_status status;
+	union acpi_operand_object *return_object = *return_object_ptr;
+	union acpi_operand_object **element_ptr;
+	union acpi_operand_object *original_element;
+	u16 original_ref_count;
+	u32 i;
+
+	/* Check for _CID as a simple string */
+
+	if (return_object->common.type == ACPI_TYPE_STRING) {
+		status = acpi_ns_repair_HID(data, return_object_ptr);
+		return (status);
+	}
+
+	/* Exit if not a Package */
+
+	if (return_object->common.type != ACPI_TYPE_PACKAGE) {
+		return (AE_OK);
+	}
+
+	/* Examine each element of the _CID package */
+
+	element_ptr = return_object->package.elements;
+	for (i = 0; i < return_object->package.count; i++) {
+		original_element = *element_ptr;
+		original_ref_count = original_element->common.reference_count;
+
+		status = acpi_ns_repair_HID(data, element_ptr);
+		if (ACPI_FAILURE(status)) {
+			return (status);
+		}
+
+		/* Take care with reference counts */
+
+		if (original_element != *element_ptr) {
+
+			/* Element was replaced */
+
+			(*element_ptr)->common.reference_count =
+			    original_ref_count;
+
+			acpi_ut_remove_reference(original_element);
+		}
+
+		element_ptr++;
+	}
+
+	return (AE_OK);
+}
+
+/******************************************************************************
+ *
+ * FUNCTION:    acpi_ns_repair_HID
+ *
+ * PARAMETERS:  Data                - Pointer to validation data structure
+ *              return_object_ptr   - Pointer to the object returned from the
+ *                                    evaluation of a method or object
+ *
+ * RETURN:      Status. AE_OK if object is OK or was repaired successfully
+ *
+ * DESCRIPTION: Repair for the _HID object. If a string, ensure that all
+ *              letters are uppercase and that there is no leading asterisk.
+ *
+ *****************************************************************************/
+
+static acpi_status
+acpi_ns_repair_HID(struct acpi_predefined_data *data,
+		   union acpi_operand_object **return_object_ptr)
+{
+	union acpi_operand_object *return_object = *return_object_ptr;
+	union acpi_operand_object *new_string;
+	char *source;
+	char *dest;
+
+	ACPI_FUNCTION_NAME(ns_repair_HID);
+
+	/* We only care about string _HID objects (not integers) */
+
+	if (return_object->common.type != ACPI_TYPE_STRING) {
+		return (AE_OK);
+	}
+
+	if (return_object->string.length == 0) {
+		ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
+				      "Invalid zero-length _HID or _CID string"));
+
+		/* Return AE_OK anyway, let driver handle it */
+
+		data->flags |= ACPI_OBJECT_REPAIRED;
+		return (AE_OK);
+	}
+
+	/* It is simplest to always create a new string object */
+
+	new_string = acpi_ut_create_string_object(return_object->string.length);
+	if (!new_string) {
+		return (AE_NO_MEMORY);
+	}
+
+	/*
+	 * Remove a leading asterisk if present. For some unknown reason, there
+	 * are many machines in the field that contains IDs like this.
+	 *
+	 * Examples: "*PNP0C03", "*ACPI0003"
+	 */
+	source = return_object->string.pointer;
+	if (*source == '*') {
+		source++;
+		new_string->string.length--;
+
+		ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
+				  "%s: Removed invalid leading asterisk\n",
+				  data->pathname));
+	}
+
+	/*
+	 * Copy and uppercase the string. From the ACPI specification:
+	 *
+	 * A valid PNP ID must be of the form "AAA####" where A is an uppercase
+	 * letter and # is a hex digit. A valid ACPI ID must be of the form
+	 * "ACPI####" where # is a hex digit.
+	 */
+	for (dest = new_string->string.pointer; *source; dest++, source++) {
+		*dest = (char)ACPI_TOUPPER(*source);
+	}
+
+	acpi_ut_remove_reference(return_object);
+	*return_object_ptr = new_string;
+	return (AE_OK);
+}
+
+/******************************************************************************
+ *
  * FUNCTION:    acpi_ns_repair_TSS
  *
  * PARAMETERS:  Data                - Pointer to validation data structure
diff --git a/drivers/acpi/acpica/nsutils.c b/drivers/acpi/acpica/nsutils.c
index e1add34..a7d6ad9 100644
--- a/drivers/acpi/acpica/nsutils.c
+++ b/drivers/acpi/acpica/nsutils.c
@@ -60,104 +60,6 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ns_report_error
- *
- * PARAMETERS:  module_name         - Caller's module name (for error output)
- *              line_number         - Caller's line number (for error output)
- *              internal_name       - Name or path of the namespace node
- *              lookup_status       - Exception code from NS lookup
- *
- * RETURN:      None
- *
- * DESCRIPTION: Print warning message with full pathname
- *
- ******************************************************************************/
-
-void
-acpi_ns_report_error(const char *module_name,
-		     u32 line_number,
-		     const char *internal_name, acpi_status lookup_status)
-{
-	acpi_status status;
-	u32 bad_name;
-	char *name = NULL;
-
-	acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number);
-
-	if (lookup_status == AE_BAD_CHARACTER) {
-
-		/* There is a non-ascii character in the name */
-
-		ACPI_MOVE_32_TO_32(&bad_name,
-				   ACPI_CAST_PTR(u32, internal_name));
-		acpi_os_printf("[0x%4.4X] (NON-ASCII)", bad_name);
-	} else {
-		/* Convert path to external format */
-
-		status = acpi_ns_externalize_name(ACPI_UINT32_MAX,
-						  internal_name, NULL, &name);
-
-		/* Print target name */
-
-		if (ACPI_SUCCESS(status)) {
-			acpi_os_printf("[%s]", name);
-		} else {
-			acpi_os_printf("[COULD NOT EXTERNALIZE NAME]");
-		}
-
-		if (name) {
-			ACPI_FREE(name);
-		}
-	}
-
-	acpi_os_printf(" Namespace lookup failure, %s\n",
-		       acpi_format_exception(lookup_status));
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ns_report_method_error
- *
- * PARAMETERS:  module_name         - Caller's module name (for error output)
- *              line_number         - Caller's line number (for error output)
- *              Message             - Error message to use on failure
- *              prefix_node         - Prefix relative to the path
- *              Path                - Path to the node (optional)
- *              method_status       - Execution status
- *
- * RETURN:      None
- *
- * DESCRIPTION: Print warning message with full pathname
- *
- ******************************************************************************/
-
-void
-acpi_ns_report_method_error(const char *module_name,
-			    u32 line_number,
-			    const char *message,
-			    struct acpi_namespace_node *prefix_node,
-			    const char *path, acpi_status method_status)
-{
-	acpi_status status;
-	struct acpi_namespace_node *node = prefix_node;
-
-	acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number);
-
-	if (path) {
-		status =
-		    acpi_ns_get_node(prefix_node, path, ACPI_NS_NO_UPSEARCH,
-				     &node);
-		if (ACPI_FAILURE(status)) {
-			acpi_os_printf("[Could not get node by pathname]");
-		}
-	}
-
-	acpi_ns_print_node_pathname(node, message);
-	acpi_os_printf(", %s\n", acpi_format_exception(method_status));
-}
-
-/*******************************************************************************
- *
  * FUNCTION:    acpi_ns_print_node_pathname
  *
  * PARAMETERS:  Node            - Object
diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c
index 1728cb9..d2ff432 100644
--- a/drivers/acpi/acpica/tbfadt.c
+++ b/drivers/acpi/acpica/tbfadt.c
@@ -49,7 +49,7 @@
 ACPI_MODULE_NAME("tbfadt")
 
 /* Local prototypes */
-static inline void
+static ACPI_INLINE void
 acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
 			     u8 space_id, u8 byte_width, u64 address);
 
@@ -181,7 +181,7 @@
  *
  ******************************************************************************/
 
-static inline void
+static ACPI_INLINE void
 acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
 			     u8 space_id, u8 byte_width, u64 address)
 {
diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c
index 9835106..f21c486 100644
--- a/drivers/acpi/acpica/utdebug.c
+++ b/drivers/acpi/acpica/utdebug.c
@@ -179,9 +179,8 @@
 	if (thread_id != acpi_gbl_prev_thread_id) {
 		if (ACPI_LV_THREADS & acpi_dbg_level) {
 			acpi_os_printf
-			    ("\n**** Context Switch from TID %p to TID %p ****\n\n",
-			     ACPI_CAST_PTR(void, acpi_gbl_prev_thread_id),
-			     ACPI_CAST_PTR(void, thread_id));
+			    ("\n**** Context Switch from TID %u to TID %u ****\n\n",
+			     (u32)acpi_gbl_prev_thread_id, (u32)thread_id);
 		}
 
 		acpi_gbl_prev_thread_id = thread_id;
@@ -194,7 +193,7 @@
 	acpi_os_printf("%8s-%04ld ", module_name, line_number);
 
 	if (ACPI_LV_THREADS & acpi_dbg_level) {
-		acpi_os_printf("[%p] ", ACPI_CAST_PTR(void, thread_id));
+		acpi_os_printf("[%u] ", (u32)thread_id);
 	}
 
 	acpi_os_printf("[%02ld] %-22.22s: ",
diff --git a/drivers/acpi/acpica/uteval.c b/drivers/acpi/acpica/uteval.c
index 6dfdeb6..22f59ef 100644
--- a/drivers/acpi/acpica/uteval.c
+++ b/drivers/acpi/acpica/uteval.c
@@ -48,153 +48,6 @@
 #define _COMPONENT          ACPI_UTILITIES
 ACPI_MODULE_NAME("uteval")
 
-/*
- * Strings supported by the _OSI predefined (internal) method.
- *
- * March 2009: Removed "Linux" as this host no longer wants to respond true
- * for this string. Basically, the only safe OS strings are windows-related
- * and in many or most cases represent the only test path within the
- * BIOS-provided ASL code.
- *
- * The second element of each entry is used to track the newest version of
- * Windows that the BIOS has requested.
- */
-static struct acpi_interface_info acpi_interfaces_supported[] = {
-	/* Operating System Vendor Strings */
-
-	{"Windows 2000", ACPI_OSI_WIN_2000},	/* Windows 2000 */
-	{"Windows 2001", ACPI_OSI_WIN_XP},	/* Windows XP */
-	{"Windows 2001 SP1", ACPI_OSI_WIN_XP_SP1},	/* Windows XP SP1 */
-	{"Windows 2001.1", ACPI_OSI_WINSRV_2003},	/* Windows Server 2003 */
-	{"Windows 2001 SP2", ACPI_OSI_WIN_XP_SP2},	/* Windows XP SP2 */
-	{"Windows 2001.1 SP1", ACPI_OSI_WINSRV_2003_SP1},	/* Windows Server 2003 SP1 - Added 03/2006 */
-	{"Windows 2006", ACPI_OSI_WIN_VISTA},	/* Windows Vista - Added 03/2006 */
-	{"Windows 2006.1", ACPI_OSI_WINSRV_2008},	/* Windows Server 2008 - Added 09/2009 */
-	{"Windows 2006 SP1", ACPI_OSI_WIN_VISTA_SP1},	/* Windows Vista SP1 - Added 09/2009 */
-	{"Windows 2009", ACPI_OSI_WIN_7},	/* Windows 7 and Server 2008 R2 - Added 09/2009 */
-
-	/* Feature Group Strings */
-
-	{"Extended Address Space Descriptor", 0}
-
-	/*
-	 * All "optional" feature group strings (features that are implemented
-	 * by the host) should be implemented in the host version of
-	 * acpi_os_validate_interface and should not be added here.
-	 */
-};
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_osi_implementation
- *
- * PARAMETERS:  walk_state          - Current walk state
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Implementation of the _OSI predefined control method
- *
- ******************************************************************************/
-
-acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state)
-{
-	acpi_status status;
-	union acpi_operand_object *string_desc;
-	union acpi_operand_object *return_desc;
-	u32 return_value;
-	u32 i;
-
-	ACPI_FUNCTION_TRACE(ut_osi_implementation);
-
-	/* Validate the string input argument */
-
-	string_desc = walk_state->arguments[0].object;
-	if (!string_desc || (string_desc->common.type != ACPI_TYPE_STRING)) {
-		return_ACPI_STATUS(AE_TYPE);
-	}
-
-	/* Create a return object */
-
-	return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
-	if (!return_desc) {
-		return_ACPI_STATUS(AE_NO_MEMORY);
-	}
-
-	/* Default return value is 0, NOT SUPPORTED */
-
-	return_value = 0;
-
-	/* Compare input string to static table of supported interfaces */
-
-	for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) {
-		if (!ACPI_STRCMP(string_desc->string.pointer,
-				 acpi_interfaces_supported[i].name)) {
-			/*
-			 * The interface is supported.
-			 * Update the osi_data if necessary. We keep track of the latest
-			 * version of Windows that has been requested by the BIOS.
-			 */
-			if (acpi_interfaces_supported[i].value >
-			    acpi_gbl_osi_data) {
-				acpi_gbl_osi_data =
-				    acpi_interfaces_supported[i].value;
-			}
-
-			return_value = ACPI_UINT32_MAX;
-			goto exit;
-		}
-	}
-
-	/*
-	 * Did not match the string in the static table, call the host OSL to
-	 * check for a match with one of the optional strings (such as
-	 * "Module Device", "3.0 Thermal Model", etc.)
-	 */
-	status = acpi_os_validate_interface(string_desc->string.pointer);
-	if (ACPI_SUCCESS(status)) {
-
-		/* The interface is supported */
-
-		return_value = ACPI_UINT32_MAX;
-	}
-
-exit:
-	ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO,
-		"ACPI: BIOS _OSI(%s) is %ssupported\n",
-		string_desc->string.pointer, return_value == 0 ? "not " : ""));
-
-	/* Complete the return value */
-
-	return_desc->integer.value = return_value;
-	walk_state->return_desc = return_desc;
-	return_ACPI_STATUS (AE_OK);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_osi_invalidate
- *
- * PARAMETERS:  interface_string
- *
- * RETURN:      Status
- *
- * DESCRIPTION: invalidate string in pre-defiend _OSI string list
- *
- ******************************************************************************/
-
-acpi_status acpi_osi_invalidate(char *interface)
-{
-	int i;
-
-	for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) {
-		if (!ACPI_STRCMP(interface, acpi_interfaces_supported[i].name)) {
-			*acpi_interfaces_supported[i].name = '\0';
-			return AE_OK;
-		}
-	}
-	return AE_NOT_FOUND;
-}
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ut_evaluate_object
diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c
index 0558747..e87bc67 100644
--- a/drivers/acpi/acpica/utglobal.c
+++ b/drivers/acpi/acpica/utglobal.c
@@ -154,14 +154,16 @@
  * 1) _SB_ is defined to be a device to allow \_SB_._INI to be run
  *    during the initialization sequence.
  * 2) _TZ_ is defined to be a thermal zone in order to allow ASL code to
- *    perform a Notify() operation on it.
+ *    perform a Notify() operation on it. 09/2010: Changed to type Device.
+ *    This still allows notifies, but does not confuse host code that
+ *    searches for valid thermal_zone objects.
  */
 const struct acpi_predefined_names acpi_gbl_pre_defined_names[] = {
 	{"_GPE", ACPI_TYPE_LOCAL_SCOPE, NULL},
 	{"_PR_", ACPI_TYPE_LOCAL_SCOPE, NULL},
 	{"_SB_", ACPI_TYPE_DEVICE, NULL},
 	{"_SI_", ACPI_TYPE_LOCAL_SCOPE, NULL},
-	{"_TZ_", ACPI_TYPE_THERMAL, NULL},
+	{"_TZ_", ACPI_TYPE_DEVICE, NULL},
 	{"_REV", ACPI_TYPE_INTEGER, (char *)ACPI_CA_SUPPORT_LEVEL},
 	{"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME},
 	{"_GL_", ACPI_TYPE_MUTEX, (char *)1},
@@ -766,6 +768,7 @@
 	acpi_gbl_gpe_fadt_blocks[0] = NULL;
 	acpi_gbl_gpe_fadt_blocks[1] = NULL;
 	acpi_current_gpe_count = 0;
+	acpi_all_gpes_initialized = FALSE;
 
 	/* Global handlers */
 
@@ -774,6 +777,7 @@
 	acpi_gbl_exception_handler = NULL;
 	acpi_gbl_init_handler = NULL;
 	acpi_gbl_table_handler = NULL;
+	acpi_gbl_interface_handler = NULL;
 
 	/* Global Lock support */
 
@@ -800,6 +804,7 @@
 	acpi_gbl_debugger_configuration = DEBUGGER_THREADING;
 	acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT;
 	acpi_gbl_osi_data = 0;
+	acpi_gbl_osi_mutex = NULL;
 
 	/* Hardware oriented */
 
diff --git a/drivers/acpi/acpica/utids.c b/drivers/acpi/acpica/utids.c
index 1397fad..d290632 100644
--- a/drivers/acpi/acpica/utids.c
+++ b/drivers/acpi/acpica/utids.c
@@ -48,42 +48,6 @@
 #define _COMPONENT          ACPI_UTILITIES
 ACPI_MODULE_NAME("utids")
 
-/* Local prototypes */
-static void acpi_ut_copy_id_string(char *destination, char *source);
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_copy_id_string
- *
- * PARAMETERS:  Destination         - Where to copy the string
- *              Source              - Source string
- *
- * RETURN:      None
- *
- * DESCRIPTION: Copies an ID string for the _HID, _CID, and _UID methods.
- *              Performs removal of a leading asterisk if present -- workaround
- *              for a known issue on a bunch of machines.
- *
- ******************************************************************************/
-
-static void acpi_ut_copy_id_string(char *destination, char *source)
-{
-
-	/*
-	 * Workaround for ID strings that have a leading asterisk. This construct
-	 * is not allowed by the ACPI specification  (ID strings must be
-	 * alphanumeric), but enough existing machines have this embedded in their
-	 * ID strings that the following code is useful.
-	 */
-	if (*source == '*') {
-		source++;
-	}
-
-	/* Do the actual copy */
-
-	ACPI_STRCPY(destination, source);
-}
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ut_execute_HID
@@ -101,7 +65,6 @@
  *              NOTE: Internal function, no parameter validation
  *
  ******************************************************************************/
-
 acpi_status
 acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
 		    struct acpica_device_id **return_id)
@@ -147,7 +110,7 @@
 	if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
 		acpi_ex_eisa_id_to_string(hid->string, obj_desc->integer.value);
 	} else {
-		acpi_ut_copy_id_string(hid->string, obj_desc->string.pointer);
+		ACPI_STRCPY(hid->string, obj_desc->string.pointer);
 	}
 
 	hid->length = length;
@@ -224,7 +187,7 @@
 	if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
 		acpi_ex_integer_to_string(uid->string, obj_desc->integer.value);
 	} else {
-		acpi_ut_copy_id_string(uid->string, obj_desc->string.pointer);
+		ACPI_STRCPY(uid->string, obj_desc->string.pointer);
 	}
 
 	uid->length = length;
@@ -357,8 +320,8 @@
 
 			/* Copy the String CID from the returned object */
 
-			acpi_ut_copy_id_string(next_id_string,
-					       cid_objects[i]->string.pointer);
+			ACPI_STRCPY(next_id_string,
+				    cid_objects[i]->string.pointer);
 			length = cid_objects[i]->string.length + 1;
 		}
 
diff --git a/drivers/acpi/acpica/utinit.c b/drivers/acpi/acpica/utinit.c
index a39c93d..c1b1c80 100644
--- a/drivers/acpi/acpica/utinit.c
+++ b/drivers/acpi/acpica/utinit.c
@@ -117,6 +117,10 @@
 	/* Close the acpi_event Handling */
 
 	acpi_ev_terminate();
+
+	/* Delete any dynamic _OSI interfaces */
+
+	acpi_ut_interface_terminate();
 #endif
 
 	/* Close the Namespace */
diff --git a/drivers/acpi/acpica/utmath.c b/drivers/acpi/acpica/utmath.c
index 35059a1..49cf7b7 100644
--- a/drivers/acpi/acpica/utmath.c
+++ b/drivers/acpi/acpica/utmath.c
@@ -48,11 +48,27 @@
 ACPI_MODULE_NAME("utmath")
 
 /*
- * Support for double-precision integer divide.  This code is included here
- * in order to support kernel environments where the double-precision math
- * library is not available.
+ * Optional support for 64-bit double-precision integer divide. This code
+ * is configurable and is implemented in order to support 32-bit kernel
+ * environments where a 64-bit double-precision math library is not available.
+ *
+ * Support for a more normal 64-bit divide/modulo (with check for a divide-
+ * by-zero) appears after this optional section of code.
  */
 #ifndef ACPI_USE_NATIVE_DIVIDE
+/* Structures used only for 64-bit divide */
+typedef struct uint64_struct {
+	u32 lo;
+	u32 hi;
+
+} uint64_struct;
+
+typedef union uint64_overlay {
+	u64 full;
+	struct uint64_struct part;
+
+} uint64_overlay;
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ut_short_divide
@@ -69,6 +85,7 @@
  *              32-bit remainder.
  *
  ******************************************************************************/
+
 acpi_status
 acpi_ut_short_divide(u64 dividend,
 		     u32 divisor, u64 *out_quotient, u32 *out_remainder)
diff --git a/drivers/acpi/acpica/utmisc.c b/drivers/acpi/acpica/utmisc.c
index e8d0724..c7d0e05 100644
--- a/drivers/acpi/acpica/utmisc.c
+++ b/drivers/acpi/acpica/utmisc.c
@@ -50,11 +50,6 @@
 #define _COMPONENT          ACPI_UTILITIES
 ACPI_MODULE_NAME("utmisc")
 
-/*
- * Common suffix for messages
- */
-#define ACPI_COMMON_MSG_SUFFIX \
-	acpi_os_printf(" (%8.8X/%s-%u)\n", ACPI_CA_VERSION, module_name, line_number)
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ut_validate_exception
@@ -1044,160 +1039,3 @@
 
 	return_ACPI_STATUS(AE_AML_INTERNAL);
 }
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_error, acpi_exception, acpi_warning, acpi_info
- *
- * PARAMETERS:  module_name         - Caller's module name (for error output)
- *              line_number         - Caller's line number (for error output)
- *              Format              - Printf format string + additional args
- *
- * RETURN:      None
- *
- * DESCRIPTION: Print message with module/line/version info
- *
- ******************************************************************************/
-
-void ACPI_INTERNAL_VAR_XFACE
-acpi_error(const char *module_name, u32 line_number, const char *format, ...)
-{
-	va_list args;
-
-	acpi_os_printf("ACPI Error: ");
-
-	va_start(args, format);
-	acpi_os_vprintf(format, args);
-	ACPI_COMMON_MSG_SUFFIX;
-	va_end(args);
-}
-
-void ACPI_INTERNAL_VAR_XFACE
-acpi_exception(const char *module_name,
-	       u32 line_number, acpi_status status, const char *format, ...)
-{
-	va_list args;
-
-	acpi_os_printf("ACPI Exception: %s, ", acpi_format_exception(status));
-
-	va_start(args, format);
-	acpi_os_vprintf(format, args);
-	ACPI_COMMON_MSG_SUFFIX;
-	va_end(args);
-}
-
-void ACPI_INTERNAL_VAR_XFACE
-acpi_warning(const char *module_name, u32 line_number, const char *format, ...)
-{
-	va_list args;
-
-	acpi_os_printf("ACPI Warning: ");
-
-	va_start(args, format);
-	acpi_os_vprintf(format, args);
-	ACPI_COMMON_MSG_SUFFIX;
-	va_end(args);
-}
-
-void ACPI_INTERNAL_VAR_XFACE
-acpi_info(const char *module_name, u32 line_number, const char *format, ...)
-{
-	va_list args;
-
-	acpi_os_printf("ACPI: ");
-
-	va_start(args, format);
-	acpi_os_vprintf(format, args);
-	acpi_os_printf("\n");
-	va_end(args);
-}
-
-ACPI_EXPORT_SYMBOL(acpi_error)
-ACPI_EXPORT_SYMBOL(acpi_exception)
-ACPI_EXPORT_SYMBOL(acpi_warning)
-ACPI_EXPORT_SYMBOL(acpi_info)
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_predefined_warning
- *
- * PARAMETERS:  module_name     - Caller's module name (for error output)
- *              line_number     - Caller's line number (for error output)
- *              Pathname        - Full pathname to the node
- *              node_flags      - From Namespace node for the method/object
- *              Format          - Printf format string + additional args
- *
- * RETURN:      None
- *
- * DESCRIPTION: Warnings for the predefined validation module. Messages are
- *              only emitted the first time a problem with a particular
- *              method/object is detected. This prevents a flood of error
- *              messages for methods that are repeatedly evaluated.
- *
-******************************************************************************/
-
-void ACPI_INTERNAL_VAR_XFACE
-acpi_ut_predefined_warning(const char *module_name,
-			   u32 line_number,
-			   char *pathname,
-			   u8 node_flags, const char *format, ...)
-{
-	va_list args;
-
-	/*
-	 * Warning messages for this method/object will be disabled after the
-	 * first time a validation fails or an object is successfully repaired.
-	 */
-	if (node_flags & ANOBJ_EVALUATED) {
-		return;
-	}
-
-	acpi_os_printf("ACPI Warning for %s: ", pathname);
-
-	va_start(args, format);
-	acpi_os_vprintf(format, args);
-	ACPI_COMMON_MSG_SUFFIX;
-	va_end(args);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_predefined_info
- *
- * PARAMETERS:  module_name     - Caller's module name (for error output)
- *              line_number     - Caller's line number (for error output)
- *              Pathname        - Full pathname to the node
- *              node_flags      - From Namespace node for the method/object
- *              Format          - Printf format string + additional args
- *
- * RETURN:      None
- *
- * DESCRIPTION: Info messages for the predefined validation module. Messages
- *              are only emitted the first time a problem with a particular
- *              method/object is detected. This prevents a flood of
- *              messages for methods that are repeatedly evaluated.
- *
- ******************************************************************************/
-
-void ACPI_INTERNAL_VAR_XFACE
-acpi_ut_predefined_info(const char *module_name,
-			u32 line_number,
-			char *pathname, u8 node_flags, const char *format, ...)
-{
-	va_list args;
-
-	/*
-	 * Warning messages for this method/object will be disabled after the
-	 * first time a validation fails or an object is successfully repaired.
-	 */
-	if (node_flags & ANOBJ_EVALUATED) {
-		return;
-	}
-
-	acpi_os_printf("ACPI Info for %s: ", pathname);
-
-	va_start(args, format);
-	acpi_os_vprintf(format, args);
-	ACPI_COMMON_MSG_SUFFIX;
-	va_end(args);
-}
diff --git a/drivers/acpi/acpica/utmutex.c b/drivers/acpi/acpica/utmutex.c
index f5cca3a..d9efa49 100644
--- a/drivers/acpi/acpica/utmutex.c
+++ b/drivers/acpi/acpica/utmutex.c
@@ -86,6 +86,12 @@
 	spin_lock_init(acpi_gbl_gpe_lock);
 	spin_lock_init(acpi_gbl_hardware_lock);
 
+	/* Mutex for _OSI support */
+	status = acpi_os_create_mutex(&acpi_gbl_osi_mutex);
+	if (ACPI_FAILURE(status)) {
+		return_ACPI_STATUS(status);
+	}
+
 	/* Create the reader/writer lock for namespace access */
 
 	status = acpi_ut_create_rw_lock(&acpi_gbl_namespace_rw_lock);
@@ -117,6 +123,8 @@
 		acpi_ut_delete_mutex(i);
 	}
 
+	acpi_os_delete_mutex(acpi_gbl_osi_mutex);
+
 	/* Delete the spinlocks */
 
 	acpi_os_delete_lock(acpi_gbl_gpe_lock);
@@ -220,18 +228,17 @@
 			if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) {
 				if (i == mutex_id) {
 					ACPI_ERROR((AE_INFO,
-						    "Mutex [%s] already acquired by this thread [%p]",
+						    "Mutex [%s] already acquired by this thread [%u]",
 						    acpi_ut_get_mutex_name
 						    (mutex_id),
-						    ACPI_CAST_PTR(void,
-								  this_thread_id)));
+						    (u32)this_thread_id));
 
 					return (AE_ALREADY_ACQUIRED);
 				}
 
 				ACPI_ERROR((AE_INFO,
-					    "Invalid acquire order: Thread %p owns [%s], wants [%s]",
-					    ACPI_CAST_PTR(void, this_thread_id),
+					    "Invalid acquire order: Thread %u owns [%s], wants [%s]",
+					    (u32)this_thread_id,
 					    acpi_ut_get_mutex_name(i),
 					    acpi_ut_get_mutex_name(mutex_id)));
 
@@ -242,24 +249,24 @@
 #endif
 
 	ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
-			  "Thread %p attempting to acquire Mutex [%s]\n",
-			  ACPI_CAST_PTR(void, this_thread_id),
+			  "Thread %u attempting to acquire Mutex [%s]\n",
+			  (u32)this_thread_id,
 			  acpi_ut_get_mutex_name(mutex_id)));
 
 	status = acpi_os_acquire_mutex(acpi_gbl_mutex_info[mutex_id].mutex,
 				       ACPI_WAIT_FOREVER);
 	if (ACPI_SUCCESS(status)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
-				  "Thread %p acquired Mutex [%s]\n",
-				  ACPI_CAST_PTR(void, this_thread_id),
+				  "Thread %u acquired Mutex [%s]\n",
+				  (u32)this_thread_id,
 				  acpi_ut_get_mutex_name(mutex_id)));
 
 		acpi_gbl_mutex_info[mutex_id].use_count++;
 		acpi_gbl_mutex_info[mutex_id].thread_id = this_thread_id;
 	} else {
 		ACPI_EXCEPTION((AE_INFO, status,
-				"Thread %p could not acquire Mutex [0x%X]",
-				ACPI_CAST_PTR(void, this_thread_id), mutex_id));
+				"Thread %u could not acquire Mutex [0x%X]",
+				(u32)this_thread_id, mutex_id));
 	}
 
 	return (status);
@@ -279,10 +286,14 @@
 
 acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)
 {
+	acpi_thread_id this_thread_id;
+
 	ACPI_FUNCTION_NAME(ut_release_mutex);
 
-	ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %p releasing Mutex [%s]\n",
-			  ACPI_CAST_PTR(void, acpi_os_get_thread_id()),
+	this_thread_id = acpi_os_get_thread_id();
+
+	ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %u releasing Mutex [%s]\n",
+			  (u32)this_thread_id,
 			  acpi_ut_get_mutex_name(mutex_id)));
 
 	if (mutex_id > ACPI_MAX_MUTEX) {
diff --git a/drivers/acpi/acpica/utosi.c b/drivers/acpi/acpica/utosi.c
new file mode 100644
index 0000000..18c59a8
--- /dev/null
+++ b/drivers/acpi/acpica/utosi.c
@@ -0,0 +1,380 @@
+/******************************************************************************
+ *
+ * Module Name: utosi - Support for the _OSI predefined control method
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2010, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+
+#define _COMPONENT          ACPI_UTILITIES
+ACPI_MODULE_NAME("utosi")
+
+/*
+ * Strings supported by the _OSI predefined control method (which is
+ * implemented internally within this module.)
+ *
+ * March 2009: Removed "Linux" as this host no longer wants to respond true
+ * for this string. Basically, the only safe OS strings are windows-related
+ * and in many or most cases represent the only test path within the
+ * BIOS-provided ASL code.
+ *
+ * The last element of each entry is used to track the newest version of
+ * Windows that the BIOS has requested.
+ */
+static struct acpi_interface_info acpi_default_supported_interfaces[] = {
+	/* Operating System Vendor Strings */
+
+	{"Windows 2000", NULL, 0, ACPI_OSI_WIN_2000},	/* Windows 2000 */
+	{"Windows 2001", NULL, 0, ACPI_OSI_WIN_XP},	/* Windows XP */
+	{"Windows 2001 SP1", NULL, 0, ACPI_OSI_WIN_XP_SP1},	/* Windows XP SP1 */
+	{"Windows 2001.1", NULL, 0, ACPI_OSI_WINSRV_2003},	/* Windows Server 2003 */
+	{"Windows 2001 SP2", NULL, 0, ACPI_OSI_WIN_XP_SP2},	/* Windows XP SP2 */
+	{"Windows 2001.1 SP1", NULL, 0, ACPI_OSI_WINSRV_2003_SP1},	/* Windows Server 2003 SP1 - Added 03/2006 */
+	{"Windows 2006", NULL, 0, ACPI_OSI_WIN_VISTA},	/* Windows Vista - Added 03/2006 */
+	{"Windows 2006.1", NULL, 0, ACPI_OSI_WINSRV_2008},	/* Windows Server 2008 - Added 09/2009 */
+	{"Windows 2006 SP1", NULL, 0, ACPI_OSI_WIN_VISTA_SP1},	/* Windows Vista SP1 - Added 09/2009 */
+	{"Windows 2006 SP2", NULL, 0, ACPI_OSI_WIN_VISTA_SP2},	/* Windows Vista SP2 - Added 09/2010 */
+	{"Windows 2009", NULL, 0, ACPI_OSI_WIN_7},	/* Windows 7 and Server 2008 R2 - Added 09/2009 */
+
+	/* Feature Group Strings */
+
+	{"Extended Address Space Descriptor", NULL, 0, 0}
+
+	/*
+	 * All "optional" feature group strings (features that are implemented
+	 * by the host) should be dynamically added by the host via
+	 * acpi_install_interface and should not be manually added here.
+	 *
+	 * Examples of optional feature group strings:
+	 *
+	 * "Module Device"
+	 * "Processor Device"
+	 * "3.0 Thermal Model"
+	 * "3.0 _SCP Extensions"
+	 * "Processor Aggregator Device"
+	 */
+};
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_initialize_interfaces
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Initialize the global _OSI supported interfaces list
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ut_initialize_interfaces(void)
+{
+	u32 i;
+
+	(void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
+	acpi_gbl_supported_interfaces = acpi_default_supported_interfaces;
+
+	/* Link the static list of supported interfaces */
+
+	for (i = 0;
+	     i < (ACPI_ARRAY_LENGTH(acpi_default_supported_interfaces) - 1);
+	     i++) {
+		acpi_default_supported_interfaces[i].next =
+		    &acpi_default_supported_interfaces[(acpi_size) i + 1];
+	}
+
+	acpi_os_release_mutex(acpi_gbl_osi_mutex);
+	return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_interface_terminate
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Delete all interfaces in the global list. Sets
+ *              acpi_gbl_supported_interfaces to NULL.
+ *
+ ******************************************************************************/
+
+void acpi_ut_interface_terminate(void)
+{
+	struct acpi_interface_info *next_interface;
+
+	(void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
+	next_interface = acpi_gbl_supported_interfaces;
+
+	while (next_interface) {
+		acpi_gbl_supported_interfaces = next_interface->next;
+
+		/* Only interfaces added at runtime can be freed */
+
+		if (next_interface->flags & ACPI_OSI_DYNAMIC) {
+			ACPI_FREE(next_interface->name);
+			ACPI_FREE(next_interface);
+		}
+
+		next_interface = acpi_gbl_supported_interfaces;
+	}
+
+	acpi_os_release_mutex(acpi_gbl_osi_mutex);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_install_interface
+ *
+ * PARAMETERS:  interface_name      - The interface to install
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Install the interface into the global interface list.
+ *              Caller MUST hold acpi_gbl_osi_mutex
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ut_install_interface(acpi_string interface_name)
+{
+	struct acpi_interface_info *interface_info;
+
+	/* Allocate info block and space for the name string */
+
+	interface_info =
+	    ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_interface_info));
+	if (!interface_info) {
+		return (AE_NO_MEMORY);
+	}
+
+	interface_info->name =
+	    ACPI_ALLOCATE_ZEROED(ACPI_STRLEN(interface_name) + 1);
+	if (!interface_info->name) {
+		ACPI_FREE(interface_info);
+		return (AE_NO_MEMORY);
+	}
+
+	/* Initialize new info and insert at the head of the global list */
+
+	ACPI_STRCPY(interface_info->name, interface_name);
+	interface_info->flags = ACPI_OSI_DYNAMIC;
+	interface_info->next = acpi_gbl_supported_interfaces;
+
+	acpi_gbl_supported_interfaces = interface_info;
+	return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_remove_interface
+ *
+ * PARAMETERS:  interface_name      - The interface to remove
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Remove the interface from the global interface list.
+ *              Caller MUST hold acpi_gbl_osi_mutex
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ut_remove_interface(acpi_string interface_name)
+{
+	struct acpi_interface_info *previous_interface;
+	struct acpi_interface_info *next_interface;
+
+	previous_interface = next_interface = acpi_gbl_supported_interfaces;
+	while (next_interface) {
+		if (!ACPI_STRCMP(interface_name, next_interface->name)) {
+
+			/* Found: name is in either the static list or was added at runtime */
+
+			if (next_interface->flags & ACPI_OSI_DYNAMIC) {
+
+				/* Interface was added dynamically, remove and free it */
+
+				if (previous_interface == next_interface) {
+					acpi_gbl_supported_interfaces =
+					    next_interface->next;
+				} else {
+					previous_interface->next =
+					    next_interface->next;
+				}
+
+				ACPI_FREE(next_interface->name);
+				ACPI_FREE(next_interface);
+			} else {
+				/*
+				 * Interface is in static list. If marked invalid, then it
+				 * does not actually exist. Else, mark it invalid.
+				 */
+				if (next_interface->flags & ACPI_OSI_INVALID) {
+					return (AE_NOT_EXIST);
+				}
+
+				next_interface->flags |= ACPI_OSI_INVALID;
+			}
+
+			return (AE_OK);
+		}
+
+		previous_interface = next_interface;
+		next_interface = next_interface->next;
+	}
+
+	/* Interface was not found */
+
+	return (AE_NOT_EXIST);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_get_interface
+ *
+ * PARAMETERS:  interface_name      - The interface to find
+ *
+ * RETURN:      struct acpi_interface_info if found. NULL if not found.
+ *
+ * DESCRIPTION: Search for the specified interface name in the global list.
+ *              Caller MUST hold acpi_gbl_osi_mutex
+ *
+ ******************************************************************************/
+
+struct acpi_interface_info *acpi_ut_get_interface(acpi_string interface_name)
+{
+	struct acpi_interface_info *next_interface;
+
+	next_interface = acpi_gbl_supported_interfaces;
+	while (next_interface) {
+		if (!ACPI_STRCMP(interface_name, next_interface->name)) {
+			return (next_interface);
+		}
+
+		next_interface = next_interface->next;
+	}
+
+	return (NULL);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_osi_implementation
+ *
+ * PARAMETERS:  walk_state          - Current walk state
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Implementation of the _OSI predefined control method. When
+ *              an invocation of _OSI is encountered in the system AML,
+ *              control is transferred to this function.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ut_osi_implementation(struct acpi_walk_state * walk_state)
+{
+	union acpi_operand_object *string_desc;
+	union acpi_operand_object *return_desc;
+	struct acpi_interface_info *interface_info;
+	acpi_interface_handler interface_handler;
+	u32 return_value;
+
+	ACPI_FUNCTION_TRACE(ut_osi_implementation);
+
+	/* Validate the string input argument (from the AML caller) */
+
+	string_desc = walk_state->arguments[0].object;
+	if (!string_desc || (string_desc->common.type != ACPI_TYPE_STRING)) {
+		return_ACPI_STATUS(AE_TYPE);
+	}
+
+	/* Create a return object */
+
+	return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
+	if (!return_desc) {
+		return_ACPI_STATUS(AE_NO_MEMORY);
+	}
+
+	/* Default return value is 0, NOT SUPPORTED */
+
+	return_value = 0;
+	(void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
+
+	/* Lookup the interface in the global _OSI list */
+
+	interface_info = acpi_ut_get_interface(string_desc->string.pointer);
+	if (interface_info && !(interface_info->flags & ACPI_OSI_INVALID)) {
+		/*
+		 * The interface is supported.
+		 * Update the osi_data if necessary. We keep track of the latest
+		 * version of Windows that has been requested by the BIOS.
+		 */
+		if (interface_info->value > acpi_gbl_osi_data) {
+			acpi_gbl_osi_data = interface_info->value;
+		}
+
+		return_value = ACPI_UINT32_MAX;
+	}
+
+	acpi_os_release_mutex(acpi_gbl_osi_mutex);
+
+	/*
+	 * Invoke an optional _OSI interface handler. The host OS may wish
+	 * to do some interface-specific handling. For example, warn about
+	 * certain interfaces or override the true/false support value.
+	 */
+	interface_handler = acpi_gbl_interface_handler;
+	if (interface_handler) {
+		return_value =
+		    interface_handler(string_desc->string.pointer,
+				      return_value);
+	}
+
+	ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO,
+			      "ACPI: BIOS _OSI(\"%s\") is %ssupported\n",
+			      string_desc->string.pointer,
+			      return_value == 0 ? "not " : ""));
+
+	/* Complete the return object */
+
+	return_desc->integer.value = return_value;
+	walk_state->return_desc = return_desc;
+	return_ACPI_STATUS(AE_OK);
+}
diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c
index 7f8cefc..1f484c9 100644
--- a/drivers/acpi/acpica/utxface.c
+++ b/drivers/acpi/acpica/utxface.c
@@ -110,6 +110,15 @@
 		return_ACPI_STATUS(status);
 	}
 
+	/* Initialize the global OSI interfaces list with the static names */
+
+	status = acpi_ut_initialize_interfaces();
+	if (ACPI_FAILURE(status)) {
+		ACPI_EXCEPTION((AE_INFO, status,
+				"During OSI interfaces initialization"));
+		return_ACPI_STATUS(status);
+	}
+
 	/* If configured, initialize the AML debugger */
 
 	ACPI_DEBUGGER_EXEC(status = acpi_db_initialize());
@@ -290,19 +299,6 @@
 	}
 
 	/*
-	 * Complete the GPE initialization for the GPE blocks defined in the FADT
-	 * (GPE block 0 and 1).
-	 *
-	 * NOTE: Currently, there seems to be no need to run the _REG methods
-	 * before enabling the GPEs.
-	 */
-	if (!(flags & ACPI_NO_EVENT_INIT)) {
-		status = acpi_ev_install_fadt_gpes();
-		if (ACPI_FAILURE(status))
-			return (status);
-	}
-
-	/*
 	 * Empty the caches (delete the cached objects) on the assumption that
 	 * the table load filled them up more than they will be at runtime --
 	 * thus wasting non-paged memory.
@@ -506,6 +502,7 @@
 
 ACPI_EXPORT_SYMBOL(acpi_install_initialization_handler)
 #endif				/*  ACPI_FUTURE_USAGE  */
+
 /*****************************************************************************
  *
  * FUNCTION:    acpi_purge_cached_objects
@@ -529,4 +526,117 @@
 }
 
 ACPI_EXPORT_SYMBOL(acpi_purge_cached_objects)
-#endif
+
+/*****************************************************************************
+ *
+ * FUNCTION:    acpi_install_interface
+ *
+ * PARAMETERS:  interface_name      - The interface to install
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Install an _OSI interface to the global list
+ *
+ ****************************************************************************/
+acpi_status acpi_install_interface(acpi_string interface_name)
+{
+	acpi_status status;
+	struct acpi_interface_info *interface_info;
+
+	/* Parameter validation */
+
+	if (!interface_name || (ACPI_STRLEN(interface_name) == 0)) {
+		return (AE_BAD_PARAMETER);
+	}
+
+	(void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
+
+	/* Check if the interface name is already in the global list */
+
+	interface_info = acpi_ut_get_interface(interface_name);
+	if (interface_info) {
+		/*
+		 * The interface already exists in the list. This is OK if the
+		 * interface has been marked invalid -- just clear the bit.
+		 */
+		if (interface_info->flags & ACPI_OSI_INVALID) {
+			interface_info->flags &= ~ACPI_OSI_INVALID;
+			status = AE_OK;
+		} else {
+			status = AE_ALREADY_EXISTS;
+		}
+	} else {
+		/* New interface name, install into the global list */
+
+		status = acpi_ut_install_interface(interface_name);
+	}
+
+	acpi_os_release_mutex(acpi_gbl_osi_mutex);
+	return (status);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_install_interface)
+
+/*****************************************************************************
+ *
+ * FUNCTION:    acpi_remove_interface
+ *
+ * PARAMETERS:  interface_name      - The interface to remove
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Remove an _OSI interface from the global list
+ *
+ ****************************************************************************/
+acpi_status acpi_remove_interface(acpi_string interface_name)
+{
+	acpi_status status;
+
+	/* Parameter validation */
+
+	if (!interface_name || (ACPI_STRLEN(interface_name) == 0)) {
+		return (AE_BAD_PARAMETER);
+	}
+
+	(void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
+
+	status = acpi_ut_remove_interface(interface_name);
+
+	acpi_os_release_mutex(acpi_gbl_osi_mutex);
+	return (status);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_remove_interface)
+
+/*****************************************************************************
+ *
+ * FUNCTION:    acpi_install_interface_handler
+ *
+ * PARAMETERS:  Handler             - The _OSI interface handler to install
+ *                                    NULL means "remove existing handler"
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Install a handler for the predefined _OSI ACPI method.
+ *              invoked during execution of the internal implementation of
+ *              _OSI. A NULL handler simply removes any existing handler.
+ *
+ ****************************************************************************/
+acpi_status acpi_install_interface_handler(acpi_interface_handler handler)
+{
+	acpi_status status = AE_OK;
+
+	(void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
+
+	if (handler && acpi_gbl_interface_handler) {
+		status = AE_ALREADY_EXISTS;
+	} else {
+		acpi_gbl_interface_handler = handler;
+	}
+
+	acpi_os_release_mutex(acpi_gbl_osi_mutex);
+	return (status);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_install_interface_handler)
+#endif				/* !ACPI_ASL_COMPILER */
diff --git a/drivers/acpi/acpica/utxferror.c b/drivers/acpi/acpica/utxferror.c
new file mode 100644
index 0000000..6f12e31
--- /dev/null
+++ b/drivers/acpi/acpica/utxferror.c
@@ -0,0 +1,415 @@
+/*******************************************************************************
+ *
+ * Module Name: utxferror - Various error/warning output functions
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2010, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "acnamesp.h"
+
+#define _COMPONENT          ACPI_UTILITIES
+ACPI_MODULE_NAME("utxferror")
+
+/*
+ * This module is used for the in-kernel ACPICA as well as the ACPICA
+ * tools/applications.
+ *
+ * For the i_aSL compiler case, the output is redirected to stderr so that
+ * any of the various ACPI errors and warnings do not appear in the output
+ * files, for either the compiler or disassembler portions of the tool.
+ */
+#ifdef ACPI_ASL_COMPILER
+#include <stdio.h>
+extern FILE *acpi_gbl_output_file;
+
+#define ACPI_MSG_REDIRECT_BEGIN \
+	FILE                            *output_file = acpi_gbl_output_file; \
+	acpi_os_redirect_output (stderr);
+
+#define ACPI_MSG_REDIRECT_END \
+	acpi_os_redirect_output (output_file);
+
+#else
+/*
+ * non-i_aSL case - no redirection, nothing to do
+ */
+#define ACPI_MSG_REDIRECT_BEGIN
+#define ACPI_MSG_REDIRECT_END
+#endif
+/*
+ * Common message prefixes
+ */
+#define ACPI_MSG_ERROR          "ACPI Error: "
+#define ACPI_MSG_EXCEPTION      "ACPI Exception: "
+#define ACPI_MSG_WARNING        "ACPI Warning: "
+#define ACPI_MSG_INFO           "ACPI: "
+/*
+ * Common message suffix
+ */
+#define ACPI_MSG_SUFFIX \
+	acpi_os_printf (" (%8.8X/%s-%u)\n", ACPI_CA_VERSION, module_name, line_number)
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_error
+ *
+ * PARAMETERS:  module_name         - Caller's module name (for error output)
+ *              line_number         - Caller's line number (for error output)
+ *              Format              - Printf format string + additional args
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Print "ACPI Error" message with module/line/version info
+ *
+ ******************************************************************************/
+void ACPI_INTERNAL_VAR_XFACE
+acpi_error(const char *module_name, u32 line_number, const char *format, ...)
+{
+	va_list arg_list;
+
+	ACPI_MSG_REDIRECT_BEGIN;
+	acpi_os_printf(ACPI_MSG_ERROR);
+
+	va_start(arg_list, format);
+	acpi_os_vprintf(format, arg_list);
+	ACPI_MSG_SUFFIX;
+	va_end(arg_list);
+
+	ACPI_MSG_REDIRECT_END;
+}
+
+ACPI_EXPORT_SYMBOL(acpi_error)
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_exception
+ *
+ * PARAMETERS:  module_name         - Caller's module name (for error output)
+ *              line_number         - Caller's line number (for error output)
+ *              Status              - Status to be formatted
+ *              Format              - Printf format string + additional args
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Print "ACPI Exception" message with module/line/version info
+ *              and decoded acpi_status.
+ *
+ ******************************************************************************/
+void ACPI_INTERNAL_VAR_XFACE
+acpi_exception(const char *module_name,
+	       u32 line_number, acpi_status status, const char *format, ...)
+{
+	va_list arg_list;
+
+	ACPI_MSG_REDIRECT_BEGIN;
+	acpi_os_printf(ACPI_MSG_EXCEPTION "%s, ",
+		       acpi_format_exception(status));
+
+	va_start(arg_list, format);
+	acpi_os_vprintf(format, arg_list);
+	ACPI_MSG_SUFFIX;
+	va_end(arg_list);
+
+	ACPI_MSG_REDIRECT_END;
+}
+
+ACPI_EXPORT_SYMBOL(acpi_exception)
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_warning
+ *
+ * PARAMETERS:  module_name         - Caller's module name (for error output)
+ *              line_number         - Caller's line number (for error output)
+ *              Format              - Printf format string + additional args
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Print "ACPI Warning" message with module/line/version info
+ *
+ ******************************************************************************/
+void ACPI_INTERNAL_VAR_XFACE
+acpi_warning(const char *module_name, u32 line_number, const char *format, ...)
+{
+	va_list arg_list;
+
+	ACPI_MSG_REDIRECT_BEGIN;
+	acpi_os_printf(ACPI_MSG_WARNING);
+
+	va_start(arg_list, format);
+	acpi_os_vprintf(format, arg_list);
+	ACPI_MSG_SUFFIX;
+	va_end(arg_list);
+
+	ACPI_MSG_REDIRECT_END;
+}
+
+ACPI_EXPORT_SYMBOL(acpi_warning)
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_info
+ *
+ * PARAMETERS:  module_name         - Caller's module name (for error output)
+ *              line_number         - Caller's line number (for error output)
+ *              Format              - Printf format string + additional args
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Print generic "ACPI:" information message. There is no
+ *              module/line/version info in order to keep the message simple.
+ *
+ * TBD: module_name and line_number args are not needed, should be removed.
+ *
+ ******************************************************************************/
+void ACPI_INTERNAL_VAR_XFACE
+acpi_info(const char *module_name, u32 line_number, const char *format, ...)
+{
+	va_list arg_list;
+
+	ACPI_MSG_REDIRECT_BEGIN;
+	acpi_os_printf(ACPI_MSG_INFO);
+
+	va_start(arg_list, format);
+	acpi_os_vprintf(format, arg_list);
+	acpi_os_printf("\n");
+	va_end(arg_list);
+
+	ACPI_MSG_REDIRECT_END;
+}
+
+ACPI_EXPORT_SYMBOL(acpi_info)
+
+/*
+ * The remainder of this module contains internal error functions that may
+ * be configured out.
+ */
+#if !defined (ACPI_NO_ERROR_MESSAGES) && !defined (ACPI_BIN_APP)
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_predefined_warning
+ *
+ * PARAMETERS:  module_name     - Caller's module name (for error output)
+ *              line_number     - Caller's line number (for error output)
+ *              Pathname        - Full pathname to the node
+ *              node_flags      - From Namespace node for the method/object
+ *              Format          - Printf format string + additional args
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Warnings for the predefined validation module. Messages are
+ *              only emitted the first time a problem with a particular
+ *              method/object is detected. This prevents a flood of error
+ *              messages for methods that are repeatedly evaluated.
+ *
+ ******************************************************************************/
+void ACPI_INTERNAL_VAR_XFACE
+acpi_ut_predefined_warning(const char *module_name,
+			   u32 line_number,
+			   char *pathname,
+			   u8 node_flags, const char *format, ...)
+{
+	va_list arg_list;
+
+	/*
+	 * Warning messages for this method/object will be disabled after the
+	 * first time a validation fails or an object is successfully repaired.
+	 */
+	if (node_flags & ANOBJ_EVALUATED) {
+		return;
+	}
+
+	acpi_os_printf(ACPI_MSG_WARNING "For %s: ", pathname);
+
+	va_start(arg_list, format);
+	acpi_os_vprintf(format, arg_list);
+	ACPI_MSG_SUFFIX;
+	va_end(arg_list);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_predefined_info
+ *
+ * PARAMETERS:  module_name     - Caller's module name (for error output)
+ *              line_number     - Caller's line number (for error output)
+ *              Pathname        - Full pathname to the node
+ *              node_flags      - From Namespace node for the method/object
+ *              Format          - Printf format string + additional args
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Info messages for the predefined validation module. Messages
+ *              are only emitted the first time a problem with a particular
+ *              method/object is detected. This prevents a flood of
+ *              messages for methods that are repeatedly evaluated.
+ *
+ ******************************************************************************/
+
+void ACPI_INTERNAL_VAR_XFACE
+acpi_ut_predefined_info(const char *module_name,
+			u32 line_number,
+			char *pathname, u8 node_flags, const char *format, ...)
+{
+	va_list arg_list;
+
+	/*
+	 * Warning messages for this method/object will be disabled after the
+	 * first time a validation fails or an object is successfully repaired.
+	 */
+	if (node_flags & ANOBJ_EVALUATED) {
+		return;
+	}
+
+	acpi_os_printf(ACPI_MSG_INFO "For %s: ", pathname);
+
+	va_start(arg_list, format);
+	acpi_os_vprintf(format, arg_list);
+	ACPI_MSG_SUFFIX;
+	va_end(arg_list);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_namespace_error
+ *
+ * PARAMETERS:  module_name         - Caller's module name (for error output)
+ *              line_number         - Caller's line number (for error output)
+ *              internal_name       - Name or path of the namespace node
+ *              lookup_status       - Exception code from NS lookup
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Print error message with the full pathname for the NS node.
+ *
+ ******************************************************************************/
+
+void
+acpi_ut_namespace_error(const char *module_name,
+			u32 line_number,
+			const char *internal_name, acpi_status lookup_status)
+{
+	acpi_status status;
+	u32 bad_name;
+	char *name = NULL;
+
+	ACPI_MSG_REDIRECT_BEGIN;
+	acpi_os_printf(ACPI_MSG_ERROR);
+
+	if (lookup_status == AE_BAD_CHARACTER) {
+
+		/* There is a non-ascii character in the name */
+
+		ACPI_MOVE_32_TO_32(&bad_name,
+				   ACPI_CAST_PTR(u32, internal_name));
+		acpi_os_printf("[0x%4.4X] (NON-ASCII)", bad_name);
+	} else {
+		/* Convert path to external format */
+
+		status = acpi_ns_externalize_name(ACPI_UINT32_MAX,
+						  internal_name, NULL, &name);
+
+		/* Print target name */
+
+		if (ACPI_SUCCESS(status)) {
+			acpi_os_printf("[%s]", name);
+		} else {
+			acpi_os_printf("[COULD NOT EXTERNALIZE NAME]");
+		}
+
+		if (name) {
+			ACPI_FREE(name);
+		}
+	}
+
+	acpi_os_printf(" Namespace lookup failure, %s",
+		       acpi_format_exception(lookup_status));
+
+	ACPI_MSG_SUFFIX;
+	ACPI_MSG_REDIRECT_END;
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_method_error
+ *
+ * PARAMETERS:  module_name         - Caller's module name (for error output)
+ *              line_number         - Caller's line number (for error output)
+ *              Message             - Error message to use on failure
+ *              prefix_node         - Prefix relative to the path
+ *              Path                - Path to the node (optional)
+ *              method_status       - Execution status
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Print error message with the full pathname for the method.
+ *
+ ******************************************************************************/
+
+void
+acpi_ut_method_error(const char *module_name,
+		     u32 line_number,
+		     const char *message,
+		     struct acpi_namespace_node *prefix_node,
+		     const char *path, acpi_status method_status)
+{
+	acpi_status status;
+	struct acpi_namespace_node *node = prefix_node;
+
+	ACPI_MSG_REDIRECT_BEGIN;
+	acpi_os_printf(ACPI_MSG_ERROR);
+
+	if (path) {
+		status =
+		    acpi_ns_get_node(prefix_node, path, ACPI_NS_NO_UPSEARCH,
+				     &node);
+		if (ACPI_FAILURE(status)) {
+			acpi_os_printf("[Could not get node by pathname]");
+		}
+	}
+
+	acpi_ns_print_node_pathname(node, message);
+	acpi_os_printf(", %s", acpi_format_exception(method_status));
+
+	ACPI_MSG_SUFFIX;
+	ACPI_MSG_REDIRECT_END;
+}
+
+#endif				/* ACPI_NO_ERROR_MESSAGES */
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 9841720..95649d3 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -42,10 +42,7 @@
 
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
-
-#ifdef CONFIG_ACPI_SYSFS_POWER
 #include <linux/power_supply.h>
-#endif
 
 #define PREFIX "ACPI: "
 
@@ -98,13 +95,12 @@
 	 * due to bad math.
 	 */
 	ACPI_BATTERY_QUIRK_SIGNED16_CURRENT,
+	ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY,
 };
 
 struct acpi_battery {
 	struct mutex lock;
-#ifdef CONFIG_ACPI_SYSFS_POWER
 	struct power_supply bat;
-#endif
 	struct acpi_device *device;
 	unsigned long update_time;
 	int rate_now;
@@ -141,7 +137,6 @@
 	return battery->device->status.battery_present;
 }
 
-#ifdef CONFIG_ACPI_SYSFS_POWER
 static int acpi_battery_technology(struct acpi_battery *battery)
 {
 	if (!strcasecmp("NiCd", battery->type))
@@ -186,6 +181,7 @@
 				     enum power_supply_property psp,
 				     union power_supply_propval *val)
 {
+	int ret = 0;
 	struct acpi_battery *battery = to_acpi_battery(psy);
 
 	if (acpi_battery_present(battery)) {
@@ -214,26 +210,44 @@
 		val->intval = battery->cycle_count;
 		break;
 	case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
-		val->intval = battery->design_voltage * 1000;
+		if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
+			ret = -ENODEV;
+		else
+			val->intval = battery->design_voltage * 1000;
 		break;
 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
-		val->intval = battery->voltage_now * 1000;
+		if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
+			ret = -ENODEV;
+		else
+			val->intval = battery->voltage_now * 1000;
 		break;
 	case POWER_SUPPLY_PROP_CURRENT_NOW:
 	case POWER_SUPPLY_PROP_POWER_NOW:
-		val->intval = battery->rate_now * 1000;
+		if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
+			ret = -ENODEV;
+		else
+			val->intval = battery->rate_now * 1000;
 		break;
 	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
 	case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
-		val->intval = battery->design_capacity * 1000;
+		if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
+			ret = -ENODEV;
+		else
+			val->intval = battery->design_capacity * 1000;
 		break;
 	case POWER_SUPPLY_PROP_CHARGE_FULL:
 	case POWER_SUPPLY_PROP_ENERGY_FULL:
-		val->intval = battery->full_charge_capacity * 1000;
+		if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
+			ret = -ENODEV;
+		else
+			val->intval = battery->full_charge_capacity * 1000;
 		break;
 	case POWER_SUPPLY_PROP_CHARGE_NOW:
 	case POWER_SUPPLY_PROP_ENERGY_NOW:
-		val->intval = battery->capacity_now * 1000;
+		if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
+			ret = -ENODEV;
+		else
+			val->intval = battery->capacity_now * 1000;
 		break;
 	case POWER_SUPPLY_PROP_MODEL_NAME:
 		val->strval = battery->model_number;
@@ -245,9 +259,9 @@
 		val->strval = battery->serial_number;
 		break;
 	default:
-		return -EINVAL;
+		ret = -EINVAL;
 	}
-	return 0;
+	return ret;
 }
 
 static enum power_supply_property charge_battery_props[] = {
@@ -281,7 +295,6 @@
 	POWER_SUPPLY_PROP_MANUFACTURER,
 	POWER_SUPPLY_PROP_SERIAL_NUMBER,
 };
-#endif
 
 #ifdef CONFIG_ACPI_PROCFS_POWER
 inline char *acpi_battery_units(struct acpi_battery *battery)
@@ -412,6 +425,8 @@
 		result = extract_package(battery, buffer.pointer,
 				info_offsets, ARRAY_SIZE(info_offsets));
 	kfree(buffer.pointer);
+	if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
+		battery->full_charge_capacity = battery->design_capacity;
 	return result;
 }
 
@@ -448,6 +463,10 @@
 	    battery->rate_now != -1)
 		battery->rate_now = abs((s16)battery->rate_now);
 
+	if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)
+	    && battery->capacity_now >= 0 && battery->capacity_now <= 100)
+		battery->capacity_now = (battery->capacity_now *
+				battery->full_charge_capacity) / 100;
 	return result;
 }
 
@@ -492,7 +511,6 @@
 	return acpi_battery_set_alarm(battery);
 }
 
-#ifdef CONFIG_ACPI_SYSFS_POWER
 static ssize_t acpi_battery_alarm_show(struct device *dev,
 					struct device_attribute *attr,
 					char *buf)
@@ -552,7 +570,6 @@
 	power_supply_unregister(&battery->bat);
 	battery->bat.dev = NULL;
 }
-#endif
 
 static void acpi_battery_quirks(struct acpi_battery *battery)
 {
@@ -561,6 +578,33 @@
 	}
 }
 
+/*
+ * According to the ACPI spec, some kinds of primary batteries can
+ * report percentage battery remaining capacity directly to OS.
+ * In this case, it reports the Last Full Charged Capacity == 100
+ * and BatteryPresentRate == 0xFFFFFFFF.
+ *
+ * Now we found some battery reports percentage remaining capacity
+ * even if it's rechargeable.
+ * https://bugzilla.kernel.org/show_bug.cgi?id=15979
+ *
+ * Handle this correctly so that they won't break userspace.
+ */
+static void acpi_battery_quirks2(struct acpi_battery *battery)
+{
+	if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
+		return ;
+
+        if (battery->full_charge_capacity == 100 &&
+            battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN &&
+            battery->capacity_now >=0 && battery->capacity_now <= 100) {
+		set_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags);
+		battery->full_charge_capacity = battery->design_capacity;
+		battery->capacity_now = (battery->capacity_now *
+				battery->full_charge_capacity) / 100;
+	}
+}
+
 static int acpi_battery_update(struct acpi_battery *battery)
 {
 	int result, old_present = acpi_battery_present(battery);
@@ -568,9 +612,7 @@
 	if (result)
 		return result;
 	if (!acpi_battery_present(battery)) {
-#ifdef CONFIG_ACPI_SYSFS_POWER
 		sysfs_remove_battery(battery);
-#endif
 		battery->update_time = 0;
 		return 0;
 	}
@@ -582,11 +624,11 @@
 		acpi_battery_quirks(battery);
 		acpi_battery_init_alarm(battery);
 	}
-#ifdef CONFIG_ACPI_SYSFS_POWER
 	if (!battery->bat.dev)
 		sysfs_add_battery(battery);
-#endif
-	return acpi_battery_get_state(battery);
+	result = acpi_battery_get_state(battery);
+	acpi_battery_quirks2(battery);
+	return result;
 }
 
 /* --------------------------------------------------------------------------
@@ -867,26 +909,20 @@
 static void acpi_battery_notify(struct acpi_device *device, u32 event)
 {
 	struct acpi_battery *battery = acpi_driver_data(device);
-#ifdef CONFIG_ACPI_SYSFS_POWER
 	struct device *old;
-#endif
 
 	if (!battery)
 		return;
-#ifdef CONFIG_ACPI_SYSFS_POWER
 	old = battery->bat.dev;
-#endif
 	acpi_battery_update(battery);
 	acpi_bus_generate_proc_event(device, event,
 				     acpi_battery_present(battery));
 	acpi_bus_generate_netlink_event(device->pnp.device_class,
 					dev_name(&device->dev), event,
 					acpi_battery_present(battery));
-#ifdef CONFIG_ACPI_SYSFS_POWER
 	/* acpi_battery_update could remove power_supply object */
 	if (old && battery->bat.dev)
 		power_supply_changed(&battery->bat);
-#endif
 }
 
 static int acpi_battery_add(struct acpi_device *device)
@@ -934,9 +970,7 @@
 #ifdef CONFIG_ACPI_PROCFS_POWER
 	acpi_battery_remove_fs(device);
 #endif
-#ifdef CONFIG_ACPI_SYSFS_POWER
 	sysfs_remove_battery(battery);
-#endif
 	mutex_destroy(&battery->lock);
 	kfree(battery);
 	return 0;
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 310e3b9..d68bd61 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -935,6 +935,12 @@
 		goto error1;
 	}
 
+	/*
+	 * _PDC control method may load dynamic SSDT tables,
+	 * and we need to install the table handler before that.
+	 */
+	acpi_sysfs_init();
+
 	acpi_early_processor_set_pdc();
 
 	/*
@@ -1026,7 +1032,6 @@
 	acpi_scan_init();
 	acpi_ec_init();
 	acpi_power_init();
-	acpi_sysfs_init();
 	acpi_debugfs_init();
 	acpi_sleep_proc_init();
 	acpi_wakeup_device_init();
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 1575a9b..71ef9cd 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -338,7 +338,8 @@
 {
 	struct acpi_button *button;
 	struct input_dev *input;
-	char *hid, *name, *class;
+	const char *hid = acpi_device_hid(device);
+	char *name, *class;
 	int error;
 
 	button = kzalloc(sizeof(struct acpi_button), GFP_KERNEL);
@@ -353,7 +354,6 @@
 		goto err_free_button;
 	}
 
-	hid = acpi_device_hid(device);
 	name = acpi_device_name(device);
 	class = acpi_device_class(device);
 
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 3fe29e9..81514a4 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -725,6 +725,7 @@
 			complete_dock(ds);
 			dock_event(ds, event, DOCK_EVENT);
 			dock_lock(ds, 1);
+			acpi_update_gpes();
 			break;
 		}
 		if (dock_present(ds) || dock_in_progress(ds))
@@ -929,7 +930,7 @@
  * allocated and initialize a new dock station device.  Find all devices
  * that are on the dock station, and register for dock event notifications.
  */
-static int dock_add(acpi_handle handle)
+static int __init dock_add(acpi_handle handle)
 {
 	int ret, id;
 	struct dock_station ds, *dock_station;
@@ -1023,7 +1024,7 @@
  *
  * This is called by acpi_walk_namespace to look for dock stations.
  */
-static acpi_status
+static __init acpi_status
 find_dock(acpi_handle handle, u32 lvl, void *context, void **rv)
 {
 	if (is_dock(handle))
@@ -1032,7 +1033,7 @@
 	return AE_OK;
 }
 
-static acpi_status
+static __init acpi_status
 find_bay(acpi_handle handle, u32 lvl, void *context, void **rv)
 {
 	/* If bay is a dock, it's already handled */
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index f31291b..372ff80 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -83,6 +83,11 @@
 	EC_FLAGS_BLOCKED,		/* Transactions are blocked */
 };
 
+/* ec.c is compiled in acpi namespace so this shows up as acpi.ec_delay param */
+static unsigned int ec_delay __read_mostly = ACPI_EC_DELAY;
+module_param(ec_delay, uint, 0644);
+MODULE_PARM_DESC(ec_delay, "Timeout(ms) waited until an EC command completes");
+
 /* If we find an EC via the ECDT, we need to keep a ptr to its context */
 /* External interfaces use first EC only, so remember */
 typedef int (*acpi_ec_query_func) (void *data);
@@ -210,7 +215,7 @@
 	int repeat = 2; /* number of command restarts */
 	while (repeat--) {
 		unsigned long delay = jiffies +
-			msecs_to_jiffies(ACPI_EC_DELAY);
+			msecs_to_jiffies(ec_delay);
 		do {
 			/* don't sleep with disabled interrupts */
 			if (EC_FLAGS_MSI || irqs_disabled()) {
@@ -265,7 +270,7 @@
 
 static int ec_wait_ibf0(struct acpi_ec *ec)
 {
-	unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
+	unsigned long delay = jiffies + msecs_to_jiffies(ec_delay);
 	/* interrupt wait manually if GPE mode is not active */
 	while (time_before(jiffies, delay))
 		if (wait_event_timeout(ec->wait, ec_check_ibf0(ec),
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index d94d295..6004908 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -27,8 +27,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
 #include <asm/uaccess.h>
 #include <linux/thermal.h>
 #include <acpi/acpi_bus.h>
@@ -119,122 +117,6 @@
 };
 
 /* --------------------------------------------------------------------------
-                              FS Interface (/proc)
-   -------------------------------------------------------------------------- */
-#ifdef CONFIG_ACPI_PROCFS
-
-static struct proc_dir_entry *acpi_fan_dir;
-
-static int acpi_fan_read_state(struct seq_file *seq, void *offset)
-{
-	struct acpi_device *device = seq->private;
-	int state = 0;
-
-
-	if (device) {
-		if (acpi_bus_get_power(device->handle, &state))
-			seq_printf(seq, "status:                  ERROR\n");
-		else
-			seq_printf(seq, "status:                  %s\n",
-				   !state ? "on" : "off");
-	}
-	return 0;
-}
-
-static int acpi_fan_state_open_fs(struct inode *inode, struct file *file)
-{
-	return single_open(file, acpi_fan_read_state, PDE(inode)->data);
-}
-
-static ssize_t
-acpi_fan_write_state(struct file *file, const char __user * buffer,
-		     size_t count, loff_t * ppos)
-{
-	int result = 0;
-	struct seq_file *m = file->private_data;
-	struct acpi_device *device = m->private;
-	char state_string[3] = { '\0' };
-
-	if (count > sizeof(state_string) - 1)
-		return -EINVAL;
-
-	if (copy_from_user(state_string, buffer, count))
-		return -EFAULT;
-
-	state_string[count] = '\0';
-	if ((state_string[0] < '0') || (state_string[0] > '3'))
-		return -EINVAL;
-	if (state_string[1] == '\n')
-		state_string[1] = '\0';
-	if (state_string[1] != '\0')
-		return -EINVAL;
-
-	result = acpi_bus_set_power(device->handle,
-				    simple_strtoul(state_string, NULL, 0));
-	if (result)
-		return result;
-
-	return count;
-}
-
-static const struct file_operations acpi_fan_state_ops = {
-	.open = acpi_fan_state_open_fs,
-	.read = seq_read,
-	.write = acpi_fan_write_state,
-	.llseek = seq_lseek,
-	.release = single_release,
-	.owner = THIS_MODULE,
-};
-
-static int acpi_fan_add_fs(struct acpi_device *device)
-{
-	struct proc_dir_entry *entry = NULL;
-
-
-	if (!device)
-		return -EINVAL;
-
-	if (!acpi_device_dir(device)) {
-		acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
-						     acpi_fan_dir);
-		if (!acpi_device_dir(device))
-			return -ENODEV;
-	}
-
-	/* 'status' [R/W] */
-	entry = proc_create_data(ACPI_FAN_FILE_STATE,
-				 S_IFREG | S_IRUGO | S_IWUSR,
-				 acpi_device_dir(device),
-				 &acpi_fan_state_ops,
-				 device);
-	if (!entry)
-		return -ENODEV;
-	return 0;
-}
-
-static int acpi_fan_remove_fs(struct acpi_device *device)
-{
-
-	if (acpi_device_dir(device)) {
-		remove_proc_entry(ACPI_FAN_FILE_STATE, acpi_device_dir(device));
-		remove_proc_entry(acpi_device_bid(device), acpi_fan_dir);
-		acpi_device_dir(device) = NULL;
-	}
-
-	return 0;
-}
-#else
-static int acpi_fan_add_fs(struct acpi_device *device)
-{
-	return 0;
-}
-
-static int acpi_fan_remove_fs(struct acpi_device *device)
-{
-	return 0;
-}
-#endif
-/* --------------------------------------------------------------------------
                                  Driver Interface
    -------------------------------------------------------------------------- */
 
@@ -284,10 +166,6 @@
 		dev_err(&device->dev, "Failed to create sysfs link "
 			"'device'\n");
 
-	result = acpi_fan_add_fs(device);
-	if (result)
-		goto end;
-
 	printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
 	       acpi_device_name(device), acpi_device_bid(device),
 	       !device->power.state ? "on" : "off");
@@ -303,7 +181,6 @@
 	if (!device || !cdev)
 		return -EINVAL;
 
-	acpi_fan_remove_fs(device);
 	sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
 	sysfs_remove_link(&cdev->device.kobj, "device");
 	thermal_cooling_device_unregister(cdev);
@@ -347,19 +224,9 @@
 {
 	int result = 0;
 
-#ifdef CONFIG_ACPI_PROCFS
-	acpi_fan_dir = proc_mkdir(ACPI_FAN_CLASS, acpi_root_dir);
-	if (!acpi_fan_dir)
-		return -ENODEV;
-#endif
-
 	result = acpi_bus_register_driver(&acpi_fan_driver);
-	if (result < 0) {
-#ifdef CONFIG_ACPI_PROCFS
-		remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir);
-#endif
+	if (result < 0)
 		return -ENODEV;
-	}
 
 	return 0;
 }
@@ -369,10 +236,6 @@
 
 	acpi_bus_unregister_driver(&acpi_fan_driver);
 
-#ifdef CONFIG_ACPI_PROCFS
-	remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir);
-#endif
-
 	return;
 }
 
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 65b25a3..966fedd 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -95,8 +95,25 @@
 static LIST_HEAD(resource_list_head);
 static DEFINE_SPINLOCK(acpi_res_lock);
 
+/*
+ * This list of permanent mappings is for memory that may be accessed from
+ * interrupt context, where we can't do the ioremap().
+ */
+struct acpi_ioremap {
+	struct list_head list;
+	void __iomem *virt;
+	acpi_physical_address phys;
+	acpi_size size;
+	struct kref ref;
+};
+
+static LIST_HEAD(acpi_ioremaps);
+static DEFINE_SPINLOCK(acpi_ioremap_lock);
+
 #define	OSI_STRING_LENGTH_MAX 64	/* arbitrary */
-static char osi_additional_string[OSI_STRING_LENGTH_MAX];
+static char osi_setup_string[OSI_STRING_LENGTH_MAX];
+
+static void __init acpi_osi_setup_late(void);
 
 /*
  * The story of _OSI(Linux)
@@ -138,6 +155,20 @@
 	unsigned int	known:1;
 } osi_linux = { 0, 0, 0, 0};
 
+static u32 acpi_osi_handler(acpi_string interface, u32 supported)
+{
+	if (!strcmp("Linux", interface)) {
+
+		printk(KERN_NOTICE FW_BUG PREFIX
+			"BIOS _OSI(Linux) query %s%s\n",
+			osi_linux.enable ? "honored" : "ignored",
+			osi_linux.cmdline ? " via cmdline" :
+			osi_linux.dmi ? " via DMI" : "");
+	}
+
+	return supported;
+}
+
 static void __init acpi_request_region (struct acpi_generic_address *addr,
 	unsigned int length, char *desc)
 {
@@ -185,36 +216,6 @@
 }
 device_initcall(acpi_reserve_resources);
 
-acpi_status __init acpi_os_initialize(void)
-{
-	return AE_OK;
-}
-
-acpi_status acpi_os_initialize1(void)
-{
-	kacpid_wq = create_workqueue("kacpid");
-	kacpi_notify_wq = create_workqueue("kacpi_notify");
-	kacpi_hotplug_wq = create_workqueue("kacpi_hotplug");
-	BUG_ON(!kacpid_wq);
-	BUG_ON(!kacpi_notify_wq);
-	BUG_ON(!kacpi_hotplug_wq);
-	return AE_OK;
-}
-
-acpi_status acpi_os_terminate(void)
-{
-	if (acpi_irq_handler) {
-		acpi_os_remove_interrupt_handler(acpi_irq_irq,
-						 acpi_irq_handler);
-	}
-
-	destroy_workqueue(kacpid_wq);
-	destroy_workqueue(kacpi_notify_wq);
-	destroy_workqueue(kacpi_hotplug_wq);
-
-	return AE_OK;
-}
-
 void acpi_os_printf(const char *fmt, ...)
 {
 	va_list args;
@@ -260,29 +261,135 @@
 	}
 }
 
+/* Must be called with 'acpi_ioremap_lock' or RCU read lock held. */
+static struct acpi_ioremap *
+acpi_map_lookup(acpi_physical_address phys, acpi_size size)
+{
+	struct acpi_ioremap *map;
+
+	list_for_each_entry_rcu(map, &acpi_ioremaps, list)
+		if (map->phys <= phys &&
+		    phys + size <= map->phys + map->size)
+			return map;
+
+	return NULL;
+}
+
+/* Must be called with 'acpi_ioremap_lock' or RCU read lock held. */
+static void __iomem *
+acpi_map_vaddr_lookup(acpi_physical_address phys, unsigned int size)
+{
+	struct acpi_ioremap *map;
+
+	map = acpi_map_lookup(phys, size);
+	if (map)
+		return map->virt + (phys - map->phys);
+
+	return NULL;
+}
+
+/* Must be called with 'acpi_ioremap_lock' or RCU read lock held. */
+static struct acpi_ioremap *
+acpi_map_lookup_virt(void __iomem *virt, acpi_size size)
+{
+	struct acpi_ioremap *map;
+
+	list_for_each_entry_rcu(map, &acpi_ioremaps, list)
+		if (map->virt <= virt &&
+		    virt + size <= map->virt + map->size)
+			return map;
+
+	return NULL;
+}
+
 void __iomem *__init_refok
 acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
 {
+	struct acpi_ioremap *map, *tmp_map;
+	unsigned long flags, pg_sz;
+	void __iomem *virt;
+	phys_addr_t pg_off;
+
 	if (phys > ULONG_MAX) {
 		printk(KERN_ERR PREFIX "Cannot map memory that high\n");
 		return NULL;
 	}
-	if (acpi_gbl_permanent_mmap)
-		/*
-		* ioremap checks to ensure this is in reserved space
-		*/
-		return ioremap((unsigned long)phys, size);
-	else
+
+	if (!acpi_gbl_permanent_mmap)
 		return __acpi_map_table((unsigned long)phys, size);
+
+	map = kzalloc(sizeof(*map), GFP_KERNEL);
+	if (!map)
+		return NULL;
+
+	pg_off = round_down(phys, PAGE_SIZE);
+	pg_sz = round_up(phys + size, PAGE_SIZE) - pg_off;
+	virt = ioremap(pg_off, pg_sz);
+	if (!virt) {
+		kfree(map);
+		return NULL;
+	}
+
+	INIT_LIST_HEAD(&map->list);
+	map->virt = virt;
+	map->phys = pg_off;
+	map->size = pg_sz;
+	kref_init(&map->ref);
+
+	spin_lock_irqsave(&acpi_ioremap_lock, flags);
+	/* Check if page has already been mapped. */
+	tmp_map = acpi_map_lookup(phys, size);
+	if (tmp_map) {
+		kref_get(&tmp_map->ref);
+		spin_unlock_irqrestore(&acpi_ioremap_lock, flags);
+		iounmap(map->virt);
+		kfree(map);
+		return tmp_map->virt + (phys - tmp_map->phys);
+	}
+	list_add_tail_rcu(&map->list, &acpi_ioremaps);
+	spin_unlock_irqrestore(&acpi_ioremap_lock, flags);
+
+	return map->virt + (phys - map->phys);
 }
 EXPORT_SYMBOL_GPL(acpi_os_map_memory);
 
+static void acpi_kref_del_iomap(struct kref *ref)
+{
+	struct acpi_ioremap *map;
+
+	map = container_of(ref, struct acpi_ioremap, ref);
+	list_del_rcu(&map->list);
+}
+
 void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
 {
-	if (acpi_gbl_permanent_mmap)
-		iounmap(virt);
-	else
+	struct acpi_ioremap *map;
+	unsigned long flags;
+	int del;
+
+	if (!acpi_gbl_permanent_mmap) {
 		__acpi_unmap_table(virt, size);
+		return;
+	}
+
+	spin_lock_irqsave(&acpi_ioremap_lock, flags);
+	map = acpi_map_lookup_virt(virt, size);
+	if (!map) {
+		spin_unlock_irqrestore(&acpi_ioremap_lock, flags);
+		printk(KERN_ERR PREFIX "%s: bad address %p\n", __func__, virt);
+		dump_stack();
+		return;
+	}
+
+	del = kref_put(&map->ref, acpi_kref_del_iomap);
+	spin_unlock_irqrestore(&acpi_ioremap_lock, flags);
+
+	if (!del)
+		return;
+
+	synchronize_rcu();
+	iounmap(map->virt);
+	kfree(map);
 }
 EXPORT_SYMBOL_GPL(acpi_os_unmap_memory);
 
@@ -292,6 +399,44 @@
 		__acpi_unmap_table(virt, size);
 }
 
+int acpi_os_map_generic_address(struct acpi_generic_address *addr)
+{
+	void __iomem *virt;
+
+	if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
+		return 0;
+
+	if (!addr->address || !addr->bit_width)
+		return -EINVAL;
+
+	virt = acpi_os_map_memory(addr->address, addr->bit_width / 8);
+	if (!virt)
+		return -EIO;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(acpi_os_map_generic_address);
+
+void acpi_os_unmap_generic_address(struct acpi_generic_address *addr)
+{
+	void __iomem *virt;
+	unsigned long flags;
+	acpi_size size = addr->bit_width / 8;
+
+	if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
+		return;
+
+	if (!addr->address || !addr->bit_width)
+		return;
+
+	spin_lock_irqsave(&acpi_ioremap_lock, flags);
+	virt = acpi_map_vaddr_lookup(addr->address, size);
+	spin_unlock_irqrestore(&acpi_ioremap_lock, flags);
+
+	acpi_os_unmap_memory(virt, size);
+}
+EXPORT_SYMBOL_GPL(acpi_os_unmap_generic_address);
+
 #ifdef ACPI_FUTURE_USAGE
 acpi_status
 acpi_os_get_physical_address(void *virt, acpi_physical_address * phys)
@@ -495,8 +640,15 @@
 {
 	u32 dummy;
 	void __iomem *virt_addr;
+	int size = width / 8, unmap = 0;
 
-	virt_addr = ioremap(phys_addr, width);
+	rcu_read_lock();
+	virt_addr = acpi_map_vaddr_lookup(phys_addr, size);
+	rcu_read_unlock();
+	if (!virt_addr) {
+		virt_addr = ioremap(phys_addr, size);
+		unmap = 1;
+	}
 	if (!value)
 		value = &dummy;
 
@@ -514,7 +666,8 @@
 		BUG();
 	}
 
-	iounmap(virt_addr);
+	if (unmap)
+		iounmap(virt_addr);
 
 	return AE_OK;
 }
@@ -523,8 +676,15 @@
 acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width)
 {
 	void __iomem *virt_addr;
+	int size = width / 8, unmap = 0;
 
-	virt_addr = ioremap(phys_addr, width);
+	rcu_read_lock();
+	virt_addr = acpi_map_vaddr_lookup(phys_addr, size);
+	rcu_read_unlock();
+	if (!virt_addr) {
+		virt_addr = ioremap(phys_addr, size);
+		unmap = 1;
+	}
 
 	switch (width) {
 	case 8:
@@ -540,16 +700,18 @@
 		BUG();
 	}
 
-	iounmap(virt_addr);
+	if (unmap)
+		iounmap(virt_addr);
 
 	return AE_OK;
 }
 
 acpi_status
 acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
-			       u32 *value, u32 width)
+			       u64 *value, u32 width)
 {
 	int result, size;
+	u32 value32;
 
 	if (!value)
 		return AE_BAD_PARAMETER;
@@ -570,7 +732,8 @@
 
 	result = raw_pci_read(pci_id->segment, pci_id->bus,
 				PCI_DEVFN(pci_id->device, pci_id->function),
-				reg, size, value);
+				reg, size, &value32);
+	*value = value32;
 
 	return (result ? AE_ERROR : AE_OK);
 }
@@ -602,74 +765,6 @@
 	return (result ? AE_ERROR : AE_OK);
 }
 
-/* TODO: Change code to take advantage of driver model more */
-static void acpi_os_derive_pci_id_2(acpi_handle rhandle,	/* upper bound  */
-				    acpi_handle chandle,	/* current node */
-				    struct acpi_pci_id **id,
-				    int *is_bridge, u8 * bus_number)
-{
-	acpi_handle handle;
-	struct acpi_pci_id *pci_id = *id;
-	acpi_status status;
-	unsigned long long temp;
-	acpi_object_type type;
-
-	acpi_get_parent(chandle, &handle);
-	if (handle != rhandle) {
-		acpi_os_derive_pci_id_2(rhandle, handle, &pci_id, is_bridge,
-					bus_number);
-
-		status = acpi_get_type(handle, &type);
-		if ((ACPI_FAILURE(status)) || (type != ACPI_TYPE_DEVICE))
-			return;
-
-		status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL,
-					  &temp);
-		if (ACPI_SUCCESS(status)) {
-			u32 val;
-			pci_id->device = ACPI_HIWORD(ACPI_LODWORD(temp));
-			pci_id->function = ACPI_LOWORD(ACPI_LODWORD(temp));
-
-			if (*is_bridge)
-				pci_id->bus = *bus_number;
-
-			/* any nicer way to get bus number of bridge ? */
-			status =
-			    acpi_os_read_pci_configuration(pci_id, 0x0e, &val,
-							   8);
-			if (ACPI_SUCCESS(status)
-			    && ((val & 0x7f) == 1 || (val & 0x7f) == 2)) {
-				status =
-				    acpi_os_read_pci_configuration(pci_id, 0x18,
-								   &val, 8);
-				if (!ACPI_SUCCESS(status)) {
-					/* Certainly broken...  FIX ME */
-					return;
-				}
-				*is_bridge = 1;
-				pci_id->bus = val;
-				status =
-				    acpi_os_read_pci_configuration(pci_id, 0x19,
-								   &val, 8);
-				if (ACPI_SUCCESS(status)) {
-					*bus_number = val;
-				}
-			} else
-				*is_bridge = 0;
-		}
-	}
-}
-
-void acpi_os_derive_pci_id(acpi_handle rhandle,	/* upper bound  */
-			   acpi_handle chandle,	/* current node */
-			   struct acpi_pci_id **id)
-{
-	int is_bridge = 1;
-	u8 bus_number = (*id)->bus;
-
-	acpi_os_derive_pci_id_2(rhandle, chandle, id, &is_bridge, &bus_number);
-}
-
 static void acpi_os_execute_deferred(struct work_struct *work)
 {
 	struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work);
@@ -780,16 +875,6 @@
 EXPORT_SYMBOL(acpi_os_wait_events_complete);
 
 /*
- * Allocate the memory for a spinlock and initialize it.
- */
-acpi_status acpi_os_create_lock(acpi_spinlock * handle)
-{
-	spin_lock_init(*handle);
-
-	return AE_OK;
-}
-
-/*
  * Deallocate the memory for a spinlock.
  */
 void acpi_os_delete_lock(acpi_spinlock handle)
@@ -977,6 +1062,12 @@
 		printk(KERN_NOTICE PREFIX "%sed _OSI(Linux)\n",
 			enable ? "Add": "Delet");
 	}
+
+	if (osi_linux.enable)
+		acpi_osi_setup("Linux");
+	else
+		acpi_osi_setup("!Linux");
+
 	return;
 }
 
@@ -1011,21 +1102,33 @@
  * string starting with '!' disables that string
  * otherwise string is added to list, augmenting built-in strings
  */
+static void __init acpi_osi_setup_late(void)
+{
+	char *str = osi_setup_string;
+
+	if (*str == '\0')
+		return;
+
+	if (!strcmp("!Linux", str)) {
+		acpi_cmdline_osi_linux(0);	/* !enable */
+	} else if (*str == '!') {
+		if (acpi_remove_interface(++str) == AE_OK)
+			printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str);
+	} else if (!strcmp("Linux", str)) {
+		acpi_cmdline_osi_linux(1);	/* enable */
+	} else {
+		if (acpi_install_interface(str) == AE_OK)
+			printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str);
+	}
+}
+
 int __init acpi_osi_setup(char *str)
 {
 	if (str == NULL || *str == '\0') {
 		printk(KERN_INFO PREFIX "_OSI method disabled\n");
 		acpi_gbl_create_osi_method = FALSE;
-	} else if (!strcmp("!Linux", str)) {
-		acpi_cmdline_osi_linux(0);	/* !enable */
-	} else if (*str == '!') {
-		if (acpi_osi_invalidate(++str) == AE_OK)
-			printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str);
-	} else if (!strcmp("Linux", str)) {
-		acpi_cmdline_osi_linux(1);	/* enable */
-	} else if (*osi_additional_string == '\0') {
-		strncpy(osi_additional_string, str, OSI_STRING_LENGTH_MAX);
-		printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str);
+	} else {
+		strncpy(osi_setup_string, str, OSI_STRING_LENGTH_MAX);
 	}
 
 	return 1;
@@ -1152,21 +1255,6 @@
 }
 EXPORT_SYMBOL(acpi_check_region);
 
-int acpi_check_mem_region(resource_size_t start, resource_size_t n,
-		      const char *name)
-{
-	struct resource res = {
-		.start = start,
-		.end   = start + n - 1,
-		.name  = name,
-		.flags = IORESOURCE_MEM,
-	};
-
-	return acpi_check_resource_conflict(&res);
-
-}
-EXPORT_SYMBOL(acpi_check_mem_region);
-
 /*
  * Let drivers know whether the resource checks are effective
  */
@@ -1282,38 +1370,6 @@
 	return (AE_OK);
 }
 
-/******************************************************************************
- *
- * FUNCTION:    acpi_os_validate_interface
- *
- * PARAMETERS:  interface           - Requested interface to be validated
- *
- * RETURN:      AE_OK if interface is supported, AE_SUPPORT otherwise
- *
- * DESCRIPTION: Match an interface string to the interfaces supported by the
- *              host. Strings originate from an AML call to the _OSI method.
- *
- *****************************************************************************/
-
-acpi_status
-acpi_os_validate_interface (char *interface)
-{
-	if (!strncmp(osi_additional_string, interface, OSI_STRING_LENGTH_MAX))
-		return AE_OK;
-	if (!strcmp("Linux", interface)) {
-
-		printk(KERN_NOTICE PREFIX
-			"BIOS _OSI(Linux) query %s%s\n",
-			osi_linux.enable ? "honored" : "ignored",
-			osi_linux.cmdline ? " via cmdline" :
-			osi_linux.dmi ? " via DMI" : "");
-
-		if (osi_linux.enable)
-			return AE_OK;
-	}
-	return AE_SUPPORT;
-}
-
 static inline int acpi_res_list_add(struct acpi_res_list *res)
 {
 	struct acpi_res_list *res_list_elem;
@@ -1462,5 +1518,46 @@
 	}
 	return AE_OK;
 }
-
 #endif
+
+acpi_status __init acpi_os_initialize(void)
+{
+	acpi_os_map_generic_address(&acpi_gbl_FADT.xpm1a_event_block);
+	acpi_os_map_generic_address(&acpi_gbl_FADT.xpm1b_event_block);
+	acpi_os_map_generic_address(&acpi_gbl_FADT.xgpe0_block);
+	acpi_os_map_generic_address(&acpi_gbl_FADT.xgpe1_block);
+
+	return AE_OK;
+}
+
+acpi_status acpi_os_initialize1(void)
+{
+	kacpid_wq = create_workqueue("kacpid");
+	kacpi_notify_wq = create_workqueue("kacpi_notify");
+	kacpi_hotplug_wq = create_workqueue("kacpi_hotplug");
+	BUG_ON(!kacpid_wq);
+	BUG_ON(!kacpi_notify_wq);
+	BUG_ON(!kacpi_hotplug_wq);
+	acpi_install_interface_handler(acpi_osi_handler);
+	acpi_osi_setup_late();
+	return AE_OK;
+}
+
+acpi_status acpi_os_terminate(void)
+{
+	if (acpi_irq_handler) {
+		acpi_os_remove_interrupt_handler(acpi_irq_irq,
+						 acpi_irq_handler);
+	}
+
+	acpi_os_unmap_generic_address(&acpi_gbl_FADT.xgpe1_block);
+	acpi_os_unmap_generic_address(&acpi_gbl_FADT.xgpe0_block);
+	acpi_os_unmap_generic_address(&acpi_gbl_FADT.xpm1b_event_block);
+	acpi_os_unmap_generic_address(&acpi_gbl_FADT.xpm1a_event_block);
+
+	destroy_workqueue(kacpid_wq);
+	destroy_workqueue(kacpi_notify_wq);
+	destroy_workqueue(kacpi_hotplug_wq);
+
+	return AE_OK;
+}
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index e4804fb..f907cfb 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -32,7 +32,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/proc_fs.h>
 #include <linux/spinlock.h>
 #include <linux/pm.h>
 #include <linux/pci.h>
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index 8d47a58..9ff80a7 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -34,7 +34,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/proc_fs.h>
 #include <linux/spinlock.h>
 #include <linux/pm.h>
 #include <linux/pci.h>
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 3ba8d1f..96668ad 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -27,7 +27,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/proc_fs.h>
 #include <linux/spinlock.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 844c155..67dedee 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -80,18 +80,13 @@
 		},
 };
 
-struct acpi_power_reference {
-	struct list_head node;
-	struct acpi_device *device;
-};
-
 struct acpi_power_resource {
 	struct acpi_device * device;
 	acpi_bus_id name;
 	u32 system_level;
 	u32 order;
+	unsigned int ref_count;
 	struct mutex resource_lock;
-	struct list_head reference;
 };
 
 static struct list_head acpi_power_resource_list;
@@ -184,45 +179,9 @@
 	return result;
 }
 
-static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)
+static int __acpi_power_on(struct acpi_power_resource *resource)
 {
-	int result = 0;
-	int found = 0;
 	acpi_status status = AE_OK;
-	struct acpi_power_resource *resource = NULL;
-	struct list_head *node, *next;
-	struct acpi_power_reference *ref;
-
-
-	result = acpi_power_get_context(handle, &resource);
-	if (result)
-		return result;
-
-	mutex_lock(&resource->resource_lock);
-	list_for_each_safe(node, next, &resource->reference) {
-		ref = container_of(node, struct acpi_power_reference, node);
-		if (dev->handle == ref->device->handle) {
-			ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] already referenced by resource [%s]\n",
-				  dev->pnp.bus_id, resource->name));
-			found = 1;
-			break;
-		}
-	}
-
-	if (!found) {
-		ref = kmalloc(sizeof (struct acpi_power_reference),
-		    irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL);
-		if (!ref) {
-			ACPI_DEBUG_PRINT((ACPI_DB_INFO, "kmalloc() failed\n"));
-			mutex_unlock(&resource->resource_lock);
-			return -ENOMEM;
-		}
-		list_add_tail(&ref->node, &resource->reference);
-		ref->device = dev;
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] added to resource [%s] references\n",
-			  dev->pnp.bus_id, resource->name));
-	}
-	mutex_unlock(&resource->resource_lock);
 
 	status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL);
 	if (ACPI_FAILURE(status))
@@ -231,56 +190,80 @@
 	/* Update the power resource's _device_ power state */
 	resource->device->power.state = ACPI_STATE_D0;
 
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned on\n",
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned on\n",
 			  resource->name));
+
 	return 0;
 }
 
-static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev)
+static int acpi_power_on(acpi_handle handle)
 {
 	int result = 0;
-	acpi_status status = AE_OK;
 	struct acpi_power_resource *resource = NULL;
-	struct list_head *node, *next;
-	struct acpi_power_reference *ref;
 
 	result = acpi_power_get_context(handle, &resource);
 	if (result)
 		return result;
 
 	mutex_lock(&resource->resource_lock);
-	list_for_each_safe(node, next, &resource->reference) {
-		ref = container_of(node, struct acpi_power_reference, node);
-		if (dev->handle == ref->device->handle) {
-			list_del(&ref->node);
-			kfree(ref);
-			ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] removed from resource [%s] references\n",
-			    dev->pnp.bus_id, resource->name));
-			break;
-		}
+
+	if (resource->ref_count++) {
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+				  "Power resource [%s] already on",
+				  resource->name));
+	} else {
+		result = __acpi_power_on(resource);
 	}
 
-	if (!list_empty(&resource->reference)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cannot turn resource [%s] off - resource is in use\n",
-		    resource->name));
-		mutex_unlock(&resource->resource_lock);
-		return 0;
-	}
 	mutex_unlock(&resource->resource_lock);
 
-	status = acpi_evaluate_object(resource->device->handle, "_OFF", NULL, NULL);
-	if (ACPI_FAILURE(status))
-		return -ENODEV;
-
-	/* Update the power resource's _device_ power state */
-	resource->device->power.state = ACPI_STATE_D3;
-
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned off\n",
-			  resource->name));
-
 	return 0;
 }
 
+static int acpi_power_off_device(acpi_handle handle)
+{
+	int result = 0;
+	acpi_status status = AE_OK;
+	struct acpi_power_resource *resource = NULL;
+
+	result = acpi_power_get_context(handle, &resource);
+	if (result)
+		return result;
+
+	mutex_lock(&resource->resource_lock);
+
+	if (!resource->ref_count) {
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+				  "Power resource [%s] already off",
+				  resource->name));
+		goto unlock;
+	}
+
+	if (--resource->ref_count) {
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+				  "Power resource [%s] still in use\n",
+				  resource->name));
+		goto unlock;
+	}
+
+	status = acpi_evaluate_object(resource->device->handle, "_OFF", NULL, NULL);
+	if (ACPI_FAILURE(status)) {
+		result = -ENODEV;
+	} else {
+		/* Update the power resource's _device_ power state */
+		resource->device->power.state = ACPI_STATE_D3;
+
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+				  "Power resource [%s] turned off\n",
+				  resource->name));
+	}
+
+ unlock:
+	mutex_unlock(&resource->resource_lock);
+
+	return result;
+}
+
 /**
  * acpi_device_sleep_wake - execute _DSW (Device Sleep Wake) or (deprecated in
  *                          ACPI 3.0) _PSW (Power State Wake)
@@ -364,7 +347,7 @@
 
 	/* Open power resource */
 	for (i = 0; i < dev->wakeup.resources.count; i++) {
-		int ret = acpi_power_on(dev->wakeup.resources.handles[i], dev);
+		int ret = acpi_power_on(dev->wakeup.resources.handles[i]);
 		if (ret) {
 			printk(KERN_ERR PREFIX "Transition power state\n");
 			dev->wakeup.flags.valid = 0;
@@ -420,7 +403,7 @@
 	/* Close power resource */
 	for (i = 0; i < dev->wakeup.resources.count; i++) {
 		int ret = acpi_power_off_device(
-				dev->wakeup.resources.handles[i], dev);
+				dev->wakeup.resources.handles[i]);
 		if (ret) {
 			printk(KERN_ERR PREFIX "Transition power state\n");
 			dev->wakeup.flags.valid = 0;
@@ -500,7 +483,7 @@
 	 * (e.g. so the device doesn't lose power while transitioning).
 	 */
 	for (i = 0; i < tl->count; i++) {
-		result = acpi_power_on(tl->handles[i], device);
+		result = acpi_power_on(tl->handles[i]);
 		if (result)
 			goto end;
 	}
@@ -513,7 +496,7 @@
 	 * Then we dereference all power resources used in the current list.
 	 */
 	for (i = 0; i < cl->count; i++) {
-		result = acpi_power_off_device(cl->handles[i], device);
+		result = acpi_power_off_device(cl->handles[i]);
 		if (result)
 			goto end;
 	}
@@ -551,7 +534,6 @@
 
 	resource->device = device;
 	mutex_init(&resource->resource_lock);
-	INIT_LIST_HEAD(&resource->reference);
 	strcpy(resource->name, device->pnp.bus_id);
 	strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME);
 	strcpy(acpi_device_class(device), ACPI_POWER_CLASS);
@@ -594,22 +576,14 @@
 
 static int acpi_power_remove(struct acpi_device *device, int type)
 {
-	struct acpi_power_resource *resource = NULL;
-	struct list_head *node, *next;
+	struct acpi_power_resource *resource;
 
-
-	if (!device || !acpi_driver_data(device))
+	if (!device)
 		return -EINVAL;
 
 	resource = acpi_driver_data(device);
-
-	mutex_lock(&resource->resource_lock);
-	list_for_each_safe(node, next, &resource->reference) {
-		struct acpi_power_reference *ref = container_of(node, struct acpi_power_reference, node);
-		list_del(&ref->node);
-		kfree(ref);
-	}
-	mutex_unlock(&resource->resource_lock);
+	if (!resource)
+		return -EINVAL;
 
 	kfree(resource);
 
@@ -619,29 +593,28 @@
 static int acpi_power_resume(struct acpi_device *device)
 {
 	int result = 0, state;
-	struct acpi_power_resource *resource = NULL;
-	struct acpi_power_reference *ref;
+	struct acpi_power_resource *resource;
 
-	if (!device || !acpi_driver_data(device))
+	if (!device)
 		return -EINVAL;
 
 	resource = acpi_driver_data(device);
+	if (!resource)
+		return -EINVAL;
+
+	mutex_lock(&resource->resource_lock);
 
 	result = acpi_power_get_state(device->handle, &state);
 	if (result)
-		return result;
+		goto unlock;
 
-	mutex_lock(&resource->resource_lock);
-	if (state == ACPI_POWER_RESOURCE_STATE_OFF &&
-	    !list_empty(&resource->reference)) {
-		ref = container_of(resource->reference.next, struct acpi_power_reference, node);
-		mutex_unlock(&resource->resource_lock);
-		result = acpi_power_on(device->handle, ref->device);
-		return result;
-	}
+	if (state == ACPI_POWER_RESOURCE_STATE_OFF && resource->ref_count)
+		result = __acpi_power_on(resource);
 
+ unlock:
 	mutex_unlock(&resource->resource_lock);
-	return 0;
+
+	return result;
 }
 
 int __init acpi_power_init(void)
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index 347eb21..85e4804 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -40,8 +40,10 @@
 #include <linux/pm.h>
 #include <linux/cpufreq.h>
 #include <linux/cpu.h>
+#ifdef CONFIG_ACPI_PROCFS
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#endif
 #include <linux/dmi.h>
 #include <linux/moduleparam.h>
 #include <linux/cpuidle.h>
@@ -244,6 +246,7 @@
 	return result;
 }
 
+#ifdef CONFIG_ACPI_PROCFS
 static struct proc_dir_entry *acpi_processor_dir = NULL;
 
 static int __cpuinit acpi_processor_add_fs(struct acpi_device *device)
@@ -280,7 +283,16 @@
 
 	return 0;
 }
-
+#else
+static inline int acpi_processor_add_fs(struct acpi_device *device)
+{
+	return 0;
+}
+static inline int acpi_processor_remove_fs(struct acpi_device *device)
+{
+	return 0;
+}
+#endif
 /* --------------------------------------------------------------------------
                                  Driver Interface
    -------------------------------------------------------------------------- */
@@ -842,9 +854,11 @@
 
 	memset(&errata, 0, sizeof(errata));
 
+#ifdef CONFIG_ACPI_PROCFS
 	acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir);
 	if (!acpi_processor_dir)
 		return -ENOMEM;
+#endif
 
 	if (!cpuidle_register_driver(&acpi_idle_driver)) {
 		printk(KERN_DEBUG "ACPI: %s registered with cpuidle\n",
@@ -871,7 +885,9 @@
 out_cpuidle:
 	cpuidle_unregister_driver(&acpi_idle_driver);
 
+#ifdef CONFIG_ACPI_PROCFS
 	remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
+#endif
 
 	return result;
 }
@@ -891,7 +907,9 @@
 
 	cpuidle_unregister_driver(&acpi_idle_driver);
 
+#ifdef CONFIG_ACPI_PROCFS
 	remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
+#endif
 
 	return;
 }
@@ -899,6 +917,4 @@
 module_init(acpi_processor_init);
 module_exit(acpi_processor_exit);
 
-EXPORT_SYMBOL(acpi_processor_set_thermal_limit);
-
 MODULE_ALIAS("processor");
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index f4428e8..dcb38f8 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -64,7 +64,6 @@
 #define ACPI_PROCESSOR_CLASS            "processor"
 #define _COMPONENT              ACPI_PROCESSOR_COMPONENT
 ACPI_MODULE_NAME("processor_idle");
-#define ACPI_PROCESSOR_FILE_POWER	"power"
 #define PM_TIMER_TICK_NS		(1000000000ULL/PM_TIMER_FREQUENCY)
 #define C2_OVERHEAD			1	/* 1us */
 #define C3_OVERHEAD			1	/* 1us */
@@ -1013,7 +1012,6 @@
 		strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN);
 		state->exit_latency = cx->latency;
 		state->target_residency = cx->latency * latency_factor;
-		state->power_usage = cx->power;
 
 		state->flags = 0;
 		switch (cx->type) {
diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c
index 953b25f..fde49b9 100644
--- a/drivers/acpi/processor_thermal.c
+++ b/drivers/acpi/processor_thermal.c
@@ -44,47 +44,6 @@
 #define _COMPONENT              ACPI_PROCESSOR_COMPONENT
 ACPI_MODULE_NAME("processor_thermal");
 
-/* --------------------------------------------------------------------------
-                                 Limit Interface
-   -------------------------------------------------------------------------- */
-static int acpi_processor_apply_limit(struct acpi_processor *pr)
-{
-	int result = 0;
-	u16 px = 0;
-	u16 tx = 0;
-
-
-	if (!pr)
-		return -EINVAL;
-
-	if (!pr->flags.limit)
-		return -ENODEV;
-
-	if (pr->flags.throttling) {
-		if (pr->limit.user.tx > tx)
-			tx = pr->limit.user.tx;
-		if (pr->limit.thermal.tx > tx)
-			tx = pr->limit.thermal.tx;
-
-		result = acpi_processor_set_throttling(pr, tx, false);
-		if (result)
-			goto end;
-	}
-
-	pr->limit.state.px = px;
-	pr->limit.state.tx = tx;
-
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-			  "Processor [%d] limit set to (P%d:T%d)\n", pr->id,
-			  pr->limit.state.px, pr->limit.state.tx));
-
-      end:
-	if (result)
-		printk(KERN_ERR PREFIX "Unable to set limit\n");
-
-	return result;
-}
-
 #ifdef CONFIG_CPU_FREQ
 
 /* If a passive cooling situation is detected, primarily CPUfreq is used, as it
@@ -107,36 +66,6 @@
 	return 1;
 }
 
-static int acpi_thermal_cpufreq_increase(unsigned int cpu)
-{
-	if (!cpu_has_cpufreq(cpu))
-		return -ENODEV;
-
-	if (per_cpu(cpufreq_thermal_reduction_pctg, cpu) <
-		CPUFREQ_THERMAL_MAX_STEP) {
-		per_cpu(cpufreq_thermal_reduction_pctg, cpu)++;
-		cpufreq_update_policy(cpu);
-		return 0;
-	}
-
-	return -ERANGE;
-}
-
-static int acpi_thermal_cpufreq_decrease(unsigned int cpu)
-{
-	if (!cpu_has_cpufreq(cpu))
-		return -ENODEV;
-
-	if (per_cpu(cpufreq_thermal_reduction_pctg, cpu) >
-		(CPUFREQ_THERMAL_MIN_STEP + 1))
-		per_cpu(cpufreq_thermal_reduction_pctg, cpu)--;
-	else
-		per_cpu(cpufreq_thermal_reduction_pctg, cpu) = 0;
-	cpufreq_update_policy(cpu);
-	/* We reached max freq again and can leave passive mode */
-	return !per_cpu(cpufreq_thermal_reduction_pctg, cpu);
-}
-
 static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb,
 					 unsigned long event, void *data)
 {
@@ -238,113 +167,6 @@
 
 #endif
 
-int acpi_processor_set_thermal_limit(acpi_handle handle, int type)
-{
-	int result = 0;
-	struct acpi_processor *pr = NULL;
-	struct acpi_device *device = NULL;
-	int tx = 0, max_tx_px = 0;
-
-
-	if ((type < ACPI_PROCESSOR_LIMIT_NONE)
-	    || (type > ACPI_PROCESSOR_LIMIT_DECREMENT))
-		return -EINVAL;
-
-	result = acpi_bus_get_device(handle, &device);
-	if (result)
-		return result;
-
-	pr = acpi_driver_data(device);
-	if (!pr)
-		return -ENODEV;
-
-	/* Thermal limits are always relative to the current Px/Tx state. */
-	if (pr->flags.throttling)
-		pr->limit.thermal.tx = pr->throttling.state;
-
-	/*
-	 * Our default policy is to only use throttling at the lowest
-	 * performance state.
-	 */
-
-	tx = pr->limit.thermal.tx;
-
-	switch (type) {
-
-	case ACPI_PROCESSOR_LIMIT_NONE:
-		do {
-			result = acpi_thermal_cpufreq_decrease(pr->id);
-		} while (!result);
-		tx = 0;
-		break;
-
-	case ACPI_PROCESSOR_LIMIT_INCREMENT:
-		/* if going up: P-states first, T-states later */
-
-		result = acpi_thermal_cpufreq_increase(pr->id);
-		if (!result)
-			goto end;
-		else if (result == -ERANGE)
-			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-					  "At maximum performance state\n"));
-
-		if (pr->flags.throttling) {
-			if (tx == (pr->throttling.state_count - 1))
-				ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-						  "At maximum throttling state\n"));
-			else
-				tx++;
-		}
-		break;
-
-	case ACPI_PROCESSOR_LIMIT_DECREMENT:
-		/* if going down: T-states first, P-states later */
-
-		if (pr->flags.throttling) {
-			if (tx == 0) {
-				max_tx_px = 1;
-				ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-						  "At minimum throttling state\n"));
-			} else {
-				tx--;
-				goto end;
-			}
-		}
-
-		result = acpi_thermal_cpufreq_decrease(pr->id);
-		if (result) {
-			/*
-			 * We only could get -ERANGE, 1 or 0.
-			 * In the first two cases we reached max freq again.
-			 */
-			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-					  "At minimum performance state\n"));
-			max_tx_px = 1;
-		} else
-			max_tx_px = 0;
-
-		break;
-	}
-
-      end:
-	if (pr->flags.throttling) {
-		pr->limit.thermal.px = 0;
-		pr->limit.thermal.tx = tx;
-
-		result = acpi_processor_apply_limit(pr);
-		if (result)
-			printk(KERN_ERR PREFIX "Unable to set thermal limit\n");
-
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Thermal limit now (P%d:T%d)\n",
-				  pr->limit.thermal.px, pr->limit.thermal.tx));
-	} else
-		result = 0;
-	if (max_tx_px)
-		return 1;
-	else
-		return result;
-}
-
 int acpi_processor_get_limit_info(struct acpi_processor *pr)
 {
 
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index 7308638..ff36327 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -32,8 +32,10 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/cpufreq.h>
+#ifdef CONFIG_ACPI_PROCFS
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#endif
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -1214,6 +1216,7 @@
 	return result;
 }
 
+#ifdef CONFIG_ACPI_PROCFS
 /* proc interface */
 static int acpi_processor_throttling_seq_show(struct seq_file *seq,
 					      void *offset)
@@ -1322,3 +1325,4 @@
 	.llseek = seq_lseek,
 	.release = single_release,
 };
+#endif
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index 4ff76e8..e5dbedb 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -40,10 +40,7 @@
 #include <linux/timer.h>
 #include <linux/jiffies.h>
 #include <linux/delay.h>
-
-#ifdef CONFIG_ACPI_SYSFS_POWER
 #include <linux/power_supply.h>
-#endif
 
 #include "sbshc.h"
 
@@ -85,9 +82,7 @@
 MODULE_DEVICE_TABLE(acpi, sbs_device_ids);
 
 struct acpi_battery {
-#ifdef CONFIG_ACPI_SYSFS_POWER
 	struct power_supply bat;
-#endif
 	struct acpi_sbs *sbs;
 #ifdef CONFIG_ACPI_PROCFS_POWER
 	struct proc_dir_entry *proc_entry;
@@ -120,9 +115,7 @@
 #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);
 
 struct acpi_sbs {
-#ifdef CONFIG_ACPI_SYSFS_POWER
 	struct power_supply charger;
-#endif
 	struct acpi_device *device;
 	struct acpi_smb_hc *hc;
 	struct mutex lock;
@@ -166,7 +159,6 @@
 	    acpi_battery_ipscale(battery);
 }
 
-#ifdef CONFIG_ACPI_SYSFS_POWER
 static int sbs_get_ac_property(struct power_supply *psy,
 			       enum power_supply_property psp,
 			       union power_supply_propval *val)
@@ -313,7 +305,6 @@
 	POWER_SUPPLY_PROP_MANUFACTURER,
 };
 
-#endif
 
 /* --------------------------------------------------------------------------
                             Smart Battery System Management
@@ -449,7 +440,6 @@
 	return result;
 }
 
-#ifdef CONFIG_ACPI_SYSFS_POWER
 static ssize_t acpi_battery_alarm_show(struct device *dev,
 					struct device_attribute *attr,
 					char *buf)
@@ -479,7 +469,6 @@
 	.show = acpi_battery_alarm_show,
 	.store = acpi_battery_alarm_store,
 };
-#endif
 
 /* --------------------------------------------------------------------------
                               FS Interface (/proc/acpi)
@@ -798,7 +787,6 @@
 			&acpi_battery_state_fops, &acpi_battery_alarm_fops,
 			battery);
 #endif
-#ifdef CONFIG_ACPI_SYSFS_POWER
 	battery->bat.name = battery->name;
 	battery->bat.type = POWER_SUPPLY_TYPE_BATTERY;
 	if (!acpi_battery_mode(battery)) {
@@ -819,7 +807,6 @@
 		goto end;
 	battery->have_sysfs_alarm = 1;
       end:
-#endif
 	printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n",
 	       ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
 	       battery->name, battery->present ? "present" : "absent");
@@ -828,17 +815,13 @@
 
 static void acpi_battery_remove(struct acpi_sbs *sbs, int id)
 {
-#if defined(CONFIG_ACPI_SYSFS_POWER) || defined(CONFIG_ACPI_PROCFS_POWER)
 	struct acpi_battery *battery = &sbs->battery[id];
-#endif
 
-#ifdef CONFIG_ACPI_SYSFS_POWER
 	if (battery->bat.dev) {
 		if (battery->have_sysfs_alarm)
 			device_remove_file(battery->bat.dev, &alarm_attr);
 		power_supply_unregister(&battery->bat);
 	}
-#endif
 #ifdef CONFIG_ACPI_PROCFS_POWER
 	if (battery->proc_entry)
 		acpi_sbs_remove_fs(&battery->proc_entry, acpi_battery_dir);
@@ -859,14 +842,12 @@
 	if (result)
 		goto end;
 #endif
-#ifdef CONFIG_ACPI_SYSFS_POWER
 	sbs->charger.name = "sbs-charger";
 	sbs->charger.type = POWER_SUPPLY_TYPE_MAINS;
 	sbs->charger.properties = sbs_ac_props;
 	sbs->charger.num_properties = ARRAY_SIZE(sbs_ac_props);
 	sbs->charger.get_property = sbs_get_ac_property;
 	power_supply_register(&sbs->device->dev, &sbs->charger);
-#endif
 	printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n",
 	       ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
 	       ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line");
@@ -876,10 +857,8 @@
 
 static void acpi_charger_remove(struct acpi_sbs *sbs)
 {
-#ifdef CONFIG_ACPI_SYSFS_POWER
 	if (sbs->charger.dev)
 		power_supply_unregister(&sbs->charger);
-#endif
 #ifdef CONFIG_ACPI_PROCFS_POWER
 	if (sbs->charger_entry)
 		acpi_sbs_remove_fs(&sbs->charger_entry, acpi_ac_dir);
@@ -900,9 +879,7 @@
 					      ACPI_SBS_NOTIFY_STATUS,
 					      sbs->charger_present);
 #endif
-#ifdef CONFIG_ACPI_SYSFS_POWER
 		kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE);
-#endif
 	}
 	if (sbs->manager_present) {
 		for (id = 0; id < MAX_SBS_BAT; ++id) {
@@ -919,9 +896,7 @@
 						      ACPI_SBS_NOTIFY_STATUS,
 						      bat->present);
 #endif
-#ifdef CONFIG_ACPI_SYSFS_POWER
 			kobject_uevent(&bat->bat.dev->kobj, KOBJ_CHANGE);
-#endif
 		}
 	}
 }
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index b23825e..2b6c21d 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -26,6 +26,8 @@
 
 #define ACPI_IS_ROOT_DEVICE(device)    (!(device)->parent)
 
+static const char *dummy_hid = "device";
+
 static LIST_HEAD(acpi_device_list);
 static LIST_HEAD(acpi_bus_id_list);
 DEFINE_MUTEX(acpi_device_lock);
@@ -49,6 +51,9 @@
 	int count;
 	struct acpi_hardware_id *id;
 
+	if (list_empty(&acpi_dev->pnp.ids))
+		return 0;
+
 	len = snprintf(modalias, size, "acpi:");
 	size -= len;
 
@@ -202,13 +207,15 @@
 			goto end;
 	}
 
-	result = device_create_file(&dev->dev, &dev_attr_hid);
-	if (result)
-		goto end;
+	if (!list_empty(&dev->pnp.ids)) {
+		result = device_create_file(&dev->dev, &dev_attr_hid);
+		if (result)
+			goto end;
 
-	result = device_create_file(&dev->dev, &dev_attr_modalias);
-	if (result)
-		goto end;
+		result = device_create_file(&dev->dev, &dev_attr_modalias);
+		if (result)
+			goto end;
+	}
 
         /*
          * If device has _EJ0, 'eject' file is created that is used to trigger
@@ -316,6 +323,9 @@
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
 	int len;
 
+	if (list_empty(&acpi_dev->pnp.ids))
+		return 0;
+
 	if (add_uevent_var(env, "MODALIAS="))
 		return -ENOMEM;
 	len = create_modalias(acpi_dev, &env->buf[env->buflen - 1],
@@ -1010,10 +1020,13 @@
 	return acpi_get_handle(device->handle, "_DCK", &tmp);
 }
 
-char *acpi_device_hid(struct acpi_device *device)
+const char *acpi_device_hid(struct acpi_device *device)
 {
 	struct acpi_hardware_id *hid;
 
+	if (list_empty(&device->pnp.ids))
+		return dummy_hid;
+
 	hid = list_first_entry(&device->pnp.ids, struct acpi_hardware_id, list);
 	return hid->id;
 }
@@ -1142,16 +1155,6 @@
 		acpi_add_id(device, ACPI_BUTTON_HID_SLEEPF);
 		break;
 	}
-
-	/*
-	 * We build acpi_devices for some objects that don't have _HID or _CID,
-	 * e.g., PCI bridges and slots.  Drivers can't bind to these objects,
-	 * but we do use them indirectly by traversing the acpi_device tree.
-	 * This generic ID isn't useful for driver binding, but it provides
-	 * the useful property that "every acpi_device has an ID."
-	 */
-	if (list_empty(&device->pnp.ids))
-		acpi_add_id(device, "device");
 }
 
 static int acpi_device_set_context(struct acpi_device *device)
@@ -1431,6 +1434,7 @@
 int acpi_bus_start(struct acpi_device *device)
 {
 	struct acpi_bus_ops ops;
+	int result;
 
 	if (!device)
 		return -EINVAL;
@@ -1438,7 +1442,11 @@
 	memset(&ops, 0, sizeof(ops));
 	ops.acpi_op_start = 1;
 
-	return acpi_bus_scan(device->handle, &ops, NULL);
+	result = acpi_bus_scan(device->handle, &ops, NULL);
+
+	acpi_update_gpes();
+
+	return result;
 }
 EXPORT_SYMBOL(acpi_bus_start);
 
@@ -1552,6 +1560,8 @@
 
 	if (result)
 		acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
+	else
+		acpi_update_gpes();
 
 	return result;
 }
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index 4754ff6..721d93b 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -25,7 +25,9 @@
 #include "internal.h"
 #include "sleep.h"
 
-u8 sleep_states[ACPI_S_STATE_COUNT];
+static u8 sleep_states[ACPI_S_STATE_COUNT];
+
+static u32 acpi_target_sleep_state = ACPI_STATE_S0;
 
 static void acpi_sleep_tts_switch(u32 acpi_state)
 {
@@ -79,8 +81,6 @@
 }
 
 #ifdef CONFIG_ACPI_SLEEP
-static u32 acpi_target_sleep_state = ACPI_STATE_S0;
-
 /*
  * The ACPI specification wants us to save NVS memory regions during hibernation
  * and to restore them during the subsequent resume.  Windows does that also for
@@ -419,6 +419,14 @@
 		DMI_MATCH(DMI_PRODUCT_NAME, "Everex StepNote Series"),
 		},
 	},
+	{
+	.callback = init_nvs_nosave,
+	.ident = "Sony Vaio VPCEB1Z1E",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1Z1E"),
+		},
+	},
 	{},
 };
 #endif /* CONFIG_SUSPEND */
@@ -562,7 +570,7 @@
 	return -EINVAL;
 }
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM_OPS
 /**
  *	acpi_pm_device_sleep_state - return preferred power state of ACPI device
  *		in the system sleep state given by %acpi_target_sleep_state
@@ -624,7 +632,7 @@
 	 * can wake the system.  _S0W may be valid, too.
 	 */
 	if (acpi_target_sleep_state == ACPI_STATE_S0 ||
-	    (device_may_wakeup(dev) && adev->wakeup.state.enabled &&
+	    (device_may_wakeup(dev) &&
 	     adev->wakeup.sleep_state <= acpi_target_sleep_state)) {
 		acpi_status status;
 
@@ -632,7 +640,9 @@
 		status = acpi_evaluate_integer(handle, acpi_method, NULL,
 						&d_max);
 		if (ACPI_FAILURE(status)) {
-			d_max = d_min;
+			if (acpi_target_sleep_state != ACPI_STATE_S0 ||
+			    status != AE_NOT_FOUND)
+				d_max = d_min;
 		} else if (d_max < d_min) {
 			/* Warn the user of the broken DSDT */
 			printk(KERN_WARNING "ACPI: Wrong value from %s\n",
@@ -646,7 +656,9 @@
 		*d_min_p = d_min;
 	return d_max;
 }
+#endif /* CONFIG_PM_OPS */
 
+#ifdef CONFIG_PM_SLEEP
 /**
  *	acpi_pm_device_sleep_wake - enable or disable the system wake-up
  *                                  capability of given device
@@ -677,7 +689,7 @@
 
 	return error;
 }
-#endif
+#endif  /* CONFIG_PM_SLEEP */
 
 static void acpi_power_off_prepare(void)
 {
@@ -702,7 +714,7 @@
  * paths through the BIOS, so disable _GTS and _BFS by default,
  * but do speak up and offer the option to enable them.
  */
-void __init acpi_gts_bfs_check(void)
+static void __init acpi_gts_bfs_check(void)
 {
 	acpi_handle dummy;
 
diff --git a/drivers/acpi/sleep.h b/drivers/acpi/sleep.h
index d882180..74d59c8 100644
--- a/drivers/acpi/sleep.h
+++ b/drivers/acpi/sleep.h
@@ -1,5 +1,4 @@
 
-extern u8 sleep_states[];
 extern int acpi_suspend(u32 state);
 
 extern void acpi_enable_wakeup_devices(u8 sleep_state);
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 2f8f171..5a27b0a 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -37,12 +37,6 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/types.h>
-
-#ifdef CONFIG_ACPI_PROCFS
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#endif
-
 #include <linux/jiffies.h>
 #include <linux/kmod.h>
 #include <linux/reboot.h>
@@ -195,61 +189,6 @@
 	struct mutex lock;
 };
 
-#ifdef CONFIG_ACPI_PROCFS
-static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file);
-static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file);
-static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file);
-static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file);
-static ssize_t acpi_thermal_write_cooling_mode(struct file *,
-					       const char __user *, size_t,
-					       loff_t *);
-static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file);
-static ssize_t acpi_thermal_write_polling(struct file *, const char __user *,
-					  size_t, loff_t *);
-
-static const struct file_operations acpi_thermal_state_fops = {
-	.owner = THIS_MODULE,
-	.open = acpi_thermal_state_open_fs,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-
-static const struct file_operations acpi_thermal_temp_fops = {
-	.owner = THIS_MODULE,
-	.open = acpi_thermal_temp_open_fs,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-
-static const struct file_operations acpi_thermal_trip_fops = {
-	.owner = THIS_MODULE,
-	.open = acpi_thermal_trip_open_fs,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-
-static const struct file_operations acpi_thermal_cooling_fops = {
-	.owner = THIS_MODULE,
-	.open = acpi_thermal_cooling_open_fs,
-	.read = seq_read,
-	.write = acpi_thermal_write_cooling_mode,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-
-static const struct file_operations acpi_thermal_polling_fops = {
-	.owner = THIS_MODULE,
-	.open = acpi_thermal_polling_open_fs,
-	.read = seq_read,
-	.write = acpi_thermal_write_polling,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-#endif /* CONFIG_ACPI_PROCFS*/
-
 /* --------------------------------------------------------------------------
                              Thermal Zone Management
    -------------------------------------------------------------------------- */
@@ -958,358 +897,6 @@
 
 
 /* --------------------------------------------------------------------------
-                              FS Interface (/proc)
-   -------------------------------------------------------------------------- */
-#ifdef CONFIG_ACPI_PROCFS
-static struct proc_dir_entry *acpi_thermal_dir;
-
-static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset)
-{
-	struct acpi_thermal *tz = seq->private;
-
-
-	if (!tz)
-		goto end;
-
-	seq_puts(seq, "state:                   ");
-
-	if (!tz->state.critical && !tz->state.hot && !tz->state.passive
-	    && !tz->state.active)
-		seq_puts(seq, "ok\n");
-	else {
-		if (tz->state.critical)
-			seq_puts(seq, "critical ");
-		if (tz->state.hot)
-			seq_puts(seq, "hot ");
-		if (tz->state.passive)
-			seq_puts(seq, "passive ");
-		if (tz->state.active)
-			seq_printf(seq, "active[%d]", tz->state.active_index);
-		seq_puts(seq, "\n");
-	}
-
-      end:
-	return 0;
-}
-
-static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file)
-{
-	return single_open(file, acpi_thermal_state_seq_show, PDE(inode)->data);
-}
-
-static int acpi_thermal_temp_seq_show(struct seq_file *seq, void *offset)
-{
-	int result = 0;
-	struct acpi_thermal *tz = seq->private;
-
-
-	if (!tz)
-		goto end;
-
-	result = acpi_thermal_get_temperature(tz);
-	if (result)
-		goto end;
-
-	seq_printf(seq, "temperature:             %ld C\n",
-		   KELVIN_TO_CELSIUS(tz->temperature));
-
-      end:
-	return 0;
-}
-
-static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file)
-{
-	return single_open(file, acpi_thermal_temp_seq_show, PDE(inode)->data);
-}
-
-static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset)
-{
-	struct acpi_thermal *tz = seq->private;
-	struct acpi_device *device;
-	acpi_status status;
-
-	int i = 0;
-	int j = 0;
-
-
-	if (!tz)
-		goto end;
-
-	if (tz->trips.critical.flags.valid)
-		seq_printf(seq, "critical (S5):           %ld C%s",
-			   KELVIN_TO_CELSIUS(tz->trips.critical.temperature),
-			   nocrt ? " <disabled>\n" : "\n");
-
-	if (tz->trips.hot.flags.valid)
-		seq_printf(seq, "hot (S4):                %ld C%s",
-			   KELVIN_TO_CELSIUS(tz->trips.hot.temperature),
-			   nocrt ? " <disabled>\n" : "\n");
-
-	if (tz->trips.passive.flags.valid) {
-		seq_printf(seq,
-			   "passive:                 %ld C: tc1=%lu tc2=%lu tsp=%lu devices=",
-			   KELVIN_TO_CELSIUS(tz->trips.passive.temperature),
-			   tz->trips.passive.tc1, tz->trips.passive.tc2,
-			   tz->trips.passive.tsp);
-		for (j = 0; j < tz->trips.passive.devices.count; j++) {
-			status = acpi_bus_get_device(tz->trips.passive.devices.
-						     handles[j], &device);
-			seq_printf(seq, "%4.4s ", status ? "" :
-				   acpi_device_bid(device));
-		}
-		seq_puts(seq, "\n");
-	} else {
-		seq_printf(seq, "passive (forced):");
-		if (tz->thermal_zone->forced_passive)
-			seq_printf(seq, "        %i C\n",
-				   tz->thermal_zone->forced_passive / 1000);
-		else
-			seq_printf(seq, "<not set>\n");
-	}
-
-	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
-		if (!(tz->trips.active[i].flags.valid))
-			break;
-		seq_printf(seq, "active[%d]:               %ld C: devices=",
-			   i,
-			   KELVIN_TO_CELSIUS(tz->trips.active[i].temperature));
-		for (j = 0; j < tz->trips.active[i].devices.count; j++){
-			status = acpi_bus_get_device(tz->trips.active[i].
-						     devices.handles[j],
-						     &device);
-			seq_printf(seq, "%4.4s ", status ? "" :
-				   acpi_device_bid(device));
-		}
-		seq_puts(seq, "\n");
-	}
-
-      end:
-	return 0;
-}
-
-static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file)
-{
-	return single_open(file, acpi_thermal_trip_seq_show, PDE(inode)->data);
-}
-
-static int acpi_thermal_cooling_seq_show(struct seq_file *seq, void *offset)
-{
-	struct acpi_thermal *tz = seq->private;
-
-
-	if (!tz)
-		goto end;
-
-	if (!tz->flags.cooling_mode)
-		seq_puts(seq, "<setting not supported>\n");
-	else
-		seq_puts(seq, "0 - Active; 1 - Passive\n");
-
-      end:
-	return 0;
-}
-
-static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file)
-{
-	return single_open(file, acpi_thermal_cooling_seq_show,
-			   PDE(inode)->data);
-}
-
-static ssize_t
-acpi_thermal_write_cooling_mode(struct file *file,
-				const char __user * buffer,
-				size_t count, loff_t * ppos)
-{
-	struct seq_file *m = file->private_data;
-	struct acpi_thermal *tz = m->private;
-	int result = 0;
-	char mode_string[12] = { '\0' };
-
-
-	if (!tz || (count > sizeof(mode_string) - 1))
-		return -EINVAL;
-
-	if (!tz->flags.cooling_mode)
-		return -ENODEV;
-
-	if (copy_from_user(mode_string, buffer, count))
-		return -EFAULT;
-
-	mode_string[count] = '\0';
-
-	result = acpi_thermal_set_cooling_mode(tz,
-					       simple_strtoul(mode_string, NULL,
-							      0));
-	if (result)
-		return result;
-
-	acpi_thermal_check(tz);
-
-	return count;
-}
-
-static int acpi_thermal_polling_seq_show(struct seq_file *seq, void *offset)
-{
-	struct acpi_thermal *tz = seq->private;
-
-
-	if (!tz)
-		goto end;
-
-	if (!tz->thermal_zone->polling_delay) {
-		seq_puts(seq, "<polling disabled>\n");
-		goto end;
-	}
-
-	seq_printf(seq, "polling frequency:       %d seconds\n",
-		   (tz->thermal_zone->polling_delay / 1000));
-
-      end:
-	return 0;
-}
-
-static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file)
-{
-	return single_open(file, acpi_thermal_polling_seq_show,
-			   PDE(inode)->data);
-}
-
-static int acpi_thermal_set_polling(struct acpi_thermal *tz, int seconds)
-{
-	if (!tz)
-		return -EINVAL;
-
-	/* Convert value to deci-seconds */
-	tz->polling_frequency = seconds * 10;
-
-	tz->thermal_zone->polling_delay = seconds * 1000;
-
-	if (tz->tz_enabled)
-		thermal_zone_device_update(tz->thermal_zone);
-
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-			  "Polling frequency set to %lu seconds\n",
-			  tz->polling_frequency/10));
-
-	return 0;
-}
-
-static ssize_t
-acpi_thermal_write_polling(struct file *file,
-			   const char __user * buffer,
-			   size_t count, loff_t * ppos)
-{
-	struct seq_file *m = file->private_data;
-	struct acpi_thermal *tz = m->private;
-	int result = 0;
-	char polling_string[12] = { '\0' };
-	int seconds = 0;
-
-
-	if (!tz || (count > sizeof(polling_string) - 1))
-		return -EINVAL;
-
-	if (copy_from_user(polling_string, buffer, count))
-		return -EFAULT;
-
-	polling_string[count] = '\0';
-
-	seconds = simple_strtoul(polling_string, NULL, 0);
-
-	result = acpi_thermal_set_polling(tz, seconds);
-	if (result)
-		return result;
-
-	acpi_thermal_check(tz);
-
-	return count;
-}
-
-static int acpi_thermal_add_fs(struct acpi_device *device)
-{
-	struct proc_dir_entry *entry = NULL;
-
-
-	if (!acpi_device_dir(device)) {
-		acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
-						     acpi_thermal_dir);
-		if (!acpi_device_dir(device))
-			return -ENODEV;
-	}
-
-	/* 'state' [R] */
-	entry = proc_create_data(ACPI_THERMAL_FILE_STATE,
-				 S_IRUGO, acpi_device_dir(device),
-				 &acpi_thermal_state_fops,
-				 acpi_driver_data(device));
-	if (!entry)
-		return -ENODEV;
-
-	/* 'temperature' [R] */
-	entry = proc_create_data(ACPI_THERMAL_FILE_TEMPERATURE,
-				 S_IRUGO, acpi_device_dir(device),
-				 &acpi_thermal_temp_fops,
-				 acpi_driver_data(device));
-	if (!entry)
-		return -ENODEV;
-
-	/* 'trip_points' [R] */
-	entry = proc_create_data(ACPI_THERMAL_FILE_TRIP_POINTS,
-				 S_IRUGO,
-				 acpi_device_dir(device),
-				 &acpi_thermal_trip_fops,
-				 acpi_driver_data(device));
-	if (!entry)
-		return -ENODEV;
-
-	/* 'cooling_mode' [R/W] */
-	entry = proc_create_data(ACPI_THERMAL_FILE_COOLING_MODE,
-				 S_IFREG | S_IRUGO | S_IWUSR,
-				 acpi_device_dir(device),
-				 &acpi_thermal_cooling_fops,
-				 acpi_driver_data(device));
-	if (!entry)
-		return -ENODEV;
-
-	/* 'polling_frequency' [R/W] */
-	entry = proc_create_data(ACPI_THERMAL_FILE_POLLING_FREQ,
-				 S_IFREG | S_IRUGO | S_IWUSR,
-				 acpi_device_dir(device),
-				 &acpi_thermal_polling_fops,
-				 acpi_driver_data(device));
-	if (!entry)
-		return -ENODEV;
-	return 0;
-}
-
-static int acpi_thermal_remove_fs(struct acpi_device *device)
-{
-
-	if (acpi_device_dir(device)) {
-		remove_proc_entry(ACPI_THERMAL_FILE_POLLING_FREQ,
-				  acpi_device_dir(device));
-		remove_proc_entry(ACPI_THERMAL_FILE_COOLING_MODE,
-				  acpi_device_dir(device));
-		remove_proc_entry(ACPI_THERMAL_FILE_TRIP_POINTS,
-				  acpi_device_dir(device));
-		remove_proc_entry(ACPI_THERMAL_FILE_TEMPERATURE,
-				  acpi_device_dir(device));
-		remove_proc_entry(ACPI_THERMAL_FILE_STATE,
-				  acpi_device_dir(device));
-		remove_proc_entry(acpi_device_bid(device), acpi_thermal_dir);
-		acpi_device_dir(device) = NULL;
-	}
-
-	return 0;
-}
-#else
-static inline int acpi_thermal_add_fs(struct acpi_device *device) { return 0; }
-static inline int acpi_thermal_remove_fs(struct acpi_device *device)
-{
-	return 0;
-}
-#endif /* CONFIG_ACPI_PROCFS */
-/* --------------------------------------------------------------------------
                                  Driver Interface
    -------------------------------------------------------------------------- */
 
@@ -1428,17 +1015,11 @@
 	if (result)
 		goto free_memory;
 
-	result = acpi_thermal_add_fs(device);
-	if (result)
-		goto unregister_thermal_zone;
-
 	printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n",
 	       acpi_device_name(device), acpi_device_bid(device),
 	       KELVIN_TO_CELSIUS(tz->temperature));
 	goto end;
 
-unregister_thermal_zone:
-	thermal_zone_device_unregister(tz->thermal_zone);
 free_memory:
 	kfree(tz);
 end:
@@ -1454,7 +1035,6 @@
 
 	tz = acpi_driver_data(device);
 
-	acpi_thermal_remove_fs(device);
 	acpi_thermal_unregister_thermal_zone(tz);
 	mutex_destroy(&tz->lock);
 	kfree(tz);
@@ -1580,19 +1160,9 @@
 		return -ENODEV;
 	}
 
-#ifdef CONFIG_ACPI_PROCFS
-	acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, acpi_root_dir);
-	if (!acpi_thermal_dir)
-		return -ENODEV;
-#endif
-
 	result = acpi_bus_register_driver(&acpi_thermal_driver);
-	if (result < 0) {
-#ifdef CONFIG_ACPI_PROCFS
-		remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir);
-#endif
+	if (result < 0)
 		return -ENODEV;
-	}
 
 	return 0;
 }
@@ -1602,10 +1172,6 @@
 
 	acpi_bus_unregister_driver(&acpi_thermal_driver);
 
-#ifdef CONFIG_ACPI_PROCFS
-	remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir);
-#endif
-
 	return;
 }
 
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 67dec0c..5cd0228 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -30,8 +30,6 @@
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
 #include <linux/input.h>
 #include <linux/backlight.h>
 #include <linux/thermal.h>
@@ -152,9 +150,6 @@
 	struct acpi_video_bus_flags flags;
 	struct list_head video_device_list;
 	struct mutex device_list_lock;	/* protects video_device_list */
-#ifdef CONFIG_ACPI_PROCFS
-	struct proc_dir_entry *dir;
-#endif
 	struct input_dev *input;
 	char phys[32];	/* for input device */
 	struct notifier_block pm_nb;
@@ -210,108 +205,6 @@
 	struct output_device *output_dev;
 };
 
-#ifdef CONFIG_ACPI_PROCFS
-/* bus */
-static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file);
-static const struct file_operations acpi_video_bus_info_fops = {
-	.owner = THIS_MODULE,
-	.open = acpi_video_bus_info_open_fs,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-
-static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file);
-static const struct file_operations acpi_video_bus_ROM_fops = {
-	.owner = THIS_MODULE,
-	.open = acpi_video_bus_ROM_open_fs,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-
-static int acpi_video_bus_POST_info_open_fs(struct inode *inode,
-					    struct file *file);
-static const struct file_operations acpi_video_bus_POST_info_fops = {
-	.owner = THIS_MODULE,
-	.open = acpi_video_bus_POST_info_open_fs,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-
-static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file);
-static ssize_t acpi_video_bus_write_POST(struct file *file,
-	const char __user *buffer, size_t count, loff_t *data);
-static const struct file_operations acpi_video_bus_POST_fops = {
-	.owner = THIS_MODULE,
-	.open = acpi_video_bus_POST_open_fs,
-	.read = seq_read,
-	.write = acpi_video_bus_write_POST,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-
-static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file);
-static ssize_t acpi_video_bus_write_DOS(struct file *file,
-	const char __user *buffer, size_t count, loff_t *data);
-static const struct file_operations acpi_video_bus_DOS_fops = {
-	.owner = THIS_MODULE,
-	.open = acpi_video_bus_DOS_open_fs,
-	.read = seq_read,
-	.write = acpi_video_bus_write_DOS,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-
-/* device */
-static int acpi_video_device_info_open_fs(struct inode *inode,
-					  struct file *file);
-static const struct file_operations acpi_video_device_info_fops = {
-	.owner = THIS_MODULE,
-	.open = acpi_video_device_info_open_fs,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-
-static int acpi_video_device_state_open_fs(struct inode *inode,
-					   struct file *file);
-static ssize_t acpi_video_device_write_state(struct file *file,
-	const char __user *buffer, size_t count, loff_t *data);
-static const struct file_operations acpi_video_device_state_fops = {
-	.owner = THIS_MODULE,
-	.open = acpi_video_device_state_open_fs,
-	.read = seq_read,
-	.write = acpi_video_device_write_state,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-
-static int acpi_video_device_brightness_open_fs(struct inode *inode,
-						struct file *file);
-static ssize_t acpi_video_device_write_brightness(struct file *file,
-	const char __user *buffer, size_t count, loff_t *data);
-static const struct file_operations acpi_video_device_brightness_fops = {
-	.owner = THIS_MODULE,
-	.open = acpi_video_device_brightness_open_fs,
-	.read = seq_read,
-	.write = acpi_video_device_write_brightness,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-
-static int acpi_video_device_EDID_open_fs(struct inode *inode,
-					  struct file *file);
-static const struct file_operations acpi_video_device_EDID_fops = {
-	.owner = THIS_MODULE,
-	.open = acpi_video_device_EDID_open_fs,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-#endif /* CONFIG_ACPI_PROCFS */
-
 static const char device_decode[][30] = {
 	"motherboard VGA device",
 	"PCI VGA device",
@@ -1111,646 +1004,6 @@
 }
 
 /* --------------------------------------------------------------------------
-                              FS Interface (/proc)
-   -------------------------------------------------------------------------- */
-#ifdef CONFIG_ACPI_PROCFS
-
-static struct proc_dir_entry *acpi_video_dir;
-
-/* video devices */
-
-static int acpi_video_device_info_seq_show(struct seq_file *seq, void *offset)
-{
-	struct acpi_video_device *dev = seq->private;
-
-
-	if (!dev)
-		goto end;
-
-	seq_printf(seq, "device_id:    0x%04x\n", (u32) dev->device_id);
-	seq_printf(seq, "type:         ");
-	if (dev->flags.crt)
-		seq_printf(seq, "CRT\n");
-	else if (dev->flags.lcd)
-		seq_printf(seq, "LCD\n");
-	else if (dev->flags.tvout)
-		seq_printf(seq, "TVOUT\n");
-	else if (dev->flags.dvi)
-		seq_printf(seq, "DVI\n");
-	else
-		seq_printf(seq, "UNKNOWN\n");
-
-	seq_printf(seq, "known by bios: %s\n", dev->flags.bios ? "yes" : "no");
-
-      end:
-	return 0;
-}
-
-static int
-acpi_video_device_info_open_fs(struct inode *inode, struct file *file)
-{
-	return single_open(file, acpi_video_device_info_seq_show,
-			   PDE(inode)->data);
-}
-
-static int
-acpi_video_device_query(struct acpi_video_device *device,
-			unsigned long long *state)
-{
-	int status;
-
-	status = acpi_evaluate_integer(device->dev->handle, "_DGS",
-				       NULL, state);
-
-	return status;
-}
-
-static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset)
-{
-	int status;
-	struct acpi_video_device *dev = seq->private;
-	unsigned long long state;
-
-
-	if (!dev)
-		goto end;
-
-	status = acpi_video_device_get_state(dev, &state);
-	seq_printf(seq, "state:     ");
-	if (ACPI_SUCCESS(status))
-		seq_printf(seq, "0x%02llx\n", state);
-	else
-		seq_printf(seq, "<not supported>\n");
-
-	status = acpi_video_device_query(dev, &state);
-	seq_printf(seq, "query:     ");
-	if (ACPI_SUCCESS(status))
-		seq_printf(seq, "0x%02llx\n", state);
-	else
-		seq_printf(seq, "<not supported>\n");
-
-      end:
-	return 0;
-}
-
-static int
-acpi_video_device_state_open_fs(struct inode *inode, struct file *file)
-{
-	return single_open(file, acpi_video_device_state_seq_show,
-			   PDE(inode)->data);
-}
-
-static ssize_t
-acpi_video_device_write_state(struct file *file,
-			      const char __user * buffer,
-			      size_t count, loff_t * data)
-{
-	int status;
-	struct seq_file *m = file->private_data;
-	struct acpi_video_device *dev = m->private;
-	char str[12] = { 0 };
-	u32 state = 0;
-
-
-	if (!dev || count >= sizeof(str))
-		return -EINVAL;
-
-	if (copy_from_user(str, buffer, count))
-		return -EFAULT;
-
-	str[count] = 0;
-	state = simple_strtoul(str, NULL, 0);
-	state &= ((1ul << 31) | (1ul << 30) | (1ul << 0));
-
-	status = acpi_video_device_set_state(dev, state);
-
-	if (status)
-		return -EFAULT;
-
-	return count;
-}
-
-static int
-acpi_video_device_brightness_seq_show(struct seq_file *seq, void *offset)
-{
-	struct acpi_video_device *dev = seq->private;
-	int i;
-
-
-	if (!dev || !dev->brightness) {
-		seq_printf(seq, "<not supported>\n");
-		return 0;
-	}
-
-	seq_printf(seq, "levels: ");
-	for (i = 2; i < dev->brightness->count; i++)
-		seq_printf(seq, " %d", dev->brightness->levels[i]);
-	seq_printf(seq, "\ncurrent: %d\n", dev->brightness->curr);
-
-	return 0;
-}
-
-static int
-acpi_video_device_brightness_open_fs(struct inode *inode, struct file *file)
-{
-	return single_open(file, acpi_video_device_brightness_seq_show,
-			   PDE(inode)->data);
-}
-
-static ssize_t
-acpi_video_device_write_brightness(struct file *file,
-				   const char __user * buffer,
-				   size_t count, loff_t * data)
-{
-	struct seq_file *m = file->private_data;
-	struct acpi_video_device *dev = m->private;
-	char str[5] = { 0 };
-	unsigned int level = 0;
-	int i;
-
-
-	if (!dev || !dev->brightness || count >= sizeof(str))
-		return -EINVAL;
-
-	if (copy_from_user(str, buffer, count))
-		return -EFAULT;
-
-	str[count] = 0;
-	level = simple_strtoul(str, NULL, 0);
-
-	if (level > 100)
-		return -EFAULT;
-
-	/* validate through the list of available levels */
-	for (i = 2; i < dev->brightness->count; i++)
-		if (level == dev->brightness->levels[i]) {
-			if (!acpi_video_device_lcd_set_level(dev, level))
-				return count;
-			break;
-		}
-
-	return -EINVAL;
-}
-
-static int acpi_video_device_EDID_seq_show(struct seq_file *seq, void *offset)
-{
-	struct acpi_video_device *dev = seq->private;
-	int status;
-	int i;
-	union acpi_object *edid = NULL;
-
-
-	if (!dev)
-		goto out;
-
-	status = acpi_video_device_EDID(dev, &edid, 128);
-	if (ACPI_FAILURE(status)) {
-		status = acpi_video_device_EDID(dev, &edid, 256);
-	}
-
-	if (ACPI_FAILURE(status)) {
-		goto out;
-	}
-
-	if (edid && edid->type == ACPI_TYPE_BUFFER) {
-		for (i = 0; i < edid->buffer.length; i++)
-			seq_putc(seq, edid->buffer.pointer[i]);
-	}
-
-      out:
-	if (!edid)
-		seq_printf(seq, "<not supported>\n");
-	else
-		kfree(edid);
-
-	return 0;
-}
-
-static int
-acpi_video_device_EDID_open_fs(struct inode *inode, struct file *file)
-{
-	return single_open(file, acpi_video_device_EDID_seq_show,
-			   PDE(inode)->data);
-}
-
-static int acpi_video_device_add_fs(struct acpi_device *device)
-{
-	struct proc_dir_entry *entry, *device_dir;
-	struct acpi_video_device *vid_dev;
-
-	vid_dev = acpi_driver_data(device);
-	if (!vid_dev)
-		return -ENODEV;
-
-	device_dir = proc_mkdir(acpi_device_bid(device),
-				vid_dev->video->dir);
-	if (!device_dir)
-		return -ENOMEM;
-
-	/* 'info' [R] */
-	entry = proc_create_data("info", S_IRUGO, device_dir,
-			&acpi_video_device_info_fops, acpi_driver_data(device));
-	if (!entry)
-		goto err_remove_dir;
-
-	/* 'state' [R/W] */
-	entry = proc_create_data("state", S_IFREG | S_IRUGO | S_IWUSR,
-				 device_dir,
-				 &acpi_video_device_state_fops,
-				 acpi_driver_data(device));
-	if (!entry)
-		goto err_remove_info;
-
-	/* 'brightness' [R/W] */
-	entry = proc_create_data("brightness", S_IFREG | S_IRUGO | S_IWUSR,
-				 device_dir,
-				 &acpi_video_device_brightness_fops,
-				 acpi_driver_data(device));
-	if (!entry)
-		goto err_remove_state;
-
-	/* 'EDID' [R] */
-	entry = proc_create_data("EDID", S_IRUGO, device_dir,
-				 &acpi_video_device_EDID_fops,
-				 acpi_driver_data(device));
-	if (!entry)
-		goto err_remove_brightness;
-
-	acpi_device_dir(device) = device_dir;
-
-	return 0;
-
- err_remove_brightness:
-	remove_proc_entry("brightness", device_dir);
- err_remove_state:
-	remove_proc_entry("state", device_dir);
- err_remove_info:
-	remove_proc_entry("info", device_dir);
- err_remove_dir:
-	remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir);
-	return -ENOMEM;
-}
-
-static int acpi_video_device_remove_fs(struct acpi_device *device)
-{
-	struct acpi_video_device *vid_dev;
-	struct proc_dir_entry *device_dir;
-
-	vid_dev = acpi_driver_data(device);
-	if (!vid_dev || !vid_dev->video || !vid_dev->video->dir)
-		return -ENODEV;
-
-	device_dir = acpi_device_dir(device);
-	if (device_dir) {
-		remove_proc_entry("info", device_dir);
-		remove_proc_entry("state", device_dir);
-		remove_proc_entry("brightness", device_dir);
-		remove_proc_entry("EDID", device_dir);
-		remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir);
-		acpi_device_dir(device) = NULL;
-	}
-
-	return 0;
-}
-
-/* video bus */
-static int acpi_video_bus_info_seq_show(struct seq_file *seq, void *offset)
-{
-	struct acpi_video_bus *video = seq->private;
-
-
-	if (!video)
-		goto end;
-
-	seq_printf(seq, "Switching heads:              %s\n",
-		   video->flags.multihead ? "yes" : "no");
-	seq_printf(seq, "Video ROM:                    %s\n",
-		   video->flags.rom ? "yes" : "no");
-	seq_printf(seq, "Device to be POSTed on boot:  %s\n",
-		   video->flags.post ? "yes" : "no");
-
-      end:
-	return 0;
-}
-
-static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file)
-{
-	return single_open(file, acpi_video_bus_info_seq_show,
-			   PDE(inode)->data);
-}
-
-static int acpi_video_bus_ROM_seq_show(struct seq_file *seq, void *offset)
-{
-	struct acpi_video_bus *video = seq->private;
-
-
-	if (!video)
-		goto end;
-
-	printk(KERN_INFO PREFIX "Please implement %s\n", __func__);
-	seq_printf(seq, "<TODO>\n");
-
-      end:
-	return 0;
-}
-
-static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file)
-{
-	return single_open(file, acpi_video_bus_ROM_seq_show, PDE(inode)->data);
-}
-
-static int
-acpi_video_bus_POST_options(struct acpi_video_bus *video,
-			    unsigned long long *options)
-{
-	int status;
-
-	status = acpi_evaluate_integer(video->device->handle, "_VPO",
-				       NULL, options);
-	*options &= 3;
-
-	return status;
-}
-
-static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset)
-{
-	struct acpi_video_bus *video = seq->private;
-	unsigned long long options;
-	int status;
-
-
-	if (!video)
-		goto end;
-
-	status = acpi_video_bus_POST_options(video, &options);
-	if (ACPI_SUCCESS(status)) {
-		if (!(options & 1)) {
-			printk(KERN_WARNING PREFIX
-			       "The motherboard VGA device is not listed as a possible POST device.\n");
-			printk(KERN_WARNING PREFIX
-			       "This indicates a BIOS bug. Please contact the manufacturer.\n");
-		}
-		printk(KERN_WARNING "%llx\n", options);
-		seq_printf(seq, "can POST: <integrated video>");
-		if (options & 2)
-			seq_printf(seq, " <PCI video>");
-		if (options & 4)
-			seq_printf(seq, " <AGP video>");
-		seq_putc(seq, '\n');
-	} else
-		seq_printf(seq, "<not supported>\n");
-      end:
-	return 0;
-}
-
-static int
-acpi_video_bus_POST_info_open_fs(struct inode *inode, struct file *file)
-{
-	return single_open(file, acpi_video_bus_POST_info_seq_show,
-			   PDE(inode)->data);
-}
-
-static int
-acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long long *id)
-{
-	int status;
-
-	status = acpi_evaluate_integer(video->device->handle, "_GPD", NULL, id);
-
-	return status;
-}
-
-static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset)
-{
-	struct acpi_video_bus *video = seq->private;
-	int status;
-	unsigned long long id;
-
-
-	if (!video)
-		goto end;
-
-	status = acpi_video_bus_get_POST(video, &id);
-	if (!ACPI_SUCCESS(status)) {
-		seq_printf(seq, "<not supported>\n");
-		goto end;
-	}
-	seq_printf(seq, "device POSTed is <%s>\n", device_decode[id & 3]);
-
-      end:
-	return 0;
-}
-
-static int acpi_video_bus_DOS_seq_show(struct seq_file *seq, void *offset)
-{
-	struct acpi_video_bus *video = seq->private;
-
-
-	seq_printf(seq, "DOS setting: <%d>\n", video->dos_setting);
-
-	return 0;
-}
-
-static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file)
-{
-	return single_open(file, acpi_video_bus_POST_seq_show,
-			   PDE(inode)->data);
-}
-
-static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file)
-{
-	return single_open(file, acpi_video_bus_DOS_seq_show, PDE(inode)->data);
-}
-
-static int
-acpi_video_bus_set_POST(struct acpi_video_bus *video, unsigned long option)
-{
-	int status;
-	unsigned long long tmp;
-	union acpi_object arg0 = { ACPI_TYPE_INTEGER };
-	struct acpi_object_list args = { 1, &arg0 };
-
-
-	arg0.integer.value = option;
-
-	status = acpi_evaluate_integer(video->device->handle, "_SPD",
-				       &args, &tmp);
-	if (ACPI_SUCCESS(status))
-		status = tmp ? (-EINVAL) : (AE_OK);
-
-	return status;
-}
-
-static ssize_t
-acpi_video_bus_write_POST(struct file *file,
-			  const char __user * buffer,
-			  size_t count, loff_t * data)
-{
-	int status;
-	struct seq_file *m = file->private_data;
-	struct acpi_video_bus *video = m->private;
-	char str[12] = { 0 };
-	unsigned long long opt, options;
-
-
-	if (!video || count >= sizeof(str))
-		return -EINVAL;
-
-	status = acpi_video_bus_POST_options(video, &options);
-	if (!ACPI_SUCCESS(status))
-		return -EINVAL;
-
-	if (copy_from_user(str, buffer, count))
-		return -EFAULT;
-
-	str[count] = 0;
-	opt = strtoul(str, NULL, 0);
-	if (opt > 3)
-		return -EFAULT;
-
-	/* just in case an OEM 'forgot' the motherboard... */
-	options |= 1;
-
-	if (options & (1ul << opt)) {
-		status = acpi_video_bus_set_POST(video, opt);
-		if (!ACPI_SUCCESS(status))
-			return -EFAULT;
-
-	}
-
-	return count;
-}
-
-static ssize_t
-acpi_video_bus_write_DOS(struct file *file,
-			 const char __user * buffer,
-			 size_t count, loff_t * data)
-{
-	int status;
-	struct seq_file *m = file->private_data;
-	struct acpi_video_bus *video = m->private;
-	char str[12] = { 0 };
-	unsigned long opt;
-
-
-	if (!video || count >= sizeof(str))
-		return -EINVAL;
-
-	if (copy_from_user(str, buffer, count))
-		return -EFAULT;
-
-	str[count] = 0;
-	opt = strtoul(str, NULL, 0);
-	if (opt > 7)
-		return -EFAULT;
-
-	status = acpi_video_bus_DOS(video, opt & 0x3, (opt & 0x4) >> 2);
-
-	if (!ACPI_SUCCESS(status))
-		return -EFAULT;
-
-	return count;
-}
-
-static int acpi_video_bus_add_fs(struct acpi_device *device)
-{
-	struct acpi_video_bus *video = acpi_driver_data(device);
-	struct proc_dir_entry *device_dir;
-	struct proc_dir_entry *entry;
-
-	device_dir = proc_mkdir(acpi_device_bid(device), acpi_video_dir);
-	if (!device_dir)
-		return -ENOMEM;
-
-	/* 'info' [R] */
-	entry = proc_create_data("info", S_IRUGO, device_dir,
-				 &acpi_video_bus_info_fops,
-				 acpi_driver_data(device));
-	if (!entry)
-		goto err_remove_dir;
-
-	/* 'ROM' [R] */
-	entry = proc_create_data("ROM", S_IRUGO, device_dir,
-				 &acpi_video_bus_ROM_fops,
-				 acpi_driver_data(device));
-	if (!entry)
-		goto err_remove_info;
-
-	/* 'POST_info' [R] */
-	entry = proc_create_data("POST_info", S_IRUGO, device_dir,
-				 &acpi_video_bus_POST_info_fops,
-				 acpi_driver_data(device));
-	if (!entry)
-		goto err_remove_rom;
-
-	/* 'POST' [R/W] */
-	entry = proc_create_data("POST", S_IFREG | S_IRUGO | S_IWUSR,
-				 device_dir,
-				 &acpi_video_bus_POST_fops,
-				 acpi_driver_data(device));
-	if (!entry)
-		goto err_remove_post_info;
-
-	/* 'DOS' [R/W] */
-	entry = proc_create_data("DOS", S_IFREG | S_IRUGO | S_IWUSR,
-				 device_dir,
-				 &acpi_video_bus_DOS_fops,
-				 acpi_driver_data(device));
-	if (!entry)
-		goto err_remove_post;
-
-	video->dir = acpi_device_dir(device) = device_dir;
-	return 0;
-
- err_remove_post:
-	remove_proc_entry("POST", device_dir);
- err_remove_post_info:
-	remove_proc_entry("POST_info", device_dir);
- err_remove_rom:
-	remove_proc_entry("ROM", device_dir);
- err_remove_info:
-	remove_proc_entry("info", device_dir);
- err_remove_dir:
-	remove_proc_entry(acpi_device_bid(device), acpi_video_dir);
-	return -ENOMEM;
-}
-
-static int acpi_video_bus_remove_fs(struct acpi_device *device)
-{
-	struct proc_dir_entry *device_dir = acpi_device_dir(device);
-
-	if (device_dir) {
-		remove_proc_entry("info", device_dir);
-		remove_proc_entry("ROM", device_dir);
-		remove_proc_entry("POST_info", device_dir);
-		remove_proc_entry("POST", device_dir);
-		remove_proc_entry("DOS", device_dir);
-		remove_proc_entry(acpi_device_bid(device), acpi_video_dir);
-		acpi_device_dir(device) = NULL;
-	}
-
-	return 0;
-}
-#else
-static inline int acpi_video_device_add_fs(struct acpi_device *device)
-{
-	return 0;
-}
-static inline int acpi_video_device_remove_fs(struct acpi_device *device)
-{
-	return 0;
-}
-static inline int acpi_video_bus_add_fs(struct acpi_device *device)
-{
-	return 0;
-}
-static inline int acpi_video_bus_remove_fs(struct acpi_device *device)
-{
-	return 0;
-}
-#endif /* CONFIG_ACPI_PROCFS */
-
-/* --------------------------------------------------------------------------
                                  Driver Interface
    -------------------------------------------------------------------------- */
 
@@ -1877,8 +1130,6 @@
 		list_add_tail(&data->entry, &video->video_device_list);
 		mutex_unlock(&video->device_list_lock);
 
-		acpi_video_device_add_fs(device);
-
 		return 0;
 	}
 
@@ -2181,8 +1432,6 @@
 	if (!device || !device->video)
 		return -ENOENT;
 
-	acpi_video_device_remove_fs(device->dev);
-
 	status = acpi_remove_notify_handler(device->dev->handle,
 					    ACPI_DEVICE_NOTIFY,
 					    acpi_video_device_notify);
@@ -2466,10 +1715,6 @@
 	if (error)
 		goto err_free_video;
 
-	error = acpi_video_bus_add_fs(device);
-	if (error)
-		goto err_free_video;
-
 	mutex_init(&video->device_list_lock);
 	INIT_LIST_HEAD(&video->video_device_list);
 
@@ -2522,7 +1767,6 @@
 	acpi_video_bus_stop_devices(video);
 	acpi_video_bus_put_devices(video);
 	kfree(video->attached_array);
-	acpi_video_bus_remove_fs(device);
  err_free_video:
 	kfree(video);
 	device->driver_data = NULL;
@@ -2544,7 +1788,6 @@
 
 	acpi_video_bus_stop_devices(video);
 	acpi_video_bus_put_devices(video);
-	acpi_video_bus_remove_fs(device);
 
 	input_unregister_device(video->input);
 	kfree(video->attached_array);
@@ -2584,17 +1827,9 @@
 		return 0;
 	}
 
-#ifdef CONFIG_ACPI_PROCFS
-	acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir);
-	if (!acpi_video_dir)
-		return -ENODEV;
-#endif
-
 	result = acpi_bus_register_driver(&acpi_video_bus);
-	if (result < 0) {
-		remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir);
+	if (result < 0)
 		return -ENODEV;
-	}
 
 	/*
 	 * When the acpi_video_bus is loaded successfully, increase
@@ -2617,10 +1852,6 @@
 	}
 	acpi_bus_unregister_driver(&acpi_video_bus);
 
-#ifdef CONFIG_ACPI_PROCFS
-	remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir);
-#endif
-
 	register_count = 0;
 
 	return;
diff --git a/drivers/base/node.c b/drivers/base/node.c
index ee53558..ce012a9 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -160,6 +160,18 @@
 }
 static SYSDEV_ATTR(numastat, S_IRUGO, node_read_numastat, NULL);
 
+static ssize_t node_read_vmstat(struct sys_device *dev,
+				struct sysdev_attribute *attr, char *buf)
+{
+	int nid = dev->id;
+	return sprintf(buf,
+		"nr_written %lu\n"
+		"nr_dirtied %lu\n",
+		node_page_state(nid, NR_WRITTEN),
+		node_page_state(nid, NR_DIRTIED));
+}
+static SYSDEV_ATTR(vmstat, S_IRUGO, node_read_vmstat, NULL);
+
 static ssize_t node_read_distance(struct sys_device * dev,
 			struct sysdev_attribute *attr, char * buf)
 {
@@ -243,6 +255,7 @@
 		sysdev_create_file(&node->sysdev, &attr_meminfo);
 		sysdev_create_file(&node->sysdev, &attr_numastat);
 		sysdev_create_file(&node->sysdev, &attr_distance);
+		sysdev_create_file(&node->sysdev, &attr_vmstat);
 
 		scan_unevictable_register_node(node);
 
@@ -267,6 +280,7 @@
 	sysdev_remove_file(&node->sysdev, &attr_meminfo);
 	sysdev_remove_file(&node->sysdev, &attr_numastat);
 	sysdev_remove_file(&node->sysdev, &attr_distance);
+	sysdev_remove_file(&node->sysdev, &attr_vmstat);
 
 	scan_unevictable_unregister_node(node);
 	hugetlb_unregister_node(node);		/* no-op, if memoryless node */
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 1dd8676..126ca49 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -503,7 +503,7 @@
 	 * the resume will actually succeed.
 	 */
 	if (dev->power.no_callbacks && !parent && dev->parent) {
-		spin_lock(&dev->parent->power.lock);
+		spin_lock_nested(&dev->parent->power.lock, SINGLE_DEPTH_NESTING);
 		if (dev->parent->power.disable_depth > 0
 		    || dev->parent->power.ignore_children
 		    || dev->parent->power.runtime_status == RPM_ACTIVE) {
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 6c48b35..450c958 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -101,8 +101,8 @@
 	else
 		memcpy(raw_buf, loop_buf, size);
 
-	kunmap_atomic(raw_buf, KM_USER0);
 	kunmap_atomic(loop_buf, KM_USER1);
+	kunmap_atomic(raw_buf, KM_USER0);
 	cond_resched();
 	return 0;
 }
@@ -130,8 +130,8 @@
 	for (i = 0; i < size; i++)
 		*out++ = *in++ ^ key[(i & 511) % keysize];
 
-	kunmap_atomic(raw_buf, KM_USER0);
 	kunmap_atomic(loop_buf, KM_USER1);
+	kunmap_atomic(raw_buf, KM_USER0);
 	cond_resched();
 	return 0;
 }
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index a4eee32..55b8667 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -32,12 +32,12 @@
 #include <linux/bitops.h>
 #include <linux/compat.h>
 #include <linux/clocksource.h>
+#include <linux/uaccess.h>
 #include <linux/slab.h>
+#include <linux/io.h>
 
 #include <asm/current.h>
-#include <asm/uaccess.h>
 #include <asm/system.h>
-#include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/div64.h>
 
@@ -81,13 +81,13 @@
 }
 
 static struct clocksource clocksource_hpet = {
-        .name           = "hpet",
-        .rating         = 250,
-        .read           = read_hpet,
-        .mask           = CLOCKSOURCE_MASK(64),
-	.mult		= 0, /* to be calculated */
-        .shift          = 10,
-        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+	.name		= "hpet",
+	.rating		= 250,
+	.read		= read_hpet,
+	.mask		= CLOCKSOURCE_MASK(64),
+	.mult		= 0,		/* to be calculated */
+	.shift		= 10,
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 static struct clocksource *hpet_clocksource;
 #endif
@@ -465,6 +465,21 @@
 	if (irq) {
 		unsigned long irq_flags;
 
+		if (devp->hd_flags & HPET_SHARED_IRQ) {
+			/*
+			 * To prevent the interrupt handler from seeing an
+			 * unwanted interrupt status bit, program the timer
+			 * so that it will not fire in the near future ...
+			 */
+			writel(readl(&timer->hpet_config) & ~Tn_TYPE_CNF_MASK,
+			       &timer->hpet_config);
+			write_counter(read_counter(&hpet->hpet_mc),
+				      &timer->hpet_compare);
+			/* ... and clear any left-over status. */
+			isr = 1 << (devp - devp->hd_hpets->hp_dev);
+			writel(isr, &hpet->hpet_isr);
+		}
+
 		sprintf(devp->hd_name, "hpet%d", (int)(devp - hpetp->hp_dev));
 		irq_flags = devp->hd_flags & HPET_SHARED_IRQ
 						? IRQF_SHARED : IRQF_DISABLED;
@@ -581,11 +596,10 @@
 		break;
 	case HPET_INFO:
 		{
+			memset(info, 0, sizeof(*info));
 			if (devp->hd_ireqfreq)
 				info->hi_ireqfreq =
 					hpet_time_div(hpetp, devp->hd_ireqfreq);
-			else
-				info->hi_ireqfreq = 0;
 			info->hi_flags =
 			    readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK;
 			info->hi_hpet = hpetp->hp_which;
@@ -811,7 +825,7 @@
 	struct hpets *hpetp;
 	size_t siz;
 	struct hpet __iomem *hpet;
-	static struct hpets *last = NULL;
+	static struct hpets *last;
 	unsigned long period;
 	unsigned long long temp;
 	u32 remainder;
@@ -1000,6 +1014,8 @@
 		return -ENODEV;
 
 	if (!data.hd_address || !data.hd_nirqs) {
+		if (data.hd_address)
+			iounmap(data.hd_address);
 		printk("%s: no address or irqs in _CRS\n", __func__);
 		return -ENODEV;
 	}
diff --git a/drivers/char/hvc_tile.c b/drivers/char/hvc_tile.c
index c4efb55..7a84a05 100644
--- a/drivers/char/hvc_tile.c
+++ b/drivers/char/hvc_tile.c
@@ -61,7 +61,8 @@
 
 static int __init hvc_tile_init(void)
 {
-	hvc_alloc(0, 0, &hvc_tile_get_put_ops, 128);
-	return 0;
+	struct hvc_struct *s;
+	s = hvc_alloc(0, 0, &hvc_tile_get_put_ops, 128);
+	return IS_ERR(s) ? PTR_ERR(s) : 0;
 }
 device_initcall(hvc_tile_init);
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index e537610..b293d57 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -1665,6 +1665,17 @@
 	return 0;
 }
 
+static struct smi_info *smi_info_alloc(void)
+{
+	struct smi_info *info = kzalloc(sizeof(*info), GFP_KERNEL);
+
+	if (info) {
+		spin_lock_init(&info->si_lock);
+		spin_lock_init(&info->msg_lock);
+	}
+	return info;
+}
+
 static int hotmod_handler(const char *val, struct kernel_param *kp)
 {
 	char *str = kstrdup(val, GFP_KERNEL);
@@ -1779,7 +1790,7 @@
 		}
 
 		if (op == HM_ADD) {
-			info = kzalloc(sizeof(*info), GFP_KERNEL);
+			info = smi_info_alloc();
 			if (!info) {
 				rv = -ENOMEM;
 				goto out;
@@ -1844,7 +1855,7 @@
 		if (!ports[i] && !addrs[i])
 			continue;
 
-		info = kzalloc(sizeof(*info), GFP_KERNEL);
+		info = smi_info_alloc();
 		if (!info)
 			return;
 
@@ -2027,7 +2038,7 @@
 		return -ENODEV;
 	}
 
-	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	info = smi_info_alloc();
 	if (!info) {
 		printk(KERN_ERR PFX "Could not allocate SI data (3)\n");
 		return -ENOMEM;
@@ -2137,7 +2148,7 @@
 	if (!acpi_dev)
 		return -ENODEV;
 
-	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	info = smi_info_alloc();
 	if (!info)
 		return -ENOMEM;
 
@@ -2318,7 +2329,7 @@
 {
 	struct smi_info *info;
 
-	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	info = smi_info_alloc();
 	if (!info) {
 		printk(KERN_ERR PFX "Could not allocate SI data\n");
 		return;
@@ -2425,7 +2436,7 @@
 	int class_type = pdev->class & PCI_ERMC_CLASSCODE_TYPE_MASK;
 	struct smi_info *info;
 
-	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	info = smi_info_alloc();
 	if (!info)
 		return -ENOMEM;
 
@@ -2566,7 +2577,7 @@
 		return -EINVAL;
 	}
 
-	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	info = smi_info_alloc();
 
 	if (!info) {
 		dev_err(&dev->dev,
@@ -3013,7 +3024,7 @@
 		if (check_legacy_ioport(ipmi_defaults[i].port))
 			continue;
 #endif
-		info = kzalloc(sizeof(*info), GFP_KERNEL);
+		info = smi_info_alloc();
 		if (!info)
 			return;
 
@@ -3138,9 +3149,6 @@
 		goto out_err;
 	}
 
-	spin_lock_init(&(new_smi->si_lock));
-	spin_lock_init(&(new_smi->msg_lock));
-
 	/* Do low-level detection first. */
 	if (new_smi->handlers->detect(new_smi->si_sm)) {
 		if (new_smi->addr_source)
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 199dcb9..c63a438 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -918,8 +918,8 @@
 
 	spin_lock_irqsave(&cpufreq_driver_lock, flags);
 	for_each_cpu(j, policy->cpus) {
-	if (!cpu_online(j))
-		continue;
+		if (!cpu_online(j))
+			continue;
 		per_cpu(cpufreq_cpu_data, j) = policy;
 		per_cpu(cpufreq_policy_cpu, j) = policy->cpu;
 	}
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 7b5093664..c631f27 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -30,6 +30,8 @@
 
 #define DEF_FREQUENCY_DOWN_DIFFERENTIAL		(10)
 #define DEF_FREQUENCY_UP_THRESHOLD		(80)
+#define DEF_SAMPLING_DOWN_FACTOR		(1)
+#define MAX_SAMPLING_DOWN_FACTOR		(100000)
 #define MICRO_FREQUENCY_DOWN_DIFFERENTIAL	(3)
 #define MICRO_FREQUENCY_UP_THRESHOLD		(95)
 #define MICRO_FREQUENCY_MIN_SAMPLE_RATE		(10000)
@@ -82,6 +84,7 @@
 	unsigned int freq_lo;
 	unsigned int freq_lo_jiffies;
 	unsigned int freq_hi_jiffies;
+	unsigned int rate_mult;
 	int cpu;
 	unsigned int sample_type:1;
 	/*
@@ -108,10 +111,12 @@
 	unsigned int up_threshold;
 	unsigned int down_differential;
 	unsigned int ignore_nice;
+	unsigned int sampling_down_factor;
 	unsigned int powersave_bias;
 	unsigned int io_is_busy;
 } dbs_tuners_ins = {
 	.up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
+	.sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR,
 	.down_differential = DEF_FREQUENCY_DOWN_DIFFERENTIAL,
 	.ignore_nice = 0,
 	.powersave_bias = 0,
@@ -259,6 +264,7 @@
 show_one(sampling_rate, sampling_rate);
 show_one(io_is_busy, io_is_busy);
 show_one(up_threshold, up_threshold);
+show_one(sampling_down_factor, sampling_down_factor);
 show_one(ignore_nice_load, ignore_nice);
 show_one(powersave_bias, powersave_bias);
 
@@ -340,6 +346,29 @@
 	return count;
 }
 
+static ssize_t store_sampling_down_factor(struct kobject *a,
+			struct attribute *b, const char *buf, size_t count)
+{
+	unsigned int input, j;
+	int ret;
+	ret = sscanf(buf, "%u", &input);
+
+	if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1)
+		return -EINVAL;
+	mutex_lock(&dbs_mutex);
+	dbs_tuners_ins.sampling_down_factor = input;
+
+	/* Reset down sampling multiplier in case it was active */
+	for_each_online_cpu(j) {
+		struct cpu_dbs_info_s *dbs_info;
+		dbs_info = &per_cpu(od_cpu_dbs_info, j);
+		dbs_info->rate_mult = 1;
+	}
+	mutex_unlock(&dbs_mutex);
+
+	return count;
+}
+
 static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b,
 				      const char *buf, size_t count)
 {
@@ -401,6 +430,7 @@
 define_one_global_rw(sampling_rate);
 define_one_global_rw(io_is_busy);
 define_one_global_rw(up_threshold);
+define_one_global_rw(sampling_down_factor);
 define_one_global_rw(ignore_nice_load);
 define_one_global_rw(powersave_bias);
 
@@ -409,6 +439,7 @@
 	&sampling_rate_min.attr,
 	&sampling_rate.attr,
 	&up_threshold.attr,
+	&sampling_down_factor.attr,
 	&ignore_nice_load.attr,
 	&powersave_bias.attr,
 	&io_is_busy.attr,
@@ -562,6 +593,10 @@
 
 	/* Check for frequency increase */
 	if (max_load_freq > dbs_tuners_ins.up_threshold * policy->cur) {
+		/* If switching to max speed, apply sampling_down_factor */
+		if (policy->cur < policy->max)
+			this_dbs_info->rate_mult =
+				dbs_tuners_ins.sampling_down_factor;
 		dbs_freq_increase(policy, policy->max);
 		return;
 	}
@@ -584,6 +619,9 @@
 				(dbs_tuners_ins.up_threshold -
 				 dbs_tuners_ins.down_differential);
 
+		/* No longer fully busy, reset rate_mult */
+		this_dbs_info->rate_mult = 1;
+
 		if (freq_next < policy->min)
 			freq_next = policy->min;
 
@@ -607,7 +645,8 @@
 	int sample_type = dbs_info->sample_type;
 
 	/* We want all CPUs to do sampling nearly on same jiffy */
-	int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
+	int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate
+		* dbs_info->rate_mult);
 
 	if (num_online_cpus() > 1)
 		delay -= jiffies % delay;
@@ -711,6 +750,7 @@
 			}
 		}
 		this_dbs_info->cpu = cpu;
+		this_dbs_info->rate_mult = 1;
 		ondemand_powersave_bias_init_cpu(cpu);
 		/*
 		 * Start the timerschedule work, when this governor
diff --git a/drivers/crypto/hifn_795x.c b/drivers/crypto/hifn_795x.c
index 0eac3da..a84250a 100644
--- a/drivers/crypto/hifn_795x.c
+++ b/drivers/crypto/hifn_795x.c
@@ -1467,7 +1467,7 @@
 		return -EINVAL;
 
 	while (size) {
-		copy = min(drest, min(size, dst->length));
+		copy = min3(drest, size, dst->length);
 
 		size -= copy;
 		drest -= copy;
@@ -1729,7 +1729,7 @@
 		return -EINVAL;
 
 	while (size) {
-		copy = min(srest, min(dst->length, size));
+		copy = min3(srest, dst->length, size);
 
 		daddr = kmap_atomic(sg_page(dst), KM_IRQ0);
 		memcpy(daddr + dst->offset + offset, saddr, copy);
diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h
index ce71466..d7ca43a 100644
--- a/drivers/edac/edac_core.h
+++ b/drivers/edac/edac_core.h
@@ -42,8 +42,10 @@
 
 #if PAGE_SHIFT < 20
 #define PAGES_TO_MiB( pages )	( ( pages ) >> ( 20 - PAGE_SHIFT ) )
+#define MiB_TO_PAGES(mb)	((mb) >> (20 - PAGE_SHIFT))
 #else				/* PAGE_SHIFT > 20 */
 #define PAGES_TO_MiB( pages )	( ( pages ) << ( PAGE_SHIFT - 20 ) )
+#define MiB_TO_PAGES(mb)	((mb) >> (PAGE_SHIFT - 20))
 #endif
 
 #define edac_printk(level, prefix, fmt, arg...) \
@@ -328,7 +330,7 @@
 
 struct mcidev_sysfs_group {
 	const char *name;				/* group name */
-	struct mcidev_sysfs_attribute *mcidev_attr;	/* group attributes */
+	const struct mcidev_sysfs_attribute *mcidev_attr; /* group attributes */
 };
 
 struct mcidev_sysfs_group_kobj {
@@ -336,7 +338,7 @@
 
 	struct kobject kobj;		/* kobj for the group */
 
-	struct mcidev_sysfs_group *grp;	/* group description table */
+	const struct mcidev_sysfs_group *grp;	/* group description table */
 	struct mem_ctl_info *mci;	/* the parent */
 };
 
@@ -347,7 +349,7 @@
 struct mcidev_sysfs_attribute {
 	/* It should use either attr or grp */
 	struct attribute attr;
-	struct mcidev_sysfs_group *grp;	/* Points to a group of attributes */
+	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 *);
@@ -440,7 +442,7 @@
 	 * If attributes are desired, then set to array of attributes
 	 * If no attributes are desired, leave NULL
 	 */
-	struct mcidev_sysfs_attribute *mc_driver_sysfs_attributes;
+	const struct mcidev_sysfs_attribute *mc_driver_sysfs_attributes;
 
 	/* work struct for this MC */
 	struct delayed_work work;
@@ -810,6 +812,7 @@
 extern int edac_mc_add_mc(struct mem_ctl_info *mci);
 extern void edac_mc_free(struct mem_ctl_info *mci);
 extern struct mem_ctl_info *edac_mc_find(int idx);
+extern struct mem_ctl_info *find_mci_by_dev(struct device *dev);
 extern struct mem_ctl_info *edac_mc_del_mc(struct device *dev);
 extern int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci,
 				      unsigned long page);
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 6b21e25..ba6586a 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -207,6 +207,7 @@
 	}
 
 	mci->op_state = OP_ALLOC;
+	INIT_LIST_HEAD(&mci->grp_kobj_list);
 
 	/*
 	 * Initialize the 'root' kobj for the edac_mc controller
@@ -234,18 +235,24 @@
  */
 void edac_mc_free(struct mem_ctl_info *mci)
 {
+	debugf1("%s()\n", __func__);
+
 	edac_mc_unregister_sysfs_main_kobj(mci);
+
+	/* free the mci instance memory here */
+	kfree(mci);
 }
 EXPORT_SYMBOL_GPL(edac_mc_free);
 
 
-/*
+/**
  * find_mci_by_dev
  *
  *	scan list of controllers looking for the one that manages
  *	the 'dev' device
+ * @dev: pointer to a struct device related with the MCI
  */
-static struct mem_ctl_info *find_mci_by_dev(struct device *dev)
+struct mem_ctl_info *find_mci_by_dev(struct device *dev)
 {
 	struct mem_ctl_info *mci;
 	struct list_head *item;
@@ -261,6 +268,7 @@
 
 	return NULL;
 }
+EXPORT_SYMBOL_GPL(find_mci_by_dev);
 
 /*
  * handler for EDAC to check if NMI type handler has asserted interrupt
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index a413586..dce61f7 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -631,9 +631,6 @@
 
 	/* decrement the module ref count */
 	module_put(mci->owner);
-
-	/* free the mci instance memory here */
-	kfree(mci);
 }
 
 static struct kobj_type ktype_mci = {
@@ -713,6 +710,8 @@
  */
 void edac_mc_unregister_sysfs_main_kobj(struct mem_ctl_info *mci)
 {
+	debugf1("%s()\n", __func__);
+
 	/* delete the kobj from the mc_kset */
 	kobject_put(&mci->edac_mci_kobj);
 }
@@ -760,8 +759,6 @@
 
 	grp = container_of(kobj, struct mcidev_sysfs_group_kobj, kobj);
 	mci = grp->mci;
-
-	kobject_put(&mci->edac_mci_kobj);
 }
 
 /* Intermediate show/store table */
@@ -784,7 +781,7 @@
  * object tree.
  */
 static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci,
-				struct mcidev_sysfs_attribute *sysfs_attrib,
+				const struct mcidev_sysfs_attribute *sysfs_attrib,
 				struct kobject *kobj)
 {
 	int err;
@@ -792,6 +789,7 @@
 	debugf1("%s()\n", __func__);
 
 	while (sysfs_attrib) {
+		debugf1("%s() sysfs_attrib = %p\n",__func__, sysfs_attrib);
 		if (sysfs_attrib->grp) {
 			struct mcidev_sysfs_group_kobj *grp_kobj;
 
@@ -799,10 +797,9 @@
 			if (!grp_kobj)
 				return -ENOMEM;
 
-			list_add_tail(&grp_kobj->list, &mci->grp_kobj_list);
-
 			grp_kobj->grp = sysfs_attrib->grp;
 			grp_kobj->mci = mci;
+			list_add_tail(&grp_kobj->list, &mci->grp_kobj_list);
 
 			debugf0("%s() grp %s, mci %p\n", __func__,
 				sysfs_attrib->grp->name, mci);
@@ -811,26 +808,28 @@
 						&ktype_inst_grp,
 						&mci->edac_mci_kobj,
 						sysfs_attrib->grp->name);
-			if (err)
+			if (err < 0) {
+				printk(KERN_ERR "kobject_init_and_add failed: %d\n", err);
 				return err;
-
+			}
 			err = edac_create_mci_instance_attributes(mci,
 					grp_kobj->grp->mcidev_attr,
 					&grp_kobj->kobj);
 
-			if (err)
+			if (err < 0)
 				return err;
 		} else if (sysfs_attrib->attr.name) {
 			debugf0("%s() file %s\n", __func__,
 				sysfs_attrib->attr.name);
 
 			err = sysfs_create_file(kobj, &sysfs_attrib->attr);
+			if (err < 0) {
+				printk(KERN_ERR "sysfs_create_file failed: %d\n", err);
+				return err;
+			}
 		} else
 			break;
 
-		if (err) {
-			return err;
-		}
 		sysfs_attrib++;
 	}
 
@@ -843,7 +842,7 @@
  *	directory of this mci instance.
  */
 static void edac_remove_mci_instance_attributes(struct mem_ctl_info *mci,
-				struct mcidev_sysfs_attribute *sysfs_attrib,
+				const struct mcidev_sysfs_attribute *sysfs_attrib,
 				struct kobject *kobj, int count)
 {
 	struct mcidev_sysfs_group_kobj *grp_kobj, *tmp;
@@ -855,13 +854,24 @@
 	 * Remove first all the atributes
 	 */
 	while (sysfs_attrib) {
+		debugf1("%s() sysfs_attrib = %p\n",__func__, sysfs_attrib);
 		if (sysfs_attrib->grp) {
-			list_for_each_entry(grp_kobj, &mci->grp_kobj_list,
-					    list)
-				if (grp_kobj->grp == sysfs_attrib->grp)
+			debugf1("%s() seeking for group %s\n",
+				__func__, sysfs_attrib->grp->name);
+			list_for_each_entry(grp_kobj,
+					    &mci->grp_kobj_list, list) {
+				debugf1("%s() grp_kobj->grp = %p\n",__func__, grp_kobj->grp);
+				if (grp_kobj->grp == sysfs_attrib->grp) {
 					edac_remove_mci_instance_attributes(mci,
 						    grp_kobj->grp->mcidev_attr,
 						    &grp_kobj->kobj, count + 1);
+					debugf0("%s() group %s\n", __func__,
+						sysfs_attrib->grp->name);
+					kobject_put(&grp_kobj->kobj);
+				}
+			}
+			debugf1("%s() end of seeking for group %s\n",
+				__func__, sysfs_attrib->grp->name);
 		} else if (sysfs_attrib->attr.name) {
 			debugf0("%s() file %s\n", __func__,
 				sysfs_attrib->attr.name);
@@ -871,15 +881,14 @@
 		sysfs_attrib++;
 	}
 
-	/*
-	 * Now that all attributes got removed, it is save to remove all groups
-	 */
-	if (!count)
-		list_for_each_entry_safe(grp_kobj, tmp, &mci->grp_kobj_list,
-					 list) {
-			debugf0("%s() grp %s\n", __func__, grp_kobj->grp->name);
-			kobject_put(&grp_kobj->kobj);
-		}
+	/* Remove the group objects */
+	if (count)
+		return;
+	list_for_each_entry_safe(grp_kobj, tmp,
+				 &mci->grp_kobj_list, list) {
+		list_del(&grp_kobj->list);
+		kfree(grp_kobj);
+	}
 }
 
 
@@ -971,6 +980,7 @@
 	debugf0("%s()\n", __func__);
 
 	/* remove all csrow kobjects */
+	debugf0("%s()  unregister this mci kobj\n", __func__);
 	for (i = 0; i < mci->nr_csrows; i++) {
 		if (mci->csrows[i].nr_pages > 0) {
 			debugf0("%s()  unreg csrow-%d\n", __func__, i);
@@ -978,20 +988,20 @@
 		}
 	}
 
-	debugf0("%s()  remove_link\n", __func__);
+	/* remove this mci instance's attribtes */
+	if (mci->mc_driver_sysfs_attributes) {
+		debugf0("%s()  unregister mci private attributes\n", __func__);
+		edac_remove_mci_instance_attributes(mci,
+						mci->mc_driver_sysfs_attributes,
+						&mci->edac_mci_kobj, 0);
+	}
 
 	/* remove the symlink */
+	debugf0("%s()  remove_link\n", __func__);
 	sysfs_remove_link(&mci->edac_mci_kobj, EDAC_DEVICE_SYMLINK);
 
-	debugf0("%s()  remove_mci_instance\n", __func__);
-
-	/* remove this mci instance's attribtes */
-	edac_remove_mci_instance_attributes(mci,
-					    mci->mc_driver_sysfs_attributes,
-					    &mci->edac_mci_kobj, 0);
-	debugf0("%s()  unregister this mci kobj\n", __func__);
-
 	/* unregister this instance's kobject */
+	debugf0("%s()  remove_mci_instance\n", __func__);
 	kobject_put(&mci->edac_mci_kobj);
 }
 
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
index 0fd5b85..362861c 100644
--- a/drivers/edac/i7core_edac.c
+++ b/drivers/edac/i7core_edac.c
@@ -39,6 +39,14 @@
 
 #include "edac_core.h"
 
+/* Static vars */
+static LIST_HEAD(i7core_edac_list);
+static DEFINE_MUTEX(i7core_edac_lock);
+static int probed;
+
+static int use_pci_fixup;
+module_param(use_pci_fixup, int, 0444);
+MODULE_PARM_DESC(use_pci_fixup, "Enable PCI fixup to seek for hidden devices");
 /*
  * This is used for Nehalem-EP and Nehalem-EX devices, where the non-core
  * registers start at bus 255, and are not reported by BIOS.
@@ -212,8 +220,8 @@
 };
 
 struct pci_id_table {
-	struct pci_id_descr	*descr;
-	int			n_devs;
+	const struct pci_id_descr	*descr;
+	int				n_devs;
 };
 
 struct i7core_dev {
@@ -235,8 +243,6 @@
 	struct i7core_inject	inject;
 	struct i7core_channel	channel[NUM_CHANS];
 
-	int		channels; /* Number of active channels */
-
 	int		ce_count_available;
 	int 		csrow_map[NUM_CHANS][MAX_DIMMS];
 
@@ -261,22 +267,22 @@
 
 	/* Count indicator to show errors not got */
 	unsigned		mce_overrun;
-};
 
-/* Static vars */
-static LIST_HEAD(i7core_edac_list);
-static DEFINE_MUTEX(i7core_edac_lock);
+	/* Struct to control EDAC polling */
+	struct edac_pci_ctl_info *i7core_pci;
+};
 
 #define PCI_DESCR(device, function, device_id)	\
 	.dev = (device),			\
 	.func = (function),			\
 	.dev_id = (device_id)
 
-struct pci_id_descr pci_dev_descr_i7core_nehalem[] = {
+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) },
 
@@ -297,19 +303,9 @@
 	{ 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)  },
-
 };
 
-struct pci_id_descr pci_dev_descr_lynnfield[] = {
+static const struct pci_id_descr pci_dev_descr_lynnfield[] = {
 	{ PCI_DESCR( 3, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MCR)         },
 	{ PCI_DESCR( 3, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TAD)      },
 	{ PCI_DESCR( 3, 4, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TEST)     },
@@ -323,15 +319,9 @@
 	{ 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)     },
 };
 
-struct pci_id_descr pci_dev_descr_i7core_westmere[] = {
+static const struct pci_id_descr pci_dev_descr_i7core_westmere[] = {
 		/* Memory controller */
 	{ PCI_DESCR(3, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MCR_REV2)     },
 	{ PCI_DESCR(3, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TAD_REV2)  },
@@ -356,17 +346,14 @@
 	{ 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) { A, ARRAY_SIZE(A) }
-struct pci_id_table pci_dev_table[] = {
+#define PCI_ID_TABLE_ENTRY(A) { .descr=A, .n_devs = ARRAY_SIZE(A) }
+static const struct pci_id_table pci_dev_table[] = {
 	PCI_ID_TABLE_ENTRY(pci_dev_descr_i7core_nehalem),
 	PCI_ID_TABLE_ENTRY(pci_dev_descr_lynnfield),
 	PCI_ID_TABLE_ENTRY(pci_dev_descr_i7core_westmere),
+	{0,}			/* 0 terminated list. */
 };
 
 /*
@@ -378,8 +365,6 @@
 	{0,}			/* 0 terminated list. */
 };
 
-static struct edac_pci_ctl_info *i7core_pci;
-
 /****************************************************************************
 			Anciliary status routines
  ****************************************************************************/
@@ -442,6 +427,36 @@
 	return NULL;
 }
 
+static struct i7core_dev *alloc_i7core_dev(u8 socket,
+					   const struct pci_id_table *table)
+{
+	struct i7core_dev *i7core_dev;
+
+	i7core_dev = kzalloc(sizeof(*i7core_dev), GFP_KERNEL);
+	if (!i7core_dev)
+		return NULL;
+
+	i7core_dev->pdev = kzalloc(sizeof(*i7core_dev->pdev) * table->n_devs,
+				   GFP_KERNEL);
+	if (!i7core_dev->pdev) {
+		kfree(i7core_dev);
+		return NULL;
+	}
+
+	i7core_dev->socket = socket;
+	i7core_dev->n_devs = table->n_devs;
+	list_add_tail(&i7core_dev->list, &i7core_edac_list);
+
+	return i7core_dev;
+}
+
+static void free_i7core_dev(struct i7core_dev *i7core_dev)
+{
+	list_del(&i7core_dev->list);
+	kfree(i7core_dev->pdev);
+	kfree(i7core_dev);
+}
+
 /****************************************************************************
 			Memory check routines
  ****************************************************************************/
@@ -484,7 +499,7 @@
  * to add a fake description for csrows.
  * So, this driver is attributing one DIMM memory for one csrow.
  */
-static int i7core_get_active_channels(u8 socket, unsigned *channels,
+static int i7core_get_active_channels(const u8 socket, unsigned *channels,
 				      unsigned *csrows)
 {
 	struct pci_dev *pdev = NULL;
@@ -545,12 +560,13 @@
 	return 0;
 }
 
-static int get_dimm_config(struct mem_ctl_info *mci, int *csrow)
+static int get_dimm_config(const struct mem_ctl_info *mci)
 {
 	struct i7core_pvt *pvt = mci->pvt_info;
 	struct csrow_info *csr;
 	struct pci_dev *pdev;
 	int i, j;
+	int csrow = 0;
 	unsigned long last_page = 0;
 	enum edac_type mode;
 	enum mem_type mtype;
@@ -664,13 +680,9 @@
 				RANKOFFSET(dimm_dod[j]),
 				banks, ranks, rows, cols);
 
-#if PAGE_SHIFT > 20
-			npages = size >> (PAGE_SHIFT - 20);
-#else
-			npages = size << (20 - PAGE_SHIFT);
-#endif
+			npages = MiB_TO_PAGES(size);
 
-			csr = &mci->csrows[*csrow];
+			csr = &mci->csrows[csrow];
 			csr->first_page = last_page + 1;
 			last_page += npages;
 			csr->last_page = last_page;
@@ -678,13 +690,13 @@
 
 			csr->page_mask = 0;
 			csr->grain = 8;
-			csr->csrow_idx = *csrow;
+			csr->csrow_idx = csrow;
 			csr->nr_channels = 1;
 
 			csr->channels[0].chan_idx = i;
 			csr->channels[0].ce_count = 0;
 
-			pvt->csrow_map[i][j] = *csrow;
+			pvt->csrow_map[i][j] = csrow;
 
 			switch (banks) {
 			case 4:
@@ -703,7 +715,7 @@
 			csr->edac_mode = mode;
 			csr->mtype = mtype;
 
-			(*csrow)++;
+			csrow++;
 		}
 
 		pci_read_config_dword(pdev, MC_SAG_CH_0, &value[0]);
@@ -736,7 +748,7 @@
    we're disabling error injection on all write calls to the sysfs nodes that
    controls the error code injection.
  */
-static int disable_inject(struct mem_ctl_info *mci)
+static int disable_inject(const struct mem_ctl_info *mci)
 {
 	struct i7core_pvt *pvt = mci->pvt_info;
 
@@ -921,7 +933,7 @@
 DECLARE_ADDR_MATCH(page, 0x10000);
 DECLARE_ADDR_MATCH(col, 0x4000);
 
-static int write_and_test(struct pci_dev *dev, int where, u32 val)
+static int write_and_test(struct pci_dev *dev, const int where, const u32 val)
 {
 	u32 read;
 	int count;
@@ -1120,35 +1132,34 @@
  * Sysfs struct
  */
 
-
-static struct mcidev_sysfs_attribute i7core_addrmatch_attrs[] = {
+static const struct mcidev_sysfs_attribute i7core_addrmatch_attrs[] = {
 	ATTR_ADDR_MATCH(channel),
 	ATTR_ADDR_MATCH(dimm),
 	ATTR_ADDR_MATCH(rank),
 	ATTR_ADDR_MATCH(bank),
 	ATTR_ADDR_MATCH(page),
 	ATTR_ADDR_MATCH(col),
-	{ .attr = { .name = NULL } }
+	{ } /* End of list */
 };
 
-static struct mcidev_sysfs_group i7core_inject_addrmatch = {
+static const struct mcidev_sysfs_group i7core_inject_addrmatch = {
 	.name  = "inject_addrmatch",
 	.mcidev_attr = i7core_addrmatch_attrs,
 };
 
-static struct mcidev_sysfs_attribute i7core_udimm_counters_attrs[] = {
+static const struct mcidev_sysfs_attribute i7core_udimm_counters_attrs[] = {
 	ATTR_COUNTER(0),
 	ATTR_COUNTER(1),
 	ATTR_COUNTER(2),
 	{ .attr = { .name = NULL } }
 };
 
-static struct mcidev_sysfs_group i7core_udimm_counters = {
+static const struct mcidev_sysfs_group i7core_udimm_counters = {
 	.name  = "all_channel_counts",
 	.mcidev_attr = i7core_udimm_counters_attrs,
 };
 
-static struct mcidev_sysfs_attribute i7core_sysfs_attrs[] = {
+static const struct mcidev_sysfs_attribute i7core_sysfs_rdimm_attrs[] = {
 	{
 		.attr = {
 			.name = "inject_section",
@@ -1180,8 +1191,44 @@
 		.show  = i7core_inject_enable_show,
 		.store = i7core_inject_enable_store,
 	},
-	{ .attr = { .name = NULL } },	/* Reserved for udimm counters */
-	{ .attr = { .name = NULL } }
+	{ }	/* End of list */
+};
+
+static const struct mcidev_sysfs_attribute i7core_sysfs_udimm_attrs[] = {
+	{
+		.attr = {
+			.name = "inject_section",
+			.mode = (S_IRUGO | S_IWUSR)
+		},
+		.show  = i7core_inject_section_show,
+		.store = i7core_inject_section_store,
+	}, {
+		.attr = {
+			.name = "inject_type",
+			.mode = (S_IRUGO | S_IWUSR)
+		},
+		.show  = i7core_inject_type_show,
+		.store = i7core_inject_type_store,
+	}, {
+		.attr = {
+			.name = "inject_eccmask",
+			.mode = (S_IRUGO | S_IWUSR)
+		},
+		.show  = i7core_inject_eccmask_show,
+		.store = i7core_inject_eccmask_store,
+	}, {
+		.grp = &i7core_inject_addrmatch,
+	}, {
+		.attr = {
+			.name = "inject_enable",
+			.mode = (S_IRUGO | S_IWUSR)
+		},
+		.show  = i7core_inject_enable_show,
+		.store = i7core_inject_enable_store,
+	}, {
+		.grp = &i7core_udimm_counters,
+	},
+	{ }	/* End of list */
 };
 
 /****************************************************************************
@@ -1189,7 +1236,7 @@
  ****************************************************************************/
 
 /*
- *	i7core_put_devices	'put' all the devices that we have
+ *	i7core_put_all_devices	'put' all the devices that we have
  *				reserved via 'get'
  */
 static void i7core_put_devices(struct i7core_dev *i7core_dev)
@@ -1206,23 +1253,23 @@
 			PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
 		pci_dev_put(pdev);
 	}
-	kfree(i7core_dev->pdev);
-	list_del(&i7core_dev->list);
-	kfree(i7core_dev);
 }
 
 static void i7core_put_all_devices(void)
 {
 	struct i7core_dev *i7core_dev, *tmp;
 
-	list_for_each_entry_safe(i7core_dev, tmp, &i7core_edac_list, list)
+	list_for_each_entry_safe(i7core_dev, tmp, &i7core_edac_list, list) {
 		i7core_put_devices(i7core_dev);
+		free_i7core_dev(i7core_dev);
+	}
 }
 
-static void __init i7core_xeon_pci_fixup(struct pci_id_table *table)
+static void __init i7core_xeon_pci_fixup(const struct pci_id_table *table)
 {
 	struct pci_dev *pdev = NULL;
 	int i;
+
 	/*
 	 * On Xeon 55xx, the Intel Quckpath Arch Generic Non-core pci buses
 	 * aren't announced by acpi. So, we need to use a legacy scan probing
@@ -1257,16 +1304,18 @@
 }
 
 /*
- *	i7core_get_devices	Find and perform 'get' operation on the MCH's
+ *	i7core_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
  */
-int i7core_get_onedevice(struct pci_dev **prev, int devno,
-			 struct pci_id_descr *dev_descr, unsigned n_devs,
-			 unsigned last_bus)
+static int i7core_get_onedevice(struct pci_dev **prev,
+				const struct pci_id_table *table,
+				const unsigned devno,
+				const unsigned last_bus)
 {
 	struct i7core_dev *i7core_dev;
+	const struct pci_id_descr *dev_descr = &table->descr[devno];
 
 	struct pci_dev *pdev = NULL;
 	u8 bus = 0;
@@ -1275,20 +1324,6 @@
 	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;
@@ -1315,18 +1350,11 @@
 
 	i7core_dev = get_i7core_dev(socket);
 	if (!i7core_dev) {
-		i7core_dev = kzalloc(sizeof(*i7core_dev), GFP_KERNEL);
-		if (!i7core_dev)
-			return -ENOMEM;
-		i7core_dev->pdev = kzalloc(sizeof(*i7core_dev->pdev) * n_devs,
-					   GFP_KERNEL);
-		if (!i7core_dev->pdev) {
-			kfree(i7core_dev);
+		i7core_dev = alloc_i7core_dev(socket, table);
+		if (!i7core_dev) {
+			pci_dev_put(pdev);
 			return -ENOMEM;
 		}
-		i7core_dev->socket = socket;
-		i7core_dev->n_devs = n_devs;
-		list_add_tail(&i7core_dev->list, &i7core_edac_list);
 	}
 
 	if (i7core_dev->pdev[devno]) {
@@ -1368,27 +1396,31 @@
 		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 i7core_get_devices(struct pci_id_table *table)
+static int i7core_get_all_devices(void)
 {
 	int i, rc, last_bus;
 	struct pci_dev *pdev = NULL;
-	struct pci_id_descr *dev_descr;
+	const struct pci_id_table *table = pci_dev_table;
 
 	last_bus = i7core_pci_lastbus();
 
 	while (table && table->descr) {
-		dev_descr = table->descr;
 		for (i = 0; i < table->n_devs; i++) {
 			pdev = NULL;
 			do {
-				rc = i7core_get_onedevice(&pdev, i,
-							  &dev_descr[i],
-							  table->n_devs,
+				rc = i7core_get_onedevice(&pdev, table, i,
 							  last_bus);
 				if (rc < 0) {
 					if (i == 0) {
@@ -1404,7 +1436,6 @@
 	}
 
 	return 0;
-	return 0;
 }
 
 static int mci_bind_devs(struct mem_ctl_info *mci,
@@ -1414,10 +1445,6 @@
 	struct pci_dev *pdev;
 	int i, func, slot;
 
-	/* Associates i7core_dev and mci for future usage */
-	pvt->i7core_dev = i7core_dev;
-	i7core_dev->mci = mci;
-
 	pvt->is_registered = 0;
 	for (i = 0; i < i7core_dev->n_devs; i++) {
 		pdev = i7core_dev->pdev[i];
@@ -1448,15 +1475,6 @@
 			pvt->is_registered = 1;
 	}
 
-	/*
-	 * Add extra nodes to count errors on udimm
-	 * For registered memory, this is not needed, since the counters
-	 * are already displayed at the standard locations
-	 */
-	if (!pvt->is_registered)
-		i7core_sysfs_attrs[ARRAY_SIZE(i7core_sysfs_attrs)-2].grp =
-			&i7core_udimm_counters;
-
 	return 0;
 
 error:
@@ -1470,7 +1488,9 @@
 			Error check routines
  ****************************************************************************/
 static void i7core_rdimm_update_csrow(struct mem_ctl_info *mci,
-					 int chan, int dimm, int add)
+				      const int chan,
+				      const int dimm,
+				      const int add)
 {
 	char *msg;
 	struct i7core_pvt *pvt = mci->pvt_info;
@@ -1487,7 +1507,10 @@
 }
 
 static void i7core_rdimm_update_ce_count(struct mem_ctl_info *mci,
-			int chan, int new0, int new1, int new2)
+					 const int chan,
+					 const int new0,
+					 const int new1,
+					 const int new2)
 {
 	struct i7core_pvt *pvt = mci->pvt_info;
 	int add0 = 0, add1 = 0, add2 = 0;
@@ -1641,7 +1664,7 @@
  * fields
  */
 static void i7core_mce_output_error(struct mem_ctl_info *mci,
-				    struct mce *m)
+				    const struct mce *m)
 {
 	struct i7core_pvt *pvt = mci->pvt_info;
 	char *type, *optype, *err, *msg;
@@ -1845,28 +1868,85 @@
 	return 1;
 }
 
-static int i7core_register_mci(struct i7core_dev *i7core_dev,
-			       int num_channels, int num_csrows)
+static void i7core_pci_ctl_create(struct i7core_pvt *pvt)
+{
+	pvt->i7core_pci = edac_pci_create_generic_ctl(
+						&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");
+}
+
+static void i7core_pci_ctl_release(struct i7core_pvt *pvt)
+{
+	if (likely(pvt->i7core_pci))
+		edac_pci_release_generic_ctl(pvt->i7core_pci);
+	else
+		i7core_printk(KERN_ERR,
+				"Couldn't find mem_ctl_info for socket %d\n",
+				pvt->i7core_dev->socket);
+	pvt->i7core_pci = NULL;
+}
+
+static void i7core_unregister_mci(struct i7core_dev *i7core_dev)
+{
+	struct mem_ctl_info *mci = i7core_dev->mci;
+	struct i7core_pvt *pvt;
+
+	if (unlikely(!mci || !mci->pvt_info)) {
+		debugf0("MC: " __FILE__ ": %s(): dev = %p\n",
+			__func__, &i7core_dev->pdev[0]->dev);
+
+		i7core_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, &i7core_dev->pdev[0]->dev);
+
+	/* Disable MCE NMI handler */
+	edac_mce_unregister(&pvt->edac_mce);
+
+	/* Disable EDAC polling */
+	i7core_pci_ctl_release(pvt);
+
+	/* 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);
+	i7core_dev->mci = NULL;
+}
+
+static int i7core_register_mci(struct i7core_dev *i7core_dev)
 {
 	struct mem_ctl_info *mci;
 	struct i7core_pvt *pvt;
-	int csrow = 0;
-	int rc;
+	int rc, channels, csrows;
+
+	/* Check the number of active and not disabled channels */
+	rc = i7core_get_active_channels(i7core_dev->socket, &channels, &csrows);
+	if (unlikely(rc < 0))
+		return rc;
 
 	/* allocate a new MC control structure */
-	mci = edac_mc_alloc(sizeof(*pvt), num_csrows, num_channels,
-			    i7core_dev->socket);
+	mci = edac_mc_alloc(sizeof(*pvt), csrows, channels, i7core_dev->socket);
 	if (unlikely(!mci))
 		return -ENOMEM;
 
-	debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci);
-
-	/* record ptr to the generic device */
-	mci->dev = &i7core_dev->pdev[0]->dev;
+	debugf0("MC: " __FILE__ ": %s(): mci = %p, dev = %p\n",
+		__func__, mci, &i7core_dev->pdev[0]->dev);
 
 	pvt = mci->pvt_info;
 	memset(pvt, 0, sizeof(*pvt));
 
+	/* Associates i7core_dev and mci for future usage */
+	pvt->i7core_dev = i7core_dev;
+	i7core_dev->mci = mci;
+
 	/*
 	 * FIXME: how to handle RDDR3 at MCI level? It is possible to have
 	 * Mixed RDDR3/UDDR3 with Nehalem, provided that they are on different
@@ -1881,17 +1961,23 @@
 				  i7core_dev->socket);
 	mci->dev_name = pci_name(i7core_dev->pdev[0]);
 	mci->ctl_page_to_phys = NULL;
-	mci->mc_driver_sysfs_attributes = i7core_sysfs_attrs;
-	/* Set the function pointer to an actual operation function */
-	mci->edac_check = i7core_check_error;
 
 	/* Store pci devices at mci for faster access */
 	rc = mci_bind_devs(mci, i7core_dev);
 	if (unlikely(rc < 0))
-		goto fail;
+		goto fail0;
+
+	if (pvt->is_registered)
+		mci->mc_driver_sysfs_attributes = i7core_sysfs_rdimm_attrs;
+	else
+		mci->mc_driver_sysfs_attributes = i7core_sysfs_udimm_attrs;
 
 	/* Get dimm basic config */
-	get_dimm_config(mci, &csrow);
+	get_dimm_config(mci);
+	/* record ptr to the generic device */
+	mci->dev = &i7core_dev->pdev[0]->dev;
+	/* Set the function pointer to an actual operation function */
+	mci->edac_check = i7core_check_error;
 
 	/* add this new MC control structure to EDAC's list of MCs */
 	if (unlikely(edac_mc_add_mc(mci))) {
@@ -1902,19 +1988,7 @@
 		 */
 
 		rc = -EINVAL;
-		goto fail;
-	}
-
-	/* allocating generic PCI control info */
-	i7core_pci = edac_pci_create_generic_ctl(&i7core_dev->pdev[0]->dev,
-						 EDAC_MOD_STR);
-	if (unlikely(!i7core_pci)) {
-		printk(KERN_WARNING
-			"%s(): Unable to create PCI control\n",
-			__func__);
-		printk(KERN_WARNING
-			"%s(): PCI error report via EDAC not setup\n",
-			__func__);
+		goto fail0;
 	}
 
 	/* Default error mask is any memory */
@@ -1925,19 +1999,28 @@
 	pvt->inject.page = -1;
 	pvt->inject.col = -1;
 
+	/* 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;
 	}
 
-fail:
-	if (rc < 0)
-		edac_mc_free(mci);
+	return 0;
+
+fail1:
+	i7core_pci_ctl_release(pvt);
+	edac_mc_del_mc(mci->dev);
+fail0:
+	kfree(mci->ctl_name);
+	edac_mc_free(mci);
+	i7core_dev->mci = NULL;
 	return rc;
 }
 
@@ -1949,8 +2032,6 @@
  *		< 0 for error code
  */
 
-static int probed = 0;
-
 static int __devinit i7core_probe(struct pci_dev *pdev,
 				  const struct pci_device_id *id)
 {
@@ -1965,25 +2046,16 @@
 	 */
 	if (unlikely(probed >= 1)) {
 		mutex_unlock(&i7core_edac_lock);
-		return -EINVAL;
+		return -ENODEV;
 	}
 	probed++;
 
-	rc = i7core_get_devices(pci_dev_table);
+	rc = i7core_get_all_devices();
 	if (unlikely(rc < 0))
 		goto fail0;
 
 	list_for_each_entry(i7core_dev, &i7core_edac_list, list) {
-		int channels;
-		int csrows;
-
-		/* Check the number of active and not disabled channels */
-		rc = i7core_get_active_channels(i7core_dev->socket,
-						&channels, &csrows);
-		if (unlikely(rc < 0))
-			goto fail1;
-
-		rc = i7core_register_mci(i7core_dev, channels, csrows);
+		rc = i7core_register_mci(i7core_dev);
 		if (unlikely(rc < 0))
 			goto fail1;
 	}
@@ -1994,6 +2066,9 @@
 	return 0;
 
 fail1:
+	list_for_each_entry(i7core_dev, &i7core_edac_list, list)
+		i7core_unregister_mci(i7core_dev);
+
 	i7core_put_all_devices();
 fail0:
 	mutex_unlock(&i7core_edac_lock);
@@ -2006,14 +2081,10 @@
  */
 static void __devexit i7core_remove(struct pci_dev *pdev)
 {
-	struct mem_ctl_info *mci;
-	struct i7core_dev *i7core_dev, *tmp;
+	struct i7core_dev *i7core_dev;
 
 	debugf0(__FILE__ ": %s()\n", __func__);
 
-	if (i7core_pci)
-		edac_pci_release_generic_ctl(i7core_pci);
-
 	/*
 	 * 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
@@ -2023,22 +2094,18 @@
 	 */
 
 	mutex_lock(&i7core_edac_lock);
-	list_for_each_entry_safe(i7core_dev, tmp, &i7core_edac_list, list) {
-		mci = edac_mc_del_mc(&i7core_dev->pdev[0]->dev);
-		if (mci) {
-			struct i7core_pvt *pvt = mci->pvt_info;
 
-			i7core_dev = pvt->i7core_dev;
-			edac_mce_unregister(&pvt->edac_mce);
-			kfree(mci->ctl_name);
-			edac_mc_free(mci);
-			i7core_put_devices(i7core_dev);
-		} else {
-			i7core_printk(KERN_ERR,
-				      "Couldn't find mci for socket %d\n",
-				      i7core_dev->socket);
-		}
+	if (unlikely(!probed)) {
+		mutex_unlock(&i7core_edac_lock);
+		return;
 	}
+
+	list_for_each_entry(i7core_dev, &i7core_edac_list, list)
+		i7core_unregister_mci(i7core_dev);
+
+	/* Release PCI resources */
+	i7core_put_all_devices();
+
 	probed--;
 
 	mutex_unlock(&i7core_edac_lock);
@@ -2070,7 +2137,8 @@
 	/* Ensure that the OPSTATE is set correctly for POLL or NMI */
 	opstate_init();
 
-	i7core_xeon_pci_fixup(pci_dev_table);
+	if (use_pci_fixup)
+		i7core_xeon_pci_fixup(pci_dev_table);
 
 	pci_rc = pci_register_driver(&i7core_driver);
 
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c
index a2b12aa..5018666 100644
--- a/drivers/gpio/pca953x.c
+++ b/drivers/gpio/pca953x.c
@@ -345,7 +345,7 @@
 
 	do {
 		level = __ffs(pending);
-		handle_nested_irq(level + chip->irq_base);
+		generic_handle_irq(level + chip->irq_base);
 
 		pending &= ~(1 << level);
 	} while (pending);
@@ -360,7 +360,8 @@
 	struct pca953x_platform_data *pdata = client->dev.platform_data;
 	int ret;
 
-	if (pdata->irq_base && (id->driver_data & PCA953X_INT)) {
+	if (pdata->irq_base != -1
+			&& (id->driver_data & PCA953X_INT)) {
 		int lvl;
 
 		ret = pca953x_read_reg(chip, PCA953X_INPUT,
@@ -383,7 +384,6 @@
 			set_irq_chip_data(irq, chip);
 			set_irq_chip_and_handler(irq, &pca953x_irq_chip,
 						 handle_edge_irq);
-			set_irq_nested_thread(irq, 1);
 #ifdef CONFIG_ARM
 			set_irq_flags(irq, IRQF_VALID);
 #else
@@ -394,6 +394,7 @@
 		ret = request_threaded_irq(client->irq,
 					   NULL,
 					   pca953x_irq_handler,
+					   IRQF_TRIGGER_RISING |
 					   IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
 					   dev_name(&client->dev), chip);
 		if (ret) {
@@ -408,13 +409,13 @@
 	return 0;
 
 out_failed:
-	chip->irq_base = 0;
+	chip->irq_base = -1;
 	return ret;
 }
 
 static void pca953x_irq_teardown(struct pca953x_chip *chip)
 {
-	if (chip->irq_base)
+	if (chip->irq_base != -1)
 		free_irq(chip->client->irq, chip);
 }
 #else /* CONFIG_GPIO_PCA953X_IRQ */
@@ -424,7 +425,7 @@
 	struct i2c_client *client = chip->client;
 	struct pca953x_platform_data *pdata = client->dev.platform_data;
 
-	if (pdata->irq_base && (id->driver_data & PCA953X_INT))
+	if (pdata->irq_base != -1 && (id->driver_data & PCA953X_INT))
 		dev_warn(&client->dev, "interrupt support not compiled in\n");
 
 	return 0;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 90b1d67..eb6c473c 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -155,11 +155,11 @@
 	char __iomem *vaddr;
 	int unwritten;
 
-	vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT], KM_USER0);
+	vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT]);
 	if (vaddr == NULL)
 		return -ENOMEM;
 	unwritten = __copy_to_user_inatomic(data, vaddr + page_offset, length);
-	kunmap_atomic(vaddr, KM_USER0);
+	kunmap_atomic(vaddr);
 
 	if (unwritten)
 		return -EFAULT;
@@ -509,10 +509,10 @@
 	char *vaddr_atomic;
 	unsigned long unwritten;
 
-	vaddr_atomic = io_mapping_map_atomic_wc(mapping, page_base, KM_USER0);
+	vaddr_atomic = io_mapping_map_atomic_wc(mapping, page_base);
 	unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + page_offset,
 						      user_data, length);
-	io_mapping_unmap_atomic(vaddr_atomic, KM_USER0);
+	io_mapping_unmap_atomic(vaddr_atomic);
 	if (unwritten)
 		return -EFAULT;
 	return 0;
@@ -551,11 +551,11 @@
 	char __iomem *vaddr;
 	unsigned long unwritten;
 
-	vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT], KM_USER0);
+	vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT]);
 	if (vaddr == NULL)
 		return -ENOMEM;
 	unwritten = __copy_from_user_inatomic(vaddr + page_offset, data, length);
-	kunmap_atomic(vaddr, KM_USER0);
+	kunmap_atomic(vaddr);
 
 	if (unwritten)
 		return -EFAULT;
@@ -3346,8 +3346,7 @@
 		reloc_offset = obj_priv->gtt_offset + reloc->offset;
 		reloc_page = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping,
 						      (reloc_offset &
-						       ~(PAGE_SIZE - 1)),
-						      KM_USER0);
+						       ~(PAGE_SIZE - 1)));
 		reloc_entry = (uint32_t __iomem *)(reloc_page +
 						   (reloc_offset & (PAGE_SIZE - 1)));
 		reloc_val = target_obj_priv->gtt_offset + reloc->delta;
@@ -3358,7 +3357,7 @@
 			  readl(reloc_entry), reloc_val);
 #endif
 		writel(reloc_val, reloc_entry);
-		io_mapping_unmap_atomic(reloc_page, KM_USER0);
+		io_mapping_unmap_atomic(reloc_page);
 
 		/* The updated presumed offset for this entry will be
 		 * copied back out to the user.
@@ -4772,11 +4771,11 @@
 	page_count = obj->size / PAGE_SIZE;
 
 	for (i = 0; i < page_count; i++) {
-		char *dst = kmap_atomic(obj_priv->pages[i], KM_USER0);
+		char *dst = kmap_atomic(obj_priv->pages[i]);
 		char *src = obj_priv->phys_obj->handle->vaddr + (i * PAGE_SIZE);
 
 		memcpy(dst, src, PAGE_SIZE);
-		kunmap_atomic(dst, KM_USER0);
+		kunmap_atomic(dst);
 	}
 	drm_clflush_pages(obj_priv->pages, page_count);
 	drm_agp_chipset_flush(dev);
@@ -4833,11 +4832,11 @@
 	page_count = obj->size / PAGE_SIZE;
 
 	for (i = 0; i < page_count; i++) {
-		char *src = kmap_atomic(obj_priv->pages[i], KM_USER0);
+		char *src = kmap_atomic(obj_priv->pages[i]);
 		char *dst = obj_priv->phys_obj->handle->vaddr + (i * PAGE_SIZE);
 
 		memcpy(dst, src, PAGE_SIZE);
-		kunmap_atomic(src, KM_USER0);
+		kunmap_atomic(src);
 	}
 
 	i915_gem_object_put_pages(obj);
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 744225e..b80010f 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -456,10 +456,9 @@
 
 		local_irq_save(flags);
 		s = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping,
-					     reloc_offset,
-					     KM_IRQ0);
+					     reloc_offset);
 		memcpy_fromio(d, s, PAGE_SIZE);
-		io_mapping_unmap_atomic(s, KM_IRQ0);
+		io_mapping_unmap_atomic(s);
 		local_irq_restore(flags);
 
 		dst->pages[page] = d;
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index 1d306a4..3264bbd 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -187,8 +187,7 @@
 
 	if (OVERLAY_NONPHYSICAL(overlay->dev)) {
 		regs = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping,
-						overlay->reg_bo->gtt_offset,
-						KM_USER0);
+						overlay->reg_bo->gtt_offset);
 
 		if (!regs) {
 			DRM_ERROR("failed to map overlay regs in GTT\n");
@@ -203,7 +202,7 @@
 static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay)
 {
 	if (OVERLAY_NONPHYSICAL(overlay->dev))
-		io_mapping_unmap_atomic(overlay->virt_addr, KM_USER0);
+		io_mapping_unmap_atomic(overlay->virt_addr);
 
 	overlay->virt_addr = NULL;
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index 974b0f8..8fa3396 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -2167,11 +2167,11 @@
 
 	if (off < pci_resource_len(dev->pdev, 1)) {
 		uint8_t __iomem *p =
-			io_mapping_map_atomic_wc(fb, off & PAGE_MASK, KM_USER0);
+			io_mapping_map_atomic_wc(fb, off & PAGE_MASK);
 
 		val = ioread32(p + (off & ~PAGE_MASK));
 
-		io_mapping_unmap_atomic(p, KM_USER0);
+		io_mapping_unmap_atomic(p);
 	}
 
 	return val;
@@ -2183,12 +2183,12 @@
 {
 	if (off < pci_resource_len(dev->pdev, 1)) {
 		uint8_t __iomem *p =
-			io_mapping_map_atomic_wc(fb, off & PAGE_MASK, KM_USER0);
+			io_mapping_map_atomic_wc(fb, off & PAGE_MASK);
 
 		iowrite32(val, p + (off & ~PAGE_MASK));
 		wmb();
 
-		io_mapping_unmap_atomic(p, KM_USER0);
+		io_mapping_unmap_atomic(p);
 	}
 }
 
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c
index 3451a82..e8a73e6 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
@@ -170,7 +170,7 @@
 	src = (void *)((unsigned long)src + (page << PAGE_SHIFT));
 
 #ifdef CONFIG_X86
-	dst = kmap_atomic_prot(d, KM_USER0, prot);
+	dst = kmap_atomic_prot(d, prot);
 #else
 	if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL))
 		dst = vmap(&d, 1, 0, prot);
@@ -183,7 +183,7 @@
 	memcpy_fromio(dst, src, PAGE_SIZE);
 
 #ifdef CONFIG_X86
-	kunmap_atomic(dst, KM_USER0);
+	kunmap_atomic(dst);
 #else
 	if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL))
 		vunmap(dst);
@@ -206,7 +206,7 @@
 
 	dst = (void *)((unsigned long)dst + (page << PAGE_SHIFT));
 #ifdef CONFIG_X86
-	src = kmap_atomic_prot(s, KM_USER0, prot);
+	src = kmap_atomic_prot(s, prot);
 #else
 	if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL))
 		src = vmap(&s, 1, 0, prot);
@@ -219,7 +219,7 @@
 	memcpy_toio(dst, src, PAGE_SIZE);
 
 #ifdef CONFIG_X86
-	kunmap_atomic(src, KM_USER0);
+	kunmap_atomic(src);
 #else
 	if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL))
 		vunmap(src);
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index e382da3..c357c83 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -399,6 +399,15 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called gl520sm.
 
+config SENSORS_GPIO_FAN
+	tristate "GPIO fan"
+	depends on GENERIC_GPIO
+	help
+	  If you say yes here you get support for fans connected to GPIO lines.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called gpio-fan.
+
 config SENSORS_CORETEMP
 	tristate "Intel Core/Core2/Atom temperature sensor"
 	depends on X86 && PCI && EXPERIMENTAL
@@ -654,6 +663,17 @@
 	  This driver can also be built as a module. If so, the module will
 	  be called ltc4245.
 
+config SENSORS_LTC4261
+	tristate "Linear Technology LTC4261"
+	depends on I2C && EXPERIMENTAL
+	default n
+	help
+	  If you say yes here you get support for Linear Technology LTC4261
+	  Negative Voltage Hot Swap Controller I2C interface.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called ltc4261.
+
 config SENSORS_LM95241
 	tristate "National Semiconductor LM95241 sensor chip"
 	depends on I2C
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index ec9cb73..d30f0f6 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -51,6 +51,7 @@
 obj-$(CONFIG_SENSORS_G760A)	+= g760a.o
 obj-$(CONFIG_SENSORS_GL518SM)	+= gl518sm.o
 obj-$(CONFIG_SENSORS_GL520SM)	+= gl520sm.o
+obj-$(CONFIG_SENSORS_GPIO_FAN)	+= gpio-fan.o
 obj-$(CONFIG_SENSORS_ULTRA45)	+= ultra45_env.o
 obj-$(CONFIG_SENSORS_I5K_AMB)	+= i5k_amb.o
 obj-$(CONFIG_SENSORS_IBMAEM)	+= ibmaem.o
@@ -79,6 +80,7 @@
 obj-$(CONFIG_SENSORS_LM95241)	+= lm95241.o
 obj-$(CONFIG_SENSORS_LTC4215)	+= ltc4215.o
 obj-$(CONFIG_SENSORS_LTC4245)	+= ltc4245.o
+obj-$(CONFIG_SENSORS_LTC4261)	+= ltc4261.o
 obj-$(CONFIG_SENSORS_MAX1111)	+= max1111.o
 obj-$(CONFIG_SENSORS_MAX1619)	+= max1619.o
 obj-$(CONFIG_SENSORS_MAX6650)	+= max6650.o
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index a23b17a..42de98d 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -21,7 +21,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/jiffies.h>
@@ -280,11 +279,9 @@
 	case 0x1a:
 		dev_warn(dev, "TjMax is assumed as 100 C!\n");
 		return 100000;
-		break;
 	case 0x17:
 	case 0x1c:		/* Atom CPUs */
 		return adjust_tjmax(c, id, dev);
-		break;
 	default:
 		dev_warn(dev, "CPU (model=0x%x) is not supported yet,"
 			" using default TjMax of 100C.\n", c->x86_model);
@@ -292,6 +289,15 @@
 	}
 }
 
+static void __devinit get_ucode_rev_on_cpu(void *edx)
+{
+	u32 eax;
+
+	wrmsr(MSR_IA32_UCODE_REV, 0, 0);
+	sync_core();
+	rdmsr(MSR_IA32_UCODE_REV, eax, *(u32 *)edx);
+}
+
 static int __devinit coretemp_probe(struct platform_device *pdev)
 {
 	struct coretemp_data *data;
@@ -327,8 +333,15 @@
 
 	if ((c->x86_model == 0xe) && (c->x86_mask < 0xc)) {
 		/* check for microcode update */
-		rdmsr_on_cpu(data->id, MSR_IA32_UCODE_REV, &eax, &edx);
-		if (edx < 0x39) {
+		err = smp_call_function_single(data->id, get_ucode_rev_on_cpu,
+					       &edx, 1);
+		if (err) {
+			dev_err(&pdev->dev,
+				"Cannot determine microcode revision of "
+				"CPU#%u (%d)!\n", data->id, err);
+			err = -ENODEV;
+			goto exit_free;
+		} else if (edx < 0x39) {
 			err = -ENODEV;
 			dev_err(&pdev->dev,
 				"Errata AE18 not fixed, update BIOS or "
@@ -490,7 +503,7 @@
 	return err;
 }
 
-static void coretemp_device_remove(unsigned int cpu)
+static void __cpuinit coretemp_device_remove(unsigned int cpu)
 {
 	struct pdev_entry *p;
 	unsigned int i;
@@ -569,9 +582,8 @@
 static void __exit coretemp_exit(void)
 {
 	struct pdev_entry *p, *n;
-#ifdef CONFIG_HOTPLUG_CPU
+
 	unregister_hotcpu_notifier(&coretemp_cpu_notifier);
-#endif
 	mutex_lock(&pdev_list_mutex);
 	list_for_each_entry_safe(p, n, &pdev_list, list) {
 		platform_device_unregister(p->pdev);
diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c
new file mode 100644
index 0000000..aa701a1
--- /dev/null
+++ b/drivers/hwmon/gpio-fan.c
@@ -0,0 +1,558 @@
+/*
+ * gpio-fan.c - Hwmon driver for fans connected to GPIO lines.
+ *
+ * Copyright (C) 2010 LaCie
+ *
+ * Author: Simon Guinot <sguinot@lacie.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/hwmon.h>
+#include <linux/gpio.h>
+#include <linux/gpio-fan.h>
+
+struct gpio_fan_data {
+	struct platform_device	*pdev;
+	struct device		*hwmon_dev;
+	struct mutex		lock; /* lock GPIOs operations. */
+	int			num_ctrl;
+	unsigned		*ctrl;
+	int			num_speed;
+	struct gpio_fan_speed	*speed;
+	int			speed_index;
+#ifdef CONFIG_PM
+	int			resume_speed;
+#endif
+	bool			pwm_enable;
+	struct gpio_fan_alarm	*alarm;
+	struct work_struct	alarm_work;
+};
+
+/*
+ * Alarm GPIO.
+ */
+
+static void fan_alarm_notify(struct work_struct *ws)
+{
+	struct gpio_fan_data *fan_data =
+		container_of(ws, struct gpio_fan_data, alarm_work);
+
+	sysfs_notify(&fan_data->pdev->dev.kobj, NULL, "fan1_alarm");
+	kobject_uevent(&fan_data->pdev->dev.kobj, KOBJ_CHANGE);
+}
+
+static irqreturn_t fan_alarm_irq_handler(int irq, void *dev_id)
+{
+	struct gpio_fan_data *fan_data = dev_id;
+
+	schedule_work(&fan_data->alarm_work);
+
+	return IRQ_NONE;
+}
+
+static ssize_t show_fan_alarm(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
+	struct gpio_fan_alarm *alarm = fan_data->alarm;
+	int value = gpio_get_value(alarm->gpio);
+
+	if (alarm->active_low)
+		value = !value;
+
+	return sprintf(buf, "%d\n", value);
+}
+
+static DEVICE_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL);
+
+static int fan_alarm_init(struct gpio_fan_data *fan_data,
+			  struct gpio_fan_alarm *alarm)
+{
+	int err;
+	int alarm_irq;
+	struct platform_device *pdev = fan_data->pdev;
+
+	fan_data->alarm = alarm;
+
+	err = gpio_request(alarm->gpio, "GPIO fan alarm");
+	if (err)
+		return err;
+
+	err = gpio_direction_input(alarm->gpio);
+	if (err)
+		goto err_free_gpio;
+
+	err = device_create_file(&pdev->dev, &dev_attr_fan1_alarm);
+	if (err)
+		goto err_free_gpio;
+
+	/*
+	 * If the alarm GPIO don't support interrupts, just leave
+	 * without initializing the fail notification support.
+	 */
+	alarm_irq = gpio_to_irq(alarm->gpio);
+	if (alarm_irq < 0)
+		return 0;
+
+	INIT_WORK(&fan_data->alarm_work, fan_alarm_notify);
+	set_irq_type(alarm_irq, IRQ_TYPE_EDGE_BOTH);
+	err = request_irq(alarm_irq, fan_alarm_irq_handler, IRQF_SHARED,
+			  "GPIO fan alarm", fan_data);
+	if (err)
+		goto err_free_sysfs;
+
+	return 0;
+
+err_free_sysfs:
+	device_remove_file(&pdev->dev, &dev_attr_fan1_alarm);
+err_free_gpio:
+	gpio_free(alarm->gpio);
+
+	return err;
+}
+
+static void fan_alarm_free(struct gpio_fan_data *fan_data)
+{
+	struct platform_device *pdev = fan_data->pdev;
+	int alarm_irq = gpio_to_irq(fan_data->alarm->gpio);
+
+	if (alarm_irq >= 0)
+		free_irq(alarm_irq, fan_data);
+	device_remove_file(&pdev->dev, &dev_attr_fan1_alarm);
+	gpio_free(fan_data->alarm->gpio);
+}
+
+/*
+ * Control GPIOs.
+ */
+
+/* Must be called with fan_data->lock held, except during initialization. */
+static void __set_fan_ctrl(struct gpio_fan_data *fan_data, int ctrl_val)
+{
+	int i;
+
+	for (i = 0; i < fan_data->num_ctrl; i++)
+		gpio_set_value(fan_data->ctrl[i], (ctrl_val >> i) & 1);
+}
+
+static int __get_fan_ctrl(struct gpio_fan_data *fan_data)
+{
+	int i;
+	int ctrl_val = 0;
+
+	for (i = 0; i < fan_data->num_ctrl; i++) {
+		int value;
+
+		value = gpio_get_value(fan_data->ctrl[i]);
+		ctrl_val |= (value << i);
+	}
+	return ctrl_val;
+}
+
+/* Must be called with fan_data->lock held, except during initialization. */
+static void set_fan_speed(struct gpio_fan_data *fan_data, int speed_index)
+{
+	if (fan_data->speed_index == speed_index)
+		return;
+
+	__set_fan_ctrl(fan_data, fan_data->speed[speed_index].ctrl_val);
+	fan_data->speed_index = speed_index;
+}
+
+static int get_fan_speed_index(struct gpio_fan_data *fan_data)
+{
+	int ctrl_val = __get_fan_ctrl(fan_data);
+	int i;
+
+	for (i = 0; i < fan_data->num_speed; i++)
+		if (fan_data->speed[i].ctrl_val == ctrl_val)
+			return i;
+
+	dev_warn(&fan_data->pdev->dev,
+		 "missing speed array entry for GPIO value 0x%x\n", ctrl_val);
+
+	return -EINVAL;
+}
+
+static int rpm_to_speed_index(struct gpio_fan_data *fan_data, int rpm)
+{
+	struct gpio_fan_speed *speed = fan_data->speed;
+	int i;
+
+	for (i = 0; i < fan_data->num_speed; i++)
+		if (speed[i].rpm >= rpm)
+			return i;
+
+	return fan_data->num_speed - 1;
+}
+
+static ssize_t show_pwm(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
+	u8 pwm = fan_data->speed_index * 255 / (fan_data->num_speed - 1);
+
+	return sprintf(buf, "%d\n", pwm);
+}
+
+static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
+		       const char *buf, size_t count)
+{
+	struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
+	unsigned long pwm;
+	int speed_index;
+	int ret = count;
+
+	if (strict_strtoul(buf, 10, &pwm) || pwm > 255)
+		return -EINVAL;
+
+	mutex_lock(&fan_data->lock);
+
+	if (!fan_data->pwm_enable) {
+		ret = -EPERM;
+		goto exit_unlock;
+	}
+
+	speed_index = DIV_ROUND_UP(pwm * (fan_data->num_speed - 1), 255);
+	set_fan_speed(fan_data, speed_index);
+
+exit_unlock:
+	mutex_unlock(&fan_data->lock);
+
+	return ret;
+}
+
+static ssize_t show_pwm_enable(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n", fan_data->pwm_enable);
+}
+
+static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
+	unsigned long val;
+
+	if (strict_strtoul(buf, 10, &val) || val > 1)
+		return -EINVAL;
+
+	if (fan_data->pwm_enable == val)
+		return count;
+
+	mutex_lock(&fan_data->lock);
+
+	fan_data->pwm_enable = val;
+
+	/* Disable manual control mode: set fan at full speed. */
+	if (val == 0)
+		set_fan_speed(fan_data, fan_data->num_speed - 1);
+
+	mutex_unlock(&fan_data->lock);
+
+	return count;
+}
+
+static ssize_t show_pwm_mode(struct device *dev,
+			     struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "0\n");
+}
+
+static ssize_t show_rpm_min(struct device *dev,
+			    struct device_attribute *attr, char *buf)
+{
+	struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n", fan_data->speed[0].rpm);
+}
+
+static ssize_t show_rpm_max(struct device *dev,
+			    struct device_attribute *attr, char *buf)
+{
+	struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n",
+		       fan_data->speed[fan_data->num_speed - 1].rpm);
+}
+
+static ssize_t show_rpm(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n", fan_data->speed[fan_data->speed_index].rpm);
+}
+
+static ssize_t set_rpm(struct device *dev, struct device_attribute *attr,
+		       const char *buf, size_t count)
+{
+	struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
+	unsigned long rpm;
+	int ret = count;
+
+	if (strict_strtoul(buf, 10, &rpm))
+		return -EINVAL;
+
+	mutex_lock(&fan_data->lock);
+
+	if (!fan_data->pwm_enable) {
+		ret = -EPERM;
+		goto exit_unlock;
+	}
+
+	set_fan_speed(fan_data, rpm_to_speed_index(fan_data, rpm));
+
+exit_unlock:
+	mutex_unlock(&fan_data->lock);
+
+	return ret;
+}
+
+static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm);
+static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
+		   show_pwm_enable, set_pwm_enable);
+static DEVICE_ATTR(pwm1_mode, S_IRUGO, show_pwm_mode, NULL);
+static DEVICE_ATTR(fan1_min, S_IRUGO, show_rpm_min, NULL);
+static DEVICE_ATTR(fan1_max, S_IRUGO, show_rpm_max, NULL);
+static DEVICE_ATTR(fan1_input, S_IRUGO, show_rpm, NULL);
+static DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR, show_rpm, set_rpm);
+
+static struct attribute *gpio_fan_ctrl_attributes[] = {
+	&dev_attr_pwm1.attr,
+	&dev_attr_pwm1_enable.attr,
+	&dev_attr_pwm1_mode.attr,
+	&dev_attr_fan1_input.attr,
+	&dev_attr_fan1_target.attr,
+	&dev_attr_fan1_min.attr,
+	&dev_attr_fan1_max.attr,
+	NULL
+};
+
+static const struct attribute_group gpio_fan_ctrl_group = {
+	.attrs = gpio_fan_ctrl_attributes,
+};
+
+static int fan_ctrl_init(struct gpio_fan_data *fan_data,
+			 struct gpio_fan_platform_data *pdata)
+{
+	struct platform_device *pdev = fan_data->pdev;
+	int num_ctrl = pdata->num_ctrl;
+	unsigned *ctrl = pdata->ctrl;
+	int i, err;
+
+	for (i = 0; i < num_ctrl; i++) {
+		err = gpio_request(ctrl[i], "GPIO fan control");
+		if (err)
+			goto err_free_gpio;
+
+		err = gpio_direction_output(ctrl[i], gpio_get_value(ctrl[i]));
+		if (err) {
+			gpio_free(ctrl[i]);
+			goto err_free_gpio;
+		}
+	}
+
+	err = sysfs_create_group(&pdev->dev.kobj, &gpio_fan_ctrl_group);
+	if (err)
+		goto err_free_gpio;
+
+	fan_data->num_ctrl = num_ctrl;
+	fan_data->ctrl = ctrl;
+	fan_data->num_speed = pdata->num_speed;
+	fan_data->speed = pdata->speed;
+	fan_data->pwm_enable = true; /* Enable manual fan speed control. */
+	fan_data->speed_index = get_fan_speed_index(fan_data);
+	if (fan_data->speed_index < 0) {
+		err = -ENODEV;
+		goto err_free_gpio;
+	}
+
+	return 0;
+
+err_free_gpio:
+	for (i = i - 1; i >= 0; i--)
+		gpio_free(ctrl[i]);
+
+	return err;
+}
+
+static void fan_ctrl_free(struct gpio_fan_data *fan_data)
+{
+	struct platform_device *pdev = fan_data->pdev;
+	int i;
+
+	sysfs_remove_group(&pdev->dev.kobj, &gpio_fan_ctrl_group);
+	for (i = 0; i < fan_data->num_ctrl; i++)
+		gpio_free(fan_data->ctrl[i]);
+}
+
+/*
+ * Platform driver.
+ */
+
+static ssize_t show_name(struct device *dev,
+			 struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "gpio-fan\n");
+}
+
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+static int __devinit gpio_fan_probe(struct platform_device *pdev)
+{
+	int err;
+	struct gpio_fan_data *fan_data;
+	struct gpio_fan_platform_data *pdata = pdev->dev.platform_data;
+
+	if (!pdata)
+		return -EINVAL;
+
+	fan_data = kzalloc(sizeof(struct gpio_fan_data), GFP_KERNEL);
+	if (!fan_data)
+		return -ENOMEM;
+
+	fan_data->pdev = pdev;
+	platform_set_drvdata(pdev, fan_data);
+	mutex_init(&fan_data->lock);
+
+	/* Configure alarm GPIO if available. */
+	if (pdata->alarm) {
+		err = fan_alarm_init(fan_data, pdata->alarm);
+		if (err)
+			goto err_free_data;
+	}
+
+	/* Configure control GPIOs if available. */
+	if (pdata->ctrl && pdata->num_ctrl > 0) {
+		if (!pdata->speed || pdata->num_speed <= 1) {
+			err = -EINVAL;
+			goto err_free_alarm;
+		}
+		err = fan_ctrl_init(fan_data, pdata);
+		if (err)
+			goto err_free_alarm;
+	}
+
+	err = device_create_file(&pdev->dev, &dev_attr_name);
+	if (err)
+		goto err_free_ctrl;
+
+	/* Make this driver part of hwmon class. */
+	fan_data->hwmon_dev = hwmon_device_register(&pdev->dev);
+	if (IS_ERR(fan_data->hwmon_dev)) {
+		err = PTR_ERR(fan_data->hwmon_dev);
+		goto err_remove_name;
+	}
+
+	dev_info(&pdev->dev, "GPIO fan initialized\n");
+
+	return 0;
+
+err_remove_name:
+	device_remove_file(&pdev->dev, &dev_attr_name);
+err_free_ctrl:
+	if (fan_data->ctrl)
+		fan_ctrl_free(fan_data);
+err_free_alarm:
+	if (fan_data->alarm)
+		fan_alarm_free(fan_data);
+err_free_data:
+	platform_set_drvdata(pdev, NULL);
+	kfree(fan_data);
+
+	return err;
+}
+
+static int __devexit gpio_fan_remove(struct platform_device *pdev)
+{
+	struct gpio_fan_data *fan_data = platform_get_drvdata(pdev);
+
+	hwmon_device_unregister(fan_data->hwmon_dev);
+	device_remove_file(&pdev->dev, &dev_attr_name);
+	if (fan_data->alarm)
+		fan_alarm_free(fan_data);
+	if (fan_data->ctrl)
+		fan_ctrl_free(fan_data);
+	kfree(fan_data);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int gpio_fan_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct gpio_fan_data *fan_data = platform_get_drvdata(pdev);
+
+	if (fan_data->ctrl) {
+		fan_data->resume_speed = fan_data->speed_index;
+		set_fan_speed(fan_data, 0);
+	}
+
+	return 0;
+}
+
+static int gpio_fan_resume(struct platform_device *pdev)
+{
+	struct gpio_fan_data *fan_data = platform_get_drvdata(pdev);
+
+	if (fan_data->ctrl)
+		set_fan_speed(fan_data, fan_data->resume_speed);
+
+	return 0;
+}
+#else
+#define gpio_fan_suspend NULL
+#define gpio_fan_resume NULL
+#endif
+
+static struct platform_driver gpio_fan_driver = {
+	.probe		= gpio_fan_probe,
+	.remove		= __devexit_p(gpio_fan_remove),
+	.suspend	= gpio_fan_suspend,
+	.resume		= gpio_fan_resume,
+	.driver	= {
+		.name	= "gpio-fan",
+	},
+};
+
+static int __init gpio_fan_init(void)
+{
+	return platform_driver_register(&gpio_fan_driver);
+}
+
+static void __exit gpio_fan_exit(void)
+{
+	platform_driver_unregister(&gpio_fan_driver);
+}
+
+module_init(gpio_fan_init);
+module_exit(gpio_fan_exit);
+
+MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>");
+MODULE_DESCRIPTION("GPIO FAN driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:gpio-fan");
diff --git a/drivers/hwmon/hp_accel.c b/drivers/hwmon/hp_accel.c
index 36e9575..a56a784 100644
--- a/drivers/hwmon/hp_accel.c
+++ b/drivers/hwmon/hp_accel.c
@@ -146,7 +146,7 @@
 
 static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi)
 {
-	lis3_dev.ac = *((struct axis_conversion *)dmi->driver_data);
+	lis3_dev.ac = *((union axis_conversion *)dmi->driver_data);
 	printk(KERN_INFO DRIVER_NAME ": hardware type %s found.\n", dmi->ident);
 
 	return 1;
@@ -154,16 +154,19 @@
 
 /* Represents, for each axis seen by userspace, the corresponding hw axis (+1).
  * If the value is negative, the opposite of the hw value is used. */
-static struct axis_conversion lis3lv02d_axis_normal = {1, 2, 3};
-static struct axis_conversion lis3lv02d_axis_y_inverted = {1, -2, 3};
-static struct axis_conversion lis3lv02d_axis_x_inverted = {-1, 2, 3};
-static struct axis_conversion lis3lv02d_axis_z_inverted = {1, 2, -3};
-static struct axis_conversion lis3lv02d_axis_xy_swap = {2, 1, 3};
-static struct axis_conversion lis3lv02d_axis_xy_rotated_left = {-2, 1, 3};
-static struct axis_conversion lis3lv02d_axis_xy_rotated_left_usd = {-2, 1, -3};
-static struct axis_conversion lis3lv02d_axis_xy_swap_inverted = {-2, -1, 3};
-static struct axis_conversion lis3lv02d_axis_xy_rotated_right = {2, -1, 3};
-static struct axis_conversion lis3lv02d_axis_xy_swap_yz_inverted = {2, -1, -3};
+#define DEFINE_CONV(name, x, y, z)			      \
+	static union axis_conversion lis3lv02d_axis_##name = \
+		{ .as_array = { x, y, z } }
+DEFINE_CONV(normal, 1, 2, 3);
+DEFINE_CONV(y_inverted, 1, -2, 3);
+DEFINE_CONV(x_inverted, -1, 2, 3);
+DEFINE_CONV(z_inverted, 1, 2, -3);
+DEFINE_CONV(xy_swap, 2, 1, 3);
+DEFINE_CONV(xy_rotated_left, -2, 1, 3);
+DEFINE_CONV(xy_rotated_left_usd, -2, 1, -3);
+DEFINE_CONV(xy_swap_inverted, -2, -1, 3);
+DEFINE_CONV(xy_rotated_right, 2, -1, 3);
+DEFINE_CONV(xy_swap_yz_inverted, 2, -1, -3);
 
 #define AXIS_DMI_MATCH(_ident, _name, _axis) {		\
 	.ident = _ident,				\
@@ -222,7 +225,7 @@
 	AXIS_DMI_MATCH("HPB452x", "HP ProBook 452", y_inverted),
 	AXIS_DMI_MATCH("HPB522x", "HP ProBook 522", xy_swap),
 	AXIS_DMI_MATCH("HPB532x", "HP ProBook 532", y_inverted),
-	AXIS_DMI_MATCH("Mini5102", "HP Mini 5102", xy_rotated_left_usd),
+	AXIS_DMI_MATCH("Mini510x", "HP Mini 510", xy_rotated_left_usd),
 	{ NULL, }
 /* Laptop models without axis info (yet):
  * "NC6910" "HP Compaq 6910"
@@ -299,7 +302,10 @@
 	lis3lv02d_enum_resources(device);
 
 	/* If possible use a "standard" axes order */
-	if (dmi_check_system(lis3lv02d_dmi_ids) == 0) {
+	if (lis3_dev.ac.x && lis3_dev.ac.y && lis3_dev.ac.z) {
+		printk(KERN_INFO DRIVER_NAME ": Using custom axes %d,%d,%d\n",
+		       lis3_dev.ac.x, lis3_dev.ac.y, lis3_dev.ac.z);
+	} else if (dmi_check_system(lis3lv02d_dmi_ids) == 0) {
 		printk(KERN_INFO DRIVER_NAME ": laptop model unknown, "
 				 "using default axes configuration\n");
 		lis3_dev.ac = lis3lv02d_axis_normal;
diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c
index fc591ae..0cee73a 100644
--- a/drivers/hwmon/lis3lv02d.c
+++ b/drivers/hwmon/lis3lv02d.c
@@ -31,9 +31,11 @@
 #include <linux/delay.h>
 #include <linux/wait.h>
 #include <linux/poll.h>
+#include <linux/slab.h>
 #include <linux/freezer.h>
 #include <linux/uaccess.h>
 #include <linux/miscdevice.h>
+#include <linux/pm_runtime.h>
 #include <asm/atomic.h>
 #include "lis3lv02d.h"
 
@@ -43,6 +45,16 @@
 #define MDPS_POLL_INTERVAL 50
 #define MDPS_POLL_MIN	   0
 #define MDPS_POLL_MAX	   2000
+
+#define LIS3_SYSFS_POWERDOWN_DELAY 5000 /* In milliseconds */
+
+#define SELFTEST_OK	       0
+#define SELFTEST_FAIL	       -1
+#define SELFTEST_IRQ	       -2
+
+#define IRQ_LINE0	       0
+#define IRQ_LINE1	       1
+
 /*
  * The sensor can also generate interrupts (DRDY) but it's pretty pointless
  * because they are generated even if the data do not change. So it's better
@@ -66,8 +78,10 @@
 #define LIS3_SENSITIVITY_12B		((LIS3_ACCURACY * 1000) / 1024)
 #define LIS3_SENSITIVITY_8B		(18 * LIS3_ACCURACY)
 
-#define LIS3_DEFAULT_FUZZ		3
-#define LIS3_DEFAULT_FLAT		3
+#define LIS3_DEFAULT_FUZZ_12B		3
+#define LIS3_DEFAULT_FLAT_12B		3
+#define LIS3_DEFAULT_FUZZ_8B		1
+#define LIS3_DEFAULT_FLAT_8B		1
 
 struct lis3lv02d lis3_dev = {
 	.misc_wait   = __WAIT_QUEUE_HEAD_INITIALIZER(lis3_dev.misc_wait),
@@ -75,6 +89,30 @@
 
 EXPORT_SYMBOL_GPL(lis3_dev);
 
+/* just like param_set_int() but does sanity-check so that it won't point
+ * over the axis array size
+ */
+static int param_set_axis(const char *val, const struct kernel_param *kp)
+{
+	int ret = param_set_int(val, kp);
+	if (!ret) {
+		int val = *(int *)kp->arg;
+		if (val < 0)
+			val = -val;
+		if (!val || val > 3)
+			return -EINVAL;
+	}
+	return ret;
+}
+
+static struct kernel_param_ops param_ops_axis = {
+	.set = param_set_axis,
+	.get = param_get_int,
+};
+
+module_param_array_named(axes, lis3_dev.ac.as_array, axis, NULL, 0644);
+MODULE_PARM_DESC(axes, "Axis-mapping for x,y,z directions");
+
 static s16 lis3lv02d_read_8(struct lis3lv02d *lis3, int reg)
 {
 	s8 lo;
@@ -123,9 +161,24 @@
 	int position[3];
 	int i;
 
-	position[0] = lis3->read_data(lis3, OUTX);
-	position[1] = lis3->read_data(lis3, OUTY);
-	position[2] = lis3->read_data(lis3, OUTZ);
+	if (lis3->blkread) {
+		if (lis3_dev.whoami == WAI_12B) {
+			u16 data[3];
+			lis3->blkread(lis3, OUTX_L, 6, (u8 *)data);
+			for (i = 0; i < 3; i++)
+				position[i] = (s16)le16_to_cpu(data[i]);
+		} else {
+			u8 data[5];
+			/* Data: x, dummy, y, dummy, z */
+			lis3->blkread(lis3, OUTX, 5, data);
+			for (i = 0; i < 3; i++)
+				position[i] = (s8)data[i * 2];
+		}
+	} else {
+		position[0] = lis3->read_data(lis3, OUTX);
+		position[1] = lis3->read_data(lis3, OUTY);
+		position[2] = lis3->read_data(lis3, OUTZ);
+	}
 
 	for (i = 0; i < 3; i++)
 		position[i] = (position[i] * lis3->scale) / LIS3_ACCURACY;
@@ -138,6 +191,7 @@
 /* conversion btw sampling rate and the register values */
 static int lis3_12_rates[4] = {40, 160, 640, 2560};
 static int lis3_8_rates[2] = {100, 400};
+static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000};
 
 /* ODR is Output Data Rate */
 static int lis3lv02d_get_odr(void)
@@ -156,6 +210,9 @@
 	u8 ctrl;
 	int i, len, shift;
 
+	if (!rate)
+		return -EINVAL;
+
 	lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl);
 	ctrl &= ~lis3_dev.odr_mask;
 	len = 1 << hweight_long(lis3_dev.odr_mask); /* # of possible values */
@@ -172,19 +229,42 @@
 
 static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
 {
-	u8 reg;
+	u8 ctlreg, reg;
 	s16 x, y, z;
 	u8 selftest;
 	int ret;
+	u8 ctrl_reg_data;
+	unsigned char irq_cfg;
 
 	mutex_lock(&lis3->mutex);
-	if (lis3_dev.whoami == WAI_12B)
-		selftest = CTRL1_ST;
-	else
-		selftest = CTRL1_STP;
 
-	lis3->read(lis3, CTRL_REG1, &reg);
-	lis3->write(lis3, CTRL_REG1, (reg | selftest));
+	irq_cfg = lis3->irq_cfg;
+	if (lis3_dev.whoami == WAI_8B) {
+		lis3->data_ready_count[IRQ_LINE0] = 0;
+		lis3->data_ready_count[IRQ_LINE1] = 0;
+
+		/* Change interrupt cfg to data ready for selftest */
+		atomic_inc(&lis3_dev.wake_thread);
+		lis3->irq_cfg = LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY;
+		lis3->read(lis3, CTRL_REG3, &ctrl_reg_data);
+		lis3->write(lis3, CTRL_REG3, (ctrl_reg_data &
+				~(LIS3_IRQ1_MASK | LIS3_IRQ2_MASK)) |
+				(LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY));
+	}
+
+	if (lis3_dev.whoami == WAI_3DC) {
+		ctlreg = CTRL_REG4;
+		selftest = CTRL4_ST0;
+	} else {
+		ctlreg = CTRL_REG1;
+		if (lis3_dev.whoami == WAI_12B)
+			selftest = CTRL1_ST;
+		else
+			selftest = CTRL1_STP;
+	}
+
+	lis3->read(lis3, ctlreg, &reg);
+	lis3->write(lis3, ctlreg, (reg | selftest));
 	msleep(lis3->pwron_delay / lis3lv02d_get_odr());
 
 	/* Read directly to avoid axis remap */
@@ -193,7 +273,7 @@
 	z = lis3->read_data(lis3, OUTZ);
 
 	/* back to normal settings */
-	lis3->write(lis3, CTRL_REG1, reg);
+	lis3->write(lis3, ctlreg, reg);
 	msleep(lis3->pwron_delay / lis3lv02d_get_odr());
 
 	results[0] = x - lis3->read_data(lis3, OUTX);
@@ -201,13 +281,33 @@
 	results[2] = z - lis3->read_data(lis3, OUTZ);
 
 	ret = 0;
+
+	if (lis3_dev.whoami == WAI_8B) {
+		/* Restore original interrupt configuration */
+		atomic_dec(&lis3_dev.wake_thread);
+		lis3->write(lis3, CTRL_REG3, ctrl_reg_data);
+		lis3->irq_cfg = irq_cfg;
+
+		if ((irq_cfg & LIS3_IRQ1_MASK) &&
+			lis3->data_ready_count[IRQ_LINE0] < 2) {
+			ret = SELFTEST_IRQ;
+			goto fail;
+		}
+
+		if ((irq_cfg & LIS3_IRQ2_MASK) &&
+			lis3->data_ready_count[IRQ_LINE1] < 2) {
+			ret = SELFTEST_IRQ;
+			goto fail;
+		}
+	}
+
 	if (lis3->pdata) {
 		int i;
 		for (i = 0; i < 3; i++) {
 			/* Check against selftest acceptance limits */
 			if ((results[i] < lis3->pdata->st_min_limits[i]) ||
 			    (results[i] > lis3->pdata->st_max_limits[i])) {
-				ret = -EIO;
+				ret = SELFTEST_FAIL;
 				goto fail;
 			}
 		}
@@ -219,10 +319,46 @@
 	return ret;
 }
 
+/*
+ * Order of registers in the list affects to order of the restore process.
+ * Perhaps it is a good idea to set interrupt enable register as a last one
+ * after all other configurations
+ */
+static u8 lis3_wai8_regs[] = { FF_WU_CFG_1, FF_WU_THS_1, FF_WU_DURATION_1,
+			       FF_WU_CFG_2, FF_WU_THS_2, FF_WU_DURATION_2,
+			       CLICK_CFG, CLICK_SRC, CLICK_THSY_X, CLICK_THSZ,
+			       CLICK_TIMELIMIT, CLICK_LATENCY, CLICK_WINDOW,
+			       CTRL_REG1, CTRL_REG2, CTRL_REG3};
+
+static u8 lis3_wai12_regs[] = {FF_WU_CFG, FF_WU_THS_L, FF_WU_THS_H,
+			       FF_WU_DURATION, DD_CFG, DD_THSI_L, DD_THSI_H,
+			       DD_THSE_L, DD_THSE_H,
+			       CTRL_REG1, CTRL_REG3, CTRL_REG2};
+
+static inline void lis3_context_save(struct lis3lv02d *lis3)
+{
+	int i;
+	for (i = 0; i < lis3->regs_size; i++)
+		lis3->read(lis3, lis3->regs[i], &lis3->reg_cache[i]);
+	lis3->regs_stored = true;
+}
+
+static inline void lis3_context_restore(struct lis3lv02d *lis3)
+{
+	int i;
+	if (lis3->regs_stored)
+		for (i = 0; i < lis3->regs_size; i++)
+			lis3->write(lis3, lis3->regs[i], lis3->reg_cache[i]);
+}
+
 void lis3lv02d_poweroff(struct lis3lv02d *lis3)
 {
+	if (lis3->reg_ctrl)
+		lis3_context_save(lis3);
 	/* disable X,Y,Z axis and power down */
 	lis3->write(lis3, CTRL_REG1, 0x00);
+	if (lis3->reg_ctrl)
+		lis3->reg_ctrl(lis3, LIS3_REG_OFF);
 }
 EXPORT_SYMBOL_GPL(lis3lv02d_poweroff);
 
@@ -232,19 +368,24 @@
 
 	lis3->init(lis3);
 
-	/* LIS3 power on delay is quite long */
-	msleep(lis3->pwron_delay / lis3lv02d_get_odr());
-
 	/*
 	 * Common configuration
 	 * BDU: (12 bits sensors only) LSB and MSB values are not updated until
 	 *      both have been read. So the value read will always be correct.
+	 * Set BOOT bit to refresh factory tuning values.
 	 */
-	if (lis3->whoami ==  WAI_12B) {
-		lis3->read(lis3, CTRL_REG2, &reg);
-		reg |= CTRL2_BDU;
-		lis3->write(lis3, CTRL_REG2, reg);
-	}
+	lis3->read(lis3, CTRL_REG2, &reg);
+	if (lis3->whoami ==  WAI_12B)
+		reg |= CTRL2_BDU | CTRL2_BOOT;
+	else
+		reg |= CTRL2_BOOT_8B;
+	lis3->write(lis3, CTRL_REG2, reg);
+
+	/* LIS3 power on delay is quite long */
+	msleep(lis3->pwron_delay / lis3lv02d_get_odr());
+
+	if (lis3->reg_ctrl)
+		lis3_context_restore(lis3);
 }
 EXPORT_SYMBOL_GPL(lis3lv02d_poweron);
 
@@ -262,6 +403,27 @@
 	mutex_unlock(&lis3_dev.mutex);
 }
 
+static void lis3lv02d_joystick_open(struct input_polled_dev *pidev)
+{
+	if (lis3_dev.pm_dev)
+		pm_runtime_get_sync(lis3_dev.pm_dev);
+
+	if (lis3_dev.pdata && lis3_dev.whoami == WAI_8B && lis3_dev.idev)
+		atomic_set(&lis3_dev.wake_thread, 1);
+	/*
+	 * Update coordinates for the case where poll interval is 0 and
+	 * the chip in running purely under interrupt control
+	 */
+	lis3lv02d_joystick_poll(pidev);
+}
+
+static void lis3lv02d_joystick_close(struct input_polled_dev *pidev)
+{
+	atomic_set(&lis3_dev.wake_thread, 0);
+	if (lis3_dev.pm_dev)
+		pm_runtime_put(lis3_dev.pm_dev);
+}
+
 static irqreturn_t lis302dl_interrupt(int irq, void *dummy)
 {
 	if (!test_bit(0, &lis3_dev.misc_opened))
@@ -277,8 +439,7 @@
 	wake_up_interruptible(&lis3_dev.misc_wait);
 	kill_fasync(&lis3_dev.async_queue, SIGIO, POLL_IN);
 out:
-	if (lis3_dev.pdata && lis3_dev.whoami == WAI_8B && lis3_dev.idev &&
-	    lis3_dev.idev->input->users)
+	if (atomic_read(&lis3_dev.wake_thread))
 		return IRQ_WAKE_THREAD;
 	return IRQ_HANDLED;
 }
@@ -309,44 +470,41 @@
 	mutex_unlock(&lis3->mutex);
 }
 
-static void lis302dl_interrupt_handle_ff_wu(struct lis3lv02d *lis3)
+static inline void lis302dl_data_ready(struct lis3lv02d *lis3, int index)
 {
-	u8 wu1_src;
-	u8 wu2_src;
+	int dummy;
 
-	lis3->read(lis3, FF_WU_SRC_1, &wu1_src);
-	lis3->read(lis3, FF_WU_SRC_2, &wu2_src);
-
-	wu1_src = wu1_src & FF_WU_SRC_IA ? wu1_src : 0;
-	wu2_src = wu2_src & FF_WU_SRC_IA ? wu2_src : 0;
-
-	/* joystick poll is internally protected by the lis3->mutex. */
-	if (wu1_src || wu2_src)
-		lis3lv02d_joystick_poll(lis3_dev.idev);
+	/* Dummy read to ack interrupt */
+	lis3lv02d_get_xyz(lis3, &dummy, &dummy, &dummy);
+	lis3->data_ready_count[index]++;
 }
 
 static irqreturn_t lis302dl_interrupt_thread1_8b(int irq, void *data)
 {
-
 	struct lis3lv02d *lis3 = data;
+	u8 irq_cfg = lis3->irq_cfg & LIS3_IRQ1_MASK;
 
-	if ((lis3->pdata->irq_cfg & LIS3_IRQ1_MASK) == LIS3_IRQ1_CLICK)
+	if (irq_cfg == LIS3_IRQ1_CLICK)
 		lis302dl_interrupt_handle_click(lis3);
+	else if (unlikely(irq_cfg == LIS3_IRQ1_DATA_READY))
+		lis302dl_data_ready(lis3, IRQ_LINE0);
 	else
-		lis302dl_interrupt_handle_ff_wu(lis3);
+		lis3lv02d_joystick_poll(lis3->idev);
 
 	return IRQ_HANDLED;
 }
 
 static irqreturn_t lis302dl_interrupt_thread2_8b(int irq, void *data)
 {
-
 	struct lis3lv02d *lis3 = data;
+	u8 irq_cfg = lis3->irq_cfg & LIS3_IRQ2_MASK;
 
-	if ((lis3->pdata->irq_cfg & LIS3_IRQ2_MASK) == LIS3_IRQ2_CLICK)
+	if (irq_cfg == LIS3_IRQ2_CLICK)
 		lis302dl_interrupt_handle_click(lis3);
+	else if (unlikely(irq_cfg == LIS3_IRQ2_DATA_READY))
+		lis302dl_data_ready(lis3, IRQ_LINE1);
 	else
-		lis302dl_interrupt_handle_ff_wu(lis3);
+		lis3lv02d_joystick_poll(lis3->idev);
 
 	return IRQ_HANDLED;
 }
@@ -356,6 +514,9 @@
 	if (test_and_set_bit(0, &lis3_dev.misc_opened))
 		return -EBUSY; /* already open */
 
+	if (lis3_dev.pm_dev)
+		pm_runtime_get_sync(lis3_dev.pm_dev);
+
 	atomic_set(&lis3_dev.count, 0);
 	return 0;
 }
@@ -364,6 +525,8 @@
 {
 	fasync_helper(-1, file, 0, &lis3_dev.async_queue);
 	clear_bit(0, &lis3_dev.misc_opened); /* release the device */
+	if (lis3_dev.pm_dev)
+		pm_runtime_put(lis3_dev.pm_dev);
 	return 0;
 }
 
@@ -460,6 +623,8 @@
 		return -ENOMEM;
 
 	lis3_dev.idev->poll = lis3lv02d_joystick_poll;
+	lis3_dev.idev->open = lis3lv02d_joystick_open;
+	lis3_dev.idev->close = lis3lv02d_joystick_close;
 	lis3_dev.idev->poll_interval = MDPS_POLL_INTERVAL;
 	lis3_dev.idev->poll_interval_min = MDPS_POLL_MIN;
 	lis3_dev.idev->poll_interval_max = MDPS_POLL_MAX;
@@ -473,8 +638,16 @@
 
 	set_bit(EV_ABS, input_dev->evbit);
 	max_val = (lis3_dev.mdps_max_val * lis3_dev.scale) / LIS3_ACCURACY;
-	fuzz = (LIS3_DEFAULT_FUZZ * lis3_dev.scale) / LIS3_ACCURACY;
-	flat = (LIS3_DEFAULT_FLAT * lis3_dev.scale) / LIS3_ACCURACY;
+	if (lis3_dev.whoami == WAI_12B) {
+		fuzz = LIS3_DEFAULT_FUZZ_12B;
+		flat = LIS3_DEFAULT_FLAT_12B;
+	} else {
+		fuzz = LIS3_DEFAULT_FUZZ_8B;
+		flat = LIS3_DEFAULT_FLAT_8B;
+	}
+	fuzz = (fuzz * lis3_dev.scale) / LIS3_ACCURACY;
+	flat = (flat * lis3_dev.scale) / LIS3_ACCURACY;
+
 	input_set_abs_params(input_dev, ABS_X, -max_val, max_val, fuzz, flat);
 	input_set_abs_params(input_dev, ABS_Y, -max_val, max_val, fuzz, flat);
 	input_set_abs_params(input_dev, ABS_Z, -max_val, max_val, fuzz, flat);
@@ -512,14 +685,47 @@
 EXPORT_SYMBOL_GPL(lis3lv02d_joystick_disable);
 
 /* Sysfs stuff */
+static void lis3lv02d_sysfs_poweron(struct lis3lv02d *lis3)
+{
+	/*
+	 * SYSFS functions are fast visitors so put-call
+	 * immediately after the get-call. However, keep
+	 * chip running for a while and schedule delayed
+	 * suspend. This way periodic sysfs calls doesn't
+	 * suffer from relatively long power up time.
+	 */
+
+	if (lis3->pm_dev) {
+		pm_runtime_get_sync(lis3->pm_dev);
+		pm_runtime_put_noidle(lis3->pm_dev);
+		pm_schedule_suspend(lis3->pm_dev, LIS3_SYSFS_POWERDOWN_DELAY);
+	}
+}
+
 static ssize_t lis3lv02d_selftest_show(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
-	int result;
 	s16 values[3];
 
-	result = lis3lv02d_selftest(&lis3_dev, values);
-	return sprintf(buf, "%s %d %d %d\n", result == 0 ? "OK" : "FAIL",
+	static const char ok[] = "OK";
+	static const char fail[] = "FAIL";
+	static const char irq[] = "FAIL_IRQ";
+	const char *res;
+
+	lis3lv02d_sysfs_poweron(&lis3_dev);
+	switch (lis3lv02d_selftest(&lis3_dev, values)) {
+	case SELFTEST_FAIL:
+		res = fail;
+		break;
+	case SELFTEST_IRQ:
+		res = irq;
+		break;
+	case SELFTEST_OK:
+	default:
+		res = ok;
+		break;
+	}
+	return sprintf(buf, "%s %d %d %d\n", res,
 		values[0], values[1], values[2]);
 }
 
@@ -528,6 +734,7 @@
 {
 	int x, y, z;
 
+	lis3lv02d_sysfs_poweron(&lis3_dev);
 	mutex_lock(&lis3_dev.mutex);
 	lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
 	mutex_unlock(&lis3_dev.mutex);
@@ -537,6 +744,7 @@
 static ssize_t lis3lv02d_rate_show(struct device *dev,
 			struct device_attribute *attr, char *buf)
 {
+	lis3lv02d_sysfs_poweron(&lis3_dev);
 	return sprintf(buf, "%d\n", lis3lv02d_get_odr());
 }
 
@@ -549,6 +757,7 @@
 	if (strict_strtoul(buf, 0, &rate))
 		return -EINVAL;
 
+	lis3lv02d_sysfs_poweron(&lis3_dev);
 	if (lis3lv02d_set_odr(rate))
 		return -EINVAL;
 
@@ -585,6 +794,18 @@
 {
 	sysfs_remove_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group);
 	platform_device_unregister(lis3->pdev);
+	if (lis3->pm_dev) {
+		/* Barrier after the sysfs remove */
+		pm_runtime_barrier(lis3->pm_dev);
+
+		/* SYSFS may have left chip running. Turn off if necessary */
+		if (!pm_runtime_suspended(lis3->pm_dev))
+			lis3lv02d_poweroff(&lis3_dev);
+
+		pm_runtime_disable(lis3->pm_dev);
+		pm_runtime_set_suspended(lis3->pm_dev);
+	}
+	kfree(lis3->reg_cache);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs);
@@ -616,16 +837,16 @@
 	if (p->wakeup_flags) {
 		dev->write(dev, FF_WU_CFG_1, p->wakeup_flags);
 		dev->write(dev, FF_WU_THS_1, p->wakeup_thresh & 0x7f);
-		/* default to 2.5ms for now */
-		dev->write(dev, FF_WU_DURATION_1, 1);
+		/* pdata value + 1 to keep this backward compatible*/
+		dev->write(dev, FF_WU_DURATION_1, p->duration1 + 1);
 		ctrl2 ^= HP_FF_WU1; /* Xor to keep compatible with old pdata*/
 	}
 
 	if (p->wakeup_flags2) {
 		dev->write(dev, FF_WU_CFG_2, p->wakeup_flags2);
 		dev->write(dev, FF_WU_THS_2, p->wakeup_thresh2 & 0x7f);
-		/* default to 2.5ms for now */
-		dev->write(dev, FF_WU_DURATION_2, 1);
+		/* pdata value + 1 to keep this backward compatible*/
+		dev->write(dev, FF_WU_DURATION_2, p->duration2 + 1);
 		ctrl2 ^= HP_FF_WU2; /* Xor to keep compatible with old pdata*/
 	}
 	/* Configure hipass filters */
@@ -635,8 +856,8 @@
 		err = request_threaded_irq(p->irq2,
 					NULL,
 					lis302dl_interrupt_thread2_8b,
-					IRQF_TRIGGER_RISING |
-					IRQF_ONESHOT,
+					IRQF_TRIGGER_RISING | IRQF_ONESHOT |
+					(p->irq_flags2 & IRQF_TRIGGER_MASK),
 					DRIVER_NAME, &lis3_dev);
 		if (err < 0)
 			printk(KERN_ERR DRIVER_NAME
@@ -652,6 +873,7 @@
 {
 	int err;
 	irq_handler_t thread_fn;
+	int irq_flags = 0;
 
 	dev->whoami = lis3lv02d_read_8(dev, WHO_AM_I);
 
@@ -664,6 +886,8 @@
 		dev->odrs = lis3_12_rates;
 		dev->odr_mask = CTRL1_DF0 | CTRL1_DF1;
 		dev->scale = LIS3_SENSITIVITY_12B;
+		dev->regs = lis3_wai12_regs;
+		dev->regs_size = ARRAY_SIZE(lis3_wai12_regs);
 		break;
 	case WAI_8B:
 		printk(KERN_INFO DRIVER_NAME ": 8 bits sensor found\n");
@@ -673,6 +897,17 @@
 		dev->odrs = lis3_8_rates;
 		dev->odr_mask = CTRL1_DR;
 		dev->scale = LIS3_SENSITIVITY_8B;
+		dev->regs = lis3_wai8_regs;
+		dev->regs_size = ARRAY_SIZE(lis3_wai8_regs);
+		break;
+	case WAI_3DC:
+		printk(KERN_INFO DRIVER_NAME ": 8 bits 3DC sensor found\n");
+		dev->read_data = lis3lv02d_read_8;
+		dev->mdps_max_val = 128;
+		dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
+		dev->odrs = lis3_3dc_rates;
+		dev->odr_mask = CTRL1_ODR0|CTRL1_ODR1|CTRL1_ODR2|CTRL1_ODR3;
+		dev->scale = LIS3_SENSITIVITY_8B;
 		break;
 	default:
 		printk(KERN_ERR DRIVER_NAME
@@ -680,11 +915,25 @@
 		return -EINVAL;
 	}
 
+	dev->reg_cache = kzalloc(max(sizeof(lis3_wai8_regs),
+				     sizeof(lis3_wai12_regs)), GFP_KERNEL);
+
+	if (dev->reg_cache == NULL) {
+		printk(KERN_ERR DRIVER_NAME "out of memory\n");
+		return -ENOMEM;
+	}
+
 	mutex_init(&dev->mutex);
+	atomic_set(&dev->wake_thread, 0);
 
 	lis3lv02d_add_fs(dev);
 	lis3lv02d_poweron(dev);
 
+	if (dev->pm_dev) {
+		pm_runtime_set_active(dev->pm_dev);
+		pm_runtime_enable(dev->pm_dev);
+	}
+
 	if (lis3lv02d_joystick_enable())
 		printk(KERN_ERR DRIVER_NAME ": joystick initialization failed\n");
 
@@ -696,8 +945,14 @@
 		if (dev->whoami == WAI_8B)
 			lis3lv02d_8b_configure(dev, p);
 
+		irq_flags = p->irq_flags1 & IRQF_TRIGGER_MASK;
+
+		dev->irq_cfg = p->irq_cfg;
 		if (p->irq_cfg)
 			dev->write(dev, CTRL_REG3, p->irq_cfg);
+
+		if (p->default_rate)
+			lis3lv02d_set_odr(p->default_rate);
 	}
 
 	/* bail if we did not get an IRQ from the bus layer */
@@ -725,7 +980,8 @@
 
 	err = request_threaded_irq(dev->irq, lis302dl_interrupt,
 				thread_fn,
-				IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+				IRQF_TRIGGER_RISING | IRQF_ONESHOT |
+				irq_flags,
 				DRIVER_NAME, &lis3_dev);
 
 	if (err < 0) {
diff --git a/drivers/hwmon/lis3lv02d.h b/drivers/hwmon/lis3lv02d.h
index 8540913..a193958 100644
--- a/drivers/hwmon/lis3lv02d.h
+++ b/drivers/hwmon/lis3lv02d.h
@@ -20,6 +20,7 @@
  */
 #include <linux/platform_device.h>
 #include <linux/input-polldev.h>
+#include <linux/regulator/consumer.h>
 
 /*
  * This driver tries to support the "digital" accelerometer chips from
@@ -45,6 +46,7 @@
 	CTRL_REG1	= 0x20,
 	CTRL_REG2	= 0x21,
 	CTRL_REG3	= 0x22,
+	CTRL_REG4	= 0x23,
 	HP_FILTER_RESET	= 0x23,
 	STATUS_REG	= 0x27,
 	OUTX_L		= 0x28,
@@ -93,6 +95,7 @@
 };
 
 enum lis3_who_am_i {
+	WAI_3DC		= 0x33,	/* 8 bits: LIS3DC, HP3DC */
 	WAI_12B		= 0x3A, /* 12 bits: LIS3LV02D[LQ]... */
 	WAI_8B		= 0x3B, /* 8 bits: LIS[23]02D[LQ]... */
 	WAI_6B		= 0x52, /* 6 bits: LIS331DLF - not supported */
@@ -118,6 +121,13 @@
 	CTRL1_DR	= 0x80,
 };
 
+enum lis3lv02d_ctrl1_3dc {
+	CTRL1_ODR0	= 0x10,
+	CTRL1_ODR1	= 0x20,
+	CTRL1_ODR2	= 0x40,
+	CTRL1_ODR3	= 0x80,
+};
+
 enum lis3lv02d_ctrl2 {
 	CTRL2_DAS	= 0x01,
 	CTRL2_SIM	= 0x02,
@@ -129,9 +139,18 @@
 	CTRL2_FS	= 0x80, /* Full Scale selection */
 };
 
+enum lis3lv02d_ctrl4_3dc {
+	CTRL4_SIM	= 0x01,
+	CTRL4_ST0	= 0x02,
+	CTRL4_ST1	= 0x04,
+	CTRL4_FS0	= 0x10,
+	CTRL4_FS1	= 0x20,
+};
+
 enum lis302d_ctrl2 {
 	HP_FF_WU2	= 0x08,
 	HP_FF_WU1	= 0x04,
+	CTRL2_BOOT_8B   = 0x40,
 };
 
 enum lis3lv02d_ctrl3 {
@@ -206,19 +225,33 @@
 	CLICK_IA	= 0x40,
 };
 
-struct axis_conversion {
-	s8	x;
-	s8	y;
-	s8	z;
+enum lis3lv02d_reg_state {
+	LIS3_REG_OFF	= 0x00,
+	LIS3_REG_ON	= 0x01,
+};
+
+union axis_conversion {
+	struct {
+		int x, y, z;
+	};
+	int as_array[3];
+
 };
 
 struct lis3lv02d {
 	void			*bus_priv; /* used by the bus layer only */
+	struct device		*pm_dev; /* for pm_runtime purposes */
 	int (*init) (struct lis3lv02d *lis3);
 	int (*write) (struct lis3lv02d *lis3, int reg, u8 val);
 	int (*read) (struct lis3lv02d *lis3, int reg, u8 *ret);
+	int (*blkread) (struct lis3lv02d *lis3, int reg, int len, u8 *ret);
+	int (*reg_ctrl) (struct lis3lv02d *lis3, bool state);
 
 	int                     *odrs;     /* Supported output data rates */
+	u8			*regs;	   /* Regs to store / restore */
+	int			regs_size;
+	u8                      *reg_cache;
+	bool			regs_stored;
 	u8                      odr_mask;  /* ODR bit mask */
 	u8			whoami;    /* indicates measurement precision */
 	s16 (*read_data) (struct lis3lv02d *lis3, int reg);
@@ -231,14 +264,18 @@
 
 	struct input_polled_dev	*idev;     /* input device */
 	struct platform_device	*pdev;     /* platform device */
+	struct regulator_bulk_data regulators[2];
 	atomic_t		count;     /* interrupt count after last read */
-	struct axis_conversion	ac;        /* hw -> logical axis */
+	union axis_conversion	ac;        /* hw -> logical axis */
 	int			mapped_btns[3];
 
 	u32			irq;       /* IRQ number */
 	struct fasync_struct	*async_queue; /* queue for the misc device */
 	wait_queue_head_t	misc_wait; /* Wait queue for the misc device */
 	unsigned long		misc_opened; /* bit0: whether the device is open */
+	int                     data_ready_count[2];
+	atomic_t		wake_thread;
+	unsigned char           irq_cfg;
 
 	struct lis3lv02d_platform_data *pdata;	/* for passing board config */
 	struct mutex		mutex;     /* Serialize poll and selftest */
diff --git a/drivers/hwmon/lis3lv02d_i2c.c b/drivers/hwmon/lis3lv02d_i2c.c
index 8e5933b..9f4bae0 100644
--- a/drivers/hwmon/lis3lv02d_i2c.c
+++ b/drivers/hwmon/lis3lv02d_i2c.c
@@ -29,10 +29,30 @@
 #include <linux/init.h>
 #include <linux/err.h>
 #include <linux/i2c.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
 #include "lis3lv02d.h"
 
 #define DRV_NAME 	"lis3lv02d_i2c"
 
+static const char reg_vdd[]    = "Vdd";
+static const char reg_vdd_io[] = "Vdd_IO";
+
+static int lis3_reg_ctrl(struct lis3lv02d *lis3, bool state)
+{
+	int ret;
+	if (state == LIS3_REG_OFF) {
+		ret = regulator_bulk_disable(ARRAY_SIZE(lis3->regulators),
+					lis3->regulators);
+	} else {
+		ret = regulator_bulk_enable(ARRAY_SIZE(lis3->regulators),
+					lis3->regulators);
+		/* Chip needs time to wakeup. Not mentioned in datasheet */
+		usleep_range(10000, 20000);
+	}
+	return ret;
+}
+
 static inline s32 lis3_i2c_write(struct lis3lv02d *lis3, int reg, u8 value)
 {
 	struct i2c_client *c = lis3->bus_priv;
@@ -46,24 +66,38 @@
 	return 0;
 }
 
+static inline s32 lis3_i2c_blockread(struct lis3lv02d *lis3, int reg, int len,
+				u8 *v)
+{
+	struct i2c_client *c = lis3->bus_priv;
+	reg |= (1 << 7); /* 7th bit enables address auto incrementation */
+	return i2c_smbus_read_i2c_block_data(c, reg, len, v);
+}
+
 static int lis3_i2c_init(struct lis3lv02d *lis3)
 {
 	u8 reg;
 	int ret;
 
+	if (lis3->reg_ctrl)
+		lis3_reg_ctrl(lis3, LIS3_REG_ON);
+
+	lis3->read(lis3, WHO_AM_I, &reg);
+	if (reg != lis3->whoami)
+		printk(KERN_ERR "lis3: power on failure\n");
+
 	/* power up the device */
 	ret = lis3->read(lis3, CTRL_REG1, &reg);
 	if (ret < 0)
 		return ret;
 
-	reg |= CTRL1_PD0;
+	reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen;
 	return lis3->write(lis3, CTRL_REG1, reg);
 }
 
 /* Default axis mapping but it can be overwritten by platform data */
-static struct axis_conversion lis3lv02d_axis_map = { LIS3_DEV_X,
-						     LIS3_DEV_Y,
-						     LIS3_DEV_Z };
+static union axis_conversion lis3lv02d_axis_map =
+	{ .as_array = { LIS3_DEV_X, LIS3_DEV_Y, LIS3_DEV_Z } };
 
 static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
 					const struct i2c_device_id *id)
@@ -72,6 +106,15 @@
 	struct lis3lv02d_platform_data *pdata = client->dev.platform_data;
 
 	if (pdata) {
+		/* Regulator control is optional */
+		if (pdata->driver_features & LIS3_USE_REGULATOR_CTRL)
+			lis3_dev.reg_ctrl = lis3_reg_ctrl;
+
+		if ((pdata->driver_features & LIS3_USE_BLOCK_READ) &&
+			(i2c_check_functionality(client->adapter,
+						I2C_FUNC_SMBUS_I2C_BLOCK)))
+			lis3_dev.blkread  = lis3_i2c_blockread;
+
 		if (pdata->axis_x)
 			lis3lv02d_axis_map.x = pdata->axis_x;
 
@@ -88,6 +131,16 @@
 			goto fail;
 	}
 
+	if (lis3_dev.reg_ctrl) {
+		lis3_dev.regulators[0].supply = reg_vdd;
+		lis3_dev.regulators[1].supply = reg_vdd_io;
+		ret = regulator_bulk_get(&client->dev,
+					ARRAY_SIZE(lis3_dev.regulators),
+					lis3_dev.regulators);
+		if (ret < 0)
+			goto fail;
+	}
+
 	lis3_dev.pdata	  = pdata;
 	lis3_dev.bus_priv = client;
 	lis3_dev.init	  = lis3_i2c_init;
@@ -95,10 +148,24 @@
 	lis3_dev.write	  = lis3_i2c_write;
 	lis3_dev.irq	  = client->irq;
 	lis3_dev.ac	  = lis3lv02d_axis_map;
+	lis3_dev.pm_dev	  = &client->dev;
 
 	i2c_set_clientdata(client, &lis3_dev);
+
+	/* Provide power over the init call */
+	if (lis3_dev.reg_ctrl)
+		lis3_reg_ctrl(&lis3_dev, LIS3_REG_ON);
+
 	ret = lis3lv02d_init_device(&lis3_dev);
+
+	if (lis3_dev.reg_ctrl)
+		lis3_reg_ctrl(&lis3_dev, LIS3_REG_OFF);
+
+	if (ret == 0)
+		return 0;
 fail:
+	if (pdata && pdata->release_resources)
+		pdata->release_resources();
 	return ret;
 }
 
@@ -111,14 +178,18 @@
 		pdata->release_resources();
 
 	lis3lv02d_joystick_disable();
-	lis3lv02d_poweroff(lis3);
+	lis3lv02d_remove_fs(&lis3_dev);
 
-	return lis3lv02d_remove_fs(&lis3_dev);
+	if (lis3_dev.reg_ctrl)
+		regulator_bulk_free(ARRAY_SIZE(lis3->regulators),
+				lis3_dev.regulators);
+	return 0;
 }
 
 #ifdef CONFIG_PM
-static int lis3lv02d_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
+static int lis3lv02d_i2c_suspend(struct device *dev)
 {
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
 	struct lis3lv02d *lis3 = i2c_get_clientdata(client);
 
 	if (!lis3->pdata || !lis3->pdata->wakeup_flags)
@@ -126,18 +197,21 @@
 	return 0;
 }
 
-static int lis3lv02d_i2c_resume(struct i2c_client *client)
+static int lis3lv02d_i2c_resume(struct device *dev)
 {
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
 	struct lis3lv02d *lis3 = i2c_get_clientdata(client);
 
-	if (!lis3->pdata || !lis3->pdata->wakeup_flags)
+	/*
+	 * pm_runtime documentation says that devices should always
+	 * be powered on at resume. Pm_runtime turns them off after system
+	 * wide resume is complete.
+	 */
+	if (!lis3->pdata || !lis3->pdata->wakeup_flags ||
+		pm_runtime_suspended(dev))
 		lis3lv02d_poweron(lis3);
-	return 0;
-}
 
-static void lis3lv02d_i2c_shutdown(struct i2c_client *client)
-{
-	lis3lv02d_i2c_suspend(client, PMSG_SUSPEND);
+	return 0;
 }
 #else
 #define lis3lv02d_i2c_suspend	NULL
@@ -145,6 +219,24 @@
 #define lis3lv02d_i2c_shutdown	NULL
 #endif
 
+static int lis3_i2c_runtime_suspend(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct lis3lv02d *lis3 = i2c_get_clientdata(client);
+
+	lis3lv02d_poweroff(lis3);
+	return 0;
+}
+
+static int lis3_i2c_runtime_resume(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct lis3lv02d *lis3 = i2c_get_clientdata(client);
+
+	lis3lv02d_poweron(lis3);
+	return 0;
+}
+
 static const struct i2c_device_id lis3lv02d_id[] = {
 	{"lis3lv02d", 0 },
 	{}
@@ -152,14 +244,20 @@
 
 MODULE_DEVICE_TABLE(i2c, lis3lv02d_id);
 
+static const struct dev_pm_ops lis3_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(lis3lv02d_i2c_suspend,
+				lis3lv02d_i2c_resume)
+	SET_RUNTIME_PM_OPS(lis3_i2c_runtime_suspend,
+			   lis3_i2c_runtime_resume,
+			   NULL)
+};
+
 static struct i2c_driver lis3lv02d_i2c_driver = {
 	.driver	 = {
 		.name   = DRV_NAME,
 		.owner  = THIS_MODULE,
+		.pm     = &lis3_pm_ops,
 	},
-	.suspend = lis3lv02d_i2c_suspend,
-	.shutdown = lis3lv02d_i2c_shutdown,
-	.resume = lis3lv02d_i2c_resume,
 	.probe	= lis3lv02d_i2c_probe,
 	.remove	= __devexit_p(lis3lv02d_i2c_remove),
 	.id_table = lis3lv02d_id,
diff --git a/drivers/hwmon/lis3lv02d_spi.c b/drivers/hwmon/lis3lv02d_spi.c
index b9be5e3..2549de1 100644
--- a/drivers/hwmon/lis3lv02d_spi.c
+++ b/drivers/hwmon/lis3lv02d_spi.c
@@ -50,11 +50,12 @@
 	if (ret < 0)
 		return ret;
 
-	reg |= CTRL1_PD0;
+	reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen;
 	return lis3->write(lis3, CTRL_REG1, reg);
 }
 
-static struct axis_conversion lis3lv02d_axis_normal = { 1, 2, 3 };
+static union axis_conversion lis3lv02d_axis_normal =
+	{ .as_array = { 1, 2, 3 } };
 
 static int __devinit lis302dl_spi_probe(struct spi_device *spi)
 {
diff --git a/drivers/hwmon/ltc4261.c b/drivers/hwmon/ltc4261.c
new file mode 100644
index 0000000..2676261
--- /dev/null
+++ b/drivers/hwmon/ltc4261.c
@@ -0,0 +1,315 @@
+/*
+ * Driver for Linear Technology LTC4261 I2C Negative Voltage Hot Swap Controller
+ *
+ * Copyright (C) 2010 Ericsson AB.
+ *
+ * Derived from:
+ *
+ *  Driver for Linear Technology LTC4245 I2C Multiple Supply Hot Swap Controller
+ *  Copyright (C) 2008 Ira W. Snyder <iws@ovro.caltech.edu>
+ *
+ * Datasheet: http://cds.linear.com/docs/Datasheet/42612fb.pdf
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+
+/* chip registers */
+#define LTC4261_STATUS	0x00	/* readonly */
+#define LTC4261_FAULT	0x01
+#define LTC4261_ALERT	0x02
+#define LTC4261_CONTROL	0x03
+#define LTC4261_SENSE_H	0x04
+#define LTC4261_SENSE_L	0x05
+#define LTC4261_ADIN2_H	0x06
+#define LTC4261_ADIN2_L	0x07
+#define LTC4261_ADIN_H	0x08
+#define LTC4261_ADIN_L	0x09
+
+/*
+ * Fault register bits
+ */
+#define FAULT_OV	(1<<0)
+#define FAULT_UV	(1<<1)
+#define FAULT_OC	(1<<2)
+
+struct ltc4261_data {
+	struct device *hwmon_dev;
+
+	struct mutex update_lock;
+	bool valid;
+	unsigned long last_updated;	/* in jiffies */
+
+	/* Registers */
+	u8 regs[10];
+};
+
+static struct ltc4261_data *ltc4261_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct ltc4261_data *data = i2c_get_clientdata(client);
+	struct ltc4261_data *ret = data;
+
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + HZ / 4) || !data->valid) {
+		int i;
+
+		/* Read registers -- 0x00 to 0x09 */
+		for (i = 0; i < ARRAY_SIZE(data->regs); i++) {
+			int val;
+
+			val = i2c_smbus_read_byte_data(client, i);
+			if (unlikely(val < 0)) {
+				dev_dbg(dev,
+					"Failed to read ADC value: error %d",
+					val);
+				ret = ERR_PTR(val);
+				goto abort;
+			}
+			data->regs[i] = val;
+		}
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+abort:
+	mutex_unlock(&data->update_lock);
+	return ret;
+}
+
+/* Return the voltage from the given register in mV or mA */
+static int ltc4261_get_value(struct ltc4261_data *data, u8 reg)
+{
+	u32 val;
+
+	val = (data->regs[reg] << 2) + (data->regs[reg + 1] >> 6);
+
+	switch (reg) {
+	case LTC4261_ADIN_H:
+	case LTC4261_ADIN2_H:
+		/* 2.5mV resolution. Convert to mV. */
+		val = val * 25 / 10;
+		break;
+	case LTC4261_SENSE_H:
+		/*
+		 * 62.5uV resolution. Convert to current as measured with
+		 * an 1 mOhm sense resistor, in mA. If a different sense
+		 * resistor is installed, calculate the actual current by
+		 * dividing the reported current by the sense resistor value
+		 * in mOhm.
+		 */
+		val = val * 625 / 10;
+		break;
+	default:
+		/* If we get here, the developer messed up */
+		WARN_ON_ONCE(1);
+		val = 0;
+		break;
+	}
+
+	return val;
+}
+
+static ssize_t ltc4261_show_value(struct device *dev,
+				  struct device_attribute *da, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct ltc4261_data *data = ltc4261_update_device(dev);
+	int value;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	value = ltc4261_get_value(data, attr->index);
+	return snprintf(buf, PAGE_SIZE, "%d\n", value);
+}
+
+static ssize_t ltc4261_show_bool(struct device *dev,
+				 struct device_attribute *da, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct ltc4261_data *data = ltc4261_update_device(dev);
+	u8 fault;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	fault = data->regs[LTC4261_FAULT] & attr->index;
+	if (fault)		/* Clear reported faults in chip register */
+		i2c_smbus_write_byte_data(client, LTC4261_FAULT, ~fault);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", fault ? 1 : 0);
+}
+
+/*
+ * These macros are used below in constructing device attribute objects
+ * for use with sysfs_create_group() to make a sysfs device file
+ * for each register.
+ */
+
+#define LTC4261_VALUE(name, ltc4261_cmd_idx) \
+	static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
+	ltc4261_show_value, NULL, ltc4261_cmd_idx)
+
+#define LTC4261_BOOL(name, mask) \
+	static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
+	ltc4261_show_bool, NULL, (mask))
+
+/*
+ * Input voltages.
+ */
+LTC4261_VALUE(in1_input, LTC4261_ADIN_H);
+LTC4261_VALUE(in2_input, LTC4261_ADIN2_H);
+
+/*
+ * Voltage alarms. The chip has only one set of voltage alarm status bits,
+ * triggered by input voltage alarms. In many designs, those alarms are
+ * associated with the ADIN2 sensor, due to the proximity of the ADIN2 pin
+ * to the OV pin. ADIN2 is, however, not available on all chip variants.
+ * To ensure that the alarm condition is reported to the user, report it
+ * with both voltage sensors.
+ */
+LTC4261_BOOL(in1_min_alarm, FAULT_UV);
+LTC4261_BOOL(in1_max_alarm, FAULT_OV);
+LTC4261_BOOL(in2_min_alarm, FAULT_UV);
+LTC4261_BOOL(in2_max_alarm, FAULT_OV);
+
+/* Currents (via sense resistor) */
+LTC4261_VALUE(curr1_input, LTC4261_SENSE_H);
+
+/* Overcurrent alarm */
+LTC4261_BOOL(curr1_max_alarm, FAULT_OC);
+
+static struct attribute *ltc4261_attributes[] = {
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in1_min_alarm.dev_attr.attr,
+	&sensor_dev_attr_in1_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+	&sensor_dev_attr_in2_min_alarm.dev_attr.attr,
+	&sensor_dev_attr_in2_max_alarm.dev_attr.attr,
+
+	&sensor_dev_attr_curr1_input.dev_attr.attr,
+	&sensor_dev_attr_curr1_max_alarm.dev_attr.attr,
+
+	NULL,
+};
+
+static const struct attribute_group ltc4261_group = {
+	.attrs = ltc4261_attributes,
+};
+
+static int ltc4261_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct i2c_adapter *adapter = client->adapter;
+	struct ltc4261_data *data;
+	int ret;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -ENODEV;
+
+	if (i2c_smbus_read_byte_data(client, LTC4261_STATUS) < 0) {
+		dev_err(&client->dev, "Failed to read register %d:%02x:%02x\n",
+			adapter->id, client->addr, LTC4261_STATUS);
+		return -ENODEV;
+	}
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data) {
+		ret = -ENOMEM;
+		goto out_kzalloc;
+	}
+
+	i2c_set_clientdata(client, data);
+	mutex_init(&data->update_lock);
+
+	/* Clear faults */
+	i2c_smbus_write_byte_data(client, LTC4261_FAULT, 0x00);
+
+	/* Register sysfs hooks */
+	ret = sysfs_create_group(&client->dev.kobj, &ltc4261_group);
+	if (ret)
+		goto out_sysfs_create_group;
+
+	data->hwmon_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		ret = PTR_ERR(data->hwmon_dev);
+		goto out_hwmon_device_register;
+	}
+
+	return 0;
+
+out_hwmon_device_register:
+	sysfs_remove_group(&client->dev.kobj, &ltc4261_group);
+out_sysfs_create_group:
+	kfree(data);
+out_kzalloc:
+	return ret;
+}
+
+static int ltc4261_remove(struct i2c_client *client)
+{
+	struct ltc4261_data *data = i2c_get_clientdata(client);
+
+	hwmon_device_unregister(data->hwmon_dev);
+	sysfs_remove_group(&client->dev.kobj, &ltc4261_group);
+
+	kfree(data);
+
+	return 0;
+}
+
+static const struct i2c_device_id ltc4261_id[] = {
+	{"ltc4261", 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, ltc4261_id);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver ltc4261_driver = {
+	.driver = {
+		   .name = "ltc4261",
+		   },
+	.probe = ltc4261_probe,
+	.remove = ltc4261_remove,
+	.id_table = ltc4261_id,
+};
+
+static int __init ltc4261_init(void)
+{
+	return i2c_add_driver(&ltc4261_driver);
+}
+
+static void __exit ltc4261_exit(void)
+{
+	i2c_del_driver(&ltc4261_driver);
+}
+
+MODULE_AUTHOR("Guenter Roeck <guenter.roeck@ericsson.com>");
+MODULE_DESCRIPTION("LTC4261 driver");
+MODULE_LICENSE("GPL");
+
+module_init(ltc4261_init);
+module_exit(ltc4261_exit);
diff --git a/drivers/hwmon/pkgtemp.c b/drivers/hwmon/pkgtemp.c
index f119039..0798210 100644
--- a/drivers/hwmon/pkgtemp.c
+++ b/drivers/hwmon/pkgtemp.c
@@ -21,7 +21,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/jiffies.h>
@@ -35,6 +34,7 @@
 #include <linux/cpu.h>
 #include <asm/msr.h>
 #include <asm/processor.h>
+#include <asm/smp.h>
 
 #define DRVNAME	"pkgtemp"
 
@@ -339,8 +339,7 @@
 	return err;
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
-static void pkgtemp_device_remove(unsigned int cpu)
+static void __cpuinit pkgtemp_device_remove(unsigned int cpu)
 {
 	struct pdev_entry *p;
 	unsigned int i;
@@ -387,12 +386,10 @@
 static struct notifier_block pkgtemp_cpu_notifier __refdata = {
 	.notifier_call = pkgtemp_cpu_callback,
 };
-#endif				/* !CONFIG_HOTPLUG_CPU */
 
 static int __init pkgtemp_init(void)
 {
 	int i, err = -ENODEV;
-	struct pdev_entry *p, *n;
 
 	/* quick check if we run Intel */
 	if (cpu_data(0).x86_vendor != X86_VENDOR_INTEL)
@@ -402,31 +399,23 @@
 	if (err)
 		goto exit;
 
-	for_each_online_cpu(i) {
-		err = pkgtemp_device_add(i);
-		if (err)
-			goto exit_devices_unreg;
-	}
+	for_each_online_cpu(i)
+		pkgtemp_device_add(i);
+
+#ifndef CONFIG_HOTPLUG_CPU
 	if (list_empty(&pdev_list)) {
 		err = -ENODEV;
 		goto exit_driver_unreg;
 	}
-
-#ifdef CONFIG_HOTPLUG_CPU
-	register_hotcpu_notifier(&pkgtemp_cpu_notifier);
 #endif
+
+	register_hotcpu_notifier(&pkgtemp_cpu_notifier);
 	return 0;
 
-exit_devices_unreg:
-	mutex_lock(&pdev_list_mutex);
-	list_for_each_entry_safe(p, n, &pdev_list, list) {
-		platform_device_unregister(p->pdev);
-		list_del(&p->list);
-		kfree(p);
-	}
-	mutex_unlock(&pdev_list_mutex);
+#ifndef CONFIG_HOTPLUG_CPU
 exit_driver_unreg:
 	platform_driver_unregister(&pkgtemp_driver);
+#endif
 exit:
 	return err;
 }
@@ -434,9 +423,8 @@
 static void __exit pkgtemp_exit(void)
 {
 	struct pdev_entry *p, *n;
-#ifdef CONFIG_HOTPLUG_CPU
+
 	unregister_hotcpu_notifier(&pkgtemp_cpu_notifier);
-#endif
 	mutex_lock(&pdev_list_mutex);
 	list_for_each_entry_safe(p, n, &pdev_list, list) {
 		platform_device_unregister(p->pdev);
diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c
index ffb793a..ec7fad7 100644
--- a/drivers/hwmon/via-cputemp.c
+++ b/drivers/hwmon/via-cputemp.c
@@ -22,10 +22,8 @@
  */
 
 #include <linux/module.h>
-#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/jiffies.h>
 #include <linux/hwmon.h>
 #include <linux/sysfs.h>
 #include <linux/hwmon-sysfs.h>
@@ -237,8 +235,7 @@
 	return err;
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
-static void via_cputemp_device_remove(unsigned int cpu)
+static void __cpuinit via_cputemp_device_remove(unsigned int cpu)
 {
 	struct pdev_entry *p, *n;
 	mutex_lock(&pdev_list_mutex);
@@ -272,7 +269,6 @@
 static struct notifier_block via_cputemp_cpu_notifier __refdata = {
 	.notifier_call = via_cputemp_cpu_callback,
 };
-#endif				/* !CONFIG_HOTPLUG_CPU */
 
 static int __init via_cputemp_init(void)
 {
@@ -313,9 +309,7 @@
 		goto exit_driver_unreg;
 	}
 
-#ifdef CONFIG_HOTPLUG_CPU
 	register_hotcpu_notifier(&via_cputemp_cpu_notifier);
-#endif
 	return 0;
 
 exit_devices_unreg:
@@ -335,9 +329,8 @@
 static void __exit via_cputemp_exit(void)
 {
 	struct pdev_entry *p, *n;
-#ifdef CONFIG_HOTPLUG_CPU
+
 	unregister_hotcpu_notifier(&via_cputemp_cpu_notifier);
-#endif
 	mutex_lock(&pdev_list_mutex);
 	list_for_each_entry_safe(p, n, &pdev_list, list) {
 		platform_device_unregister(p->pdev);
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index cb3ccf3..41665d2 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -74,7 +74,7 @@
 static unsigned int mwait_substates;
 
 /* Reliable LAPIC Timer States, bit 1 for C1 etc.  */
-static unsigned int lapic_timer_reliable_states;
+static unsigned int lapic_timer_reliable_states = (1 << 1);	 /* Default to only C1 */
 
 static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
 static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state);
@@ -94,7 +94,6 @@
 		.driver_data = (void *) 0x00,
 		.flags = CPUIDLE_FLAG_TIME_VALID,
 		.exit_latency = 3,
-		.power_usage = 1000,
 		.target_residency = 6,
 		.enter = &intel_idle },
 	{ /* MWAIT C2 */
@@ -103,7 +102,6 @@
 		.driver_data = (void *) 0x10,
 		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
 		.exit_latency = 20,
-		.power_usage = 500,
 		.target_residency = 80,
 		.enter = &intel_idle },
 	{ /* MWAIT C3 */
@@ -112,11 +110,46 @@
 		.driver_data = (void *) 0x20,
 		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
 		.exit_latency = 200,
-		.power_usage = 350,
 		.target_residency = 800,
 		.enter = &intel_idle },
 };
 
+static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = {
+	{ /* MWAIT C0 */ },
+	{ /* MWAIT C1 */
+		.name = "SNB-C1",
+		.desc = "MWAIT 0x00",
+		.driver_data = (void *) 0x00,
+		.flags = CPUIDLE_FLAG_TIME_VALID,
+		.exit_latency = 1,
+		.target_residency = 4,
+		.enter = &intel_idle },
+	{ /* MWAIT C2 */
+		.name = "SNB-C3",
+		.desc = "MWAIT 0x10",
+		.driver_data = (void *) 0x10,
+		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+		.exit_latency = 80,
+		.target_residency = 160,
+		.enter = &intel_idle },
+	{ /* MWAIT C3 */
+		.name = "SNB-C6",
+		.desc = "MWAIT 0x20",
+		.driver_data = (void *) 0x20,
+		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+		.exit_latency = 104,
+		.target_residency = 208,
+		.enter = &intel_idle },
+	{ /* MWAIT C4 */
+		.name = "SNB-C7",
+		.desc = "MWAIT 0x30",
+		.driver_data = (void *) 0x30,
+		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+		.exit_latency = 109,
+		.target_residency = 300,
+		.enter = &intel_idle },
+};
+
 static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
 	{ /* MWAIT C0 */ },
 	{ /* MWAIT C1 */
@@ -125,7 +158,6 @@
 		.driver_data = (void *) 0x00,
 		.flags = CPUIDLE_FLAG_TIME_VALID,
 		.exit_latency = 1,
-		.power_usage = 1000,
 		.target_residency = 4,
 		.enter = &intel_idle },
 	{ /* MWAIT C2 */
@@ -134,7 +166,6 @@
 		.driver_data = (void *) 0x10,
 		.flags = CPUIDLE_FLAG_TIME_VALID,
 		.exit_latency = 20,
-		.power_usage = 500,
 		.target_residency = 80,
 		.enter = &intel_idle },
 	{ /* MWAIT C3 */ },
@@ -144,7 +175,6 @@
 		.driver_data = (void *) 0x30,
 		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
 		.exit_latency = 100,
-		.power_usage = 250,
 		.target_residency = 400,
 		.enter = &intel_idle },
 	{ /* MWAIT C5 */ },
@@ -154,7 +184,6 @@
 		.driver_data = (void *) 0x52,
 		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
 		.exit_latency = 140,
-		.power_usage = 150,
 		.target_residency = 560,
 		.enter = &intel_idle },
 };
@@ -179,13 +208,10 @@
 	local_irq_disable();
 
 	/*
-	 * If the state flag indicates that the TLB will be flushed or if this
-	 * is the deepest c-state supported, do a voluntary leave mm to avoid
-	 * costly and mostly unnecessary wakeups for flushing the user TLB's
-	 * associated with the active mm.
+	 * leave_mm() to avoid costly and often unnecessary wakeups
+	 * for flushing the user TLB's associated with the active mm.
 	 */
-	if (state->flags & CPUIDLE_FLAG_TLB_FLUSHED ||
-	    (&dev->states[dev->state_count - 1] == state))
+	if (state->flags & CPUIDLE_FLAG_TLB_FLUSHED)
 		leave_mm(cpu);
 
 	if (!(lapic_timer_reliable_states & (1 << (cstate))))
@@ -269,9 +295,14 @@
 
 	case 0x1C:	/* 28 - Atom Processor */
 	case 0x26:	/* 38 - Lincroft Atom Processor */
-		lapic_timer_reliable_states = (1 << 2) | (1 << 1); /* C2, C1 */
+		lapic_timer_reliable_states = (1 << 1); /* C1 */
 		cpuidle_state_table = atom_cstates;
 		break;
+
+	case 0x2A:	/* SNB */
+	case 0x2D:	/* SNB Xeon */
+		cpuidle_state_table = snb_cstates;
+		break;
 #ifdef FUTURE_USE
 	case 0x17:	/* 23 - Core 2 Duo */
 		lapic_timer_reliable_states = (1 << 2) | (1 << 1); /* C2, C1 */
diff --git a/drivers/infiniband/core/agent.c b/drivers/infiniband/core/agent.c
index ae7c288..91916a8 100644
--- a/drivers/infiniband/core/agent.c
+++ b/drivers/infiniband/core/agent.c
@@ -59,8 +59,8 @@
 	struct ib_agent_port_private *entry;
 
 	list_for_each_entry(entry, &ib_agent_port_list, port_list) {
-		if (entry->agent[0]->device == device &&
-		    entry->agent[0]->port_num == port_num)
+		if (entry->agent[1]->device == device &&
+		    entry->agent[1]->port_num == port_num)
 			return entry;
 	}
 	return NULL;
@@ -155,14 +155,16 @@
 		goto error1;
 	}
 
-	/* Obtain send only MAD agent for SMI QP */
-	port_priv->agent[0] = ib_register_mad_agent(device, port_num,
-						    IB_QPT_SMI, NULL, 0,
-						    &agent_send_handler,
-						    NULL, NULL);
-	if (IS_ERR(port_priv->agent[0])) {
-		ret = PTR_ERR(port_priv->agent[0]);
-		goto error2;
+	if (rdma_port_get_link_layer(device, port_num) == IB_LINK_LAYER_INFINIBAND) {
+		/* Obtain send only MAD agent for SMI QP */
+		port_priv->agent[0] = ib_register_mad_agent(device, port_num,
+							    IB_QPT_SMI, NULL, 0,
+							    &agent_send_handler,
+							    NULL, NULL);
+		if (IS_ERR(port_priv->agent[0])) {
+			ret = PTR_ERR(port_priv->agent[0]);
+			goto error2;
+		}
 	}
 
 	/* Obtain send only MAD agent for GSI QP */
@@ -182,7 +184,8 @@
 	return 0;
 
 error3:
-	ib_unregister_mad_agent(port_priv->agent[0]);
+	if (port_priv->agent[0])
+		ib_unregister_mad_agent(port_priv->agent[0]);
 error2:
 	kfree(port_priv);
 error1:
@@ -205,7 +208,9 @@
 	spin_unlock_irqrestore(&ib_agent_port_list_lock, flags);
 
 	ib_unregister_mad_agent(port_priv->agent[1]);
-	ib_unregister_mad_agent(port_priv->agent[0]);
+	if (port_priv->agent[0])
+		ib_unregister_mad_agent(port_priv->agent[0]);
+
 	kfree(port_priv);
 	return 0;
 }
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index b930b81..6884da2 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -59,6 +59,7 @@
 #define CMA_CM_RESPONSE_TIMEOUT 20
 #define CMA_MAX_CM_RETRIES 15
 #define CMA_CM_MRA_SETTING (IB_CM_MRA_FLAG_DELAY | 24)
+#define CMA_IBOE_PACKET_LIFETIME 18
 
 static void cma_add_one(struct ib_device *device);
 static void cma_remove_one(struct ib_device *device);
@@ -157,6 +158,7 @@
 	struct list_head	list;
 	void			*context;
 	struct sockaddr_storage	addr;
+	struct kref		mcref;
 };
 
 struct cma_work {
@@ -173,6 +175,12 @@
 	struct rdma_cm_event	event;
 };
 
+struct iboe_mcast_work {
+	struct work_struct	 work;
+	struct rdma_id_private	*id;
+	struct cma_multicast	*mc;
+};
+
 union cma_ip_addr {
 	struct in6_addr ip6;
 	struct {
@@ -281,6 +289,8 @@
 	atomic_inc(&cma_dev->refcount);
 	id_priv->cma_dev = cma_dev;
 	id_priv->id.device = cma_dev->device;
+	id_priv->id.route.addr.dev_addr.transport =
+		rdma_node_get_transport(cma_dev->device->node_type);
 	list_add_tail(&id_priv->list, &cma_dev->id_list);
 }
 
@@ -290,6 +300,14 @@
 		complete(&cma_dev->comp);
 }
 
+static inline void release_mc(struct kref *kref)
+{
+	struct cma_multicast *mc = container_of(kref, struct cma_multicast, mcref);
+
+	kfree(mc->multicast.ib);
+	kfree(mc);
+}
+
 static void cma_detach_from_dev(struct rdma_id_private *id_priv)
 {
 	list_del(&id_priv->list);
@@ -323,22 +341,63 @@
 	return ret;
 }
 
+static int find_gid_port(struct ib_device *device, union ib_gid *gid, u8 port_num)
+{
+	int i;
+	int err;
+	struct ib_port_attr props;
+	union ib_gid tmp;
+
+	err = ib_query_port(device, port_num, &props);
+	if (err)
+		return 1;
+
+	for (i = 0; i < props.gid_tbl_len; ++i) {
+		err = ib_query_gid(device, port_num, i, &tmp);
+		if (err)
+			return 1;
+		if (!memcmp(&tmp, gid, sizeof tmp))
+			return 0;
+	}
+
+	return -EAGAIN;
+}
+
 static int cma_acquire_dev(struct rdma_id_private *id_priv)
 {
 	struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
 	struct cma_device *cma_dev;
-	union ib_gid gid;
+	union ib_gid gid, iboe_gid;
 	int ret = -ENODEV;
+	u8 port;
+	enum rdma_link_layer dev_ll = dev_addr->dev_type == ARPHRD_INFINIBAND ?
+		IB_LINK_LAYER_INFINIBAND : IB_LINK_LAYER_ETHERNET;
 
-	rdma_addr_get_sgid(dev_addr, &gid);
+	iboe_addr_get_sgid(dev_addr, &iboe_gid);
+	memcpy(&gid, dev_addr->src_dev_addr +
+	       rdma_addr_gid_offset(dev_addr), sizeof gid);
 	list_for_each_entry(cma_dev, &dev_list, list) {
-		ret = ib_find_cached_gid(cma_dev->device, &gid,
-					 &id_priv->id.port_num, NULL);
-		if (!ret) {
-			cma_attach_to_dev(id_priv, cma_dev);
-			break;
+		for (port = 1; port <= cma_dev->device->phys_port_cnt; ++port) {
+			if (rdma_port_get_link_layer(cma_dev->device, port) == dev_ll) {
+				if (rdma_node_get_transport(cma_dev->device->node_type) == RDMA_TRANSPORT_IB &&
+				    rdma_port_get_link_layer(cma_dev->device, port) == IB_LINK_LAYER_ETHERNET)
+					ret = find_gid_port(cma_dev->device, &iboe_gid, port);
+				else
+					ret = find_gid_port(cma_dev->device, &gid, port);
+
+				if (!ret) {
+					id_priv->id.port_num = port;
+					goto out;
+				} else if (ret == 1)
+					break;
+			}
 		}
 	}
+
+out:
+	if (!ret)
+		cma_attach_to_dev(id_priv, cma_dev);
+
 	return ret;
 }
 
@@ -556,10 +615,16 @@
 {
 	struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
 	int ret;
+	u16 pkey;
+
+	if (rdma_port_get_link_layer(id_priv->id.device, id_priv->id.port_num) ==
+	    IB_LINK_LAYER_INFINIBAND)
+		pkey = ib_addr_get_pkey(dev_addr);
+	else
+		pkey = 0xffff;
 
 	ret = ib_find_cached_pkey(id_priv->id.device, id_priv->id.port_num,
-				  ib_addr_get_pkey(dev_addr),
-				  &qp_attr->pkey_index);
+				  pkey, &qp_attr->pkey_index);
 	if (ret)
 		return ret;
 
@@ -737,8 +802,8 @@
 
 static void cma_cancel_route(struct rdma_id_private *id_priv)
 {
-	switch (rdma_node_get_transport(id_priv->id.device->node_type)) {
-	case RDMA_TRANSPORT_IB:
+	switch (rdma_port_get_link_layer(id_priv->id.device, id_priv->id.port_num)) {
+	case IB_LINK_LAYER_INFINIBAND:
 		if (id_priv->query)
 			ib_sa_cancel_query(id_priv->query_id, id_priv->query);
 		break;
@@ -816,8 +881,17 @@
 		mc = container_of(id_priv->mc_list.next,
 				  struct cma_multicast, list);
 		list_del(&mc->list);
-		ib_sa_free_multicast(mc->multicast.ib);
-		kfree(mc);
+		switch (rdma_port_get_link_layer(id_priv->cma_dev->device, id_priv->id.port_num)) {
+		case IB_LINK_LAYER_INFINIBAND:
+			ib_sa_free_multicast(mc->multicast.ib);
+			kfree(mc);
+			break;
+		case IB_LINK_LAYER_ETHERNET:
+			kref_put(&mc->mcref, release_mc);
+			break;
+		default:
+			break;
+		}
 	}
 }
 
@@ -833,7 +907,7 @@
 	mutex_lock(&lock);
 	if (id_priv->cma_dev) {
 		mutex_unlock(&lock);
-		switch (rdma_node_get_transport(id->device->node_type)) {
+		switch (rdma_node_get_transport(id_priv->id.device->node_type)) {
 		case RDMA_TRANSPORT_IB:
 			if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib))
 				ib_destroy_cm_id(id_priv->cm_id.ib);
@@ -1708,6 +1782,81 @@
 	return 0;
 }
 
+static int cma_resolve_iboe_route(struct rdma_id_private *id_priv)
+{
+	struct rdma_route *route = &id_priv->id.route;
+	struct rdma_addr *addr = &route->addr;
+	struct cma_work *work;
+	int ret;
+	struct sockaddr_in *src_addr = (struct sockaddr_in *)&route->addr.src_addr;
+	struct sockaddr_in *dst_addr = (struct sockaddr_in *)&route->addr.dst_addr;
+	struct net_device *ndev = NULL;
+	u16 vid;
+
+	if (src_addr->sin_family != dst_addr->sin_family)
+		return -EINVAL;
+
+	work = kzalloc(sizeof *work, GFP_KERNEL);
+	if (!work)
+		return -ENOMEM;
+
+	work->id = id_priv;
+	INIT_WORK(&work->work, cma_work_handler);
+
+	route->path_rec = kzalloc(sizeof *route->path_rec, GFP_KERNEL);
+	if (!route->path_rec) {
+		ret = -ENOMEM;
+		goto err1;
+	}
+
+	route->num_paths = 1;
+
+	if (addr->dev_addr.bound_dev_if)
+		ndev = dev_get_by_index(&init_net, addr->dev_addr.bound_dev_if);
+	if (!ndev) {
+		ret = -ENODEV;
+		goto err2;
+	}
+
+	vid = rdma_vlan_dev_vlan_id(ndev);
+
+	iboe_mac_vlan_to_ll(&route->path_rec->sgid, addr->dev_addr.src_dev_addr, vid);
+	iboe_mac_vlan_to_ll(&route->path_rec->dgid, addr->dev_addr.dst_dev_addr, vid);
+
+	route->path_rec->hop_limit = 1;
+	route->path_rec->reversible = 1;
+	route->path_rec->pkey = cpu_to_be16(0xffff);
+	route->path_rec->mtu_selector = IB_SA_EQ;
+	route->path_rec->sl = id_priv->tos >> 5;
+
+	route->path_rec->mtu = iboe_get_mtu(ndev->mtu);
+	route->path_rec->rate_selector = IB_SA_EQ;
+	route->path_rec->rate = iboe_get_rate(ndev);
+	dev_put(ndev);
+	route->path_rec->packet_life_time_selector = IB_SA_EQ;
+	route->path_rec->packet_life_time = CMA_IBOE_PACKET_LIFETIME;
+	if (!route->path_rec->mtu) {
+		ret = -EINVAL;
+		goto err2;
+	}
+
+	work->old_state = CMA_ROUTE_QUERY;
+	work->new_state = CMA_ROUTE_RESOLVED;
+	work->event.event = RDMA_CM_EVENT_ROUTE_RESOLVED;
+	work->event.status = 0;
+
+	queue_work(cma_wq, &work->work);
+
+	return 0;
+
+err2:
+	kfree(route->path_rec);
+	route->path_rec = NULL;
+err1:
+	kfree(work);
+	return ret;
+}
+
 int rdma_resolve_route(struct rdma_cm_id *id, int timeout_ms)
 {
 	struct rdma_id_private *id_priv;
@@ -1720,7 +1869,16 @@
 	atomic_inc(&id_priv->refcount);
 	switch (rdma_node_get_transport(id->device->node_type)) {
 	case RDMA_TRANSPORT_IB:
-		ret = cma_resolve_ib_route(id_priv, timeout_ms);
+		switch (rdma_port_get_link_layer(id->device, id->port_num)) {
+		case IB_LINK_LAYER_INFINIBAND:
+			ret = cma_resolve_ib_route(id_priv, timeout_ms);
+			break;
+		case IB_LINK_LAYER_ETHERNET:
+			ret = cma_resolve_iboe_route(id_priv);
+			break;
+		default:
+			ret = -ENOSYS;
+		}
 		break;
 	case RDMA_TRANSPORT_IWARP:
 		ret = cma_resolve_iw_route(id_priv, timeout_ms);
@@ -1773,7 +1931,7 @@
 		goto out;
 
 	id_priv->id.route.addr.dev_addr.dev_type =
-		(rdma_node_get_transport(cma_dev->device->node_type) == RDMA_TRANSPORT_IB) ?
+		(rdma_port_get_link_layer(cma_dev->device, p) == IB_LINK_LAYER_INFINIBAND) ?
 		ARPHRD_INFINIBAND : ARPHRD_ETHER;
 
 	rdma_addr_set_sgid(&id_priv->id.route.addr.dev_addr, &gid);
@@ -2758,6 +2916,102 @@
 	return 0;
 }
 
+static void iboe_mcast_work_handler(struct work_struct *work)
+{
+	struct iboe_mcast_work *mw = container_of(work, struct iboe_mcast_work, work);
+	struct cma_multicast *mc = mw->mc;
+	struct ib_sa_multicast *m = mc->multicast.ib;
+
+	mc->multicast.ib->context = mc;
+	cma_ib_mc_handler(0, m);
+	kref_put(&mc->mcref, release_mc);
+	kfree(mw);
+}
+
+static void cma_iboe_set_mgid(struct sockaddr *addr, union ib_gid *mgid)
+{
+	struct sockaddr_in *sin = (struct sockaddr_in *)addr;
+	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
+
+	if (cma_any_addr(addr)) {
+		memset(mgid, 0, sizeof *mgid);
+	} else if (addr->sa_family == AF_INET6) {
+		memcpy(mgid, &sin6->sin6_addr, sizeof *mgid);
+	} else {
+		mgid->raw[0] = 0xff;
+		mgid->raw[1] = 0x0e;
+		mgid->raw[2] = 0;
+		mgid->raw[3] = 0;
+		mgid->raw[4] = 0;
+		mgid->raw[5] = 0;
+		mgid->raw[6] = 0;
+		mgid->raw[7] = 0;
+		mgid->raw[8] = 0;
+		mgid->raw[9] = 0;
+		mgid->raw[10] = 0xff;
+		mgid->raw[11] = 0xff;
+		*(__be32 *)(&mgid->raw[12]) = sin->sin_addr.s_addr;
+	}
+}
+
+static int cma_iboe_join_multicast(struct rdma_id_private *id_priv,
+				   struct cma_multicast *mc)
+{
+	struct iboe_mcast_work *work;
+	struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
+	int err;
+	struct sockaddr *addr = (struct sockaddr *)&mc->addr;
+	struct net_device *ndev = NULL;
+
+	if (cma_zero_addr((struct sockaddr *)&mc->addr))
+		return -EINVAL;
+
+	work = kzalloc(sizeof *work, GFP_KERNEL);
+	if (!work)
+		return -ENOMEM;
+
+	mc->multicast.ib = kzalloc(sizeof(struct ib_sa_multicast), GFP_KERNEL);
+	if (!mc->multicast.ib) {
+		err = -ENOMEM;
+		goto out1;
+	}
+
+	cma_iboe_set_mgid(addr, &mc->multicast.ib->rec.mgid);
+
+	mc->multicast.ib->rec.pkey = cpu_to_be16(0xffff);
+	if (id_priv->id.ps == RDMA_PS_UDP)
+		mc->multicast.ib->rec.qkey = cpu_to_be32(RDMA_UDP_QKEY);
+
+	if (dev_addr->bound_dev_if)
+		ndev = dev_get_by_index(&init_net, dev_addr->bound_dev_if);
+	if (!ndev) {
+		err = -ENODEV;
+		goto out2;
+	}
+	mc->multicast.ib->rec.rate = iboe_get_rate(ndev);
+	mc->multicast.ib->rec.hop_limit = 1;
+	mc->multicast.ib->rec.mtu = iboe_get_mtu(ndev->mtu);
+	dev_put(ndev);
+	if (!mc->multicast.ib->rec.mtu) {
+		err = -EINVAL;
+		goto out2;
+	}
+	iboe_addr_get_sgid(dev_addr, &mc->multicast.ib->rec.port_gid);
+	work->id = id_priv;
+	work->mc = mc;
+	INIT_WORK(&work->work, iboe_mcast_work_handler);
+	kref_get(&mc->mcref);
+	queue_work(cma_wq, &work->work);
+
+	return 0;
+
+out2:
+	kfree(mc->multicast.ib);
+out1:
+	kfree(work);
+	return err;
+}
+
 int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr,
 			void *context)
 {
@@ -2784,7 +3038,17 @@
 
 	switch (rdma_node_get_transport(id->device->node_type)) {
 	case RDMA_TRANSPORT_IB:
-		ret = cma_join_ib_multicast(id_priv, mc);
+		switch (rdma_port_get_link_layer(id->device, id->port_num)) {
+		case IB_LINK_LAYER_INFINIBAND:
+			ret = cma_join_ib_multicast(id_priv, mc);
+			break;
+		case IB_LINK_LAYER_ETHERNET:
+			kref_init(&mc->mcref);
+			ret = cma_iboe_join_multicast(id_priv, mc);
+			break;
+		default:
+			ret = -EINVAL;
+		}
 		break;
 	default:
 		ret = -ENOSYS;
@@ -2817,8 +3081,19 @@
 				ib_detach_mcast(id->qp,
 						&mc->multicast.ib->rec.mgid,
 						mc->multicast.ib->rec.mlid);
-			ib_sa_free_multicast(mc->multicast.ib);
-			kfree(mc);
+			if (rdma_node_get_transport(id_priv->cma_dev->device->node_type) == RDMA_TRANSPORT_IB) {
+				switch (rdma_port_get_link_layer(id->device, id->port_num)) {
+				case IB_LINK_LAYER_INFINIBAND:
+					ib_sa_free_multicast(mc->multicast.ib);
+					kfree(mc);
+					break;
+				case IB_LINK_LAYER_ETHERNET:
+					kref_put(&mc->mcref, release_mc);
+					break;
+				default:
+					break;
+				}
+			}
 			return;
 		}
 	}
diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c
index bfead5b..2a1e9ae 100644
--- a/drivers/infiniband/core/iwcm.c
+++ b/drivers/infiniband/core/iwcm.c
@@ -506,6 +506,8 @@
 	qp = cm_id->device->iwcm->get_qp(cm_id->device, iw_param->qpn);
 	if (!qp) {
 		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+		clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags);
+		wake_up_all(&cm_id_priv->connect_wait);
 		return -EINVAL;
 	}
 	cm_id->device->iwcm->add_ref(qp);
@@ -565,6 +567,8 @@
 	qp = cm_id->device->iwcm->get_qp(cm_id->device, iw_param->qpn);
 	if (!qp) {
 		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+		clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags);
+		wake_up_all(&cm_id_priv->connect_wait);
 		return -EINVAL;
 	}
 	cm_id->device->iwcm->add_ref(qp);
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index ef1304f..822cfdc 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -2598,6 +2598,9 @@
 	struct ib_mad_private *recv;
 	struct ib_mad_list_head *mad_list;
 
+	if (!qp_info->qp)
+		return;
+
 	while (!list_empty(&qp_info->recv_queue.list)) {
 
 		mad_list = list_entry(qp_info->recv_queue.list.next,
@@ -2639,6 +2642,9 @@
 
 	for (i = 0; i < IB_MAD_QPS_CORE; i++) {
 		qp = port_priv->qp_info[i].qp;
+		if (!qp)
+			continue;
+
 		/*
 		 * PKey index for QP1 is irrelevant but
 		 * one is needed for the Reset to Init transition
@@ -2680,6 +2686,9 @@
 	}
 
 	for (i = 0; i < IB_MAD_QPS_CORE; i++) {
+		if (!port_priv->qp_info[i].qp)
+			continue;
+
 		ret = ib_mad_post_receive_mads(&port_priv->qp_info[i], NULL);
 		if (ret) {
 			printk(KERN_ERR PFX "Couldn't post receive WRs\n");
@@ -2758,6 +2767,9 @@
 
 static void destroy_mad_qp(struct ib_mad_qp_info *qp_info)
 {
+	if (!qp_info->qp)
+		return;
+
 	ib_destroy_qp(qp_info->qp);
 	kfree(qp_info->snoop_table);
 }
@@ -2773,6 +2785,7 @@
 	struct ib_mad_port_private *port_priv;
 	unsigned long flags;
 	char name[sizeof "ib_mad123"];
+	int has_smi;
 
 	/* Create new device info */
 	port_priv = kzalloc(sizeof *port_priv, GFP_KERNEL);
@@ -2788,7 +2801,11 @@
 	init_mad_qp(port_priv, &port_priv->qp_info[0]);
 	init_mad_qp(port_priv, &port_priv->qp_info[1]);
 
-	cq_size = (mad_sendq_size + mad_recvq_size) * 2;
+	cq_size = mad_sendq_size + mad_recvq_size;
+	has_smi = rdma_port_get_link_layer(device, port_num) == IB_LINK_LAYER_INFINIBAND;
+	if (has_smi)
+		cq_size *= 2;
+
 	port_priv->cq = ib_create_cq(port_priv->device,
 				     ib_mad_thread_completion_handler,
 				     NULL, port_priv, cq_size, 0);
@@ -2812,9 +2829,11 @@
 		goto error5;
 	}
 
-	ret = create_mad_qp(&port_priv->qp_info[0], IB_QPT_SMI);
-	if (ret)
-		goto error6;
+	if (has_smi) {
+		ret = create_mad_qp(&port_priv->qp_info[0], IB_QPT_SMI);
+		if (ret)
+			goto error6;
+	}
 	ret = create_mad_qp(&port_priv->qp_info[1], IB_QPT_GSI);
 	if (ret)
 		goto error7;
diff --git a/drivers/infiniband/core/multicast.c b/drivers/infiniband/core/multicast.c
index a519801..68b4162 100644
--- a/drivers/infiniband/core/multicast.c
+++ b/drivers/infiniband/core/multicast.c
@@ -774,6 +774,10 @@
 	int index;
 
 	dev = container_of(handler, struct mcast_device, event_handler);
+	if (rdma_port_get_link_layer(dev->device, event->element.port_num) !=
+	    IB_LINK_LAYER_INFINIBAND)
+		return;
+
 	index = event->element.port_num - dev->start_port;
 
 	switch (event->event) {
@@ -796,6 +800,7 @@
 	struct mcast_device *dev;
 	struct mcast_port *port;
 	int i;
+	int count = 0;
 
 	if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB)
 		return;
@@ -813,6 +818,9 @@
 	}
 
 	for (i = 0; i <= dev->end_port - dev->start_port; i++) {
+		if (rdma_port_get_link_layer(device, dev->start_port + i) !=
+		    IB_LINK_LAYER_INFINIBAND)
+			continue;
 		port = &dev->port[i];
 		port->dev = dev;
 		port->port_num = dev->start_port + i;
@@ -820,6 +828,12 @@
 		port->table = RB_ROOT;
 		init_completion(&port->comp);
 		atomic_set(&port->refcount, 1);
+		++count;
+	}
+
+	if (!count) {
+		kfree(dev);
+		return;
 	}
 
 	dev->device = device;
@@ -843,9 +857,12 @@
 	flush_workqueue(mcast_wq);
 
 	for (i = 0; i <= dev->end_port - dev->start_port; i++) {
-		port = &dev->port[i];
-		deref_port(port);
-		wait_for_completion(&port->comp);
+		if (rdma_port_get_link_layer(device, dev->start_port + i) ==
+		    IB_LINK_LAYER_INFINIBAND) {
+			port = &dev->port[i];
+			deref_port(port);
+			wait_for_completion(&port->comp);
+		}
 	}
 
 	kfree(dev);
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index 7e1ffd8c..91a6603 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -416,6 +416,9 @@
 		struct ib_sa_port *port =
 			&sa_dev->port[event->element.port_num - sa_dev->start_port];
 
+		if (rdma_port_get_link_layer(handler->device, port->port_num) != IB_LINK_LAYER_INFINIBAND)
+			return;
+
 		spin_lock_irqsave(&port->ah_lock, flags);
 		if (port->sm_ah)
 			kref_put(&port->sm_ah->ref, free_sm_ah);
@@ -493,6 +496,7 @@
 {
 	int ret;
 	u16 gid_index;
+	int force_grh;
 
 	memset(ah_attr, 0, sizeof *ah_attr);
 	ah_attr->dlid = be16_to_cpu(rec->dlid);
@@ -502,7 +506,9 @@
 	ah_attr->port_num = port_num;
 	ah_attr->static_rate = rec->rate;
 
-	if (rec->hop_limit > 1) {
+	force_grh = rdma_port_get_link_layer(device, port_num) == IB_LINK_LAYER_ETHERNET;
+
+	if (rec->hop_limit > 1 || force_grh) {
 		ah_attr->ah_flags = IB_AH_GRH;
 		ah_attr->grh.dgid = rec->dgid;
 
@@ -1007,7 +1013,7 @@
 		e = device->phys_port_cnt;
 	}
 
-	sa_dev = kmalloc(sizeof *sa_dev +
+	sa_dev = kzalloc(sizeof *sa_dev +
 			 (e - s + 1) * sizeof (struct ib_sa_port),
 			 GFP_KERNEL);
 	if (!sa_dev)
@@ -1017,9 +1023,12 @@
 	sa_dev->end_port   = e;
 
 	for (i = 0; i <= e - s; ++i) {
+		spin_lock_init(&sa_dev->port[i].ah_lock);
+		if (rdma_port_get_link_layer(device, i + 1) != IB_LINK_LAYER_INFINIBAND)
+			continue;
+
 		sa_dev->port[i].sm_ah    = NULL;
 		sa_dev->port[i].port_num = i + s;
-		spin_lock_init(&sa_dev->port[i].ah_lock);
 
 		sa_dev->port[i].agent =
 			ib_register_mad_agent(device, i + s, IB_QPT_GSI,
@@ -1045,13 +1054,15 @@
 		goto err;
 
 	for (i = 0; i <= e - s; ++i)
-		update_sm_ah(&sa_dev->port[i].update_task);
+		if (rdma_port_get_link_layer(device, i + 1) == IB_LINK_LAYER_INFINIBAND)
+			update_sm_ah(&sa_dev->port[i].update_task);
 
 	return;
 
 err:
 	while (--i >= 0)
-		ib_unregister_mad_agent(sa_dev->port[i].agent);
+		if (rdma_port_get_link_layer(device, i + 1) == IB_LINK_LAYER_INFINIBAND)
+			ib_unregister_mad_agent(sa_dev->port[i].agent);
 
 	kfree(sa_dev);
 
@@ -1071,9 +1082,12 @@
 	flush_scheduled_work();
 
 	for (i = 0; i <= sa_dev->end_port - sa_dev->start_port; ++i) {
-		ib_unregister_mad_agent(sa_dev->port[i].agent);
-		if (sa_dev->port[i].sm_ah)
-			kref_put(&sa_dev->port[i].sm_ah->ref, free_sm_ah);
+		if (rdma_port_get_link_layer(device, i + 1) == IB_LINK_LAYER_INFINIBAND) {
+			ib_unregister_mad_agent(sa_dev->port[i].agent);
+			if (sa_dev->port[i].sm_ah)
+				kref_put(&sa_dev->port[i].sm_ah->ref, free_sm_ah);
+		}
+
 	}
 
 	kfree(sa_dev);
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index 3627300..9ab5df7 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -222,6 +222,19 @@
 	}
 }
 
+static ssize_t link_layer_show(struct ib_port *p, struct port_attribute *unused,
+			       char *buf)
+{
+	switch (rdma_port_get_link_layer(p->ibdev, p->port_num)) {
+	case IB_LINK_LAYER_INFINIBAND:
+		return sprintf(buf, "%s\n", "InfiniBand");
+	case IB_LINK_LAYER_ETHERNET:
+		return sprintf(buf, "%s\n", "Ethernet");
+	default:
+		return sprintf(buf, "%s\n", "Unknown");
+	}
+}
+
 static PORT_ATTR_RO(state);
 static PORT_ATTR_RO(lid);
 static PORT_ATTR_RO(lid_mask_count);
@@ -230,6 +243,7 @@
 static PORT_ATTR_RO(cap_mask);
 static PORT_ATTR_RO(rate);
 static PORT_ATTR_RO(phys_state);
+static PORT_ATTR_RO(link_layer);
 
 static struct attribute *port_default_attrs[] = {
 	&port_attr_state.attr,
@@ -240,6 +254,7 @@
 	&port_attr_cap_mask.attr,
 	&port_attr_rate.attr,
 	&port_attr_phys_state.attr,
+	&port_attr_link_layer.attr,
 	NULL
 };
 
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
index ac7edc2..ca12acf 100644
--- a/drivers/infiniband/core/ucma.c
+++ b/drivers/infiniband/core/ucma.c
@@ -40,6 +40,7 @@
 #include <linux/in6.h>
 #include <linux/miscdevice.h>
 #include <linux/slab.h>
+#include <linux/sysctl.h>
 
 #include <rdma/rdma_user_cm.h>
 #include <rdma/ib_marshall.h>
@@ -50,8 +51,24 @@
 MODULE_DESCRIPTION("RDMA Userspace Connection Manager Access");
 MODULE_LICENSE("Dual BSD/GPL");
 
-enum {
-	UCMA_MAX_BACKLOG	= 128
+static unsigned int max_backlog = 1024;
+
+static struct ctl_table_header *ucma_ctl_table_hdr;
+static ctl_table ucma_ctl_table[] = {
+	{
+		.procname	= "max_backlog",
+		.data		= &max_backlog,
+		.maxlen		= sizeof max_backlog,
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec,
+	},
+	{ }
+};
+
+static struct ctl_path ucma_ctl_path[] = {
+	{ .procname = "net" },
+	{ .procname = "rdma_ucm" },
+	{ }
 };
 
 struct ucma_file {
@@ -583,6 +600,42 @@
 	}
 }
 
+static void ucma_copy_iboe_route(struct rdma_ucm_query_route_resp *resp,
+				 struct rdma_route *route)
+{
+	struct rdma_dev_addr *dev_addr;
+	struct net_device *dev;
+	u16 vid = 0;
+
+	resp->num_paths = route->num_paths;
+	switch (route->num_paths) {
+	case 0:
+		dev_addr = &route->addr.dev_addr;
+		dev = dev_get_by_index(&init_net, dev_addr->bound_dev_if);
+			if (dev) {
+				vid = rdma_vlan_dev_vlan_id(dev);
+				dev_put(dev);
+			}
+
+		iboe_mac_vlan_to_ll((union ib_gid *) &resp->ib_route[0].dgid,
+				    dev_addr->dst_dev_addr, vid);
+		iboe_addr_get_sgid(dev_addr,
+				   (union ib_gid *) &resp->ib_route[0].sgid);
+		resp->ib_route[0].pkey = cpu_to_be16(0xffff);
+		break;
+	case 2:
+		ib_copy_path_rec_to_user(&resp->ib_route[1],
+					 &route->path_rec[1]);
+		/* fall through */
+	case 1:
+		ib_copy_path_rec_to_user(&resp->ib_route[0],
+					 &route->path_rec[0]);
+		break;
+	default:
+		break;
+	}
+}
+
 static ssize_t ucma_query_route(struct ucma_file *file,
 				const char __user *inbuf,
 				int in_len, int out_len)
@@ -617,12 +670,17 @@
 
 	resp.node_guid = (__force __u64) ctx->cm_id->device->node_guid;
 	resp.port_num = ctx->cm_id->port_num;
-	switch (rdma_node_get_transport(ctx->cm_id->device->node_type)) {
-	case RDMA_TRANSPORT_IB:
-		ucma_copy_ib_route(&resp, &ctx->cm_id->route);
-		break;
-	default:
-		break;
+	if (rdma_node_get_transport(ctx->cm_id->device->node_type) == RDMA_TRANSPORT_IB) {
+		switch (rdma_port_get_link_layer(ctx->cm_id->device, ctx->cm_id->port_num)) {
+		case IB_LINK_LAYER_INFINIBAND:
+			ucma_copy_ib_route(&resp, &ctx->cm_id->route);
+			break;
+		case IB_LINK_LAYER_ETHERNET:
+			ucma_copy_iboe_route(&resp, &ctx->cm_id->route);
+			break;
+		default:
+			break;
+		}
 	}
 
 out:
@@ -686,8 +744,8 @@
 	if (IS_ERR(ctx))
 		return PTR_ERR(ctx);
 
-	ctx->backlog = cmd.backlog > 0 && cmd.backlog < UCMA_MAX_BACKLOG ?
-		       cmd.backlog : UCMA_MAX_BACKLOG;
+	ctx->backlog = cmd.backlog > 0 && cmd.backlog < max_backlog ?
+		       cmd.backlog : max_backlog;
 	ret = rdma_listen(ctx->cm_id, ctx->backlog);
 	ucma_put_ctx(ctx);
 	return ret;
@@ -1279,16 +1337,26 @@
 	ret = device_create_file(ucma_misc.this_device, &dev_attr_abi_version);
 	if (ret) {
 		printk(KERN_ERR "rdma_ucm: couldn't create abi_version attr\n");
-		goto err;
+		goto err1;
+	}
+
+	ucma_ctl_table_hdr = register_sysctl_paths(ucma_ctl_path, ucma_ctl_table);
+	if (!ucma_ctl_table_hdr) {
+		printk(KERN_ERR "rdma_ucm: couldn't register sysctl paths\n");
+		ret = -ENOMEM;
+		goto err2;
 	}
 	return 0;
-err:
+err2:
+	device_remove_file(ucma_misc.this_device, &dev_attr_abi_version);
+err1:
 	misc_deregister(&ucma_misc);
 	return ret;
 }
 
 static void __exit ucma_cleanup(void)
 {
+	unregister_sysctl_table(ucma_ctl_table_hdr);
 	device_remove_file(ucma_misc.this_device, &dev_attr_abi_version);
 	misc_deregister(&ucma_misc);
 	idr_destroy(&ctx_idr);
diff --git a/drivers/infiniband/core/ud_header.c b/drivers/infiniband/core/ud_header.c
index 650b501..bb7e192 100644
--- a/drivers/infiniband/core/ud_header.c
+++ b/drivers/infiniband/core/ud_header.c
@@ -33,6 +33,7 @@
 
 #include <linux/errno.h>
 #include <linux/string.h>
+#include <linux/if_ether.h>
 
 #include <rdma/ib_pack.h>
 
@@ -80,6 +81,40 @@
 	  .size_bits    = 16 }
 };
 
+static const struct ib_field eth_table[]  = {
+	{ STRUCT_FIELD(eth, dmac_h),
+	  .offset_words = 0,
+	  .offset_bits  = 0,
+	  .size_bits    = 32 },
+	{ STRUCT_FIELD(eth, dmac_l),
+	  .offset_words = 1,
+	  .offset_bits  = 0,
+	  .size_bits    = 16 },
+	{ STRUCT_FIELD(eth, smac_h),
+	  .offset_words = 1,
+	  .offset_bits  = 16,
+	  .size_bits    = 16 },
+	{ STRUCT_FIELD(eth, smac_l),
+	  .offset_words = 2,
+	  .offset_bits  = 0,
+	  .size_bits    = 32 },
+	{ STRUCT_FIELD(eth, type),
+	  .offset_words = 3,
+	  .offset_bits  = 0,
+	  .size_bits    = 16 }
+};
+
+static const struct ib_field vlan_table[]  = {
+	{ STRUCT_FIELD(vlan, tag),
+	  .offset_words = 0,
+	  .offset_bits  = 0,
+	  .size_bits    = 16 },
+	{ STRUCT_FIELD(vlan, type),
+	  .offset_words = 0,
+	  .offset_bits  = 16,
+	  .size_bits    = 16 }
+};
+
 static const struct ib_field grh_table[]  = {
 	{ STRUCT_FIELD(grh, ip_version),
 	  .offset_words = 0,
@@ -180,38 +215,43 @@
 /**
  * ib_ud_header_init - Initialize UD header structure
  * @payload_bytes:Length of packet payload
+ * @lrh_present: specify if LRH is present
+ * @eth_present: specify if Eth header is present
+ * @vlan_present: packet is tagged vlan
  * @grh_present:GRH flag (if non-zero, GRH will be included)
- * @immediate_present: specify if immediate data should be used
+ * @immediate_present: specify if immediate data is present
  * @header:Structure to initialize
- *
- * ib_ud_header_init() initializes the lrh.link_version, lrh.link_next_header,
- * lrh.packet_length, grh.ip_version, grh.payload_length,
- * grh.next_header, bth.opcode, bth.pad_count and
- * bth.transport_header_version fields of a &struct ib_ud_header given
- * the payload length and whether a GRH will be included.
  */
 void ib_ud_header_init(int     		    payload_bytes,
+		       int		    lrh_present,
+		       int		    eth_present,
+		       int		    vlan_present,
 		       int    		    grh_present,
 		       int		    immediate_present,
 		       struct ib_ud_header *header)
 {
-	u16 packet_length;
-
 	memset(header, 0, sizeof *header);
 
-	header->lrh.link_version     = 0;
-	header->lrh.link_next_header =
-		grh_present ? IB_LNH_IBA_GLOBAL : IB_LNH_IBA_LOCAL;
-	packet_length		     = (IB_LRH_BYTES     +
-					IB_BTH_BYTES     +
-					IB_DETH_BYTES    +
-					payload_bytes    +
-					4                + /* ICRC     */
-					3) / 4;            /* round up */
+	if (lrh_present) {
+		u16 packet_length;
 
-	header->grh_present          = grh_present;
+		header->lrh.link_version     = 0;
+		header->lrh.link_next_header =
+			grh_present ? IB_LNH_IBA_GLOBAL : IB_LNH_IBA_LOCAL;
+		packet_length = (IB_LRH_BYTES	+
+				 IB_BTH_BYTES	+
+				 IB_DETH_BYTES	+
+				 (grh_present ? IB_GRH_BYTES : 0) +
+				 payload_bytes	+
+				 4		+ /* ICRC     */
+				 3) / 4;	  /* round up */
+		header->lrh.packet_length = cpu_to_be16(packet_length);
+	}
+
+	if (vlan_present)
+		header->eth.type = cpu_to_be16(ETH_P_8021Q);
+
 	if (grh_present) {
-		packet_length		   += IB_GRH_BYTES / 4;
 		header->grh.ip_version      = 6;
 		header->grh.payload_length  =
 			cpu_to_be16((IB_BTH_BYTES     +
@@ -222,19 +262,52 @@
 		header->grh.next_header     = 0x1b;
 	}
 
-	header->lrh.packet_length = cpu_to_be16(packet_length);
-
-	header->immediate_present	     = immediate_present;
 	if (immediate_present)
 		header->bth.opcode           = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE;
 	else
 		header->bth.opcode           = IB_OPCODE_UD_SEND_ONLY;
 	header->bth.pad_count                = (4 - payload_bytes) & 3;
 	header->bth.transport_header_version = 0;
+
+	header->lrh_present = lrh_present;
+	header->eth_present = eth_present;
+	header->vlan_present = vlan_present;
+	header->grh_present = grh_present;
+	header->immediate_present = immediate_present;
 }
 EXPORT_SYMBOL(ib_ud_header_init);
 
 /**
+ * ib_lrh_header_pack - Pack LRH header struct into wire format
+ * @lrh:unpacked LRH header struct
+ * @buf:Buffer to pack into
+ *
+ * ib_lrh_header_pack() packs the LRH header structure @lrh into
+ * wire format in the buffer @buf.
+ */
+int ib_lrh_header_pack(struct ib_unpacked_lrh *lrh, void *buf)
+{
+	ib_pack(lrh_table, ARRAY_SIZE(lrh_table), lrh, buf);
+	return 0;
+}
+EXPORT_SYMBOL(ib_lrh_header_pack);
+
+/**
+ * ib_lrh_header_unpack - Unpack LRH structure from wire format
+ * @lrh:unpacked LRH header struct
+ * @buf:Buffer to pack into
+ *
+ * ib_lrh_header_unpack() unpacks the LRH header structure from
+ * wire format (in buf) into @lrh.
+ */
+int ib_lrh_header_unpack(void *buf, struct ib_unpacked_lrh *lrh)
+{
+	ib_unpack(lrh_table, ARRAY_SIZE(lrh_table), buf, lrh);
+	return 0;
+}
+EXPORT_SYMBOL(ib_lrh_header_unpack);
+
+/**
  * ib_ud_header_pack - Pack UD header struct into wire format
  * @header:UD header struct
  * @buf:Buffer to pack into
@@ -247,10 +320,21 @@
 {
 	int len = 0;
 
-	ib_pack(lrh_table, ARRAY_SIZE(lrh_table),
-		&header->lrh, buf);
-	len += IB_LRH_BYTES;
-
+	if (header->lrh_present) {
+		ib_pack(lrh_table, ARRAY_SIZE(lrh_table),
+			&header->lrh, buf + len);
+		len += IB_LRH_BYTES;
+	}
+	if (header->eth_present) {
+		ib_pack(eth_table, ARRAY_SIZE(eth_table),
+			&header->eth, buf + len);
+		len += IB_ETH_BYTES;
+	}
+	if (header->vlan_present) {
+		ib_pack(vlan_table, ARRAY_SIZE(vlan_table),
+			&header->vlan, buf + len);
+		len += IB_VLAN_BYTES;
+	}
 	if (header->grh_present) {
 		ib_pack(grh_table, ARRAY_SIZE(grh_table),
 			&header->grh, buf + len);
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index 5fa8569..cd1996d 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -1022,7 +1022,7 @@
 
 	port->ib_dev   = device;
 	port->port_num = port_num;
-	init_MUTEX(&port->sm_sem);
+	sema_init(&port->sm_sem, 1);
 	mutex_init(&port->file_mutex);
 	INIT_LIST_HEAD(&port->file_list);
 
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 6fcfbeb..b342248 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -460,6 +460,8 @@
 	resp.active_width    = attr.active_width;
 	resp.active_speed    = attr.active_speed;
 	resp.phys_state      = attr.phys_state;
+	resp.link_layer      = rdma_port_get_link_layer(file->device->ib_dev,
+							cmd.port_num);
 
 	if (copy_to_user((void __user *) (unsigned long) cmd.response,
 			 &resp, sizeof resp))
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index e0fa222..af7a8b0 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -94,6 +94,22 @@
 }
 EXPORT_SYMBOL(rdma_node_get_transport);
 
+enum rdma_link_layer rdma_port_get_link_layer(struct ib_device *device, u8 port_num)
+{
+	if (device->get_link_layer)
+		return device->get_link_layer(device, port_num);
+
+	switch (rdma_node_get_transport(device->node_type)) {
+	case RDMA_TRANSPORT_IB:
+		return IB_LINK_LAYER_INFINIBAND;
+	case RDMA_TRANSPORT_IWARP:
+		return IB_LINK_LAYER_ETHERNET;
+	default:
+		return IB_LINK_LAYER_UNSPECIFIED;
+	}
+}
+EXPORT_SYMBOL(rdma_port_get_link_layer);
+
 /* Protection domains */
 
 struct ib_pd *ib_alloc_pd(struct ib_device *device)
diff --git a/drivers/infiniband/hw/amso1100/Kbuild b/drivers/infiniband/hw/amso1100/Kbuild
index 06964c4..950dfab 100644
--- a/drivers/infiniband/hw/amso1100/Kbuild
+++ b/drivers/infiniband/hw/amso1100/Kbuild
@@ -1,6 +1,4 @@
-ifdef CONFIG_INFINIBAND_AMSO1100_DEBUG
-EXTRA_CFLAGS += -DDEBUG
-endif
+ccflags-$(CONFIG_INFINIBAND_AMSO1100_DEBUG) := -DDEBUG
 
 obj-$(CONFIG_INFINIBAND_AMSO1100) += iw_c2.o
 
diff --git a/drivers/infiniband/hw/amso1100/c2_intr.c b/drivers/infiniband/hw/amso1100/c2_intr.c
index 3b50954..0ebe4e8 100644
--- a/drivers/infiniband/hw/amso1100/c2_intr.c
+++ b/drivers/infiniband/hw/amso1100/c2_intr.c
@@ -62,8 +62,8 @@
 static void handle_mq(struct c2_dev *c2dev, u32 mq_index)
 {
 	if (c2dev->qptr_array[mq_index] == NULL) {
-		pr_debug(KERN_INFO "handle_mq: stray activity for mq_index=%d\n",
-			mq_index);
+		pr_debug("handle_mq: stray activity for mq_index=%d\n",
+			 mq_index);
 		return;
 	}
 
diff --git a/drivers/infiniband/hw/cxgb3/Makefile b/drivers/infiniband/hw/cxgb3/Makefile
index 7e7b5a6..621619c 100644
--- a/drivers/infiniband/hw/cxgb3/Makefile
+++ b/drivers/infiniband/hw/cxgb3/Makefile
@@ -1,10 +1,8 @@
-EXTRA_CFLAGS += -Idrivers/net/cxgb3
+ccflags-y := -Idrivers/net/cxgb3
 
 obj-$(CONFIG_INFINIBAND_CXGB3) += iw_cxgb3.o
 
 iw_cxgb3-y :=  iwch_cm.o iwch_ev.o iwch_cq.o iwch_qp.o iwch_mem.o \
 	       iwch_provider.o iwch.o cxio_hal.o cxio_resource.o
 
-ifdef CONFIG_INFINIBAND_CXGB3_DEBUG
-EXTRA_CFLAGS += -DDEBUG
-endif
+ccflags-$(CONFIG_INFINIBAND_CXGB3_DEBUG) += -DDEBUG
diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.c b/drivers/infiniband/hw/cxgb3/cxio_hal.c
index 005b7b5..09dda0b 100644
--- a/drivers/infiniband/hw/cxgb3/cxio_hal.c
+++ b/drivers/infiniband/hw/cxgb3/cxio_hal.c
@@ -160,6 +160,7 @@
 	struct rdma_cq_setup setup;
 	int size = (1UL << (cq->size_log2)) * sizeof(struct t3_cqe);
 
+	size += 1; /* one extra page for storing cq-in-err state */
 	cq->cqid = cxio_hal_get_cqid(rdev_p->rscp);
 	if (!cq->cqid)
 		return -ENOMEM;
diff --git a/drivers/infiniband/hw/cxgb3/cxio_wr.h b/drivers/infiniband/hw/cxgb3/cxio_wr.h
index e5ddb63..4bb997a 100644
--- a/drivers/infiniband/hw/cxgb3/cxio_wr.h
+++ b/drivers/infiniband/hw/cxgb3/cxio_wr.h
@@ -728,6 +728,22 @@
 #define CQ_VLD_ENTRY(ptr,size_log2,cqe) (Q_GENBIT(ptr,size_log2) == \
 					 CQE_GENBIT(*cqe))
 
+struct t3_cq_status_page {
+	u32 cq_err;
+};
+
+static inline int cxio_cq_in_error(struct t3_cq *cq)
+{
+	return ((struct t3_cq_status_page *)
+		&cq->queue[1 << cq->size_log2])->cq_err;
+}
+
+static inline void cxio_set_cq_in_error(struct t3_cq *cq)
+{
+	((struct t3_cq_status_page *)
+	 &cq->queue[1 << cq->size_log2])->cq_err = 1;
+}
+
 static inline void cxio_set_wq_in_error(struct t3_wq *wq)
 {
 	wq->queue->wq_in_err.err |= 1;
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
index 13c8887..d02dcc6 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
@@ -1093,8 +1093,8 @@
 	PDBG("%s ep %p credits %u\n", __func__, ep, credits);
 
 	if (credits == 0) {
-		PDBG(KERN_ERR "%s 0 credit ack  ep %p state %u\n",
-			__func__, ep, state_read(&ep->com));
+		PDBG("%s 0 credit ack  ep %p state %u\n",
+		     __func__, ep, state_read(&ep->com));
 		return CPL_RET_BUF_DONE;
 	}
 
diff --git a/drivers/infiniband/hw/cxgb3/iwch_ev.c b/drivers/infiniband/hw/cxgb3/iwch_ev.c
index 6afc89e..71e0d84 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_ev.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_ev.c
@@ -76,6 +76,14 @@
 	atomic_inc(&qhp->refcnt);
 	spin_unlock(&rnicp->lock);
 
+	if (qhp->attr.state == IWCH_QP_STATE_RTS) {
+		attrs.next_state = IWCH_QP_STATE_TERMINATE;
+		iwch_modify_qp(qhp->rhp, qhp, IWCH_QP_ATTR_NEXT_STATE,
+			       &attrs, 1);
+		if (send_term)
+			iwch_post_terminate(qhp, rsp_msg);
+	}
+
 	event.event = ib_event;
 	event.device = chp->ibcq.device;
 	if (ib_event == IB_EVENT_CQ_ERR)
@@ -86,13 +94,7 @@
 	if (qhp->ibqp.event_handler)
 		(*qhp->ibqp.event_handler)(&event, qhp->ibqp.qp_context);
 
-	if (qhp->attr.state == IWCH_QP_STATE_RTS) {
-		attrs.next_state = IWCH_QP_STATE_TERMINATE;
-		iwch_modify_qp(qhp->rhp, qhp, IWCH_QP_ATTR_NEXT_STATE,
-			       &attrs, 1);
-		if (send_term)
-			iwch_post_terminate(qhp, rsp_msg);
-	}
+	(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
 
 	if (atomic_dec_and_test(&qhp->refcnt))
 		wake_up(&qhp->wait);
@@ -179,7 +181,6 @@
 	case TPT_ERR_BOUND:
 	case TPT_ERR_INVALIDATE_SHARED_MR:
 	case TPT_ERR_INVALIDATE_MR_WITH_MW_BOUND:
-		(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
 		post_qp_event(rnicp, chp, rsp_msg, IB_EVENT_QP_ACCESS_ERR, 1);
 		break;
 
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index fca0b4b..2e27413 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -154,6 +154,8 @@
 	struct iwch_create_cq_resp uresp;
 	struct iwch_create_cq_req ureq;
 	struct iwch_ucontext *ucontext = NULL;
+	static int warned;
+	size_t resplen;
 
 	PDBG("%s ib_dev %p entries %d\n", __func__, ibdev, entries);
 	rhp = to_iwch_dev(ibdev);
@@ -217,15 +219,26 @@
 		uresp.key = ucontext->key;
 		ucontext->key += PAGE_SIZE;
 		spin_unlock(&ucontext->mmap_lock);
-		if (ib_copy_to_udata(udata, &uresp, sizeof (uresp))) {
+		mm->key = uresp.key;
+		mm->addr = virt_to_phys(chp->cq.queue);
+		if (udata->outlen < sizeof uresp) {
+			if (!warned++)
+				printk(KERN_WARNING MOD "Warning - "
+				       "downlevel libcxgb3 (non-fatal).\n");
+			mm->len = PAGE_ALIGN((1UL << uresp.size_log2) *
+					     sizeof(struct t3_cqe));
+			resplen = sizeof(struct iwch_create_cq_resp_v0);
+		} else {
+			mm->len = PAGE_ALIGN(((1UL << uresp.size_log2) + 1) *
+					     sizeof(struct t3_cqe));
+			uresp.memsize = mm->len;
+			resplen = sizeof uresp;
+		}
+		if (ib_copy_to_udata(udata, &uresp, resplen)) {
 			kfree(mm);
 			iwch_destroy_cq(&chp->ibcq);
 			return ERR_PTR(-EFAULT);
 		}
-		mm->key = uresp.key;
-		mm->addr = virt_to_phys(chp->cq.queue);
-		mm->len = PAGE_ALIGN((1UL << uresp.size_log2) *
-					     sizeof (struct t3_cqe));
 		insert_mmap(ucontext, mm);
 	}
 	PDBG("created cqid 0x%0x chp %p size 0x%0x, dma_addr 0x%0llx\n",
@@ -1414,6 +1427,7 @@
 	dev->ibdev.post_send = iwch_post_send;
 	dev->ibdev.post_recv = iwch_post_receive;
 	dev->ibdev.get_protocol_stats = iwch_get_mib;
+	dev->ibdev.uverbs_abi_ver = IWCH_UVERBS_ABI_VERSION;
 
 	dev->ibdev.iwcm = kmalloc(sizeof(struct iw_cm_verbs), GFP_KERNEL);
 	if (!dev->ibdev.iwcm)
diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c
index c64d27b..0993137 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_qp.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c
@@ -802,14 +802,12 @@
 /*
  * Assumes qhp lock is held.
  */
-static void __flush_qp(struct iwch_qp *qhp, unsigned long *flag)
+static void __flush_qp(struct iwch_qp *qhp, struct iwch_cq *rchp,
+				struct iwch_cq *schp, unsigned long *flag)
 {
-	struct iwch_cq *rchp, *schp;
 	int count;
 	int flushed;
 
-	rchp = get_chp(qhp->rhp, qhp->attr.rcq);
-	schp = get_chp(qhp->rhp, qhp->attr.scq);
 
 	PDBG("%s qhp %p rchp %p schp %p\n", __func__, qhp, rchp, schp);
 	/* take a ref on the qhp since we must release the lock */
@@ -847,10 +845,23 @@
 
 static void flush_qp(struct iwch_qp *qhp, unsigned long *flag)
 {
-	if (qhp->ibqp.uobject)
+	struct iwch_cq *rchp, *schp;
+
+	rchp = get_chp(qhp->rhp, qhp->attr.rcq);
+	schp = get_chp(qhp->rhp, qhp->attr.scq);
+
+	if (qhp->ibqp.uobject) {
 		cxio_set_wq_in_error(&qhp->wq);
-	else
-		__flush_qp(qhp, flag);
+		cxio_set_cq_in_error(&rchp->cq);
+		(*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
+		if (schp != rchp) {
+			cxio_set_cq_in_error(&schp->cq);
+			(*schp->ibcq.comp_handler)(&schp->ibcq,
+						   schp->ibcq.cq_context);
+		}
+		return;
+	}
+	__flush_qp(qhp, rchp, schp, flag);
 }
 
 
diff --git a/drivers/infiniband/hw/cxgb3/iwch_user.h b/drivers/infiniband/hw/cxgb3/iwch_user.h
index cb7086f..a277c31 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_user.h
+++ b/drivers/infiniband/hw/cxgb3/iwch_user.h
@@ -45,10 +45,18 @@
 	__u64 user_rptr_addr;
 };
 
+struct iwch_create_cq_resp_v0 {
+	__u64 key;
+	__u32 cqid;
+	__u32 size_log2;
+};
+
 struct iwch_create_cq_resp {
 	__u64 key;
 	__u32 cqid;
 	__u32 size_log2;
+	__u32 memsize;
+	__u32 reserved;
 };
 
 struct iwch_create_qp_resp {
diff --git a/drivers/infiniband/hw/cxgb4/Makefile b/drivers/infiniband/hw/cxgb4/Makefile
index e31a499..cd20b13 100644
--- a/drivers/infiniband/hw/cxgb4/Makefile
+++ b/drivers/infiniband/hw/cxgb4/Makefile
@@ -1,4 +1,4 @@
-EXTRA_CFLAGS += -Idrivers/net/cxgb4
+ccflags-y := -Idrivers/net/cxgb4
 
 obj-$(CONFIG_INFINIBAND_CXGB4) += iw_cxgb4.o
 
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
index 32d352a..0dc62b1 100644
--- a/drivers/infiniband/hw/cxgb4/cm.c
+++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -117,9 +117,9 @@
 module_param(rcv_win, int, 0644);
 MODULE_PARM_DESC(rcv_win, "TCP receive window in bytes (default=256KB)");
 
-static int snd_win = 32 * 1024;
+static int snd_win = 128 * 1024;
 module_param(snd_win, int, 0644);
-MODULE_PARM_DESC(snd_win, "TCP send window in bytes (default=32KB)");
+MODULE_PARM_DESC(snd_win, "TCP send window in bytes (default=128KB)");
 
 static struct workqueue_struct *workq;
 
@@ -172,7 +172,7 @@
 	error = cxgb4_l2t_send(rdev->lldi.ports[0], skb, l2e);
 	if (error < 0)
 		kfree_skb(skb);
-	return error;
+	return error < 0 ? error : 0;
 }
 
 int c4iw_ofld_send(struct c4iw_rdev *rdev, struct sk_buff *skb)
@@ -187,7 +187,7 @@
 	error = cxgb4_ofld_send(rdev->lldi.ports[0], skb);
 	if (error < 0)
 		kfree_skb(skb);
-	return error;
+	return error < 0 ? error : 0;
 }
 
 static void release_tid(struct c4iw_rdev *rdev, u32 hwtid, struct sk_buff *skb)
@@ -219,12 +219,11 @@
 
 static enum c4iw_ep_state state_read(struct c4iw_ep_common *epc)
 {
-	unsigned long flags;
 	enum c4iw_ep_state state;
 
-	spin_lock_irqsave(&epc->lock, flags);
+	mutex_lock(&epc->mutex);
 	state = epc->state;
-	spin_unlock_irqrestore(&epc->lock, flags);
+	mutex_unlock(&epc->mutex);
 	return state;
 }
 
@@ -235,12 +234,10 @@
 
 static void state_set(struct c4iw_ep_common *epc, enum c4iw_ep_state new)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&epc->lock, flags);
+	mutex_lock(&epc->mutex);
 	PDBG("%s - %s -> %s\n", __func__, states[epc->state], states[new]);
 	__state_set(epc, new);
-	spin_unlock_irqrestore(&epc->lock, flags);
+	mutex_unlock(&epc->mutex);
 	return;
 }
 
@@ -251,8 +248,8 @@
 	epc = kzalloc(size, gfp);
 	if (epc) {
 		kref_init(&epc->kref);
-		spin_lock_init(&epc->lock);
-		init_waitqueue_head(&epc->waitq);
+		mutex_init(&epc->mutex);
+		c4iw_init_wr_wait(&epc->wr_wait);
 	}
 	PDBG("%s alloc ep %p\n", __func__, epc);
 	return epc;
@@ -1131,7 +1128,6 @@
 {
 	struct c4iw_ep *ep;
 	struct cpl_abort_rpl_rss *rpl = cplhdr(skb);
-	unsigned long flags;
 	int release = 0;
 	unsigned int tid = GET_TID(rpl);
 	struct tid_info *t = dev->rdev.lldi.tids;
@@ -1139,7 +1135,7 @@
 	ep = lookup_tid(t, tid);
 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
 	BUG_ON(!ep);
-	spin_lock_irqsave(&ep->com.lock, flags);
+	mutex_lock(&ep->com.mutex);
 	switch (ep->com.state) {
 	case ABORTING:
 		__state_set(&ep->com, DEAD);
@@ -1150,7 +1146,7 @@
 		     __func__, ep, ep->com.state);
 		break;
 	}
-	spin_unlock_irqrestore(&ep->com.lock, flags);
+	mutex_unlock(&ep->com.mutex);
 
 	if (release)
 		release_ep_resources(ep);
@@ -1213,9 +1209,9 @@
 	}
 	PDBG("%s ep %p status %d error %d\n", __func__, ep,
 	     rpl->status, status2errno(rpl->status));
-	ep->com.rpl_err = status2errno(rpl->status);
-	ep->com.rpl_done = 1;
-	wake_up(&ep->com.waitq);
+	ep->com.wr_wait.ret = status2errno(rpl->status);
+	ep->com.wr_wait.done = 1;
+	wake_up(&ep->com.wr_wait.wait);
 
 	return 0;
 }
@@ -1249,9 +1245,9 @@
 	struct c4iw_listen_ep *ep = lookup_stid(t, stid);
 
 	PDBG("%s ep %p\n", __func__, ep);
-	ep->com.rpl_err = status2errno(rpl->status);
-	ep->com.rpl_done = 1;
-	wake_up(&ep->com.waitq);
+	ep->com.wr_wait.ret = status2errno(rpl->status);
+	ep->com.wr_wait.done = 1;
+	wake_up(&ep->com.wr_wait.wait);
 	return 0;
 }
 
@@ -1478,7 +1474,6 @@
 	struct cpl_peer_close *hdr = cplhdr(skb);
 	struct c4iw_ep *ep;
 	struct c4iw_qp_attributes attrs;
-	unsigned long flags;
 	int disconnect = 1;
 	int release = 0;
 	int closing = 0;
@@ -1489,7 +1484,7 @@
 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
 	dst_confirm(ep->dst);
 
-	spin_lock_irqsave(&ep->com.lock, flags);
+	mutex_lock(&ep->com.mutex);
 	switch (ep->com.state) {
 	case MPA_REQ_WAIT:
 		__state_set(&ep->com, CLOSING);
@@ -1507,17 +1502,17 @@
 		 * in rdma connection migration (see c4iw_accept_cr()).
 		 */
 		__state_set(&ep->com, CLOSING);
-		ep->com.rpl_done = 1;
-		ep->com.rpl_err = -ECONNRESET;
+		ep->com.wr_wait.done = 1;
+		ep->com.wr_wait.ret = -ECONNRESET;
 		PDBG("waking up ep %p tid %u\n", ep, ep->hwtid);
-		wake_up(&ep->com.waitq);
+		wake_up(&ep->com.wr_wait.wait);
 		break;
 	case MPA_REP_SENT:
 		__state_set(&ep->com, CLOSING);
-		ep->com.rpl_done = 1;
-		ep->com.rpl_err = -ECONNRESET;
+		ep->com.wr_wait.done = 1;
+		ep->com.wr_wait.ret = -ECONNRESET;
 		PDBG("waking up ep %p tid %u\n", ep, ep->hwtid);
-		wake_up(&ep->com.waitq);
+		wake_up(&ep->com.wr_wait.wait);
 		break;
 	case FPDU_MODE:
 		start_ep_timer(ep);
@@ -1550,7 +1545,7 @@
 	default:
 		BUG_ON(1);
 	}
-	spin_unlock_irqrestore(&ep->com.lock, flags);
+	mutex_unlock(&ep->com.mutex);
 	if (closing) {
 		attrs.next_state = C4IW_QP_STATE_CLOSING;
 		c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
@@ -1581,7 +1576,6 @@
 	struct c4iw_qp_attributes attrs;
 	int ret;
 	int release = 0;
-	unsigned long flags;
 	struct tid_info *t = dev->rdev.lldi.tids;
 	unsigned int tid = GET_TID(req);
 
@@ -1591,9 +1585,17 @@
 		     ep->hwtid);
 		return 0;
 	}
-	spin_lock_irqsave(&ep->com.lock, flags);
 	PDBG("%s ep %p tid %u state %u\n", __func__, ep, ep->hwtid,
 	     ep->com.state);
+
+	/*
+	 * Wake up any threads in rdma_init() or rdma_fini().
+	 */
+	ep->com.wr_wait.done = 1;
+	ep->com.wr_wait.ret = -ECONNRESET;
+	wake_up(&ep->com.wr_wait.wait);
+
+	mutex_lock(&ep->com.mutex);
 	switch (ep->com.state) {
 	case CONNECTING:
 		break;
@@ -1605,23 +1607,8 @@
 		connect_reply_upcall(ep, -ECONNRESET);
 		break;
 	case MPA_REP_SENT:
-		ep->com.rpl_done = 1;
-		ep->com.rpl_err = -ECONNRESET;
-		PDBG("waking up ep %p\n", ep);
-		wake_up(&ep->com.waitq);
 		break;
 	case MPA_REQ_RCVD:
-
-		/*
-		 * We're gonna mark this puppy DEAD, but keep
-		 * the reference on it until the ULP accepts or
-		 * rejects the CR. Also wake up anyone waiting
-		 * in rdma connection migration (see c4iw_accept_cr()).
-		 */
-		ep->com.rpl_done = 1;
-		ep->com.rpl_err = -ECONNRESET;
-		PDBG("waking up ep %p tid %u\n", ep, ep->hwtid);
-		wake_up(&ep->com.waitq);
 		break;
 	case MORIBUND:
 	case CLOSING:
@@ -1644,7 +1631,7 @@
 		break;
 	case DEAD:
 		PDBG("%s PEER_ABORT IN DEAD STATE!!!!\n", __func__);
-		spin_unlock_irqrestore(&ep->com.lock, flags);
+		mutex_unlock(&ep->com.mutex);
 		return 0;
 	default:
 		BUG_ON(1);
@@ -1655,7 +1642,7 @@
 		__state_set(&ep->com, DEAD);
 		release = 1;
 	}
-	spin_unlock_irqrestore(&ep->com.lock, flags);
+	mutex_unlock(&ep->com.mutex);
 
 	rpl_skb = get_skb(skb, sizeof(*rpl), GFP_KERNEL);
 	if (!rpl_skb) {
@@ -1681,7 +1668,6 @@
 	struct c4iw_ep *ep;
 	struct c4iw_qp_attributes attrs;
 	struct cpl_close_con_rpl *rpl = cplhdr(skb);
-	unsigned long flags;
 	int release = 0;
 	struct tid_info *t = dev->rdev.lldi.tids;
 	unsigned int tid = GET_TID(rpl);
@@ -1692,7 +1678,7 @@
 	BUG_ON(!ep);
 
 	/* The cm_id may be null if we failed to connect */
-	spin_lock_irqsave(&ep->com.lock, flags);
+	mutex_lock(&ep->com.mutex);
 	switch (ep->com.state) {
 	case CLOSING:
 		__state_set(&ep->com, MORIBUND);
@@ -1717,7 +1703,7 @@
 		BUG_ON(1);
 		break;
 	}
-	spin_unlock_irqrestore(&ep->com.lock, flags);
+	mutex_unlock(&ep->com.mutex);
 	if (release)
 		release_ep_resources(ep);
 	return 0;
@@ -1725,23 +1711,24 @@
 
 static int terminate(struct c4iw_dev *dev, struct sk_buff *skb)
 {
-	struct c4iw_ep *ep;
-	struct cpl_rdma_terminate *term = cplhdr(skb);
+	struct cpl_rdma_terminate *rpl = cplhdr(skb);
 	struct tid_info *t = dev->rdev.lldi.tids;
-	unsigned int tid = GET_TID(term);
+	unsigned int tid = GET_TID(rpl);
+	struct c4iw_ep *ep;
+	struct c4iw_qp_attributes attrs;
 
 	ep = lookup_tid(t, tid);
+	BUG_ON(!ep);
 
-	if (state_read(&ep->com) != FPDU_MODE)
-		return 0;
+	if (ep->com.qp) {
+		printk(KERN_WARNING MOD "TERM received tid %u qpid %u\n", tid,
+		       ep->com.qp->wq.sq.qid);
+		attrs.next_state = C4IW_QP_STATE_TERMINATE;
+		c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
+			       C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
+	} else
+		printk(KERN_WARNING MOD "TERM received tid %u no qp\n", tid);
 
-	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
-	skb_pull(skb, sizeof *term);
-	PDBG("%s saving %d bytes of term msg\n", __func__, skb->len);
-	skb_copy_from_linear_data(skb, ep->com.qp->attr.terminate_buffer,
-				  skb->len);
-	ep->com.qp->attr.terminate_msg_len = skb->len;
-	ep->com.qp->attr.is_terminate_local = 0;
 	return 0;
 }
 
@@ -1762,8 +1749,8 @@
 	ep = lookup_tid(t, tid);
 	PDBG("%s ep %p tid %u credits %u\n", __func__, ep, ep->hwtid, credits);
 	if (credits == 0) {
-		PDBG(KERN_ERR "%s 0 credit ack ep %p tid %u state %u\n",
-			__func__, ep, ep->hwtid, state_read(&ep->com));
+		PDBG("%s 0 credit ack ep %p tid %u state %u\n",
+		     __func__, ep, ep->hwtid, state_read(&ep->com));
 		return 0;
 	}
 
@@ -2042,6 +2029,7 @@
 	}
 
 	state_set(&ep->com, LISTEN);
+	c4iw_init_wr_wait(&ep->com.wr_wait);
 	err = cxgb4_create_server(ep->com.dev->rdev.lldi.ports[0], ep->stid,
 				  ep->com.local_addr.sin_addr.s_addr,
 				  ep->com.local_addr.sin_port,
@@ -2050,15 +2038,8 @@
 		goto fail3;
 
 	/* wait for pass_open_rpl */
-	wait_event_timeout(ep->com.waitq, ep->com.rpl_done, C4IW_WR_TO);
-	if (ep->com.rpl_done)
-		err = ep->com.rpl_err;
-	else {
-		printk(KERN_ERR MOD "Device %s not responding!\n",
-		       pci_name(ep->com.dev->rdev.lldi.pdev));
-		ep->com.dev->rdev.flags = T4_FATAL_ERROR;
-		err = -EIO;
-	}
+	err = c4iw_wait_for_reply(&ep->com.dev->rdev, &ep->com.wr_wait, 0, 0,
+				  __func__);
 	if (!err) {
 		cm_id->provider_data = ep;
 		goto out;
@@ -2082,20 +2063,12 @@
 
 	might_sleep();
 	state_set(&ep->com, DEAD);
-	ep->com.rpl_done = 0;
-	ep->com.rpl_err = 0;
+	c4iw_init_wr_wait(&ep->com.wr_wait);
 	err = listen_stop(ep);
 	if (err)
 		goto done;
-	wait_event_timeout(ep->com.waitq, ep->com.rpl_done, C4IW_WR_TO);
-	if (ep->com.rpl_done)
-		err = ep->com.rpl_err;
-	else {
-		printk(KERN_ERR MOD "Device %s not responding!\n",
-		       pci_name(ep->com.dev->rdev.lldi.pdev));
-		ep->com.dev->rdev.flags = T4_FATAL_ERROR;
-		err = -EIO;
-	}
+	err = c4iw_wait_for_reply(&ep->com.dev->rdev, &ep->com.wr_wait, 0, 0,
+				  __func__);
 	cxgb4_free_stid(ep->com.dev->rdev.lldi.tids, ep->stid, PF_INET);
 done:
 	cm_id->rem_ref(cm_id);
@@ -2106,12 +2079,11 @@
 int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
 {
 	int ret = 0;
-	unsigned long flags;
 	int close = 0;
 	int fatal = 0;
 	struct c4iw_rdev *rdev;
 
-	spin_lock_irqsave(&ep->com.lock, flags);
+	mutex_lock(&ep->com.mutex);
 
 	PDBG("%s ep %p state %s, abrupt %d\n", __func__, ep,
 	     states[ep->com.state], abrupt);
@@ -2158,7 +2130,7 @@
 		break;
 	}
 
-	spin_unlock_irqrestore(&ep->com.lock, flags);
+	mutex_unlock(&ep->com.mutex);
 	if (close) {
 		if (abrupt)
 			ret = abort_connection(ep, NULL, gfp);
@@ -2172,6 +2144,13 @@
 	return ret;
 }
 
+static int async_event(struct c4iw_dev *dev, struct sk_buff *skb)
+{
+	struct cpl_fw6_msg *rpl = cplhdr(skb);
+	c4iw_ev_dispatch(dev, (struct t4_cqe *)&rpl->data[0]);
+	return 0;
+}
+
 /*
  * These are the real handlers that are called from a
  * work queue.
@@ -2190,7 +2169,8 @@
 	[CPL_ABORT_REQ_RSS] = peer_abort,
 	[CPL_CLOSE_CON_RPL] = close_con_rpl,
 	[CPL_RDMA_TERMINATE] = terminate,
-	[CPL_FW4_ACK] = fw4_ack
+	[CPL_FW4_ACK] = fw4_ack,
+	[CPL_FW6_MSG] = async_event
 };
 
 static void process_timeout(struct c4iw_ep *ep)
@@ -2198,7 +2178,7 @@
 	struct c4iw_qp_attributes attrs;
 	int abort = 1;
 
-	spin_lock_irq(&ep->com.lock);
+	mutex_lock(&ep->com.mutex);
 	PDBG("%s ep %p tid %u state %d\n", __func__, ep, ep->hwtid,
 	     ep->com.state);
 	switch (ep->com.state) {
@@ -2225,7 +2205,7 @@
 		WARN_ON(1);
 		abort = 0;
 	}
-	spin_unlock_irq(&ep->com.lock);
+	mutex_unlock(&ep->com.mutex);
 	if (abort)
 		abort_connection(ep, NULL, GFP_KERNEL);
 	c4iw_put_ep(&ep->com);
@@ -2309,6 +2289,7 @@
 		printk(KERN_ERR MOD "Unexpected SET_TCB_RPL status %u "
 		       "for tid %u\n", rpl->status, GET_TID(rpl));
 	}
+	kfree_skb(skb);
 	return 0;
 }
 
@@ -2323,20 +2304,25 @@
 	switch (rpl->type) {
 	case 1:
 		ret = (int)((be64_to_cpu(rpl->data[0]) >> 8) & 0xff);
-		wr_waitp = (__force struct c4iw_wr_wait *)rpl->data[1];
+		wr_waitp = (struct c4iw_wr_wait *)(__force unsigned long) rpl->data[1];
 		PDBG("%s wr_waitp %p ret %u\n", __func__, wr_waitp, ret);
 		if (wr_waitp) {
-			wr_waitp->ret = ret;
+			if (ret)
+				wr_waitp->ret = -ret;
+			else
+				wr_waitp->ret = 0;
 			wr_waitp->done = 1;
 			wake_up(&wr_waitp->wait);
 		}
+		kfree_skb(skb);
 		break;
 	case 2:
-		c4iw_ev_dispatch(dev, (struct t4_cqe *)&rpl->data[0]);
+		sched(dev, skb);
 		break;
 	default:
 		printk(KERN_ERR MOD "%s unexpected fw6 msg type %u\n", __func__,
 		       rpl->type);
+		kfree_skb(skb);
 		break;
 	}
 	return 0;
diff --git a/drivers/infiniband/hw/cxgb4/cq.c b/drivers/infiniband/hw/cxgb4/cq.c
index b3daf39..8d8f8ad 100644
--- a/drivers/infiniband/hw/cxgb4/cq.c
+++ b/drivers/infiniband/hw/cxgb4/cq.c
@@ -55,7 +55,7 @@
 			V_FW_RI_RES_WR_NRES(1) |
 			FW_WR_COMPL(1));
 	res_wr->len16_pkd = cpu_to_be32(DIV_ROUND_UP(wr_len, 16));
-	res_wr->cookie = (u64)&wr_wait;
+	res_wr->cookie = (unsigned long) &wr_wait;
 	res = res_wr->res;
 	res->u.cq.restype = FW_RI_RES_TYPE_CQ;
 	res->u.cq.op = FW_RI_RES_OP_RESET;
@@ -64,14 +64,7 @@
 	c4iw_init_wr_wait(&wr_wait);
 	ret = c4iw_ofld_send(rdev, skb);
 	if (!ret) {
-		wait_event_timeout(wr_wait.wait, wr_wait.done, C4IW_WR_TO);
-		if (!wr_wait.done) {
-			printk(KERN_ERR MOD "Device %s not responding!\n",
-			       pci_name(rdev->lldi.pdev));
-			rdev->flags = T4_FATAL_ERROR;
-			ret = -EIO;
-		} else
-			ret = wr_wait.ret;
+		ret = c4iw_wait_for_reply(rdev, &wr_wait, 0, 0, __func__);
 	}
 
 	kfree(cq->sw_queue);
@@ -132,7 +125,7 @@
 			V_FW_RI_RES_WR_NRES(1) |
 			FW_WR_COMPL(1));
 	res_wr->len16_pkd = cpu_to_be32(DIV_ROUND_UP(wr_len, 16));
-	res_wr->cookie = (u64)&wr_wait;
+	res_wr->cookie = (unsigned long) &wr_wait;
 	res = res_wr->res;
 	res->u.cq.restype = FW_RI_RES_TYPE_CQ;
 	res->u.cq.op = FW_RI_RES_OP_WRITE;
@@ -157,14 +150,7 @@
 	if (ret)
 		goto err4;
 	PDBG("%s wait_event wr_wait %p\n", __func__, &wr_wait);
-	wait_event_timeout(wr_wait.wait, wr_wait.done, C4IW_WR_TO);
-	if (!wr_wait.done) {
-		printk(KERN_ERR MOD "Device %s not responding!\n",
-		       pci_name(rdev->lldi.pdev));
-		rdev->flags = T4_FATAL_ERROR;
-		ret = -EIO;
-	} else
-		ret = wr_wait.ret;
+	ret = c4iw_wait_for_reply(rdev, &wr_wait, 0, 0, __func__);
 	if (ret)
 		goto err4;
 
@@ -476,6 +462,11 @@
 		goto proc_cqe;
 	}
 
+	if (CQE_OPCODE(hw_cqe) == FW_RI_TERMINATE) {
+		ret = -EAGAIN;
+		goto skip_cqe;
+	}
+
 	/*
 	 * RECV completion.
 	 */
@@ -696,6 +687,7 @@
 		case T4_ERR_MSN_RANGE:
 		case T4_ERR_IRD_OVERFLOW:
 		case T4_ERR_OPCODE:
+		case T4_ERR_INTERNAL_ERR:
 			wc->status = IB_WC_FATAL_ERR;
 			break;
 		case T4_ERR_SWFLUSH:
diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c
index 9bbf491..54fbc11 100644
--- a/drivers/infiniband/hw/cxgb4/device.c
+++ b/drivers/infiniband/hw/cxgb4/device.c
@@ -49,29 +49,33 @@
 
 static struct dentry *c4iw_debugfs_root;
 
-struct debugfs_qp_data {
+struct c4iw_debugfs_data {
 	struct c4iw_dev *devp;
 	char *buf;
 	int bufsize;
 	int pos;
 };
 
-static int count_qps(int id, void *p, void *data)
+static int count_idrs(int id, void *p, void *data)
 {
-	struct c4iw_qp *qp = p;
 	int *countp = data;
 
-	if (id != qp->wq.sq.qid)
-		return 0;
-
 	*countp = *countp + 1;
 	return 0;
 }
 
-static int dump_qps(int id, void *p, void *data)
+static ssize_t debugfs_read(struct file *file, char __user *buf, size_t count,
+			    loff_t *ppos)
+{
+	struct c4iw_debugfs_data *d = file->private_data;
+
+	return simple_read_from_buffer(buf, count, ppos, d->buf, d->pos);
+}
+
+static int dump_qp(int id, void *p, void *data)
 {
 	struct c4iw_qp *qp = p;
-	struct debugfs_qp_data *qpd = data;
+	struct c4iw_debugfs_data *qpd = data;
 	int space;
 	int cc;
 
@@ -101,7 +105,7 @@
 
 static int qp_release(struct inode *inode, struct file *file)
 {
-	struct debugfs_qp_data *qpd = file->private_data;
+	struct c4iw_debugfs_data *qpd = file->private_data;
 	if (!qpd) {
 		printk(KERN_INFO "%s null qpd?\n", __func__);
 		return 0;
@@ -113,7 +117,7 @@
 
 static int qp_open(struct inode *inode, struct file *file)
 {
-	struct debugfs_qp_data *qpd;
+	struct c4iw_debugfs_data *qpd;
 	int ret = 0;
 	int count = 1;
 
@@ -126,7 +130,7 @@
 	qpd->pos = 0;
 
 	spin_lock_irq(&qpd->devp->lock);
-	idr_for_each(&qpd->devp->qpidr, count_qps, &count);
+	idr_for_each(&qpd->devp->qpidr, count_idrs, &count);
 	spin_unlock_irq(&qpd->devp->lock);
 
 	qpd->bufsize = count * 128;
@@ -137,7 +141,7 @@
 	}
 
 	spin_lock_irq(&qpd->devp->lock);
-	idr_for_each(&qpd->devp->qpidr, dump_qps, qpd);
+	idr_for_each(&qpd->devp->qpidr, dump_qp, qpd);
 	spin_unlock_irq(&qpd->devp->lock);
 
 	qpd->buf[qpd->pos++] = 0;
@@ -149,43 +153,86 @@
 	return ret;
 }
 
-static ssize_t qp_read(struct file *file, char __user *buf, size_t count,
-			loff_t *ppos)
-{
-	struct debugfs_qp_data *qpd = file->private_data;
-	loff_t pos = *ppos;
-	loff_t avail = qpd->pos;
-
-	if (pos < 0)
-		return -EINVAL;
-	if (pos >= avail)
-		return 0;
-	if (count > avail - pos)
-		count = avail - pos;
-
-	while (count) {
-		size_t len = 0;
-
-		len = min((int)count, (int)qpd->pos - (int)pos);
-		if (copy_to_user(buf, qpd->buf + pos, len))
-			return -EFAULT;
-		if (len == 0)
-			return -EINVAL;
-
-		buf += len;
-		pos += len;
-		count -= len;
-	}
-	count = pos - *ppos;
-	*ppos = pos;
-	return count;
-}
-
 static const struct file_operations qp_debugfs_fops = {
 	.owner   = THIS_MODULE,
 	.open    = qp_open,
 	.release = qp_release,
-	.read    = qp_read,
+	.read    = debugfs_read,
+	.llseek  = default_llseek,
+};
+
+static int dump_stag(int id, void *p, void *data)
+{
+	struct c4iw_debugfs_data *stagd = data;
+	int space;
+	int cc;
+
+	space = stagd->bufsize - stagd->pos - 1;
+	if (space == 0)
+		return 1;
+
+	cc = snprintf(stagd->buf + stagd->pos, space, "0x%x\n", id<<8);
+	if (cc < space)
+		stagd->pos += cc;
+	return 0;
+}
+
+static int stag_release(struct inode *inode, struct file *file)
+{
+	struct c4iw_debugfs_data *stagd = file->private_data;
+	if (!stagd) {
+		printk(KERN_INFO "%s null stagd?\n", __func__);
+		return 0;
+	}
+	kfree(stagd->buf);
+	kfree(stagd);
+	return 0;
+}
+
+static int stag_open(struct inode *inode, struct file *file)
+{
+	struct c4iw_debugfs_data *stagd;
+	int ret = 0;
+	int count = 1;
+
+	stagd = kmalloc(sizeof *stagd, GFP_KERNEL);
+	if (!stagd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	stagd->devp = inode->i_private;
+	stagd->pos = 0;
+
+	spin_lock_irq(&stagd->devp->lock);
+	idr_for_each(&stagd->devp->mmidr, count_idrs, &count);
+	spin_unlock_irq(&stagd->devp->lock);
+
+	stagd->bufsize = count * sizeof("0x12345678\n");
+	stagd->buf = kmalloc(stagd->bufsize, GFP_KERNEL);
+	if (!stagd->buf) {
+		ret = -ENOMEM;
+		goto err1;
+	}
+
+	spin_lock_irq(&stagd->devp->lock);
+	idr_for_each(&stagd->devp->mmidr, dump_stag, stagd);
+	spin_unlock_irq(&stagd->devp->lock);
+
+	stagd->buf[stagd->pos++] = 0;
+	file->private_data = stagd;
+	goto out;
+err1:
+	kfree(stagd);
+out:
+	return ret;
+}
+
+static const struct file_operations stag_debugfs_fops = {
+	.owner   = THIS_MODULE,
+	.open    = stag_open,
+	.release = stag_release,
+	.read    = debugfs_read,
+	.llseek  = default_llseek,
 };
 
 static int setup_debugfs(struct c4iw_dev *devp)
@@ -199,6 +246,11 @@
 				 (void *)devp, &qp_debugfs_fops);
 	if (de && de->d_inode)
 		de->d_inode->i_size = 4096;
+
+	de = debugfs_create_file("stags", S_IWUSR, devp->debugfs_root,
+				 (void *)devp, &stag_debugfs_fops);
+	if (de && de->d_inode)
+		de->d_inode->i_size = 4096;
 	return 0;
 }
 
@@ -290,7 +342,14 @@
 		printk(KERN_ERR MOD "error %d initializing rqt pool\n", err);
 		goto err3;
 	}
+	err = c4iw_ocqp_pool_create(rdev);
+	if (err) {
+		printk(KERN_ERR MOD "error %d initializing ocqp pool\n", err);
+		goto err4;
+	}
 	return 0;
+err4:
+	c4iw_rqtpool_destroy(rdev);
 err3:
 	c4iw_pblpool_destroy(rdev);
 err2:
@@ -317,6 +376,7 @@
 	idr_destroy(&dev->cqidr);
 	idr_destroy(&dev->qpidr);
 	idr_destroy(&dev->mmidr);
+	iounmap(dev->rdev.oc_mw_kva);
 	ib_dealloc_device(&dev->ibdev);
 }
 
@@ -332,6 +392,17 @@
 	}
 	devp->rdev.lldi = *infop;
 
+	devp->rdev.oc_mw_pa = pci_resource_start(devp->rdev.lldi.pdev, 2) +
+		(pci_resource_len(devp->rdev.lldi.pdev, 2) -
+		 roundup_pow_of_two(devp->rdev.lldi.vr->ocq.size));
+	devp->rdev.oc_mw_kva = ioremap_wc(devp->rdev.oc_mw_pa,
+					       devp->rdev.lldi.vr->ocq.size);
+
+	printk(KERN_INFO MOD "ocq memory: "
+	       "hw_start 0x%x size %u mw_pa 0x%lx mw_kva %p\n",
+	       devp->rdev.lldi.vr->ocq.start, devp->rdev.lldi.vr->ocq.size,
+	       devp->rdev.oc_mw_pa, devp->rdev.oc_mw_kva);
+
 	mutex_lock(&dev_mutex);
 
 	ret = c4iw_rdev_open(&devp->rdev);
@@ -383,46 +454,6 @@
 	return dev;
 }
 
-static struct sk_buff *t4_pktgl_to_skb(const struct pkt_gl *gl,
-				       unsigned int skb_len,
-				       unsigned int pull_len)
-{
-	struct sk_buff *skb;
-	struct skb_shared_info *ssi;
-
-	if (gl->tot_len <= 512) {
-		skb = alloc_skb(gl->tot_len, GFP_ATOMIC);
-		if (unlikely(!skb))
-			goto out;
-		__skb_put(skb, gl->tot_len);
-		skb_copy_to_linear_data(skb, gl->va, gl->tot_len);
-	} else {
-		skb = alloc_skb(skb_len, GFP_ATOMIC);
-		if (unlikely(!skb))
-			goto out;
-		__skb_put(skb, pull_len);
-		skb_copy_to_linear_data(skb, gl->va, pull_len);
-
-		ssi = skb_shinfo(skb);
-		ssi->frags[0].page = gl->frags[0].page;
-		ssi->frags[0].page_offset = gl->frags[0].page_offset + pull_len;
-		ssi->frags[0].size = gl->frags[0].size - pull_len;
-		if (gl->nfrags > 1)
-			memcpy(&ssi->frags[1], &gl->frags[1],
-			       (gl->nfrags - 1) * sizeof(skb_frag_t));
-		ssi->nr_frags = gl->nfrags;
-
-		skb->len = gl->tot_len;
-		skb->data_len = skb->len - pull_len;
-		skb->truesize += skb->data_len;
-
-		/* Get a reference for the last page, we don't own it */
-		get_page(gl->frags[gl->nfrags - 1].page);
-	}
-out:
-	return skb;
-}
-
 static int c4iw_uld_rx_handler(void *handle, const __be64 *rsp,
 			const struct pkt_gl *gl)
 {
@@ -447,7 +478,7 @@
 		c4iw_ev_handler(dev, qid);
 		return 0;
 	} else {
-		skb = t4_pktgl_to_skb(gl, 128, 128);
+		skb = cxgb4_pktgl_to_skb(gl, 128, 128);
 		if (unlikely(!skb))
 			goto nomem;
 	}
diff --git a/drivers/infiniband/hw/cxgb4/ev.c b/drivers/infiniband/hw/cxgb4/ev.c
index 491e76a..c13041a 100644
--- a/drivers/infiniband/hw/cxgb4/ev.c
+++ b/drivers/infiniband/hw/cxgb4/ev.c
@@ -60,7 +60,7 @@
 	if (qhp->attr.state == C4IW_QP_STATE_RTS) {
 		attrs.next_state = C4IW_QP_STATE_TERMINATE;
 		c4iw_modify_qp(qhp->rhp, qhp, C4IW_QP_ATTR_NEXT_STATE,
-			       &attrs, 1);
+			       &attrs, 0);
 	}
 
 	event.event = ib_event;
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
index ed459b8..16032cd 100644
--- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
+++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
@@ -46,6 +46,7 @@
 #include <linux/timer.h>
 #include <linux/io.h>
 #include <linux/kfifo.h>
+#include <linux/mutex.h>
 
 #include <asm/byteorder.h>
 
@@ -79,21 +80,6 @@
 	return skb->data;
 }
 
-#define C4IW_WR_TO (10*HZ)
-
-struct c4iw_wr_wait {
-	wait_queue_head_t wait;
-	int done;
-	int ret;
-};
-
-static inline void c4iw_init_wr_wait(struct c4iw_wr_wait *wr_waitp)
-{
-	wr_waitp->ret = 0;
-	wr_waitp->done = 0;
-	init_waitqueue_head(&wr_waitp->wait);
-}
-
 struct c4iw_resource {
 	struct kfifo tpt_fifo;
 	spinlock_t tpt_fifo_lock;
@@ -127,8 +113,11 @@
 	struct c4iw_dev_ucontext uctx;
 	struct gen_pool *pbl_pool;
 	struct gen_pool *rqt_pool;
+	struct gen_pool *ocqp_pool;
 	u32 flags;
 	struct cxgb4_lld_info lldi;
+	unsigned long oc_mw_pa;
+	void __iomem *oc_mw_kva;
 };
 
 static inline int c4iw_fatal_error(struct c4iw_rdev *rdev)
@@ -141,6 +130,44 @@
 	return min((int)T4_MAX_NUM_STAG, (int)(rdev->lldi.vr->stag.size >> 5));
 }
 
+#define C4IW_WR_TO (10*HZ)
+
+struct c4iw_wr_wait {
+	wait_queue_head_t wait;
+	int done;
+	int ret;
+};
+
+static inline void c4iw_init_wr_wait(struct c4iw_wr_wait *wr_waitp)
+{
+	wr_waitp->ret = 0;
+	wr_waitp->done = 0;
+	init_waitqueue_head(&wr_waitp->wait);
+}
+
+static inline int c4iw_wait_for_reply(struct c4iw_rdev *rdev,
+				 struct c4iw_wr_wait *wr_waitp,
+				 u32 hwtid, u32 qpid,
+				 const char *func)
+{
+	unsigned to = C4IW_WR_TO;
+	do {
+
+		wait_event_timeout(wr_waitp->wait, wr_waitp->done, to);
+		if (!wr_waitp->done) {
+			printk(KERN_ERR MOD "%s - Device %s not responding - "
+			       "tid %u qpid %u\n", func,
+			       pci_name(rdev->lldi.pdev), hwtid, qpid);
+			to = to << 2;
+		}
+	} while (!wr_waitp->done);
+	if (wr_waitp->ret)
+		printk(KERN_WARNING MOD "%s: FW reply %d tid %u qpid %u\n",
+		       pci_name(rdev->lldi.pdev), wr_waitp->ret, hwtid, qpid);
+	return wr_waitp->ret;
+}
+
+
 struct c4iw_dev {
 	struct ib_device ibdev;
 	struct c4iw_rdev rdev;
@@ -327,6 +354,7 @@
 	struct c4iw_qp_attributes attr;
 	struct t4_wq wq;
 	spinlock_t lock;
+	struct mutex mutex;
 	atomic_t refcnt;
 	wait_queue_head_t wait;
 	struct timer_list timer;
@@ -579,12 +607,10 @@
 	struct c4iw_dev *dev;
 	enum c4iw_ep_state state;
 	struct kref kref;
-	spinlock_t lock;
+	struct mutex mutex;
 	struct sockaddr_in local_addr;
 	struct sockaddr_in remote_addr;
-	wait_queue_head_t waitq;
-	int rpl_done;
-	int rpl_err;
+	struct c4iw_wr_wait wr_wait;
 	unsigned long flags;
 };
 
@@ -654,8 +680,10 @@
 int c4iw_init_ctrl_qp(struct c4iw_rdev *rdev);
 int c4iw_pblpool_create(struct c4iw_rdev *rdev);
 int c4iw_rqtpool_create(struct c4iw_rdev *rdev);
+int c4iw_ocqp_pool_create(struct c4iw_rdev *rdev);
 void c4iw_pblpool_destroy(struct c4iw_rdev *rdev);
 void c4iw_rqtpool_destroy(struct c4iw_rdev *rdev);
+void c4iw_ocqp_pool_destroy(struct c4iw_rdev *rdev);
 void c4iw_destroy_resource(struct c4iw_resource *rscp);
 int c4iw_destroy_ctrl_qp(struct c4iw_rdev *rdev);
 int c4iw_register_device(struct c4iw_dev *dev);
@@ -721,6 +749,8 @@
 void c4iw_rqtpool_free(struct c4iw_rdev *rdev, u32 addr, int size);
 u32 c4iw_pblpool_alloc(struct c4iw_rdev *rdev, int size);
 void c4iw_pblpool_free(struct c4iw_rdev *rdev, u32 addr, int size);
+u32 c4iw_ocqp_pool_alloc(struct c4iw_rdev *rdev, int size);
+void c4iw_ocqp_pool_free(struct c4iw_rdev *rdev, u32 addr, int size);
 int c4iw_ofld_send(struct c4iw_rdev *rdev, struct sk_buff *skb);
 void c4iw_flush_hw_cq(struct t4_cq *cq);
 void c4iw_count_rcqes(struct t4_cq *cq, struct t4_wq *wq, int *count);
diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c
index 269373a..273ffe4 100644
--- a/drivers/infiniband/hw/cxgb4/mem.c
+++ b/drivers/infiniband/hw/cxgb4/mem.c
@@ -71,7 +71,7 @@
 		if (i == (num_wqe-1)) {
 			req->wr.wr_hi = cpu_to_be32(FW_WR_OP(FW_ULPTX_WR) |
 						    FW_WR_COMPL(1));
-			req->wr.wr_lo = (__force __be64)&wr_wait;
+			req->wr.wr_lo = (__force __be64)(unsigned long) &wr_wait;
 		} else
 			req->wr.wr_hi = cpu_to_be32(FW_WR_OP(FW_ULPTX_WR));
 		req->wr.wr_mid = cpu_to_be32(
@@ -103,14 +103,7 @@
 		len -= C4IW_MAX_INLINE_SIZE;
 	}
 
-	wait_event_timeout(wr_wait.wait, wr_wait.done, C4IW_WR_TO);
-	if (!wr_wait.done) {
-		printk(KERN_ERR MOD "Device %s not responding!\n",
-		       pci_name(rdev->lldi.pdev));
-		rdev->flags = T4_FATAL_ERROR;
-		ret = -EIO;
-	} else
-		ret = wr_wait.ret;
+	ret = c4iw_wait_for_reply(rdev, &wr_wait, 0, 0, __func__);
 	return ret;
 }
 
diff --git a/drivers/infiniband/hw/cxgb4/provider.c b/drivers/infiniband/hw/cxgb4/provider.c
index 8f645c8..f66dd8b 100644
--- a/drivers/infiniband/hw/cxgb4/provider.c
+++ b/drivers/infiniband/hw/cxgb4/provider.c
@@ -54,9 +54,9 @@
 
 #include "iw_cxgb4.h"
 
-static int fastreg_support;
+static int fastreg_support = 1;
 module_param(fastreg_support, int, 0644);
-MODULE_PARM_DESC(fastreg_support, "Advertise fastreg support (default=0)");
+MODULE_PARM_DESC(fastreg_support, "Advertise fastreg support (default=1)");
 
 static int c4iw_modify_port(struct ib_device *ibdev,
 			    u8 port, int port_modify_mask,
@@ -149,19 +149,28 @@
 	addr = mm->addr;
 	kfree(mm);
 
-	if ((addr >= pci_resource_start(rdev->lldi.pdev, 2)) &&
-	    (addr < (pci_resource_start(rdev->lldi.pdev, 2) +
-		       pci_resource_len(rdev->lldi.pdev, 2)))) {
+	if ((addr >= pci_resource_start(rdev->lldi.pdev, 0)) &&
+	    (addr < (pci_resource_start(rdev->lldi.pdev, 0) +
+		    pci_resource_len(rdev->lldi.pdev, 0)))) {
 
 		/*
-		 * Map T4 DB register.
+		 * MA_SYNC register...
 		 */
-		if (vma->vm_flags & VM_READ)
-			return -EPERM;
-
 		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-		vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND;
-		vma->vm_flags &= ~VM_MAYREAD;
+		ret = io_remap_pfn_range(vma, vma->vm_start,
+					 addr >> PAGE_SHIFT,
+					 len, vma->vm_page_prot);
+	} else if ((addr >= pci_resource_start(rdev->lldi.pdev, 2)) &&
+		   (addr < (pci_resource_start(rdev->lldi.pdev, 2) +
+		    pci_resource_len(rdev->lldi.pdev, 2)))) {
+
+		/*
+		 * Map user DB or OCQP memory...
+		 */
+		if (addr >= rdev->oc_mw_pa)
+			vma->vm_page_prot = t4_pgprot_wc(vma->vm_page_prot);
+		else
+			vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 		ret = io_remap_pfn_range(vma, vma->vm_start,
 					 addr >> PAGE_SHIFT,
 					 len, vma->vm_page_prot);
@@ -382,7 +391,17 @@
 static int c4iw_get_mib(struct ib_device *ibdev,
 			union rdma_protocol_stats *stats)
 {
-	return -ENOSYS;
+	struct tp_tcp_stats v4, v6;
+	struct c4iw_dev *c4iw_dev = to_c4iw_dev(ibdev);
+
+	cxgb4_get_tcp_stats(c4iw_dev->rdev.lldi.pdev, &v4, &v6);
+	memset(stats, 0, sizeof *stats);
+	stats->iw.tcpInSegs = v4.tcpInSegs + v6.tcpInSegs;
+	stats->iw.tcpOutSegs = v4.tcpOutSegs + v6.tcpOutSegs;
+	stats->iw.tcpRetransSegs = v4.tcpRetransSegs + v6.tcpRetransSegs;
+	stats->iw.tcpOutRsts = v4.tcpOutRsts + v6.tcpOutSegs;
+
+	return 0;
 }
 
 static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
@@ -472,6 +491,7 @@
 	dev->ibdev.post_send = c4iw_post_send;
 	dev->ibdev.post_recv = c4iw_post_receive;
 	dev->ibdev.get_protocol_stats = c4iw_get_mib;
+	dev->ibdev.uverbs_abi_ver = C4IW_UVERBS_ABI_VERSION;
 
 	dev->ibdev.iwcm = kmalloc(sizeof(struct iw_cm_verbs), GFP_KERNEL);
 	if (!dev->ibdev.iwcm)
diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c
index 93f6e5b..057cb25 100644
--- a/drivers/infiniband/hw/cxgb4/qp.c
+++ b/drivers/infiniband/hw/cxgb4/qp.c
@@ -31,6 +31,63 @@
  */
 #include "iw_cxgb4.h"
 
+static int ocqp_support;
+module_param(ocqp_support, int, 0644);
+MODULE_PARM_DESC(ocqp_support, "Support on-chip SQs (default=0)");
+
+static void set_state(struct c4iw_qp *qhp, enum c4iw_qp_state state)
+{
+	unsigned long flag;
+	spin_lock_irqsave(&qhp->lock, flag);
+	qhp->attr.state = state;
+	spin_unlock_irqrestore(&qhp->lock, flag);
+}
+
+static void dealloc_oc_sq(struct c4iw_rdev *rdev, struct t4_sq *sq)
+{
+	c4iw_ocqp_pool_free(rdev, sq->dma_addr, sq->memsize);
+}
+
+static void dealloc_host_sq(struct c4iw_rdev *rdev, struct t4_sq *sq)
+{
+	dma_free_coherent(&(rdev->lldi.pdev->dev), sq->memsize, sq->queue,
+			  pci_unmap_addr(sq, mapping));
+}
+
+static void dealloc_sq(struct c4iw_rdev *rdev, struct t4_sq *sq)
+{
+	if (t4_sq_onchip(sq))
+		dealloc_oc_sq(rdev, sq);
+	else
+		dealloc_host_sq(rdev, sq);
+}
+
+static int alloc_oc_sq(struct c4iw_rdev *rdev, struct t4_sq *sq)
+{
+	if (!ocqp_support || !t4_ocqp_supported())
+		return -ENOSYS;
+	sq->dma_addr = c4iw_ocqp_pool_alloc(rdev, sq->memsize);
+	if (!sq->dma_addr)
+		return -ENOMEM;
+	sq->phys_addr = rdev->oc_mw_pa + sq->dma_addr -
+			rdev->lldi.vr->ocq.start;
+	sq->queue = (__force union t4_wr *)(rdev->oc_mw_kva + sq->dma_addr -
+					    rdev->lldi.vr->ocq.start);
+	sq->flags |= T4_SQ_ONCHIP;
+	return 0;
+}
+
+static int alloc_host_sq(struct c4iw_rdev *rdev, struct t4_sq *sq)
+{
+	sq->queue = dma_alloc_coherent(&(rdev->lldi.pdev->dev), sq->memsize,
+				       &(sq->dma_addr), GFP_KERNEL);
+	if (!sq->queue)
+		return -ENOMEM;
+	sq->phys_addr = virt_to_phys(sq->queue);
+	pci_unmap_addr_set(sq, mapping, sq->dma_addr);
+	return 0;
+}
+
 static int destroy_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
 		      struct c4iw_dev_ucontext *uctx)
 {
@@ -41,9 +98,7 @@
 	dma_free_coherent(&(rdev->lldi.pdev->dev),
 			  wq->rq.memsize, wq->rq.queue,
 			  dma_unmap_addr(&wq->rq, mapping));
-	dma_free_coherent(&(rdev->lldi.pdev->dev),
-			  wq->sq.memsize, wq->sq.queue,
-			  dma_unmap_addr(&wq->sq, mapping));
+	dealloc_sq(rdev, &wq->sq);
 	c4iw_rqtpool_free(rdev, wq->rq.rqt_hwaddr, wq->rq.rqt_size);
 	kfree(wq->rq.sw_rq);
 	kfree(wq->sq.sw_sq);
@@ -93,11 +148,12 @@
 	if (!wq->rq.rqt_hwaddr)
 		goto err4;
 
-	wq->sq.queue = dma_alloc_coherent(&(rdev->lldi.pdev->dev),
-					  wq->sq.memsize, &(wq->sq.dma_addr),
-					  GFP_KERNEL);
-	if (!wq->sq.queue)
-		goto err5;
+	if (user) {
+		if (alloc_oc_sq(rdev, &wq->sq) && alloc_host_sq(rdev, &wq->sq))
+			goto err5;
+	} else
+		if (alloc_host_sq(rdev, &wq->sq))
+			goto err5;
 	memset(wq->sq.queue, 0, wq->sq.memsize);
 	dma_unmap_addr_set(&wq->sq, mapping, wq->sq.dma_addr);
 
@@ -144,7 +200,7 @@
 			V_FW_RI_RES_WR_NRES(2) |
 			FW_WR_COMPL(1));
 	res_wr->len16_pkd = cpu_to_be32(DIV_ROUND_UP(wr_len, 16));
-	res_wr->cookie = (u64)&wr_wait;
+	res_wr->cookie = (unsigned long) &wr_wait;
 	res = res_wr->res;
 	res->u.sqrq.restype = FW_RI_RES_TYPE_SQ;
 	res->u.sqrq.op = FW_RI_RES_OP_WRITE;
@@ -158,6 +214,7 @@
 		V_FW_RI_RES_WR_HOSTFCMODE(0) |	/* no host cidx updates */
 		V_FW_RI_RES_WR_CPRIO(0) |	/* don't keep in chip cache */
 		V_FW_RI_RES_WR_PCIECHN(0) |	/* set by uP at ri_init time */
+		t4_sq_onchip(&wq->sq) ? F_FW_RI_RES_WR_ONCHIP : 0 |
 		V_FW_RI_RES_WR_IQID(scq->cqid));
 	res->u.sqrq.dcaen_to_eqsize = cpu_to_be32(
 		V_FW_RI_RES_WR_DCAEN(0) |
@@ -198,14 +255,7 @@
 	ret = c4iw_ofld_send(rdev, skb);
 	if (ret)
 		goto err7;
-	wait_event_timeout(wr_wait.wait, wr_wait.done, C4IW_WR_TO);
-	if (!wr_wait.done) {
-		printk(KERN_ERR MOD "Device %s not responding!\n",
-		       pci_name(rdev->lldi.pdev));
-		rdev->flags = T4_FATAL_ERROR;
-		ret = -EIO;
-	} else
-		ret = wr_wait.ret;
+	ret = c4iw_wait_for_reply(rdev, &wr_wait, 0, wq->sq.qid, __func__);
 	if (ret)
 		goto err7;
 
@@ -219,9 +269,7 @@
 			  wq->rq.memsize, wq->rq.queue,
 			  dma_unmap_addr(&wq->rq, mapping));
 err6:
-	dma_free_coherent(&(rdev->lldi.pdev->dev),
-			  wq->sq.memsize, wq->sq.queue,
-			  dma_unmap_addr(&wq->sq, mapping));
+	dealloc_sq(rdev, &wq->sq);
 err5:
 	c4iw_rqtpool_free(rdev, wq->rq.rqt_hwaddr, wq->rq.rqt_size);
 err4:
@@ -263,6 +311,9 @@
 			rem -= len;
 		}
 	}
+	len = roundup(plen + sizeof *immdp, 16) - (plen + sizeof *immdp);
+	if (len)
+		memset(dstp, 0, len);
 	immdp->op = FW_RI_DATA_IMMD;
 	immdp->r1 = 0;
 	immdp->r2 = 0;
@@ -292,6 +343,7 @@
 		if (++flitp == queue_end)
 			flitp = queue_start;
 	}
+	*flitp = (__force __be64)0;
 	isglp->op = FW_RI_DATA_ISGL;
 	isglp->r1 = 0;
 	isglp->nsge = cpu_to_be16(num_sge);
@@ -453,13 +505,15 @@
 	return 0;
 }
 
-static int build_fastreg(union t4_wr *wqe, struct ib_send_wr *wr, u8 *len16)
+static int build_fastreg(struct t4_sq *sq, union t4_wr *wqe,
+			 struct ib_send_wr *wr, u8 *len16)
 {
 
 	struct fw_ri_immd *imdp;
 	__be64 *p;
 	int i;
 	int pbllen = roundup(wr->wr.fast_reg.page_list_len * sizeof(u64), 32);
+	int rem;
 
 	if (wr->wr.fast_reg.page_list_len > T4_MAX_FR_DEPTH)
 		return -EINVAL;
@@ -474,32 +528,28 @@
 	wqe->fr.va_hi = cpu_to_be32(wr->wr.fast_reg.iova_start >> 32);
 	wqe->fr.va_lo_fbo = cpu_to_be32(wr->wr.fast_reg.iova_start &
 					0xffffffff);
-	if (pbllen > T4_MAX_FR_IMMD) {
-		struct c4iw_fr_page_list *c4pl =
-				to_c4iw_fr_page_list(wr->wr.fast_reg.page_list);
-		struct fw_ri_dsgl *sglp;
-
-		sglp = (struct fw_ri_dsgl *)(&wqe->fr + 1);
-		sglp->op = FW_RI_DATA_DSGL;
-		sglp->r1 = 0;
-		sglp->nsge = cpu_to_be16(1);
-		sglp->addr0 = cpu_to_be64(c4pl->dma_addr);
-		sglp->len0 = cpu_to_be32(pbllen);
-
-		*len16 = DIV_ROUND_UP(sizeof wqe->fr + sizeof *sglp, 16);
-	} else {
-		imdp = (struct fw_ri_immd *)(&wqe->fr + 1);
-		imdp->op = FW_RI_DATA_IMMD;
-		imdp->r1 = 0;
-		imdp->r2 = 0;
-		imdp->immdlen = cpu_to_be32(pbllen);
-		p = (__be64 *)(imdp + 1);
-		for (i = 0; i < wr->wr.fast_reg.page_list_len; i++, p++)
-			*p = cpu_to_be64(
-				(u64)wr->wr.fast_reg.page_list->page_list[i]);
-		*len16 = DIV_ROUND_UP(sizeof wqe->fr + sizeof *imdp + pbllen,
-				      16);
+	WARN_ON(pbllen > T4_MAX_FR_IMMD);
+	imdp = (struct fw_ri_immd *)(&wqe->fr + 1);
+	imdp->op = FW_RI_DATA_IMMD;
+	imdp->r1 = 0;
+	imdp->r2 = 0;
+	imdp->immdlen = cpu_to_be32(pbllen);
+	p = (__be64 *)(imdp + 1);
+	rem = pbllen;
+	for (i = 0; i < wr->wr.fast_reg.page_list_len; i++) {
+		*p = cpu_to_be64((u64)wr->wr.fast_reg.page_list->page_list[i]);
+		rem -= sizeof *p;
+		if (++p == (__be64 *)&sq->queue[sq->size])
+			p = (__be64 *)sq->queue;
 	}
+	BUG_ON(rem < 0);
+	while (rem) {
+		*p = 0;
+		rem -= sizeof *p;
+		if (++p == (__be64 *)&sq->queue[sq->size])
+			p = (__be64 *)sq->queue;
+	}
+	*len16 = DIV_ROUND_UP(sizeof wqe->fr + sizeof *imdp + pbllen, 16);
 	return 0;
 }
 
@@ -587,7 +637,7 @@
 			fw_opcode = FW_RI_RDMA_READ_WR;
 			swsqe->opcode = FW_RI_READ_REQ;
 			if (wr->opcode == IB_WR_RDMA_READ_WITH_INV)
-				fw_flags |= FW_RI_RDMA_READ_INVALIDATE;
+				fw_flags = FW_RI_RDMA_READ_INVALIDATE;
 			else
 				fw_flags = 0;
 			err = build_rdma_read(wqe, wr, &len16);
@@ -600,7 +650,7 @@
 		case IB_WR_FAST_REG_MR:
 			fw_opcode = FW_RI_FR_NSMR_WR;
 			swsqe->opcode = FW_RI_FAST_REGISTER;
-			err = build_fastreg(wqe, wr, &len16);
+			err = build_fastreg(&qhp->wq.sq, wqe, wr, &len16);
 			break;
 		case IB_WR_LOCAL_INV:
 			if (wr->send_flags & IB_SEND_FENCE)
@@ -905,46 +955,38 @@
  * Assumes qhp lock is held.
  */
 static void __flush_qp(struct c4iw_qp *qhp, struct c4iw_cq *rchp,
-		       struct c4iw_cq *schp, unsigned long *flag)
+		       struct c4iw_cq *schp)
 {
 	int count;
 	int flushed;
+	unsigned long flag;
 
 	PDBG("%s qhp %p rchp %p schp %p\n", __func__, qhp, rchp, schp);
-	/* take a ref on the qhp since we must release the lock */
-	atomic_inc(&qhp->refcnt);
-	spin_unlock_irqrestore(&qhp->lock, *flag);
 
 	/* locking hierarchy: cq lock first, then qp lock. */
-	spin_lock_irqsave(&rchp->lock, *flag);
+	spin_lock_irqsave(&rchp->lock, flag);
 	spin_lock(&qhp->lock);
 	c4iw_flush_hw_cq(&rchp->cq);
 	c4iw_count_rcqes(&rchp->cq, &qhp->wq, &count);
 	flushed = c4iw_flush_rq(&qhp->wq, &rchp->cq, count);
 	spin_unlock(&qhp->lock);
-	spin_unlock_irqrestore(&rchp->lock, *flag);
+	spin_unlock_irqrestore(&rchp->lock, flag);
 	if (flushed)
 		(*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
 
 	/* locking hierarchy: cq lock first, then qp lock. */
-	spin_lock_irqsave(&schp->lock, *flag);
+	spin_lock_irqsave(&schp->lock, flag);
 	spin_lock(&qhp->lock);
 	c4iw_flush_hw_cq(&schp->cq);
 	c4iw_count_scqes(&schp->cq, &qhp->wq, &count);
 	flushed = c4iw_flush_sq(&qhp->wq, &schp->cq, count);
 	spin_unlock(&qhp->lock);
-	spin_unlock_irqrestore(&schp->lock, *flag);
+	spin_unlock_irqrestore(&schp->lock, flag);
 	if (flushed)
 		(*schp->ibcq.comp_handler)(&schp->ibcq, schp->ibcq.cq_context);
-
-	/* deref */
-	if (atomic_dec_and_test(&qhp->refcnt))
-		wake_up(&qhp->wait);
-
-	spin_lock_irqsave(&qhp->lock, *flag);
 }
 
-static void flush_qp(struct c4iw_qp *qhp, unsigned long *flag)
+static void flush_qp(struct c4iw_qp *qhp)
 {
 	struct c4iw_cq *rchp, *schp;
 
@@ -958,7 +1000,7 @@
 			t4_set_cq_in_error(&schp->cq);
 		return;
 	}
-	__flush_qp(qhp, rchp, schp, flag);
+	__flush_qp(qhp, rchp, schp);
 }
 
 static int rdma_fini(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
@@ -966,7 +1008,6 @@
 {
 	struct fw_ri_wr *wqe;
 	int ret;
-	struct c4iw_wr_wait wr_wait;
 	struct sk_buff *skb;
 
 	PDBG("%s qhp %p qid 0x%x tid %u\n", __func__, qhp, qhp->wq.sq.qid,
@@ -985,28 +1026,16 @@
 	wqe->flowid_len16 = cpu_to_be32(
 		FW_WR_FLOWID(ep->hwtid) |
 		FW_WR_LEN16(DIV_ROUND_UP(sizeof *wqe, 16)));
-	wqe->cookie = (u64)&wr_wait;
+	wqe->cookie = (unsigned long) &ep->com.wr_wait;
 
 	wqe->u.fini.type = FW_RI_TYPE_FINI;
-	c4iw_init_wr_wait(&wr_wait);
+	c4iw_init_wr_wait(&ep->com.wr_wait);
 	ret = c4iw_ofld_send(&rhp->rdev, skb);
 	if (ret)
 		goto out;
 
-	wait_event_timeout(wr_wait.wait, wr_wait.done, C4IW_WR_TO);
-	if (!wr_wait.done) {
-		printk(KERN_ERR MOD "Device %s not responding!\n",
-		       pci_name(rhp->rdev.lldi.pdev));
-		rhp->rdev.flags = T4_FATAL_ERROR;
-		ret = -EIO;
-	} else {
-		ret = wr_wait.ret;
-		if (ret)
-			printk(KERN_WARNING MOD
-			       "%s: Abnormal close qpid %d ret %u\n",
-			       pci_name(rhp->rdev.lldi.pdev), qhp->wq.sq.qid,
-			       ret);
-	}
+	ret = c4iw_wait_for_reply(&rhp->rdev, &ep->com.wr_wait, qhp->ep->hwtid,
+			     qhp->wq.sq.qid, __func__);
 out:
 	PDBG("%s ret %d\n", __func__, ret);
 	return ret;
@@ -1040,7 +1069,6 @@
 {
 	struct fw_ri_wr *wqe;
 	int ret;
-	struct c4iw_wr_wait wr_wait;
 	struct sk_buff *skb;
 
 	PDBG("%s qhp %p qid 0x%x tid %u\n", __func__, qhp, qhp->wq.sq.qid,
@@ -1060,7 +1088,7 @@
 		FW_WR_FLOWID(qhp->ep->hwtid) |
 		FW_WR_LEN16(DIV_ROUND_UP(sizeof *wqe, 16)));
 
-	wqe->cookie = (u64)&wr_wait;
+	wqe->cookie = (unsigned long) &qhp->ep->com.wr_wait;
 
 	wqe->u.init.type = FW_RI_TYPE_INIT;
 	wqe->u.init.mpareqbit_p2ptype =
@@ -1097,19 +1125,13 @@
 	if (qhp->attr.mpa_attr.initiator)
 		build_rtr_msg(qhp->attr.mpa_attr.p2p_type, &wqe->u.init);
 
-	c4iw_init_wr_wait(&wr_wait);
+	c4iw_init_wr_wait(&qhp->ep->com.wr_wait);
 	ret = c4iw_ofld_send(&rhp->rdev, skb);
 	if (ret)
 		goto out;
 
-	wait_event_timeout(wr_wait.wait, wr_wait.done, C4IW_WR_TO);
-	if (!wr_wait.done) {
-		printk(KERN_ERR MOD "Device %s not responding!\n",
-		       pci_name(rhp->rdev.lldi.pdev));
-		rhp->rdev.flags = T4_FATAL_ERROR;
-		ret = -EIO;
-	} else
-		ret = wr_wait.ret;
+	ret = c4iw_wait_for_reply(&rhp->rdev, &qhp->ep->com.wr_wait,
+				  qhp->ep->hwtid, qhp->wq.sq.qid, __func__);
 out:
 	PDBG("%s ret %d\n", __func__, ret);
 	return ret;
@@ -1122,7 +1144,6 @@
 {
 	int ret = 0;
 	struct c4iw_qp_attributes newattr = qhp->attr;
-	unsigned long flag;
 	int disconnect = 0;
 	int terminate = 0;
 	int abort = 0;
@@ -1133,7 +1154,7 @@
 	     qhp, qhp->wq.sq.qid, qhp->wq.rq.qid, qhp->ep, qhp->attr.state,
 	     (mask & C4IW_QP_ATTR_NEXT_STATE) ? attrs->next_state : -1);
 
-	spin_lock_irqsave(&qhp->lock, flag);
+	mutex_lock(&qhp->mutex);
 
 	/* Process attr changes if in IDLE */
 	if (mask & C4IW_QP_ATTR_VALID_MODIFY) {
@@ -1184,7 +1205,7 @@
 			qhp->attr.mpa_attr = attrs->mpa_attr;
 			qhp->attr.llp_stream_handle = attrs->llp_stream_handle;
 			qhp->ep = qhp->attr.llp_stream_handle;
-			qhp->attr.state = C4IW_QP_STATE_RTS;
+			set_state(qhp, C4IW_QP_STATE_RTS);
 
 			/*
 			 * Ref the endpoint here and deref when we
@@ -1193,15 +1214,13 @@
 			 * transition.
 			 */
 			c4iw_get_ep(&qhp->ep->com);
-			spin_unlock_irqrestore(&qhp->lock, flag);
 			ret = rdma_init(rhp, qhp);
-			spin_lock_irqsave(&qhp->lock, flag);
 			if (ret)
 				goto err;
 			break;
 		case C4IW_QP_STATE_ERROR:
-			qhp->attr.state = C4IW_QP_STATE_ERROR;
-			flush_qp(qhp, &flag);
+			set_state(qhp, C4IW_QP_STATE_ERROR);
+			flush_qp(qhp);
 			break;
 		default:
 			ret = -EINVAL;
@@ -1212,38 +1231,38 @@
 		switch (attrs->next_state) {
 		case C4IW_QP_STATE_CLOSING:
 			BUG_ON(atomic_read(&qhp->ep->com.kref.refcount) < 2);
-			qhp->attr.state = C4IW_QP_STATE_CLOSING;
+			set_state(qhp, C4IW_QP_STATE_CLOSING);
 			ep = qhp->ep;
 			if (!internal) {
 				abort = 0;
 				disconnect = 1;
-				c4iw_get_ep(&ep->com);
+				c4iw_get_ep(&qhp->ep->com);
 			}
-			spin_unlock_irqrestore(&qhp->lock, flag);
 			ret = rdma_fini(rhp, qhp, ep);
-			spin_lock_irqsave(&qhp->lock, flag);
 			if (ret) {
-				c4iw_get_ep(&ep->com);
+				if (internal)
+					c4iw_get_ep(&qhp->ep->com);
 				disconnect = abort = 1;
 				goto err;
 			}
 			break;
 		case C4IW_QP_STATE_TERMINATE:
-			qhp->attr.state = C4IW_QP_STATE_TERMINATE;
+			set_state(qhp, C4IW_QP_STATE_TERMINATE);
 			if (qhp->ibqp.uobject)
 				t4_set_wq_in_error(&qhp->wq);
 			ep = qhp->ep;
-			c4iw_get_ep(&ep->com);
-			terminate = 1;
+			if (!internal)
+				terminate = 1;
 			disconnect = 1;
+			c4iw_get_ep(&qhp->ep->com);
 			break;
 		case C4IW_QP_STATE_ERROR:
-			qhp->attr.state = C4IW_QP_STATE_ERROR;
+			set_state(qhp, C4IW_QP_STATE_ERROR);
 			if (!internal) {
 				abort = 1;
 				disconnect = 1;
 				ep = qhp->ep;
-				c4iw_get_ep(&ep->com);
+				c4iw_get_ep(&qhp->ep->com);
 			}
 			goto err;
 			break;
@@ -1259,8 +1278,8 @@
 		}
 		switch (attrs->next_state) {
 		case C4IW_QP_STATE_IDLE:
-			flush_qp(qhp, &flag);
-			qhp->attr.state = C4IW_QP_STATE_IDLE;
+			flush_qp(qhp);
+			set_state(qhp, C4IW_QP_STATE_IDLE);
 			qhp->attr.llp_stream_handle = NULL;
 			c4iw_put_ep(&qhp->ep->com);
 			qhp->ep = NULL;
@@ -1282,7 +1301,7 @@
 			ret = -EINVAL;
 			goto out;
 		}
-		qhp->attr.state = C4IW_QP_STATE_IDLE;
+		set_state(qhp, C4IW_QP_STATE_IDLE);
 		break;
 	case C4IW_QP_STATE_TERMINATE:
 		if (!internal) {
@@ -1305,15 +1324,16 @@
 
 	/* disassociate the LLP connection */
 	qhp->attr.llp_stream_handle = NULL;
-	ep = qhp->ep;
+	if (!ep)
+		ep = qhp->ep;
 	qhp->ep = NULL;
-	qhp->attr.state = C4IW_QP_STATE_ERROR;
+	set_state(qhp, C4IW_QP_STATE_ERROR);
 	free = 1;
 	wake_up(&qhp->wait);
 	BUG_ON(!ep);
-	flush_qp(qhp, &flag);
+	flush_qp(qhp);
 out:
-	spin_unlock_irqrestore(&qhp->lock, flag);
+	mutex_unlock(&qhp->mutex);
 
 	if (terminate)
 		post_terminate(qhp, NULL, internal ? GFP_ATOMIC : GFP_KERNEL);
@@ -1335,7 +1355,6 @@
 	 */
 	if (free)
 		c4iw_put_ep(&ep->com);
-
 	PDBG("%s exit state %d\n", __func__, qhp->attr.state);
 	return ret;
 }
@@ -1380,7 +1399,7 @@
 	int sqsize, rqsize;
 	struct c4iw_ucontext *ucontext;
 	int ret;
-	struct c4iw_mm_entry *mm1, *mm2, *mm3, *mm4;
+	struct c4iw_mm_entry *mm1, *mm2, *mm3, *mm4, *mm5 = NULL;
 
 	PDBG("%s ib_pd %p\n", __func__, pd);
 
@@ -1450,6 +1469,7 @@
 	qhp->attr.max_ord = 1;
 	qhp->attr.max_ird = 1;
 	spin_lock_init(&qhp->lock);
+	mutex_init(&qhp->mutex);
 	init_waitqueue_head(&qhp->wait);
 	atomic_set(&qhp->refcnt, 1);
 
@@ -1478,7 +1498,15 @@
 			ret = -ENOMEM;
 			goto err6;
 		}
-
+		if (t4_sq_onchip(&qhp->wq.sq)) {
+			mm5 = kmalloc(sizeof *mm5, GFP_KERNEL);
+			if (!mm5) {
+				ret = -ENOMEM;
+				goto err7;
+			}
+			uresp.flags = C4IW_QPF_ONCHIP;
+		} else
+			uresp.flags = 0;
 		uresp.qid_mask = rhp->rdev.qpmask;
 		uresp.sqid = qhp->wq.sq.qid;
 		uresp.sq_size = qhp->wq.sq.size;
@@ -1487,6 +1515,10 @@
 		uresp.rq_size = qhp->wq.rq.size;
 		uresp.rq_memsize = qhp->wq.rq.memsize;
 		spin_lock(&ucontext->mmap_lock);
+		if (mm5) {
+			uresp.ma_sync_key = ucontext->key;
+			ucontext->key += PAGE_SIZE;
+		}
 		uresp.sq_key = ucontext->key;
 		ucontext->key += PAGE_SIZE;
 		uresp.rq_key = ucontext->key;
@@ -1498,9 +1530,9 @@
 		spin_unlock(&ucontext->mmap_lock);
 		ret = ib_copy_to_udata(udata, &uresp, sizeof uresp);
 		if (ret)
-			goto err7;
+			goto err8;
 		mm1->key = uresp.sq_key;
-		mm1->addr = virt_to_phys(qhp->wq.sq.queue);
+		mm1->addr = qhp->wq.sq.phys_addr;
 		mm1->len = PAGE_ALIGN(qhp->wq.sq.memsize);
 		insert_mmap(ucontext, mm1);
 		mm2->key = uresp.rq_key;
@@ -1515,6 +1547,13 @@
 		mm4->addr = qhp->wq.rq.udb;
 		mm4->len = PAGE_SIZE;
 		insert_mmap(ucontext, mm4);
+		if (mm5) {
+			mm5->key = uresp.ma_sync_key;
+			mm5->addr = (pci_resource_start(rhp->rdev.lldi.pdev, 0)
+				    + A_PCIE_MA_SYNC) & PAGE_MASK;
+			mm5->len = PAGE_SIZE;
+			insert_mmap(ucontext, mm5);
+		}
 	}
 	qhp->ibqp.qp_num = qhp->wq.sq.qid;
 	init_timer(&(qhp->timer));
@@ -1522,6 +1561,8 @@
 	     __func__, qhp, qhp->attr.sq_num_entries, qhp->attr.rq_num_entries,
 	     qhp->wq.sq.qid);
 	return &qhp->ibqp;
+err8:
+	kfree(mm5);
 err7:
 	kfree(mm4);
 err6:
diff --git a/drivers/infiniband/hw/cxgb4/resource.c b/drivers/infiniband/hw/cxgb4/resource.c
index 83b23df..4fb50d5 100644
--- a/drivers/infiniband/hw/cxgb4/resource.c
+++ b/drivers/infiniband/hw/cxgb4/resource.c
@@ -311,6 +311,9 @@
 {
 	unsigned long addr = gen_pool_alloc(rdev->pbl_pool, size);
 	PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size);
+	if (!addr && printk_ratelimit())
+		printk(KERN_WARNING MOD "%s: Out of PBL memory\n",
+		       pci_name(rdev->lldi.pdev));
 	return (u32)addr;
 }
 
@@ -370,6 +373,9 @@
 {
 	unsigned long addr = gen_pool_alloc(rdev->rqt_pool, size << 6);
 	PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size << 6);
+	if (!addr && printk_ratelimit())
+		printk(KERN_WARNING MOD "%s: Out of RQT memory\n",
+		       pci_name(rdev->lldi.pdev));
 	return (u32)addr;
 }
 
@@ -416,3 +422,59 @@
 {
 	gen_pool_destroy(rdev->rqt_pool);
 }
+
+/*
+ * On-Chip QP Memory.
+ */
+#define MIN_OCQP_SHIFT 12	/* 4KB == min ocqp size */
+
+u32 c4iw_ocqp_pool_alloc(struct c4iw_rdev *rdev, int size)
+{
+	unsigned long addr = gen_pool_alloc(rdev->ocqp_pool, size);
+	PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size);
+	return (u32)addr;
+}
+
+void c4iw_ocqp_pool_free(struct c4iw_rdev *rdev, u32 addr, int size)
+{
+	PDBG("%s addr 0x%x size %d\n", __func__, addr, size);
+	gen_pool_free(rdev->ocqp_pool, (unsigned long)addr, size);
+}
+
+int c4iw_ocqp_pool_create(struct c4iw_rdev *rdev)
+{
+	unsigned start, chunk, top;
+
+	rdev->ocqp_pool = gen_pool_create(MIN_OCQP_SHIFT, -1);
+	if (!rdev->ocqp_pool)
+		return -ENOMEM;
+
+	start = rdev->lldi.vr->ocq.start;
+	chunk = rdev->lldi.vr->ocq.size;
+	top = start + chunk;
+
+	while (start < top) {
+		chunk = min(top - start + 1, chunk);
+		if (gen_pool_add(rdev->ocqp_pool, start, chunk, -1)) {
+			PDBG("%s failed to add OCQP chunk (%x/%x)\n",
+			     __func__, start, chunk);
+			if (chunk <= 1024 << MIN_OCQP_SHIFT) {
+				printk(KERN_WARNING MOD
+				       "Failed to add all OCQP chunks (%x/%x)\n",
+				       start, top - start);
+				return 0;
+			}
+			chunk >>= 1;
+		} else {
+			PDBG("%s added OCQP chunk (%x/%x)\n",
+			     __func__, start, chunk);
+			start += chunk;
+		}
+	}
+	return 0;
+}
+
+void c4iw_ocqp_pool_destroy(struct c4iw_rdev *rdev)
+{
+	gen_pool_destroy(rdev->ocqp_pool);
+}
diff --git a/drivers/infiniband/hw/cxgb4/t4.h b/drivers/infiniband/hw/cxgb4/t4.h
index 24f3690..7000442 100644
--- a/drivers/infiniband/hw/cxgb4/t4.h
+++ b/drivers/infiniband/hw/cxgb4/t4.h
@@ -52,6 +52,7 @@
 #define T4_STAG_UNSET 0xffffffff
 #define T4_FW_MAJ 0
 #define T4_EQ_STATUS_ENTRIES (L1_CACHE_BYTES > 64 ? 2 : 1)
+#define A_PCIE_MA_SYNC 0x30b4
 
 struct t4_status_page {
 	__be32 rsvd1;	/* flit 0 - hw owns */
@@ -65,7 +66,7 @@
 
 #define T4_EQ_ENTRY_SIZE 64
 
-#define T4_SQ_NUM_SLOTS 4
+#define T4_SQ_NUM_SLOTS 5
 #define T4_SQ_NUM_BYTES (T4_EQ_ENTRY_SIZE * T4_SQ_NUM_SLOTS)
 #define T4_MAX_SEND_SGE ((T4_SQ_NUM_BYTES - sizeof(struct fw_ri_send_wr) - \
 			sizeof(struct fw_ri_isgl)) / sizeof(struct fw_ri_sge))
@@ -78,7 +79,7 @@
 			sizeof(struct fw_ri_rdma_write_wr) - \
 			sizeof(struct fw_ri_isgl)) / sizeof(struct fw_ri_sge))
 #define T4_MAX_FR_IMMD ((T4_SQ_NUM_BYTES - sizeof(struct fw_ri_fr_nsmr_wr) - \
-			sizeof(struct fw_ri_immd)))
+			sizeof(struct fw_ri_immd)) & ~31UL)
 #define T4_MAX_FR_DEPTH (T4_MAX_FR_IMMD / sizeof(u64))
 
 #define T4_RQ_NUM_SLOTS 2
@@ -266,10 +267,36 @@
 	u16			idx;
 };
 
+static inline pgprot_t t4_pgprot_wc(pgprot_t prot)
+{
+#if defined(__i386__) || defined(__x86_64__)
+	return pgprot_writecombine(prot);
+#elif defined(CONFIG_PPC64)
+	return __pgprot((pgprot_val(prot) | _PAGE_NO_CACHE) &
+			~(pgprot_t)_PAGE_GUARDED);
+#else
+	return pgprot_noncached(prot);
+#endif
+}
+
+static inline int t4_ocqp_supported(void)
+{
+#if defined(__i386__) || defined(__x86_64__) || defined(CONFIG_PPC64)
+	return 1;
+#else
+	return 0;
+#endif
+}
+
+enum {
+	T4_SQ_ONCHIP = (1<<0),
+};
+
 struct t4_sq {
 	union t4_wr *queue;
 	dma_addr_t dma_addr;
 	DEFINE_DMA_UNMAP_ADDR(mapping);
+	unsigned long phys_addr;
 	struct t4_swsqe *sw_sq;
 	struct t4_swsqe *oldest_read;
 	u64 udb;
@@ -280,6 +307,7 @@
 	u16 cidx;
 	u16 pidx;
 	u16 wq_pidx;
+	u16 flags;
 };
 
 struct t4_swrqe {
@@ -350,6 +378,11 @@
 		wq->rq.cidx = 0;
 }
 
+static inline int t4_sq_onchip(struct t4_sq *sq)
+{
+	return sq->flags & T4_SQ_ONCHIP;
+}
+
 static inline int t4_sq_empty(struct t4_wq *wq)
 {
 	return wq->sq.in_use == 0;
@@ -396,30 +429,27 @@
 
 static inline int t4_wq_in_error(struct t4_wq *wq)
 {
-	return wq->sq.queue[wq->sq.size].status.qp_err;
+	return wq->rq.queue[wq->rq.size].status.qp_err;
 }
 
 static inline void t4_set_wq_in_error(struct t4_wq *wq)
 {
-	wq->sq.queue[wq->sq.size].status.qp_err = 1;
 	wq->rq.queue[wq->rq.size].status.qp_err = 1;
 }
 
 static inline void t4_disable_wq_db(struct t4_wq *wq)
 {
-	wq->sq.queue[wq->sq.size].status.db_off = 1;
 	wq->rq.queue[wq->rq.size].status.db_off = 1;
 }
 
 static inline void t4_enable_wq_db(struct t4_wq *wq)
 {
-	wq->sq.queue[wq->sq.size].status.db_off = 0;
 	wq->rq.queue[wq->rq.size].status.db_off = 0;
 }
 
 static inline int t4_wq_db_enabled(struct t4_wq *wq)
 {
-	return !wq->sq.queue[wq->sq.size].status.db_off;
+	return !wq->rq.queue[wq->rq.size].status.db_off;
 }
 
 struct t4_cq {
diff --git a/drivers/infiniband/hw/cxgb4/user.h b/drivers/infiniband/hw/cxgb4/user.h
index ed6414a..e6669d5 100644
--- a/drivers/infiniband/hw/cxgb4/user.h
+++ b/drivers/infiniband/hw/cxgb4/user.h
@@ -50,7 +50,13 @@
 	__u32 qid_mask;
 };
 
+
+enum {
+	C4IW_QPF_ONCHIP = (1<<0)
+};
+
 struct c4iw_create_qp_resp {
+	__u64 ma_sync_key;
 	__u64 sq_key;
 	__u64 rq_key;
 	__u64 sq_db_gts_key;
@@ -62,5 +68,6 @@
 	__u32 sq_size;
 	__u32 rq_size;
 	__u32 qid_mask;
+	__u32 flags;
 };
 #endif
diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c b/drivers/infiniband/hw/ehca/ehca_mrmw.c
index 53f4cd4..43cae84 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -171,7 +171,7 @@
 		}
 
 		ret = ehca_reg_maxmr(shca, e_maxmr,
-				     (void *)ehca_map_vaddr((void *)KERNELBASE),
+				     (void *)ehca_map_vaddr((void *)(KERNELBASE + PHYSICAL_START)),
 				     mr_access_flags, e_pd,
 				     &e_maxmr->ib.ib_mr.lkey,
 				     &e_maxmr->ib.ib_mr.rkey);
@@ -1636,7 +1636,7 @@
 
 	/* register internal max-MR on HCA */
 	size_maxmr = ehca_mr_len;
-	iova_start = (u64 *)ehca_map_vaddr((void *)KERNELBASE);
+	iova_start = (u64 *)ehca_map_vaddr((void *)(KERNELBASE + PHYSICAL_START));
 	ib_pbuf.addr = 0;
 	ib_pbuf.size = size_maxmr;
 	num_kpages = NUM_CHUNKS(((u64)iova_start % PAGE_SIZE) + size_maxmr,
@@ -2209,7 +2209,7 @@
 {
 	/* a MR is treated as max-MR only if it fits following: */
 	if ((size == ehca_mr_len) &&
-	    (iova_start == (void *)ehca_map_vaddr((void *)KERNELBASE))) {
+	    (iova_start == (void *)ehca_map_vaddr((void *)(KERNELBASE + PHYSICAL_START)))) {
 		ehca_gen_dbg("this is a max-MR");
 		return 1;
 	} else
diff --git a/drivers/infiniband/hw/ipath/Makefile b/drivers/infiniband/hw/ipath/Makefile
index fa3df82..4496f28 100644
--- a/drivers/infiniband/hw/ipath/Makefile
+++ b/drivers/infiniband/hw/ipath/Makefile
@@ -1,4 +1,4 @@
-EXTRA_CFLAGS += -DIPATH_IDSTR='"QLogic kernel.org driver"' \
+ccflags-y := -DIPATH_IDSTR='"QLogic kernel.org driver"' \
 	-DIPATH_KERN_TYPE=0
 
 obj-$(CONFIG_INFINIBAND_IPATH) += ib_ipath.o
diff --git a/drivers/infiniband/hw/mlx4/ah.c b/drivers/infiniband/hw/mlx4/ah.c
index 11a236f..4b8f9c4 100644
--- a/drivers/infiniband/hw/mlx4/ah.c
+++ b/drivers/infiniband/hw/mlx4/ah.c
@@ -30,66 +30,163 @@
  * SOFTWARE.
  */
 
+#include <rdma/ib_addr.h>
+#include <rdma/ib_cache.h>
+
 #include <linux/slab.h>
+#include <linux/inet.h>
+#include <linux/string.h>
 
 #include "mlx4_ib.h"
 
-struct ib_ah *mlx4_ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
+int mlx4_ib_resolve_grh(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah_attr,
+			u8 *mac, int *is_mcast, u8 port)
+{
+	struct in6_addr in6;
+
+	*is_mcast = 0;
+
+	memcpy(&in6, ah_attr->grh.dgid.raw, sizeof in6);
+	if (rdma_link_local_addr(&in6))
+		rdma_get_ll_mac(&in6, mac);
+	else if (rdma_is_multicast_addr(&in6)) {
+		rdma_get_mcast_mac(&in6, mac);
+		*is_mcast = 1;
+	} else
+		return -EINVAL;
+
+	return 0;
+}
+
+static struct ib_ah *create_ib_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr,
+				  struct mlx4_ib_ah *ah)
 {
 	struct mlx4_dev *dev = to_mdev(pd->device)->dev;
-	struct mlx4_ib_ah *ah;
 
-	ah = kmalloc(sizeof *ah, GFP_ATOMIC);
+	ah->av.ib.port_pd = cpu_to_be32(to_mpd(pd)->pdn | (ah_attr->port_num << 24));
+	ah->av.ib.g_slid  = ah_attr->src_path_bits;
+	if (ah_attr->ah_flags & IB_AH_GRH) {
+		ah->av.ib.g_slid   |= 0x80;
+		ah->av.ib.gid_index = ah_attr->grh.sgid_index;
+		ah->av.ib.hop_limit = ah_attr->grh.hop_limit;
+		ah->av.ib.sl_tclass_flowlabel |=
+			cpu_to_be32((ah_attr->grh.traffic_class << 20) |
+				    ah_attr->grh.flow_label);
+		memcpy(ah->av.ib.dgid, ah_attr->grh.dgid.raw, 16);
+	}
+
+	ah->av.ib.dlid    = cpu_to_be16(ah_attr->dlid);
+	if (ah_attr->static_rate) {
+		ah->av.ib.stat_rate = ah_attr->static_rate + MLX4_STAT_RATE_OFFSET;
+		while (ah->av.ib.stat_rate > IB_RATE_2_5_GBPS + MLX4_STAT_RATE_OFFSET &&
+		       !(1 << ah->av.ib.stat_rate & dev->caps.stat_rate_support))
+			--ah->av.ib.stat_rate;
+	}
+	ah->av.ib.sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 28);
+
+	return &ah->ibah;
+}
+
+static struct ib_ah *create_iboe_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr,
+				    struct mlx4_ib_ah *ah)
+{
+	struct mlx4_ib_dev *ibdev = to_mdev(pd->device);
+	struct mlx4_dev *dev = ibdev->dev;
+	union ib_gid sgid;
+	u8 mac[6];
+	int err;
+	int is_mcast;
+	u16 vlan_tag;
+
+	err = mlx4_ib_resolve_grh(ibdev, ah_attr, mac, &is_mcast, ah_attr->port_num);
+	if (err)
+		return ERR_PTR(err);
+
+	memcpy(ah->av.eth.mac, mac, 6);
+	err = ib_get_cached_gid(pd->device, ah_attr->port_num, ah_attr->grh.sgid_index, &sgid);
+	if (err)
+		return ERR_PTR(err);
+	vlan_tag = rdma_get_vlan_id(&sgid);
+	if (vlan_tag < 0x1000)
+		vlan_tag |= (ah_attr->sl & 7) << 13;
+	ah->av.eth.port_pd = cpu_to_be32(to_mpd(pd)->pdn | (ah_attr->port_num << 24));
+	ah->av.eth.gid_index = ah_attr->grh.sgid_index;
+	ah->av.eth.vlan = cpu_to_be16(vlan_tag);
+	if (ah_attr->static_rate) {
+		ah->av.eth.stat_rate = ah_attr->static_rate + MLX4_STAT_RATE_OFFSET;
+		while (ah->av.eth.stat_rate > IB_RATE_2_5_GBPS + MLX4_STAT_RATE_OFFSET &&
+		       !(1 << ah->av.eth.stat_rate & dev->caps.stat_rate_support))
+			--ah->av.eth.stat_rate;
+	}
+
+	/*
+	 * HW requires multicast LID so we just choose one.
+	 */
+	if (is_mcast)
+		ah->av.ib.dlid = cpu_to_be16(0xc000);
+
+	memcpy(ah->av.eth.dgid, ah_attr->grh.dgid.raw, 16);
+	ah->av.eth.sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 28);
+
+	return &ah->ibah;
+}
+
+struct ib_ah *mlx4_ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
+{
+	struct mlx4_ib_ah *ah;
+	struct ib_ah *ret;
+
+	ah = kzalloc(sizeof *ah, GFP_ATOMIC);
 	if (!ah)
 		return ERR_PTR(-ENOMEM);
 
-	memset(&ah->av, 0, sizeof ah->av);
+	if (rdma_port_get_link_layer(pd->device, ah_attr->port_num) == IB_LINK_LAYER_ETHERNET) {
+		if (!(ah_attr->ah_flags & IB_AH_GRH)) {
+			ret = ERR_PTR(-EINVAL);
+		} else {
+			/*
+			 * TBD: need to handle the case when we get
+			 * called in an atomic context and there we
+			 * might sleep.  We don't expect this
+			 * currently since we're working with link
+			 * local addresses which we can translate
+			 * without going to sleep.
+			 */
+			ret = create_iboe_ah(pd, ah_attr, ah);
+		}
 
-	ah->av.port_pd = cpu_to_be32(to_mpd(pd)->pdn | (ah_attr->port_num << 24));
-	ah->av.g_slid  = ah_attr->src_path_bits;
-	ah->av.dlid    = cpu_to_be16(ah_attr->dlid);
-	if (ah_attr->static_rate) {
-		ah->av.stat_rate = ah_attr->static_rate + MLX4_STAT_RATE_OFFSET;
-		while (ah->av.stat_rate > IB_RATE_2_5_GBPS + MLX4_STAT_RATE_OFFSET &&
-		       !(1 << ah->av.stat_rate & dev->caps.stat_rate_support))
-			--ah->av.stat_rate;
-	}
-	ah->av.sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 28);
-	if (ah_attr->ah_flags & IB_AH_GRH) {
-		ah->av.g_slid   |= 0x80;
-		ah->av.gid_index = ah_attr->grh.sgid_index;
-		ah->av.hop_limit = ah_attr->grh.hop_limit;
-		ah->av.sl_tclass_flowlabel |=
-			cpu_to_be32((ah_attr->grh.traffic_class << 20) |
-				    ah_attr->grh.flow_label);
-		memcpy(ah->av.dgid, ah_attr->grh.dgid.raw, 16);
-	}
+		if (IS_ERR(ret))
+			kfree(ah);
 
-	return &ah->ibah;
+		return ret;
+	} else
+		return create_ib_ah(pd, ah_attr, ah); /* never fails */
 }
 
 int mlx4_ib_query_ah(struct ib_ah *ibah, struct ib_ah_attr *ah_attr)
 {
 	struct mlx4_ib_ah *ah = to_mah(ibah);
+	enum rdma_link_layer ll;
 
 	memset(ah_attr, 0, sizeof *ah_attr);
-	ah_attr->dlid	       = be16_to_cpu(ah->av.dlid);
-	ah_attr->sl	       = be32_to_cpu(ah->av.sl_tclass_flowlabel) >> 28;
-	ah_attr->port_num      = be32_to_cpu(ah->av.port_pd) >> 24;
-	if (ah->av.stat_rate)
-		ah_attr->static_rate = ah->av.stat_rate - MLX4_STAT_RATE_OFFSET;
-	ah_attr->src_path_bits = ah->av.g_slid & 0x7F;
+	ah_attr->sl = be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 28;
+	ah_attr->port_num = be32_to_cpu(ah->av.ib.port_pd) >> 24;
+	ll = rdma_port_get_link_layer(ibah->device, ah_attr->port_num);
+	ah_attr->dlid = ll == IB_LINK_LAYER_INFINIBAND ? be16_to_cpu(ah->av.ib.dlid) : 0;
+	if (ah->av.ib.stat_rate)
+		ah_attr->static_rate = ah->av.ib.stat_rate - MLX4_STAT_RATE_OFFSET;
+	ah_attr->src_path_bits = ah->av.ib.g_slid & 0x7F;
 
 	if (mlx4_ib_ah_grh_present(ah)) {
 		ah_attr->ah_flags = IB_AH_GRH;
 
 		ah_attr->grh.traffic_class =
-			be32_to_cpu(ah->av.sl_tclass_flowlabel) >> 20;
+			be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 20;
 		ah_attr->grh.flow_label =
-			be32_to_cpu(ah->av.sl_tclass_flowlabel) & 0xfffff;
-		ah_attr->grh.hop_limit  = ah->av.hop_limit;
-		ah_attr->grh.sgid_index = ah->av.gid_index;
-		memcpy(ah_attr->grh.dgid.raw, ah->av.dgid, 16);
+			be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) & 0xfffff;
+		ah_attr->grh.hop_limit  = ah->av.ib.hop_limit;
+		ah_attr->grh.sgid_index = ah->av.ib.gid_index;
+		memcpy(ah_attr->grh.dgid.raw, ah->av.ib.dgid, 16);
 	}
 
 	return 0;
diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c
index f38d5b1..c9a8dd6 100644
--- a/drivers/infiniband/hw/mlx4/mad.c
+++ b/drivers/infiniband/hw/mlx4/mad.c
@@ -311,19 +311,25 @@
 	struct ib_mad_agent *agent;
 	int p, q;
 	int ret;
+	enum rdma_link_layer ll;
 
-	for (p = 0; p < dev->num_ports; ++p)
+	for (p = 0; p < dev->num_ports; ++p) {
+		ll = rdma_port_get_link_layer(&dev->ib_dev, p + 1);
 		for (q = 0; q <= 1; ++q) {
-			agent = ib_register_mad_agent(&dev->ib_dev, p + 1,
-						      q ? IB_QPT_GSI : IB_QPT_SMI,
-						      NULL, 0, send_handler,
-						      NULL, NULL);
-			if (IS_ERR(agent)) {
-				ret = PTR_ERR(agent);
-				goto err;
-			}
-			dev->send_agent[p][q] = agent;
+			if (ll == IB_LINK_LAYER_INFINIBAND) {
+				agent = ib_register_mad_agent(&dev->ib_dev, p + 1,
+							      q ? IB_QPT_GSI : IB_QPT_SMI,
+							      NULL, 0, send_handler,
+							      NULL, NULL);
+				if (IS_ERR(agent)) {
+					ret = PTR_ERR(agent);
+					goto err;
+				}
+				dev->send_agent[p][q] = agent;
+			} else
+				dev->send_agent[p][q] = NULL;
 		}
+	}
 
 	return 0;
 
@@ -344,8 +350,10 @@
 	for (p = 0; p < dev->num_ports; ++p) {
 		for (q = 0; q <= 1; ++q) {
 			agent = dev->send_agent[p][q];
-			dev->send_agent[p][q] = NULL;
-			ib_unregister_mad_agent(agent);
+			if (agent) {
+				dev->send_agent[p][q] = NULL;
+				ib_unregister_mad_agent(agent);
+			}
 		}
 
 		if (dev->sm_ah[p])
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index 4e94e36..bf3e20c 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -35,9 +35,14 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/rtnetlink.h>
+#include <linux/if_vlan.h>
 
 #include <rdma/ib_smi.h>
 #include <rdma/ib_user_verbs.h>
+#include <rdma/ib_addr.h>
 
 #include <linux/mlx4/driver.h>
 #include <linux/mlx4/cmd.h>
@@ -58,6 +63,15 @@
 	DRV_NAME ": Mellanox ConnectX InfiniBand driver v"
 	DRV_VERSION " (" DRV_RELDATE ")\n";
 
+struct update_gid_work {
+	struct work_struct	work;
+	union ib_gid		gids[128];
+	struct mlx4_ib_dev     *dev;
+	int			port;
+};
+
+static struct workqueue_struct *wq;
+
 static void init_query_mad(struct ib_smp *mad)
 {
 	mad->base_version  = 1;
@@ -66,6 +80,8 @@
 	mad->method	   = IB_MGMT_METHOD_GET;
 }
 
+static union ib_gid zgid;
+
 static int mlx4_ib_query_device(struct ib_device *ibdev,
 				struct ib_device_attr *props)
 {
@@ -135,7 +151,7 @@
 	props->max_srq		   = dev->dev->caps.num_srqs - dev->dev->caps.reserved_srqs;
 	props->max_srq_wr	   = dev->dev->caps.max_srq_wqes - 1;
 	props->max_srq_sge	   = dev->dev->caps.max_srq_sge;
-	props->max_fast_reg_page_list_len = PAGE_SIZE / sizeof (u64);
+	props->max_fast_reg_page_list_len = MLX4_MAX_FAST_REG_PAGES;
 	props->local_ca_ack_delay  = dev->dev->caps.local_ca_ack_delay;
 	props->atomic_cap	   = dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_ATOMIC ?
 		IB_ATOMIC_HCA : IB_ATOMIC_NONE;
@@ -154,6 +170,87 @@
 	return err;
 }
 
+static enum rdma_link_layer
+mlx4_ib_port_link_layer(struct ib_device *device, u8 port_num)
+{
+	struct mlx4_dev *dev = to_mdev(device)->dev;
+
+	return dev->caps.port_mask & (1 << (port_num - 1)) ?
+		IB_LINK_LAYER_INFINIBAND : IB_LINK_LAYER_ETHERNET;
+}
+
+static int ib_link_query_port(struct ib_device *ibdev, u8 port,
+			      struct ib_port_attr *props,
+			      struct ib_smp *out_mad)
+{
+	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));
+	props->sm_sl		= out_mad->data[36] & 0xf;
+	props->state		= out_mad->data[32] & 0xf;
+	props->phys_state	= out_mad->data[33] >> 4;
+	props->port_cap_flags	= be32_to_cpup((__be32 *) (out_mad->data + 20));
+	props->gid_tbl_len	= to_mdev(ibdev)->dev->caps.gid_table_len[port];
+	props->max_msg_sz	= to_mdev(ibdev)->dev->caps.max_msg_sz;
+	props->pkey_tbl_len	= to_mdev(ibdev)->dev->caps.pkey_table_len[port];
+	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->active_width	= out_mad->data[31] & 0xf;
+	props->active_speed	= out_mad->data[35] >> 4;
+	props->max_mtu		= out_mad->data[41] & 0xf;
+	props->active_mtu	= out_mad->data[36] >> 4;
+	props->subnet_timeout	= out_mad->data[51] & 0x1f;
+	props->max_vl_num	= out_mad->data[37] >> 4;
+	props->init_type_reply	= out_mad->data[41] >> 4;
+
+	return 0;
+}
+
+static u8 state_to_phys_state(enum ib_port_state state)
+{
+	return state == IB_PORT_ACTIVE ? 5 : 3;
+}
+
+static int eth_link_query_port(struct ib_device *ibdev, u8 port,
+			       struct ib_port_attr *props,
+			       struct ib_smp *out_mad)
+{
+	struct mlx4_ib_iboe *iboe = &to_mdev(ibdev)->iboe;
+	struct net_device *ndev;
+	enum ib_mtu tmp;
+
+	props->active_width	= IB_WIDTH_4X;
+	props->active_speed	= 4;
+	props->port_cap_flags	= IB_PORT_CM_SUP;
+	props->gid_tbl_len	= to_mdev(ibdev)->dev->caps.gid_table_len[port];
+	props->max_msg_sz	= to_mdev(ibdev)->dev->caps.max_msg_sz;
+	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->subnet_timeout	= 0;
+	props->max_vl_num	= out_mad->data[37] >> 4;
+	props->init_type_reply	= 0;
+	props->state		= IB_PORT_DOWN;
+	props->phys_state	= state_to_phys_state(props->state);
+	props->active_mtu	= IB_MTU_256;
+	spin_lock(&iboe->lock);
+	ndev = iboe->netdevs[port - 1];
+	if (!ndev)
+		goto out;
+
+	tmp = iboe_get_mtu(ndev->mtu);
+	props->active_mtu = tmp ? min(props->max_mtu, tmp) : IB_MTU_256;
+
+	props->state		= netif_running(ndev) &&  netif_oper_up(ndev) ?
+					IB_PORT_ACTIVE : IB_PORT_DOWN;
+	props->phys_state	= state_to_phys_state(props->state);
+
+out:
+	spin_unlock(&iboe->lock);
+	return 0;
+}
+
 static int mlx4_ib_query_port(struct ib_device *ibdev, u8 port,
 			      struct ib_port_attr *props)
 {
@@ -176,25 +273,9 @@
 	if (err)
 		goto out;
 
-	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));
-	props->sm_sl		= out_mad->data[36] & 0xf;
-	props->state		= out_mad->data[32] & 0xf;
-	props->phys_state	= out_mad->data[33] >> 4;
-	props->port_cap_flags	= be32_to_cpup((__be32 *) (out_mad->data + 20));
-	props->gid_tbl_len	= to_mdev(ibdev)->dev->caps.gid_table_len[port];
-	props->max_msg_sz	= to_mdev(ibdev)->dev->caps.max_msg_sz;
-	props->pkey_tbl_len	= to_mdev(ibdev)->dev->caps.pkey_table_len[port];
-	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->active_width	= out_mad->data[31] & 0xf;
-	props->active_speed	= out_mad->data[35] >> 4;
-	props->max_mtu		= out_mad->data[41] & 0xf;
-	props->active_mtu	= out_mad->data[36] >> 4;
-	props->subnet_timeout	= out_mad->data[51] & 0x1f;
-	props->max_vl_num	= out_mad->data[37] >> 4;
-	props->init_type_reply	= out_mad->data[41] >> 4;
+	err = mlx4_ib_port_link_layer(ibdev, port) == IB_LINK_LAYER_INFINIBAND ?
+		ib_link_query_port(ibdev, port, props, out_mad) :
+		eth_link_query_port(ibdev, port, props, out_mad);
 
 out:
 	kfree(in_mad);
@@ -203,8 +284,8 @@
 	return err;
 }
 
-static int mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index,
-			     union ib_gid *gid)
+static int __mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index,
+			       union ib_gid *gid)
 {
 	struct ib_smp *in_mad  = NULL;
 	struct ib_smp *out_mad = NULL;
@@ -241,6 +322,25 @@
 	return err;
 }
 
+static int iboe_query_gid(struct ib_device *ibdev, u8 port, int index,
+			  union ib_gid *gid)
+{
+	struct mlx4_ib_dev *dev = to_mdev(ibdev);
+
+	*gid = dev->iboe.gid_table[port - 1][index];
+
+	return 0;
+}
+
+static int mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index,
+			     union ib_gid *gid)
+{
+	if (rdma_port_get_link_layer(ibdev, port) == IB_LINK_LAYER_INFINIBAND)
+		return __mlx4_ib_query_gid(ibdev, port, index, gid);
+	else
+		return iboe_query_gid(ibdev, port, index, gid);
+}
+
 static int mlx4_ib_query_pkey(struct ib_device *ibdev, u8 port, u16 index,
 			      u16 *pkey)
 {
@@ -272,14 +372,32 @@
 static int mlx4_ib_modify_device(struct ib_device *ibdev, int mask,
 				 struct ib_device_modify *props)
 {
+	struct mlx4_cmd_mailbox *mailbox;
+
 	if (mask & ~IB_DEVICE_MODIFY_NODE_DESC)
 		return -EOPNOTSUPP;
 
-	if (mask & IB_DEVICE_MODIFY_NODE_DESC) {
-		spin_lock(&to_mdev(ibdev)->sm_lock);
-		memcpy(ibdev->node_desc, props->node_desc, 64);
-		spin_unlock(&to_mdev(ibdev)->sm_lock);
-	}
+	if (!(mask & IB_DEVICE_MODIFY_NODE_DESC))
+		return 0;
+
+	spin_lock(&to_mdev(ibdev)->sm_lock);
+	memcpy(ibdev->node_desc, props->node_desc, 64);
+	spin_unlock(&to_mdev(ibdev)->sm_lock);
+
+	/*
+	 * If possible, pass node desc to FW, so it can generate
+	 * a 144 trap.  If cmd fails, just ignore.
+	 */
+	mailbox = mlx4_alloc_cmd_mailbox(to_mdev(ibdev)->dev);
+	if (IS_ERR(mailbox))
+		return 0;
+
+	memset(mailbox->buf, 0, 256);
+	memcpy(mailbox->buf, props->node_desc, 64);
+	mlx4_cmd(to_mdev(ibdev)->dev, mailbox->dma, 1, 0,
+		 MLX4_CMD_SET_NODE, MLX4_CMD_TIME_CLASS_A);
+
+	mlx4_free_cmd_mailbox(to_mdev(ibdev)->dev, mailbox);
 
 	return 0;
 }
@@ -289,6 +407,7 @@
 {
 	struct mlx4_cmd_mailbox *mailbox;
 	int err;
+	u8 is_eth = dev->dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH;
 
 	mailbox = mlx4_alloc_cmd_mailbox(dev->dev);
 	if (IS_ERR(mailbox))
@@ -304,7 +423,7 @@
 		((__be32 *) mailbox->buf)[1] = cpu_to_be32(cap_mask);
 	}
 
-	err = mlx4_cmd(dev->dev, mailbox->dma, port, 0, MLX4_CMD_SET_PORT,
+	err = mlx4_cmd(dev->dev, mailbox->dma, port, is_eth, MLX4_CMD_SET_PORT,
 		       MLX4_CMD_TIME_CLASS_B);
 
 	mlx4_free_cmd_mailbox(dev->dev, mailbox);
@@ -447,18 +566,132 @@
 	return 0;
 }
 
+static int add_gid_entry(struct ib_qp *ibqp, union ib_gid *gid)
+{
+	struct mlx4_ib_qp *mqp = to_mqp(ibqp);
+	struct mlx4_ib_dev *mdev = to_mdev(ibqp->device);
+	struct mlx4_ib_gid_entry *ge;
+
+	ge = kzalloc(sizeof *ge, GFP_KERNEL);
+	if (!ge)
+		return -ENOMEM;
+
+	ge->gid = *gid;
+	if (mlx4_ib_add_mc(mdev, mqp, gid)) {
+		ge->port = mqp->port;
+		ge->added = 1;
+	}
+
+	mutex_lock(&mqp->mutex);
+	list_add_tail(&ge->list, &mqp->gid_list);
+	mutex_unlock(&mqp->mutex);
+
+	return 0;
+}
+
+int mlx4_ib_add_mc(struct mlx4_ib_dev *mdev, struct mlx4_ib_qp *mqp,
+		   union ib_gid *gid)
+{
+	u8 mac[6];
+	struct net_device *ndev;
+	int ret = 0;
+
+	if (!mqp->port)
+		return 0;
+
+	spin_lock(&mdev->iboe.lock);
+	ndev = mdev->iboe.netdevs[mqp->port - 1];
+	if (ndev)
+		dev_hold(ndev);
+	spin_unlock(&mdev->iboe.lock);
+
+	if (ndev) {
+		rdma_get_mcast_mac((struct in6_addr *)gid, mac);
+		rtnl_lock();
+		dev_mc_add(mdev->iboe.netdevs[mqp->port - 1], mac);
+		ret = 1;
+		rtnl_unlock();
+		dev_put(ndev);
+	}
+
+	return ret;
+}
+
 static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
 {
-	return mlx4_multicast_attach(to_mdev(ibqp->device)->dev,
-				     &to_mqp(ibqp)->mqp, gid->raw,
-				     !!(to_mqp(ibqp)->flags &
-					MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK));
+	int err;
+	struct mlx4_ib_dev *mdev = to_mdev(ibqp->device);
+	struct mlx4_ib_qp *mqp = to_mqp(ibqp);
+
+	err = mlx4_multicast_attach(mdev->dev, &mqp->mqp, gid->raw, !!(mqp->flags &
+				    MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK));
+	if (err)
+		return err;
+
+	err = add_gid_entry(ibqp, gid);
+	if (err)
+		goto err_add;
+
+	return 0;
+
+err_add:
+	mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw);
+	return err;
+}
+
+static struct mlx4_ib_gid_entry *find_gid_entry(struct mlx4_ib_qp *qp, u8 *raw)
+{
+	struct mlx4_ib_gid_entry *ge;
+	struct mlx4_ib_gid_entry *tmp;
+	struct mlx4_ib_gid_entry *ret = NULL;
+
+	list_for_each_entry_safe(ge, tmp, &qp->gid_list, list) {
+		if (!memcmp(raw, ge->gid.raw, 16)) {
+			ret = ge;
+			break;
+		}
+	}
+
+	return ret;
 }
 
 static int mlx4_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
 {
-	return mlx4_multicast_detach(to_mdev(ibqp->device)->dev,
-				     &to_mqp(ibqp)->mqp, gid->raw);
+	int err;
+	struct mlx4_ib_dev *mdev = to_mdev(ibqp->device);
+	struct mlx4_ib_qp *mqp = to_mqp(ibqp);
+	u8 mac[6];
+	struct net_device *ndev;
+	struct mlx4_ib_gid_entry *ge;
+
+	err = mlx4_multicast_detach(mdev->dev,
+				    &mqp->mqp, gid->raw);
+	if (err)
+		return err;
+
+	mutex_lock(&mqp->mutex);
+	ge = find_gid_entry(mqp, gid->raw);
+	if (ge) {
+		spin_lock(&mdev->iboe.lock);
+		ndev = ge->added ? mdev->iboe.netdevs[ge->port - 1] : NULL;
+		if (ndev)
+			dev_hold(ndev);
+		spin_unlock(&mdev->iboe.lock);
+		rdma_get_mcast_mac((struct in6_addr *)gid, mac);
+		if (ndev) {
+			rtnl_lock();
+			dev_mc_del(mdev->iboe.netdevs[ge->port - 1], mac);
+			rtnl_unlock();
+			dev_put(ndev);
+		}
+		list_del(&ge->list);
+		kfree(ge);
+	} else
+		printk(KERN_WARNING "could not find mgid entry\n");
+
+	mutex_unlock(&mqp->mutex);
+
+	return 0;
 }
 
 static int init_node_data(struct mlx4_ib_dev *dev)
@@ -543,15 +776,215 @@
 	&dev_attr_board_id
 };
 
+static void mlx4_addrconf_ifid_eui48(u8 *eui, u16 vlan_id, struct net_device *dev)
+{
+	memcpy(eui, dev->dev_addr, 3);
+	memcpy(eui + 5, dev->dev_addr + 3, 3);
+	if (vlan_id < 0x1000) {
+		eui[3] = vlan_id >> 8;
+		eui[4] = vlan_id & 0xff;
+	} else {
+		eui[3] = 0xff;
+		eui[4] = 0xfe;
+	}
+	eui[0] ^= 2;
+}
+
+static void update_gids_task(struct work_struct *work)
+{
+	struct update_gid_work *gw = container_of(work, struct update_gid_work, work);
+	struct mlx4_cmd_mailbox *mailbox;
+	union ib_gid *gids;
+	int err;
+	struct mlx4_dev	*dev = gw->dev->dev;
+	struct ib_event event;
+
+	mailbox = mlx4_alloc_cmd_mailbox(dev);
+	if (IS_ERR(mailbox)) {
+		printk(KERN_WARNING "update gid table failed %ld\n", PTR_ERR(mailbox));
+		return;
+	}
+
+	gids = mailbox->buf;
+	memcpy(gids, gw->gids, sizeof gw->gids);
+
+	err = mlx4_cmd(dev, mailbox->dma, MLX4_SET_PORT_GID_TABLE << 8 | gw->port,
+		       1, MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B);
+	if (err)
+		printk(KERN_WARNING "set port command failed\n");
+	else {
+		memcpy(gw->dev->iboe.gid_table[gw->port - 1], gw->gids, sizeof gw->gids);
+		event.device = &gw->dev->ib_dev;
+		event.element.port_num = gw->port;
+		event.event    = IB_EVENT_LID_CHANGE;
+		ib_dispatch_event(&event);
+	}
+
+	mlx4_free_cmd_mailbox(dev, mailbox);
+	kfree(gw);
+}
+
+static int update_ipv6_gids(struct mlx4_ib_dev *dev, int port, int clear)
+{
+	struct net_device *ndev = dev->iboe.netdevs[port - 1];
+	struct update_gid_work *work;
+	struct net_device *tmp;
+	int i;
+	u8 *hits;
+	int ret;
+	union ib_gid gid;
+	int free;
+	int found;
+	int need_update = 0;
+	u16 vid;
+
+	work = kzalloc(sizeof *work, GFP_ATOMIC);
+	if (!work)
+		return -ENOMEM;
+
+	hits = kzalloc(128, GFP_ATOMIC);
+	if (!hits) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	read_lock(&dev_base_lock);
+	for_each_netdev(&init_net, tmp) {
+		if (ndev && (tmp == ndev || rdma_vlan_dev_real_dev(tmp) == ndev)) {
+			gid.global.subnet_prefix = cpu_to_be64(0xfe80000000000000LL);
+			vid = rdma_vlan_dev_vlan_id(tmp);
+			mlx4_addrconf_ifid_eui48(&gid.raw[8], vid, ndev);
+			found = 0;
+			free = -1;
+			for (i = 0; i < 128; ++i) {
+				if (free < 0 &&
+				    !memcmp(&dev->iboe.gid_table[port - 1][i], &zgid, sizeof zgid))
+					free = i;
+				if (!memcmp(&dev->iboe.gid_table[port - 1][i], &gid, sizeof gid)) {
+					hits[i] = 1;
+					found = 1;
+					break;
+				}
+			}
+
+			if (!found) {
+				if (tmp == ndev &&
+				    (memcmp(&dev->iboe.gid_table[port - 1][0],
+					    &gid, sizeof gid) ||
+				     !memcmp(&dev->iboe.gid_table[port - 1][0],
+					     &zgid, sizeof gid))) {
+					dev->iboe.gid_table[port - 1][0] = gid;
+					++need_update;
+					hits[0] = 1;
+				} else if (free >= 0) {
+					dev->iboe.gid_table[port - 1][free] = gid;
+					hits[free] = 1;
+					++need_update;
+				}
+			}
+		}
+	}
+	read_unlock(&dev_base_lock);
+
+	for (i = 0; i < 128; ++i)
+		if (!hits[i]) {
+			if (memcmp(&dev->iboe.gid_table[port - 1][i], &zgid, sizeof zgid))
+				++need_update;
+			dev->iboe.gid_table[port - 1][i] = zgid;
+		}
+
+	if (need_update) {
+		memcpy(work->gids, dev->iboe.gid_table[port - 1], sizeof work->gids);
+		INIT_WORK(&work->work, update_gids_task);
+		work->port = port;
+		work->dev = dev;
+		queue_work(wq, &work->work);
+	} else
+		kfree(work);
+
+	kfree(hits);
+	return 0;
+
+out:
+	kfree(work);
+	return ret;
+}
+
+static void handle_en_event(struct mlx4_ib_dev *dev, int port, unsigned long event)
+{
+	switch (event) {
+	case NETDEV_UP:
+	case NETDEV_CHANGEADDR:
+		update_ipv6_gids(dev, port, 0);
+		break;
+
+	case NETDEV_DOWN:
+		update_ipv6_gids(dev, port, 1);
+		dev->iboe.netdevs[port - 1] = NULL;
+	}
+}
+
+static void netdev_added(struct mlx4_ib_dev *dev, int port)
+{
+	update_ipv6_gids(dev, port, 0);
+}
+
+static void netdev_removed(struct mlx4_ib_dev *dev, int port)
+{
+	update_ipv6_gids(dev, port, 1);
+}
+
+static int mlx4_ib_netdev_event(struct notifier_block *this, unsigned long event,
+				void *ptr)
+{
+	struct net_device *dev = ptr;
+	struct mlx4_ib_dev *ibdev;
+	struct net_device *oldnd;
+	struct mlx4_ib_iboe *iboe;
+	int port;
+
+	if (!net_eq(dev_net(dev), &init_net))
+		return NOTIFY_DONE;
+
+	ibdev = container_of(this, struct mlx4_ib_dev, iboe.nb);
+	iboe = &ibdev->iboe;
+
+	spin_lock(&iboe->lock);
+	mlx4_foreach_ib_transport_port(port, ibdev->dev) {
+		oldnd = iboe->netdevs[port - 1];
+		iboe->netdevs[port - 1] =
+			mlx4_get_protocol_dev(ibdev->dev, MLX4_PROTOCOL_EN, port);
+		if (oldnd != iboe->netdevs[port - 1]) {
+			if (iboe->netdevs[port - 1])
+				netdev_added(ibdev, port);
+			else
+				netdev_removed(ibdev, port);
+		}
+	}
+
+	if (dev == iboe->netdevs[0] ||
+	    (iboe->netdevs[0] && rdma_vlan_dev_real_dev(dev) == iboe->netdevs[0]))
+		handle_en_event(ibdev, 1, event);
+	else if (dev == iboe->netdevs[1]
+		 || (iboe->netdevs[1] && rdma_vlan_dev_real_dev(dev) == iboe->netdevs[1]))
+		handle_en_event(ibdev, 2, event);
+
+	spin_unlock(&iboe->lock);
+
+	return NOTIFY_DONE;
+}
+
 static void *mlx4_ib_add(struct mlx4_dev *dev)
 {
 	struct mlx4_ib_dev *ibdev;
 	int num_ports = 0;
 	int i;
+	int err;
+	struct mlx4_ib_iboe *iboe;
 
 	printk_once(KERN_INFO "%s", mlx4_ib_version);
 
-	mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB)
+	mlx4_foreach_ib_transport_port(i, dev)
 		num_ports++;
 
 	/* No point in registering a device with no ports... */
@@ -564,6 +997,8 @@
 		return NULL;
 	}
 
+	iboe = &ibdev->iboe;
+
 	if (mlx4_pd_alloc(dev, &ibdev->priv_pdn))
 		goto err_dealloc;
 
@@ -612,6 +1047,7 @@
 
 	ibdev->ib_dev.query_device	= mlx4_ib_query_device;
 	ibdev->ib_dev.query_port	= mlx4_ib_query_port;
+	ibdev->ib_dev.get_link_layer	= mlx4_ib_port_link_layer;
 	ibdev->ib_dev.query_gid		= mlx4_ib_query_gid;
 	ibdev->ib_dev.query_pkey	= mlx4_ib_query_pkey;
 	ibdev->ib_dev.modify_device	= mlx4_ib_modify_device;
@@ -656,6 +1092,8 @@
 	ibdev->ib_dev.unmap_fmr		= mlx4_ib_unmap_fmr;
 	ibdev->ib_dev.dealloc_fmr	= mlx4_ib_fmr_dealloc;
 
+	spin_lock_init(&iboe->lock);
+
 	if (init_node_data(ibdev))
 		goto err_map;
 
@@ -668,16 +1106,28 @@
 	if (mlx4_ib_mad_init(ibdev))
 		goto err_reg;
 
+	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_IBOE && !iboe->nb.notifier_call) {
+		iboe->nb.notifier_call = mlx4_ib_netdev_event;
+		err = register_netdevice_notifier(&iboe->nb);
+		if (err)
+			goto err_reg;
+	}
+
 	for (i = 0; i < ARRAY_SIZE(mlx4_class_attributes); ++i) {
 		if (device_create_file(&ibdev->ib_dev.dev,
 				       mlx4_class_attributes[i]))
-			goto err_reg;
+			goto err_notif;
 	}
 
 	ibdev->ib_active = true;
 
 	return ibdev;
 
+err_notif:
+	if (unregister_netdevice_notifier(&ibdev->iboe.nb))
+		printk(KERN_WARNING "failure unregistering notifier\n");
+	flush_workqueue(wq);
+
 err_reg:
 	ib_unregister_device(&ibdev->ib_dev);
 
@@ -703,11 +1153,16 @@
 
 	mlx4_ib_mad_cleanup(ibdev);
 	ib_unregister_device(&ibdev->ib_dev);
+	if (ibdev->iboe.nb.notifier_call) {
+		if (unregister_netdevice_notifier(&ibdev->iboe.nb))
+			printk(KERN_WARNING "failure unregistering notifier\n");
+		ibdev->iboe.nb.notifier_call = NULL;
+	}
+	iounmap(ibdev->uar_map);
 
-	for (p = 1; p <= ibdev->num_ports; ++p)
+	mlx4_foreach_port(p, dev, MLX4_PORT_TYPE_IB)
 		mlx4_CLOSE_PORT(dev, p);
 
-	iounmap(ibdev->uar_map);
 	mlx4_uar_free(dev, &ibdev->priv_uar);
 	mlx4_pd_free(dev, ibdev->priv_pdn);
 	ib_dealloc_device(&ibdev->ib_dev);
@@ -747,19 +1202,33 @@
 }
 
 static struct mlx4_interface mlx4_ib_interface = {
-	.add	= mlx4_ib_add,
-	.remove	= mlx4_ib_remove,
-	.event	= mlx4_ib_event
+	.add		= mlx4_ib_add,
+	.remove		= mlx4_ib_remove,
+	.event		= mlx4_ib_event,
+	.protocol	= MLX4_PROTOCOL_IB
 };
 
 static int __init mlx4_ib_init(void)
 {
-	return mlx4_register_interface(&mlx4_ib_interface);
+	int err;
+
+	wq = create_singlethread_workqueue("mlx4_ib");
+	if (!wq)
+		return -ENOMEM;
+
+	err = mlx4_register_interface(&mlx4_ib_interface);
+	if (err) {
+		destroy_workqueue(wq);
+		return err;
+	}
+
+	return 0;
 }
 
 static void __exit mlx4_ib_cleanup(void)
 {
 	mlx4_unregister_interface(&mlx4_ib_interface);
+	destroy_workqueue(wq);
 }
 
 module_init(mlx4_ib_init);
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index 3486d76..2a322f2 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -112,6 +112,13 @@
 	MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK	= 1 << 1,
 };
 
+struct mlx4_ib_gid_entry {
+	struct list_head	list;
+	union ib_gid		gid;
+	int			added;
+	u8			port;
+};
+
 struct mlx4_ib_qp {
 	struct ib_qp		ibqp;
 	struct mlx4_qp		mqp;
@@ -138,6 +145,8 @@
 	u8			resp_depth;
 	u8			sq_no_prefetch;
 	u8			state;
+	int			mlx_type;
+	struct list_head	gid_list;
 };
 
 struct mlx4_ib_srq {
@@ -157,7 +166,14 @@
 
 struct mlx4_ib_ah {
 	struct ib_ah		ibah;
-	struct mlx4_av		av;
+	union mlx4_ext_av       av;
+};
+
+struct mlx4_ib_iboe {
+	spinlock_t		lock;
+	struct net_device      *netdevs[MLX4_MAX_PORTS];
+	struct notifier_block 	nb;
+	union ib_gid		gid_table[MLX4_MAX_PORTS][128];
 };
 
 struct mlx4_ib_dev {
@@ -176,6 +192,7 @@
 
 	struct mutex		cap_mask_mutex;
 	bool			ib_active;
+	struct mlx4_ib_iboe	iboe;
 };
 
 static inline struct mlx4_ib_dev *to_mdev(struct ib_device *ibdev)
@@ -314,9 +331,20 @@
 int mlx4_ib_unmap_fmr(struct list_head *fmr_list);
 int mlx4_ib_fmr_dealloc(struct ib_fmr *fmr);
 
+int mlx4_ib_resolve_grh(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah_attr,
+			u8 *mac, int *is_mcast, u8 port);
+
 static inline int mlx4_ib_ah_grh_present(struct mlx4_ib_ah *ah)
 {
-	return !!(ah->av.g_slid & 0x80);
+	u8 port = be32_to_cpu(ah->av.ib.port_pd) >> 24 & 3;
+
+	if (rdma_port_get_link_layer(ah->ibah.device, port) == IB_LINK_LAYER_ETHERNET)
+		return 1;
+
+	return !!(ah->av.ib.g_slid & 0x80);
 }
 
+int mlx4_ib_add_mc(struct mlx4_ib_dev *mdev, struct mlx4_ib_qp *mqp,
+		   union ib_gid *gid);
+
 #endif /* MLX4_IB_H */
diff --git a/drivers/infiniband/hw/mlx4/mr.c b/drivers/infiniband/hw/mlx4/mr.c
index 1d27b9a..dca55b1 100644
--- a/drivers/infiniband/hw/mlx4/mr.c
+++ b/drivers/infiniband/hw/mlx4/mr.c
@@ -226,7 +226,7 @@
 	struct mlx4_ib_fast_reg_page_list *mfrpl;
 	int size = page_list_len * sizeof (u64);
 
-	if (size > PAGE_SIZE)
+	if (page_list_len > MLX4_MAX_FAST_REG_PAGES)
 		return ERR_PTR(-EINVAL);
 
 	mfrpl = kmalloc(sizeof *mfrpl, GFP_KERNEL);
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 6a60827..9a7794a 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -33,9 +33,11 @@
 
 #include <linux/log2.h>
 #include <linux/slab.h>
+#include <linux/netdevice.h>
 
 #include <rdma/ib_cache.h>
 #include <rdma/ib_pack.h>
+#include <rdma/ib_addr.h>
 
 #include <linux/mlx4/qp.h>
 
@@ -48,17 +50,26 @@
 
 enum {
 	MLX4_IB_DEFAULT_SCHED_QUEUE	= 0x83,
-	MLX4_IB_DEFAULT_QP0_SCHED_QUEUE	= 0x3f
+	MLX4_IB_DEFAULT_QP0_SCHED_QUEUE	= 0x3f,
+	MLX4_IB_LINK_TYPE_IB		= 0,
+	MLX4_IB_LINK_TYPE_ETH		= 1
 };
 
 enum {
 	/*
-	 * Largest possible UD header: send with GRH and immediate data.
+	 * Largest possible UD header: send with GRH and immediate
+	 * data plus 18 bytes for an Ethernet header with VLAN/802.1Q
+	 * tag.  (LRH would only use 8 bytes, so Ethernet is the
+	 * biggest case)
 	 */
-	MLX4_IB_UD_HEADER_SIZE		= 72,
+	MLX4_IB_UD_HEADER_SIZE		= 82,
 	MLX4_IB_LSO_HEADER_SPARE	= 128,
 };
 
+enum {
+	MLX4_IB_IBOE_ETHERTYPE		= 0x8915
+};
+
 struct mlx4_ib_sqp {
 	struct mlx4_ib_qp	qp;
 	int			pkey_index;
@@ -462,6 +473,7 @@
 	mutex_init(&qp->mutex);
 	spin_lock_init(&qp->sq.lock);
 	spin_lock_init(&qp->rq.lock);
+	INIT_LIST_HEAD(&qp->gid_list);
 
 	qp->state	 = IB_QPS_RESET;
 	if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR)
@@ -649,6 +661,16 @@
 	}
 }
 
+static void del_gid_entries(struct mlx4_ib_qp *qp)
+{
+	struct mlx4_ib_gid_entry *ge, *tmp;
+
+	list_for_each_entry_safe(ge, tmp, &qp->gid_list, list) {
+		list_del(&ge->list);
+		kfree(ge);
+	}
+}
+
 static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
 			      int is_user)
 {
@@ -695,6 +717,8 @@
 		if (!qp->ibqp.srq)
 			mlx4_db_free(dev->dev, &qp->db);
 	}
+
+	del_gid_entries(qp);
 }
 
 struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
@@ -852,6 +876,14 @@
 static int mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah,
 			 struct mlx4_qp_path *path, u8 port)
 {
+	int err;
+	int is_eth = rdma_port_get_link_layer(&dev->ib_dev, port) ==
+		IB_LINK_LAYER_ETHERNET;
+	u8 mac[6];
+	int is_mcast;
+	u16 vlan_tag;
+	int vidx;
+
 	path->grh_mylmc     = ah->src_path_bits & 0x7f;
 	path->rlid	    = cpu_to_be16(ah->dlid);
 	if (ah->static_rate) {
@@ -879,12 +911,49 @@
 		memcpy(path->rgid, ah->grh.dgid.raw, 16);
 	}
 
-	path->sched_queue = MLX4_IB_DEFAULT_SCHED_QUEUE |
-		((port - 1) << 6) | ((ah->sl & 0xf) << 2);
+	if (is_eth) {
+		path->sched_queue = MLX4_IB_DEFAULT_SCHED_QUEUE |
+			((port - 1) << 6) | ((ah->sl & 7) << 3) | ((ah->sl & 8) >> 1);
+
+		if (!(ah->ah_flags & IB_AH_GRH))
+			return -1;
+
+		err = mlx4_ib_resolve_grh(dev, ah, mac, &is_mcast, port);
+		if (err)
+			return err;
+
+		memcpy(path->dmac, mac, 6);
+		path->ackto = MLX4_IB_LINK_TYPE_ETH;
+		/* use index 0 into MAC table for IBoE */
+		path->grh_mylmc &= 0x80;
+
+		vlan_tag = rdma_get_vlan_id(&dev->iboe.gid_table[port - 1][ah->grh.sgid_index]);
+		if (vlan_tag < 0x1000) {
+			if (mlx4_find_cached_vlan(dev->dev, port, vlan_tag, &vidx))
+				return -ENOENT;
+
+			path->vlan_index = vidx;
+			path->fl = 1 << 6;
+		}
+	} else
+		path->sched_queue = MLX4_IB_DEFAULT_SCHED_QUEUE |
+			((port - 1) << 6) | ((ah->sl & 0xf) << 2);
 
 	return 0;
 }
 
+static void update_mcg_macs(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp)
+{
+	struct mlx4_ib_gid_entry *ge, *tmp;
+
+	list_for_each_entry_safe(ge, tmp, &qp->gid_list, list) {
+		if (!ge->added && mlx4_ib_add_mc(dev, qp, &ge->gid)) {
+			ge->added = 1;
+			ge->port = qp->port;
+		}
+	}
+}
+
 static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
 			       const struct ib_qp_attr *attr, int attr_mask,
 			       enum ib_qp_state cur_state, enum ib_qp_state new_state)
@@ -980,7 +1049,7 @@
 	}
 
 	if (attr_mask & IB_QP_TIMEOUT) {
-		context->pri_path.ackto = attr->timeout << 3;
+		context->pri_path.ackto |= attr->timeout << 3;
 		optpar |= MLX4_QP_OPTPAR_ACK_TIMEOUT;
 	}
 
@@ -1118,8 +1187,10 @@
 		qp->atomic_rd_en = attr->qp_access_flags;
 	if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)
 		qp->resp_depth = attr->max_dest_rd_atomic;
-	if (attr_mask & IB_QP_PORT)
+	if (attr_mask & IB_QP_PORT) {
 		qp->port = attr->port_num;
+		update_mcg_macs(dev, qp);
+	}
 	if (attr_mask & IB_QP_ALT_PATH)
 		qp->alt_port = attr->alt_port_num;
 
@@ -1221,40 +1292,59 @@
 	struct mlx4_wqe_mlx_seg *mlx = wqe;
 	struct mlx4_wqe_inline_seg *inl = wqe + sizeof *mlx;
 	struct mlx4_ib_ah *ah = to_mah(wr->wr.ud.ah);
+	union ib_gid sgid;
 	u16 pkey;
 	int send_size;
 	int header_size;
 	int spc;
 	int i;
+	int is_eth;
+	int is_vlan = 0;
+	int is_grh;
+	u16 vlan;
 
 	send_size = 0;
 	for (i = 0; i < wr->num_sge; ++i)
 		send_size += wr->sg_list[i].length;
 
-	ib_ud_header_init(send_size, mlx4_ib_ah_grh_present(ah), 0, &sqp->ud_header);
+	is_eth = rdma_port_get_link_layer(sqp->qp.ibqp.device, sqp->qp.port) == IB_LINK_LAYER_ETHERNET;
+	is_grh = mlx4_ib_ah_grh_present(ah);
+	if (is_eth) {
+		ib_get_cached_gid(ib_dev, be32_to_cpu(ah->av.ib.port_pd) >> 24,
+				  ah->av.ib.gid_index, &sgid);
+		vlan = rdma_get_vlan_id(&sgid);
+		is_vlan = vlan < 0x1000;
+	}
+	ib_ud_header_init(send_size, !is_eth, is_eth, is_vlan, is_grh, 0, &sqp->ud_header);
 
-	sqp->ud_header.lrh.service_level   =
-		be32_to_cpu(ah->av.sl_tclass_flowlabel) >> 28;
-	sqp->ud_header.lrh.destination_lid = ah->av.dlid;
-	sqp->ud_header.lrh.source_lid      = cpu_to_be16(ah->av.g_slid & 0x7f);
-	if (mlx4_ib_ah_grh_present(ah)) {
+	if (!is_eth) {
+		sqp->ud_header.lrh.service_level =
+			be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 28;
+		sqp->ud_header.lrh.destination_lid = ah->av.ib.dlid;
+		sqp->ud_header.lrh.source_lid = cpu_to_be16(ah->av.ib.g_slid & 0x7f);
+	}
+
+	if (is_grh) {
 		sqp->ud_header.grh.traffic_class =
-			(be32_to_cpu(ah->av.sl_tclass_flowlabel) >> 20) & 0xff;
+			(be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 20) & 0xff;
 		sqp->ud_header.grh.flow_label    =
-			ah->av.sl_tclass_flowlabel & cpu_to_be32(0xfffff);
-		sqp->ud_header.grh.hop_limit     = ah->av.hop_limit;
-		ib_get_cached_gid(ib_dev, be32_to_cpu(ah->av.port_pd) >> 24,
-				  ah->av.gid_index, &sqp->ud_header.grh.source_gid);
+			ah->av.ib.sl_tclass_flowlabel & cpu_to_be32(0xfffff);
+		sqp->ud_header.grh.hop_limit     = ah->av.ib.hop_limit;
+		ib_get_cached_gid(ib_dev, be32_to_cpu(ah->av.ib.port_pd) >> 24,
+				  ah->av.ib.gid_index, &sqp->ud_header.grh.source_gid);
 		memcpy(sqp->ud_header.grh.destination_gid.raw,
-		       ah->av.dgid, 16);
+		       ah->av.ib.dgid, 16);
 	}
 
 	mlx->flags &= cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE);
-	mlx->flags |= cpu_to_be32((!sqp->qp.ibqp.qp_num ? MLX4_WQE_MLX_VL15 : 0) |
-				  (sqp->ud_header.lrh.destination_lid ==
-				   IB_LID_PERMISSIVE ? MLX4_WQE_MLX_SLR : 0) |
-				  (sqp->ud_header.lrh.service_level << 8));
-	mlx->rlid   = sqp->ud_header.lrh.destination_lid;
+
+	if (!is_eth) {
+		mlx->flags |= cpu_to_be32((!sqp->qp.ibqp.qp_num ? MLX4_WQE_MLX_VL15 : 0) |
+					  (sqp->ud_header.lrh.destination_lid ==
+					   IB_LID_PERMISSIVE ? MLX4_WQE_MLX_SLR : 0) |
+					  (sqp->ud_header.lrh.service_level << 8));
+		mlx->rlid = sqp->ud_header.lrh.destination_lid;
+	}
 
 	switch (wr->opcode) {
 	case IB_WR_SEND:
@@ -1270,9 +1360,29 @@
 		return -EINVAL;
 	}
 
-	sqp->ud_header.lrh.virtual_lane    = !sqp->qp.ibqp.qp_num ? 15 : 0;
-	if (sqp->ud_header.lrh.destination_lid == IB_LID_PERMISSIVE)
-		sqp->ud_header.lrh.source_lid = IB_LID_PERMISSIVE;
+	if (is_eth) {
+		u8 *smac;
+
+		memcpy(sqp->ud_header.eth.dmac_h, ah->av.eth.mac, 6);
+		/* FIXME: cache smac value? */
+		smac = to_mdev(sqp->qp.ibqp.device)->iboe.netdevs[sqp->qp.port - 1]->dev_addr;
+		memcpy(sqp->ud_header.eth.smac_h, smac, 6);
+		if (!memcmp(sqp->ud_header.eth.smac_h, sqp->ud_header.eth.dmac_h, 6))
+			mlx->flags |= cpu_to_be32(MLX4_WQE_CTRL_FORCE_LOOPBACK);
+		if (!is_vlan) {
+			sqp->ud_header.eth.type = cpu_to_be16(MLX4_IB_IBOE_ETHERTYPE);
+		} else {
+			u16 pcp;
+
+			sqp->ud_header.vlan.type = cpu_to_be16(MLX4_IB_IBOE_ETHERTYPE);
+			pcp = (be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 27 & 3) << 13;
+			sqp->ud_header.vlan.tag = cpu_to_be16(vlan | pcp);
+		}
+	} else {
+		sqp->ud_header.lrh.virtual_lane    = !sqp->qp.ibqp.qp_num ? 15 : 0;
+		if (sqp->ud_header.lrh.destination_lid == IB_LID_PERMISSIVE)
+			sqp->ud_header.lrh.source_lid = IB_LID_PERMISSIVE;
+	}
 	sqp->ud_header.bth.solicited_event = !!(wr->send_flags & IB_SEND_SOLICITED);
 	if (!sqp->qp.ibqp.qp_num)
 		ib_get_cached_pkey(ib_dev, sqp->qp.port, sqp->pkey_index, &pkey);
@@ -1429,11 +1539,14 @@
 }
 
 static void set_datagram_seg(struct mlx4_wqe_datagram_seg *dseg,
-			     struct ib_send_wr *wr)
+			     struct ib_send_wr *wr, __be16 *vlan)
 {
 	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)
@@ -1536,6 +1649,7 @@
 	__be32 uninitialized_var(lso_hdr_sz);
 	__be32 blh;
 	int i;
+	__be16 vlan = cpu_to_be16(0xffff);
 
 	spin_lock_irqsave(&qp->sq.lock, flags);
 
@@ -1639,7 +1753,7 @@
 			break;
 
 		case IB_QPT_UD:
-			set_datagram_seg(wqe, wr);
+			set_datagram_seg(wqe, wr, &vlan);
 			wqe  += sizeof (struct mlx4_wqe_datagram_seg);
 			size += sizeof (struct mlx4_wqe_datagram_seg) / 16;
 
@@ -1717,6 +1831,11 @@
 		ctrl->owner_opcode = mlx4_ib_opcode[wr->opcode] |
 			(ind & qp->sq.wqe_cnt ? cpu_to_be32(1 << 31) : 0) | blh;
 
+		if (be16_to_cpu(vlan) < 0x1000) {
+			ctrl->ins_vlan = 1 << 6;
+			ctrl->vlan_tag = vlan;
+		}
+
 		stamp = ind + qp->sq_spare_wqes;
 		ind += DIV_ROUND_UP(size * 16, 1U << qp->sq.wqe_shift);
 
@@ -1866,17 +1985,27 @@
 	return ib_flags;
 }
 
-static void to_ib_ah_attr(struct mlx4_dev *dev, struct ib_ah_attr *ib_ah_attr,
+static void to_ib_ah_attr(struct mlx4_ib_dev *ibdev, struct ib_ah_attr *ib_ah_attr,
 				struct mlx4_qp_path *path)
 {
+	struct mlx4_dev *dev = ibdev->dev;
+	int is_eth;
+
 	memset(ib_ah_attr, 0, sizeof *ib_ah_attr);
 	ib_ah_attr->port_num	  = path->sched_queue & 0x40 ? 2 : 1;
 
 	if (ib_ah_attr->port_num == 0 || ib_ah_attr->port_num > dev->caps.num_ports)
 		return;
 
+	is_eth = rdma_port_get_link_layer(&ibdev->ib_dev, ib_ah_attr->port_num) ==
+		IB_LINK_LAYER_ETHERNET;
+	if (is_eth)
+		ib_ah_attr->sl = ((path->sched_queue >> 3) & 0x7) |
+		((path->sched_queue & 4) << 1);
+	else
+		ib_ah_attr->sl = (path->sched_queue >> 2) & 0xf;
+
 	ib_ah_attr->dlid	  = be16_to_cpu(path->rlid);
-	ib_ah_attr->sl		  = (path->sched_queue >> 2) & 0xf;
 	ib_ah_attr->src_path_bits = path->grh_mylmc & 0x7f;
 	ib_ah_attr->static_rate   = path->static_rate ? path->static_rate - 5 : 0;
 	ib_ah_attr->ah_flags      = (path->grh_mylmc & (1 << 7)) ? IB_AH_GRH : 0;
@@ -1929,8 +2058,8 @@
 		to_ib_qp_access_flags(be32_to_cpu(context.params2));
 
 	if (qp->ibqp.qp_type == IB_QPT_RC || qp->ibqp.qp_type == IB_QPT_UC) {
-		to_ib_ah_attr(dev->dev, &qp_attr->ah_attr, &context.pri_path);
-		to_ib_ah_attr(dev->dev, &qp_attr->alt_ah_attr, &context.alt_path);
+		to_ib_ah_attr(dev, &qp_attr->ah_attr, &context.pri_path);
+		to_ib_ah_attr(dev, &qp_attr->alt_ah_attr, &context.alt_path);
 		qp_attr->alt_pkey_index = context.alt_path.pkey_index & 0x7f;
 		qp_attr->alt_port_num	= qp_attr->alt_ah_attr.port_num;
 	}
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index d2d172e..a34c9d3 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -1493,7 +1493,7 @@
 	int err;
 	u16 pkey;
 
-	ib_ud_header_init(256, /* assume a MAD */
+	ib_ud_header_init(256, /* assume a MAD */ 1, 0, 0,
 			  mthca_ah_grh_present(to_mah(wr->wr.ud.ah)), 0,
 			  &sqp->ud_header);
 
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index 6220d9d..25ad0f9 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -1424,7 +1424,6 @@
 {
 
 	int	reset = 0;	/* whether to send reset in case of err.. */
-	int	passive_state;
 	atomic_inc(&cm_resets_recvd);
 	nes_debug(NES_DBG_CM, "Received Reset, cm_node = %p, state = %u."
 			" refcnt=%d\n", cm_node, cm_node->state,
@@ -1439,7 +1438,7 @@
 		active_open_err(cm_node, skb, reset);
 		break;
 	case NES_CM_STATE_MPAREQ_RCVD:
-		passive_state = atomic_add_return(1, &cm_node->passive_state);
+		atomic_inc(&cm_node->passive_state);
 		dev_kfree_skb_any(skb);
 		break;
 	case NES_CM_STATE_ESTABLISHED:
diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c
index 10560c7..3892e2c 100644
--- a/drivers/infiniband/hw/nes/nes_nic.c
+++ b/drivers/infiniband/hw/nes/nes_nic.c
@@ -271,6 +271,7 @@
 
 	if (netif_msg_ifdown(nesvnic))
 		printk(KERN_INFO PFX "%s: disabling interface\n", netdev->name);
+	netif_carrier_off(netdev);
 
 	/* Disable network packets */
 	napi_disable(&nesvnic->napi);
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
index 546fc22..99933e4 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.c
+++ b/drivers/infiniband/hw/nes/nes_verbs.c
@@ -476,9 +476,9 @@
 	}
 	nes_debug(NES_DBG_MR, "nes_alloc_fast_reg_pbl: nes_frpl = %p, "
 		  "ibfrpl = %p, ibfrpl.page_list = %p, pbl.kva = %p, "
-		  "pbl.paddr= %p\n", pnesfrpl, &pnesfrpl->ibfrpl,
+		  "pbl.paddr = %llx\n", pnesfrpl, &pnesfrpl->ibfrpl,
 		  pnesfrpl->ibfrpl.page_list, pnesfrpl->nes_wqe_pbl.kva,
-		  (void *)pnesfrpl->nes_wqe_pbl.paddr);
+		  (unsigned long long) pnesfrpl->nes_wqe_pbl.paddr);
 
 	return pifrpl;
 }
@@ -584,7 +584,9 @@
 	props->lmc = 0;
 	props->sm_lid = 0;
 	props->sm_sl = 0;
-	if (nesvnic->linkup)
+	if (netif_queue_stopped(netdev))
+		props->state = IB_PORT_DOWN;
+	else if (nesvnic->linkup)
 		props->state = IB_PORT_ACTIVE;
 	else
 		props->state = IB_PORT_DOWN;
@@ -3483,13 +3485,13 @@
 			for (i = 0; i < ib_wr->wr.fast_reg.page_list_len; i++)
 				dst_page_list[i] = cpu_to_le64(src_page_list[i]);
 
-			nes_debug(NES_DBG_IW_TX, "SQ_FMR: iova_start: %p, "
-				  "length: %d, rkey: %0x, pgl_paddr: %p, "
+			nes_debug(NES_DBG_IW_TX, "SQ_FMR: iova_start: %llx, "
+				  "length: %d, rkey: %0x, pgl_paddr: %llx, "
 				  "page_list_len: %u, wqe_misc: %x\n",
-				  (void *)ib_wr->wr.fast_reg.iova_start,
+				  (unsigned long long) ib_wr->wr.fast_reg.iova_start,
 				  ib_wr->wr.fast_reg.length,
 				  ib_wr->wr.fast_reg.rkey,
-				  (void *)pnesfrpl->nes_wqe_pbl.paddr,
+				  (unsigned long long) pnesfrpl->nes_wqe_pbl.paddr,
 				  ib_wr->wr.fast_reg.page_list_len,
 				  wqe_misc);
 			break;
diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h
index 61de065..64c9e7d 100644
--- a/drivers/infiniband/hw/qib/qib.h
+++ b/drivers/infiniband/hw/qib/qib.h
@@ -1406,7 +1406,7 @@
  */
 #define qib_early_err(dev, fmt, ...) \
 	do { \
-		dev_info(dev, KERN_ERR QIB_DRV_NAME ": " fmt, ##__VA_ARGS__); \
+		dev_err(dev, fmt, ##__VA_ARGS__); \
 	} while (0)
 
 #define qib_dev_err(dd, fmt, ...) \
diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c
index f1d16d3..f3b5039 100644
--- a/drivers/infiniband/hw/qib/qib_init.c
+++ b/drivers/infiniband/hw/qib/qib_init.c
@@ -1243,6 +1243,7 @@
 		qib_early_err(&pdev->dev, "QLogic PCIE device 0x%x cannot "
 		      "work if CONFIG_PCI_MSI is not enabled\n",
 		      ent->device);
+		dd = ERR_PTR(-ENODEV);
 #endif
 		break;
 
diff --git a/drivers/infiniband/hw/qib/qib_pcie.c b/drivers/infiniband/hw/qib/qib_pcie.c
index 7fa6e55..48b6674 100644
--- a/drivers/infiniband/hw/qib/qib_pcie.c
+++ b/drivers/infiniband/hw/qib/qib_pcie.c
@@ -103,16 +103,20 @@
 		ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
 	} else
 		ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
-	if (ret)
+	if (ret) {
 		qib_early_err(&pdev->dev,
 			      "Unable to set DMA consistent mask: %d\n", ret);
+		goto bail;
+	}
 
 	pci_set_master(pdev);
 	ret = pci_enable_pcie_error_reporting(pdev);
-	if (ret)
+	if (ret) {
 		qib_early_err(&pdev->dev,
 			      "Unable to enable pcie error reporting: %d\n",
 			      ret);
+		ret = 0;
+	}
 	goto done;
 
 bail:
diff --git a/drivers/infiniband/hw/qib/qib_rc.c b/drivers/infiniband/hw/qib/qib_rc.c
index a093111..955fb71 100644
--- a/drivers/infiniband/hw/qib/qib_rc.c
+++ b/drivers/infiniband/hw/qib/qib_rc.c
@@ -2068,7 +2068,10 @@
 			goto nack_op_err;
 		if (!ret)
 			goto rnr_nak;
-		goto send_last_imm;
+		wc.ex.imm_data = ohdr->u.rc.imm_data;
+		hdrsize += 4;
+		wc.wc_flags = IB_WC_WITH_IMM;
+		goto send_last;
 
 	case OP(RDMA_READ_REQUEST): {
 		struct qib_ack_entry *e;
diff --git a/drivers/infiniband/hw/qib/qib_uc.c b/drivers/infiniband/hw/qib/qib_uc.c
index b9c8b63..32ccf3c 100644
--- a/drivers/infiniband/hw/qib/qib_uc.c
+++ b/drivers/infiniband/hw/qib/qib_uc.c
@@ -457,8 +457,10 @@
 		}
 		if (opcode == OP(RDMA_WRITE_ONLY))
 			goto rdma_last;
-		else if (opcode == OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE))
+		else if (opcode == OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE)) {
+			wc.ex.imm_data = ohdr->u.rc.imm_data;
 			goto rdma_last_imm;
+		}
 		/* FALLTHROUGH */
 	case OP(RDMA_WRITE_MIDDLE):
 		/* Check for invalid length PMTU or posted rwqe len. */
@@ -471,8 +473,8 @@
 		break;
 
 	case OP(RDMA_WRITE_LAST_WITH_IMMEDIATE):
-rdma_last_imm:
 		wc.ex.imm_data = ohdr->u.imm_data;
+rdma_last_imm:
 		hdrsize += 4;
 		wc.wc_flags = IB_WC_WITH_IMM;
 
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index ec6b4fb..dfa7190 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -223,6 +223,7 @@
 	unsigned int wr_id = wc->wr_id & ~IPOIB_OP_RECV;
 	struct sk_buff *skb;
 	u64 mapping[IPOIB_UD_RX_SG];
+	union ib_gid *dgid;
 
 	ipoib_dbg_data(priv, "recv completion: id %d, status: %d\n",
 		       wr_id, wc->status);
@@ -271,6 +272,16 @@
 	ipoib_ud_dma_unmap_rx(priv, mapping);
 	ipoib_ud_skb_put_frags(priv, skb, wc->byte_len);
 
+	/* First byte of dgid signals multicast when 0xff */
+	dgid = &((struct ib_grh *)skb->data)->dgid;
+
+	if (!(wc->wc_flags & IB_WC_GRH) || dgid->raw[0] != 0xff)
+		skb->pkt_type = PACKET_HOST;
+	else if (memcmp(dgid, dev->broadcast + 4, sizeof(union ib_gid)) == 0)
+		skb->pkt_type = PACKET_BROADCAST;
+	else
+		skb->pkt_type = PACKET_MULTICAST;
+
 	skb_pull(skb, IB_GRH_BYTES);
 
 	skb->protocol = ((struct ipoib_header *) skb->data)->proto;
@@ -281,9 +292,6 @@
 	dev->stats.rx_bytes += skb->len;
 
 	skb->dev = dev;
-	/* XXX get correct PACKET_ type here */
-	skb->pkt_type = PACKET_HOST;
-
 	if (test_bit(IPOIB_FLAG_CSUM, &priv->flags) && likely(wc->csum_ok))
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index b4b2257..9ff7bc7 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -1240,6 +1240,7 @@
 		goto alloc_mem_failed;
 
 	SET_NETDEV_DEV(priv->dev, hca->dma_device);
+	priv->dev->dev_id = port - 1;
 
 	if (!ib_query_port(hca, port, &attr))
 		priv->max_ib_mtu = ib_mtu_enum_to_int(attr.max_mtu);
@@ -1362,6 +1363,8 @@
 	}
 
 	for (p = s; p <= e; ++p) {
+		if (rdma_port_get_link_layer(device, p) != IB_LINK_LAYER_INFINIBAND)
+			continue;
 		dev = ipoib_add_port("ib%d", device, p);
 		if (!IS_ERR(dev)) {
 			priv = netdev_priv(dev);
@@ -1409,8 +1412,7 @@
 
 	ipoib_sendq_size = roundup_pow_of_two(ipoib_sendq_size);
 	ipoib_sendq_size = min(ipoib_sendq_size, IPOIB_MAX_QUEUE_SIZE);
-	ipoib_sendq_size = max(ipoib_sendq_size, max(2 * MAX_SEND_CQE,
-						     IPOIB_MIN_QUEUE_SIZE));
+	ipoib_sendq_size = max3(ipoib_sendq_size, 2 * MAX_SEND_CQE, IPOIB_MIN_QUEUE_SIZE);
 #ifdef CONFIG_INFINIBAND_IPOIB_CM
 	ipoib_max_conn_qp = min(ipoib_max_conn_qp, IPOIB_CM_MAX_CONN_QP);
 #endif
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 7f8f16b..cfc1d65 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -291,7 +291,7 @@
 
 	for (i = 0; i < SRP_RQ_SIZE; ++i)
 		srp_free_iu(target->srp_host, target->rx_ring[i]);
-	for (i = 0; i < SRP_SQ_SIZE + 1; ++i)
+	for (i = 0; i < SRP_SQ_SIZE; ++i)
 		srp_free_iu(target->srp_host, target->tx_ring[i]);
 }
 
@@ -811,6 +811,75 @@
 	return len;
 }
 
+/*
+ * Must be called with target->scsi_host->host_lock held to protect
+ * req_lim and tx_head.  Lock cannot be dropped between call here and
+ * call to __srp_post_send().
+ *
+ * Note:
+ * An upper limit for the number of allocated information units for each
+ * request type is:
+ * - SRP_IU_CMD: SRP_CMD_SQ_SIZE, since the SCSI mid-layer never queues
+ *   more than Scsi_Host.can_queue requests.
+ * - SRP_IU_TSK_MGMT: SRP_TSK_MGMT_SQ_SIZE.
+ * - SRP_IU_RSP: 1, since a conforming SRP target never sends more than
+ *   one unanswered SRP request to an initiator.
+ */
+static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target,
+				      enum srp_iu_type iu_type)
+{
+	s32 rsv = (iu_type == SRP_IU_TSK_MGMT) ? 0 : SRP_TSK_MGMT_SQ_SIZE;
+	struct srp_iu *iu;
+
+	srp_send_completion(target->send_cq, target);
+
+	if (target->tx_head - target->tx_tail >= SRP_SQ_SIZE)
+		return NULL;
+
+	/* Initiator responses to target requests do not consume credits */
+	if (target->req_lim <= rsv && iu_type != SRP_IU_RSP) {
+		++target->zero_req_lim;
+		return NULL;
+	}
+
+	iu = target->tx_ring[target->tx_head & SRP_SQ_MASK];
+	iu->type = iu_type;
+	return iu;
+}
+
+/*
+ * Must be called with target->scsi_host->host_lock held to protect
+ * req_lim and tx_head.
+ */
+static int __srp_post_send(struct srp_target_port *target,
+			   struct srp_iu *iu, int len)
+{
+	struct ib_sge list;
+	struct ib_send_wr wr, *bad_wr;
+	int ret = 0;
+
+	list.addr   = iu->dma;
+	list.length = len;
+	list.lkey   = target->srp_host->srp_dev->mr->lkey;
+
+	wr.next       = NULL;
+	wr.wr_id      = target->tx_head & SRP_SQ_MASK;
+	wr.sg_list    = &list;
+	wr.num_sge    = 1;
+	wr.opcode     = IB_WR_SEND;
+	wr.send_flags = IB_SEND_SIGNALED;
+
+	ret = ib_post_send(target->qp, &wr, &bad_wr);
+
+	if (!ret) {
+		++target->tx_head;
+		if (iu->type != SRP_IU_RSP)
+			--target->req_lim;
+	}
+
+	return ret;
+}
+
 static int srp_post_recv(struct srp_target_port *target)
 {
 	unsigned long flags;
@@ -822,7 +891,7 @@
 
 	spin_lock_irqsave(target->scsi_host->host_lock, flags);
 
-	next	 = target->rx_head & (SRP_RQ_SIZE - 1);
+	next	 = target->rx_head & SRP_RQ_MASK;
 	wr.wr_id = next;
 	iu	 = target->rx_ring[next];
 
@@ -896,6 +965,71 @@
 	spin_unlock_irqrestore(target->scsi_host->host_lock, flags);
 }
 
+static int srp_response_common(struct srp_target_port *target, s32 req_delta,
+			       void *rsp, int len)
+{
+	struct ib_device *dev;
+	unsigned long flags;
+	struct srp_iu *iu;
+	int err = 1;
+
+	dev = target->srp_host->srp_dev->dev;
+
+	spin_lock_irqsave(target->scsi_host->host_lock, flags);
+	target->req_lim += req_delta;
+
+	iu = __srp_get_tx_iu(target, SRP_IU_RSP);
+	if (!iu) {
+		shost_printk(KERN_ERR, target->scsi_host, PFX
+			     "no IU available to send response\n");
+		goto out;
+	}
+
+	ib_dma_sync_single_for_cpu(dev, iu->dma, len, DMA_TO_DEVICE);
+	memcpy(iu->buf, rsp, len);
+	ib_dma_sync_single_for_device(dev, iu->dma, len, DMA_TO_DEVICE);
+
+	err = __srp_post_send(target, iu, len);
+	if (err)
+		shost_printk(KERN_ERR, target->scsi_host, PFX
+			     "unable to post response: %d\n", err);
+
+out:
+	spin_unlock_irqrestore(target->scsi_host->host_lock, flags);
+	return err;
+}
+
+static void srp_process_cred_req(struct srp_target_port *target,
+				 struct srp_cred_req *req)
+{
+	struct srp_cred_rsp rsp = {
+		.opcode = SRP_CRED_RSP,
+		.tag = req->tag,
+	};
+	s32 delta = be32_to_cpu(req->req_lim_delta);
+
+	if (srp_response_common(target, delta, &rsp, sizeof rsp))
+		shost_printk(KERN_ERR, target->scsi_host, PFX
+			     "problems processing SRP_CRED_REQ\n");
+}
+
+static void srp_process_aer_req(struct srp_target_port *target,
+				struct srp_aer_req *req)
+{
+	struct srp_aer_rsp rsp = {
+		.opcode = SRP_AER_RSP,
+		.tag = req->tag,
+	};
+	s32 delta = be32_to_cpu(req->req_lim_delta);
+
+	shost_printk(KERN_ERR, target->scsi_host, PFX
+		     "ignoring AER for LUN %llu\n", be64_to_cpu(req->lun));
+
+	if (srp_response_common(target, delta, &rsp, sizeof rsp))
+		shost_printk(KERN_ERR, target->scsi_host, PFX
+			     "problems processing SRP_AER_REQ\n");
+}
+
 static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
 {
 	struct ib_device *dev;
@@ -923,6 +1057,14 @@
 		srp_process_rsp(target, iu->buf);
 		break;
 
+	case SRP_CRED_REQ:
+		srp_process_cred_req(target, iu->buf);
+		break;
+
+	case SRP_AER_REQ:
+		srp_process_aer_req(target, iu->buf);
+		break;
+
 	case SRP_T_LOGOUT:
 		/* XXX Handle target logout */
 		shost_printk(KERN_WARNING, target->scsi_host,
@@ -981,61 +1123,6 @@
 	}
 }
 
-/*
- * Must be called with target->scsi_host->host_lock held to protect
- * req_lim and tx_head.  Lock cannot be dropped between call here and
- * call to __srp_post_send().
- */
-static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target,
-					enum srp_request_type req_type)
-{
-	s32 min = (req_type == SRP_REQ_TASK_MGMT) ? 1 : 2;
-
-	srp_send_completion(target->send_cq, target);
-
-	if (target->tx_head - target->tx_tail >= SRP_SQ_SIZE)
-		return NULL;
-
-	if (target->req_lim < min) {
-		++target->zero_req_lim;
-		return NULL;
-	}
-
-	return target->tx_ring[target->tx_head & SRP_SQ_SIZE];
-}
-
-/*
- * Must be called with target->scsi_host->host_lock held to protect
- * req_lim and tx_head.
- */
-static int __srp_post_send(struct srp_target_port *target,
-			   struct srp_iu *iu, int len)
-{
-	struct ib_sge list;
-	struct ib_send_wr wr, *bad_wr;
-	int ret = 0;
-
-	list.addr   = iu->dma;
-	list.length = len;
-	list.lkey   = target->srp_host->srp_dev->mr->lkey;
-
-	wr.next       = NULL;
-	wr.wr_id      = target->tx_head & SRP_SQ_SIZE;
-	wr.sg_list    = &list;
-	wr.num_sge    = 1;
-	wr.opcode     = IB_WR_SEND;
-	wr.send_flags = IB_SEND_SIGNALED;
-
-	ret = ib_post_send(target->qp, &wr, &bad_wr);
-
-	if (!ret) {
-		++target->tx_head;
-		--target->req_lim;
-	}
-
-	return ret;
-}
-
 static int srp_queuecommand(struct scsi_cmnd *scmnd,
 			    void (*done)(struct scsi_cmnd *))
 {
@@ -1056,7 +1143,7 @@
 		return 0;
 	}
 
-	iu = __srp_get_tx_iu(target, SRP_REQ_NORMAL);
+	iu = __srp_get_tx_iu(target, SRP_IU_CMD);
 	if (!iu)
 		goto err;
 
@@ -1064,7 +1151,7 @@
 	ib_dma_sync_single_for_cpu(dev, iu->dma, srp_max_iu_len,
 				   DMA_TO_DEVICE);
 
-	req = list_entry(target->free_reqs.next, struct srp_request, list);
+	req = list_first_entry(&target->free_reqs, struct srp_request, list);
 
 	scmnd->scsi_done     = done;
 	scmnd->result        = 0;
@@ -1121,7 +1208,7 @@
 			goto err;
 	}
 
-	for (i = 0; i < SRP_SQ_SIZE + 1; ++i) {
+	for (i = 0; i < SRP_SQ_SIZE; ++i) {
 		target->tx_ring[i] = srp_alloc_iu(target->srp_host,
 						  srp_max_iu_len,
 						  GFP_KERNEL, DMA_TO_DEVICE);
@@ -1137,7 +1224,7 @@
 		target->rx_ring[i] = NULL;
 	}
 
-	for (i = 0; i < SRP_SQ_SIZE + 1; ++i) {
+	for (i = 0; i < SRP_SQ_SIZE; ++i) {
 		srp_free_iu(target->srp_host, target->tx_ring[i]);
 		target->tx_ring[i] = NULL;
 	}
@@ -1252,8 +1339,13 @@
 			target->max_ti_iu_len = be32_to_cpu(rsp->max_ti_iu_len);
 			target->req_lim       = be32_to_cpu(rsp->req_lim_delta);
 
-			target->scsi_host->can_queue = min(target->req_lim,
-							   target->scsi_host->can_queue);
+			/*
+			 * Reserve credits for task management so we don't
+			 * bounce requests back to the SCSI mid-layer.
+			 */
+			target->scsi_host->can_queue
+				= min(target->req_lim - SRP_TSK_MGMT_SQ_SIZE,
+				      target->scsi_host->can_queue);
 		} else {
 			shost_printk(KERN_WARNING, target->scsi_host,
 				    PFX "Unhandled RSP opcode %#x\n", opcode);
@@ -1350,6 +1442,7 @@
 static int srp_send_tsk_mgmt(struct srp_target_port *target,
 			     struct srp_request *req, u8 func)
 {
+	struct ib_device *dev = target->srp_host->srp_dev->dev;
 	struct srp_iu *iu;
 	struct srp_tsk_mgmt *tsk_mgmt;
 
@@ -1363,10 +1456,12 @@
 
 	init_completion(&req->done);
 
-	iu = __srp_get_tx_iu(target, SRP_REQ_TASK_MGMT);
+	iu = __srp_get_tx_iu(target, SRP_IU_TSK_MGMT);
 	if (!iu)
 		goto out;
 
+	ib_dma_sync_single_for_cpu(dev, iu->dma, sizeof *tsk_mgmt,
+				   DMA_TO_DEVICE);
 	tsk_mgmt = iu->buf;
 	memset(tsk_mgmt, 0, sizeof *tsk_mgmt);
 
@@ -1376,6 +1471,8 @@
 	tsk_mgmt->tsk_mgmt_func = func;
 	tsk_mgmt->task_tag 	= req->index;
 
+	ib_dma_sync_single_for_device(dev, iu->dma, sizeof *tsk_mgmt,
+				      DMA_TO_DEVICE);
 	if (__srp_post_send(target, iu, sizeof *tsk_mgmt))
 		goto out;
 
@@ -1626,9 +1723,9 @@
 	.eh_abort_handler		= srp_abort,
 	.eh_device_reset_handler	= srp_reset_device,
 	.eh_host_reset_handler		= srp_reset_host,
-	.can_queue			= SRP_SQ_SIZE,
+	.can_queue			= SRP_CMD_SQ_SIZE,
 	.this_id			= -1,
-	.cmd_per_lun			= SRP_SQ_SIZE,
+	.cmd_per_lun			= SRP_CMD_SQ_SIZE,
 	.use_clustering			= ENABLE_CLUSTERING,
 	.shost_attrs			= srp_host_attrs
 };
@@ -1813,7 +1910,7 @@
 				printk(KERN_WARNING PFX "bad max cmd_per_lun parameter '%s'\n", p);
 				goto out;
 			}
-			target->scsi_host->cmd_per_lun = min(token, SRP_SQ_SIZE);
+			target->scsi_host->cmd_per_lun = min(token, SRP_CMD_SQ_SIZE);
 			break;
 
 		case SRP_OPT_IO_CLASS:
@@ -1891,7 +1988,7 @@
 
 	INIT_LIST_HEAD(&target->free_reqs);
 	INIT_LIST_HEAD(&target->req_queue);
-	for (i = 0; i < SRP_SQ_SIZE; ++i) {
+	for (i = 0; i < SRP_CMD_SQ_SIZE; ++i) {
 		target->req_ring[i].index = i;
 		list_add_tail(&target->req_ring[i].list, &target->free_reqs);
 	}
@@ -2159,6 +2256,9 @@
 {
 	int ret;
 
+	BUILD_BUG_ON_NOT_POWER_OF_2(SRP_SQ_SIZE);
+	BUILD_BUG_ON_NOT_POWER_OF_2(SRP_RQ_SIZE);
+
 	if (srp_sg_tablesize > 255) {
 		printk(KERN_WARNING PFX "Clamping srp_sg_tablesize to 255\n");
 		srp_sg_tablesize = 255;
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h
index 5a80eac..ed0dce9 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.h
+++ b/drivers/infiniband/ulp/srp/ib_srp.h
@@ -59,7 +59,14 @@
 
 	SRP_RQ_SHIFT    	= 6,
 	SRP_RQ_SIZE		= 1 << SRP_RQ_SHIFT,
-	SRP_SQ_SIZE		= SRP_RQ_SIZE - 1,
+	SRP_RQ_MASK		= SRP_RQ_SIZE - 1,
+
+	SRP_SQ_SIZE		= SRP_RQ_SIZE,
+	SRP_SQ_MASK		= SRP_SQ_SIZE - 1,
+	SRP_RSP_SQ_SIZE		= 1,
+	SRP_REQ_SQ_SIZE		= SRP_SQ_SIZE - SRP_RSP_SQ_SIZE,
+	SRP_TSK_MGMT_SQ_SIZE	= 1,
+	SRP_CMD_SQ_SIZE		= SRP_REQ_SQ_SIZE - SRP_TSK_MGMT_SQ_SIZE,
 
 	SRP_TAG_TSK_MGMT	= 1 << (SRP_RQ_SHIFT + 1),
 
@@ -75,9 +82,10 @@
 	SRP_TARGET_REMOVED
 };
 
-enum srp_request_type {
-	SRP_REQ_NORMAL,
-	SRP_REQ_TASK_MGMT,
+enum srp_iu_type {
+	SRP_IU_CMD,
+	SRP_IU_TSK_MGMT,
+	SRP_IU_RSP,
 };
 
 struct srp_device {
@@ -144,11 +152,11 @@
 
 	unsigned		tx_head;
 	unsigned		tx_tail;
-	struct srp_iu	       *tx_ring[SRP_SQ_SIZE + 1];
+	struct srp_iu	       *tx_ring[SRP_SQ_SIZE];
 
 	struct list_head	free_reqs;
 	struct list_head	req_queue;
-	struct srp_request	req_ring[SRP_SQ_SIZE];
+	struct srp_request	req_ring[SRP_CMD_SQ_SIZE];
 
 	struct work_struct	work;
 
@@ -164,6 +172,7 @@
 	void		       *buf;
 	size_t			size;
 	enum dma_data_direction	direction;
+	enum srp_iu_type	type;
 };
 
 #endif /* IB_SRP_H */
diff --git a/drivers/macintosh/windfarm_pm121.c b/drivers/macintosh/windfarm_pm121.c
index 947d4af..30e6195 100644
--- a/drivers/macintosh/windfarm_pm121.c
+++ b/drivers/macintosh/windfarm_pm121.c
@@ -482,7 +482,7 @@
 	new_min += correction->offset;
 	new_min = (new_min >> 16) + min;
 
-	return max(new_setpoint, max(new_min, 0));
+	return max3(new_setpoint, new_min, 0);
 }
 
 static s32 pm121_connect(unsigned int control_id, s32 setpoint)
diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c
index 0b61792..2129cdb 100644
--- a/drivers/md/dm-snap-persistent.c
+++ b/drivers/md/dm-snap-persistent.c
@@ -254,7 +254,7 @@
 	 * Issue the synchronous I/O from a different thread
 	 * to avoid generic_make_request recursion.
 	 */
-	INIT_WORK_ON_STACK(&req.work, do_metadata);
+	INIT_WORK_ONSTACK(&req.work, do_metadata);
 	queue_work(ps->metadata_wq, &req.work);
 	flush_workqueue(ps->metadata_wq);
 
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 1f69743..5a74db7 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -4,7 +4,6 @@
 
 menuconfig MISC_DEVICES
 	bool "Misc devices"
-	default y
 	---help---
 	  Say Y here to get to see options for device drivers from various
 	  different categories. This option alone does not add any kernel code.
@@ -24,7 +23,8 @@
 	  AD5260, AD5262, AD5263, AD5290, AD5291, AD5292, AD5293,
 	  AD7376, AD8400, AD8402, AD8403, ADN2850, AD5241, AD5242,
 	  AD5243, AD5245, AD5246, AD5247, AD5248, AD5280, AD5282,
-	  ADN2860, AD5273, AD5171, AD5170, AD5172, AD5173
+	  ADN2860, AD5273, AD5171, AD5170, AD5172, AD5173, AD5270,
+	  AD5271, AD5272, AD5274
 	  digital potentiometer chips.
 
 	  See Documentation/misc-devices/ad525x_dpot.txt for the
@@ -284,6 +284,16 @@
 	This option enables addition debugging code for the SGI GRU driver. If
 	you are unsure, say N.
 
+config APDS9802ALS
+	tristate "Medfield Avago APDS9802 ALS Sensor module"
+	depends on I2C
+	help
+	  If you say yes here you get support for the ALS APDS9802 ambient
+	  light sensor.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called apds9802als.
+
 config ISL29003
 	tristate "Intersil ISL29003 ambient light sensor"
 	depends on I2C && SYSFS
@@ -294,6 +304,16 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called isl29003.
 
+config ISL29020
+	tristate "Intersil ISL29020 ambient light sensor"
+	depends on I2C
+	help
+	  If you say yes here you get support for the Intersil ISL29020
+	  ambient light sensor.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called isl29020.
+
 config SENSORS_TSL2550
 	tristate "Taos TSL2550 ambient light sensor"
 	depends on I2C && SYSFS
@@ -314,6 +334,27 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called bh1780gli.
 
+config SENSORS_BH1770
+         tristate "BH1770GLC / SFH7770 combined ALS - Proximity sensor"
+         depends on I2C
+         ---help---
+           Say Y here if you want to build a driver for BH1770GLC (ROHM) or
+	   SFH7770 (Osram) combined ambient light and proximity sensor chip.
+
+           To compile this driver as a module, choose M here: the
+           module will be called bh1770glc. If unsure, say N here.
+
+config SENSORS_APDS990X
+	 tristate "APDS990X combined als and proximity sensors"
+	 depends on I2C
+	 default n
+	 ---help---
+	   Say Y here if you want to build a driver for Avago APDS990x
+	   combined ambient light and proximity sensor chip.
+
+	   To compile this driver as a module, choose M here: the
+	   module will be called apds990x. If unsure, say N here.
+
 config HMC6352
 	tristate "Honeywell HMC6352 compass"
 	depends on I2C
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 9f2986b..4be5c6f 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -16,6 +16,8 @@
 obj-$(CONFIG_TIFM_7XX1)       	+= tifm_7xx1.o
 obj-$(CONFIG_PHANTOM)		+= phantom.o
 obj-$(CONFIG_SENSORS_BH1780)	+= bh1780gli.o
+obj-$(CONFIG_SENSORS_BH1770)	+= bh1770glc.o
+obj-$(CONFIG_SENSORS_APDS990X)	+= apds990x.o
 obj-$(CONFIG_SGI_IOC4)		+= ioc4.o
 obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o
 obj-$(CONFIG_KGDB_TESTS)	+= kgdbts.o
@@ -23,7 +25,9 @@
 obj-$(CONFIG_SGI_GRU)		+= sgi-gru/
 obj-$(CONFIG_CS5535_MFGPT)	+= cs5535-mfgpt.o
 obj-$(CONFIG_HP_ILO)		+= hpilo.o
+obj-$(CONFIG_APDS9802ALS)	+= apds9802als.o
 obj-$(CONFIG_ISL29003)		+= isl29003.o
+obj-$(CONFIG_ISL29020)		+= isl29020.o
 obj-$(CONFIG_SENSORS_TSL2550)	+= tsl2550.o
 obj-$(CONFIG_EP93XX_PWM)	+= ep93xx_pwm.o
 obj-$(CONFIG_DS1682)		+= ds1682.o
diff --git a/drivers/misc/ad525x_dpot-i2c.c b/drivers/misc/ad525x_dpot-i2c.c
index 374352a..4ff73c2 100644
--- a/drivers/misc/ad525x_dpot-i2c.c
+++ b/drivers/misc/ad525x_dpot-i2c.c
@@ -102,6 +102,8 @@
 	{"ad5170", AD5170_ID},
 	{"ad5172", AD5172_ID},
 	{"ad5173", AD5173_ID},
+	{"ad5272", AD5272_ID},
+	{"ad5274", AD5274_ID},
 	{}
 };
 MODULE_DEVICE_TABLE(i2c, ad_dpot_id);
diff --git a/drivers/misc/ad525x_dpot-spi.c b/drivers/misc/ad525x_dpot-spi.c
index b8c6df9..7f9a55a 100644
--- a/drivers/misc/ad525x_dpot-spi.c
+++ b/drivers/misc/ad525x_dpot-spi.c
@@ -38,6 +38,8 @@
 	{.name = "ad8402", .devid = AD8402_ID},
 	{.name = "ad8403", .devid = AD8403_ID},
 	{.name = "adn2850", .devid = ADN2850_ID},
+	{.name = "ad5270", .devid = AD5270_ID},
+	{.name = "ad5271", .devid = AD5271_ID},
 	{}
 };
 
@@ -53,13 +55,13 @@
 static int write16(void *client, u8 reg, u8 val)
 {
 	u8 data[2] = {reg, val};
-	return spi_write(client, data, 1);
+	return spi_write(client, data, 2);
 }
 
 static int write24(void *client, u8 reg, u16 val)
 {
 	u8 data[3] = {reg, val >> 8, val};
-	return spi_write(client, data, 1);
+	return spi_write(client, data, 3);
 }
 
 static int read8(void *client)
diff --git a/drivers/misc/ad525x_dpot.c b/drivers/misc/ad525x_dpot.c
index 5e6fa84..7cb9110 100644
--- a/drivers/misc/ad525x_dpot.c
+++ b/drivers/misc/ad525x_dpot.c
@@ -29,9 +29,9 @@
  * AD5262		2		256		20, 50, 200
  * AD5263		4		256		20, 50, 200
  * AD5290		1		256		10, 50, 100
- * AD5291		1		256		20
- * AD5292		1		1024		20
- * AD5293		1		1024		20
+ * AD5291		1		256		20, 50, 100  (20-TP)
+ * AD5292		1		1024		20, 50, 100  (20-TP)
+ * AD5293		1		1024		20, 50, 100
  * AD7376		1		128		10, 50, 100, 1M
  * AD8400		1		256		1, 10, 50, 100
  * AD8402		2		256		1, 10, 50, 100
@@ -52,6 +52,10 @@
  * AD5170		1		256		2.5, 10, 50, 100 (OTP)
  * AD5172		2		256		2.5, 10, 50, 100 (OTP)
  * AD5173		2		256		2.5, 10, 50, 100 (OTP)
+ * AD5270		1		1024		20, 50, 100 (50-TP)
+ * AD5271		1		256		20, 50, 100 (50-TP)
+ * AD5272		1		1024		20, 50, 100 (50-TP)
+ * AD5274		1		256		20, 50, 100 (50-TP)
  *
  * See Documentation/misc-devices/ad525x_dpot.txt for more info.
  *
@@ -126,18 +130,38 @@
 static s32 dpot_read_spi(struct dpot_data *dpot, u8 reg)
 {
 	unsigned ctrl = 0;
+	int value;
 
 	if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD))) {
 
 		if (dpot->feat & F_RDACS_WONLY)
 			return dpot->rdac_cache[reg & DPOT_RDAC_MASK];
-
 		if (dpot->uid == DPOT_UID(AD5291_ID) ||
 			dpot->uid == DPOT_UID(AD5292_ID) ||
-			dpot->uid == DPOT_UID(AD5293_ID))
-			return dpot_read_r8d8(dpot,
+			dpot->uid == DPOT_UID(AD5293_ID)) {
+
+			value = dpot_read_r8d8(dpot,
 				DPOT_AD5291_READ_RDAC << 2);
 
+			if (dpot->uid == DPOT_UID(AD5291_ID))
+				value = value >> 2;
+
+			return value;
+		} else if (dpot->uid == DPOT_UID(AD5270_ID) ||
+			dpot->uid == DPOT_UID(AD5271_ID)) {
+
+			value = dpot_read_r8d8(dpot,
+				DPOT_AD5270_1_2_4_READ_RDAC << 2);
+
+			if (value < 0)
+				return value;
+
+			if (dpot->uid == DPOT_UID(AD5271_ID))
+				value = value >> 2;
+
+			return value;
+		}
+
 		ctrl = DPOT_SPI_READ_RDAC;
 	} else if (reg & DPOT_ADDR_EEPROM) {
 		ctrl = DPOT_SPI_READ_EEPROM;
@@ -153,6 +177,7 @@
 
 static s32 dpot_read_i2c(struct dpot_data *dpot, u8 reg)
 {
+	int value;
 	unsigned ctrl = 0;
 	switch (dpot->uid) {
 	case DPOT_UID(AD5246_ID):
@@ -166,7 +191,7 @@
 	case DPOT_UID(AD5280_ID):
 	case DPOT_UID(AD5282_ID):
 		ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
-			0 : DPOT_AD5291_RDAC_AB;
+			0 : DPOT_AD5282_RDAC_AB;
 		return dpot_read_r8d8(dpot, ctrl);
 	case DPOT_UID(AD5170_ID):
 	case DPOT_UID(AD5171_ID):
@@ -175,8 +200,27 @@
 	case DPOT_UID(AD5172_ID):
 	case DPOT_UID(AD5173_ID):
 		ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
-			0 : DPOT_AD5272_3_A0;
+			0 : DPOT_AD5172_3_A0;
 		return dpot_read_r8d8(dpot, ctrl);
+	case DPOT_UID(AD5272_ID):
+	case DPOT_UID(AD5274_ID):
+			dpot_write_r8d8(dpot,
+				(DPOT_AD5270_1_2_4_READ_RDAC << 2), 0);
+
+			value = dpot_read_r8d16(dpot,
+				DPOT_AD5270_1_2_4_RDAC << 2);
+
+			if (value < 0)
+				return value;
+			/*
+			 * AD5272/AD5274 returns high byte first, however
+			 * underling smbus expects low byte first.
+			 */
+			value = swab16(value);
+
+			if (dpot->uid == DPOT_UID(AD5271_ID))
+				value = value >> 2;
+		return value;
 	default:
 		if ((reg & DPOT_REG_TOL) || (dpot->max_pos > 256))
 			return dpot_read_r8d16(dpot, (reg & 0xF8) |
@@ -198,7 +242,7 @@
 {
 	unsigned val = 0;
 
-	if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD))) {
+	if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD | DPOT_ADDR_OTP))) {
 		if (dpot->feat & F_RDACS_WONLY)
 			dpot->rdac_cache[reg & DPOT_RDAC_MASK] = value;
 
@@ -219,11 +263,30 @@
 		} else {
 			if (dpot->uid == DPOT_UID(AD5291_ID) ||
 				dpot->uid == DPOT_UID(AD5292_ID) ||
-				dpot->uid == DPOT_UID(AD5293_ID))
+				dpot->uid == DPOT_UID(AD5293_ID)) {
+
+				dpot_write_r8d8(dpot, DPOT_AD5291_CTRLREG << 2,
+						DPOT_AD5291_UNLOCK_CMD);
+
+				if (dpot->uid == DPOT_UID(AD5291_ID))
+					value = value << 2;
+
 				return dpot_write_r8d8(dpot,
 					(DPOT_AD5291_RDAC << 2) |
 					(value >> 8), value & 0xFF);
+			} else if (dpot->uid == DPOT_UID(AD5270_ID) ||
+				dpot->uid == DPOT_UID(AD5271_ID)) {
+				dpot_write_r8d8(dpot,
+						DPOT_AD5270_1_2_4_CTRLREG << 2,
+						DPOT_AD5270_1_2_4_UNLOCK_CMD);
 
+				if (dpot->uid == DPOT_UID(AD5271_ID))
+					value = value << 2;
+
+				return dpot_write_r8d8(dpot,
+					(DPOT_AD5270_1_2_4_RDAC << 2) |
+					(value >> 8), value & 0xFF);
+			}
 			val = DPOT_SPI_RDAC | (reg & DPOT_RDAC_MASK);
 		}
 	} else if (reg & DPOT_ADDR_EEPROM) {
@@ -243,6 +306,16 @@
 			val = DPOT_SPI_INC_ALL;
 			break;
 		}
+	} else if (reg & DPOT_ADDR_OTP) {
+		if (dpot->uid == DPOT_UID(AD5291_ID) ||
+			dpot->uid == DPOT_UID(AD5292_ID)) {
+			return dpot_write_r8d8(dpot,
+				DPOT_AD5291_STORE_XTPM << 2, 0);
+		} else if (dpot->uid == DPOT_UID(AD5270_ID) ||
+			dpot->uid == DPOT_UID(AD5271_ID)) {
+			return dpot_write_r8d8(dpot,
+				DPOT_AD5270_1_2_4_STORE_XTPM << 2, 0);
+		}
 	} else
 		BUG();
 
@@ -273,7 +346,7 @@
 	case DPOT_UID(AD5280_ID):
 	case DPOT_UID(AD5282_ID):
 		ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
-			0 : DPOT_AD5291_RDAC_AB;
+			0 : DPOT_AD5282_RDAC_AB;
 		return dpot_write_r8d8(dpot, ctrl, value);
 		break;
 	case DPOT_UID(AD5171_ID):
@@ -289,12 +362,12 @@
 	case DPOT_UID(AD5172_ID):
 	case DPOT_UID(AD5173_ID):
 		ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
-			0 : DPOT_AD5272_3_A0;
+			0 : DPOT_AD5172_3_A0;
 		if (reg & DPOT_ADDR_OTP) {
 			tmp = dpot_read_r8d16(dpot, ctrl);
 			if (tmp >> 14) /* Ready to Program? */
 				return -EFAULT;
-			ctrl |= DPOT_AD5270_2_3_FUSE;
+			ctrl |= DPOT_AD5170_2_3_FUSE;
 		}
 		return dpot_write_r8d8(dpot, ctrl, value);
 		break;
@@ -303,10 +376,25 @@
 			tmp = dpot_read_r8d16(dpot, tmp);
 			if (tmp >> 14) /* Ready to Program? */
 				return -EFAULT;
-			ctrl = DPOT_AD5270_2_3_FUSE;
+			ctrl = DPOT_AD5170_2_3_FUSE;
 		}
 		return dpot_write_r8d8(dpot, ctrl, value);
 		break;
+	case DPOT_UID(AD5272_ID):
+	case DPOT_UID(AD5274_ID):
+		dpot_write_r8d8(dpot, DPOT_AD5270_1_2_4_CTRLREG << 2,
+				DPOT_AD5270_1_2_4_UNLOCK_CMD);
+
+		if (reg & DPOT_ADDR_OTP)
+			return dpot_write_r8d8(dpot,
+					DPOT_AD5270_1_2_4_STORE_XTPM << 2, 0);
+
+		if (dpot->uid == DPOT_UID(AD5274_ID))
+			value = value << 2;
+
+		return dpot_write_r8d8(dpot, (DPOT_AD5270_1_2_4_RDAC << 2) |
+				       (value >> 8), value & 0xFF);
+		break;
 	default:
 		if (reg & DPOT_ADDR_CMD)
 			return dpot_write_d8(dpot, reg);
@@ -320,7 +408,6 @@
 	}
 }
 
-
 static s32 dpot_write(struct dpot_data *dpot, u8 reg, u16 value)
 {
 	if (dpot->feat & F_SPI)
diff --git a/drivers/misc/ad525x_dpot.h b/drivers/misc/ad525x_dpot.h
index 78b89fd..a662f59 100644
--- a/drivers/misc/ad525x_dpot.h
+++ b/drivers/misc/ad525x_dpot.h
@@ -47,9 +47,9 @@
 	AD5258_ID = DPOT_CONF(F_RDACS_RW_TOL, BRDAC0, 6, 0), /* I2C */
 	AD5259_ID = DPOT_CONF(F_RDACS_RW_TOL, BRDAC0, 8, 1),
 	AD5251_ID = DPOT_CONF(F_RDACS_RW_TOL | F_CMD_INC,
-			BRDAC0 | BRDAC3, 6, 2),
+			BRDAC1 | BRDAC3, 6, 2),
 	AD5252_ID = DPOT_CONF(F_RDACS_RW_TOL | F_CMD_INC,
-			BRDAC0 | BRDAC3, 8, 3),
+			BRDAC1 | BRDAC3, 8, 3),
 	AD5253_ID = DPOT_CONF(F_RDACS_RW_TOL | F_CMD_INC,
 			BRDAC0 | BRDAC1 | BRDAC2 | BRDAC3, 6, 4),
 	AD5254_ID = DPOT_CONF(F_RDACS_RW_TOL | F_CMD_INC,
@@ -93,8 +93,10 @@
 			BRDAC0 | BRDAC1 | BRDAC2 | BRDAC3, 8, 23),
 	AD5290_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
 			BRDAC0, 8, 24),
-	AD5291_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT, BRDAC0, 8, 25),
-	AD5292_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT, BRDAC0, 10, 26),
+	AD5291_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT | F_CMD_OTP,
+			BRDAC0, 8, 25),
+	AD5292_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT | F_CMD_OTP,
+			BRDAC0, 10, 26),
 	AD5293_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT, BRDAC0, 10, 27),
 	AD7376_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
 			BRDAC0, 7, 28),
@@ -122,6 +124,12 @@
 	AD5170_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0, 8, 45),
 	AD5172_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0 | BRDAC1, 8, 46),
 	AD5173_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0 | BRDAC1, 8, 47),
+	AD5270_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP | F_SPI_16BIT,
+			BRDAC0, 10, 48),
+	AD5271_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP | F_SPI_16BIT,
+			BRDAC0, 8, 49),
+	AD5272_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0, 10, 50),
+	AD5274_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0, 8, 51),
 };
 
 #define DPOT_RDAC0		0
@@ -165,15 +173,24 @@
 /* AD5291/2/3 use special commands */
 #define DPOT_AD5291_RDAC	0x01
 #define DPOT_AD5291_READ_RDAC	0x02
+#define DPOT_AD5291_STORE_XTPM	0x03
+#define DPOT_AD5291_CTRLREG	0x06
+#define DPOT_AD5291_UNLOCK_CMD	0x03
 
-/* AD524x use special commands */
-#define DPOT_AD5291_RDAC_AB	0x80
+/* AD5270/1/2/4 use special commands */
+#define DPOT_AD5270_1_2_4_RDAC		0x01
+#define DPOT_AD5270_1_2_4_READ_RDAC	0x02
+#define DPOT_AD5270_1_2_4_STORE_XTPM	0x03
+#define DPOT_AD5270_1_2_4_CTRLREG	0x07
+#define DPOT_AD5270_1_2_4_UNLOCK_CMD	0x03
+
+#define DPOT_AD5282_RDAC_AB	0x80
 
 #define DPOT_AD5273_FUSE	0x80
-#define DPOT_AD5270_2_3_FUSE	0x20
-#define DPOT_AD5270_2_3_OW	0x08
-#define DPOT_AD5272_3_A0	0x08
-#define DPOT_AD5270_2FUSE	0x80
+#define DPOT_AD5170_2_3_FUSE	0x20
+#define DPOT_AD5170_2_3_OW	0x08
+#define DPOT_AD5172_3_A0	0x08
+#define DPOT_AD5170_2FUSE	0x80
 
 struct dpot_data;
 
diff --git a/drivers/misc/apds9802als.c b/drivers/misc/apds9802als.c
new file mode 100644
index 0000000..f9b91ba
--- /dev/null
+++ b/drivers/misc/apds9802als.c
@@ -0,0 +1,347 @@
+/*
+ * apds9802als.c - apds9802  ALS Driver
+ *
+ * Copyright (C) 2009 Intel Corp
+ *
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/sysfs.h>
+#include <linux/pm_runtime.h>
+
+#define ALS_MIN_RANGE_VAL 1
+#define ALS_MAX_RANGE_VAL 2
+#define POWER_STA_ENABLE 1
+#define POWER_STA_DISABLE 0
+
+#define DRIVER_NAME "apds9802als"
+
+struct als_data {
+	struct mutex mutex;
+};
+
+static ssize_t als_sensing_range_show(struct device *dev,
+			struct device_attribute *attr,  char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	int  val;
+
+	val = i2c_smbus_read_byte_data(client, 0x81);
+	if (val < 0)
+		return val;
+	if (val & 1)
+		return sprintf(buf, "4095\n");
+	else
+		return sprintf(buf, "65535\n");
+}
+
+static int als_wait_for_data_ready(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	int ret;
+	int retry = 10;
+
+	do {
+		msleep(30);
+		ret = i2c_smbus_read_byte_data(client, 0x86);
+	} while (!(ret & 0x80) && retry--);
+
+	if (!retry) {
+		dev_warn(dev, "timeout waiting for data ready\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static ssize_t als_lux0_input_data_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct als_data *data = i2c_get_clientdata(client);
+	int ret_val;
+	int temp;
+
+	/* Protect against parallel reads */
+	pm_runtime_get_sync(dev);
+	mutex_lock(&data->mutex);
+
+	/* clear EOC interrupt status */
+	i2c_smbus_write_byte(client, 0x40);
+	/* start measurement */
+	temp = i2c_smbus_read_byte_data(client, 0x81);
+	i2c_smbus_write_byte_data(client, 0x81, temp | 0x08);
+
+	ret_val = als_wait_for_data_ready(dev);
+	if (ret_val < 0)
+		goto failed;
+
+	temp = i2c_smbus_read_byte_data(client, 0x8C); /* LSB data */
+	if (temp < 0) {
+		ret_val = temp;
+		goto failed;
+	}
+	ret_val = i2c_smbus_read_byte_data(client, 0x8D); /* MSB data */
+	if (ret_val < 0)
+		goto failed;
+
+	mutex_unlock(&data->mutex);
+	pm_runtime_put_sync(dev);
+
+	temp = (ret_val << 8) | temp;
+	return sprintf(buf, "%d\n", temp);
+failed:
+	mutex_unlock(&data->mutex);
+	pm_runtime_put_sync(dev);
+	return ret_val;
+}
+
+static ssize_t als_sensing_range_store(struct device *dev,
+		struct device_attribute *attr, const  char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct als_data *data = i2c_get_clientdata(client);
+	unsigned int ret_val;
+	unsigned long val;
+
+	if (strict_strtoul(buf, 10, &val))
+		return -EINVAL;
+
+	if (val < 4096)
+		val = 1;
+	else if (val < 65536)
+		val = 2;
+	else
+		return -ERANGE;
+
+	pm_runtime_get_sync(dev);
+
+	/* Make sure nobody else reads/modifies/writes 0x81 while we
+	   are active */
+	mutex_lock(&data->mutex);
+
+	ret_val = i2c_smbus_read_byte_data(client, 0x81);
+	if (ret_val < 0)
+		goto fail;
+
+	/* Reset the bits before setting them */
+	ret_val = ret_val & 0xFA;
+
+	if (val == 1) /* Setting detection range up to 4k LUX */
+		ret_val = (ret_val | 0x01);
+	else /* Setting detection range up to 64k LUX*/
+		ret_val = (ret_val | 0x00);
+
+	ret_val = i2c_smbus_write_byte_data(client, 0x81, ret_val);
+
+	if (ret_val >= 0) {
+		/* All OK */
+		mutex_unlock(&data->mutex);
+		pm_runtime_put_sync(dev);
+		return count;
+	}
+fail:
+	mutex_unlock(&data->mutex);
+	pm_runtime_put_sync(dev);
+	return ret_val;
+}
+
+static int als_set_power_state(struct i2c_client *client, bool on_off)
+{
+	int ret_val;
+	struct als_data *data = i2c_get_clientdata(client);
+
+	mutex_lock(&data->mutex);
+	ret_val = i2c_smbus_read_byte_data(client, 0x80);
+	if (ret_val < 0)
+		goto fail;
+	if (on_off)
+		ret_val = ret_val | 0x01;
+	else
+		ret_val = ret_val & 0xFE;
+	ret_val = i2c_smbus_write_byte_data(client, 0x80, ret_val);
+fail:
+	mutex_unlock(&data->mutex);
+	return ret_val;
+}
+
+static DEVICE_ATTR(lux0_sensor_range, S_IRUGO | S_IWUSR,
+	als_sensing_range_show, als_sensing_range_store);
+static DEVICE_ATTR(lux0_input, S_IRUGO, als_lux0_input_data_show, NULL);
+
+static struct attribute *mid_att_als[] = {
+	&dev_attr_lux0_sensor_range.attr,
+	&dev_attr_lux0_input.attr,
+	NULL
+};
+
+static struct attribute_group m_als_gr = {
+	.name = "apds9802als",
+	.attrs = mid_att_als
+};
+
+static int als_set_default_config(struct i2c_client *client)
+{
+	int ret_val;
+	/* Write the command and then switch on */
+	ret_val = i2c_smbus_write_byte_data(client, 0x80, 0x01);
+	if (ret_val < 0) {
+		dev_err(&client->dev, "failed default switch on write\n");
+		return ret_val;
+	}
+	/* detection range: 1~64K Lux, maunal measurement */
+	ret_val = i2c_smbus_write_byte_data(client, 0x81, 0x08);
+	if (ret_val < 0)
+		dev_err(&client->dev, "failed default LUX on write\n");
+
+	/*  We always get 0 for the 1st measurement after system power on,
+	 *  so make sure it is finished before user asks for data.
+	 */
+	als_wait_for_data_ready(&client->dev);
+
+	return ret_val;
+}
+
+static int apds9802als_probe(struct i2c_client *client,
+			     const struct i2c_device_id *id)
+{
+	int res;
+	struct als_data *data;
+
+	data = kzalloc(sizeof(struct als_data), GFP_KERNEL);
+	if (data == NULL) {
+		dev_err(&client->dev, "Memory allocation failed\n");
+		return -ENOMEM;
+	}
+	i2c_set_clientdata(client, data);
+	res = sysfs_create_group(&client->dev.kobj, &m_als_gr);
+	if (res) {
+		dev_err(&client->dev, "device create file failed\n");
+		goto als_error1;
+	}
+	dev_info(&client->dev, "ALS chip found\n");
+	als_set_default_config(client);
+	mutex_init(&data->mutex);
+
+	pm_runtime_enable(&client->dev);
+	pm_runtime_get(&client->dev);
+	pm_runtime_put(&client->dev);
+
+	return res;
+als_error1:
+	i2c_set_clientdata(client, NULL);
+	kfree(data);
+	return res;
+}
+
+static int apds9802als_remove(struct i2c_client *client)
+{
+	struct als_data *data = i2c_get_clientdata(client);
+
+	als_set_power_state(client, false);
+	sysfs_remove_group(&client->dev.kobj, &m_als_gr);
+	kfree(data);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int apds9802als_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+	als_set_power_state(client, false);
+	return 0;
+}
+
+static int apds9802als_resume(struct i2c_client *client)
+{
+	als_set_default_config(client);
+
+	pm_runtime_get(&client->dev);
+	pm_runtime_put(&client->dev);
+	return 0;
+}
+
+static int apds9802als_runtime_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+
+	als_set_power_state(client, false);
+	return 0;
+}
+
+static int apds9802als_runtime_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+
+	als_set_power_state(client, true);
+	return 0;
+}
+
+static const struct dev_pm_ops apds9802als_pm_ops = {
+	.runtime_suspend = apds9802als_runtime_suspend,
+	.runtime_resume = apds9802als_runtime_resume,
+};
+
+#define APDS9802ALS_PM_OPS (&apds9802als_pm_ops)
+
+#else	/* CONFIG_PM */
+#define apds9802als_suspend NULL
+#define apds9802als_resume NULL
+#define APDS9802ALS_PM_OPS NULL
+#endif	/* CONFIG_PM */
+
+static struct i2c_device_id apds9802als_id[] = {
+	{ DRIVER_NAME, 0 },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, apds9802als_id);
+
+static struct i2c_driver apds9802als_driver = {
+	.driver = {
+		.name = DRIVER_NAME,
+		.pm = APDS9802ALS_PM_OPS,
+	},
+	.probe = apds9802als_probe,
+	.remove = apds9802als_remove,
+	.suspend = apds9802als_suspend,
+	.resume = apds9802als_resume,
+	.id_table = apds9802als_id,
+};
+
+static int __init sensor_apds9802als_init(void)
+{
+	return i2c_add_driver(&apds9802als_driver);
+}
+
+static void  __exit sensor_apds9802als_exit(void)
+{
+	i2c_del_driver(&apds9802als_driver);
+}
+module_init(sensor_apds9802als_init);
+module_exit(sensor_apds9802als_exit);
+
+MODULE_AUTHOR("Anantha Narayanan <Anantha.Narayanan@intel.com");
+MODULE_DESCRIPTION("Avago apds9802als ALS Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/apds990x.c b/drivers/misc/apds990x.c
new file mode 100644
index 0000000..200311f
--- /dev/null
+++ b/drivers/misc/apds990x.c
@@ -0,0 +1,1295 @@
+/*
+ * This file is part of the APDS990x sensor driver.
+ * Chip is combined proximity and ambient light sensor.
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: Samu Onkalo <samu.p.onkalo@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <linux/slab.h>
+#include <linux/i2c/apds990x.h>
+
+/* Register map */
+#define APDS990X_ENABLE	 0x00 /* Enable of states and interrupts */
+#define APDS990X_ATIME	 0x01 /* ALS ADC time  */
+#define APDS990X_PTIME	 0x02 /* Proximity ADC time  */
+#define APDS990X_WTIME	 0x03 /* Wait time  */
+#define APDS990X_AILTL	 0x04 /* ALS interrupt low threshold low byte */
+#define APDS990X_AILTH	 0x05 /* ALS interrupt low threshold hi byte */
+#define APDS990X_AIHTL	 0x06 /* ALS interrupt hi threshold low byte */
+#define APDS990X_AIHTH	 0x07 /* ALS interrupt hi threshold hi byte */
+#define APDS990X_PILTL	 0x08 /* Proximity interrupt low threshold low byte */
+#define APDS990X_PILTH	 0x09 /* Proximity interrupt low threshold hi byte */
+#define APDS990X_PIHTL	 0x0a /* Proximity interrupt hi threshold low byte */
+#define APDS990X_PIHTH	 0x0b /* Proximity interrupt hi threshold hi byte */
+#define APDS990X_PERS	 0x0c /* Interrupt persistence filters */
+#define APDS990X_CONFIG	 0x0d /* Configuration */
+#define APDS990X_PPCOUNT 0x0e /* Proximity pulse count */
+#define APDS990X_CONTROL 0x0f /* Gain control register */
+#define APDS990X_REV	 0x11 /* Revision Number */
+#define APDS990X_ID	 0x12 /* Device ID */
+#define APDS990X_STATUS	 0x13 /* Device status */
+#define APDS990X_CDATAL	 0x14 /* Clear ADC low data register */
+#define APDS990X_CDATAH	 0x15 /* Clear ADC high data register */
+#define APDS990X_IRDATAL 0x16 /* IR ADC low data register */
+#define APDS990X_IRDATAH 0x17 /* IR ADC high data register */
+#define APDS990X_PDATAL	 0x18 /* Proximity ADC low data register */
+#define APDS990X_PDATAH	 0x19 /* Proximity ADC high data register */
+
+/* Control */
+#define APDS990X_MAX_AGAIN	3
+
+/* Enable register */
+#define APDS990X_EN_PIEN	(0x1 << 5)
+#define APDS990X_EN_AIEN	(0x1 << 4)
+#define APDS990X_EN_WEN		(0x1 << 3)
+#define APDS990X_EN_PEN		(0x1 << 2)
+#define APDS990X_EN_AEN		(0x1 << 1)
+#define APDS990X_EN_PON		(0x1 << 0)
+#define APDS990X_EN_DISABLE_ALL 0
+
+/* Status register */
+#define APDS990X_ST_PINT	(0x1 << 5)
+#define APDS990X_ST_AINT	(0x1 << 4)
+
+/* I2C access types */
+#define APDS990x_CMD_TYPE_MASK	(0x03 << 5)
+#define APDS990x_CMD_TYPE_RB	(0x00 << 5) /* Repeated byte */
+#define APDS990x_CMD_TYPE_INC	(0x01 << 5) /* Auto increment */
+#define APDS990x_CMD_TYPE_SPE	(0x03 << 5) /* Special function */
+
+#define APDS990x_ADDR_SHIFT	0
+#define APDS990x_CMD		0x80
+
+/* Interrupt ack commands */
+#define APDS990X_INT_ACK_ALS	0x6
+#define APDS990X_INT_ACK_PS	0x5
+#define APDS990X_INT_ACK_BOTH	0x7
+
+/* ptime */
+#define APDS990X_PTIME_DEFAULT	0xff /* Recommended conversion time 2.7ms*/
+
+/* wtime */
+#define APDS990X_WTIME_DEFAULT	0xee /* ~50ms wait time */
+
+#define APDS990X_TIME_TO_ADC	1024 /* One timetick as ADC count value */
+
+/* Persistence */
+#define APDS990X_APERS_SHIFT	0
+#define APDS990X_PPERS_SHIFT	4
+
+/* Supported ID:s */
+#define APDS990X_ID_0		0x0
+#define APDS990X_ID_4		0x4
+#define APDS990X_ID_29		0x29
+
+/* pgain and pdiode settings */
+#define APDS_PGAIN_1X	       0x0
+#define APDS_PDIODE_IR	       0x2
+
+#define APDS990X_LUX_OUTPUT_SCALE 10
+
+/* Reverse chip factors for threshold calculation */
+struct reverse_factors {
+	u32 afactor;
+	int cf1;
+	int irf1;
+	int cf2;
+	int irf2;
+};
+
+struct apds990x_chip {
+	struct apds990x_platform_data	*pdata;
+	struct i2c_client		*client;
+	struct mutex			mutex; /* avoid parallel access */
+	struct regulator_bulk_data	regs[2];
+	wait_queue_head_t		wait;
+
+	int	prox_en;
+	bool	prox_continuous_mode;
+	bool	lux_wait_fresh_res;
+
+	/* Chip parameters */
+	struct	apds990x_chip_factors	cf;
+	struct	reverse_factors		rcf;
+	u16	atime;		/* als integration time */
+	u16	arate;		/* als reporting rate */
+	u16	a_max_result;	/* Max possible ADC value with current atime */
+	u8	again_meas;	/* Gain used in last measurement */
+	u8	again_next;	/* Next calculated gain */
+	u8	pgain;
+	u8	pdiode;
+	u8	pdrive;
+	u8	lux_persistence;
+	u8	prox_persistence;
+
+	u32	lux_raw;
+	u32	lux;
+	u16	lux_clear;
+	u16	lux_ir;
+	u16	lux_calib;
+	u32	lux_thres_hi;
+	u32	lux_thres_lo;
+
+	u32	prox_thres;
+	u16	prox_data;
+	u16	prox_calib;
+
+	char	chipname[10];
+	u8	revision;
+};
+
+#define APDS_CALIB_SCALER		8192
+#define APDS_LUX_NEUTRAL_CALIB_VALUE	(1 * APDS_CALIB_SCALER)
+#define APDS_PROX_NEUTRAL_CALIB_VALUE	(1 * APDS_CALIB_SCALER)
+
+#define APDS_PROX_DEF_THRES		600
+#define APDS_PROX_HYSTERESIS		50
+#define APDS_LUX_DEF_THRES_HI		101
+#define APDS_LUX_DEF_THRES_LO		100
+#define APDS_DEFAULT_PROX_PERS		1
+
+#define APDS_TIMEOUT			2000
+#define APDS_STARTUP_DELAY		25000 /* us */
+#define APDS_RANGE			65535
+#define APDS_PROX_RANGE			1023
+#define APDS_LUX_GAIN_LO_LIMIT		100
+#define APDS_LUX_GAIN_LO_LIMIT_STRICT	25
+
+#define TIMESTEP			87 /* 2.7ms is about 87 / 32 */
+#define TIME_STEP_SCALER		32
+
+#define APDS_LUX_AVERAGING_TIME		50 /* tolerates 50/60Hz ripple */
+#define APDS_LUX_DEFAULT_RATE		200
+
+static const u8 again[]	= {1, 8, 16, 120}; /* ALS gain steps */
+static const u8 ir_currents[]	= {100, 50, 25, 12}; /* IRled currents in mA */
+
+/* Following two tables must match i.e 10Hz rate means 1 as persistence value */
+static const u16 arates_hz[] = {10, 5, 2, 1};
+static const u8 apersis[] = {1, 2, 4, 5};
+
+/* Regulators */
+static const char reg_vcc[] = "Vdd";
+static const char reg_vled[] = "Vled";
+
+static int apds990x_read_byte(struct apds990x_chip *chip, u8 reg, u8 *data)
+{
+	struct i2c_client *client = chip->client;
+	s32 ret;
+
+	reg &= ~APDS990x_CMD_TYPE_MASK;
+	reg |= APDS990x_CMD | APDS990x_CMD_TYPE_RB;
+
+	ret = i2c_smbus_read_byte_data(client, reg);
+	*data = ret;
+	return (int)ret;
+}
+
+static int apds990x_read_word(struct apds990x_chip *chip, u8 reg, u16 *data)
+{
+	struct i2c_client *client = chip->client;
+	s32 ret;
+
+	reg &= ~APDS990x_CMD_TYPE_MASK;
+	reg |= APDS990x_CMD | APDS990x_CMD_TYPE_INC;
+
+	ret = i2c_smbus_read_word_data(client, reg);
+	*data = ret;
+	return (int)ret;
+}
+
+static int apds990x_write_byte(struct apds990x_chip *chip, u8 reg, u8 data)
+{
+	struct i2c_client *client = chip->client;
+	s32 ret;
+
+	reg &= ~APDS990x_CMD_TYPE_MASK;
+	reg |= APDS990x_CMD | APDS990x_CMD_TYPE_RB;
+
+	ret = i2c_smbus_write_byte_data(client, reg, data);
+	return (int)ret;
+}
+
+static int apds990x_write_word(struct apds990x_chip *chip, u8 reg, u16 data)
+{
+	struct i2c_client *client = chip->client;
+	s32 ret;
+
+	reg &= ~APDS990x_CMD_TYPE_MASK;
+	reg |= APDS990x_CMD | APDS990x_CMD_TYPE_INC;
+
+	ret = i2c_smbus_write_word_data(client, reg, data);
+	return (int)ret;
+}
+
+static int apds990x_mode_on(struct apds990x_chip *chip)
+{
+	/* ALS is mandatory, proximity optional */
+	u8 reg = APDS990X_EN_AIEN | APDS990X_EN_PON | APDS990X_EN_AEN |
+		APDS990X_EN_WEN;
+
+	if (chip->prox_en)
+		reg |= APDS990X_EN_PIEN | APDS990X_EN_PEN;
+
+	return apds990x_write_byte(chip, APDS990X_ENABLE, reg);
+}
+
+static u16 apds990x_lux_to_threshold(struct apds990x_chip *chip, u32 lux)
+{
+	u32 thres;
+	u32 cpl;
+	u32 ir;
+
+	if (lux == 0)
+		return 0;
+	else if (lux == APDS_RANGE)
+		return APDS_RANGE;
+
+	/*
+	 * Reported LUX value is a combination of the IR and CLEAR channel
+	 * values. However, interrupt threshold is only for clear channel.
+	 * This function approximates needed HW threshold value for a given
+	 * LUX value in the current lightning type.
+	 * IR level compared to visible light varies heavily depending on the
+	 * source of the light
+	 *
+	 * Calculate threshold value for the next measurement period.
+	 * Math: threshold = lux * cpl where
+	 * cpl = atime * again / (glass_attenuation * device_factor)
+	 * (count-per-lux)
+	 *
+	 * First remove calibration. Division by four is to avoid overflow
+	 */
+	lux = lux * (APDS_CALIB_SCALER / 4) / (chip->lux_calib / 4);
+
+	/* Multiplication by 64 is to increase accuracy */
+	cpl = ((u32)chip->atime * (u32)again[chip->again_next] *
+		APDS_PARAM_SCALE * 64) / (chip->cf.ga * chip->cf.df);
+
+	thres = lux * cpl / 64;
+	/*
+	 * Convert IR light from the latest result to match with
+	 * new gain step. This helps to adapt with the current
+	 * source of light.
+	 */
+	ir = (u32)chip->lux_ir * (u32)again[chip->again_next] /
+		(u32)again[chip->again_meas];
+
+	/*
+	 * Compensate count with IR light impact
+	 * IAC1 > IAC2 (see apds990x_get_lux for formulas)
+	 */
+	if (chip->lux_clear * APDS_PARAM_SCALE >=
+		chip->rcf.afactor * chip->lux_ir)
+		thres = (chip->rcf.cf1 * thres + chip->rcf.irf1 * ir) /
+			APDS_PARAM_SCALE;
+	else
+		thres = (chip->rcf.cf2 * thres + chip->rcf.irf2 * ir) /
+			APDS_PARAM_SCALE;
+
+	if (thres >= chip->a_max_result)
+		thres = chip->a_max_result - 1;
+	return thres;
+}
+
+static inline int apds990x_set_atime(struct apds990x_chip *chip, u32 time_ms)
+{
+	u8 reg_value;
+
+	chip->atime = time_ms;
+	/* Formula is specified in the data sheet */
+	reg_value = 256 - ((time_ms * TIME_STEP_SCALER) / TIMESTEP);
+	/* Calculate max ADC value for given integration time */
+	chip->a_max_result = (u16)(256 - reg_value) * APDS990X_TIME_TO_ADC;
+	return apds990x_write_byte(chip, APDS990X_ATIME, reg_value);
+}
+
+/* Called always with mutex locked */
+static int apds990x_refresh_pthres(struct apds990x_chip *chip, int data)
+{
+	int ret, lo, hi;
+
+	/* If the chip is not in use, don't try to access it */
+	if (pm_runtime_suspended(&chip->client->dev))
+		return 0;
+
+	if (data < chip->prox_thres) {
+		lo = 0;
+		hi = chip->prox_thres;
+	} else {
+		lo = chip->prox_thres - APDS_PROX_HYSTERESIS;
+		if (chip->prox_continuous_mode)
+			hi = chip->prox_thres;
+		else
+			hi = APDS_RANGE;
+	}
+
+	ret = apds990x_write_word(chip, APDS990X_PILTL, lo);
+	ret |= apds990x_write_word(chip, APDS990X_PIHTL, hi);
+	return ret;
+}
+
+/* Called always with mutex locked */
+static int apds990x_refresh_athres(struct apds990x_chip *chip)
+{
+	int ret;
+	/* If the chip is not in use, don't try to access it */
+	if (pm_runtime_suspended(&chip->client->dev))
+		return 0;
+
+	ret = apds990x_write_word(chip, APDS990X_AILTL,
+			apds990x_lux_to_threshold(chip, chip->lux_thres_lo));
+	ret |= apds990x_write_word(chip, APDS990X_AIHTL,
+			apds990x_lux_to_threshold(chip, chip->lux_thres_hi));
+
+	return ret;
+}
+
+/* Called always with mutex locked */
+static void apds990x_force_a_refresh(struct apds990x_chip *chip)
+{
+	/* This will force ALS interrupt after the next measurement. */
+	apds990x_write_word(chip, APDS990X_AILTL, APDS_LUX_DEF_THRES_LO);
+	apds990x_write_word(chip, APDS990X_AIHTL, APDS_LUX_DEF_THRES_HI);
+}
+
+/* Called always with mutex locked */
+static void apds990x_force_p_refresh(struct apds990x_chip *chip)
+{
+	/* This will force proximity interrupt after the next measurement. */
+	apds990x_write_word(chip, APDS990X_PILTL, APDS_PROX_DEF_THRES - 1);
+	apds990x_write_word(chip, APDS990X_PIHTL, APDS_PROX_DEF_THRES);
+}
+
+/* Called always with mutex locked */
+static int apds990x_calc_again(struct apds990x_chip *chip)
+{
+	int curr_again = chip->again_meas;
+	int next_again = chip->again_meas;
+	int ret = 0;
+
+	/* Calculate suitable als gain */
+	if (chip->lux_clear == chip->a_max_result)
+		next_again -= 2; /* ALS saturated. Decrease gain by 2 steps */
+	else if (chip->lux_clear > chip->a_max_result / 2)
+		next_again--;
+	else if (chip->lux_clear < APDS_LUX_GAIN_LO_LIMIT_STRICT)
+		next_again += 2; /* Too dark. Increase gain by 2 steps */
+	else if (chip->lux_clear < APDS_LUX_GAIN_LO_LIMIT)
+		next_again++;
+
+	/* Limit gain to available range */
+	if (next_again < 0)
+		next_again = 0;
+	else if (next_again > APDS990X_MAX_AGAIN)
+		next_again = APDS990X_MAX_AGAIN;
+
+	/* Let's check can we trust the measured result */
+	if (chip->lux_clear == chip->a_max_result)
+		/* Result can be totally garbage due to saturation */
+		ret = -ERANGE;
+	else if (next_again != curr_again &&
+		chip->lux_clear < APDS_LUX_GAIN_LO_LIMIT_STRICT)
+		/*
+		 * Gain is changed and measurement result is very small.
+		 * Result can be totally garbage due to underflow
+		 */
+		ret = -ERANGE;
+
+	chip->again_next = next_again;
+	apds990x_write_byte(chip, APDS990X_CONTROL,
+			(chip->pdrive << 6) |
+			(chip->pdiode << 4) |
+			(chip->pgain << 2) |
+			(chip->again_next << 0));
+
+	/*
+	 * Error means bad result -> re-measurement is needed. The forced
+	 * refresh uses fastest possible persistence setting to get result
+	 * as soon as possible.
+	 */
+	if (ret < 0)
+		apds990x_force_a_refresh(chip);
+	else
+		apds990x_refresh_athres(chip);
+
+	return ret;
+}
+
+/* Called always with mutex locked */
+static int apds990x_get_lux(struct apds990x_chip *chip, int clear, int ir)
+{
+	int iac, iac1, iac2; /* IR adjusted counts */
+	u32 lpc; /* Lux per count */
+
+	/* Formulas:
+	 * iac1 = CF1 * CLEAR_CH - IRF1 * IR_CH
+	 * iac2 = CF2 * CLEAR_CH - IRF2 * IR_CH
+	 */
+	iac1 = (chip->cf.cf1 * clear - chip->cf.irf1 * ir) / APDS_PARAM_SCALE;
+	iac2 = (chip->cf.cf2 * clear - chip->cf.irf2 * ir) / APDS_PARAM_SCALE;
+
+	iac = max(iac1, iac2);
+	iac = max(iac, 0);
+
+	lpc = APDS990X_LUX_OUTPUT_SCALE * (chip->cf.df * chip->cf.ga) /
+		(u32)(again[chip->again_meas] * (u32)chip->atime);
+
+	return (iac * lpc) / APDS_PARAM_SCALE;
+}
+
+static int apds990x_ack_int(struct apds990x_chip *chip, u8 mode)
+{
+	struct i2c_client *client = chip->client;
+	s32 ret;
+	u8 reg = APDS990x_CMD | APDS990x_CMD_TYPE_SPE;
+
+	switch (mode & (APDS990X_ST_AINT | APDS990X_ST_PINT)) {
+	case APDS990X_ST_AINT:
+		reg |= APDS990X_INT_ACK_ALS;
+		break;
+	case APDS990X_ST_PINT:
+		reg |= APDS990X_INT_ACK_PS;
+		break;
+	default:
+		reg |= APDS990X_INT_ACK_BOTH;
+		break;
+	}
+
+	ret = i2c_smbus_read_byte_data(client, reg);
+	return (int)ret;
+}
+
+static irqreturn_t apds990x_irq(int irq, void *data)
+{
+	struct apds990x_chip *chip = data;
+	u8 status;
+
+	apds990x_read_byte(chip, APDS990X_STATUS, &status);
+	apds990x_ack_int(chip, status);
+
+	mutex_lock(&chip->mutex);
+	if (!pm_runtime_suspended(&chip->client->dev)) {
+		if (status & APDS990X_ST_AINT) {
+			apds990x_read_word(chip, APDS990X_CDATAL,
+					&chip->lux_clear);
+			apds990x_read_word(chip, APDS990X_IRDATAL,
+					&chip->lux_ir);
+			/* Store used gain for calculations */
+			chip->again_meas = chip->again_next;
+
+			chip->lux_raw = apds990x_get_lux(chip,
+							chip->lux_clear,
+							chip->lux_ir);
+
+			if (apds990x_calc_again(chip) == 0) {
+				/* Result is valid */
+				chip->lux = chip->lux_raw;
+				chip->lux_wait_fresh_res = false;
+				wake_up(&chip->wait);
+				sysfs_notify(&chip->client->dev.kobj,
+					NULL, "lux0_input");
+			}
+		}
+
+		if ((status & APDS990X_ST_PINT) && chip->prox_en) {
+			u16 clr_ch;
+
+			apds990x_read_word(chip, APDS990X_CDATAL, &clr_ch);
+			/*
+			 * If ALS channel is saturated at min gain,
+			 * proximity gives false posivite values.
+			 * Just ignore them.
+			 */
+			if (chip->again_meas == 0 &&
+				clr_ch == chip->a_max_result)
+				chip->prox_data = 0;
+			else
+				apds990x_read_word(chip,
+						APDS990X_PDATAL,
+						&chip->prox_data);
+
+			apds990x_refresh_pthres(chip, chip->prox_data);
+			if (chip->prox_data < chip->prox_thres)
+				chip->prox_data = 0;
+			else if (!chip->prox_continuous_mode)
+				chip->prox_data = APDS_PROX_RANGE;
+			sysfs_notify(&chip->client->dev.kobj,
+				NULL, "prox0_raw");
+		}
+	}
+	mutex_unlock(&chip->mutex);
+	return IRQ_HANDLED;
+}
+
+static int apds990x_configure(struct apds990x_chip *chip)
+{
+	/* It is recommended to use disabled mode during these operations */
+	apds990x_write_byte(chip, APDS990X_ENABLE, APDS990X_EN_DISABLE_ALL);
+
+	/* conversion and wait times for different state machince states */
+	apds990x_write_byte(chip, APDS990X_PTIME, APDS990X_PTIME_DEFAULT);
+	apds990x_write_byte(chip, APDS990X_WTIME, APDS990X_WTIME_DEFAULT);
+	apds990x_set_atime(chip, APDS_LUX_AVERAGING_TIME);
+
+	apds990x_write_byte(chip, APDS990X_CONFIG, 0);
+
+	/* Persistence levels */
+	apds990x_write_byte(chip, APDS990X_PERS,
+			(chip->lux_persistence << APDS990X_APERS_SHIFT) |
+			(chip->prox_persistence << APDS990X_PPERS_SHIFT));
+
+	apds990x_write_byte(chip, APDS990X_PPCOUNT, chip->pdata->ppcount);
+
+	/* Start with relatively small gain */
+	chip->again_meas = 1;
+	chip->again_next = 1;
+	apds990x_write_byte(chip, APDS990X_CONTROL,
+			(chip->pdrive << 6) |
+			(chip->pdiode << 4) |
+			(chip->pgain << 2) |
+			(chip->again_next << 0));
+	return 0;
+}
+
+static int apds990x_detect(struct apds990x_chip *chip)
+{
+	struct i2c_client *client = chip->client;
+	int ret;
+	u8 id;
+
+	ret = apds990x_read_byte(chip, APDS990X_ID, &id);
+	if (ret < 0) {
+		dev_err(&client->dev, "ID read failed\n");
+		return ret;
+	}
+
+	ret = apds990x_read_byte(chip, APDS990X_REV, &chip->revision);
+	if (ret < 0) {
+		dev_err(&client->dev, "REV read failed\n");
+		return ret;
+	}
+
+	switch (id) {
+	case APDS990X_ID_0:
+	case APDS990X_ID_4:
+	case APDS990X_ID_29:
+		snprintf(chip->chipname, sizeof(chip->chipname), "APDS-990x");
+		break;
+	default:
+		ret = -ENODEV;
+		break;
+	}
+	return ret;
+}
+
+static int apds990x_chip_on(struct apds990x_chip *chip)
+{
+	int err	 = regulator_bulk_enable(ARRAY_SIZE(chip->regs),
+					chip->regs);
+	if (err < 0)
+		return err;
+
+	usleep_range(APDS_STARTUP_DELAY, 2 * APDS_STARTUP_DELAY);
+
+	/* Refresh all configs in case of regulators were off */
+	chip->prox_data = 0;
+	apds990x_configure(chip);
+	apds990x_mode_on(chip);
+	return 0;
+}
+
+static int apds990x_chip_off(struct apds990x_chip *chip)
+{
+	apds990x_write_byte(chip, APDS990X_ENABLE, APDS990X_EN_DISABLE_ALL);
+	regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs);
+	return 0;
+}
+
+static ssize_t apds990x_lux_show(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	struct apds990x_chip *chip = dev_get_drvdata(dev);
+	ssize_t ret;
+	u32 result;
+	long timeout;
+
+	if (pm_runtime_suspended(dev))
+		return -EIO;
+
+	timeout = wait_event_interruptible_timeout(chip->wait,
+						!chip->lux_wait_fresh_res,
+						msecs_to_jiffies(APDS_TIMEOUT));
+	if (!timeout)
+		return -EIO;
+
+	mutex_lock(&chip->mutex);
+	result = (chip->lux * chip->lux_calib) / APDS_CALIB_SCALER;
+	if (result > (APDS_RANGE * APDS990X_LUX_OUTPUT_SCALE))
+		result = APDS_RANGE * APDS990X_LUX_OUTPUT_SCALE;
+
+	ret = sprintf(buf, "%d.%d\n",
+		result / APDS990X_LUX_OUTPUT_SCALE,
+		result % APDS990X_LUX_OUTPUT_SCALE);
+	mutex_unlock(&chip->mutex);
+	return ret;
+}
+
+static DEVICE_ATTR(lux0_input, S_IRUGO, apds990x_lux_show, NULL);
+
+static ssize_t apds990x_lux_range_show(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%u\n", APDS_RANGE);
+}
+
+static DEVICE_ATTR(lux0_sensor_range, S_IRUGO, apds990x_lux_range_show, NULL);
+
+static ssize_t apds990x_lux_calib_format_show(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%u\n", APDS_CALIB_SCALER);
+}
+
+static DEVICE_ATTR(lux0_calibscale_default, S_IRUGO,
+		apds990x_lux_calib_format_show, NULL);
+
+static ssize_t apds990x_lux_calib_show(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	struct apds990x_chip *chip = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%u\n", chip->lux_calib);
+}
+
+static ssize_t apds990x_lux_calib_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t len)
+{
+	struct apds990x_chip *chip = dev_get_drvdata(dev);
+	unsigned long value;
+
+	if (strict_strtoul(buf, 0, &value))
+		return -EINVAL;
+
+	if (chip->lux_calib > APDS_RANGE)
+		return -EINVAL;
+
+	chip->lux_calib = value;
+
+	return len;
+}
+
+static DEVICE_ATTR(lux0_calibscale, S_IRUGO | S_IWUSR, apds990x_lux_calib_show,
+		apds990x_lux_calib_store);
+
+static ssize_t apds990x_rate_avail(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	int i;
+	int pos = 0;
+	for (i = 0; i < ARRAY_SIZE(arates_hz); i++)
+		pos += sprintf(buf + pos, "%d ", arates_hz[i]);
+	sprintf(buf + pos - 1, "\n");
+	return pos;
+}
+
+static ssize_t apds990x_rate_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct apds990x_chip *chip =  dev_get_drvdata(dev);
+	return sprintf(buf, "%d\n", chip->arate);
+}
+
+static int apds990x_set_arate(struct apds990x_chip *chip, int rate)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(arates_hz); i++)
+		if (rate >= arates_hz[i])
+			break;
+
+	if (i == ARRAY_SIZE(arates_hz))
+		return -EINVAL;
+
+	/* Pick up corresponding persistence value */
+	chip->lux_persistence = apersis[i];
+	chip->arate = arates_hz[i];
+
+	/* If the chip is not in use, don't try to access it */
+	if (pm_runtime_suspended(&chip->client->dev))
+		return 0;
+
+	/* Persistence levels */
+	return apds990x_write_byte(chip, APDS990X_PERS,
+			(chip->lux_persistence << APDS990X_APERS_SHIFT) |
+			(chip->prox_persistence << APDS990X_PPERS_SHIFT));
+}
+
+static ssize_t apds990x_rate_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t len)
+{
+	struct apds990x_chip *chip =  dev_get_drvdata(dev);
+	unsigned long value;
+	int ret;
+
+	if (strict_strtoul(buf, 0, &value))
+		return -EINVAL;
+
+	mutex_lock(&chip->mutex);
+	ret = apds990x_set_arate(chip, value);
+	mutex_unlock(&chip->mutex);
+
+	if (ret < 0)
+		return ret;
+	return len;
+}
+
+static DEVICE_ATTR(lux0_rate_avail, S_IRUGO, apds990x_rate_avail, NULL);
+
+static DEVICE_ATTR(lux0_rate, S_IRUGO | S_IWUSR, apds990x_rate_show,
+						 apds990x_rate_store);
+
+static ssize_t apds990x_prox_show(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	struct apds990x_chip *chip =  dev_get_drvdata(dev);
+	if (pm_runtime_suspended(dev) || !chip->prox_en)
+		return -EIO;
+
+	mutex_lock(&chip->mutex);
+	ret = sprintf(buf, "%d\n", chip->prox_data);
+	mutex_unlock(&chip->mutex);
+	return ret;
+}
+
+static DEVICE_ATTR(prox0_raw, S_IRUGO, apds990x_prox_show, NULL);
+
+static ssize_t apds990x_prox_range_show(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%u\n", APDS_PROX_RANGE);
+}
+
+static DEVICE_ATTR(prox0_sensor_range, S_IRUGO, apds990x_prox_range_show, NULL);
+
+static ssize_t apds990x_prox_enable_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct apds990x_chip *chip =  dev_get_drvdata(dev);
+	return sprintf(buf, "%d\n", chip->prox_en);
+}
+
+static ssize_t apds990x_prox_enable_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t len)
+{
+	struct apds990x_chip *chip =  dev_get_drvdata(dev);
+	unsigned long value;
+
+	if (strict_strtoul(buf, 0, &value))
+		return -EINVAL;
+
+	mutex_lock(&chip->mutex);
+
+	if (!chip->prox_en)
+		chip->prox_data = 0;
+
+	if (value)
+		chip->prox_en++;
+	else if (chip->prox_en > 0)
+		chip->prox_en--;
+
+	if (!pm_runtime_suspended(dev))
+		apds990x_mode_on(chip);
+	mutex_unlock(&chip->mutex);
+	return len;
+}
+
+static DEVICE_ATTR(prox0_raw_en, S_IRUGO | S_IWUSR, apds990x_prox_enable_show,
+						   apds990x_prox_enable_store);
+
+static const char reporting_modes[][9] = {"trigger", "periodic"};
+
+static ssize_t apds990x_prox_reporting_mode_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct apds990x_chip *chip =  dev_get_drvdata(dev);
+	return sprintf(buf, "%s\n",
+		reporting_modes[!!chip->prox_continuous_mode]);
+}
+
+static ssize_t apds990x_prox_reporting_mode_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t len)
+{
+	struct apds990x_chip *chip =  dev_get_drvdata(dev);
+
+	if (sysfs_streq(buf, reporting_modes[0]))
+		chip->prox_continuous_mode = 0;
+	else if (sysfs_streq(buf, reporting_modes[1]))
+		chip->prox_continuous_mode = 1;
+	else
+		return -EINVAL;
+	return len;
+}
+
+static DEVICE_ATTR(prox0_reporting_mode, S_IRUGO | S_IWUSR,
+		apds990x_prox_reporting_mode_show,
+		apds990x_prox_reporting_mode_store);
+
+static ssize_t apds990x_prox_reporting_avail_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%s %s\n", reporting_modes[0], reporting_modes[1]);
+}
+
+static DEVICE_ATTR(prox0_reporting_mode_avail, S_IRUGO | S_IWUSR,
+		apds990x_prox_reporting_avail_show, NULL);
+
+
+static ssize_t apds990x_lux_thresh_above_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct apds990x_chip *chip =  dev_get_drvdata(dev);
+	return sprintf(buf, "%d\n", chip->lux_thres_hi);
+}
+
+static ssize_t apds990x_lux_thresh_below_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct apds990x_chip *chip =  dev_get_drvdata(dev);
+	return sprintf(buf, "%d\n", chip->lux_thres_lo);
+}
+
+static ssize_t apds990x_set_lux_thresh(struct apds990x_chip *chip, u32 *target,
+				const char *buf)
+{
+	int ret = 0;
+	unsigned long thresh;
+
+	if (strict_strtoul(buf, 0, &thresh))
+		return -EINVAL;
+
+	if (thresh > APDS_RANGE)
+		return -EINVAL;
+
+	mutex_lock(&chip->mutex);
+	*target = thresh;
+	/*
+	 * Don't update values in HW if we are still waiting for
+	 * first interrupt to come after device handle open call.
+	 */
+	if (!chip->lux_wait_fresh_res)
+		apds990x_refresh_athres(chip);
+	mutex_unlock(&chip->mutex);
+	return ret;
+
+}
+
+static ssize_t apds990x_lux_thresh_above_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t len)
+{
+	struct apds990x_chip *chip =  dev_get_drvdata(dev);
+	int ret = apds990x_set_lux_thresh(chip, &chip->lux_thres_hi, buf);
+	if (ret < 0)
+		return ret;
+	return len;
+}
+
+static ssize_t apds990x_lux_thresh_below_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t len)
+{
+	struct apds990x_chip *chip =  dev_get_drvdata(dev);
+	int ret = apds990x_set_lux_thresh(chip, &chip->lux_thres_lo, buf);
+	if (ret < 0)
+		return ret;
+	return len;
+}
+
+static DEVICE_ATTR(lux0_thresh_above_value, S_IRUGO | S_IWUSR,
+		apds990x_lux_thresh_above_show,
+		apds990x_lux_thresh_above_store);
+
+static DEVICE_ATTR(lux0_thresh_below_value, S_IRUGO | S_IWUSR,
+		apds990x_lux_thresh_below_show,
+		apds990x_lux_thresh_below_store);
+
+static ssize_t apds990x_prox_threshold_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct apds990x_chip *chip =  dev_get_drvdata(dev);
+	return sprintf(buf, "%d\n", chip->prox_thres);
+}
+
+static ssize_t apds990x_prox_threshold_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t len)
+{
+	struct apds990x_chip *chip =  dev_get_drvdata(dev);
+	unsigned long value;
+
+	if (strict_strtoul(buf, 0, &value))
+		return -EINVAL;
+
+	if ((value > APDS_RANGE) || (value == 0) ||
+		(value < APDS_PROX_HYSTERESIS))
+		return -EINVAL;
+
+	mutex_lock(&chip->mutex);
+	chip->prox_thres = value;
+
+	apds990x_force_p_refresh(chip);
+	mutex_unlock(&chip->mutex);
+	return len;
+}
+
+static DEVICE_ATTR(prox0_thresh_above_value, S_IRUGO | S_IWUSR,
+		apds990x_prox_threshold_show,
+		apds990x_prox_threshold_store);
+
+static ssize_t apds990x_power_state_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%d\n", !pm_runtime_suspended(dev));
+	return 0;
+}
+
+static ssize_t apds990x_power_state_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t len)
+{
+	struct apds990x_chip *chip =  dev_get_drvdata(dev);
+	unsigned long value;
+
+	if (strict_strtoul(buf, 0, &value))
+		return -EINVAL;
+	if (value) {
+		pm_runtime_get_sync(dev);
+		mutex_lock(&chip->mutex);
+		chip->lux_wait_fresh_res = true;
+		apds990x_force_a_refresh(chip);
+		apds990x_force_p_refresh(chip);
+		mutex_unlock(&chip->mutex);
+	} else {
+		if (!pm_runtime_suspended(dev))
+			pm_runtime_put(dev);
+	}
+	return len;
+}
+
+static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR,
+		apds990x_power_state_show,
+		apds990x_power_state_store);
+
+static ssize_t apds990x_chip_id_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct apds990x_chip *chip =  dev_get_drvdata(dev);
+	return sprintf(buf, "%s %d\n", chip->chipname, chip->revision);
+}
+
+static DEVICE_ATTR(chip_id, S_IRUGO, apds990x_chip_id_show, NULL);
+
+static struct attribute *sysfs_attrs_ctrl[] = {
+	&dev_attr_lux0_calibscale.attr,
+	&dev_attr_lux0_calibscale_default.attr,
+	&dev_attr_lux0_input.attr,
+	&dev_attr_lux0_sensor_range.attr,
+	&dev_attr_lux0_rate.attr,
+	&dev_attr_lux0_rate_avail.attr,
+	&dev_attr_lux0_thresh_above_value.attr,
+	&dev_attr_lux0_thresh_below_value.attr,
+	&dev_attr_prox0_raw_en.attr,
+	&dev_attr_prox0_raw.attr,
+	&dev_attr_prox0_sensor_range.attr,
+	&dev_attr_prox0_thresh_above_value.attr,
+	&dev_attr_prox0_reporting_mode.attr,
+	&dev_attr_prox0_reporting_mode_avail.attr,
+	&dev_attr_chip_id.attr,
+	&dev_attr_power_state.attr,
+	NULL
+};
+
+static struct attribute_group apds990x_attribute_group[] = {
+	{.attrs = sysfs_attrs_ctrl },
+};
+
+static int __devinit apds990x_probe(struct i2c_client *client,
+				const struct i2c_device_id *id)
+{
+	struct apds990x_chip *chip;
+	int err;
+
+	chip = kzalloc(sizeof *chip, GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, chip);
+	chip->client  = client;
+
+	init_waitqueue_head(&chip->wait);
+	mutex_init(&chip->mutex);
+	chip->pdata	= client->dev.platform_data;
+
+	if (chip->pdata == NULL) {
+		dev_err(&client->dev, "platform data is mandatory\n");
+		err = -EINVAL;
+		goto fail1;
+	}
+
+	if (chip->pdata->cf.ga == 0) {
+		/* set uncovered sensor default parameters */
+		chip->cf.ga = 1966; /* 0.48 * APDS_PARAM_SCALE */
+		chip->cf.cf1 = 4096; /* 1.00 * APDS_PARAM_SCALE */
+		chip->cf.irf1 = 9134; /* 2.23 * APDS_PARAM_SCALE */
+		chip->cf.cf2 = 2867; /* 0.70 * APDS_PARAM_SCALE */
+		chip->cf.irf2 = 5816; /* 1.42 * APDS_PARAM_SCALE */
+		chip->cf.df = 52;
+	} else {
+		chip->cf = chip->pdata->cf;
+	}
+
+	/* precalculate inverse chip factors for threshold control */
+	chip->rcf.afactor =
+		(chip->cf.irf1 - chip->cf.irf2) * APDS_PARAM_SCALE /
+		(chip->cf.cf1 - chip->cf.cf2);
+	chip->rcf.cf1 = APDS_PARAM_SCALE * APDS_PARAM_SCALE /
+		chip->cf.cf1;
+	chip->rcf.irf1 = chip->cf.irf1 * APDS_PARAM_SCALE /
+		chip->cf.cf1;
+	chip->rcf.cf2 = APDS_PARAM_SCALE * APDS_PARAM_SCALE /
+		chip->cf.cf2;
+	chip->rcf.irf2 = chip->cf.irf2 * APDS_PARAM_SCALE /
+		chip->cf.cf2;
+
+	/* Set something to start with */
+	chip->lux_thres_hi = APDS_LUX_DEF_THRES_HI;
+	chip->lux_thres_lo = APDS_LUX_DEF_THRES_LO;
+	chip->lux_calib = APDS_LUX_NEUTRAL_CALIB_VALUE;
+
+	chip->prox_thres = APDS_PROX_DEF_THRES;
+	chip->pdrive = chip->pdata->pdrive;
+	chip->pdiode = APDS_PDIODE_IR;
+	chip->pgain = APDS_PGAIN_1X;
+	chip->prox_calib = APDS_PROX_NEUTRAL_CALIB_VALUE;
+	chip->prox_persistence = APDS_DEFAULT_PROX_PERS;
+	chip->prox_continuous_mode = false;
+
+	chip->regs[0].supply = reg_vcc;
+	chip->regs[1].supply = reg_vled;
+
+	err = regulator_bulk_get(&client->dev,
+				 ARRAY_SIZE(chip->regs), chip->regs);
+	if (err < 0) {
+		dev_err(&client->dev, "Cannot get regulators\n");
+		goto fail1;
+	}
+
+	err = regulator_bulk_enable(ARRAY_SIZE(chip->regs), chip->regs);
+	if (err < 0) {
+		dev_err(&client->dev, "Cannot enable regulators\n");
+		goto fail2;
+	}
+
+	usleep_range(APDS_STARTUP_DELAY, 2 * APDS_STARTUP_DELAY);
+
+	err = apds990x_detect(chip);
+	if (err < 0) {
+		dev_err(&client->dev, "APDS990X not found\n");
+		goto fail3;
+	}
+
+	pm_runtime_set_active(&client->dev);
+
+	apds990x_configure(chip);
+	apds990x_set_arate(chip, APDS_LUX_DEFAULT_RATE);
+	apds990x_mode_on(chip);
+
+	pm_runtime_enable(&client->dev);
+
+	if (chip->pdata->setup_resources) {
+		err = chip->pdata->setup_resources();
+		if (err) {
+			err = -EINVAL;
+			goto fail3;
+		}
+	}
+
+	err = sysfs_create_group(&chip->client->dev.kobj,
+				apds990x_attribute_group);
+	if (err < 0) {
+		dev_err(&chip->client->dev, "Sysfs registration failed\n");
+		goto fail4;
+	}
+
+	err = request_threaded_irq(client->irq, NULL,
+				apds990x_irq,
+				IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW |
+				IRQF_ONESHOT,
+				"apds990x", chip);
+	if (err) {
+		dev_err(&client->dev, "could not get IRQ %d\n",
+			client->irq);
+		goto fail5;
+	}
+	return err;
+fail5:
+	sysfs_remove_group(&chip->client->dev.kobj,
+			&apds990x_attribute_group[0]);
+fail4:
+	if (chip->pdata && chip->pdata->release_resources)
+		chip->pdata->release_resources();
+fail3:
+	regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs);
+fail2:
+	regulator_bulk_free(ARRAY_SIZE(chip->regs), chip->regs);
+fail1:
+	kfree(chip);
+	return err;
+}
+
+static int __devexit apds990x_remove(struct i2c_client *client)
+{
+	struct apds990x_chip *chip = i2c_get_clientdata(client);
+
+	free_irq(client->irq, chip);
+	sysfs_remove_group(&chip->client->dev.kobj,
+			apds990x_attribute_group);
+
+	if (chip->pdata && chip->pdata->release_resources)
+		chip->pdata->release_resources();
+
+	if (!pm_runtime_suspended(&client->dev))
+		apds990x_chip_off(chip);
+
+	pm_runtime_disable(&client->dev);
+	pm_runtime_set_suspended(&client->dev);
+
+	regulator_bulk_free(ARRAY_SIZE(chip->regs), chip->regs);
+
+	kfree(chip);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int apds990x_suspend(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct apds990x_chip *chip = i2c_get_clientdata(client);
+
+	apds990x_chip_off(chip);
+	return 0;
+}
+
+static int apds990x_resume(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct apds990x_chip *chip = i2c_get_clientdata(client);
+
+	/*
+	 * If we were enabled at suspend time, it is expected
+	 * everything works nice and smoothly. Chip_on is enough
+	 */
+	apds990x_chip_on(chip);
+
+	return 0;
+}
+#else
+#define apds990x_suspend  NULL
+#define apds990x_resume	  NULL
+#define apds990x_shutdown NULL
+#endif
+
+#ifdef CONFIG_PM_RUNTIME
+static int apds990x_runtime_suspend(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct apds990x_chip *chip = i2c_get_clientdata(client);
+
+	apds990x_chip_off(chip);
+	return 0;
+}
+
+static int apds990x_runtime_resume(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct apds990x_chip *chip = i2c_get_clientdata(client);
+
+	apds990x_chip_on(chip);
+	return 0;
+}
+
+#endif
+
+static const struct i2c_device_id apds990x_id[] = {
+	{"apds990x", 0 },
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, apds990x_id);
+
+static const struct dev_pm_ops apds990x_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(apds990x_suspend, apds990x_resume)
+	SET_RUNTIME_PM_OPS(apds990x_runtime_suspend,
+			apds990x_runtime_resume,
+			NULL)
+};
+
+static struct i2c_driver apds990x_driver = {
+	.driver	 = {
+		.name	= "apds990x",
+		.owner	= THIS_MODULE,
+		.pm	= &apds990x_pm_ops,
+	},
+	.probe	  = apds990x_probe,
+	.remove	  = __devexit_p(apds990x_remove),
+	.id_table = apds990x_id,
+};
+
+static int __init apds990x_init(void)
+{
+	return i2c_add_driver(&apds990x_driver);
+}
+
+static void __exit apds990x_exit(void)
+{
+	i2c_del_driver(&apds990x_driver);
+}
+
+MODULE_DESCRIPTION("APDS990X combined ALS and proximity sensor");
+MODULE_AUTHOR("Samu Onkalo, Nokia Corporation");
+MODULE_LICENSE("GPL v2");
+
+module_init(apds990x_init);
+module_exit(apds990x_exit);
diff --git a/drivers/misc/bh1770glc.c b/drivers/misc/bh1770glc.c
new file mode 100644
index 0000000..cee632e
--- /dev/null
+++ b/drivers/misc/bh1770glc.c
@@ -0,0 +1,1413 @@
+/*
+ * This file is part of the ROHM BH1770GLC / OSRAM SFH7770 sensor driver.
+ * Chip is combined proximity and ambient light sensor.
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: Samu Onkalo <samu.p.onkalo@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/i2c/bh1770glc.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <linux/slab.h>
+
+#define BH1770_ALS_CONTROL	0x80 /* ALS operation mode control */
+#define BH1770_PS_CONTROL	0x81 /* PS operation mode control */
+#define BH1770_I_LED		0x82 /* active LED and LED1, LED2 current */
+#define BH1770_I_LED3		0x83 /* LED3 current setting */
+#define BH1770_ALS_PS_MEAS	0x84 /* Forced mode trigger */
+#define BH1770_PS_MEAS_RATE	0x85 /* PS meas. rate at stand alone mode */
+#define BH1770_ALS_MEAS_RATE	0x86 /* ALS meas. rate at stand alone mode */
+#define BH1770_PART_ID		0x8a /* Part number and revision ID */
+#define BH1770_MANUFACT_ID	0x8b /* Manufacturerer ID */
+#define BH1770_ALS_DATA_0	0x8c /* ALS DATA low byte */
+#define BH1770_ALS_DATA_1	0x8d /* ALS DATA high byte */
+#define BH1770_ALS_PS_STATUS	0x8e /* Measurement data and int status */
+#define BH1770_PS_DATA_LED1	0x8f /* PS data from LED1 */
+#define BH1770_PS_DATA_LED2	0x90 /* PS data from LED2 */
+#define BH1770_PS_DATA_LED3	0x91 /* PS data from LED3 */
+#define BH1770_INTERRUPT	0x92 /* Interrupt setting */
+#define BH1770_PS_TH_LED1	0x93 /* PS interrupt threshold for LED1 */
+#define BH1770_PS_TH_LED2	0x94 /* PS interrupt threshold for LED2 */
+#define BH1770_PS_TH_LED3	0x95 /* PS interrupt threshold for LED3 */
+#define BH1770_ALS_TH_UP_0	0x96 /* ALS upper threshold low byte */
+#define BH1770_ALS_TH_UP_1	0x97 /* ALS upper threshold high byte */
+#define BH1770_ALS_TH_LOW_0	0x98 /* ALS lower threshold low byte */
+#define BH1770_ALS_TH_LOW_1	0x99 /* ALS lower threshold high byte */
+
+/* MANUFACT_ID */
+#define BH1770_MANUFACT_ROHM	0x01
+#define BH1770_MANUFACT_OSRAM	0x03
+
+/* PART_ID */
+#define BH1770_PART		0x90
+#define BH1770_PART_MASK	0xf0
+#define BH1770_REV_MASK		0x0f
+#define BH1770_REV_SHIFT	0
+#define BH1770_REV_0		0x00
+#define BH1770_REV_1		0x01
+
+/* Operating modes for both */
+#define BH1770_STANDBY		0x00
+#define BH1770_FORCED		0x02
+#define BH1770_STANDALONE	0x03
+#define BH1770_SWRESET		(0x01 << 2)
+
+#define BH1770_PS_TRIG_MEAS	(1 << 0)
+#define BH1770_ALS_TRIG_MEAS	(1 << 1)
+
+/* Interrupt control */
+#define BH1770_INT_OUTPUT_MODE	(1 << 3) /* 0 = latched */
+#define BH1770_INT_POLARITY	(1 << 2) /* 1 = active high */
+#define BH1770_INT_ALS_ENA	(1 << 1)
+#define BH1770_INT_PS_ENA	(1 << 0)
+
+/* Interrupt status */
+#define BH1770_INT_LED1_DATA	(1 << 0)
+#define BH1770_INT_LED1_INT	(1 << 1)
+#define BH1770_INT_LED2_DATA	(1 << 2)
+#define BH1770_INT_LED2_INT	(1 << 3)
+#define BH1770_INT_LED3_DATA	(1 << 4)
+#define BH1770_INT_LED3_INT	(1 << 5)
+#define BH1770_INT_LEDS_INT	((1 << 1) | (1 << 3) | (1 << 5))
+#define BH1770_INT_ALS_DATA	(1 << 6)
+#define BH1770_INT_ALS_INT	(1 << 7)
+
+/* Led channels */
+#define BH1770_LED1		0x00
+
+#define BH1770_DISABLE		0
+#define BH1770_ENABLE		1
+#define BH1770_PROX_CHANNELS	1
+
+#define BH1770_LUX_DEFAULT_RATE	1 /* Index to lux rate table */
+#define BH1770_PROX_DEFAULT_RATE 1 /* Direct HW value =~ 50Hz */
+#define BH1770_PROX_DEF_RATE_THRESH 6 /* Direct HW value =~ 5 Hz */
+#define BH1770_STARTUP_DELAY	50
+#define BH1770_RESET_TIME	10
+#define BH1770_TIMEOUT		2100 /* Timeout in 2.1 seconds */
+
+#define BH1770_LUX_RANGE	65535
+#define BH1770_PROX_RANGE	255
+#define BH1770_COEF_SCALER	1024
+#define BH1770_CALIB_SCALER	8192
+#define BH1770_LUX_NEUTRAL_CALIB_VALUE (1 * BH1770_CALIB_SCALER)
+#define BH1770_LUX_DEF_THRES	1000
+#define BH1770_PROX_DEF_THRES	70
+#define BH1770_PROX_DEF_ABS_THRES   100
+#define BH1770_DEFAULT_PERSISTENCE  10
+#define BH1770_PROX_MAX_PERSISTENCE 50
+#define BH1770_LUX_GA_SCALE	16384
+#define BH1770_LUX_CF_SCALE	2048 /* CF ChipFactor */
+#define BH1770_NEUTRAL_CF	BH1770_LUX_CF_SCALE
+#define BH1770_LUX_CORR_SCALE	4096
+
+#define PROX_ABOVE_THRESHOLD	1
+#define PROX_BELOW_THRESHOLD	0
+
+#define PROX_IGNORE_LUX_LIMIT	500
+
+struct bh1770_chip {
+	struct bh1770_platform_data	*pdata;
+	char				chipname[10];
+	u8				revision;
+	struct i2c_client		*client;
+	struct regulator_bulk_data	regs[2];
+	struct mutex			mutex; /* avoid parallel access */
+	wait_queue_head_t		wait;
+
+	bool			int_mode_prox;
+	bool			int_mode_lux;
+	struct delayed_work	prox_work;
+	u32	lux_cf; /* Chip specific factor */
+	u32	lux_ga;
+	u32	lux_calib;
+	int	lux_rate_index;
+	u32	lux_corr;
+	u16	lux_data_raw;
+	u16	lux_threshold_hi;
+	u16	lux_threshold_lo;
+	u16	lux_thres_hi_onchip;
+	u16	lux_thres_lo_onchip;
+	bool	lux_wait_result;
+
+	int	prox_enable_count;
+	u16	prox_coef;
+	u16	prox_const;
+	int	prox_rate;
+	int	prox_rate_threshold;
+	u8	prox_persistence;
+	u8	prox_persistence_counter;
+	u8	prox_data;
+	u8	prox_threshold;
+	u8	prox_threshold_hw;
+	bool	prox_force_update;
+	u8	prox_abs_thres;
+	u8	prox_led;
+};
+
+static const char reg_vcc[] = "Vcc";
+static const char reg_vleds[] = "Vleds";
+
+/*
+ * Supported stand alone rates in ms from chip data sheet
+ * {10, 20, 30, 40, 70, 100, 200, 500, 1000, 2000};
+ */
+static const s16 prox_rates_hz[] = {100, 50, 33, 25, 14, 10, 5, 2};
+static const s16 prox_rates_ms[] = {10, 20, 30, 40, 70, 100, 200, 500};
+
+/* Supported IR-led currents in mA */
+static const u8 prox_curr_ma[] = {5, 10, 20, 50, 100, 150, 200};
+
+/*
+ * Supported stand alone rates in ms from chip data sheet
+ * {100, 200, 500, 1000, 2000};
+ */
+static const s16 lux_rates_hz[] = {10, 5, 2, 1, 0};
+
+/*
+ * interrupt control functions are called while keeping chip->mutex
+ * excluding module probe / remove
+ */
+static inline int bh1770_lux_interrupt_control(struct bh1770_chip *chip,
+					int lux)
+{
+	chip->int_mode_lux = lux;
+	/* Set interrupt modes, interrupt active low, latched */
+	return i2c_smbus_write_byte_data(chip->client,
+					BH1770_INTERRUPT,
+					(lux << 1) | chip->int_mode_prox);
+}
+
+static inline int bh1770_prox_interrupt_control(struct bh1770_chip *chip,
+					int ps)
+{
+	chip->int_mode_prox = ps;
+	return i2c_smbus_write_byte_data(chip->client,
+					BH1770_INTERRUPT,
+					(chip->int_mode_lux << 1) | (ps << 0));
+}
+
+/* chip->mutex is always kept here */
+static int bh1770_lux_rate(struct bh1770_chip *chip, int rate_index)
+{
+	/* sysfs may call this when the chip is powered off */
+	if (pm_runtime_suspended(&chip->client->dev))
+		return 0;
+
+	/* Proper proximity response needs fastest lux rate (100ms) */
+	if (chip->prox_enable_count)
+		rate_index = 0;
+
+	return i2c_smbus_write_byte_data(chip->client,
+					BH1770_ALS_MEAS_RATE,
+					rate_index);
+}
+
+static int bh1770_prox_rate(struct bh1770_chip *chip, int mode)
+{
+	int rate;
+
+	rate = (mode == PROX_ABOVE_THRESHOLD) ?
+		chip->prox_rate_threshold : chip->prox_rate;
+
+	return i2c_smbus_write_byte_data(chip->client,
+					BH1770_PS_MEAS_RATE,
+					rate);
+}
+
+/* InfraredLED is controlled by the chip during proximity scanning */
+static inline int bh1770_led_cfg(struct bh1770_chip *chip)
+{
+	/* LED cfg, current for leds 1 and 2 */
+	return i2c_smbus_write_byte_data(chip->client,
+					BH1770_I_LED,
+					(BH1770_LED1 << 6) |
+					(BH1770_LED_5mA << 3) |
+					chip->prox_led);
+}
+
+/*
+ * Following two functions converts raw ps values from HW to normalized
+ * values. Purpose is to compensate differences between different sensor
+ * versions and variants so that result means about the same between
+ * versions.
+ */
+static inline u8 bh1770_psraw_to_adjusted(struct bh1770_chip *chip, u8 psraw)
+{
+	u16 adjusted;
+	adjusted = (u16)(((u32)(psraw + chip->prox_const) * chip->prox_coef) /
+		BH1770_COEF_SCALER);
+	if (adjusted > BH1770_PROX_RANGE)
+		adjusted = BH1770_PROX_RANGE;
+	return adjusted;
+}
+
+static inline u8 bh1770_psadjusted_to_raw(struct bh1770_chip *chip, u8 ps)
+{
+	u16 raw;
+
+	raw = (((u32)ps * BH1770_COEF_SCALER) / chip->prox_coef);
+	if (raw > chip->prox_const)
+		raw = raw - chip->prox_const;
+	else
+		raw = 0;
+	return raw;
+}
+
+/*
+ * Following two functions converts raw lux values from HW to normalized
+ * values. Purpose is to compensate differences between different sensor
+ * versions and variants so that result means about the same between
+ * versions. Chip->mutex is kept when this is called.
+ */
+static int bh1770_prox_set_threshold(struct bh1770_chip *chip)
+{
+	u8 tmp = 0;
+
+	/* sysfs may call this when the chip is powered off */
+	if (pm_runtime_suspended(&chip->client->dev))
+		return 0;
+
+	tmp = bh1770_psadjusted_to_raw(chip, chip->prox_threshold);
+	chip->prox_threshold_hw = tmp;
+
+	return	i2c_smbus_write_byte_data(chip->client, BH1770_PS_TH_LED1,
+					tmp);
+}
+
+static inline u16 bh1770_lux_raw_to_adjusted(struct bh1770_chip *chip, u16 raw)
+{
+	u32 lux;
+	lux = ((u32)raw * chip->lux_corr) / BH1770_LUX_CORR_SCALE;
+	return min(lux, (u32)BH1770_LUX_RANGE);
+}
+
+static inline u16 bh1770_lux_adjusted_to_raw(struct bh1770_chip *chip,
+					u16 adjusted)
+{
+	return (u32)adjusted * BH1770_LUX_CORR_SCALE / chip->lux_corr;
+}
+
+/* chip->mutex is kept when this is called */
+static int bh1770_lux_update_thresholds(struct bh1770_chip *chip,
+					u16 threshold_hi, u16 threshold_lo)
+{
+	u8 data[4];
+	int ret;
+
+	/* sysfs may call this when the chip is powered off */
+	if (pm_runtime_suspended(&chip->client->dev))
+		return 0;
+
+	/*
+	 * Compensate threshold values with the correction factors if not
+	 * set to minimum or maximum.
+	 * Min & max values disables interrupts.
+	 */
+	if (threshold_hi != BH1770_LUX_RANGE && threshold_hi != 0)
+		threshold_hi = bh1770_lux_adjusted_to_raw(chip, threshold_hi);
+
+	if (threshold_lo != BH1770_LUX_RANGE && threshold_lo != 0)
+		threshold_lo = bh1770_lux_adjusted_to_raw(chip, threshold_lo);
+
+	if (chip->lux_thres_hi_onchip == threshold_hi &&
+	    chip->lux_thres_lo_onchip == threshold_lo)
+		return 0;
+
+	chip->lux_thres_hi_onchip = threshold_hi;
+	chip->lux_thres_lo_onchip = threshold_lo;
+
+	data[0] = threshold_hi;
+	data[1] = threshold_hi >> 8;
+	data[2] = threshold_lo;
+	data[3] = threshold_lo >> 8;
+
+	ret = i2c_smbus_write_i2c_block_data(chip->client,
+					BH1770_ALS_TH_UP_0,
+					ARRAY_SIZE(data),
+					data);
+	return ret;
+}
+
+static int bh1770_lux_get_result(struct bh1770_chip *chip)
+{
+	u16 data;
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(chip->client, BH1770_ALS_DATA_0);
+	if (ret < 0)
+		return ret;
+
+	data = ret & 0xff;
+	ret = i2c_smbus_read_byte_data(chip->client, BH1770_ALS_DATA_1);
+	if (ret < 0)
+		return ret;
+
+	chip->lux_data_raw = data | ((ret & 0xff) << 8);
+
+	return 0;
+}
+
+/* Calculate correction value which contains chip and device specific parts */
+static u32 bh1770_get_corr_value(struct bh1770_chip *chip)
+{
+	u32 tmp;
+	/* Impact of glass attenuation correction */
+	tmp = (BH1770_LUX_CORR_SCALE * chip->lux_ga) / BH1770_LUX_GA_SCALE;
+	/* Impact of chip factor correction */
+	tmp = (tmp * chip->lux_cf) / BH1770_LUX_CF_SCALE;
+	/* Impact of Device specific calibration correction */
+	tmp = (tmp * chip->lux_calib) / BH1770_CALIB_SCALER;
+	return tmp;
+}
+
+static int bh1770_lux_read_result(struct bh1770_chip *chip)
+{
+	bh1770_lux_get_result(chip);
+	return bh1770_lux_raw_to_adjusted(chip, chip->lux_data_raw);
+}
+
+/*
+ * Chip on / off functions are called while keeping mutex except probe
+ * or remove phase
+ */
+static int bh1770_chip_on(struct bh1770_chip *chip)
+{
+	int ret = regulator_bulk_enable(ARRAY_SIZE(chip->regs),
+					chip->regs);
+	if (ret < 0)
+		return ret;
+
+	usleep_range(BH1770_STARTUP_DELAY, BH1770_STARTUP_DELAY * 2);
+
+	/* Reset the chip */
+	i2c_smbus_write_byte_data(chip->client, BH1770_ALS_CONTROL,
+				BH1770_SWRESET);
+	usleep_range(BH1770_RESET_TIME, BH1770_RESET_TIME * 2);
+
+	/*
+	 * ALS is started always since proximity needs als results
+	 * for realibility estimation.
+	 * Let's assume dark until the first ALS measurement is ready.
+	 */
+	chip->lux_data_raw = 0;
+	chip->prox_data = 0;
+	ret = i2c_smbus_write_byte_data(chip->client,
+					BH1770_ALS_CONTROL, BH1770_STANDALONE);
+
+	/* Assume reset defaults */
+	chip->lux_thres_hi_onchip = BH1770_LUX_RANGE;
+	chip->lux_thres_lo_onchip = 0;
+
+	return ret;
+}
+
+static void bh1770_chip_off(struct bh1770_chip *chip)
+{
+	i2c_smbus_write_byte_data(chip->client,
+					BH1770_INTERRUPT, BH1770_DISABLE);
+	i2c_smbus_write_byte_data(chip->client,
+				BH1770_ALS_CONTROL, BH1770_STANDBY);
+	i2c_smbus_write_byte_data(chip->client,
+				BH1770_PS_CONTROL, BH1770_STANDBY);
+	regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs);
+}
+
+/* chip->mutex is kept when this is called */
+static int bh1770_prox_mode_control(struct bh1770_chip *chip)
+{
+	if (chip->prox_enable_count) {
+		chip->prox_force_update = true; /* Force immediate update */
+
+		bh1770_lux_rate(chip, chip->lux_rate_index);
+		bh1770_prox_set_threshold(chip);
+		bh1770_led_cfg(chip);
+		bh1770_prox_rate(chip, PROX_BELOW_THRESHOLD);
+		bh1770_prox_interrupt_control(chip, BH1770_ENABLE);
+		i2c_smbus_write_byte_data(chip->client,
+					BH1770_PS_CONTROL, BH1770_STANDALONE);
+	} else {
+		chip->prox_data = 0;
+		bh1770_lux_rate(chip, chip->lux_rate_index);
+		bh1770_prox_interrupt_control(chip, BH1770_DISABLE);
+		i2c_smbus_write_byte_data(chip->client,
+					BH1770_PS_CONTROL, BH1770_STANDBY);
+	}
+	return 0;
+}
+
+/* chip->mutex is kept when this is called */
+static int bh1770_prox_read_result(struct bh1770_chip *chip)
+{
+	int ret;
+	bool above;
+	u8 mode;
+
+	ret = i2c_smbus_read_byte_data(chip->client, BH1770_PS_DATA_LED1);
+	if (ret < 0)
+		goto out;
+
+	if (ret > chip->prox_threshold_hw)
+		above = true;
+	else
+		above = false;
+
+	/*
+	 * when ALS levels goes above limit, proximity result may be
+	 * false proximity. Thus ignore the result. With real proximity
+	 * there is a shadow causing low als levels.
+	 */
+	if (chip->lux_data_raw > PROX_IGNORE_LUX_LIMIT)
+		ret = 0;
+
+	chip->prox_data = bh1770_psraw_to_adjusted(chip, ret);
+
+	/* Strong proximity level or force mode requires immediate response */
+	if (chip->prox_data >= chip->prox_abs_thres ||
+	    chip->prox_force_update)
+		chip->prox_persistence_counter = chip->prox_persistence;
+
+	chip->prox_force_update = false;
+
+	/* Persistence filttering to reduce false proximity events */
+	if (likely(above)) {
+		if (chip->prox_persistence_counter < chip->prox_persistence) {
+			chip->prox_persistence_counter++;
+			ret = -ENODATA;
+		} else {
+			mode = PROX_ABOVE_THRESHOLD;
+			ret = 0;
+		}
+	} else {
+		chip->prox_persistence_counter = 0;
+		mode = PROX_BELOW_THRESHOLD;
+		chip->prox_data = 0;
+		ret = 0;
+	}
+
+	/* Set proximity detection rate based on above or below value */
+	if (ret == 0) {
+		bh1770_prox_rate(chip, mode);
+		sysfs_notify(&chip->client->dev.kobj, NULL, "prox0_raw");
+	}
+out:
+	return ret;
+}
+
+static int bh1770_detect(struct bh1770_chip *chip)
+{
+	struct i2c_client *client = chip->client;
+	s32 ret;
+	u8 manu, part;
+
+	ret = i2c_smbus_read_byte_data(client, BH1770_MANUFACT_ID);
+	if (ret < 0)
+		goto error;
+	manu = (u8)ret;
+
+	ret = i2c_smbus_read_byte_data(client, BH1770_PART_ID);
+	if (ret < 0)
+		goto error;
+	part = (u8)ret;
+
+	chip->revision = (part & BH1770_REV_MASK) >> BH1770_REV_SHIFT;
+	chip->prox_coef = BH1770_COEF_SCALER;
+	chip->prox_const = 0;
+	chip->lux_cf = BH1770_NEUTRAL_CF;
+
+	if ((manu == BH1770_MANUFACT_ROHM) &&
+	    ((part & BH1770_PART_MASK) == BH1770_PART)) {
+		snprintf(chip->chipname, sizeof(chip->chipname), "BH1770GLC");
+		return 0;
+	}
+
+	if ((manu == BH1770_MANUFACT_OSRAM) &&
+	    ((part & BH1770_PART_MASK) == BH1770_PART)) {
+		snprintf(chip->chipname, sizeof(chip->chipname), "SFH7770");
+		/* Values selected by comparing different versions */
+		chip->prox_coef = 819; /* 0.8 * BH1770_COEF_SCALER */
+		chip->prox_const = 40;
+		return 0;
+	}
+
+	ret = -ENODEV;
+error:
+	dev_dbg(&client->dev, "BH1770 or SFH7770 not found\n");
+
+	return ret;
+}
+
+/*
+ * This work is re-scheduled at every proximity interrupt.
+ * If this work is running, it means that there hasn't been any
+ * proximity interrupt in time. Situation is handled as no-proximity.
+ * It would be nice to have low-threshold interrupt or interrupt
+ * when measurement and hi-threshold are both 0. But neither of those exists.
+ * This is a workaroud for missing HW feature.
+ */
+
+static void bh1770_prox_work(struct work_struct *work)
+{
+	struct bh1770_chip *chip =
+		container_of(work, struct bh1770_chip, prox_work.work);
+
+	mutex_lock(&chip->mutex);
+	bh1770_prox_read_result(chip);
+	mutex_unlock(&chip->mutex);
+}
+
+/* This is threaded irq handler */
+static irqreturn_t bh1770_irq(int irq, void *data)
+{
+	struct bh1770_chip *chip = data;
+	int status;
+	int rate = 0;
+
+	mutex_lock(&chip->mutex);
+	status = i2c_smbus_read_byte_data(chip->client, BH1770_ALS_PS_STATUS);
+
+	/* Acknowledge interrupt by reading this register */
+	i2c_smbus_read_byte_data(chip->client, BH1770_INTERRUPT);
+
+	/*
+	 * Check if there is fresh data available for als.
+	 * If this is the very first data, update thresholds after that.
+	 */
+	if (status & BH1770_INT_ALS_DATA) {
+		bh1770_lux_get_result(chip);
+		if (unlikely(chip->lux_wait_result)) {
+			chip->lux_wait_result = false;
+			wake_up(&chip->wait);
+			bh1770_lux_update_thresholds(chip,
+						chip->lux_threshold_hi,
+						chip->lux_threshold_lo);
+		}
+	}
+
+	/* Disable interrupt logic to guarantee acknowledgement */
+	i2c_smbus_write_byte_data(chip->client, BH1770_INTERRUPT,
+				  (0 << 1) | (0 << 0));
+
+	if ((status & BH1770_INT_ALS_INT))
+		sysfs_notify(&chip->client->dev.kobj, NULL, "lux0_input");
+
+	if (chip->int_mode_prox && (status & BH1770_INT_LEDS_INT)) {
+		rate = prox_rates_ms[chip->prox_rate_threshold];
+		bh1770_prox_read_result(chip);
+	}
+
+	/* Re-enable interrupt logic */
+	i2c_smbus_write_byte_data(chip->client, BH1770_INTERRUPT,
+				  (chip->int_mode_lux << 1) |
+				  (chip->int_mode_prox << 0));
+	mutex_unlock(&chip->mutex);
+
+	/*
+	 * Can't cancel work while keeping mutex since the work uses the
+	 * same mutex.
+	 */
+	if (rate) {
+		/*
+		 * Simulate missing no-proximity interrupt 50ms after the
+		 * next expected interrupt time.
+		 */
+		cancel_delayed_work_sync(&chip->prox_work);
+		schedule_delayed_work(&chip->prox_work,
+				msecs_to_jiffies(rate + 50));
+	}
+	return IRQ_HANDLED;
+}
+
+static ssize_t bh1770_power_state_store(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buf, size_t count)
+{
+	struct bh1770_chip *chip =  dev_get_drvdata(dev);
+	unsigned long value;
+	size_t ret;
+
+	if (strict_strtoul(buf, 0, &value))
+		return -EINVAL;
+
+	mutex_lock(&chip->mutex);
+	if (value) {
+		pm_runtime_get_sync(dev);
+
+		ret = bh1770_lux_rate(chip, chip->lux_rate_index);
+		ret |= bh1770_lux_interrupt_control(chip, BH1770_ENABLE);
+
+		if (ret < 0) {
+			pm_runtime_put(dev);
+			goto leave;
+		}
+
+		/* This causes interrupt after the next measurement cycle */
+		bh1770_lux_update_thresholds(chip, BH1770_LUX_DEF_THRES,
+					BH1770_LUX_DEF_THRES);
+		/* Inform that we are waiting for a result from ALS */
+		chip->lux_wait_result = true;
+		bh1770_prox_mode_control(chip);
+	} else if (!pm_runtime_suspended(dev)) {
+		pm_runtime_put(dev);
+	}
+	ret = count;
+leave:
+	mutex_unlock(&chip->mutex);
+	return ret;
+}
+
+static ssize_t bh1770_power_state_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%d\n", !pm_runtime_suspended(dev));
+}
+
+static ssize_t bh1770_lux_result_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct bh1770_chip *chip =  dev_get_drvdata(dev);
+	ssize_t ret;
+	long timeout;
+
+	if (pm_runtime_suspended(dev))
+		return -EIO; /* Chip is not enabled at all */
+
+	timeout = wait_event_interruptible_timeout(chip->wait,
+					!chip->lux_wait_result,
+					msecs_to_jiffies(BH1770_TIMEOUT));
+	if (!timeout)
+		return -EIO;
+
+	mutex_lock(&chip->mutex);
+	ret = sprintf(buf, "%d\n", bh1770_lux_read_result(chip));
+	mutex_unlock(&chip->mutex);
+
+	return ret;
+}
+
+static ssize_t bh1770_lux_range_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%d\n", BH1770_LUX_RANGE);
+}
+
+static ssize_t bh1770_prox_enable_store(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buf, size_t count)
+{
+	struct bh1770_chip *chip =  dev_get_drvdata(dev);
+	unsigned long value;
+
+	if (strict_strtoul(buf, 0, &value))
+		return -EINVAL;
+
+	mutex_lock(&chip->mutex);
+	/* Assume no proximity. Sensor will tell real state soon */
+	if (!chip->prox_enable_count)
+		chip->prox_data = 0;
+
+	if (value)
+		chip->prox_enable_count++;
+	else if (chip->prox_enable_count > 0)
+		chip->prox_enable_count--;
+	else
+		goto leave;
+
+	/* Run control only when chip is powered on */
+	if (!pm_runtime_suspended(dev))
+		bh1770_prox_mode_control(chip);
+leave:
+	mutex_unlock(&chip->mutex);
+	return count;
+}
+
+static ssize_t bh1770_prox_enable_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct bh1770_chip *chip =  dev_get_drvdata(dev);
+	ssize_t len;
+
+	mutex_lock(&chip->mutex);
+	len = sprintf(buf, "%d\n", chip->prox_enable_count);
+	mutex_unlock(&chip->mutex);
+	return len;
+}
+
+static ssize_t bh1770_prox_result_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct bh1770_chip *chip =  dev_get_drvdata(dev);
+	ssize_t ret;
+
+	mutex_lock(&chip->mutex);
+	if (chip->prox_enable_count && !pm_runtime_suspended(dev))
+		ret = sprintf(buf, "%d\n", chip->prox_data);
+	else
+		ret = -EIO;
+	mutex_unlock(&chip->mutex);
+	return ret;
+}
+
+static ssize_t bh1770_prox_range_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%d\n", BH1770_PROX_RANGE);
+}
+
+static ssize_t bh1770_get_prox_rate_avail(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	int i;
+	int pos = 0;
+	for (i = 0; i < ARRAY_SIZE(prox_rates_hz); i++)
+		pos += sprintf(buf + pos, "%d ", prox_rates_hz[i]);
+	sprintf(buf + pos - 1, "\n");
+	return pos;
+}
+
+static ssize_t bh1770_get_prox_rate_above(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct bh1770_chip *chip =  dev_get_drvdata(dev);
+	return sprintf(buf, "%d\n", prox_rates_hz[chip->prox_rate_threshold]);
+}
+
+static ssize_t bh1770_get_prox_rate_below(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct bh1770_chip *chip =  dev_get_drvdata(dev);
+	return sprintf(buf, "%d\n", prox_rates_hz[chip->prox_rate]);
+}
+
+static int bh1770_prox_rate_validate(int rate)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(prox_rates_hz) - 1; i++)
+		if (rate >= prox_rates_hz[i])
+			break;
+	return i;
+}
+
+static ssize_t bh1770_set_prox_rate_above(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
+{
+	struct bh1770_chip *chip =  dev_get_drvdata(dev);
+	unsigned long value;
+
+	if (strict_strtoul(buf, 0, &value))
+		return -EINVAL;
+
+	mutex_lock(&chip->mutex);
+	chip->prox_rate_threshold = bh1770_prox_rate_validate(value);
+	mutex_unlock(&chip->mutex);
+	return count;
+}
+
+static ssize_t bh1770_set_prox_rate_below(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
+{
+	struct bh1770_chip *chip =  dev_get_drvdata(dev);
+	unsigned long value;
+
+	if (strict_strtoul(buf, 0, &value))
+		return -EINVAL;
+
+	mutex_lock(&chip->mutex);
+	chip->prox_rate = bh1770_prox_rate_validate(value);
+	mutex_unlock(&chip->mutex);
+	return count;
+}
+
+static ssize_t bh1770_get_prox_thres(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct bh1770_chip *chip =  dev_get_drvdata(dev);
+	return sprintf(buf, "%d\n", chip->prox_threshold);
+}
+
+static ssize_t bh1770_set_prox_thres(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buf, size_t count)
+{
+	struct bh1770_chip *chip =  dev_get_drvdata(dev);
+	unsigned long value;
+	int ret;
+
+	if (strict_strtoul(buf, 0, &value))
+		return -EINVAL;
+	if (value > BH1770_PROX_RANGE)
+		return -EINVAL;
+
+	mutex_lock(&chip->mutex);
+	chip->prox_threshold = value;
+	ret = bh1770_prox_set_threshold(chip);
+	mutex_unlock(&chip->mutex);
+	if (ret < 0)
+		return ret;
+	return count;
+}
+
+static ssize_t bh1770_prox_persistence_show(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	struct bh1770_chip *chip = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%u\n", chip->prox_persistence);
+}
+
+static ssize_t bh1770_prox_persistence_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t len)
+{
+	struct bh1770_chip *chip = dev_get_drvdata(dev);
+	unsigned long value;
+
+	if (strict_strtoul(buf, 0, &value))
+		return -EINVAL;
+
+	if (value > BH1770_PROX_MAX_PERSISTENCE)
+		return -EINVAL;
+
+	chip->prox_persistence = value;
+
+	return len;
+}
+
+static ssize_t bh1770_prox_abs_thres_show(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	struct bh1770_chip *chip = dev_get_drvdata(dev);
+	return sprintf(buf, "%u\n", chip->prox_abs_thres);
+}
+
+static ssize_t bh1770_prox_abs_thres_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t len)
+{
+	struct bh1770_chip *chip = dev_get_drvdata(dev);
+	unsigned long value;
+
+	if (strict_strtoul(buf, 0, &value))
+		return -EINVAL;
+
+	if (value > BH1770_PROX_RANGE)
+		return -EINVAL;
+
+	chip->prox_abs_thres = value;
+
+	return len;
+}
+
+static ssize_t bh1770_chip_id_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct bh1770_chip *chip =  dev_get_drvdata(dev);
+	return sprintf(buf, "%s rev %d\n", chip->chipname, chip->revision);
+}
+
+static ssize_t bh1770_lux_calib_default_show(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%u\n", BH1770_CALIB_SCALER);
+}
+
+static ssize_t bh1770_lux_calib_show(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	struct bh1770_chip *chip = dev_get_drvdata(dev);
+	ssize_t len;
+
+	mutex_lock(&chip->mutex);
+	len = sprintf(buf, "%u\n", chip->lux_calib);
+	mutex_unlock(&chip->mutex);
+	return len;
+}
+
+static ssize_t bh1770_lux_calib_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t len)
+{
+	struct bh1770_chip *chip = dev_get_drvdata(dev);
+	unsigned long value;
+	u32 old_calib;
+	u32 new_corr;
+
+	if (strict_strtoul(buf, 0, &value))
+		return -EINVAL;
+
+	mutex_lock(&chip->mutex);
+	old_calib = chip->lux_calib;
+	chip->lux_calib = value;
+	new_corr = bh1770_get_corr_value(chip);
+	if (new_corr == 0) {
+		chip->lux_calib = old_calib;
+		mutex_unlock(&chip->mutex);
+		return -EINVAL;
+	}
+	chip->lux_corr = new_corr;
+	/* Refresh thresholds on HW after changing correction value */
+	bh1770_lux_update_thresholds(chip, chip->lux_threshold_hi,
+				chip->lux_threshold_lo);
+
+	mutex_unlock(&chip->mutex);
+
+	return len;
+}
+
+static ssize_t bh1770_get_lux_rate_avail(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	int i;
+	int pos = 0;
+	for (i = 0; i < ARRAY_SIZE(lux_rates_hz); i++)
+		pos += sprintf(buf + pos, "%d ", lux_rates_hz[i]);
+	sprintf(buf + pos - 1, "\n");
+	return pos;
+}
+
+static ssize_t bh1770_get_lux_rate(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct bh1770_chip *chip =  dev_get_drvdata(dev);
+	return sprintf(buf, "%d\n", lux_rates_hz[chip->lux_rate_index]);
+}
+
+static ssize_t bh1770_set_lux_rate(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buf, size_t count)
+{
+	struct bh1770_chip *chip =  dev_get_drvdata(dev);
+	unsigned long rate_hz;
+	int ret, i;
+
+	if (strict_strtoul(buf, 0, &rate_hz))
+		return -EINVAL;
+
+	for (i = 0; i < ARRAY_SIZE(lux_rates_hz) - 1; i++)
+		if (rate_hz >= lux_rates_hz[i])
+			break;
+
+	mutex_lock(&chip->mutex);
+	chip->lux_rate_index = i;
+	ret = bh1770_lux_rate(chip, i);
+	mutex_unlock(&chip->mutex);
+
+	if (ret < 0)
+		return ret;
+
+	return count;
+}
+
+static ssize_t bh1770_get_lux_thresh_above(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct bh1770_chip *chip =  dev_get_drvdata(dev);
+	return sprintf(buf, "%d\n", chip->lux_threshold_hi);
+}
+
+static ssize_t bh1770_get_lux_thresh_below(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct bh1770_chip *chip =  dev_get_drvdata(dev);
+	return sprintf(buf, "%d\n", chip->lux_threshold_lo);
+}
+
+static ssize_t bh1770_set_lux_thresh(struct bh1770_chip *chip, u16 *target,
+				const char *buf)
+{
+	int ret = 0;
+	unsigned long thresh;
+
+	if (strict_strtoul(buf, 0, &thresh))
+		return -EINVAL;
+
+	if (thresh > BH1770_LUX_RANGE)
+		return -EINVAL;
+
+	mutex_lock(&chip->mutex);
+	*target = thresh;
+	/*
+	 * Don't update values in HW if we are still waiting for
+	 * first interrupt to come after device handle open call.
+	 */
+	if (!chip->lux_wait_result)
+		ret = bh1770_lux_update_thresholds(chip,
+						chip->lux_threshold_hi,
+						chip->lux_threshold_lo);
+	mutex_unlock(&chip->mutex);
+	return ret;
+
+}
+
+static ssize_t bh1770_set_lux_thresh_above(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t len)
+{
+	struct bh1770_chip *chip =  dev_get_drvdata(dev);
+	int ret = bh1770_set_lux_thresh(chip, &chip->lux_threshold_hi, buf);
+	if (ret < 0)
+		return ret;
+	return len;
+}
+
+static ssize_t bh1770_set_lux_thresh_below(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t len)
+{
+	struct bh1770_chip *chip =  dev_get_drvdata(dev);
+	int ret = bh1770_set_lux_thresh(chip, &chip->lux_threshold_lo, buf);
+	if (ret < 0)
+		return ret;
+	return len;
+}
+
+static DEVICE_ATTR(prox0_raw_en, S_IRUGO | S_IWUSR, bh1770_prox_enable_show,
+						bh1770_prox_enable_store);
+static DEVICE_ATTR(prox0_thresh_above1_value, S_IRUGO | S_IWUSR,
+						bh1770_prox_abs_thres_show,
+						bh1770_prox_abs_thres_store);
+static DEVICE_ATTR(prox0_thresh_above0_value, S_IRUGO | S_IWUSR,
+						bh1770_get_prox_thres,
+						bh1770_set_prox_thres);
+static DEVICE_ATTR(prox0_raw, S_IRUGO, bh1770_prox_result_show, NULL);
+static DEVICE_ATTR(prox0_sensor_range, S_IRUGO, bh1770_prox_range_show, NULL);
+static DEVICE_ATTR(prox0_thresh_above_count, S_IRUGO | S_IWUSR,
+						bh1770_prox_persistence_show,
+						bh1770_prox_persistence_store);
+static DEVICE_ATTR(prox0_rate_above, S_IRUGO | S_IWUSR,
+						bh1770_get_prox_rate_above,
+						bh1770_set_prox_rate_above);
+static DEVICE_ATTR(prox0_rate_below, S_IRUGO | S_IWUSR,
+						bh1770_get_prox_rate_below,
+						bh1770_set_prox_rate_below);
+static DEVICE_ATTR(prox0_rate_avail, S_IRUGO, bh1770_get_prox_rate_avail, NULL);
+
+static DEVICE_ATTR(lux0_calibscale, S_IRUGO | S_IWUSR, bh1770_lux_calib_show,
+						bh1770_lux_calib_store);
+static DEVICE_ATTR(lux0_calibscale_default, S_IRUGO,
+						bh1770_lux_calib_default_show,
+						NULL);
+static DEVICE_ATTR(lux0_input, S_IRUGO, bh1770_lux_result_show, NULL);
+static DEVICE_ATTR(lux0_sensor_range, S_IRUGO, bh1770_lux_range_show, NULL);
+static DEVICE_ATTR(lux0_rate, S_IRUGO | S_IWUSR, bh1770_get_lux_rate,
+						bh1770_set_lux_rate);
+static DEVICE_ATTR(lux0_rate_avail, S_IRUGO, bh1770_get_lux_rate_avail, NULL);
+static DEVICE_ATTR(lux0_thresh_above_value, S_IRUGO | S_IWUSR,
+						bh1770_get_lux_thresh_above,
+						bh1770_set_lux_thresh_above);
+static DEVICE_ATTR(lux0_thresh_below_value, S_IRUGO | S_IWUSR,
+						bh1770_get_lux_thresh_below,
+						bh1770_set_lux_thresh_below);
+static DEVICE_ATTR(chip_id, S_IRUGO, bh1770_chip_id_show, NULL);
+static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR, bh1770_power_state_show,
+						 bh1770_power_state_store);
+
+
+static struct attribute *sysfs_attrs[] = {
+	&dev_attr_lux0_calibscale.attr,
+	&dev_attr_lux0_calibscale_default.attr,
+	&dev_attr_lux0_input.attr,
+	&dev_attr_lux0_sensor_range.attr,
+	&dev_attr_lux0_rate.attr,
+	&dev_attr_lux0_rate_avail.attr,
+	&dev_attr_lux0_thresh_above_value.attr,
+	&dev_attr_lux0_thresh_below_value.attr,
+	&dev_attr_prox0_raw.attr,
+	&dev_attr_prox0_sensor_range.attr,
+	&dev_attr_prox0_raw_en.attr,
+	&dev_attr_prox0_thresh_above_count.attr,
+	&dev_attr_prox0_rate_above.attr,
+	&dev_attr_prox0_rate_below.attr,
+	&dev_attr_prox0_rate_avail.attr,
+	&dev_attr_prox0_thresh_above0_value.attr,
+	&dev_attr_prox0_thresh_above1_value.attr,
+	&dev_attr_chip_id.attr,
+	&dev_attr_power_state.attr,
+	NULL
+};
+
+static struct attribute_group bh1770_attribute_group = {
+	.attrs = sysfs_attrs
+};
+
+static int __devinit bh1770_probe(struct i2c_client *client,
+				const struct i2c_device_id *id)
+{
+	struct bh1770_chip *chip;
+	int err;
+
+	chip = kzalloc(sizeof *chip, GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, chip);
+	chip->client  = client;
+
+	mutex_init(&chip->mutex);
+	init_waitqueue_head(&chip->wait);
+	INIT_DELAYED_WORK(&chip->prox_work, bh1770_prox_work);
+
+	if (client->dev.platform_data == NULL) {
+		dev_err(&client->dev, "platform data is mandatory\n");
+		err = -EINVAL;
+		goto fail1;
+	}
+
+	chip->pdata		= client->dev.platform_data;
+	chip->lux_calib		= BH1770_LUX_NEUTRAL_CALIB_VALUE;
+	chip->lux_rate_index	= BH1770_LUX_DEFAULT_RATE;
+	chip->lux_threshold_lo	= BH1770_LUX_DEF_THRES;
+	chip->lux_threshold_hi	= BH1770_LUX_DEF_THRES;
+
+	if (chip->pdata->glass_attenuation == 0)
+		chip->lux_ga = BH1770_NEUTRAL_GA;
+	else
+		chip->lux_ga = chip->pdata->glass_attenuation;
+
+	chip->prox_threshold	= BH1770_PROX_DEF_THRES;
+	chip->prox_led		= chip->pdata->led_def_curr;
+	chip->prox_abs_thres	= BH1770_PROX_DEF_ABS_THRES;
+	chip->prox_persistence	= BH1770_DEFAULT_PERSISTENCE;
+	chip->prox_rate_threshold = BH1770_PROX_DEF_RATE_THRESH;
+	chip->prox_rate		= BH1770_PROX_DEFAULT_RATE;
+	chip->prox_data		= 0;
+
+	chip->regs[0].supply = reg_vcc;
+	chip->regs[1].supply = reg_vleds;
+
+	err = regulator_bulk_get(&client->dev,
+				 ARRAY_SIZE(chip->regs), chip->regs);
+	if (err < 0) {
+		dev_err(&client->dev, "Cannot get regulators\n");
+		goto fail1;
+	}
+
+	err = regulator_bulk_enable(ARRAY_SIZE(chip->regs),
+				chip->regs);
+	if (err < 0) {
+		dev_err(&client->dev, "Cannot enable regulators\n");
+		goto fail2;
+	}
+
+	usleep_range(BH1770_STARTUP_DELAY, BH1770_STARTUP_DELAY * 2);
+	err = bh1770_detect(chip);
+	if (err < 0)
+		goto fail3;
+
+	/* Start chip */
+	bh1770_chip_on(chip);
+	pm_runtime_set_active(&client->dev);
+	pm_runtime_enable(&client->dev);
+
+	chip->lux_corr = bh1770_get_corr_value(chip);
+	if (chip->lux_corr == 0) {
+		dev_err(&client->dev, "Improper correction values\n");
+		err = -EINVAL;
+		goto fail3;
+	}
+
+	if (chip->pdata->setup_resources) {
+		err = chip->pdata->setup_resources();
+		if (err) {
+			err = -EINVAL;
+			goto fail3;
+		}
+	}
+
+	err = sysfs_create_group(&chip->client->dev.kobj,
+				&bh1770_attribute_group);
+	if (err < 0) {
+		dev_err(&chip->client->dev, "Sysfs registration failed\n");
+		goto fail4;
+	}
+
+	/*
+	 * Chip needs level triggered interrupt to work. However,
+	 * level triggering doesn't work always correctly with power
+	 * management. Select both
+	 */
+	err = request_threaded_irq(client->irq, NULL,
+				bh1770_irq,
+				IRQF_TRIGGER_FALLING | IRQF_ONESHOT |
+				IRQF_TRIGGER_LOW,
+				"bh1770", chip);
+	if (err) {
+		dev_err(&client->dev, "could not get IRQ %d\n",
+			client->irq);
+		goto fail5;
+	}
+	regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs);
+	return err;
+fail5:
+	sysfs_remove_group(&chip->client->dev.kobj,
+			&bh1770_attribute_group);
+fail4:
+	if (chip->pdata->release_resources)
+		chip->pdata->release_resources();
+fail3:
+	regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs);
+fail2:
+	regulator_bulk_free(ARRAY_SIZE(chip->regs), chip->regs);
+fail1:
+	kfree(chip);
+	return err;
+}
+
+static int __devexit bh1770_remove(struct i2c_client *client)
+{
+	struct bh1770_chip *chip = i2c_get_clientdata(client);
+
+	free_irq(client->irq, chip);
+
+	sysfs_remove_group(&chip->client->dev.kobj,
+			&bh1770_attribute_group);
+
+	if (chip->pdata->release_resources)
+		chip->pdata->release_resources();
+
+	cancel_delayed_work_sync(&chip->prox_work);
+
+	if (!pm_runtime_suspended(&client->dev))
+		bh1770_chip_off(chip);
+
+	pm_runtime_disable(&client->dev);
+	pm_runtime_set_suspended(&client->dev);
+
+	regulator_bulk_free(ARRAY_SIZE(chip->regs), chip->regs);
+	kfree(chip);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int bh1770_suspend(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct bh1770_chip *chip = i2c_get_clientdata(client);
+
+	bh1770_chip_off(chip);
+
+	return 0;
+}
+
+static int bh1770_resume(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct bh1770_chip *chip = i2c_get_clientdata(client);
+	int ret = 0;
+
+	bh1770_chip_on(chip);
+
+	if (!pm_runtime_suspended(dev)) {
+		/*
+		 * If we were enabled at suspend time, it is expected
+		 * everything works nice and smoothly
+		 */
+		ret = bh1770_lux_rate(chip, chip->lux_rate_index);
+		ret |= bh1770_lux_interrupt_control(chip, BH1770_ENABLE);
+
+		/* This causes interrupt after the next measurement cycle */
+		bh1770_lux_update_thresholds(chip, BH1770_LUX_DEF_THRES,
+					BH1770_LUX_DEF_THRES);
+		/* Inform that we are waiting for a result from ALS */
+		chip->lux_wait_result = true;
+		bh1770_prox_mode_control(chip);
+	}
+	return ret;
+}
+
+#else
+#define bh1770_suspend	NULL
+#define bh1770_shutdown NULL
+#define bh1770_resume	NULL
+#endif
+
+#ifdef CONFIG_PM_RUNTIME
+static int bh1770_runtime_suspend(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct bh1770_chip *chip = i2c_get_clientdata(client);
+
+	bh1770_chip_off(chip);
+
+	return 0;
+}
+
+static int bh1770_runtime_resume(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct bh1770_chip *chip = i2c_get_clientdata(client);
+
+	bh1770_chip_on(chip);
+
+	return 0;
+}
+#endif
+
+static const struct i2c_device_id bh1770_id[] = {
+	{"bh1770glc", 0 },
+	{"sfh7770", 0 },
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, bh1770_id);
+
+static const struct dev_pm_ops bh1770_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(bh1770_suspend, bh1770_resume)
+	SET_RUNTIME_PM_OPS(bh1770_runtime_suspend, bh1770_runtime_resume, NULL)
+};
+
+static struct i2c_driver bh1770_driver = {
+	.driver	 = {
+		.name	= "bh1770glc",
+		.owner	= THIS_MODULE,
+		.pm	= &bh1770_pm_ops,
+	},
+	.probe	  = bh1770_probe,
+	.remove	  = __devexit_p(bh1770_remove),
+	.id_table = bh1770_id,
+};
+
+static int __init bh1770_init(void)
+{
+	return i2c_add_driver(&bh1770_driver);
+}
+
+static void __exit bh1770_exit(void)
+{
+	i2c_del_driver(&bh1770_driver);
+}
+
+MODULE_DESCRIPTION("BH1770GLC / SFH7770 combined ALS and proximity sensor");
+MODULE_AUTHOR("Samu Onkalo, Nokia Corporation");
+MODULE_LICENSE("GPL v2");
+
+module_init(bh1770_init);
+module_exit(bh1770_exit);
diff --git a/drivers/misc/isl29020.c b/drivers/misc/isl29020.c
new file mode 100644
index 0000000..34fe835
--- /dev/null
+++ b/drivers/misc/isl29020.c
@@ -0,0 +1,248 @@
+/*
+ * isl29020.c - Intersil  ALS Driver
+ *
+ * Copyright (C) 2008 Intel Corp
+ *
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * Data sheet at: http://www.intersil.com/data/fn/fn6505.pdf
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/sysfs.h>
+#include <linux/pm_runtime.h>
+
+static DEFINE_MUTEX(mutex);
+
+static ssize_t als_sensing_range_show(struct device *dev,
+			struct device_attribute *attr,  char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	int  val;
+
+	val = i2c_smbus_read_byte_data(client, 0x00);
+
+	if (val < 0)
+		return val;
+	return sprintf(buf, "%d000\n", 1 << (2 * (val & 3)));
+
+}
+
+static ssize_t als_lux_input_data_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	int ret_val, val;
+	unsigned long int lux;
+	int temp;
+
+	pm_runtime_get_sync(dev);
+	msleep(100);
+
+	mutex_lock(&mutex);
+	temp = i2c_smbus_read_byte_data(client, 0x02); /* MSB data */
+	if (temp < 0) {
+		pm_runtime_put_sync(dev);
+		mutex_unlock(&mutex);
+		return temp;
+	}
+
+	ret_val = i2c_smbus_read_byte_data(client, 0x01); /* LSB data */
+	mutex_unlock(&mutex);
+
+	if (ret_val < 0) {
+		pm_runtime_put_sync(dev);
+		return ret_val;
+	}
+
+	ret_val |= temp << 8;
+	val = i2c_smbus_read_byte_data(client, 0x00);
+	pm_runtime_put_sync(dev);
+	if (val < 0)
+		return val;
+	lux = ((((1 << (2 * (val & 3))))*1000) * ret_val) / 65536;
+	return sprintf(buf, "%ld\n", lux);
+}
+
+static ssize_t als_sensing_range_store(struct device *dev,
+		struct device_attribute *attr, const  char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	unsigned int ret_val;
+	unsigned long val;
+
+	if (strict_strtoul(buf, 10, &val))
+		return -EINVAL;
+	if (val < 1 || val > 64000)
+		return -EINVAL;
+
+	/* Pick the smallest sensor range that will meet our requirements */
+	if (val <= 1000)
+		val = 1;
+	else if (val <= 4000)
+		val = 2;
+	else if (val <= 16000)
+		val = 3;
+	else
+		val = 4;
+
+	ret_val = i2c_smbus_read_byte_data(client, 0x00);
+
+	ret_val &= 0xFC; /*reset the bit before setting them */
+	ret_val |= val - 1;
+	ret_val = i2c_smbus_write_byte_data(client, 0x00, ret_val);
+
+	if (ret_val < 0)
+		return ret_val;
+	return count;
+}
+
+static void als_set_power_state(struct i2c_client *client, int enable)
+{
+	int ret_val;
+
+	ret_val = i2c_smbus_read_byte_data(client, 0x00);
+	if (ret_val < 0)
+		return;
+
+	if (enable)
+		ret_val |= 0x80;
+	else
+		ret_val &= 0x7F;
+
+	i2c_smbus_write_byte_data(client, 0x00, ret_val);
+}
+
+static DEVICE_ATTR(lux0_sensor_range, S_IRUGO | S_IWUSR,
+	als_sensing_range_show, als_sensing_range_store);
+static DEVICE_ATTR(lux0_input, S_IRUGO, als_lux_input_data_show, NULL);
+
+static struct attribute *mid_att_als[] = {
+	&dev_attr_lux0_sensor_range.attr,
+	&dev_attr_lux0_input.attr,
+	NULL
+};
+
+static struct attribute_group m_als_gr = {
+	.name = "isl29020",
+	.attrs = mid_att_als
+};
+
+static int als_set_default_config(struct i2c_client *client)
+{
+	int retval;
+
+	retval = i2c_smbus_write_byte_data(client, 0x00, 0xc0);
+	if (retval < 0) {
+		dev_err(&client->dev, "default write failed.");
+		return retval;
+	}
+	return 0;;
+}
+
+static int  isl29020_probe(struct i2c_client *client,
+					const struct i2c_device_id *id)
+{
+	int res;
+
+	res = als_set_default_config(client);
+	if (res <  0)
+		return res;
+
+	res = sysfs_create_group(&client->dev.kobj, &m_als_gr);
+	if (res) {
+		dev_err(&client->dev, "isl29020: device create file failed\n");
+		return res;
+	}
+	dev_info(&client->dev, "%s isl29020: ALS chip found\n", client->name);
+	als_set_power_state(client, 0);
+	pm_runtime_enable(&client->dev);
+	return res;
+}
+
+static int isl29020_remove(struct i2c_client *client)
+{
+	struct als_data *data = i2c_get_clientdata(client);
+	sysfs_remove_group(&client->dev.kobj, &m_als_gr);
+	kfree(data);
+	return 0;
+}
+
+static struct i2c_device_id isl29020_id[] = {
+	{ "isl29020", 0 },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, isl29020_id);
+
+#ifdef CONFIG_PM
+
+static int isl29020_runtime_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	als_set_power_state(client, 0);
+	return 0;
+}
+
+static int isl29020_runtime_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	als_set_power_state(client, 1);
+	return 0;
+}
+
+static const struct dev_pm_ops isl29020_pm_ops = {
+	.runtime_suspend = isl29020_runtime_suspend,
+	.runtime_resume = isl29020_runtime_resume,
+};
+
+#define ISL29020_PM_OPS (&isl29020_pm_ops)
+#else	/* CONFIG_PM */
+#define ISL29020_PM_OPS NULL
+#endif	/* CONFIG_PM */
+
+static struct i2c_driver isl29020_driver = {
+	.driver = {
+		.name = "isl29020",
+		.pm = ISL29020_PM_OPS,
+	},
+	.probe = isl29020_probe,
+	.remove = isl29020_remove,
+	.id_table = isl29020_id,
+};
+
+static int __init sensor_isl29020_init(void)
+{
+	return i2c_add_driver(&isl29020_driver);
+}
+
+static void  __exit sensor_isl29020_exit(void)
+{
+	i2c_del_driver(&isl29020_driver);
+}
+
+module_init(sensor_isl29020_init);
+module_exit(sensor_isl29020_exit);
+
+MODULE_AUTHOR("Kalhan Trisal <kalhan.trisal@intel.com");
+MODULE_DESCRIPTION("Intersil isl29020 ALS Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c
index 343b5d8..81d7fa4 100644
--- a/drivers/misc/lkdtm.c
+++ b/drivers/misc/lkdtm.c
@@ -52,32 +52,32 @@
 #define REC_NUM_DEFAULT 10
 
 enum cname {
-	INVALID,
-	INT_HARDWARE_ENTRY,
-	INT_HW_IRQ_EN,
-	INT_TASKLET_ENTRY,
-	FS_DEVRW,
-	MEM_SWAPOUT,
-	TIMERADD,
-	SCSI_DISPATCH_CMD,
-	IDE_CORE_CP,
-	DIRECT,
+	CN_INVALID,
+	CN_INT_HARDWARE_ENTRY,
+	CN_INT_HW_IRQ_EN,
+	CN_INT_TASKLET_ENTRY,
+	CN_FS_DEVRW,
+	CN_MEM_SWAPOUT,
+	CN_TIMERADD,
+	CN_SCSI_DISPATCH_CMD,
+	CN_IDE_CORE_CP,
+	CN_DIRECT,
 };
 
 enum ctype {
-	NONE,
-	PANIC,
-	BUG,
-	EXCEPTION,
-	LOOP,
-	OVERFLOW,
-	CORRUPT_STACK,
-	UNALIGNED_LOAD_STORE_WRITE,
-	OVERWRITE_ALLOCATION,
-	WRITE_AFTER_FREE,
-	SOFTLOCKUP,
-	HARDLOCKUP,
-	HUNG_TASK,
+	CT_NONE,
+	CT_PANIC,
+	CT_BUG,
+	CT_EXCEPTION,
+	CT_LOOP,
+	CT_OVERFLOW,
+	CT_CORRUPT_STACK,
+	CT_UNALIGNED_LOAD_STORE_WRITE,
+	CT_OVERWRITE_ALLOCATION,
+	CT_WRITE_AFTER_FREE,
+	CT_SOFTLOCKUP,
+	CT_HARDLOCKUP,
+	CT_HUNG_TASK,
 };
 
 static char* cp_name[] = {
@@ -117,8 +117,8 @@
 static int cpoint_count = DEFAULT_COUNT;
 static int recur_count = REC_NUM_DEFAULT;
 
-static enum cname cpoint = INVALID;
-static enum ctype cptype = NONE;
+static enum cname cpoint = CN_INVALID;
+static enum ctype cptype = CT_NONE;
 static int count = DEFAULT_COUNT;
 
 module_param(recur_count, int, 0644);
@@ -207,12 +207,12 @@
 			return i + 1;
 	}
 
-	return NONE;
+	return CT_NONE;
 }
 
 static const char *cp_type_to_str(enum ctype type)
 {
-	if (type == NONE || type < 0 || type > ARRAY_SIZE(cp_type))
+	if (type == CT_NONE || type < 0 || type > ARRAY_SIZE(cp_type))
 		return "None";
 
 	return cp_type[type - 1];
@@ -220,7 +220,7 @@
 
 static const char *cp_name_to_str(enum cname name)
 {
-	if (name == INVALID || name < 0 || name > ARRAY_SIZE(cp_name))
+	if (name == CN_INVALID || name < 0 || name > ARRAY_SIZE(cp_name))
 		return "INVALID";
 
 	return cp_name[name - 1];
@@ -245,7 +245,7 @@
 		return -EINVAL;
 
 	cptype = parse_cp_type(cpoint_type, strlen(cpoint_type));
-	if (cptype == NONE)
+	if (cptype == CT_NONE)
 		return -EINVAL;
 
 	for (i = 0; i < ARRAY_SIZE(cp_name); i++) {
@@ -274,30 +274,30 @@
 static void lkdtm_do_action(enum ctype which)
 {
 	switch (which) {
-	case PANIC:
+	case CT_PANIC:
 		panic("dumptest");
 		break;
-	case BUG:
+	case CT_BUG:
 		BUG();
 		break;
-	case EXCEPTION:
+	case CT_EXCEPTION:
 		*((int *) 0) = 0;
 		break;
-	case LOOP:
+	case CT_LOOP:
 		for (;;)
 			;
 		break;
-	case OVERFLOW:
+	case CT_OVERFLOW:
 		(void) recursive_loop(0);
 		break;
-	case CORRUPT_STACK: {
+	case CT_CORRUPT_STACK: {
 		volatile u32 data[8];
 		volatile u32 *p = data;
 
 		p[12] = 0x12345678;
 		break;
 	}
-	case UNALIGNED_LOAD_STORE_WRITE: {
+	case CT_UNALIGNED_LOAD_STORE_WRITE: {
 		static u8 data[5] __attribute__((aligned(4))) = {1, 2,
 				3, 4, 5};
 		u32 *p;
@@ -309,7 +309,7 @@
 		*p = val;
 		 break;
 	}
-	case OVERWRITE_ALLOCATION: {
+	case CT_OVERWRITE_ALLOCATION: {
 		size_t len = 1020;
 		u32 *data = kmalloc(len, GFP_KERNEL);
 
@@ -317,7 +317,7 @@
 		kfree(data);
 		break;
 	}
-	case WRITE_AFTER_FREE: {
+	case CT_WRITE_AFTER_FREE: {
 		size_t len = 1024;
 		u32 *data = kmalloc(len, GFP_KERNEL);
 
@@ -326,21 +326,21 @@
 		memset(data, 0x78, len);
 		break;
 	}
-	case SOFTLOCKUP:
+	case CT_SOFTLOCKUP:
 		preempt_disable();
 		for (;;)
 			cpu_relax();
 		break;
-	case HARDLOCKUP:
+	case CT_HARDLOCKUP:
 		local_irq_disable();
 		for (;;)
 			cpu_relax();
 		break;
-	case HUNG_TASK:
+	case CT_HUNG_TASK:
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		schedule();
 		break;
-	case NONE:
+	case CT_NONE:
 	default:
 		break;
 	}
@@ -363,43 +363,43 @@
 {
 	int ret;
 
-	cpoint = INVALID;
+	cpoint = CN_INVALID;
 	if (lkdtm.entry != NULL)
 		unregister_jprobe(&lkdtm);
 
 	switch (which) {
-	case DIRECT:
+	case CN_DIRECT:
 		lkdtm_do_action(cptype);
 		return 0;
-	case INT_HARDWARE_ENTRY:
+	case CN_INT_HARDWARE_ENTRY:
 		lkdtm.kp.symbol_name = "do_IRQ";
 		lkdtm.entry = (kprobe_opcode_t*) jp_do_irq;
 		break;
-	case INT_HW_IRQ_EN:
+	case CN_INT_HW_IRQ_EN:
 		lkdtm.kp.symbol_name = "handle_IRQ_event";
 		lkdtm.entry = (kprobe_opcode_t*) jp_handle_irq_event;
 		break;
-	case INT_TASKLET_ENTRY:
+	case CN_INT_TASKLET_ENTRY:
 		lkdtm.kp.symbol_name = "tasklet_action";
 		lkdtm.entry = (kprobe_opcode_t*) jp_tasklet_action;
 		break;
-	case FS_DEVRW:
+	case CN_FS_DEVRW:
 		lkdtm.kp.symbol_name = "ll_rw_block";
 		lkdtm.entry = (kprobe_opcode_t*) jp_ll_rw_block;
 		break;
-	case MEM_SWAPOUT:
+	case CN_MEM_SWAPOUT:
 		lkdtm.kp.symbol_name = "shrink_inactive_list";
 		lkdtm.entry = (kprobe_opcode_t*) jp_shrink_inactive_list;
 		break;
-	case TIMERADD:
+	case CN_TIMERADD:
 		lkdtm.kp.symbol_name = "hrtimer_start";
 		lkdtm.entry = (kprobe_opcode_t*) jp_hrtimer_start;
 		break;
-	case SCSI_DISPATCH_CMD:
+	case CN_SCSI_DISPATCH_CMD:
 		lkdtm.kp.symbol_name = "scsi_dispatch_cmd";
 		lkdtm.entry = (kprobe_opcode_t*) jp_scsi_dispatch_cmd;
 		break;
-	case IDE_CORE_CP:
+	case CN_IDE_CORE_CP:
 #ifdef CONFIG_IDE
 		lkdtm.kp.symbol_name = "generic_ide_ioctl";
 		lkdtm.entry = (kprobe_opcode_t*) jp_generic_ide_ioctl;
@@ -416,7 +416,7 @@
 	cpoint = which;
 	if ((ret = register_jprobe(&lkdtm)) < 0) {
 		printk(KERN_INFO "lkdtm: Couldn't register jprobe\n");
-		cpoint = INVALID;
+		cpoint = CN_INVALID;
 	}
 
 	return ret;
@@ -445,7 +445,7 @@
 	cptype = parse_cp_type(buf, count);
 	free_page((unsigned long) buf);
 
-	if (cptype == NONE)
+	if (cptype == CT_NONE)
 		return -EINVAL;
 
 	err = lkdtm_register_cpoint(which);
@@ -487,49 +487,49 @@
 static ssize_t int_hardware_entry(struct file *f, const char __user *buf,
 		size_t count, loff_t *off)
 {
-	return do_register_entry(INT_HARDWARE_ENTRY, f, buf, count, off);
+	return do_register_entry(CN_INT_HARDWARE_ENTRY, f, buf, count, off);
 }
 
 static ssize_t int_hw_irq_en(struct file *f, const char __user *buf,
 		size_t count, loff_t *off)
 {
-	return do_register_entry(INT_HW_IRQ_EN, f, buf, count, off);
+	return do_register_entry(CN_INT_HW_IRQ_EN, f, buf, count, off);
 }
 
 static ssize_t int_tasklet_entry(struct file *f, const char __user *buf,
 		size_t count, loff_t *off)
 {
-	return do_register_entry(INT_TASKLET_ENTRY, f, buf, count, off);
+	return do_register_entry(CN_INT_TASKLET_ENTRY, f, buf, count, off);
 }
 
 static ssize_t fs_devrw_entry(struct file *f, const char __user *buf,
 		size_t count, loff_t *off)
 {
-	return do_register_entry(FS_DEVRW, f, buf, count, off);
+	return do_register_entry(CN_FS_DEVRW, f, buf, count, off);
 }
 
 static ssize_t mem_swapout_entry(struct file *f, const char __user *buf,
 		size_t count, loff_t *off)
 {
-	return do_register_entry(MEM_SWAPOUT, f, buf, count, off);
+	return do_register_entry(CN_MEM_SWAPOUT, f, buf, count, off);
 }
 
 static ssize_t timeradd_entry(struct file *f, const char __user *buf,
 		size_t count, loff_t *off)
 {
-	return do_register_entry(TIMERADD, f, buf, count, off);
+	return do_register_entry(CN_TIMERADD, f, buf, count, off);
 }
 
 static ssize_t scsi_dispatch_cmd_entry(struct file *f,
 		const char __user *buf, size_t count, loff_t *off)
 {
-	return do_register_entry(SCSI_DISPATCH_CMD, f, buf, count, off);
+	return do_register_entry(CN_SCSI_DISPATCH_CMD, f, buf, count, off);
 }
 
 static ssize_t ide_core_cp_entry(struct file *f, const char __user *buf,
 		size_t count, loff_t *off)
 {
-	return do_register_entry(IDE_CORE_CP, f, buf, count, off);
+	return do_register_entry(CN_IDE_CORE_CP, f, buf, count, off);
 }
 
 /* Special entry to just crash directly. Available without KPROBEs */
@@ -557,7 +557,7 @@
 
 	type = parse_cp_type(buf, count);
 	free_page((unsigned long) buf);
-	if (type == NONE)
+	if (type == CT_NONE)
 		return -EINVAL;
 
 	printk(KERN_INFO "lkdtm: Performing direct entry %s\n",
@@ -649,7 +649,7 @@
 		goto out_err;
 	}
 
-	if (cpoint != INVALID && cptype != NONE) {
+	if (cpoint != CN_INVALID && cptype != CT_NONE) {
 		ret = lkdtm_register_cpoint(cpoint);
 		if (ret < 0) {
 			printk(KERN_INFO "lkdtm: Invalid crash point %d\n",
diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c
index 4197a3c..b05db55 100644
--- a/drivers/misc/phantom.c
+++ b/drivers/misc/phantom.c
@@ -343,8 +343,10 @@
 	int retval;
 
 	retval = pci_enable_device(pdev);
-	if (retval)
+	if (retval) {
+		dev_err(&pdev->dev, "pci_enable_device failed!\n");
 		goto err;
+	}
 
 	minor = phantom_get_free();
 	if (minor == PHANTOM_MAX_MINORS) {
@@ -356,8 +358,10 @@
 	phantom_devices[minor] = 1;
 
 	retval = pci_request_regions(pdev, "phantom");
-	if (retval)
+	if (retval) {
+		dev_err(&pdev->dev, "pci_request_regions failed!\n");
 		goto err_null;
+	}
 
 	retval = -ENOMEM;
 	pht = kzalloc(sizeof(*pht), GFP_KERNEL);
diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c
index 1f59ee2..17bbacb 100644
--- a/drivers/misc/sgi-xp/xpc_uv.c
+++ b/drivers/misc/sgi-xp/xpc_uv.c
@@ -417,6 +417,7 @@
 static void
 xpc_handle_activate_mq_msg_uv(struct xpc_partition *part,
 			      struct xpc_activate_mq_msghdr_uv *msg_hdr,
+			      int part_setup,
 			      int *wakeup_hb_checker)
 {
 	unsigned long irq_flags;
@@ -481,6 +482,9 @@
 	case XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREQUEST_UV: {
 		struct xpc_activate_mq_msg_chctl_closerequest_uv *msg;
 
+		if (!part_setup)
+			break;
+
 		msg = container_of(msg_hdr, struct
 				   xpc_activate_mq_msg_chctl_closerequest_uv,
 				   hdr);
@@ -497,6 +501,9 @@
 	case XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREPLY_UV: {
 		struct xpc_activate_mq_msg_chctl_closereply_uv *msg;
 
+		if (!part_setup)
+			break;
+
 		msg = container_of(msg_hdr, struct
 				   xpc_activate_mq_msg_chctl_closereply_uv,
 				   hdr);
@@ -511,6 +518,9 @@
 	case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREQUEST_UV: {
 		struct xpc_activate_mq_msg_chctl_openrequest_uv *msg;
 
+		if (!part_setup)
+			break;
+
 		msg = container_of(msg_hdr, struct
 				   xpc_activate_mq_msg_chctl_openrequest_uv,
 				   hdr);
@@ -528,6 +538,9 @@
 	case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREPLY_UV: {
 		struct xpc_activate_mq_msg_chctl_openreply_uv *msg;
 
+		if (!part_setup)
+			break;
+
 		msg = container_of(msg_hdr, struct
 				   xpc_activate_mq_msg_chctl_openreply_uv, hdr);
 		args = &part->remote_openclose_args[msg->ch_number];
@@ -545,6 +558,9 @@
 	case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENCOMPLETE_UV: {
 		struct xpc_activate_mq_msg_chctl_opencomplete_uv *msg;
 
+		if (!part_setup)
+			break;
+
 		msg = container_of(msg_hdr, struct
 				xpc_activate_mq_msg_chctl_opencomplete_uv, hdr);
 		spin_lock_irqsave(&part->chctl_lock, irq_flags);
@@ -621,6 +637,7 @@
 
 			part_referenced = xpc_part_ref(part);
 			xpc_handle_activate_mq_msg_uv(part, msg_hdr,
+						      part_referenced,
 						      &wakeup_hb_checker);
 			if (part_referenced)
 				xpc_part_deref(part);
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 68d1279..1a02611 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -237,7 +237,7 @@
 
 config MMC_ATMELMCI_DMA
 	bool "Atmel MCI DMA support (EXPERIMENTAL)"
-	depends on MMC_ATMELMCI && AVR32 && DMA_ENGINE && EXPERIMENTAL
+	depends on MMC_ATMELMCI && (AVR32 || ARCH_AT91SAM9G45) && DMA_ENGINE && EXPERIMENTAL
 	help
 	  Say Y here to have the Atmel MCI driver use a DMA engine to
 	  do data transfers and thus increase the throughput and
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 4526d27..4693e62 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -364,6 +364,7 @@
 {
 	struct regulator *reg;
 	int ret = 0;
+	int ocr_value = 0;
 
 	switch (host->id) {
 	case OMAP_MMC1_DEVID:
@@ -396,6 +397,17 @@
 		}
 	} else {
 		host->vcc = reg;
+		ocr_value = mmc_regulator_get_ocrmask(reg);
+		if (!mmc_slot(host).ocr_mask) {
+			mmc_slot(host).ocr_mask = ocr_value;
+		} else {
+			if (!(mmc_slot(host).ocr_mask & ocr_value)) {
+				pr_err("MMC%d ocrmask %x is not supported\n",
+					host->id, mmc_slot(host).ocr_mask);
+				mmc_slot(host).ocr_mask = 0;
+				return -EINVAL;
+			}
+		}
 		mmc_slot(host).ocr_mask = mmc_regulator_get_ocrmask(reg);
 
 		/* Allow an aux regulator */
@@ -982,6 +994,17 @@
 	OMAP_HSMMC_WRITE(host->base, SYSCTL,
 			 OMAP_HSMMC_READ(host->base, SYSCTL) | bit);
 
+	/*
+	 * OMAP4 ES2 and greater has an updated reset logic.
+	 * Monitor a 0->1 transition first
+	 */
+	if (mmc_slot(host).features & HSMMC_HAS_UPDATED_RESET) {
+		while ((!(OMAP_HSMMC_READ(host, SYSCTL) & bit))
+					&& (i++ < limit))
+			cpu_relax();
+	}
+	i = 0;
+
 	while ((OMAP_HSMMC_READ(host->base, SYSCTL) & bit) &&
 		(i++ < limit))
 		cpu_relax();
@@ -2003,6 +2026,8 @@
 	if (res == NULL || irq < 0)
 		return -ENXIO;
 
+	res->start += pdata->reg_offset;
+	res->end += pdata->reg_offset;
 	res = request_mem_region(res->start, res->end - res->start + 1,
 							pdev->name);
 	if (res == NULL)
@@ -2116,23 +2141,9 @@
 	mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
 		     MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_ERASE;
 
-	switch (mmc_slot(host).wires) {
-	case 8:
-		mmc->caps |= MMC_CAP_8_BIT_DATA;
-		/* Fall through */
-	case 4:
+	mmc->caps |= mmc_slot(host).caps;
+	if (mmc->caps & MMC_CAP_8_BIT_DATA)
 		mmc->caps |= MMC_CAP_4_BIT_DATA;
-		break;
-	case 1:
-		/* Nothing to crib here */
-	case 0:
-		/* Assuming nothing was given by board, Core use's 1-Bit */
-		break;
-	default:
-		/* Completely unexpected.. Core goes with 1-Bit Width */
-		dev_crit(mmc_dev(host->mmc), "Invalid width %d\n used!"
-			"using 1 instead\n", mmc_slot(host).wires);
-	}
 
 	if (mmc_slot(host).nonremovable)
 		mmc->caps |= MMC_CAP_NONREMOVABLE;
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 702f598..86fe67f 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -883,14 +883,6 @@
 	help
 	  Set the number of buffer packets used in driver.
 
-config BFIN_MAC_RMII
-	bool "RMII PHY Interface"
-	depends on BFIN_MAC
-	default y if BFIN527_EZKIT
-	default n if BFIN537_STAMP
-	help
-	  Use Reduced PHY MII Interface
-
 config BFIN_MAC_USE_HWSTAMP
 	bool "Use IEEE 1588 hwstamp"
 	depends on BFIN_MAC && BF518
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c
index f723319..ce1e5e9 100644
--- a/drivers/net/bfin_mac.c
+++ b/drivers/net/bfin_mac.c
@@ -1,7 +1,7 @@
 /*
  * Blackfin On-Chip MAC Driver
  *
- * Copyright 2004-2007 Analog Devices Inc.
+ * Copyright 2004-2010 Analog Devices Inc.
  *
  * Enter bugs at http://blackfin.uclinux.org/
  *
@@ -23,7 +23,6 @@
 #include <linux/device.h>
 #include <linux/spinlock.h>
 #include <linux/mii.h>
-#include <linux/phy.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
@@ -76,12 +75,6 @@
 static struct net_dma_desc_tx *tx_desc;
 static struct net_dma_desc_rx *rx_desc;
 
-#if defined(CONFIG_BFIN_MAC_RMII)
-static u16 pin_req[] = P_RMII0;
-#else
-static u16 pin_req[] = P_MII0;
-#endif
-
 static void desc_list_free(void)
 {
 	struct net_dma_desc_rx *r;
@@ -347,23 +340,23 @@
 		}
 
 		if (phydev->speed != lp->old_speed) {
-#if defined(CONFIG_BFIN_MAC_RMII)
-			u32 opmode = bfin_read_EMAC_OPMODE();
-			switch (phydev->speed) {
-			case 10:
-				opmode |= RMII_10;
-				break;
-			case 100:
-				opmode &= ~(RMII_10);
-				break;
-			default:
-				printk(KERN_WARNING
-					"%s: Ack!  Speed (%d) is not 10/100!\n",
-					DRV_NAME, phydev->speed);
-				break;
+			if (phydev->interface == PHY_INTERFACE_MODE_RMII) {
+				u32 opmode = bfin_read_EMAC_OPMODE();
+				switch (phydev->speed) {
+				case 10:
+					opmode |= RMII_10;
+					break;
+				case 100:
+					opmode &= ~RMII_10;
+					break;
+				default:
+					printk(KERN_WARNING
+						"%s: Ack!  Speed (%d) is not 10/100!\n",
+						DRV_NAME, phydev->speed);
+					break;
+				}
+				bfin_write_EMAC_OPMODE(opmode);
 			}
-			bfin_write_EMAC_OPMODE(opmode);
-#endif
 
 			new_state = 1;
 			lp->old_speed = phydev->speed;
@@ -392,7 +385,7 @@
 /* MDC  = 2.5 MHz */
 #define MDC_CLK 2500000
 
-static int mii_probe(struct net_device *dev)
+static int mii_probe(struct net_device *dev, int phy_mode)
 {
 	struct bfin_mac_local *lp = netdev_priv(dev);
 	struct phy_device *phydev = NULL;
@@ -411,8 +404,8 @@
 	sysctl = (sysctl & ~MDCDIV) | SET_MDCDIV(mdc_div);
 	bfin_write_EMAC_SYSCTL(sysctl);
 
-	/* search for connect PHY device */
-	for (i = 0; i < PHY_MAX_ADDR; i++) {
+	/* search for connected PHY device */
+	for (i = 0; i < PHY_MAX_ADDR; ++i) {
 		struct phy_device *const tmp_phydev = lp->mii_bus->phy_map[i];
 
 		if (!tmp_phydev)
@@ -429,13 +422,14 @@
 		return -ENODEV;
 	}
 
-#if defined(CONFIG_BFIN_MAC_RMII)
+	if (phy_mode != PHY_INTERFACE_MODE_RMII &&
+		phy_mode != PHY_INTERFACE_MODE_MII) {
+		printk(KERN_INFO "%s: Invalid phy interface mode\n", dev->name);
+		return -EINVAL;
+	}
+
 	phydev = phy_connect(dev, dev_name(&phydev->dev), &bfin_mac_adjust_link,
-			0, PHY_INTERFACE_MODE_RMII);
-#else
-	phydev = phy_connect(dev, dev_name(&phydev->dev), &bfin_mac_adjust_link,
-			0, PHY_INTERFACE_MODE_MII);
-#endif
+			0, phy_mode);
 
 	if (IS_ERR(phydev)) {
 		printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
@@ -570,6 +564,8 @@
 /**************************************************************************/
 void setup_system_regs(struct net_device *dev)
 {
+	struct bfin_mac_local *lp = netdev_priv(dev);
+	int i;
 	unsigned short sysctl;
 
 	/*
@@ -577,6 +573,15 @@
 	 * Configure checksum support and rcve frame word alignment
 	 */
 	sysctl = bfin_read_EMAC_SYSCTL();
+	/*
+	 * check if interrupt is requested for any PHY,
+	 * enable PHY interrupt only if needed
+	 */
+	for (i = 0; i < PHY_MAX_ADDR; ++i)
+		if (lp->mii_bus->irq[i] != PHY_POLL)
+			break;
+	if (i < PHY_MAX_ADDR)
+		sysctl |= PHYIE;
 	sysctl |= RXDWA;
 #if defined(BFIN_MAC_CSUM_OFFLOAD)
 	sysctl |= RXCKS;
@@ -1203,7 +1208,7 @@
 /*
  * Enable Interrupts, Receive, and Transmit
  */
-static int bfin_mac_enable(void)
+static int bfin_mac_enable(struct phy_device *phydev)
 {
 	int ret;
 	u32 opmode;
@@ -1233,12 +1238,13 @@
 		opmode |= DRO | DC | PSF;
 	opmode |= RE;
 
-#if defined(CONFIG_BFIN_MAC_RMII)
-	opmode |= RMII; /* For Now only 100MBit are supported */
+	if (phydev->interface == PHY_INTERFACE_MODE_RMII) {
+		opmode |= RMII; /* For Now only 100MBit are supported */
 #if (defined(CONFIG_BF537) || defined(CONFIG_BF536)) && CONFIG_BF_REV_0_2
-	opmode |= TE;
+		opmode |= TE;
 #endif
-#endif
+	}
+
 	/* Turn on the EMAC rx */
 	bfin_write_EMAC_OPMODE(opmode);
 
@@ -1270,7 +1276,7 @@
 	if (netif_queue_stopped(lp->ndev))
 		netif_wake_queue(lp->ndev);
 
-	bfin_mac_enable();
+	bfin_mac_enable(lp->phydev);
 
 	/* We can accept TX packets again */
 	dev->trans_start = jiffies; /* prevent tx timeout */
@@ -1342,11 +1348,19 @@
 
 static int bfin_mac_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
 {
+	struct bfin_mac_local *lp = netdev_priv(netdev);
+
+	if (!netif_running(netdev))
+		return -EINVAL;
+
 	switch (cmd) {
 	case SIOCSHWTSTAMP:
 		return bfin_mac_hwtstamp_ioctl(netdev, ifr, cmd);
 	default:
-		return -EOPNOTSUPP;
+		if (lp->phydev)
+			return phy_mii_ioctl(lp->phydev, ifr, cmd);
+		else
+			return -EOPNOTSUPP;
 	}
 }
 
@@ -1394,7 +1408,7 @@
 	setup_mac_addr(dev->dev_addr);
 
 	bfin_mac_disable();
-	ret = bfin_mac_enable();
+	ret = bfin_mac_enable(lp->phydev);
 	if (ret)
 		return ret;
 	pr_debug("hardware init finished\n");
@@ -1450,6 +1464,7 @@
 	struct net_device *ndev;
 	struct bfin_mac_local *lp;
 	struct platform_device *pd;
+	struct bfin_mii_bus_platform_data *mii_bus_data;
 	int rc;
 
 	ndev = alloc_etherdev(sizeof(struct bfin_mac_local));
@@ -1501,11 +1516,12 @@
 	if (!lp->mii_bus) {
 		dev_err(&pdev->dev, "Cannot get mii_bus!\n");
 		rc = -ENODEV;
-		goto out_err_mii_bus_probe;
+		goto out_err_probe_mac;
 	}
 	lp->mii_bus->priv = ndev;
+	mii_bus_data = pd->dev.platform_data;
 
-	rc = mii_probe(ndev);
+	rc = mii_probe(ndev, mii_bus_data->phy_mode);
 	if (rc) {
 		dev_err(&pdev->dev, "MII Probe failed!\n");
 		goto out_err_mii_probe;
@@ -1552,8 +1568,6 @@
 out_err_mii_probe:
 	mdiobus_unregister(lp->mii_bus);
 	mdiobus_free(lp->mii_bus);
-out_err_mii_bus_probe:
-	peripheral_free_list(pin_req);
 out_err_probe_mac:
 	platform_set_drvdata(pdev, NULL);
 	free_netdev(ndev);
@@ -1576,8 +1590,6 @@
 
 	free_netdev(ndev);
 
-	peripheral_free_list(pin_req);
-
 	return 0;
 }
 
@@ -1623,12 +1635,21 @@
 static int __devinit bfin_mii_bus_probe(struct platform_device *pdev)
 {
 	struct mii_bus *miibus;
+	struct bfin_mii_bus_platform_data *mii_bus_pd;
+	const unsigned short *pin_req;
 	int rc, i;
 
+	mii_bus_pd = dev_get_platdata(&pdev->dev);
+	if (!mii_bus_pd) {
+		dev_err(&pdev->dev, "No peripherals in platform data!\n");
+		return -EINVAL;
+	}
+
 	/*
 	 * We are setting up a network card,
 	 * so set the GPIO pins to Ethernet mode
 	 */
+	pin_req = mii_bus_pd->mac_peripherals;
 	rc = peripheral_request_list(pin_req, DRV_NAME);
 	if (rc) {
 		dev_err(&pdev->dev, "Requesting peripherals failed!\n");
@@ -1645,13 +1666,30 @@
 
 	miibus->parent = &pdev->dev;
 	miibus->name = "bfin_mii_bus";
+	miibus->phy_mask = mii_bus_pd->phy_mask;
+
 	snprintf(miibus->id, MII_BUS_ID_SIZE, "0");
 	miibus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
-	if (miibus->irq == NULL)
-		goto out_err_alloc;
-	for (i = 0; i < PHY_MAX_ADDR; ++i)
+	if (!miibus->irq)
+		goto out_err_irq_alloc;
+
+	for (i = rc; i < PHY_MAX_ADDR; ++i)
 		miibus->irq[i] = PHY_POLL;
 
+	rc = clamp(mii_bus_pd->phydev_number, 0, PHY_MAX_ADDR);
+	if (rc != mii_bus_pd->phydev_number)
+		dev_err(&pdev->dev, "Invalid number (%i) of phydevs\n",
+			mii_bus_pd->phydev_number);
+	for (i = 0; i < rc; ++i) {
+		unsigned short phyaddr = mii_bus_pd->phydev_data[i].addr;
+		if (phyaddr < PHY_MAX_ADDR)
+			miibus->irq[phyaddr] = mii_bus_pd->phydev_data[i].irq;
+		else
+			dev_err(&pdev->dev,
+				"Invalid PHY address %i for phydev %i\n",
+				phyaddr, i);
+	}
+
 	rc = mdiobus_register(miibus);
 	if (rc) {
 		dev_err(&pdev->dev, "Cannot register MDIO bus!\n");
@@ -1663,6 +1701,7 @@
 
 out_err_mdiobus_register:
 	kfree(miibus->irq);
+out_err_irq_alloc:
 	mdiobus_free(miibus);
 out_err_alloc:
 	peripheral_free_list(pin_req);
@@ -1673,11 +1712,15 @@
 static int __devexit bfin_mii_bus_remove(struct platform_device *pdev)
 {
 	struct mii_bus *miibus = platform_get_drvdata(pdev);
+	struct bfin_mii_bus_platform_data *mii_bus_pd =
+		dev_get_platdata(&pdev->dev);
+
 	platform_set_drvdata(pdev, NULL);
 	mdiobus_unregister(miibus);
 	kfree(miibus->irq);
 	mdiobus_free(miibus);
-	peripheral_free_list(pin_req);
+	peripheral_free_list(mii_bus_pd->mac_peripherals);
+
 	return 0;
 }
 
diff --git a/drivers/net/bfin_mac.h b/drivers/net/bfin_mac.h
index 04e4050..aed68be 100644
--- a/drivers/net/bfin_mac.h
+++ b/drivers/net/bfin_mac.h
@@ -14,6 +14,8 @@
 #include <linux/clocksource.h>
 #include <linux/timecompare.h>
 #include <linux/timer.h>
+#include <linux/etherdevice.h>
+#include <linux/bfin_mac.h>
 
 #define BFIN_MAC_CSUM_OFFLOAD
 
diff --git a/drivers/net/mlx4/en_main.c b/drivers/net/mlx4/en_main.c
index 1439064..f6e0d40 100644
--- a/drivers/net/mlx4/en_main.c
+++ b/drivers/net/mlx4/en_main.c
@@ -124,6 +124,13 @@
 	return 0;
 }
 
+static void *mlx4_en_get_netdev(struct mlx4_dev *dev, void *ctx, u8 port)
+{
+	struct mlx4_en_dev *endev = ctx;
+
+	return endev->pndev[port];
+}
+
 static void mlx4_en_event(struct mlx4_dev *dev, void *endev_ptr,
 			  enum mlx4_dev_event event, int port)
 {
@@ -282,9 +289,11 @@
 }
 
 static struct mlx4_interface mlx4_en_interface = {
-	.add	= mlx4_en_add,
-	.remove	= mlx4_en_remove,
-	.event	= mlx4_en_event,
+	.add		= mlx4_en_add,
+	.remove		= mlx4_en_remove,
+	.event		= mlx4_en_event,
+	.get_dev	= mlx4_en_get_netdev,
+	.protocol	= MLX4_PROTOCOL_EN,
 };
 
 static int __init mlx4_en_init(void)
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index 79478bd..6d6806b 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -69,6 +69,7 @@
 	struct mlx4_en_priv *priv = netdev_priv(dev);
 	struct mlx4_en_dev *mdev = priv->mdev;
 	int err;
+	int idx;
 
 	if (!priv->vlgrp)
 		return;
@@ -83,7 +84,10 @@
 		if (err)
 			en_err(priv, "Failed configuring VLAN filter\n");
 	}
+	if (mlx4_register_vlan(mdev->dev, priv->port, vid, &idx))
+		en_err(priv, "failed adding vlan %d\n", vid);
 	mutex_unlock(&mdev->state_lock);
+
 }
 
 static void mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
@@ -91,6 +95,7 @@
 	struct mlx4_en_priv *priv = netdev_priv(dev);
 	struct mlx4_en_dev *mdev = priv->mdev;
 	int err;
+	int idx;
 
 	if (!priv->vlgrp)
 		return;
@@ -101,6 +106,11 @@
 
 	/* Remove VID from port VLAN filter */
 	mutex_lock(&mdev->state_lock);
+	if (!mlx4_find_cached_vlan(mdev->dev, priv->port, vid, &idx))
+		mlx4_unregister_vlan(mdev->dev, priv->port, idx);
+	else
+		en_err(priv, "could not find vid %d in cache\n", vid);
+
 	if (mdev->device_up && priv->port_up) {
 		err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlgrp);
 		if (err)
diff --git a/drivers/net/mlx4/en_port.c b/drivers/net/mlx4/en_port.c
index aa3ef2a..7f5a322 100644
--- a/drivers/net/mlx4/en_port.c
+++ b/drivers/net/mlx4/en_port.c
@@ -127,8 +127,8 @@
 	memset(context, 0, sizeof *context);
 
 	context->base_qpn = cpu_to_be32(base_qpn);
-	context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_SHIFT | base_qpn);
-	context->mcast = cpu_to_be32(1 << SET_PORT_PROMISC_SHIFT | base_qpn);
+	context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_EN_SHIFT | base_qpn);
+	context->mcast = cpu_to_be32(1 << SET_PORT_PROMISC_MODE_SHIFT | base_qpn);
 	context->intra_no_vlan = 0;
 	context->no_vlan = MLX4_NO_VLAN_IDX;
 	context->intra_vlan_miss = 0;
diff --git a/drivers/net/mlx4/en_port.h b/drivers/net/mlx4/en_port.h
index f6511aa..092e814 100644
--- a/drivers/net/mlx4/en_port.h
+++ b/drivers/net/mlx4/en_port.h
@@ -36,7 +36,8 @@
 
 
 #define SET_PORT_GEN_ALL_VALID	0x7
-#define SET_PORT_PROMISC_SHIFT	31
+#define SET_PORT_PROMISC_EN_SHIFT	31
+#define SET_PORT_PROMISC_MODE_SHIFT	30
 
 enum {
 	MLX4_CMD_SET_VLAN_FLTR  = 0x47,
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index b716e1a..b68eee2 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -98,7 +98,8 @@
 		[20] = "Address vector port checking support",
 		[21] = "UD multicast support",
 		[24] = "Demand paging support",
-		[25] = "Router support"
+		[25] = "Router support",
+		[30] = "IBoE support"
 	};
 	int i;
 
diff --git a/drivers/net/mlx4/intf.c b/drivers/net/mlx4/intf.c
index 5550678..73c94fc 100644
--- a/drivers/net/mlx4/intf.c
+++ b/drivers/net/mlx4/intf.c
@@ -161,3 +161,24 @@
 
 	mutex_unlock(&intf_mutex);
 }
+
+void *mlx4_get_protocol_dev(struct mlx4_dev *dev, enum mlx4_protocol proto, int port)
+{
+	struct mlx4_priv *priv = mlx4_priv(dev);
+	struct mlx4_device_context *dev_ctx;
+	unsigned long flags;
+	void *result = NULL;
+
+	spin_lock_irqsave(&priv->ctx_lock, flags);
+
+	list_for_each_entry(dev_ctx, &priv->ctx_list, list)
+		if (dev_ctx->intf->protocol == proto && dev_ctx->intf->get_dev) {
+			result = dev_ctx->intf->get_dev(dev, dev_ctx->context, port);
+			break;
+		}
+
+	spin_unlock_irqrestore(&priv->ctx_lock, flags);
+
+	return result;
+}
+EXPORT_SYMBOL_GPL(mlx4_get_protocol_dev);
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 569fa3d..782f11d 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -103,7 +103,7 @@
 
 static int log_mtts_per_seg = ilog2(MLX4_MTT_ENTRY_PER_SEG);
 module_param_named(log_mtts_per_seg, log_mtts_per_seg, int, 0444);
-MODULE_PARM_DESC(log_mtts_per_seg, "Log2 number of MTT entries per segment (1-5)");
+MODULE_PARM_DESC(log_mtts_per_seg, "Log2 number of MTT entries per segment (1-7)");
 
 int mlx4_check_port_params(struct mlx4_dev *dev,
 			   enum mlx4_port_type *port_type)
@@ -1310,7 +1310,7 @@
 		return -1;
 	}
 
-	if ((log_mtts_per_seg < 1) || (log_mtts_per_seg > 5)) {
+	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);
 		return -1;
 	}
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index 1fc16ab..dfed6a0 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -475,6 +475,7 @@
 	char *mc_addrs;
 	int mc_addrs_cnt;
 	struct mlx4_en_stat_out_mbox hw_stats;
+	int vids[128];
 };
 
 
diff --git a/drivers/net/mlx4/port.c b/drivers/net/mlx4/port.c
index 606aa58..56371ef 100644
--- a/drivers/net/mlx4/port.c
+++ b/drivers/net/mlx4/port.c
@@ -182,6 +182,25 @@
 	return err;
 }
 
+int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx)
+{
+	struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table;
+	int i;
+
+	for (i = 0; i < MLX4_MAX_VLAN_NUM; ++i) {
+		if (table->refs[i] &&
+		    (vid == (MLX4_VLAN_MASK &
+			      be32_to_cpu(table->entries[i])))) {
+			/* VLAN already registered, increase reference count */
+			*idx = i;
+			return 0;
+		}
+	}
+
+	return -ENOENT;
+}
+EXPORT_SYMBOL_GPL(mlx4_find_cached_vlan);
+
 int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index)
 {
 	struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table;
diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c
index f3f8be5..14f0955 100644
--- a/drivers/net/xilinx_emaclite.c
+++ b/drivers/net/xilinx_emaclite.c
@@ -430,8 +430,8 @@
 	}
 
 	/* Get the protocol type of the ethernet frame that arrived */
-	proto_type = ((in_be32(addr + XEL_HEADER_OFFSET +
-			XEL_RXBUFF_OFFSET) >> XEL_HEADER_SHIFT) &
+	proto_type = ((ntohl(in_be32(addr + XEL_HEADER_OFFSET +
+			XEL_RXBUFF_OFFSET)) >> XEL_HEADER_SHIFT) &
 			XEL_RPLR_LENGTH_MASK);
 
 	/* Check if received ethernet frame is a raw ethernet frame
@@ -439,9 +439,9 @@
 	if (proto_type > (ETH_FRAME_LEN + ETH_FCS_LEN)) {
 
 		if (proto_type == ETH_P_IP) {
-			length = ((in_be32(addr +
+			length = ((ntohl(in_be32(addr +
 					XEL_HEADER_IP_LENGTH_OFFSET +
-					XEL_RXBUFF_OFFSET) >>
+					XEL_RXBUFF_OFFSET)) >>
 					XEL_HEADER_SHIFT) &
 					XEL_RPLR_LENGTH_MASK);
 			length += ETH_HLEN + ETH_FCS_LEN;
diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h
index 0bab84e..19bc736 100644
--- a/drivers/pnp/base.h
+++ b/drivers/pnp/base.h
@@ -12,11 +12,12 @@
 
 #define PNP_EISA_ID_MASK 0x7fffffff
 void pnp_eisa_id_to_string(u32 id, char *str);
-struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *, int id, char *pnpid);
+struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *, int id,
+			      const char *pnpid);
 struct pnp_card *pnp_alloc_card(struct pnp_protocol *, int id, char *pnpid);
 
 int pnp_add_device(struct pnp_dev *dev);
-struct pnp_id *pnp_add_id(struct pnp_dev *dev, char *id);
+struct pnp_id *pnp_add_id(struct pnp_dev *dev, const char *id);
 
 int pnp_add_card(struct pnp_card *card);
 void pnp_remove_card(struct pnp_card *card);
diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c
index 88b3cde..0f34d96 100644
--- a/drivers/pnp/core.c
+++ b/drivers/pnp/core.c
@@ -124,7 +124,8 @@
 	kfree(dev);
 }
 
-struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, char *pnpid)
+struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id,
+			      const char *pnpid)
 {
 	struct pnp_dev *dev;
 	struct pnp_id *dev_id;
@@ -194,8 +195,9 @@
 	for (id = dev->id; id; id = id->next)
 		len += scnprintf(buf + len, sizeof(buf) - len, " %s", id->id);
 
-	pnp_dbg(&dev->dev, "%s device, IDs%s (%s)\n",
-		dev->protocol->name, buf, dev->active ? "active" : "disabled");
+	dev_printk(KERN_DEBUG, &dev->dev, "%s device, IDs%s (%s)\n",
+		   dev->protocol->name, buf,
+		   dev->active ? "active" : "disabled");
 	return 0;
 }
 
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c
index cd11b11..d1dbb9d 100644
--- a/drivers/pnp/driver.c
+++ b/drivers/pnp/driver.c
@@ -236,7 +236,7 @@
  * @dev: pointer to the desired device
  * @id: pointer to an EISA id string
  */
-struct pnp_id *pnp_add_id(struct pnp_dev *dev, char *id)
+struct pnp_id *pnp_add_id(struct pnp_dev *dev, const char *id)
 {
 	struct pnp_id *dev_id, *ptr;
 
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index dc4e32e..2d73dfc 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -28,7 +28,7 @@
 #include "../base.h"
 #include "pnpacpi.h"
 
-static int num = 0;
+static int num;
 
 /* We need only to blacklist devices that have already an acpi driver that
  * can't use pnp layer. We don't need to blacklist device that are directly
@@ -59,7 +59,7 @@
 #define TEST_ALPHA(c) \
 	if (!('@' <= (c) || (c) <= 'Z')) \
 		return 0
-static int __init ispnpidacpi(char *id)
+static int __init ispnpidacpi(const char *id)
 {
 	TEST_ALPHA(id[0]);
 	TEST_ALPHA(id[1]);
@@ -180,11 +180,24 @@
 };
 EXPORT_SYMBOL(pnpacpi_protocol);
 
+static char *pnpacpi_get_id(struct acpi_device *device)
+{
+	struct acpi_hardware_id *id;
+
+	list_for_each_entry(id, &device->pnp.ids, list) {
+		if (ispnpidacpi(id->id))
+			return id->id;
+	}
+
+	return NULL;
+}
+
 static int __init pnpacpi_add_device(struct acpi_device *device)
 {
 	acpi_handle temp = NULL;
 	acpi_status status;
 	struct pnp_dev *dev;
+	char *pnpid;
 	struct acpi_hardware_id *id;
 
 	/*
@@ -192,11 +205,17 @@
 	 * driver should not be loaded.
 	 */
 	status = acpi_get_handle(device->handle, "_CRS", &temp);
-	if (ACPI_FAILURE(status) || !ispnpidacpi(acpi_device_hid(device)) ||
-	    is_exclusive_device(device) || (!device->status.present))
+	if (ACPI_FAILURE(status))
 		return 0;
 
-	dev = pnp_alloc_dev(&pnpacpi_protocol, num, acpi_device_hid(device));
+	pnpid = pnpacpi_get_id(device);
+	if (!pnpid)
+		return 0;
+
+	if (is_exclusive_device(device) || !device->status.present)
+		return 0;
+
+	dev = pnp_alloc_dev(&pnpacpi_protocol, num, pnpid);
 	if (!dev)
 		return -ENOMEM;
 
@@ -227,7 +246,7 @@
 		pnpacpi_parse_resource_option_data(dev);
 
 	list_for_each_entry(id, &device->pnp.ids, list) {
-		if (!strcmp(id->id, acpi_device_hid(device)))
+		if (!strcmp(id->id, pnpid))
 			continue;
 		if (!ispnpidacpi(id->id))
 			continue;
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c
index e3446ab..a925e6b 100644
--- a/drivers/pnp/resource.c
+++ b/drivers/pnp/resource.c
@@ -523,7 +523,7 @@
 	res->start = irq;
 	res->end = irq;
 
-	pnp_dbg(&dev->dev, "  add %pr\n", res);
+	dev_printk(KERN_DEBUG, &dev->dev, "%pR\n", res);
 	return pnp_res;
 }
 
@@ -544,7 +544,7 @@
 	res->start = dma;
 	res->end = dma;
 
-	pnp_dbg(&dev->dev, "  add %pr\n", res);
+	dev_printk(KERN_DEBUG, &dev->dev, "%pR\n", res);
 	return pnp_res;
 }
 
@@ -568,7 +568,7 @@
 	res->start = start;
 	res->end = end;
 
-	pnp_dbg(&dev->dev, "  add %pr\n", res);
+	dev_printk(KERN_DEBUG, &dev->dev, "%pR\n", res);
 	return pnp_res;
 }
 
@@ -592,7 +592,7 @@
 	res->start = start;
 	res->end = end;
 
-	pnp_dbg(&dev->dev, "  add %pr\n", res);
+	dev_printk(KERN_DEBUG, &dev->dev, "%pR\n", res);
 	return pnp_res;
 }
 
@@ -616,7 +616,7 @@
 	res->start = start;
 	res->end = end;
 
-	pnp_dbg(&dev->dev, "  add %pr\n", res);
+	dev_printk(KERN_DEBUG, &dev->dev, "%pR\n", res);
 	return pnp_res;
 }
 
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 0734356..60d83d9 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -64,8 +64,7 @@
 
 config BATTERY_DS2760
 	tristate "DS2760 battery driver (HP iPAQ & others)"
-	select W1
-	select W1_SLAVE_DS2760
+	depends on W1 && W1_SLAVE_DS2760
 	help
 	  Say Y here to enable support for batteries with ds2760 chip.
 
@@ -109,6 +108,13 @@
 	help
 	  Say Y to enable support for battery measured by WM97xx aux port.
 
+config BATTERY_BQ20Z75
+        tristate "TI BQ20z75 gas gauge"
+        depends on I2C
+        help
+         Say Y to include support for TI BQ20z75 SBS-compliant
+         gas gauge and protection IC.
+
 config BATTERY_BQ27x00
 	tristate "BQ27x00 battery driver"
 	depends on I2C
@@ -166,4 +172,17 @@
 	  Say Y here to enable the battery driver on Intel MID
 	  platforms.
 
+config CHARGER_ISP1704
+	tristate "ISP1704 USB Charger Detection"
+	depends on USB_OTG_UTILS
+	help
+	  Say Y to enable support for USB Charger Detection with
+	  ISP1707/ISP1704 USB transceivers.
+
+config CHARGER_TWL4030
+	tristate "OMAP TWL4030 BCI charger driver"
+	depends on TWL4030_CORE
+	help
+	  Say Y here to enable support for TWL4030 Battery Charge Interface.
+
 endif # POWER_SUPPLY
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 10143aa..c75772e 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -1,16 +1,8 @@
-power_supply-objs := power_supply_core.o
+ccflags-$(CONFIG_POWER_SUPPLY_DEBUG) := -DDEBUG
 
-ifeq ($(CONFIG_SYSFS),y)
-power_supply-objs += power_supply_sysfs.o
-endif
-
-ifeq ($(CONFIG_LEDS_TRIGGERS),y)
-power_supply-objs += power_supply_leds.o
-endif
-
-ifeq ($(CONFIG_POWER_SUPPLY_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+power_supply-y				:= power_supply_core.o
+power_supply-$(CONFIG_SYSFS)		+= power_supply_sysfs.o
+power_supply-$(CONFIG_LEDS_TRIGGERS)	+= power_supply_leds.o
 
 obj-$(CONFIG_POWER_SUPPLY)	+= power_supply.o
 
@@ -29,6 +21,7 @@
 obj-$(CONFIG_BATTERY_TOSA)	+= tosa_battery.o
 obj-$(CONFIG_BATTERY_COLLIE)	+= collie_battery.o
 obj-$(CONFIG_BATTERY_WM97XX)	+= wm97xx_battery.o
+obj-$(CONFIG_BATTERY_BQ20Z75)	+= bq20z75.o
 obj-$(CONFIG_BATTERY_BQ27x00)	+= bq27x00_battery.o
 obj-$(CONFIG_BATTERY_DA9030)	+= da9030_battery.o
 obj-$(CONFIG_BATTERY_MAX17040)	+= max17040_battery.o
@@ -37,3 +30,5 @@
 obj-$(CONFIG_CHARGER_PCF50633)	+= pcf50633-charger.o
 obj-$(CONFIG_BATTERY_JZ4740)	+= jz4740-battery.o
 obj-$(CONFIG_BATTERY_INTEL_MID)	+= intel_mid_battery.o
+obj-$(CONFIG_CHARGER_ISP1704)	+= isp1704_charger.o
+obj-$(CONFIG_CHARGER_TWL4030)	+= twl4030_charger.o
diff --git a/drivers/power/bq20z75.c b/drivers/power/bq20z75.c
new file mode 100644
index 0000000..492da27
--- /dev/null
+++ b/drivers/power/bq20z75.c
@@ -0,0 +1,493 @@
+/*
+ * Gas Gauge driver for TI's BQ20Z75
+ *
+ * Copyright (c) 2010, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/power_supply.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+
+enum {
+	REG_MANUFACTURER_DATA,
+	REG_TEMPERATURE,
+	REG_VOLTAGE,
+	REG_CURRENT,
+	REG_CAPACITY,
+	REG_TIME_TO_EMPTY,
+	REG_TIME_TO_FULL,
+	REG_STATUS,
+	REG_CYCLE_COUNT,
+	REG_SERIAL_NUMBER,
+	REG_REMAINING_CAPACITY,
+	REG_FULL_CHARGE_CAPACITY,
+	REG_DESIGN_CAPACITY,
+	REG_DESIGN_VOLTAGE,
+};
+
+/* manufacturer access defines */
+#define MANUFACTURER_ACCESS_STATUS	0x0006
+#define MANUFACTURER_ACCESS_SLEEP	0x0011
+
+/* battery status value bits */
+#define BATTERY_DISCHARGING		0x40
+#define BATTERY_FULL_CHARGED		0x20
+#define BATTERY_FULL_DISCHARGED		0x10
+
+#define BQ20Z75_DATA(_psp, _addr, _min_value, _max_value) { \
+	.psp = _psp, \
+	.addr = _addr, \
+	.min_value = _min_value, \
+	.max_value = _max_value, \
+}
+
+static const struct bq20z75_device_data {
+	enum power_supply_property psp;
+	u8 addr;
+	int min_value;
+	int max_value;
+} bq20z75_data[] = {
+	[REG_MANUFACTURER_DATA] =
+		BQ20Z75_DATA(POWER_SUPPLY_PROP_PRESENT, 0x00, 0, 65535),
+	[REG_TEMPERATURE] =
+		BQ20Z75_DATA(POWER_SUPPLY_PROP_TEMP, 0x08, 0, 65535),
+	[REG_VOLTAGE] =
+		BQ20Z75_DATA(POWER_SUPPLY_PROP_VOLTAGE_NOW, 0x09, 0, 20000),
+	[REG_CURRENT] =
+		BQ20Z75_DATA(POWER_SUPPLY_PROP_CURRENT_NOW, 0x0A, -32768,
+			32767),
+	[REG_CAPACITY] =
+		BQ20Z75_DATA(POWER_SUPPLY_PROP_CAPACITY, 0x0E, 0, 100),
+	[REG_REMAINING_CAPACITY] =
+		BQ20Z75_DATA(POWER_SUPPLY_PROP_ENERGY_NOW, 0x0F, 0, 65535),
+	[REG_FULL_CHARGE_CAPACITY] =
+		BQ20Z75_DATA(POWER_SUPPLY_PROP_ENERGY_FULL, 0x10, 0, 65535),
+	[REG_TIME_TO_EMPTY] =
+		BQ20Z75_DATA(POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, 0x12, 0,
+			65535),
+	[REG_TIME_TO_FULL] =
+		BQ20Z75_DATA(POWER_SUPPLY_PROP_TIME_TO_FULL_AVG, 0x13, 0,
+			65535),
+	[REG_STATUS] =
+		BQ20Z75_DATA(POWER_SUPPLY_PROP_STATUS, 0x16, 0, 65535),
+	[REG_CYCLE_COUNT] =
+		BQ20Z75_DATA(POWER_SUPPLY_PROP_CYCLE_COUNT, 0x17, 0, 65535),
+	[REG_DESIGN_CAPACITY] =
+		BQ20Z75_DATA(POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, 0x18, 0,
+			65535),
+	[REG_DESIGN_VOLTAGE] =
+		BQ20Z75_DATA(POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, 0x19, 0,
+			65535),
+	[REG_SERIAL_NUMBER] =
+		BQ20Z75_DATA(POWER_SUPPLY_PROP_SERIAL_NUMBER, 0x1C, 0, 65535),
+};
+
+static enum power_supply_property bq20z75_properties[] = {
+	POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_HEALTH,
+	POWER_SUPPLY_PROP_PRESENT,
+	POWER_SUPPLY_PROP_TECHNOLOGY,
+	POWER_SUPPLY_PROP_CYCLE_COUNT,
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_CURRENT_NOW,
+	POWER_SUPPLY_PROP_CAPACITY,
+	POWER_SUPPLY_PROP_TEMP,
+	POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
+	POWER_SUPPLY_PROP_TIME_TO_FULL_AVG,
+	POWER_SUPPLY_PROP_SERIAL_NUMBER,
+	POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+	POWER_SUPPLY_PROP_ENERGY_NOW,
+	POWER_SUPPLY_PROP_ENERGY_FULL,
+	POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
+};
+
+struct bq20z75_info {
+	struct i2c_client	*client;
+	struct power_supply	power_supply;
+};
+
+static int bq20z75_read_word_data(struct i2c_client *client, u8 address)
+{
+	s32 ret;
+
+	ret = i2c_smbus_read_word_data(client, address);
+	if (ret < 0) {
+		dev_err(&client->dev,
+			"%s: i2c read at address 0x%x failed\n",
+			__func__, address);
+		return ret;
+	}
+	return le16_to_cpu(ret);
+}
+
+static int bq20z75_write_word_data(struct i2c_client *client, u8 address,
+	u16 value)
+{
+	s32 ret;
+
+	ret = i2c_smbus_write_word_data(client, address, le16_to_cpu(value));
+	if (ret < 0) {
+		dev_err(&client->dev,
+			"%s: i2c write to address 0x%x failed\n",
+			__func__, address);
+		return ret;
+	}
+	return 0;
+}
+
+static int bq20z75_get_battery_presence_and_health(
+	struct i2c_client *client, enum power_supply_property psp,
+	union power_supply_propval *val)
+{
+	s32 ret;
+
+	/* Write to ManufacturerAccess with
+	 * ManufacturerAccess command and then
+	 * read the status */
+	ret = bq20z75_write_word_data(client,
+		bq20z75_data[REG_MANUFACTURER_DATA].addr,
+		MANUFACTURER_ACCESS_STATUS);
+	if (ret < 0)
+		return ret;
+
+
+	ret = bq20z75_read_word_data(client,
+		bq20z75_data[REG_MANUFACTURER_DATA].addr);
+	if (ret < 0)
+		return ret;
+
+	if (ret < bq20z75_data[REG_MANUFACTURER_DATA].min_value ||
+	    ret > bq20z75_data[REG_MANUFACTURER_DATA].max_value) {
+		val->intval = 0;
+		return 0;
+	}
+
+	/* Mask the upper nibble of 2nd byte and
+	 * lower byte of response then
+	 * shift the result by 8 to get status*/
+	ret &= 0x0F00;
+	ret >>= 8;
+	if (psp == POWER_SUPPLY_PROP_PRESENT) {
+		if (ret == 0x0F)
+			/* battery removed */
+			val->intval = 0;
+		else
+			val->intval = 1;
+	} else if (psp == POWER_SUPPLY_PROP_HEALTH) {
+		if (ret == 0x09)
+			val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+		else if (ret == 0x0B)
+			val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
+		else if (ret == 0x0C)
+			val->intval = POWER_SUPPLY_HEALTH_DEAD;
+		else
+			val->intval = POWER_SUPPLY_HEALTH_GOOD;
+	}
+
+	return 0;
+}
+
+static int bq20z75_get_battery_property(struct i2c_client *client,
+	int reg_offset, enum power_supply_property psp,
+	union power_supply_propval *val)
+{
+	s32 ret;
+
+	ret = bq20z75_read_word_data(client,
+		bq20z75_data[reg_offset].addr);
+	if (ret < 0)
+		return ret;
+
+	/* returned values are 16 bit */
+	if (bq20z75_data[reg_offset].min_value < 0)
+		ret = (s16)ret;
+
+	if (ret >= bq20z75_data[reg_offset].min_value &&
+	    ret <= bq20z75_data[reg_offset].max_value) {
+		val->intval = ret;
+		if (psp == POWER_SUPPLY_PROP_STATUS) {
+			if (ret & BATTERY_FULL_CHARGED)
+				val->intval = POWER_SUPPLY_STATUS_FULL;
+			else if (ret & BATTERY_FULL_DISCHARGED)
+				val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+			else if (ret & BATTERY_DISCHARGING)
+				val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+			else
+				val->intval = POWER_SUPPLY_STATUS_CHARGING;
+		}
+	} else {
+		if (psp == POWER_SUPPLY_PROP_STATUS)
+			val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
+		else
+			val->intval = 0;
+	}
+
+	return 0;
+}
+
+static void  bq20z75_unit_adjustment(struct i2c_client *client,
+	enum power_supply_property psp, union power_supply_propval *val)
+{
+#define BASE_UNIT_CONVERSION		1000
+#define BATTERY_MODE_CAP_MULT_WATT	(10 * BASE_UNIT_CONVERSION)
+#define TIME_UNIT_CONVERSION		600
+#define TEMP_KELVIN_TO_CELCIUS		2731
+	switch (psp) {
+	case POWER_SUPPLY_PROP_ENERGY_NOW:
+	case POWER_SUPPLY_PROP_ENERGY_FULL:
+	case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
+		val->intval *= BATTERY_MODE_CAP_MULT_WATT;
+		break;
+
+	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+	case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+	case POWER_SUPPLY_PROP_CURRENT_NOW:
+		val->intval *= BASE_UNIT_CONVERSION;
+		break;
+
+	case POWER_SUPPLY_PROP_TEMP:
+		/* bq20z75 provides battery tempreture in 0.1°K
+		 * so convert it to 0.1°C */
+		val->intval -= TEMP_KELVIN_TO_CELCIUS;
+		val->intval *= 10;
+		break;
+
+	case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
+	case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG:
+		val->intval *= TIME_UNIT_CONVERSION;
+		break;
+
+	default:
+		dev_dbg(&client->dev,
+			"%s: no need for unit conversion %d\n", __func__, psp);
+	}
+}
+
+static int bq20z75_get_battery_capacity(struct i2c_client *client,
+	int reg_offset, enum power_supply_property psp,
+	union power_supply_propval *val)
+{
+	s32 ret;
+
+	ret = bq20z75_read_word_data(client, bq20z75_data[reg_offset].addr);
+	if (ret < 0)
+		return ret;
+
+	if (psp == POWER_SUPPLY_PROP_CAPACITY) {
+		/* bq20z75 spec says that this can be >100 %
+		* even if max value is 100 % */
+		val->intval = min(ret, 100);
+	} else
+		val->intval = ret;
+
+	return 0;
+}
+
+static char bq20z75_serial[5];
+static int bq20z75_get_battery_serial_number(struct i2c_client *client,
+	union power_supply_propval *val)
+{
+	int ret;
+
+	ret = bq20z75_read_word_data(client,
+		bq20z75_data[REG_SERIAL_NUMBER].addr);
+	if (ret < 0)
+		return ret;
+
+	ret = sprintf(bq20z75_serial, "%04x", ret);
+	val->strval = bq20z75_serial;
+
+	return 0;
+}
+
+static int bq20z75_get_property(struct power_supply *psy,
+	enum power_supply_property psp,
+	union power_supply_propval *val)
+{
+	int count;
+	int ret;
+	struct bq20z75_info *bq20z75_device = container_of(psy,
+				struct bq20z75_info, power_supply);
+	struct i2c_client *client = bq20z75_device->client;
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_PRESENT:
+	case POWER_SUPPLY_PROP_HEALTH:
+		ret = bq20z75_get_battery_presence_and_health(client, psp, val);
+		if (ret)
+			return ret;
+		break;
+
+	case POWER_SUPPLY_PROP_TECHNOLOGY:
+		val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
+		break;
+
+	case POWER_SUPPLY_PROP_ENERGY_NOW:
+	case POWER_SUPPLY_PROP_ENERGY_FULL:
+	case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
+	case POWER_SUPPLY_PROP_CAPACITY:
+		for (count = 0; count < ARRAY_SIZE(bq20z75_data); count++) {
+			if (psp == bq20z75_data[count].psp)
+				break;
+		}
+
+		ret = bq20z75_get_battery_capacity(client, count, psp, val);
+		if (ret)
+			return ret;
+
+		break;
+
+	case POWER_SUPPLY_PROP_SERIAL_NUMBER:
+		ret = bq20z75_get_battery_serial_number(client, val);
+		if (ret)
+			return ret;
+		break;
+
+	case POWER_SUPPLY_PROP_STATUS:
+	case POWER_SUPPLY_PROP_CYCLE_COUNT:
+	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+	case POWER_SUPPLY_PROP_CURRENT_NOW:
+	case POWER_SUPPLY_PROP_TEMP:
+	case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
+	case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG:
+	case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+		for (count = 0; count < ARRAY_SIZE(bq20z75_data); count++) {
+			if (psp == bq20z75_data[count].psp)
+				break;
+		}
+
+		ret = bq20z75_get_battery_property(client, count, psp, val);
+		if (ret)
+			return ret;
+
+		break;
+
+	default:
+		dev_err(&client->dev,
+			"%s: INVALID property\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Convert units to match requirements for power supply class */
+	bq20z75_unit_adjustment(client, psp, val);
+
+	dev_dbg(&client->dev,
+		"%s: property = %d, value = %d\n", __func__, psp, val->intval);
+
+	return 0;
+}
+
+static int bq20z75_probe(struct i2c_client *client,
+	const struct i2c_device_id *id)
+{
+	struct bq20z75_info *bq20z75_device;
+	int rc;
+
+	bq20z75_device = kzalloc(sizeof(struct bq20z75_info), GFP_KERNEL);
+	if (!bq20z75_device)
+		return -ENOMEM;
+
+	bq20z75_device->client = client;
+	bq20z75_device->power_supply.name = "battery";
+	bq20z75_device->power_supply.type = POWER_SUPPLY_TYPE_BATTERY;
+	bq20z75_device->power_supply.properties = bq20z75_properties;
+	bq20z75_device->power_supply.num_properties =
+		ARRAY_SIZE(bq20z75_properties);
+	bq20z75_device->power_supply.get_property = bq20z75_get_property;
+
+	i2c_set_clientdata(client, bq20z75_device);
+
+	rc = power_supply_register(&client->dev, &bq20z75_device->power_supply);
+	if (rc) {
+		dev_err(&client->dev,
+			"%s: Failed to register power supply\n", __func__);
+		kfree(bq20z75_device);
+		return rc;
+	}
+
+	dev_info(&client->dev,
+		"%s: battery gas gauge device registered\n", client->name);
+
+	return 0;
+}
+
+static int bq20z75_remove(struct i2c_client *client)
+{
+	struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
+
+	power_supply_unregister(&bq20z75_device->power_supply);
+	kfree(bq20z75_device);
+	bq20z75_device = NULL;
+
+	return 0;
+}
+
+#if defined CONFIG_PM
+static int bq20z75_suspend(struct i2c_client *client,
+	pm_message_t state)
+{
+	s32 ret;
+
+	/* write to manufacturer access with sleep command */
+	ret = bq20z75_write_word_data(client,
+		bq20z75_data[REG_MANUFACTURER_DATA].addr,
+		MANUFACTURER_ACCESS_SLEEP);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+#else
+#define bq20z75_suspend		NULL
+#endif
+/* any smbus transaction will wake up bq20z75 */
+#define bq20z75_resume		NULL
+
+static const struct i2c_device_id bq20z75_id[] = {
+	{ "bq20z75", 0 },
+	{}
+};
+
+static struct i2c_driver bq20z75_battery_driver = {
+	.probe		= bq20z75_probe,
+	.remove		= bq20z75_remove,
+	.suspend	= bq20z75_suspend,
+	.resume		= bq20z75_resume,
+	.id_table	= bq20z75_id,
+	.driver = {
+		.name	= "bq20z75-battery",
+	},
+};
+
+static int __init bq20z75_battery_init(void)
+{
+	return i2c_add_driver(&bq20z75_battery_driver);
+}
+module_init(bq20z75_battery_init);
+
+static void __exit bq20z75_battery_exit(void)
+{
+	i2c_del_driver(&bq20z75_battery_driver);
+}
+module_exit(bq20z75_battery_exit);
+
+MODULE_DESCRIPTION("BQ20z75 battery monitor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
index 3ec9c6a..eff0273 100644
--- a/drivers/power/bq27x00_battery.c
+++ b/drivers/power/bq27x00_battery.c
@@ -418,6 +418,7 @@
 
 	power_supply_unregister(&di->bat);
 
+	kfree(di->bus);
 	kfree(di->bat.name);
 
 	mutex_lock(&battery_mutex);
diff --git a/drivers/power/ds2760_battery.c b/drivers/power/ds2760_battery.c
index 4d3b272..b3c01c1 100644
--- a/drivers/power/ds2760_battery.c
+++ b/drivers/power/ds2760_battery.c
@@ -586,6 +586,7 @@
 					  &di->set_charged_work);
 	destroy_workqueue(di->monitor_wqueue);
 	power_supply_unregister(&di->bat);
+	kfree(di);
 
 	return 0;
 }
diff --git a/drivers/power/ds2782_battery.c b/drivers/power/ds2782_battery.c
index 84d3c43..6957e8a 100644
--- a/drivers/power/ds2782_battery.c
+++ b/drivers/power/ds2782_battery.c
@@ -44,8 +44,8 @@
 
 struct ds278x_battery_ops {
 	int (*get_battery_current)(struct ds278x_info *info, int *current_uA);
-	int (*get_battery_voltage)(struct ds278x_info *info, int *voltage_uA);
-	int (*get_battery_capacity)(struct ds278x_info *info, int *capacity_uA);
+	int (*get_battery_voltage)(struct ds278x_info *info, int *voltage_uV);
+	int (*get_battery_capacity)(struct ds278x_info *info, int *capacity);
 };
 
 #define to_ds278x_info(x) container_of(x, struct ds278x_info, battery)
@@ -137,7 +137,7 @@
 	return 0;
 }
 
-static int ds2782_get_voltage(struct ds278x_info *info, int *voltage_uA)
+static int ds2782_get_voltage(struct ds278x_info *info, int *voltage_uV)
 {
 	s16 raw;
 	int err;
@@ -149,7 +149,7 @@
 	err = ds278x_read_reg16(info, DS278x_REG_VOLT_MSB, &raw);
 	if (err)
 		return err;
-	*voltage_uA = (raw / 32) * 4800;
+	*voltage_uV = (raw / 32) * 4800;
 	return 0;
 }
 
@@ -177,7 +177,7 @@
 	return 0;
 }
 
-static int ds2786_get_voltage(struct ds278x_info *info, int *voltage_uA)
+static int ds2786_get_voltage(struct ds278x_info *info, int *voltage_uV)
 {
 	s16 raw;
 	int err;
@@ -189,7 +189,7 @@
 	err = ds278x_read_reg16(info, DS278x_REG_VOLT_MSB, &raw);
 	if (err)
 		return err;
-	*voltage_uA = (raw / 8) * 1220;
+	*voltage_uV = (raw / 8) * 1220;
 	return 0;
 }
 
diff --git a/drivers/power/isp1704_charger.c b/drivers/power/isp1704_charger.c
new file mode 100644
index 0000000..7251218
--- /dev/null
+++ b/drivers/power/isp1704_charger.c
@@ -0,0 +1,369 @@
+/*
+ * ISP1704 USB Charger Detection driver
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/sysfs.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/delay.h>
+
+#include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
+/* Vendor specific Power Control register */
+#define ISP1704_PWR_CTRL		0x3d
+#define ISP1704_PWR_CTRL_SWCTRL		(1 << 0)
+#define ISP1704_PWR_CTRL_DET_COMP	(1 << 1)
+#define ISP1704_PWR_CTRL_BVALID_RISE	(1 << 2)
+#define ISP1704_PWR_CTRL_BVALID_FALL	(1 << 3)
+#define ISP1704_PWR_CTRL_DP_WKPU_EN	(1 << 4)
+#define ISP1704_PWR_CTRL_VDAT_DET	(1 << 5)
+#define ISP1704_PWR_CTRL_DPVSRC_EN	(1 << 6)
+#define ISP1704_PWR_CTRL_HWDETECT	(1 << 7)
+
+#define NXP_VENDOR_ID			0x04cc
+
+static u16 isp170x_id[] = {
+	0x1704,
+	0x1707,
+};
+
+struct isp1704_charger {
+	struct device		*dev;
+	struct power_supply	psy;
+	struct otg_transceiver	*otg;
+	struct notifier_block	nb;
+	struct work_struct	work;
+
+	char			model[7];
+	unsigned		present:1;
+};
+
+/*
+ * ISP1704 detects PS/2 adapters as charger. To make sure the detected charger
+ * is actually a dedicated charger, the following steps need to be taken.
+ */
+static inline int isp1704_charger_verify(struct isp1704_charger *isp)
+{
+	int	ret = 0;
+	u8	r;
+
+	/* Reset the transceiver */
+	r = otg_io_read(isp->otg, ULPI_FUNC_CTRL);
+	r |= ULPI_FUNC_CTRL_RESET;
+	otg_io_write(isp->otg, ULPI_FUNC_CTRL, r);
+	usleep_range(1000, 2000);
+
+	/* Set normal mode */
+	r &= ~(ULPI_FUNC_CTRL_RESET | ULPI_FUNC_CTRL_OPMODE_MASK);
+	otg_io_write(isp->otg, ULPI_FUNC_CTRL, r);
+
+	/* Clear the DP and DM pull-down bits */
+	r = ULPI_OTG_CTRL_DP_PULLDOWN | ULPI_OTG_CTRL_DM_PULLDOWN;
+	otg_io_write(isp->otg, ULPI_CLR(ULPI_OTG_CTRL), r);
+
+	/* Enable strong pull-up on DP (1.5K) and reset */
+	r = ULPI_FUNC_CTRL_TERMSELECT | ULPI_FUNC_CTRL_RESET;
+	otg_io_write(isp->otg, ULPI_SET(ULPI_FUNC_CTRL), r);
+	usleep_range(1000, 2000);
+
+	/* Read the line state */
+	if (!otg_io_read(isp->otg, ULPI_DEBUG)) {
+		/* Disable strong pull-up on DP (1.5K) */
+		otg_io_write(isp->otg, ULPI_CLR(ULPI_FUNC_CTRL),
+				ULPI_FUNC_CTRL_TERMSELECT);
+		return 1;
+	}
+
+	/* Is it a charger or PS/2 connection */
+
+	/* Enable weak pull-up resistor on DP */
+	otg_io_write(isp->otg, ULPI_SET(ISP1704_PWR_CTRL),
+			ISP1704_PWR_CTRL_DP_WKPU_EN);
+
+	/* Disable strong pull-up on DP (1.5K) */
+	otg_io_write(isp->otg, ULPI_CLR(ULPI_FUNC_CTRL),
+			ULPI_FUNC_CTRL_TERMSELECT);
+
+	/* Enable weak pull-down resistor on DM */
+	otg_io_write(isp->otg, ULPI_SET(ULPI_OTG_CTRL),
+			ULPI_OTG_CTRL_DM_PULLDOWN);
+
+	/* It's a charger if the line states are clear */
+	if (!(otg_io_read(isp->otg, ULPI_DEBUG)))
+		ret = 1;
+
+	/* Disable weak pull-up resistor on DP */
+	otg_io_write(isp->otg, ULPI_CLR(ISP1704_PWR_CTRL),
+			ISP1704_PWR_CTRL_DP_WKPU_EN);
+
+	return ret;
+}
+
+static inline int isp1704_charger_detect(struct isp1704_charger *isp)
+{
+	unsigned long	timeout;
+	u8		r;
+	int		ret = 0;
+
+	/* set SW control bit in PWR_CTRL register */
+	otg_io_write(isp->otg, ISP1704_PWR_CTRL,
+			ISP1704_PWR_CTRL_SWCTRL);
+
+	/* enable manual charger detection */
+	r = (ISP1704_PWR_CTRL_SWCTRL | ISP1704_PWR_CTRL_DPVSRC_EN);
+	otg_io_write(isp->otg, ULPI_SET(ISP1704_PWR_CTRL), r);
+	usleep_range(1000, 2000);
+
+	timeout = jiffies + msecs_to_jiffies(300);
+	do {
+		/* Check if there is a charger */
+		if (otg_io_read(isp->otg, ISP1704_PWR_CTRL)
+				& ISP1704_PWR_CTRL_VDAT_DET) {
+			ret = isp1704_charger_verify(isp);
+			break;
+		}
+	} while (!time_after(jiffies, timeout));
+
+	return ret;
+}
+
+static void isp1704_charger_work(struct work_struct *data)
+{
+	int			detect;
+	struct isp1704_charger	*isp =
+		container_of(data, struct isp1704_charger, work);
+
+	/*
+	 * FIXME Only supporting dedicated chargers even though isp1704 can
+	 * detect HUB and HOST chargers. If the device has already been
+	 * enumerated, the detection will break the connection.
+	 */
+	if (isp->otg->state != OTG_STATE_B_IDLE)
+		return;
+
+	/* disable data pullups */
+	if (isp->otg->gadget)
+		usb_gadget_disconnect(isp->otg->gadget);
+
+	/* detect charger */
+	detect = isp1704_charger_detect(isp);
+	if (detect) {
+		isp->present = detect;
+		power_supply_changed(&isp->psy);
+	}
+
+	/* enable data pullups */
+	if (isp->otg->gadget)
+		usb_gadget_connect(isp->otg->gadget);
+}
+
+static int isp1704_notifier_call(struct notifier_block *nb,
+		unsigned long event, void *unused)
+{
+	struct isp1704_charger *isp =
+		container_of(nb, struct isp1704_charger, nb);
+
+	switch (event) {
+	case USB_EVENT_VBUS:
+		schedule_work(&isp->work);
+		break;
+	case USB_EVENT_NONE:
+		if (isp->present) {
+			isp->present = 0;
+			power_supply_changed(&isp->psy);
+		}
+		break;
+	default:
+		return NOTIFY_DONE;
+	}
+
+	return NOTIFY_OK;
+}
+
+static int isp1704_charger_get_property(struct power_supply *psy,
+				enum power_supply_property psp,
+				union power_supply_propval *val)
+{
+	struct isp1704_charger *isp =
+		container_of(psy, struct isp1704_charger, psy);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_PRESENT:
+		val->intval = isp->present;
+		break;
+	case POWER_SUPPLY_PROP_MODEL_NAME:
+		val->strval = isp->model;
+		break;
+	case POWER_SUPPLY_PROP_MANUFACTURER:
+		val->strval = "NXP";
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static enum power_supply_property power_props[] = {
+	POWER_SUPPLY_PROP_PRESENT,
+	POWER_SUPPLY_PROP_MODEL_NAME,
+	POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
+static inline int isp1704_test_ulpi(struct isp1704_charger *isp)
+{
+	int vendor;
+	int product;
+	int i;
+	int ret = -ENODEV;
+
+	/* Test ULPI interface */
+	ret = otg_io_write(isp->otg, ULPI_SCRATCH, 0xaa);
+	if (ret < 0)
+		return ret;
+
+	ret = otg_io_read(isp->otg, ULPI_SCRATCH);
+	if (ret < 0)
+		return ret;
+
+	if (ret != 0xaa)
+		return -ENODEV;
+
+	/* Verify the product and vendor id matches */
+	vendor = otg_io_read(isp->otg, ULPI_VENDOR_ID_LOW);
+	vendor |= otg_io_read(isp->otg, ULPI_VENDOR_ID_HIGH) << 8;
+	if (vendor != NXP_VENDOR_ID)
+		return -ENODEV;
+
+	product = otg_io_read(isp->otg, ULPI_PRODUCT_ID_LOW);
+	product |= otg_io_read(isp->otg, ULPI_PRODUCT_ID_HIGH) << 8;
+
+	for (i = 0; i < ARRAY_SIZE(isp170x_id); i++) {
+		if (product == isp170x_id[i]) {
+			sprintf(isp->model, "isp%x", product);
+			return product;
+		}
+	}
+
+	dev_err(isp->dev, "product id %x not matching known ids", product);
+
+	return -ENODEV;
+}
+
+static int __devinit isp1704_charger_probe(struct platform_device *pdev)
+{
+	struct isp1704_charger	*isp;
+	int			ret = -ENODEV;
+
+	isp = kzalloc(sizeof *isp, GFP_KERNEL);
+	if (!isp)
+		return -ENOMEM;
+
+	isp->otg = otg_get_transceiver();
+	if (!isp->otg)
+		goto fail0;
+
+	ret = isp1704_test_ulpi(isp);
+	if (ret < 0)
+		goto fail1;
+
+	isp->dev = &pdev->dev;
+	platform_set_drvdata(pdev, isp);
+
+	isp->psy.name		= "isp1704";
+	isp->psy.type		= POWER_SUPPLY_TYPE_USB;
+	isp->psy.properties	= power_props;
+	isp->psy.num_properties	= ARRAY_SIZE(power_props);
+	isp->psy.get_property	= isp1704_charger_get_property;
+
+	ret = power_supply_register(isp->dev, &isp->psy);
+	if (ret)
+		goto fail1;
+
+	/*
+	 * REVISIT: using work in order to allow the otg notifications to be
+	 * made atomically in the future.
+	 */
+	INIT_WORK(&isp->work, isp1704_charger_work);
+
+	isp->nb.notifier_call = isp1704_notifier_call;
+
+	ret = otg_register_notifier(isp->otg, &isp->nb);
+	if (ret)
+		goto fail2;
+
+	dev_info(isp->dev, "registered with product id %s\n", isp->model);
+
+	return 0;
+fail2:
+	power_supply_unregister(&isp->psy);
+fail1:
+	otg_put_transceiver(isp->otg);
+fail0:
+	kfree(isp);
+
+	dev_err(&pdev->dev, "failed to register isp1704 with error %d\n", ret);
+
+	return ret;
+}
+
+static int __devexit isp1704_charger_remove(struct platform_device *pdev)
+{
+	struct isp1704_charger *isp = platform_get_drvdata(pdev);
+
+	otg_unregister_notifier(isp->otg, &isp->nb);
+	power_supply_unregister(&isp->psy);
+	otg_put_transceiver(isp->otg);
+	kfree(isp);
+
+	return 0;
+}
+
+static struct platform_driver isp1704_charger_driver = {
+	.driver = {
+		.name = "isp1704_charger",
+	},
+	.probe = isp1704_charger_probe,
+	.remove = __devexit_p(isp1704_charger_remove),
+};
+
+static int __init isp1704_charger_init(void)
+{
+	return platform_driver_register(&isp1704_charger_driver);
+}
+module_init(isp1704_charger_init);
+
+static void __exit isp1704_charger_exit(void)
+{
+	platform_driver_unregister(&isp1704_charger_driver);
+}
+module_exit(isp1704_charger_exit);
+
+MODULE_ALIAS("platform:isp1704_charger");
+MODULE_AUTHOR("Nokia Corporation");
+MODULE_DESCRIPTION("ISP170x USB Charger driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/jz4740-battery.c b/drivers/power/jz4740-battery.c
index 20c4b95..a8108a7 100644
--- a/drivers/power/jz4740-battery.c
+++ b/drivers/power/jz4740-battery.c
@@ -383,6 +383,7 @@
 
 	iounmap(jz_battery->base);
 	release_mem_region(jz_battery->mem->start, resource_size(jz_battery->mem));
+	kfree(jz_battery);
 
 	return 0;
 }
diff --git a/drivers/power/olpc_battery.c b/drivers/power/olpc_battery.c
index aafc1c5..5bc1dcf 100644
--- a/drivers/power/olpc_battery.c
+++ b/drivers/power/olpc_battery.c
@@ -271,14 +271,14 @@
 		if (ret)
 			return ret;
 
-		val->intval = (int)be16_to_cpu(ec_word) * 9760L / 32;
+		val->intval = (s16)be16_to_cpu(ec_word) * 9760L / 32;
 		break;
 	case POWER_SUPPLY_PROP_CURRENT_AVG:
 		ret = olpc_ec_cmd(EC_BAT_CURRENT, NULL, 0, (void *)&ec_word, 2);
 		if (ret)
 			return ret;
 
-		val->intval = (int)be16_to_cpu(ec_word) * 15625L / 120;
+		val->intval = (s16)be16_to_cpu(ec_word) * 15625L / 120;
 		break;
 	case POWER_SUPPLY_PROP_CAPACITY:
 		ret = olpc_ec_cmd(EC_BAT_SOC, NULL, 0, &ec_byte, 1);
@@ -299,7 +299,7 @@
 		if (ret)
 			return ret;
 
-		val->intval = (int)be16_to_cpu(ec_word) * 100 / 256;
+		val->intval = (s16)be16_to_cpu(ec_word) * 100 / 256;
 		break;
 	case POWER_SUPPLY_PROP_TEMP_AMBIENT:
 		ret = olpc_ec_cmd(EC_AMB_TEMP, NULL, 0, (void *)&ec_word, 2);
@@ -313,7 +313,7 @@
 		if (ret)
 			return ret;
 
-		val->intval = (int)be16_to_cpu(ec_word) * 6250 / 15;
+		val->intval = (s16)be16_to_cpu(ec_word) * 6250 / 15;
 		break;
 	case POWER_SUPPLY_PROP_SERIAL_NUMBER:
 		ret = olpc_ec_cmd(EC_BAT_SERIAL, NULL, 0, (void *)&ser_buf, 8);
diff --git a/drivers/power/pcf50633-charger.c b/drivers/power/pcf50633-charger.c
index 066f994..4fa52e1 100644
--- a/drivers/power/pcf50633-charger.c
+++ b/drivers/power/pcf50633-charger.c
@@ -456,6 +456,7 @@
 	for (i = 0; i < ARRAY_SIZE(mbc_irq_handlers); i++)
 		pcf50633_free_irq(mbc->pcf, mbc_irq_handlers[i]);
 
+	sysfs_remove_group(&pdev->dev.kobj, &mbc_attr_group);
 	power_supply_unregister(&mbc->usb);
 	power_supply_unregister(&mbc->adapter);
 	power_supply_unregister(&mbc->ac);
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index 9d30eeb..cd1f907 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -42,7 +42,8 @@
 					  struct device_attribute *attr,
 					  char *buf) {
 	static char *type_text[] = {
-		"Battery", "UPS", "Mains", "USB"
+		"Battery", "UPS", "Mains", "USB",
+		"USB_DCP", "USB_CDP", "USB_ACA"
 	};
 	static char *status_text[] = {
 		"Unknown", "Charging", "Discharging", "Not charging", "Full"
@@ -138,6 +139,7 @@
 	POWER_SUPPLY_ATTR(voltage_min_design),
 	POWER_SUPPLY_ATTR(voltage_now),
 	POWER_SUPPLY_ATTR(voltage_avg),
+	POWER_SUPPLY_ATTR(current_max),
 	POWER_SUPPLY_ATTR(current_now),
 	POWER_SUPPLY_ATTR(current_avg),
 	POWER_SUPPLY_ATTR(power_now),
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
new file mode 100644
index 0000000..ff1f423
--- /dev/null
+++ b/drivers/power/twl4030_charger.c
@@ -0,0 +1,565 @@
+/*
+ * TWL4030/TPS65950 BCI (Battery Charger Interface) driver
+ *
+ * Copyright (C) 2010 Gražvydas Ignotas <notasas@gmail.com>
+ *
+ * based on twl4030_bci_battery.c by TI
+ * Copyright (C) 2008 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 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/slab.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/i2c/twl.h>
+#include <linux/power_supply.h>
+#include <linux/notifier.h>
+#include <linux/usb/otg.h>
+
+#define TWL4030_BCIMSTATEC	0x02
+#define TWL4030_BCIICHG		0x08
+#define TWL4030_BCIVAC		0x0a
+#define TWL4030_BCIVBUS		0x0c
+#define TWL4030_BCIMFSTS4	0x10
+#define TWL4030_BCICTL1		0x23
+
+#define TWL4030_BCIAUTOWEN	BIT(5)
+#define TWL4030_CONFIG_DONE	BIT(4)
+#define TWL4030_BCIAUTOUSB	BIT(1)
+#define TWL4030_BCIAUTOAC	BIT(0)
+#define TWL4030_CGAIN		BIT(5)
+#define TWL4030_USBFASTMCHG	BIT(2)
+#define TWL4030_STS_VBUS	BIT(7)
+#define TWL4030_STS_USB_ID	BIT(2)
+
+/* BCI interrupts */
+#define TWL4030_WOVF		BIT(0) /* Watchdog overflow */
+#define TWL4030_TMOVF		BIT(1) /* Timer overflow */
+#define TWL4030_ICHGHIGH	BIT(2) /* Battery charge current high */
+#define TWL4030_ICHGLOW		BIT(3) /* Battery cc. low / FSM state change */
+#define TWL4030_ICHGEOC		BIT(4) /* Battery current end-of-charge */
+#define TWL4030_TBATOR2		BIT(5) /* Battery temperature out of range 2 */
+#define TWL4030_TBATOR1		BIT(6) /* Battery temperature out of range 1 */
+#define TWL4030_BATSTS		BIT(7) /* Battery status */
+
+#define TWL4030_VBATLVL		BIT(0) /* VBAT level */
+#define TWL4030_VBATOV		BIT(1) /* VBAT overvoltage */
+#define TWL4030_VBUSOV		BIT(2) /* VBUS overvoltage */
+#define TWL4030_ACCHGOV		BIT(3) /* Ac charger overvoltage */
+
+#define TWL4030_MSTATEC_USB		BIT(4)
+#define TWL4030_MSTATEC_AC		BIT(5)
+#define TWL4030_MSTATEC_MASK		0x0f
+#define TWL4030_MSTATEC_QUICK1		0x02
+#define TWL4030_MSTATEC_QUICK7		0x07
+#define TWL4030_MSTATEC_COMPLETE1	0x0b
+#define TWL4030_MSTATEC_COMPLETE4	0x0e
+
+static bool allow_usb;
+module_param(allow_usb, bool, 1);
+MODULE_PARM_DESC(allow_usb, "Allow USB charge drawing default current");
+
+struct twl4030_bci {
+	struct device		*dev;
+	struct power_supply	ac;
+	struct power_supply	usb;
+	struct otg_transceiver	*transceiver;
+	struct notifier_block	otg_nb;
+	int			irq_chg;
+	int			irq_bci;
+};
+
+/*
+ * clear and set bits on an given register on a given module
+ */
+static int twl4030_clear_set(u8 mod_no, u8 clear, u8 set, u8 reg)
+{
+	u8 val = 0;
+	int ret;
+
+	ret = twl_i2c_read_u8(mod_no, &val, reg);
+	if (ret)
+		return ret;
+
+	val &= ~clear;
+	val |= set;
+
+	return twl_i2c_write_u8(mod_no, val, reg);
+}
+
+static int twl4030_bci_read(u8 reg, u8 *val)
+{
+	return twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, val, reg);
+}
+
+static int twl4030_clear_set_boot_bci(u8 clear, u8 set)
+{
+	return twl4030_clear_set(TWL4030_MODULE_PM_MASTER, 0,
+			TWL4030_CONFIG_DONE | TWL4030_BCIAUTOWEN | set,
+			TWL4030_PM_MASTER_BOOT_BCI);
+}
+
+static int twl4030bci_read_adc_val(u8 reg)
+{
+	int ret, temp;
+	u8 val;
+
+	/* read MSB */
+	ret = twl4030_bci_read(reg + 1, &val);
+	if (ret)
+		return ret;
+
+	temp = (int)(val & 0x03) << 8;
+
+	/* read LSB */
+	ret = twl4030_bci_read(reg, &val);
+	if (ret)
+		return ret;
+
+	return temp | val;
+}
+
+/*
+ * Check if VBUS power is present
+ */
+static int twl4030_bci_have_vbus(struct twl4030_bci *bci)
+{
+	int ret;
+	u8 hwsts;
+
+	ret = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &hwsts,
+			      TWL4030_PM_MASTER_STS_HW_CONDITIONS);
+	if (ret < 0)
+		return 0;
+
+	dev_dbg(bci->dev, "check_vbus: HW_CONDITIONS %02x\n", hwsts);
+
+	/* in case we also have STS_USB_ID, VBUS is driven by TWL itself */
+	if ((hwsts & TWL4030_STS_VBUS) && !(hwsts & TWL4030_STS_USB_ID))
+		return 1;
+
+	return 0;
+}
+
+/*
+ * Enable/Disable USB Charge funtionality.
+ */
+static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable)
+{
+	int ret;
+
+	if (enable) {
+		/* Check for USB charger conneted */
+		if (!twl4030_bci_have_vbus(bci))
+			return -ENODEV;
+
+		/*
+		 * Until we can find out what current the device can provide,
+		 * require a module param to enable USB charging.
+		 */
+		if (!allow_usb) {
+			dev_warn(bci->dev, "USB charging is disabled.\n");
+			return -EACCES;
+		}
+
+		/* forcing the field BCIAUTOUSB (BOOT_BCI[1]) to 1 */
+		ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOUSB);
+		if (ret < 0)
+			return ret;
+
+		/* forcing USBFASTMCHG(BCIMFSTS4[2]) to 1 */
+		ret = twl4030_clear_set(TWL4030_MODULE_MAIN_CHARGE, 0,
+			TWL4030_USBFASTMCHG, TWL4030_BCIMFSTS4);
+	} else {
+		ret = twl4030_clear_set_boot_bci(TWL4030_BCIAUTOUSB, 0);
+	}
+
+	return ret;
+}
+
+/*
+ * Enable/Disable AC Charge funtionality.
+ */
+static int twl4030_charger_enable_ac(bool enable)
+{
+	int ret;
+
+	if (enable)
+		ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOAC);
+	else
+		ret = twl4030_clear_set_boot_bci(TWL4030_BCIAUTOAC, 0);
+
+	return ret;
+}
+
+/*
+ * TWL4030 CHG_PRES (AC charger presence) events
+ */
+static irqreturn_t twl4030_charger_interrupt(int irq, void *arg)
+{
+	struct twl4030_bci *bci = arg;
+
+	dev_dbg(bci->dev, "CHG_PRES irq\n");
+	power_supply_changed(&bci->ac);
+	power_supply_changed(&bci->usb);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * TWL4030 BCI monitoring events
+ */
+static irqreturn_t twl4030_bci_interrupt(int irq, void *arg)
+{
+	struct twl4030_bci *bci = arg;
+	u8 irqs1, irqs2;
+	int ret;
+
+	ret = twl_i2c_read_u8(TWL4030_MODULE_INTERRUPTS, &irqs1,
+			      TWL4030_INTERRUPTS_BCIISR1A);
+	if (ret < 0)
+		return IRQ_HANDLED;
+
+	ret = twl_i2c_read_u8(TWL4030_MODULE_INTERRUPTS, &irqs2,
+			      TWL4030_INTERRUPTS_BCIISR2A);
+	if (ret < 0)
+		return IRQ_HANDLED;
+
+	dev_dbg(bci->dev, "BCI irq %02x %02x\n", irqs2, irqs1);
+
+	if (irqs1 & (TWL4030_ICHGLOW | TWL4030_ICHGEOC)) {
+		/* charger state change, inform the core */
+		power_supply_changed(&bci->ac);
+		power_supply_changed(&bci->usb);
+	}
+
+	/* various monitoring events, for now we just log them here */
+	if (irqs1 & (TWL4030_TBATOR2 | TWL4030_TBATOR1))
+		dev_warn(bci->dev, "battery temperature out of range\n");
+
+	if (irqs1 & TWL4030_BATSTS)
+		dev_crit(bci->dev, "battery disconnected\n");
+
+	if (irqs2 & TWL4030_VBATOV)
+		dev_crit(bci->dev, "VBAT overvoltage\n");
+
+	if (irqs2 & TWL4030_VBUSOV)
+		dev_crit(bci->dev, "VBUS overvoltage\n");
+
+	if (irqs2 & TWL4030_ACCHGOV)
+		dev_crit(bci->dev, "Ac charger overvoltage\n");
+
+	return IRQ_HANDLED;
+}
+
+static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val,
+			       void *priv)
+{
+	struct twl4030_bci *bci = container_of(nb, struct twl4030_bci, otg_nb);
+
+	dev_dbg(bci->dev, "OTG notify %lu\n", val);
+
+	switch (val) {
+	case USB_EVENT_VBUS:
+	case USB_EVENT_CHARGER:
+		twl4030_charger_enable_usb(bci, true);
+		break;
+	case USB_EVENT_NONE:
+		twl4030_charger_enable_usb(bci, false);
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+/*
+ * TI provided formulas:
+ * CGAIN == 0: ICHG = (BCIICHG * 1.7) / (2^10 - 1) - 0.85
+ * CGAIN == 1: ICHG = (BCIICHG * 3.4) / (2^10 - 1) - 1.7
+ * Here we use integer approximation of:
+ * CGAIN == 0: val * 1.6618 - 0.85
+ * CGAIN == 1: (val * 1.6618 - 0.85) * 2
+ */
+static int twl4030_charger_get_current(void)
+{
+	int curr;
+	int ret;
+	u8 bcictl1;
+
+	curr = twl4030bci_read_adc_val(TWL4030_BCIICHG);
+	if (curr < 0)
+		return curr;
+
+	ret = twl4030_bci_read(TWL4030_BCICTL1, &bcictl1);
+	if (ret)
+		return ret;
+
+	ret = (curr * 16618 - 850 * 10000) / 10;
+	if (bcictl1 & TWL4030_CGAIN)
+		ret *= 2;
+
+	return ret;
+}
+
+/*
+ * Returns the main charge FSM state
+ * Or < 0 on failure.
+ */
+static int twl4030bci_state(struct twl4030_bci *bci)
+{
+	int ret;
+	u8 state;
+
+	ret = twl4030_bci_read(TWL4030_BCIMSTATEC, &state);
+	if (ret) {
+		pr_err("twl4030_bci: error reading BCIMSTATEC\n");
+		return ret;
+	}
+
+	dev_dbg(bci->dev, "state: %02x\n", state);
+
+	return state;
+}
+
+static int twl4030_bci_state_to_status(int state)
+{
+	state &= TWL4030_MSTATEC_MASK;
+	if (TWL4030_MSTATEC_QUICK1 <= state && state <= TWL4030_MSTATEC_QUICK7)
+		return POWER_SUPPLY_STATUS_CHARGING;
+	else if (TWL4030_MSTATEC_COMPLETE1 <= state &&
+					state <= TWL4030_MSTATEC_COMPLETE4)
+		return POWER_SUPPLY_STATUS_FULL;
+	else
+		return POWER_SUPPLY_STATUS_NOT_CHARGING;
+}
+
+static int twl4030_bci_get_property(struct power_supply *psy,
+				    enum power_supply_property psp,
+				    union power_supply_propval *val)
+{
+	struct twl4030_bci *bci = dev_get_drvdata(psy->dev->parent);
+	int is_charging;
+	int state;
+	int ret;
+
+	state = twl4030bci_state(bci);
+	if (state < 0)
+		return state;
+
+	if (psy->type == POWER_SUPPLY_TYPE_USB)
+		is_charging = state & TWL4030_MSTATEC_USB;
+	else
+		is_charging = state & TWL4030_MSTATEC_AC;
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_STATUS:
+		if (is_charging)
+			val->intval = twl4030_bci_state_to_status(state);
+		else
+			val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+		/* charging must be active for meaningful result */
+		if (!is_charging)
+			return -ENODATA;
+		if (psy->type == POWER_SUPPLY_TYPE_USB) {
+			ret = twl4030bci_read_adc_val(TWL4030_BCIVBUS);
+			if (ret < 0)
+				return ret;
+			/* BCIVBUS uses ADCIN8, 7/1023 V/step */
+			val->intval = ret * 6843;
+		} else {
+			ret = twl4030bci_read_adc_val(TWL4030_BCIVAC);
+			if (ret < 0)
+				return ret;
+			/* BCIVAC uses ADCIN11, 10/1023 V/step */
+			val->intval = ret * 9775;
+		}
+		break;
+	case POWER_SUPPLY_PROP_CURRENT_NOW:
+		if (!is_charging)
+			return -ENODATA;
+		/* current measurement is shared between AC and USB */
+		ret = twl4030_charger_get_current();
+		if (ret < 0)
+			return ret;
+		val->intval = ret;
+		break;
+	case POWER_SUPPLY_PROP_ONLINE:
+		val->intval = is_charging &&
+			twl4030_bci_state_to_status(state) !=
+				POWER_SUPPLY_STATUS_NOT_CHARGING;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static enum power_supply_property twl4030_charger_props[] = {
+	POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_ONLINE,
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_CURRENT_NOW,
+};
+
+static int __init twl4030_bci_probe(struct platform_device *pdev)
+{
+	struct twl4030_bci *bci;
+	int ret;
+	int reg;
+
+	bci = kzalloc(sizeof(*bci), GFP_KERNEL);
+	if (bci == NULL)
+		return -ENOMEM;
+
+	bci->dev = &pdev->dev;
+	bci->irq_chg = platform_get_irq(pdev, 0);
+	bci->irq_bci = platform_get_irq(pdev, 1);
+
+	platform_set_drvdata(pdev, bci);
+
+	bci->ac.name = "twl4030_ac";
+	bci->ac.type = POWER_SUPPLY_TYPE_MAINS;
+	bci->ac.properties = twl4030_charger_props;
+	bci->ac.num_properties = ARRAY_SIZE(twl4030_charger_props);
+	bci->ac.get_property = twl4030_bci_get_property;
+
+	ret = power_supply_register(&pdev->dev, &bci->ac);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register ac: %d\n", ret);
+		goto fail_register_ac;
+	}
+
+	bci->usb.name = "twl4030_usb";
+	bci->usb.type = POWER_SUPPLY_TYPE_USB;
+	bci->usb.properties = twl4030_charger_props;
+	bci->usb.num_properties = ARRAY_SIZE(twl4030_charger_props);
+	bci->usb.get_property = twl4030_bci_get_property;
+
+	ret = power_supply_register(&pdev->dev, &bci->usb);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register usb: %d\n", ret);
+		goto fail_register_usb;
+	}
+
+	ret = request_threaded_irq(bci->irq_chg, NULL,
+			twl4030_charger_interrupt, 0, pdev->name, bci);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "could not request irq %d, status %d\n",
+			bci->irq_chg, ret);
+		goto fail_chg_irq;
+	}
+
+	ret = request_threaded_irq(bci->irq_bci, NULL,
+			twl4030_bci_interrupt, 0, pdev->name, bci);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "could not request irq %d, status %d\n",
+			bci->irq_bci, ret);
+		goto fail_bci_irq;
+	}
+
+	bci->transceiver = otg_get_transceiver();
+	if (bci->transceiver != NULL) {
+		bci->otg_nb.notifier_call = twl4030_bci_usb_ncb;
+		otg_register_notifier(bci->transceiver, &bci->otg_nb);
+	}
+
+	/* Enable interrupts now. */
+	reg = ~(TWL4030_ICHGLOW | TWL4030_ICHGEOC | TWL4030_TBATOR2 |
+		TWL4030_TBATOR1 | TWL4030_BATSTS);
+	ret = twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, reg,
+			       TWL4030_INTERRUPTS_BCIIMR1A);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to unmask interrupts: %d\n", ret);
+		goto fail_unmask_interrupts;
+	}
+
+	reg = ~(TWL4030_VBATOV | TWL4030_VBUSOV | TWL4030_ACCHGOV);
+	ret = twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, reg,
+			       TWL4030_INTERRUPTS_BCIIMR2A);
+	if (ret < 0)
+		dev_warn(&pdev->dev, "failed to unmask interrupts: %d\n", ret);
+
+	twl4030_charger_enable_ac(true);
+	twl4030_charger_enable_usb(bci, true);
+
+	return 0;
+
+fail_unmask_interrupts:
+	if (bci->transceiver != NULL) {
+		otg_unregister_notifier(bci->transceiver, &bci->otg_nb);
+		otg_put_transceiver(bci->transceiver);
+	}
+	free_irq(bci->irq_bci, bci);
+fail_bci_irq:
+	free_irq(bci->irq_chg, bci);
+fail_chg_irq:
+	power_supply_unregister(&bci->usb);
+fail_register_usb:
+	power_supply_unregister(&bci->ac);
+fail_register_ac:
+	platform_set_drvdata(pdev, NULL);
+	kfree(bci);
+
+	return ret;
+}
+
+static int __exit twl4030_bci_remove(struct platform_device *pdev)
+{
+	struct twl4030_bci *bci = platform_get_drvdata(pdev);
+
+	twl4030_charger_enable_ac(false);
+	twl4030_charger_enable_usb(bci, false);
+
+	/* mask interrupts */
+	twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff,
+			 TWL4030_INTERRUPTS_BCIIMR1A);
+	twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff,
+			 TWL4030_INTERRUPTS_BCIIMR2A);
+
+	if (bci->transceiver != NULL) {
+		otg_unregister_notifier(bci->transceiver, &bci->otg_nb);
+		otg_put_transceiver(bci->transceiver);
+	}
+	free_irq(bci->irq_bci, bci);
+	free_irq(bci->irq_chg, bci);
+	power_supply_unregister(&bci->usb);
+	power_supply_unregister(&bci->ac);
+	platform_set_drvdata(pdev, NULL);
+	kfree(bci);
+
+	return 0;
+}
+
+static struct platform_driver twl4030_bci_driver = {
+	.driver	= {
+		.name	= "twl4030_bci",
+		.owner	= THIS_MODULE,
+	},
+	.remove	= __exit_p(twl4030_bci_remove),
+};
+
+static int __init twl4030_bci_init(void)
+{
+	return platform_driver_probe(&twl4030_bci_driver, twl4030_bci_probe);
+}
+module_init(twl4030_bci_init);
+
+static void __exit twl4030_bci_exit(void)
+{
+	platform_driver_unregister(&twl4030_bci_driver);
+}
+module_exit(twl4030_bci_exit);
+
+MODULE_AUTHOR("Gražydas Ignotas");
+MODULE_DESCRIPTION("TWL4030 Battery Charger Interface driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:twl4030_bci");
diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c
index fbcc36d..ddf8cf5 100644
--- a/drivers/power/wm831x_power.c
+++ b/drivers/power/wm831x_power.c
@@ -267,7 +267,6 @@
 	ret = wm831x_set_bits(wm831x, WM831X_CHARGER_CONTROL_1,
 			      WM831X_CHG_ENA_MASK |
 			      WM831X_CHG_FAST_MASK |
-			      WM831X_CHG_ITERM_MASK |
 			      WM831X_CHG_ITERM_MASK,
 			      reg1);
 	if (ret != 0)
@@ -612,6 +611,7 @@
 	power_supply_unregister(&wm831x_power->battery);
 	power_supply_unregister(&wm831x_power->wall);
 	power_supply_unregister(&wm831x_power->usb);
+	kfree(wm831x_power);
 	return 0;
 }
 
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 48ca713..2785a0f 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -765,15 +765,15 @@
 	  AT32AP700x family processors.
 
 config RTC_DRV_AT91RM9200
-	tristate "AT91RM9200 or AT91SAM9RL"
-	depends on ARCH_AT91RM9200 || ARCH_AT91SAM9RL
+	tristate "AT91RM9200 or some AT91SAM9 RTC"
+	depends on ARCH_AT91RM9200 || ARCH_AT91SAM9RL || ARCH_AT91SAM9G45
 	help
 	  Driver for the internal RTC (Realtime Clock) module found on
-	  Atmel AT91RM9200's and AT91SAM9RL chips. On SAM9RL chips
+	  Atmel AT91RM9200's and some  AT91SAM9 chips. On AT91SAM9 chips
 	  this is powered by the backup power supply.
 
 config RTC_DRV_AT91SAM9
-	tristate "AT91SAM9x/AT91CAP9"
+	tristate "AT91SAM9x/AT91CAP9 RTT as RTC"
 	depends on ARCH_AT91 && !(ARCH_AT91RM9200 || ARCH_AT91X40)
 	help
 	  RTC driver for the Atmel AT91SAM9x and AT91CAP9 internal RTT
@@ -781,8 +781,8 @@
 	  supply (such as a small coin cell battery), but do not need to
 	  be used as RTCs.
 
-	  (On AT91SAM9rl chips you probably want to use the dedicated RTC
-	  module and leave the RTT available for other uses.)
+	  (On AT91SAM9rl and AT91SAM9G45 chips you probably want to use the
+	  dedicated RTC module and leave the RTT available for other uses.)
 
 config RTC_DRV_AT91SAM9_RTT
 	int
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 9278164..aff9dcd 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -1410,6 +1410,33 @@
 	  Currently, only 8250 compatible ports are supported, but
 	  others can easily be added.
 
+config SERIAL_OMAP
+	tristate "OMAP serial port support"
+	depends on ARCH_OMAP2 || ARCH_OMAP3 || ARCH_OMAP4
+	select SERIAL_CORE
+	help
+	  If you have a machine based on an Texas Instruments OMAP CPU you
+	  can enable its onboard serial ports by enabling this option.
+
+	  By enabling this option you take advantage of dma feature available
+	  with the omap-serial driver. DMA support can be enabled from platform
+	  data.
+
+config SERIAL_OMAP_CONSOLE
+	bool "Console on OMAP serial port"
+	depends on SERIAL_OMAP
+	select SERIAL_CORE_CONSOLE
+	help
+	  Select this option if you would like to use omap serial port as
+	  console.
+
+	  Even if you say Y here, the currently visible virtual console
+	  (/dev/tty0) will still be used as the system console by default, but
+	  you can alter that using a kernel command line option such as
+	  "console=ttyOx". (Try "man bootparam" or see the documentation of
+	  your boot loader about how to pass options to the kernel at
+	  boot time.)
+
 config SERIAL_OF_PLATFORM_NWPSERIAL
 	tristate "NWP serial port driver"
 	depends on PPC_OF && PPC_DCR
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 1ca4fd5..c570576 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -88,3 +88,4 @@
 obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o
 obj-$(CONFIG_SERIAL_MRST_MAX3110)	+= mrst_max3110.o
 obj-$(CONFIG_SERIAL_MFD_HSU)	+= mfd.o
+obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o
diff --git a/drivers/serial/omap-serial.c b/drivers/serial/omap-serial.c
new file mode 100644
index 0000000..14365f7
--- /dev/null
+++ b/drivers/serial/omap-serial.c
@@ -0,0 +1,1333 @@
+/*
+ * Driver for OMAP-UART controller.
+ * Based on drivers/serial/8250.c
+ *
+ * Copyright (C) 2010 Texas Instruments.
+ *
+ * Authors:
+ *	Govindraj R	<govindraj.raja@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 as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Note: This driver is made seperate from 8250 driver as we cannot
+ * over load 8250 driver with omap platform specific configuration for
+ * features like DMA, it makes easier to implement features like DMA and
+ * hardware flow control and software flow control configuration with
+ * this driver as required for the omap-platform.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/serial_reg.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/serial_core.h>
+#include <linux/irq.h>
+
+#include <plat/dma.h>
+#include <plat/dmtimer.h>
+#include <plat/omap-serial.h>
+
+static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
+
+/* Forward declaration of functions */
+static void uart_tx_dma_callback(int lch, u16 ch_status, void *data);
+static void serial_omap_rx_timeout(unsigned long uart_no);
+static int serial_omap_start_rxdma(struct uart_omap_port *up);
+
+static inline unsigned int serial_in(struct uart_omap_port *up, int offset)
+{
+	offset <<= up->port.regshift;
+	return readw(up->port.membase + offset);
+}
+
+static inline void serial_out(struct uart_omap_port *up, int offset, int value)
+{
+	offset <<= up->port.regshift;
+	writew(value, up->port.membase + offset);
+}
+
+static inline void serial_omap_clear_fifos(struct uart_omap_port *up)
+{
+	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
+		       UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+	serial_out(up, UART_FCR, 0);
+}
+
+/*
+ * serial_omap_get_divisor - calculate divisor value
+ * @port: uart port info
+ * @baud: baudrate for which divisor needs to be calculated.
+ *
+ * We have written our own function to get the divisor so as to support
+ * 13x mode. 3Mbps Baudrate as an different divisor.
+ * Reference OMAP TRM Chapter 17:
+ * Table 17-1. UART Mode Baud Rates, Divisor Values, and Error Rates
+ * referring to oversampling - divisor value
+ * baudrate 460,800 to 3,686,400 all have divisor 13
+ * except 3,000,000 which has divisor value 16
+ */
+static unsigned int
+serial_omap_get_divisor(struct uart_port *port, unsigned int baud)
+{
+	unsigned int divisor;
+
+	if (baud > OMAP_MODE13X_SPEED && baud != 3000000)
+		divisor = 13;
+	else
+		divisor = 16;
+	return port->uartclk/(baud * divisor);
+}
+
+static void serial_omap_stop_rxdma(struct uart_omap_port *up)
+{
+	if (up->uart_dma.rx_dma_used) {
+		del_timer(&up->uart_dma.rx_timer);
+		omap_stop_dma(up->uart_dma.rx_dma_channel);
+		omap_free_dma(up->uart_dma.rx_dma_channel);
+		up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE;
+		up->uart_dma.rx_dma_used = false;
+	}
+}
+
+static void serial_omap_enable_ms(struct uart_port *port)
+{
+	struct uart_omap_port *up = (struct uart_omap_port *)port;
+
+	dev_dbg(up->port.dev, "serial_omap_enable_ms+%d\n", up->pdev->id);
+	up->ier |= UART_IER_MSI;
+	serial_out(up, UART_IER, up->ier);
+}
+
+static void serial_omap_stop_tx(struct uart_port *port)
+{
+	struct uart_omap_port *up = (struct uart_omap_port *)port;
+
+	if (up->use_dma &&
+		up->uart_dma.tx_dma_channel != OMAP_UART_DMA_CH_FREE) {
+		/*
+		 * Check if dma is still active. If yes do nothing,
+		 * return. Else stop dma
+		 */
+		if (omap_get_dma_active_status(up->uart_dma.tx_dma_channel))
+			return;
+		omap_stop_dma(up->uart_dma.tx_dma_channel);
+		omap_free_dma(up->uart_dma.tx_dma_channel);
+		up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE;
+	}
+
+	if (up->ier & UART_IER_THRI) {
+		up->ier &= ~UART_IER_THRI;
+		serial_out(up, UART_IER, up->ier);
+	}
+}
+
+static void serial_omap_stop_rx(struct uart_port *port)
+{
+	struct uart_omap_port *up = (struct uart_omap_port *)port;
+
+	if (up->use_dma)
+		serial_omap_stop_rxdma(up);
+	up->ier &= ~UART_IER_RLSI;
+	up->port.read_status_mask &= ~UART_LSR_DR;
+	serial_out(up, UART_IER, up->ier);
+}
+
+static inline void receive_chars(struct uart_omap_port *up, int *status)
+{
+	struct tty_struct *tty = up->port.state->port.tty;
+	unsigned int flag;
+	unsigned char ch, lsr = *status;
+	int max_count = 256;
+
+	do {
+		if (likely(lsr & UART_LSR_DR))
+			ch = serial_in(up, UART_RX);
+		flag = TTY_NORMAL;
+		up->port.icount.rx++;
+
+		if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) {
+			/*
+			 * For statistics only
+			 */
+			if (lsr & UART_LSR_BI) {
+				lsr &= ~(UART_LSR_FE | UART_LSR_PE);
+				up->port.icount.brk++;
+				/*
+				 * We do the SysRQ and SAK checking
+				 * here because otherwise the break
+				 * may get masked by ignore_status_mask
+				 * or read_status_mask.
+				 */
+				if (uart_handle_break(&up->port))
+					goto ignore_char;
+			} else if (lsr & UART_LSR_PE) {
+				up->port.icount.parity++;
+			} else if (lsr & UART_LSR_FE) {
+				up->port.icount.frame++;
+			}
+
+			if (lsr & UART_LSR_OE)
+				up->port.icount.overrun++;
+
+			/*
+			 * Mask off conditions which should be ignored.
+			 */
+			lsr &= up->port.read_status_mask;
+
+#ifdef CONFIG_SERIAL_OMAP_CONSOLE
+			if (up->port.line == up->port.cons->index) {
+				/* Recover the break flag from console xmit */
+				lsr |= up->lsr_break_flag;
+				up->lsr_break_flag = 0;
+			}
+#endif
+			if (lsr & UART_LSR_BI)
+				flag = TTY_BREAK;
+			else if (lsr & UART_LSR_PE)
+				flag = TTY_PARITY;
+			else if (lsr & UART_LSR_FE)
+				flag = TTY_FRAME;
+		}
+
+		if (uart_handle_sysrq_char(&up->port, ch))
+			goto ignore_char;
+		uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag);
+ignore_char:
+		lsr = serial_in(up, UART_LSR);
+	} while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0));
+	spin_unlock(&up->port.lock);
+	tty_flip_buffer_push(tty);
+	spin_lock(&up->port.lock);
+}
+
+static void transmit_chars(struct uart_omap_port *up)
+{
+	struct circ_buf *xmit = &up->port.state->xmit;
+	int count;
+
+	if (up->port.x_char) {
+		serial_out(up, UART_TX, up->port.x_char);
+		up->port.icount.tx++;
+		up->port.x_char = 0;
+		return;
+	}
+	if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
+		serial_omap_stop_tx(&up->port);
+		return;
+	}
+	count = up->port.fifosize / 4;
+	do {
+		serial_out(up, UART_TX, xmit->buf[xmit->tail]);
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		up->port.icount.tx++;
+		if (uart_circ_empty(xmit))
+			break;
+	} while (--count > 0);
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(&up->port);
+
+	if (uart_circ_empty(xmit))
+		serial_omap_stop_tx(&up->port);
+}
+
+static inline void serial_omap_enable_ier_thri(struct uart_omap_port *up)
+{
+	if (!(up->ier & UART_IER_THRI)) {
+		up->ier |= UART_IER_THRI;
+		serial_out(up, UART_IER, up->ier);
+	}
+}
+
+static void serial_omap_start_tx(struct uart_port *port)
+{
+	struct uart_omap_port *up = (struct uart_omap_port *)port;
+	struct circ_buf *xmit;
+	unsigned int start;
+	int ret = 0;
+
+	if (!up->use_dma) {
+		serial_omap_enable_ier_thri(up);
+		return;
+	}
+
+	if (up->uart_dma.tx_dma_used)
+		return;
+
+	xmit = &up->port.state->xmit;
+
+	if (up->uart_dma.tx_dma_channel == OMAP_UART_DMA_CH_FREE) {
+		ret = omap_request_dma(up->uart_dma.uart_dma_tx,
+				"UART Tx DMA",
+				(void *)uart_tx_dma_callback, up,
+				&(up->uart_dma.tx_dma_channel));
+
+		if (ret < 0) {
+			serial_omap_enable_ier_thri(up);
+			return;
+		}
+	}
+	spin_lock(&(up->uart_dma.tx_lock));
+	up->uart_dma.tx_dma_used = true;
+	spin_unlock(&(up->uart_dma.tx_lock));
+
+	start = up->uart_dma.tx_buf_dma_phys +
+				(xmit->tail & (UART_XMIT_SIZE - 1));
+
+	up->uart_dma.tx_buf_size = uart_circ_chars_pending(xmit);
+	/*
+	 * It is a circular buffer. See if the buffer has wounded back.
+	 * If yes it will have to be transferred in two separate dma
+	 * transfers
+	 */
+	if (start + up->uart_dma.tx_buf_size >=
+			up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE)
+		up->uart_dma.tx_buf_size =
+			(up->uart_dma.tx_buf_dma_phys +
+			UART_XMIT_SIZE) - start;
+
+	omap_set_dma_dest_params(up->uart_dma.tx_dma_channel, 0,
+				OMAP_DMA_AMODE_CONSTANT,
+				up->uart_dma.uart_base, 0, 0);
+	omap_set_dma_src_params(up->uart_dma.tx_dma_channel, 0,
+				OMAP_DMA_AMODE_POST_INC, start, 0, 0);
+	omap_set_dma_transfer_params(up->uart_dma.tx_dma_channel,
+				OMAP_DMA_DATA_TYPE_S8,
+				up->uart_dma.tx_buf_size, 1,
+				OMAP_DMA_SYNC_ELEMENT,
+				up->uart_dma.uart_dma_tx, 0);
+	/* FIXME: Cache maintenance needed here? */
+	omap_start_dma(up->uart_dma.tx_dma_channel);
+}
+
+static unsigned int check_modem_status(struct uart_omap_port *up)
+{
+	unsigned int status;
+
+	status = serial_in(up, UART_MSR);
+	status |= up->msr_saved_flags;
+	up->msr_saved_flags = 0;
+	if ((status & UART_MSR_ANY_DELTA) == 0)
+		return status;
+
+	if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI &&
+	    up->port.state != NULL) {
+		if (status & UART_MSR_TERI)
+			up->port.icount.rng++;
+		if (status & UART_MSR_DDSR)
+			up->port.icount.dsr++;
+		if (status & UART_MSR_DDCD)
+			uart_handle_dcd_change
+				(&up->port, status & UART_MSR_DCD);
+		if (status & UART_MSR_DCTS)
+			uart_handle_cts_change
+				(&up->port, status & UART_MSR_CTS);
+		wake_up_interruptible(&up->port.state->port.delta_msr_wait);
+	}
+
+	return status;
+}
+
+/**
+ * serial_omap_irq() - This handles the interrupt from one port
+ * @irq: uart port irq number
+ * @dev_id: uart port info
+ */
+static inline irqreturn_t serial_omap_irq(int irq, void *dev_id)
+{
+	struct uart_omap_port *up = dev_id;
+	unsigned int iir, lsr;
+	unsigned long flags;
+
+	iir = serial_in(up, UART_IIR);
+	if (iir & UART_IIR_NO_INT)
+		return IRQ_NONE;
+
+	spin_lock_irqsave(&up->port.lock, flags);
+	lsr = serial_in(up, UART_LSR);
+	if (iir & UART_IIR_RLSI) {
+		if (!up->use_dma) {
+			if (lsr & UART_LSR_DR)
+				receive_chars(up, &lsr);
+		} else {
+			up->ier &= ~(UART_IER_RDI | UART_IER_RLSI);
+			serial_out(up, UART_IER, up->ier);
+			if ((serial_omap_start_rxdma(up) != 0) &&
+					(lsr & UART_LSR_DR))
+				receive_chars(up, &lsr);
+		}
+	}
+
+	check_modem_status(up);
+	if ((lsr & UART_LSR_THRE) && (iir & UART_IIR_THRI))
+		transmit_chars(up);
+
+	spin_unlock_irqrestore(&up->port.lock, flags);
+	up->port_activity = jiffies;
+	return IRQ_HANDLED;
+}
+
+static unsigned int serial_omap_tx_empty(struct uart_port *port)
+{
+	struct uart_omap_port *up = (struct uart_omap_port *)port;
+	unsigned long flags = 0;
+	unsigned int ret = 0;
+
+	dev_dbg(up->port.dev, "serial_omap_tx_empty+%d\n", up->pdev->id);
+	spin_lock_irqsave(&up->port.lock, flags);
+	ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
+	spin_unlock_irqrestore(&up->port.lock, flags);
+
+	return ret;
+}
+
+static unsigned int serial_omap_get_mctrl(struct uart_port *port)
+{
+	struct uart_omap_port *up = (struct uart_omap_port *)port;
+	unsigned char status;
+	unsigned int ret = 0;
+
+	status = check_modem_status(up);
+	dev_dbg(up->port.dev, "serial_omap_get_mctrl+%d\n", up->pdev->id);
+
+	if (status & UART_MSR_DCD)
+		ret |= TIOCM_CAR;
+	if (status & UART_MSR_RI)
+		ret |= TIOCM_RNG;
+	if (status & UART_MSR_DSR)
+		ret |= TIOCM_DSR;
+	if (status & UART_MSR_CTS)
+		ret |= TIOCM_CTS;
+	return ret;
+}
+
+static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+	struct uart_omap_port *up = (struct uart_omap_port *)port;
+	unsigned char mcr = 0;
+
+	dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->pdev->id);
+	if (mctrl & TIOCM_RTS)
+		mcr |= UART_MCR_RTS;
+	if (mctrl & TIOCM_DTR)
+		mcr |= UART_MCR_DTR;
+	if (mctrl & TIOCM_OUT1)
+		mcr |= UART_MCR_OUT1;
+	if (mctrl & TIOCM_OUT2)
+		mcr |= UART_MCR_OUT2;
+	if (mctrl & TIOCM_LOOP)
+		mcr |= UART_MCR_LOOP;
+
+	mcr |= up->mcr;
+	serial_out(up, UART_MCR, mcr);
+}
+
+static void serial_omap_break_ctl(struct uart_port *port, int break_state)
+{
+	struct uart_omap_port *up = (struct uart_omap_port *)port;
+	unsigned long flags = 0;
+
+	dev_dbg(up->port.dev, "serial_omap_break_ctl+%d\n", up->pdev->id);
+	spin_lock_irqsave(&up->port.lock, flags);
+	if (break_state == -1)
+		up->lcr |= UART_LCR_SBC;
+	else
+		up->lcr &= ~UART_LCR_SBC;
+	serial_out(up, UART_LCR, up->lcr);
+	spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+static int serial_omap_startup(struct uart_port *port)
+{
+	struct uart_omap_port *up = (struct uart_omap_port *)port;
+	unsigned long flags = 0;
+	int retval;
+
+	/*
+	 * Allocate the IRQ
+	 */
+	retval = request_irq(up->port.irq, serial_omap_irq, up->port.irqflags,
+				up->name, up);
+	if (retval)
+		return retval;
+
+	dev_dbg(up->port.dev, "serial_omap_startup+%d\n", up->pdev->id);
+
+	/*
+	 * Clear the FIFO buffers and disable them.
+	 * (they will be reenabled in set_termios())
+	 */
+	serial_omap_clear_fifos(up);
+	/* For Hardware flow control */
+	serial_out(up, UART_MCR, UART_MCR_RTS);
+
+	/*
+	 * Clear the interrupt registers.
+	 */
+	(void) serial_in(up, UART_LSR);
+	if (serial_in(up, UART_LSR) & UART_LSR_DR)
+		(void) serial_in(up, UART_RX);
+	(void) serial_in(up, UART_IIR);
+	(void) serial_in(up, UART_MSR);
+
+	/*
+	 * Now, initialize the UART
+	 */
+	serial_out(up, UART_LCR, UART_LCR_WLEN8);
+	spin_lock_irqsave(&up->port.lock, flags);
+	/*
+	 * Most PC uarts need OUT2 raised to enable interrupts.
+	 */
+	up->port.mctrl |= TIOCM_OUT2;
+	serial_omap_set_mctrl(&up->port, up->port.mctrl);
+	spin_unlock_irqrestore(&up->port.lock, flags);
+
+	up->msr_saved_flags = 0;
+	if (up->use_dma) {
+		free_page((unsigned long)up->port.state->xmit.buf);
+		up->port.state->xmit.buf = dma_alloc_coherent(NULL,
+			UART_XMIT_SIZE,
+			(dma_addr_t *)&(up->uart_dma.tx_buf_dma_phys),
+			0);
+		init_timer(&(up->uart_dma.rx_timer));
+		up->uart_dma.rx_timer.function = serial_omap_rx_timeout;
+		up->uart_dma.rx_timer.data = up->pdev->id;
+		/* Currently the buffer size is 4KB. Can increase it */
+		up->uart_dma.rx_buf = dma_alloc_coherent(NULL,
+			up->uart_dma.rx_buf_size,
+			(dma_addr_t *)&(up->uart_dma.rx_buf_dma_phys), 0);
+	}
+	/*
+	 * Finally, enable interrupts. Note: Modem status interrupts
+	 * are set via set_termios(), which will be occurring imminently
+	 * anyway, so we don't enable them here.
+	 */
+	up->ier = UART_IER_RLSI | UART_IER_RDI;
+	serial_out(up, UART_IER, up->ier);
+
+	up->port_activity = jiffies;
+	return 0;
+}
+
+static void serial_omap_shutdown(struct uart_port *port)
+{
+	struct uart_omap_port *up = (struct uart_omap_port *)port;
+	unsigned long flags = 0;
+
+	dev_dbg(up->port.dev, "serial_omap_shutdown+%d\n", up->pdev->id);
+	/*
+	 * Disable interrupts from this port
+	 */
+	up->ier = 0;
+	serial_out(up, UART_IER, 0);
+
+	spin_lock_irqsave(&up->port.lock, flags);
+	up->port.mctrl &= ~TIOCM_OUT2;
+	serial_omap_set_mctrl(&up->port, up->port.mctrl);
+	spin_unlock_irqrestore(&up->port.lock, flags);
+
+	/*
+	 * Disable break condition and FIFOs
+	 */
+	serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
+	serial_omap_clear_fifos(up);
+
+	/*
+	 * Read data port to reset things, and then free the irq
+	 */
+	if (serial_in(up, UART_LSR) & UART_LSR_DR)
+		(void) serial_in(up, UART_RX);
+	if (up->use_dma) {
+		dma_free_coherent(up->port.dev,
+			UART_XMIT_SIZE,	up->port.state->xmit.buf,
+			up->uart_dma.tx_buf_dma_phys);
+		up->port.state->xmit.buf = NULL;
+		serial_omap_stop_rx(port);
+		dma_free_coherent(up->port.dev,
+			up->uart_dma.rx_buf_size, up->uart_dma.rx_buf,
+			up->uart_dma.rx_buf_dma_phys);
+		up->uart_dma.rx_buf = NULL;
+	}
+	free_irq(up->port.irq, up);
+}
+
+static inline void
+serial_omap_configure_xonxoff
+		(struct uart_omap_port *up, struct ktermios *termios)
+{
+	unsigned char efr = 0;
+
+	up->lcr = serial_in(up, UART_LCR);
+	serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+	up->efr = serial_in(up, UART_EFR);
+	serial_out(up, UART_EFR, up->efr & ~UART_EFR_ECB);
+
+	serial_out(up, UART_XON1, termios->c_cc[VSTART]);
+	serial_out(up, UART_XOFF1, termios->c_cc[VSTOP]);
+
+	/* clear SW control mode bits */
+	efr = up->efr;
+	efr &= OMAP_UART_SW_CLR;
+
+	/*
+	 * IXON Flag:
+	 * Enable XON/XOFF flow control on output.
+	 * Transmit XON1, XOFF1
+	 */
+	if (termios->c_iflag & IXON)
+		efr |= OMAP_UART_SW_TX;
+
+	/*
+	 * IXOFF Flag:
+	 * Enable XON/XOFF flow control on input.
+	 * Receiver compares XON1, XOFF1.
+	 */
+	if (termios->c_iflag & IXOFF)
+		efr |= OMAP_UART_SW_RX;
+
+	serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
+	serial_out(up, UART_LCR, UART_LCR_DLAB);
+
+	up->mcr = serial_in(up, UART_MCR);
+
+	/*
+	 * IXANY Flag:
+	 * Enable any character to restart output.
+	 * Operation resumes after receiving any
+	 * character after recognition of the XOFF character
+	 */
+	if (termios->c_iflag & IXANY)
+		up->mcr |= UART_MCR_XONANY;
+
+	serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
+	serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+	serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
+	/* Enable special char function UARTi.EFR_REG[5] and
+	 * load the new software flow control mode IXON or IXOFF
+	 * and restore the UARTi.EFR_REG[4] ENHANCED_EN value.
+	 */
+	serial_out(up, UART_EFR, efr | UART_EFR_SCD);
+	serial_out(up, UART_LCR, UART_LCR_DLAB);
+
+	serial_out(up, UART_MCR, up->mcr & ~UART_MCR_TCRTLR);
+	serial_out(up, UART_LCR, up->lcr);
+}
+
+static void
+serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
+			struct ktermios *old)
+{
+	struct uart_omap_port *up = (struct uart_omap_port *)port;
+	unsigned char cval = 0;
+	unsigned char efr = 0;
+	unsigned long flags = 0;
+	unsigned int baud, quot;
+
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		cval = UART_LCR_WLEN5;
+		break;
+	case CS6:
+		cval = UART_LCR_WLEN6;
+		break;
+	case CS7:
+		cval = UART_LCR_WLEN7;
+		break;
+	default:
+	case CS8:
+		cval = UART_LCR_WLEN8;
+		break;
+	}
+
+	if (termios->c_cflag & CSTOPB)
+		cval |= UART_LCR_STOP;
+	if (termios->c_cflag & PARENB)
+		cval |= UART_LCR_PARITY;
+	if (!(termios->c_cflag & PARODD))
+		cval |= UART_LCR_EPAR;
+
+	/*
+	 * Ask the core to calculate the divisor for us.
+	 */
+
+	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/13);
+	quot = serial_omap_get_divisor(port, baud);
+
+	up->fcr = UART_FCR_R_TRIG_01 | UART_FCR_T_TRIG_01 |
+			UART_FCR_ENABLE_FIFO;
+	if (up->use_dma)
+		up->fcr |= UART_FCR_DMA_SELECT;
+
+	/*
+	 * Ok, we're now changing the port state. Do it with
+	 * interrupts disabled.
+	 */
+	spin_lock_irqsave(&up->port.lock, flags);
+
+	/*
+	 * Update the per-port timeout.
+	 */
+	uart_update_timeout(port, termios->c_cflag, baud);
+
+	up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
+	if (termios->c_iflag & INPCK)
+		up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
+	if (termios->c_iflag & (BRKINT | PARMRK))
+		up->port.read_status_mask |= UART_LSR_BI;
+
+	/*
+	 * Characters to ignore
+	 */
+	up->port.ignore_status_mask = 0;
+	if (termios->c_iflag & IGNPAR)
+		up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
+	if (termios->c_iflag & IGNBRK) {
+		up->port.ignore_status_mask |= UART_LSR_BI;
+		/*
+		 * If we're ignoring parity and break indicators,
+		 * ignore overruns too (for real raw support).
+		 */
+		if (termios->c_iflag & IGNPAR)
+			up->port.ignore_status_mask |= UART_LSR_OE;
+	}
+
+	/*
+	 * ignore all characters if CREAD is not set
+	 */
+	if ((termios->c_cflag & CREAD) == 0)
+		up->port.ignore_status_mask |= UART_LSR_DR;
+
+	/*
+	 * Modem status interrupts
+	 */
+	up->ier &= ~UART_IER_MSI;
+	if (UART_ENABLE_MS(&up->port, termios->c_cflag))
+		up->ier |= UART_IER_MSI;
+	serial_out(up, UART_IER, up->ier);
+	serial_out(up, UART_LCR, cval);		/* reset DLAB */
+
+	/* FIFOs and DMA Settings */
+
+	/* FCR can be changed only when the
+	 * baud clock is not running
+	 * DLL_REG and DLH_REG set to 0.
+	 */
+	serial_out(up, UART_LCR, UART_LCR_DLAB);
+	serial_out(up, UART_DLL, 0);
+	serial_out(up, UART_DLM, 0);
+	serial_out(up, UART_LCR, 0);
+
+	serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+
+	up->efr = serial_in(up, UART_EFR);
+	serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
+
+	serial_out(up, UART_LCR, UART_LCR_DLAB);
+	up->mcr = serial_in(up, UART_MCR);
+	serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
+	/* FIFO ENABLE, DMA MODE */
+	serial_out(up, UART_FCR, up->fcr);
+	serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+
+	if (up->use_dma) {
+		serial_out(up, UART_TI752_TLR, 0);
+		serial_out(up, UART_OMAP_SCR,
+			(UART_FCR_TRIGGER_4 | UART_FCR_TRIGGER_8));
+	}
+
+	serial_out(up, UART_EFR, up->efr);
+	serial_out(up, UART_LCR, UART_LCR_DLAB);
+	serial_out(up, UART_MCR, up->mcr);
+
+	/* Protocol, Baud Rate, and Interrupt Settings */
+
+	serial_out(up, UART_OMAP_MDR1, OMAP_MDR1_DISABLE);
+	serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+
+	up->efr = serial_in(up, UART_EFR);
+	serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
+
+	serial_out(up, UART_LCR, 0);
+	serial_out(up, UART_IER, 0);
+	serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+
+	serial_out(up, UART_DLL, quot & 0xff);          /* LS of divisor */
+	serial_out(up, UART_DLM, quot >> 8);            /* MS of divisor */
+
+	serial_out(up, UART_LCR, 0);
+	serial_out(up, UART_IER, up->ier);
+	serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+
+	serial_out(up, UART_EFR, up->efr);
+	serial_out(up, UART_LCR, cval);
+
+	if (baud > 230400 && baud != 3000000)
+		serial_out(up, UART_OMAP_MDR1, OMAP_MDR1_MODE13X);
+	else
+		serial_out(up, UART_OMAP_MDR1, OMAP_MDR1_MODE16X);
+
+	/* Hardware Flow Control Configuration */
+
+	if (termios->c_cflag & CRTSCTS) {
+		efr |= (UART_EFR_CTS | UART_EFR_RTS);
+		serial_out(up, UART_LCR, UART_LCR_DLAB);
+
+		up->mcr = serial_in(up, UART_MCR);
+		serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
+
+		serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+		up->efr = serial_in(up, UART_EFR);
+		serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
+
+		serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
+		serial_out(up, UART_EFR, efr); /* Enable AUTORTS and AUTOCTS */
+		serial_out(up, UART_LCR, UART_LCR_DLAB);
+		serial_out(up, UART_MCR, up->mcr | UART_MCR_RTS);
+		serial_out(up, UART_LCR, cval);
+	}
+
+	serial_omap_set_mctrl(&up->port, up->port.mctrl);
+	/* Software Flow Control Configuration */
+	if (termios->c_iflag & (IXON | IXOFF))
+		serial_omap_configure_xonxoff(up, termios);
+
+	spin_unlock_irqrestore(&up->port.lock, flags);
+	dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->pdev->id);
+}
+
+static void
+serial_omap_pm(struct uart_port *port, unsigned int state,
+	       unsigned int oldstate)
+{
+	struct uart_omap_port *up = (struct uart_omap_port *)port;
+	unsigned char efr;
+
+	dev_dbg(up->port.dev, "serial_omap_pm+%d\n", up->pdev->id);
+	serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+	efr = serial_in(up, UART_EFR);
+	serial_out(up, UART_EFR, efr | UART_EFR_ECB);
+	serial_out(up, UART_LCR, 0);
+
+	serial_out(up, UART_IER, (state != 0) ? UART_IERX_SLEEP : 0);
+	serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+	serial_out(up, UART_EFR, efr);
+	serial_out(up, UART_LCR, 0);
+	/* Enable module level wake up */
+	serial_out(up, UART_OMAP_WER,
+		(state != 0) ? OMAP_UART_WER_MOD_WKUP : 0);
+}
+
+static void serial_omap_release_port(struct uart_port *port)
+{
+	dev_dbg(port->dev, "serial_omap_release_port+\n");
+}
+
+static int serial_omap_request_port(struct uart_port *port)
+{
+	dev_dbg(port->dev, "serial_omap_request_port+\n");
+	return 0;
+}
+
+static void serial_omap_config_port(struct uart_port *port, int flags)
+{
+	struct uart_omap_port *up = (struct uart_omap_port *)port;
+
+	dev_dbg(up->port.dev, "serial_omap_config_port+%d\n",
+							up->pdev->id);
+	up->port.type = PORT_OMAP;
+}
+
+static int
+serial_omap_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+	/* we don't want the core code to modify any port params */
+	dev_dbg(port->dev, "serial_omap_verify_port+\n");
+	return -EINVAL;
+}
+
+static const char *
+serial_omap_type(struct uart_port *port)
+{
+	struct uart_omap_port *up = (struct uart_omap_port *)port;
+
+	dev_dbg(up->port.dev, "serial_omap_type+%d\n", up->pdev->id);
+	return up->name;
+}
+
+#ifdef CONFIG_SERIAL_OMAP_CONSOLE
+
+static struct uart_omap_port *serial_omap_console_ports[4];
+
+static struct uart_driver serial_omap_reg;
+
+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+static inline void wait_for_xmitr(struct uart_omap_port *up)
+{
+	unsigned int status, tmout = 10000;
+
+	/* Wait up to 10ms for the character(s) to be sent. */
+	do {
+		status = serial_in(up, UART_LSR);
+
+		if (status & UART_LSR_BI)
+			up->lsr_break_flag = UART_LSR_BI;
+
+		if (--tmout == 0)
+			break;
+		udelay(1);
+	} while ((status & BOTH_EMPTY) != BOTH_EMPTY);
+
+	/* Wait up to 1s for flow control if necessary */
+	if (up->port.flags & UPF_CONS_FLOW) {
+		tmout = 1000000;
+		for (tmout = 1000000; tmout; tmout--) {
+			unsigned int msr = serial_in(up, UART_MSR);
+
+			up->msr_saved_flags |= msr & MSR_SAVE_FLAGS;
+			if (msr & UART_MSR_CTS)
+				break;
+
+			udelay(1);
+		}
+	}
+}
+
+static void serial_omap_console_putchar(struct uart_port *port, int ch)
+{
+	struct uart_omap_port *up = (struct uart_omap_port *)port;
+
+	wait_for_xmitr(up);
+	serial_out(up, UART_TX, ch);
+}
+
+static void
+serial_omap_console_write(struct console *co, const char *s,
+		unsigned int count)
+{
+	struct uart_omap_port *up = serial_omap_console_ports[co->index];
+	unsigned long flags;
+	unsigned int ier;
+	int locked = 1;
+
+	local_irq_save(flags);
+	if (up->port.sysrq)
+		locked = 0;
+	else if (oops_in_progress)
+		locked = spin_trylock(&up->port.lock);
+	else
+		spin_lock(&up->port.lock);
+
+	/*
+	 * First save the IER then disable the interrupts
+	 */
+	ier = serial_in(up, UART_IER);
+	serial_out(up, UART_IER, 0);
+
+	uart_console_write(&up->port, s, count, serial_omap_console_putchar);
+
+	/*
+	 * Finally, wait for transmitter to become empty
+	 * and restore the IER
+	 */
+	wait_for_xmitr(up);
+	serial_out(up, UART_IER, ier);
+	/*
+	 * The receive handling will happen properly because the
+	 * receive ready bit will still be set; it is not cleared
+	 * on read.  However, modem control will not, we must
+	 * call it if we have saved something in the saved flags
+	 * while processing with interrupts off.
+	 */
+	if (up->msr_saved_flags)
+		check_modem_status(up);
+
+	if (locked)
+		spin_unlock(&up->port.lock);
+	local_irq_restore(flags);
+}
+
+static int __init
+serial_omap_console_setup(struct console *co, char *options)
+{
+	struct uart_omap_port *up;
+	int baud = 115200;
+	int bits = 8;
+	int parity = 'n';
+	int flow = 'n';
+
+	if (serial_omap_console_ports[co->index] == NULL)
+		return -ENODEV;
+	up = serial_omap_console_ports[co->index];
+
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+	return uart_set_options(&up->port, co, baud, parity, bits, flow);
+}
+
+static struct console serial_omap_console = {
+	.name		= OMAP_SERIAL_NAME,
+	.write		= serial_omap_console_write,
+	.device		= uart_console_device,
+	.setup		= serial_omap_console_setup,
+	.flags		= CON_PRINTBUFFER,
+	.index		= -1,
+	.data		= &serial_omap_reg,
+};
+
+static void serial_omap_add_console_port(struct uart_omap_port *up)
+{
+	serial_omap_console_ports[up->pdev->id] = up;
+}
+
+#define OMAP_CONSOLE	(&serial_omap_console)
+
+#else
+
+#define OMAP_CONSOLE	NULL
+
+static inline void serial_omap_add_console_port(struct uart_omap_port *up)
+{}
+
+#endif
+
+static struct uart_ops serial_omap_pops = {
+	.tx_empty	= serial_omap_tx_empty,
+	.set_mctrl	= serial_omap_set_mctrl,
+	.get_mctrl	= serial_omap_get_mctrl,
+	.stop_tx	= serial_omap_stop_tx,
+	.start_tx	= serial_omap_start_tx,
+	.stop_rx	= serial_omap_stop_rx,
+	.enable_ms	= serial_omap_enable_ms,
+	.break_ctl	= serial_omap_break_ctl,
+	.startup	= serial_omap_startup,
+	.shutdown	= serial_omap_shutdown,
+	.set_termios	= serial_omap_set_termios,
+	.pm		= serial_omap_pm,
+	.type		= serial_omap_type,
+	.release_port	= serial_omap_release_port,
+	.request_port	= serial_omap_request_port,
+	.config_port	= serial_omap_config_port,
+	.verify_port	= serial_omap_verify_port,
+};
+
+static struct uart_driver serial_omap_reg = {
+	.owner		= THIS_MODULE,
+	.driver_name	= "OMAP-SERIAL",
+	.dev_name	= OMAP_SERIAL_NAME,
+	.nr		= OMAP_MAX_HSUART_PORTS,
+	.cons		= OMAP_CONSOLE,
+};
+
+static int
+serial_omap_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct uart_omap_port *up = platform_get_drvdata(pdev);
+
+	if (up)
+		uart_suspend_port(&serial_omap_reg, &up->port);
+	return 0;
+}
+
+static int serial_omap_resume(struct platform_device *dev)
+{
+	struct uart_omap_port *up = platform_get_drvdata(dev);
+
+	if (up)
+		uart_resume_port(&serial_omap_reg, &up->port);
+	return 0;
+}
+
+static void serial_omap_rx_timeout(unsigned long uart_no)
+{
+	struct uart_omap_port *up = ui[uart_no];
+	unsigned int curr_dma_pos, curr_transmitted_size;
+	int ret = 0;
+
+	curr_dma_pos = omap_get_dma_dst_pos(up->uart_dma.rx_dma_channel);
+	if ((curr_dma_pos == up->uart_dma.prev_rx_dma_pos) ||
+			     (curr_dma_pos == 0)) {
+		if (jiffies_to_msecs(jiffies - up->port_activity) <
+							RX_TIMEOUT) {
+			mod_timer(&up->uart_dma.rx_timer, jiffies +
+				usecs_to_jiffies(up->uart_dma.rx_timeout));
+		} else {
+			serial_omap_stop_rxdma(up);
+			up->ier |= (UART_IER_RDI | UART_IER_RLSI);
+			serial_out(up, UART_IER, up->ier);
+		}
+		return;
+	}
+
+	curr_transmitted_size = curr_dma_pos -
+					up->uart_dma.prev_rx_dma_pos;
+	up->port.icount.rx += curr_transmitted_size;
+	tty_insert_flip_string(up->port.state->port.tty,
+			up->uart_dma.rx_buf +
+			(up->uart_dma.prev_rx_dma_pos -
+			up->uart_dma.rx_buf_dma_phys),
+			curr_transmitted_size);
+	tty_flip_buffer_push(up->port.state->port.tty);
+	up->uart_dma.prev_rx_dma_pos = curr_dma_pos;
+	if (up->uart_dma.rx_buf_size +
+			up->uart_dma.rx_buf_dma_phys == curr_dma_pos) {
+		ret = serial_omap_start_rxdma(up);
+		if (ret < 0) {
+			serial_omap_stop_rxdma(up);
+			up->ier |= (UART_IER_RDI | UART_IER_RLSI);
+			serial_out(up, UART_IER, up->ier);
+		}
+	} else  {
+		mod_timer(&up->uart_dma.rx_timer, jiffies +
+			usecs_to_jiffies(up->uart_dma.rx_timeout));
+	}
+	up->port_activity = jiffies;
+}
+
+static void uart_rx_dma_callback(int lch, u16 ch_status, void *data)
+{
+	return;
+}
+
+static int serial_omap_start_rxdma(struct uart_omap_port *up)
+{
+	int ret = 0;
+
+	if (up->uart_dma.rx_dma_channel == -1) {
+		ret = omap_request_dma(up->uart_dma.uart_dma_rx,
+				"UART Rx DMA",
+				(void *)uart_rx_dma_callback, up,
+				&(up->uart_dma.rx_dma_channel));
+		if (ret < 0)
+			return ret;
+
+		omap_set_dma_src_params(up->uart_dma.rx_dma_channel, 0,
+				OMAP_DMA_AMODE_CONSTANT,
+				up->uart_dma.uart_base, 0, 0);
+		omap_set_dma_dest_params(up->uart_dma.rx_dma_channel, 0,
+				OMAP_DMA_AMODE_POST_INC,
+				up->uart_dma.rx_buf_dma_phys, 0, 0);
+		omap_set_dma_transfer_params(up->uart_dma.rx_dma_channel,
+				OMAP_DMA_DATA_TYPE_S8,
+				up->uart_dma.rx_buf_size, 1,
+				OMAP_DMA_SYNC_ELEMENT,
+				up->uart_dma.uart_dma_rx, 0);
+	}
+	up->uart_dma.prev_rx_dma_pos = up->uart_dma.rx_buf_dma_phys;
+	/* FIXME: Cache maintenance needed here? */
+	omap_start_dma(up->uart_dma.rx_dma_channel);
+	mod_timer(&up->uart_dma.rx_timer, jiffies +
+				usecs_to_jiffies(up->uart_dma.rx_timeout));
+	up->uart_dma.rx_dma_used = true;
+	return ret;
+}
+
+static void serial_omap_continue_tx(struct uart_omap_port *up)
+{
+	struct circ_buf *xmit = &up->port.state->xmit;
+	unsigned int start = up->uart_dma.tx_buf_dma_phys
+			+ (xmit->tail & (UART_XMIT_SIZE - 1));
+
+	if (uart_circ_empty(xmit))
+		return;
+
+	up->uart_dma.tx_buf_size = uart_circ_chars_pending(xmit);
+	/*
+	 * It is a circular buffer. See if the buffer has wounded back.
+	 * If yes it will have to be transferred in two separate dma
+	 * transfers
+	 */
+	if (start + up->uart_dma.tx_buf_size >=
+			up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE)
+		up->uart_dma.tx_buf_size =
+			(up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE) - start;
+	omap_set_dma_dest_params(up->uart_dma.tx_dma_channel, 0,
+				OMAP_DMA_AMODE_CONSTANT,
+				up->uart_dma.uart_base, 0, 0);
+	omap_set_dma_src_params(up->uart_dma.tx_dma_channel, 0,
+				OMAP_DMA_AMODE_POST_INC, start, 0, 0);
+	omap_set_dma_transfer_params(up->uart_dma.tx_dma_channel,
+				OMAP_DMA_DATA_TYPE_S8,
+				up->uart_dma.tx_buf_size, 1,
+				OMAP_DMA_SYNC_ELEMENT,
+				up->uart_dma.uart_dma_tx, 0);
+	/* FIXME: Cache maintenance needed here? */
+	omap_start_dma(up->uart_dma.tx_dma_channel);
+}
+
+static void uart_tx_dma_callback(int lch, u16 ch_status, void *data)
+{
+	struct uart_omap_port *up = (struct uart_omap_port *)data;
+	struct circ_buf *xmit = &up->port.state->xmit;
+
+	xmit->tail = (xmit->tail + up->uart_dma.tx_buf_size) & \
+			(UART_XMIT_SIZE - 1);
+	up->port.icount.tx += up->uart_dma.tx_buf_size;
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(&up->port);
+
+	if (uart_circ_empty(xmit)) {
+		spin_lock(&(up->uart_dma.tx_lock));
+		serial_omap_stop_tx(&up->port);
+		up->uart_dma.tx_dma_used = false;
+		spin_unlock(&(up->uart_dma.tx_lock));
+	} else {
+		omap_stop_dma(up->uart_dma.tx_dma_channel);
+		serial_omap_continue_tx(up);
+	}
+	up->port_activity = jiffies;
+	return;
+}
+
+static int serial_omap_probe(struct platform_device *pdev)
+{
+	struct uart_omap_port	*up;
+	struct resource		*mem, *irq, *dma_tx, *dma_rx;
+	struct omap_uart_port_info *omap_up_info = pdev->dev.platform_data;
+	int ret = -ENOSPC;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "no mem resource?\n");
+		return -ENODEV;
+	}
+
+	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!irq) {
+		dev_err(&pdev->dev, "no irq resource?\n");
+		return -ENODEV;
+	}
+
+	if (!request_mem_region(mem->start, (mem->end - mem->start) + 1,
+				     pdev->dev.driver->name)) {
+		dev_err(&pdev->dev, "memory region already claimed\n");
+		return -EBUSY;
+	}
+
+	dma_rx = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
+	if (!dma_rx) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	dma_tx = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
+	if (!dma_tx) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	up = kzalloc(sizeof(*up), GFP_KERNEL);
+	if (up == NULL) {
+		ret = -ENOMEM;
+		goto do_release_region;
+	}
+	sprintf(up->name, "OMAP UART%d", pdev->id);
+	up->pdev = pdev;
+	up->port.dev = &pdev->dev;
+	up->port.type = PORT_OMAP;
+	up->port.iotype = UPIO_MEM;
+	up->port.irq = irq->start;
+
+	up->port.regshift = 2;
+	up->port.fifosize = 64;
+	up->port.ops = &serial_omap_pops;
+	up->port.line = pdev->id;
+
+	up->port.membase = omap_up_info->membase;
+	up->port.mapbase = omap_up_info->mapbase;
+	up->port.flags = omap_up_info->flags;
+	up->port.irqflags = omap_up_info->irqflags;
+	up->port.uartclk = omap_up_info->uartclk;
+	up->uart_dma.uart_base = mem->start;
+
+	if (omap_up_info->dma_enabled) {
+		up->uart_dma.uart_dma_tx = dma_tx->start;
+		up->uart_dma.uart_dma_rx = dma_rx->start;
+		up->use_dma = 1;
+		up->uart_dma.rx_buf_size = 4096;
+		up->uart_dma.rx_timeout = 2;
+		spin_lock_init(&(up->uart_dma.tx_lock));
+		spin_lock_init(&(up->uart_dma.rx_lock));
+		up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE;
+		up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE;
+	}
+
+	ui[pdev->id] = up;
+	serial_omap_add_console_port(up);
+
+	ret = uart_add_one_port(&serial_omap_reg, &up->port);
+	if (ret != 0)
+		goto do_release_region;
+
+	platform_set_drvdata(pdev, up);
+	return 0;
+err:
+	dev_err(&pdev->dev, "[UART%d]: failure [%s]: %d\n",
+				pdev->id, __func__, ret);
+do_release_region:
+	release_mem_region(mem->start, (mem->end - mem->start) + 1);
+	return ret;
+}
+
+static int serial_omap_remove(struct platform_device *dev)
+{
+	struct uart_omap_port *up = platform_get_drvdata(dev);
+
+	platform_set_drvdata(dev, NULL);
+	if (up) {
+		uart_remove_one_port(&serial_omap_reg, &up->port);
+		kfree(up);
+	}
+	return 0;
+}
+
+static struct platform_driver serial_omap_driver = {
+	.probe          = serial_omap_probe,
+	.remove         = serial_omap_remove,
+
+	.suspend	= serial_omap_suspend,
+	.resume		= serial_omap_resume,
+	.driver		= {
+		.name	= DRIVER_NAME,
+	},
+};
+
+static int __init serial_omap_init(void)
+{
+	int ret;
+
+	ret = uart_register_driver(&serial_omap_reg);
+	if (ret != 0)
+		return ret;
+	ret = platform_driver_register(&serial_omap_driver);
+	if (ret != 0)
+		uart_unregister_driver(&serial_omap_reg);
+	return ret;
+}
+
+static void __exit serial_omap_exit(void)
+{
+	platform_driver_unregister(&serial_omap_driver);
+	uart_unregister_driver(&serial_omap_reg);
+}
+
+module_init(serial_omap_init);
+module_exit(serial_omap_exit);
+
+MODULE_DESCRIPTION("OMAP High Speed UART driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Texas Instruments Inc");
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 4b9eec6..78f9fd0 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -329,6 +329,13 @@
 	help
 	  SPI driver for Freescale STMP37xx/378x SoC SSP interface
 
+config SPI_TEGRA
+	tristate "Nvidia Tegra SPI controller"
+	depends on ARCH_TEGRA
+	select TEGRA_SYSTEM_DMA
+	help
+	  SPI driver for NVidia Tegra SoCs
+
 config SPI_TOPCLIFF_PCH
 	tristate "Topcliff PCH SPI Controller"
 	depends on PCI
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 557aaad..8bc1a5a 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -39,6 +39,7 @@
 obj-$(CONFIG_SPI_S3C24XX_GPIO)		+= spi_s3c24xx_gpio.o
 obj-$(CONFIG_SPI_S3C24XX)		+= spi_s3c24xx_hw.o
 obj-$(CONFIG_SPI_S3C64XX)		+= spi_s3c64xx.o
+obj-$(CONFIG_SPI_TEGRA)			+= spi_tegra.o
 obj-$(CONFIG_SPI_TOPCLIFF_PCH)		+= spi_topcliff_pch.o
 obj-$(CONFIG_SPI_TXX9)			+= spi_txx9.o
 obj-$(CONFIG_SPI_XILINX)		+= xilinx_spi.o
diff --git a/drivers/spi/spi_tegra.c b/drivers/spi/spi_tegra.c
new file mode 100644
index 0000000..bb7df02
--- /dev/null
+++ b/drivers/spi/spi_tegra.c
@@ -0,0 +1,618 @@
+/*
+ * Driver for Nvidia TEGRA spi controller.
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Erik Gilling <konkers@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include <linux/spi/spi.h>
+
+#include <mach/dma.h>
+
+#define SLINK_COMMAND		0x000
+#define   SLINK_BIT_LENGTH(x)		(((x) & 0x1f) << 0)
+#define   SLINK_WORD_SIZE(x)		(((x) & 0x1f) << 5)
+#define   SLINK_BOTH_EN			(1 << 10)
+#define   SLINK_CS_SW			(1 << 11)
+#define   SLINK_CS_VALUE		(1 << 12)
+#define   SLINK_CS_POLARITY		(1 << 13)
+#define   SLINK_IDLE_SDA_DRIVE_LOW	(0 << 16)
+#define   SLINK_IDLE_SDA_DRIVE_HIGH	(1 << 16)
+#define   SLINK_IDLE_SDA_PULL_LOW	(2 << 16)
+#define   SLINK_IDLE_SDA_PULL_HIGH	(3 << 16)
+#define   SLINK_IDLE_SDA_MASK		(3 << 16)
+#define   SLINK_CS_POLARITY1		(1 << 20)
+#define   SLINK_CK_SDA			(1 << 21)
+#define   SLINK_CS_POLARITY2		(1 << 22)
+#define   SLINK_CS_POLARITY3		(1 << 23)
+#define   SLINK_IDLE_SCLK_DRIVE_LOW	(0 << 24)
+#define   SLINK_IDLE_SCLK_DRIVE_HIGH	(1 << 24)
+#define   SLINK_IDLE_SCLK_PULL_LOW	(2 << 24)
+#define   SLINK_IDLE_SCLK_PULL_HIGH	(3 << 24)
+#define   SLINK_IDLE_SCLK_MASK		(3 << 24)
+#define   SLINK_M_S			(1 << 28)
+#define   SLINK_WAIT			(1 << 29)
+#define   SLINK_GO			(1 << 30)
+#define   SLINK_ENB			(1 << 31)
+
+#define SLINK_COMMAND2		0x004
+#define   SLINK_LSBFE			(1 << 0)
+#define   SLINK_SSOE			(1 << 1)
+#define   SLINK_SPIE			(1 << 4)
+#define   SLINK_BIDIROE			(1 << 6)
+#define   SLINK_MODFEN			(1 << 7)
+#define   SLINK_INT_SIZE(x)		(((x) & 0x1f) << 8)
+#define   SLINK_CS_ACTIVE_BETWEEN	(1 << 17)
+#define   SLINK_SS_EN_CS(x)		(((x) & 0x3) << 18)
+#define   SLINK_SS_SETUP(x)		(((x) & 0x3) << 20)
+#define   SLINK_FIFO_REFILLS_0		(0 << 22)
+#define   SLINK_FIFO_REFILLS_1		(1 << 22)
+#define   SLINK_FIFO_REFILLS_2		(2 << 22)
+#define   SLINK_FIFO_REFILLS_3		(3 << 22)
+#define   SLINK_FIFO_REFILLS_MASK	(3 << 22)
+#define   SLINK_WAIT_PACK_INT(x)	(((x) & 0x7) << 26)
+#define   SLINK_SPC0			(1 << 29)
+#define   SLINK_TXEN			(1 << 30)
+#define   SLINK_RXEN			(1 << 31)
+
+#define SLINK_STATUS		0x008
+#define   SLINK_COUNT(val)		(((val) >> 0) & 0x1f)
+#define   SLINK_WORD(val)		(((val) >> 5) & 0x1f)
+#define   SLINK_BLK_CNT(val)		(((val) >> 0) & 0xffff)
+#define   SLINK_MODF			(1 << 16)
+#define   SLINK_RX_UNF			(1 << 18)
+#define   SLINK_TX_OVF			(1 << 19)
+#define   SLINK_TX_FULL			(1 << 20)
+#define   SLINK_TX_EMPTY		(1 << 21)
+#define   SLINK_RX_FULL			(1 << 22)
+#define   SLINK_RX_EMPTY		(1 << 23)
+#define   SLINK_TX_UNF			(1 << 24)
+#define   SLINK_RX_OVF			(1 << 25)
+#define   SLINK_TX_FLUSH		(1 << 26)
+#define   SLINK_RX_FLUSH		(1 << 27)
+#define   SLINK_SCLK			(1 << 28)
+#define   SLINK_ERR			(1 << 29)
+#define   SLINK_RDY			(1 << 30)
+#define   SLINK_BSY			(1 << 31)
+
+#define SLINK_MAS_DATA		0x010
+#define SLINK_SLAVE_DATA	0x014
+
+#define SLINK_DMA_CTL		0x018
+#define   SLINK_DMA_BLOCK_SIZE(x)	(((x) & 0xffff) << 0)
+#define   SLINK_TX_TRIG_1		(0 << 16)
+#define   SLINK_TX_TRIG_4		(1 << 16)
+#define   SLINK_TX_TRIG_8		(2 << 16)
+#define   SLINK_TX_TRIG_16		(3 << 16)
+#define   SLINK_TX_TRIG_MASK		(3 << 16)
+#define   SLINK_RX_TRIG_1		(0 << 18)
+#define   SLINK_RX_TRIG_4		(1 << 18)
+#define   SLINK_RX_TRIG_8		(2 << 18)
+#define   SLINK_RX_TRIG_16		(3 << 18)
+#define   SLINK_RX_TRIG_MASK		(3 << 18)
+#define   SLINK_PACKED			(1 << 20)
+#define   SLINK_PACK_SIZE_4		(0 << 21)
+#define   SLINK_PACK_SIZE_8		(1 << 21)
+#define   SLINK_PACK_SIZE_16		(2 << 21)
+#define   SLINK_PACK_SIZE_32		(3 << 21)
+#define   SLINK_PACK_SIZE_MASK		(3 << 21)
+#define   SLINK_IE_TXC			(1 << 26)
+#define   SLINK_IE_RXC			(1 << 27)
+#define   SLINK_DMA_EN			(1 << 31)
+
+#define SLINK_STATUS2		0x01c
+#define   SLINK_TX_FIFO_EMPTY_COUNT(val)	(((val) & 0x3f) >> 0)
+#define   SLINK_RX_FIFO_FULL_COUNT(val)		(((val) & 0x3f) >> 16)
+
+#define SLINK_TX_FIFO		0x100
+#define SLINK_RX_FIFO		0x180
+
+static const unsigned long spi_tegra_req_sels[] = {
+	TEGRA_DMA_REQ_SEL_SL2B1,
+	TEGRA_DMA_REQ_SEL_SL2B2,
+	TEGRA_DMA_REQ_SEL_SL2B3,
+	TEGRA_DMA_REQ_SEL_SL2B4,
+};
+
+#define BB_LEN			32
+
+struct spi_tegra_data {
+	struct spi_master	*master;
+	struct platform_device	*pdev;
+	spinlock_t		lock;
+
+	struct clk		*clk;
+	void __iomem		*base;
+	unsigned long		phys;
+
+	u32			cur_speed;
+
+	struct list_head	queue;
+	struct spi_transfer	*cur;
+	unsigned		cur_pos;
+	unsigned		cur_len;
+	unsigned		cur_bytes_per_word;
+
+	/* The tegra spi controller has a bug which causes the first word
+	 * in PIO transactions to be garbage.  Since packed DMA transactions
+	 * require transfers to be 4 byte aligned we need a bounce buffer
+	 * for the generic case.
+	 */
+	struct tegra_dma_req	rx_dma_req;
+	struct tegra_dma_channel *rx_dma;
+	u32			*rx_bb;
+	dma_addr_t		rx_bb_phys;
+};
+
+
+static inline unsigned long spi_tegra_readl(struct spi_tegra_data *tspi,
+					    unsigned long reg)
+{
+	return readl(tspi->base + reg);
+}
+
+static inline void spi_tegra_writel(struct spi_tegra_data *tspi,
+				    unsigned long val,
+				    unsigned long reg)
+{
+	writel(val, tspi->base + reg);
+}
+
+static void spi_tegra_go(struct spi_tegra_data *tspi)
+{
+	unsigned long val;
+
+	wmb();
+
+	val = spi_tegra_readl(tspi, SLINK_DMA_CTL);
+	val &= ~SLINK_DMA_BLOCK_SIZE(~0) & ~SLINK_DMA_EN;
+	val |= SLINK_DMA_BLOCK_SIZE(tspi->rx_dma_req.size / 4 - 1);
+	spi_tegra_writel(tspi, val, SLINK_DMA_CTL);
+
+	tegra_dma_enqueue_req(tspi->rx_dma, &tspi->rx_dma_req);
+
+	val |= SLINK_DMA_EN;
+	spi_tegra_writel(tspi, val, SLINK_DMA_CTL);
+}
+
+static unsigned spi_tegra_fill_tx_fifo(struct spi_tegra_data *tspi,
+				  struct spi_transfer *t)
+{
+	unsigned len = min(t->len - tspi->cur_pos, BB_LEN *
+			   tspi->cur_bytes_per_word);
+	u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_pos;
+	int i, j;
+	unsigned long val;
+
+	val = spi_tegra_readl(tspi, SLINK_COMMAND);
+	val &= ~SLINK_WORD_SIZE(~0);
+	val |= SLINK_WORD_SIZE(len / tspi->cur_bytes_per_word - 1);
+	spi_tegra_writel(tspi, val, SLINK_COMMAND);
+
+	for (i = 0; i < len; i += tspi->cur_bytes_per_word) {
+		val = 0;
+		for (j = 0; j < tspi->cur_bytes_per_word; j++)
+			val |= tx_buf[i + j] << j * 8;
+
+		spi_tegra_writel(tspi, val, SLINK_TX_FIFO);
+	}
+
+	tspi->rx_dma_req.size = len / tspi->cur_bytes_per_word * 4;
+
+	return len;
+}
+
+static unsigned spi_tegra_drain_rx_fifo(struct spi_tegra_data *tspi,
+				  struct spi_transfer *t)
+{
+	unsigned len = tspi->cur_len;
+	u8 *rx_buf = (u8 *)t->rx_buf + tspi->cur_pos;
+	int i, j;
+	unsigned long val;
+
+	for (i = 0; i < len; i += tspi->cur_bytes_per_word) {
+		val = tspi->rx_bb[i / tspi->cur_bytes_per_word];
+		for (j = 0; j < tspi->cur_bytes_per_word; j++)
+			rx_buf[i + j] = (val >> (j * 8)) & 0xff;
+	}
+
+	return len;
+}
+
+static void spi_tegra_start_transfer(struct spi_device *spi,
+				    struct spi_transfer *t)
+{
+	struct spi_tegra_data *tspi = spi_master_get_devdata(spi->master);
+	u32 speed;
+	u8 bits_per_word;
+	unsigned long val;
+
+	speed = t->speed_hz ? t->speed_hz : spi->max_speed_hz;
+	bits_per_word = t->bits_per_word ? t->bits_per_word  :
+		spi->bits_per_word;
+
+	tspi->cur_bytes_per_word = (bits_per_word - 1) / 8 + 1;
+
+	if (speed != tspi->cur_speed)
+		clk_set_rate(tspi->clk, speed);
+
+	if (tspi->cur_speed == 0)
+		clk_enable(tspi->clk);
+
+	tspi->cur_speed = speed;
+
+	val = spi_tegra_readl(tspi, SLINK_COMMAND2);
+	val &= ~SLINK_SS_EN_CS(~0) | SLINK_RXEN | SLINK_TXEN;
+	if (t->rx_buf)
+		val |= SLINK_RXEN;
+	if (t->tx_buf)
+		val |= SLINK_TXEN;
+	val |= SLINK_SS_EN_CS(spi->chip_select);
+	val |= SLINK_SPIE;
+	spi_tegra_writel(tspi, val, SLINK_COMMAND2);
+
+	val = spi_tegra_readl(tspi, SLINK_COMMAND);
+	val &= ~SLINK_BIT_LENGTH(~0);
+	val |= SLINK_BIT_LENGTH(bits_per_word - 1);
+
+	/* FIXME: should probably control CS manually so that we can be sure
+	 * it does not go low between transfer and to support delay_usecs
+	 * correctly.
+	 */
+	val &= ~SLINK_IDLE_SCLK_MASK & ~SLINK_CK_SDA & ~SLINK_CS_SW;
+
+	if (spi->mode & SPI_CPHA)
+		val |= SLINK_CK_SDA;
+
+	if (spi->mode & SPI_CPOL)
+		val |= SLINK_IDLE_SCLK_DRIVE_HIGH;
+	else
+		val |= SLINK_IDLE_SCLK_DRIVE_LOW;
+
+	val |= SLINK_M_S;
+
+	spi_tegra_writel(tspi, val, SLINK_COMMAND);
+
+	spi_tegra_writel(tspi, SLINK_RX_FLUSH | SLINK_TX_FLUSH, SLINK_STATUS);
+
+	tspi->cur = t;
+	tspi->cur_pos = 0;
+	tspi->cur_len = spi_tegra_fill_tx_fifo(tspi, t);
+
+	spi_tegra_go(tspi);
+}
+
+static void spi_tegra_start_message(struct spi_device *spi,
+				    struct spi_message *m)
+{
+	struct spi_transfer *t;
+
+	m->actual_length = 0;
+	m->status = 0;
+
+	t = list_first_entry(&m->transfers, struct spi_transfer, transfer_list);
+	spi_tegra_start_transfer(spi, t);
+}
+
+static void tegra_spi_rx_dma_complete(struct tegra_dma_req *req)
+{
+	struct spi_tegra_data *tspi = req->dev;
+	unsigned long flags;
+	struct spi_message *m;
+	struct spi_device *spi;
+	int timeout = 0;
+	unsigned long val;
+
+	/* the SPI controller may come back with both the BSY and RDY bits
+	 * set.  In this case we need to wait for the BSY bit to clear so
+	 * that we are sure the DMA is finished.  1000 reads was empirically
+	 * determined to be long enough.
+	 */
+	while (timeout++ < 1000) {
+		if (!(spi_tegra_readl(tspi, SLINK_STATUS) & SLINK_BSY))
+			break;
+	}
+
+	spin_lock_irqsave(&tspi->lock, flags);
+
+	val = spi_tegra_readl(tspi, SLINK_STATUS);
+	val |= SLINK_RDY;
+	spi_tegra_writel(tspi, val, SLINK_STATUS);
+
+	m = list_first_entry(&tspi->queue, struct spi_message, queue);
+
+	if (timeout >= 1000)
+		m->status = -EIO;
+
+	spi = m->state;
+
+	tspi->cur_pos += spi_tegra_drain_rx_fifo(tspi, tspi->cur);
+	m->actual_length += tspi->cur_pos;
+
+	if (tspi->cur_pos < tspi->cur->len) {
+		tspi->cur_len = spi_tegra_fill_tx_fifo(tspi, tspi->cur);
+		spi_tegra_go(tspi);
+	} else if (!list_is_last(&tspi->cur->transfer_list,
+				 &m->transfers)) {
+		tspi->cur =  list_first_entry(&tspi->cur->transfer_list,
+					      struct spi_transfer,
+					      transfer_list);
+		spi_tegra_start_transfer(spi, tspi->cur);
+	} else {
+		list_del(&m->queue);
+
+		m->complete(m->context);
+
+		if (!list_empty(&tspi->queue)) {
+			m = list_first_entry(&tspi->queue, struct spi_message,
+					     queue);
+			spi = m->state;
+			spi_tegra_start_message(spi, m);
+		} else {
+			clk_disable(tspi->clk);
+			tspi->cur_speed = 0;
+		}
+	}
+
+	spin_unlock_irqrestore(&tspi->lock, flags);
+}
+
+static int spi_tegra_setup(struct spi_device *spi)
+{
+	struct spi_tegra_data *tspi = spi_master_get_devdata(spi->master);
+	unsigned long cs_bit;
+	unsigned long val;
+	unsigned long flags;
+
+	dev_dbg(&spi->dev, "setup %d bpw, %scpol, %scpha, %dHz\n",
+		spi->bits_per_word,
+		spi->mode & SPI_CPOL ? "" : "~",
+		spi->mode & SPI_CPHA ? "" : "~",
+		spi->max_speed_hz);
+
+
+	switch (spi->chip_select) {
+	case 0:
+		cs_bit = SLINK_CS_POLARITY;
+		break;
+
+	case 1:
+		cs_bit = SLINK_CS_POLARITY1;
+		break;
+
+	case 2:
+		cs_bit = SLINK_CS_POLARITY2;
+		break;
+
+	case 4:
+		cs_bit = SLINK_CS_POLARITY3;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&tspi->lock, flags);
+
+	val = spi_tegra_readl(tspi, SLINK_COMMAND);
+	if (spi->mode & SPI_CS_HIGH)
+		val |= cs_bit;
+	else
+		val &= ~cs_bit;
+	spi_tegra_writel(tspi, val, SLINK_COMMAND);
+
+	spin_unlock_irqrestore(&tspi->lock, flags);
+
+	return 0;
+}
+
+static int spi_tegra_transfer(struct spi_device *spi, struct spi_message *m)
+{
+	struct spi_tegra_data *tspi = spi_master_get_devdata(spi->master);
+	struct spi_transfer *t;
+	unsigned long flags;
+	int was_empty;
+
+	if (list_empty(&m->transfers) || !m->complete)
+		return -EINVAL;
+
+	list_for_each_entry(t, &m->transfers, transfer_list) {
+		if (t->bits_per_word < 0 || t->bits_per_word > 32)
+			return -EINVAL;
+
+		if (t->len == 0)
+			return -EINVAL;
+
+		if (!t->rx_buf && !t->tx_buf)
+			return -EINVAL;
+	}
+
+	m->state = spi;
+
+	spin_lock_irqsave(&tspi->lock, flags);
+	was_empty = list_empty(&tspi->queue);
+	list_add_tail(&m->queue, &tspi->queue);
+
+	if (was_empty)
+		spi_tegra_start_message(spi, m);
+
+	spin_unlock_irqrestore(&tspi->lock, flags);
+
+	return 0;
+}
+
+static int __init spi_tegra_probe(struct platform_device *pdev)
+{
+	struct spi_master	*master;
+	struct spi_tegra_data	*tspi;
+	struct resource		*r;
+	int ret;
+
+	master = spi_alloc_master(&pdev->dev, sizeof *tspi);
+	if (master == NULL) {
+		dev_err(&pdev->dev, "master allocation failed\n");
+		return -ENOMEM;
+	}
+
+	/* the spi->mode bits understood by this driver: */
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+
+	master->bus_num = pdev->id;
+
+	master->setup = spi_tegra_setup;
+	master->transfer = spi_tegra_transfer;
+	master->num_chipselect = 4;
+
+	dev_set_drvdata(&pdev->dev, master);
+	tspi = spi_master_get_devdata(master);
+	tspi->master = master;
+	tspi->pdev = pdev;
+	spin_lock_init(&tspi->lock);
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (r == NULL) {
+		ret = -ENODEV;
+		goto err0;
+	}
+
+	if (!request_mem_region(r->start, (r->end - r->start) + 1,
+				dev_name(&pdev->dev))) {
+		ret = -EBUSY;
+		goto err0;
+	}
+
+	tspi->phys = r->start;
+	tspi->base = ioremap(r->start, r->end - r->start + 1);
+	if (!tspi->base) {
+		dev_err(&pdev->dev, "can't ioremap iomem\n");
+		ret = -ENOMEM;
+		goto err1;
+	}
+
+	tspi->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR_OR_NULL(tspi->clk)) {
+		dev_err(&pdev->dev, "can not get clock\n");
+		ret = PTR_ERR(tspi->clk);
+		goto err2;
+	}
+
+	INIT_LIST_HEAD(&tspi->queue);
+
+	tspi->rx_dma = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT);
+	if (!tspi->rx_dma) {
+		dev_err(&pdev->dev, "can not allocate rx dma channel\n");
+		ret = -ENODEV;
+		goto err3;
+	}
+
+	tspi->rx_bb = dma_alloc_coherent(&pdev->dev, sizeof(u32) * BB_LEN,
+					 &tspi->rx_bb_phys, GFP_KERNEL);
+	if (!tspi->rx_bb) {
+		dev_err(&pdev->dev, "can not allocate rx bounce buffer\n");
+		ret = -ENOMEM;
+		goto err4;
+	}
+
+	tspi->rx_dma_req.complete = tegra_spi_rx_dma_complete;
+	tspi->rx_dma_req.to_memory = 1;
+	tspi->rx_dma_req.dest_addr = tspi->rx_bb_phys;
+	tspi->rx_dma_req.dest_bus_width = 32;
+	tspi->rx_dma_req.source_addr = tspi->phys + SLINK_RX_FIFO;
+	tspi->rx_dma_req.source_bus_width = 32;
+	tspi->rx_dma_req.source_wrap = 4;
+	tspi->rx_dma_req.req_sel = spi_tegra_req_sels[pdev->id];
+	tspi->rx_dma_req.dev = tspi;
+
+	ret = spi_register_master(master);
+
+	if (ret < 0)
+		goto err5;
+
+	return ret;
+
+err5:
+	dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN,
+			  tspi->rx_bb, tspi->rx_bb_phys);
+err4:
+	tegra_dma_free_channel(tspi->rx_dma);
+err3:
+	clk_put(tspi->clk);
+err2:
+	iounmap(tspi->base);
+err1:
+	release_mem_region(r->start, (r->end - r->start) + 1);
+err0:
+	spi_master_put(master);
+	return ret;
+}
+
+static int __devexit spi_tegra_remove(struct platform_device *pdev)
+{
+	struct spi_master	*master;
+	struct spi_tegra_data	*tspi;
+	struct resource		*r;
+
+	master = dev_get_drvdata(&pdev->dev);
+	tspi = spi_master_get_devdata(master);
+
+	tegra_dma_free_channel(tspi->rx_dma);
+
+	dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN,
+			  tspi->rx_bb, tspi->rx_bb_phys);
+
+	clk_put(tspi->clk);
+	iounmap(tspi->base);
+
+	spi_master_put(master);
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(r->start, (r->end - r->start) + 1);
+
+	return 0;
+}
+
+MODULE_ALIAS("platform:spi_tegra");
+
+static struct platform_driver spi_tegra_driver = {
+	.driver = {
+		.name =		"spi_tegra",
+		.owner =	THIS_MODULE,
+	},
+	.remove =	__devexit_p(spi_tegra_remove),
+};
+
+static int __init spi_tegra_init(void)
+{
+	return platform_driver_probe(&spi_tegra_driver, spi_tegra_probe);
+}
+module_init(spi_tegra_init);
+
+static void __exit spi_tegra_exit(void)
+{
+	platform_driver_unregister(&spi_tegra_driver);
+}
+module_exit(spi_tegra_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 61d3ca6..cb5cd42 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -54,7 +54,6 @@
 
 #include <plat/dma.h>
 #include <plat/usb.h>
-#include <plat/control.h>
 
 #include "omap_udc.h"
 
@@ -2309,21 +2308,12 @@
 static int proc_otg_show(struct seq_file *s)
 {
 	u32		tmp;
-	u32		trans;
-	char		*ctrl_name;
+	u32		trans = 0;
+	char		*ctrl_name = "(UNKNOWN)";
 
+	/* XXX This needs major revision for OMAP2+ */
 	tmp = omap_readl(OTG_REV);
-	if (cpu_is_omap24xx()) {
-		/*
-		 * REVISIT: Not clear how this works on OMAP2.  trans
-		 * is ANDed to produce bits 7 and 8, which might make
-		 * sense for USB_TRANSCEIVER_CTRL on OMAP1,
-		 * but with CONTROL_DEVCONF, these bits have something to
-		 * do with the frame adjustment counter and McBSP2.
-		 */
-		ctrl_name = "control_devconf";
-		trans = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
-	} else {
+	if (cpu_class_is_omap1()) {
 		ctrl_name = "tranceiver_ctrl";
 		trans = omap_readw(USB_TRANSCEIVER_CTRL);
 	}
diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c
index e77e8e4..4ea187d 100644
--- a/drivers/video/au1200fb.c
+++ b/drivers/video/au1200fb.c
@@ -1079,7 +1079,7 @@
 	 * clock can only be obtain by dividing this value by an even integer.
 	 * Fallback to a slower pixel clock if necessary. */
 	pixclock = max((u32)(PICOS2KHZ(var->pixclock) * 1000), fbi->monspecs.dclkmin);
-	pixclock = min(pixclock, min(fbi->monspecs.dclkmax, (u32)AU1200_LCD_MAX_CLK/2));
+	pixclock = min3(pixclock, fbi->monspecs.dclkmax, (u32)AU1200_LCD_MAX_CLK/2);
 
 	if (AU1200_LCD_MAX_CLK % pixclock) {
 		int diff = AU1200_LCD_MAX_CLK % pixclock;
diff --git a/drivers/video/omap/lcd_omap3beagle.c b/drivers/video/omap/lcd_omap3beagle.c
index ca75cc2..d7c6c3e 100644
--- a/drivers/video/omap/lcd_omap3beagle.c
+++ b/drivers/video/omap/lcd_omap3beagle.c
@@ -25,8 +25,6 @@
 #include <linux/gpio.h>
 #include <linux/i2c/twl.h>
 
-#include <plat/mux.h>
-#include <plat/mux.h>
 #include <asm/mach-types.h>
 
 #include "omapfb.h"
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
index 881c9f7..12327bb 100644
--- a/drivers/video/omap2/displays/Kconfig
+++ b/drivers/video/omap2/displays/Kconfig
@@ -40,7 +40,7 @@
 
 config PANEL_ACX565AKM
 	tristate "ACX565AKM Panel"
-	depends on OMAP2_DSS_SDI
+	depends on OMAP2_DSS_SDI && SPI
 	select BACKLIGHT_CLASS_DEVICE
 	help
 	  This is the LCD panel used on Nokia N900
diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c
index 07fbb8a..e773106 100644
--- a/drivers/video/omap2/displays/panel-acx565akm.c
+++ b/drivers/video/omap2/displays/panel-acx565akm.c
@@ -587,6 +587,9 @@
 
 	dev_dbg(&dssdev->dev, "%s\n", __func__);
 
+	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+		return 0;
+
 	mutex_lock(&md->mutex);
 
 	r = omapdss_sdi_display_enable(dssdev);
@@ -644,6 +647,9 @@
 
 	dev_dbg(&dssdev->dev, "%s\n", __func__);
 
+	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+		return;
+
 	mutex_lock(&md->mutex);
 
 	if (!md->enabled) {
diff --git a/drivers/video/omap2/displays/panel-generic.c b/drivers/video/omap2/displays/panel-generic.c
index 300eff5..395a68d 100644
--- a/drivers/video/omap2/displays/panel-generic.c
+++ b/drivers/video/omap2/displays/panel-generic.c
@@ -39,6 +39,9 @@
 {
 	int r;
 
+	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+		return 0;
+
 	r = omapdss_dpi_display_enable(dssdev);
 	if (r)
 		goto err0;
@@ -58,6 +61,9 @@
 
 static void generic_panel_power_off(struct omap_dss_device *dssdev)
 {
+	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+		return;
+
 	if (dssdev->platform_disable)
 		dssdev->platform_disable(dssdev);
 
diff --git a/drivers/video/omap2/displays/panel-sharp-lq043t1dg01.c b/drivers/video/omap2/displays/panel-sharp-lq043t1dg01.c
index 1026746..0c6896c 100644
--- a/drivers/video/omap2/displays/panel-sharp-lq043t1dg01.c
+++ b/drivers/video/omap2/displays/panel-sharp-lq043t1dg01.c
@@ -43,6 +43,9 @@
 {
 	int r;
 
+	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+		return 0;
+
 	r = omapdss_dpi_display_enable(dssdev);
 	if (r)
 		goto err0;
@@ -65,6 +68,9 @@
 
 static void sharp_lq_panel_power_off(struct omap_dss_device *dssdev)
 {
+	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+		return;
+
 	if (dssdev->platform_disable)
 		dssdev->platform_disable(dssdev);
 
diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
index 7d9eb2b..9a138f6 100644
--- a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
+++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
@@ -135,6 +135,9 @@
 {
 	int r = 0;
 
+	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+		return 0;
+
 	r = omapdss_dpi_display_enable(dssdev);
 	if (r)
 		goto err0;
@@ -157,6 +160,9 @@
 
 static void sharp_ls_power_off(struct omap_dss_device *dssdev)
 {
+	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+		return;
+
 	if (dssdev->platform_disable)
 		dssdev->platform_disable(dssdev);
 
diff --git a/drivers/video/omap2/displays/panel-toppoly-tdo35s.c b/drivers/video/omap2/displays/panel-toppoly-tdo35s.c
index e320e67..526e906 100644
--- a/drivers/video/omap2/displays/panel-toppoly-tdo35s.c
+++ b/drivers/video/omap2/displays/panel-toppoly-tdo35s.c
@@ -46,6 +46,9 @@
 {
 	int r;
 
+	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+		return 0;
+
 	r = omapdss_dpi_display_enable(dssdev);
 	if (r)
 		goto err0;
@@ -65,6 +68,9 @@
 
 static void toppoly_tdo_panel_power_off(struct omap_dss_device *dssdev)
 {
+	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+		return;
+
 	if (dssdev->platform_disable)
 		dssdev->platform_disable(dssdev);
 
diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
index e866e76..dbe9d43 100644
--- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
+++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
@@ -269,6 +269,9 @@
 	int nreset_gpio = dssdev->reset_gpio;
 	int r;
 
+	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+		return 0;
+
 	r = omapdss_dpi_display_enable(dssdev);
 	if (r)
 		goto err0;
@@ -308,6 +311,9 @@
 	struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
 	int nreset_gpio = dssdev->reset_gpio;
 
+	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+		return;
+
 	tpo_td043_write(tpo_td043->spi, 3,
 			TPO_R03_VAL_STANDBY | TPO_R03_EN_PWM);
 
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
index d71b5d9..7db17b5 100644
--- a/drivers/video/omap2/dss/Makefile
+++ b/drivers/video/omap2/dss/Makefile
@@ -1,5 +1,5 @@
 obj-$(CONFIG_OMAP2_DSS) += omapdss.o
-omapdss-y := core.o dss.o dispc.o display.o manager.o overlay.o
+omapdss-y := core.o dss.o dss_features.o dispc.o display.o manager.o overlay.o
 omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
 omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
 omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index b3a498f..8e89f60 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -37,6 +37,7 @@
 #include <plat/clock.h>
 
 #include "dss.h"
+#include "dss_features.h"
 
 static struct {
 	struct platform_device *pdev;
@@ -502,6 +503,8 @@
 
 	core.pdev = pdev;
 
+	dss_features_init();
+
 	dss_init_overlay_managers(pdev);
 	dss_init_overlays(pdev);
 
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 5ecdc00..fa40fa5 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -39,6 +39,7 @@
 #include <plat/display.h>
 
 #include "dss.h"
+#include "dss_features.h"
 
 /* DISPC */
 #define DISPC_BASE			0x48050400
@@ -139,6 +140,22 @@
 	u32			mask;
 };
 
+struct dispc_h_coef {
+	s8 hc4;
+	s8 hc3;
+	u8 hc2;
+	s8 hc1;
+	s8 hc0;
+};
+
+struct dispc_v_coef {
+	s8 vc22;
+	s8 vc2;
+	u8 vc1;
+	s8 vc0;
+	s8 vc00;
+};
+
 #define REG_GET(idx, start, end) \
 	FLD_GET(dispc_read_reg(idx), start, end)
 
@@ -564,106 +581,77 @@
 		int vscaleup, int five_taps)
 {
 	/* Coefficients for horizontal up-sampling */
-	static const u32 coef_hup[8] = {
-		0x00800000,
-		0x0D7CF800,
-		0x1E70F5FF,
-		0x335FF5FE,
-		0xF74949F7,
-		0xF55F33FB,
-		0xF5701EFE,
-		0xF87C0DFF,
-	};
-
-	/* Coefficients for horizontal down-sampling */
-	static const u32 coef_hdown[8] = {
-		0x24382400,
-		0x28371FFE,
-		0x2C361BFB,
-		0x303516F9,
-		0x11343311,
-		0x1635300C,
-		0x1B362C08,
-		0x1F372804,
-	};
-
-	/* Coefficients for horizontal and vertical up-sampling */
-	static const u32 coef_hvup[2][8] = {
-		{
-		0x00800000,
-		0x037B02FF,
-		0x0C6F05FE,
-		0x205907FB,
-		0x00404000,
-		0x075920FE,
-		0x056F0CFF,
-		0x027B0300,
-		},
-		{
-		0x00800000,
-		0x0D7CF8FF,
-		0x1E70F5FE,
-		0x335FF5FB,
-		0xF7404000,
-		0xF55F33FE,
-		0xF5701EFF,
-		0xF87C0D00,
-		},
-	};
-
-	/* Coefficients for horizontal and vertical down-sampling */
-	static const u32 coef_hvdown[2][8] = {
-		{
-		0x24382400,
-		0x28391F04,
-		0x2D381B08,
-		0x3237170C,
-		0x123737F7,
-		0x173732F9,
-		0x1B382DFB,
-		0x1F3928FE,
-		},
-		{
-		0x24382400,
-		0x28371F04,
-		0x2C361B08,
-		0x3035160C,
-		0x113433F7,
-		0x163530F9,
-		0x1B362CFB,
-		0x1F3728FE,
-		},
+	static const struct dispc_h_coef coef_hup[8] = {
+		{  0,   0, 128,   0,  0 },
+		{ -1,  13, 124,  -8,  0 },
+		{ -2,  30, 112, -11, -1 },
+		{ -5,  51,  95, -11, -2 },
+		{  0,  -9,  73,  73, -9 },
+		{ -2, -11,  95,  51, -5 },
+		{ -1, -11, 112,  30, -2 },
+		{  0,  -8, 124,  13, -1 },
 	};
 
 	/* Coefficients for vertical up-sampling */
-	static const u32 coef_vup[8] = {
-		0x00000000,
-		0x0000FF00,
-		0x0000FEFF,
-		0x0000FBFE,
-		0x000000F7,
-		0x0000FEFB,
-		0x0000FFFE,
-		0x000000FF,
+	static const struct dispc_v_coef coef_vup_3tap[8] = {
+		{ 0,  0, 128,  0, 0 },
+		{ 0,  3, 123,  2, 0 },
+		{ 0, 12, 111,  5, 0 },
+		{ 0, 32,  89,  7, 0 },
+		{ 0,  0,  64, 64, 0 },
+		{ 0,  7,  89, 32, 0 },
+		{ 0,  5, 111, 12, 0 },
+		{ 0,  2, 123,  3, 0 },
 	};
 
+	static const struct dispc_v_coef coef_vup_5tap[8] = {
+		{  0,   0, 128,   0,  0 },
+		{ -1,  13, 124,  -8,  0 },
+		{ -2,  30, 112, -11, -1 },
+		{ -5,  51,  95, -11, -2 },
+		{  0,  -9,  73,  73, -9 },
+		{ -2, -11,  95,  51, -5 },
+		{ -1, -11, 112,  30, -2 },
+		{  0,  -8, 124,  13, -1 },
+	};
+
+	/* Coefficients for horizontal down-sampling */
+	static const struct dispc_h_coef coef_hdown[8] = {
+		{   0, 36, 56, 36,  0 },
+		{   4, 40, 55, 31, -2 },
+		{   8, 44, 54, 27, -5 },
+		{  12, 48, 53, 22, -7 },
+		{  -9, 17, 52, 51, 17 },
+		{  -7, 22, 53, 48, 12 },
+		{  -5, 27, 54, 44,  8 },
+		{  -2, 31, 55, 40,  4 },
+	};
 
 	/* Coefficients for vertical down-sampling */
-	static const u32 coef_vdown[8] = {
-		0x00000000,
-		0x000004FE,
-		0x000008FB,
-		0x00000CF9,
-		0x0000F711,
-		0x0000F90C,
-		0x0000FB08,
-		0x0000FE04,
+	static const struct dispc_v_coef coef_vdown_3tap[8] = {
+		{ 0, 36, 56, 36, 0 },
+		{ 0, 40, 57, 31, 0 },
+		{ 0, 45, 56, 27, 0 },
+		{ 0, 50, 55, 23, 0 },
+		{ 0, 18, 55, 55, 0 },
+		{ 0, 23, 55, 50, 0 },
+		{ 0, 27, 56, 45, 0 },
+		{ 0, 31, 57, 40, 0 },
 	};
 
-	const u32 *h_coef;
-	const u32 *hv_coef;
-	const u32 *hv_coef_mod;
-	const u32 *v_coef;
+	static const struct dispc_v_coef coef_vdown_5tap[8] = {
+		{   0, 36, 56, 36,  0 },
+		{   4, 40, 55, 31, -2 },
+		{   8, 44, 54, 27, -5 },
+		{  12, 48, 53, 22, -7 },
+		{  -9, 17, 52, 51, 17 },
+		{  -7, 22, 53, 48, 12 },
+		{  -5, 27, 54, 44,  8 },
+		{  -2, 31, 55, 40,  4 },
+	};
+
+	const struct dispc_h_coef *h_coef;
+	const struct dispc_v_coef *v_coef;
 	int i;
 
 	if (hscaleup)
@@ -671,47 +659,34 @@
 	else
 		h_coef = coef_hdown;
 
-	if (vscaleup) {
-		hv_coef = coef_hvup[five_taps];
-		v_coef = coef_vup;
-
-		if (hscaleup)
-			hv_coef_mod = NULL;
-		else
-			hv_coef_mod = coef_hvdown[five_taps];
-	} else {
-		hv_coef = coef_hvdown[five_taps];
-		v_coef = coef_vdown;
-
-		if (hscaleup)
-			hv_coef_mod = coef_hvup[five_taps];
-		else
-			hv_coef_mod = NULL;
-	}
+	if (vscaleup)
+		v_coef = five_taps ? coef_vup_5tap : coef_vup_3tap;
+	else
+		v_coef = five_taps ? coef_vdown_5tap : coef_vdown_3tap;
 
 	for (i = 0; i < 8; i++) {
 		u32 h, hv;
 
-		h = h_coef[i];
-
-		hv = hv_coef[i];
-
-		if (hv_coef_mod) {
-			hv &= 0xffffff00;
-			hv |= (hv_coef_mod[i] & 0xff);
-		}
+		h = FLD_VAL(h_coef[i].hc0, 7, 0)
+			| FLD_VAL(h_coef[i].hc1, 15, 8)
+			| FLD_VAL(h_coef[i].hc2, 23, 16)
+			| FLD_VAL(h_coef[i].hc3, 31, 24);
+		hv = FLD_VAL(h_coef[i].hc4, 7, 0)
+			| FLD_VAL(v_coef[i].vc0, 15, 8)
+			| FLD_VAL(v_coef[i].vc1, 23, 16)
+			| FLD_VAL(v_coef[i].vc2, 31, 24);
 
 		_dispc_write_firh_reg(plane, i, h);
 		_dispc_write_firhv_reg(plane, i, hv);
 	}
 
-	if (!five_taps)
-		return;
-
-	for (i = 0; i < 8; i++) {
-		u32 v;
-		v = v_coef[i];
-		_dispc_write_firv_reg(plane, i, v);
+	if (five_taps) {
+		for (i = 0; i < 8; i++) {
+			u32 v;
+			v = FLD_VAL(v_coef[i].vc00, 7, 0)
+				| FLD_VAL(v_coef[i].vc22, 15, 8);
+			_dispc_write_firv_reg(plane, i, v);
+		}
 	}
 }
 
@@ -800,12 +775,12 @@
 
 static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha)
 {
-
-	BUG_ON(plane == OMAP_DSS_VIDEO1);
-
-	if (cpu_is_omap24xx())
+	if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
 		return;
 
+	BUG_ON(!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
+			plane == OMAP_DSS_VIDEO1);
+
 	if (plane == OMAP_DSS_GFX)
 		REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 7, 0);
 	else if (plane == OMAP_DSS_VIDEO2)
@@ -975,17 +950,14 @@
 				      DISPC_VID_FIFO_SIZE_STATUS(1) };
 	u32 size;
 	int plane;
+	u8 start, end;
 
 	enable_clocks(1);
 
-	for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) {
-		if (cpu_is_omap24xx())
-			size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 8, 0);
-		else if (cpu_is_omap34xx())
-			size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 10, 0);
-		else
-			BUG();
+	dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end);
 
+	for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) {
+		size = FLD_GET(dispc_read_reg(fsz_reg[plane]), start, end);
 		dispc.fifo_size[plane] = size;
 	}
 
@@ -1002,6 +974,8 @@
 	const struct dispc_reg ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD,
 				       DISPC_VID_FIFO_THRESHOLD(0),
 				       DISPC_VID_FIFO_THRESHOLD(1) };
+	u8 hi_start, hi_end, lo_start, lo_end;
+
 	enable_clocks(1);
 
 	DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n",
@@ -1010,12 +984,12 @@
 			REG_GET(ftrs_reg[plane], 27, 16),
 			low, high);
 
-	if (cpu_is_omap24xx())
-		dispc_write_reg(ftrs_reg[plane],
-				FLD_VAL(high, 24, 16) | FLD_VAL(low, 8, 0));
-	else
-		dispc_write_reg(ftrs_reg[plane],
-				FLD_VAL(high, 27, 16) | FLD_VAL(low, 11, 0));
+	dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end);
+	dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end);
+
+	dispc_write_reg(ftrs_reg[plane],
+			FLD_VAL(high, hi_start, hi_end) |
+			FLD_VAL(low, lo_start, lo_end));
 
 	enable_clocks(0);
 }
@@ -1035,13 +1009,16 @@
 	u32 val;
 	const struct dispc_reg fir_reg[] = { DISPC_VID_FIR(0),
 				      DISPC_VID_FIR(1) };
+	u8 hinc_start, hinc_end, vinc_start, vinc_end;
 
 	BUG_ON(plane == OMAP_DSS_GFX);
 
-	if (cpu_is_omap24xx())
-		val = FLD_VAL(vinc, 27, 16) | FLD_VAL(hinc, 11, 0);
-	else
-		val = FLD_VAL(vinc, 28, 16) | FLD_VAL(hinc, 12, 0);
+	dss_feat_get_reg_field(FEAT_REG_FIRHINC, &hinc_start, &hinc_end);
+	dss_feat_get_reg_field(FEAT_REG_FIRVINC, &vinc_start, &vinc_end);
+
+	val = FLD_VAL(vinc, vinc_start, vinc_end) |
+			FLD_VAL(hinc, hinc_start, hinc_end);
+
 	dispc_write_reg(fir_reg[plane-1], val);
 }
 
@@ -1567,6 +1544,8 @@
 		case OMAP_DSS_COLOR_ARGB16:
 		case OMAP_DSS_COLOR_ARGB32:
 		case OMAP_DSS_COLOR_RGBA32:
+			if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
+				return -EINVAL;
 		case OMAP_DSS_COLOR_RGBX32:
 			if (cpu_is_omap24xx())
 				return -EINVAL;
@@ -1607,9 +1586,10 @@
 		case OMAP_DSS_COLOR_ARGB16:
 		case OMAP_DSS_COLOR_ARGB32:
 		case OMAP_DSS_COLOR_RGBA32:
-			if (cpu_is_omap24xx())
+			if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
 				return -EINVAL;
-			if (plane == OMAP_DSS_VIDEO1)
+			if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
+					plane == OMAP_DSS_VIDEO1)
 				return -EINVAL;
 			break;
 
@@ -2002,7 +1982,7 @@
 }
 void dispc_enable_alpha_blending(enum omap_channel ch, bool enable)
 {
-	if (cpu_is_omap24xx())
+	if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
 		return;
 
 	enable_clocks(1);
@@ -2016,7 +1996,7 @@
 {
 	bool enabled;
 
-	if (cpu_is_omap24xx())
+	if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
 		return false;
 
 	enable_clocks(1);
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index b3fa3a7..aa4f7a5 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -3274,7 +3274,6 @@
 
 	dsi.vdds_dsi_reg = dss_get_vdds_dsi();
 	if (IS_ERR(dsi.vdds_dsi_reg)) {
-		iounmap(dsi.base);
 		DSSERR("can't get VDDS_DSI regulator\n");
 		r = PTR_ERR(dsi.vdds_dsi_reg);
 		goto err2;
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
new file mode 100644
index 0000000..867f68d
--- /dev/null
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -0,0 +1,191 @@
+/*
+ * linux/drivers/video/omap2/dss/dss_features.c
+ *
+ * Copyright (C) 2010 Texas Instruments
+ * Author: Archit Taneja <archit@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include <plat/display.h>
+#include <plat/cpu.h>
+
+#include "dss_features.h"
+
+/* Defines a generic omap register field */
+struct dss_reg_field {
+	enum dss_feat_reg_field id;
+	u8 start, end;
+};
+
+struct omap_dss_features {
+	const struct dss_reg_field *reg_fields;
+	const int num_reg_fields;
+
+	const u32 has_feature;
+
+	const int num_mgrs;
+	const int num_ovls;
+	const enum omap_display_type *supported_displays;
+	const enum omap_color_mode *supported_color_modes;
+};
+
+/* This struct is assigned to one of the below during initialization */
+static struct omap_dss_features *omap_current_dss_features;
+
+static const struct dss_reg_field omap2_dss_reg_fields[] = {
+	{ FEAT_REG_FIRHINC, 11, 0 },
+	{ FEAT_REG_FIRVINC, 27, 16 },
+	{ FEAT_REG_FIFOLOWTHRESHOLD, 8, 0 },
+	{ FEAT_REG_FIFOHIGHTHRESHOLD, 24, 16 },
+	{ FEAT_REG_FIFOSIZE, 8, 0 },
+};
+
+static const struct dss_reg_field omap3_dss_reg_fields[] = {
+	{ FEAT_REG_FIRHINC, 12, 0 },
+	{ FEAT_REG_FIRVINC, 28, 16 },
+	{ FEAT_REG_FIFOLOWTHRESHOLD, 11, 0 },
+	{ FEAT_REG_FIFOHIGHTHRESHOLD, 27, 16 },
+	{ FEAT_REG_FIFOSIZE, 10, 0 },
+};
+
+static const enum omap_display_type omap2_dss_supported_displays[] = {
+	/* OMAP_DSS_CHANNEL_LCD */
+	OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
+	OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI,
+
+	/* OMAP_DSS_CHANNEL_DIGIT */
+	OMAP_DISPLAY_TYPE_VENC,
+};
+
+static const enum omap_display_type omap3_dss_supported_displays[] = {
+	/* OMAP_DSS_CHANNEL_LCD */
+	OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
+	OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI,
+
+	/* OMAP_DSS_CHANNEL_DIGIT */
+	OMAP_DISPLAY_TYPE_VENC,
+};
+
+static const enum omap_color_mode omap2_dss_supported_color_modes[] = {
+	/* OMAP_DSS_GFX */
+	OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
+	OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
+	OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_RGB16 |
+	OMAP_DSS_COLOR_RGB24U | OMAP_DSS_COLOR_RGB24P,
+
+	/* OMAP_DSS_VIDEO1 */
+	OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
+	OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 |
+	OMAP_DSS_COLOR_UYVY,
+
+	/* OMAP_DSS_VIDEO2 */
+	OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
+	OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 |
+	OMAP_DSS_COLOR_UYVY,
+};
+
+static const enum omap_color_mode omap3_dss_supported_color_modes[] = {
+	/* OMAP_DSS_GFX */
+	OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
+	OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
+	OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
+	OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
+	OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
+	OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
+
+	/* OMAP_DSS_VIDEO1 */
+	OMAP_DSS_COLOR_RGB24U | OMAP_DSS_COLOR_RGB24P |
+	OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_RGB16 |
+	OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_UYVY,
+
+	/* OMAP_DSS_VIDEO2 */
+	OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
+	OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
+	OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 |
+	OMAP_DSS_COLOR_UYVY | OMAP_DSS_COLOR_ARGB32 |
+	OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
+};
+
+/* OMAP2 DSS Features */
+static struct omap_dss_features omap2_dss_features = {
+	.reg_fields = omap2_dss_reg_fields,
+	.num_reg_fields = ARRAY_SIZE(omap2_dss_reg_fields),
+
+	.num_mgrs = 2,
+	.num_ovls = 3,
+	.supported_displays = omap2_dss_supported_displays,
+	.supported_color_modes = omap2_dss_supported_color_modes,
+};
+
+/* OMAP3 DSS Features */
+static struct omap_dss_features omap3_dss_features = {
+	.reg_fields = omap3_dss_reg_fields,
+	.num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
+
+	.has_feature	= FEAT_GLOBAL_ALPHA,
+
+	.num_mgrs = 2,
+	.num_ovls = 3,
+	.supported_displays = omap3_dss_supported_displays,
+	.supported_color_modes = omap3_dss_supported_color_modes,
+};
+
+/* Functions returning values related to a DSS feature */
+int dss_feat_get_num_mgrs(void)
+{
+	return omap_current_dss_features->num_mgrs;
+}
+
+int dss_feat_get_num_ovls(void)
+{
+	return omap_current_dss_features->num_ovls;
+}
+
+enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel)
+{
+	return omap_current_dss_features->supported_displays[channel];
+}
+
+enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane)
+{
+	return omap_current_dss_features->supported_color_modes[plane];
+}
+
+/* DSS has_feature check */
+bool dss_has_feature(enum dss_feat_id id)
+{
+	return omap_current_dss_features->has_feature & id;
+}
+
+void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end)
+{
+	if (id >= omap_current_dss_features->num_reg_fields)
+		BUG();
+
+	*start = omap_current_dss_features->reg_fields[id].start;
+	*end = omap_current_dss_features->reg_fields[id].end;
+}
+
+void dss_features_init(void)
+{
+	if (cpu_is_omap24xx())
+		omap_current_dss_features = &omap2_dss_features;
+	else
+		omap_current_dss_features = &omap3_dss_features;
+}
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
new file mode 100644
index 0000000..cb231ea
--- /dev/null
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -0,0 +1,50 @@
+/*
+ * linux/drivers/video/omap2/dss/dss_features.h
+ *
+ * Copyright (C) 2010 Texas Instruments
+ * Author: Archit Taneja <archit@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __OMAP2_DSS_FEATURES_H
+#define __OMAP2_DSS_FEATURES_H
+
+#define MAX_DSS_MANAGERS	2
+#define MAX_DSS_OVERLAYS	3
+
+/* DSS has feature id */
+enum dss_feat_id {
+	FEAT_GLOBAL_ALPHA	= 1 << 0,
+	FEAT_GLOBAL_ALPHA_VID1	= 1 << 1,
+};
+
+/* DSS register field id */
+enum dss_feat_reg_field {
+	FEAT_REG_FIRHINC,
+	FEAT_REG_FIRVINC,
+	FEAT_REG_FIFOHIGHTHRESHOLD,
+	FEAT_REG_FIFOLOWTHRESHOLD,
+	FEAT_REG_FIFOSIZE,
+};
+
+/* DSS Feature Functions */
+int dss_feat_get_num_mgrs(void);
+int dss_feat_get_num_ovls(void);
+enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel);
+enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane);
+
+bool dss_has_feature(enum dss_feat_id id);
+void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end);
+void dss_features_init(void);
+#endif
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index 6a649ab..545e9b9 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -33,6 +33,7 @@
 #include <plat/cpu.h>
 
 #include "dss.h"
+#include "dss_features.h"
 
 static int num_managers;
 static struct list_head manager_list;
@@ -448,8 +449,8 @@
 
 static struct {
 	spinlock_t lock;
-	struct overlay_cache_data overlay_cache[3];
-	struct manager_cache_data manager_cache[2];
+	struct overlay_cache_data overlay_cache[MAX_DSS_OVERLAYS];
+	struct manager_cache_data manager_cache[MAX_DSS_MANAGERS];
 
 	bool irq_enabled;
 } dss_cache;
@@ -882,12 +883,12 @@
 {
 	struct overlay_cache_data *oc;
 	struct manager_cache_data *mc;
-	const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
-	const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache);
+	const int num_ovls = dss_feat_get_num_ovls();
+	const int num_mgrs = dss_feat_get_num_mgrs();
 	int i;
 	int r;
-	bool mgr_busy[2];
-	bool mgr_go[2];
+	bool mgr_busy[MAX_DSS_MANAGERS];
+	bool mgr_go[MAX_DSS_MANAGERS];
 	bool busy;
 
 	r = 0;
@@ -989,7 +990,7 @@
 {
 	struct overlay_cache_data *oc;
 	struct manager_cache_data *mc;
-	const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
+	const int num_ovls = dss_feat_get_num_ovls();
 	struct omap_overlay_manager *mgr;
 	int i;
 	u16 x, y, w, h;
@@ -1121,8 +1122,8 @@
 {
 	struct manager_cache_data *mc;
 	struct overlay_cache_data *oc;
-	const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
-	const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache);
+	const int num_ovls = dss_feat_get_num_ovls();
+	const int num_mgrs = dss_feat_get_num_mgrs();
 	struct omap_overlay_manager *mgr;
 	int i;
 
@@ -1151,10 +1152,10 @@
 {
 	struct manager_cache_data *mc;
 	struct overlay_cache_data *oc;
-	const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
-	const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache);
+	const int num_ovls = dss_feat_get_num_ovls();
+	const int num_mgrs = dss_feat_get_num_mgrs();
 	int i, r;
-	bool mgr_busy[2];
+	bool mgr_busy[MAX_DSS_MANAGERS];
 
 	mgr_busy[0] = dispc_go_busy(0);
 	mgr_busy[1] = dispc_go_busy(1);
@@ -1461,7 +1462,7 @@
 
 	num_managers = 0;
 
-	for (i = 0; i < 2; ++i) {
+	for (i = 0; i < dss_feat_get_num_mgrs(); ++i) {
 		struct omap_overlay_manager *mgr;
 		mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
 
@@ -1471,14 +1472,10 @@
 		case 0:
 			mgr->name = "lcd";
 			mgr->id = OMAP_DSS_CHANNEL_LCD;
-			mgr->supported_displays =
-				OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
-				OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI;
 			break;
 		case 1:
 			mgr->name = "tv";
 			mgr->id = OMAP_DSS_CHANNEL_DIGIT;
-			mgr->supported_displays = OMAP_DISPLAY_TYPE_VENC;
 			break;
 		}
 
@@ -1494,6 +1491,8 @@
 		mgr->disable = &dss_mgr_disable;
 
 		mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC;
+		mgr->supported_displays =
+			dss_feat_get_supported_displays(mgr->id);
 
 		dss_overlay_setup_dispc_manager(mgr);
 
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index 244dca8..75642c2 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -35,6 +35,7 @@
 #include <plat/cpu.h>
 
 #include "dss.h"
+#include "dss_features.h"
 
 static int num_overlays;
 static struct list_head overlay_list;
@@ -237,7 +238,8 @@
 	/* Video1 plane does not support global alpha
 	 * to always make it 255 completely opaque
 	 */
-	if (ovl->id == OMAP_DSS_VIDEO1)
+	if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
+			ovl->id == OMAP_DSS_VIDEO1)
 		info.global_alpha = 255;
 	else
 		info.global_alpha = simple_strtoul(buf, NULL, 10);
@@ -510,11 +512,11 @@
 	list_add_tail(&overlay->list, &overlay_list);
 }
 
-static struct omap_overlay *dispc_overlays[3];
+static struct omap_overlay *dispc_overlays[MAX_DSS_OVERLAYS];
 
 void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr)
 {
-	mgr->num_overlays = 3;
+	mgr->num_overlays = dss_feat_get_num_ovls();
 	mgr->overlays = dispc_overlays;
 }
 
@@ -535,7 +537,7 @@
 
 	num_overlays = 0;
 
-	for (i = 0; i < 3; ++i) {
+	for (i = 0; i < dss_feat_get_num_ovls(); ++i) {
 		struct omap_overlay *ovl;
 		ovl = kzalloc(sizeof(*ovl), GFP_KERNEL);
 
@@ -545,18 +547,12 @@
 		case 0:
 			ovl->name = "gfx";
 			ovl->id = OMAP_DSS_GFX;
-			ovl->supported_modes = cpu_is_omap34xx() ?
-				OMAP_DSS_COLOR_GFX_OMAP3 :
-				OMAP_DSS_COLOR_GFX_OMAP2;
 			ovl->caps = OMAP_DSS_OVL_CAP_DISPC;
 			ovl->info.global_alpha = 255;
 			break;
 		case 1:
 			ovl->name = "vid1";
 			ovl->id = OMAP_DSS_VIDEO1;
-			ovl->supported_modes = cpu_is_omap34xx() ?
-				OMAP_DSS_COLOR_VID1_OMAP3 :
-				OMAP_DSS_COLOR_VID_OMAP2;
 			ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
 				OMAP_DSS_OVL_CAP_DISPC;
 			ovl->info.global_alpha = 255;
@@ -564,9 +560,6 @@
 		case 2:
 			ovl->name = "vid2";
 			ovl->id = OMAP_DSS_VIDEO2;
-			ovl->supported_modes = cpu_is_omap34xx() ?
-				OMAP_DSS_COLOR_VID2_OMAP3 :
-				OMAP_DSS_COLOR_VID_OMAP2;
 			ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
 				OMAP_DSS_OVL_CAP_DISPC;
 			ovl->info.global_alpha = 255;
@@ -579,6 +572,9 @@
 		ovl->get_overlay_info = &dss_ovl_get_overlay_info;
 		ovl->wait_for_go = &dss_ovl_wait_for_go;
 
+		ovl->supported_modes =
+			dss_feat_get_supported_color_modes(ovl->id);
+
 		omap_dss_add_overlay(ovl);
 
 		r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
@@ -651,7 +647,7 @@
 	}
 
 	if (mgr) {
-		for (i = 0; i < 3; i++) {
+		for (i = 0; i < dss_feat_get_num_ovls(); i++) {
 			struct omap_overlay *ovl;
 			ovl = omap_dss_get_overlay(i);
 			if (!ovl->manager || force) {
diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig
index 43496d6..65149b2 100644
--- a/drivers/video/omap2/omapfb/Kconfig
+++ b/drivers/video/omap2/omapfb/Kconfig
@@ -3,7 +3,7 @@
         depends on FB && OMAP2_DSS
 
 	select OMAP2_VRAM
-	select OMAP2_VRFB
+	select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3
         select FB_CFB_FILLRECT
         select FB_CFB_COPYAREA
         select FB_CFB_IMAGEBLIT
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 04034d4..6a704f1 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -714,10 +714,10 @@
 		var->pixclock = timings.pixel_clock != 0 ?
 			KHZ2PICOS(timings.pixel_clock) :
 			0;
-		var->left_margin = timings.hfp;
-		var->right_margin = timings.hbp;
-		var->upper_margin = timings.vfp;
-		var->lower_margin = timings.vbp;
+		var->left_margin = timings.hbp;
+		var->right_margin = timings.hfp;
+		var->upper_margin = timings.vbp;
+		var->lower_margin = timings.vfp;
 		var->hsync_len = timings.hsw;
 		var->vsync_len = timings.vsw;
 	} else {
@@ -2059,10 +2059,10 @@
 
 	if (r != 0) {
 		timings->pixel_clock = PICOS2KHZ(var.pixclock);
-		timings->hfp = var.left_margin;
-		timings->hbp = var.right_margin;
-		timings->vfp = var.upper_margin;
-		timings->vbp = var.lower_margin;
+		timings->hbp = var.left_margin;
+		timings->hfp = var.right_margin;
+		timings->vbp = var.upper_margin;
+		timings->vfp = var.lower_margin;
 		timings->hsw = var.hsync_len;
 		timings->vsw = var.vsync_len;
 		timings->x_res = var.xres;
@@ -2198,6 +2198,16 @@
 		goto err0;
 	}
 
+	/* TODO : Replace cpu check with omap_has_vrfb once HAS_FEATURE
+	*	 available for OMAP2 and OMAP3
+	*/
+	if (def_vrfb && !cpu_is_omap24xx() && !cpu_is_omap34xx()) {
+		def_vrfb = 0;
+		dev_warn(&pdev->dev, "VRFB is not supported on this hardware, "
+				"ignoring the module parameter vrfb=y\n");
+	}
+
+
 	mutex_init(&fbdev->mtx);
 
 	fbdev->dev = &pdev->dev;
diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c
index 0c9ce88..68bd234 100644
--- a/drivers/video/xilinxfb.c
+++ b/drivers/video/xilinxfb.c
@@ -32,10 +32,14 @@
 #include <linux/dma-mapping.h>
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
+#include <linux/of_address.h>
 #include <linux/io.h>
 #include <linux/xilinxfb.h>
 #include <linux/slab.h>
+
+#ifdef CONFIG_PPC_DCR
 #include <asm/dcr.h>
+#endif
 
 #define DRIVER_NAME		"xilinxfb"
 
@@ -123,10 +127,10 @@
 						registers */
 	void __iomem	*regs;		/* virt. address of the control
 						registers */
-
+#ifdef CONFIG_PPC_DCR
 	dcr_host_t      dcr_host;
 	unsigned int    dcr_len;
-
+#endif
 	void		*fb_virt;	/* virt. address of the frame buffer */
 	dma_addr_t	fb_phys;	/* phys. address of the frame buffer */
 	int		fb_alloced;	/* Flag, was the fb memory alloced? */
@@ -152,9 +156,10 @@
 {
 	if (drvdata->flags & PLB_ACCESS_FLAG)
 		out_be32(drvdata->regs + (offset << 2), val);
+#ifdef CONFIG_PPC_DCR
 	else
 		dcr_write(drvdata->dcr_host, offset, val);
-
+#endif
 }
 
 static int
@@ -383,8 +388,11 @@
 	if (drvdata->flags & PLB_ACCESS_FLAG) {
 		iounmap(drvdata->regs);
 		release_mem_region(drvdata->regs_phys, 8);
-	} else
+	}
+#ifdef CONFIG_PPC_DCR
+	else
 		dcr_unmap(drvdata->dcr_host, drvdata->dcr_len);
+#endif
 
 	kfree(drvdata);
 	dev_set_drvdata(dev, NULL);
@@ -404,7 +412,7 @@
 	u32 tft_access;
 	struct xilinxfb_platform_data pdata;
 	struct resource res;
-	int size, rc, start;
+	int size, rc;
 	struct xilinxfb_drvdata *drvdata;
 
 	/* Copy with the default pdata (not a ptr reference!) */
@@ -437,7 +445,10 @@
 			dev_err(&op->dev, "invalid address\n");
 			goto err;
 		}
-	} else {
+	}
+#ifdef CONFIG_PPC_DCR
+	else {
+		int start;
 		res.start = 0;
 		start = dcr_resource_start(op->dev.of_node, 0);
 		drvdata->dcr_len = dcr_resource_len(op->dev.of_node, 0);
@@ -447,6 +458,7 @@
 			goto err;
 		}
 	}
+#endif
 
 	prop = of_get_property(op->dev.of_node, "phys-size", &size);
 	if ((prop) && (size >= sizeof(u32)*2)) {
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
index 81e3d61..3dd4971 100644
--- a/drivers/watchdog/omap_wdt.c
+++ b/drivers/watchdog/omap_wdt.c
@@ -38,11 +38,11 @@
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/moduleparam.h>
-#include <linux/clk.h>
 #include <linux/bitops.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
 #include <linux/slab.h>
+#include <linux/pm_runtime.h>
 #include <mach/hardware.h>
 #include <plat/prcm.h>
 
@@ -61,8 +61,6 @@
 	void __iomem    *base;          /* physical */
 	struct device   *dev;
 	int             omap_wdt_users;
-	struct clk      *ick;
-	struct clk      *fck;
 	struct resource *mem;
 	struct miscdevice omap_wdt_miscdev;
 };
@@ -146,8 +144,7 @@
 	if (test_and_set_bit(1, (unsigned long *)&(wdev->omap_wdt_users)))
 		return -EBUSY;
 
-	clk_enable(wdev->ick);    /* Enable the interface clock */
-	clk_enable(wdev->fck);    /* Enable the functional clock */
+	pm_runtime_get_sync(wdev->dev);
 
 	/* initialize prescaler */
 	while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01)
@@ -177,8 +174,7 @@
 
 	omap_wdt_disable(wdev);
 
-	clk_disable(wdev->ick);
-	clk_disable(wdev->fck);
+	pm_runtime_put_sync(wdev->dev);
 #else
 	printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n");
 #endif
@@ -293,19 +289,7 @@
 
 	wdev->omap_wdt_users = 0;
 	wdev->mem = mem;
-
-	wdev->ick = clk_get(&pdev->dev, "ick");
-	if (IS_ERR(wdev->ick)) {
-		ret = PTR_ERR(wdev->ick);
-		wdev->ick = NULL;
-		goto err_clk;
-	}
-	wdev->fck = clk_get(&pdev->dev, "fck");
-	if (IS_ERR(wdev->fck)) {
-		ret = PTR_ERR(wdev->fck);
-		wdev->fck = NULL;
-		goto err_clk;
-	}
+	wdev->dev = &pdev->dev;
 
 	wdev->base = ioremap(res->start, resource_size(res));
 	if (!wdev->base) {
@@ -315,8 +299,8 @@
 
 	platform_set_drvdata(pdev, wdev);
 
-	clk_enable(wdev->ick);
-	clk_enable(wdev->fck);
+	pm_runtime_enable(wdev->dev);
+	pm_runtime_get_sync(wdev->dev);
 
 	omap_wdt_disable(wdev);
 	omap_wdt_adjust_timeout(timer_margin);
@@ -334,11 +318,7 @@
 		__raw_readl(wdev->base + OMAP_WATCHDOG_REV) & 0xFF,
 		timer_margin);
 
-	/* autogate OCP interface clock */
-	__raw_writel(0x01, wdev->base + OMAP_WATCHDOG_SYS_CONFIG);
-
-	clk_disable(wdev->ick);
-	clk_disable(wdev->fck);
+	pm_runtime_put_sync(wdev->dev);
 
 	omap_wdt_dev = pdev;
 
@@ -350,12 +330,6 @@
 
 err_ioremap:
 	wdev->base = NULL;
-
-err_clk:
-	if (wdev->ick)
-		clk_put(wdev->ick);
-	if (wdev->fck)
-		clk_put(wdev->fck);
 	kfree(wdev);
 
 err_kzalloc:
@@ -387,8 +361,6 @@
 	release_mem_region(res->start, resource_size(res));
 	platform_set_drvdata(pdev, NULL);
 
-	clk_put(wdev->ick);
-	clk_put(wdev->fck);
 	iounmap(wdev->base);
 
 	kfree(wdev);
diff --git a/firmware/ihex2fw.c b/firmware/ihex2fw.c
index 5a03ba8..ba0cf0b 100644
--- a/firmware/ihex2fw.c
+++ b/firmware/ihex2fw.c
@@ -55,6 +55,7 @@
 
 static int sort_records = 0;
 static int wide_records = 0;
+static int include_jump = 0;
 
 static int usage(void)
 {
@@ -63,6 +64,7 @@
 	fprintf(stderr, "usage: ihex2fw [<options>] <src.HEX> <dst.fw>\n");
 	fprintf(stderr, "       -w: wide records (16-bit length)\n");
 	fprintf(stderr, "       -s: sort records by address\n");
+	fprintf(stderr, "       -j: include records for CS:IP/EIP address\n");
 	return 1;
 }
 
@@ -73,7 +75,7 @@
 	uint8_t *data;
 	int opt;
 
-	while ((opt = getopt(argc, argv, "ws")) != -1) {
+	while ((opt = getopt(argc, argv, "wsj")) != -1) {
 		switch (opt) {
 		case 'w':
 			wide_records = 1;
@@ -81,7 +83,9 @@
 		case 's':
 			sort_records = 1;
 			break;
-		default:
+		case 'j':
+			include_jump = 1;
+			break;
 			return usage();
 		}
 	}
@@ -128,6 +132,7 @@
 {
 	struct ihex_binrec *record;
 	uint32_t offset = 0;
+	uint32_t data32;
 	uint8_t type, crc = 0, crcbyte = 0;
 	int i, j;
 	int line = 1;
@@ -223,8 +228,14 @@
 			return -EINVAL;
 		}
 
+		memcpy(&data32, &record->data[0], sizeof(data32));
+		data32 = htonl(data32);
+		memcpy(&record->data[0], &data32, sizeof(data32));
+
 		/* These records contain the CS/IP or EIP where execution
-		 * starts. Don't really know what to do with them. */
+		 * starts. If requested output this as a record. */
+		if (include_jump)
+			file_record(record);
 		goto next_record;
 
 	default:
diff --git a/fs/Makefile b/fs/Makefile
index e6ec1d3..26956fc 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -29,10 +29,7 @@
 obj-$(CONFIG_AIO)               += aio.o
 obj-$(CONFIG_FILE_LOCKING)      += locks.o
 obj-$(CONFIG_COMPAT)		+= compat.o compat_ioctl.o
-
-nfsd-$(CONFIG_NFSD)		:= nfsctl.o
-obj-y				+= $(nfsd-y) $(nfsd-m)
-
+obj-$(CONFIG_NFSD_DEPRECATED)	+= nfsctl.o
 obj-$(CONFIG_BINFMT_AOUT)	+= binfmt_aout.o
 obj-$(CONFIG_BINFMT_EM86)	+= binfmt_em86.o
 obj-$(CONFIG_BINFMT_MISC)	+= binfmt_misc.o
diff --git a/fs/afs/write.c b/fs/afs/write.c
index 722743b..15690bb 100644
--- a/fs/afs/write.c
+++ b/fs/afs/write.c
@@ -438,7 +438,6 @@
  */
 int afs_writepage(struct page *page, struct writeback_control *wbc)
 {
-	struct backing_dev_info *bdi = page->mapping->backing_dev_info;
 	struct afs_writeback *wb;
 	int ret;
 
@@ -455,8 +454,6 @@
 	}
 
 	wbc->nr_to_write -= ret;
-	if (wbc->nonblocking && bdi_write_congested(bdi))
-		wbc->encountered_congestion = 1;
 
 	_leave(" = 0");
 	return 0;
@@ -469,7 +466,6 @@
 				 struct writeback_control *wbc,
 				 pgoff_t index, pgoff_t end, pgoff_t *_next)
 {
-	struct backing_dev_info *bdi = mapping->backing_dev_info;
 	struct afs_writeback *wb;
 	struct page *page;
 	int ret, n;
@@ -529,11 +525,6 @@
 
 		wbc->nr_to_write -= ret;
 
-		if (wbc->nonblocking && bdi_write_congested(bdi)) {
-			wbc->encountered_congestion = 1;
-			break;
-		}
-
 		cond_resched();
 	} while (index < end && wbc->nr_to_write > 0);
 
@@ -548,24 +539,16 @@
 int afs_writepages(struct address_space *mapping,
 		   struct writeback_control *wbc)
 {
-	struct backing_dev_info *bdi = mapping->backing_dev_info;
 	pgoff_t start, end, next;
 	int ret;
 
 	_enter("");
 
-	if (wbc->nonblocking && bdi_write_congested(bdi)) {
-		wbc->encountered_congestion = 1;
-		_leave(" = 0 [congest]");
-		return 0;
-	}
-
 	if (wbc->range_cyclic) {
 		start = mapping->writeback_index;
 		end = -1;
 		ret = afs_writepages_region(mapping, wbc, start, end, &next);
-		if (start > 0 && wbc->nr_to_write > 0 && ret == 0 &&
-		    !(wbc->nonblocking && wbc->encountered_congestion))
+		if (start > 0 && wbc->nr_to_write > 0 && ret == 0)
 			ret = afs_writepages_region(mapping, wbc, 0, start,
 						    &next);
 		mapping->writeback_index = next;
diff --git a/fs/buffer.c b/fs/buffer.c
index d895d9f..5930e38 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1705,7 +1705,7 @@
 		 * and kswapd activity, but those code paths have their own
 		 * higher-level throttling.
 		 */
-		if (wbc->sync_mode != WB_SYNC_NONE || !wbc->nonblocking) {
+		if (wbc->sync_mode != WB_SYNC_NONE) {
 			lock_buffer(bh);
 		} else if (!trylock_buffer(bh)) {
 			redirty_page_for_writepage(wbc, page);
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index 51bcc5c..e9c874a 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -591,7 +591,6 @@
 				 struct writeback_control *wbc)
 {
 	struct inode *inode = mapping->host;
-	struct backing_dev_info *bdi = mapping->backing_dev_info;
 	struct ceph_inode_info *ci = ceph_inode(inode);
 	struct ceph_fs_client *fsc;
 	pgoff_t index, start, end;
@@ -633,13 +632,6 @@
 
 	pagevec_init(&pvec, 0);
 
-	/* ?? */
-	if (wbc->nonblocking && bdi_write_congested(bdi)) {
-		dout(" writepages congested\n");
-		wbc->encountered_congestion = 1;
-		goto out_final;
-	}
-
 	/* where to start/end? */
 	if (wbc->range_cyclic) {
 		start = mapping->writeback_index; /* Start from prev offset */
@@ -885,7 +877,6 @@
 		rc = 0;  /* vfs expects us to return 0 */
 	ceph_put_snap_context(snapc);
 	dout("writepages done, rc = %d\n", rc);
-out_final:
 	return rc;
 }
 
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 8c81e7b..45af003 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1303,7 +1303,6 @@
 static int cifs_writepages(struct address_space *mapping,
 			   struct writeback_control *wbc)
 {
-	struct backing_dev_info *bdi = mapping->backing_dev_info;
 	unsigned int bytes_to_write;
 	unsigned int bytes_written;
 	struct cifs_sb_info *cifs_sb;
@@ -1326,15 +1325,6 @@
 	int scanned = 0;
 	int xid, long_op;
 
-	/*
-	 * BB: Is this meaningful for a non-block-device file system?
-	 * If it is, we should test it again after we do I/O
-	 */
-	if (wbc->nonblocking && bdi_write_congested(bdi)) {
-		wbc->encountered_congestion = 1;
-		return 0;
-	}
-
 	cifs_sb = CIFS_SB(mapping->host->i_sb);
 
 	/*
diff --git a/fs/compat.c b/fs/compat.c
index 0644a15..f03abda 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1963,7 +1963,7 @@
 }
 #endif /* HAVE_SET_RESTORE_SIGMASK */
 
-#if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)
+#if (defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)) && !defined(CONFIG_NFSD_DEPRECATED)
 /* Stuff for NFS server syscalls... */
 struct compat_nfsctl_svc {
 	u16			svc32_port;
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 48d74c7..85882f6 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -218,7 +218,7 @@
  * filesystems can use it to hold additional state between get_block calls and
  * dio_complete.
  */
-static int dio_complete(struct dio *dio, loff_t offset, int ret, bool is_async)
+static ssize_t dio_complete(struct dio *dio, loff_t offset, ssize_t ret, bool is_async)
 {
 	ssize_t transferred = 0;
 
diff --git a/fs/exec.c b/fs/exec.c
index 6d2b6f9..3aa75b8 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -54,6 +54,7 @@
 #include <linux/fsnotify.h>
 #include <linux/fs_struct.h>
 #include <linux/pipe_fs_i.h>
+#include <linux/oom.h>
 
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -759,6 +760,10 @@
 	tsk->mm = mm;
 	tsk->active_mm = mm;
 	activate_mm(active_mm, mm);
+	if (old_mm && tsk->signal->oom_score_adj == OOM_SCORE_ADJ_MIN) {
+		atomic_dec(&old_mm->oom_disable_count);
+		atomic_inc(&tsk->mm->oom_disable_count);
+	}
 	task_unlock(tsk);
 	arch_pick_mmap_layout(mm);
 	if (old_mm) {
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index f6af81a..aed881a 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -586,7 +586,7 @@
 	global_dirty_limits(&background_thresh, &dirty_thresh);
 
 	return (global_page_state(NR_FILE_DIRTY) +
-		global_page_state(NR_UNSTABLE_NFS) >= background_thresh);
+		global_page_state(NR_UNSTABLE_NFS) > background_thresh);
 }
 
 /*
@@ -724,6 +724,10 @@
 		return 0;
 
 	wb->last_old_flush = jiffies;
+	/*
+	 * Add in the number of potentially dirty inodes, because each inode
+	 * write can dirty pagecache in the underlying blockdev.
+	 */
 	nr_pages = global_page_state(NR_FILE_DIRTY) +
 			global_page_state(NR_UNSTABLE_NFS) +
 			get_nr_dirty_inodes();
@@ -793,7 +797,7 @@
 	struct backing_dev_info *bdi = wb->bdi;
 	long pages_written;
 
-	current->flags |= PF_FLUSHER | PF_SWAPWRITE;
+	current->flags |= PF_SWAPWRITE;
 	set_freezable();
 	wb->last_active = jiffies;
 
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index cde755c..b986642 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -809,11 +809,9 @@
 	int err;
 	struct page *page = *pagep;
 
-	if (page && zeroing && count < PAGE_SIZE) {
-		void *mapaddr = kmap_atomic(page, KM_USER1);
-		memset(mapaddr, 0, PAGE_SIZE);
-		kunmap_atomic(mapaddr, KM_USER1);
-	}
+	if (page && zeroing && count < PAGE_SIZE)
+		clear_highpage(page);
+
 	while (count) {
 		if (cs->write && cs->pipebufs && page) {
 			return fuse_ref_page(cs, page, offset, count);
@@ -830,10 +828,10 @@
 			}
 		}
 		if (page) {
-			void *mapaddr = kmap_atomic(page, KM_USER1);
+			void *mapaddr = kmap_atomic(page, KM_USER0);
 			void *buf = mapaddr + offset;
 			offset += fuse_copy_do(cs, &buf, &count);
-			kunmap_atomic(mapaddr, KM_USER1);
+			kunmap_atomic(mapaddr, KM_USER0);
 		} else
 			offset += fuse_copy_do(cs, NULL, &count);
 	}
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c
index f3b071f..939739c 100644
--- a/fs/gfs2/meta_io.c
+++ b/fs/gfs2/meta_io.c
@@ -55,7 +55,7 @@
 		 * activity, but those code paths have their own higher-level
 		 * throttling.
 		 */
-		if (wbc->sync_mode != WB_SYNC_NONE || !wbc->nonblocking) {
+		if (wbc->sync_mode != WB_SYNC_NONE) {
 			lock_buffer(bh);
 		} else if (!trylock_buffer(bh)) {
 			redirty_page_for_writepage(wbc, page);
diff --git a/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c
index 8d02683..d51a9838 100644
--- a/fs/hostfs/hostfs_user.c
+++ b/fs/hostfs/hostfs_user.c
@@ -94,8 +94,7 @@
 
 	dir = opendir(path);
 	*err_out = errno;
-	if (dir == NULL)
-		return NULL;
+
 	return dir;
 }
 
@@ -205,7 +204,7 @@
 	if (attrs->ia_valid & HOSTFS_ATTR_MODE) {
 		if (fd >= 0) {
 			if (fchmod(fd, attrs->ia_mode) != 0)
-				return (-errno);
+				return -errno;
 		} else if (chmod(file, attrs->ia_mode) != 0) {
 			return -errno;
 		}
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 8d0607b..b14be3f 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -31,6 +31,7 @@
 #include <linux/statfs.h>
 #include <linux/security.h>
 #include <linux/magic.h>
+#include <linux/migrate.h>
 
 #include <asm/uaccess.h>
 
@@ -574,6 +575,19 @@
 	return 0;
 }
 
+static int hugetlbfs_migrate_page(struct address_space *mapping,
+				struct page *newpage, struct page *page)
+{
+	int rc;
+
+	rc = migrate_huge_page_move_mapping(mapping, newpage, page);
+	if (rc)
+		return rc;
+	migrate_page_copy(newpage, page);
+
+	return 0;
+}
+
 static int hugetlbfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
 	struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(dentry->d_sb);
@@ -660,6 +674,7 @@
 	.write_begin	= hugetlbfs_write_begin,
 	.write_end	= hugetlbfs_write_end,
 	.set_page_dirty	= hugetlbfs_set_page_dirty,
+	.migratepage    = hugetlbfs_migrate_page,
 };
 
 
diff --git a/fs/inode.c b/fs/inode.c
index a6d6068..ae2727a 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -24,6 +24,7 @@
 #include <linux/mount.h>
 #include <linux/async.h>
 #include <linux/posix_acl.h>
+#include <linux/ima.h>
 
 /*
  * This is needed for the following functions:
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
index 64fd427..d5bb868 100644
--- a/fs/lockd/clntlock.c
+++ b/fs/lockd/clntlock.c
@@ -42,6 +42,7 @@
 };
 
 static LIST_HEAD(nlm_blocked);
+static DEFINE_SPINLOCK(nlm_blocked_lock);
 
 /**
  * nlmclnt_init - Set up per-NFS mount point lockd data structures
@@ -97,7 +98,10 @@
 		block->b_lock = fl;
 		init_waitqueue_head(&block->b_wait);
 		block->b_status = nlm_lck_blocked;
+
+		spin_lock(&nlm_blocked_lock);
 		list_add(&block->b_list, &nlm_blocked);
+		spin_unlock(&nlm_blocked_lock);
 	}
 	return block;
 }
@@ -106,7 +110,9 @@
 {
 	if (block == NULL)
 		return;
+	spin_lock(&nlm_blocked_lock);
 	list_del(&block->b_list);
+	spin_unlock(&nlm_blocked_lock);
 	kfree(block);
 }
 
@@ -154,6 +160,7 @@
 	 * Look up blocked request based on arguments. 
 	 * Warning: must not use cookie to match it!
 	 */
+	spin_lock(&nlm_blocked_lock);
 	list_for_each_entry(block, &nlm_blocked, b_list) {
 		struct file_lock *fl_blocked = block->b_lock;
 
@@ -178,6 +185,7 @@
 		wake_up(&block->b_wait);
 		res = nlm_granted;
 	}
+	spin_unlock(&nlm_blocked_lock);
 	return res;
 }
 
@@ -216,10 +224,6 @@
 	allow_signal(SIGKILL);
 
 	down_write(&host->h_rwsem);
-
-	/* This one ensures that our parent doesn't terminate while the
-	 * reclaim is in progress */
-	lock_kernel();
 	lockd_up();	/* note: this cannot fail as lockd is already running */
 
 	dprintk("lockd: reclaiming locks for host %s\n", host->h_name);
@@ -260,16 +264,17 @@
 	dprintk("NLM: done reclaiming locks for host %s\n", host->h_name);
 
 	/* Now, wake up all processes that sleep on a blocked lock */
+	spin_lock(&nlm_blocked_lock);
 	list_for_each_entry(block, &nlm_blocked, b_list) {
 		if (block->b_host == host) {
 			block->b_status = nlm_lck_denied_grace_period;
 			wake_up(&block->b_wait);
 		}
 	}
+	spin_unlock(&nlm_blocked_lock);
 
 	/* Release host handle after use */
 	nlm_release_host(host);
 	lockd_down();
-	unlock_kernel();
 	return 0;
 }
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index 7932c39..47ea1e1 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -166,7 +166,6 @@
 	/* Set up the argument struct */
 	nlmclnt_setlockargs(call, fl);
 
-	lock_kernel();
 	if (IS_SETLK(cmd) || IS_SETLKW(cmd)) {
 		if (fl->fl_type != F_UNLCK) {
 			call->a_args.block = IS_SETLKW(cmd) ? 1 : 0;
@@ -177,10 +176,8 @@
 		status = nlmclnt_test(call, fl);
 	else
 		status = -EINVAL;
-
 	fl->fl_ops->fl_release_private(fl);
 	fl->fl_ops = NULL;
-	unlock_kernel();
 
 	dprintk("lockd: clnt proc returns %d\n", status);
 	return status;
@@ -226,9 +223,7 @@
 
 static void nlmclnt_rpc_release(void *data)
 {
-	lock_kernel();
 	nlm_release_call(data);
-	unlock_kernel();
 }
 
 static int nlm_wait_on_grace(wait_queue_head_t *queue)
@@ -448,14 +443,18 @@
 
 static void nlmclnt_locks_copy_lock(struct file_lock *new, struct file_lock *fl)
 {
+	spin_lock(&fl->fl_u.nfs_fl.owner->host->h_lock);
 	new->fl_u.nfs_fl.state = fl->fl_u.nfs_fl.state;
 	new->fl_u.nfs_fl.owner = nlm_get_lockowner(fl->fl_u.nfs_fl.owner);
 	list_add_tail(&new->fl_u.nfs_fl.list, &fl->fl_u.nfs_fl.owner->host->h_granted);
+	spin_unlock(&fl->fl_u.nfs_fl.owner->host->h_lock);
 }
 
 static void nlmclnt_locks_release_private(struct file_lock *fl)
 {
+	spin_lock(&fl->fl_u.nfs_fl.owner->host->h_lock);
 	list_del(&fl->fl_u.nfs_fl.list);
+	spin_unlock(&fl->fl_u.nfs_fl.owner->host->h_lock);
 	nlm_put_lockowner(fl->fl_u.nfs_fl.owner);
 }
 
@@ -721,9 +720,7 @@
 die:
 	return;
  retry_rebind:
-	lock_kernel();
 	nlm_rebind_host(req->a_host);
-	unlock_kernel();
  retry_unlock:
 	rpc_restart_call(task);
 }
@@ -801,9 +798,7 @@
 	/* Don't ever retry more than 3 times */
 	if (req->a_retries++ >= NLMCLNT_MAX_RETRIES)
 		goto die;
-	lock_kernel();
 	nlm_rebind_host(req->a_host);
-	unlock_kernel();
 	rpc_restart_call(task);
 	rpc_delay(task, 30 * HZ);
 }
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index bb464d1210..25e21e4 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -353,6 +353,7 @@
 			.to_retries	= 5U,
 		};
 		struct rpc_create_args args = {
+			.net		= &init_net,
 			.protocol	= host->h_proto,
 			.address	= nlm_addr(host),
 			.addrsize	= host->h_addrlen,
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index e301546..e0c9189 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -69,6 +69,7 @@
 		.sin_addr.s_addr	= htonl(INADDR_LOOPBACK),
 	};
 	struct rpc_create_args args = {
+		.net			= &init_net,
 		.protocol		= XPRT_TRANSPORT_UDP,
 		.address		= (struct sockaddr *)&sin,
 		.addrsize		= sizeof(sin),
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index f1bacf1..b13aabc 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -206,7 +206,7 @@
 
 	xprt = svc_find_xprt(serv, name, family, 0);
 	if (xprt == NULL)
-		return svc_create_xprt(serv, name, family, port,
+		return svc_create_xprt(serv, name, &init_net, family, port,
 						SVC_SOCK_DEFAULTS);
 	svc_xprt_put(xprt);
 	return 0;
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index 031c656..a336e83 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -230,9 +230,7 @@
 
 static void nlm4svc_callback_release(void *data)
 {
-	lock_kernel();
 	nlm_release_call(data);
-	unlock_kernel();
 }
 
 static const struct rpc_call_ops nlm4svc_callback_ops = {
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index 84055d3..6f1ef00 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -52,12 +52,13 @@
  * The list of blocked locks to retry
  */
 static LIST_HEAD(nlm_blocked);
+static DEFINE_SPINLOCK(nlm_blocked_lock);
 
 /*
  * Insert a blocked lock into the global list
  */
 static void
-nlmsvc_insert_block(struct nlm_block *block, unsigned long when)
+nlmsvc_insert_block_locked(struct nlm_block *block, unsigned long when)
 {
 	struct nlm_block *b;
 	struct list_head *pos;
@@ -87,6 +88,13 @@
 	block->b_when = when;
 }
 
+static void nlmsvc_insert_block(struct nlm_block *block, unsigned long when)
+{
+	spin_lock(&nlm_blocked_lock);
+	nlmsvc_insert_block_locked(block, when);
+	spin_unlock(&nlm_blocked_lock);
+}
+
 /*
  * Remove a block from the global list
  */
@@ -94,7 +102,9 @@
 nlmsvc_remove_block(struct nlm_block *block)
 {
 	if (!list_empty(&block->b_list)) {
+		spin_lock(&nlm_blocked_lock);
 		list_del_init(&block->b_list);
+		spin_unlock(&nlm_blocked_lock);
 		nlmsvc_release_block(block);
 	}
 }
@@ -651,7 +661,7 @@
 	struct nlm_block *block;
 	int rc = -ENOENT;
 
-	lock_kernel();
+	spin_lock(&nlm_blocked_lock);
 	list_for_each_entry(block, &nlm_blocked, b_list) {
 		if (nlm_compare_locks(&block->b_call->a_args.lock.fl, fl)) {
 			dprintk("lockd: nlmsvc_notify_blocked block %p flags %d\n",
@@ -665,13 +675,13 @@
 			} else if (result == 0)
 				block->b_granted = 1;
 
-			nlmsvc_insert_block(block, 0);
+			nlmsvc_insert_block_locked(block, 0);
 			svc_wake_up(block->b_daemon);
 			rc = 0;
 			break;
 		}
 	}
-	unlock_kernel();
+	spin_unlock(&nlm_blocked_lock);
 	if (rc == -ENOENT)
 		printk(KERN_WARNING "lockd: grant for unknown block\n");
 	return rc;
@@ -803,7 +813,7 @@
 
 	dprintk("lockd: GRANT_MSG RPC callback\n");
 
-	lock_kernel();
+	spin_lock(&nlm_blocked_lock);
 	/* if the block is not on a list at this point then it has
 	 * been invalidated. Don't try to requeue it.
 	 *
@@ -825,19 +835,20 @@
 		/* Call was successful, now wait for client callback */
 		timeout = 60 * HZ;
 	}
-	nlmsvc_insert_block(block, timeout);
+	nlmsvc_insert_block_locked(block, timeout);
 	svc_wake_up(block->b_daemon);
 out:
-	unlock_kernel();
+	spin_unlock(&nlm_blocked_lock);
 }
 
+/*
+ * FIXME: nlmsvc_release_block() grabs a mutex.  This is not allowed for an
+ * .rpc_release rpc_call_op
+ */
 static void nlmsvc_grant_release(void *data)
 {
 	struct nlm_rqst		*call = data;
-
-	lock_kernel();
 	nlmsvc_release_block(call->a_block);
-	unlock_kernel();
 }
 
 static const struct rpc_call_ops nlmsvc_grant_ops = {
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index 0f2ab74..c3069f3 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -260,9 +260,7 @@
 
 static void nlmsvc_callback_release(void *data)
 {
-	lock_kernel();
 	nlm_release_call(data);
-	unlock_kernel();
 }
 
 static const struct rpc_call_ops nlmsvc_callback_ops = {
diff --git a/fs/locks.c b/fs/locks.c
index 8b2b6ad..4de3a26 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -2109,7 +2109,7 @@
 #include <linux/seq_file.h>
 
 static void lock_get_status(struct seq_file *f, struct file_lock *fl,
-							int id, char *pfx)
+			    loff_t id, char *pfx)
 {
 	struct inode *inode = NULL;
 	unsigned int fl_pid;
@@ -2122,7 +2122,7 @@
 	if (fl->fl_file != NULL)
 		inode = fl->fl_file->f_path.dentry->d_inode;
 
-	seq_printf(f, "%d:%s ", id, pfx);
+	seq_printf(f, "%lld:%s ", id, pfx);
 	if (IS_POSIX(fl)) {
 		seq_printf(f, "%6s %s ",
 			     (fl->fl_flags & FL_ACCESS) ? "ACCESS" : "POSIX ",
@@ -2185,24 +2185,27 @@
 
 	fl = list_entry(v, struct file_lock, fl_link);
 
-	lock_get_status(f, fl, (long)f->private, "");
+	lock_get_status(f, fl, *((loff_t *)f->private), "");
 
 	list_for_each_entry(bfl, &fl->fl_block, fl_block)
-		lock_get_status(f, bfl, (long)f->private, " ->");
+		lock_get_status(f, bfl, *((loff_t *)f->private), " ->");
 
-	f->private++;
 	return 0;
 }
 
 static void *locks_start(struct seq_file *f, loff_t *pos)
 {
+	loff_t *p = f->private;
+
 	lock_flocks();
-	f->private = (void *)1;
+	*p = (*pos + 1);
 	return seq_list_start(&file_lock_list, *pos);
 }
 
 static void *locks_next(struct seq_file *f, void *v, loff_t *pos)
 {
+	loff_t *p = f->private;
+	++*p;
 	return seq_list_next(v, &file_lock_list, pos);
 }
 
@@ -2220,14 +2223,14 @@
 
 static int locks_open(struct inode *inode, struct file *filp)
 {
-	return seq_open(filp, &locks_seq_operations);
+	return seq_open_private(filp, &locks_seq_operations, sizeof(loff_t));
 }
 
 static const struct file_operations proc_locks_operations = {
 	.open		= locks_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
-	.release	= seq_release,
+	.release	= seq_release_private,
 };
 
 static int __init proc_locks_init(void)
diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
index b950415..fd66765 100644
--- a/fs/nfs/Kconfig
+++ b/fs/nfs/Kconfig
@@ -77,13 +77,17 @@
 
 config NFS_V4_1
 	bool "NFS client support for NFSv4.1 (EXPERIMENTAL)"
-	depends on NFS_V4 && EXPERIMENTAL
+	depends on NFS_FS && NFS_V4 && EXPERIMENTAL
+	select PNFS_FILE_LAYOUT
 	help
 	  This option enables support for minor version 1 of the NFSv4 protocol
-	  (draft-ietf-nfsv4-minorversion1) in the kernel's NFS client.
+	  (RFC 5661) in the kernel's NFS client.
 
 	  If unsure, say N.
 
+config PNFS_FILE_LAYOUT
+	tristate
+
 config ROOT_NFS
 	bool "Root file system on NFS"
 	depends on NFS_FS=y && IP_PNP
@@ -118,3 +122,14 @@
 	select DNS_RESOLVER
 	select KEYS
 	default y
+
+config NFS_USE_NEW_IDMAPPER
+	bool "Use the new idmapper upcall routine"
+	depends on NFS_V4 && KEYS
+	help
+	  Say Y here if you want NFS to use the new idmapper upcall functions.
+	  You will need /sbin/request-key (usually provided by the keyutils
+	  package).  For details, read
+	  <file:Documentation/filesystems/nfs/idmapper.txt>.
+
+	  If you are unsure, say N.
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index da7fda6..4776ff9 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -15,5 +15,9 @@
 			   delegation.o idmap.o \
 			   callback.o callback_xdr.o callback_proc.o \
 			   nfs4namespace.o
+nfs-$(CONFIG_NFS_V4_1)	+= pnfs.o
 nfs-$(CONFIG_SYSCTL) += sysctl.o
 nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o
+
+obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o
+nfs_layout_nfsv41_files-y := nfs4filelayout.o nfs4filelayoutdev.o
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index e17b49e..aeec017 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -109,7 +109,7 @@
 {
 	int ret;
 
-	ret = svc_create_xprt(serv, "tcp", PF_INET,
+	ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET,
 				nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS);
 	if (ret <= 0)
 		goto out_err;
@@ -117,7 +117,7 @@
 	dprintk("NFS: Callback listener port = %u (af %u)\n",
 			nfs_callback_tcpport, PF_INET);
 
-	ret = svc_create_xprt(serv, "tcp", PF_INET6,
+	ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET6,
 				nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS);
 	if (ret > 0) {
 		nfs_callback_tcpport6 = ret;
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index 930d10f..2950fca 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -118,11 +118,11 @@
 	if (delegation == NULL)
 		return 0;
 
-	/* seqid is 4-bytes long */
-	if (((u32 *) &stateid->data)[0] != 0)
+	if (stateid->stateid.seqid != 0)
 		return 0;
-	if (memcmp(&delegation->stateid.data[4], &stateid->data[4],
-		   sizeof(stateid->data)-4))
+	if (memcmp(&delegation->stateid.stateid.other,
+		   &stateid->stateid.other,
+		   NFS4_STATEID_OTHER_SIZE))
 		return 0;
 
 	return 1;
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index e734072..0870d0d 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -48,6 +48,7 @@
 #include "iostat.h"
 #include "internal.h"
 #include "fscache.h"
+#include "pnfs.h"
 
 #define NFSDBG_FACILITY		NFSDBG_CLIENT
 
@@ -155,7 +156,9 @@
 	cred = rpc_lookup_machine_cred();
 	if (!IS_ERR(cred))
 		clp->cl_machine_cred = cred;
-
+#if defined(CONFIG_NFS_V4_1)
+	INIT_LIST_HEAD(&clp->cl_layouts);
+#endif
 	nfs_fscache_get_client_cookie(clp);
 
 	return clp;
@@ -252,6 +255,7 @@
 		nfs_free_client(clp);
 	}
 }
+EXPORT_SYMBOL_GPL(nfs_put_client);
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 /*
@@ -601,6 +605,7 @@
 {
 	struct rpc_clnt		*clnt = NULL;
 	struct rpc_create_args args = {
+		.net		= &init_net,
 		.protocol	= clp->cl_proto,
 		.address	= (struct sockaddr *)&clp->cl_addr,
 		.addrsize	= clp->cl_addrlen,
@@ -635,7 +640,8 @@
  */
 static void nfs_destroy_server(struct nfs_server *server)
 {
-	if (!(server->flags & NFS_MOUNT_NONLM))
+	if (!(server->flags & NFS_MOUNT_LOCAL_FLOCK) ||
+			!(server->flags & NFS_MOUNT_LOCAL_FCNTL))
 		nlmclnt_done(server->nlm_host);
 }
 
@@ -657,7 +663,8 @@
 
 	if (nlm_init.nfs_version > 3)
 		return 0;
-	if (server->flags & NFS_MOUNT_NONLM)
+	if ((server->flags & NFS_MOUNT_LOCAL_FLOCK) &&
+			(server->flags & NFS_MOUNT_LOCAL_FCNTL))
 		return 0;
 
 	switch (clp->cl_proto) {
@@ -898,11 +905,13 @@
 	if (server->wsize > NFS_MAX_FILE_IO_SIZE)
 		server->wsize = NFS_MAX_FILE_IO_SIZE;
 	server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+	set_pnfs_layoutdriver(server, fsinfo->layouttype);
+
 	server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL);
 
 	server->dtsize = nfs_block_size(fsinfo->dtpref, NULL);
-	if (server->dtsize > PAGE_CACHE_SIZE)
-		server->dtsize = PAGE_CACHE_SIZE;
+	if (server->dtsize > PAGE_CACHE_SIZE * NFS_MAX_READDIR_PAGES)
+		server->dtsize = PAGE_CACHE_SIZE * NFS_MAX_READDIR_PAGES;
 	if (server->dtsize > server->rsize)
 		server->dtsize = server->rsize;
 
@@ -913,6 +922,8 @@
 
 	server->maxfilesize = fsinfo->maxfilesize;
 
+	server->time_delta = fsinfo->time_delta;
+
 	/* We're airborne Set socket buffersize */
 	rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100);
 }
@@ -935,6 +946,7 @@
 	}
 
 	fsinfo.fattr = fattr;
+	fsinfo.layouttype = 0;
 	error = clp->rpc_ops->fsinfo(server, mntfh, &fsinfo);
 	if (error < 0)
 		goto out_error;
@@ -1017,6 +1029,7 @@
 {
 	dprintk("--> nfs_free_server()\n");
 
+	unset_pnfs_layoutdriver(server);
 	spin_lock(&nfs_client_lock);
 	list_del(&server->client_link);
 	list_del(&server->master_link);
@@ -1356,8 +1369,9 @@
 
 	/* Initialise the client representation from the mount data */
 	server->flags = data->flags;
-	server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR|
-		NFS_CAP_POSIX_LOCK;
+	server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR|NFS_CAP_POSIX_LOCK;
+	if (!(data->flags & NFS_MOUNT_NORDIRPLUS))
+			server->caps |= NFS_CAP_READDIRPLUS;
 	server->options = data->options;
 
 	/* Get a client record */
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 0fac7fe..07ac384 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -33,11 +33,12 @@
 #include <linux/namei.h>
 #include <linux/mount.h>
 #include <linux/sched.h>
+#include <linux/vmalloc.h>
 
-#include "nfs4_fs.h"
 #include "delegation.h"
 #include "iostat.h"
 #include "internal.h"
+#include "fscache.h"
 
 /* #define NFS_DEBUG_VERBOSE 1 */
 
@@ -55,6 +56,7 @@
 		      struct inode *, struct dentry *);
 static int nfs_fsync_dir(struct file *, int);
 static loff_t nfs_llseek_dir(struct file *, loff_t, int);
+static int nfs_readdir_clear_array(struct page*, gfp_t);
 
 const struct file_operations nfs_dir_operations = {
 	.llseek		= nfs_llseek_dir,
@@ -80,6 +82,10 @@
 	.setattr	= nfs_setattr,
 };
 
+const struct address_space_operations nfs_dir_addr_space_ops = {
+	.releasepage = nfs_readdir_clear_array,
+};
+
 #ifdef CONFIG_NFS_V3
 const struct inode_operations nfs3_dir_inode_operations = {
 	.create		= nfs_create,
@@ -104,8 +110,9 @@
 #ifdef CONFIG_NFS_V4
 
 static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *);
+static int nfs_open_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd);
 const struct inode_operations nfs4_dir_inode_operations = {
-	.create		= nfs_create,
+	.create		= nfs_open_create,
 	.lookup		= nfs_atomic_lookup,
 	.link		= nfs_link,
 	.unlink		= nfs_unlink,
@@ -150,51 +157,197 @@
 	return res;
 }
 
-typedef __be32 * (*decode_dirent_t)(__be32 *, struct nfs_entry *, int);
+struct nfs_cache_array_entry {
+	u64 cookie;
+	u64 ino;
+	struct qstr string;
+};
+
+struct nfs_cache_array {
+	unsigned int size;
+	int eof_index;
+	u64 last_cookie;
+	struct nfs_cache_array_entry array[0];
+};
+
+#define MAX_READDIR_ARRAY ((PAGE_SIZE - sizeof(struct nfs_cache_array)) / sizeof(struct nfs_cache_array_entry))
+
+typedef __be32 * (*decode_dirent_t)(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int);
 typedef struct {
 	struct file	*file;
 	struct page	*page;
 	unsigned long	page_index;
-	__be32		*ptr;
 	u64		*dir_cookie;
 	loff_t		current_index;
-	struct nfs_entry *entry;
 	decode_dirent_t	decode;
-	int		plus;
+
 	unsigned long	timestamp;
 	unsigned long	gencount;
-	int		timestamp_valid;
+	unsigned int	cache_entry_index;
+	unsigned int	plus:1;
+	unsigned int	eof:1;
 } nfs_readdir_descriptor_t;
 
-/* Now we cache directories properly, by stuffing the dirent
- * data directly in the page cache.
- *
- * Inode invalidation due to refresh etc. takes care of
- * _everything_, no sloppy entry flushing logic, no extraneous
- * copying, network direct to page cache, the way it was meant
- * to be.
- *
- * NOTE: Dirent information verification is done always by the
- *	 page-in of the RPC reply, nowhere else, this simplies
- *	 things substantially.
+/*
+ * The caller is responsible for calling nfs_readdir_release_array(page)
  */
 static
-int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
+struct nfs_cache_array *nfs_readdir_get_array(struct page *page)
 {
-	struct file	*file = desc->file;
-	struct inode	*inode = file->f_path.dentry->d_inode;
+	if (page == NULL)
+		return ERR_PTR(-EIO);
+	return (struct nfs_cache_array *)kmap(page);
+}
+
+static
+void nfs_readdir_release_array(struct page *page)
+{
+	kunmap(page);
+}
+
+/*
+ * we are freeing strings created by nfs_add_to_readdir_array()
+ */
+static
+int nfs_readdir_clear_array(struct page *page, gfp_t mask)
+{
+	struct nfs_cache_array *array = nfs_readdir_get_array(page);
+	int i;
+	for (i = 0; i < array->size; i++)
+		kfree(array->array[i].string.name);
+	nfs_readdir_release_array(page);
+	return 0;
+}
+
+/*
+ * the caller is responsible for freeing qstr.name
+ * when called by nfs_readdir_add_to_array, the strings will be freed in
+ * nfs_clear_readdir_array()
+ */
+static
+int nfs_readdir_make_qstr(struct qstr *string, const char *name, unsigned int len)
+{
+	string->len = len;
+	string->name = kmemdup(name, len, GFP_KERNEL);
+	if (string->name == NULL)
+		return -ENOMEM;
+	string->hash = full_name_hash(name, len);
+	return 0;
+}
+
+static
+int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page)
+{
+	struct nfs_cache_array *array = nfs_readdir_get_array(page);
+	struct nfs_cache_array_entry *cache_entry;
+	int ret;
+
+	if (IS_ERR(array))
+		return PTR_ERR(array);
+	ret = -EIO;
+	if (array->size >= MAX_READDIR_ARRAY)
+		goto out;
+
+	cache_entry = &array->array[array->size];
+	cache_entry->cookie = entry->prev_cookie;
+	cache_entry->ino = entry->ino;
+	ret = nfs_readdir_make_qstr(&cache_entry->string, entry->name, entry->len);
+	if (ret)
+		goto out;
+	array->last_cookie = entry->cookie;
+	if (entry->eof == 1)
+		array->eof_index = array->size;
+	array->size++;
+out:
+	nfs_readdir_release_array(page);
+	return ret;
+}
+
+static
+int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descriptor_t *desc)
+{
+	loff_t diff = desc->file->f_pos - desc->current_index;
+	unsigned int index;
+
+	if (diff < 0)
+		goto out_eof;
+	if (diff >= array->size) {
+		if (array->eof_index > 0)
+			goto out_eof;
+		desc->current_index += array->size;
+		return -EAGAIN;
+	}
+
+	index = (unsigned int)diff;
+	*desc->dir_cookie = array->array[index].cookie;
+	desc->cache_entry_index = index;
+	if (index == array->eof_index)
+		desc->eof = 1;
+	return 0;
+out_eof:
+	desc->eof = 1;
+	return -EBADCOOKIE;
+}
+
+static
+int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_descriptor_t *desc)
+{
+	int i;
+	int status = -EAGAIN;
+
+	for (i = 0; i < array->size; i++) {
+		if (i == array->eof_index) {
+			desc->eof = 1;
+			status = -EBADCOOKIE;
+		}
+		if (array->array[i].cookie == *desc->dir_cookie) {
+			desc->cache_entry_index = i;
+			status = 0;
+			break;
+		}
+	}
+
+	return status;
+}
+
+static
+int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc)
+{
+	struct nfs_cache_array *array;
+	int status = -EBADCOOKIE;
+
+	if (desc->dir_cookie == NULL)
+		goto out;
+
+	array = nfs_readdir_get_array(desc->page);
+	if (IS_ERR(array)) {
+		status = PTR_ERR(array);
+		goto out;
+	}
+
+	if (*desc->dir_cookie == 0)
+		status = nfs_readdir_search_for_pos(array, desc);
+	else
+		status = nfs_readdir_search_for_cookie(array, desc);
+
+	nfs_readdir_release_array(desc->page);
+out:
+	return status;
+}
+
+/* Fill a page with xdr information before transferring to the cache page */
+static
+int nfs_readdir_xdr_filler(struct page **pages, nfs_readdir_descriptor_t *desc,
+			struct nfs_entry *entry, struct file *file, struct inode *inode)
+{
 	struct rpc_cred	*cred = nfs_file_cred(file);
 	unsigned long	timestamp, gencount;
 	int		error;
 
-	dfprintk(DIRCACHE, "NFS: %s: reading cookie %Lu into page %lu\n",
-			__func__, (long long)desc->entry->cookie,
-			page->index);
-
  again:
 	timestamp = jiffies;
 	gencount = nfs_inc_attr_generation_counter();
-	error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, desc->entry->cookie, page,
+	error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, entry->cookie, pages,
 					  NFS_SERVER(inode)->dtsize, desc->plus);
 	if (error < 0) {
 		/* We requested READDIRPLUS, but the server doesn't grok it */
@@ -208,12 +361,232 @@
 	}
 	desc->timestamp = timestamp;
 	desc->gencount = gencount;
-	desc->timestamp_valid = 1;
+error:
+	return error;
+}
+
+/* Fill in an entry based on the xdr code stored in desc->page */
+static
+int xdr_decode(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, struct xdr_stream *stream)
+{
+	__be32 *p = desc->decode(stream, entry, NFS_SERVER(desc->file->f_path.dentry->d_inode), desc->plus);
+	if (IS_ERR(p))
+		return PTR_ERR(p);
+
+	entry->fattr->time_start = desc->timestamp;
+	entry->fattr->gencount = desc->gencount;
+	return 0;
+}
+
+static
+int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry)
+{
+	struct nfs_inode *node;
+	if (dentry->d_inode == NULL)
+		goto different;
+	node = NFS_I(dentry->d_inode);
+	if (node->fh.size != entry->fh->size)
+		goto different;
+	if (strncmp(node->fh.data, entry->fh->data, node->fh.size) != 0)
+		goto different;
+	return 1;
+different:
+	return 0;
+}
+
+static
+void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry)
+{
+	struct qstr filename = {
+		.len = entry->len,
+		.name = entry->name,
+	};
+	struct dentry *dentry;
+	struct dentry *alias;
+	struct inode *dir = parent->d_inode;
+	struct inode *inode;
+
+	if (filename.name[0] == '.') {
+		if (filename.len == 1)
+			return;
+		if (filename.len == 2 && filename.name[1] == '.')
+			return;
+	}
+	filename.hash = full_name_hash(filename.name, filename.len);
+
+	dentry = d_lookup(parent, &filename);
+	if (dentry != NULL) {
+		if (nfs_same_file(dentry, entry)) {
+			nfs_refresh_inode(dentry->d_inode, entry->fattr);
+			goto out;
+		} else {
+			d_drop(dentry);
+			dput(dentry);
+		}
+	}
+
+	dentry = d_alloc(parent, &filename);
+	if (dentry == NULL)
+		return;
+
+	dentry->d_op = NFS_PROTO(dir)->dentry_ops;
+	inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr);
+	if (IS_ERR(inode))
+		goto out;
+
+	alias = d_materialise_unique(dentry, inode);
+	if (IS_ERR(alias))
+		goto out;
+	else if (alias) {
+		nfs_set_verifier(alias, nfs_save_change_attribute(dir));
+		dput(alias);
+	} else
+		nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
+
+out:
+	dput(dentry);
+}
+
+/* Perform conversion from xdr to cache array */
+static
+void nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry,
+				void *xdr_page, struct page *page, unsigned int buflen)
+{
+	struct xdr_stream stream;
+	struct xdr_buf buf;
+	__be32 *ptr = xdr_page;
+	int status;
+	struct nfs_cache_array *array;
+
+	buf.head->iov_base = xdr_page;
+	buf.head->iov_len = buflen;
+	buf.tail->iov_len = 0;
+	buf.page_base = 0;
+	buf.page_len = 0;
+	buf.buflen = buf.head->iov_len;
+	buf.len = buf.head->iov_len;
+
+	xdr_init_decode(&stream, &buf, ptr);
+
+
+	do {
+		status = xdr_decode(desc, entry, &stream);
+		if (status != 0)
+			break;
+
+		if (nfs_readdir_add_to_array(entry, page) == -1)
+			break;
+		if (desc->plus == 1)
+			nfs_prime_dcache(desc->file->f_path.dentry, entry);
+	} while (!entry->eof);
+
+	if (status == -EBADCOOKIE && entry->eof) {
+		array = nfs_readdir_get_array(page);
+		array->eof_index = array->size - 1;
+		status = 0;
+		nfs_readdir_release_array(page);
+	}
+}
+
+static
+void nfs_readdir_free_pagearray(struct page **pages, unsigned int npages)
+{
+	unsigned int i;
+	for (i = 0; i < npages; i++)
+		put_page(pages[i]);
+}
+
+static
+void nfs_readdir_free_large_page(void *ptr, struct page **pages,
+		unsigned int npages)
+{
+	vm_unmap_ram(ptr, npages);
+	nfs_readdir_free_pagearray(pages, npages);
+}
+
+/*
+ * nfs_readdir_large_page will allocate pages that must be freed with a call
+ * to nfs_readdir_free_large_page
+ */
+static
+void *nfs_readdir_large_page(struct page **pages, unsigned int npages)
+{
+	void *ptr;
+	unsigned int i;
+
+	for (i = 0; i < npages; i++) {
+		struct page *page = alloc_page(GFP_KERNEL);
+		if (page == NULL)
+			goto out_freepages;
+		pages[i] = page;
+	}
+
+	ptr = vm_map_ram(pages, npages, 0, PAGE_KERNEL);
+	if (!IS_ERR_OR_NULL(ptr))
+		return ptr;
+out_freepages:
+	nfs_readdir_free_pagearray(pages, i);
+	return NULL;
+}
+
+static
+int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, struct inode *inode)
+{
+	struct page *pages[NFS_MAX_READDIR_PAGES];
+	void *pages_ptr = NULL;
+	struct nfs_entry entry;
+	struct file	*file = desc->file;
+	struct nfs_cache_array *array;
+	int status = 0;
+	unsigned int array_size = ARRAY_SIZE(pages);
+
+	entry.prev_cookie = 0;
+	entry.cookie = *desc->dir_cookie;
+	entry.eof = 0;
+	entry.fh = nfs_alloc_fhandle();
+	entry.fattr = nfs_alloc_fattr();
+	if (entry.fh == NULL || entry.fattr == NULL)
+		goto out;
+
+	array = nfs_readdir_get_array(page);
+	memset(array, 0, sizeof(struct nfs_cache_array));
+	array->eof_index = -1;
+
+	pages_ptr = nfs_readdir_large_page(pages, array_size);
+	if (!pages_ptr)
+		goto out_release_array;
+	do {
+		status = nfs_readdir_xdr_filler(pages, desc, &entry, file, inode);
+
+		if (status < 0)
+			break;
+		nfs_readdir_page_filler(desc, &entry, pages_ptr, page, array_size * PAGE_SIZE);
+	} while (array->eof_index < 0 && array->size < MAX_READDIR_ARRAY);
+
+	nfs_readdir_free_large_page(pages_ptr, pages, array_size);
+out_release_array:
+	nfs_readdir_release_array(page);
+out:
+	nfs_free_fattr(entry.fattr);
+	nfs_free_fhandle(entry.fh);
+	return status;
+}
+
+/*
+ * Now we cache directories properly, by converting xdr information
+ * to an array that can be used for lookups later.  This results in
+ * fewer cache pages, since we can store more information on each page.
+ * We only need to convert from xdr once so future lookups are much simpler
+ */
+static
+int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page* page)
+{
+	struct inode	*inode = desc->file->f_path.dentry->d_inode;
+
+	if (nfs_readdir_xdr_to_array(desc, page, inode) < 0)
+		goto error;
 	SetPageUptodate(page);
-	/* Ensure consistent page alignment of the data.
-	 * Note: assumes we have exclusive access to this mapping either
-	 *	 through inode->i_mutex or some other mechanism.
-	 */
+
 	if (invalidate_inode_pages2_range(inode->i_mapping, page->index + 1, -1) < 0) {
 		/* Should never happen */
 		nfs_zap_mapping(inode, inode->i_mapping);
@@ -225,173 +598,55 @@
 	return -EIO;
 }
 
-static inline
-int dir_decode(nfs_readdir_descriptor_t *desc)
+static
+void cache_page_release(nfs_readdir_descriptor_t *desc)
 {
-	__be32	*p = desc->ptr;
-	p = desc->decode(p, desc->entry, desc->plus);
-	if (IS_ERR(p))
-		return PTR_ERR(p);
-	desc->ptr = p;
-	if (desc->timestamp_valid) {
-		desc->entry->fattr->time_start = desc->timestamp;
-		desc->entry->fattr->gencount = desc->gencount;
-	} else
-		desc->entry->fattr->valid &= ~NFS_ATTR_FATTR;
-	return 0;
-}
-
-static inline
-void dir_page_release(nfs_readdir_descriptor_t *desc)
-{
-	kunmap(desc->page);
 	page_cache_release(desc->page);
 	desc->page = NULL;
-	desc->ptr = NULL;
 }
 
-/*
- * Given a pointer to a buffer that has already been filled by a call
- * to readdir, find the next entry with cookie '*desc->dir_cookie'.
- *
- * If the end of the buffer has been reached, return -EAGAIN, if not,
- * return the offset within the buffer of the next entry to be
- * read.
- */
-static inline
-int find_dirent(nfs_readdir_descriptor_t *desc)
+static
+struct page *get_cache_page(nfs_readdir_descriptor_t *desc)
 {
-	struct nfs_entry *entry = desc->entry;
-	int		loop_count = 0,
-			status;
-
-	while((status = dir_decode(desc)) == 0) {
-		dfprintk(DIRCACHE, "NFS: %s: examining cookie %Lu\n",
-				__func__, (unsigned long long)entry->cookie);
-		if (entry->prev_cookie == *desc->dir_cookie)
-			break;
-		if (loop_count++ > 200) {
-			loop_count = 0;
-			schedule();
-		}
-	}
-	return status;
+	struct page *page;
+	page = read_cache_page(desc->file->f_path.dentry->d_inode->i_mapping,
+			desc->page_index, (filler_t *)nfs_readdir_filler, desc);
+	if (IS_ERR(page))
+		desc->eof = 1;
+	return page;
 }
 
 /*
- * Given a pointer to a buffer that has already been filled by a call
- * to readdir, find the entry at offset 'desc->file->f_pos'.
- *
- * If the end of the buffer has been reached, return -EAGAIN, if not,
- * return the offset within the buffer of the next entry to be
- * read.
+ * Returns 0 if desc->dir_cookie was found on page desc->page_index
  */
-static inline
-int find_dirent_index(nfs_readdir_descriptor_t *desc)
+static
+int find_cache_page(nfs_readdir_descriptor_t *desc)
 {
-	struct nfs_entry *entry = desc->entry;
-	int		loop_count = 0,
-			status;
+	int res;
 
-	for(;;) {
-		status = dir_decode(desc);
-		if (status)
-			break;
+	desc->page = get_cache_page(desc);
+	if (IS_ERR(desc->page))
+		return PTR_ERR(desc->page);
 
-		dfprintk(DIRCACHE, "NFS: found cookie %Lu at index %Ld\n",
-				(unsigned long long)entry->cookie, desc->current_index);
-
-		if (desc->file->f_pos == desc->current_index) {
-			*desc->dir_cookie = entry->cookie;
-			break;
-		}
-		desc->current_index++;
-		if (loop_count++ > 200) {
-			loop_count = 0;
-			schedule();
-		}
-	}
-	return status;
+	res = nfs_readdir_search_array(desc);
+	if (res == 0)
+		return 0;
+	cache_page_release(desc);
+	return res;
 }
 
-/*
- * Find the given page, and call find_dirent() or find_dirent_index in
- * order to try to return the next entry.
- */
-static inline
-int find_dirent_page(nfs_readdir_descriptor_t *desc)
-{
-	struct inode	*inode = desc->file->f_path.dentry->d_inode;
-	struct page	*page;
-	int		status;
-
-	dfprintk(DIRCACHE, "NFS: %s: searching page %ld for target %Lu\n",
-			__func__, desc->page_index,
-			(long long) *desc->dir_cookie);
-
-	/* If we find the page in the page_cache, we cannot be sure
-	 * how fresh the data is, so we will ignore readdir_plus attributes.
-	 */
-	desc->timestamp_valid = 0;
-	page = read_cache_page(inode->i_mapping, desc->page_index,
-			       (filler_t *)nfs_readdir_filler, desc);
-	if (IS_ERR(page)) {
-		status = PTR_ERR(page);
-		goto out;
-	}
-
-	/* NOTE: Someone else may have changed the READDIRPLUS flag */
-	desc->page = page;
-	desc->ptr = kmap(page);		/* matching kunmap in nfs_do_filldir */
-	if (*desc->dir_cookie != 0)
-		status = find_dirent(desc);
-	else
-		status = find_dirent_index(desc);
-	if (status < 0)
-		dir_page_release(desc);
- out:
-	dfprintk(DIRCACHE, "NFS: %s: returns %d\n", __func__, status);
-	return status;
-}
-
-/*
- * Recurse through the page cache pages, and return a
- * filled nfs_entry structure of the next directory entry if possible.
- *
- * The target for the search is '*desc->dir_cookie' if non-0,
- * 'desc->file->f_pos' otherwise
- */
+/* Search for desc->dir_cookie from the beginning of the page cache */
 static inline
 int readdir_search_pagecache(nfs_readdir_descriptor_t *desc)
 {
-	int		loop_count = 0;
-	int		res;
+	int res = -EAGAIN;
 
-	/* Always search-by-index from the beginning of the cache */
-	if (*desc->dir_cookie == 0) {
-		dfprintk(DIRCACHE, "NFS: readdir_search_pagecache() searching for offset %Ld\n",
-				(long long)desc->file->f_pos);
-		desc->page_index = 0;
-		desc->entry->cookie = desc->entry->prev_cookie = 0;
-		desc->entry->eof = 0;
-		desc->current_index = 0;
-	} else
-		dfprintk(DIRCACHE, "NFS: readdir_search_pagecache() searching for cookie %Lu\n",
-				(unsigned long long)*desc->dir_cookie);
-
-	for (;;) {
-		res = find_dirent_page(desc);
+	while (1) {
+		res = find_cache_page(desc);
 		if (res != -EAGAIN)
 			break;
-		/* Align to beginning of next page */
-		desc->page_index ++;
-		if (loop_count++ > 200) {
-			loop_count = 0;
-			schedule();
-		}
+		desc->page_index++;
 	}
-
-	dfprintk(DIRCACHE, "NFS: %s: returns %d\n", __func__, res);
 	return res;
 }
 
@@ -400,8 +655,6 @@
 	return (inode->i_mode >> 12) & 15;
 }
 
-static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc);
-
 /*
  * Once we've found the start of the dirent within a page: fill 'er up...
  */
@@ -410,49 +663,36 @@
 		   filldir_t filldir)
 {
 	struct file	*file = desc->file;
-	struct nfs_entry *entry = desc->entry;
-	struct dentry	*dentry = NULL;
-	u64		fileid;
-	int		loop_count = 0,
-			res;
+	int i = 0;
+	int res = 0;
+	struct nfs_cache_array *array = NULL;
+	unsigned int d_type = DT_UNKNOWN;
+	struct dentry *dentry = NULL;
 
-	dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling starting @ cookie %Lu\n",
-			(unsigned long long)entry->cookie);
+	array = nfs_readdir_get_array(desc->page);
 
-	for(;;) {
-		unsigned d_type = DT_UNKNOWN;
-		/* Note: entry->prev_cookie contains the cookie for
-		 *	 retrieving the current dirent on the server */
-		fileid = entry->ino;
+	for (i = desc->cache_entry_index; i < array->size; i++) {
+		d_type = DT_UNKNOWN;
 
-		/* Get a dentry if we have one */
-		if (dentry != NULL)
-			dput(dentry);
-		dentry = nfs_readdir_lookup(desc);
-
-		/* Use readdirplus info */
-		if (dentry != NULL && dentry->d_inode != NULL) {
-			d_type = dt_type(dentry->d_inode);
-			fileid = NFS_FILEID(dentry->d_inode);
-		}
-
-		res = filldir(dirent, entry->name, entry->len, 
-			      file->f_pos, nfs_compat_user_ino64(fileid),
-			      d_type);
+		res = filldir(dirent, array->array[i].string.name,
+			array->array[i].string.len, file->f_pos,
+			nfs_compat_user_ino64(array->array[i].ino), d_type);
 		if (res < 0)
 			break;
 		file->f_pos++;
-		*desc->dir_cookie = entry->cookie;
-		if (dir_decode(desc) != 0) {
-			desc->page_index ++;
+		desc->cache_entry_index = i;
+		if (i < (array->size-1))
+			*desc->dir_cookie = array->array[i+1].cookie;
+		else
+			*desc->dir_cookie = array->last_cookie;
+		if (i == array->eof_index) {
+			desc->eof = 1;
 			break;
 		}
-		if (loop_count++ > 200) {
-			loop_count = 0;
-			schedule();
-		}
 	}
-	dir_page_release(desc);
+
+	nfs_readdir_release_array(desc->page);
+	cache_page_release(desc);
 	if (dentry != NULL)
 		dput(dentry);
 	dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n",
@@ -476,12 +716,9 @@
 int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
 		     filldir_t filldir)
 {
-	struct file	*file = desc->file;
-	struct inode	*inode = file->f_path.dentry->d_inode;
-	struct rpc_cred	*cred = nfs_file_cred(file);
 	struct page	*page = NULL;
 	int		status;
-	unsigned long	timestamp, gencount;
+	struct inode *inode = desc->file->f_path.dentry->d_inode;
 
 	dfprintk(DIRCACHE, "NFS: uncached_readdir() searching for cookie %Lu\n",
 			(unsigned long long)*desc->dir_cookie);
@@ -491,38 +728,22 @@
 		status = -ENOMEM;
 		goto out;
 	}
-	timestamp = jiffies;
-	gencount = nfs_inc_attr_generation_counter();
-	status = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred,
-						*desc->dir_cookie, page,
-						NFS_SERVER(inode)->dtsize,
-						desc->plus);
-	desc->page = page;
-	desc->ptr = kmap(page);		/* matching kunmap in nfs_do_filldir */
-	if (status >= 0) {
-		desc->timestamp = timestamp;
-		desc->gencount = gencount;
-		desc->timestamp_valid = 1;
-		if ((status = dir_decode(desc)) == 0)
-			desc->entry->prev_cookie = *desc->dir_cookie;
-	} else
-		status = -EIO;
-	if (status < 0)
-		goto out_release;
 
+	if (nfs_readdir_xdr_to_array(desc, page, inode) == -1) {
+		status = -EIO;
+		goto out_release;
+	}
+
+	desc->page_index = 0;
+	desc->page = page;
 	status = nfs_do_filldir(desc, dirent, filldir);
 
-	/* Reset read descriptor so it searches the page cache from
-	 * the start upon the next call to readdir_search_pagecache() */
-	desc->page_index = 0;
-	desc->entry->cookie = desc->entry->prev_cookie = 0;
-	desc->entry->eof = 0;
  out:
 	dfprintk(DIRCACHE, "NFS: %s: returns %d\n",
 			__func__, status);
 	return status;
  out_release:
-	dir_page_release(desc);
+	cache_page_release(desc);
 	goto out;
 }
 
@@ -536,7 +757,6 @@
 	struct inode	*inode = dentry->d_inode;
 	nfs_readdir_descriptor_t my_desc,
 			*desc = &my_desc;
-	struct nfs_entry my_entry;
 	int res = -ENOMEM;
 
 	dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n",
@@ -557,26 +777,17 @@
 	desc->decode = NFS_PROTO(inode)->decode_dirent;
 	desc->plus = NFS_USE_READDIRPLUS(inode);
 
-	my_entry.cookie = my_entry.prev_cookie = 0;
-	my_entry.eof = 0;
-	my_entry.fh = nfs_alloc_fhandle();
-	my_entry.fattr = nfs_alloc_fattr();
-	if (my_entry.fh == NULL || my_entry.fattr == NULL)
-		goto out_alloc_failed;
-
-	desc->entry = &my_entry;
-
 	nfs_block_sillyrename(dentry);
 	res = nfs_revalidate_mapping(inode, filp->f_mapping);
 	if (res < 0)
 		goto out;
 
-	while(!desc->entry->eof) {
+	while (desc->eof != 1) {
 		res = readdir_search_pagecache(desc);
 
 		if (res == -EBADCOOKIE) {
 			/* This means either end of directory */
-			if (*desc->dir_cookie && desc->entry->cookie != *desc->dir_cookie) {
+			if (*desc->dir_cookie && desc->eof == 0) {
 				/* Or that the server has 'lost' a cookie */
 				res = uncached_readdir(desc, dirent, filldir);
 				if (res >= 0)
@@ -588,8 +799,9 @@
 		if (res == -ETOOSMALL && desc->plus) {
 			clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags);
 			nfs_zap_caches(inode);
+			desc->page_index = 0;
 			desc->plus = 0;
-			desc->entry->eof = 0;
+			desc->eof = 0;
 			continue;
 		}
 		if (res < 0)
@@ -605,9 +817,6 @@
 	nfs_unblock_sillyrename(dentry);
 	if (res > 0)
 		res = 0;
-out_alloc_failed:
-	nfs_free_fattr(my_entry.fattr);
-	nfs_free_fhandle(my_entry.fh);
 	dfprintk(FILE, "NFS: readdir(%s/%s) returns %d\n",
 			dentry->d_parent->d_name.name, dentry->d_name.name,
 			res);
@@ -1029,10 +1238,63 @@
 	return 1;
 }
 
+static struct nfs_open_context *nameidata_to_nfs_open_context(struct dentry *dentry, struct nameidata *nd)
+{
+	struct path path = {
+		.mnt = nd->path.mnt,
+		.dentry = dentry,
+	};
+	struct nfs_open_context *ctx;
+	struct rpc_cred *cred;
+	fmode_t fmode = nd->intent.open.flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC);
+
+	cred = rpc_lookup_cred();
+	if (IS_ERR(cred))
+		return ERR_CAST(cred);
+	ctx = alloc_nfs_open_context(&path, cred, fmode);
+	put_rpccred(cred);
+	if (ctx == NULL)
+		return ERR_PTR(-ENOMEM);
+	return ctx;
+}
+
+static int do_open(struct inode *inode, struct file *filp)
+{
+	nfs_fscache_set_inode_cookie(inode, filp);
+	return 0;
+}
+
+static int nfs_intent_set_file(struct nameidata *nd, struct nfs_open_context *ctx)
+{
+	struct file *filp;
+	int ret = 0;
+
+	/* If the open_intent is for execute, we have an extra check to make */
+	if (ctx->mode & FMODE_EXEC) {
+		ret = nfs_may_open(ctx->path.dentry->d_inode,
+				ctx->cred,
+				nd->intent.open.flags);
+		if (ret < 0)
+			goto out;
+	}
+	filp = lookup_instantiate_filp(nd, ctx->path.dentry, do_open);
+	if (IS_ERR(filp))
+		ret = PTR_ERR(filp);
+	else
+		nfs_file_set_open_context(filp, ctx);
+out:
+	put_nfs_open_context(ctx);
+	return ret;
+}
+
 static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
+	struct nfs_open_context *ctx;
+	struct iattr attr;
 	struct dentry *res = NULL;
-	int error;
+	struct inode *inode;
+	int open_flags;
+	int err;
 
 	dfprintk(VFS, "NFS: atomic_lookup(%s/%ld), %s\n",
 			dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
@@ -1054,13 +1316,32 @@
 		goto out;
 	}
 
+	ctx = nameidata_to_nfs_open_context(dentry, nd);
+	res = ERR_CAST(ctx);
+	if (IS_ERR(ctx))
+		goto out;
+
+	open_flags = nd->intent.open.flags;
+	if (nd->flags & LOOKUP_CREATE) {
+		attr.ia_mode = nd->intent.open.create_mode;
+		attr.ia_valid = ATTR_MODE;
+		if (!IS_POSIXACL(dir))
+			attr.ia_mode &= ~current_umask();
+	} else {
+		open_flags &= ~(O_EXCL | O_CREAT);
+		attr.ia_valid = 0;
+	}
+
 	/* Open the file on the server */
-	res = nfs4_atomic_open(dir, dentry, nd);
-	if (IS_ERR(res)) {
-		error = PTR_ERR(res);
-		switch (error) {
+	nfs_block_sillyrename(dentry->d_parent);
+	inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr);
+	if (IS_ERR(inode)) {
+		nfs_unblock_sillyrename(dentry->d_parent);
+		put_nfs_open_context(ctx);
+		switch (PTR_ERR(inode)) {
 			/* Make a negative dentry */
 			case -ENOENT:
+				d_add(dentry, NULL);
 				res = NULL;
 				goto out;
 			/* This turned out not to be a regular file */
@@ -1072,11 +1353,25 @@
 					goto no_open;
 			/* case -EINVAL: */
 			default:
+				res = ERR_CAST(inode);
 				goto out;
 		}
-	} else if (res != NULL)
+	}
+	res = d_add_unique(dentry, inode);
+	nfs_unblock_sillyrename(dentry->d_parent);
+	if (res != NULL) {
+		dput(ctx->path.dentry);
+		ctx->path.dentry = dget(res);
 		dentry = res;
+	}
+	err = nfs_intent_set_file(nd, ctx);
+	if (err < 0) {
+		if (res != NULL)
+			dput(res);
+		return ERR_PTR(err);
+	}
 out:
+	nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
 	return res;
 no_open:
 	return nfs_lookup(dir, dentry, nd);
@@ -1087,12 +1382,15 @@
 	struct dentry *parent = NULL;
 	struct inode *inode = dentry->d_inode;
 	struct inode *dir;
+	struct nfs_open_context *ctx;
 	int openflags, ret = 0;
 
 	if (!is_atomic_open(nd) || d_mountpoint(dentry))
 		goto no_open;
+
 	parent = dget_parent(dentry);
 	dir = parent->d_inode;
+
 	/* We can't create new files in nfs_open_revalidate(), so we
 	 * optimize away revalidation of negative dentries.
 	 */
@@ -1112,99 +1410,96 @@
 	/* We can't create new files, or truncate existing ones here */
 	openflags &= ~(O_CREAT|O_EXCL|O_TRUNC);
 
+	ctx = nameidata_to_nfs_open_context(dentry, nd);
+	ret = PTR_ERR(ctx);
+	if (IS_ERR(ctx))
+		goto out;
 	/*
 	 * Note: we're not holding inode->i_mutex and so may be racing with
 	 * operations that change the directory. We therefore save the
 	 * change attribute *before* we do the RPC call.
 	 */
-	ret = nfs4_open_revalidate(dir, dentry, openflags, nd);
+	inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, NULL);
+	if (IS_ERR(inode)) {
+		ret = PTR_ERR(inode);
+		switch (ret) {
+		case -EPERM:
+		case -EACCES:
+		case -EDQUOT:
+		case -ENOSPC:
+		case -EROFS:
+			goto out_put_ctx;
+		default:
+			goto out_drop;
+		}
+	}
+	iput(inode);
+	if (inode != dentry->d_inode)
+		goto out_drop;
+
+	nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
+	ret = nfs_intent_set_file(nd, ctx);
+	if (ret >= 0)
+		ret = 1;
 out:
 	dput(parent);
-	if (!ret)
-		d_drop(dentry);
 	return ret;
+out_drop:
+	d_drop(dentry);
+	ret = 0;
+out_put_ctx:
+	put_nfs_open_context(ctx);
+	goto out;
+
 no_open_dput:
 	dput(parent);
 no_open:
 	return nfs_lookup_revalidate(dentry, nd);
 }
-#endif /* CONFIG_NFSV4 */
 
-static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc)
+static int nfs_open_create(struct inode *dir, struct dentry *dentry, int mode,
+		struct nameidata *nd)
 {
-	struct dentry *parent = desc->file->f_path.dentry;
-	struct inode *dir = parent->d_inode;
-	struct nfs_entry *entry = desc->entry;
-	struct dentry *dentry, *alias;
-	struct qstr name = {
-		.name = entry->name,
-		.len = entry->len,
-	};
-	struct inode *inode;
-	unsigned long verf = nfs_save_change_attribute(dir);
+	struct nfs_open_context *ctx = NULL;
+	struct iattr attr;
+	int error;
+	int open_flags = 0;
 
-	switch (name.len) {
-		case 2:
-			if (name.name[0] == '.' && name.name[1] == '.')
-				return dget_parent(parent);
-			break;
-		case 1:
-			if (name.name[0] == '.')
-				return dget(parent);
+	dfprintk(VFS, "NFS: create(%s/%ld), %s\n",
+			dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
+
+	attr.ia_mode = mode;
+	attr.ia_valid = ATTR_MODE;
+
+	if ((nd->flags & LOOKUP_CREATE) != 0) {
+		open_flags = nd->intent.open.flags;
+
+		ctx = nameidata_to_nfs_open_context(dentry, nd);
+		error = PTR_ERR(ctx);
+		if (IS_ERR(ctx))
+			goto out_err_drop;
 	}
 
-	spin_lock(&dir->i_lock);
-	if (NFS_I(dir)->cache_validity & NFS_INO_INVALID_DATA) {
-		spin_unlock(&dir->i_lock);
-		return NULL;
+	error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, ctx);
+	if (error != 0)
+		goto out_put_ctx;
+	if (ctx != NULL) {
+		error = nfs_intent_set_file(nd, ctx);
+		if (error < 0)
+			goto out_err;
 	}
-	spin_unlock(&dir->i_lock);
-
-	name.hash = full_name_hash(name.name, name.len);
-	dentry = d_lookup(parent, &name);
-	if (dentry != NULL) {
-		/* Is this a positive dentry that matches the readdir info? */
-		if (dentry->d_inode != NULL &&
-				(NFS_FILEID(dentry->d_inode) == entry->ino ||
-				d_mountpoint(dentry))) {
-			if (!desc->plus || entry->fh->size == 0)
-				return dentry;
-			if (nfs_compare_fh(NFS_FH(dentry->d_inode),
-						entry->fh) == 0)
-				goto out_renew;
-		}
-		/* No, so d_drop to allow one to be created */
-		d_drop(dentry);
-		dput(dentry);
-	}
-	if (!desc->plus || !(entry->fattr->valid & NFS_ATTR_FATTR))
-		return NULL;
-	if (name.len > NFS_SERVER(dir)->namelen)
-		return NULL;
-	/* Note: caller is already holding the dir->i_mutex! */
-	dentry = d_alloc(parent, &name);
-	if (dentry == NULL)
-		return NULL;
-	dentry->d_op = NFS_PROTO(dir)->dentry_ops;
-	inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr);
-	if (IS_ERR(inode)) {
-		dput(dentry);
-		return NULL;
-	}
-
-	alias = d_materialise_unique(dentry, inode);
-	if (alias != NULL) {
-		dput(dentry);
-		if (IS_ERR(alias))
-			return NULL;
-		dentry = alias;
-	}
-
-out_renew:
-	nfs_set_verifier(dentry, verf);
-	return dentry;
+	return 0;
+out_put_ctx:
+	if (ctx != NULL)
+		put_nfs_open_context(ctx);
+out_err_drop:
+	d_drop(dentry);
+out_err:
+	return error;
 }
 
+#endif /* CONFIG_NFSV4 */
+
 /*
  * Code common to create, mkdir, and mknod.
  */
@@ -1258,7 +1553,6 @@
 {
 	struct iattr attr;
 	int error;
-	int open_flags = 0;
 
 	dfprintk(VFS, "NFS: create(%s/%ld), %s\n",
 			dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
@@ -1266,10 +1560,7 @@
 	attr.ia_mode = mode;
 	attr.ia_valid = ATTR_MODE;
 
-	if ((nd->flags & LOOKUP_CREATE) != 0)
-		open_flags = nd->intent.open.flags;
-
-	error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, nd);
+	error = NFS_PROTO(dir)->create(dir, dentry, &attr, 0, NULL);
 	if (error != 0)
 		goto out_err;
 	return 0;
@@ -1351,76 +1642,6 @@
 	return error;
 }
 
-static int nfs_sillyrename(struct inode *dir, struct dentry *dentry)
-{
-	static unsigned int sillycounter;
-	const int      fileidsize  = sizeof(NFS_FILEID(dentry->d_inode))*2;
-	const int      countersize = sizeof(sillycounter)*2;
-	const int      slen        = sizeof(".nfs")+fileidsize+countersize-1;
-	char           silly[slen+1];
-	struct qstr    qsilly;
-	struct dentry *sdentry;
-	int            error = -EIO;
-
-	dfprintk(VFS, "NFS: silly-rename(%s/%s, ct=%d)\n",
-		dentry->d_parent->d_name.name, dentry->d_name.name, 
-		atomic_read(&dentry->d_count));
-	nfs_inc_stats(dir, NFSIOS_SILLYRENAME);
-
-	/*
-	 * We don't allow a dentry to be silly-renamed twice.
-	 */
-	error = -EBUSY;
-	if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
-		goto out;
-
-	sprintf(silly, ".nfs%*.*Lx",
-		fileidsize, fileidsize,
-		(unsigned long long)NFS_FILEID(dentry->d_inode));
-
-	/* Return delegation in anticipation of the rename */
-	nfs_inode_return_delegation(dentry->d_inode);
-
-	sdentry = NULL;
-	do {
-		char *suffix = silly + slen - countersize;
-
-		dput(sdentry);
-		sillycounter++;
-		sprintf(suffix, "%*.*x", countersize, countersize, sillycounter);
-
-		dfprintk(VFS, "NFS: trying to rename %s to %s\n",
-				dentry->d_name.name, silly);
-		
-		sdentry = lookup_one_len(silly, dentry->d_parent, slen);
-		/*
-		 * N.B. Better to return EBUSY here ... it could be
-		 * dangerous to delete the file while it's in use.
-		 */
-		if (IS_ERR(sdentry))
-			goto out;
-	} while(sdentry->d_inode != NULL); /* need negative lookup */
-
-	qsilly.name = silly;
-	qsilly.len  = strlen(silly);
-	if (dentry->d_inode) {
-		error = NFS_PROTO(dir)->rename(dir, &dentry->d_name,
-				dir, &qsilly);
-		nfs_mark_for_revalidate(dentry->d_inode);
-	} else
-		error = NFS_PROTO(dir)->rename(dir, &dentry->d_name,
-				dir, &qsilly);
-	if (!error) {
-		nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
-		d_move(dentry, sdentry);
-		error = nfs_async_unlink(dir, dentry);
- 		/* If we return 0 we don't unlink */
-	}
-	dput(sdentry);
-out:
-	return error;
-}
-
 /*
  * Remove a file after making sure there are no pending writes,
  * and after checking that the file has only one user. 
@@ -1711,14 +1932,14 @@
 int nfs_access_cache_shrinker(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask)
 {
 	LIST_HEAD(head);
-	struct nfs_inode *nfsi;
+	struct nfs_inode *nfsi, *next;
 	struct nfs_access_entry *cache;
 
 	if ((gfp_mask & GFP_KERNEL) != GFP_KERNEL)
 		return (nr_to_scan == 0) ? 0 : -1;
 
 	spin_lock(&nfs_access_lru_lock);
-	list_for_each_entry(nfsi, &nfs_access_lru_list, access_cache_inode_lru) {
+	list_for_each_entry_safe(nfsi, next, &nfs_access_lru_list, access_cache_inode_lru) {
 		struct inode *inode;
 
 		if (nr_to_scan-- == 0)
diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c
index dba50a5..a6e711a 100644
--- a/fs/nfs/dns_resolve.c
+++ b/fs/nfs/dns_resolve.c
@@ -167,7 +167,7 @@
 		return 0;
 	}
 	item = container_of(h, struct nfs_dns_ent, h);
-	ttl = (long)item->h.expiry_time - (long)get_seconds();
+	ttl = item->h.expiry_time - seconds_since_boot();
 	if (ttl < 0)
 		ttl = 0;
 
@@ -239,7 +239,7 @@
 	ttl = get_expiry(&buf);
 	if (ttl == 0)
 		goto out;
-	key.h.expiry_time = ttl + get_seconds();
+	key.h.expiry_time = ttl + seconds_since_boot();
 
 	ret = -ENOMEM;
 	item = nfs_dns_lookup(cd, &key);
@@ -301,7 +301,7 @@
 		goto out_err;
 	ret = -ETIMEDOUT;
 	if (!test_bit(CACHE_VALID, &(*item)->h.flags)
-			|| (*item)->h.expiry_time < get_seconds()
+			|| (*item)->h.expiry_time < seconds_since_boot()
 			|| cd->flush_time > (*item)->h.last_refresh)
 		goto out_put;
 	ret = -ENOENT;
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 05bf3c0..e756075 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -36,6 +36,7 @@
 #include "internal.h"
 #include "iostat.h"
 #include "fscache.h"
+#include "pnfs.h"
 
 #define NFSDBG_FACILITY		NFSDBG_FILE
 
@@ -386,6 +387,10 @@
 		file->f_path.dentry->d_name.name,
 		mapping->host->i_ino, len, (long long) pos);
 
+	pnfs_update_layout(mapping->host,
+			   nfs_file_open_context(file),
+			   IOMODE_RW);
+
 start:
 	/*
 	 * Prevent starvation issues if someone is doing a consistency
@@ -551,7 +556,7 @@
 	struct file *filp = vma->vm_file;
 	struct dentry *dentry = filp->f_path.dentry;
 	unsigned pagelen;
-	int ret = -EINVAL;
+	int ret = VM_FAULT_NOPAGE;
 	struct address_space *mapping;
 
 	dfprintk(PAGECACHE, "NFS: vm_page_mkwrite(%s/%s(%ld), offset %lld)\n",
@@ -567,21 +572,20 @@
 	if (mapping != dentry->d_inode->i_mapping)
 		goto out_unlock;
 
-	ret = 0;
 	pagelen = nfs_page_length(page);
 	if (pagelen == 0)
 		goto out_unlock;
 
-	ret = nfs_flush_incompatible(filp, page);
-	if (ret != 0)
-		goto out_unlock;
+	ret = VM_FAULT_LOCKED;
+	if (nfs_flush_incompatible(filp, page) == 0 &&
+	    nfs_updatepage(filp, page, 0, pagelen) == 0)
+		goto out;
 
-	ret = nfs_updatepage(filp, page, 0, pagelen);
+	ret = VM_FAULT_SIGBUS;
 out_unlock:
-	if (!ret)
-		return VM_FAULT_LOCKED;
 	unlock_page(page);
-	return VM_FAULT_SIGBUS;
+out:
+	return ret;
 }
 
 static const struct vm_operations_struct nfs_file_vm_ops = {
@@ -684,7 +688,8 @@
 	return ret;
 }
 
-static int do_getlk(struct file *filp, int cmd, struct file_lock *fl)
+static int
+do_getlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
 {
 	struct inode *inode = filp->f_mapping->host;
 	int status = 0;
@@ -699,7 +704,7 @@
 	if (nfs_have_delegation(inode, FMODE_READ))
 		goto out_noconflict;
 
-	if (NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM)
+	if (is_local)
 		goto out_noconflict;
 
 	status = NFS_PROTO(inode)->lock(filp, cmd, fl);
@@ -726,7 +731,8 @@
 	return res;
 }
 
-static int do_unlk(struct file *filp, int cmd, struct file_lock *fl)
+static int
+do_unlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
 {
 	struct inode *inode = filp->f_mapping->host;
 	int status;
@@ -741,15 +747,24 @@
 	 * 	If we're signalled while cleaning up locks on process exit, we
 	 * 	still need to complete the unlock.
 	 */
-	/* Use local locking if mounted with "-onolock" */
-	if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM))
+	/*
+	 * Use local locking if mounted with "-onolock" or with appropriate
+	 * "-olocal_lock="
+	 */
+	if (!is_local)
 		status = NFS_PROTO(inode)->lock(filp, cmd, fl);
 	else
 		status = do_vfs_lock(filp, fl);
 	return status;
 }
 
-static int do_setlk(struct file *filp, int cmd, struct file_lock *fl)
+static int
+is_time_granular(struct timespec *ts) {
+	return ((ts->tv_sec == 0) && (ts->tv_nsec <= 1000));
+}
+
+static int
+do_setlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
 {
 	struct inode *inode = filp->f_mapping->host;
 	int status;
@@ -762,20 +777,31 @@
 	if (status != 0)
 		goto out;
 
-	/* Use local locking if mounted with "-onolock" */
-	if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM))
+	/*
+	 * Use local locking if mounted with "-onolock" or with appropriate
+	 * "-olocal_lock="
+	 */
+	if (!is_local)
 		status = NFS_PROTO(inode)->lock(filp, cmd, fl);
 	else
 		status = do_vfs_lock(filp, fl);
 	if (status < 0)
 		goto out;
+
 	/*
-	 * Make sure we clear the cache whenever we try to get the lock.
+	 * Revalidate the cache if the server has time stamps granular
+	 * enough to detect subsecond changes.  Otherwise, clear the
+	 * cache to prevent missing any changes.
+	 *
 	 * This makes locking act as a cache coherency point.
 	 */
 	nfs_sync_mapping(filp->f_mapping);
-	if (!nfs_have_delegation(inode, FMODE_READ))
-		nfs_zap_caches(inode);
+	if (!nfs_have_delegation(inode, FMODE_READ)) {
+		if (is_time_granular(&NFS_SERVER(inode)->time_delta))
+			__nfs_revalidate_inode(NFS_SERVER(inode), inode);
+		else
+			nfs_zap_caches(inode);
+	}
 out:
 	return status;
 }
@@ -787,6 +813,7 @@
 {
 	struct inode *inode = filp->f_mapping->host;
 	int ret = -ENOLCK;
+	int is_local = 0;
 
 	dprintk("NFS: lock(%s/%s, t=%x, fl=%x, r=%lld:%lld)\n",
 			filp->f_path.dentry->d_parent->d_name.name,
@@ -800,6 +827,9 @@
 	if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK)
 		goto out_err;
 
+	if (NFS_SERVER(inode)->flags & NFS_MOUNT_LOCAL_FCNTL)
+		is_local = 1;
+
 	if (NFS_PROTO(inode)->lock_check_bounds != NULL) {
 		ret = NFS_PROTO(inode)->lock_check_bounds(fl);
 		if (ret < 0)
@@ -807,11 +837,11 @@
 	}
 
 	if (IS_GETLK(cmd))
-		ret = do_getlk(filp, cmd, fl);
+		ret = do_getlk(filp, cmd, fl, is_local);
 	else if (fl->fl_type == F_UNLCK)
-		ret = do_unlk(filp, cmd, fl);
+		ret = do_unlk(filp, cmd, fl, is_local);
 	else
-		ret = do_setlk(filp, cmd, fl);
+		ret = do_setlk(filp, cmd, fl, is_local);
 out_err:
 	return ret;
 }
@@ -821,6 +851,9 @@
  */
 static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
 {
+	struct inode *inode = filp->f_mapping->host;
+	int is_local = 0;
+
 	dprintk("NFS: flock(%s/%s, t=%x, fl=%x)\n",
 			filp->f_path.dentry->d_parent->d_name.name,
 			filp->f_path.dentry->d_name.name,
@@ -829,14 +862,17 @@
 	if (!(fl->fl_flags & FL_FLOCK))
 		return -ENOLCK;
 
+	if (NFS_SERVER(inode)->flags & NFS_MOUNT_LOCAL_FLOCK)
+		is_local = 1;
+
 	/* We're simulating flock() locks using posix locks on the server */
 	fl->fl_owner = (fl_owner_t)filp;
 	fl->fl_start = 0;
 	fl->fl_end = OFFSET_MAX;
 
 	if (fl->fl_type == F_UNLCK)
-		return do_unlk(filp, cmd, fl);
-	return do_setlk(filp, cmd, fl);
+		return do_unlk(filp, cmd, fl, is_local);
+	return do_setlk(filp, cmd, fl, is_local);
 }
 
 /*
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c
index 21a84d45..dec47ed 100644
--- a/fs/nfs/idmap.c
+++ b/fs/nfs/idmap.c
@@ -34,6 +34,212 @@
  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#ifdef CONFIG_NFS_USE_NEW_IDMAPPER
+
+#include <linux/slab.h>
+#include <linux/cred.h>
+#include <linux/nfs_idmap.h>
+#include <linux/keyctl.h>
+#include <linux/key-type.h>
+#include <linux/rcupdate.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+
+#include <keys/user-type.h>
+
+#define NFS_UINT_MAXLEN 11
+
+const struct cred *id_resolver_cache;
+
+struct key_type key_type_id_resolver = {
+	.name		= "id_resolver",
+	.instantiate	= user_instantiate,
+	.match		= user_match,
+	.revoke		= user_revoke,
+	.destroy	= user_destroy,
+	.describe	= user_describe,
+	.read		= user_read,
+};
+
+int nfs_idmap_init(void)
+{
+	struct cred *cred;
+	struct key *keyring;
+	int ret = 0;
+
+	printk(KERN_NOTICE "Registering the %s key type\n", key_type_id_resolver.name);
+
+	cred = prepare_kernel_cred(NULL);
+	if (!cred)
+		return -ENOMEM;
+
+	keyring = key_alloc(&key_type_keyring, ".id_resolver", 0, 0, cred,
+			     (KEY_POS_ALL & ~KEY_POS_SETATTR) |
+			     KEY_USR_VIEW | KEY_USR_READ,
+			     KEY_ALLOC_NOT_IN_QUOTA);
+	if (IS_ERR(keyring)) {
+		ret = PTR_ERR(keyring);
+		goto failed_put_cred;
+	}
+
+	ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL);
+	if (ret < 0)
+		goto failed_put_key;
+
+	ret = register_key_type(&key_type_id_resolver);
+	if (ret < 0)
+		goto failed_put_key;
+
+	cred->thread_keyring = keyring;
+	cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
+	id_resolver_cache = cred;
+	return 0;
+
+failed_put_key:
+	key_put(keyring);
+failed_put_cred:
+	put_cred(cred);
+	return ret;
+}
+
+void nfs_idmap_quit(void)
+{
+	key_revoke(id_resolver_cache->thread_keyring);
+	unregister_key_type(&key_type_id_resolver);
+	put_cred(id_resolver_cache);
+}
+
+/*
+ * Assemble the description to pass to request_key()
+ * This function will allocate a new string and update dest to point
+ * at it.  The caller is responsible for freeing dest.
+ *
+ * On error 0 is returned.  Otherwise, the length of dest is returned.
+ */
+static ssize_t nfs_idmap_get_desc(const char *name, size_t namelen,
+				const char *type, size_t typelen, char **desc)
+{
+	char *cp;
+	size_t desclen = typelen + namelen + 2;
+
+	*desc = kmalloc(desclen, GFP_KERNEL);
+	if (!desc)
+		return -ENOMEM;
+
+	cp = *desc;
+	memcpy(cp, type, typelen);
+	cp += typelen;
+	*cp++ = ':';
+
+	memcpy(cp, name, namelen);
+	cp += namelen;
+	*cp = '\0';
+	return desclen;
+}
+
+static ssize_t nfs_idmap_request_key(const char *name, size_t namelen,
+		const char *type, void *data, size_t data_size)
+{
+	const struct cred *saved_cred;
+	struct key *rkey;
+	char *desc;
+	struct user_key_payload *payload;
+	ssize_t ret;
+
+	ret = nfs_idmap_get_desc(name, namelen, type, strlen(type), &desc);
+	if (ret <= 0)
+		goto out;
+
+	saved_cred = override_creds(id_resolver_cache);
+	rkey = request_key(&key_type_id_resolver, desc, "");
+	revert_creds(saved_cred);
+	kfree(desc);
+	if (IS_ERR(rkey)) {
+		ret = PTR_ERR(rkey);
+		goto out;
+	}
+
+	rcu_read_lock();
+	rkey->perm |= KEY_USR_VIEW;
+
+	ret = key_validate(rkey);
+	if (ret < 0)
+		goto out_up;
+
+	payload = rcu_dereference(rkey->payload.data);
+	if (IS_ERR_OR_NULL(payload)) {
+		ret = PTR_ERR(payload);
+		goto out_up;
+	}
+
+	ret = payload->datalen;
+	if (ret > 0 && ret <= data_size)
+		memcpy(data, payload->data, ret);
+	else
+		ret = -EINVAL;
+
+out_up:
+	rcu_read_unlock();
+	key_put(rkey);
+out:
+	return ret;
+}
+
+
+/* ID -> Name */
+static ssize_t nfs_idmap_lookup_name(__u32 id, const char *type, char *buf, size_t buflen)
+{
+	char id_str[NFS_UINT_MAXLEN];
+	int id_len;
+	ssize_t ret;
+
+	id_len = snprintf(id_str, sizeof(id_str), "%u", id);
+	ret = nfs_idmap_request_key(id_str, id_len, type, buf, buflen);
+	if (ret < 0)
+		return -EINVAL;
+	return ret;
+}
+
+/* Name -> ID */
+static int nfs_idmap_lookup_id(const char *name, size_t namelen,
+				const char *type, __u32 *id)
+{
+	char id_str[NFS_UINT_MAXLEN];
+	long id_long;
+	ssize_t data_size;
+	int ret = 0;
+
+	data_size = nfs_idmap_request_key(name, namelen, type, id_str, NFS_UINT_MAXLEN);
+	if (data_size <= 0) {
+		ret = -EINVAL;
+	} else {
+		ret = strict_strtol(id_str, 10, &id_long);
+		*id = (__u32)id_long;
+	}
+	return ret;
+}
+
+int nfs_map_name_to_uid(struct nfs_client *clp, const char *name, size_t namelen, __u32 *uid)
+{
+	return nfs_idmap_lookup_id(name, namelen, "uid", uid);
+}
+
+int nfs_map_group_to_gid(struct nfs_client *clp, const char *name, size_t namelen, __u32 *gid)
+{
+	return nfs_idmap_lookup_id(name, namelen, "gid", gid);
+}
+
+int nfs_map_uid_to_name(struct nfs_client *clp, __u32 uid, char *buf, size_t buflen)
+{
+	return nfs_idmap_lookup_name(uid, "user", buf, buflen);
+}
+int nfs_map_gid_to_group(struct nfs_client *clp, __u32 gid, char *buf, size_t buflen)
+{
+	return nfs_idmap_lookup_name(gid, "group", buf, buflen);
+}
+
+#else  /* CONFIG_NFS_USE_IDMAPPER not defined */
+
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/init.h>
@@ -503,16 +709,17 @@
 	return nfs_idmap_id(idmap, &idmap->idmap_group_hash, name, namelen, uid);
 }
 
-int nfs_map_uid_to_name(struct nfs_client *clp, __u32 uid, char *buf)
+int nfs_map_uid_to_name(struct nfs_client *clp, __u32 uid, char *buf, size_t buflen)
 {
 	struct idmap *idmap = clp->cl_idmap;
 
 	return nfs_idmap_name(idmap, &idmap->idmap_user_hash, uid, buf);
 }
-int nfs_map_gid_to_group(struct nfs_client *clp, __u32 uid, char *buf)
+int nfs_map_gid_to_group(struct nfs_client *clp, __u32 uid, char *buf, size_t buflen)
 {
 	struct idmap *idmap = clp->cl_idmap;
 
 	return nfs_idmap_name(idmap, &idmap->idmap_group_hash, uid, buf);
 }
 
+#endif /* CONFIG_NFS_USE_NEW_IDMAPPER */
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 7d2d6c7..314f571 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -48,6 +48,7 @@
 #include "internal.h"
 #include "fscache.h"
 #include "dns_resolve.h"
+#include "pnfs.h"
 
 #define NFSDBG_FACILITY		NFSDBG_VFS
 
@@ -234,9 +235,6 @@
 	return 0;
 }
 
-/* Don't use READDIRPLUS on directories that we believe are too large */
-#define NFS_LIMIT_READDIRPLUS (8*PAGE_SIZE)
-
 /*
  * This is our front-end to iget that looks up inodes by file handle
  * instead of inode number.
@@ -291,8 +289,7 @@
 		} else if (S_ISDIR(inode->i_mode)) {
 			inode->i_op = NFS_SB(sb)->nfs_client->rpc_ops->dir_inode_ops;
 			inode->i_fop = &nfs_dir_operations;
-			if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS)
-			    && fattr->size <= NFS_LIMIT_READDIRPLUS)
+			if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS))
 				set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags);
 			/* Deal with crossing mountpoints */
 			if ((fattr->valid & NFS_ATTR_FATTR_FSID)
@@ -623,7 +620,7 @@
 	nfs_revalidate_inode(server, inode);
 }
 
-static struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct rpc_cred *cred)
+struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct rpc_cred *cred, fmode_t f_mode)
 {
 	struct nfs_open_context *ctx;
 
@@ -633,11 +630,13 @@
 		path_get(&ctx->path);
 		ctx->cred = get_rpccred(cred);
 		ctx->state = NULL;
+		ctx->mode = f_mode;
 		ctx->flags = 0;
 		ctx->error = 0;
 		ctx->dir_cookie = 0;
 		nfs_init_lock_context(&ctx->lock_context);
 		ctx->lock_context.open_context = ctx;
+		INIT_LIST_HEAD(&ctx->list);
 	}
 	return ctx;
 }
@@ -653,11 +652,15 @@
 {
 	struct inode *inode = ctx->path.dentry->d_inode;
 
-	if (!atomic_dec_and_lock(&ctx->lock_context.count, &inode->i_lock))
+	if (!list_empty(&ctx->list)) {
+		if (!atomic_dec_and_lock(&ctx->lock_context.count, &inode->i_lock))
+			return;
+		list_del(&ctx->list);
+		spin_unlock(&inode->i_lock);
+	} else if (!atomic_dec_and_test(&ctx->lock_context.count))
 		return;
-	list_del(&ctx->list);
-	spin_unlock(&inode->i_lock);
-	NFS_PROTO(inode)->close_context(ctx, is_sync);
+	if (inode != NULL)
+		NFS_PROTO(inode)->close_context(ctx, is_sync);
 	if (ctx->cred != NULL)
 		put_rpccred(ctx->cred);
 	path_put(&ctx->path);
@@ -673,7 +676,7 @@
  * Ensure that mmap has a recent RPC credential for use when writing out
  * shared pages
  */
-static void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
+void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
 {
 	struct inode *inode = filp->f_path.dentry->d_inode;
 	struct nfs_inode *nfsi = NFS_I(inode);
@@ -730,11 +733,10 @@
 	cred = rpc_lookup_cred();
 	if (IS_ERR(cred))
 		return PTR_ERR(cred);
-	ctx = alloc_nfs_open_context(&filp->f_path, cred);
+	ctx = alloc_nfs_open_context(&filp->f_path, cred, filp->f_mode);
 	put_rpccred(cred);
 	if (ctx == NULL)
 		return -ENOMEM;
-	ctx->mode = filp->f_mode;
 	nfs_file_set_open_context(filp, ctx);
 	put_nfs_open_context(ctx);
 	nfs_fscache_set_inode_cookie(inode, filp);
@@ -1409,6 +1411,7 @@
 {
 	truncate_inode_pages(&inode->i_data, 0);
 	end_writeback(inode);
+	pnfs_destroy_layout(NFS_I(inode));
 	/* If we are holding a delegation, return it! */
 	nfs_inode_return_delegation_noreclaim(inode);
 	/* First call standard NFS clear_inode() code */
@@ -1446,6 +1449,7 @@
 	nfsi->delegation = NULL;
 	nfsi->delegation_state = 0;
 	init_rwsem(&nfsi->rwsem);
+	nfsi->layout = NULL;
 #endif
 }
 
@@ -1493,7 +1497,7 @@
 {
 	struct workqueue_struct *wq;
 	dprintk("RPC:       creating workqueue nfsiod\n");
-	wq = create_singlethread_workqueue("nfsiod");
+	wq = alloc_workqueue("nfsiod", WQ_RESCUER, 0);
 	if (wq == NULL)
 		return -ENOMEM;
 	nfsiod_workqueue = wq;
@@ -1521,6 +1525,10 @@
 {
 	int err;
 
+	err = nfs_idmap_init();
+	if (err < 0)
+		goto out9;
+
 	err = nfs_dns_resolver_init();
 	if (err < 0)
 		goto out8;
@@ -1585,6 +1593,8 @@
 out7:
 	nfs_dns_resolver_destroy();
 out8:
+	nfs_idmap_quit();
+out9:
 	return err;
 }
 
@@ -1597,6 +1607,7 @@
 	nfs_destroy_nfspagecache();
 	nfs_fscache_unregister();
 	nfs_dns_resolver_destroy();
+	nfs_idmap_quit();
 #ifdef CONFIG_PROC_FS
 	rpc_proc_unregister("nfs");
 #endif
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index c961bc9..db08ff3 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -63,6 +63,12 @@
 #define NFS_UNSPEC_PORT		(-1)
 
 /*
+ * Maximum number of pages that readdir can use for creating
+ * a vmapped array of pages.
+ */
+#define NFS_MAX_READDIR_PAGES 8
+
+/*
  * In-kernel mount arguments
  */
 struct nfs_parsed_mount_data {
@@ -181,15 +187,15 @@
 /* nfs2xdr.c */
 extern int nfs_stat_to_errno(int);
 extern struct rpc_procinfo nfs_procedures[];
-extern __be32 * nfs_decode_dirent(__be32 *, struct nfs_entry *, int);
+extern __be32 *nfs_decode_dirent(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int);
 
 /* nfs3xdr.c */
 extern struct rpc_procinfo nfs3_procedures[];
-extern __be32 *nfs3_decode_dirent(__be32 *, struct nfs_entry *, int);
+extern __be32 *nfs3_decode_dirent(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int);
 
 /* nfs4xdr.c */
 #ifdef CONFIG_NFS_V4
-extern __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus);
+extern __be32 *nfs4_decode_dirent(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int);
 #endif
 #ifdef CONFIG_NFS_V4_1
 extern const u32 nfs41_maxread_overhead;
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
index 59047f8..eceafe7 100644
--- a/fs/nfs/mount_clnt.c
+++ b/fs/nfs/mount_clnt.c
@@ -153,6 +153,7 @@
 		.rpc_resp	= &result,
 	};
 	struct rpc_create_args args = {
+		.net		= &init_net,
 		.protocol	= info->protocol,
 		.address	= info->sap,
 		.addrsize	= info->salen,
@@ -224,6 +225,7 @@
 		.to_retries = 2,
 	};
 	struct rpc_create_args args = {
+		.net		= &init_net,
 		.protocol	= IPPROTO_UDP,
 		.address	= info->sap,
 		.addrsize	= info->salen,
@@ -436,7 +438,7 @@
 
 	for (i = 0; i < entries; i++) {
 		flavors[i] = ntohl(*p++);
-		dprintk("NFS:\tflavor %u: %d\n", i, flavors[i]);
+		dprintk("NFS:   auth flavor[%u]: %d\n", i, flavors[i]);
 	}
 	*count = i;
 
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
index db8846a..e6bf457 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2xdr.c
@@ -337,10 +337,10 @@
 static int
 nfs_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs_renameargs *args)
 {
-	p = xdr_encode_fhandle(p, args->fromfh);
-	p = xdr_encode_array(p, args->fromname, args->fromlen);
-	p = xdr_encode_fhandle(p, args->tofh);
-	p = xdr_encode_array(p, args->toname, args->tolen);
+	p = xdr_encode_fhandle(p, args->old_dir);
+	p = xdr_encode_array(p, args->old_name->name, args->old_name->len);
+	p = xdr_encode_fhandle(p, args->new_dir);
+	p = xdr_encode_array(p, args->new_name->name, args->new_name->len);
 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
 	return 0;
 }
@@ -423,9 +423,7 @@
 	struct page **page;
 	size_t hdrlen;
 	unsigned int pglen, recvd;
-	u32 len;
 	int status, nr = 0;
-	__be32 *end, *entry, *kaddr;
 
 	if ((status = ntohl(*p++)))
 		return nfs_stat_to_errno(status);
@@ -445,80 +443,59 @@
 	if (pglen > recvd)
 		pglen = recvd;
 	page = rcvbuf->pages;
-	kaddr = p = kmap_atomic(*page, KM_USER0);
-	end = (__be32 *)((char *)p + pglen);
-	entry = p;
-
-	/* Make sure the packet actually has a value_follows and EOF entry */
-	if ((entry + 1) > end)
-		goto short_pkt;
-
-	for (; *p++; nr++) {
-		if (p + 2 > end)
-			goto short_pkt;
-		p++; /* fileid */
-		len = ntohl(*p++);
-		p += XDR_QUADLEN(len) + 1;	/* name plus cookie */
-		if (len > NFS2_MAXNAMLEN) {
-			dprintk("NFS: giant filename in readdir (len 0x%x)!\n",
-						len);
-			goto err_unmap;
-		}
-		if (p + 2 > end)
-			goto short_pkt;
-		entry = p;
-	}
-
-	/*
-	 * Apparently some server sends responses that are a valid size, but
-	 * contain no entries, and have value_follows==0 and EOF==0. For
-	 * those, just set the EOF marker.
-	 */
-	if (!nr && entry[1] == 0) {
-		dprintk("NFS: readdir reply truncated!\n");
-		entry[1] = 1;
-	}
- out:
-	kunmap_atomic(kaddr, KM_USER0);
 	return nr;
- short_pkt:
-	/*
-	 * When we get a short packet there are 2 possibilities. We can
-	 * return an error, or fix up the response to look like a valid
-	 * response and return what we have so far. If there are no
-	 * entries and the packet was short, then return -EIO. If there
-	 * are valid entries in the response, return them and pretend that
-	 * the call was successful, but incomplete. The caller can retry the
-	 * readdir starting at the last cookie.
-	 */
-	entry[0] = entry[1] = 0;
-	if (!nr)
-		nr = -errno_NFSERR_IO;
-	goto out;
-err_unmap:
-	nr = -errno_NFSERR_IO;
-	goto out;
+}
+
+static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
+{
+	dprintk("nfs: %s: prematurely hit end of receive buffer. "
+		"Remaining buffer length is %tu words.\n",
+		func, xdr->end - xdr->p);
 }
 
 __be32 *
-nfs_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
+nfs_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_server *server, int plus)
 {
-	if (!*p++) {
-		if (!*p)
+	__be32 *p;
+	p = xdr_inline_decode(xdr, 4);
+	if (unlikely(!p))
+		goto out_overflow;
+	if (!ntohl(*p++)) {
+		p = xdr_inline_decode(xdr, 4);
+		if (unlikely(!p))
+			goto out_overflow;
+		if (!ntohl(*p++))
 			return ERR_PTR(-EAGAIN);
 		entry->eof = 1;
 		return ERR_PTR(-EBADCOOKIE);
 	}
 
+	p = xdr_inline_decode(xdr, 8);
+	if (unlikely(!p))
+		goto out_overflow;
+
 	entry->ino	  = ntohl(*p++);
 	entry->len	  = ntohl(*p++);
+
+	p = xdr_inline_decode(xdr, entry->len + 4);
+	if (unlikely(!p))
+		goto out_overflow;
 	entry->name	  = (const char *) p;
 	p		 += XDR_QUADLEN(entry->len);
 	entry->prev_cookie	  = entry->cookie;
 	entry->cookie	  = ntohl(*p++);
-	entry->eof	  = !p[0] && p[1];
+
+	p = xdr_inline_peek(xdr, 8);
+	if (p != NULL)
+		entry->eof = !p[0] && p[1];
+	else
+		entry->eof = 0;
 
 	return p;
+
+out_overflow:
+	print_overflow_msg(__func__, xdr);
+	return ERR_PTR(-EIO);
 }
 
 /*
@@ -596,7 +573,6 @@
 	struct kvec *iov = rcvbuf->head;
 	size_t hdrlen;
 	u32 len, recvd;
-	char	*kaddr;
 	int	status;
 
 	if ((status = ntohl(*p++)))
@@ -623,10 +599,7 @@
 		return -EIO;
 	}
 
-	/* NULL terminate the string we got */
-	kaddr = (char *)kmap_atomic(rcvbuf->pages[0], KM_USER0);
-	kaddr[len+rcvbuf->page_base] = '\0';
-	kunmap_atomic(kaddr, KM_USER0);
+	xdr_terminate_string(rcvbuf, len);
 	return 0;
 }
 
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index fabb4f2..ce939c0 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -313,7 +313,7 @@
  */
 static int
 nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
-		 int flags, struct nameidata *nd)
+		 int flags, struct nfs_open_context *ctx)
 {
 	struct nfs3_createdata *data;
 	mode_t mode = sattr->ia_mode;
@@ -438,19 +438,38 @@
 	return 1;
 }
 
+static void
+nfs3_proc_rename_setup(struct rpc_message *msg, struct inode *dir)
+{
+	msg->rpc_proc = &nfs3_procedures[NFS3PROC_RENAME];
+}
+
+static int
+nfs3_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
+		      struct inode *new_dir)
+{
+	struct nfs_renameres *res;
+
+	if (nfs3_async_handle_jukebox(task, old_dir))
+		return 0;
+	res = task->tk_msg.rpc_resp;
+
+	nfs_post_op_update_inode(old_dir, res->old_fattr);
+	nfs_post_op_update_inode(new_dir, res->new_fattr);
+	return 1;
+}
+
 static int
 nfs3_proc_rename(struct inode *old_dir, struct qstr *old_name,
 		 struct inode *new_dir, struct qstr *new_name)
 {
-	struct nfs3_renameargs	arg = {
-		.fromfh		= NFS_FH(old_dir),
-		.fromname	= old_name->name,
-		.fromlen	= old_name->len,
-		.tofh		= NFS_FH(new_dir),
-		.toname		= new_name->name,
-		.tolen		= new_name->len
+	struct nfs_renameargs	arg = {
+		.old_dir	= NFS_FH(old_dir),
+		.old_name	= old_name,
+		.new_dir	= NFS_FH(new_dir),
+		.new_name	= new_name,
 	};
-	struct nfs3_renameres res;
+	struct nfs_renameres res;
 	struct rpc_message msg = {
 		.rpc_proc	= &nfs3_procedures[NFS3PROC_RENAME],
 		.rpc_argp	= &arg,
@@ -460,17 +479,17 @@
 
 	dprintk("NFS call  rename %s -> %s\n", old_name->name, new_name->name);
 
-	res.fromattr = nfs_alloc_fattr();
-	res.toattr = nfs_alloc_fattr();
-	if (res.fromattr == NULL || res.toattr == NULL)
+	res.old_fattr = nfs_alloc_fattr();
+	res.new_fattr = nfs_alloc_fattr();
+	if (res.old_fattr == NULL || res.new_fattr == NULL)
 		goto out;
 
 	status = rpc_call_sync(NFS_CLIENT(old_dir), &msg, 0);
-	nfs_post_op_update_inode(old_dir, res.fromattr);
-	nfs_post_op_update_inode(new_dir, res.toattr);
+	nfs_post_op_update_inode(old_dir, res.old_fattr);
+	nfs_post_op_update_inode(new_dir, res.new_fattr);
 out:
-	nfs_free_fattr(res.toattr);
-	nfs_free_fattr(res.fromattr);
+	nfs_free_fattr(res.old_fattr);
+	nfs_free_fattr(res.new_fattr);
 	dprintk("NFS reply rename: %d\n", status);
 	return status;
 }
@@ -611,7 +630,7 @@
  */
 static int
 nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
-		  u64 cookie, struct page *page, unsigned int count, int plus)
+		  u64 cookie, struct page **pages, unsigned int count, int plus)
 {
 	struct inode		*dir = dentry->d_inode;
 	__be32			*verf = NFS_COOKIEVERF(dir);
@@ -621,7 +640,7 @@
 		.verf		= {verf[0], verf[1]},
 		.plus		= plus,
 		.count		= count,
-		.pages		= &page
+		.pages		= pages
 	};
 	struct nfs3_readdirres	res = {
 		.verf		= verf,
@@ -652,7 +671,8 @@
 
 	nfs_free_fattr(res.dir_attr);
 out:
-	dprintk("NFS reply readdir: %d\n", status);
+	dprintk("NFS reply readdir%s: %d\n",
+			plus? "plus" : "", status);
 	return status;
 }
 
@@ -722,7 +742,7 @@
 	dprintk("NFS call  fsstat\n");
 	nfs_fattr_init(stat->fattr);
 	status = rpc_call_sync(server->client, &msg, 0);
-	dprintk("NFS reply statfs: %d\n", status);
+	dprintk("NFS reply fsstat: %d\n", status);
 	return status;
 }
 
@@ -844,6 +864,8 @@
 	.unlink_setup	= nfs3_proc_unlink_setup,
 	.unlink_done	= nfs3_proc_unlink_done,
 	.rename		= nfs3_proc_rename,
+	.rename_setup	= nfs3_proc_rename_setup,
+	.rename_done	= nfs3_proc_rename_done,
 	.link		= nfs3_proc_link,
 	.symlink	= nfs3_proc_symlink,
 	.mkdir		= nfs3_proc_mkdir,
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index 9769704..d9a5e83 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -100,6 +100,13 @@
 	[NF3FIFO] = S_IFIFO,
 };
 
+static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
+{
+	dprintk("nfs: %s: prematurely hit end of receive buffer. "
+		"Remaining buffer length is %tu words.\n",
+		func, xdr->end - xdr->p);
+}
+
 /*
  * Common NFS XDR functions as inlines
  */
@@ -119,6 +126,29 @@
 	return NULL;
 }
 
+static inline __be32 *
+xdr_decode_fhandle_stream(struct xdr_stream *xdr, struct nfs_fh *fh)
+{
+	__be32 *p;
+	p = xdr_inline_decode(xdr, 4);
+	if (unlikely(!p))
+		goto out_overflow;
+	fh->size = ntohl(*p++);
+
+	if (fh->size <= NFS3_FHSIZE) {
+		p = xdr_inline_decode(xdr, fh->size);
+		if (unlikely(!p))
+			goto out_overflow;
+		memcpy(fh->data, p, fh->size);
+		return p + XDR_QUADLEN(fh->size);
+	}
+	return NULL;
+
+out_overflow:
+	print_overflow_msg(__func__, xdr);
+	return ERR_PTR(-EIO);
+}
+
 /*
  * Encode/decode time.
  */
@@ -241,6 +271,26 @@
 }
 
 static inline __be32 *
+xdr_decode_post_op_attr_stream(struct xdr_stream *xdr, struct nfs_fattr *fattr)
+{
+	__be32 *p;
+
+	p = xdr_inline_decode(xdr, 4);
+	if (unlikely(!p))
+		goto out_overflow;
+	if (ntohl(*p++)) {
+		p = xdr_inline_decode(xdr, 84);
+		if (unlikely(!p))
+			goto out_overflow;
+		p = xdr_decode_fattr(p, fattr);
+	}
+	return p;
+out_overflow:
+	print_overflow_msg(__func__, xdr);
+	return ERR_PTR(-EIO);
+}
+
+static inline __be32 *
 xdr_decode_pre_op_attr(__be32 *p, struct nfs_fattr *fattr)
 {
 	if (*p++)
@@ -442,12 +492,12 @@
  * Encode RENAME arguments
  */
 static int
-nfs3_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs3_renameargs *args)
+nfs3_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs_renameargs *args)
 {
-	p = xdr_encode_fhandle(p, args->fromfh);
-	p = xdr_encode_array(p, args->fromname, args->fromlen);
-	p = xdr_encode_fhandle(p, args->tofh);
-	p = xdr_encode_array(p, args->toname, args->tolen);
+	p = xdr_encode_fhandle(p, args->old_dir);
+	p = xdr_encode_array(p, args->old_name->name, args->old_name->len);
+	p = xdr_encode_fhandle(p, args->new_dir);
+	p = xdr_encode_array(p, args->new_name->name, args->new_name->len);
 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
 	return 0;
 }
@@ -504,9 +554,8 @@
 	struct kvec *iov = rcvbuf->head;
 	struct page **page;
 	size_t hdrlen;
-	u32 len, recvd, pglen;
+	u32 recvd, pglen;
 	int status, nr = 0;
-	__be32 *entry, *end, *kaddr;
 
 	status = ntohl(*p++);
 	/* Decode post_op_attrs */
@@ -536,99 +585,38 @@
 	if (pglen > recvd)
 		pglen = recvd;
 	page = rcvbuf->pages;
-	kaddr = p = kmap_atomic(*page, KM_USER0);
-	end = (__be32 *)((char *)p + pglen);
-	entry = p;
 
-	/* Make sure the packet actually has a value_follows and EOF entry */
-	if ((entry + 1) > end)
-		goto short_pkt;
-
-	for (; *p++; nr++) {
-		if (p + 3 > end)
-			goto short_pkt;
-		p += 2;				/* inode # */
-		len = ntohl(*p++);		/* string length */
-		p += XDR_QUADLEN(len) + 2;	/* name + cookie */
-		if (len > NFS3_MAXNAMLEN) {
-			dprintk("NFS: giant filename in readdir (len 0x%x)!\n",
-						len);
-			goto err_unmap;
-		}
-
-		if (res->plus) {
-			/* post_op_attr */
-			if (p + 2 > end)
-				goto short_pkt;
-			if (*p++) {
-				p += 21;
-				if (p + 1 > end)
-					goto short_pkt;
-			}
-			/* post_op_fh3 */
-			if (*p++) {
-				if (p + 1 > end)
-					goto short_pkt;
-				len = ntohl(*p++);
-				if (len > NFS3_FHSIZE) {
-					dprintk("NFS: giant filehandle in "
-						"readdir (len 0x%x)!\n", len);
-					goto err_unmap;
-				}
-				p += XDR_QUADLEN(len);
-			}
-		}
-
-		if (p + 2 > end)
-			goto short_pkt;
-		entry = p;
-	}
-
-	/*
-	 * Apparently some server sends responses that are a valid size, but
-	 * contain no entries, and have value_follows==0 and EOF==0. For
-	 * those, just set the EOF marker.
-	 */
-	if (!nr && entry[1] == 0) {
-		dprintk("NFS: readdir reply truncated!\n");
-		entry[1] = 1;
-	}
- out:
-	kunmap_atomic(kaddr, KM_USER0);
 	return nr;
- short_pkt:
-	/*
-	 * When we get a short packet there are 2 possibilities. We can
-	 * return an error, or fix up the response to look like a valid
-	 * response and return what we have so far. If there are no
-	 * entries and the packet was short, then return -EIO. If there
-	 * are valid entries in the response, return them and pretend that
-	 * the call was successful, but incomplete. The caller can retry the
-	 * readdir starting at the last cookie.
-	 */
-	entry[0] = entry[1] = 0;
-	if (!nr)
-		nr = -errno_NFSERR_IO;
-	goto out;
-err_unmap:
-	nr = -errno_NFSERR_IO;
-	goto out;
 }
 
 __be32 *
-nfs3_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
+nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_server *server, int plus)
 {
+	__be32 *p;
 	struct nfs_entry old = *entry;
 
-	if (!*p++) {
-		if (!*p)
+	p = xdr_inline_decode(xdr, 4);
+	if (unlikely(!p))
+		goto out_overflow;
+	if (!ntohl(*p++)) {
+		p = xdr_inline_decode(xdr, 4);
+		if (unlikely(!p))
+			goto out_overflow;
+		if (!ntohl(*p++))
 			return ERR_PTR(-EAGAIN);
 		entry->eof = 1;
 		return ERR_PTR(-EBADCOOKIE);
 	}
 
+	p = xdr_inline_decode(xdr, 12);
+	if (unlikely(!p))
+		goto out_overflow;
 	p = xdr_decode_hyper(p, &entry->ino);
 	entry->len  = ntohl(*p++);
+
+	p = xdr_inline_decode(xdr, entry->len + 8);
+	if (unlikely(!p))
+		goto out_overflow;
 	entry->name = (const char *) p;
 	p += XDR_QUADLEN(entry->len);
 	entry->prev_cookie = entry->cookie;
@@ -636,10 +624,17 @@
 
 	if (plus) {
 		entry->fattr->valid = 0;
-		p = xdr_decode_post_op_attr(p, entry->fattr);
+		p = xdr_decode_post_op_attr_stream(xdr, entry->fattr);
+		if (IS_ERR(p))
+			goto out_overflow_exit;
 		/* In fact, a post_op_fh3: */
+		p = xdr_inline_decode(xdr, 4);
+		if (unlikely(!p))
+			goto out_overflow;
 		if (*p++) {
-			p = xdr_decode_fhandle(p, entry->fh);
+			p = xdr_decode_fhandle_stream(xdr, entry->fh);
+			if (IS_ERR(p))
+				goto out_overflow_exit;
 			/* Ugh -- server reply was truncated */
 			if (p == NULL) {
 				dprintk("NFS: FH truncated\n");
@@ -650,8 +645,18 @@
 			memset((u8*)(entry->fh), 0, sizeof(*entry->fh));
 	}
 
-	entry->eof = !p[0] && p[1];
+	p = xdr_inline_peek(xdr, 8);
+	if (p != NULL)
+		entry->eof = !p[0] && p[1];
+	else
+		entry->eof = 0;
+
 	return p;
+
+out_overflow:
+	print_overflow_msg(__func__, xdr);
+out_overflow_exit:
+	return ERR_PTR(-EIO);
 }
 
 /*
@@ -824,7 +829,6 @@
 	struct kvec *iov = rcvbuf->head;
 	size_t hdrlen;
 	u32 len, recvd;
-	char	*kaddr;
 	int	status;
 
 	status = ntohl(*p++);
@@ -857,10 +861,7 @@
 		return -EIO;
 	}
 
-	/* NULL terminate the string we got */
-	kaddr = (char*)kmap_atomic(rcvbuf->pages[0], KM_USER0);
-	kaddr[len+rcvbuf->page_base] = '\0';
-	kunmap_atomic(kaddr, KM_USER0);
+	xdr_terminate_string(rcvbuf, len);
 	return 0;
 }
 
@@ -970,14 +971,14 @@
  * Decode RENAME reply
  */
 static int
-nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs3_renameres *res)
+nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs_renameres *res)
 {
 	int	status;
 
 	if ((status = ntohl(*p++)) != 0)
 		status = nfs_stat_to_errno(status);
-	p = xdr_decode_wcc_data(p, res->fromattr);
-	p = xdr_decode_wcc_data(p, res->toattr);
+	p = xdr_decode_wcc_data(p, res->old_fattr);
+	p = xdr_decode_wcc_data(p, res->new_fattr);
 	return status;
 }
 
@@ -1043,8 +1044,9 @@
 	res->wtmult = ntohl(*p++);
 	res->dtpref = ntohl(*p++);
 	p = xdr_decode_hyper(p, &res->maxfilesize);
+	p = xdr_decode_time3(p, &res->time_delta);
 
-	/* ignore time_delta and properties */
+	/* ignore properties */
 	res->lease_time = 0;
 	return 0;
 }
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 311e15c..9fa4963 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -242,8 +242,6 @@
 extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *);
 extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *);
 extern int nfs4_do_close(struct path *path, struct nfs4_state *state, gfp_t gfp_mask, int wait);
-extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
-extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
 extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
 extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
 		struct nfs4_fs_locations *fs_locations, struct page *page);
@@ -333,7 +331,7 @@
 extern const nfs4_stateid zero_stateid;
 
 /* nfs4xdr.c */
-extern __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus);
+extern __be32 *nfs4_decode_dirent(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int);
 extern struct rpc_procinfo nfs4_procedures[];
 
 struct nfs4_mount_data;
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
new file mode 100644
index 0000000..2e92f0d
--- /dev/null
+++ b/fs/nfs/nfs4filelayout.c
@@ -0,0 +1,280 @@
+/*
+ *  Module for the pnfs nfs4 file layout driver.
+ *  Defines all I/O and Policy interface operations, plus code
+ *  to register itself with the pNFS client.
+ *
+ *  Copyright (c) 2002
+ *  The Regents of the University of Michigan
+ *  All Rights Reserved
+ *
+ *  Dean Hildebrand <dhildebz@umich.edu>
+ *
+ *  Permission is granted to use, copy, create derivative works, and
+ *  redistribute this software and such derivative works for any purpose,
+ *  so long as the name of the University of Michigan is not used in
+ *  any advertising or publicity pertaining to the use or distribution
+ *  of this software without specific, written prior authorization. If
+ *  the above copyright notice or any other identification of the
+ *  University of Michigan is included in any copy of any portion of
+ *  this software, then the disclaimer below must also be included.
+ *
+ *  This software is provided as is, without representation or warranty
+ *  of any kind either express or implied, including without limitation
+ *  the implied warranties of merchantability, fitness for a particular
+ *  purpose, or noninfringement.  The Regents of the University of
+ *  Michigan shall not be liable for any damages, including special,
+ *  indirect, incidental, or consequential damages, with respect to any
+ *  claim arising out of or in connection with the use of the software,
+ *  even if it has been or is hereafter advised of the possibility of
+ *  such damages.
+ */
+
+#include <linux/nfs_fs.h>
+
+#include "internal.h"
+#include "nfs4filelayout.h"
+
+#define NFSDBG_FACILITY         NFSDBG_PNFS_LD
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Dean Hildebrand <dhildebz@umich.edu>");
+MODULE_DESCRIPTION("The NFSv4 file layout driver");
+
+static int
+filelayout_set_layoutdriver(struct nfs_server *nfss)
+{
+	int status = pnfs_alloc_init_deviceid_cache(nfss->nfs_client,
+						nfs4_fl_free_deviceid_callback);
+	if (status) {
+		printk(KERN_WARNING "%s: deviceid cache could not be "
+			"initialized\n", __func__);
+		return status;
+	}
+	dprintk("%s: deviceid cache has been initialized successfully\n",
+		__func__);
+	return 0;
+}
+
+/* Clear out the layout by destroying its device list */
+static int
+filelayout_clear_layoutdriver(struct nfs_server *nfss)
+{
+	dprintk("--> %s\n", __func__);
+
+	if (nfss->nfs_client->cl_devid_cache)
+		pnfs_put_deviceid_cache(nfss->nfs_client);
+	return 0;
+}
+
+/*
+ * filelayout_check_layout()
+ *
+ * Make sure layout segment parameters are sane WRT the device.
+ * At this point no generic layer initialization of the lseg has occurred,
+ * and nothing has been added to the layout_hdr cache.
+ *
+ */
+static int
+filelayout_check_layout(struct pnfs_layout_hdr *lo,
+			struct nfs4_filelayout_segment *fl,
+			struct nfs4_layoutget_res *lgr,
+			struct nfs4_deviceid *id)
+{
+	struct nfs4_file_layout_dsaddr *dsaddr;
+	int status = -EINVAL;
+	struct nfs_server *nfss = NFS_SERVER(lo->inode);
+
+	dprintk("--> %s\n", __func__);
+
+	if (fl->pattern_offset > lgr->range.offset) {
+		dprintk("%s pattern_offset %lld to large\n",
+				__func__, fl->pattern_offset);
+		goto out;
+	}
+
+	if (fl->stripe_unit % PAGE_SIZE) {
+		dprintk("%s Stripe unit (%u) not page aligned\n",
+			__func__, fl->stripe_unit);
+		goto out;
+	}
+
+	/* find and reference the deviceid */
+	dsaddr = nfs4_fl_find_get_deviceid(nfss->nfs_client, id);
+	if (dsaddr == NULL) {
+		dsaddr = get_device_info(lo->inode, id);
+		if (dsaddr == NULL)
+			goto out;
+	}
+	fl->dsaddr = dsaddr;
+
+	if (fl->first_stripe_index < 0 ||
+	    fl->first_stripe_index >= dsaddr->stripe_count) {
+		dprintk("%s Bad first_stripe_index %d\n",
+				__func__, fl->first_stripe_index);
+		goto out_put;
+	}
+
+	if ((fl->stripe_type == STRIPE_SPARSE &&
+	    fl->num_fh > 1 && fl->num_fh != dsaddr->ds_num) ||
+	    (fl->stripe_type == STRIPE_DENSE &&
+	    fl->num_fh != dsaddr->stripe_count)) {
+		dprintk("%s num_fh %u not valid for given packing\n",
+			__func__, fl->num_fh);
+		goto out_put;
+	}
+
+	if (fl->stripe_unit % nfss->rsize || fl->stripe_unit % nfss->wsize) {
+		dprintk("%s Stripe unit (%u) not aligned with rsize %u "
+			"wsize %u\n", __func__, fl->stripe_unit, nfss->rsize,
+			nfss->wsize);
+	}
+
+	status = 0;
+out:
+	dprintk("--> %s returns %d\n", __func__, status);
+	return status;
+out_put:
+	pnfs_put_deviceid(nfss->nfs_client->cl_devid_cache, &dsaddr->deviceid);
+	goto out;
+}
+
+static void filelayout_free_fh_array(struct nfs4_filelayout_segment *fl)
+{
+	int i;
+
+	for (i = 0; i < fl->num_fh; i++) {
+		if (!fl->fh_array[i])
+			break;
+		kfree(fl->fh_array[i]);
+	}
+	kfree(fl->fh_array);
+	fl->fh_array = NULL;
+}
+
+static void
+_filelayout_free_lseg(struct nfs4_filelayout_segment *fl)
+{
+	filelayout_free_fh_array(fl);
+	kfree(fl);
+}
+
+static int
+filelayout_decode_layout(struct pnfs_layout_hdr *flo,
+			 struct nfs4_filelayout_segment *fl,
+			 struct nfs4_layoutget_res *lgr,
+			 struct nfs4_deviceid *id)
+{
+	uint32_t *p = (uint32_t *)lgr->layout.buf;
+	uint32_t nfl_util;
+	int i;
+
+	dprintk("%s: set_layout_map Begin\n", __func__);
+
+	memcpy(id, p, sizeof(*id));
+	p += XDR_QUADLEN(NFS4_DEVICEID4_SIZE);
+	print_deviceid(id);
+
+	nfl_util = be32_to_cpup(p++);
+	if (nfl_util & NFL4_UFLG_COMMIT_THRU_MDS)
+		fl->commit_through_mds = 1;
+	if (nfl_util & NFL4_UFLG_DENSE)
+		fl->stripe_type = STRIPE_DENSE;
+	else
+		fl->stripe_type = STRIPE_SPARSE;
+	fl->stripe_unit = nfl_util & ~NFL4_UFLG_MASK;
+
+	fl->first_stripe_index = be32_to_cpup(p++);
+	p = xdr_decode_hyper(p, &fl->pattern_offset);
+	fl->num_fh = be32_to_cpup(p++);
+
+	dprintk("%s: nfl_util 0x%X num_fh %u fsi %u po %llu\n",
+		__func__, nfl_util, fl->num_fh, fl->first_stripe_index,
+		fl->pattern_offset);
+
+	fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *),
+			       GFP_KERNEL);
+	if (!fl->fh_array)
+		return -ENOMEM;
+
+	for (i = 0; i < fl->num_fh; i++) {
+		/* Do we want to use a mempool here? */
+		fl->fh_array[i] = kmalloc(sizeof(struct nfs_fh), GFP_KERNEL);
+		if (!fl->fh_array[i]) {
+			filelayout_free_fh_array(fl);
+			return -ENOMEM;
+		}
+		fl->fh_array[i]->size = be32_to_cpup(p++);
+		if (sizeof(struct nfs_fh) < fl->fh_array[i]->size) {
+			printk(KERN_ERR "Too big fh %d received %d\n",
+			       i, fl->fh_array[i]->size);
+			filelayout_free_fh_array(fl);
+			return -EIO;
+		}
+		memcpy(fl->fh_array[i]->data, p, fl->fh_array[i]->size);
+		p += XDR_QUADLEN(fl->fh_array[i]->size);
+		dprintk("DEBUG: %s: fh len %d\n", __func__,
+			fl->fh_array[i]->size);
+	}
+
+	return 0;
+}
+
+static struct pnfs_layout_segment *
+filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid,
+		      struct nfs4_layoutget_res *lgr)
+{
+	struct nfs4_filelayout_segment *fl;
+	int rc;
+	struct nfs4_deviceid id;
+
+	dprintk("--> %s\n", __func__);
+	fl = kzalloc(sizeof(*fl), GFP_KERNEL);
+	if (!fl)
+		return NULL;
+
+	rc = filelayout_decode_layout(layoutid, fl, lgr, &id);
+	if (rc != 0 || filelayout_check_layout(layoutid, fl, lgr, &id)) {
+		_filelayout_free_lseg(fl);
+		return NULL;
+	}
+	return &fl->generic_hdr;
+}
+
+static void
+filelayout_free_lseg(struct pnfs_layout_segment *lseg)
+{
+	struct nfs_server *nfss = NFS_SERVER(lseg->layout->inode);
+	struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg);
+
+	dprintk("--> %s\n", __func__);
+	pnfs_put_deviceid(nfss->nfs_client->cl_devid_cache,
+			  &fl->dsaddr->deviceid);
+	_filelayout_free_lseg(fl);
+}
+
+static struct pnfs_layoutdriver_type filelayout_type = {
+	.id = LAYOUT_NFSV4_1_FILES,
+	.name = "LAYOUT_NFSV4_1_FILES",
+	.owner = THIS_MODULE,
+	.set_layoutdriver = filelayout_set_layoutdriver,
+	.clear_layoutdriver = filelayout_clear_layoutdriver,
+	.alloc_lseg              = filelayout_alloc_lseg,
+	.free_lseg               = filelayout_free_lseg,
+};
+
+static int __init nfs4filelayout_init(void)
+{
+	printk(KERN_INFO "%s: NFSv4 File Layout Driver Registering...\n",
+	       __func__);
+	return pnfs_register_layoutdriver(&filelayout_type);
+}
+
+static void __exit nfs4filelayout_exit(void)
+{
+	printk(KERN_INFO "%s: NFSv4 File Layout Driver Unregistering...\n",
+	       __func__);
+	pnfs_unregister_layoutdriver(&filelayout_type);
+}
+
+module_init(nfs4filelayout_init);
+module_exit(nfs4filelayout_exit);
diff --git a/fs/nfs/nfs4filelayout.h b/fs/nfs/nfs4filelayout.h
new file mode 100644
index 0000000..bbf60dd
--- /dev/null
+++ b/fs/nfs/nfs4filelayout.h
@@ -0,0 +1,94 @@
+/*
+ *  NFSv4 file layout driver data structures.
+ *
+ *  Copyright (c) 2002
+ *  The Regents of the University of Michigan
+ *  All Rights Reserved
+ *
+ *  Dean Hildebrand <dhildebz@umich.edu>
+ *
+ *  Permission is granted to use, copy, create derivative works, and
+ *  redistribute this software and such derivative works for any purpose,
+ *  so long as the name of the University of Michigan is not used in
+ *  any advertising or publicity pertaining to the use or distribution
+ *  of this software without specific, written prior authorization. If
+ *  the above copyright notice or any other identification of the
+ *  University of Michigan is included in any copy of any portion of
+ *  this software, then the disclaimer below must also be included.
+ *
+ *  This software is provided as is, without representation or warranty
+ *  of any kind either express or implied, including without limitation
+ *  the implied warranties of merchantability, fitness for a particular
+ *  purpose, or noninfringement.  The Regents of the University of
+ *  Michigan shall not be liable for any damages, including special,
+ *  indirect, incidental, or consequential damages, with respect to any
+ *  claim arising out of or in connection with the use of the software,
+ *  even if it has been or is hereafter advised of the possibility of
+ *  such damages.
+ */
+
+#ifndef FS_NFS_NFS4FILELAYOUT_H
+#define FS_NFS_NFS4FILELAYOUT_H
+
+#include "pnfs.h"
+
+/*
+ * Field testing shows we need to support upto 4096 stripe indices.
+ * We store each index as a u8 (u32 on the wire) to keep the memory footprint
+ * reasonable. This in turn means we support a maximum of 256
+ * RFC 5661 multipath_list4 structures.
+ */
+#define NFS4_PNFS_MAX_STRIPE_CNT 4096
+#define NFS4_PNFS_MAX_MULTI_CNT  256 /* 256 fit into a u8 stripe_index */
+
+enum stripetype4 {
+	STRIPE_SPARSE = 1,
+	STRIPE_DENSE = 2
+};
+
+/* Individual ip address */
+struct nfs4_pnfs_ds {
+	struct list_head	ds_node;  /* nfs4_pnfs_dev_hlist dev_dslist */
+	u32			ds_ip_addr;
+	u32			ds_port;
+	struct nfs_client	*ds_clp;
+	atomic_t		ds_count;
+};
+
+struct nfs4_file_layout_dsaddr {
+	struct pnfs_deviceid_node	deviceid;
+	u32				stripe_count;
+	u8				*stripe_indices;
+	u32				ds_num;
+	struct nfs4_pnfs_ds		*ds_list[1];
+};
+
+struct nfs4_filelayout_segment {
+	struct pnfs_layout_segment generic_hdr;
+	u32 stripe_type;
+	u32 commit_through_mds;
+	u32 stripe_unit;
+	u32 first_stripe_index;
+	u64 pattern_offset;
+	struct nfs4_file_layout_dsaddr *dsaddr; /* Point to GETDEVINFO data */
+	unsigned int num_fh;
+	struct nfs_fh **fh_array;
+};
+
+static inline struct nfs4_filelayout_segment *
+FILELAYOUT_LSEG(struct pnfs_layout_segment *lseg)
+{
+	return container_of(lseg,
+			    struct nfs4_filelayout_segment,
+			    generic_hdr);
+}
+
+extern void nfs4_fl_free_deviceid_callback(struct pnfs_deviceid_node *);
+extern void print_ds(struct nfs4_pnfs_ds *ds);
+extern void print_deviceid(struct nfs4_deviceid *dev_id);
+extern struct nfs4_file_layout_dsaddr *
+nfs4_fl_find_get_deviceid(struct nfs_client *, struct nfs4_deviceid *dev_id);
+struct nfs4_file_layout_dsaddr *
+get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id);
+
+#endif /* FS_NFS_NFS4FILELAYOUT_H */
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c
new file mode 100644
index 0000000..51fe64a
--- /dev/null
+++ b/fs/nfs/nfs4filelayoutdev.c
@@ -0,0 +1,448 @@
+/*
+ *  Device operations for the pnfs nfs4 file layout driver.
+ *
+ *  Copyright (c) 2002
+ *  The Regents of the University of Michigan
+ *  All Rights Reserved
+ *
+ *  Dean Hildebrand <dhildebz@umich.edu>
+ *  Garth Goodson   <Garth.Goodson@netapp.com>
+ *
+ *  Permission is granted to use, copy, create derivative works, and
+ *  redistribute this software and such derivative works for any purpose,
+ *  so long as the name of the University of Michigan is not used in
+ *  any advertising or publicity pertaining to the use or distribution
+ *  of this software without specific, written prior authorization. If
+ *  the above copyright notice or any other identification of the
+ *  University of Michigan is included in any copy of any portion of
+ *  this software, then the disclaimer below must also be included.
+ *
+ *  This software is provided as is, without representation or warranty
+ *  of any kind either express or implied, including without limitation
+ *  the implied warranties of merchantability, fitness for a particular
+ *  purpose, or noninfringement.  The Regents of the University of
+ *  Michigan shall not be liable for any damages, including special,
+ *  indirect, incidental, or consequential damages, with respect to any
+ *  claim arising out of or in connection with the use of the software,
+ *  even if it has been or is hereafter advised of the possibility of
+ *  such damages.
+ */
+
+#include <linux/nfs_fs.h>
+#include <linux/vmalloc.h>
+
+#include "internal.h"
+#include "nfs4filelayout.h"
+
+#define NFSDBG_FACILITY		NFSDBG_PNFS_LD
+
+/*
+ * Data server cache
+ *
+ * Data servers can be mapped to different device ids.
+ * nfs4_pnfs_ds reference counting
+ *   - set to 1 on allocation
+ *   - incremented when a device id maps a data server already in the cache.
+ *   - decremented when deviceid is removed from the cache.
+ */
+DEFINE_SPINLOCK(nfs4_ds_cache_lock);
+static LIST_HEAD(nfs4_data_server_cache);
+
+/* Debug routines */
+void
+print_ds(struct nfs4_pnfs_ds *ds)
+{
+	if (ds == NULL) {
+		printk("%s NULL device\n", __func__);
+		return;
+	}
+	printk("        ip_addr %x port %hu\n"
+		"        ref count %d\n"
+		"        client %p\n"
+		"        cl_exchange_flags %x\n",
+		ntohl(ds->ds_ip_addr), ntohs(ds->ds_port),
+		atomic_read(&ds->ds_count), ds->ds_clp,
+		ds->ds_clp ? ds->ds_clp->cl_exchange_flags : 0);
+}
+
+void
+print_ds_list(struct nfs4_file_layout_dsaddr *dsaddr)
+{
+	int i;
+
+	ifdebug(FACILITY) {
+		printk("%s dsaddr->ds_num %d\n", __func__,
+		       dsaddr->ds_num);
+		for (i = 0; i < dsaddr->ds_num; i++)
+			print_ds(dsaddr->ds_list[i]);
+	}
+}
+
+void print_deviceid(struct nfs4_deviceid *id)
+{
+	u32 *p = (u32 *)id;
+
+	dprintk("%s: device id= [%x%x%x%x]\n", __func__,
+		p[0], p[1], p[2], p[3]);
+}
+
+/* nfs4_ds_cache_lock is held */
+static struct nfs4_pnfs_ds *
+_data_server_lookup_locked(u32 ip_addr, u32 port)
+{
+	struct nfs4_pnfs_ds *ds;
+
+	dprintk("_data_server_lookup: ip_addr=%x port=%hu\n",
+			ntohl(ip_addr), ntohs(port));
+
+	list_for_each_entry(ds, &nfs4_data_server_cache, ds_node) {
+		if (ds->ds_ip_addr == ip_addr &&
+		    ds->ds_port == port) {
+			return ds;
+		}
+	}
+	return NULL;
+}
+
+static void
+destroy_ds(struct nfs4_pnfs_ds *ds)
+{
+	dprintk("--> %s\n", __func__);
+	ifdebug(FACILITY)
+		print_ds(ds);
+
+	if (ds->ds_clp)
+		nfs_put_client(ds->ds_clp);
+	kfree(ds);
+}
+
+static void
+nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr)
+{
+	struct nfs4_pnfs_ds *ds;
+	int i;
+
+	print_deviceid(&dsaddr->deviceid.de_id);
+
+	for (i = 0; i < dsaddr->ds_num; i++) {
+		ds = dsaddr->ds_list[i];
+		if (ds != NULL) {
+			if (atomic_dec_and_lock(&ds->ds_count,
+						&nfs4_ds_cache_lock)) {
+				list_del_init(&ds->ds_node);
+				spin_unlock(&nfs4_ds_cache_lock);
+				destroy_ds(ds);
+			}
+		}
+	}
+	kfree(dsaddr->stripe_indices);
+	kfree(dsaddr);
+}
+
+void
+nfs4_fl_free_deviceid_callback(struct pnfs_deviceid_node *device)
+{
+	struct nfs4_file_layout_dsaddr *dsaddr =
+		container_of(device, struct nfs4_file_layout_dsaddr, deviceid);
+
+	nfs4_fl_free_deviceid(dsaddr);
+}
+
+static struct nfs4_pnfs_ds *
+nfs4_pnfs_ds_add(struct inode *inode, u32 ip_addr, u32 port)
+{
+	struct nfs4_pnfs_ds *tmp_ds, *ds;
+
+	ds = kzalloc(sizeof(*tmp_ds), GFP_KERNEL);
+	if (!ds)
+		goto out;
+
+	spin_lock(&nfs4_ds_cache_lock);
+	tmp_ds = _data_server_lookup_locked(ip_addr, port);
+	if (tmp_ds == NULL) {
+		ds->ds_ip_addr = ip_addr;
+		ds->ds_port = port;
+		atomic_set(&ds->ds_count, 1);
+		INIT_LIST_HEAD(&ds->ds_node);
+		ds->ds_clp = NULL;
+		list_add(&ds->ds_node, &nfs4_data_server_cache);
+		dprintk("%s add new data server ip 0x%x\n", __func__,
+			ds->ds_ip_addr);
+	} else {
+		kfree(ds);
+		atomic_inc(&tmp_ds->ds_count);
+		dprintk("%s data server found ip 0x%x, inc'ed ds_count to %d\n",
+			__func__, tmp_ds->ds_ip_addr,
+			atomic_read(&tmp_ds->ds_count));
+		ds = tmp_ds;
+	}
+	spin_unlock(&nfs4_ds_cache_lock);
+out:
+	return ds;
+}
+
+/*
+ * Currently only support ipv4, and one multi-path address.
+ */
+static struct nfs4_pnfs_ds *
+decode_and_add_ds(__be32 **pp, struct inode *inode)
+{
+	struct nfs4_pnfs_ds *ds = NULL;
+	char *buf;
+	const char *ipend, *pstr;
+	u32 ip_addr, port;
+	int nlen, rlen, i;
+	int tmp[2];
+	__be32 *r_netid, *r_addr, *p = *pp;
+
+	/* r_netid */
+	nlen = be32_to_cpup(p++);
+	r_netid = p;
+	p += XDR_QUADLEN(nlen);
+
+	/* r_addr */
+	rlen = be32_to_cpup(p++);
+	r_addr = p;
+	p += XDR_QUADLEN(rlen);
+	*pp = p;
+
+	/* Check that netid is "tcp" */
+	if (nlen != 3 ||  memcmp((char *)r_netid, "tcp", 3)) {
+		dprintk("%s: ERROR: non ipv4 TCP r_netid\n", __func__);
+		goto out_err;
+	}
+
+	/* ipv6 length plus port is legal */
+	if (rlen > INET6_ADDRSTRLEN + 8) {
+		dprintk("%s Invalid address, length %d\n", __func__,
+			rlen);
+		goto out_err;
+	}
+	buf = kmalloc(rlen + 1, GFP_KERNEL);
+	buf[rlen] = '\0';
+	memcpy(buf, r_addr, rlen);
+
+	/* replace the port dots with dashes for the in4_pton() delimiter*/
+	for (i = 0; i < 2; i++) {
+		char *res = strrchr(buf, '.');
+		*res = '-';
+	}
+
+	/* Currently only support ipv4 address */
+	if (in4_pton(buf, rlen, (u8 *)&ip_addr, '-', &ipend) == 0) {
+		dprintk("%s: Only ipv4 addresses supported\n", __func__);
+		goto out_free;
+	}
+
+	/* port */
+	pstr = ipend;
+	sscanf(pstr, "-%d-%d", &tmp[0], &tmp[1]);
+	port = htons((tmp[0] << 8) | (tmp[1]));
+
+	ds = nfs4_pnfs_ds_add(inode, ip_addr, port);
+	dprintk("%s Decoded address and port %s\n", __func__, buf);
+out_free:
+	kfree(buf);
+out_err:
+	return ds;
+}
+
+/* Decode opaque device data and return the result */
+static struct nfs4_file_layout_dsaddr*
+decode_device(struct inode *ino, struct pnfs_device *pdev)
+{
+	int i, dummy;
+	u32 cnt, num;
+	u8 *indexp;
+	__be32 *p = (__be32 *)pdev->area, *indicesp;
+	struct nfs4_file_layout_dsaddr *dsaddr;
+
+	/* Get the stripe count (number of stripe index) */
+	cnt = be32_to_cpup(p++);
+	dprintk("%s stripe count  %d\n", __func__, cnt);
+	if (cnt > NFS4_PNFS_MAX_STRIPE_CNT) {
+		printk(KERN_WARNING "%s: stripe count %d greater than "
+		       "supported maximum %d\n", __func__,
+			cnt, NFS4_PNFS_MAX_STRIPE_CNT);
+		goto out_err;
+	}
+
+	/* Check the multipath list count */
+	indicesp = p;
+	p += XDR_QUADLEN(cnt << 2);
+	num = be32_to_cpup(p++);
+	dprintk("%s ds_num %u\n", __func__, num);
+	if (num > NFS4_PNFS_MAX_MULTI_CNT) {
+		printk(KERN_WARNING "%s: multipath count %d greater than "
+			"supported maximum %d\n", __func__,
+			num, NFS4_PNFS_MAX_MULTI_CNT);
+		goto out_err;
+	}
+	dsaddr = kzalloc(sizeof(*dsaddr) +
+			(sizeof(struct nfs4_pnfs_ds *) * (num - 1)),
+			GFP_KERNEL);
+	if (!dsaddr)
+		goto out_err;
+
+	dsaddr->stripe_indices = kzalloc(sizeof(u8) * cnt, GFP_KERNEL);
+	if (!dsaddr->stripe_indices)
+		goto out_err_free;
+
+	dsaddr->stripe_count = cnt;
+	dsaddr->ds_num = num;
+
+	memcpy(&dsaddr->deviceid.de_id, &pdev->dev_id, sizeof(pdev->dev_id));
+
+	/* Go back an read stripe indices */
+	p = indicesp;
+	indexp = &dsaddr->stripe_indices[0];
+	for (i = 0; i < dsaddr->stripe_count; i++) {
+		*indexp = be32_to_cpup(p++);
+		if (*indexp >= num)
+			goto out_err_free;
+		indexp++;
+	}
+	/* Skip already read multipath list count */
+	p++;
+
+	for (i = 0; i < dsaddr->ds_num; i++) {
+		int j;
+
+		dummy = be32_to_cpup(p++); /* multipath count */
+		if (dummy > 1) {
+			printk(KERN_WARNING
+			       "%s: Multipath count %d not supported, "
+			       "skipping all greater than 1\n", __func__,
+				dummy);
+		}
+		for (j = 0; j < dummy; j++) {
+			if (j == 0) {
+				dsaddr->ds_list[i] = decode_and_add_ds(&p, ino);
+				if (dsaddr->ds_list[i] == NULL)
+					goto out_err_free;
+			} else {
+				u32 len;
+				/* skip extra multipath */
+				len = be32_to_cpup(p++);
+				p += XDR_QUADLEN(len);
+				len = be32_to_cpup(p++);
+				p += XDR_QUADLEN(len);
+				continue;
+			}
+		}
+	}
+	return dsaddr;
+
+out_err_free:
+	nfs4_fl_free_deviceid(dsaddr);
+out_err:
+	dprintk("%s ERROR: returning NULL\n", __func__);
+	return NULL;
+}
+
+/*
+ * Decode the opaque device specified in 'dev'
+ * and add it to the list of available devices.
+ * If the deviceid is already cached, nfs4_add_deviceid will return
+ * a pointer to the cached struct and throw away the new.
+ */
+static struct nfs4_file_layout_dsaddr*
+decode_and_add_device(struct inode *inode, struct pnfs_device *dev)
+{
+	struct nfs4_file_layout_dsaddr *dsaddr;
+	struct pnfs_deviceid_node *d;
+
+	dsaddr = decode_device(inode, dev);
+	if (!dsaddr) {
+		printk(KERN_WARNING "%s: Could not decode or add device\n",
+			__func__);
+		return NULL;
+	}
+
+	d = pnfs_add_deviceid(NFS_SERVER(inode)->nfs_client->cl_devid_cache,
+			      &dsaddr->deviceid);
+
+	return container_of(d, struct nfs4_file_layout_dsaddr, deviceid);
+}
+
+/*
+ * Retrieve the information for dev_id, add it to the list
+ * of available devices, and return it.
+ */
+struct nfs4_file_layout_dsaddr *
+get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id)
+{
+	struct pnfs_device *pdev = NULL;
+	u32 max_resp_sz;
+	int max_pages;
+	struct page **pages = NULL;
+	struct nfs4_file_layout_dsaddr *dsaddr = NULL;
+	int rc, i;
+	struct nfs_server *server = NFS_SERVER(inode);
+
+	/*
+	 * Use the session max response size as the basis for setting
+	 * GETDEVICEINFO's maxcount
+	 */
+	max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
+	max_pages = max_resp_sz >> PAGE_SHIFT;
+	dprintk("%s inode %p max_resp_sz %u max_pages %d\n",
+		__func__, inode, max_resp_sz, max_pages);
+
+	pdev = kzalloc(sizeof(struct pnfs_device), GFP_KERNEL);
+	if (pdev == NULL)
+		return NULL;
+
+	pages = kzalloc(max_pages * sizeof(struct page *), GFP_KERNEL);
+	if (pages == NULL) {
+		kfree(pdev);
+		return NULL;
+	}
+	for (i = 0; i < max_pages; i++) {
+		pages[i] = alloc_page(GFP_KERNEL);
+		if (!pages[i])
+			goto out_free;
+	}
+
+	/* set pdev->area */
+	pdev->area = vmap(pages, max_pages, VM_MAP, PAGE_KERNEL);
+	if (!pdev->area)
+		goto out_free;
+
+	memcpy(&pdev->dev_id, dev_id, sizeof(*dev_id));
+	pdev->layout_type = LAYOUT_NFSV4_1_FILES;
+	pdev->pages = pages;
+	pdev->pgbase = 0;
+	pdev->pglen = PAGE_SIZE * max_pages;
+	pdev->mincount = 0;
+
+	rc = nfs4_proc_getdeviceinfo(server, pdev);
+	dprintk("%s getdevice info returns %d\n", __func__, rc);
+	if (rc)
+		goto out_free;
+
+	/*
+	 * Found new device, need to decode it and then add it to the
+	 * list of known devices for this mountpoint.
+	 */
+	dsaddr = decode_and_add_device(inode, pdev);
+out_free:
+	if (pdev->area != NULL)
+		vunmap(pdev->area);
+	for (i = 0; i < max_pages; i++)
+		__free_page(pages[i]);
+	kfree(pages);
+	kfree(pdev);
+	dprintk("<-- %s dsaddr %p\n", __func__, dsaddr);
+	return dsaddr;
+}
+
+struct nfs4_file_layout_dsaddr *
+nfs4_fl_find_get_deviceid(struct nfs_client *clp, struct nfs4_deviceid *id)
+{
+	struct pnfs_deviceid_node *d;
+
+	d = pnfs_find_get_deviceid(clp->cl_devid_cache, id);
+	return (d == NULL) ? NULL :
+		container_of(d, struct nfs4_file_layout_dsaddr, deviceid);
+}
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 089da5b5..32c8758 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -55,6 +55,7 @@
 #include "internal.h"
 #include "iostat.h"
 #include "callback.h"
+#include "pnfs.h"
 
 #define NFSDBG_FACILITY		NFSDBG_PROC
 
@@ -129,7 +130,8 @@
 			| FATTR4_WORD0_MAXREAD
 			| FATTR4_WORD0_MAXWRITE
 			| FATTR4_WORD0_LEASE_TIME,
-			0
+			FATTR4_WORD1_TIME_DELTA
+			| FATTR4_WORD1_FS_LAYOUT_TYPES
 };
 
 const u32 nfs4_fs_locations_bitmap[2] = {
@@ -255,9 +257,6 @@
 			nfs4_state_mark_reclaim_nograce(clp, state);
 			goto do_state_recovery;
 		case -NFS4ERR_STALE_STATEID:
-			if (state == NULL)
-				break;
-			nfs4_state_mark_reclaim_reboot(clp, state);
 		case -NFS4ERR_STALE_CLIENTID:
 		case -NFS4ERR_EXPIRED:
 			goto do_state_recovery;
@@ -334,10 +333,12 @@
  * Must be called while holding tbl->slot_tbl_lock
  */
 static void
-nfs4_free_slot(struct nfs4_slot_table *tbl, u8 free_slotid)
+nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *free_slot)
 {
+	int free_slotid = free_slot - tbl->slots;
 	int slotid = free_slotid;
 
+	BUG_ON(slotid < 0 || slotid >= NFS4_MAX_SLOT_TABLE);
 	/* clear used bit in bitmap */
 	__clear_bit(slotid, tbl->used_slots);
 
@@ -379,7 +380,7 @@
 	struct nfs4_slot_table *tbl;
 
 	tbl = &res->sr_session->fc_slot_table;
-	if (res->sr_slotid == NFS4_MAX_SLOT_TABLE) {
+	if (!res->sr_slot) {
 		/* just wake up the next guy waiting since
 		 * we may have not consumed a slot after all */
 		dprintk("%s: No slot\n", __func__);
@@ -387,17 +388,15 @@
 	}
 
 	spin_lock(&tbl->slot_tbl_lock);
-	nfs4_free_slot(tbl, res->sr_slotid);
+	nfs4_free_slot(tbl, res->sr_slot);
 	nfs41_check_drain_session_complete(res->sr_session);
 	spin_unlock(&tbl->slot_tbl_lock);
-	res->sr_slotid = NFS4_MAX_SLOT_TABLE;
+	res->sr_slot = NULL;
 }
 
 static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res)
 {
 	unsigned long timestamp;
-	struct nfs4_slot_table *tbl;
-	struct nfs4_slot *slot;
 	struct nfs_client *clp;
 
 	/*
@@ -410,17 +409,14 @@
 		res->sr_status = NFS_OK;
 
 	/* -ERESTARTSYS can result in skipping nfs41_sequence_setup */
-	if (res->sr_slotid == NFS4_MAX_SLOT_TABLE)
+	if (!res->sr_slot)
 		goto out;
 
-	tbl = &res->sr_session->fc_slot_table;
-	slot = tbl->slots + res->sr_slotid;
-
 	/* Check the SEQUENCE operation status */
 	switch (res->sr_status) {
 	case 0:
 		/* Update the slot's sequence and clientid lease timer */
-		++slot->seq_nr;
+		++res->sr_slot->seq_nr;
 		timestamp = res->sr_renewal_time;
 		clp = res->sr_session->clp;
 		do_renew_lease(clp, timestamp);
@@ -433,12 +429,14 @@
 		 * returned NFS4ERR_DELAY as per Section 2.10.6.2
 		 * of RFC5661.
 		 */
-		dprintk("%s: slot=%d seq=%d: Operation in progress\n",
-				__func__, res->sr_slotid, slot->seq_nr);
+		dprintk("%s: slot=%ld seq=%d: Operation in progress\n",
+			__func__,
+			res->sr_slot - res->sr_session->fc_slot_table.slots,
+			res->sr_slot->seq_nr);
 		goto out_retry;
 	default:
 		/* Just update the slot sequence no. */
-		++slot->seq_nr;
+		++res->sr_slot->seq_nr;
 	}
 out:
 	/* The session may be reset by one of the error handlers. */
@@ -505,10 +503,9 @@
 
 	dprintk("--> %s\n", __func__);
 	/* slot already allocated? */
-	if (res->sr_slotid != NFS4_MAX_SLOT_TABLE)
+	if (res->sr_slot != NULL)
 		return 0;
 
-	res->sr_slotid = NFS4_MAX_SLOT_TABLE;
 	tbl = &session->fc_slot_table;
 
 	spin_lock(&tbl->slot_tbl_lock);
@@ -550,7 +547,7 @@
 	dprintk("<-- %s slotid=%d seqid=%d\n", __func__, slotid, slot->seq_nr);
 
 	res->sr_session = session;
-	res->sr_slotid = slotid;
+	res->sr_slot = slot;
 	res->sr_renewal_time = jiffies;
 	res->sr_status_flags = 0;
 	/*
@@ -576,8 +573,9 @@
 		goto out;
 	}
 
-	dprintk("--> %s clp %p session %p sr_slotid %d\n",
-		__func__, session->clp, session, res->sr_slotid);
+	dprintk("--> %s clp %p session %p sr_slot %ld\n",
+		__func__, session->clp, session, res->sr_slot ?
+			res->sr_slot - session->fc_slot_table.slots : -1);
 
 	ret = nfs41_setup_sequence(session, args, res, cache_reply,
 				   task);
@@ -650,7 +648,7 @@
 		.callback_data = &data
 	};
 
-	res->sr_slotid = NFS4_MAX_SLOT_TABLE;
+	res->sr_slot = NULL;
 	if (privileged)
 		task_setup.callback_ops = &nfs41_call_priv_sync_ops;
 	task = rpc_run_task(&task_setup);
@@ -735,7 +733,6 @@
 	p->o_res.server = p->o_arg.server;
 	nfs_fattr_init(&p->f_attr);
 	nfs_fattr_init(&p->dir_attr);
-	p->o_res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
 }
 
 static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path,
@@ -1120,6 +1117,7 @@
 	clear_bit(NFS_DELEGATED_STATE, &state->flags);
 	smp_rmb();
 	if (state->n_rdwr != 0) {
+		clear_bit(NFS_O_RDWR_STATE, &state->flags);
 		ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE, &newstate);
 		if (ret != 0)
 			return ret;
@@ -1127,6 +1125,7 @@
 			return -ESTALE;
 	}
 	if (state->n_wronly != 0) {
+		clear_bit(NFS_O_WRONLY_STATE, &state->flags);
 		ret = nfs4_open_recover_helper(opendata, FMODE_WRITE, &newstate);
 		if (ret != 0)
 			return ret;
@@ -1134,6 +1133,7 @@
 			return -ESTALE;
 	}
 	if (state->n_rdonly != 0) {
+		clear_bit(NFS_O_RDONLY_STATE, &state->flags);
 		ret = nfs4_open_recover_helper(opendata, FMODE_READ, &newstate);
 		if (ret != 0)
 			return ret;
@@ -1188,7 +1188,7 @@
 	int err;
 	do {
 		err = _nfs4_do_open_reclaim(ctx, state);
-		if (err != -NFS4ERR_DELAY && err != -EKEYEXPIRED)
+		if (err != -NFS4ERR_DELAY)
 			break;
 		nfs4_handle_exception(server, err, &exception);
 	} while (exception.retry);
@@ -1258,6 +1258,13 @@
 			case -NFS4ERR_ADMIN_REVOKED:
 			case -NFS4ERR_BAD_STATEID:
 				nfs4_state_mark_reclaim_nograce(server->nfs_client, state);
+			case -EKEYEXPIRED:
+				/*
+				 * User RPCSEC_GSS context has expired.
+				 * We cannot recover this stateid now, so
+				 * skip it and allow recovery thread to
+				 * proceed.
+				 */
 			case -ENOMEM:
 				err = 0;
 				goto out;
@@ -1605,7 +1612,6 @@
 			goto out;
 		case -NFS4ERR_GRACE:
 		case -NFS4ERR_DELAY:
-		case -EKEYEXPIRED:
 			nfs4_handle_exception(server, err, &exception);
 			err = 0;
 		}
@@ -1975,7 +1981,6 @@
 	calldata->res.fattr = &calldata->fattr;
 	calldata->res.seqid = calldata->arg.seqid;
 	calldata->res.server = server;
-	calldata->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
 	path_get(path);
 	calldata->path = *path;
 
@@ -1998,120 +2003,17 @@
 	return status;
 }
 
-static int nfs4_intent_set_file(struct nameidata *nd, struct path *path, struct nfs4_state *state, fmode_t fmode)
+static struct inode *
+nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags, struct iattr *attr)
 {
-	struct file *filp;
-	int ret;
-
-	/* If the open_intent is for execute, we have an extra check to make */
-	if (fmode & FMODE_EXEC) {
-		ret = nfs_may_open(state->inode,
-				state->owner->so_cred,
-				nd->intent.open.flags);
-		if (ret < 0)
-			goto out_close;
-	}
-	filp = lookup_instantiate_filp(nd, path->dentry, NULL);
-	if (!IS_ERR(filp)) {
-		struct nfs_open_context *ctx;
-		ctx = nfs_file_open_context(filp);
-		ctx->state = state;
-		return 0;
-	}
-	ret = PTR_ERR(filp);
-out_close:
-	nfs4_close_sync(path, state, fmode & (FMODE_READ|FMODE_WRITE));
-	return ret;
-}
-
-struct dentry *
-nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
-{
-	struct path path = {
-		.mnt = nd->path.mnt,
-		.dentry = dentry,
-	};
-	struct dentry *parent;
-	struct iattr attr;
-	struct rpc_cred *cred;
 	struct nfs4_state *state;
-	struct dentry *res;
-	int open_flags = nd->intent.open.flags;
-	fmode_t fmode = open_flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC);
 
-	if (nd->flags & LOOKUP_CREATE) {
-		attr.ia_mode = nd->intent.open.create_mode;
-		attr.ia_valid = ATTR_MODE;
-		if (!IS_POSIXACL(dir))
-			attr.ia_mode &= ~current_umask();
-	} else {
-		open_flags &= ~O_EXCL;
-		attr.ia_valid = 0;
-		BUG_ON(open_flags & O_CREAT);
-	}
-
-	cred = rpc_lookup_cred();
-	if (IS_ERR(cred))
-		return (struct dentry *)cred;
-	parent = dentry->d_parent;
 	/* Protect against concurrent sillydeletes */
-	nfs_block_sillyrename(parent);
-	state = nfs4_do_open(dir, &path, fmode, open_flags, &attr, cred);
-	put_rpccred(cred);
-	if (IS_ERR(state)) {
-		if (PTR_ERR(state) == -ENOENT) {
-			d_add(dentry, NULL);
-			nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
-		}
-		nfs_unblock_sillyrename(parent);
-		return (struct dentry *)state;
-	}
-	res = d_add_unique(dentry, igrab(state->inode));
-	if (res != NULL)
-		path.dentry = res;
-	nfs_set_verifier(path.dentry, nfs_save_change_attribute(dir));
-	nfs_unblock_sillyrename(parent);
-	nfs4_intent_set_file(nd, &path, state, fmode);
-	return res;
-}
-
-int
-nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, struct nameidata *nd)
-{
-	struct path path = {
-		.mnt = nd->path.mnt,
-		.dentry = dentry,
-	};
-	struct rpc_cred *cred;
-	struct nfs4_state *state;
-	fmode_t fmode = openflags & (FMODE_READ | FMODE_WRITE);
-
-	cred = rpc_lookup_cred();
-	if (IS_ERR(cred))
-		return PTR_ERR(cred);
-	state = nfs4_do_open(dir, &path, fmode, openflags, NULL, cred);
-	put_rpccred(cred);
-	if (IS_ERR(state)) {
-		switch (PTR_ERR(state)) {
-			case -EPERM:
-			case -EACCES:
-			case -EDQUOT:
-			case -ENOSPC:
-			case -EROFS:
-				return PTR_ERR(state);
-			default:
-				goto out_drop;
-		}
-	}
-	if (state->inode == dentry->d_inode) {
-		nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
-		nfs4_intent_set_file(nd, &path, state, fmode);
-		return 1;
-	}
-	nfs4_close_sync(&path, state, fmode);
-out_drop:
-	d_drop(dentry);
-	return 0;
+	state = nfs4_do_open(dir, &ctx->path, ctx->mode, open_flags, attr, ctx->cred);
+	if (IS_ERR(state))
+		return ERR_CAST(state);
+	ctx->state = state;
+	return igrab(state->inode);
 }
 
 static void nfs4_close_context(struct nfs_open_context *ctx, int is_sync)
@@ -2568,36 +2470,34 @@
 
 static int
 nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
-                 int flags, struct nameidata *nd)
+                 int flags, struct nfs_open_context *ctx)
 {
-	struct path path = {
-		.mnt = nd->path.mnt,
+	struct path my_path = {
 		.dentry = dentry,
 	};
+	struct path *path = &my_path;
 	struct nfs4_state *state;
-	struct rpc_cred *cred;
-	fmode_t fmode = flags & (FMODE_READ | FMODE_WRITE);
+	struct rpc_cred *cred = NULL;
+	fmode_t fmode = 0;
 	int status = 0;
 
-	cred = rpc_lookup_cred();
-	if (IS_ERR(cred)) {
-		status = PTR_ERR(cred);
-		goto out;
+	if (ctx != NULL) {
+		cred = ctx->cred;
+		path = &ctx->path;
+		fmode = ctx->mode;
 	}
-	state = nfs4_do_open(dir, &path, fmode, flags, sattr, cred);
+	state = nfs4_do_open(dir, path, fmode, flags, sattr, cred);
 	d_drop(dentry);
 	if (IS_ERR(state)) {
 		status = PTR_ERR(state);
-		goto out_putcred;
+		goto out;
 	}
 	d_add(dentry, igrab(state->inode));
 	nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
-	if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0)
-		status = nfs4_intent_set_file(nd, &path, state, fmode);
+	if (ctx != NULL)
+		ctx->state = state;
 	else
-		nfs4_close_sync(&path, state, fmode);
-out_putcred:
-	put_rpccred(cred);
+		nfs4_close_sync(path, state, fmode);
 out:
 	return status;
 }
@@ -2655,6 +2555,7 @@
 
 	args->bitmask = server->cache_consistency_bitmask;
 	res->server = server;
+	res->seq_res.sr_slot = NULL;
 	msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE];
 }
 
@@ -2671,18 +2572,46 @@
 	return 1;
 }
 
+static void nfs4_proc_rename_setup(struct rpc_message *msg, struct inode *dir)
+{
+	struct nfs_server *server = NFS_SERVER(dir);
+	struct nfs_renameargs *arg = msg->rpc_argp;
+	struct nfs_renameres *res = msg->rpc_resp;
+
+	msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME];
+	arg->bitmask = server->attr_bitmask;
+	res->server = server;
+}
+
+static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
+				 struct inode *new_dir)
+{
+	struct nfs_renameres *res = task->tk_msg.rpc_resp;
+
+	if (!nfs4_sequence_done(task, &res->seq_res))
+		return 0;
+	if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN)
+		return 0;
+
+	update_changeattr(old_dir, &res->old_cinfo);
+	nfs_post_op_update_inode(old_dir, res->old_fattr);
+	update_changeattr(new_dir, &res->new_cinfo);
+	nfs_post_op_update_inode(new_dir, res->new_fattr);
+	return 1;
+}
+
 static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
 		struct inode *new_dir, struct qstr *new_name)
 {
 	struct nfs_server *server = NFS_SERVER(old_dir);
-	struct nfs4_rename_arg arg = {
+	struct nfs_renameargs arg = {
 		.old_dir = NFS_FH(old_dir),
 		.new_dir = NFS_FH(new_dir),
 		.old_name = old_name,
 		.new_name = new_name,
 		.bitmask = server->attr_bitmask,
 	};
-	struct nfs4_rename_res res = {
+	struct nfs_renameres res = {
 		.server = server,
 	};
 	struct rpc_message msg = {
@@ -2896,15 +2825,16 @@
 }
 
 static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
-                  u64 cookie, struct page *page, unsigned int count, int plus)
+		u64 cookie, struct page **pages, unsigned int count, int plus)
 {
 	struct inode		*dir = dentry->d_inode;
 	struct nfs4_readdir_arg args = {
 		.fh = NFS_FH(dir),
-		.pages = &page,
+		.pages = pages,
 		.pgbase = 0,
 		.count = count,
 		.bitmask = NFS_SERVER(dentry->d_inode)->attr_bitmask,
+		.plus = plus,
 	};
 	struct nfs4_readdir_res res;
 	struct rpc_message msg = {
@@ -2932,14 +2862,14 @@
 }
 
 static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
-                  u64 cookie, struct page *page, unsigned int count, int plus)
+		u64 cookie, struct page **pages, unsigned int count, int plus)
 {
 	struct nfs4_exception exception = { };
 	int err;
 	do {
 		err = nfs4_handle_exception(NFS_SERVER(dentry->d_inode),
 				_nfs4_proc_readdir(dentry, cred, cookie,
-					page, count, plus),
+					pages, count, plus),
 				&exception);
 	} while (exception.retry);
 	return err;
@@ -3490,9 +3420,6 @@
 			nfs4_state_mark_reclaim_nograce(clp, state);
 			goto do_state_recovery;
 		case -NFS4ERR_STALE_STATEID:
-			if (state == NULL)
-				break;
-			nfs4_state_mark_reclaim_reboot(clp, state);
 		case -NFS4ERR_STALE_CLIENTID:
 		case -NFS4ERR_EXPIRED:
 			goto do_state_recovery;
@@ -3626,7 +3553,6 @@
 			case -NFS4ERR_RESOURCE:
 				/* The IBM lawyers misread another document! */
 			case -NFS4ERR_DELAY:
-			case -EKEYEXPIRED:
 				err = nfs4_delay(clp->cl_rpcclient, &timeout);
 		}
 	} while (err == 0);
@@ -3721,7 +3647,6 @@
 	memcpy(&data->stateid, stateid, sizeof(data->stateid));
 	data->res.fattr = &data->fattr;
 	data->res.server = server;
-	data->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
 	nfs_fattr_init(data->res.fattr);
 	data->timestamp = jiffies;
 	data->rpc_status = 0;
@@ -3874,7 +3799,6 @@
 	p->arg.fl = &p->fl;
 	p->arg.seqid = seqid;
 	p->res.seqid = seqid;
-	p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
 	p->arg.stateid = &lsp->ls_stateid;
 	p->lsp = lsp;
 	atomic_inc(&lsp->ls_count);
@@ -4054,7 +3978,6 @@
 	p->arg.lock_owner.clientid = server->nfs_client->cl_clientid;
 	p->arg.lock_owner.id = lsp->ls_id.id;
 	p->res.lock_seqid = p->arg.lock_seqid;
-	p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
 	p->lsp = lsp;
 	p->server = server;
 	atomic_inc(&lsp->ls_count);
@@ -4241,7 +4164,7 @@
 		if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0)
 			return 0;
 		err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_RECLAIM);
-		if (err != -NFS4ERR_DELAY && err != -EKEYEXPIRED)
+		if (err != -NFS4ERR_DELAY)
 			break;
 		nfs4_handle_exception(server, err, &exception);
 	} while (exception.retry);
@@ -4266,7 +4189,6 @@
 			goto out;
 		case -NFS4ERR_GRACE:
 		case -NFS4ERR_DELAY:
-		case -EKEYEXPIRED:
 			nfs4_handle_exception(server, err, &exception);
 			err = 0;
 		}
@@ -4412,13 +4334,21 @@
 				nfs4_state_mark_reclaim_nograce(server->nfs_client, state);
 				err = 0;
 				goto out;
+			case -EKEYEXPIRED:
+				/*
+				 * User RPCSEC_GSS context has expired.
+				 * We cannot recover this stateid now, so
+				 * skip it and allow recovery thread to
+				 * proceed.
+				 */
+				err = 0;
+				goto out;
 			case -ENOMEM:
 			case -NFS4ERR_DENIED:
 				/* kill_proc(fl->fl_pid, SIGLOST, 1); */
 				err = 0;
 				goto out;
 			case -NFS4ERR_DELAY:
-			case -EKEYEXPIRED:
 				break;
 		}
 		err = nfs4_handle_exception(server, err, &exception);
@@ -4647,7 +4577,6 @@
 	switch (task->tk_status) {
 	case -NFS4ERR_DELAY:
 	case -NFS4ERR_GRACE:
-	case -EKEYEXPIRED:
 		dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status);
 		rpc_delay(task, NFS4_POLL_RETRY_MIN);
 		task->tk_status = 0;
@@ -4687,7 +4616,6 @@
 	};
 	int status;
 
-	res.lr_seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
 	dprintk("--> %s\n", __func__);
 	task = rpc_run_task(&task_setup);
 
@@ -4914,49 +4842,56 @@
 		args->bc_attrs.max_reqs);
 }
 
-static int _verify_channel_attr(char *chan, char *attr_name, u32 sent, u32 rcvd)
+static int nfs4_verify_fore_channel_attrs(struct nfs41_create_session_args *args, struct nfs4_session *session)
 {
-	if (rcvd <= sent)
-		return 0;
-	printk(KERN_WARNING "%s: Session INVALID: %s channel %s increased. "
-		"sent=%u rcvd=%u\n", __func__, chan, attr_name, sent, rcvd);
-	return -EINVAL;
+	struct nfs4_channel_attrs *sent = &args->fc_attrs;
+	struct nfs4_channel_attrs *rcvd = &session->fc_attrs;
+
+	if (rcvd->headerpadsz > sent->headerpadsz)
+		return -EINVAL;
+	if (rcvd->max_resp_sz > sent->max_resp_sz)
+		return -EINVAL;
+	/*
+	 * Our requested max_ops is the minimum we need; we're not
+	 * prepared to break up compounds into smaller pieces than that.
+	 * So, no point even trying to continue if the server won't
+	 * cooperate:
+	 */
+	if (rcvd->max_ops < sent->max_ops)
+		return -EINVAL;
+	if (rcvd->max_reqs == 0)
+		return -EINVAL;
+	return 0;
 }
 
-#define _verify_fore_channel_attr(_name_) \
-	_verify_channel_attr("fore", #_name_, \
-			     args->fc_attrs._name_, \
-			     session->fc_attrs._name_)
+static int nfs4_verify_back_channel_attrs(struct nfs41_create_session_args *args, struct nfs4_session *session)
+{
+	struct nfs4_channel_attrs *sent = &args->bc_attrs;
+	struct nfs4_channel_attrs *rcvd = &session->bc_attrs;
 
-#define _verify_back_channel_attr(_name_) \
-	_verify_channel_attr("back", #_name_, \
-			     args->bc_attrs._name_, \
-			     session->bc_attrs._name_)
+	if (rcvd->max_rqst_sz > sent->max_rqst_sz)
+		return -EINVAL;
+	if (rcvd->max_resp_sz < sent->max_resp_sz)
+		return -EINVAL;
+	if (rcvd->max_resp_sz_cached > sent->max_resp_sz_cached)
+		return -EINVAL;
+	/* These would render the backchannel useless: */
+	if (rcvd->max_ops  == 0)
+		return -EINVAL;
+	if (rcvd->max_reqs == 0)
+		return -EINVAL;
+	return 0;
+}
 
-/*
- * The server is not allowed to increase the fore channel header pad size,
- * maximum response size, or maximum number of operations.
- *
- * The back channel attributes are only negotiatied down: We send what the
- * (back channel) server insists upon.
- */
 static int nfs4_verify_channel_attrs(struct nfs41_create_session_args *args,
 				     struct nfs4_session *session)
 {
-	int ret = 0;
+	int ret;
 
-	ret |= _verify_fore_channel_attr(headerpadsz);
-	ret |= _verify_fore_channel_attr(max_resp_sz);
-	ret |= _verify_fore_channel_attr(max_ops);
-
-	ret |= _verify_back_channel_attr(headerpadsz);
-	ret |= _verify_back_channel_attr(max_rqst_sz);
-	ret |= _verify_back_channel_attr(max_resp_sz);
-	ret |= _verify_back_channel_attr(max_resp_sz_cached);
-	ret |= _verify_back_channel_attr(max_ops);
-	ret |= _verify_back_channel_attr(max_reqs);
-
-	return ret;
+	ret = nfs4_verify_fore_channel_attrs(args, session);
+	if (ret)
+		return ret;
+	return nfs4_verify_back_channel_attrs(args, session);
 }
 
 static int _nfs4_proc_create_session(struct nfs_client *clp)
@@ -5111,7 +5046,6 @@
 {
 	switch(task->tk_status) {
 	case -NFS4ERR_DELAY:
-	case -EKEYEXPIRED:
 		rpc_delay(task, NFS4_POLL_RETRY_MAX);
 		return -EAGAIN;
 	default:
@@ -5180,12 +5114,11 @@
 
 	if (!atomic_inc_not_zero(&clp->cl_count))
 		return ERR_PTR(-EIO);
-	calldata = kmalloc(sizeof(*calldata), GFP_NOFS);
+	calldata = kzalloc(sizeof(*calldata), GFP_NOFS);
 	if (calldata == NULL) {
 		nfs_put_client(clp);
 		return ERR_PTR(-ENOMEM);
 	}
-	calldata->res.sr_slotid = NFS4_MAX_SLOT_TABLE;
 	msg.rpc_argp = &calldata->args;
 	msg.rpc_resp = &calldata->res;
 	calldata->clp = clp;
@@ -5254,7 +5187,6 @@
 	case -NFS4ERR_WRONG_CRED: /* What to do here? */
 		break;
 	case -NFS4ERR_DELAY:
-	case -EKEYEXPIRED:
 		rpc_delay(task, NFS4_POLL_RETRY_MAX);
 		return -EAGAIN;
 	default:
@@ -5317,7 +5249,6 @@
 		goto out;
 	calldata->clp = clp;
 	calldata->arg.one_fs = 0;
-	calldata->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
 
 	msg.rpc_argp = &calldata->arg;
 	msg.rpc_resp = &calldata->res;
@@ -5333,6 +5264,147 @@
 	dprintk("<-- %s status=%d\n", __func__, status);
 	return status;
 }
+
+static void
+nfs4_layoutget_prepare(struct rpc_task *task, void *calldata)
+{
+	struct nfs4_layoutget *lgp = calldata;
+	struct inode *ino = lgp->args.inode;
+	struct nfs_server *server = NFS_SERVER(ino);
+
+	dprintk("--> %s\n", __func__);
+	if (nfs4_setup_sequence(server, &lgp->args.seq_args,
+				&lgp->res.seq_res, 0, task))
+		return;
+	rpc_call_start(task);
+}
+
+static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
+{
+	struct nfs4_layoutget *lgp = calldata;
+	struct nfs_server *server = NFS_SERVER(lgp->args.inode);
+
+	dprintk("--> %s\n", __func__);
+
+	if (!nfs4_sequence_done(task, &lgp->res.seq_res))
+		return;
+
+	switch (task->tk_status) {
+	case 0:
+		break;
+	case -NFS4ERR_LAYOUTTRYLATER:
+	case -NFS4ERR_RECALLCONFLICT:
+		task->tk_status = -NFS4ERR_DELAY;
+		/* Fall through */
+	default:
+		if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) {
+			rpc_restart_call_prepare(task);
+			return;
+		}
+	}
+	lgp->status = task->tk_status;
+	dprintk("<-- %s\n", __func__);
+}
+
+static void nfs4_layoutget_release(void *calldata)
+{
+	struct nfs4_layoutget *lgp = calldata;
+
+	dprintk("--> %s\n", __func__);
+	put_layout_hdr(lgp->args.inode);
+	if (lgp->res.layout.buf != NULL)
+		free_page((unsigned long) lgp->res.layout.buf);
+	put_nfs_open_context(lgp->args.ctx);
+	kfree(calldata);
+	dprintk("<-- %s\n", __func__);
+}
+
+static const struct rpc_call_ops nfs4_layoutget_call_ops = {
+	.rpc_call_prepare = nfs4_layoutget_prepare,
+	.rpc_call_done = nfs4_layoutget_done,
+	.rpc_release = nfs4_layoutget_release,
+};
+
+int nfs4_proc_layoutget(struct nfs4_layoutget *lgp)
+{
+	struct nfs_server *server = NFS_SERVER(lgp->args.inode);
+	struct rpc_task *task;
+	struct rpc_message msg = {
+		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET],
+		.rpc_argp = &lgp->args,
+		.rpc_resp = &lgp->res,
+	};
+	struct rpc_task_setup task_setup_data = {
+		.rpc_client = server->client,
+		.rpc_message = &msg,
+		.callback_ops = &nfs4_layoutget_call_ops,
+		.callback_data = lgp,
+		.flags = RPC_TASK_ASYNC,
+	};
+	int status = 0;
+
+	dprintk("--> %s\n", __func__);
+
+	lgp->res.layout.buf = (void *)__get_free_page(GFP_NOFS);
+	if (lgp->res.layout.buf == NULL) {
+		nfs4_layoutget_release(lgp);
+		return -ENOMEM;
+	}
+
+	lgp->res.seq_res.sr_slot = NULL;
+	task = rpc_run_task(&task_setup_data);
+	if (IS_ERR(task))
+		return PTR_ERR(task);
+	status = nfs4_wait_for_completion_rpc_task(task);
+	if (status != 0)
+		goto out;
+	status = lgp->status;
+	if (status != 0)
+		goto out;
+	status = pnfs_layout_process(lgp);
+out:
+	rpc_put_task(task);
+	dprintk("<-- %s status=%d\n", __func__, status);
+	return status;
+}
+
+static int
+_nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev)
+{
+	struct nfs4_getdeviceinfo_args args = {
+		.pdev = pdev,
+	};
+	struct nfs4_getdeviceinfo_res res = {
+		.pdev = pdev,
+	};
+	struct rpc_message msg = {
+		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETDEVICEINFO],
+		.rpc_argp = &args,
+		.rpc_resp = &res,
+	};
+	int status;
+
+	dprintk("--> %s\n", __func__);
+	status = nfs4_call_sync(server, &msg, &args, &res, 0);
+	dprintk("<-- %s status=%d\n", __func__, status);
+
+	return status;
+}
+
+int nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev)
+{
+	struct nfs4_exception exception = { };
+	int err;
+
+	do {
+		err = nfs4_handle_exception(server,
+					_nfs4_proc_getdeviceinfo(server, pdev),
+					&exception);
+	} while (exception.retry);
+	return err;
+}
+EXPORT_SYMBOL_GPL(nfs4_proc_getdeviceinfo);
+
 #endif /* CONFIG_NFS_V4_1 */
 
 struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = {
@@ -5443,6 +5515,8 @@
 	.unlink_setup	= nfs4_proc_unlink_setup,
 	.unlink_done	= nfs4_proc_unlink_done,
 	.rename		= nfs4_proc_rename,
+	.rename_setup	= nfs4_proc_rename_setup,
+	.rename_done	= nfs4_proc_rename_done,
 	.link		= nfs4_proc_link,
 	.symlink	= nfs4_proc_symlink,
 	.mkdir		= nfs4_proc_mkdir,
@@ -5463,6 +5537,7 @@
 	.lock		= nfs4_proc_lock,
 	.clear_acl_cache = nfs4_zap_acl_attr,
 	.close_context  = nfs4_close_context,
+	.open_context	= nfs4_atomic_open,
 };
 
 /*
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 96524c5..f575a31 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -46,6 +46,7 @@
 #include <linux/kthread.h>
 #include <linux/module.h>
 #include <linux/random.h>
+#include <linux/ratelimit.h>
 #include <linux/workqueue.h>
 #include <linux/bitops.h>
 
@@ -53,6 +54,7 @@
 #include "callback.h"
 #include "delegation.h"
 #include "internal.h"
+#include "pnfs.h"
 
 #define OPENOWNER_POOL_SIZE	8
 
@@ -1063,6 +1065,14 @@
 				/* Mark the file as being 'closed' */
 				state->state = 0;
 				break;
+			case -EKEYEXPIRED:
+				/*
+				 * User RPCSEC_GSS context has expired.
+				 * We cannot recover this stateid now, so
+				 * skip it and allow recovery thread to
+				 * proceed.
+				 */
+				break;
 			case -NFS4ERR_ADMIN_REVOKED:
 			case -NFS4ERR_STALE_STATEID:
 			case -NFS4ERR_BAD_STATEID:
@@ -1138,16 +1148,14 @@
 		(void)ops->reclaim_complete(clp);
 }
 
-static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp)
+static int nfs4_state_clear_reclaim_reboot(struct nfs_client *clp)
 {
 	struct nfs4_state_owner *sp;
 	struct rb_node *pos;
 	struct nfs4_state *state;
 
 	if (!test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state))
-		return;
-
-	nfs4_reclaim_complete(clp, clp->cl_mvops->reboot_recovery_ops);
+		return 0;
 
 	for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) {
 		sp = rb_entry(pos, struct nfs4_state_owner, so_client_node);
@@ -1161,6 +1169,14 @@
 	}
 
 	nfs_delegation_reap_unclaimed(clp);
+	return 1;
+}
+
+static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp)
+{
+	if (!nfs4_state_clear_reclaim_reboot(clp))
+		return;
+	nfs4_reclaim_complete(clp, clp->cl_mvops->reboot_recovery_ops);
 }
 
 static void nfs_delegation_clear_all(struct nfs_client *clp)
@@ -1175,6 +1191,14 @@
 	nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_nograce);
 }
 
+static void nfs4_warn_keyexpired(const char *s)
+{
+	printk_ratelimited(KERN_WARNING "Error: state manager"
+			" encountered RPCSEC_GSS session"
+			" expired against NFSv4 server %s.\n",
+			s);
+}
+
 static int nfs4_recovery_handle_error(struct nfs_client *clp, int error)
 {
 	switch (error) {
@@ -1187,7 +1211,7 @@
 		case -NFS4ERR_STALE_CLIENTID:
 		case -NFS4ERR_LEASE_MOVED:
 			set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
-			nfs4_state_end_reclaim_reboot(clp);
+			nfs4_state_clear_reclaim_reboot(clp);
 			nfs4_state_start_reclaim_reboot(clp);
 			break;
 		case -NFS4ERR_EXPIRED:
@@ -1204,6 +1228,10 @@
 			set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state);
 			/* Zero session reset errors */
 			return 0;
+		case -EKEYEXPIRED:
+			/* Nothing we can do */
+			nfs4_warn_keyexpired(clp->cl_hostname);
+			return 0;
 	}
 	return error;
 }
@@ -1414,9 +1442,10 @@
 		case -NFS4ERR_DELAY:
 		case -NFS4ERR_CLID_INUSE:
 		case -EAGAIN:
-		case -EKEYEXPIRED:
 			break;
 
+		case -EKEYEXPIRED:
+			nfs4_warn_keyexpired(clp->cl_hostname);
 		case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery
 					 * in nfs4_exchange_id */
 		default:
@@ -1447,6 +1476,7 @@
 			}
 			clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state);
 			set_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state);
+			pnfs_destroy_all_layouts(clp);
 		}
 
 		if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) {
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 08ef912..f313c4c 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -52,6 +52,7 @@
 #include <linux/nfs_idmap.h>
 #include "nfs4_fs.h"
 #include "internal.h"
+#include "pnfs.h"
 
 #define NFSDBG_FACILITY		NFSDBG_XDR
 
@@ -310,6 +311,19 @@
 				XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5)
 #define encode_reclaim_complete_maxsz	(op_encode_hdr_maxsz + 4)
 #define decode_reclaim_complete_maxsz	(op_decode_hdr_maxsz + 4)
+#define encode_getdeviceinfo_maxsz (op_encode_hdr_maxsz + 4 + \
+				XDR_QUADLEN(NFS4_DEVICEID4_SIZE))
+#define decode_getdeviceinfo_maxsz (op_decode_hdr_maxsz + \
+				1 /* layout type */ + \
+				1 /* opaque devaddr4 length */ + \
+				  /* devaddr4 payload is read into page */ \
+				1 /* notification bitmap length */ + \
+				1 /* notification bitmap */)
+#define encode_layoutget_maxsz	(op_encode_hdr_maxsz + 10 + \
+				encode_stateid_maxsz)
+#define decode_layoutget_maxsz	(op_decode_hdr_maxsz + 8 + \
+				decode_stateid_maxsz + \
+				XDR_QUADLEN(PNFS_LAYOUT_MAXSIZE))
 #else /* CONFIG_NFS_V4_1 */
 #define encode_sequence_maxsz	0
 #define decode_sequence_maxsz	0
@@ -699,6 +713,20 @@
 #define NFS4_dec_reclaim_complete_sz	(compound_decode_hdr_maxsz + \
 					 decode_sequence_maxsz + \
 					 decode_reclaim_complete_maxsz)
+#define NFS4_enc_getdeviceinfo_sz (compound_encode_hdr_maxsz +    \
+				encode_sequence_maxsz +\
+				encode_getdeviceinfo_maxsz)
+#define NFS4_dec_getdeviceinfo_sz (compound_decode_hdr_maxsz +    \
+				decode_sequence_maxsz + \
+				decode_getdeviceinfo_maxsz)
+#define NFS4_enc_layoutget_sz	(compound_encode_hdr_maxsz + \
+				encode_sequence_maxsz + \
+				encode_putfh_maxsz +        \
+				encode_layoutget_maxsz)
+#define NFS4_dec_layoutget_sz	(compound_decode_hdr_maxsz + \
+				decode_sequence_maxsz + \
+				decode_putfh_maxsz +        \
+				decode_layoutget_maxsz)
 
 const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
 				      compound_encode_hdr_maxsz +
@@ -816,7 +844,7 @@
 	if (iap->ia_valid & ATTR_MODE)
 		len += 4;
 	if (iap->ia_valid & ATTR_UID) {
-		owner_namelen = nfs_map_uid_to_name(server->nfs_client, iap->ia_uid, owner_name);
+		owner_namelen = nfs_map_uid_to_name(server->nfs_client, iap->ia_uid, owner_name, IDMAP_NAMESZ);
 		if (owner_namelen < 0) {
 			dprintk("nfs: couldn't resolve uid %d to string\n",
 					iap->ia_uid);
@@ -828,7 +856,7 @@
 		len += 4 + (XDR_QUADLEN(owner_namelen) << 2);
 	}
 	if (iap->ia_valid & ATTR_GID) {
-		owner_grouplen = nfs_map_gid_to_group(server->nfs_client, iap->ia_gid, owner_group);
+		owner_grouplen = nfs_map_gid_to_group(server->nfs_client, iap->ia_gid, owner_group, IDMAP_NAMESZ);
 		if (owner_grouplen < 0) {
 			dprintk("nfs: couldn't resolve gid %d to string\n",
 					iap->ia_gid);
@@ -1385,24 +1413,35 @@
 
 static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr)
 {
-	uint32_t attrs[2] = {
-		FATTR4_WORD0_RDATTR_ERROR|FATTR4_WORD0_FILEID,
-		FATTR4_WORD1_MOUNTED_ON_FILEID,
-	};
+	uint32_t attrs[2] = {0, 0};
+	uint32_t dircount = readdir->count >> 1;
 	__be32 *p;
 
-	p = reserve_space(xdr, 12+NFS4_VERIFIER_SIZE+20);
-	*p++ = cpu_to_be32(OP_READDIR);
-	p = xdr_encode_hyper(p, readdir->cookie);
-	p = xdr_encode_opaque_fixed(p, readdir->verifier.data, NFS4_VERIFIER_SIZE);
-	*p++ = cpu_to_be32(readdir->count >> 1);  /* We're not doing readdirplus */
-	*p++ = cpu_to_be32(readdir->count);
-	*p++ = cpu_to_be32(2);
+	if (readdir->plus) {
+		attrs[0] |= FATTR4_WORD0_TYPE|FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE|
+			FATTR4_WORD0_FSID|FATTR4_WORD0_FILEHANDLE;
+		attrs[1] |= FATTR4_WORD1_MODE|FATTR4_WORD1_NUMLINKS|FATTR4_WORD1_OWNER|
+			FATTR4_WORD1_OWNER_GROUP|FATTR4_WORD1_RAWDEV|
+			FATTR4_WORD1_SPACE_USED|FATTR4_WORD1_TIME_ACCESS|
+			FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY;
+		dircount >>= 1;
+	}
+	attrs[0] |= FATTR4_WORD0_RDATTR_ERROR|FATTR4_WORD0_FILEID;
+	attrs[1] |= FATTR4_WORD1_MOUNTED_ON_FILEID;
 	/* Switch to mounted_on_fileid if the server supports it */
 	if (readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)
 		attrs[0] &= ~FATTR4_WORD0_FILEID;
 	else
 		attrs[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
+
+	p = reserve_space(xdr, 12+NFS4_VERIFIER_SIZE+20);
+	*p++ = cpu_to_be32(OP_READDIR);
+	p = xdr_encode_hyper(p, readdir->cookie);
+	p = xdr_encode_opaque_fixed(p, readdir->verifier.data, NFS4_VERIFIER_SIZE);
+	*p++ = cpu_to_be32(dircount);
+	*p++ = cpu_to_be32(readdir->count);
+	*p++ = cpu_to_be32(2);
+
 	*p++ = cpu_to_be32(attrs[0] & readdir->bitmask[0]);
 	*p = cpu_to_be32(attrs[1] & readdir->bitmask[1]);
 	hdr->nops++;
@@ -1726,6 +1765,58 @@
 #endif /* CONFIG_NFS_V4_1 */
 }
 
+#ifdef CONFIG_NFS_V4_1
+static void
+encode_getdeviceinfo(struct xdr_stream *xdr,
+		     const struct nfs4_getdeviceinfo_args *args,
+		     struct compound_hdr *hdr)
+{
+	__be32 *p;
+
+	p = reserve_space(xdr, 16 + NFS4_DEVICEID4_SIZE);
+	*p++ = cpu_to_be32(OP_GETDEVICEINFO);
+	p = xdr_encode_opaque_fixed(p, args->pdev->dev_id.data,
+				    NFS4_DEVICEID4_SIZE);
+	*p++ = cpu_to_be32(args->pdev->layout_type);
+	*p++ = cpu_to_be32(args->pdev->pglen);		/* gdia_maxcount */
+	*p++ = cpu_to_be32(0);				/* bitmap length 0 */
+	hdr->nops++;
+	hdr->replen += decode_getdeviceinfo_maxsz;
+}
+
+static void
+encode_layoutget(struct xdr_stream *xdr,
+		      const struct nfs4_layoutget_args *args,
+		      struct compound_hdr *hdr)
+{
+	nfs4_stateid stateid;
+	__be32 *p;
+
+	p = reserve_space(xdr, 44 + NFS4_STATEID_SIZE);
+	*p++ = cpu_to_be32(OP_LAYOUTGET);
+	*p++ = cpu_to_be32(0);     /* Signal layout available */
+	*p++ = cpu_to_be32(args->type);
+	*p++ = cpu_to_be32(args->range.iomode);
+	p = xdr_encode_hyper(p, args->range.offset);
+	p = xdr_encode_hyper(p, args->range.length);
+	p = xdr_encode_hyper(p, args->minlength);
+	pnfs_get_layout_stateid(&stateid, NFS_I(args->inode)->layout,
+				args->ctx->state);
+	p = xdr_encode_opaque_fixed(p, &stateid.data, NFS4_STATEID_SIZE);
+	*p = cpu_to_be32(args->maxcount);
+
+	dprintk("%s: 1st type:0x%x iomode:%d off:%lu len:%lu mc:%d\n",
+		__func__,
+		args->type,
+		args->range.iomode,
+		(unsigned long)args->range.offset,
+		(unsigned long)args->range.length,
+		args->maxcount);
+	hdr->nops++;
+	hdr->replen += decode_layoutget_maxsz;
+}
+#endif /* CONFIG_NFS_V4_1 */
+
 /*
  * END OF "GENERIC" ENCODE ROUTINES.
  */
@@ -1823,7 +1914,7 @@
 /*
  * Encode RENAME request
  */
-static int nfs4_xdr_enc_rename(struct rpc_rqst *req, __be32 *p, const struct nfs4_rename_arg *args)
+static int nfs4_xdr_enc_rename(struct rpc_rqst *req, __be32 *p, const struct nfs_renameargs *args)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
@@ -2543,6 +2634,51 @@
 	return 0;
 }
 
+/*
+ * Encode GETDEVICEINFO request
+ */
+static int nfs4_xdr_enc_getdeviceinfo(struct rpc_rqst *req, uint32_t *p,
+				      struct nfs4_getdeviceinfo_args *args)
+{
+	struct xdr_stream xdr;
+	struct compound_hdr hdr = {
+		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
+	};
+
+	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+	encode_compound_hdr(&xdr, req, &hdr);
+	encode_sequence(&xdr, &args->seq_args, &hdr);
+	encode_getdeviceinfo(&xdr, args, &hdr);
+
+	/* set up reply kvec. Subtract notification bitmap max size (2)
+	 * so that notification bitmap is put in xdr_buf tail */
+	xdr_inline_pages(&req->rq_rcv_buf, (hdr.replen - 2) << 2,
+			 args->pdev->pages, args->pdev->pgbase,
+			 args->pdev->pglen);
+
+	encode_nops(&hdr);
+	return 0;
+}
+
+/*
+ *  Encode LAYOUTGET request
+ */
+static int nfs4_xdr_enc_layoutget(struct rpc_rqst *req, uint32_t *p,
+				  struct nfs4_layoutget_args *args)
+{
+	struct xdr_stream xdr;
+	struct compound_hdr hdr = {
+		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
+	};
+
+	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+	encode_compound_hdr(&xdr, req, &hdr);
+	encode_sequence(&xdr, &args->seq_args, &hdr);
+	encode_putfh(&xdr, NFS_FH(args->inode), &hdr);
+	encode_layoutget(&xdr, args, &hdr);
+	encode_nops(&hdr);
+	return 0;
+}
 #endif /* CONFIG_NFS_V4_1 */
 
 static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
@@ -2676,7 +2812,10 @@
 static int decode_attr_supported(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *bitmask)
 {
 	if (likely(bitmap[0] & FATTR4_WORD0_SUPPORTED_ATTRS)) {
-		decode_attr_bitmap(xdr, bitmask);
+		int ret;
+		ret = decode_attr_bitmap(xdr, bitmask);
+		if (unlikely(ret < 0))
+			return ret;
 		bitmap[0] &= ~FATTR4_WORD0_SUPPORTED_ATTRS;
 	} else
 		bitmask[0] = bitmask[1] = 0;
@@ -2848,6 +2987,56 @@
 	return -EIO;
 }
 
+static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap)
+{
+	__be32 *p;
+
+	if (unlikely(bitmap[0] & (FATTR4_WORD0_RDATTR_ERROR - 1U)))
+		return -EIO;
+	if (likely(bitmap[0] & FATTR4_WORD0_RDATTR_ERROR)) {
+		p = xdr_inline_decode(xdr, 4);
+		if (unlikely(!p))
+			goto out_overflow;
+		bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR;
+	}
+	return 0;
+out_overflow:
+	print_overflow_msg(__func__, xdr);
+	return -EIO;
+}
+
+static int decode_attr_filehandle(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fh *fh)
+{
+	__be32 *p;
+	int len;
+
+	if (fh != NULL)
+		memset(fh, 0, sizeof(*fh));
+
+	if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEHANDLE - 1U)))
+		return -EIO;
+	if (likely(bitmap[0] & FATTR4_WORD0_FILEHANDLE)) {
+		p = xdr_inline_decode(xdr, 4);
+		if (unlikely(!p))
+			goto out_overflow;
+		len = be32_to_cpup(p);
+		if (len > NFS4_FHSIZE)
+			return -EIO;
+		p = xdr_inline_decode(xdr, len);
+		if (unlikely(!p))
+			goto out_overflow;
+		if (fh != NULL) {
+			memcpy(fh->data, p, len);
+			fh->size = len;
+		}
+		bitmap[0] &= ~FATTR4_WORD0_FILEHANDLE;
+	}
+	return 0;
+out_overflow:
+	print_overflow_msg(__func__, xdr);
+	return -EIO;
+}
+
 static int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
 {
 	__be32 *p;
@@ -3521,6 +3710,24 @@
 	return status;
 }
 
+static int decode_attr_time_delta(struct xdr_stream *xdr, uint32_t *bitmap,
+				  struct timespec *time)
+{
+	int status = 0;
+
+	time->tv_sec = 0;
+	time->tv_nsec = 0;
+	if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_DELTA - 1U)))
+		return -EIO;
+	if (likely(bitmap[1] & FATTR4_WORD1_TIME_DELTA)) {
+		status = decode_attr_time(xdr, time);
+		bitmap[1] &= ~FATTR4_WORD1_TIME_DELTA;
+	}
+	dprintk("%s: time_delta=%ld %ld\n", __func__, (long)time->tv_sec,
+		(long)time->tv_nsec);
+	return status;
+}
+
 static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time)
 {
 	int status = 0;
@@ -3744,29 +3951,14 @@
 	return status;
 }
 
-static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr,
+static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap,
+		struct nfs_fattr *fattr, struct nfs_fh *fh,
 		const struct nfs_server *server, int may_sleep)
 {
-	__be32 *savep;
-	uint32_t attrlen,
-		 bitmap[2] = {0},
-		 type;
 	int status;
 	umode_t fmode = 0;
 	uint64_t fileid;
-
-	status = decode_op_hdr(xdr, OP_GETATTR);
-	if (status < 0)
-		goto xdr_error;
-
-	status = decode_attr_bitmap(xdr, bitmap);
-	if (status < 0)
-		goto xdr_error;
-
-	status = decode_attr_length(xdr, &attrlen, &savep);
-	if (status < 0)
-		goto xdr_error;
-
+	uint32_t type;
 
 	status = decode_attr_type(xdr, bitmap, &type);
 	if (status < 0)
@@ -3792,6 +3984,14 @@
 		goto xdr_error;
 	fattr->valid |= status;
 
+	status = decode_attr_error(xdr, bitmap);
+	if (status < 0)
+		goto xdr_error;
+
+	status = decode_attr_filehandle(xdr, bitmap, fh);
+	if (status < 0)
+		goto xdr_error;
+
 	status = decode_attr_fileid(xdr, bitmap, &fattr->fileid);
 	if (status < 0)
 		goto xdr_error;
@@ -3862,12 +4062,101 @@
 		fattr->valid |= status;
 	}
 
+xdr_error:
+	dprintk("%s: xdr returned %d\n", __func__, -status);
+	return status;
+}
+
+static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr,
+		struct nfs_fh *fh, const struct nfs_server *server, int may_sleep)
+{
+	__be32 *savep;
+	uint32_t attrlen,
+		 bitmap[2] = {0};
+	int status;
+
+	status = decode_op_hdr(xdr, OP_GETATTR);
+	if (status < 0)
+		goto xdr_error;
+
+	status = decode_attr_bitmap(xdr, bitmap);
+	if (status < 0)
+		goto xdr_error;
+
+	status = decode_attr_length(xdr, &attrlen, &savep);
+	if (status < 0)
+		goto xdr_error;
+
+	status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, server, may_sleep);
+	if (status < 0)
+		goto xdr_error;
+
 	status = verify_attr_len(xdr, savep, attrlen);
 xdr_error:
 	dprintk("%s: xdr returned %d\n", __func__, -status);
 	return status;
 }
 
+static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr,
+		const struct nfs_server *server, int may_sleep)
+{
+	return decode_getfattr_generic(xdr, fattr, NULL, server, may_sleep);
+}
+
+/*
+ * Decode potentially multiple layout types. Currently we only support
+ * one layout driver per file system.
+ */
+static int decode_first_pnfs_layout_type(struct xdr_stream *xdr,
+					 uint32_t *layouttype)
+{
+	uint32_t *p;
+	int num;
+
+	p = xdr_inline_decode(xdr, 4);
+	if (unlikely(!p))
+		goto out_overflow;
+	num = be32_to_cpup(p);
+
+	/* pNFS is not supported by the underlying file system */
+	if (num == 0) {
+		*layouttype = 0;
+		return 0;
+	}
+	if (num > 1)
+		printk(KERN_INFO "%s: Warning: Multiple pNFS layout drivers "
+			"per filesystem not supported\n", __func__);
+
+	/* Decode and set first layout type, move xdr->p past unused types */
+	p = xdr_inline_decode(xdr, num * 4);
+	if (unlikely(!p))
+		goto out_overflow;
+	*layouttype = be32_to_cpup(p);
+	return 0;
+out_overflow:
+	print_overflow_msg(__func__, xdr);
+	return -EIO;
+}
+
+/*
+ * The type of file system exported.
+ * Note we must ensure that layouttype is set in any non-error case.
+ */
+static int decode_attr_pnfstype(struct xdr_stream *xdr, uint32_t *bitmap,
+				uint32_t *layouttype)
+{
+	int status = 0;
+
+	dprintk("%s: bitmap is %x\n", __func__, bitmap[1]);
+	if (unlikely(bitmap[1] & (FATTR4_WORD1_FS_LAYOUT_TYPES - 1U)))
+		return -EIO;
+	if (bitmap[1] & FATTR4_WORD1_FS_LAYOUT_TYPES) {
+		status = decode_first_pnfs_layout_type(xdr, layouttype);
+		bitmap[1] &= ~FATTR4_WORD1_FS_LAYOUT_TYPES;
+	} else
+		*layouttype = 0;
+	return status;
+}
 
 static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo)
 {
@@ -3894,6 +4183,12 @@
 	if ((status = decode_attr_maxwrite(xdr, bitmap, &fsinfo->wtmax)) != 0)
 		goto xdr_error;
 	fsinfo->wtpref = fsinfo->wtmax;
+	status = decode_attr_time_delta(xdr, bitmap, &fsinfo->time_delta);
+	if (status != 0)
+		goto xdr_error;
+	status = decode_attr_pnfstype(xdr, bitmap, &fsinfo->layouttype);
+	if (status != 0)
+		goto xdr_error;
 
 	status = verify_attr_len(xdr, savep, attrlen);
 xdr_error:
@@ -3950,13 +4245,13 @@
 	__be32 *p;
 	uint32_t namelen, type;
 
-	p = xdr_inline_decode(xdr, 32);
+	p = xdr_inline_decode(xdr, 32); /* read 32 bytes */
 	if (unlikely(!p))
 		goto out_overflow;
-	p = xdr_decode_hyper(p, &offset);
+	p = xdr_decode_hyper(p, &offset); /* read 2 8-byte long words */
 	p = xdr_decode_hyper(p, &length);
-	type = be32_to_cpup(p++);
-	if (fl != NULL) {
+	type = be32_to_cpup(p++); /* 4 byte read */
+	if (fl != NULL) { /* manipulate file lock */
 		fl->fl_start = (loff_t)offset;
 		fl->fl_end = fl->fl_start + (loff_t)length - 1;
 		if (length == ~(uint64_t)0)
@@ -3966,9 +4261,9 @@
 			fl->fl_type = F_RDLCK;
 		fl->fl_pid = 0;
 	}
-	p = xdr_decode_hyper(p, &clientid);
-	namelen = be32_to_cpup(p);
-	p = xdr_inline_decode(xdr, namelen);
+	p = xdr_decode_hyper(p, &clientid); /* read 8 bytes */
+	namelen = be32_to_cpup(p); /* read 4 bytes */  /* have read all 32 bytes now */
+	p = xdr_inline_decode(xdr, namelen); /* variable size field */
 	if (likely(p))
 		return -NFS4ERR_DENIED;
 out_overflow:
@@ -4200,12 +4495,9 @@
 static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_readdir_res *readdir)
 {
 	struct xdr_buf	*rcvbuf = &req->rq_rcv_buf;
-	struct page	*page = *rcvbuf->pages;
 	struct kvec	*iov = rcvbuf->head;
 	size_t		hdrlen;
 	u32		recvd, pglen = rcvbuf->page_len;
-	__be32		*end, *entry, *p, *kaddr;
-	unsigned int	nr = 0;
 	int		status;
 
 	status = decode_op_hdr(xdr, OP_READDIR);
@@ -4225,71 +4517,8 @@
 		pglen = recvd;
 	xdr_read_pages(xdr, pglen);
 
-	BUG_ON(pglen + readdir->pgbase > PAGE_CACHE_SIZE);
-	kaddr = p = kmap_atomic(page, KM_USER0);
-	end = p + ((pglen + readdir->pgbase) >> 2);
-	entry = p;
 
-	/* Make sure the packet actually has a value_follows and EOF entry */
-	if ((entry + 1) > end)
-		goto short_pkt;
-
-	for (; *p++; nr++) {
-		u32 len, attrlen, xlen;
-		if (end - p < 3)
-			goto short_pkt;
-		dprintk("cookie = %Lu, ", *((unsigned long long *)p));
-		p += 2;			/* cookie */
-		len = ntohl(*p++);	/* filename length */
-		if (len > NFS4_MAXNAMLEN) {
-			dprintk("NFS: giant filename in readdir (len 0x%x)\n",
-					len);
-			goto err_unmap;
-		}
-		xlen = XDR_QUADLEN(len);
-		if (end - p < xlen + 1)
-			goto short_pkt;
-		dprintk("filename = %*s\n", len, (char *)p);
-		p += xlen;
-		len = ntohl(*p++);	/* bitmap length */
-		if (end - p < len + 1)
-			goto short_pkt;
-		p += len;
-		attrlen = XDR_QUADLEN(ntohl(*p++));
-		if (end - p < attrlen + 2)
-			goto short_pkt;
-		p += attrlen;		/* attributes */
-		entry = p;
-	}
-	/*
-	 * Apparently some server sends responses that are a valid size, but
-	 * contain no entries, and have value_follows==0 and EOF==0. For
-	 * those, just set the EOF marker.
-	 */
-	if (!nr && entry[1] == 0) {
-		dprintk("NFS: readdir reply truncated!\n");
-		entry[1] = 1;
-	}
-out:
-	kunmap_atomic(kaddr, KM_USER0);
 	return 0;
-short_pkt:
-	/*
-	 * When we get a short packet there are 2 possibilities. We can
-	 * return an error, or fix up the response to look like a valid
-	 * response and return what we have so far. If there are no
-	 * entries and the packet was short, then return -EIO. If there
-	 * are valid entries in the response, return them and pretend that
-	 * the call was successful, but incomplete. The caller can retry the
-	 * readdir starting at the last cookie.
-	 */
-	dprintk("%s: short packet at entry %d\n", __func__, nr);
-	entry[0] = entry[1] = 0;
-	if (nr)
-		goto out;
-err_unmap:
-	kunmap_atomic(kaddr, KM_USER0);
-	return -errno_NFSERR_IO;
 }
 
 static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req)
@@ -4299,7 +4528,6 @@
 	size_t hdrlen;
 	u32 len, recvd;
 	__be32 *p;
-	char *kaddr;
 	int status;
 
 	status = decode_op_hdr(xdr, OP_READLINK);
@@ -4330,9 +4558,7 @@
 	 * and and null-terminate the text (the VFS expects
 	 * null-termination).
 	 */
-	kaddr = (char *)kmap_atomic(rcvbuf->pages[0], KM_USER0);
-	kaddr[len+rcvbuf->page_base] = '\0';
-	kunmap_atomic(kaddr, KM_USER0);
+	xdr_terminate_string(rcvbuf, len);
 	return 0;
 out_overflow:
 	print_overflow_msg(__func__, xdr);
@@ -4668,7 +4894,6 @@
 			   struct rpc_rqst *rqstp)
 {
 #if defined(CONFIG_NFS_V4_1)
-	struct nfs4_slot *slot;
 	struct nfs4_sessionid id;
 	u32 dummy;
 	int status;
@@ -4700,15 +4925,14 @@
 		goto out_overflow;
 
 	/* seqid */
-	slot = &res->sr_session->fc_slot_table.slots[res->sr_slotid];
 	dummy = be32_to_cpup(p++);
-	if (dummy != slot->seq_nr) {
+	if (dummy != res->sr_slot->seq_nr) {
 		dprintk("%s Invalid sequence number\n", __func__);
 		goto out_err;
 	}
 	/* slot id */
 	dummy = be32_to_cpup(p++);
-	if (dummy != res->sr_slotid) {
+	if (dummy != res->sr_slot - res->sr_session->fc_slot_table.slots) {
 		dprintk("%s Invalid slot id\n", __func__);
 		goto out_err;
 	}
@@ -4731,6 +4955,134 @@
 #endif /* CONFIG_NFS_V4_1 */
 }
 
+#if defined(CONFIG_NFS_V4_1)
+
+static int decode_getdeviceinfo(struct xdr_stream *xdr,
+				struct pnfs_device *pdev)
+{
+	__be32 *p;
+	uint32_t len, type;
+	int status;
+
+	status = decode_op_hdr(xdr, OP_GETDEVICEINFO);
+	if (status) {
+		if (status == -ETOOSMALL) {
+			p = xdr_inline_decode(xdr, 4);
+			if (unlikely(!p))
+				goto out_overflow;
+			pdev->mincount = be32_to_cpup(p);
+			dprintk("%s: Min count too small. mincnt = %u\n",
+				__func__, pdev->mincount);
+		}
+		return status;
+	}
+
+	p = xdr_inline_decode(xdr, 8);
+	if (unlikely(!p))
+		goto out_overflow;
+	type = be32_to_cpup(p++);
+	if (type != pdev->layout_type) {
+		dprintk("%s: layout mismatch req: %u pdev: %u\n",
+			__func__, pdev->layout_type, type);
+		return -EINVAL;
+	}
+	/*
+	 * Get the length of the opaque device_addr4. xdr_read_pages places
+	 * the opaque device_addr4 in the xdr_buf->pages (pnfs_device->pages)
+	 * and places the remaining xdr data in xdr_buf->tail
+	 */
+	pdev->mincount = be32_to_cpup(p);
+	xdr_read_pages(xdr, pdev->mincount); /* include space for the length */
+
+	/* Parse notification bitmap, verifying that it is zero. */
+	p = xdr_inline_decode(xdr, 4);
+	if (unlikely(!p))
+		goto out_overflow;
+	len = be32_to_cpup(p);
+	if (len) {
+		int i;
+
+		p = xdr_inline_decode(xdr, 4 * len);
+		if (unlikely(!p))
+			goto out_overflow;
+		for (i = 0; i < len; i++, p++) {
+			if (be32_to_cpup(p)) {
+				dprintk("%s: notifications not supported\n",
+					__func__);
+				return -EIO;
+			}
+		}
+	}
+	return 0;
+out_overflow:
+	print_overflow_msg(__func__, xdr);
+	return -EIO;
+}
+
+static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
+			    struct nfs4_layoutget_res *res)
+{
+	__be32 *p;
+	int status;
+	u32 layout_count;
+
+	status = decode_op_hdr(xdr, OP_LAYOUTGET);
+	if (status)
+		return status;
+	p = xdr_inline_decode(xdr, 8 + NFS4_STATEID_SIZE);
+	if (unlikely(!p))
+		goto out_overflow;
+	res->return_on_close = be32_to_cpup(p++);
+	p = xdr_decode_opaque_fixed(p, res->stateid.data, NFS4_STATEID_SIZE);
+	layout_count = be32_to_cpup(p);
+	if (!layout_count) {
+		dprintk("%s: server responded with empty layout array\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	p = xdr_inline_decode(xdr, 24);
+	if (unlikely(!p))
+		goto out_overflow;
+	p = xdr_decode_hyper(p, &res->range.offset);
+	p = xdr_decode_hyper(p, &res->range.length);
+	res->range.iomode = be32_to_cpup(p++);
+	res->type = be32_to_cpup(p++);
+
+	status = decode_opaque_inline(xdr, &res->layout.len, (char **)&p);
+	if (unlikely(status))
+		return status;
+
+	dprintk("%s roff:%lu rlen:%lu riomode:%d, lo_type:0x%x, lo.len:%d\n",
+		__func__,
+		(unsigned long)res->range.offset,
+		(unsigned long)res->range.length,
+		res->range.iomode,
+		res->type,
+		res->layout.len);
+
+	/* nfs4_proc_layoutget allocated a single page */
+	if (res->layout.len > PAGE_SIZE)
+		return -ENOMEM;
+	memcpy(res->layout.buf, p, res->layout.len);
+
+	if (layout_count > 1) {
+		/* We only handle a length one array at the moment.  Any
+		 * further entries are just ignored.  Note that this means
+		 * the client may see a response that is less than the
+		 * minimum it requested.
+		 */
+		dprintk("%s: server responded with %d layouts, dropping tail\n",
+			__func__, layout_count);
+	}
+
+	return 0;
+out_overflow:
+	print_overflow_msg(__func__, xdr);
+	return -EIO;
+}
+#endif /* CONFIG_NFS_V4_1 */
+
 /*
  * END OF "GENERIC" DECODE ROUTINES.
  */
@@ -4873,7 +5225,7 @@
 /*
  * Decode RENAME response
  */
-static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_rename_res *res)
+static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, __be32 *p, struct nfs_renameres *res)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr;
@@ -5758,25 +6110,84 @@
 		status = decode_reclaim_complete(&xdr, (void *)NULL);
 	return status;
 }
+
+/*
+ * Decode GETDEVINFO response
+ */
+static int nfs4_xdr_dec_getdeviceinfo(struct rpc_rqst *rqstp, uint32_t *p,
+				      struct nfs4_getdeviceinfo_res *res)
+{
+	struct xdr_stream xdr;
+	struct compound_hdr hdr;
+	int status;
+
+	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+	status = decode_compound_hdr(&xdr, &hdr);
+	if (status != 0)
+		goto out;
+	status = decode_sequence(&xdr, &res->seq_res, rqstp);
+	if (status != 0)
+		goto out;
+	status = decode_getdeviceinfo(&xdr, res->pdev);
+out:
+	return status;
+}
+
+/*
+ * Decode LAYOUTGET response
+ */
+static int nfs4_xdr_dec_layoutget(struct rpc_rqst *rqstp, uint32_t *p,
+				  struct nfs4_layoutget_res *res)
+{
+	struct xdr_stream xdr;
+	struct compound_hdr hdr;
+	int status;
+
+	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+	status = decode_compound_hdr(&xdr, &hdr);
+	if (status)
+		goto out;
+	status = decode_sequence(&xdr, &res->seq_res, rqstp);
+	if (status)
+		goto out;
+	status = decode_putfh(&xdr);
+	if (status)
+		goto out;
+	status = decode_layoutget(&xdr, rqstp, res);
+out:
+	return status;
+}
 #endif /* CONFIG_NFS_V4_1 */
 
-__be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
+__be32 *nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
+			   struct nfs_server *server, int plus)
 {
 	uint32_t bitmap[2] = {0};
 	uint32_t len;
-
-	if (!*p++) {
-		if (!*p)
+	__be32 *p = xdr_inline_decode(xdr, 4);
+	if (unlikely(!p))
+		goto out_overflow;
+	if (!ntohl(*p++)) {
+		p = xdr_inline_decode(xdr, 4);
+		if (unlikely(!p))
+			goto out_overflow;
+		if (!ntohl(*p++))
 			return ERR_PTR(-EAGAIN);
 		entry->eof = 1;
 		return ERR_PTR(-EBADCOOKIE);
 	}
 
+	p = xdr_inline_decode(xdr, 12);
+	if (unlikely(!p))
+		goto out_overflow;
 	entry->prev_cookie = entry->cookie;
 	p = xdr_decode_hyper(p, &entry->cookie);
 	entry->len = ntohl(*p++);
+
+	p = xdr_inline_decode(xdr, entry->len);
+	if (unlikely(!p))
+		goto out_overflow;
 	entry->name = (const char *) p;
-	p += XDR_QUADLEN(entry->len);
 
 	/*
 	 * In case the server doesn't return an inode number,
@@ -5784,32 +6195,33 @@
 	 * since glibc seems to choke on it...)
 	 */
 	entry->ino = 1;
+	entry->fattr->valid = 0;
 
-	len = ntohl(*p++);		/* bitmap length */
-	if (len-- > 0) {
-		bitmap[0] = ntohl(*p++);
-		if (len-- > 0) {
-			bitmap[1] = ntohl(*p++);
-			p += len;
-		}
-	}
-	len = XDR_QUADLEN(ntohl(*p++));	/* attribute buffer length */
-	if (len > 0) {
-		if (bitmap[0] & FATTR4_WORD0_RDATTR_ERROR) {
-			bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR;
-			/* Ignore the return value of rdattr_error for now */
-			p++;
-			len--;
-		}
-		if (bitmap[0] == 0 && bitmap[1] == FATTR4_WORD1_MOUNTED_ON_FILEID)
-			xdr_decode_hyper(p, &entry->ino);
-		else if (bitmap[0] == FATTR4_WORD0_FILEID)
-			xdr_decode_hyper(p, &entry->ino);
-		p += len;
-	}
+	if (decode_attr_bitmap(xdr, bitmap) < 0)
+		goto out_overflow;
 
-	entry->eof = !p[0] && p[1];
+	if (decode_attr_length(xdr, &len, &p) < 0)
+		goto out_overflow;
+
+	if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, server, 1) < 0)
+		goto out_overflow;
+	if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID)
+		entry->ino = entry->fattr->fileid;
+
+	if (verify_attr_len(xdr, p, len) < 0)
+		goto out_overflow;
+
+	p = xdr_inline_peek(xdr, 8);
+	if (p != NULL)
+		entry->eof = !p[0] && p[1];
+	else
+		entry->eof = 0;
+
 	return p;
+
+out_overflow:
+	print_overflow_msg(__func__, xdr);
+	return ERR_PTR(-EIO);
 }
 
 /*
@@ -5936,6 +6348,8 @@
   PROC(SEQUENCE,	enc_sequence,	dec_sequence),
   PROC(GET_LEASE_TIME,	enc_get_lease_time,	dec_get_lease_time),
   PROC(RECLAIM_COMPLETE, enc_reclaim_complete,  dec_reclaim_complete),
+  PROC(GETDEVICEINFO, enc_getdeviceinfo, dec_getdeviceinfo),
+  PROC(LAYOUTGET,  enc_layoutget,     dec_layoutget),
 #endif /* CONFIG_NFS_V4_1 */
 };
 
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
index df101d9..903908a 100644
--- a/fs/nfs/nfsroot.c
+++ b/fs/nfs/nfsroot.c
@@ -3,9 +3,10 @@
  *
  *  Allow an NFS filesystem to be mounted as root. The way this works is:
  *     (1) Use the IP autoconfig mechanism to set local IP addresses and routes.
- *     (2) Handle RPC negotiation with the system which replied to RARP or
- *         was reported as a boot server by BOOTP or manually.
- *     (3) The actual mounting is done later, when init() is running.
+ *     (2) Construct the device string and the options string using DHCP
+ *         option 17 and/or kernel command line options.
+ *     (3) When mount_root() sets up the root file system, pass these strings
+ *         to the NFS client's regular mount interface via sys_mount().
  *
  *
  *	Changes:
@@ -65,470 +66,245 @@
  *	Hua Qin		:	Support for mounting root file system via
  *				NFS over TCP.
  *	Fabian Frederick:	Option parser rebuilt (using parser lib)
-*/
+ *	Chuck Lever	:	Use super.c's text-based mount option parsing
+ *	Chuck Lever	:	Add "nfsrootdebug".
+ */
 
 #include <linux/types.h>
 #include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/time.h>
-#include <linux/fs.h>
 #include <linux/init.h>
-#include <linux/sunrpc/clnt.h>
-#include <linux/sunrpc/xprtsock.h>
 #include <linux/nfs.h>
 #include <linux/nfs_fs.h>
-#include <linux/nfs_mount.h>
-#include <linux/in.h>
-#include <linux/major.h>
 #include <linux/utsname.h>
-#include <linux/inet.h>
 #include <linux/root_dev.h>
 #include <net/ipconfig.h>
-#include <linux/parser.h>
 
 #include "internal.h"
 
-/* Define this to allow debugging output */
-#undef NFSROOT_DEBUG
 #define NFSDBG_FACILITY NFSDBG_ROOT
 
-/* Default port to use if server is not running a portmapper */
-#define NFS_MNT_PORT	627
-
 /* Default path we try to mount. "%s" gets replaced by our IP address */
 #define NFS_ROOT		"/tftpboot/%s"
 
 /* Parameters passed from the kernel command line */
-static char nfs_root_name[256] __initdata = "";
+static char nfs_root_parms[256] __initdata = "";
+
+/* Text-based mount options passed to super.c */
+static char nfs_root_options[256] __initdata = "";
 
 /* Address of NFS server */
-static __be32 servaddr __initdata = 0;
+static __be32 servaddr __initdata = htonl(INADDR_NONE);
 
 /* Name of directory to mount */
-static char nfs_export_path[NFS_MAXPATHLEN + 1] __initdata = { 0, };
+static char nfs_export_path[NFS_MAXPATHLEN + 1] __initdata = "";
 
-/* NFS-related data */
-static struct nfs_mount_data nfs_data __initdata = { 0, };/* NFS mount info */
-static int nfs_port __initdata = 0;		/* Port to connect to for NFS */
-static int mount_port __initdata = 0;		/* Mount daemon port number */
+/* server:export path string passed to super.c */
+static char nfs_root_device[NFS_MAXPATHLEN + 1] __initdata = "";
 
-
-/***************************************************************************
-
-			     Parsing of options
-
- ***************************************************************************/
-
-enum {
-	/* Options that take integer arguments */
-	Opt_port, Opt_rsize, Opt_wsize, Opt_timeo, Opt_retrans, Opt_acregmin,
-	Opt_acregmax, Opt_acdirmin, Opt_acdirmax,
-	/* Options that take no arguments */
-	Opt_soft, Opt_hard, Opt_intr,
-	Opt_nointr, Opt_posix, Opt_noposix, Opt_cto, Opt_nocto, Opt_ac, 
-	Opt_noac, Opt_lock, Opt_nolock, Opt_v2, Opt_v3, Opt_udp, Opt_tcp,
-	Opt_acl, Opt_noacl,
-	/* Error token */
-	Opt_err
-};
-
-static const match_table_t tokens __initconst = {
-	{Opt_port, "port=%u"},
-	{Opt_rsize, "rsize=%u"},
-	{Opt_wsize, "wsize=%u"},
-	{Opt_timeo, "timeo=%u"},
-	{Opt_retrans, "retrans=%u"},
-	{Opt_acregmin, "acregmin=%u"},
-	{Opt_acregmax, "acregmax=%u"},
-	{Opt_acdirmin, "acdirmin=%u"},
-	{Opt_acdirmax, "acdirmax=%u"},
-	{Opt_soft, "soft"},
-	{Opt_hard, "hard"},
-	{Opt_intr, "intr"},
-	{Opt_nointr, "nointr"},
-	{Opt_posix, "posix"},
-	{Opt_noposix, "noposix"},
-	{Opt_cto, "cto"},
-	{Opt_nocto, "nocto"},
-	{Opt_ac, "ac"},
-	{Opt_noac, "noac"},
-	{Opt_lock, "lock"},
-	{Opt_nolock, "nolock"},
-	{Opt_v2, "nfsvers=2"},
-	{Opt_v2, "v2"},
-	{Opt_v3, "nfsvers=3"},
-	{Opt_v3, "v3"},
-	{Opt_udp, "proto=udp"},
-	{Opt_udp, "udp"},
-	{Opt_tcp, "proto=tcp"},
-	{Opt_tcp, "tcp"},
-	{Opt_acl, "acl"},
-	{Opt_noacl, "noacl"},
-	{Opt_err, NULL}
-	
-};
-
+#ifdef RPC_DEBUG
 /*
- *  Parse option string.
+ * When the "nfsrootdebug" kernel command line option is specified,
+ * enable debugging messages for NFSROOT.
  */
-
-static int __init root_nfs_parse(char *name, char *buf)
+static int __init nfs_root_debug(char *__unused)
 {
-
-	char *p;
-	substring_t args[MAX_OPT_ARGS];
-	int option;
-
-	if (!name)
-		return 1;
-
-	/* Set the NFS remote path */
-	p = strsep(&name, ",");
-	if (p[0] != '\0' && strcmp(p, "default") != 0)
-		strlcpy(buf, p, NFS_MAXPATHLEN);
-
-	while ((p = strsep (&name, ",")) != NULL) {
-		int token; 
-		if (!*p)
-			continue;
-		token = match_token(p, tokens, args);
-
-		/* %u tokens only. Beware if you add new tokens! */
-		if (token < Opt_soft && match_int(&args[0], &option))
-			return 0;
-		switch (token) {
-			case Opt_port:
-				nfs_port = option;
-				break;
-			case Opt_rsize:
-				nfs_data.rsize = option;
-				break;
-			case Opt_wsize:
-				nfs_data.wsize = option;
-				break;
-			case Opt_timeo:
-				nfs_data.timeo = option;
-				break;
-			case Opt_retrans:
-				nfs_data.retrans = option;
-				break;
-			case Opt_acregmin:
-				nfs_data.acregmin = option;
-				break;
-			case Opt_acregmax:
-				nfs_data.acregmax = option;
-				break;
-			case Opt_acdirmin:
-				nfs_data.acdirmin = option;
-				break;
-			case Opt_acdirmax:
-				nfs_data.acdirmax = option;
-				break;
-			case Opt_soft:
-				nfs_data.flags |= NFS_MOUNT_SOFT;
-				break;
-			case Opt_hard:
-				nfs_data.flags &= ~NFS_MOUNT_SOFT;
-				break;
-			case Opt_intr:
-			case Opt_nointr:
-				break;
-			case Opt_posix:
-				nfs_data.flags |= NFS_MOUNT_POSIX;
-				break;
-			case Opt_noposix:
-				nfs_data.flags &= ~NFS_MOUNT_POSIX;
-				break;
-			case Opt_cto:
-				nfs_data.flags &= ~NFS_MOUNT_NOCTO;
-				break;
-			case Opt_nocto:
-				nfs_data.flags |= NFS_MOUNT_NOCTO;
-				break;
-			case Opt_ac:
-				nfs_data.flags &= ~NFS_MOUNT_NOAC;
-				break;
-			case Opt_noac:
-				nfs_data.flags |= NFS_MOUNT_NOAC;
-				break;
-			case Opt_lock:
-				nfs_data.flags &= ~NFS_MOUNT_NONLM;
-				break;
-			case Opt_nolock:
-				nfs_data.flags |= NFS_MOUNT_NONLM;
-				break;
-			case Opt_v2:
-				nfs_data.flags &= ~NFS_MOUNT_VER3;
-				break;
-			case Opt_v3:
-				nfs_data.flags |= NFS_MOUNT_VER3;
-				break;
-			case Opt_udp:
-				nfs_data.flags &= ~NFS_MOUNT_TCP;
-				break;
-			case Opt_tcp:
-				nfs_data.flags |= NFS_MOUNT_TCP;
-				break;
-			case Opt_acl:
-				nfs_data.flags &= ~NFS_MOUNT_NOACL;
-				break;
-			case Opt_noacl:
-				nfs_data.flags |= NFS_MOUNT_NOACL;
-				break;
-			default:
-				printk(KERN_WARNING "Root-NFS: unknown "
-					"option: %s\n", p);
-				return 0;
-		}
-	}
-
+	nfs_debug |= NFSDBG_ROOT | NFSDBG_MOUNT;
 	return 1;
 }
 
-/*
- *  Prepare the NFS data structure and parse all options.
- */
-static int __init root_nfs_name(char *name)
-{
-	static char buf[NFS_MAXPATHLEN] __initdata;
-	char *cp;
-
-	/* Set some default values */
-	memset(&nfs_data, 0, sizeof(nfs_data));
-	nfs_port          = -1;
-	nfs_data.version  = NFS_MOUNT_VERSION;
-	nfs_data.flags    = NFS_MOUNT_NONLM;	/* No lockd in nfs root yet */
-	nfs_data.rsize    = NFS_DEF_FILE_IO_SIZE;
-	nfs_data.wsize    = NFS_DEF_FILE_IO_SIZE;
-	nfs_data.acregmin = NFS_DEF_ACREGMIN;
-	nfs_data.acregmax = NFS_DEF_ACREGMAX;
-	nfs_data.acdirmin = NFS_DEF_ACDIRMIN;
-	nfs_data.acdirmax = NFS_DEF_ACDIRMAX;
-	strcpy(buf, NFS_ROOT);
-
-	/* Process options received from the remote server */
-	root_nfs_parse(root_server_path, buf);
-
-	/* Override them by options set on kernel command-line */
-	root_nfs_parse(name, buf);
-
-	cp = utsname()->nodename;
-	if (strlen(buf) + strlen(cp) > NFS_MAXPATHLEN) {
-		printk(KERN_ERR "Root-NFS: Pathname for remote directory too long.\n");
-		return -1;
-	}
-	sprintf(nfs_export_path, buf, cp);
-
-	return 1;
-}
-
-
-/*
- *  Get NFS server address.
- */
-static int __init root_nfs_addr(void)
-{
-	if ((servaddr = root_server_addr) == htonl(INADDR_NONE)) {
-		printk(KERN_ERR "Root-NFS: No NFS server available, giving up.\n");
-		return -1;
-	}
-
-	snprintf(nfs_data.hostname, sizeof(nfs_data.hostname),
-		 "%pI4", &servaddr);
-	return 0;
-}
-
-/*
- *  Tell the user what's going on.
- */
-#ifdef NFSROOT_DEBUG
-static void __init root_nfs_print(void)
-{
-	printk(KERN_NOTICE "Root-NFS: Mounting %s on server %s as root\n",
-		nfs_export_path, nfs_data.hostname);
-	printk(KERN_NOTICE "Root-NFS:     rsize = %d, wsize = %d, timeo = %d, retrans = %d\n",
-		nfs_data.rsize, nfs_data.wsize, nfs_data.timeo, nfs_data.retrans);
-	printk(KERN_NOTICE "Root-NFS:     acreg (min,max) = (%d,%d), acdir (min,max) = (%d,%d)\n",
-		nfs_data.acregmin, nfs_data.acregmax,
-		nfs_data.acdirmin, nfs_data.acdirmax);
-	printk(KERN_NOTICE "Root-NFS:     nfsd port = %d, mountd port = %d, flags = %08x\n",
-		nfs_port, mount_port, nfs_data.flags);
-}
+__setup("nfsrootdebug", nfs_root_debug);
 #endif
 
-
-static int __init root_nfs_init(void)
-{
-#ifdef NFSROOT_DEBUG
-	nfs_debug |= NFSDBG_ROOT;
-#endif
-
-	/*
-	 * Decode the root directory path name and NFS options from
-	 * the kernel command line. This has to go here in order to
-	 * be able to use the client IP address for the remote root
-	 * directory (necessary for pure RARP booting).
-	 */
-	if (root_nfs_name(nfs_root_name) < 0 ||
-	    root_nfs_addr() < 0)
-		return -1;
-
-#ifdef NFSROOT_DEBUG
-	root_nfs_print();
-#endif
-
-	return 0;
-}
-
-
 /*
  *  Parse NFS server and directory information passed on the kernel
  *  command line.
+ *
+ *  nfsroot=[<server-ip>:]<root-dir>[,<nfs-options>]
+ *
+ *  If there is a "%s" token in the <root-dir> string, it is replaced
+ *  by the ASCII-representation of the client's IP address.
  */
 static int __init nfs_root_setup(char *line)
 {
 	ROOT_DEV = Root_NFS;
+
 	if (line[0] == '/' || line[0] == ',' || (line[0] >= '0' && line[0] <= '9')) {
-		strlcpy(nfs_root_name, line, sizeof(nfs_root_name));
+		strlcpy(nfs_root_parms, line, sizeof(nfs_root_parms));
 	} else {
-		int n = strlen(line) + sizeof(NFS_ROOT) - 1;
-		if (n >= sizeof(nfs_root_name))
-			line[sizeof(nfs_root_name) - sizeof(NFS_ROOT) - 2] = '\0';
-		sprintf(nfs_root_name, NFS_ROOT, line);
+		size_t n = strlen(line) + sizeof(NFS_ROOT) - 1;
+		if (n >= sizeof(nfs_root_parms))
+			line[sizeof(nfs_root_parms) - sizeof(NFS_ROOT) - 2] = '\0';
+		sprintf(nfs_root_parms, NFS_ROOT, line);
 	}
-	root_server_addr = root_nfs_parse_addr(nfs_root_name);
+
+	/*
+	 * Extract the IP address of the NFS server containing our
+	 * root file system, if one was specified.
+	 *
+	 * Note: root_nfs_parse_addr() removes the server-ip from
+	 *	 nfs_root_parms, if it exists.
+	 */
+	root_server_addr = root_nfs_parse_addr(nfs_root_parms);
+
 	return 1;
 }
 
 __setup("nfsroot=", nfs_root_setup);
 
-/***************************************************************************
-
-	       Routines to actually mount the root directory
-
- ***************************************************************************/
-
-/*
- *  Construct sockaddr_in from address and port number.
- */
-static inline void
-set_sockaddr(struct sockaddr_in *sin, __be32 addr, __be16 port)
+static int __init root_nfs_copy(char *dest, const char *src,
+				     const size_t destlen)
 {
-	sin->sin_family = AF_INET;
-	sin->sin_addr.s_addr = addr;
-	sin->sin_port = port;
+	if (strlcpy(dest, src, destlen) > destlen)
+		return -1;
+	return 0;
+}
+
+static int __init root_nfs_cat(char *dest, const char *src,
+				  const size_t destlen)
+{
+	if (strlcat(dest, src, destlen) > destlen)
+		return -1;
+	return 0;
 }
 
 /*
- *  Query server portmapper for the port of a daemon program.
+ * Parse out root export path and mount options from
+ * passed-in string @incoming.
+ *
+ * Copy the export path into @exppath.
  */
-static int __init root_nfs_getport(int program, int version, int proto)
+static int __init root_nfs_parse_options(char *incoming, char *exppath,
+					 const size_t exppathlen)
 {
-	struct sockaddr_in sin;
+	char *p;
 
-	printk(KERN_NOTICE "Looking up port of RPC %d/%d on %pI4\n",
-		program, version, &servaddr);
-	set_sockaddr(&sin, servaddr, 0);
-	return rpcb_getport_sync(&sin, program, version, proto);
-}
+	/*
+	 * Set the NFS remote path
+	 */
+	p = strsep(&incoming, ",");
+	if (*p != '\0' && strcmp(p, "default") != 0)
+		if (root_nfs_copy(exppath, p, exppathlen))
+			return -1;
 
+	/*
+	 * @incoming now points to the rest of the string; if it
+	 * contains something, append it to our root options buffer
+	 */
+	if (incoming != NULL && *incoming != '\0')
+		if (root_nfs_cat(nfs_root_options, incoming,
+						sizeof(nfs_root_options)))
+			return -1;
 
-/*
- *  Use portmapper to find mountd and nfsd port numbers if not overriden
- *  by the user. Use defaults if portmapper is not available.
- *  XXX: Is there any nfs server with no portmapper?
- */
-static int __init root_nfs_ports(void)
-{
-	int port;
-	int nfsd_ver, mountd_ver;
-	int nfsd_port, mountd_port;
-	int proto;
-
-	if (nfs_data.flags & NFS_MOUNT_VER3) {
-		nfsd_ver = NFS3_VERSION;
-		mountd_ver = NFS_MNT3_VERSION;
-		nfsd_port = NFS_PORT;
-		mountd_port = NFS_MNT_PORT;
-	} else {
-		nfsd_ver = NFS2_VERSION;
-		mountd_ver = NFS_MNT_VERSION;
-		nfsd_port = NFS_PORT;
-		mountd_port = NFS_MNT_PORT;
-	}
-
-	proto = (nfs_data.flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP;
-
-	if (nfs_port < 0) {
-		if ((port = root_nfs_getport(NFS_PROGRAM, nfsd_ver, proto)) < 0) {
-			printk(KERN_ERR "Root-NFS: Unable to get nfsd port "
-					"number from server, using default\n");
-			port = nfsd_port;
-		}
-		nfs_port = port;
-		dprintk("Root-NFS: Portmapper on server returned %d "
-			"as nfsd port\n", port);
-	}
-
-	if ((port = root_nfs_getport(NFS_MNT_PROGRAM, mountd_ver, proto)) < 0) {
-		printk(KERN_ERR "Root-NFS: Unable to get mountd port "
-				"number from server, using default\n");
-		port = mountd_port;
-	}
-	mount_port = port;
-	dprintk("Root-NFS: mountd port is %d\n", port);
+	/*
+	 * Possibly prepare for more options to be appended
+	 */
+	if (nfs_root_options[0] != '\0' &&
+	    nfs_root_options[strlen(nfs_root_options)] != ',')
+		if (root_nfs_cat(nfs_root_options, ",",
+						sizeof(nfs_root_options)))
+			return -1;
 
 	return 0;
 }
 
-
 /*
- *  Get a file handle from the server for the directory which is to be
- *  mounted.
+ *  Decode the export directory path name and NFS options from
+ *  the kernel command line.  This has to be done late in order to
+ *  use a dynamically acquired client IP address for the remote
+ *  root directory path.
+ *
+ *  Returns zero if successful; otherwise -1 is returned.
  */
-static int __init root_nfs_get_handle(void)
+static int __init root_nfs_data(char *cmdline)
 {
-	struct sockaddr_in sin;
-	unsigned int auth_flav_len = 0;
-	struct nfs_mount_request request = {
-		.sap		= (struct sockaddr *)&sin,
-		.salen		= sizeof(sin),
-		.dirpath	= nfs_export_path,
-		.version	= (nfs_data.flags & NFS_MOUNT_VER3) ?
-					NFS_MNT3_VERSION : NFS_MNT_VERSION,
-		.protocol	= (nfs_data.flags & NFS_MOUNT_TCP) ?
-					XPRT_TRANSPORT_TCP : XPRT_TRANSPORT_UDP,
-		.auth_flav_len	= &auth_flav_len,
-	};
-	int status = -ENOMEM;
+	char addr_option[sizeof("nolock,addr=") + INET_ADDRSTRLEN + 1];
+	int len, retval = -1;
+	char *tmp = NULL;
+	const size_t tmplen = sizeof(nfs_export_path);
 
-	request.fh = nfs_alloc_fhandle();
-	if (!request.fh)
-		goto out;
-	set_sockaddr(&sin, servaddr, htons(mount_port));
-	status = nfs_mount(&request);
-	if (status < 0)
-		printk(KERN_ERR "Root-NFS: Server returned error %d "
-				"while mounting %s\n", status, nfs_export_path);
-	else {
-		nfs_data.root.size = request.fh->size;
-		memcpy(&nfs_data.root.data, request.fh->data, request.fh->size);
+	tmp = kzalloc(tmplen, GFP_KERNEL);
+	if (tmp == NULL)
+		goto out_nomem;
+	strcpy(tmp, NFS_ROOT);
+
+	if (root_server_path[0] != '\0') {
+		dprintk("Root-NFS: DHCPv4 option 17: %s\n",
+			root_server_path);
+		if (root_nfs_parse_options(root_server_path, tmp, tmplen))
+			goto out_optionstoolong;
 	}
-	nfs_free_fhandle(request.fh);
+
+	if (cmdline[0] != '\0') {
+		dprintk("Root-NFS: nfsroot=%s\n", cmdline);
+		if (root_nfs_parse_options(cmdline, tmp, tmplen))
+			goto out_optionstoolong;
+	}
+
+	/*
+	 * Append mandatory options for nfsroot so they override
+	 * what has come before
+	 */
+	snprintf(addr_option, sizeof(addr_option), "nolock,addr=%pI4",
+			&servaddr);
+	if (root_nfs_cat(nfs_root_options, addr_option,
+						sizeof(nfs_root_options)))
+		goto out_optionstoolong;
+
+	/*
+	 * Set up nfs_root_device.  For NFS mounts, this looks like
+	 *
+	 *	server:/path
+	 *
+	 * At this point, utsname()->nodename contains our local
+	 * IP address or hostname, set by ipconfig.  If "%s" exists
+	 * in tmp, substitute the nodename, then shovel the whole
+	 * mess into nfs_root_device.
+	 */
+	len = snprintf(nfs_export_path, sizeof(nfs_export_path),
+				tmp, utsname()->nodename);
+	if (len > (int)sizeof(nfs_export_path))
+		goto out_devnametoolong;
+	len = snprintf(nfs_root_device, sizeof(nfs_root_device),
+				"%pI4:%s", &servaddr, nfs_export_path);
+	if (len > (int)sizeof(nfs_root_device))
+		goto out_devnametoolong;
+
+	retval = 0;
+
 out:
-	return status;
+	kfree(tmp);
+	return retval;
+out_nomem:
+	printk(KERN_ERR "Root-NFS: could not allocate memory\n");
+	goto out;
+out_optionstoolong:
+	printk(KERN_ERR "Root-NFS: mount options string too long\n");
+	goto out;
+out_devnametoolong:
+	printk(KERN_ERR "Root-NFS: root device name too long.\n");
+	goto out;
 }
 
-/*
- *  Get the NFS port numbers and file handle, and return the prepared 'data'
- *  argument for mount() if everything went OK. Return NULL otherwise.
+/**
+ * nfs_root_data - Return prepared 'data' for NFSROOT mount
+ * @root_device: OUT: address of string containing NFSROOT device
+ * @root_data: OUT: address of string containing NFSROOT mount options
+ *
+ * Returns zero and sets @root_device and @root_data if successful,
+ * otherwise -1 is returned.
  */
-void * __init nfs_root_data(void)
+int __init nfs_root_data(char **root_device, char **root_data)
 {
-	if (root_nfs_init() < 0
-	 || root_nfs_ports() < 0
-	 || root_nfs_get_handle() < 0)
-		return NULL;
-	set_sockaddr((struct sockaddr_in *) &nfs_data.addr, servaddr, htons(nfs_port));
-	return (void*)&nfs_data;
+	servaddr = root_server_addr;
+	if (servaddr == htonl(INADDR_NONE)) {
+		printk(KERN_ERR "Root-NFS: no NFS server address\n");
+		return -1;
+	}
+
+	if (root_nfs_data(nfs_root_parms) < 0)
+		return -1;
+
+	*root_device = nfs_root_device;
+	*root_data = nfs_root_options;
+	return 0;
 }
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
new file mode 100644
index 0000000..db77342
--- /dev/null
+++ b/fs/nfs/pnfs.c
@@ -0,0 +1,783 @@
+/*
+ *  pNFS functions to call and manage layout drivers.
+ *
+ *  Copyright (c) 2002 [year of first publication]
+ *  The Regents of the University of Michigan
+ *  All Rights Reserved
+ *
+ *  Dean Hildebrand <dhildebz@umich.edu>
+ *
+ *  Permission is granted to use, copy, create derivative works, and
+ *  redistribute this software and such derivative works for any purpose,
+ *  so long as the name of the University of Michigan is not used in
+ *  any advertising or publicity pertaining to the use or distribution
+ *  of this software without specific, written prior authorization. If
+ *  the above copyright notice or any other identification of the
+ *  University of Michigan is included in any copy of any portion of
+ *  this software, then the disclaimer below must also be included.
+ *
+ *  This software is provided as is, without representation or warranty
+ *  of any kind either express or implied, including without limitation
+ *  the implied warranties of merchantability, fitness for a particular
+ *  purpose, or noninfringement.  The Regents of the University of
+ *  Michigan shall not be liable for any damages, including special,
+ *  indirect, incidental, or consequential damages, with respect to any
+ *  claim arising out of or in connection with the use of the software,
+ *  even if it has been or is hereafter advised of the possibility of
+ *  such damages.
+ */
+
+#include <linux/nfs_fs.h>
+#include "internal.h"
+#include "pnfs.h"
+
+#define NFSDBG_FACILITY		NFSDBG_PNFS
+
+/* Locking:
+ *
+ * pnfs_spinlock:
+ *      protects pnfs_modules_tbl.
+ */
+static DEFINE_SPINLOCK(pnfs_spinlock);
+
+/*
+ * pnfs_modules_tbl holds all pnfs modules
+ */
+static LIST_HEAD(pnfs_modules_tbl);
+
+/* Return the registered pnfs layout driver module matching given id */
+static struct pnfs_layoutdriver_type *
+find_pnfs_driver_locked(u32 id)
+{
+	struct pnfs_layoutdriver_type *local;
+
+	list_for_each_entry(local, &pnfs_modules_tbl, pnfs_tblid)
+		if (local->id == id)
+			goto out;
+	local = NULL;
+out:
+	dprintk("%s: Searching for id %u, found %p\n", __func__, id, local);
+	return local;
+}
+
+static struct pnfs_layoutdriver_type *
+find_pnfs_driver(u32 id)
+{
+	struct pnfs_layoutdriver_type *local;
+
+	spin_lock(&pnfs_spinlock);
+	local = find_pnfs_driver_locked(id);
+	spin_unlock(&pnfs_spinlock);
+	return local;
+}
+
+void
+unset_pnfs_layoutdriver(struct nfs_server *nfss)
+{
+	if (nfss->pnfs_curr_ld) {
+		nfss->pnfs_curr_ld->clear_layoutdriver(nfss);
+		module_put(nfss->pnfs_curr_ld->owner);
+	}
+	nfss->pnfs_curr_ld = NULL;
+}
+
+/*
+ * Try to set the server's pnfs module to the pnfs layout type specified by id.
+ * Currently only one pNFS layout driver per filesystem is supported.
+ *
+ * @id layout type. Zero (illegal layout type) indicates pNFS not in use.
+ */
+void
+set_pnfs_layoutdriver(struct nfs_server *server, u32 id)
+{
+	struct pnfs_layoutdriver_type *ld_type = NULL;
+
+	if (id == 0)
+		goto out_no_driver;
+	if (!(server->nfs_client->cl_exchange_flags &
+		 (EXCHGID4_FLAG_USE_NON_PNFS | EXCHGID4_FLAG_USE_PNFS_MDS))) {
+		printk(KERN_ERR "%s: id %u cl_exchange_flags 0x%x\n", __func__,
+		       id, server->nfs_client->cl_exchange_flags);
+		goto out_no_driver;
+	}
+	ld_type = find_pnfs_driver(id);
+	if (!ld_type) {
+		request_module("%s-%u", LAYOUT_NFSV4_1_MODULE_PREFIX, id);
+		ld_type = find_pnfs_driver(id);
+		if (!ld_type) {
+			dprintk("%s: No pNFS module found for %u.\n",
+				__func__, id);
+			goto out_no_driver;
+		}
+	}
+	if (!try_module_get(ld_type->owner)) {
+		dprintk("%s: Could not grab reference on module\n", __func__);
+		goto out_no_driver;
+	}
+	server->pnfs_curr_ld = ld_type;
+	if (ld_type->set_layoutdriver(server)) {
+		printk(KERN_ERR
+		       "%s: Error initializing mount point for layout driver %u.\n",
+		       __func__, id);
+		module_put(ld_type->owner);
+		goto out_no_driver;
+	}
+	dprintk("%s: pNFS module for %u set\n", __func__, id);
+	return;
+
+out_no_driver:
+	dprintk("%s: Using NFSv4 I/O\n", __func__);
+	server->pnfs_curr_ld = NULL;
+}
+
+int
+pnfs_register_layoutdriver(struct pnfs_layoutdriver_type *ld_type)
+{
+	int status = -EINVAL;
+	struct pnfs_layoutdriver_type *tmp;
+
+	if (ld_type->id == 0) {
+		printk(KERN_ERR "%s id 0 is reserved\n", __func__);
+		return status;
+	}
+	if (!ld_type->alloc_lseg || !ld_type->free_lseg) {
+		printk(KERN_ERR "%s Layout driver must provide "
+		       "alloc_lseg and free_lseg.\n", __func__);
+		return status;
+	}
+
+	spin_lock(&pnfs_spinlock);
+	tmp = find_pnfs_driver_locked(ld_type->id);
+	if (!tmp) {
+		list_add(&ld_type->pnfs_tblid, &pnfs_modules_tbl);
+		status = 0;
+		dprintk("%s Registering id:%u name:%s\n", __func__, ld_type->id,
+			ld_type->name);
+	} else {
+		printk(KERN_ERR "%s Module with id %d already loaded!\n",
+			__func__, ld_type->id);
+	}
+	spin_unlock(&pnfs_spinlock);
+
+	return status;
+}
+EXPORT_SYMBOL_GPL(pnfs_register_layoutdriver);
+
+void
+pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *ld_type)
+{
+	dprintk("%s Deregistering id:%u\n", __func__, ld_type->id);
+	spin_lock(&pnfs_spinlock);
+	list_del(&ld_type->pnfs_tblid);
+	spin_unlock(&pnfs_spinlock);
+}
+EXPORT_SYMBOL_GPL(pnfs_unregister_layoutdriver);
+
+/*
+ * pNFS client layout cache
+ */
+
+static void
+get_layout_hdr_locked(struct pnfs_layout_hdr *lo)
+{
+	assert_spin_locked(&lo->inode->i_lock);
+	lo->refcount++;
+}
+
+static void
+put_layout_hdr_locked(struct pnfs_layout_hdr *lo)
+{
+	assert_spin_locked(&lo->inode->i_lock);
+	BUG_ON(lo->refcount == 0);
+
+	lo->refcount--;
+	if (!lo->refcount) {
+		dprintk("%s: freeing layout cache %p\n", __func__, lo);
+		BUG_ON(!list_empty(&lo->layouts));
+		NFS_I(lo->inode)->layout = NULL;
+		kfree(lo);
+	}
+}
+
+void
+put_layout_hdr(struct inode *inode)
+{
+	spin_lock(&inode->i_lock);
+	put_layout_hdr_locked(NFS_I(inode)->layout);
+	spin_unlock(&inode->i_lock);
+}
+
+static void
+init_lseg(struct pnfs_layout_hdr *lo, struct pnfs_layout_segment *lseg)
+{
+	INIT_LIST_HEAD(&lseg->fi_list);
+	kref_init(&lseg->kref);
+	lseg->layout = lo;
+}
+
+/* Called without i_lock held, as the free_lseg call may sleep */
+static void
+destroy_lseg(struct kref *kref)
+{
+	struct pnfs_layout_segment *lseg =
+		container_of(kref, struct pnfs_layout_segment, kref);
+	struct inode *ino = lseg->layout->inode;
+
+	dprintk("--> %s\n", __func__);
+	NFS_SERVER(ino)->pnfs_curr_ld->free_lseg(lseg);
+	/* Matched by get_layout_hdr_locked in pnfs_insert_layout */
+	put_layout_hdr(ino);
+}
+
+static void
+put_lseg(struct pnfs_layout_segment *lseg)
+{
+	if (!lseg)
+		return;
+
+	dprintk("%s: lseg %p ref %d\n", __func__, lseg,
+		atomic_read(&lseg->kref.refcount));
+	kref_put(&lseg->kref, destroy_lseg);
+}
+
+static void
+pnfs_clear_lseg_list(struct pnfs_layout_hdr *lo, struct list_head *tmp_list)
+{
+	struct pnfs_layout_segment *lseg, *next;
+	struct nfs_client *clp;
+
+	dprintk("%s:Begin lo %p\n", __func__, lo);
+
+	assert_spin_locked(&lo->inode->i_lock);
+	list_for_each_entry_safe(lseg, next, &lo->segs, fi_list) {
+		dprintk("%s: freeing lseg %p\n", __func__, lseg);
+		list_move(&lseg->fi_list, tmp_list);
+	}
+	clp = NFS_SERVER(lo->inode)->nfs_client;
+	spin_lock(&clp->cl_lock);
+	/* List does not take a reference, so no need for put here */
+	list_del_init(&lo->layouts);
+	spin_unlock(&clp->cl_lock);
+	write_seqlock(&lo->seqlock);
+	clear_bit(NFS_LAYOUT_STATEID_SET, &lo->state);
+	write_sequnlock(&lo->seqlock);
+
+	dprintk("%s:Return\n", __func__);
+}
+
+static void
+pnfs_free_lseg_list(struct list_head *tmp_list)
+{
+	struct pnfs_layout_segment *lseg;
+
+	while (!list_empty(tmp_list)) {
+		lseg = list_entry(tmp_list->next, struct pnfs_layout_segment,
+				fi_list);
+		dprintk("%s calling put_lseg on %p\n", __func__, lseg);
+		list_del(&lseg->fi_list);
+		put_lseg(lseg);
+	}
+}
+
+void
+pnfs_destroy_layout(struct nfs_inode *nfsi)
+{
+	struct pnfs_layout_hdr *lo;
+	LIST_HEAD(tmp_list);
+
+	spin_lock(&nfsi->vfs_inode.i_lock);
+	lo = nfsi->layout;
+	if (lo) {
+		pnfs_clear_lseg_list(lo, &tmp_list);
+		/* Matched by refcount set to 1 in alloc_init_layout_hdr */
+		put_layout_hdr_locked(lo);
+	}
+	spin_unlock(&nfsi->vfs_inode.i_lock);
+	pnfs_free_lseg_list(&tmp_list);
+}
+
+/*
+ * Called by the state manger to remove all layouts established under an
+ * expired lease.
+ */
+void
+pnfs_destroy_all_layouts(struct nfs_client *clp)
+{
+	struct pnfs_layout_hdr *lo;
+	LIST_HEAD(tmp_list);
+
+	spin_lock(&clp->cl_lock);
+	list_splice_init(&clp->cl_layouts, &tmp_list);
+	spin_unlock(&clp->cl_lock);
+
+	while (!list_empty(&tmp_list)) {
+		lo = list_entry(tmp_list.next, struct pnfs_layout_hdr,
+				layouts);
+		dprintk("%s freeing layout for inode %lu\n", __func__,
+			lo->inode->i_ino);
+		pnfs_destroy_layout(NFS_I(lo->inode));
+	}
+}
+
+/* update lo->stateid with new if is more recent
+ *
+ * lo->stateid could be the open stateid, in which case we just use what given.
+ */
+static void
+pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo,
+			const nfs4_stateid *new)
+{
+	nfs4_stateid *old = &lo->stateid;
+	bool overwrite = false;
+
+	write_seqlock(&lo->seqlock);
+	if (!test_bit(NFS_LAYOUT_STATEID_SET, &lo->state) ||
+	    memcmp(old->stateid.other, new->stateid.other, sizeof(new->stateid.other)))
+		overwrite = true;
+	else {
+		u32 oldseq, newseq;
+
+		oldseq = be32_to_cpu(old->stateid.seqid);
+		newseq = be32_to_cpu(new->stateid.seqid);
+		if ((int)(newseq - oldseq) > 0)
+			overwrite = true;
+	}
+	if (overwrite)
+		memcpy(&old->stateid, &new->stateid, sizeof(new->stateid));
+	write_sequnlock(&lo->seqlock);
+}
+
+static void
+pnfs_layout_from_open_stateid(struct pnfs_layout_hdr *lo,
+			      struct nfs4_state *state)
+{
+	int seq;
+
+	dprintk("--> %s\n", __func__);
+	write_seqlock(&lo->seqlock);
+	do {
+		seq = read_seqbegin(&state->seqlock);
+		memcpy(lo->stateid.data, state->stateid.data,
+		       sizeof(state->stateid.data));
+	} while (read_seqretry(&state->seqlock, seq));
+	set_bit(NFS_LAYOUT_STATEID_SET, &lo->state);
+	write_sequnlock(&lo->seqlock);
+	dprintk("<-- %s\n", __func__);
+}
+
+void
+pnfs_get_layout_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo,
+			struct nfs4_state *open_state)
+{
+	int seq;
+
+	dprintk("--> %s\n", __func__);
+	do {
+		seq = read_seqbegin(&lo->seqlock);
+		if (!test_bit(NFS_LAYOUT_STATEID_SET, &lo->state)) {
+			/* This will trigger retry of the read */
+			pnfs_layout_from_open_stateid(lo, open_state);
+		} else
+			memcpy(dst->data, lo->stateid.data,
+			       sizeof(lo->stateid.data));
+	} while (read_seqretry(&lo->seqlock, seq));
+	dprintk("<-- %s\n", __func__);
+}
+
+/*
+* Get layout from server.
+*    for now, assume that whole file layouts are requested.
+*    arg->offset: 0
+*    arg->length: all ones
+*/
+static struct pnfs_layout_segment *
+send_layoutget(struct pnfs_layout_hdr *lo,
+	   struct nfs_open_context *ctx,
+	   u32 iomode)
+{
+	struct inode *ino = lo->inode;
+	struct nfs_server *server = NFS_SERVER(ino);
+	struct nfs4_layoutget *lgp;
+	struct pnfs_layout_segment *lseg = NULL;
+
+	dprintk("--> %s\n", __func__);
+
+	BUG_ON(ctx == NULL);
+	lgp = kzalloc(sizeof(*lgp), GFP_KERNEL);
+	if (lgp == NULL) {
+		put_layout_hdr(lo->inode);
+		return NULL;
+	}
+	lgp->args.minlength = NFS4_MAX_UINT64;
+	lgp->args.maxcount = PNFS_LAYOUT_MAXSIZE;
+	lgp->args.range.iomode = iomode;
+	lgp->args.range.offset = 0;
+	lgp->args.range.length = NFS4_MAX_UINT64;
+	lgp->args.type = server->pnfs_curr_ld->id;
+	lgp->args.inode = ino;
+	lgp->args.ctx = get_nfs_open_context(ctx);
+	lgp->lsegpp = &lseg;
+
+	/* Synchronously retrieve layout information from server and
+	 * store in lseg.
+	 */
+	nfs4_proc_layoutget(lgp);
+	if (!lseg) {
+		/* remember that LAYOUTGET failed and suspend trying */
+		set_bit(lo_fail_bit(iomode), &lo->state);
+	}
+	return lseg;
+}
+
+/*
+ * Compare two layout segments for sorting into layout cache.
+ * We want to preferentially return RW over RO layouts, so ensure those
+ * are seen first.
+ */
+static s64
+cmp_layout(u32 iomode1, u32 iomode2)
+{
+	/* read > read/write */
+	return (int)(iomode2 == IOMODE_READ) - (int)(iomode1 == IOMODE_READ);
+}
+
+static void
+pnfs_insert_layout(struct pnfs_layout_hdr *lo,
+		   struct pnfs_layout_segment *lseg)
+{
+	struct pnfs_layout_segment *lp;
+	int found = 0;
+
+	dprintk("%s:Begin\n", __func__);
+
+	assert_spin_locked(&lo->inode->i_lock);
+	if (list_empty(&lo->segs)) {
+		struct nfs_client *clp = NFS_SERVER(lo->inode)->nfs_client;
+
+		spin_lock(&clp->cl_lock);
+		BUG_ON(!list_empty(&lo->layouts));
+		list_add_tail(&lo->layouts, &clp->cl_layouts);
+		spin_unlock(&clp->cl_lock);
+	}
+	list_for_each_entry(lp, &lo->segs, fi_list) {
+		if (cmp_layout(lp->range.iomode, lseg->range.iomode) > 0)
+			continue;
+		list_add_tail(&lseg->fi_list, &lp->fi_list);
+		dprintk("%s: inserted lseg %p "
+			"iomode %d offset %llu length %llu before "
+			"lp %p iomode %d offset %llu length %llu\n",
+			__func__, lseg, lseg->range.iomode,
+			lseg->range.offset, lseg->range.length,
+			lp, lp->range.iomode, lp->range.offset,
+			lp->range.length);
+		found = 1;
+		break;
+	}
+	if (!found) {
+		list_add_tail(&lseg->fi_list, &lo->segs);
+		dprintk("%s: inserted lseg %p "
+			"iomode %d offset %llu length %llu at tail\n",
+			__func__, lseg, lseg->range.iomode,
+			lseg->range.offset, lseg->range.length);
+	}
+	get_layout_hdr_locked(lo);
+
+	dprintk("%s:Return\n", __func__);
+}
+
+static struct pnfs_layout_hdr *
+alloc_init_layout_hdr(struct inode *ino)
+{
+	struct pnfs_layout_hdr *lo;
+
+	lo = kzalloc(sizeof(struct pnfs_layout_hdr), GFP_KERNEL);
+	if (!lo)
+		return NULL;
+	lo->refcount = 1;
+	INIT_LIST_HEAD(&lo->layouts);
+	INIT_LIST_HEAD(&lo->segs);
+	seqlock_init(&lo->seqlock);
+	lo->inode = ino;
+	return lo;
+}
+
+static struct pnfs_layout_hdr *
+pnfs_find_alloc_layout(struct inode *ino)
+{
+	struct nfs_inode *nfsi = NFS_I(ino);
+	struct pnfs_layout_hdr *new = NULL;
+
+	dprintk("%s Begin ino=%p layout=%p\n", __func__, ino, nfsi->layout);
+
+	assert_spin_locked(&ino->i_lock);
+	if (nfsi->layout)
+		return nfsi->layout;
+
+	spin_unlock(&ino->i_lock);
+	new = alloc_init_layout_hdr(ino);
+	spin_lock(&ino->i_lock);
+
+	if (likely(nfsi->layout == NULL))	/* Won the race? */
+		nfsi->layout = new;
+	else
+		kfree(new);
+	return nfsi->layout;
+}
+
+/*
+ * iomode matching rules:
+ * iomode	lseg	match
+ * -----	-----	-----
+ * ANY		READ	true
+ * ANY		RW	true
+ * RW		READ	false
+ * RW		RW	true
+ * READ		READ	true
+ * READ		RW	true
+ */
+static int
+is_matching_lseg(struct pnfs_layout_segment *lseg, u32 iomode)
+{
+	return (iomode != IOMODE_RW || lseg->range.iomode == IOMODE_RW);
+}
+
+/*
+ * lookup range in layout
+ */
+static struct pnfs_layout_segment *
+pnfs_has_layout(struct pnfs_layout_hdr *lo, u32 iomode)
+{
+	struct pnfs_layout_segment *lseg, *ret = NULL;
+
+	dprintk("%s:Begin\n", __func__);
+
+	assert_spin_locked(&lo->inode->i_lock);
+	list_for_each_entry(lseg, &lo->segs, fi_list) {
+		if (is_matching_lseg(lseg, iomode)) {
+			ret = lseg;
+			break;
+		}
+		if (cmp_layout(iomode, lseg->range.iomode) > 0)
+			break;
+	}
+
+	dprintk("%s:Return lseg %p ref %d\n",
+		__func__, ret, ret ? atomic_read(&ret->kref.refcount) : 0);
+	return ret;
+}
+
+/*
+ * Layout segment is retreived from the server if not cached.
+ * The appropriate layout segment is referenced and returned to the caller.
+ */
+struct pnfs_layout_segment *
+pnfs_update_layout(struct inode *ino,
+		   struct nfs_open_context *ctx,
+		   enum pnfs_iomode iomode)
+{
+	struct nfs_inode *nfsi = NFS_I(ino);
+	struct pnfs_layout_hdr *lo;
+	struct pnfs_layout_segment *lseg = NULL;
+
+	if (!pnfs_enabled_sb(NFS_SERVER(ino)))
+		return NULL;
+	spin_lock(&ino->i_lock);
+	lo = pnfs_find_alloc_layout(ino);
+	if (lo == NULL) {
+		dprintk("%s ERROR: can't get pnfs_layout_hdr\n", __func__);
+		goto out_unlock;
+	}
+
+	/* Check to see if the layout for the given range already exists */
+	lseg = pnfs_has_layout(lo, iomode);
+	if (lseg) {
+		dprintk("%s: Using cached lseg %p for iomode %d)\n",
+			__func__, lseg, iomode);
+		goto out_unlock;
+	}
+
+	/* if LAYOUTGET already failed once we don't try again */
+	if (test_bit(lo_fail_bit(iomode), &nfsi->layout->state))
+		goto out_unlock;
+
+	get_layout_hdr_locked(lo); /* Matched in nfs4_layoutget_release */
+	spin_unlock(&ino->i_lock);
+
+	lseg = send_layoutget(lo, ctx, iomode);
+out:
+	dprintk("%s end, state 0x%lx lseg %p\n", __func__,
+		nfsi->layout->state, lseg);
+	return lseg;
+out_unlock:
+	spin_unlock(&ino->i_lock);
+	goto out;
+}
+
+int
+pnfs_layout_process(struct nfs4_layoutget *lgp)
+{
+	struct pnfs_layout_hdr *lo = NFS_I(lgp->args.inode)->layout;
+	struct nfs4_layoutget_res *res = &lgp->res;
+	struct pnfs_layout_segment *lseg;
+	struct inode *ino = lo->inode;
+	int status = 0;
+
+	/* Inject layout blob into I/O device driver */
+	lseg = NFS_SERVER(ino)->pnfs_curr_ld->alloc_lseg(lo, res);
+	if (!lseg || IS_ERR(lseg)) {
+		if (!lseg)
+			status = -ENOMEM;
+		else
+			status = PTR_ERR(lseg);
+		dprintk("%s: Could not allocate layout: error %d\n",
+		       __func__, status);
+		goto out;
+	}
+
+	spin_lock(&ino->i_lock);
+	init_lseg(lo, lseg);
+	lseg->range = res->range;
+	*lgp->lsegpp = lseg;
+	pnfs_insert_layout(lo, lseg);
+
+	/* Done processing layoutget. Set the layout stateid */
+	pnfs_set_layout_stateid(lo, &res->stateid);
+	spin_unlock(&ino->i_lock);
+out:
+	return status;
+}
+
+/*
+ * Device ID cache. Currently supports one layout type per struct nfs_client.
+ * Add layout type to the lookup key to expand to support multiple types.
+ */
+int
+pnfs_alloc_init_deviceid_cache(struct nfs_client *clp,
+			 void (*free_callback)(struct pnfs_deviceid_node *))
+{
+	struct pnfs_deviceid_cache *c;
+
+	c = kzalloc(sizeof(struct pnfs_deviceid_cache), GFP_KERNEL);
+	if (!c)
+		return -ENOMEM;
+	spin_lock(&clp->cl_lock);
+	if (clp->cl_devid_cache != NULL) {
+		atomic_inc(&clp->cl_devid_cache->dc_ref);
+		dprintk("%s [kref [%d]]\n", __func__,
+			atomic_read(&clp->cl_devid_cache->dc_ref));
+		kfree(c);
+	} else {
+		/* kzalloc initializes hlists */
+		spin_lock_init(&c->dc_lock);
+		atomic_set(&c->dc_ref, 1);
+		c->dc_free_callback = free_callback;
+		clp->cl_devid_cache = c;
+		dprintk("%s [new]\n", __func__);
+	}
+	spin_unlock(&clp->cl_lock);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pnfs_alloc_init_deviceid_cache);
+
+/*
+ * Called from pnfs_layoutdriver_type->free_lseg
+ * last layout segment reference frees deviceid
+ */
+void
+pnfs_put_deviceid(struct pnfs_deviceid_cache *c,
+		  struct pnfs_deviceid_node *devid)
+{
+	struct nfs4_deviceid *id = &devid->de_id;
+	struct pnfs_deviceid_node *d;
+	struct hlist_node *n;
+	long h = nfs4_deviceid_hash(id);
+
+	dprintk("%s [%d]\n", __func__, atomic_read(&devid->de_ref));
+	if (!atomic_dec_and_lock(&devid->de_ref, &c->dc_lock))
+		return;
+
+	hlist_for_each_entry_rcu(d, n, &c->dc_deviceids[h], de_node)
+		if (!memcmp(&d->de_id, id, sizeof(*id))) {
+			hlist_del_rcu(&d->de_node);
+			spin_unlock(&c->dc_lock);
+			synchronize_rcu();
+			c->dc_free_callback(devid);
+			return;
+		}
+	spin_unlock(&c->dc_lock);
+	/* Why wasn't it found in  the list? */
+	BUG();
+}
+EXPORT_SYMBOL_GPL(pnfs_put_deviceid);
+
+/* Find and reference a deviceid */
+struct pnfs_deviceid_node *
+pnfs_find_get_deviceid(struct pnfs_deviceid_cache *c, struct nfs4_deviceid *id)
+{
+	struct pnfs_deviceid_node *d;
+	struct hlist_node *n;
+	long hash = nfs4_deviceid_hash(id);
+
+	dprintk("--> %s hash %ld\n", __func__, hash);
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(d, n, &c->dc_deviceids[hash], de_node) {
+		if (!memcmp(&d->de_id, id, sizeof(*id))) {
+			if (!atomic_inc_not_zero(&d->de_ref)) {
+				goto fail;
+			} else {
+				rcu_read_unlock();
+				return d;
+			}
+		}
+	}
+fail:
+	rcu_read_unlock();
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(pnfs_find_get_deviceid);
+
+/*
+ * Add a deviceid to the cache.
+ * GETDEVICEINFOs for same deviceid can race. If deviceid is found, discard new
+ */
+struct pnfs_deviceid_node *
+pnfs_add_deviceid(struct pnfs_deviceid_cache *c, struct pnfs_deviceid_node *new)
+{
+	struct pnfs_deviceid_node *d;
+	long hash = nfs4_deviceid_hash(&new->de_id);
+
+	dprintk("--> %s hash %ld\n", __func__, hash);
+	spin_lock(&c->dc_lock);
+	d = pnfs_find_get_deviceid(c, &new->de_id);
+	if (d) {
+		spin_unlock(&c->dc_lock);
+		dprintk("%s [discard]\n", __func__);
+		c->dc_free_callback(new);
+		return d;
+	}
+	INIT_HLIST_NODE(&new->de_node);
+	atomic_set(&new->de_ref, 1);
+	hlist_add_head_rcu(&new->de_node, &c->dc_deviceids[hash]);
+	spin_unlock(&c->dc_lock);
+	dprintk("%s [new]\n", __func__);
+	return new;
+}
+EXPORT_SYMBOL_GPL(pnfs_add_deviceid);
+
+void
+pnfs_put_deviceid_cache(struct nfs_client *clp)
+{
+	struct pnfs_deviceid_cache *local = clp->cl_devid_cache;
+
+	dprintk("--> %s cl_devid_cache %p\n", __func__, clp->cl_devid_cache);
+	if (atomic_dec_and_lock(&local->dc_ref, &clp->cl_lock)) {
+		int i;
+		/* Verify cache is empty */
+		for (i = 0; i < NFS4_DEVICE_ID_HASH_SIZE; i++)
+			BUG_ON(!hlist_empty(&local->dc_deviceids[i]));
+		clp->cl_devid_cache = NULL;
+		spin_unlock(&clp->cl_lock);
+		kfree(local);
+	}
+}
+EXPORT_SYMBOL_GPL(pnfs_put_deviceid_cache);
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
new file mode 100644
index 0000000..e12367d
--- /dev/null
+++ b/fs/nfs/pnfs.h
@@ -0,0 +1,189 @@
+/*
+ *  pNFS client data structures.
+ *
+ *  Copyright (c) 2002
+ *  The Regents of the University of Michigan
+ *  All Rights Reserved
+ *
+ *  Dean Hildebrand <dhildebz@umich.edu>
+ *
+ *  Permission is granted to use, copy, create derivative works, and
+ *  redistribute this software and such derivative works for any purpose,
+ *  so long as the name of the University of Michigan is not used in
+ *  any advertising or publicity pertaining to the use or distribution
+ *  of this software without specific, written prior authorization. If
+ *  the above copyright notice or any other identification of the
+ *  University of Michigan is included in any copy of any portion of
+ *  this software, then the disclaimer below must also be included.
+ *
+ *  This software is provided as is, without representation or warranty
+ *  of any kind either express or implied, including without limitation
+ *  the implied warranties of merchantability, fitness for a particular
+ *  purpose, or noninfringement.  The Regents of the University of
+ *  Michigan shall not be liable for any damages, including special,
+ *  indirect, incidental, or consequential damages, with respect to any
+ *  claim arising out of or in connection with the use of the software,
+ *  even if it has been or is hereafter advised of the possibility of
+ *  such damages.
+ */
+
+#ifndef FS_NFS_PNFS_H
+#define FS_NFS_PNFS_H
+
+struct pnfs_layout_segment {
+	struct list_head fi_list;
+	struct pnfs_layout_range range;
+	struct kref kref;
+	struct pnfs_layout_hdr *layout;
+};
+
+#ifdef CONFIG_NFS_V4_1
+
+#define LAYOUT_NFSV4_1_MODULE_PREFIX "nfs-layouttype4"
+
+enum {
+	NFS_LAYOUT_RO_FAILED = 0,	/* get ro layout failed stop trying */
+	NFS_LAYOUT_RW_FAILED,		/* get rw layout failed stop trying */
+	NFS_LAYOUT_STATEID_SET,		/* have a valid layout stateid */
+};
+
+/* Per-layout driver specific registration structure */
+struct pnfs_layoutdriver_type {
+	struct list_head pnfs_tblid;
+	const u32 id;
+	const char *name;
+	struct module *owner;
+	int (*set_layoutdriver) (struct nfs_server *);
+	int (*clear_layoutdriver) (struct nfs_server *);
+	struct pnfs_layout_segment * (*alloc_lseg) (struct pnfs_layout_hdr *layoutid, struct nfs4_layoutget_res *lgr);
+	void (*free_lseg) (struct pnfs_layout_segment *lseg);
+};
+
+struct pnfs_layout_hdr {
+	unsigned long		refcount;
+	struct list_head	layouts;   /* other client layouts */
+	struct list_head	segs;      /* layout segments list */
+	seqlock_t		seqlock;   /* Protects the stateid */
+	nfs4_stateid		stateid;
+	unsigned long		state;
+	struct inode		*inode;
+};
+
+struct pnfs_device {
+	struct nfs4_deviceid dev_id;
+	unsigned int  layout_type;
+	unsigned int  mincount;
+	struct page **pages;
+	void          *area;
+	unsigned int  pgbase;
+	unsigned int  pglen;
+};
+
+/*
+ * Device ID RCU cache. A device ID is unique per client ID and layout type.
+ */
+#define NFS4_DEVICE_ID_HASH_BITS	5
+#define NFS4_DEVICE_ID_HASH_SIZE	(1 << NFS4_DEVICE_ID_HASH_BITS)
+#define NFS4_DEVICE_ID_HASH_MASK	(NFS4_DEVICE_ID_HASH_SIZE - 1)
+
+static inline u32
+nfs4_deviceid_hash(struct nfs4_deviceid *id)
+{
+	unsigned char *cptr = (unsigned char *)id->data;
+	unsigned int nbytes = NFS4_DEVICEID4_SIZE;
+	u32 x = 0;
+
+	while (nbytes--) {
+		x *= 37;
+		x += *cptr++;
+	}
+	return x & NFS4_DEVICE_ID_HASH_MASK;
+}
+
+struct pnfs_deviceid_node {
+	struct hlist_node	de_node;
+	struct nfs4_deviceid	de_id;
+	atomic_t		de_ref;
+};
+
+struct pnfs_deviceid_cache {
+	spinlock_t		dc_lock;
+	atomic_t		dc_ref;
+	void			(*dc_free_callback)(struct pnfs_deviceid_node *);
+	struct hlist_head	dc_deviceids[NFS4_DEVICE_ID_HASH_SIZE];
+};
+
+extern int pnfs_alloc_init_deviceid_cache(struct nfs_client *,
+			void (*free_callback)(struct pnfs_deviceid_node *));
+extern void pnfs_put_deviceid_cache(struct nfs_client *);
+extern struct pnfs_deviceid_node *pnfs_find_get_deviceid(
+				struct pnfs_deviceid_cache *,
+				struct nfs4_deviceid *);
+extern struct pnfs_deviceid_node *pnfs_add_deviceid(
+				struct pnfs_deviceid_cache *,
+				struct pnfs_deviceid_node *);
+extern void pnfs_put_deviceid(struct pnfs_deviceid_cache *c,
+			      struct pnfs_deviceid_node *devid);
+
+extern int pnfs_register_layoutdriver(struct pnfs_layoutdriver_type *);
+extern void pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *);
+
+/* nfs4proc.c */
+extern int nfs4_proc_getdeviceinfo(struct nfs_server *server,
+				   struct pnfs_device *dev);
+extern int nfs4_proc_layoutget(struct nfs4_layoutget *lgp);
+
+/* pnfs.c */
+struct pnfs_layout_segment *
+pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx,
+		   enum pnfs_iomode access_type);
+void set_pnfs_layoutdriver(struct nfs_server *, u32 id);
+void unset_pnfs_layoutdriver(struct nfs_server *);
+int pnfs_layout_process(struct nfs4_layoutget *lgp);
+void pnfs_destroy_layout(struct nfs_inode *);
+void pnfs_destroy_all_layouts(struct nfs_client *);
+void put_layout_hdr(struct inode *inode);
+void pnfs_get_layout_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo,
+			     struct nfs4_state *open_state);
+
+
+static inline int lo_fail_bit(u32 iomode)
+{
+	return iomode == IOMODE_RW ?
+			 NFS_LAYOUT_RW_FAILED : NFS_LAYOUT_RO_FAILED;
+}
+
+/* Return true if a layout driver is being used for this mountpoint */
+static inline int pnfs_enabled_sb(struct nfs_server *nfss)
+{
+	return nfss->pnfs_curr_ld != NULL;
+}
+
+#else  /* CONFIG_NFS_V4_1 */
+
+static inline void pnfs_destroy_all_layouts(struct nfs_client *clp)
+{
+}
+
+static inline void pnfs_destroy_layout(struct nfs_inode *nfsi)
+{
+}
+
+static inline struct pnfs_layout_segment *
+pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx,
+		   enum pnfs_iomode access_type)
+{
+	return NULL;
+}
+
+static inline void set_pnfs_layoutdriver(struct nfs_server *s, u32 id)
+{
+}
+
+static inline void unset_pnfs_layoutdriver(struct nfs_server *s)
+{
+}
+
+#endif /* CONFIG_NFS_V4_1 */
+
+#endif /* FS_NFS_PNFS_H */
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 611bec2..58e7f84 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -258,7 +258,7 @@
 
 static int
 nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
-		int flags, struct nameidata *nd)
+		int flags, struct nfs_open_context *ctx)
 {
 	struct nfs_createdata *data;
 	struct rpc_message msg = {
@@ -365,17 +365,32 @@
 	return 1;
 }
 
+static void
+nfs_proc_rename_setup(struct rpc_message *msg, struct inode *dir)
+{
+	msg->rpc_proc = &nfs_procedures[NFSPROC_RENAME];
+}
+
+static int
+nfs_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
+		     struct inode *new_dir)
+{
+	if (nfs_async_handle_expired_key(task))
+		return 0;
+	nfs_mark_for_revalidate(old_dir);
+	nfs_mark_for_revalidate(new_dir);
+	return 1;
+}
+
 static int
 nfs_proc_rename(struct inode *old_dir, struct qstr *old_name,
 		struct inode *new_dir, struct qstr *new_name)
 {
 	struct nfs_renameargs	arg = {
-		.fromfh		= NFS_FH(old_dir),
-		.fromname	= old_name->name,
-		.fromlen	= old_name->len,
-		.tofh		= NFS_FH(new_dir),
-		.toname		= new_name->name,
-		.tolen		= new_name->len
+		.old_dir	= NFS_FH(old_dir),
+		.old_name	= old_name,
+		.new_dir	= NFS_FH(new_dir),
+		.new_name	= new_name,
 	};
 	struct rpc_message msg = {
 		.rpc_proc	= &nfs_procedures[NFSPROC_RENAME],
@@ -519,14 +534,14 @@
  */
 static int
 nfs_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
-		 u64 cookie, struct page *page, unsigned int count, int plus)
+		 u64 cookie, struct page **pages, unsigned int count, int plus)
 {
 	struct inode		*dir = dentry->d_inode;
 	struct nfs_readdirargs	arg = {
 		.fh		= NFS_FH(dir),
 		.cookie		= cookie,
 		.count		= count,
-		.pages		= &page,
+		.pages		= pages,
 	};
 	struct rpc_message	msg = {
 		.rpc_proc	= &nfs_procedures[NFSPROC_READDIR],
@@ -705,6 +720,8 @@
 	.unlink_setup	= nfs_proc_unlink_setup,
 	.unlink_done	= nfs_proc_unlink_done,
 	.rename		= nfs_proc_rename,
+	.rename_setup	= nfs_proc_rename_setup,
+	.rename_done	= nfs_proc_rename_done,
 	.link		= nfs_proc_link,
 	.symlink	= nfs_proc_symlink,
 	.mkdir		= nfs_proc_mkdir,
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 87adc27..e4b62c6 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -25,6 +25,7 @@
 #include "internal.h"
 #include "iostat.h"
 #include "fscache.h"
+#include "pnfs.h"
 
 #define NFSDBG_FACILITY		NFSDBG_PAGECACHE
 
@@ -46,7 +47,6 @@
 		memset(p, 0, sizeof(*p));
 		INIT_LIST_HEAD(&p->pages);
 		p->npages = pagecount;
-		p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
 		if (pagecount <= ARRAY_SIZE(p->page_array))
 			p->pagevec = p->page_array;
 		else {
@@ -121,6 +121,7 @@
 	len = nfs_page_length(page);
 	if (len == 0)
 		return nfs_return_empty_page(page);
+	pnfs_update_layout(inode, ctx, IOMODE_READ);
 	new = nfs_create_request(ctx, inode, page, 0, len);
 	if (IS_ERR(new)) {
 		unlock_page(page);
@@ -625,6 +626,7 @@
 	if (ret == 0)
 		goto read_complete; /* all pages were read */
 
+	pnfs_update_layout(inode, desc.ctx, IOMODE_READ);
 	if (rsize < PAGE_CACHE_SIZE)
 		nfs_pageio_init(&pgio, inode, nfs_pagein_multi, rsize, 0);
 	else
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index f4cbf0c..3600ec7 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -100,6 +100,7 @@
 	Opt_addr, Opt_mountaddr, Opt_clientaddr,
 	Opt_lookupcache,
 	Opt_fscache_uniq,
+	Opt_local_lock,
 
 	/* Special mount options */
 	Opt_userspace, Opt_deprecated, Opt_sloppy,
@@ -171,6 +172,7 @@
 
 	{ Opt_lookupcache, "lookupcache=%s" },
 	{ Opt_fscache_uniq, "fsc=%s" },
+	{ Opt_local_lock, "local_lock=%s" },
 
 	{ Opt_err, NULL }
 };
@@ -236,6 +238,22 @@
 	{ Opt_lookupcache_err, NULL }
 };
 
+enum {
+	Opt_local_lock_all, Opt_local_lock_flock, Opt_local_lock_posix,
+	Opt_local_lock_none,
+
+	Opt_local_lock_err
+};
+
+static match_table_t nfs_local_lock_tokens = {
+	{ Opt_local_lock_all, "all" },
+	{ Opt_local_lock_flock, "flock" },
+	{ Opt_local_lock_posix, "posix" },
+	{ Opt_local_lock_none, "none" },
+
+	{ Opt_local_lock_err, NULL }
+};
+
 
 static void nfs_umount_begin(struct super_block *);
 static int  nfs_statfs(struct dentry *, struct kstatfs *);
@@ -622,6 +640,7 @@
 	const struct proc_nfs_info *nfs_infop;
 	struct nfs_client *clp = nfss->nfs_client;
 	u32 version = clp->rpc_ops->version;
+	int local_flock, local_fcntl;
 
 	seq_printf(m, ",vers=%u", version);
 	seq_printf(m, ",rsize=%u", nfss->rsize);
@@ -670,6 +689,18 @@
 		else
 			seq_printf(m, ",lookupcache=pos");
 	}
+
+	local_flock = nfss->flags & NFS_MOUNT_LOCAL_FLOCK;
+	local_fcntl = nfss->flags & NFS_MOUNT_LOCAL_FCNTL;
+
+	if (!local_flock && !local_fcntl)
+		seq_printf(m, ",local_lock=none");
+	else if (local_flock && local_fcntl)
+		seq_printf(m, ",local_lock=all");
+	else if (local_flock)
+		seq_printf(m, ",local_lock=flock");
+	else
+		seq_printf(m, ",local_lock=posix");
 }
 
 /*
@@ -1017,9 +1048,13 @@
 			break;
 		case Opt_lock:
 			mnt->flags &= ~NFS_MOUNT_NONLM;
+			mnt->flags &= ~(NFS_MOUNT_LOCAL_FLOCK |
+					NFS_MOUNT_LOCAL_FCNTL);
 			break;
 		case Opt_nolock:
 			mnt->flags |= NFS_MOUNT_NONLM;
+			mnt->flags |= (NFS_MOUNT_LOCAL_FLOCK |
+				       NFS_MOUNT_LOCAL_FCNTL);
 			break;
 		case Opt_v2:
 			mnt->flags &= ~NFS_MOUNT_VER3;
@@ -1420,6 +1455,34 @@
 			mnt->fscache_uniq = string;
 			mnt->options |= NFS_OPTION_FSCACHE;
 			break;
+		case Opt_local_lock:
+			string = match_strdup(args);
+			if (string == NULL)
+				goto out_nomem;
+			token = match_token(string, nfs_local_lock_tokens,
+					args);
+			kfree(string);
+			switch (token) {
+			case Opt_local_lock_all:
+				mnt->flags |= (NFS_MOUNT_LOCAL_FLOCK |
+					       NFS_MOUNT_LOCAL_FCNTL);
+				break;
+			case Opt_local_lock_flock:
+				mnt->flags |= NFS_MOUNT_LOCAL_FLOCK;
+				break;
+			case Opt_local_lock_posix:
+				mnt->flags |= NFS_MOUNT_LOCAL_FCNTL;
+				break;
+			case Opt_local_lock_none:
+				mnt->flags &= ~(NFS_MOUNT_LOCAL_FLOCK |
+						NFS_MOUNT_LOCAL_FCNTL);
+				break;
+			default:
+				dfprintk(MOUNT, "NFS:	invalid	"
+						"local_lock argument\n");
+				return 0;
+			};
+			break;
 
 		/*
 		 * Special options
@@ -1825,6 +1888,12 @@
 		if (!args->nfs_server.hostname)
 			goto out_nomem;
 
+		if (!(data->flags & NFS_MOUNT_NONLM))
+			args->flags &= ~(NFS_MOUNT_LOCAL_FLOCK|
+					 NFS_MOUNT_LOCAL_FCNTL);
+		else
+			args->flags |= (NFS_MOUNT_LOCAL_FLOCK|
+					NFS_MOUNT_LOCAL_FCNTL);
 		/*
 		 * The legacy version 6 binary mount data from userspace has a
 		 * field used only to transport selinux information into the
@@ -2441,7 +2510,8 @@
 
 static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *args)
 {
-	args->flags &= ~(NFS_MOUNT_NONLM|NFS_MOUNT_NOACL|NFS_MOUNT_VER3);
+	args->flags &= ~(NFS_MOUNT_NONLM|NFS_MOUNT_NOACL|NFS_MOUNT_VER3|
+			 NFS_MOUNT_LOCAL_FLOCK|NFS_MOUNT_LOCAL_FCNTL);
 }
 
 static int nfs4_validate_text_mount_data(void *options,
diff --git a/fs/nfs/sysctl.c b/fs/nfs/sysctl.c
index ad4d2e7..978aaeb 100644
--- a/fs/nfs/sysctl.c
+++ b/fs/nfs/sysctl.c
@@ -32,6 +32,7 @@
 		.extra1 = (int *)&nfs_set_port_min,
 		.extra2 = (int *)&nfs_set_port_max,
 	},
+#ifndef CONFIG_NFS_USE_NEW_IDMAPPER
 	{
 		.procname = "idmap_cache_timeout",
 		.data = &nfs_idmap_cache_timeout,
@@ -39,6 +40,7 @@
 		.mode = 0644,
 		.proc_handler = proc_dointvec_jiffies,
 	},
+#endif /* CONFIG_NFS_USE_NEW_IDMAPPER */
 #endif
 	{
 		.procname	= "nfs_mountpoint_timeout",
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index 2f84ada..9a16bad 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -13,9 +13,12 @@
 #include <linux/nfs_fs.h>
 #include <linux/sched.h>
 #include <linux/wait.h>
+#include <linux/namei.h>
 
 #include "internal.h"
 #include "nfs4_fs.h"
+#include "iostat.h"
+#include "delegation.h"
 
 struct nfs_unlinkdata {
 	struct hlist_node list;
@@ -244,7 +247,7 @@
  * @dir: parent directory of dentry
  * @dentry: dentry to unlink
  */
-int
+static int
 nfs_async_unlink(struct inode *dir, struct dentry *dentry)
 {
 	struct nfs_unlinkdata *data;
@@ -259,7 +262,6 @@
 		status = PTR_ERR(data->cred);
 		goto out_free;
 	}
-	data->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
 	data->res.dir_attr = &data->dir_attr;
 
 	status = -EBUSY;
@@ -303,3 +305,256 @@
 	if (data != NULL && (NFS_STALE(inode) || !nfs_call_unlink(dentry, data)))
 		nfs_free_unlinkdata(data);
 }
+
+/* Cancel a queued async unlink. Called when a sillyrename run fails. */
+static void
+nfs_cancel_async_unlink(struct dentry *dentry)
+{
+	spin_lock(&dentry->d_lock);
+	if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
+		struct nfs_unlinkdata *data = dentry->d_fsdata;
+
+		dentry->d_flags &= ~DCACHE_NFSFS_RENAMED;
+		spin_unlock(&dentry->d_lock);
+		nfs_free_unlinkdata(data);
+		return;
+	}
+	spin_unlock(&dentry->d_lock);
+}
+
+struct nfs_renamedata {
+	struct nfs_renameargs	args;
+	struct nfs_renameres	res;
+	struct rpc_cred		*cred;
+	struct inode		*old_dir;
+	struct dentry		*old_dentry;
+	struct nfs_fattr	old_fattr;
+	struct inode		*new_dir;
+	struct dentry		*new_dentry;
+	struct nfs_fattr	new_fattr;
+};
+
+/**
+ * nfs_async_rename_done - Sillyrename post-processing
+ * @task: rpc_task of the sillyrename
+ * @calldata: nfs_renamedata for the sillyrename
+ *
+ * Do the directory attribute updates and the d_move
+ */
+static void nfs_async_rename_done(struct rpc_task *task, void *calldata)
+{
+	struct nfs_renamedata *data = calldata;
+	struct inode *old_dir = data->old_dir;
+	struct inode *new_dir = data->new_dir;
+
+	if (!NFS_PROTO(old_dir)->rename_done(task, old_dir, new_dir)) {
+		nfs_restart_rpc(task, NFS_SERVER(old_dir)->nfs_client);
+		return;
+	}
+
+	if (task->tk_status != 0) {
+		nfs_cancel_async_unlink(data->old_dentry);
+		return;
+	}
+
+	nfs_set_verifier(data->old_dentry, nfs_save_change_attribute(old_dir));
+	d_move(data->old_dentry, data->new_dentry);
+}
+
+/**
+ * nfs_async_rename_release - Release the sillyrename data.
+ * @calldata: the struct nfs_renamedata to be released
+ */
+static void nfs_async_rename_release(void *calldata)
+{
+	struct nfs_renamedata	*data = calldata;
+	struct super_block *sb = data->old_dir->i_sb;
+
+	if (data->old_dentry->d_inode)
+		nfs_mark_for_revalidate(data->old_dentry->d_inode);
+
+	dput(data->old_dentry);
+	dput(data->new_dentry);
+	iput(data->old_dir);
+	iput(data->new_dir);
+	nfs_sb_deactive(sb);
+	put_rpccred(data->cred);
+	kfree(data);
+}
+
+#if defined(CONFIG_NFS_V4_1)
+static void nfs_rename_prepare(struct rpc_task *task, void *calldata)
+{
+	struct nfs_renamedata *data = calldata;
+	struct nfs_server *server = NFS_SERVER(data->old_dir);
+
+	if (nfs4_setup_sequence(server, &data->args.seq_args,
+				&data->res.seq_res, 1, task))
+		return;
+	rpc_call_start(task);
+}
+#endif /* CONFIG_NFS_V4_1 */
+
+static const struct rpc_call_ops nfs_rename_ops = {
+	.rpc_call_done = nfs_async_rename_done,
+	.rpc_release = nfs_async_rename_release,
+#if defined(CONFIG_NFS_V4_1)
+	.rpc_call_prepare = nfs_rename_prepare,
+#endif /* CONFIG_NFS_V4_1 */
+};
+
+/**
+ * nfs_async_rename - perform an asynchronous rename operation
+ * @old_dir: directory that currently holds the dentry to be renamed
+ * @new_dir: target directory for the rename
+ * @old_dentry: original dentry to be renamed
+ * @new_dentry: dentry to which the old_dentry should be renamed
+ *
+ * It's expected that valid references to the dentries and inodes are held
+ */
+static struct rpc_task *
+nfs_async_rename(struct inode *old_dir, struct inode *new_dir,
+		 struct dentry *old_dentry, struct dentry *new_dentry)
+{
+	struct nfs_renamedata *data;
+	struct rpc_message msg = { };
+	struct rpc_task_setup task_setup_data = {
+		.rpc_message = &msg,
+		.callback_ops = &nfs_rename_ops,
+		.workqueue = nfsiod_workqueue,
+		.rpc_client = NFS_CLIENT(old_dir),
+		.flags = RPC_TASK_ASYNC,
+	};
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (data == NULL)
+		return ERR_PTR(-ENOMEM);
+	task_setup_data.callback_data = data,
+
+	data->cred = rpc_lookup_cred();
+	if (IS_ERR(data->cred)) {
+		struct rpc_task *task = ERR_CAST(data->cred);
+		kfree(data);
+		return task;
+	}
+
+	msg.rpc_argp = &data->args;
+	msg.rpc_resp = &data->res;
+	msg.rpc_cred = data->cred;
+
+	/* set up nfs_renamedata */
+	data->old_dir = old_dir;
+	atomic_inc(&old_dir->i_count);
+	data->new_dir = new_dir;
+	atomic_inc(&new_dir->i_count);
+	data->old_dentry = dget(old_dentry);
+	data->new_dentry = dget(new_dentry);
+	nfs_fattr_init(&data->old_fattr);
+	nfs_fattr_init(&data->new_fattr);
+
+	/* set up nfs_renameargs */
+	data->args.old_dir = NFS_FH(old_dir);
+	data->args.old_name = &old_dentry->d_name;
+	data->args.new_dir = NFS_FH(new_dir);
+	data->args.new_name = &new_dentry->d_name;
+
+	/* set up nfs_renameres */
+	data->res.old_fattr = &data->old_fattr;
+	data->res.new_fattr = &data->new_fattr;
+
+	nfs_sb_active(old_dir->i_sb);
+
+	NFS_PROTO(data->old_dir)->rename_setup(&msg, old_dir);
+
+	return rpc_run_task(&task_setup_data);
+}
+
+/**
+ * nfs_sillyrename - Perform a silly-rename of a dentry
+ * @dir: inode of directory that contains dentry
+ * @dentry: dentry to be sillyrenamed
+ *
+ * NFSv2/3 is stateless and the server doesn't know when the client is
+ * holding a file open. To prevent application problems when a file is
+ * unlinked while it's still open, the client performs a "silly-rename".
+ * That is, it renames the file to a hidden file in the same directory,
+ * and only performs the unlink once the last reference to it is put.
+ *
+ * The final cleanup is done during dentry_iput.
+ */
+int
+nfs_sillyrename(struct inode *dir, struct dentry *dentry)
+{
+	static unsigned int sillycounter;
+	const int      fileidsize  = sizeof(NFS_FILEID(dentry->d_inode))*2;
+	const int      countersize = sizeof(sillycounter)*2;
+	const int      slen        = sizeof(".nfs")+fileidsize+countersize-1;
+	char           silly[slen+1];
+	struct dentry *sdentry;
+	struct rpc_task *task;
+	int            error = -EIO;
+
+	dfprintk(VFS, "NFS: silly-rename(%s/%s, ct=%d)\n",
+		dentry->d_parent->d_name.name, dentry->d_name.name,
+		atomic_read(&dentry->d_count));
+	nfs_inc_stats(dir, NFSIOS_SILLYRENAME);
+
+	/*
+	 * We don't allow a dentry to be silly-renamed twice.
+	 */
+	error = -EBUSY;
+	if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
+		goto out;
+
+	sprintf(silly, ".nfs%*.*Lx",
+		fileidsize, fileidsize,
+		(unsigned long long)NFS_FILEID(dentry->d_inode));
+
+	/* Return delegation in anticipation of the rename */
+	nfs_inode_return_delegation(dentry->d_inode);
+
+	sdentry = NULL;
+	do {
+		char *suffix = silly + slen - countersize;
+
+		dput(sdentry);
+		sillycounter++;
+		sprintf(suffix, "%*.*x", countersize, countersize, sillycounter);
+
+		dfprintk(VFS, "NFS: trying to rename %s to %s\n",
+				dentry->d_name.name, silly);
+
+		sdentry = lookup_one_len(silly, dentry->d_parent, slen);
+		/*
+		 * N.B. Better to return EBUSY here ... it could be
+		 * dangerous to delete the file while it's in use.
+		 */
+		if (IS_ERR(sdentry))
+			goto out;
+	} while (sdentry->d_inode != NULL); /* need negative lookup */
+
+	/* queue unlink first. Can't do this from rpc_release as it
+	 * has to allocate memory
+	 */
+	error = nfs_async_unlink(dir, dentry);
+	if (error)
+		goto out_dput;
+
+	/* run the rename task, undo unlink if it fails */
+	task = nfs_async_rename(dir, dir, dentry, sdentry);
+	if (IS_ERR(task)) {
+		error = -EBUSY;
+		nfs_cancel_async_unlink(dentry);
+		goto out_dput;
+	}
+
+	/* wait for the RPC task to complete, unless a SIGKILL intervenes */
+	error = rpc_wait_for_completion_task(task);
+	if (error == 0)
+		error = task->tk_status;
+	rpc_put_task(task);
+out_dput:
+	dput(sdentry);
+out:
+	return error;
+}
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 874972d..4c14c17 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -55,7 +55,6 @@
 	if (p) {
 		memset(p, 0, sizeof(*p));
 		INIT_LIST_HEAD(&p->pages);
-		p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
 	}
 	return p;
 }
@@ -75,7 +74,6 @@
 		memset(p, 0, sizeof(*p));
 		INIT_LIST_HEAD(&p->pages);
 		p->npages = pagecount;
-		p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
 		if (pagecount <= ARRAY_SIZE(p->page_array))
 			p->pagevec = p->page_array;
 		else {
@@ -292,9 +290,7 @@
 	nfs_add_stats(inode, NFSIOS_WRITEPAGES, 1);
 
 	nfs_pageio_cond_complete(pgio, page->index);
-	ret = nfs_page_async_flush(pgio, page,
-			wbc->sync_mode == WB_SYNC_NONE ||
-			wbc->nonblocking != 0);
+	ret = nfs_page_async_flush(pgio, page, wbc->sync_mode == WB_SYNC_NONE);
 	if (ret == -EAGAIN) {
 		redirty_page_for_writepage(wbc, page);
 		ret = 0;
@@ -1433,15 +1429,17 @@
 	int flags = FLUSH_SYNC;
 	int ret = 0;
 
-	/* Don't commit yet if this is a non-blocking flush and there are
-	 * lots of outstanding writes for this mapping.
-	 */
-	if (wbc->sync_mode == WB_SYNC_NONE &&
-	    nfsi->ncommit <= (nfsi->npages >> 1))
-		goto out_mark_dirty;
+	if (wbc->sync_mode == WB_SYNC_NONE) {
+		/* Don't commit yet if this is a non-blocking flush and there
+		 * are a lot of outstanding writes for this mapping.
+		 */
+		if (nfsi->ncommit <= (nfsi->npages >> 1))
+			goto out_mark_dirty;
 
-	if (wbc->nonblocking || wbc->for_background)
+		/* don't wait for the COMMIT response */
 		flags = 0;
+	}
+
 	ret = nfs_commit_inode(inode, flags);
 	if (ret >= 0) {
 		if (wbc->sync_mode == WB_SYNC_NONE) {
diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig
index 7cf4dda..31a78fc 100644
--- a/fs/nfsd/Kconfig
+++ b/fs/nfsd/Kconfig
@@ -29,6 +29,18 @@
 
 	  If unsure, say N.
 
+config NFSD_DEPRECATED
+	bool "Include support for deprecated syscall interface to NFSD"
+	depends on NFSD
+	default y
+	help
+	  The syscall interface to nfsd was obsoleted in 2.6.0 by a new
+	  filesystem based interface.  The old interface is due for removal
+	  in 2.6.40.  If you wish to remove the interface before then
+	  say N.
+
+	  In unsure, say Y.
+
 config NFSD_V2_ACL
 	bool
 	depends on NFSD
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index c2a4f71..c0fcb7a 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -28,9 +28,6 @@
 typedef struct auth_domain	svc_client;
 typedef struct svc_export	svc_export;
 
-static void		exp_do_unexport(svc_export *unexp);
-static int		exp_verify_string(char *cp, int max);
-
 /*
  * We have two caches.
  * One maps client+vfsmnt+dentry to export options - the export map
@@ -802,6 +799,7 @@
 	return ek;
 }
 
+#ifdef CONFIG_NFSD_DEPRECATED
 static int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv,
 		       struct svc_export *exp)
 {
@@ -852,6 +850,7 @@
 
 	return exp_find_key(clp, FSID_NUM, fsidv, NULL);
 }
+#endif
 
 static svc_export *exp_get_by_name(svc_client *clp, const struct path *path,
 				     struct cache_req *reqp)
@@ -893,6 +892,7 @@
 	return exp;
 }
 
+#ifdef CONFIG_NFSD_DEPRECATED
 /*
  * Hashtable locking. Write locks are placed only by user processes
  * wanting to modify export information.
@@ -925,6 +925,19 @@
 {
 	up_write(&hash_sem);
 }
+#else
+
+/* hash_sem not needed once deprecated interface is removed */
+void exp_readlock(void) {}
+static inline void exp_writelock(void){}
+void exp_readunlock(void) {}
+static inline void exp_writeunlock(void){}
+
+#endif
+
+#ifdef CONFIG_NFSD_DEPRECATED
+static void		exp_do_unexport(svc_export *unexp);
+static int		exp_verify_string(char *cp, int max);
 
 static void exp_fsid_unhash(struct svc_export *exp)
 {
@@ -935,10 +948,9 @@
 
 	ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid);
 	if (!IS_ERR(ek)) {
-		ek->h.expiry_time = get_seconds()-1;
+		sunrpc_invalidate(&ek->h, &svc_expkey_cache);
 		cache_put(&ek->h, &svc_expkey_cache);
 	}
-	svc_expkey_cache.nextcheck = get_seconds();
 }
 
 static int exp_fsid_hash(svc_client *clp, struct svc_export *exp)
@@ -973,10 +985,9 @@
 
 	ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino);
 	if (!IS_ERR(ek)) {
-		ek->h.expiry_time = get_seconds()-1;
+		sunrpc_invalidate(&ek->h, &svc_expkey_cache);
 		cache_put(&ek->h, &svc_expkey_cache);
 	}
-	svc_expkey_cache.nextcheck = get_seconds();
 }
 	
 /*
@@ -1097,8 +1108,7 @@
 static void
 exp_do_unexport(svc_export *unexp)
 {
-	unexp->h.expiry_time = get_seconds()-1;
-	svc_export_cache.nextcheck = get_seconds();
+	sunrpc_invalidate(&unexp->h, &svc_export_cache);
 	exp_unhash(unexp);
 	exp_fsid_unhash(unexp);
 }
@@ -1150,6 +1160,7 @@
 	exp_writeunlock();
 	return err;
 }
+#endif /* CONFIG_NFSD_DEPRECATED */
 
 /*
  * Obtain the root fh on behalf of a client.
@@ -1459,25 +1470,43 @@
 	show_expflags(m, flags, NFSEXP_SECINFO_FLAGS);
 }
 
+static bool secinfo_flags_equal(int f, int g)
+{
+	f &= NFSEXP_SECINFO_FLAGS;
+	g &= NFSEXP_SECINFO_FLAGS;
+	return f == g;
+}
+
+static int show_secinfo_run(struct seq_file *m, struct exp_flavor_info **fp, struct exp_flavor_info *end)
+{
+	int flags;
+
+	flags = (*fp)->flags;
+	seq_printf(m, ",sec=%d", (*fp)->pseudoflavor);
+	(*fp)++;
+	while (*fp != end && secinfo_flags_equal(flags, (*fp)->flags)) {
+		seq_printf(m, ":%d", (*fp)->pseudoflavor);
+		(*fp)++;
+	}
+	return flags;
+}
+
 static void show_secinfo(struct seq_file *m, struct svc_export *exp)
 {
 	struct exp_flavor_info *f;
 	struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
-	int lastflags = 0, first = 0;
+	int flags;
 
 	if (exp->ex_nflavors == 0)
 		return;
-	for (f = exp->ex_flavors; f < end; f++) {
-		if (first || f->flags != lastflags) {
-			if (!first)
-				show_secinfo_flags(m, lastflags);
-			seq_printf(m, ",sec=%d", f->pseudoflavor);
-			lastflags = f->flags;
-		} else {
-			seq_printf(m, ":%d", f->pseudoflavor);
-		}
+	f = exp->ex_flavors;
+	flags = show_secinfo_run(m, &f, end);
+	if (!secinfo_flags_equal(flags, exp->ex_flags))
+		show_secinfo_flags(m, flags);
+	while (f != end) {
+		flags = show_secinfo_run(m, &f, end);
+		show_secinfo_flags(m, flags);
 	}
-	show_secinfo_flags(m, lastflags);
 }
 
 static void exp_flags(struct seq_file *m, int flag, int fsid,
@@ -1532,6 +1561,7 @@
 	.show	= e_show,
 };
 
+#ifdef CONFIG_NFSD_DEPRECATED
 /*
  * Add or modify a client.
  * Change requests may involve the list of host addresses. The list of
@@ -1563,7 +1593,7 @@
 	/* Insert client into hashtable. */
 	for (i = 0; i < ncp->cl_naddr; i++) {
 		ipv6_addr_set_v4mapped(ncp->cl_addrlist[i].s_addr, &addr6);
-		auth_unix_add_addr(&addr6, dom);
+		auth_unix_add_addr(&init_net, &addr6, dom);
 	}
 	auth_unix_forget_old(dom);
 	auth_domain_put(dom);
@@ -1621,6 +1651,7 @@
 	printk(KERN_NOTICE "nfsd: couldn't validate string %s\n", cp);
 	return 0;
 }
+#endif /* CONFIG_NFSD_DEPRECATED */
 
 /*
  * Initialize the exports module.
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 988cbb3..143da2e 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -41,7 +41,6 @@
 
 #define NFSPROC4_CB_NULL 0
 #define NFSPROC4_CB_COMPOUND 1
-#define NFS4_STATEID_SIZE 16
 
 /* Index of predefined Linux callback client operations */
 
@@ -248,10 +247,11 @@
 }
 
 static void
-encode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_cb_sequence *args,
+encode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_callback *cb,
 		   struct nfs4_cb_compound_hdr *hdr)
 {
 	__be32 *p;
+	struct nfsd4_session *ses = cb->cb_clp->cl_cb_session;
 
 	if (hdr->minorversion == 0)
 		return;
@@ -259,8 +259,8 @@
 	RESERVE_SPACE(1 + NFS4_MAX_SESSIONID_LEN + 20);
 
 	WRITE32(OP_CB_SEQUENCE);
-	WRITEMEM(args->cbs_clp->cl_sessionid.data, NFS4_MAX_SESSIONID_LEN);
-	WRITE32(args->cbs_clp->cl_cb_seq_nr);
+	WRITEMEM(ses->se_sessionid.data, NFS4_MAX_SESSIONID_LEN);
+	WRITE32(ses->se_cb_seq_nr);
 	WRITE32(0);		/* slotid, always 0 */
 	WRITE32(0);		/* highest slotid always 0 */
 	WRITE32(0);		/* cachethis always 0 */
@@ -280,18 +280,18 @@
 
 static int
 nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, __be32 *p,
-		struct nfs4_rpc_args *rpc_args)
+		struct nfsd4_callback *cb)
 {
 	struct xdr_stream xdr;
-	struct nfs4_delegation *args = rpc_args->args_op;
+	struct nfs4_delegation *args = cb->cb_op;
 	struct nfs4_cb_compound_hdr hdr = {
-		.ident = args->dl_ident,
-		.minorversion = rpc_args->args_seq.cbs_minorversion,
+		.ident = cb->cb_clp->cl_cb_ident,
+		.minorversion = cb->cb_minorversion,
 	};
 
 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
 	encode_cb_compound_hdr(&xdr, &hdr);
-	encode_cb_sequence(&xdr, &rpc_args->args_seq, &hdr);
+	encode_cb_sequence(&xdr, cb, &hdr);
 	encode_cb_recall(&xdr, args, &hdr);
 	encode_cb_nops(&hdr);
 	return 0;
@@ -339,15 +339,16 @@
  * with a single slot.
  */
 static int
-decode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_cb_sequence *res,
+decode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_callback *cb,
 		   struct rpc_rqst *rqstp)
 {
+	struct nfsd4_session *ses = cb->cb_clp->cl_cb_session;
 	struct nfs4_sessionid id;
 	int status;
 	u32 dummy;
 	__be32 *p;
 
-	if (res->cbs_minorversion == 0)
+	if (cb->cb_minorversion == 0)
 		return 0;
 
 	status = decode_cb_op_hdr(xdr, OP_CB_SEQUENCE);
@@ -363,13 +364,12 @@
 	READ_BUF(NFS4_MAX_SESSIONID_LEN + 16);
 	memcpy(id.data, p, NFS4_MAX_SESSIONID_LEN);
 	p += XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN);
-	if (memcmp(id.data, res->cbs_clp->cl_sessionid.data,
-		   NFS4_MAX_SESSIONID_LEN)) {
+	if (memcmp(id.data, ses->se_sessionid.data, NFS4_MAX_SESSIONID_LEN)) {
 		dprintk("%s Invalid session id\n", __func__);
 		goto out;
 	}
 	READ32(dummy);
-	if (dummy != res->cbs_clp->cl_cb_seq_nr) {
+	if (dummy != ses->se_cb_seq_nr) {
 		dprintk("%s Invalid sequence number\n", __func__);
 		goto out;
 	}
@@ -393,7 +393,7 @@
 
 static int
 nfs4_xdr_dec_cb_recall(struct rpc_rqst *rqstp, __be32 *p,
-		struct nfsd4_cb_sequence *seq)
+		struct nfsd4_callback *cb)
 {
 	struct xdr_stream xdr;
 	struct nfs4_cb_compound_hdr hdr;
@@ -403,8 +403,8 @@
 	status = decode_cb_compound_hdr(&xdr, &hdr);
 	if (status)
 		goto out;
-	if (seq) {
-		status = decode_cb_sequence(&xdr, seq, rqstp);
+	if (cb) {
+		status = decode_cb_sequence(&xdr, cb, rqstp);
 		if (status)
 			goto out;
 	}
@@ -473,30 +473,34 @@
 /* Reference counting, callback cleanup, etc., all look racy as heck.
  * And why is cl_cb_set an atomic? */
 
-int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *cb)
+int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn)
 {
 	struct rpc_timeout	timeparms = {
 		.to_initval	= max_cb_time(),
 		.to_retries	= 0,
 	};
 	struct rpc_create_args args = {
-		.protocol	= XPRT_TRANSPORT_TCP,
-		.address	= (struct sockaddr *) &cb->cb_addr,
-		.addrsize	= cb->cb_addrlen,
+		.net		= &init_net,
+		.address	= (struct sockaddr *) &conn->cb_addr,
+		.addrsize	= conn->cb_addrlen,
 		.timeout	= &timeparms,
 		.program	= &cb_program,
-		.prognumber	= cb->cb_prog,
 		.version	= 0,
 		.authflavor	= clp->cl_flavor,
 		.flags		= (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET),
-		.client_name    = clp->cl_principal,
 	};
 	struct rpc_clnt *client;
 
-	if (!clp->cl_principal && (clp->cl_flavor >= RPC_AUTH_GSS_KRB5))
-		return -EINVAL;
-	if (cb->cb_minorversion) {
-		args.bc_xprt = cb->cb_xprt;
+	if (clp->cl_minorversion == 0) {
+		if (!clp->cl_principal && (clp->cl_flavor >= RPC_AUTH_GSS_KRB5))
+			return -EINVAL;
+		args.client_name = clp->cl_principal;
+		args.prognumber	= conn->cb_prog,
+		args.protocol = XPRT_TRANSPORT_TCP;
+		clp->cl_cb_ident = conn->cb_ident;
+	} else {
+		args.bc_xprt = conn->cb_xprt;
+		args.prognumber = clp->cl_cb_session->se_cb_prog;
 		args.protocol = XPRT_TRANSPORT_BC_TCP;
 	}
 	/* Create RPC client */
@@ -506,7 +510,7 @@
 			PTR_ERR(client));
 		return PTR_ERR(client);
 	}
-	nfsd4_set_callback_client(clp, client);
+	clp->cl_cb_client = client;
 	return 0;
 
 }
@@ -519,7 +523,7 @@
 
 static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata)
 {
-	struct nfs4_client *clp = calldata;
+	struct nfs4_client *clp = container_of(calldata, struct nfs4_client, cl_cb_null);
 
 	if (task->tk_status)
 		warn_no_callback_path(clp, task->tk_status);
@@ -528,6 +532,8 @@
 }
 
 static const struct rpc_call_ops nfsd4_cb_probe_ops = {
+	/* XXX: release method to ensure we set the cb channel down if
+	 * necessary on early failure? */
 	.rpc_call_done = nfsd4_cb_probe_done,
 };
 
@@ -543,38 +549,42 @@
 	return 0;
 }
 
+static struct workqueue_struct *callback_wq;
 
-void do_probe_callback(struct nfs4_client *clp)
+static void do_probe_callback(struct nfs4_client *clp)
 {
-	struct rpc_message msg = {
-		.rpc_proc       = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
-		.rpc_argp       = clp,
-		.rpc_cred	= callback_cred
-	};
-	int status;
+	struct nfsd4_callback *cb = &clp->cl_cb_null;
 
-	status = rpc_call_async(clp->cl_cb_client, &msg,
-				RPC_TASK_SOFT | RPC_TASK_SOFTCONN,
-				&nfsd4_cb_probe_ops, (void *)clp);
-	if (status)
-		warn_no_callback_path(clp, status);
+	cb->cb_op = NULL;
+	cb->cb_clp = clp;
+
+	cb->cb_msg.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL];
+	cb->cb_msg.rpc_argp = NULL;
+	cb->cb_msg.rpc_resp = NULL;
+	cb->cb_msg.rpc_cred = callback_cred;
+
+	cb->cb_ops = &nfsd4_cb_probe_ops;
+
+	queue_work(callback_wq, &cb->cb_work);
 }
 
 /*
- * Set up the callback client and put a NFSPROC4_CB_NULL on the wire...
+ * Poke the callback thread to process any updates to the callback
+ * parameters, and send a null probe.
  */
-void nfsd4_probe_callback(struct nfs4_client *clp, struct nfs4_cb_conn *cb)
+void nfsd4_probe_callback(struct nfs4_client *clp)
 {
-	int status;
+	set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags);
+	do_probe_callback(clp);
+}
 
+void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *conn)
+{
 	BUG_ON(atomic_read(&clp->cl_cb_set));
 
-	status = setup_callback_client(clp, cb);
-	if (status) {
-		warn_no_callback_path(clp, status);
-		return;
-	}
-	do_probe_callback(clp);
+	spin_lock(&clp->cl_lock);
+	memcpy(&clp->cl_cb_conn, conn, sizeof(struct nfs4_cb_conn));
+	spin_unlock(&clp->cl_lock);
 }
 
 /*
@@ -585,8 +595,7 @@
 static int nfsd41_cb_setup_sequence(struct nfs4_client *clp,
 		struct rpc_task *task)
 {
-	struct nfs4_rpc_args *args = task->tk_msg.rpc_argp;
-	u32 *ptr = (u32 *)clp->cl_sessionid.data;
+	u32 *ptr = (u32 *)clp->cl_cb_session->se_sessionid.data;
 	int status = 0;
 
 	dprintk("%s: %u:%u:%u:%u\n", __func__,
@@ -598,14 +607,6 @@
 		status = -EAGAIN;
 		goto out;
 	}
-
-	/*
-	 * We'll need the clp during XDR encoding and decoding,
-	 * and the sequence during decoding to verify the reply
-	 */
-	args->args_seq.cbs_clp = clp;
-	task->tk_msg.rpc_resp = &args->args_seq;
-
 out:
 	dprintk("%s status=%d\n", __func__, status);
 	return status;
@@ -617,13 +618,13 @@
  */
 static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata)
 {
-	struct nfs4_delegation *dp = calldata;
+	struct nfsd4_callback *cb = calldata;
+	struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall);
 	struct nfs4_client *clp = dp->dl_client;
-	struct nfs4_rpc_args *args = task->tk_msg.rpc_argp;
-	u32 minorversion = clp->cl_cb_conn.cb_minorversion;
+	u32 minorversion = clp->cl_minorversion;
 	int status = 0;
 
-	args->args_seq.cbs_minorversion = minorversion;
+	cb->cb_minorversion = minorversion;
 	if (minorversion) {
 		status = nfsd41_cb_setup_sequence(clp, task);
 		if (status) {
@@ -640,19 +641,20 @@
 
 static void nfsd4_cb_done(struct rpc_task *task, void *calldata)
 {
-	struct nfs4_delegation *dp = calldata;
+	struct nfsd4_callback *cb = calldata;
+	struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall);
 	struct nfs4_client *clp = dp->dl_client;
 
 	dprintk("%s: minorversion=%d\n", __func__,
-		clp->cl_cb_conn.cb_minorversion);
+		clp->cl_minorversion);
 
-	if (clp->cl_cb_conn.cb_minorversion) {
+	if (clp->cl_minorversion) {
 		/* No need for lock, access serialized in nfsd4_cb_prepare */
-		++clp->cl_cb_seq_nr;
+		++clp->cl_cb_session->se_cb_seq_nr;
 		clear_bit(0, &clp->cl_cb_slot_busy);
 		rpc_wake_up_next(&clp->cl_cb_waitq);
 		dprintk("%s: freed slot, new seqid=%d\n", __func__,
-			clp->cl_cb_seq_nr);
+			clp->cl_cb_session->se_cb_seq_nr);
 
 		/* We're done looking into the sequence information */
 		task->tk_msg.rpc_resp = NULL;
@@ -662,7 +664,8 @@
 
 static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
 {
-	struct nfs4_delegation *dp = calldata;
+	struct nfsd4_callback *cb = calldata;
+	struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall);
 	struct nfs4_client *clp = dp->dl_client;
 	struct rpc_clnt *current_rpc_client = clp->cl_cb_client;
 
@@ -707,7 +710,8 @@
 
 static void nfsd4_cb_recall_release(void *calldata)
 {
-	struct nfs4_delegation *dp = calldata;
+	struct nfsd4_callback *cb = calldata;
+	struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall);
 
 	nfs4_put_delegation(dp);
 }
@@ -718,8 +722,6 @@
 	.rpc_release = nfsd4_cb_recall_release,
 };
 
-static struct workqueue_struct *callback_wq;
-
 int nfsd4_create_callback_queue(void)
 {
 	callback_wq = create_singlethread_workqueue("nfsd4_callbacks");
@@ -734,57 +736,88 @@
 }
 
 /* must be called under the state lock */
-void nfsd4_set_callback_client(struct nfs4_client *clp, struct rpc_clnt *new)
+void nfsd4_shutdown_callback(struct nfs4_client *clp)
 {
-	struct rpc_clnt *old = clp->cl_cb_client;
-
-	clp->cl_cb_client = new;
+	set_bit(NFSD4_CLIENT_KILL, &clp->cl_cb_flags);
 	/*
-	 * After this, any work that saw the old value of cl_cb_client will
-	 * be gone:
+	 * Note this won't actually result in a null callback;
+	 * instead, nfsd4_do_callback_rpc() will detect the killed
+	 * client, destroy the rpc client, and stop:
 	 */
+	do_probe_callback(clp);
 	flush_workqueue(callback_wq);
-	/* So we can safely shut it down: */
-	if (old)
-		rpc_shutdown_client(old);
 }
 
-/*
- * called with dp->dl_count inc'ed.
- */
-static void _nfsd4_cb_recall(struct nfs4_delegation *dp)
+void nfsd4_release_cb(struct nfsd4_callback *cb)
 {
-	struct nfs4_client *clp = dp->dl_client;
-	struct rpc_clnt *clnt = clp->cl_cb_client;
-	struct nfs4_rpc_args *args = &dp->dl_recall.cb_args;
-	struct rpc_message msg = {
-		.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL],
-		.rpc_cred = callback_cred
-	};
+	if (cb->cb_ops->rpc_release)
+		cb->cb_ops->rpc_release(cb);
+}
 
-	if (clnt == NULL) {
-		nfs4_put_delegation(dp);
-		return; /* Client is shutting down; give up. */
+void nfsd4_process_cb_update(struct nfsd4_callback *cb)
+{
+	struct nfs4_cb_conn conn;
+	struct nfs4_client *clp = cb->cb_clp;
+	int err;
+
+	/*
+	 * This is either an update, or the client dying; in either case,
+	 * kill the old client:
+	 */
+	if (clp->cl_cb_client) {
+		rpc_shutdown_client(clp->cl_cb_client);
+		clp->cl_cb_client = NULL;
 	}
+	if (test_bit(NFSD4_CLIENT_KILL, &clp->cl_cb_flags))
+		return;
+	spin_lock(&clp->cl_lock);
+	/*
+	 * Only serialized callback code is allowed to clear these
+	 * flags; main nfsd code can only set them:
+	 */
+	BUG_ON(!clp->cl_cb_flags);
+	clear_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags);
+	memcpy(&conn, &cb->cb_clp->cl_cb_conn, sizeof(struct nfs4_cb_conn));
+	spin_unlock(&clp->cl_lock);
 
-	args->args_op = dp;
-	msg.rpc_argp = args;
-	dp->dl_retries = 1;
-	rpc_call_async(clnt, &msg, RPC_TASK_SOFT, &nfsd4_cb_recall_ops, dp);
+	err = setup_callback_client(clp, &conn);
+	if (err)
+		warn_no_callback_path(clp, err);
 }
 
 void nfsd4_do_callback_rpc(struct work_struct *w)
 {
-	/* XXX: for now, just send off delegation recall. */
-	/* In future, generalize to handle any sort of callback. */
-	struct nfsd4_callback *c = container_of(w, struct nfsd4_callback, cb_work);
-	struct nfs4_delegation *dp = container_of(c, struct nfs4_delegation, dl_recall);
+	struct nfsd4_callback *cb = container_of(w, struct nfsd4_callback, cb_work);
+	struct nfs4_client *clp = cb->cb_clp;
+	struct rpc_clnt *clnt;
 
-	_nfsd4_cb_recall(dp);
+	if (clp->cl_cb_flags)
+		nfsd4_process_cb_update(cb);
+
+	clnt = clp->cl_cb_client;
+	if (!clnt) {
+		/* Callback channel broken, or client killed; give up: */
+		nfsd4_release_cb(cb);
+		return;
+	}
+	rpc_call_async(clnt, &cb->cb_msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN,
+			cb->cb_ops, cb);
 }
 
-
 void nfsd4_cb_recall(struct nfs4_delegation *dp)
 {
+	struct nfsd4_callback *cb = &dp->dl_recall;
+
+	dp->dl_retries = 1;
+	cb->cb_op = dp;
+	cb->cb_clp = dp->dl_client;
+	cb->cb_msg.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL];
+	cb->cb_msg.rpc_argp = cb;
+	cb->cb_msg.rpc_resp = cb;
+	cb->cb_msg.rpc_cred = callback_cred;
+
+	cb->cb_ops = &nfsd4_cb_recall_ops;
+	dp->dl_retries = 1;
+
 	queue_work(callback_wq, &dp->dl_recall.cb_work);
 }
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
index c78dbf4..f0695e8 100644
--- a/fs/nfsd/nfs4idmap.c
+++ b/fs/nfsd/nfs4idmap.c
@@ -482,109 +482,26 @@
 	cache_unregister(&nametoid_cache);
 }
 
-/*
- * Deferred request handling
- */
-
-struct idmap_defer_req {
-       struct cache_req		req;
-       struct cache_deferred_req deferred_req;
-       wait_queue_head_t	waitq;
-       atomic_t			count;
-};
-
-static inline void
-put_mdr(struct idmap_defer_req *mdr)
-{
-	if (atomic_dec_and_test(&mdr->count))
-		kfree(mdr);
-}
-
-static inline void
-get_mdr(struct idmap_defer_req *mdr)
-{
-	atomic_inc(&mdr->count);
-}
-
-static void
-idmap_revisit(struct cache_deferred_req *dreq, int toomany)
-{
-	struct idmap_defer_req *mdr =
-		container_of(dreq, struct idmap_defer_req, deferred_req);
-
-	wake_up(&mdr->waitq);
-	put_mdr(mdr);
-}
-
-static struct cache_deferred_req *
-idmap_defer(struct cache_req *req)
-{
-	struct idmap_defer_req *mdr =
-		container_of(req, struct idmap_defer_req, req);
-
-	mdr->deferred_req.revisit = idmap_revisit;
-	get_mdr(mdr);
-	return (&mdr->deferred_req);
-}
-
-static inline int
-do_idmap_lookup(struct ent *(*lookup_fn)(struct ent *), struct ent *key,
-		struct cache_detail *detail, struct ent **item,
-		struct idmap_defer_req *mdr)
-{
-	*item = lookup_fn(key);
-	if (!*item)
-		return -ENOMEM;
-	return cache_check(detail, &(*item)->h, &mdr->req);
-}
-
-static inline int
-do_idmap_lookup_nowait(struct ent *(*lookup_fn)(struct ent *),
-			struct ent *key, struct cache_detail *detail,
-			struct ent **item)
-{
-	int ret = -ENOMEM;
-
-	*item = lookup_fn(key);
-	if (!*item)
-		goto out_err;
-	ret = -ETIMEDOUT;
-	if (!test_bit(CACHE_VALID, &(*item)->h.flags)
-			|| (*item)->h.expiry_time < get_seconds()
-			|| detail->flush_time > (*item)->h.last_refresh)
-		goto out_put;
-	ret = -ENOENT;
-	if (test_bit(CACHE_NEGATIVE, &(*item)->h.flags))
-		goto out_put;
-	return 0;
-out_put:
-	cache_put(&(*item)->h, detail);
-out_err:
-	*item = NULL;
-	return ret;
-}
-
 static int
 idmap_lookup(struct svc_rqst *rqstp,
 		struct ent *(*lookup_fn)(struct ent *), struct ent *key,
 		struct cache_detail *detail, struct ent **item)
 {
-	struct idmap_defer_req *mdr;
 	int ret;
 
-	mdr = kzalloc(sizeof(*mdr), GFP_KERNEL);
-	if (!mdr)
+	*item = lookup_fn(key);
+	if (!*item)
 		return -ENOMEM;
-	atomic_set(&mdr->count, 1);
-	init_waitqueue_head(&mdr->waitq);
-	mdr->req.defer = idmap_defer;
-	ret = do_idmap_lookup(lookup_fn, key, detail, item, mdr);
-	if (ret == -EAGAIN) {
-		wait_event_interruptible_timeout(mdr->waitq,
-			test_bit(CACHE_VALID, &(*item)->h.flags), 1 * HZ);
-		ret = do_idmap_lookup_nowait(lookup_fn, key, detail, item);
+ retry:
+	ret = cache_check(detail, &(*item)->h, &rqstp->rq_chandle);
+
+	if (ret == -ETIMEDOUT) {
+		struct ent *prev_item = *item;
+		*item = lookup_fn(key);
+		if (*item != prev_item)
+			goto retry;
+		cache_put(&(*item)->h, detail);
 	}
-	put_mdr(mdr);
 	return ret;
 }
 
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 59ec449..0cdfd02 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -1031,8 +1031,11 @@
 	resp->cstate.session = NULL;
 	fh_init(&resp->cstate.current_fh, NFS4_FHSIZE);
 	fh_init(&resp->cstate.save_fh, NFS4_FHSIZE);
-	/* Use the deferral mechanism only for NFSv4.0 compounds */
-	rqstp->rq_usedeferral = (args->minorversion == 0);
+	/*
+	 * Don't use the deferral mechanism for NFSv4; compounds make it
+	 * too hard to avoid non-idempotency problems.
+	 */
+	rqstp->rq_usedeferral = 0;
 
 	/*
 	 * According to RFC3010, this takes precedence over all other errors.
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index a7292fc..9019e8e 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -207,7 +207,6 @@
 {
 	struct nfs4_delegation *dp;
 	struct nfs4_file *fp = stp->st_file;
-	struct nfs4_cb_conn *cb = &stp->st_stateowner->so_client->cl_cb_conn;
 
 	dprintk("NFSD alloc_init_deleg\n");
 	/*
@@ -234,7 +233,6 @@
 	nfs4_file_get_access(fp, O_RDONLY);
 	dp->dl_flock = NULL;
 	dp->dl_type = type;
-	dp->dl_ident = cb->cb_ident;
 	dp->dl_stateid.si_boot = boot_time;
 	dp->dl_stateid.si_stateownerid = current_delegid++;
 	dp->dl_stateid.si_fileid = 0;
@@ -535,94 +533,6 @@
  */
 #define NFSD_MIN_HDR_SEQ_SZ  (24 + 12 + 44)
 
-/*
- * Give the client the number of ca_maxresponsesize_cached slots it
- * requests, of size bounded by NFSD_SLOT_CACHE_SIZE,
- * NFSD_MAX_MEM_PER_SESSION, and nfsd_drc_max_mem. Do not allow more
- * than NFSD_MAX_SLOTS_PER_SESSION.
- *
- * If we run out of reserved DRC memory we should (up to a point)
- * re-negotiate active sessions and reduce their slot usage to make
- * rooom for new connections. For now we just fail the create session.
- */
-static int set_forechannel_drc_size(struct nfsd4_channel_attrs *fchan)
-{
-	int mem, size = fchan->maxresp_cached;
-
-	if (fchan->maxreqs < 1)
-		return nfserr_inval;
-
-	if (size < NFSD_MIN_HDR_SEQ_SZ)
-		size = NFSD_MIN_HDR_SEQ_SZ;
-	size -= NFSD_MIN_HDR_SEQ_SZ;
-	if (size > NFSD_SLOT_CACHE_SIZE)
-		size = NFSD_SLOT_CACHE_SIZE;
-
-	/* bound the maxreqs by NFSD_MAX_MEM_PER_SESSION */
-	mem = fchan->maxreqs * size;
-	if (mem > NFSD_MAX_MEM_PER_SESSION) {
-		fchan->maxreqs = NFSD_MAX_MEM_PER_SESSION / size;
-		if (fchan->maxreqs > NFSD_MAX_SLOTS_PER_SESSION)
-			fchan->maxreqs = NFSD_MAX_SLOTS_PER_SESSION;
-		mem = fchan->maxreqs * size;
-	}
-
-	spin_lock(&nfsd_drc_lock);
-	/* bound the total session drc memory ussage */
-	if (mem + nfsd_drc_mem_used > nfsd_drc_max_mem) {
-		fchan->maxreqs = (nfsd_drc_max_mem - nfsd_drc_mem_used) / size;
-		mem = fchan->maxreqs * size;
-	}
-	nfsd_drc_mem_used += mem;
-	spin_unlock(&nfsd_drc_lock);
-
-	if (fchan->maxreqs == 0)
-		return nfserr_jukebox;
-
-	fchan->maxresp_cached = size + NFSD_MIN_HDR_SEQ_SZ;
-	return 0;
-}
-
-/*
- * fchan holds the client values on input, and the server values on output
- * sv_max_mesg is the maximum payload plus one page for overhead.
- */
-static int init_forechannel_attrs(struct svc_rqst *rqstp,
-				  struct nfsd4_channel_attrs *session_fchan,
-				  struct nfsd4_channel_attrs *fchan)
-{
-	int status = 0;
-	__u32   maxcount = nfsd_serv->sv_max_mesg;
-
-	/* headerpadsz set to zero in encode routine */
-
-	/* Use the client's max request and max response size if possible */
-	if (fchan->maxreq_sz > maxcount)
-		fchan->maxreq_sz = maxcount;
-	session_fchan->maxreq_sz = fchan->maxreq_sz;
-
-	if (fchan->maxresp_sz > maxcount)
-		fchan->maxresp_sz = maxcount;
-	session_fchan->maxresp_sz = fchan->maxresp_sz;
-
-	/* Use the client's maxops if possible */
-	if (fchan->maxops > NFSD_MAX_OPS_PER_COMPOUND)
-		fchan->maxops = NFSD_MAX_OPS_PER_COMPOUND;
-	session_fchan->maxops = fchan->maxops;
-
-	/* FIXME: Error means no more DRC pages so the server should
-	 * recover pages from existing sessions. For now fail session
-	 * creation.
-	 */
-	status = set_forechannel_drc_size(fchan);
-
-	session_fchan->maxresp_cached = fchan->maxresp_cached;
-	session_fchan->maxreqs = fchan->maxreqs;
-
-	dprintk("%s status %d\n", __func__, status);
-	return status;
-}
-
 static void
 free_session_slots(struct nfsd4_session *ses)
 {
@@ -641,65 +551,240 @@
 	return ca->maxresp_cached - NFSD_MIN_HDR_SEQ_SZ;
 }
 
-static int
-alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp,
-		   struct nfsd4_create_session *cses)
+static int nfsd4_sanitize_slot_size(u32 size)
 {
-	struct nfsd4_session *new, tmp;
-	struct nfsd4_slot *sp;
-	int idx, slotsize, cachesize, i;
-	int status;
+	size -= NFSD_MIN_HDR_SEQ_SZ; /* We don't cache the rpc header */
+	size = min_t(u32, size, NFSD_SLOT_CACHE_SIZE);
 
-	memset(&tmp, 0, sizeof(tmp));
+	return size;
+}
 
-	/* FIXME: For now, we just accept the client back channel attributes. */
-	tmp.se_bchannel = cses->back_channel;
-	status = init_forechannel_attrs(rqstp, &tmp.se_fchannel,
-					&cses->fore_channel);
-	if (status)
-		goto out;
+/*
+ * XXX: If we run out of reserved DRC memory we could (up to a point)
+ * re-negotiate active sessions and reduce their slot usage to make
+ * rooom for new connections. For now we just fail the create session.
+ */
+static int nfsd4_get_drc_mem(int slotsize, u32 num)
+{
+	int avail;
 
-	BUILD_BUG_ON(NFSD_MAX_SLOTS_PER_SESSION * sizeof(struct nfsd4_slot)
-		     + sizeof(struct nfsd4_session) > PAGE_SIZE);
+	num = min_t(u32, num, NFSD_MAX_SLOTS_PER_SESSION);
 
-	status = nfserr_jukebox;
-	/* allocate struct nfsd4_session and slot table pointers in one piece */
-	slotsize = tmp.se_fchannel.maxreqs * sizeof(struct nfsd4_slot *);
-	new = kzalloc(sizeof(*new) + slotsize, GFP_KERNEL);
+	spin_lock(&nfsd_drc_lock);
+	avail = min_t(int, NFSD_MAX_MEM_PER_SESSION,
+			nfsd_drc_max_mem - nfsd_drc_mem_used);
+	num = min_t(int, num, avail / slotsize);
+	nfsd_drc_mem_used += num * slotsize;
+	spin_unlock(&nfsd_drc_lock);
+
+	return num;
+}
+
+static void nfsd4_put_drc_mem(int slotsize, int num)
+{
+	spin_lock(&nfsd_drc_lock);
+	nfsd_drc_mem_used -= slotsize * num;
+	spin_unlock(&nfsd_drc_lock);
+}
+
+static struct nfsd4_session *alloc_session(int slotsize, int numslots)
+{
+	struct nfsd4_session *new;
+	int mem, i;
+
+	BUILD_BUG_ON(NFSD_MAX_SLOTS_PER_SESSION * sizeof(struct nfsd4_slot *)
+			+ sizeof(struct nfsd4_session) > PAGE_SIZE);
+	mem = numslots * sizeof(struct nfsd4_slot *);
+
+	new = kzalloc(sizeof(*new) + mem, GFP_KERNEL);
 	if (!new)
-		goto out;
-
-	memcpy(new, &tmp, sizeof(*new));
-
+		return NULL;
 	/* allocate each struct nfsd4_slot and data cache in one piece */
-	cachesize = slot_bytes(&new->se_fchannel);
-	for (i = 0; i < new->se_fchannel.maxreqs; i++) {
-		sp = kzalloc(sizeof(*sp) + cachesize, GFP_KERNEL);
-		if (!sp)
+	for (i = 0; i < numslots; i++) {
+		mem = sizeof(struct nfsd4_slot) + slotsize;
+		new->se_slots[i] = kzalloc(mem, GFP_KERNEL);
+		if (!new->se_slots[i])
 			goto out_free;
-		new->se_slots[i] = sp;
 	}
+	return new;
+out_free:
+	while (i--)
+		kfree(new->se_slots[i]);
+	kfree(new);
+	return NULL;
+}
+
+static void init_forechannel_attrs(struct nfsd4_channel_attrs *new, struct nfsd4_channel_attrs *req, int numslots, int slotsize)
+{
+	u32 maxrpc = nfsd_serv->sv_max_mesg;
+
+	new->maxreqs = numslots;
+	new->maxresp_cached = slotsize + NFSD_MIN_HDR_SEQ_SZ;
+	new->maxreq_sz = min_t(u32, req->maxreq_sz, maxrpc);
+	new->maxresp_sz = min_t(u32, req->maxresp_sz, maxrpc);
+	new->maxops = min_t(u32, req->maxops, NFSD_MAX_OPS_PER_COMPOUND);
+}
+
+static void free_conn(struct nfsd4_conn *c)
+{
+	svc_xprt_put(c->cn_xprt);
+	kfree(c);
+}
+
+static void nfsd4_conn_lost(struct svc_xpt_user *u)
+{
+	struct nfsd4_conn *c = container_of(u, struct nfsd4_conn, cn_xpt_user);
+	struct nfs4_client *clp = c->cn_session->se_client;
+
+	spin_lock(&clp->cl_lock);
+	if (!list_empty(&c->cn_persession)) {
+		list_del(&c->cn_persession);
+		free_conn(c);
+	}
+	spin_unlock(&clp->cl_lock);
+}
+
+static struct nfsd4_conn *alloc_conn(struct svc_rqst *rqstp, u32 flags)
+{
+	struct nfsd4_conn *conn;
+
+	conn = kmalloc(sizeof(struct nfsd4_conn), GFP_KERNEL);
+	if (!conn)
+		return NULL;
+	svc_xprt_get(rqstp->rq_xprt);
+	conn->cn_xprt = rqstp->rq_xprt;
+	conn->cn_flags = flags;
+	INIT_LIST_HEAD(&conn->cn_xpt_user.list);
+	return conn;
+}
+
+static void __nfsd4_hash_conn(struct nfsd4_conn *conn, struct nfsd4_session *ses)
+{
+	conn->cn_session = ses;
+	list_add(&conn->cn_persession, &ses->se_conns);
+}
+
+static void nfsd4_hash_conn(struct nfsd4_conn *conn, struct nfsd4_session *ses)
+{
+	struct nfs4_client *clp = ses->se_client;
+
+	spin_lock(&clp->cl_lock);
+	__nfsd4_hash_conn(conn, ses);
+	spin_unlock(&clp->cl_lock);
+}
+
+static void nfsd4_register_conn(struct nfsd4_conn *conn)
+{
+	conn->cn_xpt_user.callback = nfsd4_conn_lost;
+	register_xpt_user(conn->cn_xprt, &conn->cn_xpt_user);
+}
+
+static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses)
+{
+	struct nfsd4_conn *conn;
+	u32 flags = NFS4_CDFC4_FORE;
+
+	if (ses->se_flags & SESSION4_BACK_CHAN)
+		flags |= NFS4_CDFC4_BACK;
+	conn = alloc_conn(rqstp, flags);
+	if (!conn)
+		return nfserr_jukebox;
+	nfsd4_hash_conn(conn, ses);
+	nfsd4_register_conn(conn);
+	return nfs_ok;
+}
+
+static void nfsd4_del_conns(struct nfsd4_session *s)
+{
+	struct nfs4_client *clp = s->se_client;
+	struct nfsd4_conn *c;
+
+	spin_lock(&clp->cl_lock);
+	while (!list_empty(&s->se_conns)) {
+		c = list_first_entry(&s->se_conns, struct nfsd4_conn, cn_persession);
+		list_del_init(&c->cn_persession);
+		spin_unlock(&clp->cl_lock);
+
+		unregister_xpt_user(c->cn_xprt, &c->cn_xpt_user);
+		free_conn(c);
+
+		spin_lock(&clp->cl_lock);
+	}
+	spin_unlock(&clp->cl_lock);
+}
+
+void free_session(struct kref *kref)
+{
+	struct nfsd4_session *ses;
+	int mem;
+
+	ses = container_of(kref, struct nfsd4_session, se_ref);
+	nfsd4_del_conns(ses);
+	spin_lock(&nfsd_drc_lock);
+	mem = ses->se_fchannel.maxreqs * slot_bytes(&ses->se_fchannel);
+	nfsd_drc_mem_used -= mem;
+	spin_unlock(&nfsd_drc_lock);
+	free_session_slots(ses);
+	kfree(ses);
+}
+
+static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp, struct nfsd4_create_session *cses)
+{
+	struct nfsd4_session *new;
+	struct nfsd4_channel_attrs *fchan = &cses->fore_channel;
+	int numslots, slotsize;
+	int status;
+	int idx;
+
+	/*
+	 * Note decreasing slot size below client's request may
+	 * make it difficult for client to function correctly, whereas
+	 * decreasing the number of slots will (just?) affect
+	 * performance.  When short on memory we therefore prefer to
+	 * decrease number of slots instead of their size.
+	 */
+	slotsize = nfsd4_sanitize_slot_size(fchan->maxresp_cached);
+	numslots = nfsd4_get_drc_mem(slotsize, fchan->maxreqs);
+
+	new = alloc_session(slotsize, numslots);
+	if (!new) {
+		nfsd4_put_drc_mem(slotsize, fchan->maxreqs);
+		return NULL;
+	}
+	init_forechannel_attrs(&new->se_fchannel, fchan, numslots, slotsize);
 
 	new->se_client = clp;
 	gen_sessionid(new);
-	idx = hash_sessionid(&new->se_sessionid);
-	memcpy(clp->cl_sessionid.data, new->se_sessionid.data,
-	       NFS4_MAX_SESSIONID_LEN);
 
+	INIT_LIST_HEAD(&new->se_conns);
+
+	new->se_cb_seq_nr = 1;
 	new->se_flags = cses->flags;
+	new->se_cb_prog = cses->callback_prog;
 	kref_init(&new->se_ref);
+	idx = hash_sessionid(&new->se_sessionid);
 	spin_lock(&client_lock);
 	list_add(&new->se_hash, &sessionid_hashtbl[idx]);
 	list_add(&new->se_perclnt, &clp->cl_sessions);
 	spin_unlock(&client_lock);
 
-	status = nfs_ok;
-out:
-	return status;
-out_free:
-	free_session_slots(new);
-	kfree(new);
-	goto out;
+	status = nfsd4_new_conn(rqstp, new);
+	/* whoops: benny points out, status is ignored! (err, or bogus) */
+	if (status) {
+		free_session(&new->se_ref);
+		return NULL;
+	}
+	if (!clp->cl_cb_session && (cses->flags & SESSION4_BACK_CHAN)) {
+		struct sockaddr *sa = svc_addr(rqstp);
+
+		clp->cl_cb_session = new;
+		clp->cl_cb_conn.cb_xprt = rqstp->rq_xprt;
+		svc_xprt_get(rqstp->rq_xprt);
+		rpc_copy_addr((struct sockaddr *)&clp->cl_cb_conn.cb_addr, sa);
+		clp->cl_cb_conn.cb_addrlen = svc_addr_len(sa);
+		nfsd4_probe_callback(clp);
+	}
+	return new;
 }
 
 /* caller must hold client_lock */
@@ -731,21 +816,6 @@
 	list_del(&ses->se_perclnt);
 }
 
-void
-free_session(struct kref *kref)
-{
-	struct nfsd4_session *ses;
-	int mem;
-
-	ses = container_of(kref, struct nfsd4_session, se_ref);
-	spin_lock(&nfsd_drc_lock);
-	mem = ses->se_fchannel.maxreqs * slot_bytes(&ses->se_fchannel);
-	nfsd_drc_mem_used -= mem;
-	spin_unlock(&nfsd_drc_lock);
-	free_session_slots(ses);
-	kfree(ses);
-}
-
 /* must be called under the client_lock */
 static inline void
 renew_client_locked(struct nfs4_client *clp)
@@ -812,6 +882,13 @@
 static inline void
 free_client(struct nfs4_client *clp)
 {
+	while (!list_empty(&clp->cl_sessions)) {
+		struct nfsd4_session *ses;
+		ses = list_entry(clp->cl_sessions.next, struct nfsd4_session,
+				se_perclnt);
+		list_del(&ses->se_perclnt);
+		nfsd4_put_session(ses);
+	}
 	if (clp->cl_cred.cr_group_info)
 		put_group_info(clp->cl_cred.cr_group_info);
 	kfree(clp->cl_principal);
@@ -838,15 +915,12 @@
 static inline void
 unhash_client_locked(struct nfs4_client *clp)
 {
+	struct nfsd4_session *ses;
+
 	mark_client_expired(clp);
 	list_del(&clp->cl_lru);
-	while (!list_empty(&clp->cl_sessions)) {
-		struct nfsd4_session  *ses;
-		ses = list_entry(clp->cl_sessions.next, struct nfsd4_session,
-				 se_perclnt);
-		unhash_session(ses);
-		nfsd4_put_session(ses);
-	}
+	list_for_each_entry(ses, &clp->cl_sessions, se_perclnt)
+		list_del_init(&ses->se_hash);
 }
 
 static void
@@ -875,7 +949,7 @@
 		sop = list_entry(clp->cl_openowners.next, struct nfs4_stateowner, so_perclient);
 		release_openowner(sop);
 	}
-	nfsd4_set_callback_client(clp, NULL);
+	nfsd4_shutdown_callback(clp);
 	if (clp->cl_cb_conn.cb_xprt)
 		svc_xprt_put(clp->cl_cb_conn.cb_xprt);
 	list_del(&clp->cl_idhash);
@@ -960,6 +1034,8 @@
 	if (clp == NULL)
 		return NULL;
 
+	INIT_LIST_HEAD(&clp->cl_sessions);
+
 	princ = svc_gss_principal(rqstp);
 	if (princ) {
 		clp->cl_principal = kstrdup(princ, GFP_KERNEL);
@@ -976,8 +1052,9 @@
 	INIT_LIST_HEAD(&clp->cl_strhash);
 	INIT_LIST_HEAD(&clp->cl_openowners);
 	INIT_LIST_HEAD(&clp->cl_delegations);
-	INIT_LIST_HEAD(&clp->cl_sessions);
 	INIT_LIST_HEAD(&clp->cl_lru);
+	spin_lock_init(&clp->cl_lock);
+	INIT_WORK(&clp->cl_cb_null.cb_work, nfsd4_do_callback_rpc);
 	clp->cl_time = get_seconds();
 	clear_bit(0, &clp->cl_cb_slot_busy);
 	rpc_init_wait_queue(&clp->cl_cb_waitq, "Backchannel slot table");
@@ -986,7 +1063,7 @@
 	clp->cl_flavor = rqstp->rq_flavor;
 	copy_cred(&clp->cl_cred, &rqstp->rq_cred);
 	gen_confirm(clp);
-
+	clp->cl_cb_session = NULL;
 	return clp;
 }
 
@@ -1098,7 +1175,7 @@
 static void
 gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se, u32 scopeid)
 {
-	struct nfs4_cb_conn *cb = &clp->cl_cb_conn;
+	struct nfs4_cb_conn *conn = &clp->cl_cb_conn;
 	unsigned short expected_family;
 
 	/* Currently, we only support tcp and tcp6 for the callback channel */
@@ -1111,24 +1188,23 @@
 	else
 		goto out_err;
 
-	cb->cb_addrlen = rpc_uaddr2sockaddr(se->se_callback_addr_val,
+	conn->cb_addrlen = rpc_uaddr2sockaddr(se->se_callback_addr_val,
 					    se->se_callback_addr_len,
-					    (struct sockaddr *) &cb->cb_addr,
-					    sizeof(cb->cb_addr));
+					    (struct sockaddr *)&conn->cb_addr,
+					    sizeof(conn->cb_addr));
 
-	if (!cb->cb_addrlen || cb->cb_addr.ss_family != expected_family)
+	if (!conn->cb_addrlen || conn->cb_addr.ss_family != expected_family)
 		goto out_err;
 
-	if (cb->cb_addr.ss_family == AF_INET6)
-		((struct sockaddr_in6 *) &cb->cb_addr)->sin6_scope_id = scopeid;
+	if (conn->cb_addr.ss_family == AF_INET6)
+		((struct sockaddr_in6 *)&conn->cb_addr)->sin6_scope_id = scopeid;
 
-	cb->cb_minorversion = 0;
-	cb->cb_prog = se->se_callback_prog;
-	cb->cb_ident = se->se_callback_ident;
+	conn->cb_prog = se->se_callback_prog;
+	conn->cb_ident = se->se_callback_ident;
 	return;
 out_err:
-	cb->cb_addr.ss_family = AF_UNSPEC;
-	cb->cb_addrlen = 0;
+	conn->cb_addr.ss_family = AF_UNSPEC;
+	conn->cb_addrlen = 0;
 	dprintk(KERN_INFO "NFSD: this client (clientid %08x/%08x) "
 		"will not receive delegations\n",
 		clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
@@ -1415,7 +1491,9 @@
 {
 	struct sockaddr *sa = svc_addr(rqstp);
 	struct nfs4_client *conf, *unconf;
+	struct nfsd4_session *new;
 	struct nfsd4_clid_slot *cs_slot = NULL;
+	bool confirm_me = false;
 	int status = 0;
 
 	nfs4_lock_state();
@@ -1438,7 +1516,6 @@
 				cs_slot->sl_seqid, cr_ses->seqid);
 			goto out;
 		}
-		cs_slot->sl_seqid++;
 	} else if (unconf) {
 		if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred) ||
 		    !rpc_cmp_addr(sa, (struct sockaddr *) &unconf->cl_addr)) {
@@ -1451,25 +1528,10 @@
 		if (status) {
 			/* an unconfirmed replay returns misordered */
 			status = nfserr_seq_misordered;
-			goto out_cache;
+			goto out;
 		}
 
-		cs_slot->sl_seqid++; /* from 0 to 1 */
-		move_to_confirmed(unconf);
-
-		if (cr_ses->flags & SESSION4_BACK_CHAN) {
-			unconf->cl_cb_conn.cb_xprt = rqstp->rq_xprt;
-			svc_xprt_get(rqstp->rq_xprt);
-			rpc_copy_addr(
-				(struct sockaddr *)&unconf->cl_cb_conn.cb_addr,
-				sa);
-			unconf->cl_cb_conn.cb_addrlen = svc_addr_len(sa);
-			unconf->cl_cb_conn.cb_minorversion =
-				cstate->minorversion;
-			unconf->cl_cb_conn.cb_prog = cr_ses->callback_prog;
-			unconf->cl_cb_seq_nr = 1;
-			nfsd4_probe_callback(unconf, &unconf->cl_cb_conn);
-		}
+		confirm_me = true;
 		conf = unconf;
 	} else {
 		status = nfserr_stale_clientid;
@@ -1477,22 +1539,30 @@
 	}
 
 	/*
+	 * XXX: we should probably set this at creation time, and check
+	 * for consistent minorversion use throughout:
+	 */
+	conf->cl_minorversion = 1;
+	/*
 	 * We do not support RDMA or persistent sessions
 	 */
 	cr_ses->flags &= ~SESSION4_PERSIST;
 	cr_ses->flags &= ~SESSION4_RDMA;
 
-	status = alloc_init_session(rqstp, conf, cr_ses);
-	if (status)
+	status = nfserr_jukebox;
+	new = alloc_init_session(rqstp, conf, cr_ses);
+	if (!new)
 		goto out;
-
-	memcpy(cr_ses->sessionid.data, conf->cl_sessionid.data,
+	status = nfs_ok;
+	memcpy(cr_ses->sessionid.data, new->se_sessionid.data,
 	       NFS4_MAX_SESSIONID_LEN);
+	cs_slot->sl_seqid++;
 	cr_ses->seqid = cs_slot->sl_seqid;
 
-out_cache:
 	/* cache solo and embedded create sessions under the state lock */
 	nfsd4_cache_create_session(cr_ses, cs_slot, status);
+	if (confirm_me)
+		move_to_confirmed(conf);
 out:
 	nfs4_unlock_state();
 	dprintk("%s returns %d\n", __func__, ntohl(status));
@@ -1546,8 +1616,11 @@
 
 	nfs4_lock_state();
 	/* wait for callbacks */
-	nfsd4_set_callback_client(ses->se_client, NULL);
+	nfsd4_shutdown_callback(ses->se_client);
 	nfs4_unlock_state();
+
+	nfsd4_del_conns(ses);
+
 	nfsd4_put_session(ses);
 	status = nfs_ok;
 out:
@@ -1555,6 +1628,36 @@
 	return status;
 }
 
+static struct nfsd4_conn *__nfsd4_find_conn(struct svc_xprt *xpt, struct nfsd4_session *s)
+{
+	struct nfsd4_conn *c;
+
+	list_for_each_entry(c, &s->se_conns, cn_persession) {
+		if (c->cn_xprt == xpt) {
+			return c;
+		}
+	}
+	return NULL;
+}
+
+static void nfsd4_sequence_check_conn(struct nfsd4_conn *new, struct nfsd4_session *ses)
+{
+	struct nfs4_client *clp = ses->se_client;
+	struct nfsd4_conn *c;
+
+	spin_lock(&clp->cl_lock);
+	c = __nfsd4_find_conn(new->cn_xprt, ses);
+	if (c) {
+		spin_unlock(&clp->cl_lock);
+		free_conn(new);
+		return;
+	}
+	__nfsd4_hash_conn(new, ses);
+	spin_unlock(&clp->cl_lock);
+	nfsd4_register_conn(new);
+	return;
+}
+
 __be32
 nfsd4_sequence(struct svc_rqst *rqstp,
 	       struct nfsd4_compound_state *cstate,
@@ -1563,11 +1666,20 @@
 	struct nfsd4_compoundres *resp = rqstp->rq_resp;
 	struct nfsd4_session *session;
 	struct nfsd4_slot *slot;
+	struct nfsd4_conn *conn;
 	int status;
 
 	if (resp->opcnt != 1)
 		return nfserr_sequence_pos;
 
+	/*
+	 * Will be either used or freed by nfsd4_sequence_check_conn
+	 * below.
+	 */
+	conn = alloc_conn(rqstp, NFS4_CDFC4_FORE);
+	if (!conn)
+		return nfserr_jukebox;
+
 	spin_lock(&client_lock);
 	status = nfserr_badsession;
 	session = find_in_sessionid_hashtbl(&seq->sessionid);
@@ -1599,6 +1711,9 @@
 	if (status)
 		goto out;
 
+	nfsd4_sequence_check_conn(conn, session);
+	conn = NULL;
+
 	/* Success! bump slot seqid */
 	slot->sl_inuse = true;
 	slot->sl_seqid = seq->seqid;
@@ -1613,6 +1728,7 @@
 		nfsd4_get_session(cstate->session);
 		atomic_inc(&session->se_client->cl_refcount);
 	}
+	kfree(conn);
 	spin_unlock(&client_lock);
 	dprintk("%s: return %d\n", __func__, ntohl(status));
 	return status;
@@ -1747,6 +1863,11 @@
 			goto out;
 		gen_clid(new);
 	}
+	/*
+	 * XXX: we should probably set this at creation time, and check
+	 * for consistent minorversion use throughout:
+	 */
+	new->cl_minorversion = 0;
 	gen_callback(new, setclid, rpc_get_scope_id(sa));
 	add_to_unconfirmed(new, strhashval);
 	setclid->se_clientid.cl_boot = new->cl_clientid.cl_boot;
@@ -1807,7 +1928,8 @@
 			status = nfserr_clid_inuse;
 		else {
 			atomic_set(&conf->cl_cb_set, 0);
-			nfsd4_probe_callback(conf, &unconf->cl_cb_conn);
+			nfsd4_change_callback(conf, &unconf->cl_cb_conn);
+			nfsd4_probe_callback(conf);
 			expire_client(unconf);
 			status = nfs_ok;
 
@@ -1841,7 +1963,7 @@
 			}
 			move_to_confirmed(unconf);
 			conf = unconf;
-			nfsd4_probe_callback(conf, &conf->cl_cb_conn);
+			nfsd4_probe_callback(conf);
 			status = nfs_ok;
 		}
 	} else if ((!conf || (conf && !same_verf(&conf->cl_confirm, &confirm)))
@@ -2944,7 +3066,11 @@
 	if (STALE_STATEID(stateid)) 
 		goto out;
 
-	status = nfserr_bad_stateid;
+	/*
+	 * We assume that any stateid that has the current boot time,
+	 * but that we can't find, is expired:
+	 */
+	status = nfserr_expired;
 	if (is_delegation_stateid(stateid)) {
 		dp = find_delegation_stateid(ino, stateid);
 		if (!dp)
@@ -2964,6 +3090,7 @@
 		stp = find_stateid(stateid, flags);
 		if (!stp)
 			goto out;
+		status = nfserr_bad_stateid;
 		if (nfs4_check_fh(current_fh, stp))
 			goto out;
 		if (!stp->st_stateowner->so_confirmed)
@@ -3038,8 +3165,9 @@
 		 * a replayed close:
 		 */
 		sop = search_close_lru(stateid->si_stateownerid, flags);
+		/* It's not stale; let's assume it's expired: */
 		if (sop == NULL)
-			return nfserr_bad_stateid;
+			return nfserr_expired;
 		*sopp = sop;
 		goto check_replay;
 	}
@@ -3304,6 +3432,7 @@
 	status = nfserr_bad_stateid;
 	if (!is_delegation_stateid(stateid))
 		goto out;
+	status = nfserr_expired;
 	dp = find_delegation_stateid(inode, stateid);
 	if (!dp)
 		goto out;
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 1a468bb..f35a94a 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1805,19 +1805,23 @@
 				goto out_nfserr;
 		}
 	}
-	if ((buflen -= 16) < 0)
-		goto out_resource;
 
-	if (unlikely(bmval2)) {
+	if (bmval2) {
+		if ((buflen -= 16) < 0)
+			goto out_resource;
 		WRITE32(3);
 		WRITE32(bmval0);
 		WRITE32(bmval1);
 		WRITE32(bmval2);
-	} else if (likely(bmval1)) {
+	} else if (bmval1) {
+		if ((buflen -= 12) < 0)
+			goto out_resource;
 		WRITE32(2);
 		WRITE32(bmval0);
 		WRITE32(bmval1);
 	} else {
+		if ((buflen -= 8) < 0)
+			goto out_resource;
 		WRITE32(1);
 		WRITE32(bmval0);
 	}
@@ -1828,15 +1832,17 @@
 		u32 word1 = nfsd_suppattrs1(minorversion);
 		u32 word2 = nfsd_suppattrs2(minorversion);
 
-		if ((buflen -= 12) < 0)
-			goto out_resource;
 		if (!aclsupport)
 			word0 &= ~FATTR4_WORD0_ACL;
 		if (!word2) {
+			if ((buflen -= 12) < 0)
+				goto out_resource;
 			WRITE32(2);
 			WRITE32(word0);
 			WRITE32(word1);
 		} else {
+			if ((buflen -= 16) < 0)
+				goto out_resource;
 			WRITE32(3);
 			WRITE32(word0);
 			WRITE32(word1);
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 06fa87e..d6dc3f6 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -22,6 +22,7 @@
  */
 enum {
 	NFSD_Root = 1,
+#ifdef CONFIG_NFSD_DEPRECATED
 	NFSD_Svc,
 	NFSD_Add,
 	NFSD_Del,
@@ -29,6 +30,7 @@
 	NFSD_Unexport,
 	NFSD_Getfd,
 	NFSD_Getfs,
+#endif
 	NFSD_List,
 	NFSD_Export_features,
 	NFSD_Fh,
@@ -54,6 +56,7 @@
 /*
  * write() for these nodes.
  */
+#ifdef CONFIG_NFSD_DEPRECATED
 static ssize_t write_svc(struct file *file, char *buf, size_t size);
 static ssize_t write_add(struct file *file, char *buf, size_t size);
 static ssize_t write_del(struct file *file, char *buf, size_t size);
@@ -61,6 +64,7 @@
 static ssize_t write_unexport(struct file *file, char *buf, size_t size);
 static ssize_t write_getfd(struct file *file, char *buf, size_t size);
 static ssize_t write_getfs(struct file *file, char *buf, size_t size);
+#endif
 static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
 static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size);
 static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size);
@@ -76,6 +80,7 @@
 #endif
 
 static ssize_t (*write_op[])(struct file *, char *, size_t) = {
+#ifdef CONFIG_NFSD_DEPRECATED
 	[NFSD_Svc] = write_svc,
 	[NFSD_Add] = write_add,
 	[NFSD_Del] = write_del,
@@ -83,6 +88,7 @@
 	[NFSD_Unexport] = write_unexport,
 	[NFSD_Getfd] = write_getfd,
 	[NFSD_Getfs] = write_getfs,
+#endif
 	[NFSD_Fh] = write_filehandle,
 	[NFSD_FO_UnlockIP] = write_unlock_ip,
 	[NFSD_FO_UnlockFS] = write_unlock_fs,
@@ -121,6 +127,14 @@
 
 static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
 {
+	static int warned;
+	if (file->f_dentry->d_name.name[0] == '.' && !warned) {
+		printk(KERN_INFO
+		       "Warning: \"%s\" uses deprecated NFSD interface: %s."
+		       "  This will be removed in 2.6.40\n",
+		       current->comm, file->f_dentry->d_name.name);
+		warned = 1;
+	}
 	if (! file->private_data) {
 		/* An attempt to read a transaction file without writing
 		 * causes a 0-byte write so that the file can return
@@ -187,6 +201,7 @@
  * payload - write methods
  */
 
+#ifdef CONFIG_NFSD_DEPRECATED
 /**
  * write_svc - Start kernel's NFSD server
  *
@@ -402,7 +417,7 @@
 
 	ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6);
 
-	clp = auth_unix_lookup(&in6);
+	clp = auth_unix_lookup(&init_net, &in6);
 	if (!clp)
 		err = -EPERM;
 	else {
@@ -465,7 +480,7 @@
 
 	ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6);
 
-	clp = auth_unix_lookup(&in6);
+	clp = auth_unix_lookup(&init_net, &in6);
 	if (!clp)
 		err = -EPERM;
 	else {
@@ -482,6 +497,7 @@
  out:
 	return err;
 }
+#endif /* CONFIG_NFSD_DEPRECATED */
 
 /**
  * write_unlock_ip - Release all locks used by a client
@@ -1000,12 +1016,12 @@
 	if (err != 0)
 		return err;
 
-	err = svc_create_xprt(nfsd_serv, transport,
+	err = svc_create_xprt(nfsd_serv, transport, &init_net,
 				PF_INET, port, SVC_SOCK_ANONYMOUS);
 	if (err < 0)
 		goto out_err;
 
-	err = svc_create_xprt(nfsd_serv, transport,
+	err = svc_create_xprt(nfsd_serv, transport, &init_net,
 				PF_INET6, port, SVC_SOCK_ANONYMOUS);
 	if (err < 0 && err != -EAFNOSUPPORT)
 		goto out_close;
@@ -1356,6 +1372,7 @@
 static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
 {
 	static struct tree_descr nfsd_files[] = {
+#ifdef CONFIG_NFSD_DEPRECATED
 		[NFSD_Svc] = {".svc", &transaction_ops, S_IWUSR},
 		[NFSD_Add] = {".add", &transaction_ops, S_IWUSR},
 		[NFSD_Del] = {".del", &transaction_ops, S_IWUSR},
@@ -1363,6 +1380,7 @@
 		[NFSD_Unexport] = {".unexport", &transaction_ops, S_IWUSR},
 		[NFSD_Getfd] = {".getfd", &transaction_ops, S_IWUSR|S_IRUSR},
 		[NFSD_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR},
+#endif
 		[NFSD_List] = {"exports", &exports_operations, S_IRUGO},
 		[NFSD_Export_features] = {"export_features",
 					&export_features_operations, S_IRUGO},
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index b76ac3a..6b641cf 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -249,7 +249,7 @@
 #define	COMPOUND_SLACK_SPACE		140    /* OP_GETFH */
 #define COMPOUND_ERR_SLACK_SPACE	12     /* OP_SETATTR */
 
-#define NFSD_LAUNDROMAT_MINTIMEOUT      10   /* seconds */
+#define NFSD_LAUNDROMAT_MINTIMEOUT      1   /* seconds */
 
 /*
  * The following attributes are currently not supported by the NFSv4 server:
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index e2c4346..2bae1d8 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -16,6 +16,7 @@
 #include <linux/lockd/bind.h>
 #include <linux/nfsacl.h>
 #include <linux/seq_file.h>
+#include <net/net_namespace.h>
 #include "nfsd.h"
 #include "cache.h"
 #include "vfs.h"
@@ -186,12 +187,12 @@
 	if (!list_empty(&nfsd_serv->sv_permsocks))
 		return 0;
 
-	error = svc_create_xprt(nfsd_serv, "udp", PF_INET, port,
+	error = svc_create_xprt(nfsd_serv, "udp", &init_net, PF_INET, port,
 					SVC_SOCK_DEFAULTS);
 	if (error < 0)
 		return error;
 
-	error = svc_create_xprt(nfsd_serv, "tcp", PF_INET, port,
+	error = svc_create_xprt(nfsd_serv, "tcp", &init_net, PF_INET, port,
 					SVC_SOCK_DEFAULTS);
 	if (error < 0)
 		return error;
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 322518c..39adc27 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -35,6 +35,7 @@
 #ifndef _NFSD4_STATE_H
 #define _NFSD4_STATE_H
 
+#include <linux/sunrpc/svc_xprt.h>
 #include <linux/nfsd/nfsfh.h>
 #include "nfsfh.h"
 
@@ -64,19 +65,12 @@
 	(s)->si_fileid, \
 	(s)->si_generation
 
-struct nfsd4_cb_sequence {
-	/* args/res */
-	u32			cbs_minorversion;
-	struct nfs4_client	*cbs_clp;
-};
-
-struct nfs4_rpc_args {
-	void				*args_op;
-	struct nfsd4_cb_sequence	args_seq;
-};
-
 struct nfsd4_callback {
-	struct nfs4_rpc_args cb_args;
+	void *cb_op;
+	struct nfs4_client *cb_clp;
+	u32 cb_minorversion;
+	struct rpc_message cb_msg;
+	const struct rpc_call_ops *cb_ops;
 	struct work_struct cb_work;
 };
 
@@ -91,7 +85,6 @@
 	u32			dl_type;
 	time_t			dl_time;
 /* For recall: */
-	u32			dl_ident;
 	stateid_t		dl_stateid;
 	struct knfsd_fh		dl_fh;
 	int			dl_retries;
@@ -103,8 +96,8 @@
 	/* SETCLIENTID info */
 	struct sockaddr_storage	cb_addr;
 	size_t			cb_addrlen;
-	u32                     cb_prog;
-	u32			cb_minorversion;
+	u32                     cb_prog; /* used only in 4.0 case;
+					    per-session otherwise */
 	u32                     cb_ident;	/* minorversion 0 only */
 	struct svc_xprt		*cb_xprt;	/* minorversion 1 only */
 };
@@ -160,6 +153,15 @@
 	struct nfsd4_create_session	sl_cr_ses;
 };
 
+struct nfsd4_conn {
+	struct list_head cn_persession;
+	struct svc_xprt *cn_xprt;
+	struct svc_xpt_user cn_xpt_user;
+	struct nfsd4_session *cn_session;
+/* CDFC4_FORE, CDFC4_BACK: */
+	unsigned char cn_flags;
+};
+
 struct nfsd4_session {
 	struct kref		se_ref;
 	struct list_head	se_hash;	/* hash by sessionid */
@@ -169,6 +171,9 @@
 	struct nfs4_sessionid	se_sessionid;
 	struct nfsd4_channel_attrs se_fchannel;
 	struct nfsd4_channel_attrs se_bchannel;
+	struct list_head	se_conns;
+	u32			se_cb_prog;
+	u32			se_cb_seq_nr;
 	struct nfsd4_slot	*se_slots[];	/* forward channel slots */
 };
 
@@ -221,24 +226,32 @@
 	clientid_t		cl_clientid;	/* generated by server */
 	nfs4_verifier		cl_confirm;	/* generated by server */
 	u32			cl_firststate;	/* recovery dir creation */
+	u32			cl_minorversion;
 
 	/* for v4.0 and v4.1 callbacks: */
 	struct nfs4_cb_conn	cl_cb_conn;
+#define NFSD4_CLIENT_CB_UPDATE	1
+#define NFSD4_CLIENT_KILL	2
+	unsigned long		cl_cb_flags;
 	struct rpc_clnt		*cl_cb_client;
+	u32			cl_cb_ident;
 	atomic_t		cl_cb_set;
+	struct nfsd4_callback	cl_cb_null;
+	struct nfsd4_session	*cl_cb_session;
+
+	/* for all client information that callback code might need: */
+	spinlock_t		cl_lock;
 
 	/* for nfs41 */
 	struct list_head	cl_sessions;
 	struct nfsd4_clid_slot	cl_cs_slot;	/* create_session slot */
 	u32			cl_exchange_flags;
-	struct nfs4_sessionid	cl_sessionid;
 	/* number of rpc's in progress over an associated session: */
 	atomic_t		cl_refcount;
 
 	/* for nfs41 callbacks */
 	/* We currently support a single back channel with a single slot */
 	unsigned long		cl_cb_slot_busy;
-	u32			cl_cb_seq_nr;
 	struct rpc_wait_queue	cl_cb_waitq;	/* backchannel callers may */
 						/* wait here for slots */
 };
@@ -440,12 +453,13 @@
 extern __be32 nfs4_check_open_reclaim(clientid_t *clid);
 extern void nfs4_free_stateowner(struct kref *kref);
 extern int set_callback_cred(void);
-extern void nfsd4_probe_callback(struct nfs4_client *clp, struct nfs4_cb_conn *);
+extern void nfsd4_probe_callback(struct nfs4_client *clp);
+extern void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *);
 extern void nfsd4_do_callback_rpc(struct work_struct *);
 extern void nfsd4_cb_recall(struct nfs4_delegation *dp);
 extern int nfsd4_create_callback_queue(void);
 extern void nfsd4_destroy_callback_queue(void);
-extern void nfsd4_set_callback_client(struct nfs4_client *, struct rpc_clnt *);
+extern void nfsd4_shutdown_callback(struct nfs4_client *);
 extern void nfs4_put_delegation(struct nfs4_delegation *dp);
 extern __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname);
 extern void nfsd4_init_recdir(char *recdir_name);
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
index d926af6..687d090 100644
--- a/fs/nilfs2/segment.c
+++ b/fs/nilfs2/segment.c
@@ -1609,7 +1609,7 @@
 	kunmap_atomic(kaddr, KM_USER0);
 
 	if (!TestSetPageWriteback(clone_page))
-		inc_zone_page_state(clone_page, NR_WRITEBACK);
+		account_page_writeback(clone_page);
 	unlock_page(clone_page);
 
 	return 0;
diff --git a/fs/proc/Kconfig b/fs/proc/Kconfig
index 50f8f06..6a00688 100644
--- a/fs/proc/Kconfig
+++ b/fs/proc/Kconfig
@@ -33,8 +33,8 @@
 	depends on PROC_FS && MMU
 
 config PROC_VMCORE
-        bool "/proc/vmcore support (EXPERIMENTAL)"
-        depends on PROC_FS && CRASH_DUMP
+	bool "/proc/vmcore support"
+	depends on PROC_FS && CRASH_DUMP
 	default y
         help
         Exports the dump image of crashed kernel in ELF format.
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 9883f1e..9b094c1 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1025,28 +1025,47 @@
 	memset(buffer, 0, sizeof(buffer));
 	if (count > sizeof(buffer) - 1)
 		count = sizeof(buffer) - 1;
-	if (copy_from_user(buffer, buf, count))
-		return -EFAULT;
+	if (copy_from_user(buffer, buf, count)) {
+		err = -EFAULT;
+		goto out;
+	}
 
 	err = strict_strtol(strstrip(buffer), 0, &oom_adjust);
 	if (err)
-		return -EINVAL;
+		goto out;
 	if ((oom_adjust < OOM_ADJUST_MIN || oom_adjust > OOM_ADJUST_MAX) &&
-	     oom_adjust != OOM_DISABLE)
-		return -EINVAL;
+	     oom_adjust != OOM_DISABLE) {
+		err = -EINVAL;
+		goto out;
+	}
 
 	task = get_proc_task(file->f_path.dentry->d_inode);
-	if (!task)
-		return -ESRCH;
+	if (!task) {
+		err = -ESRCH;
+		goto out;
+	}
+
+	task_lock(task);
+	if (!task->mm) {
+		err = -EINVAL;
+		goto err_task_lock;
+	}
+
 	if (!lock_task_sighand(task, &flags)) {
-		put_task_struct(task);
-		return -ESRCH;
+		err = -ESRCH;
+		goto err_task_lock;
 	}
 
 	if (oom_adjust < task->signal->oom_adj && !capable(CAP_SYS_RESOURCE)) {
-		unlock_task_sighand(task, &flags);
-		put_task_struct(task);
-		return -EACCES;
+		err = -EACCES;
+		goto err_sighand;
+	}
+
+	if (oom_adjust != task->signal->oom_adj) {
+		if (oom_adjust == OOM_DISABLE)
+			atomic_inc(&task->mm->oom_disable_count);
+		if (task->signal->oom_adj == OOM_DISABLE)
+			atomic_dec(&task->mm->oom_disable_count);
 	}
 
 	/*
@@ -1067,10 +1086,13 @@
 	else
 		task->signal->oom_score_adj = (oom_adjust * OOM_SCORE_ADJ_MAX) /
 								-OOM_DISABLE;
+err_sighand:
 	unlock_task_sighand(task, &flags);
+err_task_lock:
+	task_unlock(task);
 	put_task_struct(task);
-
-	return count;
+out:
+	return err < 0 ? err : count;
 }
 
 static const struct file_operations proc_oom_adjust_operations = {
@@ -1111,30 +1133,49 @@
 	memset(buffer, 0, sizeof(buffer));
 	if (count > sizeof(buffer) - 1)
 		count = sizeof(buffer) - 1;
-	if (copy_from_user(buffer, buf, count))
-		return -EFAULT;
+	if (copy_from_user(buffer, buf, count)) {
+		err = -EFAULT;
+		goto out;
+	}
 
 	err = strict_strtol(strstrip(buffer), 0, &oom_score_adj);
 	if (err)
-		return -EINVAL;
+		goto out;
 	if (oom_score_adj < OOM_SCORE_ADJ_MIN ||
-			oom_score_adj > OOM_SCORE_ADJ_MAX)
-		return -EINVAL;
+			oom_score_adj > OOM_SCORE_ADJ_MAX) {
+		err = -EINVAL;
+		goto out;
+	}
 
 	task = get_proc_task(file->f_path.dentry->d_inode);
-	if (!task)
-		return -ESRCH;
-	if (!lock_task_sighand(task, &flags)) {
-		put_task_struct(task);
-		return -ESRCH;
-	}
-	if (oom_score_adj < task->signal->oom_score_adj &&
-			!capable(CAP_SYS_RESOURCE)) {
-		unlock_task_sighand(task, &flags);
-		put_task_struct(task);
-		return -EACCES;
+	if (!task) {
+		err = -ESRCH;
+		goto out;
 	}
 
+	task_lock(task);
+	if (!task->mm) {
+		err = -EINVAL;
+		goto err_task_lock;
+	}
+
+	if (!lock_task_sighand(task, &flags)) {
+		err = -ESRCH;
+		goto err_task_lock;
+	}
+
+	if (oom_score_adj < task->signal->oom_score_adj &&
+			!capable(CAP_SYS_RESOURCE)) {
+		err = -EACCES;
+		goto err_sighand;
+	}
+
+	if (oom_score_adj != task->signal->oom_score_adj) {
+		if (oom_score_adj == OOM_SCORE_ADJ_MIN)
+			atomic_inc(&task->mm->oom_disable_count);
+		if (task->signal->oom_score_adj == OOM_SCORE_ADJ_MIN)
+			atomic_dec(&task->mm->oom_disable_count);
+	}
 	task->signal->oom_score_adj = oom_score_adj;
 	/*
 	 * Scale /proc/pid/oom_adj appropriately ensuring that OOM_DISABLE is
@@ -1145,9 +1186,13 @@
 	else
 		task->signal->oom_adj = (oom_score_adj * OOM_ADJUST_MAX) /
 							OOM_SCORE_ADJ_MAX;
+err_sighand:
 	unlock_task_sighand(task, &flags);
+err_task_lock:
+	task_unlock(task);
 	put_task_struct(task);
-	return count;
+out:
+	return err < 0 ? err : count;
 }
 
 static const struct file_operations proc_oom_score_adj_operations = {
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 4dcb880..41656d4 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -2437,7 +2437,7 @@
 		/* from this point on, we know the buffer is mapped to a
 		 * real block and not a direct item
 		 */
-		if (wbc->sync_mode != WB_SYNC_NONE || !wbc->nonblocking) {
+		if (wbc->sync_mode != WB_SYNC_NONE) {
 			lock_buffer(bh);
 		} else {
 			if (!trylock_buffer(bh)) {
diff --git a/fs/signalfd.c b/fs/signalfd.c
index 7404730..492465b 100644
--- a/fs/signalfd.c
+++ b/fs/signalfd.c
@@ -99,6 +99,16 @@
 #ifdef __ARCH_SI_TRAPNO
 		err |= __put_user(kinfo->si_trapno, &uinfo->ssi_trapno);
 #endif
+#ifdef BUS_MCEERR_AO
+		/* 
+		 * Other callers might not initialize the si_lsb field,
+		 * so check explicitly for the right codes here.
+		 */
+		if (kinfo->si_code == BUS_MCEERR_AR ||
+		    kinfo->si_code == BUS_MCEERR_AO)
+			err |= __put_user((short) kinfo->si_addr_lsb,
+					  &uinfo->ssi_addr_lsb);
+#endif
 		break;
 	case __SI_CHLD:
 		err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid);
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index b552f81..c9af48f 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -1139,8 +1139,7 @@
 				type = IO_DELAY;
 				flags = BMAPI_ALLOCATE;
 
-				if (wbc->sync_mode == WB_SYNC_NONE &&
-				    wbc->nonblocking)
+				if (wbc->sync_mode == WB_SYNC_NONE)
 					flags |= BMAPI_TRYLOCK;
 			}
 
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 4de84ce..359ef11 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -184,7 +184,7 @@
 
 #define acpi_device_bid(d)	((d)->pnp.bus_id)
 #define acpi_device_adr(d)	((d)->pnp.bus_address)
-char *acpi_device_hid(struct acpi_device *device);
+const char *acpi_device_hid(struct acpi_device *device);
 #define acpi_device_name(d)	((d)->pnp.device_name)
 #define acpi_device_class(d)	((d)->pnp.device_class)
 
@@ -389,21 +389,25 @@
 int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state);
 int acpi_disable_wakeup_device_power(struct acpi_device *dev);
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM_OPS
 int acpi_pm_device_sleep_state(struct device *, int *);
-int acpi_pm_device_sleep_wake(struct device *, bool);
-#else /* !CONFIG_PM_SLEEP */
+#else
 static inline int acpi_pm_device_sleep_state(struct device *d, int *p)
 {
 	if (p)
 		*p = ACPI_STATE_D0;
 	return ACPI_STATE_D3;
 }
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+int acpi_pm_device_sleep_wake(struct device *, bool);
+#else
 static inline int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
 {
 	return -ENODEV;
 }
-#endif /* !CONFIG_PM_SLEEP */
+#endif
 
 #endif				/* CONFIG_ACPI */
 
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
index 23d78b4..3090471 100644
--- a/include/acpi/acpi_drivers.h
+++ b/include/acpi/acpi_drivers.h
@@ -115,8 +115,6 @@
 #define ACPI_PROCESSOR_LIMIT_INCREMENT	0x01
 #define ACPI_PROCESSOR_LIMIT_DECREMENT	0x02
 
-int acpi_processor_set_thermal_limit(acpi_handle handle, int type);
-
 /*--------------------------------------------------------------------------
                                   Dock Station
   -------------------------------------------------------------------------- */
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
index 29bf945..65b3f58 100644
--- a/include/acpi/acpiosxf.h
+++ b/include/acpi/acpiosxf.h
@@ -98,8 +98,6 @@
 /*
  * Spinlock primitives
  */
-acpi_status acpi_os_create_lock(acpi_spinlock * out_handle);
-
 void acpi_os_delete_lock(acpi_spinlock handle);
 
 acpi_cpu_flags acpi_os_acquire_lock(acpi_spinlock handle);
@@ -223,25 +221,15 @@
  */
 acpi_status
 acpi_os_read_pci_configuration(struct acpi_pci_id *pci_id,
-			       u32 reg, u32 *value, u32 width);
+			       u32 reg, u64 *value, u32 width);
 
 acpi_status
 acpi_os_write_pci_configuration(struct acpi_pci_id *pci_id,
 				u32 reg, u64 value, u32 width);
 
 /*
- * Interim function needed for PCI IRQ routing
- */
-void
-acpi_os_derive_pci_id(acpi_handle device,
-		      acpi_handle region, struct acpi_pci_id **pci_id);
-
-/*
  * Miscellaneous
  */
-acpi_status acpi_os_validate_interface(char *interface);
-acpi_status acpi_osi_invalidate(char* interface);
-
 acpi_status
 acpi_os_validate_address(u8 space_id, acpi_physical_address address,
 			 acpi_size length, char *name);
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index 984cdc6..53b7cfd 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -47,7 +47,7 @@
 
 /* Current ACPICA subsystem version in YYYYMMDD format */
 
-#define ACPI_CA_VERSION                 0x20100702
+#define ACPI_CA_VERSION                 0x20101013
 
 #include "actypes.h"
 #include "actbl.h"
@@ -72,6 +72,7 @@
 
 extern u32 acpi_current_gpe_count;
 extern struct acpi_table_fadt acpi_gbl_FADT;
+extern u8 acpi_gbl_system_awake_and_running;
 
 extern u32 acpi_rsdt_forced;
 /*
@@ -105,6 +106,10 @@
 
 acpi_status acpi_purge_cached_objects(void);
 
+acpi_status acpi_install_interface(acpi_string interface_name);
+
+acpi_status acpi_remove_interface(acpi_string interface_name);
+
 /*
  * ACPI Memory management
  */
@@ -263,6 +268,8 @@
 acpi_status acpi_install_exception_handler(acpi_exception_handler handler);
 #endif
 
+acpi_status acpi_install_interface_handler(acpi_interface_handler handler);
+
 /*
  * Event interfaces
  */
@@ -308,6 +315,8 @@
 
 acpi_status acpi_remove_gpe_block(acpi_handle gpe_device);
 
+acpi_status acpi_update_gpes(void);
+
 /*
  * Resource interfaces
  */
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index 5db8f47..2b134b6 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -115,7 +115,6 @@
  *
  * ACPI_SIZE        16/32/64-bit unsigned value
  * ACPI_NATIVE_INT  16/32/64-bit signed value
- *
  */
 
 /*******************************************************************************
@@ -132,6 +131,16 @@
 
 /*! [End] no source code translation !*/
 
+/*
+ * Value returned by acpi_os_get_thread_id. There is no standard "thread_id"
+ * across operating systems or even the various UNIX systems. Since ACPICA
+ * only needs the thread ID as a unique thread identifier, we use a u64
+ * as the only common data type - it will accommodate any type of pointer or
+ * any type of integer. It is up to the host-dependent OSL to cast the
+ * native thread ID type to a u64 (in acpi_os_get_thread_id).
+ */
+#define acpi_thread_id                  u64
+
 /*******************************************************************************
  *
  * Types specific to 64-bit targets
@@ -211,12 +220,6 @@
  *
  ******************************************************************************/
 
-/* Value returned by acpi_os_get_thread_id */
-
-#ifndef acpi_thread_id
-#define acpi_thread_id			acpi_size
-#endif
-
 /* Flags for acpi_os_acquire_lock/acpi_os_release_lock */
 
 #ifndef acpi_cpu_flags
@@ -375,16 +378,6 @@
 typedef u8 acpi_owner_id;
 #define ACPI_OWNER_ID_MAX               0xFF
 
-struct uint64_struct {
-	u32 lo;
-	u32 hi;
-};
-
-union uint64_overlay {
-	u64 full;
-	struct uint64_struct part;
-};
-
 #define ACPI_INTEGER_BIT_SIZE           64
 #define ACPI_MAX_DECIMAL_DIGITS         20	/* 2^64 = 18,446,744,073,709,551,616 */
 
@@ -950,6 +943,9 @@
 				  u32 nesting_level,
 				  void *context, void **return_value);
 
+typedef
+u32 (*acpi_interface_handler) (acpi_string interface_name, u32 supported);
+
 /* Interrupt handler return values */
 
 #define ACPI_INTERRUPT_NOT_HANDLED      0x00
diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h
index c05aeba..a3e334a 100644
--- a/include/acpi/platform/acenv.h
+++ b/include/acpi/platform/acenv.h
@@ -193,6 +193,12 @@
 #define ACPI_MUTEX_TYPE             ACPI_BINARY_SEMAPHORE
 #endif
 
+/* "inline" keywords - configurable since inline is not standardized */
+
+#ifndef ACPI_INLINE
+#define ACPI_INLINE
+#endif
+
 /*
  * Debugger threading model
  * Use single threaded if the entire subsystem is contained in an application
diff --git a/include/acpi/platform/acgcc.h b/include/acpi/platform/acgcc.h
index 0cd53e3..5dcb953 100644
--- a/include/acpi/platform/acgcc.h
+++ b/include/acpi/platform/acgcc.h
@@ -44,6 +44,8 @@
 #ifndef __ACGCC_H__
 #define __ACGCC_H__
 
+#define ACPI_INLINE             __inline__
+
 /* Function name is used for debug output. Non-ANSI, compiler-dependent */
 
 #define ACPI_GET_FUNCTION_NAME          __func__
diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h
index 103f08a..572189e 100644
--- a/include/acpi/platform/aclinux.h
+++ b/include/acpi/platform/aclinux.h
@@ -75,7 +75,6 @@
 #define acpi_cache_t                        struct kmem_cache
 #define acpi_spinlock                       spinlock_t *
 #define acpi_cpu_flags                      unsigned long
-#define acpi_thread_id                      struct task_struct *
 
 #else /* !__KERNEL__ */
 
@@ -88,7 +87,7 @@
 /* Host-dependent types and defines for user-space ACPICA */
 
 #define ACPI_FLUSH_CPU_CACHE()
-#define acpi_thread_id                      pthread_t
+#define ACPI_CAST_PTHREAD_T(pthread) ((acpi_thread_id) (pthread))
 
 #if defined(__ia64__) || defined(__x86_64__)
 #define ACPI_MACHINE_WIDTH          64
@@ -113,12 +112,13 @@
 
 
 #ifdef __KERNEL__
+#include <acpi/actypes.h>
 /*
  * Overrides for in-kernel ACPICA
  */
 static inline acpi_thread_id acpi_os_get_thread_id(void)
 {
-	return current;
+	return (acpi_thread_id)(unsigned long)current;
 }
 
 /*
@@ -127,7 +127,6 @@
  * However, boot has  (system_state != SYSTEM_RUNNING)
  * to quiet __might_sleep() in kmalloc() and resume does not.
  */
-#include <acpi/actypes.h>
 static inline void *acpi_os_allocate(acpi_size size)
 {
 	return kmalloc(size, irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL);
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index f4229fb..2c0fc10 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -150,6 +150,7 @@
 #define DATA_DATA							\
 	*(.data)							\
 	*(.ref.data)							\
+	*(.data..shared_aligned) /* percpu related */			\
 	DEV_KEEP(init.data)						\
 	DEV_KEEP(exit.data)						\
 	CPU_KEEP(init.data)						\
@@ -636,7 +637,7 @@
 
 #ifdef CONFIG_BLK_DEV_INITRD
 #define INIT_RAM_FS							\
-	. = ALIGN(PAGE_SIZE);						\
+	. = ALIGN(4);							\
 	VMLINUX_SYMBOL(__initramfs_start) = .;				\
 	*(.init.ramfs)							\
 	VMLINUX_SYMBOL(__initramfs_end) = .;
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index c227757..050a7bc 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -245,8 +245,6 @@
 
 int acpi_check_region(resource_size_t start, resource_size_t n,
 		      const char *name);
-int acpi_check_mem_region(resource_size_t start, resource_size_t n,
-		      const char *name);
 
 int acpi_resources_are_enforced(void);
 
@@ -308,6 +306,9 @@
 					     u32 *mask, u32 req);
 extern void acpi_early_init(void);
 
+int acpi_os_map_generic_address(struct acpi_generic_address *addr);
+void acpi_os_unmap_generic_address(struct acpi_generic_address *addr);
+
 #else	/* !CONFIG_ACPI */
 
 #define acpi_disabled 1
@@ -344,12 +345,6 @@
 	return 0;
 }
 
-static inline int acpi_check_mem_region(resource_size_t start,
-					resource_size_t n, const char *name)
-{
-	return 0;
-}
-
 struct acpi_table_header;
 static inline int acpi_table_parse(char *id,
 				int (*handler)(struct acpi_table_header *))
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index 35b0074..4ce34fa 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -111,6 +111,7 @@
 
 extern spinlock_t bdi_lock;
 extern struct list_head bdi_list;
+extern struct list_head bdi_pending_list;
 
 static inline int wb_has_dirty_io(struct bdi_writeback *wb)
 {
@@ -285,7 +286,7 @@
 void clear_bdi_congested(struct backing_dev_info *bdi, int sync);
 void set_bdi_congested(struct backing_dev_info *bdi, int sync);
 long congestion_wait(int sync, long timeout);
-
+long wait_iff_congested(struct zone *zone, int sync, long timeout);
 
 static inline bool bdi_cap_writeback_dirty(struct backing_dev_info *bdi)
 {
diff --git a/include/linux/bfin_mac.h b/include/linux/bfin_mac.h
new file mode 100644
index 0000000..904dec7
--- /dev/null
+++ b/include/linux/bfin_mac.h
@@ -0,0 +1,29 @@
+/*
+ * Blackfin On-Chip MAC Driver
+ *
+ * Copyright 2004-2010 Analog Devices Inc.
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _LINUX_BFIN_MAC_H_
+#define _LINUX_BFIN_MAC_H_
+
+#include <linux/phy.h>
+
+struct bfin_phydev_platform_data {
+	unsigned short addr;
+	int irq;
+};
+
+struct bfin_mii_bus_platform_data {
+	int phydev_number;
+	struct bfin_phydev_platform_data *phydev_data;
+	const unsigned short *mac_peripherals;
+	int phy_mode;
+	unsigned int phy_mask;
+};
+
+#endif
diff --git a/include/linux/completion.h b/include/linux/completion.h
index 51e3145..36d57f74 100644
--- a/include/linux/completion.h
+++ b/include/linux/completion.h
@@ -10,7 +10,7 @@
 
 #include <linux/wait.h>
 
-/**
+/*
  * struct completion - structure used to maintain state for a "completion"
  *
  * This is the opaque structure used to maintain the state for a "completion".
@@ -34,7 +34,7 @@
 	({ init_completion(&work); work; })
 
 /**
- * DECLARE_COMPLETION: - declare and initialize a completion structure
+ * DECLARE_COMPLETION - declare and initialize a completion structure
  * @work:  identifier for the completion structure
  *
  * This macro declares and initializes a completion structure. Generally used
@@ -50,7 +50,7 @@
  * are on the kernel stack:
  */
 /**
- * DECLARE_COMPLETION_ONSTACK: - declare and initialize a completion structure
+ * DECLARE_COMPLETION_ONSTACK - declare and initialize a completion structure
  * @work:  identifier for the completion structure
  *
  * This macro declares and initializes a completion structure on the kernel
@@ -64,7 +64,7 @@
 #endif
 
 /**
- * init_completion: - Initialize a dynamically allocated completion
+ * init_completion - Initialize a dynamically allocated completion
  * @x:  completion structure that is to be initialized
  *
  * This inline function will initialize a dynamically created completion
@@ -92,7 +92,7 @@
 extern void complete_all(struct completion *);
 
 /**
- * INIT_COMPLETION: - reinitialize a completion structure
+ * INIT_COMPLETION - reinitialize a completion structure
  * @x:  completion structure to be reinitialized
  *
  * This macro should be used to reinitialize a completion structure so it can
diff --git a/include/linux/fs.h b/include/linux/fs.h
index f300a65..240eb1d 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -234,6 +234,7 @@
 #define S_NOCMTIME	128	/* Do not update file c/mtime */
 #define S_SWAPFILE	256	/* Do not truncate: swapon got its bmaps */
 #define S_PRIVATE	512	/* Inode is fs-internal */
+#define S_IMA		1024	/* Inode has an associated IMA struct */
 
 /*
  * Note that nosuid etc flags are inode-specific: setting some file-system
@@ -268,6 +269,7 @@
 #define IS_NOCMTIME(inode)	((inode)->i_flags & S_NOCMTIME)
 #define IS_SWAPFILE(inode)	((inode)->i_flags & S_SWAPFILE)
 #define IS_PRIVATE(inode)	((inode)->i_flags & S_PRIVATE)
+#define IS_IMA(inode)		((inode)->i_flags & S_IMA)
 
 /* the read-only stuff doesn't really belong here, but any other place is
    probably as bad and I don't want to create yet another include file. */
@@ -776,6 +778,10 @@
 
 	unsigned int		i_flags;
 
+#ifdef CONFIG_IMA
+	/* protected by i_lock */
+	unsigned int		i_readcount; /* struct files open RO */
+#endif
 	atomic_t		i_writecount;
 #ifdef CONFIG_SECURITY
 	void			*i_security;
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index 975609c..e8713d5 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -9,6 +9,32 @@
 
 struct vm_area_struct;
 
+/* Plain integer GFP bitmasks. Do not use this directly. */
+#define ___GFP_DMA		0x01u
+#define ___GFP_HIGHMEM		0x02u
+#define ___GFP_DMA32		0x04u
+#define ___GFP_MOVABLE		0x08u
+#define ___GFP_WAIT		0x10u
+#define ___GFP_HIGH		0x20u
+#define ___GFP_IO		0x40u
+#define ___GFP_FS		0x80u
+#define ___GFP_COLD		0x100u
+#define ___GFP_NOWARN		0x200u
+#define ___GFP_REPEAT		0x400u
+#define ___GFP_NOFAIL		0x800u
+#define ___GFP_NORETRY		0x1000u
+#define ___GFP_COMP		0x4000u
+#define ___GFP_ZERO		0x8000u
+#define ___GFP_NOMEMALLOC	0x10000u
+#define ___GFP_HARDWALL		0x20000u
+#define ___GFP_THISNODE		0x40000u
+#define ___GFP_RECLAIMABLE	0x80000u
+#ifdef CONFIG_KMEMCHECK
+#define ___GFP_NOTRACK		0x200000u
+#else
+#define ___GFP_NOTRACK		0
+#endif
+
 /*
  * GFP bitmasks..
  *
@@ -18,10 +44,10 @@
  * without the underscores and use them consistently. The definitions here may
  * be used in bit comparisons.
  */
-#define __GFP_DMA	((__force gfp_t)0x01u)
-#define __GFP_HIGHMEM	((__force gfp_t)0x02u)
-#define __GFP_DMA32	((__force gfp_t)0x04u)
-#define __GFP_MOVABLE	((__force gfp_t)0x08u)  /* Page is movable */
+#define __GFP_DMA	((__force gfp_t)___GFP_DMA)
+#define __GFP_HIGHMEM	((__force gfp_t)___GFP_HIGHMEM)
+#define __GFP_DMA32	((__force gfp_t)___GFP_DMA32)
+#define __GFP_MOVABLE	((__force gfp_t)___GFP_MOVABLE)  /* Page is movable */
 #define GFP_ZONEMASK	(__GFP_DMA|__GFP_HIGHMEM|__GFP_DMA32|__GFP_MOVABLE)
 /*
  * Action modifiers - doesn't change the zoning
@@ -38,27 +64,22 @@
  * __GFP_MOVABLE: Flag that this page will be movable by the page migration
  * mechanism or reclaimed
  */
-#define __GFP_WAIT	((__force gfp_t)0x10u)	/* Can wait and reschedule? */
-#define __GFP_HIGH	((__force gfp_t)0x20u)	/* Should access emergency pools? */
-#define __GFP_IO	((__force gfp_t)0x40u)	/* Can start physical IO? */
-#define __GFP_FS	((__force gfp_t)0x80u)	/* Can call down to low-level FS? */
-#define __GFP_COLD	((__force gfp_t)0x100u)	/* Cache-cold page required */
-#define __GFP_NOWARN	((__force gfp_t)0x200u)	/* Suppress page allocation failure warning */
-#define __GFP_REPEAT	((__force gfp_t)0x400u)	/* See above */
-#define __GFP_NOFAIL	((__force gfp_t)0x800u)	/* See above */
-#define __GFP_NORETRY	((__force gfp_t)0x1000u)/* See above */
-#define __GFP_COMP	((__force gfp_t)0x4000u)/* Add compound page metadata */
-#define __GFP_ZERO	((__force gfp_t)0x8000u)/* Return zeroed page on success */
-#define __GFP_NOMEMALLOC ((__force gfp_t)0x10000u) /* Don't use emergency reserves */
-#define __GFP_HARDWALL   ((__force gfp_t)0x20000u) /* Enforce hardwall cpuset memory allocs */
-#define __GFP_THISNODE	((__force gfp_t)0x40000u)/* No fallback, no policies */
-#define __GFP_RECLAIMABLE ((__force gfp_t)0x80000u) /* Page is reclaimable */
-
-#ifdef CONFIG_KMEMCHECK
-#define __GFP_NOTRACK	((__force gfp_t)0x200000u)  /* Don't track with kmemcheck */
-#else
-#define __GFP_NOTRACK	((__force gfp_t)0)
-#endif
+#define __GFP_WAIT	((__force gfp_t)___GFP_WAIT)	/* Can wait and reschedule? */
+#define __GFP_HIGH	((__force gfp_t)___GFP_HIGH)	/* Should access emergency pools? */
+#define __GFP_IO	((__force gfp_t)___GFP_IO)	/* Can start physical IO? */
+#define __GFP_FS	((__force gfp_t)___GFP_FS)	/* Can call down to low-level FS? */
+#define __GFP_COLD	((__force gfp_t)___GFP_COLD)	/* Cache-cold page required */
+#define __GFP_NOWARN	((__force gfp_t)___GFP_NOWARN)	/* Suppress page allocation failure warning */
+#define __GFP_REPEAT	((__force gfp_t)___GFP_REPEAT)	/* See above */
+#define __GFP_NOFAIL	((__force gfp_t)___GFP_NOFAIL)	/* See above */
+#define __GFP_NORETRY	((__force gfp_t)___GFP_NORETRY) /* See above */
+#define __GFP_COMP	((__force gfp_t)___GFP_COMP)	/* Add compound page metadata */
+#define __GFP_ZERO	((__force gfp_t)___GFP_ZERO)	/* Return zeroed page on success */
+#define __GFP_NOMEMALLOC ((__force gfp_t)___GFP_NOMEMALLOC) /* Don't use emergency reserves */
+#define __GFP_HARDWALL   ((__force gfp_t)___GFP_HARDWALL) /* Enforce hardwall cpuset memory allocs */
+#define __GFP_THISNODE	((__force gfp_t)___GFP_THISNODE)/* No fallback, no policies */
+#define __GFP_RECLAIMABLE ((__force gfp_t)___GFP_RECLAIMABLE) /* Page is reclaimable */
+#define __GFP_NOTRACK	((__force gfp_t)___GFP_NOTRACK)  /* Don't track with kmemcheck */
 
 /*
  * This may seem redundant, but it's a way of annotating false positives vs.
@@ -186,14 +207,14 @@
 #endif
 
 #define GFP_ZONE_TABLE ( \
-	(ZONE_NORMAL << 0 * ZONES_SHIFT)				\
-	| (OPT_ZONE_DMA << __GFP_DMA * ZONES_SHIFT)			\
-	| (OPT_ZONE_HIGHMEM << __GFP_HIGHMEM * ZONES_SHIFT)		\
-	| (OPT_ZONE_DMA32 << __GFP_DMA32 * ZONES_SHIFT)			\
-	| (ZONE_NORMAL << __GFP_MOVABLE * ZONES_SHIFT)			\
-	| (OPT_ZONE_DMA << (__GFP_MOVABLE | __GFP_DMA) * ZONES_SHIFT)	\
-	| (ZONE_MOVABLE << (__GFP_MOVABLE | __GFP_HIGHMEM) * ZONES_SHIFT)\
-	| (OPT_ZONE_DMA32 << (__GFP_MOVABLE | __GFP_DMA32) * ZONES_SHIFT)\
+	(ZONE_NORMAL << 0 * ZONES_SHIFT)				      \
+	| (OPT_ZONE_DMA << ___GFP_DMA * ZONES_SHIFT)			      \
+	| (OPT_ZONE_HIGHMEM << ___GFP_HIGHMEM * ZONES_SHIFT)		      \
+	| (OPT_ZONE_DMA32 << ___GFP_DMA32 * ZONES_SHIFT)		      \
+	| (ZONE_NORMAL << ___GFP_MOVABLE * ZONES_SHIFT)			      \
+	| (OPT_ZONE_DMA << (___GFP_MOVABLE | ___GFP_DMA) * ZONES_SHIFT)	      \
+	| (ZONE_MOVABLE << (___GFP_MOVABLE | ___GFP_HIGHMEM) * ZONES_SHIFT)   \
+	| (OPT_ZONE_DMA32 << (___GFP_MOVABLE | ___GFP_DMA32) * ZONES_SHIFT)   \
 )
 
 /*
@@ -203,20 +224,20 @@
  * allowed.
  */
 #define GFP_ZONE_BAD ( \
-	1 << (__GFP_DMA | __GFP_HIGHMEM)				\
-	| 1 << (__GFP_DMA | __GFP_DMA32)				\
-	| 1 << (__GFP_DMA32 | __GFP_HIGHMEM)				\
-	| 1 << (__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM)		\
-	| 1 << (__GFP_MOVABLE | __GFP_HIGHMEM | __GFP_DMA)		\
-	| 1 << (__GFP_MOVABLE | __GFP_DMA32 | __GFP_DMA)		\
-	| 1 << (__GFP_MOVABLE | __GFP_DMA32 | __GFP_HIGHMEM)		\
-	| 1 << (__GFP_MOVABLE | __GFP_DMA32 | __GFP_DMA | __GFP_HIGHMEM)\
+	1 << (___GFP_DMA | ___GFP_HIGHMEM)				      \
+	| 1 << (___GFP_DMA | ___GFP_DMA32)				      \
+	| 1 << (___GFP_DMA32 | ___GFP_HIGHMEM)				      \
+	| 1 << (___GFP_DMA | ___GFP_DMA32 | ___GFP_HIGHMEM)		      \
+	| 1 << (___GFP_MOVABLE | ___GFP_HIGHMEM | ___GFP_DMA)		      \
+	| 1 << (___GFP_MOVABLE | ___GFP_DMA32 | ___GFP_DMA)		      \
+	| 1 << (___GFP_MOVABLE | ___GFP_DMA32 | ___GFP_HIGHMEM)		      \
+	| 1 << (___GFP_MOVABLE | ___GFP_DMA32 | ___GFP_DMA | ___GFP_HIGHMEM)  \
 )
 
 static inline enum zone_type gfp_zone(gfp_t flags)
 {
 	enum zone_type z;
-	int bit = flags & GFP_ZONEMASK;
+	int bit = (__force int) (flags & GFP_ZONEMASK);
 
 	z = (GFP_ZONE_TABLE >> (bit * ZONES_SHIFT)) &
 					 ((1 << ZONES_SHIFT) - 1);
diff --git a/include/linux/gpio-fan.h b/include/linux/gpio-fan.h
new file mode 100644
index 0000000..0966591
--- /dev/null
+++ b/include/linux/gpio-fan.h
@@ -0,0 +1,36 @@
+/*
+ * include/linux/gpio-fan.h
+ *
+ * Platform data structure for GPIO fan driver
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __LINUX_GPIO_FAN_H
+#define __LINUX_GPIO_FAN_H
+
+struct gpio_fan_alarm {
+	unsigned	gpio;
+	unsigned	active_low;
+};
+
+struct gpio_fan_speed {
+	int rpm;
+	int ctrl_val;
+};
+
+struct gpio_fan_platform_data {
+	int			num_ctrl;
+	unsigned		*ctrl;	/* fan control GPIOs. */
+	struct gpio_fan_alarm	*alarm;	/* fan alarm GPIO. */
+	/*
+	 * Speed conversion array: rpm from/to GPIO bit field.
+	 * This array _must_ be sorted in ascending rpm order.
+	 */
+	int			num_speed;
+	struct gpio_fan_speed	*speed;
+};
+
+#endif /* __LINUX_GPIO_FAN_H */
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
index e3060ef..8a85ec1 100644
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -28,18 +28,6 @@
 
 #include <asm/kmap_types.h>
 
-#ifdef CONFIG_DEBUG_HIGHMEM
-
-void debug_kmap_atomic(enum km_type type);
-
-#else
-
-static inline void debug_kmap_atomic(enum km_type type)
-{
-}
-
-#endif
-
 #ifdef CONFIG_HIGHMEM
 #include <asm/highmem.h>
 
@@ -49,6 +37,27 @@
 
 void kmap_flush_unused(void);
 
+DECLARE_PER_CPU(int, __kmap_atomic_idx);
+
+static inline int kmap_atomic_idx_push(void)
+{
+	int idx = __get_cpu_var(__kmap_atomic_idx)++;
+#ifdef CONFIG_DEBUG_HIGHMEM
+	WARN_ON_ONCE(in_irq() && !irqs_disabled());
+	BUG_ON(idx > KM_TYPE_NR);
+#endif
+	return idx;
+}
+
+static inline int kmap_atomic_idx_pop(void)
+{
+	int idx = --__get_cpu_var(__kmap_atomic_idx);
+#ifdef CONFIG_DEBUG_HIGHMEM
+	BUG_ON(idx < 0);
+#endif
+	return idx;
+}
+
 #else /* CONFIG_HIGHMEM */
 
 static inline unsigned int nr_free_highpages(void) { return 0; }
@@ -66,19 +75,19 @@
 {
 }
 
-static inline void *kmap_atomic(struct page *page, enum km_type idx)
+static inline void *__kmap_atomic(struct page *page)
 {
 	pagefault_disable();
 	return page_address(page);
 }
-#define kmap_atomic_prot(page, idx, prot)	kmap_atomic(page, idx)
+#define kmap_atomic_prot(page, prot)	__kmap_atomic(page)
 
-static inline void kunmap_atomic_notypecheck(void *addr, enum km_type idx)
+static inline void __kunmap_atomic(void *addr)
 {
 	pagefault_enable();
 }
 
-#define kmap_atomic_pfn(pfn, idx)	kmap_atomic(pfn_to_page(pfn), (idx))
+#define kmap_atomic_pfn(pfn)	kmap_atomic(pfn_to_page(pfn))
 #define kmap_atomic_to_page(ptr)	virt_to_page(ptr)
 
 #define kmap_flush_unused()	do {} while(0)
@@ -86,12 +95,20 @@
 
 #endif /* CONFIG_HIGHMEM */
 
-/* Prevent people trying to call kunmap_atomic() as if it were kunmap() */
-/* kunmap_atomic() should get the return value of kmap_atomic, not the page. */
-#define kunmap_atomic(addr, idx) do { \
-		BUILD_BUG_ON(__same_type((addr), struct page *)); \
-		kunmap_atomic_notypecheck((addr), (idx)); \
-	} while (0)
+/*
+ * Make both: kmap_atomic(page, idx) and kmap_atomic(page) work.
+ */
+#define kmap_atomic(page, args...) __kmap_atomic(page)
+
+/*
+ * Prevent people trying to call kunmap_atomic() as if it were kunmap()
+ * kunmap_atomic() should get the return value of kmap_atomic, not the page.
+ */
+#define kunmap_atomic(addr, args...)				\
+do {								\
+	BUILD_BUG_ON(__same_type((addr), struct page *));	\
+	__kunmap_atomic(addr);					\
+} while (0)
 
 /* when CONFIG_HIGHMEM is not set these will be plain clear/copy_page */
 #ifndef clear_user_highpage
@@ -201,8 +218,8 @@
 	vfrom = kmap_atomic(from, KM_USER0);
 	vto = kmap_atomic(to, KM_USER1);
 	copy_user_page(vto, vfrom, vaddr, to);
-	kunmap_atomic(vfrom, KM_USER0);
 	kunmap_atomic(vto, KM_USER1);
+	kunmap_atomic(vfrom, KM_USER0);
 }
 
 #endif
@@ -214,8 +231,8 @@
 	vfrom = kmap_atomic(from, KM_USER0);
 	vto = kmap_atomic(to, KM_USER1);
 	copy_page(vto, vfrom);
-	kunmap_atomic(vfrom, KM_USER0);
 	kunmap_atomic(vto, KM_USER1);
+	kunmap_atomic(vfrom, KM_USER0);
 }
 
 #endif /* _LINUX_HIGHMEM_H */
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index f479700..943c76b 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -43,7 +43,8 @@
 						struct vm_area_struct *vma,
 						int acctflags);
 void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed);
-void __isolate_hwpoisoned_huge_page(struct page *page);
+int dequeue_hwpoisoned_huge_page(struct page *page);
+void copy_huge_page(struct page *dst, struct page *src);
 
 extern unsigned long hugepages_treat_as_movable;
 extern const unsigned long hugetlb_zero, hugetlb_infinity;
@@ -101,7 +102,10 @@
 #define hugetlb_free_pgd_range(tlb, addr, end, floor, ceiling) ({BUG(); 0; })
 #define hugetlb_fault(mm, vma, addr, flags)	({ BUG(); 0; })
 #define huge_pte_offset(mm, address)	0
-#define __isolate_hwpoisoned_huge_page(page)	0
+#define dequeue_hwpoisoned_huge_page(page)	0
+static inline void copy_huge_page(struct page *dst, struct page *src)
+{
+}
 
 #define hugetlb_change_protection(vma, address, end, newprot)
 
@@ -228,6 +232,8 @@
 	struct hstate *hstate;
 };
 
+struct page *alloc_huge_page_node(struct hstate *h, int nid);
+
 /* arch callback */
 int __init alloc_bootmem_huge_page(struct hstate *h);
 
@@ -301,8 +307,14 @@
 	return size_to_hstate(PAGE_SIZE << compound_order(page));
 }
 
+static inline unsigned hstate_index_to_shift(unsigned index)
+{
+	return hstates[index].order + PAGE_SHIFT;
+}
+
 #else
 struct hstate {};
+#define alloc_huge_page_node(h, nid) NULL
 #define alloc_bootmem_huge_page(h) NULL
 #define hstate_file(f) NULL
 #define hstate_vma(v) NULL
@@ -317,6 +329,7 @@
 {
 	return 1;
 }
+#define hstate_index_to_shift(index) 0
 #endif
 
 #endif /* _LINUX_HUGETLB_H */
diff --git a/include/linux/i2c/apds990x.h b/include/linux/i2c/apds990x.h
new file mode 100644
index 0000000..d186fcc
--- /dev/null
+++ b/include/linux/i2c/apds990x.h
@@ -0,0 +1,79 @@
+/*
+ * This file is part of the APDS990x sensor driver.
+ * Chip is combined proximity and ambient light sensor.
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: Samu Onkalo <samu.p.onkalo@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __APDS990X_H__
+#define __APDS990X_H__
+
+
+#define APDS_IRLED_CURR_12mA	0x3
+#define APDS_IRLED_CURR_25mA	0x2
+#define APDS_IRLED_CURR_50mA	0x1
+#define APDS_IRLED_CURR_100mA	0x0
+
+/**
+ * struct apds990x_chip_factors - defines effect of the cover window
+ * @ga: Total glass attenuation
+ * @cf1: clear channel factor 1 for raw to lux conversion
+ * @irf1: IR channel factor 1 for raw to lux conversion
+ * @cf2: clear channel factor 2 for raw to lux conversion
+ * @irf2: IR channel factor 2 for raw to lux conversion
+ * @df: device factor for conversion formulas
+ *
+ * Structure for tuning ALS calculation to match with environment.
+ * Values depend on the material above the sensor and the sensor
+ * itself. If the GA is zero, driver will use uncovered sensor default values
+ * format: decimal value * APDS_PARAM_SCALE except df which is plain integer.
+ */
+#define APDS_PARAM_SCALE 4096
+struct apds990x_chip_factors {
+	int ga;
+	int cf1;
+	int irf1;
+	int cf2;
+	int irf2;
+	int df;
+};
+
+/**
+ * struct apds990x_platform_data - platform data for apsd990x.c driver
+ * @cf: chip factor data
+ * @pddrive: IR-led driving current
+ * @ppcount: number of IR pulses used for proximity estimation
+ * @setup_resources: interrupt line setup call back function
+ * @release_resources: interrupt line release call back function
+ *
+ * Proximity detection result depends heavily on correct ppcount, pdrive
+ * and cover window.
+ *
+ */
+
+struct apds990x_platform_data {
+	struct apds990x_chip_factors cf;
+	u8     pdrive;
+	u8     ppcount;
+	int    (*setup_resources)(void);
+	int    (*release_resources)(void);
+};
+
+#endif
diff --git a/include/linux/i2c/bh1770glc.h b/include/linux/i2c/bh1770glc.h
new file mode 100644
index 0000000..8b5e2df
--- /dev/null
+++ b/include/linux/i2c/bh1770glc.h
@@ -0,0 +1,53 @@
+/*
+ * This file is part of the ROHM BH1770GLC / OSRAM SFH7770 sensor driver.
+ * Chip is combined proximity and ambient light sensor.
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: Samu Onkalo <samu.p.onkalo@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __BH1770_H__
+#define __BH1770_H__
+
+/**
+ * struct bh1770_platform_data - platform data for bh1770glc driver
+ * @led_def_curr: IR led driving current.
+ * @glass_attenuation: Attenuation factor for covering window.
+ * @setup_resources: Call back for interrupt line setup function
+ * @release_resources: Call back for interrupte line release function
+ *
+ * Example of glass attenuation: 16384 * 385 / 100 means attenuation factor
+ * of 3.85. i.e. light_above_sensor = light_above_cover_window / 3.85
+ */
+
+struct bh1770_platform_data {
+#define BH1770_LED_5mA	0
+#define BH1770_LED_10mA	1
+#define BH1770_LED_20mA	2
+#define BH1770_LED_50mA	3
+#define BH1770_LED_100mA 4
+#define BH1770_LED_150mA 5
+#define BH1770_LED_200mA 6
+	__u8 led_def_curr;
+#define BH1770_NEUTRAL_GA 16384 /* 16384 / 16384 = 1 */
+	__u32 glass_attenuation;
+	int (*setup_resources)(void);
+	int (*release_resources)(void);
+};
+#endif
diff --git a/include/linux/idr.h b/include/linux/idr.h
index 928ae71..13a801f 100644
--- a/include/linux/idr.h
+++ b/include/linux/idr.h
@@ -81,6 +81,7 @@
 #define _idr_rc_to_errno(rc) ((rc) == -1 ? -EAGAIN : -ENOSPC)
 
 /**
+ * DOC: idr sync
  * idr synchronization (stolen from radix-tree.h)
  *
  * idr_find() is able to be called locklessly, using RCU. The caller must
diff --git a/include/linux/io-mapping.h b/include/linux/io-mapping.h
index 7fb5927..8cdcc2a1 100644
--- a/include/linux/io-mapping.h
+++ b/include/linux/io-mapping.h
@@ -81,8 +81,7 @@
 /* Atomic map/unmap */
 static inline void __iomem *
 io_mapping_map_atomic_wc(struct io_mapping *mapping,
-			 unsigned long offset,
-			 int slot)
+			 unsigned long offset)
 {
 	resource_size_t phys_addr;
 	unsigned long pfn;
@@ -90,13 +89,13 @@
 	BUG_ON(offset >= mapping->size);
 	phys_addr = mapping->base + offset;
 	pfn = (unsigned long) (phys_addr >> PAGE_SHIFT);
-	return iomap_atomic_prot_pfn(pfn, slot, mapping->prot);
+	return iomap_atomic_prot_pfn(pfn, mapping->prot);
 }
 
 static inline void
-io_mapping_unmap_atomic(void __iomem *vaddr, int slot)
+io_mapping_unmap_atomic(void __iomem *vaddr)
 {
-	iounmap_atomic(vaddr, slot);
+	iounmap_atomic(vaddr);
 }
 
 static inline void __iomem *
@@ -137,14 +136,13 @@
 /* Atomic map/unmap */
 static inline void __iomem *
 io_mapping_map_atomic_wc(struct io_mapping *mapping,
-			 unsigned long offset,
-			 int slot)
+			 unsigned long offset)
 {
 	return ((char __force __iomem *) mapping) + offset;
 }
 
 static inline void
-io_mapping_unmap_atomic(void __iomem *vaddr, int slot)
+io_mapping_unmap_atomic(void __iomem *vaddr)
 {
 }
 
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index edef168..450092c 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -173,6 +173,11 @@
 		(__x < 0) ? -__x : __x;		\
 	})
 
+#define abs64(x) ({				\
+		s64 __x = (x);			\
+		(__x < 0) ? -__x : __x;		\
+	})
+
 #ifdef CONFIG_PROVE_LOCKING
 void might_fault(void);
 #else
@@ -203,10 +208,10 @@
 extern long simple_strtol(const char *,char **,unsigned int);
 extern unsigned long long simple_strtoull(const char *,char **,unsigned int);
 extern long long simple_strtoll(const char *,char **,unsigned int);
-extern int strict_strtoul(const char *, unsigned int, unsigned long *);
-extern int strict_strtol(const char *, unsigned int, long *);
-extern int strict_strtoull(const char *, unsigned int, unsigned long long *);
-extern int strict_strtoll(const char *, unsigned int, long long *);
+extern int __must_check strict_strtoul(const char *, unsigned int, unsigned long *);
+extern int __must_check strict_strtol(const char *, unsigned int, long *);
+extern int __must_check strict_strtoull(const char *, unsigned int, unsigned long long *);
+extern int __must_check strict_strtoll(const char *, unsigned int, long long *);
 extern int sprintf(char * buf, const char * fmt, ...)
 	__attribute__ ((format (printf, 2, 3)));
 extern int vsprintf(char *buf, const char *, va_list)
@@ -277,6 +282,11 @@
 asmlinkage int printk(const char * fmt, ...)
 	__attribute__ ((format (printf, 1, 2))) __cold;
 
+/*
+ * Please don't use printk_ratelimit(), because it shares ratelimiting state
+ * with all other unrelated printk_ratelimit() callsites.  Instead use
+ * printk_ratelimited() or plain old __ratelimit().
+ */
 extern int __printk_ratelimit(const char *func);
 #define printk_ratelimit() __printk_ratelimit(__func__)
 extern bool printk_timed_ratelimit(unsigned long *caller_jiffies,
@@ -651,6 +661,24 @@
 	(void) (&_max1 == &_max2);		\
 	_max1 > _max2 ? _max1 : _max2; })
 
+#define min3(x, y, z) ({			\
+	typeof(x) _min1 = (x);			\
+	typeof(y) _min2 = (y);			\
+	typeof(z) _min3 = (z);			\
+	(void) (&_min1 == &_min2);		\
+	(void) (&_min1 == &_min3);		\
+	_min1 < _min2 ? (_min1 < _min3 ? _min1 : _min3) : \
+		(_min2 < _min3 ? _min2 : _min3); })
+
+#define max3(x, y, z) ({			\
+	typeof(x) _max1 = (x);			\
+	typeof(y) _max2 = (y);			\
+	typeof(z) _max3 = (z);			\
+	(void) (&_max1 == &_max2);		\
+	(void) (&_max1 == &_max3);		\
+	_max1 > _max2 ? (_max1 > _max3 ? _max1 : _max3) : \
+		(_max2 > _max3 ? _max2 : _max3); })
+
 /**
  * min_not_zero - return the minimum that is _not_ zero, unless both are zero
  * @x: value1
diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h
index 62dbee5..c238ad2 100644
--- a/include/linux/kfifo.h
+++ b/include/linux/kfifo.h
@@ -171,11 +171,8 @@
 	}
 
 
-static inline unsigned int __must_check
-__kfifo_must_check_helper(unsigned int val)
-{
-	return val;
-}
+/* __kfifo_must_check_helper() is temporarily disabled because it was faulty */
+#define __kfifo_must_check_helper(x) (x)
 
 /**
  * kfifo_initialized - Check if the fifo is initialized
diff --git a/include/linux/lis3lv02d.h b/include/linux/lis3lv02d.h
index 0e8a346..d4292c8 100644
--- a/include/linux/lis3lv02d.h
+++ b/include/linux/lis3lv02d.h
@@ -1,6 +1,52 @@
 #ifndef __LIS3LV02D_H_
 #define __LIS3LV02D_H_
 
+/**
+ * struct lis3lv02d_platform_data - lis3 chip family platform data
+ * @click_flags:	Click detection unit configuration
+ * @click_thresh_x:	Click detection unit x axis threshold
+ * @click_thresh_y:	Click detection unit y axis threshold
+ * @click_thresh_z:	Click detection unit z axis threshold
+ * @click_time_limit:	Click detection unit time parameter
+ * @click_latency:	Click detection unit latency parameter
+ * @click_window:	Click detection unit window parameter
+ * @irq_cfg:		On chip irq source and type configuration (click /
+ *			data available / wake up, open drain, polarity)
+ * @irq_flags1:		Additional irq triggering flags for irq channel 0
+ * @irq_flags2:		Additional irq triggering flags for irq channel 1
+ * @duration1:		Wake up unit 1 duration parameter
+ * @duration2:		Wake up unit 2 duration parameter
+ * @wakeup_flags:	Wake up unit 1 flags
+ * @wakeup_thresh:	Wake up unit 1 threshold value
+ * @wakeup_flags2:	Wake up unit 2 flags
+ * @wakeup_thresh2:	Wake up unit 2 threshold value
+ * @hipass_ctrl:	High pass filter control (enable / disable, cut off
+ *			frequency)
+ * @axis_x:		Sensor orientation remapping for x-axis
+ * @axis_y:		Sensor orientation remapping for y-axis
+ * @axis_z:		Sensor orientation remapping for z-axis
+ * @driver_features:	Enable bits for different features. Disabled by default
+ * @default_rate:	Default sampling rate. 0 means reset default
+ * @setup_resources:	Interrupt line setup call back function
+ * @release_resources:	Interrupt line release call back function
+ * @st_min_limits[3]:	Selftest acceptance minimum values
+ * @st_max_limits[3]:	Selftest acceptance maximum values
+ * @irq2:		Irq line 2 number
+ *
+ * Platform data is used to setup the sensor chip. Meaning of the different
+ * chip features can be found from the data sheet. It is publicly available
+ * at www.st.com web pages. Currently the platform data is used
+ * only for the 8 bit device. The 8 bit device has two wake up / free fall
+ * detection units and click detection unit. There are plenty of ways to
+ * configure the chip which makes is quite hard to explain deeper meaning of
+ * the fields here. Behaviour of the detection blocks varies heavily depending
+ * on the configuration. For example, interrupt detection block can use high
+ * pass filtered data which makes it react to the changes in the acceleration.
+ * Irq_flags can be used to enable interrupt detection on the both edges.
+ * With proper chip configuration this produces interrupt when some trigger
+ * starts and when it goes away.
+ */
+
 struct lis3lv02d_platform_data {
 	/* please note: the 'click' feature is only supported for
 	 * LIS[32]02DL variants of the chip and will be ignored for
@@ -36,7 +82,10 @@
 #define LIS3_IRQ_OPEN_DRAIN	(1 << 6)
 #define LIS3_IRQ_ACTIVE_LOW	(1 << 7)
 	unsigned char irq_cfg;
-
+	unsigned char irq_flags1; /* Additional irq edge / level flags */
+	unsigned char irq_flags2; /* Additional irq edge / level flags */
+	unsigned char duration1;
+	unsigned char duration2;
 #define LIS3_WAKEUP_X_LO	(1 << 0)
 #define LIS3_WAKEUP_X_HI	(1 << 1)
 #define LIS3_WAKEUP_Y_LO	(1 << 2)
@@ -64,6 +113,10 @@
 	s8 axis_x;
 	s8 axis_y;
 	s8 axis_z;
+#define LIS3_USE_REGULATOR_CTRL 0x01
+#define LIS3_USE_BLOCK_READ	0x02
+	u16 driver_features;
+	int default_rate;
 	int (*setup_resources)(void);
 	int (*release_resources)(void);
 	/* Limits for selftest are specified in chip data sheet */
diff --git a/include/linux/math64.h b/include/linux/math64.h
index c87f152..23fcdfc 100644
--- a/include/linux/math64.h
+++ b/include/linux/math64.h
@@ -35,6 +35,14 @@
 	return dividend / divisor;
 }
 
+/**
+ * div64_s64 - signed 64bit divide with 64bit divisor
+ */
+static inline s64 div64_s64(s64 dividend, s64 divisor)
+{
+	return dividend / divisor;
+}
+
 #elif BITS_PER_LONG == 32
 
 #ifndef div_u64_rem
@@ -53,6 +61,10 @@
 extern u64 div64_u64(u64 dividend, u64 divisor);
 #endif
 
+#ifndef div64_s64
+extern s64 div64_s64(s64 dividend, s64 divisor);
+#endif
+
 #endif /* BITS_PER_LONG */
 
 /**
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
index 864035f..4307231 100644
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
@@ -70,6 +70,10 @@
 extern int online_pages(unsigned long, unsigned long);
 extern void __offline_isolated_pages(unsigned long, unsigned long);
 
+#ifdef CONFIG_MEMORY_HOTREMOVE
+extern bool is_pageblock_removable_nolock(struct page *page);
+#endif /* CONFIG_MEMORY_HOTREMOVE */
+
 /* reasonably generic interface to expand the physical pages in a zone  */
 extern int __add_pages(int nid, struct zone *zone, unsigned long start_pfn,
 	unsigned long nr_pages);
diff --git a/include/linux/migrate.h b/include/linux/migrate.h
index 7238231..085527f 100644
--- a/include/linux/migrate.h
+++ b/include/linux/migrate.h
@@ -14,6 +14,8 @@
 			struct page *, struct page *);
 extern int migrate_pages(struct list_head *l, new_page_t x,
 			unsigned long private, int offlining);
+extern int migrate_huge_pages(struct list_head *l, new_page_t x,
+			unsigned long private, int offlining);
 
 extern int fail_migrate_page(struct address_space *,
 			struct page *, struct page *);
@@ -23,12 +25,17 @@
 extern int migrate_vmas(struct mm_struct *mm,
 		const nodemask_t *from, const nodemask_t *to,
 		unsigned long flags);
+extern void migrate_page_copy(struct page *newpage, struct page *page);
+extern int migrate_huge_page_move_mapping(struct address_space *mapping,
+				  struct page *newpage, struct page *page);
 #else
 #define PAGE_MIGRATION 0
 
 static inline void putback_lru_pages(struct list_head *l) {}
 static inline int migrate_pages(struct list_head *l, new_page_t x,
 		unsigned long private, int offlining) { return -ENOSYS; }
+static inline int migrate_huge_pages(struct list_head *l, new_page_t x,
+		unsigned long private, int offlining) { return -ENOSYS; }
 
 static inline int migrate_prep(void) { return -ENOSYS; }
 static inline int migrate_prep_local(void) { return -ENOSYS; }
@@ -40,6 +47,15 @@
 	return -ENOSYS;
 }
 
+static inline void migrate_page_copy(struct page *newpage,
+				     struct page *page) {}
+
+static inline int migrate_huge_page_move_mapping(struct address_space *mapping,
+				  struct page *newpage, struct page *page)
+{
+	return -ENOSYS;
+}
+
 /* Possible settings for the migrate_page() method in address_operations */
 #define migrate_page NULL
 #define fail_migrate_page NULL
diff --git a/include/linux/mlx4/cmd.h b/include/linux/mlx4/cmd.h
index 78a1b96..9a18667 100644
--- a/include/linux/mlx4/cmd.h
+++ b/include/linux/mlx4/cmd.h
@@ -58,6 +58,7 @@
 	MLX4_CMD_SENSE_PORT	 = 0x4d,
 	MLX4_CMD_HW_HEALTH_CHECK = 0x50,
 	MLX4_CMD_SET_PORT	 = 0xc,
+	MLX4_CMD_SET_NODE	 = 0x5a,
 	MLX4_CMD_ACCESS_DDR	 = 0x2e,
 	MLX4_CMD_MAP_ICM	 = 0xffa,
 	MLX4_CMD_UNMAP_ICM	 = 0xff9,
@@ -141,6 +142,7 @@
 	MLX4_SET_PORT_MAC_TABLE = 0x2,
 	MLX4_SET_PORT_VLAN_TABLE = 0x3,
 	MLX4_SET_PORT_PRIO_MAP  = 0x4,
+	MLX4_SET_PORT_GID_TABLE = 0x5,
 };
 
 struct mlx4_dev;
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 7338654..a7b15bc 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -67,7 +67,8 @@
 	MLX4_DEV_CAP_FLAG_ATOMIC	= 1 << 18,
 	MLX4_DEV_CAP_FLAG_RAW_MCAST	= 1 << 19,
 	MLX4_DEV_CAP_FLAG_UD_AV_PORT	= 1 << 20,
-	MLX4_DEV_CAP_FLAG_UD_MCAST	= 1 << 21
+	MLX4_DEV_CAP_FLAG_UD_MCAST	= 1 << 21,
+	MLX4_DEV_CAP_FLAG_IBOE		= 1 << 30
 };
 
 enum {
@@ -171,6 +172,10 @@
 	MLX4_NUM_FEXCH          = 64 * 1024,
 };
 
+enum {
+	MLX4_MAX_FAST_REG_PAGES = 511,
+};
+
 static inline u64 mlx4_fw_ver(u64 major, u64 minor, u64 subminor)
 {
 	return (major << 32) | (minor << 16) | subminor;
@@ -379,6 +384,27 @@
 	u8			dgid[16];
 };
 
+struct mlx4_eth_av {
+	__be32		port_pd;
+	u8		reserved1;
+	u8		smac_idx;
+	u16		reserved2;
+	u8		reserved3;
+	u8		gid_index;
+	u8		stat_rate;
+	u8		hop_limit;
+	__be32		sl_tclass_flowlabel;
+	u8		dgid[16];
+	u32		reserved4[2];
+	__be16		vlan;
+	u8		mac[6];
+};
+
+union mlx4_ext_av {
+	struct mlx4_av		ib;
+	struct mlx4_eth_av	eth;
+};
+
 struct mlx4_dev {
 	struct pci_dev	       *pdev;
 	unsigned long		flags;
@@ -407,6 +433,12 @@
 		if (((type) == MLX4_PORT_TYPE_IB ? (dev)->caps.port_mask : \
 		     ~(dev)->caps.port_mask) & 1 << ((port) - 1))
 
+#define mlx4_foreach_ib_transport_port(port, dev)			\
+	for ((port) = 1; (port) <= (dev)->caps.num_ports; (port)++)	\
+		if (((dev)->caps.port_mask & 1 << ((port) - 1)) ||	\
+		    ((dev)->caps.flags & MLX4_DEV_CAP_FLAG_IBOE))
+
+
 int mlx4_buf_alloc(struct mlx4_dev *dev, int size, int max_direct,
 		   struct mlx4_buf *buf);
 void mlx4_buf_free(struct mlx4_dev *dev, int size, struct mlx4_buf *buf);
@@ -474,6 +506,7 @@
 int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *index);
 void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int index);
 
+int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx);
 int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index);
 void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index);
 
diff --git a/include/linux/mlx4/driver.h b/include/linux/mlx4/driver.h
index 53c5fdb..f407cd4 100644
--- a/include/linux/mlx4/driver.h
+++ b/include/linux/mlx4/driver.h
@@ -44,15 +44,24 @@
 	MLX4_DEV_EVENT_PORT_REINIT,
 };
 
+enum mlx4_protocol {
+	MLX4_PROTOCOL_IB,
+	MLX4_PROTOCOL_EN,
+};
+
 struct mlx4_interface {
 	void *			(*add)	 (struct mlx4_dev *dev);
 	void			(*remove)(struct mlx4_dev *dev, void *context);
 	void			(*event) (struct mlx4_dev *dev, void *context,
 					  enum mlx4_dev_event event, int port);
+	void *			(*get_dev)(struct mlx4_dev *dev, void *context, u8 port);
 	struct list_head	list;
+	enum mlx4_protocol	protocol;
 };
 
 int mlx4_register_interface(struct mlx4_interface *intf);
 void mlx4_unregister_interface(struct mlx4_interface *intf);
 
+void *mlx4_get_protocol_dev(struct mlx4_dev *dev, enum mlx4_protocol proto, int port);
+
 #endif /* MLX4_DRIVER_H */
diff --git a/include/linux/mlx4/qp.h b/include/linux/mlx4/qp.h
index 7abe643..0eeb2a1 100644
--- a/include/linux/mlx4/qp.h
+++ b/include/linux/mlx4/qp.h
@@ -109,10 +109,11 @@
 	__be32			tclass_flowlabel;
 	u8			rgid[16];
 	u8			sched_queue;
-	u8			snooper_flags;
+	u8			vlan_index;
 	u8			reserved3[2];
 	u8			counter_index;
-	u8			reserved4[7];
+	u8			reserved4;
+	u8			dmac[6];
 };
 
 struct mlx4_qp_context {
@@ -166,6 +167,7 @@
 	MLX4_WQE_CTRL_TCP_UDP_CSUM	= 1 << 5,
 	MLX4_WQE_CTRL_INS_VLAN		= 1 << 6,
 	MLX4_WQE_CTRL_STRONG_ORDER	= 1 << 7,
+	MLX4_WQE_CTRL_FORCE_LOOPBACK	= 1 << 0,
 };
 
 struct mlx4_wqe_ctrl_seg {
@@ -219,7 +221,8 @@
 	__be32			av[8];
 	__be32			dqpn;
 	__be32			qkey;
-	__be32			reservd[2];
+	__be16			vlan;
+	u8			mac[6];
 };
 
 struct mlx4_wqe_lso_seg {
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 7687228..721f451 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -144,6 +144,7 @@
 #define FAULT_FLAG_WRITE	0x01	/* Fault was a write access */
 #define FAULT_FLAG_NONLINEAR	0x02	/* Fault was via a nonlinear mapping */
 #define FAULT_FLAG_MKWRITE	0x04	/* Fault was mkwrite of existing pte */
+#define FAULT_FLAG_ALLOW_RETRY	0x08	/* Retry fault if blocking */
 
 /*
  * This interface is used by x86 PAT code to identify a pfn mapping that is
@@ -497,8 +498,8 @@
 #define NODES_PGSHIFT		(NODES_PGOFF * (NODES_WIDTH != 0))
 #define ZONES_PGSHIFT		(ZONES_PGOFF * (ZONES_WIDTH != 0))
 
-/* NODE:ZONE or SECTION:ZONE is used to ID a zone for the buddy allcator */
-#ifdef NODE_NOT_IN_PAGEFLAGS
+/* NODE:ZONE or SECTION:ZONE is used to ID a zone for the buddy allocator */
+#ifdef NODE_NOT_IN_PAGE_FLAGS
 #define ZONEID_SHIFT		(SECTIONS_SHIFT + ZONES_SHIFT)
 #define ZONEID_PGOFF		((SECTIONS_PGOFF < ZONES_PGOFF)? \
 						SECTIONS_PGOFF : ZONES_PGOFF)
@@ -718,12 +719,21 @@
 #define VM_FAULT_SIGBUS	0x0002
 #define VM_FAULT_MAJOR	0x0004
 #define VM_FAULT_WRITE	0x0008	/* Special case for get_user_pages */
-#define VM_FAULT_HWPOISON 0x0010	/* Hit poisoned page */
+#define VM_FAULT_HWPOISON 0x0010	/* Hit poisoned small page */
+#define VM_FAULT_HWPOISON_LARGE 0x0020  /* Hit poisoned large page. Index encoded in upper bits */
 
 #define VM_FAULT_NOPAGE	0x0100	/* ->fault installed the pte, not return page */
 #define VM_FAULT_LOCKED	0x0200	/* ->fault locked the returned page */
+#define VM_FAULT_RETRY	0x0400	/* ->fault blocked, must retry */
 
-#define VM_FAULT_ERROR	(VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_HWPOISON)
+#define VM_FAULT_HWPOISON_LARGE_MASK 0xf000 /* encodes hpage index for large hwpoison */
+
+#define VM_FAULT_ERROR	(VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_HWPOISON | \
+			 VM_FAULT_HWPOISON_LARGE)
+
+/* Encode hstate index for a hwpoisoned large page */
+#define VM_FAULT_SET_HINDEX(x) ((x) << 12)
+#define VM_FAULT_GET_HINDEX(x) (((x) >> 12) & 0xf)
 
 /*
  * Can be called by the pagefault handler when it gets a VM_FAULT_OOM.
@@ -860,6 +870,7 @@
 int redirty_page_for_writepage(struct writeback_control *wbc,
 				struct page *page);
 void account_page_dirtied(struct page *page, struct address_space *mapping);
+void account_page_writeback(struct page *page);
 int set_page_dirty(struct page *page);
 int set_page_dirty_lock(struct page *page);
 int clear_page_dirty_for_io(struct page *page);
@@ -1023,7 +1034,15 @@
 
 int vma_wants_writenotify(struct vm_area_struct *vma);
 
-extern pte_t *get_locked_pte(struct mm_struct *mm, unsigned long addr, spinlock_t **ptl);
+extern pte_t *__get_locked_pte(struct mm_struct *mm, unsigned long addr,
+			       spinlock_t **ptl);
+static inline pte_t *get_locked_pte(struct mm_struct *mm, unsigned long addr,
+				    spinlock_t **ptl)
+{
+	pte_t *ptep;
+	__cond_lock(*ptl, ptep = __get_locked_pte(mm, addr, ptl));
+	return ptep;
+}
 
 #ifdef __PAGETABLE_PUD_FOLDED
 static inline int __pud_alloc(struct mm_struct *mm, pgd_t *pgd,
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index cb57d65..bb7288a 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -310,6 +310,8 @@
 #ifdef CONFIG_MMU_NOTIFIER
 	struct mmu_notifier_mm *mmu_notifier_mm;
 #endif
+	/* How many tasks sharing this mm are OOM_DISABLE */
+	atomic_t oom_disable_count;
 };
 
 /* Future-safe accessor for struct mm_struct's cpu_vm_mask. */
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 3984c4e..39c24eb 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -104,6 +104,8 @@
 	NR_ISOLATED_ANON,	/* Temporary isolated pages from anon lru */
 	NR_ISOLATED_FILE,	/* Temporary isolated pages from file lru */
 	NR_SHMEM,		/* shmem pages (included tmpfs/GEM pages) */
+	NR_DIRTIED,		/* page dirtyings since bootup */
+	NR_WRITTEN,		/* page writings since bootup */
 #ifdef CONFIG_NUMA
 	NUMA_HIT,		/* allocated in intended node */
 	NUMA_MISS,		/* allocated in non intended node */
@@ -421,6 +423,9 @@
 typedef enum {
 	ZONE_RECLAIM_LOCKED,		/* prevents concurrent reclaim */
 	ZONE_OOM_LOCKED,		/* zone is in OOM killer zonelist */
+	ZONE_CONGESTED,			/* zone has many dirty pages backed by
+					 * a congested BDI
+					 */
 } zone_flags_t;
 
 static inline void zone_set_flag(struct zone *zone, zone_flags_t flag)
@@ -438,6 +443,11 @@
 	clear_bit(flag, &zone->flags);
 }
 
+static inline int zone_is_reclaim_congested(const struct zone *zone)
+{
+	return test_bit(ZONE_CONGESTED, &zone->flags);
+}
+
 static inline int zone_is_reclaim_locked(const struct zone *zone)
 {
 	return test_bit(ZONE_RECLAIM_LOCKED, &zone->flags);
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h
index 9d2f183..112adf8 100644
--- a/include/linux/moduleparam.h
+++ b/include/linux/moduleparam.h
@@ -21,8 +21,8 @@
 #define __module_cat(a,b) ___module_cat(a,b)
 #define __MODULE_INFO(tag, name, info)					  \
 static const char __module_cat(name,__LINE__)[]				  \
-  __used								  \
-  __attribute__((section(".modinfo"),unused)) = __stringify(tag) "=" info
+  __used __attribute__((section(".modinfo"), unused, aligned(1)))	  \
+  = __stringify(tag) "=" info
 #else  /* !MODULE */
 #define __MODULE_INFO(tag, name, info)
 #endif
diff --git a/include/linux/net.h b/include/linux/net.h
index dee0b11..16faa13 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -229,6 +229,8 @@
 extern int	     sock_wake_async(struct socket *sk, int how, int band);
 extern int	     sock_register(const struct net_proto_family *fam);
 extern void	     sock_unregister(int family);
+extern int	     __sock_create(struct net *net, int family, int type, int proto,
+				 struct socket **res, int kern);
 extern int	     sock_create(int family, int type, int proto,
 				 struct socket **res);
 extern int	     sock_create_kern(int family, int type, int proto,
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index 07e40c6..4925b22 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -17,7 +17,9 @@
 
 #define NFS4_BITMAP_SIZE	2
 #define NFS4_VERIFIER_SIZE	8
-#define NFS4_STATEID_SIZE	16
+#define NFS4_STATEID_SEQID_SIZE 4
+#define NFS4_STATEID_OTHER_SIZE 12
+#define NFS4_STATEID_SIZE	(NFS4_STATEID_SEQID_SIZE + NFS4_STATEID_OTHER_SIZE)
 #define NFS4_FHSIZE		128
 #define NFS4_MAXPATHLEN		PATH_MAX
 #define NFS4_MAXNAMLEN		NAME_MAX
@@ -61,6 +63,9 @@
 #define NFS4_SHARE_SIGNAL_DELEG_WHEN_RESRC_AVAIL	0x10000
 #define NFS4_SHARE_PUSH_DELEG_WHEN_UNCONTENDED		0x20000
 
+#define NFS4_CDFC4_FORE	0x1
+#define NFS4_CDFC4_BACK 0x2
+
 #define NFS4_SET_TO_SERVER_TIME	0
 #define NFS4_SET_TO_CLIENT_TIME	1
 
@@ -167,7 +172,16 @@
 };
 
 typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier;
-typedef struct { char data[NFS4_STATEID_SIZE]; } nfs4_stateid;
+
+struct nfs41_stateid {
+	__be32 seqid;
+	char other[NFS4_STATEID_OTHER_SIZE];
+} __attribute__ ((packed));
+
+typedef union {
+	char data[NFS4_STATEID_SIZE];
+	struct nfs41_stateid stateid;
+} nfs4_stateid;
 
 enum nfs_opnum4 {
 	OP_ACCESS = 3,
@@ -471,6 +485,8 @@
 #define FATTR4_WORD1_TIME_MODIFY        (1UL << 21)
 #define FATTR4_WORD1_TIME_MODIFY_SET    (1UL << 22)
 #define FATTR4_WORD1_MOUNTED_ON_FILEID  (1UL << 23)
+#define FATTR4_WORD1_FS_LAYOUT_TYPES    (1UL << 30)
+#define FATTR4_WORD2_LAYOUT_BLKSIZE     (1UL << 1)
 
 #define NFSPROC4_NULL 0
 #define NFSPROC4_COMPOUND 1
@@ -532,6 +548,8 @@
 	NFSPROC4_CLNT_SEQUENCE,
 	NFSPROC4_CLNT_GET_LEASE_TIME,
 	NFSPROC4_CLNT_RECLAIM_COMPLETE,
+	NFSPROC4_CLNT_LAYOUTGET,
+	NFSPROC4_CLNT_GETDEVICEINFO,
 };
 
 /* nfs41 types */
@@ -550,6 +568,49 @@
 	SP4_SSV		= 2
 };
 
+enum pnfs_layouttype {
+	LAYOUT_NFSV4_1_FILES  = 1,
+	LAYOUT_OSD2_OBJECTS = 2,
+	LAYOUT_BLOCK_VOLUME = 3,
+};
+
+/* used for both layout return and recall */
+enum pnfs_layoutreturn_type {
+	RETURN_FILE = 1,
+	RETURN_FSID = 2,
+	RETURN_ALL  = 3
+};
+
+enum pnfs_iomode {
+	IOMODE_READ = 1,
+	IOMODE_RW = 2,
+	IOMODE_ANY = 3,
+};
+
+enum pnfs_notify_deviceid_type4 {
+	NOTIFY_DEVICEID4_CHANGE = 1 << 1,
+	NOTIFY_DEVICEID4_DELETE = 1 << 2,
+};
+
+#define NFL4_UFLG_MASK			0x0000003F
+#define NFL4_UFLG_DENSE			0x00000001
+#define NFL4_UFLG_COMMIT_THRU_MDS	0x00000002
+#define NFL4_UFLG_STRIPE_UNIT_SIZE_MASK	0xFFFFFFC0
+
+/* Encoded in the loh_body field of type layouthint4 */
+enum filelayout_hint_care4 {
+	NFLH4_CARE_DENSE		= NFL4_UFLG_DENSE,
+	NFLH4_CARE_COMMIT_THRU_MDS	= NFL4_UFLG_COMMIT_THRU_MDS,
+	NFLH4_CARE_STRIPE_UNIT_SIZE	= 0x00000040,
+	NFLH4_CARE_STRIPE_COUNT		= 0x00000080
+};
+
+#define NFS4_DEVICEID4_SIZE 16
+
+struct nfs4_deviceid {
+	char data[NFS4_DEVICEID4_SIZE];
+};
+
 #endif
 #endif
 
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index d0edf7d..bba2668 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -188,6 +188,9 @@
 	struct nfs_delegation __rcu *delegation;
 	fmode_t			 delegation_state;
 	struct rw_semaphore	rwsem;
+
+	/* pNFS layout information */
+	struct pnfs_layout_hdr *layout;
 #endif /* CONFIG_NFS_V4*/
 #ifdef CONFIG_NFS_FSCACHE
 	struct fscache_cookie	*fscache;
@@ -360,10 +363,13 @@
 extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx);
 extern void put_nfs_open_context(struct nfs_open_context *ctx);
 extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, fmode_t mode);
+extern struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct rpc_cred *cred, fmode_t f_mode);
+extern void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx);
 extern struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx);
 extern void nfs_put_lock_context(struct nfs_lock_context *l_ctx);
 extern u64 nfs_compat_user_ino64(u64 fileid);
 extern void nfs_fattr_init(struct nfs_fattr *fattr);
+extern unsigned long nfs_inc_attr_generation_counter(void);
 
 extern struct nfs_fattr *nfs_alloc_fattr(void);
 
@@ -379,9 +385,12 @@
 	kfree(fh);
 }
 
+/*
+ * linux/fs/nfs/nfsroot.c
+ */
+extern int  nfs_root_data(char **root_device, char **root_data); /*__init*/
 /* linux/net/ipv4/ipconfig.c: trims ip addr off front of name, too. */
 extern __be32 root_nfs_parse_addr(char *name); /*__init*/
-extern unsigned long nfs_inc_attr_generation_counter(void);
 
 /*
  * linux/fs/nfs/file.c
@@ -479,10 +488,10 @@
 /*
  * linux/fs/nfs/unlink.c
  */
-extern int  nfs_async_unlink(struct inode *dir, struct dentry *dentry);
 extern void nfs_complete_unlink(struct dentry *dentry, struct inode *);
 extern void nfs_block_sillyrename(struct dentry *dentry);
 extern void nfs_unblock_sillyrename(struct dentry *dentry);
+extern int  nfs_sillyrename(struct inode *dir, struct dentry *dentry);
 
 /*
  * linux/fs/nfs/write.c
@@ -584,10 +593,6 @@
 	return ino;
 }
 
-/* NFS root */
-
-extern void * nfs_root_data(void);
-
 #define nfs_wait_event(clnt, wq, condition)				\
 ({									\
 	int __retval = wait_event_killable(wq, condition);		\
@@ -613,6 +618,8 @@
 #define NFSDBG_CLIENT		0x0200
 #define NFSDBG_MOUNT		0x0400
 #define NFSDBG_FSCACHE		0x0800
+#define NFSDBG_PNFS		0x1000
+#define NFSDBG_PNFS_LD		0x2000
 #define NFSDBG_ALL		0xFFFF
 
 #ifdef __KERNEL__
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index c82ee7c..452d964 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -82,6 +82,8 @@
 	/* The flags used for obtaining the clientid during EXCHANGE_ID */
 	u32			cl_exchange_flags;
 	struct nfs4_session	*cl_session; 	/* sharred session */
+	struct list_head	cl_layouts;
+	struct pnfs_deviceid_cache *cl_devid_cache; /* pNFS deviceid cache */
 #endif /* CONFIG_NFS_V4_1 */
 
 #ifdef CONFIG_NFS_FSCACHE
@@ -124,6 +126,7 @@
 
 	struct nfs_fsid		fsid;
 	__u64			maxfilesize;	/* maximum file size */
+	struct timespec		time_delta;	/* smallest time granularity */
 	unsigned long		mount_time;	/* when this fs was mounted */
 	dev_t			s_dev;		/* superblock dev numbers */
 
@@ -144,6 +147,7 @@
 	u32			acl_bitmask;	/* V4 bitmask representing the ACEs
 						   that are supported on this
 						   filesystem */
+	struct pnfs_layoutdriver_type  *pnfs_curr_ld; /* Active layout driver */
 #endif
 	void (*destroy)(struct nfs_server *);
 
diff --git a/include/linux/nfs_idmap.h b/include/linux/nfs_idmap.h
index 91a1c24..e8352dc 100644
--- a/include/linux/nfs_idmap.h
+++ b/include/linux/nfs_idmap.h
@@ -66,13 +66,40 @@
 /* Forward declaration to make this header independent of others */
 struct nfs_client;
 
+#ifdef CONFIG_NFS_USE_NEW_IDMAPPER
+
+int nfs_idmap_init(void);
+void nfs_idmap_quit(void);
+
+static inline int nfs_idmap_new(struct nfs_client *clp)
+{
+	return 0;
+}
+
+static inline void nfs_idmap_delete(struct nfs_client *clp)
+{
+}
+
+#else /* CONFIG_NFS_USE_NEW_IDMAPPER not set */
+
+static inline int nfs_idmap_init(void)
+{
+	return 0;
+}
+
+static inline void nfs_idmap_quit(void)
+{
+}
+
 int nfs_idmap_new(struct nfs_client *);
 void nfs_idmap_delete(struct nfs_client *);
 
+#endif /* CONFIG_NFS_USE_NEW_IDMAPPER */
+
 int nfs_map_name_to_uid(struct nfs_client *, const char *, size_t, __u32 *);
 int nfs_map_group_to_gid(struct nfs_client *, const char *, size_t, __u32 *);
-int nfs_map_uid_to_name(struct nfs_client *, __u32, char *);
-int nfs_map_gid_to_group(struct nfs_client *, __u32, char *);
+int nfs_map_uid_to_name(struct nfs_client *, __u32, char *, size_t);
+int nfs_map_gid_to_group(struct nfs_client *, __u32, char *, size_t);
 
 extern unsigned int nfs_idmap_cache_timeout;
 #endif /* __KERNEL__ */
diff --git a/include/linux/nfs_mount.h b/include/linux/nfs_mount.h
index 5d59ae8..576bddd 100644
--- a/include/linux/nfs_mount.h
+++ b/include/linux/nfs_mount.h
@@ -71,4 +71,7 @@
 #define NFS_MOUNT_NORESVPORT		0x40000
 #define NFS_MOUNT_LEGACY_INTERFACE	0x80000
 
+#define NFS_MOUNT_LOCAL_FLOCK	0x100000
+#define NFS_MOUNT_LOCAL_FCNTL	0x200000
+
 #endif
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index fc46192..ba6cc8f 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -112,7 +112,9 @@
 	__u32			wtmult;	/* writes should be multiple of this */
 	__u32			dtpref;	/* pref. readdir transfer size */
 	__u64			maxfilesize;
+	struct timespec		time_delta; /* server time granularity */
 	__u32			lease_time; /* in seconds */
+	__u32			layouttype; /* supported pnfs layout driver */
 };
 
 struct nfs_fsstat {
@@ -170,7 +172,7 @@
 
 struct nfs4_sequence_res {
 	struct nfs4_session	*sr_session;
-	u8			sr_slotid;	/* slot used to send request */
+	struct nfs4_slot	*sr_slot;	/* slot used to send request */
 	int			sr_status;	/* sequence operation status */
 	unsigned long		sr_renewal_time;
 	u32			sr_status_flags;
@@ -185,6 +187,55 @@
 	struct nfs4_sequence_res	lr_seq_res;
 };
 
+#define PNFS_LAYOUT_MAXSIZE 4096
+
+struct nfs4_layoutdriver_data {
+	__u32 len;
+	void *buf;
+};
+
+struct pnfs_layout_range {
+	u32 iomode;
+	u64 offset;
+	u64 length;
+};
+
+struct nfs4_layoutget_args {
+	__u32 type;
+	struct pnfs_layout_range range;
+	__u64 minlength;
+	__u32 maxcount;
+	struct inode *inode;
+	struct nfs_open_context *ctx;
+	struct nfs4_sequence_args seq_args;
+};
+
+struct nfs4_layoutget_res {
+	__u32 return_on_close;
+	struct pnfs_layout_range range;
+	__u32 type;
+	nfs4_stateid stateid;
+	struct nfs4_layoutdriver_data layout;
+	struct nfs4_sequence_res seq_res;
+};
+
+struct nfs4_layoutget {
+	struct nfs4_layoutget_args args;
+	struct nfs4_layoutget_res res;
+	struct pnfs_layout_segment **lsegpp;
+	int status;
+};
+
+struct nfs4_getdeviceinfo_args {
+	struct pnfs_device *pdev;
+	struct nfs4_sequence_args seq_args;
+};
+
+struct nfs4_getdeviceinfo_res {
+	struct pnfs_device *pdev;
+	struct nfs4_sequence_res seq_res;
+};
+
 /*
  * Arguments to the open call.
  */
@@ -400,6 +451,27 @@
 };
 
 /*
+ * Common arguments to the rename call
+ */
+struct nfs_renameargs {
+	const struct nfs_fh		*old_dir;
+	const struct nfs_fh		*new_dir;
+	const struct qstr		*old_name;
+	const struct qstr		*new_name;
+	const u32			*bitmask;
+	struct nfs4_sequence_args	seq_args;
+};
+
+struct nfs_renameres {
+	const struct nfs_server		*server;
+	struct nfs4_change_info		old_cinfo;
+	struct nfs_fattr		*old_fattr;
+	struct nfs4_change_info		new_cinfo;
+	struct nfs_fattr		*new_fattr;
+	struct nfs4_sequence_res	seq_res;
+};
+
+/*
  * Argument struct for decode_entry function
  */
 struct nfs_entry {
@@ -434,15 +506,6 @@
 	struct iattr *		sattr;
 };
 
-struct nfs_renameargs {
-	struct nfs_fh *		fromfh;
-	const char *		fromname;
-	unsigned int		fromlen;
-	struct nfs_fh *		tofh;
-	const char *		toname;
-	unsigned int		tolen;
-};
-
 struct nfs_setattrargs {
 	struct nfs_fh *                 fh;
 	nfs4_stateid                    stateid;
@@ -586,15 +649,6 @@
 	dev_t			rdev;
 };
 
-struct nfs3_renameargs {
-	struct nfs_fh *		fromfh;
-	const char *		fromname;
-	unsigned int		fromlen;
-	struct nfs_fh *		tofh;
-	const char *		toname;
-	unsigned int		tolen;
-};
-
 struct nfs3_linkargs {
 	struct nfs_fh *		fromfh;
 	struct nfs_fh *		tofh;
@@ -629,11 +683,6 @@
 	struct page **		pages;
 };
 
-struct nfs3_renameres {
-	struct nfs_fattr *	fromattr;
-	struct nfs_fattr *	toattr;
-};
-
 struct nfs3_linkres {
 	struct nfs_fattr *	dir_attr;
 	struct nfs_fattr *	fattr;
@@ -780,6 +829,7 @@
 	struct page **			pages;	/* zero-copy data */
 	unsigned int			pgbase;	/* zero-copy data */
 	const u32 *			bitmask;
+	int				plus;
 	struct nfs4_sequence_args	seq_args;
 };
 
@@ -801,24 +851,6 @@
 	struct nfs4_sequence_res	seq_res;
 };
 
-struct nfs4_rename_arg {
-	const struct nfs_fh *		old_dir;
-	const struct nfs_fh *		new_dir;
-	const struct qstr *		old_name;
-	const struct qstr *		new_name;
-	const u32 *			bitmask;
-	struct nfs4_sequence_args	seq_args;
-};
-
-struct nfs4_rename_res {
-	const struct nfs_server *	server;
-	struct nfs4_change_info		old_cinfo;
-	struct nfs_fattr *		old_fattr;
-	struct nfs4_change_info		new_cinfo;
-	struct nfs_fattr *		new_fattr;
-	struct nfs4_sequence_res	seq_res;
-};
-
 #define NFS4_SETCLIENTID_NAMELEN	(127)
 struct nfs4_setclientid {
 	const nfs4_verifier *		sc_verifier;
@@ -1032,19 +1064,21 @@
 	int	(*readlink)(struct inode *, struct page *, unsigned int,
 			    unsigned int);
 	int	(*create)  (struct inode *, struct dentry *,
-			    struct iattr *, int, struct nameidata *);
+			    struct iattr *, int, struct nfs_open_context *);
 	int	(*remove)  (struct inode *, struct qstr *);
 	void	(*unlink_setup)  (struct rpc_message *, struct inode *dir);
 	int	(*unlink_done) (struct rpc_task *, struct inode *);
 	int	(*rename)  (struct inode *, struct qstr *,
 			    struct inode *, struct qstr *);
+	void	(*rename_setup)  (struct rpc_message *msg, struct inode *dir);
+	int	(*rename_done) (struct rpc_task *task, struct inode *old_dir, struct inode *new_dir);
 	int	(*link)    (struct inode *, struct inode *, struct qstr *);
 	int	(*symlink) (struct inode *, struct dentry *, struct page *,
 			    unsigned int, struct iattr *);
 	int	(*mkdir)   (struct inode *, struct dentry *, struct iattr *);
 	int	(*rmdir)   (struct inode *, struct qstr *);
 	int	(*readdir) (struct dentry *, struct rpc_cred *,
-			    u64, struct page *, unsigned int, int);
+			    u64, struct page **, unsigned int, int);
 	int	(*mknod)   (struct inode *, struct dentry *, struct iattr *,
 			    dev_t);
 	int	(*statfs)  (struct nfs_server *, struct nfs_fh *,
@@ -1054,7 +1088,7 @@
 	int	(*pathconf) (struct nfs_server *, struct nfs_fh *,
 			     struct nfs_pathconf *);
 	int	(*set_capabilities)(struct nfs_server *, struct nfs_fh *);
-	__be32 *(*decode_dirent)(__be32 *, struct nfs_entry *, int plus);
+	__be32 *(*decode_dirent)(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int plus);
 	void	(*read_setup)   (struct nfs_read_data *, struct rpc_message *);
 	int	(*read_done)  (struct rpc_task *, struct nfs_read_data *);
 	void	(*write_setup)  (struct nfs_write_data *, struct rpc_message *);
@@ -1065,6 +1099,10 @@
 	int	(*lock_check_bounds)(const struct file_lock *);
 	void	(*clear_acl_cache)(struct inode *);
 	void	(*close_context)(struct nfs_open_context *ctx, int);
+	struct inode * (*open_context) (struct inode *dir,
+				struct nfs_open_context *ctx,
+				int open_flags,
+				struct iattr *iattr);
 };
 
 /*
diff --git a/include/linux/pageblock-flags.h b/include/linux/pageblock-flags.h
index e8c0612..19ef95d 100644
--- a/include/linux/pageblock-flags.h
+++ b/include/linux/pageblock-flags.h
@@ -67,7 +67,8 @@
 
 #define get_pageblock_flags(page) \
 			get_pageblock_flags_group(page, 0, NR_PAGEBLOCK_BITS-1)
-#define set_pageblock_flags(page) \
-			set_pageblock_flags_group(page, 0, NR_PAGEBLOCK_BITS-1)
+#define set_pageblock_flags(page, flags) \
+			set_pageblock_flags_group(page, flags,	\
+						  0, NR_PAGEBLOCK_BITS-1)
 
 #endif	/* PAGEBLOCK_FLAGS_H */
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index e12cdc6..2d1ffe3 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -299,6 +299,8 @@
 extern void __lock_page(struct page *page);
 extern int __lock_page_killable(struct page *page);
 extern void __lock_page_nosync(struct page *page);
+extern int __lock_page_or_retry(struct page *page, struct mm_struct *mm,
+				unsigned int flags);
 extern void unlock_page(struct page *page);
 
 static inline void __set_page_locked(struct page *page)
@@ -351,6 +353,17 @@
 }
 	
 /*
+ * lock_page_or_retry - Lock the page, unless this would block and the
+ * caller indicated that it can handle a retry.
+ */
+static inline int lock_page_or_retry(struct page *page, struct mm_struct *mm,
+				     unsigned int flags)
+{
+	might_sleep();
+	return trylock_page(page) || __lock_page_or_retry(page, mm, flags);
+}
+
+/*
  * This is exported only for wait_on_page_locked/wait_on_page_writeback.
  * Never use this directly!
  */
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 30083a8..7d73256 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -89,6 +89,7 @@
 	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
 	POWER_SUPPLY_PROP_VOLTAGE_AVG,
+	POWER_SUPPLY_PROP_CURRENT_MAX,
 	POWER_SUPPLY_PROP_CURRENT_NOW,
 	POWER_SUPPLY_PROP_CURRENT_AVG,
 	POWER_SUPPLY_PROP_POWER_NOW,
@@ -125,7 +126,10 @@
 	POWER_SUPPLY_TYPE_BATTERY = 0,
 	POWER_SUPPLY_TYPE_UPS,
 	POWER_SUPPLY_TYPE_MAINS,
-	POWER_SUPPLY_TYPE_USB,
+	POWER_SUPPLY_TYPE_USB,		/* Standard Downstream Port */
+	POWER_SUPPLY_TYPE_USB_DCP,	/* Dedicated Charging Port */
+	POWER_SUPPLY_TYPE_USB_CDP,	/* Charging Downstream Port */
+	POWER_SUPPLY_TYPE_USB_ACA,	/* Accessory Charger Adapters */
 };
 
 union power_supply_propval {
diff --git a/include/linux/ratelimit.h b/include/linux/ratelimit.h
index 8f69d09..03ff67b 100644
--- a/include/linux/ratelimit.h
+++ b/include/linux/ratelimit.h
@@ -36,6 +36,8 @@
 	rs->begin = 0;
 }
 
+extern struct ratelimit_state printk_ratelimit_state;
+
 extern int ___ratelimit(struct ratelimit_state *rs, const char *func);
 #define __ratelimit(state) ___ratelimit(state, __func__)
 
diff --git a/include/linux/rmap.h b/include/linux/rmap.h
index 31b2fd7..bb83c0d 100644
--- a/include/linux/rmap.h
+++ b/include/linux/rmap.h
@@ -25,8 +25,8 @@
  * pointing to this anon_vma once its vma list is empty.
  */
 struct anon_vma {
-	spinlock_t lock;	/* Serialize access to vma list */
 	struct anon_vma *root;	/* Root of this anon_vma tree */
+	spinlock_t lock;	/* Serialize access to vma list */
 #if defined(CONFIG_KSM) || defined(CONFIG_MIGRATION)
 
 	/*
@@ -205,9 +205,20 @@
 /*
  * Called from mm/filemap_xip.c to unmap empty zero page
  */
-pte_t *page_check_address(struct page *, struct mm_struct *,
+pte_t *__page_check_address(struct page *, struct mm_struct *,
 				unsigned long, spinlock_t **, int);
 
+static inline pte_t *page_check_address(struct page *page, struct mm_struct *mm,
+					unsigned long address,
+					spinlock_t **ptlp, int sync)
+{
+	pte_t *ptep;
+
+	__cond_lock(*ptlp, ptep = __page_check_address(page, mm, address,
+						       ptlp, sync));
+	return ptep;
+}
+
 /*
  * Used by swapoff to help locate where page is expected in vma.
  */
@@ -230,7 +241,20 @@
 /*
  * Called by memory-failure.c to kill processes.
  */
-struct anon_vma *page_lock_anon_vma(struct page *page);
+struct anon_vma *__page_lock_anon_vma(struct page *page);
+
+static inline struct anon_vma *page_lock_anon_vma(struct page *page)
+{
+	struct anon_vma *anon_vma;
+
+	__cond_lock(RCU, anon_vma = __page_lock_anon_vma(page));
+
+	/* (void) is needed to make gcc happy */
+	(void) __cond_lock(&anon_vma->root->lock, anon_vma);
+
+	return anon_vma;
+}
+
 void page_unlock_anon_vma(struct anon_vma *anon_vma);
 int page_mapped_in_vma(struct page *page, struct vm_area_struct *vma);
 
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 56154bb..393ce94 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1706,7 +1706,6 @@
 #define PF_DUMPCORE	0x00000200	/* dumped core */
 #define PF_SIGNALED	0x00000400	/* killed by a signal */
 #define PF_MEMALLOC	0x00000800	/* Allocating memory */
-#define PF_FLUSHER	0x00001000	/* responsible for disk writeback */
 #define PF_USED_MATH	0x00002000	/* if unset the fpu must be initialized before use */
 #define PF_FREEZING	0x00004000	/* freeze in progress. do not account to load */
 #define PF_NOFREEZE	0x00008000	/* this thread should not be frozen */
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 99e5994..212eb4c 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -196,6 +196,9 @@
 /* High Speed UART for Medfield */
 #define PORT_MFD	95
 
+/* TI OMAP-UART */
+#define PORT_OMAP	96
+
 #ifdef __KERNEL__
 
 #include <linux/compiler.h>
diff --git a/include/linux/sfi.h b/include/linux/sfi.h
index 0299b4c..7f770c6 100644
--- a/include/linux/sfi.h
+++ b/include/linux/sfi.h
@@ -70,9 +70,6 @@
 #define SFI_SIG_APIC		"APIC"
 #define SFI_SIG_XSDT		"XSDT"
 #define SFI_SIG_WAKE		"WAKE"
-#define SFI_SIG_SPIB		"SPIB"
-#define SFI_SIG_I2CB		"I2CB"
-#define SFI_SIG_GPEM		"GPEM"
 #define SFI_SIG_DEVS		"DEVS"
 #define SFI_SIG_GPIO		"GPIO"
 
@@ -168,27 +165,6 @@
 	char	pin_name[16];
 } __packed;
 
-struct sfi_spi_table_entry {
-	u16	host_num;	/* attached to host 0, 1...*/
-	u16	cs;		/* chip select */
-	u16	irq_info;
-	char	name[16];
-	u8	dev_info[10];
-} __packed;
-
-struct sfi_i2c_table_entry {
-	u16	host_num;
-	u16	addr;		/* slave addr */
-	u16	irq_info;
-	char	name[16];
-	u8	dev_info[10];
-} __packed;
-
-struct sfi_gpe_table_entry {
-	u16	logical_id;	/* logical id */
-	u16	phys_id;	/* physical GPE id */
-} __packed;
-
 typedef int (*sfi_table_handler) (struct sfi_table_header *table);
 
 #ifdef CONFIG_SFI
diff --git a/include/linux/signalfd.h b/include/linux/signalfd.h
index b363b91..3ff4961 100644
--- a/include/linux/signalfd.h
+++ b/include/linux/signalfd.h
@@ -33,6 +33,7 @@
 	__u64 ssi_utime;
 	__u64 ssi_stime;
 	__u64 ssi_addr;
+	__u16 ssi_addr_lsb;
 
 	/*
 	 * Pad strcture to 128 bytes. Remember to update the
@@ -43,7 +44,7 @@
 	 * comes out of a read(2) and we really don't want to have
 	 * a compat on read(2).
 	 */
-	__u8 __pad[48];
+	__u8 __pad[46];
 };
 
 
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
index 5bbc447..b202475 100644
--- a/include/linux/sunrpc/auth.h
+++ b/include/linux/sunrpc/auth.h
@@ -122,8 +122,8 @@
 int __init		rpc_init_authunix(void);
 int __init		rpc_init_generic_auth(void);
 int __init		rpcauth_init_module(void);
-void __exit		rpcauth_remove_module(void);
-void __exit		rpc_destroy_generic_auth(void);
+void			rpcauth_remove_module(void);
+void			rpc_destroy_generic_auth(void);
 void 			rpc_destroy_authunix(void);
 
 struct rpc_cred *	rpc_lookup_cred(void);
diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h
index 7bf3e84..6950c98 100644
--- a/include/linux/sunrpc/cache.h
+++ b/include/linux/sunrpc/cache.h
@@ -125,12 +125,15 @@
  */
 struct cache_req {
 	struct cache_deferred_req *(*defer)(struct cache_req *req);
+	int thread_wait;  /* How long (jiffies) we can block the
+			   * current thread to wait for updates.
+			   */
 };
 /* this must be embedded in a deferred_request that is being
  * delayed awaiting cache-fill
  */
 struct cache_deferred_req {
-	struct list_head	hash;	/* on hash chain */
+	struct hlist_node	hash;	/* on hash chain */
 	struct list_head	recent; /* on fifo */
 	struct cache_head	*item;  /* cache item we wait on */
 	void			*owner; /* we might need to discard all defered requests
@@ -194,7 +197,9 @@
 #define NEVER (0x7FFFFFFF)
 extern void __init cache_initialize(void);
 extern int cache_register(struct cache_detail *cd);
+extern int cache_register_net(struct cache_detail *cd, struct net *net);
 extern void cache_unregister(struct cache_detail *cd);
+extern void cache_unregister_net(struct cache_detail *cd, struct net *net);
 
 extern int sunrpc_cache_register_pipefs(struct dentry *parent, const char *,
 					mode_t, struct cache_detail *);
@@ -218,14 +223,42 @@
 	return 0;
 }
 
+/*
+ * timestamps kept in the cache are expressed in seconds
+ * since boot.  This is the best for measuring differences in
+ * real time.
+ */
+static inline time_t seconds_since_boot(void)
+{
+	struct timespec boot;
+	getboottime(&boot);
+	return get_seconds() - boot.tv_sec;
+}
+
+static inline time_t convert_to_wallclock(time_t sinceboot)
+{
+	struct timespec boot;
+	getboottime(&boot);
+	return boot.tv_sec + sinceboot;
+}
+
 static inline time_t get_expiry(char **bpp)
 {
 	int rv;
+	struct timespec boot;
+
 	if (get_int(bpp, &rv))
 		return 0;
 	if (rv < 0)
 		return 0;
-	return rv;
+	getboottime(&boot);
+	return rv - boot.tv_sec;
 }
 
+static inline void sunrpc_invalidate(struct cache_head *h,
+				     struct cache_detail *detail)
+{
+	h->expiry_time = seconds_since_boot() - 1;
+	detail->nextcheck = seconds_since_boot();
+}
 #endif /*  _LINUX_SUNRPC_CACHE_H_ */
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 85f38a63..a5a55f2 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -102,6 +102,7 @@
 #ifdef __KERNEL__
 
 struct rpc_create_args {
+	struct net		*net;
 	int			protocol;
 	struct sockaddr		*address;
 	size_t			addrsize;
@@ -137,7 +138,6 @@
 int		rpcb_v4_register(const u32 program, const u32 version,
 				 const struct sockaddr *address,
 				 const char *netid);
-int		rpcb_getport_sync(struct sockaddr_in *, u32, u32, int);
 void		rpcb_getport_async(struct rpc_task *);
 
 void		rpc_call_start(struct rpc_task *);
diff --git a/include/linux/sunrpc/gss_spkm3.h b/include/linux/sunrpc/gss_spkm3.h
deleted file mode 100644
index e3e6a34..0000000
--- a/include/linux/sunrpc/gss_spkm3.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- *  linux/include/linux/sunrpc/gss_spkm3.h
- *
- *  Copyright (c) 2000 The Regents of the University of Michigan.
- *  All rights reserved.
- *
- *  Andy Adamson   <andros@umich.edu>
- */
-
-#include <linux/sunrpc/auth_gss.h>
-#include <linux/sunrpc/gss_err.h>
-#include <linux/sunrpc/gss_asn1.h>
-
-struct spkm3_ctx {
-	struct xdr_netobj	ctx_id;  /* per message context id */
-	int			endtime; /* endtime of the context */
-	struct xdr_netobj	mech_used;
-	unsigned int		ret_flags ;
-	struct xdr_netobj	conf_alg;
-	struct xdr_netobj	derived_conf_key;
-	struct xdr_netobj	intg_alg;
-	struct xdr_netobj 	derived_integ_key;
-};
-
-/* OIDs declarations for K-ALG, I-ALG, C-ALG, and OWF-ALG */
-extern const struct xdr_netobj hmac_md5_oid;
-extern const struct xdr_netobj cast5_cbc_oid;
-
-/* SPKM InnerContext Token types */
-
-#define SPKM_ERROR_TOK	3
-#define SPKM_MIC_TOK	4
-#define SPKM_WRAP_TOK	5
-#define SPKM_DEL_TOK	6
-
-u32 spkm3_make_token(struct spkm3_ctx *ctx, struct xdr_buf * text, struct xdr_netobj * token, int toktype);
-
-u32 spkm3_read_token(struct spkm3_ctx *ctx, struct xdr_netobj *read_token, struct xdr_buf *message_buffer, int toktype);
-
-#define CKSUMTYPE_RSA_MD5            0x0007
-#define CKSUMTYPE_HMAC_MD5           0x0008
-
-s32 make_spkm3_checksum(s32 cksumtype, struct xdr_netobj *key, char *header,
-		unsigned int hdrlen, struct xdr_buf *body,
-		unsigned int body_offset, struct xdr_netobj *cksum);
-void asn1_bitstring_len(struct xdr_netobj *in, int *enclen, int *zerobits);
-int decode_asn1_bitstring(struct xdr_netobj *out, char *in, int enclen,
-                   int explen);
-void spkm3_mic_header(unsigned char **hdrbuf, unsigned int *hdrlen, 
-                   unsigned char *ctxhdr, int elen, int zbit);
-void spkm3_make_mic_token(unsigned  char **tokp, int toklen, 
-                   struct xdr_netobj *mic_hdr,
-                   struct xdr_netobj *md5cksum, int md5elen, int md5zbit);
-u32 spkm3_verify_mic_token(unsigned char **tokp, int *mic_hdrlen, 
-                   unsigned char **cksum);
diff --git a/include/linux/sunrpc/stats.h b/include/linux/sunrpc/stats.h
index 5fa0f20..680471d 100644
--- a/include/linux/sunrpc/stats.h
+++ b/include/linux/sunrpc/stats.h
@@ -38,8 +38,21 @@
 				rpcbadclnt;
 };
 
-void			rpc_proc_init(void);
-void			rpc_proc_exit(void);
+struct net;
+#ifdef CONFIG_PROC_FS
+int			rpc_proc_init(struct net *);
+void			rpc_proc_exit(struct net *);
+#else
+static inline int rpc_proc_init(struct net *net)
+{
+	return 0;
+}
+
+static inline void rpc_proc_exit(struct net *net)
+{
+}
+#endif
+
 #ifdef MODULE
 void			rpc_modcount(struct inode *, int);
 #endif
@@ -54,9 +67,6 @@
 
 void			svc_seq_show(struct seq_file *,
 				     const struct svc_stat *);
-
-extern struct proc_dir_entry	*proc_net_rpc;
-
 #else
 
 static inline struct proc_dir_entry *rpc_proc_register(struct rpc_stat *s) { return NULL; }
@@ -69,9 +79,6 @@
 
 static inline void svc_seq_show(struct seq_file *seq,
 				const struct svc_stat *st) {}
-
-#define proc_net_rpc NULL
-
 #endif
 
 #endif /* _LINUX_SUNRPC_STATS_H */
diff --git a/include/linux/sunrpc/svc_xprt.h b/include/linux/sunrpc/svc_xprt.h
index 5f4e18b..bbdb680 100644
--- a/include/linux/sunrpc/svc_xprt.h
+++ b/include/linux/sunrpc/svc_xprt.h
@@ -12,6 +12,7 @@
 
 struct svc_xprt_ops {
 	struct svc_xprt	*(*xpo_create)(struct svc_serv *,
+				       struct net *net,
 				       struct sockaddr *, int,
 				       int);
 	struct svc_xprt	*(*xpo_accept)(struct svc_xprt *);
@@ -32,6 +33,16 @@
 	u32			xcl_max_payload;
 };
 
+/*
+ * This is embedded in an object that wants a callback before deleting
+ * an xprt; intended for use by NFSv4.1, which needs to know when a
+ * client's tcp connection (and hence possibly a backchannel) goes away.
+ */
+struct svc_xpt_user {
+	struct list_head list;
+	void (*callback)(struct svc_xpt_user *);
+};
+
 struct svc_xprt {
 	struct svc_xprt_class	*xpt_class;
 	struct svc_xprt_ops	*xpt_ops;
@@ -66,14 +77,31 @@
 	struct sockaddr_storage	xpt_remote;	/* remote peer's address */
 	size_t			xpt_remotelen;	/* length of address */
 	struct rpc_wait_queue	xpt_bc_pending;	/* backchannel wait queue */
+	struct list_head	xpt_users;	/* callbacks on free */
+
+	struct net		*xpt_net;
 };
 
+static inline void register_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u)
+{
+	spin_lock(&xpt->xpt_lock);
+	list_add(&u->list, &xpt->xpt_users);
+	spin_unlock(&xpt->xpt_lock);
+}
+
+static inline void unregister_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u)
+{
+	spin_lock(&xpt->xpt_lock);
+	list_del_init(&u->list);
+	spin_unlock(&xpt->xpt_lock);
+}
+
 int	svc_reg_xprt_class(struct svc_xprt_class *);
 void	svc_unreg_xprt_class(struct svc_xprt_class *);
 void	svc_xprt_init(struct svc_xprt_class *, struct svc_xprt *,
 		      struct svc_serv *);
-int	svc_create_xprt(struct svc_serv *, const char *, const int,
-			const unsigned short, int);
+int	svc_create_xprt(struct svc_serv *, const char *, struct net *,
+			const int, const unsigned short, int);
 void	svc_xprt_enqueue(struct svc_xprt *xprt);
 void	svc_xprt_received(struct svc_xprt *);
 void	svc_xprt_put(struct svc_xprt *xprt);
diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h
index d39dbdc..25d333c 100644
--- a/include/linux/sunrpc/svcauth.h
+++ b/include/linux/sunrpc/svcauth.h
@@ -108,10 +108,15 @@
 #define	SVC_NEGATIVE	4
 #define	SVC_OK		5
 #define	SVC_DROP	6
-#define	SVC_DENIED	7
-#define	SVC_PENDING	8
-#define	SVC_COMPLETE	9
+#define	SVC_CLOSE	7	/* Like SVC_DROP, but request is definitely
+				 * lost so if there is a tcp connection, it
+				 * should be closed
+				 */
+#define	SVC_DENIED	8
+#define	SVC_PENDING	9
+#define	SVC_COMPLETE	10
 
+struct svc_xprt;
 
 extern int	svc_authenticate(struct svc_rqst *rqstp, __be32 *authp);
 extern int	svc_authorise(struct svc_rqst *rqstp);
@@ -121,13 +126,13 @@
 
 extern struct auth_domain *unix_domain_find(char *name);
 extern void auth_domain_put(struct auth_domain *item);
-extern int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain *dom);
+extern int auth_unix_add_addr(struct net *net, struct in6_addr *addr, struct auth_domain *dom);
 extern struct auth_domain *auth_domain_lookup(char *name, struct auth_domain *new);
 extern struct auth_domain *auth_domain_find(char *name);
-extern struct auth_domain *auth_unix_lookup(struct in6_addr *addr);
+extern struct auth_domain *auth_unix_lookup(struct net *net, struct in6_addr *addr);
 extern int auth_unix_forget_old(struct auth_domain *dom);
 extern void svcauth_unix_purge(void);
-extern void svcauth_unix_info_release(void *);
+extern void svcauth_unix_info_release(struct svc_xprt *xpt);
 extern int svcauth_unix_set_client(struct svc_rqst *rqstp);
 
 static inline unsigned long hash_str(char *name, int bits)
diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
index 35cf2e8..498ab93 100644
--- a/include/linux/sunrpc/xdr.h
+++ b/include/linux/sunrpc/xdr.h
@@ -108,6 +108,7 @@
 			 unsigned int);
 void	xdr_inline_pages(struct xdr_buf *, unsigned int,
 			 struct page **, unsigned int, unsigned int);
+void	xdr_terminate_string(struct xdr_buf *, const u32);
 
 static inline __be32 *xdr_encode_array(__be32 *p, const void *s, unsigned int len)
 {
@@ -131,6 +132,13 @@
 	return p + 2;
 }
 
+static inline __be32 *
+xdr_decode_opaque_fixed(__be32 *p, void *ptr, unsigned int len)
+{
+	memcpy(ptr, p, len);
+	return p + XDR_QUADLEN(len);
+}
+
 /*
  * Adjust kvec to reflect end of xdr'ed data (RPC client XDR)
  */
@@ -200,6 +208,7 @@
 extern void xdr_write_pages(struct xdr_stream *xdr, struct page **pages,
 		unsigned int base, unsigned int len);
 extern void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p);
+extern __be32 *xdr_inline_peek(struct xdr_stream *xdr, size_t nbytes);
 extern __be32 *xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes);
 extern void xdr_read_pages(struct xdr_stream *xdr, unsigned int len);
 extern void xdr_enter_page(struct xdr_stream *xdr, unsigned int len);
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index ff5a77b..89d10d2 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -224,6 +224,7 @@
 					bklog_u;	/* backlog queue utilization */
 	} stat;
 
+	struct net		*xprt_net;
 	const char		*address_strings[RPC_DISPLAY_MAX];
 };
 
@@ -249,6 +250,7 @@
 
 struct xprt_create {
 	int			ident;		/* XPRT_TRANSPORT identifier */
+	struct net *		net;
 	struct sockaddr *	srcaddr;	/* optional local address */
 	struct sockaddr *	dstaddr;	/* remote peer address */
 	size_t			addrlen;
@@ -280,6 +282,8 @@
 void			xprt_release(struct rpc_task *task);
 struct rpc_xprt *	xprt_get(struct rpc_xprt *xprt);
 void			xprt_put(struct rpc_xprt *xprt);
+struct rpc_xprt *	xprt_alloc(struct net *net, int size, int max_req);
+void			xprt_free(struct rpc_xprt *);
 
 static inline __be32 *xprt_skip_transport_header(struct rpc_xprt *xprt, __be32 *p)
 {
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 7cdd633..eba53e7 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -271,8 +271,18 @@
 extern unsigned long scan_unevictable_pages;
 extern int scan_unevictable_handler(struct ctl_table *, int,
 					void __user *, size_t *, loff_t *);
+#ifdef CONFIG_NUMA
 extern int scan_unevictable_register_node(struct node *node);
 extern void scan_unevictable_unregister_node(struct node *node);
+#else
+static inline int scan_unevictable_register_node(struct node *node)
+{
+	return 0;
+}
+static inline void scan_unevictable_unregister_node(struct node *node)
+{
+}
+#endif
 
 extern int kswapd_run(int nid);
 extern void kswapd_stop(int nid);
diff --git a/include/linux/types.h b/include/linux/types.h
index 357dbc1..c2a9eb4 100644
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -121,15 +121,7 @@
 typedef		__s64		int64_t;
 #endif
 
-/*
- * aligned_u64 should be used in defining kernel<->userspace ABIs to avoid
- * common 32/64-bit compat problems.
- * 64-bit values align to 4-byte boundaries on x86_32 (and possibly other
- * architectures) and to 8-byte boundaries on 64-bit architetures.  The new
- * aligned_64 type enforces 8-byte alignment so that structs containing
- * aligned_64 values have the same alignment on 32-bit and 64-bit architectures.
- * No conversions are necessary between 32-bit user-space and a 64-bit kernel.
- */
+/* this is a special 64bit data type that is 8-byte aligned */
 #define aligned_u64 __u64 __attribute__((aligned(8)))
 #define aligned_be64 __be64 __attribute__((aligned(8)))
 #define aligned_le64 __le64 __attribute__((aligned(8)))
@@ -186,7 +178,15 @@
 typedef __u16 __bitwise __sum16;
 typedef __u32 __bitwise __wsum;
 
-/* this is a special 64bit data type that is 8-byte aligned */
+/*
+ * aligned_u64 should be used in defining kernel<->userspace ABIs to avoid
+ * common 32/64-bit compat problems.
+ * 64-bit values align to 4-byte boundaries on x86_32 (and possibly other
+ * architectures) and to 8-byte boundaries on 64-bit architetures.  The new
+ * aligned_64 type enforces 8-byte alignment so that structs containing
+ * aligned_64 values have the same alignment on 32-bit and 64-bit architectures.
+ * No conversions are necessary between 32-bit user-space and a 64-bit kernel.
+ */
 #define __aligned_u64 __u64 __attribute__((aligned(8)))
 #define __aligned_be64 __be64 __attribute__((aligned(8)))
 #define __aligned_le64 __le64 __attribute__((aligned(8)))
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index 63a4fe6..a03dcf6 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -53,8 +53,10 @@
 #endif
 
 extern void *vmalloc(unsigned long size);
+extern void *vzalloc(unsigned long size);
 extern void *vmalloc_user(unsigned long size);
 extern void *vmalloc_node(unsigned long size, int node);
+extern void *vzalloc_node(unsigned long size, int node);
 extern void *vmalloc_exec(unsigned long size);
 extern void *vmalloc_32(unsigned long size);
 extern void *vmalloc_32_user(unsigned long size);
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index 070bb7a..0c0771f 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -190,7 +190,7 @@
 		__INIT_WORK((_work), (_func), 0);		\
 	} while (0)
 
-#define INIT_WORK_ON_STACK(_work, _func)			\
+#define INIT_WORK_ONSTACK(_work, _func)				\
 	do {							\
 		__INIT_WORK((_work), (_func), 1);		\
 	} while (0)
@@ -201,9 +201,9 @@
 		init_timer(&(_work)->timer);			\
 	} while (0)
 
-#define INIT_DELAYED_WORK_ON_STACK(_work, _func)		\
+#define INIT_DELAYED_WORK_ONSTACK(_work, _func)			\
 	do {							\
-		INIT_WORK_ON_STACK(&(_work)->work, (_func));	\
+		INIT_WORK_ONSTACK(&(_work)->work, (_func));	\
 		init_timer_on_stack(&(_work)->timer);		\
 	} while (0)
 
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index 242b6f8..d5c7aaa 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -147,6 +147,8 @@
 int do_writepages(struct address_space *mapping, struct writeback_control *wbc);
 void set_page_dirty_balance(struct page *page, int page_mkwrite);
 void writeback_set_ratelimit(void);
+void tag_pages_for_writeback(struct address_space *mapping,
+			     pgoff_t start, pgoff_t end);
 
 /* pdflush.c */
 extern int nr_pdflush_threads;	/* Global so it can be exported to sysctl
diff --git a/include/rdma/ib_addr.h b/include/rdma/ib_addr.h
index fa0d52b..b5fc9f3 100644
--- a/include/rdma/ib_addr.h
+++ b/include/rdma/ib_addr.h
@@ -39,7 +39,9 @@
 #include <linux/if_arp.h>
 #include <linux/netdevice.h>
 #include <linux/socket.h>
+#include <linux/if_vlan.h>
 #include <rdma/ib_verbs.h>
+#include <rdma/ib_pack.h>
 
 struct rdma_addr_client {
 	atomic_t refcount;
@@ -63,6 +65,7 @@
 	unsigned char broadcast[MAX_ADDR_LEN];
 	unsigned short dev_type;
 	int bound_dev_if;
+	enum rdma_transport_type transport;
 };
 
 /**
@@ -127,9 +130,51 @@
 	return dev_addr->dev_type == ARPHRD_INFINIBAND ? 4 : 0;
 }
 
+static inline void iboe_mac_vlan_to_ll(union ib_gid *gid, u8 *mac, u16 vid)
+{
+	memset(gid->raw, 0, 16);
+	*((__be32 *) gid->raw) = cpu_to_be32(0xfe800000);
+	if (vid < 0x1000) {
+		gid->raw[12] = vid & 0xff;
+		gid->raw[11] = vid >> 8;
+	} else {
+		gid->raw[12] = 0xfe;
+		gid->raw[11] = 0xff;
+	}
+	memcpy(gid->raw + 13, mac + 3, 3);
+	memcpy(gid->raw + 8, mac, 3);
+	gid->raw[8] ^= 2;
+}
+
+static inline u16 rdma_vlan_dev_vlan_id(const struct net_device *dev)
+{
+	return dev->priv_flags & IFF_802_1Q_VLAN ?
+		vlan_dev_vlan_id(dev) : 0xffff;
+}
+
+static inline void iboe_addr_get_sgid(struct rdma_dev_addr *dev_addr,
+				      union ib_gid *gid)
+{
+	struct net_device *dev;
+	u16 vid = 0xffff;
+
+	dev = dev_get_by_index(&init_net, dev_addr->bound_dev_if);
+	if (dev) {
+		vid = rdma_vlan_dev_vlan_id(dev);
+		dev_put(dev);
+	}
+
+	iboe_mac_vlan_to_ll(gid, dev_addr->src_dev_addr, vid);
+}
+
 static inline void rdma_addr_get_sgid(struct rdma_dev_addr *dev_addr, union ib_gid *gid)
 {
-	memcpy(gid, dev_addr->src_dev_addr + rdma_addr_gid_offset(dev_addr), sizeof *gid);
+	if (dev_addr->transport == RDMA_TRANSPORT_IB &&
+	    dev_addr->dev_type != ARPHRD_INFINIBAND)
+		iboe_addr_get_sgid(dev_addr, gid);
+	else
+		memcpy(gid, dev_addr->src_dev_addr +
+		       rdma_addr_gid_offset(dev_addr), sizeof *gid);
 }
 
 static inline void rdma_addr_set_sgid(struct rdma_dev_addr *dev_addr, union ib_gid *gid)
@@ -147,4 +192,91 @@
 	memcpy(dev_addr->dst_dev_addr + rdma_addr_gid_offset(dev_addr), gid, sizeof *gid);
 }
 
+static inline enum ib_mtu iboe_get_mtu(int mtu)
+{
+	/*
+	 * reduce IB headers from effective IBoE MTU. 28 stands for
+	 * atomic header which is the biggest possible header after BTH
+	 */
+	mtu = mtu - IB_GRH_BYTES - IB_BTH_BYTES - 28;
+
+	if (mtu >= ib_mtu_enum_to_int(IB_MTU_4096))
+		return IB_MTU_4096;
+	else if (mtu >= ib_mtu_enum_to_int(IB_MTU_2048))
+		return IB_MTU_2048;
+	else if (mtu >= ib_mtu_enum_to_int(IB_MTU_1024))
+		return IB_MTU_1024;
+	else if (mtu >= ib_mtu_enum_to_int(IB_MTU_512))
+		return IB_MTU_512;
+	else if (mtu >= ib_mtu_enum_to_int(IB_MTU_256))
+		return IB_MTU_256;
+	else
+		return 0;
+}
+
+static inline int iboe_get_rate(struct net_device *dev)
+{
+	struct ethtool_cmd cmd;
+
+	if (!dev->ethtool_ops || !dev->ethtool_ops->get_settings ||
+	    dev->ethtool_ops->get_settings(dev, &cmd))
+		return IB_RATE_PORT_CURRENT;
+
+	if (cmd.speed >= 40000)
+		return IB_RATE_40_GBPS;
+	else if (cmd.speed >= 30000)
+		return IB_RATE_30_GBPS;
+	else if (cmd.speed >= 20000)
+		return IB_RATE_20_GBPS;
+	else if (cmd.speed >= 10000)
+		return IB_RATE_10_GBPS;
+	else
+		return IB_RATE_PORT_CURRENT;
+}
+
+static inline int rdma_link_local_addr(struct in6_addr *addr)
+{
+	if (addr->s6_addr32[0] == htonl(0xfe800000) &&
+	    addr->s6_addr32[1] == 0)
+		return 1;
+
+	return 0;
+}
+
+static inline void rdma_get_ll_mac(struct in6_addr *addr, u8 *mac)
+{
+	memcpy(mac, &addr->s6_addr[8], 3);
+	memcpy(mac + 3, &addr->s6_addr[13], 3);
+	mac[0] ^= 2;
+}
+
+static inline int rdma_is_multicast_addr(struct in6_addr *addr)
+{
+	return addr->s6_addr[0] == 0xff;
+}
+
+static inline void rdma_get_mcast_mac(struct in6_addr *addr, u8 *mac)
+{
+	int i;
+
+	mac[0] = 0x33;
+	mac[1] = 0x33;
+	for (i = 2; i < 6; ++i)
+		mac[i] = addr->s6_addr[i + 10];
+}
+
+static inline u16 rdma_get_vlan_id(union ib_gid *dgid)
+{
+	u16 vid;
+
+	vid = dgid->raw[11] << 8 | dgid->raw[12];
+	return vid < 0x1000 ? vid : 0xffff;
+}
+
+static inline struct net_device *rdma_vlan_dev_real_dev(const struct net_device *dev)
+{
+	return dev->priv_flags & IFF_802_1Q_VLAN ?
+		vlan_dev_real_dev(dev) : 0;
+}
+
 #endif /* IB_ADDR_H */
diff --git a/include/rdma/ib_pack.h b/include/rdma/ib_pack.h
index cbb50f4..b37fe3b 100644
--- a/include/rdma/ib_pack.h
+++ b/include/rdma/ib_pack.h
@@ -37,6 +37,8 @@
 
 enum {
 	IB_LRH_BYTES  = 8,
+	IB_ETH_BYTES  = 14,
+	IB_VLAN_BYTES = 4,
 	IB_GRH_BYTES  = 40,
 	IB_BTH_BYTES  = 12,
 	IB_DETH_BYTES = 8
@@ -210,14 +212,32 @@
 	__be32       source_qpn;
 };
 
+struct ib_unpacked_eth {
+	u8	dmac_h[4];
+	u8	dmac_l[2];
+	u8	smac_h[2];
+	u8	smac_l[4];
+	__be16	type;
+};
+
+struct ib_unpacked_vlan {
+	__be16  tag;
+	__be16  type;
+};
+
 struct ib_ud_header {
+	int                     lrh_present;
 	struct ib_unpacked_lrh  lrh;
-	int                     grh_present;
-	struct ib_unpacked_grh  grh;
-	struct ib_unpacked_bth  bth;
+	int			eth_present;
+	struct ib_unpacked_eth	eth;
+	int                     vlan_present;
+	struct ib_unpacked_vlan vlan;
+	int			grh_present;
+	struct ib_unpacked_grh	grh;
+	struct ib_unpacked_bth	bth;
 	struct ib_unpacked_deth deth;
-	int            		immediate_present;
-	__be32         		immediate_data;
+	int			immediate_present;
+	__be32			immediate_data;
 };
 
 void ib_pack(const struct ib_field        *desc,
@@ -230,9 +250,12 @@
 	       void                         *buf,
 	       void                         *structure);
 
-void ib_ud_header_init(int     		   payload_bytes,
-		       int    		   grh_present,
-		       int		   immediate_present,
+void ib_ud_header_init(int		    payload_bytes,
+		       int		    lrh_present,
+		       int		    eth_present,
+		       int		    vlan_present,
+		       int		    grh_present,
+		       int		    immediate_present,
 		       struct ib_ud_header *header);
 
 int ib_ud_header_pack(struct ib_ud_header *header,
diff --git a/include/rdma/ib_user_verbs.h b/include/rdma/ib_user_verbs.h
index a17f771..fe5b051 100644
--- a/include/rdma/ib_user_verbs.h
+++ b/include/rdma/ib_user_verbs.h
@@ -205,7 +205,8 @@
 	__u8  active_width;
 	__u8  active_speed;
 	__u8  phys_state;
-	__u8  reserved[3];
+	__u8  link_layer;
+	__u8  reserved[2];
 };
 
 struct ib_uverbs_alloc_pd {
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 857b3b9..e04c488 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -75,6 +75,12 @@
 enum rdma_transport_type
 rdma_node_get_transport(enum rdma_node_type node_type) __attribute_const__;
 
+enum rdma_link_layer {
+	IB_LINK_LAYER_UNSPECIFIED,
+	IB_LINK_LAYER_INFINIBAND,
+	IB_LINK_LAYER_ETHERNET,
+};
+
 enum ib_device_cap_flags {
 	IB_DEVICE_RESIZE_MAX_WR		= 1,
 	IB_DEVICE_BAD_PKEY_CNTR		= (1<<1),
@@ -1010,6 +1016,8 @@
 	int		           (*query_port)(struct ib_device *device,
 						 u8 port_num,
 						 struct ib_port_attr *port_attr);
+	enum rdma_link_layer	   (*get_link_layer)(struct ib_device *device,
+						     u8 port_num);
 	int		           (*query_gid)(struct ib_device *device,
 						u8 port_num, int index,
 						union ib_gid *gid);
@@ -1222,6 +1230,9 @@
 int ib_query_port(struct ib_device *device,
 		  u8 port_num, struct ib_port_attr *port_attr);
 
+enum rdma_link_layer rdma_port_get_link_layer(struct ib_device *device,
+					       u8 port_num);
+
 int ib_query_gid(struct ib_device *device,
 		 u8 port_num, int index, union ib_gid *gid);
 
diff --git a/include/scsi/srp.h b/include/scsi/srp.h
index ad178fa..1ae84db 100644
--- a/include/scsi/srp.h
+++ b/include/scsi/srp.h
@@ -239,4 +239,42 @@
 	u8	data[0];
 } __attribute__((packed));
 
+struct srp_cred_req {
+	u8	opcode;
+	u8	sol_not;
+	u8	reserved[2];
+	__be32	req_lim_delta;
+	u64	tag;
+};
+
+struct srp_cred_rsp {
+	u8	opcode;
+	u8	reserved[7];
+	u64	tag;
+};
+
+/*
+ * The SRP spec defines the fixed portion of the AER_REQ structure to be
+ * 36 bytes, so it needs to be packed to avoid having it padded to 40 bytes
+ * on 64-bit architectures.
+ */
+struct srp_aer_req {
+	u8	opcode;
+	u8	sol_not;
+	u8	reserved[2];
+	__be32	req_lim_delta;
+	u64	tag;
+	u32	reserved2;
+	__be64	lun;
+	__be32	sense_data_len;
+	u32	reserved3;
+	u8	sense_data[0];
+} __attribute__((packed));
+
+struct srp_aer_rsp {
+	u8	opcode;
+	u8	reserved[7];
+	u64	tag;
+};
+
 #endif /* SCSI_SRP_H */
diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
index 01e9e00..6bcb006 100644
--- a/include/trace/events/ext4.h
+++ b/include/trace/events/ext4.h
@@ -242,18 +242,20 @@
 		__entry->pages_skipped	= wbc->pages_skipped;
 		__entry->range_start	= wbc->range_start;
 		__entry->range_end	= wbc->range_end;
-		__entry->nonblocking	= wbc->nonblocking;
 		__entry->for_kupdate	= wbc->for_kupdate;
 		__entry->for_reclaim	= wbc->for_reclaim;
 		__entry->range_cyclic	= wbc->range_cyclic;
 		__entry->writeback_index = inode->i_mapping->writeback_index;
 	),
 
-	TP_printk("dev %s ino %lu nr_to_write %ld pages_skipped %ld range_start %llu range_end %llu nonblocking %d for_kupdate %d for_reclaim %d range_cyclic %d writeback_index %lu",
+	TP_printk("dev %s ino %lu nr_to_write %ld pages_skipped %ld "
+		  "range_start %llu range_end %llu "
+		  "for_kupdate %d for_reclaim %d "
+		  "range_cyclic %d writeback_index %lu",
 		  jbd2_dev_to_name(__entry->dev),
 		  (unsigned long) __entry->ino, __entry->nr_to_write,
 		  __entry->pages_skipped, __entry->range_start,
-		  __entry->range_end, __entry->nonblocking,
+		  __entry->range_end,
 		  __entry->for_kupdate, __entry->for_reclaim,
 		  __entry->range_cyclic,
 		  (unsigned long) __entry->writeback_index)
diff --git a/include/trace/events/vmscan.h b/include/trace/events/vmscan.h
index 370aa5a..c255fcc 100644
--- a/include/trace/events/vmscan.h
+++ b/include/trace/events/vmscan.h
@@ -10,6 +10,7 @@
 
 #define RECLAIM_WB_ANON		0x0001u
 #define RECLAIM_WB_FILE		0x0002u
+#define RECLAIM_WB_MIXED	0x0010u
 #define RECLAIM_WB_SYNC		0x0004u
 #define RECLAIM_WB_ASYNC	0x0008u
 
@@ -17,13 +18,20 @@
 	(flags) ? __print_flags(flags, "|",			\
 		{RECLAIM_WB_ANON,	"RECLAIM_WB_ANON"},	\
 		{RECLAIM_WB_FILE,	"RECLAIM_WB_FILE"},	\
+		{RECLAIM_WB_MIXED,	"RECLAIM_WB_MIXED"},	\
 		{RECLAIM_WB_SYNC,	"RECLAIM_WB_SYNC"},	\
 		{RECLAIM_WB_ASYNC,	"RECLAIM_WB_ASYNC"}	\
 		) : "RECLAIM_WB_NONE"
 
 #define trace_reclaim_flags(page, sync) ( \
 	(page_is_file_cache(page) ? RECLAIM_WB_FILE : RECLAIM_WB_ANON) | \
-	(sync == PAGEOUT_IO_SYNC ? RECLAIM_WB_SYNC : RECLAIM_WB_ASYNC)   \
+	(sync == LUMPY_MODE_SYNC ? RECLAIM_WB_SYNC : RECLAIM_WB_ASYNC)   \
+	)
+
+#define trace_shrink_flags(file, sync) ( \
+	(sync == LUMPY_MODE_SYNC ? RECLAIM_WB_MIXED : \
+			(file ? RECLAIM_WB_FILE : RECLAIM_WB_ANON)) |  \
+	(sync == LUMPY_MODE_SYNC ? RECLAIM_WB_SYNC : RECLAIM_WB_ASYNC) \
 	)
 
 TRACE_EVENT(mm_vmscan_kswapd_sleep,
@@ -269,6 +277,40 @@
 		show_reclaim_flags(__entry->reclaim_flags))
 );
 
+TRACE_EVENT(mm_vmscan_lru_shrink_inactive,
+
+	TP_PROTO(int nid, int zid,
+			unsigned long nr_scanned, unsigned long nr_reclaimed,
+			int priority, int reclaim_flags),
+
+	TP_ARGS(nid, zid, nr_scanned, nr_reclaimed, priority, reclaim_flags),
+
+	TP_STRUCT__entry(
+		__field(int, nid)
+		__field(int, zid)
+		__field(unsigned long, nr_scanned)
+		__field(unsigned long, nr_reclaimed)
+		__field(int, priority)
+		__field(int, reclaim_flags)
+	),
+
+	TP_fast_assign(
+		__entry->nid = nid;
+		__entry->zid = zid;
+		__entry->nr_scanned = nr_scanned;
+		__entry->nr_reclaimed = nr_reclaimed;
+		__entry->priority = priority;
+		__entry->reclaim_flags = reclaim_flags;
+	),
+
+	TP_printk("nid=%d zid=%d nr_scanned=%ld nr_reclaimed=%ld priority=%d flags=%s",
+		__entry->nid, __entry->zid,
+		__entry->nr_scanned, __entry->nr_reclaimed,
+		__entry->priority,
+		show_reclaim_flags(__entry->reclaim_flags))
+);
+
+
 #endif /* _TRACE_VMSCAN_H */
 
 /* This part must be outside protection */
diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h
index f345f66..89a2b2d 100644
--- a/include/trace/events/writeback.h
+++ b/include/trace/events/writeback.h
@@ -96,8 +96,6 @@
 		__field(long, nr_to_write)
 		__field(long, pages_skipped)
 		__field(int, sync_mode)
-		__field(int, nonblocking)
-		__field(int, encountered_congestion)
 		__field(int, for_kupdate)
 		__field(int, for_background)
 		__field(int, for_reclaim)
@@ -153,6 +151,41 @@
 DEFINE_WBC_EVENT(wbc_balance_dirty_wait);
 DEFINE_WBC_EVENT(wbc_writepage);
 
+DECLARE_EVENT_CLASS(writeback_congest_waited_template,
+
+	TP_PROTO(unsigned int usec_timeout, unsigned int usec_delayed),
+
+	TP_ARGS(usec_timeout, usec_delayed),
+
+	TP_STRUCT__entry(
+		__field(	unsigned int,	usec_timeout	)
+		__field(	unsigned int,	usec_delayed	)
+	),
+
+	TP_fast_assign(
+		__entry->usec_timeout	= usec_timeout;
+		__entry->usec_delayed	= usec_delayed;
+	),
+
+	TP_printk("usec_timeout=%u usec_delayed=%u",
+			__entry->usec_timeout,
+			__entry->usec_delayed)
+);
+
+DEFINE_EVENT(writeback_congest_waited_template, writeback_congestion_wait,
+
+	TP_PROTO(unsigned int usec_timeout, unsigned int usec_delayed),
+
+	TP_ARGS(usec_timeout, usec_delayed)
+);
+
+DEFINE_EVENT(writeback_congest_waited_template, writeback_wait_iff_congested,
+
+	TP_PROTO(unsigned int usec_timeout, unsigned int usec_delayed),
+
+	TP_ARGS(usec_timeout, usec_delayed)
+);
+
 #endif /* _TRACE_WRITEBACK_H */
 
 /* This part must be outside protection */
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 42db055..830aaec 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -291,7 +291,7 @@
 	if (err)
 		return err;
 
-	sys_chdir("/root");
+	sys_chdir((const char __user __force *)"/root");
 	ROOT_DEV = current->fs->pwd.mnt->mnt_sb->s_dev;
 	printk("VFS: Mounted root (%s filesystem)%s on device %u:%u.\n",
 	       current->fs->pwd.mnt->mnt_sb->s_type->name,
@@ -361,13 +361,13 @@
 #ifdef CONFIG_ROOT_NFS
 static int __init mount_nfs_root(void)
 {
-	void *data = nfs_root_data();
+	char *root_dev, *root_data;
 
-	create_dev("/dev/root", ROOT_DEV);
-	if (data &&
-	    do_mount_root("/dev/root", "nfs", root_mountflags, data) == 0)
-		return 1;
-	return 0;
+	if (nfs_root_data(&root_dev, &root_data) != 0)
+		return 0;
+	if (do_mount_root(root_dev, "nfs", root_mountflags, root_data) != 0)
+		return 0;
+	return 1;
 }
 #endif
 
@@ -488,5 +488,5 @@
 out:
 	devtmpfs_mount("dev");
 	sys_mount(".", "/", NULL, MS_MOVE, NULL);
-	sys_chroot(".");
+	sys_chroot((const char __user __force *)".");
 }
diff --git a/init/do_mounts_md.c b/init/do_mounts_md.c
index 69aebbf..32c4799 100644
--- a/init/do_mounts_md.c
+++ b/init/do_mounts_md.c
@@ -283,7 +283,7 @@
 
 	wait_for_device_probe();
 
-	fd = sys_open("/dev/md0", 0, 0);
+	fd = sys_open((const char __user __force *) "/dev/md0", 0, 0);
 	if (fd >= 0) {
 		sys_ioctl(fd, RAID_AUTORUN, raid_autopart);
 		sys_close(fd);
diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c
index bf3ef66..6e1ee69 100644
--- a/init/do_mounts_rd.c
+++ b/init/do_mounts_rd.c
@@ -168,7 +168,7 @@
 	char rotator[4] = { '|' , '/' , '-' , '\\' };
 #endif
 
-	out_fd = sys_open("/dev/ram", O_RDWR, 0);
+	out_fd = sys_open((const char __user __force *) "/dev/ram", O_RDWR, 0);
 	if (out_fd < 0)
 		goto out;
 
@@ -267,7 +267,7 @@
 	sys_close(out_fd);
 out:
 	kfree(buf);
-	sys_unlink("/dev/ram");
+	sys_unlink((const char __user __force *) "/dev/ram");
 	return res;
 }
 
diff --git a/init/initramfs.c b/init/initramfs.c
index 4b9c202..d9c6e78 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -528,7 +528,7 @@
 	struct linux_dirent64 *dirp;
 	int num;
 
-	fd = sys_open("/", O_RDONLY, 0);
+	fd = sys_open((const char __user __force *) "/", O_RDONLY, 0);
 	WARN_ON(fd < 0);
 	if (fd < 0)
 		return;
@@ -590,7 +590,8 @@
 		}
 		printk(KERN_INFO "rootfs image is not initramfs (%s)"
 				"; looks like an initrd\n", err);
-		fd = sys_open("/initrd.image", O_WRONLY|O_CREAT, 0700);
+		fd = sys_open((const char __user __force *) "/initrd.image",
+			      O_WRONLY|O_CREAT, 0700);
 		if (fd >= 0) {
 			sys_write(fd, (char *)initrd_start,
 					initrd_end - initrd_start);
diff --git a/init/noinitramfs.c b/init/noinitramfs.c
index f4c1a3a..267739d 100644
--- a/init/noinitramfs.c
+++ b/init/noinitramfs.c
@@ -29,17 +29,17 @@
 {
 	int err;
 
-	err = sys_mkdir("/dev", 0755);
+	err = sys_mkdir((const char __user __force *) "/dev", 0755);
 	if (err < 0)
 		goto out;
 
-	err = sys_mknod((const char __user *) "/dev/console",
+	err = sys_mknod((const char __user __force *) "/dev/console",
 			S_IFCHR | S_IRUSR | S_IWUSR,
 			new_encode_dev(MKDEV(5, 1)));
 	if (err < 0)
 		goto out;
 
-	err = sys_mkdir("/root", 0700);
+	err = sys_mkdir((const char __user __force *) "/root", 0700);
 	if (err < 0)
 		goto out;
 
diff --git a/kernel/exit.c b/kernel/exit.c
index e2bdf37..894179a 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -50,6 +50,7 @@
 #include <linux/perf_event.h>
 #include <trace/events/sched.h>
 #include <linux/hw_breakpoint.h>
+#include <linux/oom.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -687,6 +688,8 @@
 	enter_lazy_tlb(mm, current);
 	/* We don't want this task to be frozen prematurely */
 	clear_freeze_flag(tsk);
+	if (tsk->signal->oom_score_adj == OOM_SCORE_ADJ_MIN)
+		atomic_dec(&mm->oom_disable_count);
 	task_unlock(tsk);
 	mm_update_next_owner(mm);
 	mmput(mm);
diff --git a/kernel/fork.c b/kernel/fork.c
index c445f8c..e87aaaa 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -65,6 +65,7 @@
 #include <linux/perf_event.h>
 #include <linux/posix-timers.h>
 #include <linux/user-return-notifier.h>
+#include <linux/oom.h>
 
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -488,6 +489,7 @@
 	mm->cached_hole_size = ~0UL;
 	mm_init_aio(mm);
 	mm_init_owner(mm, p);
+	atomic_set(&mm->oom_disable_count, 0);
 
 	if (likely(!mm_alloc_pgd(mm))) {
 		mm->def_flags = 0;
@@ -741,6 +743,8 @@
 	/* Initializing for Swap token stuff */
 	mm->token_priority = 0;
 	mm->last_interval = 0;
+	if (tsk->signal->oom_score_adj == OOM_SCORE_ADJ_MIN)
+		atomic_inc(&mm->oom_disable_count);
 
 	tsk->mm = mm;
 	tsk->active_mm = mm;
@@ -1299,8 +1303,13 @@
 bad_fork_cleanup_namespaces:
 	exit_task_namespaces(p);
 bad_fork_cleanup_mm:
-	if (p->mm)
+	if (p->mm) {
+		task_lock(p);
+		if (p->signal->oom_score_adj == OOM_SCORE_ADJ_MIN)
+			atomic_dec(&p->mm->oom_disable_count);
+		task_unlock(p);
 		mmput(p->mm);
+	}
 bad_fork_cleanup_signal:
 	if (!(clone_flags & CLONE_THREAD))
 		free_signal_struct(p->signal);
@@ -1693,6 +1702,10 @@
 			active_mm = current->active_mm;
 			current->mm = new_mm;
 			current->active_mm = new_mm;
+			if (current->signal->oom_score_adj == OOM_SCORE_ADJ_MIN) {
+				atomic_dec(&mm->oom_disable_count);
+				atomic_inc(&new_mm->oom_disable_count);
+			}
 			activate_mm(active_mm, new_mm);
 			new_mm = mm;
 		}
diff --git a/kernel/kexec.c b/kernel/kexec.c
index c0613f7..b55045b 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -816,7 +816,7 @@
 
 		ptr = kmap(page);
 		/* Start with a clear page */
-		memset(ptr, 0, PAGE_SIZE);
+		clear_page(ptr);
 		ptr += maddr & ~PAGE_MASK;
 		mchunk = PAGE_SIZE - (maddr & ~PAGE_MASK);
 		if (mchunk > mbytes)
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index ac7eb10..0dac75e 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -984,8 +984,8 @@
 		src = kmap_atomic(s_page, KM_USER0);
 		dst = kmap_atomic(d_page, KM_USER1);
 		do_copy_page(dst, src);
-		kunmap_atomic(src, KM_USER0);
 		kunmap_atomic(dst, KM_USER1);
+		kunmap_atomic(src, KM_USER0);
 	} else {
 		if (PageHighMem(d_page)) {
 			/* Page pointed to by src may contain some kernel
@@ -993,7 +993,7 @@
 			 */
 			safe_copy_page(buffer, s_page);
 			dst = kmap_atomic(d_page, KM_USER0);
-			memcpy(dst, buffer, PAGE_SIZE);
+			copy_page(dst, buffer);
 			kunmap_atomic(dst, KM_USER0);
 		} else {
 			safe_copy_page(page_address(d_page), s_page);
@@ -1687,7 +1687,7 @@
 		memory_bm_position_reset(&orig_bm);
 		memory_bm_position_reset(&copy_bm);
 	} else if (handle->cur <= nr_meta_pages) {
-		memset(buffer, 0, PAGE_SIZE);
+		clear_page(buffer);
 		pack_pfns(buffer, &orig_bm);
 	} else {
 		struct page *page;
@@ -1701,7 +1701,7 @@
 			void *kaddr;
 
 			kaddr = kmap_atomic(page, KM_USER0);
-			memcpy(buffer, kaddr, PAGE_SIZE);
+			copy_page(buffer, kaddr);
 			kunmap_atomic(kaddr, KM_USER0);
 			handle->buffer = buffer;
 		} else {
@@ -1984,7 +1984,7 @@
 		void *dst;
 
 		dst = kmap_atomic(last_highmem_page, KM_USER0);
-		memcpy(dst, buffer, PAGE_SIZE);
+		copy_page(dst, buffer);
 		kunmap_atomic(dst, KM_USER0);
 		last_highmem_page = NULL;
 	}
@@ -2270,11 +2270,11 @@
 
 	kaddr1 = kmap_atomic(p1, KM_USER0);
 	kaddr2 = kmap_atomic(p2, KM_USER1);
-	memcpy(buf, kaddr1, PAGE_SIZE);
-	memcpy(kaddr1, kaddr2, PAGE_SIZE);
-	memcpy(kaddr2, buf, PAGE_SIZE);
-	kunmap_atomic(kaddr1, KM_USER0);
+	copy_page(buf, kaddr1);
+	copy_page(kaddr1, kaddr2);
+	copy_page(kaddr2, buf);
 	kunmap_atomic(kaddr2, KM_USER1);
+	kunmap_atomic(kaddr1, KM_USER0);
 }
 
 /**
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 916eaa7..a0e4a86 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -251,7 +251,7 @@
 	if (bio_chain) {
 		src = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
 		if (src) {
-			memcpy(src, buf, PAGE_SIZE);
+			copy_page(src, buf);
 		} else {
 			WARN_ON_ONCE(1);
 			bio_chain = NULL;	/* Go synchronous */
@@ -325,7 +325,7 @@
 		error = write_page(handle->cur, handle->cur_swap, NULL);
 		if (error)
 			goto out;
-		memset(handle->cur, 0, PAGE_SIZE);
+		clear_page(handle->cur);
 		handle->cur_swap = offset;
 		handle->k = 0;
 	}
@@ -910,7 +910,7 @@
 	hib_resume_bdev = open_by_devnum(swsusp_resume_device, FMODE_READ);
 	if (!IS_ERR(hib_resume_bdev)) {
 		set_blocksize(hib_resume_bdev, PAGE_SIZE);
-		memset(swsusp_header, 0, PAGE_SIZE);
+		clear_page(swsusp_header);
 		error = hib_bio_read_page(swsusp_resume_block,
 					swsusp_header, NULL);
 		if (error)
diff --git a/kernel/printk.c b/kernel/printk.c
index 2531017..b2ebaee 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -210,7 +210,7 @@
 
 #ifdef CONFIG_BOOT_PRINTK_DELAY
 
-static unsigned int boot_delay; /* msecs delay after each printk during bootup */
+static int boot_delay; /* msecs delay after each printk during bootup */
 static unsigned long long loops_per_msec;	/* based on boot_delay */
 
 static int __init boot_delay_setup(char *str)
@@ -647,6 +647,7 @@
  * released but interrupts still disabled.
  */
 static int acquire_console_semaphore_for_printk(unsigned int cpu)
+	__releases(&logbuf_lock)
 {
 	int retval = 0;
 
@@ -1511,7 +1512,7 @@
 }
 EXPORT_SYMBOL_GPL(kmsg_dump_unregister);
 
-static const char const *kmsg_reasons[] = {
+static const char * const kmsg_reasons[] = {
 	[KMSG_DUMP_OOPS]	= "oops",
 	[KMSG_DUMP_PANIC]	= "panic",
 	[KMSG_DUMP_KEXEC]	= "kexec",
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 090c288..2df820b 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -262,7 +262,7 @@
 		cpu_stop_fn_t fn = work->fn;
 		void *arg = work->arg;
 		struct cpu_stop_done *done = work->done;
-		char ksym_buf[KSYM_NAME_LEN];
+		char ksym_buf[KSYM_NAME_LEN] __maybe_unused;
 
 		__set_current_state(TASK_RUNNING);
 
@@ -304,7 +304,7 @@
 		p = kthread_create(cpu_stopper_thread, stopper, "migration/%d",
 				   cpu);
 		if (IS_ERR(p))
-			return NOTIFY_BAD;
+			return notifier_from_errno(PTR_ERR(p));
 		get_task_struct(p);
 		kthread_bind(p, cpu);
 		sched_set_stop_task(cpu, p);
@@ -372,7 +372,7 @@
 	/* start one for the boot cpu */
 	err = cpu_stop_cpu_callback(&cpu_stop_cpu_notifier, CPU_UP_PREPARE,
 				    bcpu);
-	BUG_ON(err == NOTIFY_BAD);
+	BUG_ON(err != NOTIFY_OK);
 	cpu_stop_cpu_callback(&cpu_stop_cpu_notifier, CPU_ONLINE, bcpu);
 	register_cpu_notifier(&cpu_stop_cpu_notifier);
 
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 8b77ff5..c33a1ed 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -161,8 +161,6 @@
 extern int unaligned_dump_stack;
 #endif
 
-extern struct ratelimit_state printk_ratelimit_state;
-
 #ifdef CONFIG_PROC_SYSCTL
 static int proc_do_cad_pid(struct ctl_table *table, int write,
 		  void __user *buffer, size_t *lenp, loff_t *ppos);
diff --git a/kernel/user.c b/kernel/user.c
index 7e72614..2c7d8d5 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -91,6 +91,7 @@
  * upon function exit.
  */
 static void free_user(struct user_struct *up, unsigned long flags)
+	__releases(&uidhash_lock)
 {
 	uid_hash_remove(up);
 	spin_unlock_irqrestore(&uidhash_lock, flags);
diff --git a/kernel/wait.c b/kernel/wait.c
index c4bd3d8..b0310eb 100644
--- a/kernel/wait.c
+++ b/kernel/wait.c
@@ -92,7 +92,7 @@
 }
 EXPORT_SYMBOL(prepare_to_wait_exclusive);
 
-/*
+/**
  * finish_wait - clean up after waiting in a queue
  * @q: waitqueue waited on
  * @wait: wait descriptor
@@ -127,11 +127,11 @@
 }
 EXPORT_SYMBOL(finish_wait);
 
-/*
+/**
  * abort_exclusive_wait - abort exclusive waiting in a queue
  * @q: waitqueue waited on
  * @wait: wait descriptor
- * @state: runstate of the waiter to be woken
+ * @mode: runstate of the waiter to be woken
  * @key: key to identify a wait bit queue or %NULL
  *
  * Sets current thread back to running state and removes
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 30acdb7..90db1bd 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -2064,7 +2064,7 @@
 	 * checks and call back into the fixup functions where we
 	 * might deadlock.
 	 */
-	INIT_WORK_ON_STACK(&barr->work, wq_barrier_func);
+	INIT_WORK_ONSTACK(&barr->work, wq_barrier_func);
 	__set_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(&barr->work));
 	init_completion(&barr->done);
 
@@ -2791,7 +2791,9 @@
 		}
 	}
 
-	/* just in case, make sure it's actually aligned */
+	/* just in case, make sure it's actually aligned
+	 * - this is affected by PERCPU() alignment in vmlinux.lds.S
+	 */
 	BUG_ON(!IS_ALIGNED(wq->cpu_wq.v, align));
 	return wq->cpu_wq.v ? 0 : -ENOMEM;
 }
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 69a3266..9958406 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -317,6 +317,14 @@
 	help
 	  Enable this to turn on debugging of RCU list heads (call_rcu() usage).
 
+config DEBUG_OBJECTS_PERCPU_COUNTER
+	bool "Debug percpu counter objects"
+	depends on DEBUG_OBJECTS
+	help
+	  If you say Y here, additional code will be inserted into the
+	  percpu counter routines to track the life time of percpu counter
+	  objects and validate the percpu counter operations.
+
 config DEBUG_OBJECTS_ENABLE_DEFAULT
 	int "debug_objects bootup default value (0-1)"
         range 0 1
@@ -366,7 +374,7 @@
 config DEBUG_KMEMLEAK
 	bool "Kernel memory leak detector"
 	depends on DEBUG_KERNEL && EXPERIMENTAL && !MEMORY_HOTPLUG && \
-		(X86 || ARM || PPC || S390 || SPARC64 || SUPERH || MICROBLAZE)
+		(X86 || ARM || PPC || S390 || SPARC64 || SUPERH || MICROBLAZE || TILE)
 
 	select DEBUG_FS if SYSFS
 	select STACKTRACE if STACKTRACE_SUPPORT
@@ -740,6 +748,15 @@
 
 	  If unsure, say N.
 
+config TEST_LIST_SORT
+	bool "Linked list sorting test"
+	depends on DEBUG_KERNEL
+	help
+	  Enable this to turn on 'list_sort()' function test. This test is
+	  executed only once during system boot, so affects only boot time.
+
+	  If unsure, say N.
+
 config DEBUG_SG
 	bool "Debug SG table operations"
 	depends on DEBUG_KERNEL
diff --git a/lib/bitmap.c b/lib/bitmap.c
index ffb78c9..741fae9 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -359,7 +359,6 @@
 
 #define CHUNKSZ				32
 #define nbits_to_hold_value(val)	fls(val)
-#define unhex(c)			(isdigit(c) ? (c - '0') : (toupper(c) - 'A' + 10))
 #define BASEDEC 10		/* fancier cpuset lists input in decimal */
 
 /**
@@ -466,7 +465,7 @@
 			if (chunk & ~((1UL << (CHUNKSZ - 4)) - 1))
 				return -EOVERFLOW;
 
-			chunk = (chunk << 4) | unhex(c);
+			chunk = (chunk << 4) | hex_to_bin(c);
 			ndigits++; totaldigits++;
 		}
 		if (ndigits == 0)
diff --git a/lib/div64.c b/lib/div64.c
index a111eb8..5b49191 100644
--- a/lib/div64.c
+++ b/lib/div64.c
@@ -77,26 +77,58 @@
 EXPORT_SYMBOL(div_s64_rem);
 #endif
 
-/* 64bit divisor, dividend and result. dynamic precision */
+/**
+ * div64_u64 - unsigned 64bit divide with 64bit divisor
+ * @dividend:	64bit dividend
+ * @divisor:	64bit divisor
+ *
+ * This implementation is a modified version of the algorithm proposed
+ * by the book 'Hacker's Delight'.  The original source and full proof
+ * can be found here and is available for use without restriction.
+ *
+ * 'http://www.hackersdelight.org/HDcode/newCode/divDouble.c'
+ */
 #ifndef div64_u64
 u64 div64_u64(u64 dividend, u64 divisor)
 {
-	u32 high, d;
+	u32 high = divisor >> 32;
+	u64 quot;
 
-	high = divisor >> 32;
-	if (high) {
-		unsigned int shift = fls(high);
+	if (high == 0) {
+		quot = div_u64(dividend, divisor);
+	} else {
+		int n = 1 + fls(high);
+		quot = div_u64(dividend >> n, divisor >> n);
 
-		d = divisor >> shift;
-		dividend >>= shift;
-	} else
-		d = divisor;
+		if (quot != 0)
+			quot--;
+		if ((dividend - quot * divisor) >= divisor)
+			quot++;
+	}
 
-	return div_u64(dividend, d);
+	return quot;
 }
 EXPORT_SYMBOL(div64_u64);
 #endif
 
+/**
+ * div64_s64 - signed 64bit divide with 64bit divisor
+ * @dividend:	64bit dividend
+ * @divisor:	64bit divisor
+ */
+#ifndef div64_s64
+s64 div64_s64(s64 dividend, s64 divisor)
+{
+	s64 quot, t;
+
+	quot = div64_u64(abs64(dividend), abs64(divisor));
+	t = (dividend ^ divisor) >> 63;
+
+	return (quot ^ t) - t;
+}
+EXPORT_SYMBOL(div64_s64);
+#endif
+
 #endif /* BITS_PER_LONG == 32 */
 
 /*
diff --git a/lib/idr.c b/lib/idr.c
index 5e0966b..e15502e 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -106,16 +106,17 @@
 }
 
 /**
- * idr_pre_get - reserver resources for idr allocation
+ * idr_pre_get - reserve resources for idr allocation
  * @idp:	idr handle
  * @gfp_mask:	memory allocation flags
  *
- * This function should be called prior to locking and calling the
- * idr_get_new* functions. It preallocates enough memory to satisfy
- * the worst possible allocation.
+ * This function should be called prior to calling the idr_get_new* functions.
+ * It preallocates enough memory to satisfy the worst possible allocation. The
+ * caller should pass in GFP_KERNEL if possible.  This of course requires that
+ * no spinning locks be held.
  *
- * If the system is REALLY out of memory this function returns 0,
- * otherwise 1.
+ * If the system is REALLY out of memory this function returns %0,
+ * otherwise %1.
  */
 int idr_pre_get(struct idr *idp, gfp_t gfp_mask)
 {
@@ -290,11 +291,13 @@
  * This is the allocate id function.  It should be called with any
  * required locks.
  *
- * If memory is required, it will return -EAGAIN, you should unlock
- * and go back to the idr_pre_get() call.  If the idr is full, it will
- * return -ENOSPC.
+ * If allocation from IDR's private freelist fails, idr_get_new_above() will
+ * return %-EAGAIN.  The caller should retry the idr_pre_get() call to refill
+ * IDR's preallocation and then retry the idr_get_new_above() call.
  *
- * @id returns a value in the range @starting_id ... 0x7fffffff
+ * If the idr is full idr_get_new_above() will return %-ENOSPC.
+ *
+ * @id returns a value in the range @starting_id ... %0x7fffffff
  */
 int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id)
 {
@@ -318,14 +321,13 @@
  * @ptr: pointer you want associated with the id
  * @id: pointer to the allocated handle
  *
- * This is the allocate id function.  It should be called with any
- * required locks.
+ * If allocation from IDR's private freelist fails, idr_get_new_above() will
+ * return %-EAGAIN.  The caller should retry the idr_pre_get() call to refill
+ * IDR's preallocation and then retry the idr_get_new_above() call.
  *
- * If memory is required, it will return -EAGAIN, you should unlock
- * and go back to the idr_pre_get() call.  If the idr is full, it will
- * return -ENOSPC.
+ * If the idr is full idr_get_new_above() will return %-ENOSPC.
  *
- * @id returns a value in the range 0 ... 0x7fffffff
+ * @id returns a value in the range %0 ... %0x7fffffff
  */
 int idr_get_new(struct idr *idp, void *ptr, int *id)
 {
@@ -388,7 +390,7 @@
 }
 
 /**
- * idr_remove - remove the given id and free it's slot
+ * idr_remove - remove the given id and free its slot
  * @idp: idr handle
  * @id: unique key
  */
@@ -437,7 +439,7 @@
  * function will remove all id mappings and leave all idp_layers
  * unused.
  *
- * A typical clean-up sequence for objects stored in an idr tree, will
+ * A typical clean-up sequence for objects stored in an idr tree will
  * use idr_for_each() to free all objects, if necessay, then
  * idr_remove_all() to remove all ids, and idr_destroy() to free
  * up the cached idr_layers.
@@ -542,7 +544,7 @@
  * not allowed.
  *
  * We check the return of @fn each time. If it returns anything other
- * than 0, we break out and return that value.
+ * than %0, we break out and return that value.
  *
  * The caller must serialize idr_for_each() vs idr_get_new() and idr_remove().
  */
@@ -637,8 +639,8 @@
  * @id: lookup key
  *
  * Replace the pointer registered with an id and return the old value.
- * A -ENOENT return indicates that @id was not found.
- * A -EINVAL return indicates that @id was not within valid constraints.
+ * A %-ENOENT return indicates that @id was not found.
+ * A %-EINVAL return indicates that @id was not within valid constraints.
  *
  * The caller must serialize with writers.
  */
@@ -696,10 +698,11 @@
 EXPORT_SYMBOL(idr_init);
 
 
-/*
+/**
+ * DOC: IDA description
  * IDA - IDR based ID allocator
  *
- * this is id allocator without id -> pointer translation.  Memory
+ * This is id allocator without id -> pointer translation.  Memory
  * usage is much lower than full blown idr because each id only
  * occupies a bit.  ida uses a custom leaf node which contains
  * IDA_BITMAP_BITS slots.
@@ -732,8 +735,8 @@
  * following function.  It preallocates enough memory to satisfy the
  * worst possible allocation.
  *
- * If the system is REALLY out of memory this function returns 0,
- * otherwise 1.
+ * If the system is REALLY out of memory this function returns %0,
+ * otherwise %1.
  */
 int ida_pre_get(struct ida *ida, gfp_t gfp_mask)
 {
@@ -765,11 +768,11 @@
  * Allocate new ID above or equal to @ida.  It should be called with
  * any required locks.
  *
- * If memory is required, it will return -EAGAIN, you should unlock
+ * If memory is required, it will return %-EAGAIN, you should unlock
  * and go back to the ida_pre_get() call.  If the ida is full, it will
- * return -ENOSPC.
+ * return %-ENOSPC.
  *
- * @p_id returns a value in the range @starting_id ... 0x7fffffff.
+ * @p_id returns a value in the range @starting_id ... %0x7fffffff.
  */
 int ida_get_new_above(struct ida *ida, int starting_id, int *p_id)
 {
@@ -851,11 +854,11 @@
  *
  * Allocate new ID.  It should be called with any required locks.
  *
- * If memory is required, it will return -EAGAIN, you should unlock
+ * If memory is required, it will return %-EAGAIN, you should unlock
  * and go back to the idr_pre_get() call.  If the idr is full, it will
- * return -ENOSPC.
+ * return %-ENOSPC.
  *
- * @id returns a value in the range 0 ... 0x7fffffff.
+ * @id returns a value in the range %0 ... %0x7fffffff.
  */
 int ida_get_new(struct ida *ida, int *p_id)
 {
diff --git a/lib/list_sort.c b/lib/list_sort.c
index a7616fa..d7325c6b 100644
--- a/lib/list_sort.c
+++ b/lib/list_sort.c
@@ -141,77 +141,151 @@
 }
 EXPORT_SYMBOL(list_sort);
 
-#ifdef DEBUG_LIST_SORT
-struct debug_el {
-	struct list_head l_h;
-	int value;
-	unsigned serial;
-};
+#ifdef CONFIG_TEST_LIST_SORT
 
-static int cmp(void *priv, struct list_head *a, struct list_head *b)
-{
-	return container_of(a, struct debug_el, l_h)->value
-	     - container_of(b, struct debug_el, l_h)->value;
-}
+#include <linux/random.h>
 
 /*
  * The pattern of set bits in the list length determines which cases
  * are hit in list_sort().
  */
-#define LIST_SORT_TEST_LENGTH (512+128+2) /* not including head */
+#define TEST_LIST_LEN (512+128+2) /* not including head */
 
-static int __init list_sort_test(void)
+#define TEST_POISON1 0xDEADBEEF
+#define TEST_POISON2 0xA324354C
+
+struct debug_el {
+	unsigned int poison1;
+	struct list_head list;
+	unsigned int poison2;
+	int value;
+	unsigned serial;
+};
+
+/* Array, containing pointers to all elements in the test list */
+static struct debug_el **elts __initdata;
+
+static int __init check(struct debug_el *ela, struct debug_el *elb)
 {
-	int i, r = 1, count;
-	struct list_head *head = kmalloc(sizeof(*head), GFP_KERNEL);
-	struct list_head *cur;
-
-	printk(KERN_WARNING "testing list_sort()\n");
-
-	cur = head;
-	for (i = 0; i < LIST_SORT_TEST_LENGTH; i++) {
-		struct debug_el *el = kmalloc(sizeof(*el), GFP_KERNEL);
-		BUG_ON(!el);
-		 /* force some equivalencies */
-		el->value = (r = (r * 725861) % 6599) % (LIST_SORT_TEST_LENGTH/3);
-		el->serial = i;
-
-		el->l_h.prev = cur;
-		cur->next = &el->l_h;
-		cur = cur->next;
+	if (ela->serial >= TEST_LIST_LEN) {
+		printk(KERN_ERR "list_sort_test: error: incorrect serial %d\n",
+				ela->serial);
+		return -EINVAL;
 	}
-	head->prev = cur;
-
-	list_sort(NULL, head, cmp);
-
-	count = 1;
-	for (cur = head->next; cur->next != head; cur = cur->next) {
-		struct debug_el *el = container_of(cur, struct debug_el, l_h);
-		int cmp_result = cmp(NULL, cur, cur->next);
-		if (cur->next->prev != cur) {
-			printk(KERN_EMERG "list_sort() returned "
-						"a corrupted list!\n");
-			return 1;
-		} else if (cmp_result > 0) {
-			printk(KERN_EMERG "list_sort() failed to sort!\n");
-			return 1;
-		} else if (cmp_result == 0 &&
-				el->serial >= container_of(cur->next,
-					struct debug_el, l_h)->serial) {
-			printk(KERN_EMERG "list_sort() failed to preserve order"
-						 " of equivalent elements!\n");
-			return 1;
-		}
-		kfree(cur->prev);
-		count++;
+	if (elb->serial >= TEST_LIST_LEN) {
+		printk(KERN_ERR "list_sort_test: error: incorrect serial %d\n",
+				elb->serial);
+		return -EINVAL;
 	}
-	kfree(cur);
-	if (count != LIST_SORT_TEST_LENGTH) {
-		printk(KERN_EMERG "list_sort() returned list of"
-						"different length!\n");
-		return 1;
+	if (elts[ela->serial] != ela || elts[elb->serial] != elb) {
+		printk(KERN_ERR "list_sort_test: error: phantom element\n");
+		return -EINVAL;
+	}
+	if (ela->poison1 != TEST_POISON1 || ela->poison2 != TEST_POISON2) {
+		printk(KERN_ERR "list_sort_test: error: bad poison: %#x/%#x\n",
+				ela->poison1, ela->poison2);
+		return -EINVAL;
+	}
+	if (elb->poison1 != TEST_POISON1 || elb->poison2 != TEST_POISON2) {
+		printk(KERN_ERR "list_sort_test: error: bad poison: %#x/%#x\n",
+				elb->poison1, elb->poison2);
+		return -EINVAL;
 	}
 	return 0;
 }
+
+static int __init cmp(void *priv, struct list_head *a, struct list_head *b)
+{
+	struct debug_el *ela, *elb;
+
+	ela = container_of(a, struct debug_el, list);
+	elb = container_of(b, struct debug_el, list);
+
+	check(ela, elb);
+	return ela->value - elb->value;
+}
+
+static int __init list_sort_test(void)
+{
+	int i, count = 1, err = -EINVAL;
+	struct debug_el *el;
+	struct list_head *cur, *tmp;
+	LIST_HEAD(head);
+
+	printk(KERN_DEBUG "list_sort_test: start testing list_sort()\n");
+
+	elts = kmalloc(sizeof(void *) * TEST_LIST_LEN, GFP_KERNEL);
+	if (!elts) {
+		printk(KERN_ERR "list_sort_test: error: cannot allocate "
+				"memory\n");
+		goto exit;
+	}
+
+	for (i = 0; i < TEST_LIST_LEN; i++) {
+		el = kmalloc(sizeof(*el), GFP_KERNEL);
+		if (!el) {
+			printk(KERN_ERR "list_sort_test: error: cannot "
+					"allocate memory\n");
+			goto exit;
+		}
+		 /* force some equivalencies */
+		el->value = random32() % (TEST_LIST_LEN/3);
+		el->serial = i;
+		el->poison1 = TEST_POISON1;
+		el->poison2 = TEST_POISON2;
+		elts[i] = el;
+		list_add_tail(&el->list, &head);
+	}
+
+	list_sort(NULL, &head, cmp);
+
+	for (cur = head.next; cur->next != &head; cur = cur->next) {
+		struct debug_el *el1;
+		int cmp_result;
+
+		if (cur->next->prev != cur) {
+			printk(KERN_ERR "list_sort_test: error: list is "
+					"corrupted\n");
+			goto exit;
+		}
+
+		cmp_result = cmp(NULL, cur, cur->next);
+		if (cmp_result > 0) {
+			printk(KERN_ERR "list_sort_test: error: list is not "
+					"sorted\n");
+			goto exit;
+		}
+
+		el = container_of(cur, struct debug_el, list);
+		el1 = container_of(cur->next, struct debug_el, list);
+		if (cmp_result == 0 && el->serial >= el1->serial) {
+			printk(KERN_ERR "list_sort_test: error: order of "
+					"equivalent elements not preserved\n");
+			goto exit;
+		}
+
+		if (check(el, el1)) {
+			printk(KERN_ERR "list_sort_test: error: element check "
+					"failed\n");
+			goto exit;
+		}
+		count++;
+	}
+
+	if (count != TEST_LIST_LEN) {
+		printk(KERN_ERR "list_sort_test: error: bad list length %d",
+				count);
+		goto exit;
+	}
+
+	err = 0;
+exit:
+	kfree(elts);
+	list_for_each_safe(cur, tmp, &head) {
+		list_del(cur);
+		kfree(container_of(cur, struct debug_el, list));
+	}
+	return err;
+}
 module_init(list_sort_test);
-#endif
+#endif /* CONFIG_TEST_LIST_SORT */
diff --git a/lib/parser.c b/lib/parser.c
index fb34977..6e89eca 100644
--- a/lib/parser.c
+++ b/lib/parser.c
@@ -128,12 +128,13 @@
 	char *endp;
 	char *buf;
 	int ret;
+	size_t len = s->to - s->from;
 
-	buf = kmalloc(s->to - s->from + 1, GFP_KERNEL);
+	buf = kmalloc(len + 1, GFP_KERNEL);
 	if (!buf)
 		return -ENOMEM;
-	memcpy(buf, s->from, s->to - s->from);
-	buf[s->to - s->from] = '\0';
+	memcpy(buf, s->from, len);
+	buf[len] = '\0';
 	*result = simple_strtol(buf, &endp, base);
 	ret = 0;
 	if (endp == buf)
diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c
index ec9048e..604678d 100644
--- a/lib/percpu_counter.c
+++ b/lib/percpu_counter.c
@@ -8,10 +8,53 @@
 #include <linux/init.h>
 #include <linux/cpu.h>
 #include <linux/module.h>
+#include <linux/debugobjects.h>
 
 static LIST_HEAD(percpu_counters);
 static DEFINE_MUTEX(percpu_counters_lock);
 
+#ifdef CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER
+
+static struct debug_obj_descr percpu_counter_debug_descr;
+
+static int percpu_counter_fixup_free(void *addr, enum debug_obj_state state)
+{
+	struct percpu_counter *fbc = addr;
+
+	switch (state) {
+	case ODEBUG_STATE_ACTIVE:
+		percpu_counter_destroy(fbc);
+		debug_object_free(fbc, &percpu_counter_debug_descr);
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+static struct debug_obj_descr percpu_counter_debug_descr = {
+	.name		= "percpu_counter",
+	.fixup_free	= percpu_counter_fixup_free,
+};
+
+static inline void debug_percpu_counter_activate(struct percpu_counter *fbc)
+{
+	debug_object_init(fbc, &percpu_counter_debug_descr);
+	debug_object_activate(fbc, &percpu_counter_debug_descr);
+}
+
+static inline void debug_percpu_counter_deactivate(struct percpu_counter *fbc)
+{
+	debug_object_deactivate(fbc, &percpu_counter_debug_descr);
+	debug_object_free(fbc, &percpu_counter_debug_descr);
+}
+
+#else	/* CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER */
+static inline void debug_percpu_counter_activate(struct percpu_counter *fbc)
+{ }
+static inline void debug_percpu_counter_deactivate(struct percpu_counter *fbc)
+{ }
+#endif	/* CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER */
+
 void percpu_counter_set(struct percpu_counter *fbc, s64 amount)
 {
 	int cpu;
@@ -30,9 +73,9 @@
 {
 	s64 count;
 	s32 *pcount;
-	int cpu = get_cpu();
 
-	pcount = per_cpu_ptr(fbc->counters, cpu);
+	preempt_disable();
+	pcount = this_cpu_ptr(fbc->counters);
 	count = *pcount + amount;
 	if (count >= batch || count <= -batch) {
 		spin_lock(&fbc->lock);
@@ -42,7 +85,7 @@
 	} else {
 		*pcount = count;
 	}
-	put_cpu();
+	preempt_enable();
 }
 EXPORT_SYMBOL(__percpu_counter_add);
 
@@ -75,7 +118,11 @@
 	fbc->counters = alloc_percpu(s32);
 	if (!fbc->counters)
 		return -ENOMEM;
+
+	debug_percpu_counter_activate(fbc);
+
 #ifdef CONFIG_HOTPLUG_CPU
+	INIT_LIST_HEAD(&fbc->list);
 	mutex_lock(&percpu_counters_lock);
 	list_add(&fbc->list, &percpu_counters);
 	mutex_unlock(&percpu_counters_lock);
@@ -89,6 +136,8 @@
 	if (!fbc->counters)
 		return;
 
+	debug_percpu_counter_deactivate(fbc);
+
 #ifdef CONFIG_HOTPLUG_CPU
 	mutex_lock(&percpu_counters_lock);
 	list_del(&fbc->list);
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 7af9d84..c150d3d 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -988,8 +988,15 @@
 char *pointer(const char *fmt, char *buf, char *end, void *ptr,
 	      struct printf_spec spec)
 {
-	if (!ptr)
+	if (!ptr) {
+		/*
+		 * Print (null) with the same width as a pointer so it makes
+		 * tabular output look nice.
+		 */
+		if (spec.field_width == -1)
+			spec.field_width = 2 * sizeof(void *);
 		return string(buf, end, "(null)", spec);
+	}
 
 	switch (*fmt) {
 	case 'F':
@@ -1031,7 +1038,7 @@
 	}
 	spec.flags |= SMALL;
 	if (spec.field_width == -1) {
-		spec.field_width = 2*sizeof(void *);
+		spec.field_width = 2 * sizeof(void *);
 		spec.flags |= ZEROPAD;
 	}
 	spec.base = 16;
@@ -1497,7 +1504,7 @@
  * @...: Arguments for the format string
  *
  * The return value is the number of characters written into @buf not including
- * the trailing '\0'. If @size is <= 0 the function returns 0.
+ * the trailing '\0'. If @size is == 0 the function returns 0.
  */
 
 int scnprintf(char *buf, size_t size, const char *fmt, ...)
@@ -1509,7 +1516,11 @@
 	i = vsnprintf(buf, size, fmt, args);
 	va_end(args);
 
-	return (i >= size) ? (size - 1) : i;
+	if (likely(i < size))
+		return i;
+	if (size != 0)
+		return size - 1;
+	return 0;
 }
 EXPORT_SYMBOL(scnprintf);
 
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 15d5097..027100d 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -362,7 +362,7 @@
 {
 	struct bdi_writeback *me = ptr;
 
-	current->flags |= PF_FLUSHER | PF_SWAPWRITE;
+	current->flags |= PF_SWAPWRITE;
 	set_freezable();
 
 	/*
@@ -729,6 +729,7 @@
 		__WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[0]),
 		__WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[1])
 	};
+static atomic_t nr_bdi_congested[2];
 
 void clear_bdi_congested(struct backing_dev_info *bdi, int sync)
 {
@@ -736,7 +737,8 @@
 	wait_queue_head_t *wqh = &congestion_wqh[sync];
 
 	bit = sync ? BDI_sync_congested : BDI_async_congested;
-	clear_bit(bit, &bdi->state);
+	if (test_and_clear_bit(bit, &bdi->state))
+		atomic_dec(&nr_bdi_congested[sync]);
 	smp_mb__after_clear_bit();
 	if (waitqueue_active(wqh))
 		wake_up(wqh);
@@ -748,7 +750,8 @@
 	enum bdi_state bit;
 
 	bit = sync ? BDI_sync_congested : BDI_async_congested;
-	set_bit(bit, &bdi->state);
+	if (!test_and_set_bit(bit, &bdi->state))
+		atomic_inc(&nr_bdi_congested[sync]);
 }
 EXPORT_SYMBOL(set_bdi_congested);
 
@@ -764,13 +767,72 @@
 long congestion_wait(int sync, long timeout)
 {
 	long ret;
+	unsigned long start = jiffies;
 	DEFINE_WAIT(wait);
 	wait_queue_head_t *wqh = &congestion_wqh[sync];
 
 	prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE);
 	ret = io_schedule_timeout(timeout);
 	finish_wait(wqh, &wait);
+
+	trace_writeback_congestion_wait(jiffies_to_usecs(timeout),
+					jiffies_to_usecs(jiffies - start));
+
 	return ret;
 }
 EXPORT_SYMBOL(congestion_wait);
 
+/**
+ * wait_iff_congested - Conditionally wait for a backing_dev to become uncongested or a zone to complete writes
+ * @zone: A zone to check if it is heavily congested
+ * @sync: SYNC or ASYNC IO
+ * @timeout: timeout in jiffies
+ *
+ * In the event of a congested backing_dev (any backing_dev) and the given
+ * @zone has experienced recent congestion, this waits for up to @timeout
+ * jiffies for either a BDI to exit congestion of the given @sync queue
+ * or a write to complete.
+ *
+ * In the absense of zone congestion, cond_resched() is called to yield
+ * the processor if necessary but otherwise does not sleep.
+ *
+ * The return value is 0 if the sleep is for the full timeout. Otherwise,
+ * it is the number of jiffies that were still remaining when the function
+ * returned. return_value == timeout implies the function did not sleep.
+ */
+long wait_iff_congested(struct zone *zone, int sync, long timeout)
+{
+	long ret;
+	unsigned long start = jiffies;
+	DEFINE_WAIT(wait);
+	wait_queue_head_t *wqh = &congestion_wqh[sync];
+
+	/*
+	 * If there is no congestion, or heavy congestion is not being
+	 * encountered in the current zone, yield if necessary instead
+	 * of sleeping on the congestion queue
+	 */
+	if (atomic_read(&nr_bdi_congested[sync]) == 0 ||
+			!zone_is_reclaim_congested(zone)) {
+		cond_resched();
+
+		/* In case we scheduled, work out time remaining */
+		ret = timeout - (jiffies - start);
+		if (ret < 0)
+			ret = 0;
+
+		goto out;
+	}
+
+	/* Sleep until uncongested or a write happens */
+	prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE);
+	ret = io_schedule_timeout(timeout);
+	finish_wait(wqh, &wait);
+
+out:
+	trace_writeback_wait_iff_congested(jiffies_to_usecs(timeout),
+					jiffies_to_usecs(jiffies - start));
+
+	return ret;
+}
+EXPORT_SYMBOL(wait_iff_congested);
diff --git a/mm/dmapool.c b/mm/dmapool.c
index 3df0637..4df2de7 100644
--- a/mm/dmapool.c
+++ b/mm/dmapool.c
@@ -311,6 +311,8 @@
 	size_t offset;
 	void *retval;
 
+	might_sleep_if(mem_flags & __GFP_WAIT);
+
 	spin_lock_irqsave(&pool->lock, flags);
  restart:
 	list_for_each_entry(page, &pool->page_list, page_list) {
diff --git a/mm/filemap.c b/mm/filemap.c
index 3d4df44..75572b5 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -612,6 +612,19 @@
 							TASK_UNINTERRUPTIBLE);
 }
 
+int __lock_page_or_retry(struct page *page, struct mm_struct *mm,
+			 unsigned int flags)
+{
+	if (!(flags & FAULT_FLAG_ALLOW_RETRY)) {
+		__lock_page(page);
+		return 1;
+	} else {
+		up_read(&mm->mmap_sem);
+		wait_on_page_locked(page);
+		return 0;
+	}
+}
+
 /**
  * find_get_page - find and get a page reference
  * @mapping: the address_space to search
@@ -1539,25 +1552,28 @@
 		 * waiting for the lock.
 		 */
 		do_async_mmap_readahead(vma, ra, file, page, offset);
-		lock_page(page);
-
-		/* Did it get truncated? */
-		if (unlikely(page->mapping != mapping)) {
-			unlock_page(page);
-			put_page(page);
-			goto no_cached_page;
-		}
 	} else {
 		/* No page in the page cache at all */
 		do_sync_mmap_readahead(vma, ra, file, offset);
 		count_vm_event(PGMAJFAULT);
 		ret = VM_FAULT_MAJOR;
 retry_find:
-		page = find_lock_page(mapping, offset);
+		page = find_get_page(mapping, offset);
 		if (!page)
 			goto no_cached_page;
 	}
 
+	if (!lock_page_or_retry(page, vma->vm_mm, vmf->flags))
+		return ret | VM_FAULT_RETRY;
+
+	/* Did it get truncated? */
+	if (unlikely(page->mapping != mapping)) {
+		unlock_page(page);
+		put_page(page);
+		goto retry_find;
+	}
+	VM_BUG_ON(page->index != offset);
+
 	/*
 	 * We have a locked page in the page cache, now we need to check
 	 * that it's up-to-date. If not, it is going to be due to an error.
@@ -2177,12 +2193,12 @@
 	}
 
 	if (written > 0) {
-		loff_t end = pos + written;
-		if (end > i_size_read(inode) && !S_ISBLK(inode->i_mode)) {
-			i_size_write(inode,  end);
+		pos += written;
+		if (pos > i_size_read(inode) && !S_ISBLK(inode->i_mode)) {
+			i_size_write(inode, pos);
 			mark_inode_dirty(inode);
 		}
-		*ppos = end;
+		*ppos = pos;
 	}
 out:
 	return written;
diff --git a/mm/highmem.c b/mm/highmem.c
index 7a0aa1b..781e754 100644
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -42,6 +42,10 @@
 unsigned long totalhigh_pages __read_mostly;
 EXPORT_SYMBOL(totalhigh_pages);
 
+
+DEFINE_PER_CPU(int, __kmap_atomic_idx);
+EXPORT_PER_CPU_SYMBOL(__kmap_atomic_idx);
+
 unsigned int nr_free_highpages (void)
 {
 	pg_data_t *pgdat;
@@ -422,61 +426,3 @@
 }
 
 #endif	/* defined(CONFIG_HIGHMEM) && !defined(WANT_PAGE_VIRTUAL) */
-
-#ifdef CONFIG_DEBUG_HIGHMEM
-
-void debug_kmap_atomic(enum km_type type)
-{
-	static int warn_count = 10;
-
-	if (unlikely(warn_count < 0))
-		return;
-
-	if (unlikely(in_interrupt())) {
-		if (in_nmi()) {
-			if (type != KM_NMI && type != KM_NMI_PTE) {
-				WARN_ON(1);
-				warn_count--;
-			}
-		} else if (in_irq()) {
-			if (type != KM_IRQ0 && type != KM_IRQ1 &&
-			    type != KM_BIO_SRC_IRQ && type != KM_BIO_DST_IRQ &&
-			    type != KM_BOUNCE_READ && type != KM_IRQ_PTE) {
-				WARN_ON(1);
-				warn_count--;
-			}
-		} else if (!irqs_disabled()) {	/* softirq */
-			if (type != KM_IRQ0 && type != KM_IRQ1 &&
-			    type != KM_SOFTIRQ0 && type != KM_SOFTIRQ1 &&
-			    type != KM_SKB_SUNRPC_DATA &&
-			    type != KM_SKB_DATA_SOFTIRQ &&
-			    type != KM_BOUNCE_READ) {
-				WARN_ON(1);
-				warn_count--;
-			}
-		}
-	}
-
-	if (type == KM_IRQ0 || type == KM_IRQ1 || type == KM_BOUNCE_READ ||
-			type == KM_BIO_SRC_IRQ || type == KM_BIO_DST_IRQ ||
-			type == KM_IRQ_PTE || type == KM_NMI ||
-			type == KM_NMI_PTE ) {
-		if (!irqs_disabled()) {
-			WARN_ON(1);
-			warn_count--;
-		}
-	} else if (type == KM_SOFTIRQ0 || type == KM_SOFTIRQ1) {
-		if (irq_count() == 0 && !irqs_disabled()) {
-			WARN_ON(1);
-			warn_count--;
-		}
-	}
-#ifdef CONFIG_KGDB_KDB
-	if (unlikely(type == KM_KDB && atomic_read(&kgdb_active) == -1)) {
-		WARN_ON(1);
-		warn_count--;
-	}
-#endif /* CONFIG_KGDB_KDB */
-}
-
-#endif
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index c032738..c4a3558 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -423,14 +423,14 @@
 	}
 }
 
-static void copy_gigantic_page(struct page *dst, struct page *src,
+static void copy_user_gigantic_page(struct page *dst, struct page *src,
 			   unsigned long addr, struct vm_area_struct *vma)
 {
 	int i;
 	struct hstate *h = hstate_vma(vma);
 	struct page *dst_base = dst;
 	struct page *src_base = src;
-	might_sleep();
+
 	for (i = 0; i < pages_per_huge_page(h); ) {
 		cond_resched();
 		copy_user_highpage(dst, src, addr + i*PAGE_SIZE, vma);
@@ -440,14 +440,15 @@
 		src = mem_map_next(src, src_base, i);
 	}
 }
-static void copy_huge_page(struct page *dst, struct page *src,
+
+static void copy_user_huge_page(struct page *dst, struct page *src,
 			   unsigned long addr, struct vm_area_struct *vma)
 {
 	int i;
 	struct hstate *h = hstate_vma(vma);
 
 	if (unlikely(pages_per_huge_page(h) > MAX_ORDER_NR_PAGES)) {
-		copy_gigantic_page(dst, src, addr, vma);
+		copy_user_gigantic_page(dst, src, addr, vma);
 		return;
 	}
 
@@ -458,6 +459,40 @@
 	}
 }
 
+static void copy_gigantic_page(struct page *dst, struct page *src)
+{
+	int i;
+	struct hstate *h = page_hstate(src);
+	struct page *dst_base = dst;
+	struct page *src_base = src;
+
+	for (i = 0; i < pages_per_huge_page(h); ) {
+		cond_resched();
+		copy_highpage(dst, src);
+
+		i++;
+		dst = mem_map_next(dst, dst_base, i);
+		src = mem_map_next(src, src_base, i);
+	}
+}
+
+void copy_huge_page(struct page *dst, struct page *src)
+{
+	int i;
+	struct hstate *h = page_hstate(src);
+
+	if (unlikely(pages_per_huge_page(h) > MAX_ORDER_NR_PAGES)) {
+		copy_gigantic_page(dst, src);
+		return;
+	}
+
+	might_sleep();
+	for (i = 0; i < pages_per_huge_page(h); i++) {
+		cond_resched();
+		copy_highpage(dst + i, src + i);
+	}
+}
+
 static void enqueue_huge_page(struct hstate *h, struct page *page)
 {
 	int nid = page_to_nid(page);
@@ -466,11 +501,24 @@
 	h->free_huge_pages_node[nid]++;
 }
 
+static struct page *dequeue_huge_page_node(struct hstate *h, int nid)
+{
+	struct page *page;
+
+	if (list_empty(&h->hugepage_freelists[nid]))
+		return NULL;
+	page = list_entry(h->hugepage_freelists[nid].next, struct page, lru);
+	list_del(&page->lru);
+	set_page_refcounted(page);
+	h->free_huge_pages--;
+	h->free_huge_pages_node[nid]--;
+	return page;
+}
+
 static struct page *dequeue_huge_page_vma(struct hstate *h,
 				struct vm_area_struct *vma,
 				unsigned long address, int avoid_reserve)
 {
-	int nid;
 	struct page *page = NULL;
 	struct mempolicy *mpol;
 	nodemask_t *nodemask;
@@ -496,19 +544,13 @@
 
 	for_each_zone_zonelist_nodemask(zone, z, zonelist,
 						MAX_NR_ZONES - 1, nodemask) {
-		nid = zone_to_nid(zone);
-		if (cpuset_zone_allowed_softwall(zone, htlb_alloc_mask) &&
-		    !list_empty(&h->hugepage_freelists[nid])) {
-			page = list_entry(h->hugepage_freelists[nid].next,
-					  struct page, lru);
-			list_del(&page->lru);
-			h->free_huge_pages--;
-			h->free_huge_pages_node[nid]--;
-
-			if (!avoid_reserve)
-				decrement_hugepage_resv_vma(h, vma);
-
-			break;
+		if (cpuset_zone_allowed_softwall(zone, htlb_alloc_mask)) {
+			page = dequeue_huge_page_node(h, zone_to_nid(zone));
+			if (page) {
+				if (!avoid_reserve)
+					decrement_hugepage_resv_vma(h, vma);
+				break;
+			}
 		}
 	}
 err:
@@ -770,11 +812,10 @@
 	return ret;
 }
 
-static struct page *alloc_buddy_huge_page(struct hstate *h,
-			struct vm_area_struct *vma, unsigned long address)
+static struct page *alloc_buddy_huge_page(struct hstate *h, int nid)
 {
 	struct page *page;
-	unsigned int nid;
+	unsigned int r_nid;
 
 	if (h->order >= MAX_ORDER)
 		return NULL;
@@ -812,9 +853,14 @@
 	}
 	spin_unlock(&hugetlb_lock);
 
-	page = alloc_pages(htlb_alloc_mask|__GFP_COMP|
-					__GFP_REPEAT|__GFP_NOWARN,
-					huge_page_order(h));
+	if (nid == NUMA_NO_NODE)
+		page = alloc_pages(htlb_alloc_mask|__GFP_COMP|
+				   __GFP_REPEAT|__GFP_NOWARN,
+				   huge_page_order(h));
+	else
+		page = alloc_pages_exact_node(nid,
+			htlb_alloc_mask|__GFP_COMP|__GFP_THISNODE|
+			__GFP_REPEAT|__GFP_NOWARN, huge_page_order(h));
 
 	if (page && arch_prepare_hugepage(page)) {
 		__free_pages(page, huge_page_order(h));
@@ -823,19 +869,13 @@
 
 	spin_lock(&hugetlb_lock);
 	if (page) {
-		/*
-		 * This page is now managed by the hugetlb allocator and has
-		 * no users -- drop the buddy allocator's reference.
-		 */
-		put_page_testzero(page);
-		VM_BUG_ON(page_count(page));
-		nid = page_to_nid(page);
+		r_nid = page_to_nid(page);
 		set_compound_page_dtor(page, free_huge_page);
 		/*
 		 * We incremented the global counters already
 		 */
-		h->nr_huge_pages_node[nid]++;
-		h->surplus_huge_pages_node[nid]++;
+		h->nr_huge_pages_node[r_nid]++;
+		h->surplus_huge_pages_node[r_nid]++;
 		__count_vm_event(HTLB_BUDDY_PGALLOC);
 	} else {
 		h->nr_huge_pages--;
@@ -848,6 +888,25 @@
 }
 
 /*
+ * This allocation function is useful in the context where vma is irrelevant.
+ * E.g. soft-offlining uses this function because it only cares physical
+ * address of error page.
+ */
+struct page *alloc_huge_page_node(struct hstate *h, int nid)
+{
+	struct page *page;
+
+	spin_lock(&hugetlb_lock);
+	page = dequeue_huge_page_node(h, nid);
+	spin_unlock(&hugetlb_lock);
+
+	if (!page)
+		page = alloc_buddy_huge_page(h, nid);
+
+	return page;
+}
+
+/*
  * Increase the hugetlb pool such that it can accomodate a reservation
  * of size 'delta'.
  */
@@ -871,17 +930,14 @@
 retry:
 	spin_unlock(&hugetlb_lock);
 	for (i = 0; i < needed; i++) {
-		page = alloc_buddy_huge_page(h, NULL, 0);
-		if (!page) {
+		page = alloc_buddy_huge_page(h, NUMA_NO_NODE);
+		if (!page)
 			/*
 			 * We were not able to allocate enough pages to
 			 * satisfy the entire reservation so we free what
 			 * we've allocated so far.
 			 */
-			spin_lock(&hugetlb_lock);
-			needed = 0;
 			goto free;
-		}
 
 		list_add(&page->lru, &surplus_list);
 	}
@@ -908,31 +964,31 @@
 	needed += allocated;
 	h->resv_huge_pages += delta;
 	ret = 0;
-free:
+
+	spin_unlock(&hugetlb_lock);
 	/* Free the needed pages to the hugetlb pool */
 	list_for_each_entry_safe(page, tmp, &surplus_list, lru) {
 		if ((--needed) < 0)
 			break;
 		list_del(&page->lru);
+		/*
+		 * This page is now managed by the hugetlb allocator and has
+		 * no users -- drop the buddy allocator's reference.
+		 */
+		put_page_testzero(page);
+		VM_BUG_ON(page_count(page));
 		enqueue_huge_page(h, page);
 	}
 
 	/* Free unnecessary surplus pages to the buddy allocator */
+free:
 	if (!list_empty(&surplus_list)) {
-		spin_unlock(&hugetlb_lock);
 		list_for_each_entry_safe(page, tmp, &surplus_list, lru) {
 			list_del(&page->lru);
-			/*
-			 * The page has a reference count of zero already, so
-			 * call free_huge_page directly instead of using
-			 * put_page.  This must be done with hugetlb_lock
-			 * unlocked which is safe because free_huge_page takes
-			 * hugetlb_lock before deciding how to free the page.
-			 */
-			free_huge_page(page);
+			put_page(page);
 		}
-		spin_lock(&hugetlb_lock);
 	}
+	spin_lock(&hugetlb_lock);
 
 	return ret;
 }
@@ -1052,14 +1108,13 @@
 	spin_unlock(&hugetlb_lock);
 
 	if (!page) {
-		page = alloc_buddy_huge_page(h, vma, addr);
+		page = alloc_buddy_huge_page(h, NUMA_NO_NODE);
 		if (!page) {
 			hugetlb_put_quota(inode->i_mapping, chg);
 			return ERR_PTR(-VM_FAULT_SIGBUS);
 		}
 	}
 
-	set_page_refcounted(page);
 	set_page_private(page, (unsigned long) mapping);
 
 	vma_commit_reservation(h, vma, addr);
@@ -2153,6 +2208,19 @@
 	return -ENOMEM;
 }
 
+static int is_hugetlb_entry_migration(pte_t pte)
+{
+	swp_entry_t swp;
+
+	if (huge_pte_none(pte) || pte_present(pte))
+		return 0;
+	swp = pte_to_swp_entry(pte);
+	if (non_swap_entry(swp) && is_migration_entry(swp)) {
+		return 1;
+	} else
+		return 0;
+}
+
 static int is_hugetlb_entry_hwpoisoned(pte_t pte)
 {
 	swp_entry_t swp;
@@ -2380,10 +2448,13 @@
 	 * When the original hugepage is shared one, it does not have
 	 * anon_vma prepared.
 	 */
-	if (unlikely(anon_vma_prepare(vma)))
+	if (unlikely(anon_vma_prepare(vma))) {
+		/* Caller expects lock to be held */
+		spin_lock(&mm->page_table_lock);
 		return VM_FAULT_OOM;
+	}
 
-	copy_huge_page(new_page, old_page, address, vma);
+	copy_user_huge_page(new_page, old_page, address, vma);
 	__SetPageUptodate(new_page);
 
 	/*
@@ -2515,22 +2586,20 @@
 			hugepage_add_new_anon_rmap(page, vma, address);
 		}
 	} else {
+		/*
+		 * If memory error occurs between mmap() and fault, some process
+		 * don't have hwpoisoned swap entry for errored virtual address.
+		 * So we need to block hugepage fault by PG_hwpoison bit check.
+		 */
+		if (unlikely(PageHWPoison(page))) {
+			ret = VM_FAULT_HWPOISON | 
+			      VM_FAULT_SET_HINDEX(h - hstates);
+			goto backout_unlocked;
+		}
 		page_dup_rmap(page);
 	}
 
 	/*
-	 * Since memory error handler replaces pte into hwpoison swap entry
-	 * at the time of error handling, a process which reserved but not have
-	 * the mapping to the error hugepage does not have hwpoison swap entry.
-	 * So we need to block accesses from such a process by checking
-	 * PG_hwpoison bit here.
-	 */
-	if (unlikely(PageHWPoison(page))) {
-		ret = VM_FAULT_HWPOISON;
-		goto backout_unlocked;
-	}
-
-	/*
 	 * If we are going to COW a private mapping later, we examine the
 	 * pending reservations for this page now. This will ensure that
 	 * any allocations necessary to record that reservation occur outside
@@ -2587,8 +2656,12 @@
 	ptep = huge_pte_offset(mm, address);
 	if (ptep) {
 		entry = huge_ptep_get(ptep);
-		if (unlikely(is_hugetlb_entry_hwpoisoned(entry)))
-			return VM_FAULT_HWPOISON;
+		if (unlikely(is_hugetlb_entry_migration(entry))) {
+			migration_entry_wait(mm, (pmd_t *)ptep, address);
+			return 0;
+		} else if (unlikely(is_hugetlb_entry_hwpoisoned(entry)))
+			return VM_FAULT_HWPOISON_LARGE | 
+			       VM_FAULT_SET_HINDEX(h - hstates);
 	}
 
 	ptep = huge_pte_alloc(mm, address, huge_page_size(h));
@@ -2878,18 +2951,41 @@
 	hugetlb_acct_memory(h, -(chg - freed));
 }
 
+#ifdef CONFIG_MEMORY_FAILURE
+
+/* Should be called in hugetlb_lock */
+static int is_hugepage_on_freelist(struct page *hpage)
+{
+	struct page *page;
+	struct page *tmp;
+	struct hstate *h = page_hstate(hpage);
+	int nid = page_to_nid(hpage);
+
+	list_for_each_entry_safe(page, tmp, &h->hugepage_freelists[nid], lru)
+		if (page == hpage)
+			return 1;
+	return 0;
+}
+
 /*
  * This function is called from memory failure code.
  * Assume the caller holds page lock of the head page.
  */
-void __isolate_hwpoisoned_huge_page(struct page *hpage)
+int dequeue_hwpoisoned_huge_page(struct page *hpage)
 {
 	struct hstate *h = page_hstate(hpage);
 	int nid = page_to_nid(hpage);
+	int ret = -EBUSY;
 
 	spin_lock(&hugetlb_lock);
-	list_del(&hpage->lru);
-	h->free_huge_pages--;
-	h->free_huge_pages_node[nid]--;
+	if (is_hugepage_on_freelist(hpage)) {
+		list_del(&hpage->lru);
+		set_page_refcounted(hpage);
+		h->free_huge_pages--;
+		h->free_huge_pages_node[nid]--;
+		ret = 0;
+	}
 	spin_unlock(&hugetlb_lock);
+	return ret;
 }
+#endif
diff --git a/mm/internal.h b/mm/internal.h
index 6a697bb..dedb0af 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -62,7 +62,7 @@
  */
 static inline unsigned long page_order(struct page *page)
 {
-	VM_BUG_ON(!PageBuddy(page));
+	/* PageBuddy() must be checked by the caller */
 	return page_private(page);
 }
 
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 757f6b0..1243241 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -7,21 +7,26 @@
  * Free Software Foundation.
  *
  * High level machine check handler. Handles pages reported by the
- * hardware as being corrupted usually due to a 2bit ECC memory or cache
+ * hardware as being corrupted usually due to a multi-bit ECC memory or cache
  * failure.
+ * 
+ * In addition there is a "soft offline" entry point that allows stop using
+ * not-yet-corrupted-by-suspicious pages without killing anything.
  *
  * Handles page cache pages in various states.	The tricky part
- * here is that we can access any page asynchronous to other VM
- * users, because memory failures could happen anytime and anywhere,
- * possibly violating some of their assumptions. This is why this code
- * has to be extremely careful. Generally it tries to use normal locking
- * rules, as in get the standard locks, even if that means the
- * error handling takes potentially a long time.
- *
- * The operation to map back from RMAP chains to processes has to walk
- * the complete process list and has non linear complexity with the number
- * mappings. In short it can be quite slow. But since memory corruptions
- * are rare we hope to get away with this.
+ * here is that we can access any page asynchronously in respect to 
+ * other VM users, because memory failures could happen anytime and 
+ * anywhere. This could violate some of their assumptions. This is why 
+ * this code has to be extremely careful. Generally it tries to use 
+ * normal locking rules, as in get the standard locks, even if that means 
+ * the error handling takes potentially a long time.
+ * 
+ * There are several operations here with exponential complexity because
+ * of unsuitable VM data structures. For example the operation to map back 
+ * from RMAP chains to processes has to walk the complete process list and 
+ * has non linear complexity with the number. But since memory corruptions
+ * are rare we hope to get away with this. This avoids impacting the core 
+ * VM.
  */
 
 /*
@@ -30,7 +35,6 @@
  * - kcore/oldmem/vmcore/mem/kmem check for hwpoison pages
  * - pass bad pages to kdump next kernel
  */
-#define DEBUG 1		/* remove me in 2.6.34 */
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/page-flags.h>
@@ -78,7 +82,7 @@
 		return 0;
 
 	/*
-	 * page_mapping() does not accept slab page
+	 * page_mapping() does not accept slab pages.
 	 */
 	if (PageSlab(p))
 		return -EINVAL;
@@ -268,7 +272,7 @@
 	struct list_head nd;
 	struct task_struct *tsk;
 	unsigned long addr;
-	unsigned addr_valid:1;
+	char addr_valid;
 };
 
 /*
@@ -309,7 +313,7 @@
 	 * a SIGKILL because the error is not contained anymore.
 	 */
 	if (tk->addr == -EFAULT) {
-		pr_debug("MCE: Unable to find user space address %lx in %s\n",
+		pr_info("MCE: Unable to find user space address %lx in %s\n",
 			page_to_pfn(p), tsk->comm);
 		tk->addr_valid = 0;
 	}
@@ -577,7 +581,7 @@
 					pfn, err);
 		} else if (page_has_private(p) &&
 				!try_to_release_page(p, GFP_NOIO)) {
-			pr_debug("MCE %#lx: failed to release buffers\n", pfn);
+			pr_info("MCE %#lx: failed to release buffers\n", pfn);
 		} else {
 			ret = RECOVERED;
 		}
@@ -693,11 +697,10 @@
  * Issues:
  * - Error on hugepage is contained in hugepage unit (not in raw page unit.)
  *   To narrow down kill region to one page, we need to break up pmd.
- * - To support soft-offlining for hugepage, we need to support hugepage
- *   migration.
  */
 static int me_huge_page(struct page *p, unsigned long pfn)
 {
+	int res = 0;
 	struct page *hpage = compound_head(p);
 	/*
 	 * We can safely recover from error on free or reserved (i.e.
@@ -710,8 +713,9 @@
 	 * so there is no race between isolation and mapping/unmapping.
 	 */
 	if (!(page_mapping(hpage) || PageAnon(hpage))) {
-		__isolate_hwpoisoned_huge_page(hpage);
-		return RECOVERED;
+		res = dequeue_hwpoisoned_huge_page(hpage);
+		if (!res)
+			return RECOVERED;
 	}
 	return DELAYED;
 }
@@ -836,8 +840,6 @@
 	return (result == RECOVERED || result == DELAYED) ? 0 : -EBUSY;
 }
 
-#define N_UNMAP_TRIES 5
-
 /*
  * Do all that is necessary to remove user space mappings. Unmap
  * the pages and send SIGBUS to the processes if the data was dirty.
@@ -849,7 +851,6 @@
 	struct address_space *mapping;
 	LIST_HEAD(tokill);
 	int ret;
-	int i;
 	int kill = 1;
 	struct page *hpage = compound_head(p);
 
@@ -903,17 +904,7 @@
 	if (kill)
 		collect_procs(hpage, &tokill);
 
-	/*
-	 * try_to_unmap can fail temporarily due to races.
-	 * Try a few times (RED-PEN better strategy?)
-	 */
-	for (i = 0; i < N_UNMAP_TRIES; i++) {
-		ret = try_to_unmap(hpage, ttu);
-		if (ret == SWAP_SUCCESS)
-			break;
-		pr_debug("MCE %#lx: try_to_unmap retry needed %d\n", pfn,  ret);
-	}
-
+	ret = try_to_unmap(hpage, ttu);
 	if (ret != SWAP_SUCCESS)
 		printk(KERN_ERR "MCE %#lx: failed to unmap page (mapcount=%d)\n",
 				pfn, page_mapcount(hpage));
@@ -981,7 +972,10 @@
 	 * We need/can do nothing about count=0 pages.
 	 * 1) it's a free page, and therefore in safe hand:
 	 *    prep_new_page() will be the gate keeper.
-	 * 2) it's part of a non-compound high order page.
+	 * 2) it's a free hugepage, which is also safe:
+	 *    an affected hugepage will be dequeued from hugepage freelist,
+	 *    so there's no concern about reusing it ever after.
+	 * 3) it's part of a non-compound high order page.
 	 *    Implies some kernel user: cannot stop them from
 	 *    R/W the page; let's pray that the page has been
 	 *    used and will be freed some time later.
@@ -993,6 +987,24 @@
 		if (is_free_buddy_page(p)) {
 			action_result(pfn, "free buddy", DELAYED);
 			return 0;
+		} else if (PageHuge(hpage)) {
+			/*
+			 * Check "just unpoisoned", "filter hit", and
+			 * "race with other subpage."
+			 */
+			lock_page_nosync(hpage);
+			if (!PageHWPoison(hpage)
+			    || (hwpoison_filter(p) && TestClearPageHWPoison(p))
+			    || (p != hpage && TestSetPageHWPoison(hpage))) {
+				atomic_long_sub(nr_pages, &mce_bad_pages);
+				return 0;
+			}
+			set_page_hwpoison_huge_page(hpage);
+			res = dequeue_hwpoisoned_huge_page(hpage);
+			action_result(pfn, "free huge",
+				      res ? IGNORED : DELAYED);
+			unlock_page(hpage);
+			return res;
 		} else {
 			action_result(pfn, "high order kernel", IGNORED);
 			return -EBUSY;
@@ -1147,16 +1159,26 @@
 	page = compound_head(p);
 
 	if (!PageHWPoison(p)) {
-		pr_debug("MCE: Page was already unpoisoned %#lx\n", pfn);
+		pr_info("MCE: Page was already unpoisoned %#lx\n", pfn);
 		return 0;
 	}
 
 	nr_pages = 1 << compound_order(page);
 
 	if (!get_page_unless_zero(page)) {
+		/*
+		 * Since HWPoisoned hugepage should have non-zero refcount,
+		 * race between memory failure and unpoison seems to happen.
+		 * In such case unpoison fails and memory failure runs
+		 * to the end.
+		 */
+		if (PageHuge(page)) {
+			pr_debug("MCE: Memory failure is now running on free hugepage %#lx\n", pfn);
+			return 0;
+		}
 		if (TestClearPageHWPoison(p))
 			atomic_long_sub(nr_pages, &mce_bad_pages);
-		pr_debug("MCE: Software-unpoisoned free page %#lx\n", pfn);
+		pr_info("MCE: Software-unpoisoned free page %#lx\n", pfn);
 		return 0;
 	}
 
@@ -1168,12 +1190,12 @@
 	 * the free buddy page pool.
 	 */
 	if (TestClearPageHWPoison(page)) {
-		pr_debug("MCE: Software-unpoisoned page %#lx\n", pfn);
+		pr_info("MCE: Software-unpoisoned page %#lx\n", pfn);
 		atomic_long_sub(nr_pages, &mce_bad_pages);
 		freeit = 1;
+		if (PageHuge(page))
+			clear_page_hwpoison_huge_page(page);
 	}
-	if (PageHuge(p))
-		clear_page_hwpoison_huge_page(page);
 	unlock_page(page);
 
 	put_page(page);
@@ -1187,7 +1209,11 @@
 static struct page *new_page(struct page *p, unsigned long private, int **x)
 {
 	int nid = page_to_nid(p);
-	return alloc_pages_exact_node(nid, GFP_HIGHUSER_MOVABLE, 0);
+	if (PageHuge(p))
+		return alloc_huge_page_node(page_hstate(compound_head(p)),
+						   nid);
+	else
+		return alloc_pages_exact_node(nid, GFP_HIGHUSER_MOVABLE, 0);
 }
 
 /*
@@ -1215,14 +1241,21 @@
 	 * was free.
 	 */
 	set_migratetype_isolate(p);
+	/*
+	 * When the target page is a free hugepage, just remove it
+	 * from free hugepage list.
+	 */
 	if (!get_page_unless_zero(compound_head(p))) {
-		if (is_free_buddy_page(p)) {
-			pr_debug("get_any_page: %#lx free buddy page\n", pfn);
+		if (PageHuge(p)) {
+			pr_info("get_any_page: %#lx free huge page\n", pfn);
+			ret = dequeue_hwpoisoned_huge_page(compound_head(p));
+		} else if (is_free_buddy_page(p)) {
+			pr_info("get_any_page: %#lx free buddy page\n", pfn);
 			/* Set hwpoison bit while page is still isolated */
 			SetPageHWPoison(p);
 			ret = 0;
 		} else {
-			pr_debug("get_any_page: %#lx: unknown zero refcount page type %lx\n",
+			pr_info("get_any_page: %#lx: unknown zero refcount page type %lx\n",
 				pfn, p->flags);
 			ret = -EIO;
 		}
@@ -1235,6 +1268,46 @@
 	return ret;
 }
 
+static int soft_offline_huge_page(struct page *page, int flags)
+{
+	int ret;
+	unsigned long pfn = page_to_pfn(page);
+	struct page *hpage = compound_head(page);
+	LIST_HEAD(pagelist);
+
+	ret = get_any_page(page, pfn, flags);
+	if (ret < 0)
+		return ret;
+	if (ret == 0)
+		goto done;
+
+	if (PageHWPoison(hpage)) {
+		put_page(hpage);
+		pr_debug("soft offline: %#lx hugepage already poisoned\n", pfn);
+		return -EBUSY;
+	}
+
+	/* Keep page count to indicate a given hugepage is isolated. */
+
+	list_add(&hpage->lru, &pagelist);
+	ret = migrate_huge_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL, 0);
+	if (ret) {
+			putback_lru_pages(&pagelist);
+		pr_debug("soft offline: %#lx: migration failed %d, type %lx\n",
+			 pfn, ret, page->flags);
+		if (ret > 0)
+			ret = -EIO;
+		return ret;
+	}
+done:
+	if (!PageHWPoison(hpage))
+		atomic_long_add(1 << compound_order(hpage), &mce_bad_pages);
+	set_page_hwpoison_huge_page(hpage);
+	dequeue_hwpoisoned_huge_page(hpage);
+	/* keep elevated page count for bad page */
+	return ret;
+}
+
 /**
  * soft_offline_page - Soft offline a page.
  * @page: page to offline
@@ -1262,6 +1335,9 @@
 	int ret;
 	unsigned long pfn = page_to_pfn(page);
 
+	if (PageHuge(page))
+		return soft_offline_huge_page(page, flags);
+
 	ret = get_any_page(page, pfn, flags);
 	if (ret < 0)
 		return ret;
@@ -1288,7 +1364,7 @@
 			goto done;
 	}
 	if (!PageLRU(page)) {
-		pr_debug("soft_offline: %#lx: unknown non LRU page type %lx\n",
+		pr_info("soft_offline: %#lx: unknown non LRU page type %lx\n",
 				pfn, page->flags);
 		return -EIO;
 	}
@@ -1302,7 +1378,7 @@
 	if (PageHWPoison(page)) {
 		unlock_page(page);
 		put_page(page);
-		pr_debug("soft offline: %#lx page already poisoned\n", pfn);
+		pr_info("soft offline: %#lx page already poisoned\n", pfn);
 		return -EBUSY;
 	}
 
@@ -1323,7 +1399,7 @@
 	put_page(page);
 	if (ret == 1) {
 		ret = 0;
-		pr_debug("soft_offline: %#lx: invalidated\n", pfn);
+		pr_info("soft_offline: %#lx: invalidated\n", pfn);
 		goto done;
 	}
 
@@ -1339,13 +1415,13 @@
 		list_add(&page->lru, &pagelist);
 		ret = migrate_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL, 0);
 		if (ret) {
-			pr_debug("soft offline: %#lx: migration failed %d, type %lx\n",
+			pr_info("soft offline: %#lx: migration failed %d, type %lx\n",
 				pfn, ret, page->flags);
 			if (ret > 0)
 				ret = -EIO;
 		}
 	} else {
-		pr_debug("soft offline: %#lx: isolation failed: %d, page count %d, type %lx\n",
+		pr_info("soft offline: %#lx: isolation failed: %d, page count %d, type %lx\n",
 				pfn, ret, page_count(page), page->flags);
 	}
 	if (ret)
diff --git a/mm/memory.c b/mm/memory.c
index 98b58fe..02e48aa 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -736,7 +736,7 @@
 	dst_pte = pte_alloc_map_lock(dst_mm, dst_pmd, addr, &dst_ptl);
 	if (!dst_pte)
 		return -ENOMEM;
-	src_pte = pte_offset_map_nested(src_pmd, addr);
+	src_pte = pte_offset_map(src_pmd, addr);
 	src_ptl = pte_lockptr(src_mm, src_pmd);
 	spin_lock_nested(src_ptl, SINGLE_DEPTH_NESTING);
 	orig_src_pte = src_pte;
@@ -767,7 +767,7 @@
 
 	arch_leave_lazy_mmu_mode();
 	spin_unlock(src_ptl);
-	pte_unmap_nested(orig_src_pte);
+	pte_unmap(orig_src_pte);
 	add_mm_rss_vec(dst_mm, rss);
 	pte_unmap_unlock(orig_dst_pte, dst_ptl);
 	cond_resched();
@@ -1450,7 +1450,8 @@
 					if (ret & VM_FAULT_OOM)
 						return i ? i : -ENOMEM;
 					if (ret &
-					    (VM_FAULT_HWPOISON|VM_FAULT_SIGBUS))
+					    (VM_FAULT_HWPOISON|VM_FAULT_HWPOISON_LARGE|
+					     VM_FAULT_SIGBUS))
 						return i ? i : -EFAULT;
 					BUG();
 				}
@@ -1590,7 +1591,7 @@
 }
 #endif /* CONFIG_ELF_CORE */
 
-pte_t *get_locked_pte(struct mm_struct *mm, unsigned long addr,
+pte_t *__get_locked_pte(struct mm_struct *mm, unsigned long addr,
 			spinlock_t **ptl)
 {
 	pgd_t * pgd = pgd_offset(mm, addr);
@@ -2079,7 +2080,7 @@
 		 * zeroes.
 		 */
 		if (__copy_from_user_inatomic(kaddr, uaddr, PAGE_SIZE))
-			memset(kaddr, 0, PAGE_SIZE);
+			clear_page(kaddr);
 		kunmap_atomic(kaddr, KM_USER0);
 		flush_dcache_page(dst);
 	} else
@@ -2107,6 +2108,7 @@
 static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
 		unsigned long address, pte_t *page_table, pmd_t *pmd,
 		spinlock_t *ptl, pte_t orig_pte)
+	__releases(ptl)
 {
 	struct page *old_page, *new_page;
 	pte_t entry;
@@ -2626,6 +2628,7 @@
 	struct page *page, *swapcache = NULL;
 	swp_entry_t entry;
 	pte_t pte;
+	int locked;
 	struct mem_cgroup *ptr = NULL;
 	int exclusive = 0;
 	int ret = 0;
@@ -2676,8 +2679,12 @@
 		goto out_release;
 	}
 
-	lock_page(page);
+	locked = lock_page_or_retry(page, mm, flags);
 	delayacct_clear_flag(DELAYACCT_PF_SWAPIN);
+	if (!locked) {
+		ret |= VM_FAULT_RETRY;
+		goto out_release;
+	}
 
 	/*
 	 * Make sure try_to_free_swap or reuse_swap_page or swapoff did not
@@ -2926,7 +2933,8 @@
 	vmf.page = NULL;
 
 	ret = vma->vm_ops->fault(vma, &vmf);
-	if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE)))
+	if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE |
+			    VM_FAULT_RETRY)))
 		return ret;
 
 	if (unlikely(PageHWPoison(vmf.page))) {
@@ -3343,7 +3351,7 @@
 
 #endif	/* __HAVE_ARCH_GATE_AREA */
 
-static int follow_pte(struct mm_struct *mm, unsigned long address,
+static int __follow_pte(struct mm_struct *mm, unsigned long address,
 		pte_t **ptepp, spinlock_t **ptlp)
 {
 	pgd_t *pgd;
@@ -3380,6 +3388,17 @@
 	return -EINVAL;
 }
 
+static inline int follow_pte(struct mm_struct *mm, unsigned long address,
+			     pte_t **ptepp, spinlock_t **ptlp)
+{
+	int res;
+
+	/* (void) is needed to make gcc happy */
+	(void) __cond_lock(*ptlp,
+			   !(res = __follow_pte(mm, address, ptepp, ptlp)));
+	return res;
+}
+
 /**
  * follow_pfn - look up PFN at a user virtual address
  * @vma: memory mapping
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index d4e940a..9260314 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -602,27 +602,14 @@
 /* Checks if this range of memory is likely to be hot-removable. */
 int is_mem_section_removable(unsigned long start_pfn, unsigned long nr_pages)
 {
-	int type;
 	struct page *page = pfn_to_page(start_pfn);
 	struct page *end_page = page + nr_pages;
 
 	/* Check the starting page of each pageblock within the range */
 	for (; page < end_page; page = next_active_pageblock(page)) {
-		type = get_pageblock_migratetype(page);
-
-		/*
-		 * A pageblock containing MOVABLE or free pages is considered
-		 * removable
-		 */
-		if (type != MIGRATE_MOVABLE && !pageblock_free(page))
+		if (!is_pageblock_removable_nolock(page))
 			return 0;
-
-		/*
-		 * A pageblock starting with a PageReserved page is not
-		 * considered removable.
-		 */
-		if (PageReserved(page))
-			return 0;
+		cond_resched();
 	}
 
 	/* All pageblocks in the memory block are likely to be hot-removable */
@@ -659,7 +646,7 @@
  * Scanning pfn is much easier than scanning lru list.
  * Scan pfn from start to end and Find LRU page.
  */
-int scan_lru_pages(unsigned long start, unsigned long end)
+static unsigned long scan_lru_pages(unsigned long start, unsigned long end)
 {
 	unsigned long pfn;
 	struct page *page;
@@ -709,29 +696,30 @@
 					    page_is_file_cache(page));
 
 		} else {
-			/* Becasue we don't have big zone->lock. we should
-			   check this again here. */
-			if (page_count(page))
-				not_managed++;
 #ifdef CONFIG_DEBUG_VM
 			printk(KERN_ALERT "removing pfn %lx from LRU failed\n",
 			       pfn);
 			dump_page(page);
 #endif
+			/* Becasue we don't have big zone->lock. we should
+			   check this again here. */
+			if (page_count(page)) {
+				not_managed++;
+				ret = -EBUSY;
+				break;
+			}
 		}
 	}
-	ret = -EBUSY;
-	if (not_managed) {
-		if (!list_empty(&source))
+	if (!list_empty(&source)) {
+		if (not_managed) {
 			putback_lru_pages(&source);
-		goto out;
+			goto out;
+		}
+		/* this function returns # of failed pages */
+		ret = migrate_pages(&source, hotremove_migrate_alloc, 0, 1);
+		if (ret)
+			putback_lru_pages(&source);
 	}
-	ret = 0;
-	if (list_empty(&source))
-		goto out;
-	/* this function returns # of failed pages */
-	ret = migrate_pages(&source, hotremove_migrate_alloc, 0, 1);
-
 out:
 	return ret;
 }
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index f969da5..81a1276 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -924,15 +924,21 @@
 	nodemask_t nmask;
 	LIST_HEAD(pagelist);
 	int err = 0;
+	struct vm_area_struct *vma;
 
 	nodes_clear(nmask);
 	node_set(source, nmask);
 
-	check_range(mm, mm->mmap->vm_start, mm->task_size, &nmask,
+	vma = check_range(mm, mm->mmap->vm_start, mm->task_size, &nmask,
 			flags | MPOL_MF_DISCONTIG_OK, &pagelist);
+	if (IS_ERR(vma))
+		return PTR_ERR(vma);
 
-	if (!list_empty(&pagelist))
+	if (!list_empty(&pagelist)) {
 		err = migrate_pages(&pagelist, new_node_page, dest, 0);
+		if (err)
+			putback_lru_pages(&pagelist);
+	}
 
 	return err;
 }
@@ -1147,9 +1153,12 @@
 
 		err = mbind_range(mm, start, end, new);
 
-		if (!list_empty(&pagelist))
+		if (!list_empty(&pagelist)) {
 			nr_failed = migrate_pages(&pagelist, new_vma_page,
 						(unsigned long)vma, 0);
+			if (nr_failed)
+				putback_lru_pages(&pagelist);
+		}
 
 		if (!err && nr_failed && (flags & MPOL_MF_STRICT))
 			err = -EIO;
diff --git a/mm/migrate.c b/mm/migrate.c
index 38e7cad..fe5a3c6 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -32,6 +32,7 @@
 #include <linux/security.h>
 #include <linux/memcontrol.h>
 #include <linux/syscalls.h>
+#include <linux/hugetlb.h>
 #include <linux/gfp.h>
 
 #include "internal.h"
@@ -95,26 +96,34 @@
 	pte_t *ptep, pte;
  	spinlock_t *ptl;
 
- 	pgd = pgd_offset(mm, addr);
-	if (!pgd_present(*pgd))
-		goto out;
+	if (unlikely(PageHuge(new))) {
+		ptep = huge_pte_offset(mm, addr);
+		if (!ptep)
+			goto out;
+		ptl = &mm->page_table_lock;
+	} else {
+		pgd = pgd_offset(mm, addr);
+		if (!pgd_present(*pgd))
+			goto out;
 
-	pud = pud_offset(pgd, addr);
-	if (!pud_present(*pud))
-		goto out;
+		pud = pud_offset(pgd, addr);
+		if (!pud_present(*pud))
+			goto out;
 
-	pmd = pmd_offset(pud, addr);
-	if (!pmd_present(*pmd))
-		goto out;
+		pmd = pmd_offset(pud, addr);
+		if (!pmd_present(*pmd))
+			goto out;
 
-	ptep = pte_offset_map(pmd, addr);
+		ptep = pte_offset_map(pmd, addr);
 
-	if (!is_swap_pte(*ptep)) {
-		pte_unmap(ptep);
-		goto out;
- 	}
+		if (!is_swap_pte(*ptep)) {
+			pte_unmap(ptep);
+			goto out;
+		}
 
- 	ptl = pte_lockptr(mm, pmd);
+		ptl = pte_lockptr(mm, pmd);
+	}
+
  	spin_lock(ptl);
 	pte = *ptep;
 	if (!is_swap_pte(pte))
@@ -130,10 +139,19 @@
 	pte = pte_mkold(mk_pte(new, vma->vm_page_prot));
 	if (is_write_migration_entry(entry))
 		pte = pte_mkwrite(pte);
+#ifdef CONFIG_HUGETLB_PAGE
+	if (PageHuge(new))
+		pte = pte_mkhuge(pte);
+#endif
 	flush_cache_page(vma, addr, pte_pfn(pte));
 	set_pte_at(mm, addr, ptep, pte);
 
-	if (PageAnon(new))
+	if (PageHuge(new)) {
+		if (PageAnon(new))
+			hugepage_add_anon_rmap(new, vma, addr);
+		else
+			page_dup_rmap(new);
+	} else if (PageAnon(new))
 		page_add_anon_rmap(new, vma, addr);
 	else
 		page_add_file_rmap(new);
@@ -276,11 +294,59 @@
 }
 
 /*
+ * The expected number of remaining references is the same as that
+ * of migrate_page_move_mapping().
+ */
+int migrate_huge_page_move_mapping(struct address_space *mapping,
+				   struct page *newpage, struct page *page)
+{
+	int expected_count;
+	void **pslot;
+
+	if (!mapping) {
+		if (page_count(page) != 1)
+			return -EAGAIN;
+		return 0;
+	}
+
+	spin_lock_irq(&mapping->tree_lock);
+
+	pslot = radix_tree_lookup_slot(&mapping->page_tree,
+					page_index(page));
+
+	expected_count = 2 + page_has_private(page);
+	if (page_count(page) != expected_count ||
+	    (struct page *)radix_tree_deref_slot(pslot) != page) {
+		spin_unlock_irq(&mapping->tree_lock);
+		return -EAGAIN;
+	}
+
+	if (!page_freeze_refs(page, expected_count)) {
+		spin_unlock_irq(&mapping->tree_lock);
+		return -EAGAIN;
+	}
+
+	get_page(newpage);
+
+	radix_tree_replace_slot(pslot, newpage);
+
+	page_unfreeze_refs(page, expected_count);
+
+	__put_page(page);
+
+	spin_unlock_irq(&mapping->tree_lock);
+	return 0;
+}
+
+/*
  * Copy the page to its new location
  */
-static void migrate_page_copy(struct page *newpage, struct page *page)
+void migrate_page_copy(struct page *newpage, struct page *page)
 {
-	copy_highpage(newpage, page);
+	if (PageHuge(page))
+		copy_huge_page(newpage, page);
+	else
+		copy_highpage(newpage, page);
 
 	if (PageError(page))
 		SetPageError(newpage);
@@ -431,7 +497,6 @@
 		.nr_to_write = 1,
 		.range_start = 0,
 		.range_end = LLONG_MAX,
-		.nonblocking = 1,
 		.for_reclaim = 1
 	};
 	int rc;
@@ -724,6 +789,92 @@
 }
 
 /*
+ * Counterpart of unmap_and_move_page() for hugepage migration.
+ *
+ * This function doesn't wait the completion of hugepage I/O
+ * because there is no race between I/O and migration for hugepage.
+ * Note that currently hugepage I/O occurs only in direct I/O
+ * where no lock is held and PG_writeback is irrelevant,
+ * and writeback status of all subpages are counted in the reference
+ * count of the head page (i.e. if all subpages of a 2MB hugepage are
+ * under direct I/O, the reference of the head page is 512 and a bit more.)
+ * This means that when we try to migrate hugepage whose subpages are
+ * doing direct I/O, some references remain after try_to_unmap() and
+ * hugepage migration fails without data corruption.
+ *
+ * There is also no race when direct I/O is issued on the page under migration,
+ * because then pte is replaced with migration swap entry and direct I/O code
+ * will wait in the page fault for migration to complete.
+ */
+static int unmap_and_move_huge_page(new_page_t get_new_page,
+				unsigned long private, struct page *hpage,
+				int force, int offlining)
+{
+	int rc = 0;
+	int *result = NULL;
+	struct page *new_hpage = get_new_page(hpage, private, &result);
+	int rcu_locked = 0;
+	struct anon_vma *anon_vma = NULL;
+
+	if (!new_hpage)
+		return -ENOMEM;
+
+	rc = -EAGAIN;
+
+	if (!trylock_page(hpage)) {
+		if (!force)
+			goto out;
+		lock_page(hpage);
+	}
+
+	if (PageAnon(hpage)) {
+		rcu_read_lock();
+		rcu_locked = 1;
+
+		if (page_mapped(hpage)) {
+			anon_vma = page_anon_vma(hpage);
+			atomic_inc(&anon_vma->external_refcount);
+		}
+	}
+
+	try_to_unmap(hpage, TTU_MIGRATION|TTU_IGNORE_MLOCK|TTU_IGNORE_ACCESS);
+
+	if (!page_mapped(hpage))
+		rc = move_to_new_page(new_hpage, hpage, 1);
+
+	if (rc)
+		remove_migration_ptes(hpage, hpage);
+
+	if (anon_vma && atomic_dec_and_lock(&anon_vma->external_refcount,
+					    &anon_vma->lock)) {
+		int empty = list_empty(&anon_vma->head);
+		spin_unlock(&anon_vma->lock);
+		if (empty)
+			anon_vma_free(anon_vma);
+	}
+
+	if (rcu_locked)
+		rcu_read_unlock();
+out:
+	unlock_page(hpage);
+
+	if (rc != -EAGAIN) {
+		list_del(&hpage->lru);
+		put_page(hpage);
+	}
+
+	put_page(new_hpage);
+
+	if (result) {
+		if (rc)
+			*result = rc;
+		else
+			*result = page_to_nid(new_hpage);
+	}
+	return rc;
+}
+
+/*
  * migrate_pages
  *
  * The function takes one list of pages to migrate and a function
@@ -732,8 +883,9 @@
  *
  * The function returns after 10 attempts or if no pages
  * are movable anymore because to has become empty
- * or no retryable pages exist anymore. All pages will be
- * returned to the LRU or freed.
+ * or no retryable pages exist anymore.
+ * Caller should call putback_lru_pages to return pages to the LRU
+ * or free list.
  *
  * Return: Number of pages not migrated or error code.
  */
@@ -780,7 +932,51 @@
 	if (!swapwrite)
 		current->flags &= ~PF_SWAPWRITE;
 
-	putback_lru_pages(from);
+	if (rc)
+		return rc;
+
+	return nr_failed + retry;
+}
+
+int migrate_huge_pages(struct list_head *from,
+		new_page_t get_new_page, unsigned long private, int offlining)
+{
+	int retry = 1;
+	int nr_failed = 0;
+	int pass = 0;
+	struct page *page;
+	struct page *page2;
+	int rc;
+
+	for (pass = 0; pass < 10 && retry; pass++) {
+		retry = 0;
+
+		list_for_each_entry_safe(page, page2, from, lru) {
+			cond_resched();
+
+			rc = unmap_and_move_huge_page(get_new_page,
+					private, page, pass > 2, offlining);
+
+			switch(rc) {
+			case -ENOMEM:
+				goto out;
+			case -EAGAIN:
+				retry++;
+				break;
+			case 0:
+				break;
+			default:
+				/* Permanent failure */
+				nr_failed++;
+				break;
+			}
+		}
+	}
+	rc = 0;
+out:
+
+	list_for_each_entry_safe(page, page2, from, lru)
+		put_page(page);
 
 	if (rc)
 		return rc;
@@ -841,7 +1037,7 @@
 
 		err = -EFAULT;
 		vma = find_vma(mm, pp->addr);
-		if (!vma || !vma_migratable(vma))
+		if (!vma || pp->addr < vma->vm_start || !vma_migratable(vma))
 			goto set_status;
 
 		page = follow_page(vma, pp->addr, FOLL_GET);
@@ -890,9 +1086,12 @@
 	}
 
 	err = 0;
-	if (!list_empty(&pagelist))
+	if (!list_empty(&pagelist)) {
 		err = migrate_pages(&pagelist, new_page_node,
 				(unsigned long)pm, 0);
+		if (err)
+			putback_lru_pages(&pagelist);
+	}
 
 	up_read(&mm->mmap_sem);
 	return err;
@@ -1005,7 +1204,7 @@
 		int err = -EFAULT;
 
 		vma = find_vma(mm, addr);
-		if (!vma)
+		if (!vma || addr < vma->vm_start)
 			goto set_status;
 
 		page = follow_page(vma, addr, 0);
diff --git a/mm/mremap.c b/mm/mremap.c
index cde56ee..563fbdd 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -101,7 +101,7 @@
 	 * pte locks because exclusive mmap_sem prevents deadlock.
 	 */
 	old_pte = pte_offset_map_lock(mm, old_pmd, old_addr, &old_ptl);
- 	new_pte = pte_offset_map_nested(new_pmd, new_addr);
+	new_pte = pte_offset_map(new_pmd, new_addr);
 	new_ptl = pte_lockptr(mm, new_pmd);
 	if (new_ptl != old_ptl)
 		spin_lock_nested(new_ptl, SINGLE_DEPTH_NESTING);
@@ -119,7 +119,7 @@
 	arch_leave_lazy_mmu_mode();
 	if (new_ptl != old_ptl)
 		spin_unlock(new_ptl);
-	pte_unmap_nested(new_pte - 1);
+	pte_unmap(new_pte - 1);
 	pte_unmap_unlock(old_pte - 1, old_ptl);
 	if (mapping)
 		spin_unlock(&mapping->i_mmap_lock);
diff --git a/mm/nommu.c b/mm/nommu.c
index 88ff091..30b5c20 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -293,11 +293,58 @@
 }
 EXPORT_SYMBOL(vmalloc);
 
+/*
+ *	vzalloc - allocate virtually continguos memory with zero fill
+ *
+ *	@size:		allocation size
+ *
+ *	Allocate enough pages to cover @size from the page level
+ *	allocator and map them into continguos kernel virtual space.
+ *	The memory allocated is set to zero.
+ *
+ *	For tight control over page level allocator and protection flags
+ *	use __vmalloc() instead.
+ */
+void *vzalloc(unsigned long size)
+{
+	return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO,
+			PAGE_KERNEL);
+}
+EXPORT_SYMBOL(vzalloc);
+
+/**
+ * vmalloc_node - allocate memory on a specific node
+ * @size:	allocation size
+ * @node:	numa node
+ *
+ * Allocate enough pages to cover @size from the page level
+ * allocator and map them into contiguous kernel virtual space.
+ *
+ * For tight control over page level allocator and protection flags
+ * use __vmalloc() instead.
+ */
 void *vmalloc_node(unsigned long size, int node)
 {
 	return vmalloc(size);
 }
-EXPORT_SYMBOL(vmalloc_node);
+
+/**
+ * vzalloc_node - allocate memory on a specific node with zero fill
+ * @size:	allocation size
+ * @node:	numa node
+ *
+ * Allocate enough pages to cover @size from the page level
+ * allocator and map them into contiguous kernel virtual space.
+ * The memory allocated is set to zero.
+ *
+ * For tight control over page level allocator and protection flags
+ * use __vmalloc() instead.
+ */
+void *vzalloc_node(unsigned long size, int node)
+{
+	return vzalloc(size);
+}
+EXPORT_SYMBOL(vzalloc_node);
 
 #ifndef PAGE_KERNEL_EXEC
 # define PAGE_KERNEL_EXEC PAGE_KERNEL
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 4029583..7dcca55 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -162,10 +162,11 @@
 		return 0;
 
 	/*
-	 * Shortcut check for OOM_SCORE_ADJ_MIN so the entire heuristic doesn't
-	 * need to be executed for something that cannot be killed.
+	 * Shortcut check for a thread sharing p->mm that is OOM_SCORE_ADJ_MIN
+	 * so the entire heuristic doesn't need to be executed for something
+	 * that cannot be killed.
 	 */
-	if (p->signal->oom_score_adj == OOM_SCORE_ADJ_MIN) {
+	if (atomic_read(&p->mm->oom_disable_count)) {
 		task_unlock(p);
 		return 0;
 	}
@@ -403,16 +404,40 @@
 #define K(x) ((x) << (PAGE_SHIFT-10))
 static int oom_kill_task(struct task_struct *p, struct mem_cgroup *mem)
 {
+	struct task_struct *q;
+	struct mm_struct *mm;
+
 	p = find_lock_task_mm(p);
 	if (!p)
 		return 1;
 
+	/* mm cannot be safely dereferenced after task_unlock(p) */
+	mm = p->mm;
+
 	pr_err("Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB\n",
 		task_pid_nr(p), p->comm, K(p->mm->total_vm),
 		K(get_mm_counter(p->mm, MM_ANONPAGES)),
 		K(get_mm_counter(p->mm, MM_FILEPAGES)));
 	task_unlock(p);
 
+	/*
+	 * Kill all processes sharing p->mm in other thread groups, if any.
+	 * They don't get access to memory reserves or a higher scheduler
+	 * priority, though, to avoid depletion of all memory or task
+	 * starvation.  This prevents mm->mmap_sem livelock when an oom killed
+	 * task cannot exit because it requires the semaphore and its contended
+	 * by another thread trying to allocate memory itself.  That thread will
+	 * now get access to memory reserves since it has a pending fatal
+	 * signal.
+	 */
+	for_each_process(q)
+		if (q->mm == mm && !same_thread_group(q, p)) {
+			task_lock(q);	/* Protect ->comm from prctl() */
+			pr_err("Kill process %d (%s) sharing same memory\n",
+				task_pid_nr(q), q->comm);
+			task_unlock(q);
+			force_sig(SIGKILL, q);
+		}
 
 	set_tsk_thread_flag(p, TIF_MEMDIE);
 	force_sig(SIGKILL, p);
@@ -680,7 +705,7 @@
 	read_lock(&tasklist_lock);
 	if (sysctl_oom_kill_allocating_task &&
 	    !oom_unkillable_task(current, NULL, nodemask) &&
-	    (current->signal->oom_adj != OOM_DISABLE)) {
+	    current->mm && !atomic_read(&current->mm->oom_disable_count)) {
 		/*
 		 * oom_kill_process() needs tasklist_lock held.  If it returns
 		 * non-zero, current could not be killed so we must fallback to
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index e3bccac..b840afa 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -415,14 +415,8 @@
 
 	if (vm_dirty_bytes)
 		dirty = DIV_ROUND_UP(vm_dirty_bytes, PAGE_SIZE);
-	else {
-		int dirty_ratio;
-
-		dirty_ratio = vm_dirty_ratio;
-		if (dirty_ratio < 5)
-			dirty_ratio = 5;
-		dirty = (dirty_ratio * available_memory) / 100;
-	}
+	else
+		dirty = (vm_dirty_ratio * available_memory) / 100;
 
 	if (dirty_background_bytes)
 		background = DIV_ROUND_UP(dirty_background_bytes, PAGE_SIZE);
@@ -510,7 +504,7 @@
 		 * catch-up. This avoids (excessively) small writeouts
 		 * when the bdi limits are ramping up.
 		 */
-		if (nr_reclaimable + nr_writeback <
+		if (nr_reclaimable + nr_writeback <=
 				(background_thresh + dirty_thresh) / 2)
 			break;
 
@@ -542,8 +536,8 @@
 		 * the last resort safeguard.
 		 */
 		dirty_exceeded =
-			(bdi_nr_reclaimable + bdi_nr_writeback >= bdi_thresh)
-			|| (nr_reclaimable + nr_writeback >= dirty_thresh);
+			(bdi_nr_reclaimable + bdi_nr_writeback > bdi_thresh)
+			|| (nr_reclaimable + nr_writeback > dirty_thresh);
 
 		if (!dirty_exceeded)
 			break;
@@ -1121,6 +1115,7 @@
 {
 	if (mapping_cap_account_dirty(mapping)) {
 		__inc_zone_page_state(page, NR_FILE_DIRTY);
+		__inc_zone_page_state(page, NR_DIRTIED);
 		__inc_bdi_stat(mapping->backing_dev_info, BDI_RECLAIMABLE);
 		task_dirty_inc(current);
 		task_io_account_write(PAGE_CACHE_SIZE);
@@ -1129,6 +1124,18 @@
 EXPORT_SYMBOL(account_page_dirtied);
 
 /*
+ * Helper function for set_page_writeback family.
+ * NOTE: Unlike account_page_dirtied this does not rely on being atomic
+ * wrt interrupts.
+ */
+void account_page_writeback(struct page *page)
+{
+	inc_zone_page_state(page, NR_WRITEBACK);
+	inc_zone_page_state(page, NR_WRITTEN);
+}
+EXPORT_SYMBOL(account_page_writeback);
+
+/*
  * For address_spaces which do not use buffers.  Just tag the page as dirty in
  * its radix tree.
  *
@@ -1366,7 +1373,7 @@
 		ret = TestSetPageWriteback(page);
 	}
 	if (!ret)
-		inc_zone_page_state(page, NR_WRITEBACK);
+		account_page_writeback(page);
 	return ret;
 
 }
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 2a362c5..07a6544 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -531,7 +531,7 @@
 	 * so it's less likely to be used soon and more likely to be merged
 	 * as a higher order page
 	 */
-	if ((order < MAX_ORDER-1) && pfn_valid_within(page_to_pfn(buddy))) {
+	if ((order < MAX_ORDER-2) && pfn_valid_within(page_to_pfn(buddy))) {
 		struct page *higher_page, *higher_buddy;
 		combined_idx = __find_combined_index(page_idx, order);
 		higher_page = page + combined_idx - page_idx;
@@ -1907,7 +1907,7 @@
 			preferred_zone, migratetype);
 
 		if (!page && gfp_mask & __GFP_NOFAIL)
-			congestion_wait(BLK_RW_ASYNC, HZ/50);
+			wait_iff_congested(preferred_zone, BLK_RW_ASYNC, HZ/50);
 	} while (!page && (gfp_mask & __GFP_NOFAIL));
 
 	return page;
@@ -1932,7 +1932,7 @@
 	const gfp_t wait = gfp_mask & __GFP_WAIT;
 
 	/* __GFP_HIGH is assumed to be the same as ALLOC_HIGH to save a branch. */
-	BUILD_BUG_ON(__GFP_HIGH != ALLOC_HIGH);
+	BUILD_BUG_ON(__GFP_HIGH != (__force gfp_t) ALLOC_HIGH);
 
 	/*
 	 * The caller may dip into page reserves a bit more if the caller
@@ -1940,7 +1940,7 @@
 	 * policy or is asking for __GFP_HIGH memory.  GFP_ATOMIC requests will
 	 * set both ALLOC_HARDER (!wait) and ALLOC_HIGH (__GFP_HIGH).
 	 */
-	alloc_flags |= (gfp_mask & __GFP_HIGH);
+	alloc_flags |= (__force int) (gfp_mask & __GFP_HIGH);
 
 	if (!wait) {
 		alloc_flags |= ALLOC_HARDER;
@@ -2095,7 +2095,7 @@
 	pages_reclaimed += did_some_progress;
 	if (should_alloc_retry(gfp_mask, order, pages_reclaimed)) {
 		/* Wait for some write requests to complete then retry */
-		congestion_wait(BLK_RW_ASYNC, HZ/50);
+		wait_iff_congested(preferred_zone, BLK_RW_ASYNC, HZ/50);
 		goto rebalance;
 	}
 
@@ -5297,12 +5297,65 @@
  * page allocater never alloc memory from ISOLATE block.
  */
 
+static int
+__count_immobile_pages(struct zone *zone, struct page *page, int count)
+{
+	unsigned long pfn, iter, found;
+	/*
+	 * For avoiding noise data, lru_add_drain_all() should be called
+	 * If ZONE_MOVABLE, the zone never contains immobile pages
+	 */
+	if (zone_idx(zone) == ZONE_MOVABLE)
+		return true;
+
+	if (get_pageblock_migratetype(page) == MIGRATE_MOVABLE)
+		return true;
+
+	pfn = page_to_pfn(page);
+	for (found = 0, iter = 0; iter < pageblock_nr_pages; iter++) {
+		unsigned long check = pfn + iter;
+
+		if (!pfn_valid_within(check)) {
+			iter++;
+			continue;
+		}
+		page = pfn_to_page(check);
+		if (!page_count(page)) {
+			if (PageBuddy(page))
+				iter += (1 << page_order(page)) - 1;
+			continue;
+		}
+		if (!PageLRU(page))
+			found++;
+		/*
+		 * If there are RECLAIMABLE pages, we need to check it.
+		 * But now, memory offline itself doesn't call shrink_slab()
+		 * and it still to be fixed.
+		 */
+		/*
+		 * If the page is not RAM, page_count()should be 0.
+		 * we don't need more check. This is an _used_ not-movable page.
+		 *
+		 * The problematic thing here is PG_reserved pages. PG_reserved
+		 * is set to both of a memory hole page and a _used_ kernel
+		 * page at boot.
+		 */
+		if (found > count)
+			return false;
+	}
+	return true;
+}
+
+bool is_pageblock_removable_nolock(struct page *page)
+{
+	struct zone *zone = page_zone(page);
+	return __count_immobile_pages(zone, page, 0);
+}
+
 int set_migratetype_isolate(struct page *page)
 {
 	struct zone *zone;
-	struct page *curr_page;
-	unsigned long flags, pfn, iter;
-	unsigned long immobile = 0;
+	unsigned long flags, pfn;
 	struct memory_isolate_notify arg;
 	int notifier_ret;
 	int ret = -EBUSY;
@@ -5312,11 +5365,6 @@
 	zone_idx = zone_idx(zone);
 
 	spin_lock_irqsave(&zone->lock, flags);
-	if (get_pageblock_migratetype(page) == MIGRATE_MOVABLE ||
-	    zone_idx == ZONE_MOVABLE) {
-		ret = 0;
-		goto out;
-	}
 
 	pfn = page_to_pfn(page);
 	arg.start_pfn = pfn;
@@ -5336,23 +5384,20 @@
 	 */
 	notifier_ret = memory_isolate_notify(MEM_ISOLATE_COUNT, &arg);
 	notifier_ret = notifier_to_errno(notifier_ret);
-	if (notifier_ret || !arg.pages_found)
+	if (notifier_ret)
 		goto out;
-
-	for (iter = pfn; iter < (pfn + pageblock_nr_pages); iter++) {
-		if (!pfn_valid_within(pfn))
-			continue;
-
-		curr_page = pfn_to_page(iter);
-		if (!page_count(curr_page) || PageLRU(curr_page))
-			continue;
-
-		immobile++;
-	}
-
-	if (arg.pages_found == immobile)
+	/*
+	 * FIXME: Now, memory hotplug doesn't call shrink_slab() by itself.
+	 * We just check MOVABLE pages.
+	 */
+	if (__count_immobile_pages(zone, page, arg.pages_found))
 		ret = 0;
 
+	/*
+	 * immobile means "not-on-lru" paes. If immobile is larger than
+	 * removable-by-driver pages reported by notifier, we'll fail.
+	 */
+
 out:
 	if (!ret) {
 		set_pageblock_migratetype(page, MIGRATE_ISOLATE);
diff --git a/mm/page_isolation.c b/mm/page_isolation.c
index 5e0ffd9..4ae42bb 100644
--- a/mm/page_isolation.c
+++ b/mm/page_isolation.c
@@ -86,7 +86,7 @@
  * all pages in [start_pfn...end_pfn) must be in the same zone.
  * zone->lock must be held before call this.
  *
- * Returns 0 if all pages in the range is isolated.
+ * Returns 1 if all pages in the range is isolated.
  */
 static int
 __test_page_isolated_in_pageblock(unsigned long pfn, unsigned long end_pfn)
@@ -119,7 +119,6 @@
 	struct zone *zone;
 	int ret;
 
-	pfn = start_pfn;
 	/*
 	 * Note: pageblock_nr_page != MAX_ORDER. Then, chunks of free page
 	 * is not aligned to pageblock_nr_pages.
diff --git a/mm/rmap.c b/mm/rmap.c
index 5f17fad..1a8bf76b 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -80,7 +80,7 @@
 	return kmem_cache_alloc(anon_vma_chain_cachep, GFP_KERNEL);
 }
 
-void anon_vma_chain_free(struct anon_vma_chain *anon_vma_chain)
+static void anon_vma_chain_free(struct anon_vma_chain *anon_vma_chain)
 {
 	kmem_cache_free(anon_vma_chain_cachep, anon_vma_chain);
 }
@@ -314,7 +314,7 @@
  * Getting a lock on a stable anon_vma from a page off the LRU is
  * tricky: page_lock_anon_vma rely on RCU to guard against the races.
  */
-struct anon_vma *page_lock_anon_vma(struct page *page)
+struct anon_vma *__page_lock_anon_vma(struct page *page)
 {
 	struct anon_vma *anon_vma, *root_anon_vma;
 	unsigned long anon_mapping;
@@ -348,6 +348,8 @@
 }
 
 void page_unlock_anon_vma(struct anon_vma *anon_vma)
+	__releases(&anon_vma->root->lock)
+	__releases(RCU)
 {
 	anon_vma_unlock(anon_vma);
 	rcu_read_unlock();
@@ -407,7 +409,7 @@
  *
  * On success returns with pte mapped and locked.
  */
-pte_t *page_check_address(struct page *page, struct mm_struct *mm,
+pte_t *__page_check_address(struct page *page, struct mm_struct *mm,
 			  unsigned long address, spinlock_t **ptlp, int sync)
 {
 	pgd_t *pgd;
@@ -780,10 +782,10 @@
 }
 
 /**
- * __page_set_anon_rmap - setup new anonymous rmap
- * @page:	the page to add the mapping to
- * @vma:	the vm area in which the mapping is added
- * @address:	the user virtual address mapped
+ * __page_set_anon_rmap - set up new anonymous rmap
+ * @page:	Page to add to rmap	
+ * @vma:	VM area to add page to.
+ * @address:	User virtual address of the mapping	
  * @exclusive:	the page is exclusively owned by the current process
  */
 static void __page_set_anon_rmap(struct page *page,
@@ -793,25 +795,16 @@
 
 	BUG_ON(!anon_vma);
 
+	if (PageAnon(page))
+		return;
+
 	/*
 	 * If the page isn't exclusively mapped into this vma,
 	 * we must use the _oldest_ possible anon_vma for the
 	 * page mapping!
 	 */
-	if (!exclusive) {
-		if (PageAnon(page))
-			return;
+	if (!exclusive)
 		anon_vma = anon_vma->root;
-	} else {
-		/*
-		 * In this case, swapped-out-but-not-discarded swap-cache
-		 * is remapped. So, no need to update page->mapping here.
-		 * We convice anon_vma poitned by page->mapping is not obsolete
-		 * because vma->anon_vma is necessary to be a family of it.
-		 */
-		if (PageAnon(page))
-			return;
-	}
 
 	anon_vma = (void *) anon_vma + PAGE_MAPPING_ANON;
 	page->mapping = (struct address_space *) anon_vma;
diff --git a/mm/slab.c b/mm/slab.c
index fcae981..b1e40da 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -901,7 +901,7 @@
 		struct array_cache *from, unsigned int max)
 {
 	/* Figure out how many entries to transfer */
-	int nr = min(min(from->avail, max), to->limit - to->avail);
+	int nr = min3(from->avail, max, to->limit - to->avail);
 
 	if (!nr)
 		return 0;
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 9fc7bac..67ddaaf 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -30,6 +30,7 @@
 #include <linux/capability.h>
 #include <linux/syscalls.h>
 #include <linux/memcontrol.h>
+#include <linux/poll.h>
 
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
@@ -58,6 +59,10 @@
 
 static DEFINE_MUTEX(swapon_mutex);
 
+static DECLARE_WAIT_QUEUE_HEAD(proc_poll_wait);
+/* Activity counter to indicate that a swapon or swapoff has occurred */
+static atomic_t proc_poll_event = ATOMIC_INIT(0);
+
 static inline unsigned char swap_count(unsigned char ent)
 {
 	return ent & ~SWAP_HAS_CACHE;	/* may include SWAP_HAS_CONT flag */
@@ -1680,6 +1685,8 @@
 	}
 	filp_close(swap_file, NULL);
 	err = 0;
+	atomic_inc(&proc_poll_event);
+	wake_up_interruptible(&proc_poll_wait);
 
 out_dput:
 	filp_close(victim, NULL);
@@ -1688,6 +1695,25 @@
 }
 
 #ifdef CONFIG_PROC_FS
+struct proc_swaps {
+	struct seq_file seq;
+	int event;
+};
+
+static unsigned swaps_poll(struct file *file, poll_table *wait)
+{
+	struct proc_swaps *s = file->private_data;
+
+	poll_wait(file, &proc_poll_wait, wait);
+
+	if (s->event != atomic_read(&proc_poll_event)) {
+		s->event = atomic_read(&proc_poll_event);
+		return POLLIN | POLLRDNORM | POLLERR | POLLPRI;
+	}
+
+	return POLLIN | POLLRDNORM;
+}
+
 /* iterator */
 static void *swap_start(struct seq_file *swap, loff_t *pos)
 {
@@ -1771,7 +1797,24 @@
 
 static int swaps_open(struct inode *inode, struct file *file)
 {
-	return seq_open(file, &swaps_op);
+	struct proc_swaps *s;
+	int ret;
+
+	s = kmalloc(sizeof(struct proc_swaps), GFP_KERNEL);
+	if (!s)
+		return -ENOMEM;
+
+	file->private_data = s;
+
+	ret = seq_open(file, &swaps_op);
+	if (ret) {
+		kfree(s);
+		return ret;
+	}
+
+	s->seq.private = s;
+	s->event = atomic_read(&proc_poll_event);
+	return ret;
 }
 
 static const struct file_operations proc_swaps_operations = {
@@ -1779,6 +1822,7 @@
 	.read		= seq_read,
 	.llseek		= seq_lseek,
 	.release	= seq_release,
+	.poll		= swaps_poll,
 };
 
 static int __init procswaps_init(void)
@@ -2084,6 +2128,9 @@
 		swap_info[prev]->next = type;
 	spin_unlock(&swap_lock);
 	mutex_unlock(&swapon_mutex);
+	atomic_inc(&proc_poll_event);
+	wake_up_interruptible(&proc_poll_wait);
+
 	error = 0;
 	goto out;
 bad_swap:
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 9f90962..a3d66b3 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -293,13 +293,13 @@
 	struct rb_node *tmp;
 
 	while (*p) {
-		struct vmap_area *tmp;
+		struct vmap_area *tmp_va;
 
 		parent = *p;
-		tmp = rb_entry(parent, struct vmap_area, rb_node);
-		if (va->va_start < tmp->va_end)
+		tmp_va = rb_entry(parent, struct vmap_area, rb_node);
+		if (va->va_start < tmp_va->va_end)
 			p = &(*p)->rb_left;
-		else if (va->va_end > tmp->va_start)
+		else if (va->va_end > tmp_va->va_start)
 			p = &(*p)->rb_right;
 		else
 			BUG();
@@ -1596,6 +1596,13 @@
 }
 EXPORT_SYMBOL(__vmalloc);
 
+static inline void *__vmalloc_node_flags(unsigned long size,
+					int node, gfp_t flags)
+{
+	return __vmalloc_node(size, 1, flags, PAGE_KERNEL,
+					node, __builtin_return_address(0));
+}
+
 /**
  *	vmalloc  -  allocate virtually contiguous memory
  *	@size:		allocation size
@@ -1607,12 +1614,28 @@
  */
 void *vmalloc(unsigned long size)
 {
-	return __vmalloc_node(size, 1, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL,
-					-1, __builtin_return_address(0));
+	return __vmalloc_node_flags(size, -1, GFP_KERNEL | __GFP_HIGHMEM);
 }
 EXPORT_SYMBOL(vmalloc);
 
 /**
+ *	vzalloc - allocate virtually contiguous memory with zero fill
+ *	@size:	allocation size
+ *	Allocate enough pages to cover @size from the page level
+ *	allocator and map them into contiguous kernel virtual space.
+ *	The memory allocated is set to zero.
+ *
+ *	For tight control over page level allocator and protection flags
+ *	use __vmalloc() instead.
+ */
+void *vzalloc(unsigned long size)
+{
+	return __vmalloc_node_flags(size, -1,
+				GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO);
+}
+EXPORT_SYMBOL(vzalloc);
+
+/**
  * vmalloc_user - allocate zeroed virtually contiguous memory for userspace
  * @size: allocation size
  *
@@ -1653,6 +1676,25 @@
 }
 EXPORT_SYMBOL(vmalloc_node);
 
+/**
+ * vzalloc_node - allocate memory on a specific node with zero fill
+ * @size:	allocation size
+ * @node:	numa node
+ *
+ * Allocate enough pages to cover @size from the page level
+ * allocator and map them into contiguous kernel virtual space.
+ * The memory allocated is set to zero.
+ *
+ * For tight control over page level allocator and protection flags
+ * use __vmalloc_node() instead.
+ */
+void *vzalloc_node(unsigned long size, int node)
+{
+	return __vmalloc_node_flags(size, node,
+			 GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO);
+}
+EXPORT_SYMBOL(vzalloc_node);
+
 #ifndef PAGE_KERNEL_EXEC
 # define PAGE_KERNEL_EXEC PAGE_KERNEL
 #endif
@@ -2350,6 +2392,7 @@
 
 #ifdef CONFIG_PROC_FS
 static void *s_start(struct seq_file *m, loff_t *pos)
+	__acquires(&vmlist_lock)
 {
 	loff_t n = *pos;
 	struct vm_struct *v;
@@ -2376,6 +2419,7 @@
 }
 
 static void s_stop(struct seq_file *m, void *p)
+	__releases(&vmlist_lock)
 {
 	read_unlock(&vmlist_lock);
 }
diff --git a/mm/vmscan.c b/mm/vmscan.c
index b94c946..b8a6fdc 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -51,6 +51,12 @@
 #define CREATE_TRACE_POINTS
 #include <trace/events/vmscan.h>
 
+enum lumpy_mode {
+	LUMPY_MODE_NONE,
+	LUMPY_MODE_ASYNC,
+	LUMPY_MODE_SYNC,
+};
+
 struct scan_control {
 	/* Incremented by the number of inactive pages that were scanned */
 	unsigned long nr_scanned;
@@ -82,7 +88,7 @@
 	 * Intend to reclaim enough continuous memory rather than reclaim
 	 * enough amount of memory. i.e, mode for high order allocation.
 	 */
-	bool lumpy_reclaim_mode;
+	enum lumpy_mode lumpy_reclaim_mode;
 
 	/* Which cgroup do we reclaim from */
 	struct mem_cgroup *mem_cgroup;
@@ -265,6 +271,36 @@
 	return ret;
 }
 
+static void set_lumpy_reclaim_mode(int priority, struct scan_control *sc,
+				   bool sync)
+{
+	enum lumpy_mode mode = sync ? LUMPY_MODE_SYNC : LUMPY_MODE_ASYNC;
+
+	/*
+	 * Some reclaim have alredy been failed. No worth to try synchronous
+	 * lumpy reclaim.
+	 */
+	if (sync && sc->lumpy_reclaim_mode == LUMPY_MODE_NONE)
+		return;
+
+	/*
+	 * If we need a large contiguous chunk of memory, or have
+	 * trouble getting a small set of contiguous pages, we
+	 * will reclaim both active and inactive pages.
+	 */
+	if (sc->order > PAGE_ALLOC_COSTLY_ORDER)
+		sc->lumpy_reclaim_mode = mode;
+	else if (sc->order && priority < DEF_PRIORITY - 2)
+		sc->lumpy_reclaim_mode = mode;
+	else
+		sc->lumpy_reclaim_mode = LUMPY_MODE_NONE;
+}
+
+static void disable_lumpy_reclaim_mode(struct scan_control *sc)
+{
+	sc->lumpy_reclaim_mode = LUMPY_MODE_NONE;
+}
+
 static inline int is_page_cache_freeable(struct page *page)
 {
 	/*
@@ -275,7 +311,8 @@
 	return page_count(page) - page_has_private(page) == 2;
 }
 
-static int may_write_to_queue(struct backing_dev_info *bdi)
+static int may_write_to_queue(struct backing_dev_info *bdi,
+			      struct scan_control *sc)
 {
 	if (current->flags & PF_SWAPWRITE)
 		return 1;
@@ -283,6 +320,10 @@
 		return 1;
 	if (bdi == current->backing_dev_info)
 		return 1;
+
+	/* lumpy reclaim for hugepage often need a lot of write */
+	if (sc->order > PAGE_ALLOC_COSTLY_ORDER)
+		return 1;
 	return 0;
 }
 
@@ -307,12 +348,6 @@
 	unlock_page(page);
 }
 
-/* Request for sync pageout. */
-enum pageout_io {
-	PAGEOUT_IO_ASYNC,
-	PAGEOUT_IO_SYNC,
-};
-
 /* possible outcome of pageout() */
 typedef enum {
 	/* failed to write page out, page is locked */
@@ -330,7 +365,7 @@
  * Calls ->writepage().
  */
 static pageout_t pageout(struct page *page, struct address_space *mapping,
-						enum pageout_io sync_writeback)
+			 struct scan_control *sc)
 {
 	/*
 	 * If the page is dirty, only perform writeback if that write
@@ -366,7 +401,7 @@
 	}
 	if (mapping->a_ops->writepage == NULL)
 		return PAGE_ACTIVATE;
-	if (!may_write_to_queue(mapping->backing_dev_info))
+	if (!may_write_to_queue(mapping->backing_dev_info, sc))
 		return PAGE_KEEP;
 
 	if (clear_page_dirty_for_io(page)) {
@@ -376,7 +411,6 @@
 			.nr_to_write = SWAP_CLUSTER_MAX,
 			.range_start = 0,
 			.range_end = LLONG_MAX,
-			.nonblocking = 1,
 			.for_reclaim = 1,
 		};
 
@@ -394,7 +428,8 @@
 		 * direct reclaiming a large contiguous area and the
 		 * first attempt to free a range of pages fails.
 		 */
-		if (PageWriteback(page) && sync_writeback == PAGEOUT_IO_SYNC)
+		if (PageWriteback(page) &&
+		    sc->lumpy_reclaim_mode == LUMPY_MODE_SYNC)
 			wait_on_page_writeback(page);
 
 		if (!PageWriteback(page)) {
@@ -402,7 +437,7 @@
 			ClearPageReclaim(page);
 		}
 		trace_mm_vmscan_writepage(page,
-			trace_reclaim_flags(page, sync_writeback));
+			trace_reclaim_flags(page, sc->lumpy_reclaim_mode));
 		inc_zone_page_state(page, NR_VMSCAN_WRITE);
 		return PAGE_SUCCESS;
 	}
@@ -580,7 +615,7 @@
 	referenced_page = TestClearPageReferenced(page);
 
 	/* Lumpy reclaim - ignore references */
-	if (sc->lumpy_reclaim_mode)
+	if (sc->lumpy_reclaim_mode != LUMPY_MODE_NONE)
 		return PAGEREF_RECLAIM;
 
 	/*
@@ -616,7 +651,7 @@
 	}
 
 	/* Reclaim if clean, defer dirty pages to writeback */
-	if (referenced_page)
+	if (referenced_page && !PageSwapBacked(page))
 		return PAGEREF_RECLAIM_CLEAN;
 
 	return PAGEREF_RECLAIM;
@@ -644,12 +679,14 @@
  * shrink_page_list() returns the number of reclaimed pages
  */
 static unsigned long shrink_page_list(struct list_head *page_list,
-					struct scan_control *sc,
-					enum pageout_io sync_writeback)
+				      struct zone *zone,
+				      struct scan_control *sc)
 {
 	LIST_HEAD(ret_pages);
 	LIST_HEAD(free_pages);
 	int pgactivate = 0;
+	unsigned long nr_dirty = 0;
+	unsigned long nr_congested = 0;
 	unsigned long nr_reclaimed = 0;
 
 	cond_resched();
@@ -669,6 +706,7 @@
 			goto keep;
 
 		VM_BUG_ON(PageActive(page));
+		VM_BUG_ON(page_zone(page) != zone);
 
 		sc->nr_scanned++;
 
@@ -694,10 +732,13 @@
 			 * for any page for which writeback has already
 			 * started.
 			 */
-			if (sync_writeback == PAGEOUT_IO_SYNC && may_enter_fs)
+			if (sc->lumpy_reclaim_mode == LUMPY_MODE_SYNC &&
+			    may_enter_fs)
 				wait_on_page_writeback(page);
-			else
-				goto keep_locked;
+			else {
+				unlock_page(page);
+				goto keep_lumpy;
+			}
 		}
 
 		references = page_check_references(page, sc);
@@ -743,6 +784,8 @@
 		}
 
 		if (PageDirty(page)) {
+			nr_dirty++;
+
 			if (references == PAGEREF_RECLAIM_CLEAN)
 				goto keep_locked;
 			if (!may_enter_fs)
@@ -751,14 +794,18 @@
 				goto keep_locked;
 
 			/* Page is dirty, try to write it out here */
-			switch (pageout(page, mapping, sync_writeback)) {
+			switch (pageout(page, mapping, sc)) {
 			case PAGE_KEEP:
+				nr_congested++;
 				goto keep_locked;
 			case PAGE_ACTIVATE:
 				goto activate_locked;
 			case PAGE_SUCCESS:
-				if (PageWriteback(page) || PageDirty(page))
+				if (PageWriteback(page))
+					goto keep_lumpy;
+				if (PageDirty(page))
 					goto keep;
+
 				/*
 				 * A synchronous write - probably a ramdisk.  Go
 				 * ahead and try to reclaim the page.
@@ -841,6 +888,7 @@
 			try_to_free_swap(page);
 		unlock_page(page);
 		putback_lru_page(page);
+		disable_lumpy_reclaim_mode(sc);
 		continue;
 
 activate_locked:
@@ -853,10 +901,21 @@
 keep_locked:
 		unlock_page(page);
 keep:
+		disable_lumpy_reclaim_mode(sc);
+keep_lumpy:
 		list_add(&page->lru, &ret_pages);
 		VM_BUG_ON(PageLRU(page) || PageUnevictable(page));
 	}
 
+	/*
+	 * Tag a zone as congested if all the dirty pages encountered were
+	 * backed by a congested BDI. In this case, reclaimers should just
+	 * back off and wait for congestion to clear because further reclaim
+	 * will encounter the same problem
+	 */
+	if (nr_dirty == nr_congested)
+		zone_set_flag(zone, ZONE_CONGESTED);
+
 	free_page_list(&free_pages);
 
 	list_splice(&ret_pages, page_list);
@@ -1006,7 +1065,7 @@
 
 			/* Check that we have not crossed a zone boundary. */
 			if (unlikely(page_zone_id(cursor_page) != zone_id))
-				continue;
+				break;
 
 			/*
 			 * If we don't have enough swap space, reclaiming of
@@ -1014,8 +1073,8 @@
 			 * pointless.
 			 */
 			if (nr_swap_pages <= 0 && PageAnon(cursor_page) &&
-					!PageSwapCache(cursor_page))
-				continue;
+			    !PageSwapCache(cursor_page))
+				break;
 
 			if (__isolate_lru_page(cursor_page, mode, file) == 0) {
 				list_move(&cursor_page->lru, dst);
@@ -1026,11 +1085,16 @@
 					nr_lumpy_dirty++;
 				scan++;
 			} else {
-				if (mode == ISOLATE_BOTH &&
-						page_count(cursor_page))
-					nr_lumpy_failed++;
+				/* the page is freed already. */
+				if (!page_count(cursor_page))
+					continue;
+				break;
 			}
 		}
+
+		/* If we break out of the loop above, lumpy reclaim failed */
+		if (pfn < end_pfn)
+			nr_lumpy_failed++;
 	}
 
 	*scanned = scan;
@@ -1253,7 +1317,7 @@
 		return false;
 
 	/* Only stall on lumpy reclaim */
-	if (!sc->lumpy_reclaim_mode)
+	if (sc->lumpy_reclaim_mode == LUMPY_MODE_NONE)
 		return false;
 
 	/* If we have relaimed everything on the isolated list, no stall */
@@ -1286,7 +1350,6 @@
 	unsigned long nr_scanned;
 	unsigned long nr_reclaimed = 0;
 	unsigned long nr_taken;
-	unsigned long nr_active;
 	unsigned long nr_anon;
 	unsigned long nr_file;
 
@@ -1298,15 +1361,15 @@
 			return SWAP_CLUSTER_MAX;
 	}
 
-
+	set_lumpy_reclaim_mode(priority, sc, false);
 	lru_add_drain();
 	spin_lock_irq(&zone->lru_lock);
 
 	if (scanning_global_lru(sc)) {
 		nr_taken = isolate_pages_global(nr_to_scan,
 			&page_list, &nr_scanned, sc->order,
-			sc->lumpy_reclaim_mode ?
-				ISOLATE_BOTH : ISOLATE_INACTIVE,
+			sc->lumpy_reclaim_mode == LUMPY_MODE_NONE ?
+					ISOLATE_INACTIVE : ISOLATE_BOTH,
 			zone, 0, file);
 		zone->pages_scanned += nr_scanned;
 		if (current_is_kswapd())
@@ -1318,8 +1381,8 @@
 	} else {
 		nr_taken = mem_cgroup_isolate_pages(nr_to_scan,
 			&page_list, &nr_scanned, sc->order,
-			sc->lumpy_reclaim_mode ?
-				ISOLATE_BOTH : ISOLATE_INACTIVE,
+			sc->lumpy_reclaim_mode == LUMPY_MODE_NONE ?
+					ISOLATE_INACTIVE : ISOLATE_BOTH,
 			zone, sc->mem_cgroup,
 			0, file);
 		/*
@@ -1337,20 +1400,12 @@
 
 	spin_unlock_irq(&zone->lru_lock);
 
-	nr_reclaimed = shrink_page_list(&page_list, sc, PAGEOUT_IO_ASYNC);
+	nr_reclaimed = shrink_page_list(&page_list, zone, sc);
 
 	/* Check if we should syncronously wait for writeback */
 	if (should_reclaim_stall(nr_taken, nr_reclaimed, priority, sc)) {
-		congestion_wait(BLK_RW_ASYNC, HZ/10);
-
-		/*
-		 * The attempt at page out may have made some
-		 * of the pages active, mark them inactive again.
-		 */
-		nr_active = clear_active_flags(&page_list, NULL);
-		count_vm_events(PGDEACTIVATE, nr_active);
-
-		nr_reclaimed += shrink_page_list(&page_list, sc, PAGEOUT_IO_SYNC);
+		set_lumpy_reclaim_mode(priority, sc, true);
+		nr_reclaimed += shrink_page_list(&page_list, zone, sc);
 	}
 
 	local_irq_disable();
@@ -1359,6 +1414,12 @@
 	__count_zone_vm_events(PGSTEAL, zone, nr_reclaimed);
 
 	putback_lru_pages(zone, sc, nr_anon, nr_file, &page_list);
+
+	trace_mm_vmscan_lru_shrink_inactive(zone->zone_pgdat->node_id,
+		zone_idx(zone),
+		nr_scanned, nr_reclaimed,
+		priority,
+		trace_shrink_flags(file, sc->lumpy_reclaim_mode));
 	return nr_reclaimed;
 }
 
@@ -1506,6 +1567,7 @@
 	spin_unlock_irq(&zone->lru_lock);
 }
 
+#ifdef CONFIG_SWAP
 static int inactive_anon_is_low_global(struct zone *zone)
 {
 	unsigned long active, inactive;
@@ -1531,12 +1593,26 @@
 {
 	int low;
 
+	/*
+	 * If we don't have swap space, anonymous page deactivation
+	 * is pointless.
+	 */
+	if (!total_swap_pages)
+		return 0;
+
 	if (scanning_global_lru(sc))
 		low = inactive_anon_is_low_global(zone);
 	else
 		low = mem_cgroup_inactive_anon_is_low(sc->mem_cgroup);
 	return low;
 }
+#else
+static inline int inactive_anon_is_low(struct zone *zone,
+					struct scan_control *sc)
+{
+	return 0;
+}
+#endif
 
 static int inactive_file_is_low_global(struct zone *zone)
 {
@@ -1721,21 +1797,6 @@
 	}
 }
 
-static void set_lumpy_reclaim_mode(int priority, struct scan_control *sc)
-{
-	/*
-	 * If we need a large contiguous chunk of memory, or have
-	 * trouble getting a small set of contiguous pages, we
-	 * will reclaim both active and inactive pages.
-	 */
-	if (sc->order > PAGE_ALLOC_COSTLY_ORDER)
-		sc->lumpy_reclaim_mode = 1;
-	else if (sc->order && priority < DEF_PRIORITY - 2)
-		sc->lumpy_reclaim_mode = 1;
-	else
-		sc->lumpy_reclaim_mode = 0;
-}
-
 /*
  * This is a basic per-zone page freer.  Used by both kswapd and direct reclaim.
  */
@@ -1750,8 +1811,6 @@
 
 	get_scan_count(zone, sc, nr, priority);
 
-	set_lumpy_reclaim_mode(priority, sc);
-
 	while (nr[LRU_INACTIVE_ANON] || nr[LRU_ACTIVE_FILE] ||
 					nr[LRU_INACTIVE_FILE]) {
 		for_each_evictable_lru(l) {
@@ -1782,7 +1841,7 @@
 	 * Even if we did not try to evict anon pages at all, we want to
 	 * rebalance the anon lru active/inactive ratio.
 	 */
-	if (inactive_anon_is_low(zone, sc) && nr_swap_pages > 0)
+	if (inactive_anon_is_low(zone, sc))
 		shrink_active_list(SWAP_CLUSTER_MAX, zone, sc, priority, 0);
 
 	throttle_vm_writeout(sc->gfp_mask);
@@ -1937,21 +1996,16 @@
 
 		/* Take a nap, wait for some writeback to complete */
 		if (!sc->hibernation_mode && sc->nr_scanned &&
-		    priority < DEF_PRIORITY - 2)
-			congestion_wait(BLK_RW_ASYNC, HZ/10);
+		    priority < DEF_PRIORITY - 2) {
+			struct zone *preferred_zone;
+
+			first_zones_zonelist(zonelist, gfp_zone(sc->gfp_mask),
+							NULL, &preferred_zone);
+			wait_iff_congested(preferred_zone, BLK_RW_ASYNC, HZ/10);
+		}
 	}
 
 out:
-	/*
-	 * Now that we've scanned all the zones at this priority level, note
-	 * that level within the zone so that the next thread which performs
-	 * scanning of this zone will immediately start out at this priority
-	 * level.  This affects only the decision whether or not to bring
-	 * mapped pages onto the inactive list.
-	 */
-	if (priority < 0)
-		priority = 0;
-
 	delayacct_freepages_end();
 	put_mems_allowed();
 
@@ -2247,6 +2301,15 @@
 				if (!zone_watermark_ok(zone, order,
 					    min_wmark_pages(zone), end_zone, 0))
 					has_under_min_watermark_zone = 1;
+			} else {
+				/*
+				 * If a zone reaches its high watermark,
+				 * consider it to be no longer congested. It's
+				 * possible there are dirty pages backed by
+				 * congested BDIs but as pressure is relieved,
+				 * spectulatively avoid congestion waits
+				 */
+				zone_clear_flag(zone, ZONE_CONGESTED);
 			}
 
 		}
@@ -2987,6 +3050,7 @@
 	return 0;
 }
 
+#ifdef CONFIG_NUMA
 /*
  * per node 'scan_unevictable_pages' attribute.  On demand re-scan of
  * a specified node's per zone unevictable lists for evictable pages.
@@ -3033,4 +3097,4 @@
 {
 	sysdev_remove_file(&node->sysdev, &attr_scan_unevictable_pages);
 }
-
+#endif
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 355a9e6..cd2e42b 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -17,6 +17,8 @@
 #include <linux/vmstat.h>
 #include <linux/sched.h>
 #include <linux/math64.h>
+#include <linux/writeback.h>
+#include <linux/compaction.h>
 
 #ifdef CONFIG_VM_EVENT_COUNTERS
 DEFINE_PER_CPU(struct vm_event_state, vm_event_states) = {{0}};
@@ -394,6 +396,7 @@
 #endif
 
 #ifdef CONFIG_COMPACTION
+
 struct contig_page_info {
 	unsigned long free_pages;
 	unsigned long free_blocks_total;
@@ -745,6 +748,11 @@
 	"nr_isolated_anon",
 	"nr_isolated_file",
 	"nr_shmem",
+	"nr_dirtied",
+	"nr_written",
+	"nr_dirty_threshold",
+	"nr_dirty_background_threshold",
+
 #ifdef CONFIG_NUMA
 	"numa_hit",
 	"numa_miss",
@@ -904,36 +912,44 @@
 	.release	= seq_release,
 };
 
+enum writeback_stat_item {
+	NR_DIRTY_THRESHOLD,
+	NR_DIRTY_BG_THRESHOLD,
+	NR_VM_WRITEBACK_STAT_ITEMS,
+};
+
 static void *vmstat_start(struct seq_file *m, loff_t *pos)
 {
 	unsigned long *v;
-#ifdef CONFIG_VM_EVENT_COUNTERS
-	unsigned long *e;
-#endif
-	int i;
+	int i, stat_items_size;
 
 	if (*pos >= ARRAY_SIZE(vmstat_text))
 		return NULL;
+	stat_items_size = NR_VM_ZONE_STAT_ITEMS * sizeof(unsigned long) +
+			  NR_VM_WRITEBACK_STAT_ITEMS * sizeof(unsigned long);
 
 #ifdef CONFIG_VM_EVENT_COUNTERS
-	v = kmalloc(NR_VM_ZONE_STAT_ITEMS * sizeof(unsigned long)
-			+ sizeof(struct vm_event_state), GFP_KERNEL);
-#else
-	v = kmalloc(NR_VM_ZONE_STAT_ITEMS * sizeof(unsigned long),
-			GFP_KERNEL);
+	stat_items_size += sizeof(struct vm_event_state);
 #endif
+
+	v = kmalloc(stat_items_size, GFP_KERNEL);
 	m->private = v;
 	if (!v)
 		return ERR_PTR(-ENOMEM);
 	for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
 		v[i] = global_page_state(i);
+	v += NR_VM_ZONE_STAT_ITEMS;
+
+	global_dirty_limits(v + NR_DIRTY_BG_THRESHOLD,
+			    v + NR_DIRTY_THRESHOLD);
+	v += NR_VM_WRITEBACK_STAT_ITEMS;
+
 #ifdef CONFIG_VM_EVENT_COUNTERS
-	e = v + NR_VM_ZONE_STAT_ITEMS;
-	all_vm_events(e);
-	e[PGPGIN] /= 2;		/* sectors -> kbytes */
-	e[PGPGOUT] /= 2;
+	all_vm_events(v);
+	v[PGPGIN] /= 2;		/* sectors -> kbytes */
+	v[PGPGOUT] /= 2;
 #endif
-	return v + *pos;
+	return m->private + *pos;
 }
 
 static void *vmstat_next(struct seq_file *m, void *arg, loff_t *pos)
diff --git a/net/socket.c b/net/socket.c
index 5cac1c7..ee3cd28 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1146,7 +1146,7 @@
 }
 EXPORT_SYMBOL(sock_wake_async);
 
-static int __sock_create(struct net *net, int family, int type, int protocol,
+int __sock_create(struct net *net, int family, int type, int protocol,
 			 struct socket **res, int kern)
 {
 	int err;
@@ -1258,6 +1258,7 @@
 	rcu_read_unlock();
 	goto out_sock_release;
 }
+EXPORT_SYMBOL(__sock_create);
 
 int sock_create(int family, int type, int protocol, struct socket **res)
 {
diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig
index 3376d76..8873fd8 100644
--- a/net/sunrpc/Kconfig
+++ b/net/sunrpc/Kconfig
@@ -36,22 +36,3 @@
 	  Kerberos support should be installed.
 
 	  If unsure, say Y.
-
-config RPCSEC_GSS_SPKM3
-	tristate "Secure RPC: SPKM3 mechanism (EXPERIMENTAL)"
-	depends on SUNRPC && EXPERIMENTAL
-	select SUNRPC_GSS
-	select CRYPTO
-	select CRYPTO_MD5
-	select CRYPTO_DES
-	select CRYPTO_CAST5
-	select CRYPTO_CBC
-	help
-	  Choose Y here to enable Secure RPC using the SPKM3 public key
-	  GSS-API mechanism (RFC 2025).
-
-	  Secure RPC calls with SPKM3 require an auxiliary userspace
-	  daemon which may be found in the Linux nfs-utils package
-	  available from http://linux-nfs.org/.
-
-	  If unsure, say N.
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index e9eaaf7..afe6784 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -595,7 +595,7 @@
 int
 rpcauth_refreshcred(struct rpc_task *task)
 {
-	struct rpc_cred	*cred = task->tk_rqstp->rq_cred;
+	struct rpc_cred	*cred;
 	int err;
 
 	cred = task->tk_rqstp->rq_cred;
@@ -658,7 +658,7 @@
 	return err;
 }
 
-void __exit rpcauth_remove_module(void)
+void rpcauth_remove_module(void)
 {
 	rpc_destroy_authunix();
 	rpc_destroy_generic_auth();
diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c
index 43162bb..e010a01 100644
--- a/net/sunrpc/auth_generic.c
+++ b/net/sunrpc/auth_generic.c
@@ -158,7 +158,7 @@
 	return rpcauth_init_credcache(&generic_auth);
 }
 
-void __exit rpc_destroy_generic_auth(void)
+void rpc_destroy_generic_auth(void)
 {
 	rpcauth_destroy_credcache(&generic_auth);
 }
diff --git a/net/sunrpc/auth_gss/Makefile b/net/sunrpc/auth_gss/Makefile
index 74a2317..7350d86 100644
--- a/net/sunrpc/auth_gss/Makefile
+++ b/net/sunrpc/auth_gss/Makefile
@@ -11,8 +11,3 @@
 
 rpcsec_gss_krb5-objs := gss_krb5_mech.o gss_krb5_seal.o gss_krb5_unseal.o \
 	gss_krb5_seqnum.o gss_krb5_wrap.o gss_krb5_crypto.o gss_krb5_keys.o
-
-obj-$(CONFIG_RPCSEC_GSS_SPKM3) += rpcsec_gss_spkm3.o
-
-rpcsec_gss_spkm3-objs := gss_spkm3_mech.o gss_spkm3_seal.o gss_spkm3_unseal.o \
-	gss_spkm3_token.o
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 778e5df..f375dec 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -427,7 +427,7 @@
 context_derive_keys_rc4(struct krb5_ctx *ctx)
 {
 	struct crypto_hash *hmac;
-	char sigkeyconstant[] = "signaturekey";
+	static const char sigkeyconstant[] = "signaturekey";
 	int slen = strlen(sigkeyconstant) + 1;	/* include null terminator */
 	struct hash_desc desc;
 	struct scatterlist sg[1];
diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c
deleted file mode 100644
index adade3d..0000000
--- a/net/sunrpc/auth_gss/gss_spkm3_mech.c
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- *  linux/net/sunrpc/gss_spkm3_mech.c
- *
- *  Copyright (c) 2003 The Regents of the University of Michigan.
- *  All rights reserved.
- *
- *  Andy Adamson <andros@umich.edu>
- *  J. Bruce Fields <bfields@umich.edu>
- *
- *  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 the University nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/sunrpc/auth.h>
-#include <linux/in.h>
-#include <linux/sunrpc/svcauth_gss.h>
-#include <linux/sunrpc/gss_spkm3.h>
-#include <linux/sunrpc/xdr.h>
-#include <linux/crypto.h>
-
-#ifdef RPC_DEBUG
-# define RPCDBG_FACILITY	RPCDBG_AUTH
-#endif
-
-static const void *
-simple_get_bytes(const void *p, const void *end, void *res, int len)
-{
-	const void *q = (const void *)((const char *)p + len);
-	if (unlikely(q > end || q < p))
-		return ERR_PTR(-EFAULT);
-	memcpy(res, p, len);
-	return q;
-}
-
-static const void *
-simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res)
-{
-	const void *q;
-	unsigned int len;
-	p = simple_get_bytes(p, end, &len, sizeof(len));
-	if (IS_ERR(p))
-		return p;
-	res->len = len;
-	if (len == 0) {
-		res->data = NULL;
-		return p;
-	}
-	q = (const void *)((const char *)p + len);
-	if (unlikely(q > end || q < p))
-		return ERR_PTR(-EFAULT);
-	res->data = kmemdup(p, len, GFP_NOFS);
-	if (unlikely(res->data == NULL))
-		return ERR_PTR(-ENOMEM);
-	return q;
-}
-
-static int
-gss_import_sec_context_spkm3(const void *p, size_t len,
-				struct gss_ctx *ctx_id,
-				gfp_t gfp_mask)
-{
-	const void *end = (const void *)((const char *)p + len);
-	struct	spkm3_ctx *ctx;
-	int	version;
-
-	if (!(ctx = kzalloc(sizeof(*ctx), gfp_mask)))
-		goto out_err;
-
-	p = simple_get_bytes(p, end, &version, sizeof(version));
-	if (IS_ERR(p))
-		goto out_err_free_ctx;
-	if (version != 1) {
-		dprintk("RPC:       unknown spkm3 token format: "
-				"obsolete nfs-utils?\n");
-		p = ERR_PTR(-EINVAL);
-		goto out_err_free_ctx;
-	}
-
-	p = simple_get_netobj(p, end, &ctx->ctx_id);
-	if (IS_ERR(p))
-		goto out_err_free_ctx;
-
-	p = simple_get_bytes(p, end, &ctx->endtime, sizeof(ctx->endtime));
-	if (IS_ERR(p))
-		goto out_err_free_ctx_id;
-
-	p = simple_get_netobj(p, end, &ctx->mech_used);
-	if (IS_ERR(p))
-		goto out_err_free_ctx_id;
-
-	p = simple_get_bytes(p, end, &ctx->ret_flags, sizeof(ctx->ret_flags));
-	if (IS_ERR(p))
-		goto out_err_free_mech;
-
-	p = simple_get_netobj(p, end, &ctx->conf_alg);
-	if (IS_ERR(p))
-		goto out_err_free_mech;
-
-	p = simple_get_netobj(p, end, &ctx->derived_conf_key);
-	if (IS_ERR(p))
-		goto out_err_free_conf_alg;
-
-	p = simple_get_netobj(p, end, &ctx->intg_alg);
-	if (IS_ERR(p))
-		goto out_err_free_conf_key;
-
-	p = simple_get_netobj(p, end, &ctx->derived_integ_key);
-	if (IS_ERR(p))
-		goto out_err_free_intg_alg;
-
-	if (p != end) {
-		p = ERR_PTR(-EFAULT);
-		goto out_err_free_intg_key;
-	}
-
-	ctx_id->internal_ctx_id = ctx;
-
-	dprintk("RPC:       Successfully imported new spkm context.\n");
-	return 0;
-
-out_err_free_intg_key:
-	kfree(ctx->derived_integ_key.data);
-out_err_free_intg_alg:
-	kfree(ctx->intg_alg.data);
-out_err_free_conf_key:
-	kfree(ctx->derived_conf_key.data);
-out_err_free_conf_alg:
-	kfree(ctx->conf_alg.data);
-out_err_free_mech:
-	kfree(ctx->mech_used.data);
-out_err_free_ctx_id:
-	kfree(ctx->ctx_id.data);
-out_err_free_ctx:
-	kfree(ctx);
-out_err:
-	return PTR_ERR(p);
-}
-
-static void
-gss_delete_sec_context_spkm3(void *internal_ctx)
-{
-	struct spkm3_ctx *sctx = internal_ctx;
-
-	kfree(sctx->derived_integ_key.data);
-	kfree(sctx->intg_alg.data);
-	kfree(sctx->derived_conf_key.data);
-	kfree(sctx->conf_alg.data);
-	kfree(sctx->mech_used.data);
-	kfree(sctx->ctx_id.data);
-	kfree(sctx);
-}
-
-static u32
-gss_verify_mic_spkm3(struct gss_ctx		*ctx,
-			struct xdr_buf		*signbuf,
-			struct xdr_netobj	*checksum)
-{
-	u32 maj_stat = 0;
-	struct spkm3_ctx *sctx = ctx->internal_ctx_id;
-
-	maj_stat = spkm3_read_token(sctx, checksum, signbuf, SPKM_MIC_TOK);
-
-	dprintk("RPC:       gss_verify_mic_spkm3 returning %d\n", maj_stat);
-	return maj_stat;
-}
-
-static u32
-gss_get_mic_spkm3(struct gss_ctx	*ctx,
-		     struct xdr_buf	*message_buffer,
-		     struct xdr_netobj	*message_token)
-{
-	u32 err = 0;
-	struct spkm3_ctx *sctx = ctx->internal_ctx_id;
-
-	err = spkm3_make_token(sctx, message_buffer,
-				message_token, SPKM_MIC_TOK);
-	dprintk("RPC:       gss_get_mic_spkm3 returning %d\n", err);
-	return err;
-}
-
-static const struct gss_api_ops gss_spkm3_ops = {
-	.gss_import_sec_context	= gss_import_sec_context_spkm3,
-	.gss_get_mic		= gss_get_mic_spkm3,
-	.gss_verify_mic		= gss_verify_mic_spkm3,
-	.gss_delete_sec_context	= gss_delete_sec_context_spkm3,
-};
-
-static struct pf_desc gss_spkm3_pfs[] = {
-	{RPC_AUTH_GSS_SPKM, RPC_GSS_SVC_NONE, "spkm3"},
-	{RPC_AUTH_GSS_SPKMI, RPC_GSS_SVC_INTEGRITY, "spkm3i"},
-};
-
-static struct gss_api_mech gss_spkm3_mech = {
-	.gm_name	= "spkm3",
-	.gm_owner	= THIS_MODULE,
-	.gm_oid		= {7, "\053\006\001\005\005\001\003"},
-	.gm_ops		= &gss_spkm3_ops,
-	.gm_pf_num	= ARRAY_SIZE(gss_spkm3_pfs),
-	.gm_pfs		= gss_spkm3_pfs,
-};
-
-static int __init init_spkm3_module(void)
-{
-	int status;
-
-	status = gss_mech_register(&gss_spkm3_mech);
-	if (status)
-		printk("Failed to register spkm3 gss mechanism!\n");
-	return status;
-}
-
-static void __exit cleanup_spkm3_module(void)
-{
-	gss_mech_unregister(&gss_spkm3_mech);
-}
-
-MODULE_LICENSE("GPL");
-module_init(init_spkm3_module);
-module_exit(cleanup_spkm3_module);
diff --git a/net/sunrpc/auth_gss/gss_spkm3_seal.c b/net/sunrpc/auth_gss/gss_spkm3_seal.c
deleted file mode 100644
index 5a3a65a..0000000
--- a/net/sunrpc/auth_gss/gss_spkm3_seal.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- *  linux/net/sunrpc/gss_spkm3_seal.c
- *
- *  Copyright (c) 2003 The Regents of the University of Michigan.
- *  All rights reserved.
- *
- *  Andy Adamson <andros@umich.edu>
- *
- *  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 the University nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <linux/types.h>
-#include <linux/jiffies.h>
-#include <linux/sunrpc/gss_spkm3.h>
-#include <linux/random.h>
-#include <linux/crypto.h>
-#include <linux/pagemap.h>
-#include <linux/scatterlist.h>
-#include <linux/sunrpc/xdr.h>
-
-#ifdef RPC_DEBUG
-# define RPCDBG_FACILITY        RPCDBG_AUTH
-#endif
-
-const struct xdr_netobj hmac_md5_oid = { 8, "\x2B\x06\x01\x05\x05\x08\x01\x01"};
-const struct xdr_netobj cast5_cbc_oid = {9, "\x2A\x86\x48\x86\xF6\x7D\x07\x42\x0A"};
-
-/*
- * spkm3_make_token()
- *
- * Only SPKM_MIC_TOK with md5 intg-alg is supported
- */
-
-u32
-spkm3_make_token(struct spkm3_ctx *ctx,
-		   struct xdr_buf * text, struct xdr_netobj * token,
-		   int toktype)
-{
-	s32			checksum_type;
-	char			tokhdrbuf[25];
-	char			cksumdata[16];
-	struct xdr_netobj	md5cksum = {.len = 0, .data = cksumdata};
-	struct xdr_netobj	mic_hdr = {.len = 0, .data = tokhdrbuf};
-	int			tokenlen = 0;
-	unsigned char		*ptr;
-	s32			now;
-	int			ctxelen = 0, ctxzbit = 0;
-	int			md5elen = 0, md5zbit = 0;
-
-	now = jiffies;
-
-	if (ctx->ctx_id.len != 16) {
-		dprintk("RPC:       spkm3_make_token BAD ctx_id.len %d\n",
-				ctx->ctx_id.len);
-		goto out_err;
-	}
-
-	if (!g_OID_equal(&ctx->intg_alg, &hmac_md5_oid)) {
-		dprintk("RPC:       gss_spkm3_seal: unsupported I-ALG "
-				"algorithm.  only support hmac-md5 I-ALG.\n");
-		goto out_err;
-	} else
-		checksum_type = CKSUMTYPE_HMAC_MD5;
-
-	if (!g_OID_equal(&ctx->conf_alg, &cast5_cbc_oid)) {
-		dprintk("RPC:       gss_spkm3_seal: unsupported C-ALG "
-				"algorithm\n");
-		goto out_err;
-	}
-
-	if (toktype == SPKM_MIC_TOK) {
-		/* Calculate checksum over the mic-header */
-		asn1_bitstring_len(&ctx->ctx_id, &ctxelen, &ctxzbit);
-		spkm3_mic_header(&mic_hdr.data, &mic_hdr.len, ctx->ctx_id.data,
-				ctxelen, ctxzbit);
-		if (make_spkm3_checksum(checksum_type, &ctx->derived_integ_key,
-					(char *)mic_hdr.data, mic_hdr.len,
-					text, 0, &md5cksum))
-			goto out_err;
-
-		asn1_bitstring_len(&md5cksum, &md5elen, &md5zbit);
-		tokenlen = 10 + ctxelen + 1 + md5elen + 1;
-
-		/* Create token header using generic routines */
-		token->len = g_token_size(&ctx->mech_used, tokenlen + 2);
-
-		ptr = token->data;
-		g_make_token_header(&ctx->mech_used, tokenlen + 2, &ptr);
-
-		spkm3_make_mic_token(&ptr, tokenlen, &mic_hdr, &md5cksum, md5elen, md5zbit);
-	} else if (toktype == SPKM_WRAP_TOK) { /* Not Supported */
-		dprintk("RPC:       gss_spkm3_seal: SPKM_WRAP_TOK "
-				"not supported\n");
-		goto out_err;
-	}
-
-	/* XXX need to implement sequence numbers, and ctx->expired */
-
-	return  GSS_S_COMPLETE;
-out_err:
-	token->data = NULL;
-	token->len = 0;
-	return GSS_S_FAILURE;
-}
-
-static int
-spkm3_checksummer(struct scatterlist *sg, void *data)
-{
-	struct hash_desc *desc = data;
-
-	return crypto_hash_update(desc, sg, sg->length);
-}
-
-/* checksum the plaintext data and hdrlen bytes of the token header */
-s32
-make_spkm3_checksum(s32 cksumtype, struct xdr_netobj *key, char *header,
-		    unsigned int hdrlen, struct xdr_buf *body,
-		    unsigned int body_offset, struct xdr_netobj *cksum)
-{
-	char				*cksumname;
-	struct hash_desc		desc; /* XXX add to ctx? */
-	struct scatterlist		sg[1];
-	int err;
-
-	switch (cksumtype) {
-		case CKSUMTYPE_HMAC_MD5:
-			cksumname = "hmac(md5)";
-			break;
-		default:
-			dprintk("RPC:       spkm3_make_checksum:"
-					" unsupported checksum %d", cksumtype);
-			return GSS_S_FAILURE;
-	}
-
-	if (key->data == NULL || key->len <= 0) return GSS_S_FAILURE;
-
-	desc.tfm = crypto_alloc_hash(cksumname, 0, CRYPTO_ALG_ASYNC);
-	if (IS_ERR(desc.tfm))
-		return GSS_S_FAILURE;
-	cksum->len = crypto_hash_digestsize(desc.tfm);
-	desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
-
-	err = crypto_hash_setkey(desc.tfm, key->data, key->len);
-	if (err)
-		goto out;
-
-	err = crypto_hash_init(&desc);
-	if (err)
-		goto out;
-
-	sg_init_one(sg, header, hdrlen);
-	crypto_hash_update(&desc, sg, sg->length);
-
-	xdr_process_buf(body, body_offset, body->len - body_offset,
-			spkm3_checksummer, &desc);
-	crypto_hash_final(&desc, cksum->data);
-
-out:
-	crypto_free_hash(desc.tfm);
-
-	return err ? GSS_S_FAILURE : 0;
-}
diff --git a/net/sunrpc/auth_gss/gss_spkm3_token.c b/net/sunrpc/auth_gss/gss_spkm3_token.c
deleted file mode 100644
index a99825d..0000000
--- a/net/sunrpc/auth_gss/gss_spkm3_token.c
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- *  linux/net/sunrpc/gss_spkm3_token.c
- *
- *  Copyright (c) 2003 The Regents of the University of Michigan.
- *  All rights reserved.
- *
- *  Andy Adamson <andros@umich.edu>
- *
- *  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 the University nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/jiffies.h>
-#include <linux/sunrpc/gss_spkm3.h>
-#include <linux/random.h>
-#include <linux/crypto.h>
-
-#ifdef RPC_DEBUG
-# define RPCDBG_FACILITY        RPCDBG_AUTH
-#endif
-
-/*
- * asn1_bitstring_len()
- *
- * calculate the asn1 bitstring length of the xdr_netobject
- */
-void
-asn1_bitstring_len(struct xdr_netobj *in, int *enclen, int *zerobits)
-{
-	int i, zbit = 0,elen = in->len;
-	char *ptr;
-
-	ptr = &in->data[in->len -1];
-
-	/* count trailing 0's */
-	for(i = in->len; i > 0; i--) {
-		if (*ptr == 0) {
-			ptr--;
-			elen--;
-		} else
-			break;
-	}
-
-	/* count number of 0 bits in final octet */
-	ptr = &in->data[elen - 1];
-	for(i = 0; i < 8; i++) {
-		short mask = 0x01;
-
-		if (!((mask << i) & *ptr))
-			zbit++;
-		else
-			break;
-	}
-	*enclen = elen;
-	*zerobits = zbit;
-}
-
-/*
- * decode_asn1_bitstring()
- *
- * decode a bitstring into a buffer of the expected length.
- * enclen = bit string length
- * explen = expected length (define in rfc)
- */
-int
-decode_asn1_bitstring(struct xdr_netobj *out, char *in, int enclen, int explen)
-{
-	if (!(out->data = kzalloc(explen,GFP_NOFS)))
-		return 0;
-	out->len = explen;
-	memcpy(out->data, in, enclen);
-	return 1;
-}
-
-/*
- * SPKMInnerContextToken choice SPKM_MIC asn1 token layout
- *
- * contextid is always 16 bytes plain data. max asn1 bitstring len = 17.
- *
- * tokenlen = pos[0] to end of token (max pos[45] with MD5 cksum)
- *
- * pos  value
- * ----------
- * [0]	a4  SPKM-MIC tag
- * [1]	??  innertoken length  (max 44)
- *
- *
- * tok_hdr piece of checksum data starts here
- *
- * the maximum mic-header len = 9 + 17 = 26
- *	mic-header
- *	----------
- * [2]	30      SEQUENCE tag
- * [3]	??	mic-header length: (max 23) = TokenID + ContextID
- *
- *		TokenID  - all fields constant and can be hardcoded
- *		-------
- * [4]	  02	Type 2
- * [5]	  02	Length 2
- * [6][7] 01 01	TokenID (SPKM_MIC_TOK)
- *
- *		ContextID  - encoded length not constant, calculated
- *		---------
- * [8]	03	Type 3
- * [9]	??	encoded length
- * [10]	??	ctxzbit
- * [11]	 	contextid
- *
- * mic_header piece of checksum data ends here.
- *
- *	int-cksum - encoded length not constant, calculated
- *	---------
- * [??]	03	Type 3
- * [??]	??	encoded length
- * [??]	??	md5zbit
- * [??]	 	int-cksum (NID_md5 = 16)
- *
- * maximum SPKM-MIC innercontext token length =
- *	 10 + encoded contextid_size(17 max) + 2 + encoded
- *       cksum_size (17 maxfor NID_md5) = 46
- */
-
-/*
- * spkm3_mic_header()
- *
- * Prepare the SPKM_MIC_TOK mic-header for check-sum calculation
- * elen: 16 byte context id asn1 bitstring encoded length
- */
-void
-spkm3_mic_header(unsigned char **hdrbuf, unsigned int *hdrlen, unsigned char *ctxdata, int elen, int zbit)
-{
-	char *hptr = *hdrbuf;
-	char *top = *hdrbuf;
-
-	*(u8 *)hptr++ = 0x30;
-	*(u8 *)hptr++ = elen + 7;  /* on the wire header length */
-
-	/* tokenid */
-	*(u8 *)hptr++ = 0x02;
-	*(u8 *)hptr++ = 0x02;
-	*(u8 *)hptr++ = 0x01;
-	*(u8 *)hptr++ = 0x01;
-
-	/* coniextid */
-	*(u8 *)hptr++ = 0x03;
-	*(u8 *)hptr++ = elen + 1; /* add 1 to include zbit */
-	*(u8 *)hptr++ = zbit;
-	memcpy(hptr, ctxdata, elen);
-	hptr += elen;
-	*hdrlen = hptr - top;
-}
-
-/*
- * spkm3_mic_innercontext_token()
- *
- * *tokp points to the beginning of the SPKM_MIC token  described
- * in rfc 2025, section 3.2.1:
- *
- * toklen is the inner token length
- */
-void
-spkm3_make_mic_token(unsigned char **tokp, int toklen, struct xdr_netobj *mic_hdr, struct xdr_netobj *md5cksum, int md5elen, int md5zbit)
-{
-	unsigned char *ict = *tokp;
-
-	*(u8 *)ict++ = 0xa4;
-	*(u8 *)ict++ = toklen;
-	memcpy(ict, mic_hdr->data, mic_hdr->len);
-	ict += mic_hdr->len;
-
-	*(u8 *)ict++ = 0x03;
-	*(u8 *)ict++ = md5elen + 1; /* add 1 to include zbit */
-	*(u8 *)ict++ = md5zbit;
-	memcpy(ict, md5cksum->data, md5elen);
-}
-
-u32
-spkm3_verify_mic_token(unsigned char **tokp, int *mic_hdrlen, unsigned char **cksum)
-{
-	struct xdr_netobj       spkm3_ctx_id = {.len =0, .data = NULL};
-	unsigned char 		*ptr = *tokp;
-	int 			ctxelen;
-	u32     		ret = GSS_S_DEFECTIVE_TOKEN;
-
-	/* spkm3 innercontext token preamble */
-	if ((ptr[0] != 0xa4) || (ptr[2] != 0x30)) {
-		dprintk("RPC:       BAD SPKM ictoken preamble\n");
-		goto out;
-	}
-
-	*mic_hdrlen = ptr[3];
-
-	/* token type */
-	if ((ptr[4] != 0x02) || (ptr[5] != 0x02)) {
-		dprintk("RPC:       BAD asn1 SPKM3 token type\n");
-		goto out;
-	}
-
-	/* only support SPKM_MIC_TOK */
-	if((ptr[6] != 0x01) || (ptr[7] != 0x01)) {
-		dprintk("RPC:       ERROR unsupported SPKM3 token\n");
-		goto out;
-	}
-
-	/* contextid */
-	if (ptr[8] != 0x03) {
-		dprintk("RPC:       BAD SPKM3 asn1 context-id type\n");
-		goto out;
-	}
-
-	ctxelen = ptr[9];
-	if (ctxelen > 17) {  /* length includes asn1 zbit octet */
-		dprintk("RPC:       BAD SPKM3 contextid len %d\n", ctxelen);
-		goto out;
-	}
-
-	/* ignore ptr[10] */
-
-	if(!decode_asn1_bitstring(&spkm3_ctx_id, &ptr[11], ctxelen - 1, 16))
-		goto out;
-
-	/*
-	* in the current implementation: the optional int-alg is not present
-	* so the default int-alg (md5) is used the optional snd-seq field is
-	* also not present
-	*/
-
-	if (*mic_hdrlen != 6 + ctxelen) {
-		dprintk("RPC:       BAD SPKM_ MIC_TOK header len %d: we only "
-				"support default int-alg (should be absent) "
-				"and do not support snd-seq\n", *mic_hdrlen);
-		goto out;
-	}
-	/* checksum */
-	*cksum = (&ptr[10] + ctxelen); /* ctxelen includes ptr[10] */
-
-	ret = GSS_S_COMPLETE;
-out:
-	kfree(spkm3_ctx_id.data);
-	return ret;
-}
-
diff --git a/net/sunrpc/auth_gss/gss_spkm3_unseal.c b/net/sunrpc/auth_gss/gss_spkm3_unseal.c
deleted file mode 100644
index cc21ee8..0000000
--- a/net/sunrpc/auth_gss/gss_spkm3_unseal.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- *  linux/net/sunrpc/gss_spkm3_unseal.c
- *
- *  Copyright (c) 2003 The Regents of the University of Michigan.
- *  All rights reserved.
- *
- *  Andy Adamson <andros@umich.edu>
- *
- *  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 the University nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/jiffies.h>
-#include <linux/sunrpc/gss_spkm3.h>
-#include <linux/crypto.h>
-
-#ifdef RPC_DEBUG
-# define RPCDBG_FACILITY        RPCDBG_AUTH
-#endif
-
-/*
- * spkm3_read_token()
- *
- * only SPKM_MIC_TOK with md5 intg-alg is supported
- */
-u32
-spkm3_read_token(struct spkm3_ctx *ctx,
-		struct xdr_netobj *read_token,    /* checksum */
-		struct xdr_buf *message_buffer, /* signbuf */
-		int toktype)
-{
-	s32			checksum_type;
-	s32			code;
-	struct xdr_netobj	wire_cksum = {.len =0, .data = NULL};
-	char			cksumdata[16];
-	struct xdr_netobj	md5cksum = {.len = 0, .data = cksumdata};
-	unsigned char		*ptr = (unsigned char *)read_token->data;
-	unsigned char		*cksum;
-	int			bodysize, md5elen;
-	int			mic_hdrlen;
-	u32			ret = GSS_S_DEFECTIVE_TOKEN;
-
-	if (g_verify_token_header((struct xdr_netobj *) &ctx->mech_used,
-					&bodysize, &ptr, read_token->len))
-		goto out;
-
-	/* decode the token */
-
-	if (toktype != SPKM_MIC_TOK) {
-		dprintk("RPC:       BAD SPKM3 token type: %d\n", toktype);
-		goto out;
-	}
-
-	if ((ret = spkm3_verify_mic_token(&ptr, &mic_hdrlen, &cksum)))
-		goto out;
-
-	if (*cksum++ != 0x03) {
-		dprintk("RPC:       spkm3_read_token BAD checksum type\n");
-		goto out;
-	}
-	md5elen = *cksum++;
-	cksum++; 	/* move past the zbit */
-
-	if (!decode_asn1_bitstring(&wire_cksum, cksum, md5elen - 1, 16))
-		goto out;
-
-	/* HARD CODED FOR MD5 */
-
-	/* compute the checksum of the message.
-	 * ptr + 2 = start of header piece of checksum
-	 * mic_hdrlen + 2 = length of header piece of checksum
-	 */
-	ret = GSS_S_DEFECTIVE_TOKEN;
-	if (!g_OID_equal(&ctx->intg_alg, &hmac_md5_oid)) {
-		dprintk("RPC:       gss_spkm3_seal: unsupported I-ALG "
-				"algorithm\n");
-		goto out;
-	}
-
-	checksum_type = CKSUMTYPE_HMAC_MD5;
-
-	code = make_spkm3_checksum(checksum_type,
-		&ctx->derived_integ_key, ptr + 2, mic_hdrlen + 2,
-		message_buffer, 0, &md5cksum);
-
-	if (code)
-		goto out;
-
-	ret = GSS_S_BAD_SIG;
-	code = memcmp(md5cksum.data, wire_cksum.data, wire_cksum.len);
-	if (code) {
-		dprintk("RPC:       bad MIC checksum\n");
-		goto out;
-	}
-
-
-	/* XXX: need to add expiration and sequencing */
-	ret = GSS_S_COMPLETE;
-out:
-	kfree(wire_cksum.data);
-	return ret;
-}
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index cc385b3..dec2a6f 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -964,7 +964,7 @@
 	if (rqstp->rq_gssclient == NULL)
 		return SVC_DENIED;
 	stat = svcauth_unix_set_client(rqstp);
-	if (stat == SVC_DROP)
+	if (stat == SVC_DROP || stat == SVC_CLOSE)
 		return stat;
 	return SVC_OK;
 }
@@ -1018,7 +1018,7 @@
 		return SVC_DENIED;
 	memset(&rsikey, 0, sizeof(rsikey));
 	if (dup_netobj(&rsikey.in_handle, &gc->gc_ctx))
-		return SVC_DROP;
+		return SVC_CLOSE;
 	*authp = rpc_autherr_badverf;
 	if (svc_safe_getnetobj(argv, &tmpobj)) {
 		kfree(rsikey.in_handle.data);
@@ -1026,38 +1026,35 @@
 	}
 	if (dup_netobj(&rsikey.in_token, &tmpobj)) {
 		kfree(rsikey.in_handle.data);
-		return SVC_DROP;
+		return SVC_CLOSE;
 	}
 
 	/* Perform upcall, or find upcall result: */
 	rsip = rsi_lookup(&rsikey);
 	rsi_free(&rsikey);
 	if (!rsip)
-		return SVC_DROP;
-	switch (cache_check(&rsi_cache, &rsip->h, &rqstp->rq_chandle)) {
-	case -EAGAIN:
-	case -ETIMEDOUT:
-	case -ENOENT:
+		return SVC_CLOSE;
+	if (cache_check(&rsi_cache, &rsip->h, &rqstp->rq_chandle) < 0)
 		/* No upcall result: */
-		return SVC_DROP;
-	case 0:
-		ret = SVC_DROP;
-		/* Got an answer to the upcall; use it: */
-		if (gss_write_init_verf(rqstp, rsip))
-			goto out;
-		if (resv->iov_len + 4 > PAGE_SIZE)
-			goto out;
-		svc_putnl(resv, RPC_SUCCESS);
-		if (svc_safe_putnetobj(resv, &rsip->out_handle))
-			goto out;
-		if (resv->iov_len + 3 * 4 > PAGE_SIZE)
-			goto out;
-		svc_putnl(resv, rsip->major_status);
-		svc_putnl(resv, rsip->minor_status);
-		svc_putnl(resv, GSS_SEQ_WIN);
-		if (svc_safe_putnetobj(resv, &rsip->out_token))
-			goto out;
-	}
+		return SVC_CLOSE;
+
+	ret = SVC_CLOSE;
+	/* Got an answer to the upcall; use it: */
+	if (gss_write_init_verf(rqstp, rsip))
+		goto out;
+	if (resv->iov_len + 4 > PAGE_SIZE)
+		goto out;
+	svc_putnl(resv, RPC_SUCCESS);
+	if (svc_safe_putnetobj(resv, &rsip->out_handle))
+		goto out;
+	if (resv->iov_len + 3 * 4 > PAGE_SIZE)
+		goto out;
+	svc_putnl(resv, rsip->major_status);
+	svc_putnl(resv, rsip->minor_status);
+	svc_putnl(resv, GSS_SEQ_WIN);
+	if (svc_safe_putnetobj(resv, &rsip->out_token))
+		goto out;
+
 	ret = SVC_COMPLETE;
 out:
 	cache_put(&rsip->h, &rsi_cache);
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 7dce81a..e433e75 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -33,15 +33,16 @@
 #include <linux/sunrpc/cache.h>
 #include <linux/sunrpc/stats.h>
 #include <linux/sunrpc/rpc_pipe_fs.h>
+#include "netns.h"
 
 #define	 RPCDBG_FACILITY RPCDBG_CACHE
 
-static int cache_defer_req(struct cache_req *req, struct cache_head *item);
+static void cache_defer_req(struct cache_req *req, struct cache_head *item);
 static void cache_revisit_request(struct cache_head *item);
 
 static void cache_init(struct cache_head *h)
 {
-	time_t now = get_seconds();
+	time_t now = seconds_since_boot();
 	h->next = NULL;
 	h->flags = 0;
 	kref_init(&h->ref);
@@ -51,7 +52,7 @@
 
 static inline int cache_is_expired(struct cache_detail *detail, struct cache_head *h)
 {
-	return  (h->expiry_time < get_seconds()) ||
+	return  (h->expiry_time < seconds_since_boot()) ||
 		(detail->flush_time > h->last_refresh);
 }
 
@@ -126,7 +127,7 @@
 static void cache_fresh_locked(struct cache_head *head, time_t expiry)
 {
 	head->expiry_time = expiry;
-	head->last_refresh = get_seconds();
+	head->last_refresh = seconds_since_boot();
 	set_bit(CACHE_VALID, &head->flags);
 }
 
@@ -237,7 +238,7 @@
 
 	/* now see if we want to start an upcall */
 	refresh_age = (h->expiry_time - h->last_refresh);
-	age = get_seconds() - h->last_refresh;
+	age = seconds_since_boot() - h->last_refresh;
 
 	if (rqstp == NULL) {
 		if (rv == -EAGAIN)
@@ -252,7 +253,7 @@
 				cache_revisit_request(h);
 				if (rv == -EAGAIN) {
 					set_bit(CACHE_NEGATIVE, &h->flags);
-					cache_fresh_locked(h, get_seconds()+CACHE_NEW_EXPIRY);
+					cache_fresh_locked(h, seconds_since_boot()+CACHE_NEW_EXPIRY);
 					cache_fresh_unlocked(h, detail);
 					rv = -ENOENT;
 				}
@@ -267,7 +268,8 @@
 	}
 
 	if (rv == -EAGAIN) {
-		if (cache_defer_req(rqstp, h) < 0) {
+		cache_defer_req(rqstp, h);
+		if (!test_bit(CACHE_PENDING, &h->flags)) {
 			/* Request is not deferred */
 			rv = cache_is_valid(detail, h);
 			if (rv == -EAGAIN)
@@ -387,11 +389,11 @@
 			return -1;
 		}
 		current_detail = list_entry(next, struct cache_detail, others);
-		if (current_detail->nextcheck > get_seconds())
+		if (current_detail->nextcheck > seconds_since_boot())
 			current_index = current_detail->hash_size;
 		else {
 			current_index = 0;
-			current_detail->nextcheck = get_seconds()+30*60;
+			current_detail->nextcheck = seconds_since_boot()+30*60;
 		}
 	}
 
@@ -476,7 +478,7 @@
 void cache_purge(struct cache_detail *detail)
 {
 	detail->flush_time = LONG_MAX;
-	detail->nextcheck = get_seconds();
+	detail->nextcheck = seconds_since_boot();
 	cache_flush();
 	detail->flush_time = 1;
 }
@@ -505,81 +507,155 @@
 
 static DEFINE_SPINLOCK(cache_defer_lock);
 static LIST_HEAD(cache_defer_list);
-static struct list_head cache_defer_hash[DFR_HASHSIZE];
+static struct hlist_head cache_defer_hash[DFR_HASHSIZE];
 static int cache_defer_cnt;
 
-static int cache_defer_req(struct cache_req *req, struct cache_head *item)
+static void __unhash_deferred_req(struct cache_deferred_req *dreq)
 {
-	struct cache_deferred_req *dreq, *discard;
+	hlist_del_init(&dreq->hash);
+	if (!list_empty(&dreq->recent)) {
+		list_del_init(&dreq->recent);
+		cache_defer_cnt--;
+	}
+}
+
+static void __hash_deferred_req(struct cache_deferred_req *dreq, struct cache_head *item)
+{
 	int hash = DFR_HASH(item);
 
-	if (cache_defer_cnt >= DFR_MAX) {
-		/* too much in the cache, randomly drop this one,
-		 * or continue and drop the oldest below
-		 */
-		if (net_random()&1)
-			return -ENOMEM;
-	}
-	dreq = req->defer(req);
-	if (dreq == NULL)
-		return -ENOMEM;
+	INIT_LIST_HEAD(&dreq->recent);
+	hlist_add_head(&dreq->hash, &cache_defer_hash[hash]);
+}
+
+static void setup_deferral(struct cache_deferred_req *dreq,
+			   struct cache_head *item,
+			   int count_me)
+{
 
 	dreq->item = item;
 
 	spin_lock(&cache_defer_lock);
 
-	list_add(&dreq->recent, &cache_defer_list);
+	__hash_deferred_req(dreq, item);
 
-	if (cache_defer_hash[hash].next == NULL)
-		INIT_LIST_HEAD(&cache_defer_hash[hash]);
-	list_add(&dreq->hash, &cache_defer_hash[hash]);
-
-	/* it is in, now maybe clean up */
-	discard = NULL;
-	if (++cache_defer_cnt > DFR_MAX) {
-		discard = list_entry(cache_defer_list.prev,
-				     struct cache_deferred_req, recent);
-		list_del_init(&discard->recent);
-		list_del_init(&discard->hash);
-		cache_defer_cnt--;
+	if (count_me) {
+		cache_defer_cnt++;
+		list_add(&dreq->recent, &cache_defer_list);
 	}
+
 	spin_unlock(&cache_defer_lock);
 
-	if (discard)
-		/* there was one too many */
-		discard->revisit(discard, 1);
+}
 
-	if (!test_bit(CACHE_PENDING, &item->flags)) {
-		/* must have just been validated... */
-		cache_revisit_request(item);
-		return -EAGAIN;
+struct thread_deferred_req {
+	struct cache_deferred_req handle;
+	struct completion completion;
+};
+
+static void cache_restart_thread(struct cache_deferred_req *dreq, int too_many)
+{
+	struct thread_deferred_req *dr =
+		container_of(dreq, struct thread_deferred_req, handle);
+	complete(&dr->completion);
+}
+
+static void cache_wait_req(struct cache_req *req, struct cache_head *item)
+{
+	struct thread_deferred_req sleeper;
+	struct cache_deferred_req *dreq = &sleeper.handle;
+
+	sleeper.completion = COMPLETION_INITIALIZER_ONSTACK(sleeper.completion);
+	dreq->revisit = cache_restart_thread;
+
+	setup_deferral(dreq, item, 0);
+
+	if (!test_bit(CACHE_PENDING, &item->flags) ||
+	    wait_for_completion_interruptible_timeout(
+		    &sleeper.completion, req->thread_wait) <= 0) {
+		/* The completion wasn't completed, so we need
+		 * to clean up
+		 */
+		spin_lock(&cache_defer_lock);
+		if (!hlist_unhashed(&sleeper.handle.hash)) {
+			__unhash_deferred_req(&sleeper.handle);
+			spin_unlock(&cache_defer_lock);
+		} else {
+			/* cache_revisit_request already removed
+			 * this from the hash table, but hasn't
+			 * called ->revisit yet.  It will very soon
+			 * and we need to wait for it.
+			 */
+			spin_unlock(&cache_defer_lock);
+			wait_for_completion(&sleeper.completion);
+		}
 	}
-	return 0;
+}
+
+static void cache_limit_defers(void)
+{
+	/* Make sure we haven't exceed the limit of allowed deferred
+	 * requests.
+	 */
+	struct cache_deferred_req *discard = NULL;
+
+	if (cache_defer_cnt <= DFR_MAX)
+		return;
+
+	spin_lock(&cache_defer_lock);
+
+	/* Consider removing either the first or the last */
+	if (cache_defer_cnt > DFR_MAX) {
+		if (net_random() & 1)
+			discard = list_entry(cache_defer_list.next,
+					     struct cache_deferred_req, recent);
+		else
+			discard = list_entry(cache_defer_list.prev,
+					     struct cache_deferred_req, recent);
+		__unhash_deferred_req(discard);
+	}
+	spin_unlock(&cache_defer_lock);
+	if (discard)
+		discard->revisit(discard, 1);
+}
+
+static void cache_defer_req(struct cache_req *req, struct cache_head *item)
+{
+	struct cache_deferred_req *dreq;
+
+	if (req->thread_wait) {
+		cache_wait_req(req, item);
+		if (!test_bit(CACHE_PENDING, &item->flags))
+			return;
+	}
+	dreq = req->defer(req);
+	if (dreq == NULL)
+		return;
+	setup_deferral(dreq, item, 1);
+	if (!test_bit(CACHE_PENDING, &item->flags))
+		/* Bit could have been cleared before we managed to
+		 * set up the deferral, so need to revisit just in case
+		 */
+		cache_revisit_request(item);
+
+	cache_limit_defers();
 }
 
 static void cache_revisit_request(struct cache_head *item)
 {
 	struct cache_deferred_req *dreq;
 	struct list_head pending;
-
-	struct list_head *lp;
+	struct hlist_node *lp, *tmp;
 	int hash = DFR_HASH(item);
 
 	INIT_LIST_HEAD(&pending);
 	spin_lock(&cache_defer_lock);
 
-	lp = cache_defer_hash[hash].next;
-	if (lp) {
-		while (lp != &cache_defer_hash[hash]) {
-			dreq = list_entry(lp, struct cache_deferred_req, hash);
-			lp = lp->next;
-			if (dreq->item == item) {
-				list_del_init(&dreq->hash);
-				list_move(&dreq->recent, &pending);
-				cache_defer_cnt--;
-			}
+	hlist_for_each_entry_safe(dreq, lp, tmp, &cache_defer_hash[hash], hash)
+		if (dreq->item == item) {
+			__unhash_deferred_req(dreq);
+			list_add(&dreq->recent, &pending);
 		}
-	}
+
 	spin_unlock(&cache_defer_lock);
 
 	while (!list_empty(&pending)) {
@@ -600,9 +676,8 @@
 
 	list_for_each_entry_safe(dreq, tmp, &cache_defer_list, recent) {
 		if (dreq->owner == owner) {
-			list_del_init(&dreq->hash);
-			list_move(&dreq->recent, &pending);
-			cache_defer_cnt--;
+			__unhash_deferred_req(dreq);
+			list_add(&dreq->recent, &pending);
 		}
 	}
 	spin_unlock(&cache_defer_lock);
@@ -901,7 +976,7 @@
 		filp->private_data = NULL;
 		kfree(rp);
 
-		cd->last_close = get_seconds();
+		cd->last_close = seconds_since_boot();
 		atomic_dec(&cd->readers);
 	}
 	module_put(cd->owner);
@@ -1014,6 +1089,23 @@
 	}
 }
 
+static bool cache_listeners_exist(struct cache_detail *detail)
+{
+	if (atomic_read(&detail->readers))
+		return true;
+	if (detail->last_close == 0)
+		/* This cache was never opened */
+		return false;
+	if (detail->last_close < seconds_since_boot() - 30)
+		/*
+		 * We allow for the possibility that someone might
+		 * restart a userspace daemon without restarting the
+		 * server; but after 30 seconds, we give up.
+		 */
+		 return false;
+	return true;
+}
+
 /*
  * register an upcall request to user-space and queue it up for read() by the
  * upcall daemon.
@@ -1032,10 +1124,9 @@
 	char *bp;
 	int len;
 
-	if (atomic_read(&detail->readers) == 0 &&
-	    detail->last_close < get_seconds() - 30) {
-			warn_no_listener(detail);
-			return -EINVAL;
+	if (!cache_listeners_exist(detail)) {
+		warn_no_listener(detail);
+		return -EINVAL;
 	}
 
 	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
@@ -1094,13 +1185,19 @@
 	if (bp[0] == '\\' && bp[1] == 'x') {
 		/* HEX STRING */
 		bp += 2;
-		while (isxdigit(bp[0]) && isxdigit(bp[1]) && len < bufsize) {
-			int byte = isdigit(*bp) ? *bp-'0' : toupper(*bp)-'A'+10;
-			bp++;
-			byte <<= 4;
-			byte |= isdigit(*bp) ? *bp-'0' : toupper(*bp)-'A'+10;
-			*dest++ = byte;
-			bp++;
+		while (len < bufsize) {
+			int h, l;
+
+			h = hex_to_bin(bp[0]);
+			if (h < 0)
+				break;
+
+			l = hex_to_bin(bp[1]);
+			if (l < 0)
+				break;
+
+			*dest++ = (h << 4) | l;
+			bp += 2;
 			len++;
 		}
 	} else {
@@ -1218,7 +1315,8 @@
 
 	ifdebug(CACHE)
 		seq_printf(m, "# expiry=%ld refcnt=%d flags=%lx\n",
-			   cp->expiry_time, atomic_read(&cp->ref.refcount), cp->flags);
+			   convert_to_wallclock(cp->expiry_time),
+			   atomic_read(&cp->ref.refcount), cp->flags);
 	cache_get(cp);
 	if (cache_check(cd, cp, NULL))
 		/* cache_check does a cache_put on failure */
@@ -1284,7 +1382,7 @@
 	unsigned long p = *ppos;
 	size_t len;
 
-	sprintf(tbuf, "%lu\n", cd->flush_time);
+	sprintf(tbuf, "%lu\n", convert_to_wallclock(cd->flush_time));
 	len = strlen(tbuf);
 	if (p >= len)
 		return 0;
@@ -1302,19 +1400,20 @@
 			   struct cache_detail *cd)
 {
 	char tbuf[20];
-	char *ep;
-	long flushtime;
+	char *bp, *ep;
+
 	if (*ppos || count > sizeof(tbuf)-1)
 		return -EINVAL;
 	if (copy_from_user(tbuf, buf, count))
 		return -EFAULT;
 	tbuf[count] = 0;
-	flushtime = simple_strtoul(tbuf, &ep, 0);
+	simple_strtoul(tbuf, &ep, 0);
 	if (*ep && *ep != '\n')
 		return -EINVAL;
 
-	cd->flush_time = flushtime;
-	cd->nextcheck = get_seconds();
+	bp = tbuf;
+	cd->flush_time = get_expiry(&bp);
+	cd->nextcheck = seconds_since_boot();
 	cache_flush();
 
 	*ppos += count;
@@ -1438,8 +1537,10 @@
 	.llseek		= no_llseek,
 };
 
-static void remove_cache_proc_entries(struct cache_detail *cd)
+static void remove_cache_proc_entries(struct cache_detail *cd, struct net *net)
 {
+	struct sunrpc_net *sn;
+
 	if (cd->u.procfs.proc_ent == NULL)
 		return;
 	if (cd->u.procfs.flush_ent)
@@ -1449,15 +1550,18 @@
 	if (cd->u.procfs.content_ent)
 		remove_proc_entry("content", cd->u.procfs.proc_ent);
 	cd->u.procfs.proc_ent = NULL;
-	remove_proc_entry(cd->name, proc_net_rpc);
+	sn = net_generic(net, sunrpc_net_id);
+	remove_proc_entry(cd->name, sn->proc_net_rpc);
 }
 
 #ifdef CONFIG_PROC_FS
-static int create_cache_proc_entries(struct cache_detail *cd)
+static int create_cache_proc_entries(struct cache_detail *cd, struct net *net)
 {
 	struct proc_dir_entry *p;
+	struct sunrpc_net *sn;
 
-	cd->u.procfs.proc_ent = proc_mkdir(cd->name, proc_net_rpc);
+	sn = net_generic(net, sunrpc_net_id);
+	cd->u.procfs.proc_ent = proc_mkdir(cd->name, sn->proc_net_rpc);
 	if (cd->u.procfs.proc_ent == NULL)
 		goto out_nomem;
 	cd->u.procfs.channel_ent = NULL;
@@ -1488,11 +1592,11 @@
 	}
 	return 0;
 out_nomem:
-	remove_cache_proc_entries(cd);
+	remove_cache_proc_entries(cd, net);
 	return -ENOMEM;
 }
 #else /* CONFIG_PROC_FS */
-static int create_cache_proc_entries(struct cache_detail *cd)
+static int create_cache_proc_entries(struct cache_detail *cd, struct net *net)
 {
 	return 0;
 }
@@ -1503,22 +1607,32 @@
 	INIT_DELAYED_WORK_DEFERRABLE(&cache_cleaner, do_cache_clean);
 }
 
-int cache_register(struct cache_detail *cd)
+int cache_register_net(struct cache_detail *cd, struct net *net)
 {
 	int ret;
 
 	sunrpc_init_cache_detail(cd);
-	ret = create_cache_proc_entries(cd);
+	ret = create_cache_proc_entries(cd, net);
 	if (ret)
 		sunrpc_destroy_cache_detail(cd);
 	return ret;
 }
+
+int cache_register(struct cache_detail *cd)
+{
+	return cache_register_net(cd, &init_net);
+}
 EXPORT_SYMBOL_GPL(cache_register);
 
+void cache_unregister_net(struct cache_detail *cd, struct net *net)
+{
+	remove_cache_proc_entries(cd, net);
+	sunrpc_destroy_cache_detail(cd);
+}
+
 void cache_unregister(struct cache_detail *cd)
 {
-	remove_cache_proc_entries(cd);
-	sunrpc_destroy_cache_detail(cd);
+	cache_unregister_net(cd, &init_net);
 }
 EXPORT_SYMBOL_GPL(cache_unregister);
 
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index fa55490..9dab957 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -284,6 +284,7 @@
 	struct rpc_xprt *xprt;
 	struct rpc_clnt *clnt;
 	struct xprt_create xprtargs = {
+		.net = args->net,
 		.ident = args->protocol,
 		.srcaddr = args->saddress,
 		.dstaddr = args->address,
@@ -1675,7 +1676,7 @@
 			rpcauth_invalcred(task);
 			/* Ensure we obtain a new XID! */
 			xprt_release(task);
-			task->tk_action = call_refresh;
+			task->tk_action = call_reserve;
 			goto out_retry;
 		case RPC_AUTH_BADCRED:
 		case RPC_AUTH_BADVERF:
diff --git a/net/sunrpc/netns.h b/net/sunrpc/netns.h
new file mode 100644
index 0000000..d013bf2
--- /dev/null
+++ b/net/sunrpc/netns.h
@@ -0,0 +1,19 @@
+#ifndef __SUNRPC_NETNS_H__
+#define __SUNRPC_NETNS_H__
+
+#include <net/net_namespace.h>
+#include <net/netns/generic.h>
+
+struct cache_detail;
+
+struct sunrpc_net {
+	struct proc_dir_entry *proc_net_rpc;
+	struct cache_detail *ip_map_cache;
+};
+
+extern int sunrpc_net_id;
+
+int ip_map_cache_create(struct net *);
+void ip_map_cache_destroy(struct net *);
+
+#endif
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index dac219a..fa6d7ca 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -177,6 +177,7 @@
 static int rpcb_create_local(void)
 {
 	struct rpc_create_args args = {
+		.net		= &init_net,
 		.protocol	= XPRT_TRANSPORT_TCP,
 		.address	= (struct sockaddr *)&rpcb_inaddr_loopback,
 		.addrsize	= sizeof(rpcb_inaddr_loopback),
@@ -211,8 +212,9 @@
 	 */
 	clnt4 = rpc_bind_new_program(clnt, &rpcb_program, RPCBVERS_4);
 	if (IS_ERR(clnt4)) {
-		dprintk("RPC:       failed to create local rpcbind v4 "
-				"cleint (errno %ld).\n", PTR_ERR(clnt4));
+		dprintk("RPC:       failed to bind second program to "
+				"rpcbind v4 client (errno %ld).\n",
+				PTR_ERR(clnt4));
 		clnt4 = NULL;
 	}
 
@@ -228,6 +230,7 @@
 				    size_t salen, int proto, u32 version)
 {
 	struct rpc_create_args args = {
+		.net		= &init_net,
 		.protocol	= proto,
 		.address	= srvaddr,
 		.addrsize	= salen,
@@ -247,7 +250,7 @@
 		((struct sockaddr_in6 *)srvaddr)->sin6_port = htons(RPCBIND_PORT);
 		break;
 	default:
-		return NULL;
+		return ERR_PTR(-EAFNOSUPPORT);
 	}
 
 	return rpc_create(&args);
@@ -475,57 +478,6 @@
 	return -EAFNOSUPPORT;
 }
 
-/**
- * rpcb_getport_sync - obtain the port for an RPC service on a given host
- * @sin: address of remote peer
- * @prog: RPC program number to bind
- * @vers: RPC version number to bind
- * @prot: transport protocol to use to make this request
- *
- * Return value is the requested advertised port number,
- * or a negative errno value.
- *
- * Called from outside the RPC client in a synchronous task context.
- * Uses default timeout parameters specified by underlying transport.
- *
- * XXX: Needs to support IPv6
- */
-int rpcb_getport_sync(struct sockaddr_in *sin, u32 prog, u32 vers, int prot)
-{
-	struct rpcbind_args map = {
-		.r_prog		= prog,
-		.r_vers		= vers,
-		.r_prot		= prot,
-		.r_port		= 0,
-	};
-	struct rpc_message msg = {
-		.rpc_proc	= &rpcb_procedures2[RPCBPROC_GETPORT],
-		.rpc_argp	= &map,
-		.rpc_resp	= &map,
-	};
-	struct rpc_clnt	*rpcb_clnt;
-	int status;
-
-	dprintk("RPC:       %s(%pI4, %u, %u, %d)\n",
-		__func__, &sin->sin_addr.s_addr, prog, vers, prot);
-
-	rpcb_clnt = rpcb_create(NULL, (struct sockaddr *)sin,
-				sizeof(*sin), prot, RPCBVERS_2);
-	if (IS_ERR(rpcb_clnt))
-		return PTR_ERR(rpcb_clnt);
-
-	status = rpc_call_sync(rpcb_clnt, &msg, 0);
-	rpc_shutdown_client(rpcb_clnt);
-
-	if (status >= 0) {
-		if (map.r_port != 0)
-			return map.r_port;
-		status = -EACCES;
-	}
-	return status;
-}
-EXPORT_SYMBOL_GPL(rpcb_getport_sync);
-
 static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbind_args *map, struct rpc_procinfo *proc)
 {
 	struct rpc_message msg = {
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index aa5dbda..243fc09 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -908,7 +908,7 @@
 	 * Create the rpciod thread and wait for it to start.
 	 */
 	dprintk("RPC:       creating workqueue rpciod\n");
-	wq = create_workqueue("rpciod");
+	wq = alloc_workqueue("rpciod", WQ_RESCUER, 0);
 	rpciod_workqueue = wq;
 	return rpciod_workqueue != NULL;
 }
diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c
index ea1046f..f71a731 100644
--- a/net/sunrpc/stats.c
+++ b/net/sunrpc/stats.c
@@ -22,12 +22,11 @@
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/svcsock.h>
 #include <linux/sunrpc/metrics.h>
-#include <net/net_namespace.h>
+
+#include "netns.h"
 
 #define RPCDBG_FACILITY	RPCDBG_MISC
 
-struct proc_dir_entry	*proc_net_rpc = NULL;
-
 /*
  * Get RPC client stats
  */
@@ -218,10 +217,11 @@
 static inline struct proc_dir_entry *
 do_register(const char *name, void *data, const struct file_operations *fops)
 {
-	rpc_proc_init();
-	dprintk("RPC:       registering /proc/net/rpc/%s\n", name);
+	struct sunrpc_net *sn;
 
-	return proc_create_data(name, 0, proc_net_rpc, fops, data);
+	dprintk("RPC:       registering /proc/net/rpc/%s\n", name);
+	sn = net_generic(&init_net, sunrpc_net_id);
+	return proc_create_data(name, 0, sn->proc_net_rpc, fops, data);
 }
 
 struct proc_dir_entry *
@@ -234,7 +234,10 @@
 void
 rpc_proc_unregister(const char *name)
 {
-	remove_proc_entry(name, proc_net_rpc);
+	struct sunrpc_net *sn;
+
+	sn = net_generic(&init_net, sunrpc_net_id);
+	remove_proc_entry(name, sn->proc_net_rpc);
 }
 EXPORT_SYMBOL_GPL(rpc_proc_unregister);
 
@@ -248,25 +251,29 @@
 void
 svc_proc_unregister(const char *name)
 {
-	remove_proc_entry(name, proc_net_rpc);
+	struct sunrpc_net *sn;
+
+	sn = net_generic(&init_net, sunrpc_net_id);
+	remove_proc_entry(name, sn->proc_net_rpc);
 }
 EXPORT_SYMBOL_GPL(svc_proc_unregister);
 
-void
-rpc_proc_init(void)
+int rpc_proc_init(struct net *net)
 {
+	struct sunrpc_net *sn;
+
 	dprintk("RPC:       registering /proc/net/rpc\n");
-	if (!proc_net_rpc)
-		proc_net_rpc = proc_mkdir("rpc", init_net.proc_net);
+	sn = net_generic(net, sunrpc_net_id);
+	sn->proc_net_rpc = proc_mkdir("rpc", net->proc_net);
+	if (sn->proc_net_rpc == NULL)
+		return -ENOMEM;
+
+	return 0;
 }
 
-void
-rpc_proc_exit(void)
+void rpc_proc_exit(struct net *net)
 {
 	dprintk("RPC:       unregistering /proc/net/rpc\n");
-	if (proc_net_rpc) {
-		proc_net_rpc = NULL;
-		remove_proc_entry("rpc", init_net.proc_net);
-	}
+	remove_proc_entry("rpc", net->proc_net);
 }
 
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index c0d0850..9d08091 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -22,7 +22,44 @@
 #include <linux/sunrpc/rpc_pipe_fs.h>
 #include <linux/sunrpc/xprtsock.h>
 
-extern struct cache_detail ip_map_cache, unix_gid_cache;
+#include "netns.h"
+
+int sunrpc_net_id;
+
+static __net_init int sunrpc_init_net(struct net *net)
+{
+	int err;
+
+	err = rpc_proc_init(net);
+	if (err)
+		goto err_proc;
+
+	err = ip_map_cache_create(net);
+	if (err)
+		goto err_ipmap;
+
+	return 0;
+
+err_ipmap:
+	rpc_proc_exit(net);
+err_proc:
+	return err;
+}
+
+static __net_exit void sunrpc_exit_net(struct net *net)
+{
+	ip_map_cache_destroy(net);
+	rpc_proc_exit(net);
+}
+
+static struct pernet_operations sunrpc_net_ops = {
+	.init = sunrpc_init_net,
+	.exit = sunrpc_exit_net,
+	.id = &sunrpc_net_id,
+	.size = sizeof(struct sunrpc_net),
+};
+
+extern struct cache_detail unix_gid_cache;
 
 extern void cleanup_rpcb_clnt(void);
 
@@ -38,18 +75,22 @@
 	err = rpcauth_init_module();
 	if (err)
 		goto out3;
+
+	cache_initialize();
+
+	err = register_pernet_subsys(&sunrpc_net_ops);
+	if (err)
+		goto out4;
 #ifdef RPC_DEBUG
 	rpc_register_sysctl();
 #endif
-#ifdef CONFIG_PROC_FS
-	rpc_proc_init();
-#endif
-	cache_initialize();
-	cache_register(&ip_map_cache);
 	cache_register(&unix_gid_cache);
 	svc_init_xprt_sock();	/* svc sock transport */
 	init_socket_xprt();	/* clnt sock transport */
 	return 0;
+
+out4:
+	rpcauth_remove_module();
 out3:
 	rpc_destroy_mempool();
 out2:
@@ -67,14 +108,11 @@
 	svc_cleanup_xprt_sock();
 	unregister_rpc_pipefs();
 	rpc_destroy_mempool();
-	cache_unregister(&ip_map_cache);
 	cache_unregister(&unix_gid_cache);
+	unregister_pernet_subsys(&sunrpc_net_ops);
 #ifdef RPC_DEBUG
 	rpc_unregister_sysctl();
 #endif
-#ifdef CONFIG_PROC_FS
-	rpc_proc_exit();
-#endif
 	rcu_barrier(); /* Wait for completion of call_rcu()'s */
 }
 MODULE_LICENSE("GPL");
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index d9017d6..6359c42 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -1055,6 +1055,9 @@
 		goto err_bad;
 	case SVC_DENIED:
 		goto err_bad_auth;
+	case SVC_CLOSE:
+		if (test_bit(XPT_TEMP, &rqstp->rq_xprt->xpt_flags))
+			svc_close_xprt(rqstp->rq_xprt);
 	case SVC_DROP:
 		goto dropit;
 	case SVC_COMPLETE:
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index cbc0849..c82fe73 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -100,16 +100,14 @@
  */
 int svc_print_xprts(char *buf, int maxlen)
 {
-	struct list_head *le;
+	struct svc_xprt_class *xcl;
 	char tmpstr[80];
 	int len = 0;
 	buf[0] = '\0';
 
 	spin_lock(&svc_xprt_class_lock);
-	list_for_each(le, &svc_xprt_class_list) {
+	list_for_each_entry(xcl, &svc_xprt_class_list, xcl_list) {
 		int slen;
-		struct svc_xprt_class *xcl =
-			list_entry(le, struct svc_xprt_class, xcl_list);
 
 		sprintf(tmpstr, "%s %d\n", xcl->xcl_name, xcl->xcl_max_payload);
 		slen = strlen(tmpstr);
@@ -128,9 +126,9 @@
 	struct svc_xprt *xprt =
 		container_of(kref, struct svc_xprt, xpt_ref);
 	struct module *owner = xprt->xpt_class->xcl_owner;
-	if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags) &&
-	    xprt->xpt_auth_cache != NULL)
-		svcauth_unix_info_release(xprt->xpt_auth_cache);
+	if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags))
+		svcauth_unix_info_release(xprt);
+	put_net(xprt->xpt_net);
 	xprt->xpt_ops->xpo_free(xprt);
 	module_put(owner);
 }
@@ -156,15 +154,18 @@
 	INIT_LIST_HEAD(&xprt->xpt_list);
 	INIT_LIST_HEAD(&xprt->xpt_ready);
 	INIT_LIST_HEAD(&xprt->xpt_deferred);
+	INIT_LIST_HEAD(&xprt->xpt_users);
 	mutex_init(&xprt->xpt_mutex);
 	spin_lock_init(&xprt->xpt_lock);
 	set_bit(XPT_BUSY, &xprt->xpt_flags);
 	rpc_init_wait_queue(&xprt->xpt_bc_pending, "xpt_bc_pending");
+	xprt->xpt_net = get_net(&init_net);
 }
 EXPORT_SYMBOL_GPL(svc_xprt_init);
 
 static struct svc_xprt *__svc_xpo_create(struct svc_xprt_class *xcl,
 					 struct svc_serv *serv,
+					 struct net *net,
 					 const int family,
 					 const unsigned short port,
 					 int flags)
@@ -199,12 +200,12 @@
 		return ERR_PTR(-EAFNOSUPPORT);
 	}
 
-	return xcl->xcl_ops->xpo_create(serv, sap, len, flags);
+	return xcl->xcl_ops->xpo_create(serv, net, sap, len, flags);
 }
 
 int svc_create_xprt(struct svc_serv *serv, const char *xprt_name,
-		    const int family, const unsigned short port,
-		    int flags)
+		    struct net *net, const int family,
+		    const unsigned short port, int flags)
 {
 	struct svc_xprt_class *xcl;
 
@@ -220,7 +221,7 @@
 			goto err;
 
 		spin_unlock(&svc_xprt_class_lock);
-		newxprt = __svc_xpo_create(xcl, serv, family, port, flags);
+		newxprt = __svc_xpo_create(xcl, serv, net, family, port, flags);
 		if (IS_ERR(newxprt)) {
 			module_put(xcl->xcl_owner);
 			return PTR_ERR(newxprt);
@@ -329,12 +330,6 @@
 		       "svc_xprt_enqueue: "
 		       "threads and transports both waiting??\n");
 
-	if (test_bit(XPT_DEAD, &xprt->xpt_flags)) {
-		/* Don't enqueue dead transports */
-		dprintk("svc: transport %p is dead, not enqueued\n", xprt);
-		goto out_unlock;
-	}
-
 	pool->sp_stats.packets++;
 
 	/* Mark transport as busy. It will remain in this state until
@@ -651,6 +646,11 @@
 	if (signalled() || kthread_should_stop())
 		return -EINTR;
 
+	/* Normally we will wait up to 5 seconds for any required
+	 * cache information to be provided.
+	 */
+	rqstp->rq_chandle.thread_wait = 5*HZ;
+
 	spin_lock_bh(&pool->sp_lock);
 	xprt = svc_xprt_dequeue(pool);
 	if (xprt) {
@@ -658,6 +658,12 @@
 		svc_xprt_get(xprt);
 		rqstp->rq_reserved = serv->sv_max_mesg;
 		atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved);
+
+		/* As there is a shortage of threads and this request
+		 * had to be queued, don't allow the thread to wait so
+		 * long for cache updates.
+		 */
+		rqstp->rq_chandle.thread_wait = 1*HZ;
 	} else {
 		/* No data pending. Go to sleep */
 		svc_thread_enqueue(pool, rqstp);
@@ -868,6 +874,19 @@
 	mod_timer(&serv->sv_temptimer, jiffies + svc_conn_age_period * HZ);
 }
 
+static void call_xpt_users(struct svc_xprt *xprt)
+{
+	struct svc_xpt_user *u;
+
+	spin_lock(&xprt->xpt_lock);
+	while (!list_empty(&xprt->xpt_users)) {
+		u = list_first_entry(&xprt->xpt_users, struct svc_xpt_user, list);
+		list_del(&u->list);
+		u->callback(u);
+	}
+	spin_unlock(&xprt->xpt_lock);
+}
+
 /*
  * Remove a dead transport
  */
@@ -878,7 +897,7 @@
 
 	/* Only do this once */
 	if (test_and_set_bit(XPT_DEAD, &xprt->xpt_flags))
-		return;
+		BUG();
 
 	dprintk("svc: svc_delete_xprt(%p)\n", xprt);
 	xprt->xpt_ops->xpo_detach(xprt);
@@ -900,6 +919,7 @@
 	while ((dr = svc_deferred_dequeue(xprt)) != NULL)
 		kfree(dr);
 
+	call_xpt_users(xprt);
 	svc_xprt_put(xprt);
 }
 
@@ -910,10 +930,7 @@
 		/* someone else will have to effect the close */
 		return;
 
-	svc_xprt_get(xprt);
 	svc_delete_xprt(xprt);
-	clear_bit(XPT_BUSY, &xprt->xpt_flags);
-	svc_xprt_put(xprt);
 }
 EXPORT_SYMBOL_GPL(svc_close_xprt);
 
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 2073116..560677d 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -18,6 +18,8 @@
 
 #include <linux/sunrpc/clnt.h>
 
+#include "netns.h"
+
 /*
  * AUTHUNIX and AUTHNULL credentials are both handled here.
  * AUTHNULL is treated just like AUTHUNIX except that the uid/gid
@@ -92,7 +94,6 @@
 	struct unix_domain	*m_client;
 	int			m_add_change;
 };
-static struct cache_head	*ip_table[IP_HASHMAX];
 
 static void ip_map_put(struct kref *kref)
 {
@@ -178,8 +179,8 @@
 	return sunrpc_cache_pipe_upcall(cd, h, ip_map_request);
 }
 
-static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr);
-static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t expiry);
+static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class, struct in6_addr *addr);
+static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm, struct unix_domain *udom, time_t expiry);
 
 static int ip_map_parse(struct cache_detail *cd,
 			  char *mesg, int mlen)
@@ -219,10 +220,9 @@
 	switch (address.sa.sa_family) {
 	case AF_INET:
 		/* Form a mapped IPv4 address in sin6 */
-		memset(&sin6, 0, sizeof(sin6));
 		sin6.sin6_family = AF_INET6;
-		sin6.sin6_addr.s6_addr32[2] = htonl(0xffff);
-		sin6.sin6_addr.s6_addr32[3] = address.s4.sin_addr.s_addr;
+		ipv6_addr_set_v4mapped(address.s4.sin_addr.s_addr,
+				&sin6.sin6_addr);
 		break;
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	case AF_INET6:
@@ -249,9 +249,9 @@
 		dom = NULL;
 
 	/* IPv6 scope IDs are ignored for now */
-	ipmp = ip_map_lookup(class, &sin6.sin6_addr);
+	ipmp = __ip_map_lookup(cd, class, &sin6.sin6_addr);
 	if (ipmp) {
-		err = ip_map_update(ipmp,
+		err = __ip_map_update(cd, ipmp,
 			     container_of(dom, struct unix_domain, h),
 			     expiry);
 	} else
@@ -294,29 +294,15 @@
 }
 
 
-struct cache_detail ip_map_cache = {
-	.owner		= THIS_MODULE,
-	.hash_size	= IP_HASHMAX,
-	.hash_table	= ip_table,
-	.name		= "auth.unix.ip",
-	.cache_put	= ip_map_put,
-	.cache_upcall	= ip_map_upcall,
-	.cache_parse	= ip_map_parse,
-	.cache_show	= ip_map_show,
-	.match		= ip_map_match,
-	.init		= ip_map_init,
-	.update		= update,
-	.alloc		= ip_map_alloc,
-};
-
-static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr)
+static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class,
+		struct in6_addr *addr)
 {
 	struct ip_map ip;
 	struct cache_head *ch;
 
 	strcpy(ip.m_class, class);
 	ipv6_addr_copy(&ip.m_addr, addr);
-	ch = sunrpc_cache_lookup(&ip_map_cache, &ip.h,
+	ch = sunrpc_cache_lookup(cd, &ip.h,
 				 hash_str(class, IP_HASHBITS) ^
 				 hash_ip6(*addr));
 
@@ -326,7 +312,17 @@
 		return NULL;
 }
 
-static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t expiry)
+static inline struct ip_map *ip_map_lookup(struct net *net, char *class,
+		struct in6_addr *addr)
+{
+	struct sunrpc_net *sn;
+
+	sn = net_generic(net, sunrpc_net_id);
+	return __ip_map_lookup(sn->ip_map_cache, class, addr);
+}
+
+static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm,
+		struct unix_domain *udom, time_t expiry)
 {
 	struct ip_map ip;
 	struct cache_head *ch;
@@ -344,17 +340,25 @@
 			ip.m_add_change++;
 	}
 	ip.h.expiry_time = expiry;
-	ch = sunrpc_cache_update(&ip_map_cache,
-				 &ip.h, &ipm->h,
+	ch = sunrpc_cache_update(cd, &ip.h, &ipm->h,
 				 hash_str(ipm->m_class, IP_HASHBITS) ^
 				 hash_ip6(ipm->m_addr));
 	if (!ch)
 		return -ENOMEM;
-	cache_put(ch, &ip_map_cache);
+	cache_put(ch, cd);
 	return 0;
 }
 
-int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain *dom)
+static inline int ip_map_update(struct net *net, struct ip_map *ipm,
+		struct unix_domain *udom, time_t expiry)
+{
+	struct sunrpc_net *sn;
+
+	sn = net_generic(net, sunrpc_net_id);
+	return __ip_map_update(sn->ip_map_cache, ipm, udom, expiry);
+}
+
+int auth_unix_add_addr(struct net *net, struct in6_addr *addr, struct auth_domain *dom)
 {
 	struct unix_domain *udom;
 	struct ip_map *ipmp;
@@ -362,10 +366,10 @@
 	if (dom->flavour != &svcauth_unix)
 		return -EINVAL;
 	udom = container_of(dom, struct unix_domain, h);
-	ipmp = ip_map_lookup("nfsd", addr);
+	ipmp = ip_map_lookup(net, "nfsd", addr);
 
 	if (ipmp)
-		return ip_map_update(ipmp, udom, NEVER);
+		return ip_map_update(net, ipmp, udom, NEVER);
 	else
 		return -ENOMEM;
 }
@@ -383,16 +387,18 @@
 }
 EXPORT_SYMBOL_GPL(auth_unix_forget_old);
 
-struct auth_domain *auth_unix_lookup(struct in6_addr *addr)
+struct auth_domain *auth_unix_lookup(struct net *net, struct in6_addr *addr)
 {
 	struct ip_map *ipm;
 	struct auth_domain *rv;
+	struct sunrpc_net *sn;
 
-	ipm = ip_map_lookup("nfsd", addr);
+	sn = net_generic(net, sunrpc_net_id);
+	ipm = ip_map_lookup(net, "nfsd", addr);
 
 	if (!ipm)
 		return NULL;
-	if (cache_check(&ip_map_cache, &ipm->h, NULL))
+	if (cache_check(sn->ip_map_cache, &ipm->h, NULL))
 		return NULL;
 
 	if ((ipm->m_client->addr_changes - ipm->m_add_change) >0) {
@@ -403,22 +409,29 @@
 		rv = &ipm->m_client->h;
 		kref_get(&rv->ref);
 	}
-	cache_put(&ipm->h, &ip_map_cache);
+	cache_put(&ipm->h, sn->ip_map_cache);
 	return rv;
 }
 EXPORT_SYMBOL_GPL(auth_unix_lookup);
 
 void svcauth_unix_purge(void)
 {
-	cache_purge(&ip_map_cache);
+	struct net *net;
+
+	for_each_net(net) {
+		struct sunrpc_net *sn;
+
+		sn = net_generic(net, sunrpc_net_id);
+		cache_purge(sn->ip_map_cache);
+	}
 }
 EXPORT_SYMBOL_GPL(svcauth_unix_purge);
 
 static inline struct ip_map *
-ip_map_cached_get(struct svc_rqst *rqstp)
+ip_map_cached_get(struct svc_xprt *xprt)
 {
 	struct ip_map *ipm = NULL;
-	struct svc_xprt *xprt = rqstp->rq_xprt;
+	struct sunrpc_net *sn;
 
 	if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) {
 		spin_lock(&xprt->xpt_lock);
@@ -430,9 +443,10 @@
 				 * remembered, e.g. by a second mount from the
 				 * same IP address.
 				 */
+				sn = net_generic(xprt->xpt_net, sunrpc_net_id);
 				xprt->xpt_auth_cache = NULL;
 				spin_unlock(&xprt->xpt_lock);
-				cache_put(&ipm->h, &ip_map_cache);
+				cache_put(&ipm->h, sn->ip_map_cache);
 				return NULL;
 			}
 			cache_get(&ipm->h);
@@ -443,10 +457,8 @@
 }
 
 static inline void
-ip_map_cached_put(struct svc_rqst *rqstp, struct ip_map *ipm)
+ip_map_cached_put(struct svc_xprt *xprt, struct ip_map *ipm)
 {
-	struct svc_xprt *xprt = rqstp->rq_xprt;
-
 	if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) {
 		spin_lock(&xprt->xpt_lock);
 		if (xprt->xpt_auth_cache == NULL) {
@@ -456,15 +468,26 @@
 		}
 		spin_unlock(&xprt->xpt_lock);
 	}
-	if (ipm)
-		cache_put(&ipm->h, &ip_map_cache);
+	if (ipm) {
+		struct sunrpc_net *sn;
+
+		sn = net_generic(xprt->xpt_net, sunrpc_net_id);
+		cache_put(&ipm->h, sn->ip_map_cache);
+	}
 }
 
 void
-svcauth_unix_info_release(void *info)
+svcauth_unix_info_release(struct svc_xprt *xpt)
 {
-	struct ip_map *ipm = info;
-	cache_put(&ipm->h, &ip_map_cache);
+	struct ip_map *ipm;
+
+	ipm = xpt->xpt_auth_cache;
+	if (ipm != NULL) {
+		struct sunrpc_net *sn;
+
+		sn = net_generic(xpt->xpt_net, sunrpc_net_id);
+		cache_put(&ipm->h, sn->ip_map_cache);
+	}
 }
 
 /****************************************************************************
@@ -674,6 +697,8 @@
 	switch (ret) {
 	case -ENOENT:
 		return ERR_PTR(-ENOENT);
+	case -ETIMEDOUT:
+		return ERR_PTR(-ESHUTDOWN);
 	case 0:
 		gi = get_group_info(ug->gi);
 		cache_put(&ug->h, &unix_gid_cache);
@@ -691,6 +716,9 @@
 	struct ip_map *ipm;
 	struct group_info *gi;
 	struct svc_cred *cred = &rqstp->rq_cred;
+	struct svc_xprt *xprt = rqstp->rq_xprt;
+	struct net *net = xprt->xpt_net;
+	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
 
 	switch (rqstp->rq_addr.ss_family) {
 	case AF_INET:
@@ -709,26 +737,27 @@
 	if (rqstp->rq_proc == 0)
 		return SVC_OK;
 
-	ipm = ip_map_cached_get(rqstp);
+	ipm = ip_map_cached_get(xprt);
 	if (ipm == NULL)
-		ipm = ip_map_lookup(rqstp->rq_server->sv_program->pg_class,
+		ipm = __ip_map_lookup(sn->ip_map_cache, rqstp->rq_server->sv_program->pg_class,
 				    &sin6->sin6_addr);
 
 	if (ipm == NULL)
 		return SVC_DENIED;
 
-	switch (cache_check(&ip_map_cache, &ipm->h, &rqstp->rq_chandle)) {
+	switch (cache_check(sn->ip_map_cache, &ipm->h, &rqstp->rq_chandle)) {
 		default:
 			BUG();
-		case -EAGAIN:
 		case -ETIMEDOUT:
+			return SVC_CLOSE;
+		case -EAGAIN:
 			return SVC_DROP;
 		case -ENOENT:
 			return SVC_DENIED;
 		case 0:
 			rqstp->rq_client = &ipm->m_client->h;
 			kref_get(&rqstp->rq_client->ref);
-			ip_map_cached_put(rqstp, ipm);
+			ip_map_cached_put(xprt, ipm);
 			break;
 	}
 
@@ -736,6 +765,8 @@
 	switch (PTR_ERR(gi)) {
 	case -EAGAIN:
 		return SVC_DROP;
+	case -ESHUTDOWN:
+		return SVC_CLOSE;
 	case -ENOENT:
 		break;
 	default:
@@ -776,7 +807,7 @@
 	cred->cr_gid = (gid_t) -1;
 	cred->cr_group_info = groups_alloc(0);
 	if (cred->cr_group_info == NULL)
-		return SVC_DROP; /* kmalloc failure - client must retry */
+		return SVC_CLOSE; /* kmalloc failure - client must retry */
 
 	/* Put NULL verifier */
 	svc_putnl(resv, RPC_AUTH_NULL);
@@ -840,7 +871,7 @@
 		goto badcred;
 	cred->cr_group_info = groups_alloc(slen);
 	if (cred->cr_group_info == NULL)
-		return SVC_DROP;
+		return SVC_CLOSE;
 	for (i = 0; i < slen; i++)
 		GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv);
 	if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) {
@@ -886,3 +917,56 @@
 	.set_client	= svcauth_unix_set_client,
 };
 
+int ip_map_cache_create(struct net *net)
+{
+	int err = -ENOMEM;
+	struct cache_detail *cd;
+	struct cache_head **tbl;
+	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
+
+	cd = kzalloc(sizeof(struct cache_detail), GFP_KERNEL);
+	if (cd == NULL)
+		goto err_cd;
+
+	tbl = kzalloc(IP_HASHMAX * sizeof(struct cache_head *), GFP_KERNEL);
+	if (tbl == NULL)
+		goto err_tbl;
+
+	cd->owner = THIS_MODULE,
+	cd->hash_size = IP_HASHMAX,
+	cd->hash_table = tbl,
+	cd->name = "auth.unix.ip",
+	cd->cache_put = ip_map_put,
+	cd->cache_upcall = ip_map_upcall,
+	cd->cache_parse = ip_map_parse,
+	cd->cache_show = ip_map_show,
+	cd->match = ip_map_match,
+	cd->init = ip_map_init,
+	cd->update = update,
+	cd->alloc = ip_map_alloc,
+
+	err = cache_register_net(cd, net);
+	if (err)
+		goto err_reg;
+
+	sn->ip_map_cache = cd;
+	return 0;
+
+err_reg:
+	kfree(tbl);
+err_tbl:
+	kfree(cd);
+err_cd:
+	return err;
+}
+
+void ip_map_cache_destroy(struct net *net)
+{
+	struct sunrpc_net *sn;
+
+	sn = net_generic(net, sunrpc_net_id);
+	cache_purge(sn->ip_map_cache);
+	cache_unregister_net(sn->ip_map_cache, net);
+	kfree(sn->ip_map_cache->hash_table);
+	kfree(sn->ip_map_cache);
+}
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 7e534dd..07919e1 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -64,7 +64,8 @@
 static void		svc_sock_free(struct svc_xprt *);
 
 static struct svc_xprt *svc_create_socket(struct svc_serv *, int,
-					  struct sockaddr *, int, int);
+					  struct net *, struct sockaddr *,
+					  int, int);
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 static struct lock_class_key svc_key[2];
 static struct lock_class_key svc_slock_key[2];
@@ -657,10 +658,11 @@
 }
 
 static struct svc_xprt *svc_udp_create(struct svc_serv *serv,
+				       struct net *net,
 				       struct sockaddr *sa, int salen,
 				       int flags)
 {
-	return svc_create_socket(serv, IPPROTO_UDP, sa, salen, flags);
+	return svc_create_socket(serv, IPPROTO_UDP, net, sa, salen, flags);
 }
 
 static struct svc_xprt_ops svc_udp_ops = {
@@ -1133,9 +1135,6 @@
 	reclen = htonl(0x80000000|((xbufp->len ) - 4));
 	memcpy(xbufp->head[0].iov_base, &reclen, 4);
 
-	if (test_bit(XPT_DEAD, &rqstp->rq_xprt->xpt_flags))
-		return -ENOTCONN;
-
 	sent = svc_sendto(rqstp, &rqstp->rq_res);
 	if (sent != xbufp->len) {
 		printk(KERN_NOTICE
@@ -1178,10 +1177,11 @@
 }
 
 static struct svc_xprt *svc_tcp_create(struct svc_serv *serv,
+				       struct net *net,
 				       struct sockaddr *sa, int salen,
 				       int flags)
 {
-	return svc_create_socket(serv, IPPROTO_TCP, sa, salen, flags);
+	return svc_create_socket(serv, IPPROTO_TCP, net, sa, salen, flags);
 }
 
 static struct svc_xprt_ops svc_tcp_ops = {
@@ -1258,19 +1258,13 @@
 	 * The number of server threads has changed. Update
 	 * rcvbuf and sndbuf accordingly on all sockets
 	 */
-	struct list_head *le;
+	struct svc_sock *svsk;
 
 	spin_lock_bh(&serv->sv_lock);
-	list_for_each(le, &serv->sv_permsocks) {
-		struct svc_sock *svsk =
-			list_entry(le, struct svc_sock, sk_xprt.xpt_list);
+	list_for_each_entry(svsk, &serv->sv_permsocks, sk_xprt.xpt_list)
 		set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags);
-	}
-	list_for_each(le, &serv->sv_tempsocks) {
-		struct svc_sock *svsk =
-			list_entry(le, struct svc_sock, sk_xprt.xpt_list);
+	list_for_each_entry(svsk, &serv->sv_tempsocks, sk_xprt.xpt_list)
 		set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags);
-	}
 	spin_unlock_bh(&serv->sv_lock);
 }
 EXPORT_SYMBOL_GPL(svc_sock_update_bufs);
@@ -1385,6 +1379,7 @@
  */
 static struct svc_xprt *svc_create_socket(struct svc_serv *serv,
 					  int protocol,
+					  struct net *net,
 					  struct sockaddr *sin, int len,
 					  int flags)
 {
@@ -1421,7 +1416,7 @@
 		return ERR_PTR(-EINVAL);
 	}
 
-	error = sock_create_kern(family, type, protocol, &sock);
+	error = __sock_create(net, family, type, protocol, &sock, 1);
 	if (error < 0)
 		return ERR_PTR(error);
 
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c
index a1f82a8..cd9e841 100644
--- a/net/sunrpc/xdr.c
+++ b/net/sunrpc/xdr.c
@@ -111,6 +111,23 @@
 }
 EXPORT_SYMBOL_GPL(xdr_decode_string_inplace);
 
+/**
+ * xdr_terminate_string - '\0'-terminate a string residing in an xdr_buf
+ * @buf: XDR buffer where string resides
+ * @len: length of string, in bytes
+ *
+ */
+void
+xdr_terminate_string(struct xdr_buf *buf, const u32 len)
+{
+	char *kaddr;
+
+	kaddr = kmap_atomic(buf->pages[0], KM_USER0);
+	kaddr[buf->page_base + len] = '\0';
+	kunmap_atomic(kaddr, KM_USER0);
+}
+EXPORT_SYMBOL(xdr_terminate_string);
+
 void
 xdr_encode_pages(struct xdr_buf *xdr, struct page **pages, unsigned int base,
 		 unsigned int len)
@@ -395,24 +412,29 @@
 {
 	struct kvec *tail;
 	size_t copy;
-	char *p;
 	unsigned int pglen = buf->page_len;
+	unsigned int tailbuf_len;
 
 	tail = buf->tail;
 	BUG_ON (len > pglen);
 
+	tailbuf_len = buf->buflen - buf->head->iov_len - buf->page_len;
+
 	/* Shift the tail first */
-	if (tail->iov_len != 0) {
-		p = (char *)tail->iov_base + len;
-		if (tail->iov_len > len) {
-			copy = tail->iov_len - len;
-			memmove(p, tail->iov_base, copy);
-		} else
-			buf->buflen -= len;
-		/* Copy from the inlined pages into the tail */
+	if (tailbuf_len != 0) {
+		unsigned int free_space = tailbuf_len - tail->iov_len;
+
+		if (len < free_space)
+			free_space = len;
+		tail->iov_len += free_space;
+
 		copy = len;
-		if (copy > tail->iov_len)
+		if (tail->iov_len > len) {
+			char *p = (char *)tail->iov_base + len;
+			memmove(p, tail->iov_base, tail->iov_len - len);
+		} else
 			copy = tail->iov_len;
+		/* Copy from the inlined pages into the tail */
 		_copy_from_pages((char *)tail->iov_base,
 				buf->pages, buf->page_base + pglen - len,
 				copy);
@@ -551,6 +573,27 @@
 EXPORT_SYMBOL_GPL(xdr_init_decode);
 
 /**
+ * xdr_inline_peek - Allow read-ahead in the XDR data stream
+ * @xdr: pointer to xdr_stream struct
+ * @nbytes: number of bytes of data to decode
+ *
+ * Check if the input buffer is long enough to enable us to decode
+ * 'nbytes' more bytes of data starting at the current position.
+ * If so return the current pointer without updating the current
+ * pointer position.
+ */
+__be32 * xdr_inline_peek(struct xdr_stream *xdr, size_t nbytes)
+{
+	__be32 *p = xdr->p;
+	__be32 *q = p + XDR_QUADLEN(nbytes);
+
+	if (unlikely(q > xdr->end || q < p))
+		return NULL;
+	return p;
+}
+EXPORT_SYMBOL_GPL(xdr_inline_peek);
+
+/**
  * xdr_inline_decode - Retrieve non-page XDR data to decode
  * @xdr: pointer to xdr_stream struct
  * @nbytes: number of bytes of data to decode
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 970fb00..4c8f18a 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -199,8 +199,6 @@
 	if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) {
 		if (task == xprt->snd_task)
 			return 1;
-		if (task == NULL)
-			return 0;
 		goto out_sleep;
 	}
 	xprt->snd_task = task;
@@ -757,13 +755,11 @@
  */
 struct rpc_rqst *xprt_lookup_rqst(struct rpc_xprt *xprt, __be32 xid)
 {
-	struct list_head *pos;
+	struct rpc_rqst *entry;
 
-	list_for_each(pos, &xprt->recv) {
-		struct rpc_rqst *entry = list_entry(pos, struct rpc_rqst, rq_list);
+	list_for_each_entry(entry, &xprt->recv, rq_list)
 		if (entry->rq_xid == xid)
 			return entry;
-	}
 
 	dprintk("RPC:       xprt_lookup_rqst did not find xid %08x\n",
 			ntohl(xid));
@@ -962,6 +958,37 @@
 	spin_unlock(&xprt->reserve_lock);
 }
 
+struct rpc_xprt *xprt_alloc(struct net *net, int size, int max_req)
+{
+	struct rpc_xprt *xprt;
+
+	xprt = kzalloc(size, GFP_KERNEL);
+	if (xprt == NULL)
+		goto out;
+
+	xprt->max_reqs = max_req;
+	xprt->slot = kcalloc(max_req, sizeof(struct rpc_rqst), GFP_KERNEL);
+	if (xprt->slot == NULL)
+		goto out_free;
+
+	xprt->xprt_net = get_net(net);
+	return xprt;
+
+out_free:
+	kfree(xprt);
+out:
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(xprt_alloc);
+
+void xprt_free(struct rpc_xprt *xprt)
+{
+	put_net(xprt->xprt_net);
+	kfree(xprt->slot);
+	kfree(xprt);
+}
+EXPORT_SYMBOL_GPL(xprt_free);
+
 /**
  * xprt_reserve - allocate an RPC request slot
  * @task: RPC task requesting a slot allocation
diff --git a/net/sunrpc/xprtrdma/svc_rdma.c b/net/sunrpc/xprtrdma/svc_rdma.c
index d718b8f..09af4fa 100644
--- a/net/sunrpc/xprtrdma/svc_rdma.c
+++ b/net/sunrpc/xprtrdma/svc_rdma.c
@@ -43,6 +43,7 @@
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/sysctl.h>
+#include <linux/workqueue.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/sched.h>
 #include <linux/sunrpc/svc_rdma.h>
@@ -74,6 +75,8 @@
 struct kmem_cache *svc_rdma_map_cachep;
 struct kmem_cache *svc_rdma_ctxt_cachep;
 
+struct workqueue_struct *svc_rdma_wq;
+
 /*
  * This function implements reading and resetting an atomic_t stat
  * variable through read/write to a proc file. Any write to the file
@@ -231,7 +234,7 @@
 void svc_rdma_cleanup(void)
 {
 	dprintk("SVCRDMA Module Removed, deregister RPC RDMA transport\n");
-	flush_scheduled_work();
+	destroy_workqueue(svc_rdma_wq);
 	if (svcrdma_table_header) {
 		unregister_sysctl_table(svcrdma_table_header);
 		svcrdma_table_header = NULL;
@@ -249,6 +252,11 @@
 	dprintk("\tsq_depth         : %d\n",
 		svcrdma_max_requests * RPCRDMA_SQ_DEPTH_MULT);
 	dprintk("\tmax_inline       : %d\n", svcrdma_max_req_size);
+
+	svc_rdma_wq = alloc_workqueue("svc_rdma", 0, 0);
+	if (!svc_rdma_wq)
+		return -ENOMEM;
+
 	if (!svcrdma_table_header)
 		svcrdma_table_header =
 			register_sysctl_table(svcrdma_root_table);
@@ -283,6 +291,7 @@
 	kmem_cache_destroy(svc_rdma_map_cachep);
  err0:
 	unregister_sysctl_table(svcrdma_table_header);
+	destroy_workqueue(svc_rdma_wq);
 	return -ENOMEM;
 }
 MODULE_AUTHOR("Tom Tucker <tom@opengridcomputing.com>");
diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
index 0194de8..df67211 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
@@ -263,9 +263,9 @@
 	frmr->page_list_len = PAGE_ALIGN(byte_count) >> PAGE_SHIFT;
 	for (page_no = 0; page_no < frmr->page_list_len; page_no++) {
 		frmr->page_list->page_list[page_no] =
-			ib_dma_map_single(xprt->sc_cm_id->device,
-					  page_address(rqstp->rq_arg.pages[page_no]),
-					  PAGE_SIZE, DMA_FROM_DEVICE);
+			ib_dma_map_page(xprt->sc_cm_id->device,
+					rqstp->rq_arg.pages[page_no], 0,
+					PAGE_SIZE, DMA_FROM_DEVICE);
 		if (ib_dma_mapping_error(xprt->sc_cm_id->device,
 					 frmr->page_list->page_list[page_no]))
 			goto fatal_err;
@@ -309,17 +309,21 @@
 			     int count)
 {
 	int i;
+	unsigned long off;
 
 	ctxt->count = count;
 	ctxt->direction = DMA_FROM_DEVICE;
 	for (i = 0; i < count; i++) {
 		ctxt->sge[i].length = 0; /* in case map fails */
 		if (!frmr) {
+			BUG_ON(0 == virt_to_page(vec[i].iov_base));
+			off = (unsigned long)vec[i].iov_base & ~PAGE_MASK;
 			ctxt->sge[i].addr =
-				ib_dma_map_single(xprt->sc_cm_id->device,
-						  vec[i].iov_base,
-						  vec[i].iov_len,
-						  DMA_FROM_DEVICE);
+				ib_dma_map_page(xprt->sc_cm_id->device,
+						virt_to_page(vec[i].iov_base),
+						off,
+						vec[i].iov_len,
+						DMA_FROM_DEVICE);
 			if (ib_dma_mapping_error(xprt->sc_cm_id->device,
 						 ctxt->sge[i].addr))
 				return -EINVAL;
@@ -491,6 +495,7 @@
 			printk(KERN_ERR "svcrdma: Error %d posting RDMA_READ\n",
 			       err);
 			set_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags);
+			svc_rdma_unmap_dma(ctxt);
 			svc_rdma_put_context(ctxt, 0);
 			goto out;
 		}
diff --git a/net/sunrpc/xprtrdma/svc_rdma_sendto.c b/net/sunrpc/xprtrdma/svc_rdma_sendto.c
index b15e1eb..249a835 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_sendto.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_sendto.c
@@ -70,8 +70,8 @@
  * on extra page for the RPCRMDA header.
  */
 static int fast_reg_xdr(struct svcxprt_rdma *xprt,
-		 struct xdr_buf *xdr,
-		 struct svc_rdma_req_map *vec)
+			struct xdr_buf *xdr,
+			struct svc_rdma_req_map *vec)
 {
 	int sge_no;
 	u32 sge_bytes;
@@ -96,21 +96,25 @@
 	vec->count = 2;
 	sge_no++;
 
-	/* Build the FRMR */
+	/* Map the XDR head */
 	frmr->kva = frva;
 	frmr->direction = DMA_TO_DEVICE;
 	frmr->access_flags = 0;
 	frmr->map_len = PAGE_SIZE;
 	frmr->page_list_len = 1;
+	page_off = (unsigned long)xdr->head[0].iov_base & ~PAGE_MASK;
 	frmr->page_list->page_list[page_no] =
-		ib_dma_map_single(xprt->sc_cm_id->device,
-				  (void *)xdr->head[0].iov_base,
-				  PAGE_SIZE, DMA_TO_DEVICE);
+		ib_dma_map_page(xprt->sc_cm_id->device,
+				virt_to_page(xdr->head[0].iov_base),
+				page_off,
+				PAGE_SIZE - page_off,
+				DMA_TO_DEVICE);
 	if (ib_dma_mapping_error(xprt->sc_cm_id->device,
 				 frmr->page_list->page_list[page_no]))
 		goto fatal_err;
 	atomic_inc(&xprt->sc_dma_used);
 
+	/* Map the XDR page list */
 	page_off = xdr->page_base;
 	page_bytes = xdr->page_len + page_off;
 	if (!page_bytes)
@@ -128,9 +132,9 @@
 		page_bytes -= sge_bytes;
 
 		frmr->page_list->page_list[page_no] =
-			ib_dma_map_single(xprt->sc_cm_id->device,
-					  page_address(page),
-					  PAGE_SIZE, DMA_TO_DEVICE);
+			ib_dma_map_page(xprt->sc_cm_id->device,
+					page, page_off,
+					sge_bytes, DMA_TO_DEVICE);
 		if (ib_dma_mapping_error(xprt->sc_cm_id->device,
 					 frmr->page_list->page_list[page_no]))
 			goto fatal_err;
@@ -166,8 +170,10 @@
 		vec->sge[sge_no].iov_base = frva + frmr->map_len + page_off;
 
 		frmr->page_list->page_list[page_no] =
-			ib_dma_map_single(xprt->sc_cm_id->device, va, PAGE_SIZE,
-					  DMA_TO_DEVICE);
+		    ib_dma_map_page(xprt->sc_cm_id->device, virt_to_page(va),
+				    page_off,
+				    PAGE_SIZE,
+				    DMA_TO_DEVICE);
 		if (ib_dma_mapping_error(xprt->sc_cm_id->device,
 					 frmr->page_list->page_list[page_no]))
 			goto fatal_err;
@@ -245,6 +251,35 @@
 	return 0;
 }
 
+static dma_addr_t dma_map_xdr(struct svcxprt_rdma *xprt,
+			      struct xdr_buf *xdr,
+			      u32 xdr_off, size_t len, int dir)
+{
+	struct page *page;
+	dma_addr_t dma_addr;
+	if (xdr_off < xdr->head[0].iov_len) {
+		/* This offset is in the head */
+		xdr_off += (unsigned long)xdr->head[0].iov_base & ~PAGE_MASK;
+		page = virt_to_page(xdr->head[0].iov_base);
+	} else {
+		xdr_off -= xdr->head[0].iov_len;
+		if (xdr_off < xdr->page_len) {
+			/* This offset is in the page list */
+			page = xdr->pages[xdr_off >> PAGE_SHIFT];
+			xdr_off &= ~PAGE_MASK;
+		} else {
+			/* This offset is in the tail */
+			xdr_off -= xdr->page_len;
+			xdr_off += (unsigned long)
+				xdr->tail[0].iov_base & ~PAGE_MASK;
+			page = virt_to_page(xdr->tail[0].iov_base);
+		}
+	}
+	dma_addr = ib_dma_map_page(xprt->sc_cm_id->device, page, xdr_off,
+				   min_t(size_t, PAGE_SIZE, len), dir);
+	return dma_addr;
+}
+
 /* Assumptions:
  * - We are using FRMR
  *     - or -
@@ -293,10 +328,9 @@
 		sge[sge_no].length = sge_bytes;
 		if (!vec->frmr) {
 			sge[sge_no].addr =
-				ib_dma_map_single(xprt->sc_cm_id->device,
-						  (void *)
-						  vec->sge[xdr_sge_no].iov_base + sge_off,
-						  sge_bytes, DMA_TO_DEVICE);
+				dma_map_xdr(xprt, &rqstp->rq_res, xdr_off,
+					    sge_bytes, DMA_TO_DEVICE);
+			xdr_off += sge_bytes;
 			if (ib_dma_mapping_error(xprt->sc_cm_id->device,
 						 sge[sge_no].addr))
 				goto err;
@@ -333,6 +367,8 @@
 		goto err;
 	return 0;
  err:
+	svc_rdma_unmap_dma(ctxt);
+	svc_rdma_put_frmr(xprt, vec->frmr);
 	svc_rdma_put_context(ctxt, 0);
 	/* Fatal error, close transport */
 	return -EIO;
@@ -494,7 +530,8 @@
  * In all three cases, this function prepares the RPCRDMA header in
  * sge[0], the 'type' parameter indicates the type to place in the
  * RPCRDMA header, and the 'byte_count' field indicates how much of
- * the XDR to include in this RDMA_SEND.
+ * the XDR to include in this RDMA_SEND. NB: The offset of the payload
+ * to send is zero in the XDR.
  */
 static int send_reply(struct svcxprt_rdma *rdma,
 		      struct svc_rqst *rqstp,
@@ -536,23 +573,24 @@
 	ctxt->sge[0].lkey = rdma->sc_dma_lkey;
 	ctxt->sge[0].length = svc_rdma_xdr_get_reply_hdr_len(rdma_resp);
 	ctxt->sge[0].addr =
-		ib_dma_map_single(rdma->sc_cm_id->device, page_address(page),
-				  ctxt->sge[0].length, DMA_TO_DEVICE);
+	    ib_dma_map_page(rdma->sc_cm_id->device, page, 0,
+			    ctxt->sge[0].length, DMA_TO_DEVICE);
 	if (ib_dma_mapping_error(rdma->sc_cm_id->device, ctxt->sge[0].addr))
 		goto err;
 	atomic_inc(&rdma->sc_dma_used);
 
 	ctxt->direction = DMA_TO_DEVICE;
 
-	/* Determine how many of our SGE are to be transmitted */
+	/* Map the payload indicated by 'byte_count' */
 	for (sge_no = 1; byte_count && sge_no < vec->count; sge_no++) {
+		int xdr_off = 0;
 		sge_bytes = min_t(size_t, vec->sge[sge_no].iov_len, byte_count);
 		byte_count -= sge_bytes;
 		if (!vec->frmr) {
 			ctxt->sge[sge_no].addr =
-				ib_dma_map_single(rdma->sc_cm_id->device,
-						  vec->sge[sge_no].iov_base,
-						  sge_bytes, DMA_TO_DEVICE);
+				dma_map_xdr(rdma, &rqstp->rq_res, xdr_off,
+					    sge_bytes, DMA_TO_DEVICE);
+			xdr_off += sge_bytes;
 			if (ib_dma_mapping_error(rdma->sc_cm_id->device,
 						 ctxt->sge[sge_no].addr))
 				goto err;
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c
index edea15a..9df1ead 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_transport.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c
@@ -45,6 +45,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <linux/workqueue.h>
 #include <rdma/ib_verbs.h>
 #include <rdma/rdma_cm.h>
 #include <linux/sunrpc/svc_rdma.h>
@@ -52,6 +53,7 @@
 #define RPCDBG_FACILITY	RPCDBG_SVCXPRT
 
 static struct svc_xprt *svc_rdma_create(struct svc_serv *serv,
+					struct net *net,
 					struct sockaddr *sa, int salen,
 					int flags);
 static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt);
@@ -89,6 +91,9 @@
 /* WR context cache. Created in svc_rdma.c  */
 extern struct kmem_cache *svc_rdma_ctxt_cachep;
 
+/* Workqueue created in svc_rdma.c */
+extern struct workqueue_struct *svc_rdma_wq;
+
 struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *xprt)
 {
 	struct svc_rdma_op_ctxt *ctxt;
@@ -120,7 +125,7 @@
 		 */
 		if (ctxt->sge[i].lkey == xprt->sc_dma_lkey) {
 			atomic_dec(&xprt->sc_dma_used);
-			ib_dma_unmap_single(xprt->sc_cm_id->device,
+			ib_dma_unmap_page(xprt->sc_cm_id->device,
 					    ctxt->sge[i].addr,
 					    ctxt->sge[i].length,
 					    ctxt->direction);
@@ -502,8 +507,8 @@
 		BUG_ON(sge_no >= xprt->sc_max_sge);
 		page = svc_rdma_get_page();
 		ctxt->pages[sge_no] = page;
-		pa = ib_dma_map_single(xprt->sc_cm_id->device,
-				     page_address(page), PAGE_SIZE,
+		pa = ib_dma_map_page(xprt->sc_cm_id->device,
+				     page, 0, PAGE_SIZE,
 				     DMA_FROM_DEVICE);
 		if (ib_dma_mapping_error(xprt->sc_cm_id->device, pa))
 			goto err_put_ctxt;
@@ -511,9 +516,9 @@
 		ctxt->sge[sge_no].addr = pa;
 		ctxt->sge[sge_no].length = PAGE_SIZE;
 		ctxt->sge[sge_no].lkey = xprt->sc_dma_lkey;
+		ctxt->count = sge_no + 1;
 		buflen += PAGE_SIZE;
 	}
-	ctxt->count = sge_no;
 	recv_wr.next = NULL;
 	recv_wr.sg_list = &ctxt->sge[0];
 	recv_wr.num_sge = ctxt->count;
@@ -529,6 +534,7 @@
 	return ret;
 
  err_put_ctxt:
+	svc_rdma_unmap_dma(ctxt);
 	svc_rdma_put_context(ctxt, 1);
 	return -ENOMEM;
 }
@@ -670,6 +676,7 @@
  * Create a listening RDMA service endpoint.
  */
 static struct svc_xprt *svc_rdma_create(struct svc_serv *serv,
+					struct net *net,
 					struct sockaddr *sa, int salen,
 					int flags)
 {
@@ -798,8 +805,8 @@
 		if (ib_dma_mapping_error(frmr->mr->device, addr))
 			continue;
 		atomic_dec(&xprt->sc_dma_used);
-		ib_dma_unmap_single(frmr->mr->device, addr, PAGE_SIZE,
-				    frmr->direction);
+		ib_dma_unmap_page(frmr->mr->device, addr, PAGE_SIZE,
+				  frmr->direction);
 	}
 }
 
@@ -1184,7 +1191,7 @@
 	struct svcxprt_rdma *rdma =
 		container_of(xprt, struct svcxprt_rdma, sc_xprt);
 	INIT_WORK(&rdma->sc_work, __svc_rdma_free);
-	schedule_work(&rdma->sc_work);
+	queue_work(svc_rdma_wq, &rdma->sc_work);
 }
 
 static int svc_rdma_has_wspace(struct svc_xprt *xprt)
@@ -1274,7 +1281,7 @@
 				   atomic_read(&xprt->sc_sq_count) <
 				   xprt->sc_sq_depth);
 			if (test_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags))
-				return 0;
+				return -ENOTCONN;
 			continue;
 		}
 		/* Take a transport ref for each WR posted */
@@ -1306,7 +1313,6 @@
 			 enum rpcrdma_errcode err)
 {
 	struct ib_send_wr err_wr;
-	struct ib_sge sge;
 	struct page *p;
 	struct svc_rdma_op_ctxt *ctxt;
 	u32 *va;
@@ -1319,26 +1325,27 @@
 	/* XDR encode error */
 	length = svc_rdma_xdr_encode_error(xprt, rmsgp, err, va);
 
+	ctxt = svc_rdma_get_context(xprt);
+	ctxt->direction = DMA_FROM_DEVICE;
+	ctxt->count = 1;
+	ctxt->pages[0] = p;
+
 	/* Prepare SGE for local address */
-	sge.addr = ib_dma_map_single(xprt->sc_cm_id->device,
-				   page_address(p), PAGE_SIZE, DMA_FROM_DEVICE);
-	if (ib_dma_mapping_error(xprt->sc_cm_id->device, sge.addr)) {
+	ctxt->sge[0].addr = ib_dma_map_page(xprt->sc_cm_id->device,
+					    p, 0, length, DMA_FROM_DEVICE);
+	if (ib_dma_mapping_error(xprt->sc_cm_id->device, ctxt->sge[0].addr)) {
 		put_page(p);
 		return;
 	}
 	atomic_inc(&xprt->sc_dma_used);
-	sge.lkey = xprt->sc_dma_lkey;
-	sge.length = length;
-
-	ctxt = svc_rdma_get_context(xprt);
-	ctxt->count = 1;
-	ctxt->pages[0] = p;
+	ctxt->sge[0].lkey = xprt->sc_dma_lkey;
+	ctxt->sge[0].length = length;
 
 	/* Prepare SEND WR */
 	memset(&err_wr, 0, sizeof err_wr);
 	ctxt->wr_op = IB_WR_SEND;
 	err_wr.wr_id = (unsigned long)ctxt;
-	err_wr.sg_list = &sge;
+	err_wr.sg_list = ctxt->sge;
 	err_wr.num_sge = 1;
 	err_wr.opcode = IB_WR_SEND;
 	err_wr.send_flags = IB_SEND_SIGNALED;
@@ -1348,9 +1355,7 @@
 	if (ret) {
 		dprintk("svcrdma: Error %d posting send for protocol error\n",
 			ret);
-		ib_dma_unmap_single(xprt->sc_cm_id->device,
-				  sge.addr, PAGE_SIZE,
-				  DMA_FROM_DEVICE);
+		svc_rdma_unmap_dma(ctxt);
 		svc_rdma_put_context(ctxt, 1);
 	}
 }
diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c
index a85e866..0867070 100644
--- a/net/sunrpc/xprtrdma/transport.c
+++ b/net/sunrpc/xprtrdma/transport.c
@@ -237,8 +237,7 @@
 
 	dprintk("RPC:       %s: called\n", __func__);
 
-	cancel_delayed_work(&r_xprt->rdma_connect);
-	flush_scheduled_work();
+	cancel_delayed_work_sync(&r_xprt->rdma_connect);
 
 	xprt_clear_connected(xprt);
 
@@ -251,9 +250,7 @@
 
 	xprt_rdma_free_addresses(xprt);
 
-	kfree(xprt->slot);
-	xprt->slot = NULL;
-	kfree(xprt);
+	xprt_free(xprt);
 
 	dprintk("RPC:       %s: returning\n", __func__);
 
@@ -285,23 +282,14 @@
 		return ERR_PTR(-EBADF);
 	}
 
-	xprt = kzalloc(sizeof(struct rpcrdma_xprt), GFP_KERNEL);
+	xprt = xprt_alloc(args->net, sizeof(struct rpcrdma_xprt),
+			xprt_rdma_slot_table_entries);
 	if (xprt == NULL) {
 		dprintk("RPC:       %s: couldn't allocate rpcrdma_xprt\n",
 			__func__);
 		return ERR_PTR(-ENOMEM);
 	}
 
-	xprt->max_reqs = xprt_rdma_slot_table_entries;
-	xprt->slot = kcalloc(xprt->max_reqs,
-				sizeof(struct rpc_rqst), GFP_KERNEL);
-	if (xprt->slot == NULL) {
-		dprintk("RPC:       %s: couldn't allocate %d slots\n",
-			__func__, xprt->max_reqs);
-		kfree(xprt);
-		return ERR_PTR(-ENOMEM);
-	}
-
 	/* 60 second timeout, no retries */
 	xprt->timeout = &xprt_rdma_default_timeout;
 	xprt->bind_timeout = (60U * HZ);
@@ -410,8 +398,7 @@
 out2:
 	rpcrdma_ia_close(&new_xprt->rx_ia);
 out1:
-	kfree(xprt->slot);
-	kfree(xprt);
+	xprt_free(xprt);
 	return ERR_PTR(rc);
 }
 
@@ -460,7 +447,7 @@
 	} else {
 		schedule_delayed_work(&r_xprt->rdma_connect, 0);
 		if (!RPC_IS_ASYNC(task))
-			flush_scheduled_work();
+			flush_delayed_work(&r_xprt->rdma_connect);
 	}
 }
 
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index fe9306b..dfcab5a 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -774,8 +774,7 @@
 
 	xs_close(xprt);
 	xs_free_peer_addresses(xprt);
-	kfree(xprt->slot);
-	kfree(xprt);
+	xprt_free(xprt);
 	module_put(THIS_MODULE);
 }
 
@@ -1516,7 +1515,7 @@
 	xs_update_peer_port(xprt);
 }
 
-static unsigned short xs_get_srcport(struct sock_xprt *transport, struct socket *sock)
+static unsigned short xs_get_srcport(struct sock_xprt *transport)
 {
 	unsigned short port = transport->srcport;
 
@@ -1525,7 +1524,7 @@
 	return port;
 }
 
-static unsigned short xs_next_srcport(struct sock_xprt *transport, struct socket *sock, unsigned short port)
+static unsigned short xs_next_srcport(struct sock_xprt *transport, unsigned short port)
 {
 	if (transport->srcport != 0)
 		transport->srcport = 0;
@@ -1535,23 +1534,18 @@
 		return xprt_max_resvport;
 	return --port;
 }
-
-static int xs_bind4(struct sock_xprt *transport, struct socket *sock)
+static int xs_bind(struct sock_xprt *transport, struct socket *sock)
 {
-	struct sockaddr_in myaddr = {
-		.sin_family = AF_INET,
-	};
-	struct sockaddr_in *sa;
+	struct sockaddr_storage myaddr;
 	int err, nloop = 0;
-	unsigned short port = xs_get_srcport(transport, sock);
+	unsigned short port = xs_get_srcport(transport);
 	unsigned short last;
 
-	sa = (struct sockaddr_in *)&transport->srcaddr;
-	myaddr.sin_addr = sa->sin_addr;
+	memcpy(&myaddr, &transport->srcaddr, transport->xprt.addrlen);
 	do {
-		myaddr.sin_port = htons(port);
-		err = kernel_bind(sock, (struct sockaddr *) &myaddr,
-						sizeof(myaddr));
+		rpc_set_port((struct sockaddr *)&myaddr, port);
+		err = kernel_bind(sock, (struct sockaddr *)&myaddr,
+				transport->xprt.addrlen);
 		if (port == 0)
 			break;
 		if (err == 0) {
@@ -1559,47 +1553,22 @@
 			break;
 		}
 		last = port;
-		port = xs_next_srcport(transport, sock, port);
+		port = xs_next_srcport(transport, port);
 		if (port > last)
 			nloop++;
 	} while (err == -EADDRINUSE && nloop != 2);
-	dprintk("RPC:       %s %pI4:%u: %s (%d)\n",
-			__func__, &myaddr.sin_addr,
-			port, err ? "failed" : "ok", err);
+
+	if (myaddr.ss_family == AF_INET)
+		dprintk("RPC:       %s %pI4:%u: %s (%d)\n", __func__,
+				&((struct sockaddr_in *)&myaddr)->sin_addr,
+				port, err ? "failed" : "ok", err);
+	else
+		dprintk("RPC:       %s %pI6:%u: %s (%d)\n", __func__,
+				&((struct sockaddr_in6 *)&myaddr)->sin6_addr,
+				port, err ? "failed" : "ok", err);
 	return err;
 }
 
-static int xs_bind6(struct sock_xprt *transport, struct socket *sock)
-{
-	struct sockaddr_in6 myaddr = {
-		.sin6_family = AF_INET6,
-	};
-	struct sockaddr_in6 *sa;
-	int err, nloop = 0;
-	unsigned short port = xs_get_srcport(transport, sock);
-	unsigned short last;
-
-	sa = (struct sockaddr_in6 *)&transport->srcaddr;
-	myaddr.sin6_addr = sa->sin6_addr;
-	do {
-		myaddr.sin6_port = htons(port);
-		err = kernel_bind(sock, (struct sockaddr *) &myaddr,
-						sizeof(myaddr));
-		if (port == 0)
-			break;
-		if (err == 0) {
-			transport->srcport = port;
-			break;
-		}
-		last = port;
-		port = xs_next_srcport(transport, sock, port);
-		if (port > last)
-			nloop++;
-	} while (err == -EADDRINUSE && nloop != 2);
-	dprintk("RPC:       xs_bind6 %pI6:%u: %s (%d)\n",
-		&myaddr.sin6_addr, port, err ? "failed" : "ok", err);
-	return err;
-}
 
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 static struct lock_class_key xs_key[2];
@@ -1622,6 +1591,18 @@
 	sock_lock_init_class_and_name(sk, "slock-AF_INET6-RPC",
 		&xs_slock_key[1], "sk_lock-AF_INET6-RPC", &xs_key[1]);
 }
+
+static inline void xs_reclassify_socket(int family, struct socket *sock)
+{
+	switch (family) {
+	case AF_INET:
+		xs_reclassify_socket4(sock);
+		break;
+	case AF_INET6:
+		xs_reclassify_socket6(sock);
+		break;
+	}
+}
 #else
 static inline void xs_reclassify_socket4(struct socket *sock)
 {
@@ -1630,8 +1611,36 @@
 static inline void xs_reclassify_socket6(struct socket *sock)
 {
 }
+
+static inline void xs_reclassify_socket(int family, struct socket *sock)
+{
+}
 #endif
 
+static struct socket *xs_create_sock(struct rpc_xprt *xprt,
+		struct sock_xprt *transport, int family, int type, int protocol)
+{
+	struct socket *sock;
+	int err;
+
+	err = __sock_create(xprt->xprt_net, family, type, protocol, &sock, 1);
+	if (err < 0) {
+		dprintk("RPC:       can't create %d transport socket (%d).\n",
+				protocol, -err);
+		goto out;
+	}
+	xs_reclassify_socket(family, sock);
+
+	if (xs_bind(transport, sock)) {
+		sock_release(sock);
+		goto out;
+	}
+
+	return sock;
+out:
+	return ERR_PTR(err);
+}
+
 static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
 {
 	struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
@@ -1661,82 +1670,23 @@
 	xs_udp_do_set_buffer_size(xprt);
 }
 
-/**
- * xs_udp_connect_worker4 - set up a UDP socket
- * @work: RPC transport to connect
- *
- * Invoked by a work queue tasklet.
- */
-static void xs_udp_connect_worker4(struct work_struct *work)
+static void xs_udp_setup_socket(struct work_struct *work)
 {
 	struct sock_xprt *transport =
 		container_of(work, struct sock_xprt, connect_worker.work);
 	struct rpc_xprt *xprt = &transport->xprt;
 	struct socket *sock = transport->sock;
-	int err, status = -EIO;
+	int status = -EIO;
 
 	if (xprt->shutdown)
 		goto out;
 
 	/* Start by resetting any existing state */
 	xs_reset_transport(transport);
-
-	err = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);
-	if (err < 0) {
-		dprintk("RPC:       can't create UDP transport socket (%d).\n", -err);
+	sock = xs_create_sock(xprt, transport,
+			xs_addr(xprt)->sa_family, SOCK_DGRAM, IPPROTO_UDP);
+	if (IS_ERR(sock))
 		goto out;
-	}
-	xs_reclassify_socket4(sock);
-
-	if (xs_bind4(transport, sock)) {
-		sock_release(sock);
-		goto out;
-	}
-
-	dprintk("RPC:       worker connecting xprt %p via %s to "
-				"%s (port %s)\n", xprt,
-			xprt->address_strings[RPC_DISPLAY_PROTO],
-			xprt->address_strings[RPC_DISPLAY_ADDR],
-			xprt->address_strings[RPC_DISPLAY_PORT]);
-
-	xs_udp_finish_connecting(xprt, sock);
-	status = 0;
-out:
-	xprt_clear_connecting(xprt);
-	xprt_wake_pending_tasks(xprt, status);
-}
-
-/**
- * xs_udp_connect_worker6 - set up a UDP socket
- * @work: RPC transport to connect
- *
- * Invoked by a work queue tasklet.
- */
-static void xs_udp_connect_worker6(struct work_struct *work)
-{
-	struct sock_xprt *transport =
-		container_of(work, struct sock_xprt, connect_worker.work);
-	struct rpc_xprt *xprt = &transport->xprt;
-	struct socket *sock = transport->sock;
-	int err, status = -EIO;
-
-	if (xprt->shutdown)
-		goto out;
-
-	/* Start by resetting any existing state */
-	xs_reset_transport(transport);
-
-	err = sock_create_kern(PF_INET6, SOCK_DGRAM, IPPROTO_UDP, &sock);
-	if (err < 0) {
-		dprintk("RPC:       can't create UDP transport socket (%d).\n", -err);
-		goto out;
-	}
-	xs_reclassify_socket6(sock);
-
-	if (xs_bind6(transport, sock) < 0) {
-		sock_release(sock);
-		goto out;
-	}
 
 	dprintk("RPC:       worker connecting xprt %p via %s to "
 				"%s (port %s)\n", xprt,
@@ -1755,12 +1705,12 @@
  * We need to preserve the port number so the reply cache on the server can
  * find our cached RPC replies when we get around to reconnecting.
  */
-static void xs_abort_connection(struct rpc_xprt *xprt, struct sock_xprt *transport)
+static void xs_abort_connection(struct sock_xprt *transport)
 {
 	int result;
 	struct sockaddr any;
 
-	dprintk("RPC:       disconnecting xprt %p to reuse port\n", xprt);
+	dprintk("RPC:       disconnecting xprt %p to reuse port\n", transport);
 
 	/*
 	 * Disconnect the transport socket by doing a connect operation
@@ -1770,13 +1720,13 @@
 	any.sa_family = AF_UNSPEC;
 	result = kernel_connect(transport->sock, &any, sizeof(any), 0);
 	if (!result)
-		xs_sock_mark_closed(xprt);
+		xs_sock_mark_closed(&transport->xprt);
 	else
 		dprintk("RPC:       AF_UNSPEC connect return code %d\n",
 				result);
 }
 
-static void xs_tcp_reuse_connection(struct rpc_xprt *xprt, struct sock_xprt *transport)
+static void xs_tcp_reuse_connection(struct sock_xprt *transport)
 {
 	unsigned int state = transport->inet->sk_state;
 
@@ -1799,7 +1749,7 @@
 				"sk_shutdown set to %d\n",
 				__func__, transport->inet->sk_shutdown);
 	}
-	xs_abort_connection(xprt, transport);
+	xs_abort_connection(transport);
 }
 
 static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
@@ -1852,12 +1802,12 @@
  *
  * Invoked by a work queue tasklet.
  */
-static void xs_tcp_setup_socket(struct rpc_xprt *xprt,
-		struct sock_xprt *transport,
-		struct socket *(*create_sock)(struct rpc_xprt *,
-			struct sock_xprt *))
+static void xs_tcp_setup_socket(struct work_struct *work)
 {
+	struct sock_xprt *transport =
+		container_of(work, struct sock_xprt, connect_worker.work);
 	struct socket *sock = transport->sock;
+	struct rpc_xprt *xprt = &transport->xprt;
 	int status = -EIO;
 
 	if (xprt->shutdown)
@@ -1865,7 +1815,8 @@
 
 	if (!sock) {
 		clear_bit(XPRT_CONNECTION_ABORT, &xprt->state);
-		sock = create_sock(xprt, transport);
+		sock = xs_create_sock(xprt, transport,
+				xs_addr(xprt)->sa_family, SOCK_STREAM, IPPROTO_TCP);
 		if (IS_ERR(sock)) {
 			status = PTR_ERR(sock);
 			goto out;
@@ -1876,7 +1827,7 @@
 		abort_and_exit = test_and_clear_bit(XPRT_CONNECTION_ABORT,
 				&xprt->state);
 		/* "close" the socket, preserving the local port */
-		xs_tcp_reuse_connection(xprt, transport);
+		xs_tcp_reuse_connection(transport);
 
 		if (abort_and_exit)
 			goto out_eagain;
@@ -1925,84 +1876,6 @@
 	xprt_wake_pending_tasks(xprt, status);
 }
 
-static struct socket *xs_create_tcp_sock4(struct rpc_xprt *xprt,
-		struct sock_xprt *transport)
-{
-	struct socket *sock;
-	int err;
-
-	/* start from scratch */
-	err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
-	if (err < 0) {
-		dprintk("RPC:       can't create TCP transport socket (%d).\n",
-				-err);
-		goto out_err;
-	}
-	xs_reclassify_socket4(sock);
-
-	if (xs_bind4(transport, sock) < 0) {
-		sock_release(sock);
-		goto out_err;
-	}
-	return sock;
-out_err:
-	return ERR_PTR(-EIO);
-}
-
-/**
- * xs_tcp_connect_worker4 - connect a TCP socket to a remote endpoint
- * @work: RPC transport to connect
- *
- * Invoked by a work queue tasklet.
- */
-static void xs_tcp_connect_worker4(struct work_struct *work)
-{
-	struct sock_xprt *transport =
-		container_of(work, struct sock_xprt, connect_worker.work);
-	struct rpc_xprt *xprt = &transport->xprt;
-
-	xs_tcp_setup_socket(xprt, transport, xs_create_tcp_sock4);
-}
-
-static struct socket *xs_create_tcp_sock6(struct rpc_xprt *xprt,
-		struct sock_xprt *transport)
-{
-	struct socket *sock;
-	int err;
-
-	/* start from scratch */
-	err = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, &sock);
-	if (err < 0) {
-		dprintk("RPC:       can't create TCP transport socket (%d).\n",
-				-err);
-		goto out_err;
-	}
-	xs_reclassify_socket6(sock);
-
-	if (xs_bind6(transport, sock) < 0) {
-		sock_release(sock);
-		goto out_err;
-	}
-	return sock;
-out_err:
-	return ERR_PTR(-EIO);
-}
-
-/**
- * xs_tcp_connect_worker6 - connect a TCP socket to a remote endpoint
- * @work: RPC transport to connect
- *
- * Invoked by a work queue tasklet.
- */
-static void xs_tcp_connect_worker6(struct work_struct *work)
-{
-	struct sock_xprt *transport =
-		container_of(work, struct sock_xprt, connect_worker.work);
-	struct rpc_xprt *xprt = &transport->xprt;
-
-	xs_tcp_setup_socket(xprt, transport, xs_create_tcp_sock6);
-}
-
 /**
  * xs_connect - connect a socket to a remote endpoint
  * @task: address of RPC task that manages state of connect request
@@ -2262,6 +2135,31 @@
 	.print_stats		= xs_tcp_print_stats,
 };
 
+static int xs_init_anyaddr(const int family, struct sockaddr *sap)
+{
+	static const struct sockaddr_in sin = {
+		.sin_family		= AF_INET,
+		.sin_addr.s_addr	= htonl(INADDR_ANY),
+	};
+	static const struct sockaddr_in6 sin6 = {
+		.sin6_family		= AF_INET6,
+		.sin6_addr		= IN6ADDR_ANY_INIT,
+	};
+
+	switch (family) {
+	case AF_INET:
+		memcpy(sap, &sin, sizeof(sin));
+		break;
+	case AF_INET6:
+		memcpy(sap, &sin6, sizeof(sin6));
+		break;
+	default:
+		dprintk("RPC:       %s: Bad address family\n", __func__);
+		return -EAFNOSUPPORT;
+	}
+	return 0;
+}
+
 static struct rpc_xprt *xs_setup_xprt(struct xprt_create *args,
 				      unsigned int slot_table_size)
 {
@@ -2273,27 +2171,25 @@
 		return ERR_PTR(-EBADF);
 	}
 
-	new = kzalloc(sizeof(*new), GFP_KERNEL);
-	if (new == NULL) {
+	xprt = xprt_alloc(args->net, sizeof(*new), slot_table_size);
+	if (xprt == NULL) {
 		dprintk("RPC:       xs_setup_xprt: couldn't allocate "
 				"rpc_xprt\n");
 		return ERR_PTR(-ENOMEM);
 	}
-	xprt = &new->xprt;
 
-	xprt->max_reqs = slot_table_size;
-	xprt->slot = kcalloc(xprt->max_reqs, sizeof(struct rpc_rqst), GFP_KERNEL);
-	if (xprt->slot == NULL) {
-		kfree(xprt);
-		dprintk("RPC:       xs_setup_xprt: couldn't allocate slot "
-				"table\n");
-		return ERR_PTR(-ENOMEM);
-	}
-
+	new = container_of(xprt, struct sock_xprt, xprt);
 	memcpy(&xprt->addr, args->dstaddr, args->addrlen);
 	xprt->addrlen = args->addrlen;
 	if (args->srcaddr)
 		memcpy(&new->srcaddr, args->srcaddr, args->addrlen);
+	else {
+		int err;
+		err = xs_init_anyaddr(args->dstaddr->sa_family,
+					(struct sockaddr *)&new->srcaddr);
+		if (err != 0)
+			return ERR_PTR(err);
+	}
 
 	return xprt;
 }
@@ -2341,7 +2237,7 @@
 			xprt_set_bound(xprt);
 
 		INIT_DELAYED_WORK(&transport->connect_worker,
-					xs_udp_connect_worker4);
+					xs_udp_setup_socket);
 		xs_format_peer_addresses(xprt, "udp", RPCBIND_NETID_UDP);
 		break;
 	case AF_INET6:
@@ -2349,7 +2245,7 @@
 			xprt_set_bound(xprt);
 
 		INIT_DELAYED_WORK(&transport->connect_worker,
-					xs_udp_connect_worker6);
+					xs_udp_setup_socket);
 		xs_format_peer_addresses(xprt, "udp", RPCBIND_NETID_UDP6);
 		break;
 	default:
@@ -2371,8 +2267,7 @@
 		return xprt;
 	ret = ERR_PTR(-EINVAL);
 out_err:
-	kfree(xprt->slot);
-	kfree(xprt);
+	xprt_free(xprt);
 	return ret;
 }
 
@@ -2416,7 +2311,7 @@
 			xprt_set_bound(xprt);
 
 		INIT_DELAYED_WORK(&transport->connect_worker,
-					xs_tcp_connect_worker4);
+					xs_tcp_setup_socket);
 		xs_format_peer_addresses(xprt, "tcp", RPCBIND_NETID_TCP);
 		break;
 	case AF_INET6:
@@ -2424,7 +2319,7 @@
 			xprt_set_bound(xprt);
 
 		INIT_DELAYED_WORK(&transport->connect_worker,
-					xs_tcp_connect_worker6);
+					xs_tcp_setup_socket);
 		xs_format_peer_addresses(xprt, "tcp", RPCBIND_NETID_TCP6);
 		break;
 	default:
@@ -2447,8 +2342,7 @@
 		return xprt;
 	ret = ERR_PTR(-EINVAL);
 out_err:
-	kfree(xprt->slot);
-	kfree(xprt);
+	xprt_free(xprt);
 	return ret;
 }
 
@@ -2507,15 +2401,10 @@
 		goto out_err;
 	}
 
-	if (xprt_bound(xprt))
-		dprintk("RPC:       set up xprt to %s (port %s) via %s\n",
-				xprt->address_strings[RPC_DISPLAY_ADDR],
-				xprt->address_strings[RPC_DISPLAY_PORT],
-				xprt->address_strings[RPC_DISPLAY_PROTO]);
-	else
-		dprintk("RPC:       set up xprt to %s (autobind) via %s\n",
-				xprt->address_strings[RPC_DISPLAY_ADDR],
-				xprt->address_strings[RPC_DISPLAY_PROTO]);
+	dprintk("RPC:       set up xprt to %s (port %s) via %s\n",
+			xprt->address_strings[RPC_DISPLAY_ADDR],
+			xprt->address_strings[RPC_DISPLAY_PORT],
+			xprt->address_strings[RPC_DISPLAY_PROTO]);
 
 	/*
 	 * Since we don't want connections for the backchannel, we set
@@ -2528,8 +2417,7 @@
 		return xprt;
 	ret = ERR_PTR(-EINVAL);
 out_err:
-	kfree(xprt->slot);
-	kfree(xprt);
+	xprt_free(xprt);
 	return ret;
 }
 
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 2039acd..90b54d4 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -2,7 +2,7 @@
 # (c) 2001, Dave Jones. (the file handling bit)
 # (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit)
 # (c) 2007,2008, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite)
-# (c) 2008,2009, Andy Whitcroft <apw@canonical.com>
+# (c) 2008-2010 Andy Whitcroft <apw@canonical.com>
 # Licensed under the terms of the GNU GPL License version 2
 
 use strict;
@@ -10,7 +10,7 @@
 my $P = $0;
 $P =~ s@.*/@@g;
 
-my $V = '0.30';
+my $V = '0.31';
 
 use Getopt::Long qw(:config no_auto_abbrev);
 
@@ -103,6 +103,8 @@
 	die "$@" if ($@);
 }
 
+my $rpt_cleaners = 0;
+
 if ($terse) {
 	$emacs = 1;
 	$quiet++;
@@ -150,6 +152,20 @@
 # We need \b after 'init' otherwise 'initconst' will cause a false positive in a check
 our $Attribute	= qr{
 			const|
+			__percpu|
+			__nocast|
+			__safe|
+			__bitwise__|
+			__packed__|
+			__packed2__|
+			__naked|
+			__maybe_unused|
+			__always_unused|
+			__noreturn|
+			__used|
+			__cold|
+			__noclone|
+			__deprecated|
 			__read_mostly|
 			__kprobes|
 			__(?:mem|cpu|dev|)(?:initdata|initconst|init\b)|
@@ -675,15 +691,15 @@
 		$blk .= $rawlines[$line];
 
 		# Handle nested #if/#else.
-		if ($rawlines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) {
+		if ($lines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) {
 			push(@stack, $level);
-		} elsif ($rawlines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) {
+		} elsif ($lines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) {
 			$level = $stack[$#stack - 1];
-		} elsif ($rawlines[$line] =~ /^.\s*#\s*endif\b/) {
+		} elsif ($lines[$line] =~ /^.\s*#\s*endif\b/) {
 			$level = pop(@stack);
 		}
 
-		foreach my $c (split(//, $rawlines[$line])) {
+		foreach my $c (split(//, $lines[$line])) {
 			##print "C<$c>L<$level><$open$close>O<$off>\n";
 			if ($off > 0) {
 				$off--;
@@ -843,7 +859,12 @@
 				$av_preprocessor = 0;
 			}
 
-		} elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\()/) {
+		} elsif ($cur =~ /^(\(\s*$Type\s*)\)/) {
+			print "CAST($1)\n" if ($dbg_values > 1);
+			push(@av_paren_type, $type);
+			$type = 'C';
+
+		} elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\(|\s*$)/) {
 			print "DECLARE($1)\n" if ($dbg_values > 1);
 			$type = 'T';
 
@@ -1308,7 +1329,11 @@
 		$here = "#$realline: " if ($file);
 
 		# extract the filename as it passes
-		if ($line=~/^\+\+\+\s+(\S+)/) {
+		if ($line =~ /^diff --git.*?(\S+)$/) {
+			$realfile = $1;
+			$realfile =~ s@^([^/]*)/@@;
+
+		} elsif ($line =~ /^\+\+\+\s+(\S+)/) {
 			$realfile = $1;
 			$realfile =~ s@^([^/]*)/@@;
 
@@ -1332,6 +1357,14 @@
 
 		$cnt_lines++ if ($realcnt != 0);
 
+# Check for incorrect file permissions
+		if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) {
+			my $permhere = $here . "FILE: $realfile\n";
+			if ($realfile =~ /(Makefile|Kconfig|\.c|\.h|\.S|\.tmpl)$/) {
+				ERROR("do not set execute permissions for source files\n" . $permhere);
+			}
+		}
+
 #check the patch for a signoff:
 		if ($line =~ /^\s*signed-off-by:/i) {
 			# This is a signoff, if ugly, so do not double report.
@@ -1389,21 +1422,38 @@
 		} elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) {
 			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
 			ERROR("trailing whitespace\n" . $herevet);
+			$rpt_cleaners = 1;
 		}
 
 # check for Kconfig help text having a real description
+# Only applies when adding the entry originally, after that we do not have
+# sufficient context to determine whether it is indeed long enough.
 		if ($realfile =~ /Kconfig/ &&
-		    $line =~ /\+?\s*(---)?help(---)?$/) {
+		    $line =~ /\+\s*(?:---)?help(?:---)?$/) {
 			my $length = 0;
-			for (my $l = $linenr; defined($lines[$l]); $l++) {
-				my $f = $lines[$l];
+			my $cnt = $realcnt;
+			my $ln = $linenr + 1;
+			my $f;
+			my $is_end = 0;
+			while ($cnt > 0 && defined $lines[$ln - 1]) {
+				$f = $lines[$ln - 1];
+				$cnt-- if ($lines[$ln - 1] !~ /^-/);
+				$is_end = $lines[$ln - 1] =~ /^\+/;
+				$ln++;
+
+				next if ($f =~ /^-/);
+				$f =~ s/^.//;
 				$f =~ s/#.*//;
 				$f =~ s/^\s+//;
 				next if ($f =~ /^$/);
-				last if ($f =~ /^\s*config\s/);
+				if ($f =~ /^\s*config\s/) {
+					$is_end = 1;
+					last;
+				}
 				$length++;
 			}
-			WARN("please write a paragraph that describes the config symbol fully\n" . $herecurr) if ($length < 4);
+			WARN("please write a paragraph that describes the config symbol fully\n" . $herecurr) if ($is_end && $length < 4);
+			#print "is_end<$is_end> length<$length>\n";
 		}
 
 # check we are in a valid source file if not then ignore this hunk
@@ -1450,6 +1500,7 @@
 		    $rawline =~ /^\+\s*        \s*/) {
 			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
 			ERROR("code indent should use tabs where possible\n" . $herevet);
+			$rpt_cleaners = 1;
 		}
 
 # check for space before tabs.
@@ -1459,10 +1510,13 @@
 		}
 
 # check for spaces at the beginning of a line.
-		if ($rawline =~ /^\+ / && $rawline !~ /\+ +\*/)  {
+# Exceptions:
+#  1) within comments
+#  2) indented preprocessor commands
+#  3) hanging labels
+		if ($rawline =~ /^\+ / && $line !~ /\+ *(?:$;|#|$Ident:)/)  {
 			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
-			WARN("please, no space for starting a line, \
-				excluding comments\n" . $herevet);
+			WARN("please, no spaces at the start of a line\n" . $herevet);
 		}
 
 # check we are in a valid C source file if not then ignore this hunk
@@ -1598,7 +1652,7 @@
 
 			if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln -1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) {
 				ERROR("that open brace { should be on the previous line\n" .
-					"$here\n$ctx\n$lines[$ctx_ln - 1]\n");
+					"$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
 			}
 			if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ &&
 			    $ctx =~ /\)\s*\;\s*$/ &&
@@ -1607,7 +1661,7 @@
 				my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]);
 				if ($nindent > $indent) {
 					WARN("trailing semicolon indicates no statements, indent implies otherwise\n" .
-						"$here\n$ctx\n$lines[$ctx_ln - 1]\n");
+						"$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
 				}
 			}
 		}
@@ -1768,8 +1822,17 @@
 		    !defined $suppress_export{$realline_next} &&
 		    ($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/ ||
 		     $lines[$realline_next - 1] =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) {
+			# Handle definitions which produce identifiers with
+			# a prefix:
+			#   XXX(foo);
+			#   EXPORT_SYMBOL(something_foo);
 			my $name = $1;
-			if ($stat !~ /(?:
+			if ($stat =~ /^.([A-Z_]+)\s*\(\s*($Ident)/ &&
+			    $name =~ /^${Ident}_$2/) {
+#print "FOO C name<$name>\n";
+				$suppress_export{$realline_next} = 1;
+
+			} elsif ($stat !~ /(?:
 				\n.}\s*$|
 				^.DEFINE_$Ident\(\Q$name\E\)|
 				^.DECLARE_$Ident\(\Q$name\E\)|
@@ -1806,6 +1869,23 @@
 				$herecurr);
 		}
 
+# check for static const char * arrays.
+		if ($line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/) {
+			WARN("static const char * array should probably be static const char * const\n" .
+				$herecurr);
+               }
+
+# check for static char foo[] = "bar" declarations.
+		if ($line =~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=\s*"/) {
+			WARN("static char array declaration should probably be static const char\n" .
+				$herecurr);
+               }
+
+# check for declarations of struct pci_device_id
+		if ($line =~ /\bstruct\s+pci_device_id\s+\w+\s*\[\s*\]\s*\=\s*\{/) {
+			WARN("Use DEFINE_PCI_DEVICE_TABLE for struct pci_device_id\n" . $herecurr);
+		}
+
 # check for new typedefs, only function parameters and sparse annotations
 # make sense.
 		if ($line =~ /\btypedef\s/ &&
@@ -1899,6 +1979,11 @@
 			ERROR("open brace '{' following $1 go on the same line\n" . $hereprev);
 		}
 
+# missing space after union, struct or enum definition
+		if ($line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?(?:\s+$Ident)?[=\{]/) {
+		    WARN("missing space after $1 definition\n" . $herecurr);
+		}
+
 # check for spacing round square brackets; allowed:
 #  1. with a type on the left -- int [] a;
 #  2. at the beginning of a line for slice initialisers -- [0...10] = 5,
@@ -2176,21 +2261,29 @@
 			my $value = $2;
 
 			# Flatten any parentheses
-			$value =~ s/\)\(/\) \(/g;
+			$value =~ s/\(/ \(/g;
+			$value =~ s/\)/\) /g;
 			while ($value =~ s/\[[^\{\}]*\]/1/ ||
 			       $value !~ /(?:$Ident|-?$Constant)\s*
 					     $Compare\s*
 					     (?:$Ident|-?$Constant)/x &&
 			       $value =~ s/\([^\(\)]*\)/1/) {
 			}
-
-			if ($value =~ /^(?:$Ident|-?$Constant)$/) {
+#print "value<$value>\n";
+			if ($value =~ /^\s*(?:$Ident|-?$Constant)\s*$/) {
 				ERROR("return is not a function, parentheses are not required\n" . $herecurr);
 
 			} elsif ($spacing !~ /\s+/) {
 				ERROR("space required before the open parenthesis '('\n" . $herecurr);
 			}
 		}
+# Return of what appears to be an errno should normally be -'ve
+		if ($line =~ /^.\s*return\s*(E[A-Z]*)\s*;/) {
+			my $name = $1;
+			if ($name ne 'EOF' && $name ne 'ERROR') {
+				WARN("return of an errno should typically be -ve (return -$1)\n" . $herecurr);
+			}
+		}
 
 # Need a space before open parenthesis after if, while etc
 		if ($line=~/\b(if|while|for|switch)\(/) {
@@ -2409,8 +2502,8 @@
 				\.$Ident\s*=\s*|
 				^\"|\"$
 			}x;
-			#print "REST<$rest> dstat<$dstat>\n";
-			if ($rest ne '') {
+			#print "REST<$rest> dstat<$dstat> ctx<$ctx>\n";
+			if ($rest ne '' && $rest ne ',') {
 				if ($rest !~ /while\s*\(/ &&
 				    $dstat !~ /$exceptions/)
 				{
@@ -2839,6 +2932,15 @@
 		print "\n" if ($quiet == 0);
 	}
 
+	if ($quiet == 0) {
+		# If there were whitespace errors which cleanpatch can fix
+		# then suggest that.
+		if ($rpt_cleaners) {
+			print "NOTE: whitespace errors detected, you may wish to use scripts/cleanpatch or\n";
+			print "      scripts/cleanfile\n\n";
+		}
+	}
+
 	if ($clean == 1 && $quiet == 0) {
 		print "$vname has no obvious style problems and is ready for submission.\n"
 	}
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
index b228198..d21ec3a 100755
--- a/scripts/get_maintainer.pl
+++ b/scripts/get_maintainer.pl
@@ -13,7 +13,7 @@
 use strict;
 
 my $P = $0;
-my $V = '0.24';
+my $V = '0.26-beta6';
 
 use Getopt::Long qw(:config no_auto_abbrev);
 
@@ -24,15 +24,19 @@
 my $email_list = 1;
 my $email_subscriber_list = 0;
 my $email_git_penguin_chiefs = 0;
-my $email_git = 1;
+my $email_git = 0;
 my $email_git_all_signature_types = 0;
 my $email_git_blame = 0;
+my $email_git_blame_signatures = 1;
+my $email_git_fallback = 1;
 my $email_git_min_signatures = 1;
 my $email_git_max_maintainers = 5;
 my $email_git_min_percent = 5;
 my $email_git_since = "1-year-ago";
 my $email_hg_since = "-365";
+my $interactive = 0;
 my $email_remove_duplicates = 1;
+my $email_use_mailmap = 1;
 my $output_multiline = 1;
 my $output_separator = ", ";
 my $output_roles = 0;
@@ -49,8 +53,13 @@
 my $version = 0;
 my $help = 0;
 
+my $vcs_used = 0;
+
 my $exit = 0;
 
+my %commit_author_hash;
+my %commit_signer_hash;
+
 my @penguin_chief = ();
 push(@penguin_chief, "Linus Torvalds:torvalds\@linux-foundation.org");
 #Andrew wants in on most everything - 2009/01/14
@@ -73,7 +82,6 @@
 push(@signature_tags, "Signed-off-by:");
 push(@signature_tags, "Reviewed-by:");
 push(@signature_tags, "Acked-by:");
-my $signaturePattern = "\(" . join("|", @signature_tags) . "\)";
 
 # rfc822 email address - preloaded methods go here.
 my $rfc822_lwsp = "(?:(?:\\r\\n)?[ \\t])";
@@ -86,31 +94,70 @@
 my %VCS_cmds_git = (
     "execute_cmd" => \&git_execute_cmd,
     "available" => '(which("git") ne "") && (-d ".git")',
-    "find_signers_cmd" => "git log --no-color --since=\$email_git_since -- \$file",
-    "find_commit_signers_cmd" => "git log --no-color -1 \$commit",
+    "find_signers_cmd" =>
+	"git log --no-color --since=\$email_git_since " .
+	    '--format="GitCommit: %H%n' .
+		      'GitAuthor: %an <%ae>%n' .
+		      'GitDate: %aD%n' .
+		      'GitSubject: %s%n' .
+		      '%b%n"' .
+	    " -- \$file",
+    "find_commit_signers_cmd" =>
+	"git log --no-color " .
+	    '--format="GitCommit: %H%n' .
+		      'GitAuthor: %an <%ae>%n' .
+		      'GitDate: %aD%n' .
+		      'GitSubject: %s%n' .
+		      '%b%n"' .
+	    " -1 \$commit",
+    "find_commit_author_cmd" =>
+	"git log --no-color " .
+	    '--format="GitCommit: %H%n' .
+		      'GitAuthor: %an <%ae>%n' .
+		      'GitDate: %aD%n' .
+		      'GitSubject: %s%n"' .
+	    " -1 \$commit",
     "blame_range_cmd" => "git blame -l -L \$diff_start,+\$diff_length \$file",
     "blame_file_cmd" => "git blame -l \$file",
-    "commit_pattern" => "^commit [0-9a-f]{40,40}",
-    "blame_commit_pattern" => "^([0-9a-f]+) "
+    "commit_pattern" => "^GitCommit: ([0-9a-f]{40,40})",
+    "blame_commit_pattern" => "^([0-9a-f]+) ",
+    "author_pattern" => "^GitAuthor: (.*)",
+    "subject_pattern" => "^GitSubject: (.*)",
 );
 
 my %VCS_cmds_hg = (
     "execute_cmd" => \&hg_execute_cmd,
     "available" => '(which("hg") ne "") && (-d ".hg")',
     "find_signers_cmd" =>
-	"hg log --date=\$email_hg_since" .
-		" --template='commit {node}\\n{desc}\\n' -- \$file",
-    "find_commit_signers_cmd" => "hg log --template='{desc}\\n' -r \$commit",
+	"hg log --date=\$email_hg_since " .
+	    "--template='HgCommit: {node}\\n" .
+	                "HgAuthor: {author}\\n" .
+			"HgSubject: {desc}\\n'" .
+	    " -- \$file",
+    "find_commit_signers_cmd" =>
+	"hg log " .
+	    "--template='HgSubject: {desc}\\n'" .
+	    " -r \$commit",
+    "find_commit_author_cmd" =>
+	"hg log " .
+	    "--template='HgCommit: {node}\\n" .
+		        "HgAuthor: {author}\\n" .
+			"HgSubject: {desc|firstline}\\n'" .
+	    " -r \$commit",
     "blame_range_cmd" => "",		# not supported
-    "blame_file_cmd" => "hg blame -c \$file",
-    "commit_pattern" => "^commit [0-9a-f]{40,40}",
-    "blame_commit_pattern" => "^([0-9a-f]+):"
+    "blame_file_cmd" => "hg blame -n \$file",
+    "commit_pattern" => "^HgCommit: ([0-9a-f]{40,40})",
+    "blame_commit_pattern" => "^([ 0-9a-f]+):",
+    "author_pattern" => "^HgAuthor: (.*)",
+    "subject_pattern" => "^HgSubject: (.*)",
 );
 
-if (-f "${lk_path}.get_maintainer.conf") {
+my $conf = which_conf(".get_maintainer.conf");
+if (-f $conf) {
     my @conf_args;
-    open(my $conffile, '<', "${lk_path}.get_maintainer.conf")
-	or warn "$P: Can't open .get_maintainer.conf: $!\n";
+    open(my $conffile, '<', "$conf")
+	or warn "$P: Can't find a readable .get_maintainer.conf file $!\n";
+
     while (<$conffile>) {
 	my $line = $_;
 
@@ -136,13 +183,17 @@
 		'git!' => \$email_git,
 		'git-all-signature-types!' => \$email_git_all_signature_types,
 		'git-blame!' => \$email_git_blame,
+		'git-blame-signatures!' => \$email_git_blame_signatures,
+		'git-fallback!' => \$email_git_fallback,
 		'git-chief-penguins!' => \$email_git_penguin_chiefs,
 		'git-min-signatures=i' => \$email_git_min_signatures,
 		'git-max-maintainers=i' => \$email_git_max_maintainers,
 		'git-min-percent=i' => \$email_git_min_percent,
 		'git-since=s' => \$email_git_since,
 		'hg-since=s' => \$email_hg_since,
+		'i|interactive!' => \$interactive,
 		'remove-duplicates!' => \$email_remove_duplicates,
+		'mailmap!' => \$email_use_mailmap,
 		'm!' => \$email_maintainer,
 		'n!' => \$email_usename,
 		'l!' => \$email_list,
@@ -181,13 +232,9 @@
     die "$P: missing patchfile or -f file - use --help if necessary\n";
 }
 
-if ($output_separator ne ", ") {
-    $output_multiline = 0;
-}
-
-if ($output_rolestats) {
-    $output_roles = 1;
-}
+$output_multiline = 0 if ($output_separator ne ", ");
+$output_rolestats = 1 if ($interactive);
+$output_roles = 1 if ($output_rolestats);
 
 if ($sections) {
     $email = 0;
@@ -197,6 +244,7 @@
     $subsystem = 0;
     $web = 0;
     $keywords = 0;
+    $interactive = 0;
 } else {
     my $selections = $email + $scm + $status + $subsystem + $web;
     if ($selections == 0) {
@@ -215,10 +263,6 @@
 	. "a linux kernel source tree.\n";
 }
 
-if ($email_git_all_signature_types) {
-    $signaturePattern = "(.+?)[Bb][Yy]:";
-}
-
 ## Read MAINTAINERS for type/value pairs
 
 my @typevalue = ();
@@ -253,31 +297,82 @@
 }
 close($maint);
 
-my %mailmap;
 
-if ($email_remove_duplicates) {
-    open(my $mailmap, '<', "${lk_path}.mailmap")
+#
+# Read mail address map
+#
+
+my $mailmap;
+
+read_mailmap();
+
+sub read_mailmap {
+    $mailmap = {
+	names => {},
+	addresses => {}
+    };
+
+    return if (!$email_use_mailmap || !(-f "${lk_path}.mailmap"));
+
+    open(my $mailmap_file, '<', "${lk_path}.mailmap")
 	or warn "$P: Can't open .mailmap: $!\n";
-    while (<$mailmap>) {
-	my $line = $_;
 
-	next if ($line =~ m/^\s*#/);
-	next if ($line =~ m/^\s*$/);
+    while (<$mailmap_file>) {
+	s/#.*$//; #strip comments
+	s/^\s+|\s+$//g; #trim
 
-	my ($name, $address) = parse_email($line);
-	$line = format_email($name, $address, $email_usename);
+	next if (/^\s*$/); #skip empty lines
+	#entries have one of the following formats:
+	# name1 <mail1>
+	# <mail1> <mail2>
+	# name1 <mail1> <mail2>
+	# name1 <mail1> name2 <mail2>
+	# (see man git-shortlog)
+	if (/^(.+)<(.+)>$/) {
+	    my $real_name = $1;
+	    my $address = $2;
 
-	next if ($line =~ m/^\s*$/);
+	    $real_name =~ s/\s+$//;
+	    ($real_name, $address) = parse_email("$real_name <$address>");
+	    $mailmap->{names}->{$address} = $real_name;
 
-	if (exists($mailmap{$name})) {
-	    my $obj = $mailmap{$name};
-	    push(@$obj, $address);
-	} else {
-	    my @arr = ($address);
-	    $mailmap{$name} = \@arr;
+	} elsif (/^<([^\s]+)>\s*<([^\s]+)>$/) {
+	    my $real_address = $1;
+	    my $wrong_address = $2;
+
+	    $mailmap->{addresses}->{$wrong_address} = $real_address;
+
+	} elsif (/^(.+)<([^\s]+)>\s*<([^\s]+)>$/) {
+	    my $real_name = $1;
+	    my $real_address = $2;
+	    my $wrong_address = $3;
+
+	    $real_name =~ s/\s+$//;
+	    ($real_name, $real_address) =
+		parse_email("$real_name <$real_address>");
+	    $mailmap->{names}->{$wrong_address} = $real_name;
+	    $mailmap->{addresses}->{$wrong_address} = $real_address;
+
+	} elsif (/^(.+)<([^\s]+)>\s*([^\s].*)<([^\s]+)>$/) {
+	    my $real_name = $1;
+	    my $real_address = $2;
+	    my $wrong_name = $3;
+	    my $wrong_address = $4;
+
+	    $real_name =~ s/\s+$//;
+	    ($real_name, $real_address) =
+		parse_email("$real_name <$real_address>");
+
+	    $wrong_name =~ s/\s+$//;
+	    ($wrong_name, $wrong_address) =
+		parse_email("$wrong_name <$wrong_address>");
+
+	    my $wrong_email = format_email($wrong_name, $wrong_address, 1);
+	    $mailmap->{names}->{$wrong_email} = $real_name;
+	    $mailmap->{addresses}->{$wrong_email} = $real_address;
 	}
     }
-    close($mailmap);
+    close($mailmap_file);
 }
 
 ## use the filenames on the command line or find the filenames in the patchfiles
@@ -302,7 +397,7 @@
     }
     if ($from_filename) {
 	push(@files, $file);
-	if (-f $file && ($keywords || $file_emails)) {
+	if ($file ne "MAINTAINERS" && -f $file && ($keywords || $file_emails)) {
 	    open(my $f, '<', $file)
 		or die "$P: Can't open $file: $!\n";
 	    my $text = do { local($/) ; <$f> };
@@ -357,134 +452,24 @@
 
 @file_emails = uniq(@file_emails);
 
+my %email_hash_name;
+my %email_hash_address;
 my @email_to = ();
+my %hash_list_to;
 my @list_to = ();
 my @scm = ();
 my @web = ();
 my @subsystem = ();
 my @status = ();
+my %deduplicate_name_hash = ();
+my %deduplicate_address_hash = ();
+my $signature_pattern;
 
-# Find responsible parties
+my @maintainers = get_maintainers();
 
-foreach my $file (@files) {
-
-    my %hash;
-    my $tvi = find_first_section();
-    while ($tvi < @typevalue) {
-	my $start = find_starting_index($tvi);
-	my $end = find_ending_index($tvi);
-	my $exclude = 0;
-	my $i;
-
-	#Do not match excluded file patterns
-
-	for ($i = $start; $i < $end; $i++) {
-	    my $line = $typevalue[$i];
-	    if ($line =~ m/^(\C):\s*(.*)/) {
-		my $type = $1;
-		my $value = $2;
-		if ($type eq 'X') {
-		    if (file_match_pattern($file, $value)) {
-			$exclude = 1;
-			last;
-		    }
-		}
-	    }
-	}
-
-	if (!$exclude) {
-	    for ($i = $start; $i < $end; $i++) {
-		my $line = $typevalue[$i];
-		if ($line =~ m/^(\C):\s*(.*)/) {
-		    my $type = $1;
-		    my $value = $2;
-		    if ($type eq 'F') {
-			if (file_match_pattern($file, $value)) {
-			    my $value_pd = ($value =~ tr@/@@);
-			    my $file_pd = ($file  =~ tr@/@@);
-			    $value_pd++ if (substr($value,-1,1) ne "/");
-			    if ($pattern_depth == 0 ||
-				(($file_pd - $value_pd) < $pattern_depth)) {
-				$hash{$tvi} = $value_pd;
-			    }
-			}
-		    }
-		}
-	    }
-	}
-
-	$tvi = $end + 1;
-    }
-
-    foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
-	add_categories($line);
-	    if ($sections) {
-		my $i;
-		my $start = find_starting_index($line);
-		my $end = find_ending_index($line);
-		for ($i = $start; $i < $end; $i++) {
-		    my $line = $typevalue[$i];
-		    if ($line =~ /^[FX]:/) {		##Restore file patterns
-			$line =~ s/([^\\])\.([^\*])/$1\?$2/g;
-			$line =~ s/([^\\])\.$/$1\?/g;	##Convert . back to ?
-			$line =~ s/\\\./\./g;       	##Convert \. to .
-			$line =~ s/\.\*/\*/g;       	##Convert .* to *
-		    }
-		    $line =~ s/^([A-Z]):/$1:\t/g;
-		    print("$line\n");
-		}
-		print("\n");
-	    }
-    }
-
-    if ($email && $email_git) {
-	vcs_file_signoffs($file);
-    }
-
-    if ($email && $email_git_blame) {
-	vcs_file_blame($file);
-    }
-}
-
-if ($keywords) {
-    @keyword_tvi = sort_and_uniq(@keyword_tvi);
-    foreach my $line (@keyword_tvi) {
-	add_categories($line);
-    }
-}
-
-if ($email) {
-    foreach my $chief (@penguin_chief) {
-	if ($chief =~ m/^(.*):(.*)/) {
-	    my $email_address;
-
-	    $email_address = format_email($1, $2, $email_usename);
-	    if ($email_git_penguin_chiefs) {
-		push(@email_to, [$email_address, 'chief penguin']);
-	    } else {
-		@email_to = grep($_->[0] !~ /${email_address}/, @email_to);
-	    }
-	}
-    }
-
-    foreach my $email (@file_emails) {
-	my ($name, $address) = parse_email($email);
-
-	my $tmp_email = format_email($name, $address, $email_usename);
-	push_email_address($tmp_email, '');
-	add_role($tmp_email, 'in file');
-    }
-}
-
-if ($email || $email_list) {
-    my @to = ();
-    if ($email) {
-	@to = (@to, @email_to);
-    }
-    if ($email_list) {
-	@to = (@to, @list_to);
-    }
-    output(merge_email(@to));
+if (@maintainers) {
+    @maintainers = merge_email(@maintainers);
+    output(@maintainers);
 }
 
 if ($scm) {
@@ -509,6 +494,167 @@
 
 exit($exit);
 
+sub get_maintainers {
+    %email_hash_name = ();
+    %email_hash_address = ();
+    %commit_author_hash = ();
+    %commit_signer_hash = ();
+    @email_to = ();
+    %hash_list_to = ();
+    @list_to = ();
+    @scm = ();
+    @web = ();
+    @subsystem = ();
+    @status = ();
+    %deduplicate_name_hash = ();
+    %deduplicate_address_hash = ();
+    if ($email_git_all_signature_types) {
+	$signature_pattern = "(.+?)[Bb][Yy]:";
+    } else {
+	$signature_pattern = "\(" . join("|", @signature_tags) . "\)";
+    }
+
+    # Find responsible parties
+
+    my %exact_pattern_match_hash = ();
+
+    foreach my $file (@files) {
+
+	my %hash;
+	my $tvi = find_first_section();
+	while ($tvi < @typevalue) {
+	    my $start = find_starting_index($tvi);
+	    my $end = find_ending_index($tvi);
+	    my $exclude = 0;
+	    my $i;
+
+	    #Do not match excluded file patterns
+
+	    for ($i = $start; $i < $end; $i++) {
+		my $line = $typevalue[$i];
+		if ($line =~ m/^(\C):\s*(.*)/) {
+		    my $type = $1;
+		    my $value = $2;
+		    if ($type eq 'X') {
+			if (file_match_pattern($file, $value)) {
+			    $exclude = 1;
+			    last;
+			}
+		    }
+		}
+	    }
+
+	    if (!$exclude) {
+		for ($i = $start; $i < $end; $i++) {
+		    my $line = $typevalue[$i];
+		    if ($line =~ m/^(\C):\s*(.*)/) {
+			my $type = $1;
+			my $value = $2;
+			if ($type eq 'F') {
+			    if (file_match_pattern($file, $value)) {
+				my $value_pd = ($value =~ tr@/@@);
+				my $file_pd = ($file  =~ tr@/@@);
+				$value_pd++ if (substr($value,-1,1) ne "/");
+				$value_pd = -1 if ($value =~ /^\.\*/);
+				if ($value_pd >= $file_pd) {
+				    $exact_pattern_match_hash{$file} = 1;
+				}
+				if ($pattern_depth == 0 ||
+				    (($file_pd - $value_pd) < $pattern_depth)) {
+				    $hash{$tvi} = $value_pd;
+				}
+			    }
+			}
+		    }
+		}
+	    }
+	    $tvi = $end + 1;
+	}
+
+	foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
+	    add_categories($line);
+	    if ($sections) {
+		my $i;
+		my $start = find_starting_index($line);
+		my $end = find_ending_index($line);
+		for ($i = $start; $i < $end; $i++) {
+		    my $line = $typevalue[$i];
+		    if ($line =~ /^[FX]:/) {		##Restore file patterns
+			$line =~ s/([^\\])\.([^\*])/$1\?$2/g;
+			$line =~ s/([^\\])\.$/$1\?/g;	##Convert . back to ?
+			$line =~ s/\\\./\./g;       	##Convert \. to .
+			$line =~ s/\.\*/\*/g;       	##Convert .* to *
+		    }
+		    $line =~ s/^([A-Z]):/$1:\t/g;
+		    print("$line\n");
+		}
+		print("\n");
+	    }
+	}
+    }
+
+    if ($keywords) {
+	@keyword_tvi = sort_and_uniq(@keyword_tvi);
+	foreach my $line (@keyword_tvi) {
+	    add_categories($line);
+	}
+    }
+
+    foreach my $email (@email_to, @list_to) {
+	$email->[0] = deduplicate_email($email->[0]);
+    }
+
+    foreach my $file (@files) {
+	if ($email &&
+	    ($email_git || ($email_git_fallback &&
+			    !$exact_pattern_match_hash{$file}))) {
+	    vcs_file_signoffs($file);
+	}
+	if ($email && $email_git_blame) {
+	    vcs_file_blame($file);
+	}
+    }
+
+    if ($email) {
+	foreach my $chief (@penguin_chief) {
+	    if ($chief =~ m/^(.*):(.*)/) {
+		my $email_address;
+
+		$email_address = format_email($1, $2, $email_usename);
+		if ($email_git_penguin_chiefs) {
+		    push(@email_to, [$email_address, 'chief penguin']);
+		} else {
+		    @email_to = grep($_->[0] !~ /${email_address}/, @email_to);
+		}
+	    }
+	}
+
+	foreach my $email (@file_emails) {
+	    my ($name, $address) = parse_email($email);
+
+	    my $tmp_email = format_email($name, $address, $email_usename);
+	    push_email_address($tmp_email, '');
+	    add_role($tmp_email, 'in file');
+	}
+    }
+
+    my @to = ();
+    if ($email || $email_list) {
+	if ($email) {
+	    @to = (@to, @email_to);
+	}
+	if ($email_list) {
+	    @to = (@to, @list_to);
+	}
+    }
+
+    if ($interactive) {
+	@to = interactive_get_maintainers(\@to);
+    }
+
+    return @to;
+}
+
 sub file_match_pattern {
     my ($file, $pattern) = @_;
     if (substr($pattern, -1) eq "/") {
@@ -537,7 +683,8 @@
   --email => print email address(es) if any
     --git => include recent git \*-by: signers
     --git-all-signature-types => include signers regardless of signature type
-        or use only ${signaturePattern} signers (default: $email_git_all_signature_types)
+        or use only ${signature_pattern} signers (default: $email_git_all_signature_types)
+    --git-fallback => use git when no exact MAINTAINERS pattern (default: $email_git_fallback)
     --git-chief-penguins => include ${penguin_chiefs}
     --git-min-signatures => number of signatures required (default: $email_git_min_signatures)
     --git-max-maintainers => maximum maintainers to add (default: $email_git_max_maintainers)
@@ -545,6 +692,7 @@
     --git-blame => use git blame to find modified commits for patch or file
     --git-since => git history to use (default: $email_git_since)
     --hg-since => hg history to use (default: $email_hg_since)
+    --interactive => display a menu (mostly useful if used with the --git option)
     --m => include maintainer(s) if any
     --n => include name 'Full Name <addr\@domain.tld>'
     --l => include list(s) if any
@@ -565,8 +713,9 @@
 
 Other options:
   --pattern-depth => Number of pattern directory traversals (default: 0 (all))
-  --keywords => scan patch for keywords (default: 1 (on))
-  --sections => print the entire subsystem sections with pattern matches
+  --keywords => scan patch for keywords (default: $keywords)
+  --sections => print all of the subsystem sections with pattern matches
+  --mailmap => use .mailmap file (default: $email_use_mailmap)
   --version => show version
   --help => show this help information
 
@@ -606,30 +755,30 @@
 }
 
 sub top_of_kernel_tree {
-	my ($lk_path) = @_;
+    my ($lk_path) = @_;
 
-	if ($lk_path ne "" && substr($lk_path,length($lk_path)-1,1) ne "/") {
-	    $lk_path .= "/";
-	}
-	if (   (-f "${lk_path}COPYING")
-	    && (-f "${lk_path}CREDITS")
-	    && (-f "${lk_path}Kbuild")
-	    && (-f "${lk_path}MAINTAINERS")
-	    && (-f "${lk_path}Makefile")
-	    && (-f "${lk_path}README")
-	    && (-d "${lk_path}Documentation")
-	    && (-d "${lk_path}arch")
-	    && (-d "${lk_path}include")
-	    && (-d "${lk_path}drivers")
-	    && (-d "${lk_path}fs")
-	    && (-d "${lk_path}init")
-	    && (-d "${lk_path}ipc")
-	    && (-d "${lk_path}kernel")
-	    && (-d "${lk_path}lib")
-	    && (-d "${lk_path}scripts")) {
-		return 1;
-	}
-	return 0;
+    if ($lk_path ne "" && substr($lk_path,length($lk_path)-1,1) ne "/") {
+	$lk_path .= "/";
+    }
+    if (   (-f "${lk_path}COPYING")
+	&& (-f "${lk_path}CREDITS")
+	&& (-f "${lk_path}Kbuild")
+	&& (-f "${lk_path}MAINTAINERS")
+	&& (-f "${lk_path}Makefile")
+	&& (-f "${lk_path}README")
+	&& (-d "${lk_path}Documentation")
+	&& (-d "${lk_path}arch")
+	&& (-d "${lk_path}include")
+	&& (-d "${lk_path}drivers")
+	&& (-d "${lk_path}fs")
+	&& (-d "${lk_path}init")
+	&& (-d "${lk_path}ipc")
+	&& (-d "${lk_path}kernel")
+	&& (-d "${lk_path}lib")
+	&& (-d "${lk_path}scripts")) {
+	return 1;
+    }
+    return 0;
 }
 
 sub parse_email {
@@ -821,11 +970,19 @@
 		}
 		if ($list_additional =~ m/subscribers-only/) {
 		    if ($email_subscriber_list) {
-			push(@list_to, [$list_address, "subscriber list${list_role}"]);
+			if (!$hash_list_to{lc($list_address)}) {
+			    $hash_list_to{lc($list_address)} = 1;
+			    push(@list_to, [$list_address,
+					    "subscriber list${list_role}"]);
+			}
 		    }
 		} else {
 		    if ($email_list) {
-			push(@list_to, [$list_address, "open list${list_role}"]);
+			if (!$hash_list_to{lc($list_address)}) {
+			    $hash_list_to{lc($list_address)} = 1;
+			    push(@list_to, [$list_address,
+					    "open list${list_role}"]);
+			}
 		    }
 		}
 	    } elsif ($ptype eq "M") {
@@ -856,15 +1013,12 @@
     }
 }
 
-my %email_hash_name;
-my %email_hash_address;
-
 sub email_inuse {
     my ($name, $address) = @_;
 
     return 1 if (($name eq "") && ($address eq ""));
-    return 1 if (($name ne "") && exists($email_hash_name{$name}));
-    return 1 if (($address ne "") && exists($email_hash_address{$address}));
+    return 1 if (($name ne "") && exists($email_hash_name{lc($name)}));
+    return 1 if (($address ne "") && exists($email_hash_address{lc($address)}));
 
     return 0;
 }
@@ -882,8 +1036,8 @@
 	push(@email_to, [format_email($name, $address, $email_usename), $role]);
     } elsif (!email_inuse($name, $address)) {
 	push(@email_to, [format_email($name, $address, $email_usename), $role]);
-	$email_hash_name{$name}++;
-	$email_hash_address{$address}++;
+	$email_hash_name{lc($name)}++ if ($name ne "");
+	$email_hash_address{lc($address)}++;
     }
 
     return 1;
@@ -952,30 +1106,69 @@
     return "";
 }
 
-sub mailmap {
-    my (@lines) = @_;
-    my %hash;
+sub which_conf {
+    my ($conf) = @_;
 
-    foreach my $line (@lines) {
-	my ($name, $address) = parse_email($line);
-	if (!exists($hash{$name})) {
-	    $hash{$name} = $address;
-	} elsif ($address ne $hash{$name}) {
-	    $address = $hash{$name};
-	    $line = format_email($name, $address, $email_usename);
-	}
-	if (exists($mailmap{$name})) {
-	    my $obj = $mailmap{$name};
-	    foreach my $map_address (@$obj) {
-		if (($map_address eq $address) &&
-		    ($map_address ne $hash{$name})) {
-		    $line = format_email($name, $hash{$name}, $email_usename);
-		}
-	    }
+    foreach my $path (split(/:/, ".:$ENV{HOME}:.scripts")) {
+	if (-e "$path/$conf") {
+	    return "$path/$conf";
 	}
     }
 
-    return @lines;
+    return "";
+}
+
+sub mailmap_email {
+    my ($line) = @_;
+
+    my ($name, $address) = parse_email($line);
+    my $email = format_email($name, $address, 1);
+    my $real_name = $name;
+    my $real_address = $address;
+
+    if (exists $mailmap->{names}->{$email} ||
+	exists $mailmap->{addresses}->{$email}) {
+	if (exists $mailmap->{names}->{$email}) {
+	    $real_name = $mailmap->{names}->{$email};
+	}
+	if (exists $mailmap->{addresses}->{$email}) {
+	    $real_address = $mailmap->{addresses}->{$email};
+	}
+    } else {
+	if (exists $mailmap->{names}->{$address}) {
+	    $real_name = $mailmap->{names}->{$address};
+	}
+	if (exists $mailmap->{addresses}->{$address}) {
+	    $real_address = $mailmap->{addresses}->{$address};
+	}
+    }
+    return format_email($real_name, $real_address, 1);
+}
+
+sub mailmap {
+    my (@addresses) = @_;
+
+    my @mapped_emails = ();
+    foreach my $line (@addresses) {
+	push(@mapped_emails, mailmap_email($line));
+    }
+    merge_by_realname(@mapped_emails) if ($email_use_mailmap);
+    return @mapped_emails;
+}
+
+sub merge_by_realname {
+    my %address_map;
+    my (@emails) = @_;
+
+    foreach my $email (@emails) {
+	my ($name, $address) = parse_email($email);
+	if (exists $address_map{$name}) {
+	    $address = $address_map{$name};
+	    $email = format_email($name, $address, 1);
+	} else {
+	    $address_map{$name} = $address;
+	}
+    }
 }
 
 sub git_execute_cmd {
@@ -999,10 +1192,30 @@
     return @lines;
 }
 
+sub extract_formatted_signatures {
+    my (@signature_lines) = @_;
+
+    my @type = @signature_lines;
+
+    s/\s*(.*):.*/$1/ for (@type);
+
+    # cut -f2- -d":"
+    s/\s*.*:\s*(.+)\s*/$1/ for (@signature_lines);
+
+## Reformat email addresses (with names) to avoid badly written signatures
+
+    foreach my $signer (@signature_lines) {
+	$signer = deduplicate_email($signer);
+    }
+
+    return (\@type, \@signature_lines);
+}
+
 sub vcs_find_signers {
     my ($cmd) = @_;
-    my @lines = ();
     my $commits;
+    my @lines = ();
+    my @signatures = ();
 
     @lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
 
@@ -1010,21 +1223,48 @@
 
     $commits = grep(/$pattern/, @lines);	# of commits
 
-    @lines = grep(/^[ \t]*${signaturePattern}.*\@.*$/, @lines);
+    @signatures = grep(/^[ \t]*${signature_pattern}.*\@.*$/, @lines);
+
+    return (0, @signatures) if !@signatures;
+
+    save_commits_by_author(@lines) if ($interactive);
+    save_commits_by_signer(@lines) if ($interactive);
+
+    if (!$email_git_penguin_chiefs) {
+	@signatures = grep(!/${penguin_chiefs}/i, @signatures);
+    }
+
+    my ($types_ref, $signers_ref) = extract_formatted_signatures(@signatures);
+
+    return ($commits, @$signers_ref);
+}
+
+sub vcs_find_author {
+    my ($cmd) = @_;
+    my @lines = ();
+
+    @lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
+
     if (!$email_git_penguin_chiefs) {
 	@lines = grep(!/${penguin_chiefs}/i, @lines);
     }
-    # cut -f2- -d":"
-    s/.*:\s*(.+)\s*/$1/ for (@lines);
 
-## Reformat email addresses (with names) to avoid badly written signatures
+    return @lines if !@lines;
 
+    my @authors = ();
     foreach my $line (@lines) {
-	my ($name, $address) = parse_email($line);
-	$line = format_email($name, $address, 1);
+	if ($line =~ m/$VCS_cmds{"author_pattern"}/) {
+	    my $author = $1;
+	    my ($name, $address) = parse_email($author);
+	    $author = format_email($name, $address, 1);
+	    push(@authors, $author);
+	}
     }
 
-    return ($commits, @lines);
+    save_commits_by_author(@lines) if ($interactive);
+    save_commits_by_signer(@lines) if ($interactive);
+
+    return @authors;
 }
 
 sub vcs_save_commits {
@@ -1084,6 +1324,10 @@
 	@commits = vcs_save_commits($cmd);
     }
 
+    foreach my $commit (@commits) {
+	$commit =~ s/^\^//g;
+    }
+
     return @commits;
 }
 
@@ -1092,7 +1336,7 @@
     %VCS_cmds = %VCS_cmds_git;
     return 1 if eval $VCS_cmds{"available"};
     %VCS_cmds = %VCS_cmds_hg;
-    return 1 if eval $VCS_cmds{"available"};
+    return 2 if eval $VCS_cmds{"available"};
     %VCS_cmds = ();
     if (!$printed_novcs) {
 	warn("$P: No supported VCS found.  Add --nogit to options?\n");
@@ -1104,6 +1348,405 @@
     return 0;
 }
 
+sub vcs_is_git {
+    vcs_exists();
+    return $vcs_used == 1;
+}
+
+sub vcs_is_hg {
+    return $vcs_used == 2;
+}
+
+sub interactive_get_maintainers {
+    my ($list_ref) = @_;
+    my @list = @$list_ref;
+
+    vcs_exists();
+
+    my %selected;
+    my %authored;
+    my %signed;
+    my $count = 0;
+    my $maintained = 0;
+    foreach my $entry (@list) {
+	$maintained = 1 if ($entry->[1] =~ /^(maintainer|supporter)/i);
+	$selected{$count} = 1;
+	$authored{$count} = 0;
+	$signed{$count} = 0;
+	$count++;
+    }
+
+    #menu loop
+    my $done = 0;
+    my $print_options = 0;
+    my $redraw = 1;
+    while (!$done) {
+	$count = 0;
+	if ($redraw) {
+	    printf STDERR "\n%1s %2s %-65s",
+			  "*", "#", "email/list and role:stats";
+	    if ($email_git ||
+		($email_git_fallback && !$maintained) ||
+		$email_git_blame) {
+		print STDERR "auth sign";
+	    }
+	    print STDERR "\n";
+	    foreach my $entry (@list) {
+		my $email = $entry->[0];
+		my $role = $entry->[1];
+		my $sel = "";
+		$sel = "*" if ($selected{$count});
+		my $commit_author = $commit_author_hash{$email};
+		my $commit_signer = $commit_signer_hash{$email};
+		my $authored = 0;
+		my $signed = 0;
+		$authored++ for (@{$commit_author});
+		$signed++ for (@{$commit_signer});
+		printf STDERR "%1s %2d %-65s", $sel, $count + 1, $email;
+		printf STDERR "%4d %4d", $authored, $signed
+		    if ($authored > 0 || $signed > 0);
+		printf STDERR "\n     %s\n", $role;
+		if ($authored{$count}) {
+		    my $commit_author = $commit_author_hash{$email};
+		    foreach my $ref (@{$commit_author}) {
+			print STDERR "     Author: @{$ref}[1]\n";
+		    }
+		}
+		if ($signed{$count}) {
+		    my $commit_signer = $commit_signer_hash{$email};
+		    foreach my $ref (@{$commit_signer}) {
+			print STDERR "     @{$ref}[2]: @{$ref}[1]\n";
+		    }
+		}
+
+		$count++;
+	    }
+	}
+	my $date_ref = \$email_git_since;
+	$date_ref = \$email_hg_since if (vcs_is_hg());
+	if ($print_options) {
+	    $print_options = 0;
+	    if (vcs_exists()) {
+		print STDERR <<EOT
+
+Version Control options:
+g  use git history      [$email_git]
+gf use git-fallback     [$email_git_fallback]
+b  use git blame        [$email_git_blame]
+bs use blame signatures [$email_git_blame_signatures]
+c# minimum commits      [$email_git_min_signatures]
+%# min percent          [$email_git_min_percent]
+d# history to use       [$$date_ref]
+x# max maintainers      [$email_git_max_maintainers]
+t  all signature types  [$email_git_all_signature_types]
+m  use .mailmap         [$email_use_mailmap]
+EOT
+	    }
+	    print STDERR <<EOT
+
+Additional options:
+0  toggle all
+tm toggle maintainers
+tg toggle git entries
+tl toggle open list entries
+ts toggle subscriber list entries
+f  emails in file       [$file_emails]
+k  keywords in file     [$keywords]
+r  remove duplicates    [$email_remove_duplicates]
+p# pattern match depth  [$pattern_depth]
+EOT
+	}
+	print STDERR
+"\n#(toggle), A#(author), S#(signed) *(all), ^(none), O(options), Y(approve): ";
+
+	my $input = <STDIN>;
+	chomp($input);
+
+	$redraw = 1;
+	my $rerun = 0;
+	my @wish = split(/[, ]+/, $input);
+	foreach my $nr (@wish) {
+	    $nr = lc($nr);
+	    my $sel = substr($nr, 0, 1);
+	    my $str = substr($nr, 1);
+	    my $val = 0;
+	    $val = $1 if $str =~ /^(\d+)$/;
+
+	    if ($sel eq "y") {
+		$interactive = 0;
+		$done = 1;
+		$output_rolestats = 0;
+		$output_roles = 0;
+		last;
+	    } elsif ($nr =~ /^\d+$/ && $nr > 0 && $nr <= $count) {
+		$selected{$nr - 1} = !$selected{$nr - 1};
+	    } elsif ($sel eq "*" || $sel eq '^') {
+		my $toggle = 0;
+		$toggle = 1 if ($sel eq '*');
+		for (my $i = 0; $i < $count; $i++) {
+		    $selected{$i} = $toggle;
+		}
+	    } elsif ($sel eq "0") {
+		for (my $i = 0; $i < $count; $i++) {
+		    $selected{$i} = !$selected{$i};
+		}
+	    } elsif ($sel eq "t") {
+		if (lc($str) eq "m") {
+		    for (my $i = 0; $i < $count; $i++) {
+			$selected{$i} = !$selected{$i}
+			    if ($list[$i]->[1] =~ /^(maintainer|supporter)/i);
+		    }
+		} elsif (lc($str) eq "g") {
+		    for (my $i = 0; $i < $count; $i++) {
+			$selected{$i} = !$selected{$i}
+			    if ($list[$i]->[1] =~ /^(author|commit|signer)/i);
+		    }
+		} elsif (lc($str) eq "l") {
+		    for (my $i = 0; $i < $count; $i++) {
+			$selected{$i} = !$selected{$i}
+			    if ($list[$i]->[1] =~ /^(open list)/i);
+		    }
+		} elsif (lc($str) eq "s") {
+		    for (my $i = 0; $i < $count; $i++) {
+			$selected{$i} = !$selected{$i}
+			    if ($list[$i]->[1] =~ /^(subscriber list)/i);
+		    }
+		}
+	    } elsif ($sel eq "a") {
+		if ($val > 0 && $val <= $count) {
+		    $authored{$val - 1} = !$authored{$val - 1};
+		} elsif ($str eq '*' || $str eq '^') {
+		    my $toggle = 0;
+		    $toggle = 1 if ($str eq '*');
+		    for (my $i = 0; $i < $count; $i++) {
+			$authored{$i} = $toggle;
+		    }
+		}
+	    } elsif ($sel eq "s") {
+		if ($val > 0 && $val <= $count) {
+		    $signed{$val - 1} = !$signed{$val - 1};
+		} elsif ($str eq '*' || $str eq '^') {
+		    my $toggle = 0;
+		    $toggle = 1 if ($str eq '*');
+		    for (my $i = 0; $i < $count; $i++) {
+			$signed{$i} = $toggle;
+		    }
+		}
+	    } elsif ($sel eq "o") {
+		$print_options = 1;
+		$redraw = 1;
+	    } elsif ($sel eq "g") {
+		if ($str eq "f") {
+		    bool_invert(\$email_git_fallback);
+		} else {
+		    bool_invert(\$email_git);
+		}
+		$rerun = 1;
+	    } elsif ($sel eq "b") {
+		if ($str eq "s") {
+		    bool_invert(\$email_git_blame_signatures);
+		} else {
+		    bool_invert(\$email_git_blame);
+		}
+		$rerun = 1;
+	    } elsif ($sel eq "c") {
+		if ($val > 0) {
+		    $email_git_min_signatures = $val;
+		    $rerun = 1;
+		}
+	    } elsif ($sel eq "x") {
+		if ($val > 0) {
+		    $email_git_max_maintainers = $val;
+		    $rerun = 1;
+		}
+	    } elsif ($sel eq "%") {
+		if ($str ne "" && $val >= 0) {
+		    $email_git_min_percent = $val;
+		    $rerun = 1;
+		}
+	    } elsif ($sel eq "d") {
+		if (vcs_is_git()) {
+		    $email_git_since = $str;
+		} elsif (vcs_is_hg()) {
+		    $email_hg_since = $str;
+		}
+		$rerun = 1;
+	    } elsif ($sel eq "t") {
+		bool_invert(\$email_git_all_signature_types);
+		$rerun = 1;
+	    } elsif ($sel eq "f") {
+		bool_invert(\$file_emails);
+		$rerun = 1;
+	    } elsif ($sel eq "r") {
+		bool_invert(\$email_remove_duplicates);
+		$rerun = 1;
+	    } elsif ($sel eq "m") {
+		bool_invert(\$email_use_mailmap);
+		read_mailmap();
+		$rerun = 1;
+	    } elsif ($sel eq "k") {
+		bool_invert(\$keywords);
+		$rerun = 1;
+	    } elsif ($sel eq "p") {
+		if ($str ne "" && $val >= 0) {
+		    $pattern_depth = $val;
+		    $rerun = 1;
+		}
+	    } elsif ($sel eq "h" || $sel eq "?") {
+		print STDERR <<EOT
+
+Interactive mode allows you to select the various maintainers, submitters,
+commit signers and mailing lists that could be CC'd on a patch.
+
+Any *'d entry is selected.
+
+If you have git or hg installed, you can choose to summarize the commit
+history of files in the patch.  Also, each line of the current file can
+be matched to its commit author and that commits signers with blame.
+
+Various knobs exist to control the length of time for active commit
+tracking, the maximum number of commit authors and signers to add,
+and such.
+
+Enter selections at the prompt until you are satisfied that the selected
+maintainers are appropriate.  You may enter multiple selections separated
+by either commas or spaces.
+
+EOT
+	    } else {
+		print STDERR "invalid option: '$nr'\n";
+		$redraw = 0;
+	    }
+	}
+	if ($rerun) {
+	    print STDERR "git-blame can be very slow, please have patience..."
+		if ($email_git_blame);
+	    goto &get_maintainers;
+	}
+    }
+
+    #drop not selected entries
+    $count = 0;
+    my @new_emailto = ();
+    foreach my $entry (@list) {
+	if ($selected{$count}) {
+	    push(@new_emailto, $list[$count]);
+	}
+	$count++;
+    }
+    return @new_emailto;
+}
+
+sub bool_invert {
+    my ($bool_ref) = @_;
+
+    if ($$bool_ref) {
+	$$bool_ref = 0;
+    } else {
+	$$bool_ref = 1;
+    }
+}
+
+sub deduplicate_email {
+    my ($email) = @_;
+
+    my $matched = 0;
+    my ($name, $address) = parse_email($email);
+    $email = format_email($name, $address, 1);
+    $email = mailmap_email($email);
+
+    return $email if (!$email_remove_duplicates);
+
+    ($name, $address) = parse_email($email);
+
+    if ($name ne "" && $deduplicate_name_hash{lc($name)}) {
+	$name = $deduplicate_name_hash{lc($name)}->[0];
+	$address = $deduplicate_name_hash{lc($name)}->[1];
+	$matched = 1;
+    } elsif ($deduplicate_address_hash{lc($address)}) {
+	$name = $deduplicate_address_hash{lc($address)}->[0];
+	$address = $deduplicate_address_hash{lc($address)}->[1];
+	$matched = 1;
+    }
+    if (!$matched) {
+	$deduplicate_name_hash{lc($name)} = [ $name, $address ];
+	$deduplicate_address_hash{lc($address)} = [ $name, $address ];
+    }
+    $email = format_email($name, $address, 1);
+    $email = mailmap_email($email);
+    return $email;
+}
+
+sub save_commits_by_author {
+    my (@lines) = @_;
+
+    my @authors = ();
+    my @commits = ();
+    my @subjects = ();
+
+    foreach my $line (@lines) {
+	if ($line =~ m/$VCS_cmds{"author_pattern"}/) {
+	    my $author = $1;
+	    $author = deduplicate_email($author);
+	    push(@authors, $author);
+	}
+	push(@commits, $1) if ($line =~ m/$VCS_cmds{"commit_pattern"}/);
+	push(@subjects, $1) if ($line =~ m/$VCS_cmds{"subject_pattern"}/);
+    }
+
+    for (my $i = 0; $i < @authors; $i++) {
+	my $exists = 0;
+	foreach my $ref(@{$commit_author_hash{$authors[$i]}}) {
+	    if (@{$ref}[0] eq $commits[$i] &&
+		@{$ref}[1] eq $subjects[$i]) {
+		$exists = 1;
+		last;
+	    }
+	}
+	if (!$exists) {
+	    push(@{$commit_author_hash{$authors[$i]}},
+		 [ ($commits[$i], $subjects[$i]) ]);
+	}
+    }
+}
+
+sub save_commits_by_signer {
+    my (@lines) = @_;
+
+    my $commit = "";
+    my $subject = "";
+
+    foreach my $line (@lines) {
+	$commit = $1 if ($line =~ m/$VCS_cmds{"commit_pattern"}/);
+	$subject = $1 if ($line =~ m/$VCS_cmds{"subject_pattern"}/);
+	if ($line =~ /^[ \t]*${signature_pattern}.*\@.*$/) {
+	    my @signatures = ($line);
+	    my ($types_ref, $signers_ref) = extract_formatted_signatures(@signatures);
+	    my @types = @$types_ref;
+	    my @signers = @$signers_ref;
+
+	    my $type = $types[0];
+	    my $signer = $signers[0];
+
+	    $signer = deduplicate_email($signer);
+
+	    my $exists = 0;
+	    foreach my $ref(@{$commit_signer_hash{$signer}}) {
+		if (@{$ref}[0] eq $commit &&
+		    @{$ref}[1] eq $subject &&
+		    @{$ref}[2] eq $type) {
+		    $exists = 1;
+		    last;
+		}
+	    }
+	    if (!$exists) {
+		push(@{$commit_signer_hash{$signer}},
+		     [ ($commit, $subject, $type) ]);
+	    }
+	}
+    }
+}
+
 sub vcs_assign {
     my ($role, $divisor, @lines) = @_;
 
@@ -1117,9 +1760,9 @@
 	$divisor = 1;
     }
 
-    if ($email_remove_duplicates) {
-	@lines = mailmap(@lines);
-    }
+    @lines = mailmap(@lines);
+
+    return if (@lines <= 0);
 
     @lines = sort(@lines);
 
@@ -1152,12 +1795,18 @@
     my @signers = ();
     my $commits;
 
-    return if (!vcs_exists());
+    $vcs_used = vcs_exists();
+    return if (!$vcs_used);
 
     my $cmd = $VCS_cmds{"find_signers_cmd"};
     $cmd =~ s/(\$\w+)/$1/eeg;		# interpolate $cmd
 
     ($commits, @signers) = vcs_find_signers($cmd);
+
+    foreach my $signer (@signers) {
+	$signer = deduplicate_email($signer);
+    }
+
     vcs_assign("commit_signer", $commits, @signers);
 }
 
@@ -1165,29 +1814,114 @@
     my ($file) = @_;
 
     my @signers = ();
+    my @all_commits = ();
     my @commits = ();
     my $total_commits;
+    my $total_lines;
 
-    return if (!vcs_exists());
+    $vcs_used = vcs_exists();
+    return if (!$vcs_used);
 
-    @commits = vcs_blame($file);
-    @commits = uniq(@commits);
+    @all_commits = vcs_blame($file);
+    @commits = uniq(@all_commits);
     $total_commits = @commits;
+    $total_lines = @all_commits;
 
-    foreach my $commit (@commits) {
-	my $commit_count;
-	my @commit_signers = ();
+    if ($email_git_blame_signatures) {
+	if (vcs_is_hg()) {
+	    my $commit_count;
+	    my @commit_signers = ();
+	    my $commit = join(" -r ", @commits);
+	    my $cmd;
 
-	my $cmd = $VCS_cmds{"find_commit_signers_cmd"};
-	$cmd =~ s/(\$\w+)/$1/eeg;	#interpolate $cmd
+	    $cmd = $VCS_cmds{"find_commit_signers_cmd"};
+	    $cmd =~ s/(\$\w+)/$1/eeg;	#substitute variables in $cmd
 
-	($commit_count, @commit_signers) = vcs_find_signers($cmd);
-	push(@signers, @commit_signers);
+	    ($commit_count, @commit_signers) = vcs_find_signers($cmd);
+
+	    push(@signers, @commit_signers);
+	} else {
+	    foreach my $commit (@commits) {
+		my $commit_count;
+		my @commit_signers = ();
+		my $cmd;
+
+		$cmd = $VCS_cmds{"find_commit_signers_cmd"};
+		$cmd =~ s/(\$\w+)/$1/eeg;	#substitute variables in $cmd
+
+		($commit_count, @commit_signers) = vcs_find_signers($cmd);
+
+		push(@signers, @commit_signers);
+	    }
+	}
     }
 
     if ($from_filename) {
+	if ($output_rolestats) {
+	    my @blame_signers;
+	    if (vcs_is_hg()) {{		# Double brace for last exit
+		my $commit_count;
+		my @commit_signers = ();
+		@commits = uniq(@commits);
+		@commits = sort(@commits);
+		my $commit = join(" -r ", @commits);
+		my $cmd;
+
+		$cmd = $VCS_cmds{"find_commit_author_cmd"};
+		$cmd =~ s/(\$\w+)/$1/eeg;	#substitute variables in $cmd
+
+		my @lines = ();
+
+		@lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
+
+		if (!$email_git_penguin_chiefs) {
+		    @lines = grep(!/${penguin_chiefs}/i, @lines);
+		}
+
+		last if !@lines;
+
+		my @authors = ();
+		foreach my $line (@lines) {
+		    if ($line =~ m/$VCS_cmds{"author_pattern"}/) {
+			my $author = $1;
+			$author = deduplicate_email($author);
+			push(@authors, $author);
+		    }
+		}
+
+		save_commits_by_author(@lines) if ($interactive);
+		save_commits_by_signer(@lines) if ($interactive);
+
+		push(@signers, @authors);
+	    }}
+	    else {
+		foreach my $commit (@commits) {
+		    my $i;
+		    my $cmd = $VCS_cmds{"find_commit_author_cmd"};
+		    $cmd =~ s/(\$\w+)/$1/eeg;	#interpolate $cmd
+		    my @author = vcs_find_author($cmd);
+		    next if !@author;
+
+		    my $formatted_author = deduplicate_email($author[0]);
+
+		    my $count = grep(/$commit/, @all_commits);
+		    for ($i = 0; $i < $count ; $i++) {
+			push(@blame_signers, $formatted_author);
+		    }
+		}
+	    }
+	    if (@blame_signers) {
+		vcs_assign("authored lines", $total_lines, @blame_signers);
+	    }
+	}
+	foreach my $signer (@signers) {
+	    $signer = deduplicate_email($signer);
+	}
 	vcs_assign("commits", $total_commits, @signers);
     } else {
+	foreach my $signer (@signers) {
+	    $signer = deduplicate_email($signer);
+	}
 	vcs_assign("modified commits", $total_commits, @signers);
     }
 }
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 3fbcd1d..ac79032 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -70,6 +70,7 @@
 void ima_cleanup(void);
 int ima_fs_init(void);
 void ima_fs_cleanup(void);
+int ima_inode_alloc(struct inode *inode);
 int ima_add_template_entry(struct ima_template_entry *entry, int violation,
 			   const char *op, struct inode *inode);
 int ima_calc_hash(struct file *file, char *digest);
@@ -96,19 +97,16 @@
 }
 
 /* iint cache flags */
-#define IMA_MEASURED		1
+#define IMA_MEASURED		0x01
 
 /* integrity data associated with an inode */
 struct ima_iint_cache {
+	struct rb_node rb_node; /* rooted in ima_iint_tree */
+	struct inode *inode;	/* back pointer to inode in question */
 	u64 version;		/* track inode changes */
-	unsigned long flags;
+	unsigned char flags;
 	u8 digest[IMA_DIGEST_SIZE];
 	struct mutex mutex;	/* protects: version, flags, digest */
-	long readcount;		/* measured files readcount */
-	long writecount;	/* measured files writecount */
-	long opencount;		/* opens reference count */
-	struct kref refcount;	/* ima_iint_cache reference count */
-	struct rcu_head rcu;
 };
 
 /* LIM API function definitions */
@@ -122,13 +120,11 @@
 void ima_template_show(struct seq_file *m, void *e,
 		       enum ima_show_type show);
 
-/* radix tree calls to lookup, insert, delete
+/* rbtree tree calls to lookup, insert, delete
  * integrity data associated with an inode.
  */
 struct ima_iint_cache *ima_iint_insert(struct inode *inode);
-struct ima_iint_cache *ima_iint_find_get(struct inode *inode);
-void iint_free(struct kref *kref);
-void iint_rcu_free(struct rcu_head *rcu);
+struct ima_iint_cache *ima_iint_find(struct inode *inode);
 
 /* IMA policy related functions */
 enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK };
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 52015d0..d3963de 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -116,7 +116,7 @@
 {
 	int must_measure;
 
-	if (iint->flags & IMA_MEASURED)
+	if (iint && iint->flags & IMA_MEASURED)
 		return 1;
 
 	must_measure = ima_match_policy(inode, function, mask);
diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c
index afba4ae..c442e47 100644
--- a/security/integrity/ima/ima_iint.c
+++ b/security/integrity/ima/ima_iint.c
@@ -12,100 +12,121 @@
  * File: ima_iint.c
  * 	- implements the IMA hooks: ima_inode_alloc, ima_inode_free
  *	- cache integrity information associated with an inode
- *	  using a radix tree.
+ *	  using a rbtree tree.
  */
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
-#include <linux/radix-tree.h>
+#include <linux/rbtree.h>
 #include "ima.h"
 
-RADIX_TREE(ima_iint_store, GFP_ATOMIC);
-DEFINE_SPINLOCK(ima_iint_lock);
+static struct rb_root ima_iint_tree = RB_ROOT;
+static DEFINE_SPINLOCK(ima_iint_lock);
 static struct kmem_cache *iint_cache __read_mostly;
 
 int iint_initialized = 0;
 
-/* ima_iint_find_get - return the iint associated with an inode
- *
- * ima_iint_find_get gets a reference to the iint. Caller must
- * remember to put the iint reference.
+/*
+ * __ima_iint_find - return the iint associated with an inode
  */
-struct ima_iint_cache *ima_iint_find_get(struct inode *inode)
+static struct ima_iint_cache *__ima_iint_find(struct inode *inode)
+{
+	struct ima_iint_cache *iint;
+	struct rb_node *n = ima_iint_tree.rb_node;
+
+	assert_spin_locked(&ima_iint_lock);
+
+	while (n) {
+		iint = rb_entry(n, struct ima_iint_cache, rb_node);
+
+		if (inode < iint->inode)
+			n = n->rb_left;
+		else if (inode > iint->inode)
+			n = n->rb_right;
+		else
+			break;
+	}
+	if (!n)
+		return NULL;
+
+	return iint;
+}
+
+/*
+ * ima_iint_find - return the iint associated with an inode
+ */
+struct ima_iint_cache *ima_iint_find(struct inode *inode)
 {
 	struct ima_iint_cache *iint;
 
-	rcu_read_lock();
-	iint = radix_tree_lookup(&ima_iint_store, (unsigned long)inode);
-	if (!iint)
-		goto out;
-	kref_get(&iint->refcount);
-out:
-	rcu_read_unlock();
+	if (!IS_IMA(inode))
+		return NULL;
+
+	spin_lock(&ima_iint_lock);
+	iint = __ima_iint_find(inode);
+	spin_unlock(&ima_iint_lock);
+
 	return iint;
 }
 
+static void iint_free(struct ima_iint_cache *iint)
+{
+	iint->version = 0;
+	iint->flags = 0UL;
+	kmem_cache_free(iint_cache, iint);
+}
+
 /**
  * ima_inode_alloc - allocate an iint associated with an inode
  * @inode: pointer to the inode
  */
 int ima_inode_alloc(struct inode *inode)
 {
-	struct ima_iint_cache *iint = NULL;
-	int rc = 0;
+	struct rb_node **p;
+	struct rb_node *new_node, *parent = NULL;
+	struct ima_iint_cache *new_iint, *test_iint;
+	int rc;
 
-	iint = kmem_cache_alloc(iint_cache, GFP_NOFS);
-	if (!iint)
+	new_iint = kmem_cache_alloc(iint_cache, GFP_NOFS);
+	if (!new_iint)
 		return -ENOMEM;
 
-	rc = radix_tree_preload(GFP_NOFS);
-	if (rc < 0)
-		goto out;
+	new_iint->inode = inode;
+	new_node = &new_iint->rb_node;
 
+	mutex_lock(&inode->i_mutex); /* i_flags */
 	spin_lock(&ima_iint_lock);
-	rc = radix_tree_insert(&ima_iint_store, (unsigned long)inode, iint);
+
+	p = &ima_iint_tree.rb_node;
+	while (*p) {
+		parent = *p;
+		test_iint = rb_entry(parent, struct ima_iint_cache, rb_node);
+
+		rc = -EEXIST;
+		if (inode < test_iint->inode)
+			p = &(*p)->rb_left;
+		else if (inode > test_iint->inode)
+			p = &(*p)->rb_right;
+		else
+			goto out_err;
+	}
+
+	inode->i_flags |= S_IMA;
+	rb_link_node(new_node, parent, p);
+	rb_insert_color(new_node, &ima_iint_tree);
+
 	spin_unlock(&ima_iint_lock);
-	radix_tree_preload_end();
-out:
-	if (rc < 0)
-		kmem_cache_free(iint_cache, iint);
+	mutex_unlock(&inode->i_mutex); /* i_flags */
+
+	return 0;
+out_err:
+	spin_unlock(&ima_iint_lock);
+	mutex_unlock(&inode->i_mutex); /* i_flags */
+	iint_free(new_iint);
 
 	return rc;
 }
 
-/* iint_free - called when the iint refcount goes to zero */
-void iint_free(struct kref *kref)
-{
-	struct ima_iint_cache *iint = container_of(kref, struct ima_iint_cache,
-						   refcount);
-	iint->version = 0;
-	iint->flags = 0UL;
-	if (iint->readcount != 0) {
-		printk(KERN_INFO "%s: readcount: %ld\n", __func__,
-		       iint->readcount);
-		iint->readcount = 0;
-	}
-	if (iint->writecount != 0) {
-		printk(KERN_INFO "%s: writecount: %ld\n", __func__,
-		       iint->writecount);
-		iint->writecount = 0;
-	}
-	if (iint->opencount != 0) {
-		printk(KERN_INFO "%s: opencount: %ld\n", __func__,
-		       iint->opencount);
-		iint->opencount = 0;
-	}
-	kref_init(&iint->refcount);
-	kmem_cache_free(iint_cache, iint);
-}
-
-void iint_rcu_free(struct rcu_head *rcu_head)
-{
-	struct ima_iint_cache *iint = container_of(rcu_head,
-						   struct ima_iint_cache, rcu);
-	kref_put(&iint->refcount, iint_free);
-}
-
 /**
  * ima_inode_free - called on security_inode_free
  * @inode: pointer to the inode
@@ -116,11 +137,20 @@
 {
 	struct ima_iint_cache *iint;
 
+	if (inode->i_readcount)
+		printk(KERN_INFO "%s: readcount: %u\n", __func__, inode->i_readcount);
+
+	inode->i_readcount = 0;
+
+	if (!IS_IMA(inode))
+		return;
+
 	spin_lock(&ima_iint_lock);
-	iint = radix_tree_delete(&ima_iint_store, (unsigned long)inode);
+	iint = __ima_iint_find(inode);
+	rb_erase(&iint->rb_node, &ima_iint_tree);
 	spin_unlock(&ima_iint_lock);
-	if (iint)
-		call_rcu(&iint->rcu, iint_rcu_free);
+
+	iint_free(iint);
 }
 
 static void init_once(void *foo)
@@ -131,10 +161,6 @@
 	iint->version = 0;
 	iint->flags = 0UL;
 	mutex_init(&iint->mutex);
-	iint->readcount = 0;
-	iint->writecount = 0;
-	iint->opencount = 0;
-	kref_init(&iint->refcount);
 }
 
 static int __init ima_iintcache_init(void)
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index e662b89..203de97 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -85,50 +85,6 @@
 	return found;
 }
 
-/* ima_read_write_check - reflect possible reading/writing errors in the PCR.
- *
- * When opening a file for read, if the file is already open for write,
- * the file could change, resulting in a file measurement error.
- *
- * Opening a file for write, if the file is already open for read, results
- * in a time of measure, time of use (ToMToU) error.
- *
- * In either case invalidate the PCR.
- */
-enum iint_pcr_error { TOMTOU, OPEN_WRITERS };
-static void ima_read_write_check(enum iint_pcr_error error,
-				 struct ima_iint_cache *iint,
-				 struct inode *inode,
-				 const unsigned char *filename)
-{
-	switch (error) {
-	case TOMTOU:
-		if (iint->readcount > 0)
-			ima_add_violation(inode, filename, "invalid_pcr",
-					  "ToMToU");
-		break;
-	case OPEN_WRITERS:
-		if (iint->writecount > 0)
-			ima_add_violation(inode, filename, "invalid_pcr",
-					  "open_writers");
-		break;
-	}
-}
-
-/*
- * Update the counts given an fmode_t
- */
-static void ima_inc_counts(struct ima_iint_cache *iint, fmode_t mode)
-{
-	BUG_ON(!mutex_is_locked(&iint->mutex));
-
-	iint->opencount++;
-	if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
-		iint->readcount++;
-	if (mode & FMODE_WRITE)
-		iint->writecount++;
-}
-
 /*
  * ima_counts_get - increment file counts
  *
@@ -145,62 +101,101 @@
 	struct dentry *dentry = file->f_path.dentry;
 	struct inode *inode = dentry->d_inode;
 	fmode_t mode = file->f_mode;
-	struct ima_iint_cache *iint;
 	int rc;
+	bool send_tomtou = false, send_writers = false;
 
-	if (!iint_initialized || !S_ISREG(inode->i_mode))
+	if (!S_ISREG(inode->i_mode))
 		return;
-	iint = ima_iint_find_get(inode);
-	if (!iint)
-		return;
-	mutex_lock(&iint->mutex);
+
+	spin_lock(&inode->i_lock);
+
 	if (!ima_initialized)
 		goto out;
-	rc = ima_must_measure(iint, inode, MAY_READ, FILE_CHECK);
-	if (rc < 0)
-		goto out;
 
 	if (mode & FMODE_WRITE) {
-		ima_read_write_check(TOMTOU, iint, inode, dentry->d_name.name);
+		if (inode->i_readcount && IS_IMA(inode))
+			send_tomtou = true;
 		goto out;
 	}
-	ima_read_write_check(OPEN_WRITERS, iint, inode, dentry->d_name.name);
-out:
-	ima_inc_counts(iint, file->f_mode);
-	mutex_unlock(&iint->mutex);
 
-	kref_put(&iint->refcount, iint_free);
+	rc = ima_must_measure(NULL, inode, MAY_READ, FILE_CHECK);
+	if (rc < 0)
+		goto out;
+
+	if (atomic_read(&inode->i_writecount) > 0)
+		send_writers = true;
+out:
+	/* remember the vfs deals with i_writecount */
+	if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
+		inode->i_readcount++;
+
+	spin_unlock(&inode->i_lock);
+
+	if (send_tomtou)
+		ima_add_violation(inode, dentry->d_name.name, "invalid_pcr",
+				  "ToMToU");
+	if (send_writers)
+		ima_add_violation(inode, dentry->d_name.name, "invalid_pcr",
+				  "open_writers");
 }
 
 /*
  * Decrement ima counts
  */
-static void ima_dec_counts(struct ima_iint_cache *iint, struct inode *inode,
-			   struct file *file)
+static void ima_dec_counts(struct inode *inode, struct file *file)
 {
 	mode_t mode = file->f_mode;
-	BUG_ON(!mutex_is_locked(&iint->mutex));
 
-	iint->opencount--;
-	if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
-		iint->readcount--;
-	if (mode & FMODE_WRITE) {
-		iint->writecount--;
-		if (iint->writecount == 0) {
-			if (iint->version != inode->i_version)
-				iint->flags &= ~IMA_MEASURED;
+	assert_spin_locked(&inode->i_lock);
+
+	if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
+		if (unlikely(inode->i_readcount == 0)) {
+			if (!ima_limit_imbalance(file)) {
+				printk(KERN_INFO "%s: open/free imbalance (r:%u)\n",
+				       __func__, inode->i_readcount);
+				dump_stack();
+			}
+			return;
 		}
+		inode->i_readcount--;
 	}
+}
 
-	if (((iint->opencount < 0) ||
-	     (iint->readcount < 0) ||
-	     (iint->writecount < 0)) &&
-	    !ima_limit_imbalance(file)) {
-		printk(KERN_INFO "%s: open/free imbalance (r:%ld w:%ld o:%ld)\n",
-		       __func__, iint->readcount, iint->writecount,
-		       iint->opencount);
-		dump_stack();
-	}
+static void ima_check_last_writer(struct ima_iint_cache *iint,
+				  struct inode *inode,
+				  struct file *file)
+{
+	mode_t mode = file->f_mode;
+
+	BUG_ON(!mutex_is_locked(&iint->mutex));
+	assert_spin_locked(&inode->i_lock);
+
+	if (mode & FMODE_WRITE &&
+	    atomic_read(&inode->i_writecount) == 1 &&
+	    iint->version != inode->i_version)
+		iint->flags &= ~IMA_MEASURED;
+}
+
+static void ima_file_free_iint(struct ima_iint_cache *iint, struct inode *inode,
+			       struct file *file)
+{
+	mutex_lock(&iint->mutex);
+	spin_lock(&inode->i_lock);
+
+	ima_dec_counts(inode, file);
+	ima_check_last_writer(iint, inode, file);
+
+	spin_unlock(&inode->i_lock);
+	mutex_unlock(&iint->mutex);
+}
+
+static void ima_file_free_noiint(struct inode *inode, struct file *file)
+{
+	spin_lock(&inode->i_lock);
+
+	ima_dec_counts(inode, file);
+
+	spin_unlock(&inode->i_lock);
 }
 
 /**
@@ -208,7 +203,7 @@
  * @file: pointer to file structure being freed
  *
  * Flag files that changed, based on i_version;
- * and decrement the iint readcount/writecount.
+ * and decrement the i_readcount.
  */
 void ima_file_free(struct file *file)
 {
@@ -217,14 +212,14 @@
 
 	if (!iint_initialized || !S_ISREG(inode->i_mode))
 		return;
-	iint = ima_iint_find_get(inode);
-	if (!iint)
-		return;
 
-	mutex_lock(&iint->mutex);
-	ima_dec_counts(iint, inode, file);
-	mutex_unlock(&iint->mutex);
-	kref_put(&iint->refcount, iint_free);
+	iint = ima_iint_find(inode);
+
+	if (iint)
+		ima_file_free_iint(iint, inode, file);
+	else
+		ima_file_free_noiint(inode, file);
+
 }
 
 static int process_measurement(struct file *file, const unsigned char *filename,
@@ -236,11 +231,21 @@
 
 	if (!ima_initialized || !S_ISREG(inode->i_mode))
 		return 0;
-	iint = ima_iint_find_get(inode);
-	if (!iint)
-		return -ENOMEM;
+
+	rc = ima_must_measure(NULL, inode, mask, function);
+	if (rc != 0)
+		return rc;
+retry:
+	iint = ima_iint_find(inode);
+	if (!iint) {
+		rc = ima_inode_alloc(inode);
+		if (!rc || rc == -EEXIST)
+			goto retry;
+		return rc;
+	}
 
 	mutex_lock(&iint->mutex);
+
 	rc = ima_must_measure(iint, inode, mask, function);
 	if (rc != 0)
 		goto out;
@@ -250,7 +255,6 @@
 		ima_store_measurement(iint, file, filename);
 out:
 	mutex_unlock(&iint->mutex);
-	kref_put(&iint->refcount, iint_free);
 	return rc;
 }
 
diff --git a/security/security.c b/security/security.c
index b50f472..3ef5e2a 100644
--- a/security/security.c
+++ b/security/security.c
@@ -325,16 +325,8 @@
 
 int security_inode_alloc(struct inode *inode)
 {
-	int ret;
-
 	inode->i_security = NULL;
-	ret =  security_ops->inode_alloc_security(inode);
-	if (ret)
-		return ret;
-	ret = ima_inode_alloc(inode);
-	if (ret)
-		security_inode_free(inode);
-	return ret;
+	return security_ops->inode_alloc_security(inode);
 }
 
 void security_inode_free(struct inode *inode)
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 9969618..d211c9f 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -31,7 +31,6 @@
 #include <sound/initval.h>
 #include <sound/soc.h>
 
-#include <plat/control.h>
 #include <plat/dma.h>
 #include <plat/mcbsp.h>
 #include "omap-mcbsp.h"
@@ -598,93 +597,6 @@
 	return 0;
 }
 
-static int omap_mcbsp_dai_set_clks_src(struct omap_mcbsp_data *mcbsp_data,
-				       int clk_id)
-{
-	int sel_bit;
-	u16 reg, reg_devconf1 = OMAP243X_CONTROL_DEVCONF1;
-
-	if (cpu_class_is_omap1()) {
-		/* OMAP1's can use only external source clock */
-		if (unlikely(clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK))
-			return -EINVAL;
-		else
-			return 0;
-	}
-
-	if (cpu_is_omap2420() && mcbsp_data->bus_id > 1)
-		return -EINVAL;
-
-	if (cpu_is_omap343x())
-		reg_devconf1 = OMAP343X_CONTROL_DEVCONF1;
-
-	switch (mcbsp_data->bus_id) {
-	case 0:
-		reg = OMAP2_CONTROL_DEVCONF0;
-		sel_bit = 2;
-		break;
-	case 1:
-		reg = OMAP2_CONTROL_DEVCONF0;
-		sel_bit = 6;
-		break;
-	case 2:
-		reg = reg_devconf1;
-		sel_bit = 0;
-		break;
-	case 3:
-		reg = reg_devconf1;
-		sel_bit = 2;
-		break;
-	case 4:
-		reg = reg_devconf1;
-		sel_bit = 4;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if (clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK)
-		omap_ctrl_writel(omap_ctrl_readl(reg) & ~(1 << sel_bit), reg);
-	else
-		omap_ctrl_writel(omap_ctrl_readl(reg) | (1 << sel_bit), reg);
-
-	return 0;
-}
-
-static int omap_mcbsp_dai_set_rcvr_src(struct omap_mcbsp_data *mcbsp_data,
-				       int clk_id)
-{
-	int sel_bit, set = 0;
-	u16 reg = OMAP2_CONTROL_DEVCONF0;
-
-	if (cpu_class_is_omap1())
-		return -EINVAL; /* TODO: Can this be implemented for OMAP1? */
-	if (mcbsp_data->bus_id != 0)
-		return -EINVAL;
-
-	switch (clk_id) {
-	case OMAP_MCBSP_CLKR_SRC_CLKX:
-		set = 1;
-	case OMAP_MCBSP_CLKR_SRC_CLKR:
-		sel_bit = 3;
-		break;
-	case OMAP_MCBSP_FSR_SRC_FSX:
-		set = 1;
-	case OMAP_MCBSP_FSR_SRC_FSR:
-		sel_bit = 4;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if (set)
-		omap_ctrl_writel(omap_ctrl_readl(reg) | (1 << sel_bit), reg);
-	else
-		omap_ctrl_writel(omap_ctrl_readl(reg) & ~(1 << sel_bit), reg);
-
-	return 0;
-}
-
 static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
 					 int clk_id, unsigned int freq,
 					 int dir)
@@ -693,6 +605,14 @@
 	struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
 	int err = 0;
 
+	/* The McBSP signal muxing functions are only available on McBSP1 */
+	if (clk_id == OMAP_MCBSP_CLKR_SRC_CLKR ||
+	    clk_id == OMAP_MCBSP_CLKR_SRC_CLKX ||
+	    clk_id == OMAP_MCBSP_FSR_SRC_FSR ||
+	    clk_id == OMAP_MCBSP_FSR_SRC_FSX)
+		if (cpu_class_is_omap1() || mcbsp_data->bus_id != 0)
+			return -EINVAL;
+
 	mcbsp_data->in_freq = freq;
 
 	switch (clk_id) {
@@ -700,8 +620,20 @@
 		regs->srgr2	|= CLKSM;
 		break;
 	case OMAP_MCBSP_SYSCLK_CLKS_FCLK:
+		if (cpu_class_is_omap1()) {
+			err = -EINVAL;
+			break;
+		}
+		err = omap2_mcbsp_set_clks_src(mcbsp_data->bus_id,
+					       MCBSP_CLKS_PRCM_SRC);
+		break;
 	case OMAP_MCBSP_SYSCLK_CLKS_EXT:
-		err = omap_mcbsp_dai_set_clks_src(mcbsp_data, clk_id);
+		if (cpu_class_is_omap1()) {
+			err = 0;
+			break;
+		}
+		err = omap2_mcbsp_set_clks_src(mcbsp_data->bus_id,
+					       MCBSP_CLKS_PAD_SRC);
 		break;
 
 	case OMAP_MCBSP_SYSCLK_CLKX_EXT:
@@ -710,11 +642,18 @@
 		regs->pcr0	|= SCLKME;
 		break;
 
+
 	case OMAP_MCBSP_CLKR_SRC_CLKR:
+		omap2_mcbsp1_mux_clkr_src(CLKR_SRC_CLKR);
+		break;
 	case OMAP_MCBSP_CLKR_SRC_CLKX:
+		omap2_mcbsp1_mux_clkr_src(CLKR_SRC_CLKX);
+		break;
 	case OMAP_MCBSP_FSR_SRC_FSR:
+		omap2_mcbsp1_mux_fsr_src(FSR_SRC_FSR);
+		break;
 	case OMAP_MCBSP_FSR_SRC_FSX:
-		err = omap_mcbsp_dai_set_rcvr_src(mcbsp_data, clk_id);
+		omap2_mcbsp1_mux_fsr_src(FSR_SRC_FSX);
 		break;
 	default:
 		err = -ENODEV;
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c
index f161c2f..bed09c2 100644
--- a/sound/soc/omap/omap-mcpdm.c
+++ b/sound/soc/omap/omap-mcpdm.c
@@ -32,7 +32,6 @@
 #include <sound/initval.h>
 #include <sound/soc.h>
 
-#include <plat/control.h>
 #include <plat/dma.h>
 #include <plat/mcbsp.h>
 #include "mcpdm.h"